feat(new tool): Docker Compose Converter

- Convert Docker Compose files between V1, 2.x, 3.x and CommonSpec
- Expand Ports and Volumes syntaxes
This commit is contained in:
sharevb 2024-01-21 15:23:22 +01:00 committed by ShareVB
parent 22e836bb3d
commit 1b17302bf6
7 changed files with 246 additions and 37 deletions

1
components.d.ts vendored
View file

@ -69,6 +69,7 @@ declare module '@vue/runtime-core' {
DemoWrapper: typeof import('./src/ui/demo/demo-wrapper.vue')['default'] DemoWrapper: typeof import('./src/ui/demo/demo-wrapper.vue')['default']
DeviceInformation: typeof import('./src/tools/device-information/device-information.vue')['default'] DeviceInformation: typeof import('./src/tools/device-information/device-information.vue')['default']
DiffViewer: typeof import('./src/tools/json-diff/diff-viewer/diff-viewer.vue')['default'] DiffViewer: typeof import('./src/tools/json-diff/diff-viewer/diff-viewer.vue')['default']
DockerComposeConverter: typeof import('./src/tools/docker-compose-converter/docker-compose-converter.vue')['default']
DockerRunToDockerComposeConverter: typeof import('./src/tools/docker-run-to-docker-compose-converter/docker-run-to-docker-compose-converter.vue')['default'] DockerRunToDockerComposeConverter: typeof import('./src/tools/docker-run-to-docker-compose-converter/docker-run-to-docker-compose-converter.vue')['default']
DynamicValues: typeof import('./src/tools/benchmark-builder/dynamic-values.vue')['default'] DynamicValues: typeof import('./src/tools/benchmark-builder/dynamic-values.vue')['default']
Editor: typeof import('./src/tools/html-wysiwyg-editor/editor/editor.vue')['default'] Editor: typeof import('./src/tools/html-wysiwyg-editor/editor/editor.vue')['default']

View file

@ -51,6 +51,7 @@
"change-case": "^4.1.2", "change-case": "^4.1.2",
"colord": "^2.9.3", "colord": "^2.9.3",
"composerize-ts": "^0.6.2", "composerize-ts": "^0.6.2",
"composeverter": "^1.6.2",
"country-code-lookup": "^0.1.0", "country-code-lookup": "^0.1.0",
"cron-validator": "^1.3.1", "cron-validator": "^1.3.1",
"cronstrue": "^2.26.0", "cronstrue": "^2.26.0",

104
pnpm-lock.yaml generated
View file

@ -50,9 +50,12 @@ dependencies:
colord: colord:
specifier: ^2.9.3 specifier: ^2.9.3
version: 2.9.3 version: 2.9.3
composerize: composerize-ts:
specifier: ^1.6.6 specifier: ^0.6.2
version: 1.6.6 version: 0.6.2
composeverter:
specifier: ^1.6.2
version: 1.6.2
country-code-lookup: country-code-lookup:
specifier: ^0.1.0 specifier: ^0.1.0
version: 0.1.0 version: 0.1.0
@ -4164,7 +4167,6 @@ packages:
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
dependencies: dependencies:
sprintf-js: 1.0.3 sprintf-js: 1.0.3
dev: true
/argparse@2.0.1: /argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
@ -4297,7 +4299,6 @@ packages:
dependencies: dependencies:
balanced-match: 1.0.2 balanced-match: 1.0.2
concat-map: 0.0.1 concat-map: 0.0.1
dev: true
/brace-expansion@2.0.1: /brace-expansion@2.0.1:
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
@ -4587,6 +4588,11 @@ packages:
delayed-stream: 1.0.0 delayed-stream: 1.0.0
dev: true dev: true
/commander@10.0.1:
resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
engines: {node: '>=14'}
dev: false
/commander@2.20.3: /commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
@ -4604,16 +4610,16 @@ packages:
resolution: {integrity: sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==} resolution: {integrity: sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==}
dev: false dev: false
/composerize@1.6.6: /composerize-ts@0.6.2:
resolution: {integrity: sha512-ZvnntVZvz4VzMSmxDc/BF+l5ra7pMAUDxDrljTosVCKhIFKR3mBVVKRJrne3Dx9xIDyvVwA1pRhmrAq+JGJX4g==} resolution: {integrity: sha512-8tw5p/FBxg77ubjVftaXA+pknWbkUgbZ4rbZZs2yFUsj2yvO38IvtfpGLfaJ9mGFj324lFEr/OU9xULrKSF9Ag==}
hasBin: true hasBin: true
dependencies: dependencies:
composeverter: 1.6.2 commander: 10.0.1
core-js: 2.6.12 deepmerge-ts: 5.1.0
deepmerge: 2.2.1 flex-js: 1.0.5
invariant: 2.2.4 ip-cidr: 3.1.0
yaml: 1.10.2 set-value: 4.1.0
yargs-parser: 13.1.2 yamljs: 0.3.0
dev: false dev: false
/composeverter@1.6.2: /composeverter@1.6.2:
@ -4627,7 +4633,6 @@ packages:
/concat-map@0.0.1: /concat-map@0.0.1:
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
dev: true
/config-chain@1.1.13: /config-chain@1.1.13:
resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==}
@ -4867,6 +4872,11 @@ packages:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
dev: true dev: true
/deepmerge-ts@5.1.0:
resolution: {integrity: sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw==}
engines: {node: '>=16.0.0'}
dev: false
/deepmerge@2.2.1: /deepmerge@2.2.1:
resolution: {integrity: sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==} resolution: {integrity: sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -5715,6 +5725,10 @@ packages:
resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
dev: true dev: true
/flex-js@1.0.5:
resolution: {integrity: sha512-Z5uoLzOGtTB/nzaTVVBbwmxOHBzHovAGJHLXE1TUKsQuN1RRWMOWeA08J9RRKtAl9TH9tkaH6fpjA4sLf0DzQw==}
dev: false
/for-each@0.3.3: /for-each@0.3.3:
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
dependencies: dependencies:
@ -5781,7 +5795,6 @@ packages:
/fs.realpath@1.0.0: /fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
dev: true
/fsevents@2.3.2: /fsevents@2.3.2:
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
@ -5893,7 +5906,6 @@ packages:
minimatch: 3.1.2 minimatch: 3.1.2
once: 1.4.0 once: 1.4.0
path-is-absolute: 1.0.1 path-is-absolute: 1.0.1
dev: true
/glob@8.1.0: /glob@8.1.0:
resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
@ -6212,11 +6224,9 @@ packages:
dependencies: dependencies:
once: 1.4.0 once: 1.4.0
wrappy: 1.0.2 wrappy: 1.0.2
dev: true
/inherits@2.0.4: /inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
dev: true
/ini@1.3.8: /ini@1.3.8:
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
@ -6231,10 +6241,20 @@ packages:
side-channel: 1.0.4 side-channel: 1.0.4
dev: true dev: true
/invariant@2.2.4: /ip-address@7.1.0:
resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} resolution: {integrity: sha512-V9pWC/VJf2lsXqP7IWJ+pe3P1/HCYGBMZrrnT62niLGjAfCbeiwXMUxaeHvnVlz19O27pvXP4azs+Pj/A0x+SQ==}
engines: {node: '>= 10'}
dependencies: dependencies:
loose-envify: 1.4.0 jsbn: 1.1.0
sprintf-js: 1.1.2
dev: false
/ip-cidr@3.1.0:
resolution: {integrity: sha512-HUCn4snshEX1P8cja/IyU3qk8FVDW8T5zZcegDFbu4w7NojmAhk5NcOgj3M8+0fmumo1afJTPDtJlzsxLdOjtg==}
engines: {node: '>=10.0.0'}
dependencies:
ip-address: 7.1.0
jsbn: 1.1.0
dev: false dev: false
/is-alphabetical@1.0.4: /is-alphabetical@1.0.4:
@ -6404,6 +6424,11 @@ packages:
resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
dev: true dev: true
/is-primitive@3.0.1:
resolution: {integrity: sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==}
engines: {node: '>=0.10.0'}
dev: false
/is-regex@1.1.4: /is-regex@1.1.4:
resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -6551,6 +6576,10 @@ packages:
argparse: 2.0.1 argparse: 2.0.1
dev: true dev: true
/jsbn@1.1.0:
resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==}
dev: false
/jsdom@22.0.0: /jsdom@22.0.0:
resolution: {integrity: sha512-p5ZTEb5h+O+iU02t0GfEjAnkdYPrQSkfuTSMkMYyIoMvUNEHsbG0bHHbfXIcfTqD2UfvjQX7mmgiFsyRwGscVw==} resolution: {integrity: sha512-p5ZTEb5h+O+iU02t0GfEjAnkdYPrQSkfuTSMkMYyIoMvUNEHsbG0bHHbfXIcfTqD2UfvjQX7mmgiFsyRwGscVw==}
engines: {node: '>=16'} engines: {node: '>=16'}
@ -6763,13 +6792,6 @@ packages:
is-unicode-supported: 0.1.0 is-unicode-supported: 0.1.0
dev: true dev: true
/loose-envify@1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
dependencies:
js-tokens: 4.0.0
dev: false
/loupe@2.3.6: /loupe@2.3.6:
resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==}
dependencies: dependencies:
@ -6966,7 +6988,6 @@ packages:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
dependencies: dependencies:
brace-expansion: 1.1.11 brace-expansion: 1.1.11
dev: true
/minimatch@5.1.6: /minimatch@5.1.6:
resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
@ -7213,7 +7234,6 @@ packages:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
dependencies: dependencies:
wrappy: 1.0.2 wrappy: 1.0.2
dev: true
/onetime@5.1.2: /onetime@5.1.2:
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
@ -7401,7 +7421,6 @@ packages:
/path-is-absolute@1.0.1: /path-is-absolute@1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dev: true
/path-key@3.1.1: /path-key@3.1.1:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
@ -8119,6 +8138,14 @@ packages:
has-property-descriptors: 1.0.1 has-property-descriptors: 1.0.1
dev: true dev: true
/set-value@4.1.0:
resolution: {integrity: sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==}
engines: {node: '>=11.0'}
dependencies:
is-plain-object: 2.0.4
is-primitive: 3.0.1
dev: false
/shebang-command@2.0.0: /shebang-command@2.0.0:
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -8239,7 +8266,10 @@ packages:
/sprintf-js@1.0.3: /sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
dev: true
/sprintf-js@1.1.2:
resolution: {integrity: sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==}
dev: false
/sql-formatter@13.0.0: /sql-formatter@13.0.0:
resolution: {integrity: sha512-V21cVvge4rhn9Fa7K/fTKcmPM+x1yee6Vhq8ZwgaWh3VPBqApgsaoFB5kLAhiqRo5AmSaRyLU7LIdgnNwH01/w==} resolution: {integrity: sha512-V21cVvge4rhn9Fa7K/fTKcmPM+x1yee6Vhq8ZwgaWh3VPBqApgsaoFB5kLAhiqRo5AmSaRyLU7LIdgnNwH01/w==}
@ -9595,7 +9625,6 @@ packages:
/wrappy@1.0.2: /wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
dev: true
/ws@8.13.0: /ws@8.13.0:
resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==}
@ -9663,11 +9692,12 @@ packages:
resolution: {integrity: sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==} resolution: {integrity: sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==}
engines: {node: '>= 14'} engines: {node: '>= 14'}
/yargs-parser@13.1.2: /yamljs@0.3.0:
resolution: {integrity: sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==} resolution: {integrity: sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==}
hasBin: true
dependencies: dependencies:
camelcase: 5.3.1 argparse: 1.0.10
decamelize: 1.2.0 glob: 7.2.3
dev: false dev: false
/yargs-parser@18.1.3: /yargs-parser@18.1.3:

