diff --git a/package-lock.json b/package-lock.json index 1062d49..29cb3ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,8 +14,8 @@ "@icp-sdk/core": "^5.0.0", "@junobuild/admin": "^4.2.1", "@junobuild/cdn": "^2.3.1", - "@junobuild/cli-tools": "^0.12.4", - "@junobuild/config": "^2.15.0", + "@junobuild/cli-tools": "file:../juno-js/packages/cli-tools", + "@junobuild/config": "file:../juno-js/packages/config", "@junobuild/config-loader": "^0.4.9", "@junobuild/core": "^5.2.2", "@junobuild/functions-tools": "^0.5.3", @@ -57,6 +57,39 @@ "node": ">=20" } }, + "../juno-js/packages/cli-tools": { + "name": "@junobuild/cli-tools", + "version": "0.12.4", + "license": "MIT", + "dependencies": { + "file-type": "^21.3.2", + "listr2": "^10.2.1", + "mime-types": "^3.0.2", + "minimatch": "^10.2.4" + }, + "devDependencies": { + "@types/mime-types": "^3.0.1", + "@types/minimatch": "^6.0.0" + }, + "peerDependencies": { + "@dfinity/utils": "^4.1", + "@junobuild/cdn": "^2.3", + "@junobuild/config": "^2.14", + "@junobuild/functions-tools": "^0.5.2", + "@junobuild/storage": "^2.3", + "esbuild": "^0.27.0", + "ora": "^9" + } + }, + "../juno-js/packages/config": { + "name": "@junobuild/config", + "version": "2.15.0", + "license": "MIT", + "peerDependencies": { + "@junobuild/schema": "^1.1", + "zod": "^4.3" + } + }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", @@ -861,16 +894,6 @@ "node": ">=6.9.0" } }, - "node_modules/@borewit/text-codec": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.2.tgz", - "integrity": "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/@dfinity/cbor": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/@dfinity/cbor/-/cbor-0.2.2.tgz", @@ -903,6 +926,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -919,6 +943,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -935,6 +960,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -951,6 +977,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -967,6 +994,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -983,6 +1011,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -999,6 +1028,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1015,6 +1045,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1031,6 +1062,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1047,6 +1079,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1063,6 +1096,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1079,6 +1113,7 @@ "cpu": [ "loong64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1095,6 +1130,7 @@ "cpu": [ "mips64el" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1111,6 +1147,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1127,6 +1164,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1143,6 +1181,7 @@ "cpu": [ "s390x" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1159,6 +1198,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1175,6 +1215,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1191,6 +1232,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1207,6 +1249,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1223,6 +1266,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1239,6 +1283,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1255,6 +1300,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1271,6 +1317,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1287,6 +1334,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1303,6 +1351,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1758,35 +1807,12 @@ } }, "node_modules/@junobuild/cli-tools": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/@junobuild/cli-tools/-/cli-tools-0.12.4.tgz", - "integrity": "sha512-huEUnn9IEb7pbpC66oyepA6uAS29MbNUT98DehdjzZjgsy/tHUZwOSW851ISjWowkRD2MYbc1XsWpoOe4AdCRQ==", - "license": "MIT", - "dependencies": { - "file-type": "^21.3.2", - "listr2": "^10.2.1", - "mime-types": "^3.0.2", - "minimatch": "^10.2.4" - }, - "peerDependencies": { - "@dfinity/utils": "^4.1", - "@junobuild/cdn": "^2.3", - "@junobuild/config": "^2.14", - "@junobuild/functions-tools": "^0.5.2", - "@junobuild/storage": "^2.3", - "esbuild": "^0.27.0", - "ora": "^9" - } + "resolved": "../juno-js/packages/cli-tools", + "link": true }, "node_modules/@junobuild/config": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/@junobuild/config/-/config-2.15.0.tgz", - "integrity": "sha512-4SiFDmayi6GxGFdr0BG/sOSk6iinW0ijv7mD3Xp8ufvVEhzfOsT8Ta6GS+HD2Eb0lRpnvXaAtw6xzdB5ub56cg==", - "license": "MIT", - "peerDependencies": { - "@junobuild/schema": "^1.1", - "zod": "^4.3" - } + "resolved": "../juno-js/packages/config", + "link": true }, "node_modules/@junobuild/config-loader": { "version": "0.4.9", @@ -2003,29 +2029,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@tokenizer/inflate": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz", - "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.3", - "token-types": "^6.1.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", - "license": "MIT" - }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -2843,22 +2846,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", - "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", - "license": "MIT", - "dependencies": { - "slice-ansi": "^8.0.0", - "string-width": "^8.2.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -3145,12 +3132,6 @@ "license": "ISC", "peer": true }, - "node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT" - }, "node_modules/enhanced-resolve": { "version": "5.18.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", @@ -3341,6 +3322,7 @@ "version": "0.27.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "dev": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -3921,12 +3903,6 @@ "node": ">=0.10.0" } }, - "node_modules/eventemitter3": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", - "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", - "license": "MIT" - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3981,24 +3957,6 @@ "node": ">=16.0.0" } }, - "node_modules/file-type": { - "version": "21.3.2", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.2.tgz", - "integrity": "sha512-DLkUvGwep3poOV2wpzbHCOnSKGk1LzyXTv+aHFgN2VFl96wnp8YA9YjO2qPzg5PuL8q/SW9Pdi6WTkYOIh995w==", - "license": "MIT", - "dependencies": { - "@tokenizer/inflate": "^0.4.1", - "strtok3": "^10.3.4", - "token-types": "^6.1.1", - "uint8array-extras": "^1.4.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" - } - }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -4369,26 +4327,6 @@ "license": "Apache-2.0", "peer": true }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -4615,21 +4553,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-fullwidth-code-point": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", - "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.3.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-generator-function": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", @@ -5033,22 +4956,6 @@ "node": ">= 0.8.0" } }, - "node_modules/listr2": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-10.2.1.tgz", - "integrity": "sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q==", - "license": "MIT", - "dependencies": { - "cli-truncate": "^5.2.0", - "eventemitter3": "^5.0.4", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", - "wrap-ansi": "^10.0.0" - }, - "engines": { - "node": ">=22.13.0" - } - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -5086,87 +4993,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", - "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", - "license": "MIT", - "dependencies": { - "ansi-escapes": "^7.0.0", - "cli-cursor": "^5.0.0", - "slice-ansi": "^7.1.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", - "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -5199,31 +5025,6 @@ "node": ">=10.0.0" } }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/mimic-function": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", @@ -5236,42 +5037,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minimatch": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", - "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimatch/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/minimatch/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -5850,12 +5615,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "license": "MIT" - }, "node_modules/run-applescript": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", @@ -6100,34 +5859,6 @@ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" }, - "node_modules/slice-ansi": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-8.0.0.tgz", - "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.3", - "is-fullwidth-code-point": "^5.1.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/stdin-discarder": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", @@ -6267,22 +5998,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strtok3": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz", - "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==", - "license": "MIT", - "dependencies": { - "@tokenizer/token": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/stubborn-fs": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/stubborn-fs/-/stubborn-fs-1.2.5.tgz", @@ -6396,24 +6111,6 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/token-types": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz", - "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==", - "license": "MIT", - "dependencies": { - "@borewit/text-codec": "^0.2.1", - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/ts-api-utils": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", @@ -6774,35 +6471,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/wrap-ansi": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-10.0.0.tgz", - "integrity": "sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.3", - "string-width": "^8.2.0", - "strip-ansi": "^7.1.2" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/wsl-utils": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.0.tgz", @@ -7420,11 +7088,6 @@ "@babel/helper-validator-identifier": "^7.27.1" } }, - "@borewit/text-codec": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.2.tgz", - "integrity": "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==" - }, "@dfinity/cbor": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/@dfinity/cbor/-/cbor-0.2.2.tgz", @@ -7446,156 +7109,182 @@ "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "dev": true, "optional": true }, "@esbuild/android-arm": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "dev": true, "optional": true }, "@esbuild/android-arm64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "dev": true, "optional": true }, "@esbuild/android-x64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "dev": true, "optional": true }, "@esbuild/darwin-arm64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "dev": true, "optional": true }, "@esbuild/darwin-x64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "dev": true, "optional": true }, "@esbuild/freebsd-arm64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "dev": true, "optional": true }, "@esbuild/freebsd-x64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "dev": true, "optional": true }, "@esbuild/linux-arm": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "dev": true, "optional": true }, "@esbuild/linux-arm64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "dev": true, "optional": true }, "@esbuild/linux-ia32": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "dev": true, "optional": true }, "@esbuild/linux-loong64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "dev": true, "optional": true }, "@esbuild/linux-mips64el": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "dev": true, "optional": true }, "@esbuild/linux-ppc64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "dev": true, "optional": true }, "@esbuild/linux-riscv64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "dev": true, "optional": true }, "@esbuild/linux-s390x": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "dev": true, "optional": true }, "@esbuild/linux-x64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "dev": true, "optional": true }, "@esbuild/netbsd-arm64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "dev": true, "optional": true }, "@esbuild/netbsd-x64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "dev": true, "optional": true }, "@esbuild/openbsd-arm64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "dev": true, "optional": true }, "@esbuild/openbsd-x64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "dev": true, "optional": true }, "@esbuild/openharmony-arm64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "dev": true, "optional": true }, "@esbuild/sunos-x64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "dev": true, "optional": true }, "@esbuild/win32-arm64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "dev": true, "optional": true }, "@esbuild/win32-ia32": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "dev": true, "optional": true }, "@esbuild/win32-x64": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "dev": true, "optional": true }, "@eslint-community/eslint-plugin-eslint-comments": { @@ -7895,10 +7584,10 @@ "requires": {} }, "@junobuild/cli-tools": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/@junobuild/cli-tools/-/cli-tools-0.12.4.tgz", - "integrity": "sha512-huEUnn9IEb7pbpC66oyepA6uAS29MbNUT98DehdjzZjgsy/tHUZwOSW851ISjWowkRD2MYbc1XsWpoOe4AdCRQ==", + "version": "file:../juno-js/packages/cli-tools", "requires": { + "@types/mime-types": "^3.0.1", + "@types/minimatch": "^6.0.0", "file-type": "^21.3.2", "listr2": "^10.2.1", "mime-types": "^3.0.2", @@ -7906,9 +7595,7 @@ } }, "@junobuild/config": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/@junobuild/config/-/config-2.15.0.tgz", - "integrity": "sha512-4SiFDmayi6GxGFdr0BG/sOSk6iinW0ijv7mD3Xp8ufvVEhzfOsT8Ta6GS+HD2Eb0lRpnvXaAtw6xzdB5ub56cg==", + "version": "file:../juno-js/packages/config", "requires": {} }, "@junobuild/config-loader": { @@ -8031,20 +7718,6 @@ "@scure/base": "~1.2.5" } }, - "@tokenizer/inflate": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz", - "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==", - "requires": { - "debug": "^4.4.3", - "token-types": "^6.1.1" - } - }, - "@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" - }, "@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -8531,15 +8204,6 @@ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-3.3.0.tgz", "integrity": "sha512-/+40ljC3ONVnYIttjMWrlL51nItDAbBrq2upN8BPyvGU/2n5Oxw3tbNwORCaNuNqLJnxGqOfjUuhsv7l5Q4IsQ==" }, - "cli-truncate": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", - "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", - "requires": { - "slice-ansi": "^8.0.0", - "string-width": "^8.2.0" - } - }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -8724,11 +8388,6 @@ "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==", "peer": true }, - "emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==" - }, "enhanced-resolve": { "version": "5.18.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", @@ -8868,6 +8527,7 @@ "version": "0.27.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "dev": true, "requires": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", @@ -9259,11 +8919,6 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, - "eventemitter3": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", - "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==" - }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -9302,17 +8957,6 @@ "flat-cache": "^4.0.0" } }, - "file-type": { - "version": "21.3.2", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.2.tgz", - "integrity": "sha512-DLkUvGwep3poOV2wpzbHCOnSKGk1LzyXTv+aHFgN2VFl96wnp8YA9YjO2qPzg5PuL8q/SW9Pdi6WTkYOIh995w==", - "requires": { - "@tokenizer/inflate": "^0.4.1", - "strtok3": "^10.3.4", - "token-types": "^6.1.1", - "uint8array-extras": "^1.4.0" - } - }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -9543,11 +9187,6 @@ "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==", "peer": true }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, "ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -9680,14 +9319,6 @@ "call-bound": "^1.0.3" } }, - "is-fullwidth-code-point": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", - "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", - "requires": { - "get-east-asian-width": "^1.3.1" - } - }, "is-generator-function": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", @@ -9932,18 +9563,6 @@ "type-check": "~0.4.0" } }, - "listr2": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-10.2.1.tgz", - "integrity": "sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q==", - "requires": { - "cli-truncate": "^5.2.0", - "eventemitter3": "^5.0.4", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", - "wrap-ansi": "^10.0.0" - } - }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -9968,54 +9587,6 @@ "yoctocolors": "^2.1.1" } }, - "log-update": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", - "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", - "requires": { - "ansi-escapes": "^7.0.0", - "cli-cursor": "^5.0.0", - "slice-ansi": "^7.1.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==" - }, - "slice-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", - "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", - "requires": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" - } - }, - "string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "requires": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - } - }, - "wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "requires": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - } - } - } - }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -10036,47 +9607,11 @@ "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==" }, - "mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==" - }, - "mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", - "requires": { - "mime-db": "^1.54.0" - } - }, "mimic-function": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==" }, - "minimatch": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", - "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", - "requires": { - "brace-expansion": "^5.0.2" - }, - "dependencies": { - "balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==" - }, - "brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", - "requires": { - "balanced-match": "^4.0.2" - } - } - } - }, "minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -10435,11 +9970,6 @@ "signal-exit": "^4.1.0" } }, - "rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" - }, "run-applescript": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", @@ -10594,22 +10124,6 @@ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" }, - "slice-ansi": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-8.0.0.tgz", - "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", - "requires": { - "ansi-styles": "^6.2.3", - "is-fullwidth-code-point": "^5.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==" - } - } - }, "stdin-discarder": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", @@ -10692,14 +10206,6 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, - "strtok3": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz", - "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==", - "requires": { - "@tokenizer/token": "^0.3.0" - } - }, "stubborn-fs": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/stubborn-fs/-/stubborn-fs-1.2.5.tgz", @@ -10766,16 +10272,6 @@ "picomatch": "^4.0.3" } }, - "token-types": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz", - "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==", - "requires": { - "@borewit/text-codec": "^0.2.1", - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - } - }, "ts-api-utils": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", @@ -11002,23 +10498,6 @@ "has-tostringtag": "^1.0.2" } }, - "wrap-ansi": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-10.0.0.tgz", - "integrity": "sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==", - "requires": { - "ansi-styles": "^6.2.3", - "string-width": "^8.2.0", - "strip-ansi": "^7.1.2" - }, - "dependencies": { - "ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==" - } - } - }, "wsl-utils": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.0.tgz", diff --git a/package.json b/package.json index 9e48be9..b95fcd1 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,8 @@ "@icp-sdk/core": "^5.0.0", "@junobuild/admin": "^4.2.1", "@junobuild/cdn": "^2.3.1", - "@junobuild/cli-tools": "^0.12.4", - "@junobuild/config": "^2.15.0", + "@junobuild/cli-tools": "file:../juno-js/packages/cli-tools", + "@junobuild/config": "file:../juno-js/packages/config", "@junobuild/config-loader": "^0.4.9", "@junobuild/core": "^5.2.2", "@junobuild/functions-tools": "^0.5.3", diff --git a/src/commands/storage.ts b/src/commands/storage.ts new file mode 100644 index 0000000..0b56765 --- /dev/null +++ b/src/commands/storage.ts @@ -0,0 +1,45 @@ +import {red} from 'kleur'; +import {logHelpStorageClear} from '../help/storage.clear.help'; +import {logHelpStorageDeploy} from '../help/storage.deploy.help'; +import {logHelpStorage} from '../help/storage.help'; +import {logHelpStoragePrune} from '../help/storage.prune.help'; +import {clearStorage} from '../services/storage/clear.services'; +import {deployStorage} from '../services/storage/deploy.services'; +import {pruneStorage} from '../services/storage/prune.services'; + +export const storage = async (args?: string[]) => { + const [subCommand] = args ?? []; + + switch (subCommand) { + case 'deploy': + await deployStorage(args); + break; + case 'clear': + await clearStorage(args); + break; + case 'prune': + await pruneStorage(args); + break; + default: + console.log(red('Unknown subcommand.')); + logHelpStorage(args); + } +}; + +export const helpStorage = (args?: string[]) => { + const [subCommand] = args ?? []; + + switch (subCommand) { + case 'deploy': + logHelpStorageDeploy(args); + break; + case 'clear': + logHelpStorageClear(args); + break; + case 'prune': + logHelpStoragePrune(args); + break; + default: + logHelpStorage(args); + } +}; diff --git a/src/constants/help.constants.ts b/src/constants/help.constants.ts index 3d1da38..63e8b7a 100644 --- a/src/constants/help.constants.ts +++ b/src/constants/help.constants.ts @@ -31,6 +31,13 @@ export const HOSTING_CLEAR_DESCRIPTION = export const HOSTING_PRUNE_DESCRIPTION = 'Remove stale frontend files from your satellite that are no longer in your build output.'; +export const STORAGE_DESCRIPTION = + 'Deploy and manage assets in your satellite storage collections.'; +export const STORAGE_DEPLOY_DESCRIPTION = 'Deploy files to your satellite storage collections.'; +export const STORAGE_CLEAR_DESCRIPTION = 'Remove assets from your satellite storage collections.'; +export const STORAGE_PRUNE_DESCRIPTION = + 'Remove stale assets from your satellite storage collections that are no longer in your local source.'; + export const EMULATOR_START_DESCRIPTION = 'Start the emulator for local development.'; export const EMULATOR_WAIT_DESCRIPTION = 'Wait until the emulator is ready.'; export const EMULATOR_CLEAR_DESCRIPTION = 'Clear the local emulator state (volume and container).'; diff --git a/src/help/help.ts b/src/help/help.ts index 8181e06..4cac5be 100644 --- a/src/help/help.ts +++ b/src/help/help.ts @@ -12,6 +12,7 @@ import { START_DESCRIPTION, STATUS_DESCRIPTION, STOP_DESCRIPTION, + STORAGE_DESCRIPTION, UPGRADE_DESCRIPTION, VERSION_DESCRIPTION, WHOAMI_DESCRIPTION @@ -44,6 +45,7 @@ Commands: ${cyan('start')} ${START_DESCRIPTION} ${cyan('stop')} ${STOP_DESCRIPTION} ${cyan('status')} ${STATUS_DESCRIPTION} + ${cyan('storage')} ${STORAGE_DESCRIPTION} ${cyan('upgrade')} ${UPGRADE_DESCRIPTION} ${cyan('version')} ${VERSION_DESCRIPTION} ${cyan('whoami')} ${WHOAMI_DESCRIPTION} diff --git a/src/help/storage.clear.help.ts b/src/help/storage.clear.help.ts new file mode 100644 index 0000000..bf7280c --- /dev/null +++ b/src/help/storage.clear.help.ts @@ -0,0 +1,30 @@ +import {cyan, green, magenta, yellow} from 'kleur'; +import {STORAGE_CLEAR_DESCRIPTION} from '../constants/help.constants'; +import {helpOutput} from './common.help'; +import {TITLE} from './help'; + +const usage = `Usage: ${green('juno')} ${cyan('storage')} ${magenta('clear')} ${yellow('[options]')} + +Options: + ${yellow('-c, --collection')} Specify the collection to clear a specific file from. + ${yellow('-f, --fullPath')} Specify the full path of a specific file to clear. + ${yellow('-m, --mode')} Choose which environment to use (production, staging, development). + ${yellow('-h, --help')} Output usage information.`; + +const doc = `${STORAGE_CLEAR_DESCRIPTION} + +\`\`\` +${usage} +\`\`\` +`; + +const help = `${TITLE} + +${STORAGE_CLEAR_DESCRIPTION} + +${usage} +`; + +export const logHelpStorageClear = (args?: string[]) => { + console.log(helpOutput(args) === 'doc' ? doc : help); +}; diff --git a/src/help/storage.deploy.help.ts b/src/help/storage.deploy.help.ts new file mode 100644 index 0000000..2868e76 --- /dev/null +++ b/src/help/storage.deploy.help.ts @@ -0,0 +1,30 @@ +import {cyan, green, magenta, yellow} from 'kleur'; +import {STORAGE_DEPLOY_DESCRIPTION} from '../constants/help.constants'; +import {helpOutput} from './common.help'; +import {TITLE} from './help'; + +const usage = `Usage: ${green('juno')} ${cyan('storage')} ${magenta('deploy')} ${yellow('[options]')} + +Options: + ${yellow('--batch')} Number of files to upload per batch. + ${yellow('--prune')} Remove stale remote assets not present in local source after deploy. + ${yellow('-m, --mode')} Choose which environment to use (production, staging, development). + ${yellow('-h, --help')} Output usage information.`; + +const doc = `${STORAGE_DEPLOY_DESCRIPTION} + +\`\`\` +${usage} +\`\`\` +`; + +const help = `${TITLE} + +${STORAGE_DEPLOY_DESCRIPTION} + +${usage} +`; + +export const logHelpStorageDeploy = (args?: string[]) => { + console.log(helpOutput(args) === 'doc' ? doc : help); +}; diff --git a/src/help/storage.help.ts b/src/help/storage.help.ts new file mode 100644 index 0000000..52ce592 --- /dev/null +++ b/src/help/storage.help.ts @@ -0,0 +1,34 @@ +import {cyan, green, magenta, yellow} from 'kleur'; +import { + STORAGE_CLEAR_DESCRIPTION, + STORAGE_DEPLOY_DESCRIPTION, + STORAGE_DESCRIPTION, + STORAGE_PRUNE_DESCRIPTION +} from '../constants/help.constants'; +import {helpOutput} from './common.help'; +import {TITLE} from './help'; + +const usage = `Usage: ${green('juno')} ${cyan('storage')} ${magenta('')} ${yellow('[options]')} + +Subcommands: + ${magenta('clear')} ${STORAGE_CLEAR_DESCRIPTION} + ${magenta('deploy')} ${STORAGE_DEPLOY_DESCRIPTION} + ${magenta('prune')} ${STORAGE_PRUNE_DESCRIPTION}`; + +const doc = `${STORAGE_DESCRIPTION} + +\`\`\` +${usage} +\`\`\` +`; + +const help = `${TITLE} + +${STORAGE_DESCRIPTION} + +${usage} +`; + +export const logHelpStorage = (args?: string[]) => { + console.log(helpOutput(args) === 'doc' ? doc : help); +}; diff --git a/src/help/storage.prune.help.ts b/src/help/storage.prune.help.ts new file mode 100644 index 0000000..b2368d8 --- /dev/null +++ b/src/help/storage.prune.help.ts @@ -0,0 +1,28 @@ +import {cyan, green, magenta, yellow} from 'kleur'; +import {STORAGE_PRUNE_DESCRIPTION} from '../constants/help.constants'; +import {helpOutput} from './common.help'; +import {TITLE} from './help'; + +const usage = `Usage: ${green('juno')} ${cyan('storage')} ${magenta('prune')} ${yellow('[options]')} + +Options: + ${yellow('-m, --mode')} Choose which environment to use (production, staging, development). + ${yellow('-h, --help')} Output usage information.`; + +const doc = `${STORAGE_PRUNE_DESCRIPTION} + +\`\`\` +${usage} +\`\`\` +`; + +const help = `${TITLE} + +${STORAGE_PRUNE_DESCRIPTION} + +${usage} +`; + +export const logHelpStoragePrune = (args?: string[]) => { + console.log(helpOutput(args) === 'doc' ? doc : help); +}; diff --git a/src/index.ts b/src/index.ts index 94a8dd4..5d1a786 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,6 +15,7 @@ import {helpHosting, hosting} from './commands/hosting'; import {open} from './commands/open'; import {helpRun, run as runCmd} from './commands/run'; import {helpSnapshot, snapshot} from './commands/snapshot'; +import {helpStorage, storage} from './commands/storage'; import {startStop} from './commands/start-stop'; import {status} from './commands/status'; import {upgrade} from './commands/upgrade'; @@ -98,6 +99,9 @@ export const run = async () => { case 'snapshot': helpSnapshot(args); break; + case 'storage': + helpStorage(args); + break; case 'init': helpInit(args); break; @@ -188,6 +192,9 @@ export const run = async () => { case 'snapshot': await snapshot(args); break; + case 'storage': + await storage(args); + break; case 'changes': await changes(args); break; diff --git a/src/services/storage/clear.services.ts b/src/services/storage/clear.services.ts new file mode 100644 index 0000000..abace23 --- /dev/null +++ b/src/services/storage/clear.services.ts @@ -0,0 +1,80 @@ +import {isNullish} from '@dfinity/utils'; +import {deleteAssets} from '@junobuild/admin'; +import {hasArgs, nextArg} from '@junobuild/cli-tools'; +import {deleteAsset} from '@junobuild/core'; +import {cyan, green, yellow} from 'kleur'; +import ora from 'ora'; +import {noJunoConfig} from '../../configs/juno.config'; +import {assertConfigAndLoadSatelliteContext} from '../../utils/juno.config.utils'; +import {consoleNoConfigFound} from '../../utils/msg.utils'; + +export const clearStorage = async (args?: string[]) => { + if (await noJunoConfig()) { + consoleNoConfigFound(); + return; + } + + const {satellite, satelliteConfig} = await assertConfigAndLoadSatelliteContext(); + const deployMappings = satelliteConfig.deploy; + + if (isNullish(deployMappings) || deployMappings.length === 0) { + console.log(yellow('No storage deploy mappings found in configuration.')); + return; + } + + if (hasArgs({args, options: ['-f', '--fullpath', '--fullPath']})) { + const file = + nextArg({args, option: '-f'}) ?? + nextArg({args, option: '--fullpath'}) ?? + nextArg({args, option: '--fullPath'}); + const collection = nextArg({args, option: '-c'}) ?? nextArg({args, option: '--collection'}); + + if (isNullish(file) || isNullish(collection)) { + console.log( + `Provide both ${yellow('--collection')} and ${yellow('--fullPath')} to clear a specific file.` + ); + return; + } + + const spinner = ora(`Clearing ${file} from collection "${collection}"...`).start(); + + try { + await deleteAsset({ + collection, + satellite, + fullPath: cleanFullPath(file) + }); + + console.log(`${green('āœ”')} ${file} cleared from "${collection}".`); + } finally { + spinner.stop(); + } + + return; + } + + for (const {collection} of deployMappings) { + const spinner = ora(`Clearing collection "${collection}"...`).start(); + + try { + await deleteAssets({ + collection, + satellite + }); + + spinner.stop(); + console.log(`${green('āœ”')} Collection ${cyan(`"${collection}"`)} cleared.`); + } catch (err: unknown) { + spinner.stop(); + throw err; + } + } + + console.log(''); + console.log(`${green('āœ”')} All storage collections cleared.`); +}; + +const cleanFullPath = (fullPath: string): string => { + const path = fullPath.replace(/\\/g, '/'); + return `${path.startsWith('/') ? '' : '/'}${path}`; +}; diff --git a/src/services/storage/deploy.services.ts b/src/services/storage/deploy.services.ts new file mode 100644 index 0000000..de58471 --- /dev/null +++ b/src/services/storage/deploy.services.ts @@ -0,0 +1,140 @@ +import {isNullish} from '@dfinity/utils'; +import {listRules} from '@junobuild/admin'; +import {deployToCollection} from '@junobuild/cli-tools'; +import type {EncodingType} from '@junobuild/config'; +import {type Asset, uploadBlob} from '@junobuild/core'; +import {cyan, green, red, yellow} from 'kleur'; +import {lstatSync} from 'node:fs'; +import {noJunoConfig} from '../../configs/juno.config'; +import type {SatelliteParametersWithId} from '../../types/satellite'; +import {assertConfigAndLoadSatelliteContext} from '../../utils/juno.config.utils'; +import {consoleNoConfigFound} from '../../utils/msg.utils'; +import {assertSatelliteMemorySize} from '../assert.services'; +import {parseBatchSize} from '../assets/_args.services'; +import {listAssetsForCollection} from './list.services'; + +export const deployStorage = async (args?: string[]) => { + if (await noJunoConfig()) { + consoleNoConfigFound(); + return; + } + + const {satellite, satelliteConfig} = await assertConfigAndLoadSatelliteContext(); + const deployMappings = satelliteConfig.deploy; + + if (isNullish(deployMappings) || deployMappings.length === 0) { + console.log( + `${yellow('No storage deploy mappings found.')} Add a ${cyan('"deploy"')} section to your Juno configuration.` + ); + console.log(''); + console.log('Example:'); + console.log(' deploy: ['); + console.log(' { source: "storage/audio", collection: "audio" },'); + console.log(' { source: "storage/images", collection: "images" }'); + console.log(' ]'); + return; + } + + const existingRules = await listRules({type: 'storage', satellite}); + const existingCollections = new Set(existingRules.items.map((r) => r.collection)); + + const missingCollections = deployMappings.filter( + ({collection}) => !existingCollections.has(collection) + ); + + if (missingCollections.length > 0) { + const names = missingCollections.map(({collection}) => `"${collection}"`).join(', '); + console.log( + `${red('Cannot proceed with storage deploy.')} The following storage collection${missingCollections.length > 1 ? 's do' : ' does'} not exist: ${names}.` + ); + console.log(''); + console.log( + `Run ${green('juno config apply')} first to create the missing collection${missingCollections.length > 1 ? 's' : ''}.` + ); + process.exit(1); + } + + const {value: uploadBatchSize} = parseBatchSize(args); + + for (const mapping of deployMappings) { + await deployCollectionFromMapping({ + mapping, + satellite, + uploadBatchSize + }); + } + + console.log(''); + console.log(`${green('āœ”')} Storage deploy complete.`); +}; + +const deployCollectionFromMapping = async ({ + mapping: {source, collection}, + satellite, + uploadBatchSize +}: { + mapping: {source: string; collection: string}; + satellite: SatelliteParametersWithId; + uploadBatchSize?: number; +}) => { + console.log(`\nšŸ“¦ ${cyan(source)} → collection ${green(`"${collection}"`)}`); + + const listExistingAssets = async ({startAfter}: {startAfter?: string}): Promise => + await listAssetsForCollection({ + startAfter, + satellite, + collection + }); + + const assertMemory = async () => { + await assertSatelliteMemorySize(); + }; + + const uploadFn = async ({ + filename, + fullPath, + data, + headers, + encoding + }: { + filename: string; + fullPath?: string; + data: Blob; + collection: string; + headers?: Array<[string, string]>; + encoding?: EncodingType; + }) => { + await uploadBlob({ + satellite, + filename, + fullPath, + data, + collection, + headers, + encoding + }); + }; + + await deployToCollection({ + params: { + config: {source}, + listAssets: listExistingAssets, + assertSourceDirExists, + assertMemory, + uploadBatchSize + }, + upload: {uploadFile: uploadFn}, + collection + }); +}; + +const assertSourceDirExists = (source: string) => { + try { + lstatSync(source); + } catch (_err: unknown) { + console.log( + `${red('Cannot proceed with storage deploy.')} Source directory "${source}" does not exist or is not accessible.` + ); + process.exit(1); + } +}; diff --git a/src/services/storage/list.services.ts b/src/services/storage/list.services.ts new file mode 100644 index 0000000..dbe01a3 --- /dev/null +++ b/src/services/storage/list.services.ts @@ -0,0 +1,41 @@ +import {listAssets as listAssetsLib} from '@junobuild/core'; +import type {Asset} from '@junobuild/core'; +import {DEPLOY_LIST_ASSETS_PAGINATION} from '../../constants/deploy.constants'; +import type {SatelliteParametersWithId} from '../../types/satellite'; +import {last} from '../../utils/array.utils'; + +export const listAssetsForCollection = async ({ + startAfter, + satellite, + collection +}: { + startAfter?: string; + satellite: SatelliteParametersWithId; + collection: string; +}): Promise => { + const {items, items_page, matches_pages} = await listAssetsLib({ + collection, + satellite, + filter: { + order: { + desc: true, + field: 'keys' + }, + paginate: { + startAfter, + limit: DEPLOY_LIST_ASSETS_PAGINATION + } + } + }); + + if ((items_page ?? 0n) < (matches_pages ?? 0n)) { + const nextItems = await listAssetsForCollection({ + startAfter: last(items)?.fullPath, + satellite, + collection + }); + return [...items, ...nextItems]; + } + + return items; +}; diff --git a/src/services/storage/prune.services.ts b/src/services/storage/prune.services.ts new file mode 100644 index 0000000..a78c905 --- /dev/null +++ b/src/services/storage/prune.services.ts @@ -0,0 +1,109 @@ +import {isNullish} from '@dfinity/utils'; +import {deleteAsset} from '@junobuild/core'; +import {cyan, green, yellow} from 'kleur'; +import ora from 'ora'; +import {existsSync, readdirSync} from 'node:fs'; +import {join, relative} from 'node:path'; +import {noJunoConfig} from '../../configs/juno.config'; +import type {SatelliteParametersWithId} from '../../types/satellite'; +import {assertConfigAndLoadSatelliteContext} from '../../utils/juno.config.utils'; +import {consoleNoConfigFound} from '../../utils/msg.utils'; +import {listAssetsForCollection} from './list.services'; + +export const pruneStorage = async (_args?: string[]) => { + if (await noJunoConfig()) { + consoleNoConfigFound(); + return; + } + + const {satellite, satelliteConfig} = await assertConfigAndLoadSatelliteContext(); + const deployMappings = satelliteConfig.deploy; + + if (isNullish(deployMappings) || deployMappings.length === 0) { + console.log(yellow('No storage deploy mappings found in configuration.')); + return; + } + + let totalPruned = 0; + + for (const mapping of deployMappings) { + const pruned = await pruneCollection({mapping, satellite}); + totalPruned += pruned; + } + + console.log(''); + if (totalPruned === 0) { + console.log(`${green('āœ”')} No stale storage assets found. Nothing to prune.`); + } else { + console.log(`${green('āœ”')} Pruned ${totalPruned} stale storage asset${totalPruned > 1 ? 's' : ''}.`); + } +}; + +const pruneCollection = async ({ + mapping: {source, collection}, + satellite +}: { + mapping: {source: string; collection: string}; + satellite: SatelliteParametersWithId; +}): Promise => { + const spinner = ora(`Checking collection "${collection}" for stale storage assets...`).start(); + + try { + const remoteAssets = await listAssetsForCollection({satellite, collection}); + + if (remoteAssets.length === 0) { + spinner.stop(); + return 0; + } + + const localPaths = new Set(); + if (existsSync(source)) { + collectLocalPaths(source, source, collection, localPaths); + } + + const staleAssets = remoteAssets.filter((asset) => !localPaths.has(asset.fullPath)); + + if (staleAssets.length === 0) { + spinner.stop(); + return 0; + } + + spinner.text = `Pruning ${staleAssets.length} stale storage asset${staleAssets.length > 1 ? 's' : ''} from "${collection}"...`; + + for (const asset of staleAssets) { + await deleteAsset({ + satellite, + collection, + fullPath: asset.fullPath + }); + } + + spinner.stop(); + console.log( + `${green('āœ”')} Pruned ${staleAssets.length} storage asset${staleAssets.length > 1 ? 's' : ''} from ${cyan(`"${collection}"`)}.` + ); + + return staleAssets.length; + } catch (err: unknown) { + spinner.stop(); + throw err; + } +}; + +/** + * Recursively collect local file paths prefixed with /{collection}/ to match remote fullPaths. + */ +const collectLocalPaths = (dir: string, baseDir: string, collection: string, paths: Set) => { + const entries = readdirSync(dir, {withFileTypes: true}); + + for (const entry of entries) { + const fullFsPath = join(dir, entry.name); + if (entry.isDirectory()) { + collectLocalPaths(fullFsPath, baseDir, collection, paths); + } else { + const relativePath = relative(baseDir, fullFsPath).replace(/\\/g, '/'); + paths.add(`/${collection}/${relativePath}`); + } + } +}; +