diff --git a/package-lock.json b/package-lock.json index d772072..c753c4a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@icp-sdk/core": "^5.0.0", "@junobuild/admin": "^4.2.0", "@junobuild/cdn": "^2.3.0", - "@junobuild/cli-tools": "^0.12.2", + "@junobuild/cli-tools": "^0.12.2-next-2026-03-15.2", "@junobuild/config": "^2.14.1", "@junobuild/config-loader": "^0.4.8", "@junobuild/core": "^5.2.1", @@ -1758,24 +1758,24 @@ } }, "node_modules/@junobuild/cli-tools": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@junobuild/cli-tools/-/cli-tools-0.12.2.tgz", - "integrity": "sha512-YkAxYfAUlQ/s+8JPcaTH7zgXkiyz/hZG6723B56wM9lOR4Dsnr9eYdEwMdoL7VlO1mew8kAIdCKXdTd+y04kAA==", + "version": "0.12.2-next-2026-03-15.2", + "resolved": "https://registry.npmjs.org/@junobuild/cli-tools/-/cli-tools-0.12.2-next-2026-03-15.2.tgz", + "integrity": "sha512-LBfTaUfM2E0a+h8N6syMrQDW4B3am+X19tz6okdDyU7WJpUo5re0PamIayTHl385EEBuImU1LQvTshrs+Cyxag==", "license": "MIT", "dependencies": { - "file-type": "^21.1.1", - "listr2": "^9.0.5", + "file-type": "^21.3.2", + "listr2": "^10.2.1", "mime-types": "^3.0.2", - "minimatch": "^10.1.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" + "@dfinity/utils": "*", + "@junobuild/cdn": "*", + "@junobuild/config": "*", + "@junobuild/functions-tools": "*", + "@junobuild/storage": "*", + "esbuild": "*", + "ora": "*" } }, "node_modules/@junobuild/config": { @@ -2859,22 +2859,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate/node_modules/string-width": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.0.tgz", - "integrity": "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==", - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.5.0", - "strip-ansi": "^7.1.2" - }, - "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", @@ -2893,12 +2877,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "license": "MIT" - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -4004,9 +3982,9 @@ } }, "node_modules/file-type": { - "version": "21.3.1", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.1.tgz", - "integrity": "sha512-SrzXX46I/zsRDjTb82eucsGg0ODq2NpGDp4HcsFKApPy8P8vACjpJRDoGGMfEzhFC0ry61ajd7f72J3603anBA==", + "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", @@ -5056,20 +5034,19 @@ } }, "node_modules/listr2": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", - "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", + "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.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", + "cli-truncate": "^5.2.0", + "eventemitter3": "^5.0.4", "log-update": "^6.1.0", "rfdc": "^1.4.1", - "wrap-ansi": "^9.0.0" + "wrap-ansi": "^10.0.0" }, "engines": { - "node": ">=20.0.0" + "node": ">=22.13.0" } }, "node_modules/locate-path": { @@ -5156,6 +5133,40 @@ "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", @@ -6144,13 +6155,13 @@ } }, "node_modules/string-width": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz", - "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.0.tgz", + "integrity": "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==", "license": "MIT", "dependencies": { - "get-east-asian-width": "^1.3.0", - "strip-ansi": "^7.1.0" + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" }, "engines": { "node": ">=20" @@ -6764,17 +6775,17 @@ } }, "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==", + "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.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" + "ansi-styles": "^6.2.3", + "string-width": "^8.2.0", + "strip-ansi": "^7.1.2" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -6792,23 +6803,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi/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/wsl-utils": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.0.tgz", @@ -7901,14 +7895,14 @@ "requires": {} }, "@junobuild/cli-tools": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@junobuild/cli-tools/-/cli-tools-0.12.2.tgz", - "integrity": "sha512-YkAxYfAUlQ/s+8JPcaTH7zgXkiyz/hZG6723B56wM9lOR4Dsnr9eYdEwMdoL7VlO1mew8kAIdCKXdTd+y04kAA==", + "version": "0.12.2-next-2026-03-15.2", + "resolved": "https://registry.npmjs.org/@junobuild/cli-tools/-/cli-tools-0.12.2-next-2026-03-15.2.tgz", + "integrity": "sha512-LBfTaUfM2E0a+h8N6syMrQDW4B3am+X19tz6okdDyU7WJpUo5re0PamIayTHl385EEBuImU1LQvTshrs+Cyxag==", "requires": { - "file-type": "^21.1.1", - "listr2": "^9.0.5", + "file-type": "^21.3.2", + "listr2": "^10.2.1", "mime-types": "^3.0.2", - "minimatch": "^10.1.2" + "minimatch": "^10.2.4" } }, "@junobuild/config": { @@ -8544,17 +8538,6 @@ "requires": { "slice-ansi": "^8.0.0", "string-width": "^8.2.0" - }, - "dependencies": { - "string-width": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.0.tgz", - "integrity": "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==", - "requires": { - "get-east-asian-width": "^1.5.0", - "strip-ansi": "^7.1.2" - } - } } }, "color-convert": { @@ -8572,11 +8555,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -9325,9 +9303,9 @@ } }, "file-type": { - "version": "21.3.1", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.1.tgz", - "integrity": "sha512-SrzXX46I/zsRDjTb82eucsGg0ODq2NpGDp4HcsFKApPy8P8vACjpJRDoGGMfEzhFC0ry61ajd7f72J3603anBA==", + "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", @@ -9955,16 +9933,15 @@ } }, "listr2": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", - "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", + "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.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", + "cli-truncate": "^5.2.0", + "eventemitter3": "^5.0.4", "log-update": "^6.1.0", "rfdc": "^1.4.1", - "wrap-ansi": "^9.0.0" + "wrap-ansi": "^10.0.0" } }, "locate-path": { @@ -10016,6 +9993,26 @@ "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" + } } } }, @@ -10629,12 +10626,12 @@ } }, "string-width": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz", - "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.0.tgz", + "integrity": "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==", "requires": { - "get-east-asian-width": "^1.3.0", - "strip-ansi": "^7.1.0" + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" } }, "string.prototype.trim": { @@ -11006,29 +11003,19 @@ } }, "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==", + "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.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" + "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==" - }, - "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" - } } } }, diff --git a/package.json b/package.json index 00a4853..9c559eb 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@icp-sdk/core": "^5.0.0", "@junobuild/admin": "^4.2.0", "@junobuild/cdn": "^2.3.0", - "@junobuild/cli-tools": "^0.12.2", + "@junobuild/cli-tools": "^0.12.2-next-2026-03-15.2", "@junobuild/config": "^2.14.1", "@junobuild/config-loader": "^0.4.8", "@junobuild/core": "^5.2.1", diff --git a/src/services/assets/prune.services.ts b/src/services/assets/prune.services.ts index dd3c9bf..48c921e 100644 --- a/src/services/assets/prune.services.ts +++ b/src/services/assets/prune.services.ts @@ -1,60 +1,19 @@ import { COLLECTION_DAPP, - DEPLOY_DEFAULT_IGNORE, - DEPLOY_DEFAULT_SOURCE, hasArgs, - files as listFiles + prune as pruneServices, + type PruneFilesFn, + type PruneFileStorage } from '@junobuild/cli-tools'; import {deleteManyAssets, type Asset} from '@junobuild/core'; -import {green, red, yellow} from 'kleur'; -import {minimatch} from 'minimatch'; -import {join} from 'node:path'; -import ora from 'ora'; +import {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 {listAssets} from './_deploy/deploy.list.services'; -/** - * Converts an absolute file path to its fullPath form. - * e.g. "/path/to/build/index.html" -> "/index.html" - */ -const toFullPath = ({ - file, - sourceAbsolutePath -}: { - file: string; - sourceAbsolutePath: string; -}): string => file.replace(sourceAbsolutePath, '').replace(/\\/g, '/'); - -/** - * Returns true if the file should be excluded based on the ignore patterns. - */ -const isIgnored = ({file, ignore}: {file: string; ignore: string[]}): boolean => - ignore.some((pattern) => minimatch(file, pattern, {matchBase: true})); - -/** - * Returns true if the file should be included for deletion. - */ -const shouldBeIncluded = (params: {file: string; ignore: string[]}): boolean => !isIgnored(params); - -/** - * Scans the local source directory and returns a Set of fullPaths that are present. - * Throws if the directory cannot be read. - */ -const buildLocalPaths = ({ - sourceAbsolutePath, - ignore -}: { - sourceAbsolutePath: string; - ignore: string[]; -}): Set => { - const allFiles = listFiles(sourceAbsolutePath); - const filteredFiles = allFiles.filter((file) => shouldBeIncluded({file, ignore})); - return new Set(filteredFiles.map((file) => toFullPath({file, sourceAbsolutePath}))); -}; - export const prune = async (args?: string[]) => { if (await noJunoConfig()) { consoleNoConfigFound(); @@ -69,101 +28,54 @@ const executePrune = async (args?: string[]) => { const {satellite, satelliteConfig} = await assertConfigAndLoadSatelliteContext(); - const source = satelliteConfig.source ?? DEPLOY_DEFAULT_SOURCE; - const ignore = satelliteConfig.ignore ?? DEPLOY_DEFAULT_IGNORE; - - const sourceAbsolutePath = join(process.cwd(), source); - - // 1. Scan local build output - const localPathsResult = scanLocalFiles({sourceAbsolutePath, ignore}); - - if (localPathsResult.status === 'error') { - console.log( - `${red('Cannot scan source directory.')} Is "${source}" built and configured in juno.config?` - ); - return; - } - - const {paths: localPaths} = localPathsResult; - - // 2. Fetch all live assets (paginated) - const liveAssets = await fetchLiveAssets({satellite}); - - // 3. Compute stale = live_assets − local_files - const stale = liveAssets.filter(({fullPath}) => !localPaths.has(fullPath)); - - if (stale.length === 0) { - console.log(`${green('✔')} No stale assets found. Satellite is already clean.`); - return; - } - - // 4. Report - console.log(`\nFound ${yellow(String(stale.length))} stale asset(s):`); - for (const {fullPath} of stale) { - console.log(` ${yellow('−')} ${fullPath}`); - } + const listExistingAssets = async ({startAfter}: {startAfter?: string}): Promise => + await listAssets({ + startAfter, + satellite + }); - if (dryRun) { + const pruneFn: PruneFilesFn = async (params) => { + await pruneStaleAssets({satellite, ...params}); + }; + + const result = await pruneServices({ + params: { + config: satelliteConfig, + listAssets: listExistingAssets, + assertSourceDirExists, + dryRun + }, + pruneFn + }); + + if (result.result === 'simulated') { console.log(`\n${yellow('[dry-run]')} No files have been deleted.`); - return; - } - - // 5. Delete stale assets - await pruneStaleAssets({stale, satellite}); -}; - -const scanLocalFiles = ({ - sourceAbsolutePath, - ignore -}: { - sourceAbsolutePath: string; - ignore: string[]; -}): {status: 'success'; paths: Set} | {status: 'error'; err: unknown} => { - const scanSpinner = ora('Scanning local build output...').start(); - - try { - const paths = buildLocalPaths({sourceAbsolutePath, ignore}); - return {status: 'success', paths}; - } catch (err: unknown) { - return {status: 'error', err}; - } finally { - scanSpinner.stop(); } }; -const fetchLiveAssets = async ({ +const pruneStaleAssets = async ({ + files, satellite }: { + files: PruneFileStorage[]; satellite: SatelliteParametersWithId; -}): Promise => { - const fetchSpinner = ora('Fetching live assets from satellite...').start(); - - try { - return await listAssets({satellite}); - } finally { - fetchSpinner.stop(); - } +}): Promise => { + await deleteManyAssets({ + assets: files.map(({fullPath}) => ({ + collection: COLLECTION_DAPP, + fullPath + })), + satellite + }); }; -const pruneStaleAssets = async ({ - stale, - satellite -}: { - stale: Asset[]; - satellite: Parameters[0]['satellite']; -}): Promise => { - const deleteSpinner = ora(`Deleting ${stale.length} stale asset(s)...`).start(); +const assertSourceDirExists = (source: string) => { try { - await deleteManyAssets({ - assets: stale.map(({fullPath}) => ({ - collection: COLLECTION_DAPP, - fullPath - })), - satellite - }); - } finally { - deleteSpinner.stop(); + lstatSync(source); + } catch (_err: unknown) { + console.log( + `${red('Cannot scan source directory.')} Is "${source}" built and configured in juno.config?` + ); + process.exit(1); } - - console.log(`\n${green('✔')} Pruned ${stale.length} stale asset(s).`); };