View file

@ -0,0 +1,19 @@
declare module 'composeverter' {
interface Configuration {
expandVolumes?: boolean;
expandPorts?: boolean;
indent?: number;
}
interface DockerComposeValidatioError {
line?: number;
message: string;
helpLink?: string;
}
export function validateDockerComposeToCommonSpec(content: string): DockerComposeValidatioError[];
export function migrateFromV2xToV3x(content: string, configuration?: Configuration = null): string;
export function migrateFromV3xToV2x(content: string, configuration?: Configuration = null): string;
export function migrateFromV1ToV2x(content: string, configuration?: Configuration = null): string;
export function migrateToCommonSpec(content: string, configuration?: Configuration = null): string;
export function migrateFromV2xToV3x(content: string, configuration?: Configuration = null): string;
export function getDockerComposeSchemaWithoutFormats(): object;
}

View file

@ -0,0 +1,144 @@
<script setup lang="ts">
import Composeverter from 'composeverter';
import { useDownloadFileFromBase64 } from '@/composable/downloadBase64';
import { textToBase64 } from '@/utils/base64';
import TextareaCopyable from '@/components/TextareaCopyable.vue';
const dockerCompose = ref(
`nginx:
ports:
- '80:80'
volumes:
- '/var/run/docker.sock:/tmp/docker.sock:ro'
image: nginx`,
);
const indentSize = useStorage('docker-compose-converter:indent-size', 4);
const expandVolumes = ref(
false,
);
const expandPorts = ref(
false,
);
const conversion = useStorage('docker-compose-converter:conversion', 'latest');
const conversionOptions = [
{ value: 'v1ToV2x', label: 'V1 to V2 2.x' },
{ value: 'v1ToV3x', label: 'V1 to V2 3.x' },
{ value: 'v2xToV3x', label: 'V2 - 2.x to 3.x' },
{ value: 'v3xToV2x', label: 'V2 - 3.x to 2.x' },
{ value: 'latest', label: 'To CommonSpec' },
];
const conversionResult = computed(() => {
try {
let convertedDockerCompose = '';
const config = {
expandPorts: expandPorts.value,
expandVolumes: expandVolumes.value,
indent: indentSize.value,
};
switch (conversion.value) {
case 'latest':
convertedDockerCompose = Composeverter.migrateToCommonSpec(dockerCompose.value, config);
break;
case 'v1ToV2x':
convertedDockerCompose = Composeverter.migrateFromV1ToV2x(dockerCompose.value, config);
break;
case 'v1ToV3x':
convertedDockerCompose = Composeverter.migrateFromV2xToV3x(Composeverter.migrateFromV1ToV2x(dockerCompose.value), config);
break;
case 'v2xToV3x':
convertedDockerCompose = Composeverter.migrateFromV2xToV3x(dockerCompose.value, config);
break;
case 'v3xToV2x':
convertedDockerCompose = Composeverter.migrateFromV3xToV2x(dockerCompose.value, config);
break;
default:
throw new Error(`Unknown conversion '${conversion}'`);
}
return { yaml: convertedDockerCompose, errors: [] };
}
catch (e: any) {
return { yaml: '#see error messages', errors: e.toString().split('\n') };
}
});
const convertedDockerCompose = computed(() => conversionResult.value.yaml);
const errors = computed(() => conversionResult.value.errors);
const convertedDockerComposeBase64 = computed(() => `data:application/yaml;base64,${textToBase64(convertedDockerCompose.value)}`);
const { download } = useDownloadFileFromBase64({ source: convertedDockerComposeBase64, filename: 'docker-compose.yml' });
const MONACO_EDITOR_OPTIONS = {
automaticLayout: true,
formatOnType: true,
formatOnPaste: true,
};
</script>
<template>
<div>
<c-label label="Paste your existing Docker Compose:">
<div relative w-full>
<c-monaco-editor
v-model:value="dockerCompose"
theme="vs-dark"
language="yaml"
height="200px"
:options="MONACO_EDITOR_OPTIONS"
/>
</div>
</c-label>
<div v-if="errors.length > 0">
<n-alert title="The following errors occured" type="error" mt-5>
<ul>
<li v-for="(message, index) of errors" :key="index">
{{ message }}
</li>
</ul>
</n-alert>
</div>
<n-divider />
<n-grid cols="4" x-gap="12" w-full>
<n-gi span="2">
<c-select
v-model:value="conversion"
label-position="top"
label="Docker Compose conversion:"
:options="conversionOptions"
placeholder="Select Docker Compose conversion"
/>
</n-gi>
<n-gi span="2">
<n-form-item label="Indent size:" label-placement="top" label-width="100" :show-feedback="false">
<n-input-number v-model:value="indentSize" min="0" max="10" w-100px />
</n-form-item>
</n-gi>
</n-grid>
<n-divider />
<div class="mb-6 flex flex-row items-center gap-2">
<n-checkbox v-model:checked="expandPorts">
Expand Ports
</n-checkbox>
<n-checkbox v-model:checked="expandVolumes">
Expand Volumes
</n-checkbox>
</div>
<n-divider />
<TextareaCopyable :value="convertedDockerCompose" language="yaml" />
<div mt-5 flex justify-center>
<c-button :disabled="dockerCompose === ''" secondary @click="download">
Download converted docker-compose.yml
</c-button>
</div>
</div>
</template>

