diff --git a/package-lock.json b/package-lock.json index 549ed881..5681073e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,10 +18,10 @@ "@dfinity/zod-schemas": "^1.1.0", "@junobuild/admin": "^2.0.0", "@junobuild/cdn": "^1.1.0", - "@junobuild/cli-tools": "^0.6.0", + "@junobuild/cli-tools": "^0.6.1", "@junobuild/config": "^2.0.0", "@junobuild/config-loader": "^0.4.1", - "@junobuild/core": "^1.1.0", + "@junobuild/core": "^1.1.1", "@junobuild/did-tools": "^0.2.4", "@junobuild/ic-client": "^1.1.0", "@junobuild/storage": "^1.1.0", @@ -1472,9 +1472,9 @@ } }, "node_modules/@junobuild/cli-tools": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@junobuild/cli-tools/-/cli-tools-0.6.0.tgz", - "integrity": "sha512-5PLZzunhdmdWRKv7LmSZGXWkgm/6z9NGR5D13mYf3Dq5u6TK2hdSLYuvQLJhRAbf0AIl0sVZpsgexYfnVEyTBQ==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@junobuild/cli-tools/-/cli-tools-0.6.1.tgz", + "integrity": "sha512-Mfay1WaAH2DYp5A/9G+eV2WPBnA1oFOLe6U2w9VzwbII/LAMzmQJjLQ9uWfRQezBopdbNOoGGAJKmNy5HIN1CQ==", "license": "MIT", "dependencies": { "file-type": "^21.0.0", @@ -1514,9 +1514,9 @@ } }, "node_modules/@junobuild/core": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@junobuild/core/-/core-1.1.0.tgz", - "integrity": "sha512-NwDkqD4MCzG8sU1sj3esdWH6J64zZO4evdeffp0KA+N3KB63gclejxrTwN3mk4y6om0Fv1VgS8RkOe6jsuCA3A==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@junobuild/core/-/core-1.1.1.tgz", + "integrity": "sha512-PTQ4OTrFiIL2Noik5TizSDSz/Q8fz3oPNOHgbgp6reor2LJI7tlaWF1MwqCIN0Z///CylurtTcP7BvLYWcZfvw==", "license": "MIT", "dependencies": { "@junobuild/errors": "*", @@ -7473,9 +7473,9 @@ "requires": {} }, "@junobuild/cli-tools": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@junobuild/cli-tools/-/cli-tools-0.6.0.tgz", - "integrity": "sha512-5PLZzunhdmdWRKv7LmSZGXWkgm/6z9NGR5D13mYf3Dq5u6TK2hdSLYuvQLJhRAbf0AIl0sVZpsgexYfnVEyTBQ==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@junobuild/cli-tools/-/cli-tools-0.6.1.tgz", + "integrity": "sha512-Mfay1WaAH2DYp5A/9G+eV2WPBnA1oFOLe6U2w9VzwbII/LAMzmQJjLQ9uWfRQezBopdbNOoGGAJKmNy5HIN1CQ==", "requires": { "file-type": "^21.0.0", "listr2": "^9.0.1", @@ -7496,9 +7496,9 @@ "requires": {} }, "@junobuild/core": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@junobuild/core/-/core-1.1.0.tgz", - "integrity": "sha512-NwDkqD4MCzG8sU1sj3esdWH6J64zZO4evdeffp0KA+N3KB63gclejxrTwN3mk4y6om0Fv1VgS8RkOe6jsuCA3A==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@junobuild/core/-/core-1.1.1.tgz", + "integrity": "sha512-PTQ4OTrFiIL2Noik5TizSDSz/Q8fz3oPNOHgbgp6reor2LJI7tlaWF1MwqCIN0Z///CylurtTcP7BvLYWcZfvw==", "requires": { "@junobuild/errors": "*", "@junobuild/ic-client": "^1", diff --git a/package.json b/package.json index 948ccaec..c5d107e6 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,10 @@ "@dfinity/zod-schemas": "^1.1.0", "@junobuild/admin": "^2.0.0", "@junobuild/cdn": "^1.1.0", - "@junobuild/cli-tools": "^0.6.0", + "@junobuild/cli-tools": "^0.6.1", "@junobuild/config": "^2.0.0", "@junobuild/config-loader": "^0.4.1", - "@junobuild/core": "^1.1.0", + "@junobuild/core": "^1.1.1", "@junobuild/did-tools": "^0.2.4", "@junobuild/ic-client": "^1.1.0", "@junobuild/storage": "^1.1.0", diff --git a/src/help/deploy.help.ts b/src/help/deploy.help.ts index 27c6d91d..ef5fd402 100644 --- a/src/help/deploy.help.ts +++ b/src/help/deploy.help.ts @@ -12,6 +12,7 @@ import {TITLE} from './help'; const usage = `Usage: ${green('juno')} ${cyan('deploy')} ${yellow('[options]')} Options: + ${yellow('--batch')} Number of files to upload in parallel per batch (default: 20). ${yellow('--clear')} Clear existing app files before proceeding with deployment. ${yellow('--config')} Apply configuration after deployment succeeds. ${yellow('--no-apply')} Submit the deployment as a change but do not apply it yet. diff --git a/src/services/assets/_deploy/deploy.execute.services.ts b/src/services/assets/_deploy/deploy.execute.services.ts index fd0a6f39..d0d81c62 100644 --- a/src/services/assets/_deploy/deploy.execute.services.ts +++ b/src/services/assets/_deploy/deploy.execute.services.ts @@ -12,6 +12,7 @@ import {red} from 'kleur'; import {lstatSync} from 'node:fs'; import { type DeployFnParams, + type DeployOptions, type UploadFileFnParams, type UploadFn, type UploadInput, @@ -26,7 +27,7 @@ export const executeDeployWithProposal = async ({ options, ...rest }: { - options: {deprecatedGzip?: string}; + options: DeployOptions; } & UploadFn): Promise => { return await executeDeploy({ options, @@ -41,7 +42,7 @@ export const executeDeployImmediate = async ({ }: { deployFn: (params: DeployFnParams) => Promise; uploadFn: (params: UploadFileFnParams) => Promise; - options: {deprecatedGzip?: string}; + options: DeployOptions; }): Promise => { return await executeDeploy({ deployFn, @@ -55,19 +56,19 @@ const executeDeploy = async < P extends UploadFileStorage, R extends DeployResult | DeployResultWithProposal >({ - options, + options: {deprecatedGzip, ...restOptions}, ...rest }: { - options: {deprecatedGzip?: string}; + options: DeployOptions; } & UploadFn): Promise => { const {satellite, satelliteConfig: satelliteConfigRead} = await assertConfigAndLoadSatelliteContext(); const precompress = satelliteConfigRead.precompress ?? - (nonNullish(options.deprecatedGzip) + (nonNullish(deprecatedGzip) ? { - pattern: options.deprecatedGzip + pattern: deprecatedGzip } : undefined); @@ -80,6 +81,7 @@ const executeDeploy = async < const result = await deployWithMethod({ ...rest, + ...restOptions, satellite, satelliteConfig }); @@ -100,12 +102,14 @@ const deployWithMethod = async < deployFn, uploadFn, method, + uploadBatchSize, satellite, satelliteConfig }: { satellite: SatelliteParametersWithId; satelliteConfig: SatelliteConfig; -} & UploadFn): Promise => { +} & Omit & + UploadFn): Promise => { const assertMemory = async () => { await assertSatelliteMemorySize(); }; @@ -120,7 +124,8 @@ const deployWithMethod = async < config: satelliteConfig, listAssets: listExistingAssets, assertSourceDirExists, - assertMemory + assertMemory, + uploadBatchSize }; if (method === 'batch') { diff --git a/src/services/assets/_deploy/deploy.individual.services.ts b/src/services/assets/_deploy/deploy.individual.services.ts index 142d5d2f..4f52eb6b 100644 --- a/src/services/assets/_deploy/deploy.individual.services.ts +++ b/src/services/assets/_deploy/deploy.individual.services.ts @@ -1,17 +1,20 @@ import type {DeployResult} from '@junobuild/cli-tools'; import {deploy as cliDeploy} from '@junobuild/cli-tools'; import {uploadBlob} from '@junobuild/core'; -import type {DeployFnParams, UploadFileFnParams} from '../../../types/deploy'; +import { + type DeployFnParams, + type DeployOptions, + type UploadFileFnParams +} from '../../../types/deploy'; import {clear} from '../clear.services'; import {executeDeployImmediate} from './deploy.execute.services'; export const deployImmediate = async ({ clearOption, - deprecatedGzip + ...restOptions }: { clearOption: boolean; - deprecatedGzip: string | undefined; -}) => { +} & DeployOptions) => { if (clearOption) { await clear(); } @@ -45,6 +48,6 @@ export const deployImmediate = async ({ await executeDeployImmediate({ deployFn, uploadFn, - options: {deprecatedGzip} + options: restOptions }); }; diff --git a/src/services/assets/_deploy/deploy.with-proposal.services.ts b/src/services/assets/_deploy/deploy.with-proposal.services.ts index dd83ad01..e3720d32 100644 --- a/src/services/assets/_deploy/deploy.with-proposal.services.ts +++ b/src/services/assets/_deploy/deploy.with-proposal.services.ts @@ -12,17 +12,17 @@ import { import type {UploadAsset} from '@junobuild/storage'; import { type DeployFnParams, + type DeployOptions, type UploadFileFnParamsWithProposal, type UploadFilesFnParamsWithProposal } from '../../../types/deploy'; import type {SatelliteParametersWithId} from '../../../types/satellite'; import {executeDeployWithProposal} from './deploy.execute.services'; -interface DeployWithProposalParams { +type DeployWithProposalParams = DeployOptions & { clearOption: boolean; - deprecatedGzip: string | undefined; noCommit: boolean; -} +}; export const deployWithProposal = async ({ withBatch, @@ -35,6 +35,7 @@ export const deployWithProposal = async ({ const uploadFilesIndividually = async ({ deprecatedGzip, + uploadBatchSize, ...cliParams }: DeployWithProposalParams): Promise => { const uploadFn = async ({ @@ -64,13 +65,14 @@ const uploadFilesIndividually = async ({ return await executeDeployWithProposal({ deployFn, uploadFn, - options: {deprecatedGzip}, + options: {deprecatedGzip, uploadBatchSize}, method: 'individual' }); }; const uploadFilesWithBatch = async ({ deprecatedGzip, + uploadBatchSize, ...cliParams }: DeployWithProposalParams): Promise => { const uploadFn = async ({files, satellite, ...rest}: UploadFilesFnParamsWithProposal) => { @@ -95,7 +97,7 @@ const uploadFilesWithBatch = async ({ deployFn, uploadFn, method: 'batch', - options: {deprecatedGzip} + options: {deprecatedGzip, uploadBatchSize} }); }; @@ -109,7 +111,7 @@ const deployWithUpload = async ({ upload: UploadIndividually | UploadWithBatch; }; satellite: SatelliteParametersWithId; - cliParams: Omit; + cliParams: Omit; }): Promise => await cliDeployWithProposal({ deploy: { diff --git a/src/services/assets/deploy.services.ts b/src/services/assets/deploy.services.ts index e0033e83..c88bc809 100644 --- a/src/services/assets/deploy.services.ts +++ b/src/services/assets/deploy.services.ts @@ -1,6 +1,8 @@ -import {hasArgs} from '@junobuild/cli-tools'; +import {isEmptyString} from '@dfinity/utils'; +import {hasArgs, nextArg} from '@junobuild/cli-tools'; import {yellow} from 'kleur'; import {compare} from 'semver'; +import {type DeployOptions} from '../../types/deploy'; import {clearProposalStagedAssets} from '../changes/changes.clear.services'; import {getSatelliteVersion} from '../version.services'; import {deployImmediate} from './_deploy/deploy.individual.services'; @@ -20,11 +22,13 @@ export const deploy = async (args?: string[]) => { // wouldn't harm usage, it might prevent crawlers from properly fetching content. const deprecatedGzip = compare(result.version, '0.1.1') < 0 ? '**/*.+(css|js|mjs)' : undefined; + const {value: uploadBatchSize} = parseUploadBatchSize(args); + const clearOption = hasArgs({args, options: ['--clear']}); const immediate = hasArgs({args, options: ['-i', '--immediate']}); if (immediate) { - await deployImmediate({clearOption, deprecatedGzip}); + await deployImmediate({clearOption, deprecatedGzip, uploadBatchSize}); return; } @@ -36,7 +40,7 @@ export const deploy = async (args?: string[]) => { console.log( `${yellow('[Warn]')} Your Satellite is outdated. Please upgrade to take full advantage of the new deployment flow.` ); - await deployImmediate({clearOption, deprecatedGzip}); + await deployImmediate({clearOption, deprecatedGzip, uploadBatchSize}); return; } @@ -44,27 +48,22 @@ export const deploy = async (args?: string[]) => { // const withBatch = compare(result.version, '0.1.2') >= 0; const withBatch = true; - await deployWithProposal({args, clearOption, deprecatedGzip, withBatch}); + await deployWithProposal({args, clearOption, deprecatedGzip, uploadBatchSize, withBatch}); }; const deployWithProposal = async ({ args, - clearOption, - withBatch, - deprecatedGzip + ...rest }: { args?: string[]; clearOption: boolean; withBatch: boolean; - deprecatedGzip: string | undefined; -}) => { +} & DeployOptions) => { const noCommit = hasArgs({args, options: ['--no-apply']}); const result = await executeDeployWithProposal({ - withBatch, - clearOption, - deprecatedGzip, - noCommit + noCommit, + ...rest }); if (result.result !== 'deployed') { @@ -78,3 +77,23 @@ const deployWithProposal = async ({ proposalId }); }; + +const parseUploadBatchSize = (args?: string[]): {valid: boolean; value?: number} => { + const batchArg = nextArg({args, option: '--batch'}); + + if (isEmptyString(batchArg)) { + return {valid: true}; + } + + const batch = parseInt(batchArg); + + if (isNaN(batch)) { + return {valid: false}; + } + + if (batch <= 0) { + return {valid: false}; + } + + return {valid: true, value: batch}; +}; diff --git a/src/types/deploy.ts b/src/types/deploy.ts index d9bfa07f..b1f60dc0 100644 --- a/src/types/deploy.ts +++ b/src/types/deploy.ts @@ -8,6 +8,11 @@ import type { import type {OnUploadProgress} from '@junobuild/storage'; import type {SatelliteParametersWithId} from './satellite'; +export interface DeployOptions { + deprecatedGzip?: string; + uploadBatchSize: number | undefined; +} + export interface DeployFnParams { deploy: {params: DeployParams; upload: T}; satellite: SatelliteParametersWithId;