View file

@ -0,0 +1,12 @@
import { BrandDocker } from '@vicons/tabler';
import { defineTool } from '../tool';
export const tool = defineTool({
name: 'Docker Compose Format Converter',
path: '/docker-compose-converter',
description: 'Convert Docker Compose file between V1, 2.x, 3.x or CommonSpec and may expand ports/volumes syntaxes',
keywords: ['docker', 'compose', 'converter'],
component: () => import('./docker-compose-converter.vue'),
icon: BrandDocker,
createdAt: new Date('2024-01-04'),
});

View file

@ -75,6 +75,7 @@ import { tool as urlParser } from './url-parser';
import { tool as uuidGenerator } from './uuid-generator'; import { tool as uuidGenerator } from './uuid-generator';
import { tool as macAddressLookup } from './mac-address-lookup'; import { tool as macAddressLookup } from './mac-address-lookup';
import { tool as xmlFormatter } from './xml-formatter'; import { tool as xmlFormatter } from './xml-formatter';
import { tool as dockerComposeConverter } from './docker-compose-converter';
export const toolsByCategory: ToolCategory[] = [ export const toolsByCategory: ToolCategory[] = [
{ {
@ -138,6 +139,7 @@ export const toolsByCategory: ToolCategory[] = [
sqlPrettify, sqlPrettify,
chmodCalculator, chmodCalculator,
dockerRunToDockerComposeConverter, dockerRunToDockerComposeConverter,
dockerComposeConverter,
xmlFormatter, xmlFormatter,
], ],
}, },