netlify-cli 27.12.0 → 27.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/deploy/deploy.js +28 -59
- package/dist/lib/spinner.d.ts +2 -2
- package/dist/lib/spinner.js +1 -1
- package/dist/utils/deploy/deploy-site.d.ts +32 -12
- package/dist/utils/deploy/deploy-site.js +18 -40
- package/dist/utils/deploy/drop-api.d.ts +7 -1
- package/dist/utils/deploy/drop-api.js +3 -4
- package/dist/utils/deploy/file.d.ts +4 -2
- package/dist/utils/deploy/hash-config.d.ts +5 -6
- package/dist/utils/deploy/hash-config.js +1 -4
- package/dist/utils/deploy/hash-files.d.ts +9 -8
- package/dist/utils/deploy/hash-fns.d.ts +45 -10
- package/dist/utils/deploy/hasher-segments.d.ts +10 -6
- package/dist/utils/deploy/hasher-segments.js +0 -1
- package/dist/utils/deploy/process-files.d.ts +1 -1
- package/dist/utils/deploy/process-files.js +1 -0
- package/dist/utils/deploy/types.d.ts +17 -0
- package/dist/utils/deploy/types.js +2 -0
- package/dist/utils/deploy/upload-files.d.ts +8 -3
- package/dist/utils/deploy/upload-files.js +4 -3
- package/dist/utils/deploy/upload-source-zip.js +4 -7
- package/dist/utils/deploy/util.d.ts +6 -3
- package/dist/utils/deploy/util.js +4 -16
- package/functions-templates/javascript/scheduled-function/package.json +1 -1
- package/functions-templates/typescript/database/package-lock.json +8 -8
- package/functions-templates/typescript/database/package.json +1 -1
- package/functions-templates/typescript/database-drizzle/package-lock.json +8 -8
- package/functions-templates/typescript/database-drizzle/package.json +1 -1
- package/functions-templates/typescript/hello-world/package-lock.json +15 -17
- package/functions-templates/typescript/hello-world/package.json +1 -1
- package/functions-templates/typescript/scheduled-function/package.json +1 -1
- package/package.json +2 -2
|
@@ -166,13 +166,6 @@ const validateFolders = async ({ deployFolder, functionsFolder, }) => {
|
|
|
166
166
|
const functionsFolderStat = await validateFunctionsFolder(functionsFolder);
|
|
167
167
|
return { deployFolderStat, functionsFolderStat };
|
|
168
168
|
};
|
|
169
|
-
/**
|
|
170
|
-
* @param {object} config
|
|
171
|
-
* @param {string} config.deployFolder
|
|
172
|
-
* @param {*} config.site
|
|
173
|
-
* @returns
|
|
174
|
-
*/
|
|
175
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'deployFolder' implicitly has an '... Remove this comment to see the full error message
|
|
176
169
|
const getDeployFilesFilter = ({ deployFolder, site }) => {
|
|
177
170
|
// site.root === deployFolder can happen when users run `netlify deploy --dir .`
|
|
178
171
|
// in that specific case we don't want to publish the repo node_modules
|
|
@@ -258,9 +251,9 @@ const generateDeployCommand = (options, availableTeams, command) => {
|
|
|
258
251
|
}
|
|
259
252
|
return parts.join(' ');
|
|
260
253
|
};
|
|
261
|
-
|
|
262
|
-
const prepareProductionDeploy = async ({ api, siteData, options, command }) => {
|
|
254
|
+
const prepareProductionDeploy = async ({ api, siteData, options, command, }) => {
|
|
263
255
|
if (typeof siteData.published_deploy === 'object' &&
|
|
256
|
+
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain -- FIXME: a non-object `published_deploy` must not count as locked
|
|
264
257
|
siteData.published_deploy !== null &&
|
|
265
258
|
siteData.published_deploy.locked) {
|
|
266
259
|
log(`\n${NETLIFYDEVERR} Deployments are "locked" for production context of this project\n`);
|
|
@@ -337,6 +330,7 @@ const deployProgressCb = function () {
|
|
|
337
330
|
return;
|
|
338
331
|
case 'stop':
|
|
339
332
|
default: {
|
|
333
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- FIXME: a `stop` event is assumed to follow a `start` event of the same type
|
|
340
334
|
spinnersByType[event.type].success(event.msg);
|
|
341
335
|
delete spinnersByType[event.type];
|
|
342
336
|
}
|
|
@@ -357,7 +351,7 @@ const uploadDeployBlobs = async ({ cachedConfig, deployId, options, packagePath,
|
|
|
357
351
|
// We log our own progress so we don't want this as well. Plus, this logs much of the same
|
|
358
352
|
// information as the build that (likely) came before this as part of the deploy build.
|
|
359
353
|
quiet: options.debug ?? true,
|
|
360
|
-
// @ts-expect-error(
|
|
354
|
+
// @ts-expect-error FIXME(@netlify/build): the `cachedConfig` flag is typed `Record<string, unknown>`, rejecting `CachedConfig`
|
|
361
355
|
cachedConfig,
|
|
362
356
|
packagePath,
|
|
363
357
|
deployId,
|
|
@@ -378,37 +372,7 @@ const uploadDeployBlobs = async ({ cachedConfig, deployId, options, packagePath,
|
|
|
378
372
|
phase: 'stop',
|
|
379
373
|
});
|
|
380
374
|
};
|
|
381
|
-
const runDeploy = async ({
|
|
382
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'alias' implicitly has an 'any' ty... Remove this comment to see the full error message
|
|
383
|
-
alias,
|
|
384
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message
|
|
385
|
-
api, command,
|
|
386
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message
|
|
387
|
-
config,
|
|
388
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'deployFolder' implicitly has an '... Remove this comment to see the full error message
|
|
389
|
-
deployFolder,
|
|
390
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'deployTimeout' implicitly has an ... Remove this comment to see the full error message
|
|
391
|
-
deployTimeout,
|
|
392
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'deployToProduction' implicitly ha... Remove this comment to see the full error message
|
|
393
|
-
deployToProduction,
|
|
394
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'functionsConfig' implicitly has a... Remove this comment to see the full error message
|
|
395
|
-
functionsConfig, functionsFolder,
|
|
396
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'options' implicitly has an 'a... Remove this comment to see the full error message
|
|
397
|
-
options,
|
|
398
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'packagePath' implicitly has an 'a... Remove this comment to see the full error message
|
|
399
|
-
packagePath,
|
|
400
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'silent' implicitly has an 'any' t... Remove this comment to see the full error message
|
|
401
|
-
silent,
|
|
402
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'site' implicitly has an 'any' typ... Remove this comment to see the full error message
|
|
403
|
-
site,
|
|
404
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'siteData' implicitly has an 'any'... Remove this comment to see the full error message
|
|
405
|
-
siteData,
|
|
406
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'siteId' implicitly has an 'any' t... Remove this comment to see the full error message
|
|
407
|
-
siteId,
|
|
408
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'skipFunctionsCache' implicitly ha... Remove this comment to see the full error message
|
|
409
|
-
skipFunctionsCache,
|
|
410
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'title' implicitly has an 'any' ty... Remove this comment to see the full error message
|
|
411
|
-
title, deployId: existingDeployId, }) => {
|
|
375
|
+
const runDeploy = async ({ alias, api, command, config, deployFolder, deployTimeout, deployToProduction, functionsConfig, functionsFolder, options, packagePath, silent, site, siteData, siteId, skipFunctionsCache, title, deployId: existingDeployId, }) => {
|
|
412
376
|
let results;
|
|
413
377
|
let deployId = existingDeployId;
|
|
414
378
|
let uploadSourceZipResult;
|
|
@@ -426,7 +390,11 @@ title, deployId: existingDeployId, }) => {
|
|
|
426
390
|
include_upload_url: options.uploadSourceZip,
|
|
427
391
|
...getDeploySourceFields(),
|
|
428
392
|
};
|
|
429
|
-
const createDeployResponse = await api.createSiteDeploy({
|
|
393
|
+
const createDeployResponse = (await api.createSiteDeploy({
|
|
394
|
+
siteId,
|
|
395
|
+
title,
|
|
396
|
+
body: createDeployBody,
|
|
397
|
+
}));
|
|
430
398
|
deployId = createDeployResponse.id;
|
|
431
399
|
if (options.uploadSourceZip &&
|
|
432
400
|
createDeployResponse.source_zip_upload_url &&
|
|
@@ -449,17 +417,21 @@ title, deployId: existingDeployId, }) => {
|
|
|
449
417
|
command.netlify.frameworksAPIPaths.functions.path,
|
|
450
418
|
functionsFolder,
|
|
451
419
|
].filter((folder) => Boolean(folder));
|
|
452
|
-
const manifestPath = skipFunctionsCache
|
|
420
|
+
const manifestPath = skipFunctionsCache
|
|
421
|
+
? undefined
|
|
422
|
+
: await getFunctionsManifestPath({ base: site.root, packagePath });
|
|
453
423
|
const serverManifestPath = await getServerManifestPath({ base: site.root, packagePath });
|
|
454
424
|
const redirectsPath = `${deployFolder}/_redirects`;
|
|
455
425
|
const headersPath = `${deployFolder}/_headers`;
|
|
456
426
|
const { redirects } = await parseAllRedirects({
|
|
427
|
+
// @ts-expect-error FIXME(@netlify/redirect-parser): `configRedirects` is typed `string[]` but takes redirect objects
|
|
457
428
|
configRedirects: config.redirects,
|
|
458
429
|
redirectsFiles: [redirectsPath],
|
|
459
430
|
minimal: true,
|
|
460
431
|
});
|
|
461
432
|
config.redirects = redirects;
|
|
462
433
|
const { headers } = await parseAllHeaders({
|
|
434
|
+
// @ts-expect-error FIXME(@netlify/headers-parser): `MinimalHeader` rejects the array values `NetlifyConfig['headers']` allows
|
|
463
435
|
configHeaders: config.headers,
|
|
464
436
|
headersFiles: [headersPath],
|
|
465
437
|
minimal: true,
|
|
@@ -474,7 +446,6 @@ title, deployId: existingDeployId, }) => {
|
|
|
474
446
|
packagePath: command.workspacePackage,
|
|
475
447
|
});
|
|
476
448
|
results = await deploySite(command, api, siteId, deployFolder, {
|
|
477
|
-
// @ts-expect-error FIXME
|
|
478
449
|
config,
|
|
479
450
|
fnDir: functionDirectories,
|
|
480
451
|
functionsConfig,
|
|
@@ -485,7 +456,7 @@ title, deployId: existingDeployId, }) => {
|
|
|
485
456
|
deployId,
|
|
486
457
|
filter: getDeployFilesFilter({ site, deployFolder }),
|
|
487
458
|
workingDir: command.workingDir,
|
|
488
|
-
manifestPath,
|
|
459
|
+
manifestPath: manifestPath ?? undefined,
|
|
489
460
|
packagePath,
|
|
490
461
|
serverEnabled: Boolean(siteData?.feature_flags?.netlify_build_server_standalone),
|
|
491
462
|
serverManifestPath: serverManifestPath ?? undefined,
|
|
@@ -581,10 +552,8 @@ const bundleEdgeFunctions = async (options, command) => {
|
|
|
581
552
|
// We log our own progress so we don't want this as well. Plus, this logs much of the same
|
|
582
553
|
// information as the build that (likely) came before this as part of the deploy build.
|
|
583
554
|
quiet: options.debug ?? true,
|
|
584
|
-
// (cachedConfig type error hides this one, but it still is valid) @ts-expect-error FIXME(serhalp): This is missing from the `runCoreSteps` type in @netlify/build
|
|
585
555
|
edgeFunctionsBootstrapURL: await getBootstrapURL(),
|
|
586
|
-
// @ts-expect-error
|
|
587
|
-
// Index signature for type 'string' is missing in type 'CachedConfig'.
|
|
556
|
+
// @ts-expect-error FIXME(@netlify/build): `cachedConfig` is typed `Record<string, unknown>` and `edgeFunctionsBootstrapURL` is missing from the flags
|
|
588
557
|
cachedConfig: command.netlify.cachedConfig,
|
|
589
558
|
});
|
|
590
559
|
if (!success) {
|
|
@@ -722,7 +691,6 @@ const prepAndRunDeploy = async ({ api, command, config, deployToProduction, opti
|
|
|
722
691
|
siteEnv,
|
|
723
692
|
});
|
|
724
693
|
const results = await runDeploy({
|
|
725
|
-
// @ts-expect-error FIXME
|
|
726
694
|
alias,
|
|
727
695
|
api,
|
|
728
696
|
command,
|
|
@@ -735,7 +703,7 @@ const prepAndRunDeploy = async ({ api, command, config, deployToProduction, opti
|
|
|
735
703
|
functionsFolder: functionsFolderStat && functionsFolder,
|
|
736
704
|
options,
|
|
737
705
|
packagePath: command.workspacePackage,
|
|
738
|
-
silent: options.json || options.silent,
|
|
706
|
+
silent: options.json || Boolean(options.silent),
|
|
739
707
|
site,
|
|
740
708
|
siteData,
|
|
741
709
|
siteId,
|
|
@@ -768,10 +736,11 @@ const createSiteWithFlags = async (options, command, site) => {
|
|
|
768
736
|
throw new Error('Team must be specified to create a site');
|
|
769
737
|
}
|
|
770
738
|
try {
|
|
771
|
-
|
|
739
|
+
// FIXME(@netlify/api): the `site` response type makes every field optional, unlike `SiteInfo`
|
|
740
|
+
const siteData = (await api.createSiteInTeam({
|
|
772
741
|
accountSlug: options.team,
|
|
773
742
|
body,
|
|
774
|
-
});
|
|
743
|
+
}));
|
|
775
744
|
site.id = siteData.id;
|
|
776
745
|
return siteData;
|
|
777
746
|
}
|
|
@@ -781,10 +750,11 @@ const createSiteWithFlags = async (options, command, site) => {
|
|
|
781
750
|
const suffixedName = `${siteName.trim()}-${suffix}`;
|
|
782
751
|
log(`Site name "${siteName}" is taken. Retrying with "${suffixedName}"...`);
|
|
783
752
|
try {
|
|
784
|
-
|
|
753
|
+
// FIXME(@netlify/api): the `site` response type makes every field optional, unlike `SiteInfo`
|
|
754
|
+
const siteData = (await api.createSiteInTeam({
|
|
785
755
|
accountSlug: options.team,
|
|
786
756
|
body: { name: suffixedName },
|
|
787
|
-
});
|
|
757
|
+
}));
|
|
788
758
|
site.id = siteData.id;
|
|
789
759
|
return siteData;
|
|
790
760
|
}
|
|
@@ -901,7 +871,7 @@ const anonymousDeploy = async (options, command) => {
|
|
|
901
871
|
const filter = getDeployFilesFilter({ site, deployFolder });
|
|
902
872
|
const { files, filesShaMap } = await hashFiles({
|
|
903
873
|
concurrentHash: DEFAULT_CONCURRENT_HASH,
|
|
904
|
-
directories: [deployFolder, edgeFunctionsDistPath].filter(Boolean),
|
|
874
|
+
directories: [deployFolder, edgeFunctionsDistPath].filter((dir) => Boolean(dir)),
|
|
905
875
|
filter,
|
|
906
876
|
normalizer: deployFileNormalizer.bind(null, workingDir),
|
|
907
877
|
statusCb: options.json ? () => { } : deployProgressCb(),
|
|
@@ -941,7 +911,7 @@ const anonymousDeploy = async (options, command) => {
|
|
|
941
911
|
}
|
|
942
912
|
const deploy = await waitForDropDeploy(dropApiOptions, deployInfo.id, deployInfo.deploy_id, options.timeout ? options.timeout * 1000 : DEFAULT_DEPLOY_TIMEOUT);
|
|
943
913
|
site.id = deployInfo.id;
|
|
944
|
-
const siteUrl =
|
|
914
|
+
const siteUrl = deploy.ssl_url || deploy.url || `https://${deployInfo.subdomain}.netlify.app`;
|
|
945
915
|
const isPasswordProtected = !options.createdVia || options.createdVia === 'drop';
|
|
946
916
|
const claimUrl = `https://app.netlify.com/drop/${deployInfo.subdomain}#drop_token=${dropToken}`;
|
|
947
917
|
if (options.json) {
|
|
@@ -1023,7 +993,6 @@ export const deploy = async (options, command) => {
|
|
|
1023
993
|
include_upload_url: options.uploadSourceZip,
|
|
1024
994
|
...getDeploySourceFields(),
|
|
1025
995
|
};
|
|
1026
|
-
// TODO: Type this properly in `@netlify/api`.
|
|
1027
996
|
const deployMetadata = (await api.createSiteDeploy({
|
|
1028
997
|
siteId,
|
|
1029
998
|
title: options.message,
|
|
@@ -1058,7 +1027,7 @@ export const deploy = async (options, command) => {
|
|
|
1058
1027
|
options,
|
|
1059
1028
|
workingDir,
|
|
1060
1029
|
api,
|
|
1061
|
-
site,
|
|
1030
|
+
site: site,
|
|
1062
1031
|
config: netlifyConfig,
|
|
1063
1032
|
siteData,
|
|
1064
1033
|
siteId,
|
|
@@ -1087,7 +1056,7 @@ export const deploy = async (options, command) => {
|
|
|
1087
1056
|
options,
|
|
1088
1057
|
workingDir,
|
|
1089
1058
|
api,
|
|
1090
|
-
site,
|
|
1059
|
+
site: site,
|
|
1091
1060
|
config: command.netlify.config,
|
|
1092
1061
|
siteData,
|
|
1093
1062
|
siteId,
|
package/dist/lib/spinner.d.ts
CHANGED
|
@@ -8,9 +8,9 @@ export declare const startSpinner: ({ text }: {
|
|
|
8
8
|
/**
|
|
9
9
|
* Stops the spinner with the following text
|
|
10
10
|
*/
|
|
11
|
-
export declare const stopSpinner: ({ error, spinner, text }: {
|
|
11
|
+
export declare const stopSpinner: ({ error, spinner, text, }: {
|
|
12
12
|
error?: boolean;
|
|
13
|
-
spinner: Spinner;
|
|
13
|
+
spinner: Spinner | undefined;
|
|
14
14
|
text?: string;
|
|
15
15
|
}) => void;
|
|
16
16
|
/**
|
package/dist/lib/spinner.js
CHANGED
|
@@ -33,7 +33,7 @@ export const startSpinner = ({ text }) => {
|
|
|
33
33
|
/**
|
|
34
34
|
* Stops the spinner with the following text
|
|
35
35
|
*/
|
|
36
|
-
export const stopSpinner = ({ error, spinner, text }) => {
|
|
36
|
+
export const stopSpinner = ({ error, spinner, text, }) => {
|
|
37
37
|
if (!spinner) {
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
@@ -1,26 +1,46 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import type
|
|
1
|
+
import type { NetlifyAPI } from '@netlify/api';
|
|
2
|
+
import type { Config as FunctionsConfig } from '@netlify/zip-it-and-ship-it';
|
|
3
|
+
import type BaseCommand from '../../commands/base-command.js';
|
|
4
|
+
import type { File } from './file.js';
|
|
5
|
+
import type { DeployEvent, StatusCallback } from './status-cb.js';
|
|
6
|
+
import type { DeployConfig } from './types.js';
|
|
4
7
|
import type { DeployEnvironmentVariable } from '../env/deploy-env-vars.js';
|
|
5
8
|
export type { DeployEvent };
|
|
6
|
-
export
|
|
9
|
+
export interface DeploySiteOptions {
|
|
10
|
+
assetType?: 'file' | undefined;
|
|
11
|
+
branch?: string;
|
|
7
12
|
concurrentHash?: number;
|
|
8
13
|
concurrentUpload?: number;
|
|
14
|
+
/** The site configuration, uploaded as the deploy's `netlify.toml` */
|
|
15
|
+
config: DeployConfig;
|
|
16
|
+
deployId: string;
|
|
9
17
|
deployTimeout?: number;
|
|
10
18
|
draft?: boolean;
|
|
11
19
|
environment?: DeployEnvironmentVariable[];
|
|
20
|
+
filter: (filename: string) => boolean;
|
|
21
|
+
fnDir?: string[];
|
|
22
|
+
functionsConfig?: FunctionsConfig | undefined;
|
|
23
|
+
hashAlgorithm?: string;
|
|
24
|
+
manifestPath?: string | undefined;
|
|
12
25
|
maxRetry?: number;
|
|
13
|
-
packagePath?: string;
|
|
26
|
+
packagePath?: string | undefined;
|
|
14
27
|
serverEnabled?: boolean;
|
|
15
|
-
serverManifestPath?: string;
|
|
16
|
-
|
|
28
|
+
serverManifestPath?: string | undefined;
|
|
29
|
+
siteRoot?: string | undefined;
|
|
30
|
+
skipFunctionsCache?: boolean | undefined;
|
|
31
|
+
statusCb?: StatusCallback;
|
|
17
32
|
syncFileLimit?: number;
|
|
18
33
|
tmpDir?: string;
|
|
19
|
-
fnDir?: string[];
|
|
20
34
|
workingDir: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
35
|
+
}
|
|
36
|
+
export declare const deploySite: (command: BaseCommand, api: NetlifyAPI, siteId: string, dir: string, { assetType, branch, concurrentHash, concurrentUpload, config, deployId, deployTimeout, draft, environment, filter, fnDir, functionsConfig, hashAlgorithm, manifestPath, maxRetry, packagePath, serverEnabled, serverManifestPath, siteRoot, skipFunctionsCache, statusCb, syncFileLimit, tmpDir, workingDir, }: DeploySiteOptions) => Promise<{
|
|
37
|
+
deployId: string;
|
|
38
|
+
deploy: import("./util.js").ReadyDeploy;
|
|
39
|
+
uploadList: (import("./upload-files.js").EdgeFunctionUploadFile | import("./upload-files.js").ServerUploadFile | File | (import("./upload-files.js").FunctionUploadFile & {
|
|
40
|
+
hash: string;
|
|
41
|
+
relname: string;
|
|
42
|
+
}) | (import("./upload-files.js").InlineUploadFile & {
|
|
43
|
+
hash: string;
|
|
44
|
+
}))[];
|
|
25
45
|
}>;
|
|
26
46
|
//# sourceMappingURL=deploy-site.d.ts.map
|
|
@@ -18,31 +18,7 @@ const buildStatsString = (possibleParts) => {
|
|
|
18
18
|
}
|
|
19
19
|
return `${parts.slice(0, -1).join(', ')} and ${parts[parts.length - 1]}`;
|
|
20
20
|
};
|
|
21
|
-
export const deploySite = async (command, api,
|
|
22
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'siteId' implicitly has an 'any' type.
|
|
23
|
-
siteId,
|
|
24
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'dir' implicitly has an 'any' type.
|
|
25
|
-
dir, {
|
|
26
|
-
// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message
|
|
27
|
-
assetType,
|
|
28
|
-
// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message
|
|
29
|
-
branch, concurrentHash = DEFAULT_CONCURRENT_HASH, concurrentUpload = DEFAULT_CONCURRENT_UPLOAD,
|
|
30
|
-
// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message
|
|
31
|
-
config,
|
|
32
|
-
// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message
|
|
33
|
-
deployId, deployTimeout = DEFAULT_DEPLOY_TIMEOUT, draft = false, environment,
|
|
34
|
-
// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message
|
|
35
|
-
filter, fnDir = [],
|
|
36
|
-
// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message
|
|
37
|
-
functionsConfig,
|
|
38
|
-
// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message
|
|
39
|
-
hashAlgorithm,
|
|
40
|
-
// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message
|
|
41
|
-
manifestPath, maxRetry = DEFAULT_MAX_RETRY, packagePath, serverEnabled, serverManifestPath,
|
|
42
|
-
// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message
|
|
43
|
-
siteRoot,
|
|
44
|
-
// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message
|
|
45
|
-
skipFunctionsCache, statusCb = () => {
|
|
21
|
+
export const deploySite = async (command, api, siteId, dir, { assetType, branch, concurrentHash = DEFAULT_CONCURRENT_HASH, concurrentUpload = DEFAULT_CONCURRENT_UPLOAD, config, deployId, deployTimeout = DEFAULT_DEPLOY_TIMEOUT, draft = false, environment, filter, fnDir = [], functionsConfig, hashAlgorithm, manifestPath, maxRetry = DEFAULT_MAX_RETRY, packagePath, serverEnabled, serverManifestPath, siteRoot, skipFunctionsCache, statusCb = () => {
|
|
46
22
|
/* default to noop */
|
|
47
23
|
}, syncFileLimit = DEFAULT_SYNC_LIMIT, tmpDir = temporaryDirectory(), workingDir, }) => {
|
|
48
24
|
statusCb({
|
|
@@ -57,7 +33,7 @@ skipFunctionsCache, statusCb = () => {
|
|
|
57
33
|
hashFiles({
|
|
58
34
|
assetType,
|
|
59
35
|
concurrentHash,
|
|
60
|
-
directories: [dir, edgeFunctionsDistPath, deployConfigPath, dbMigrationsDistPath].filter(Boolean),
|
|
36
|
+
directories: [dir, edgeFunctionsDistPath, deployConfigPath, dbMigrationsDistPath].filter((d) => Boolean(d)),
|
|
61
37
|
filter,
|
|
62
38
|
hashAlgorithm,
|
|
63
39
|
normalizer: deployFileNormalizer.bind(null, workingDir),
|
|
@@ -99,9 +75,7 @@ skipFunctionsCache, statusCb = () => {
|
|
|
99
75
|
throw new Error('Nothing to deploy');
|
|
100
76
|
}
|
|
101
77
|
if (functionsWithNativeModules.length !== 0) {
|
|
102
|
-
const functionsWithNativeModulesMessage = functionsWithNativeModules
|
|
103
|
-
.map(({ name }) => `- ${name}`)
|
|
104
|
-
.join('\n');
|
|
78
|
+
const functionsWithNativeModulesMessage = functionsWithNativeModules.map(({ name }) => `- ${name}`).join('\n');
|
|
105
79
|
warn(`Modules with native dependencies\n
|
|
106
80
|
${functionsWithNativeModulesMessage}
|
|
107
81
|
|
|
@@ -120,8 +94,7 @@ For more information, visit https://ntl.fyi/cli-native-modules.`);
|
|
|
120
94
|
});
|
|
121
95
|
const packageFrameworks = command.project.frameworks.get(command.workspacePackage ?? '');
|
|
122
96
|
const primaryFramework = packageFrameworks?.[0];
|
|
123
|
-
|
|
124
|
-
const cleanedParams = cleanDeep({
|
|
97
|
+
const params = {
|
|
125
98
|
siteId,
|
|
126
99
|
deploy_id: deployId,
|
|
127
100
|
body: {
|
|
@@ -138,21 +111,27 @@ For more information, visit https://ntl.fyi/cli-native-modules.`);
|
|
|
138
111
|
framework_version: primaryFramework?.detected.package?.version?.toString() ?? 'unknown',
|
|
139
112
|
build_version: getNetlifyBuildVersion(),
|
|
140
113
|
},
|
|
141
|
-
}
|
|
114
|
+
};
|
|
115
|
+
const cleanedParams =
|
|
116
|
+
// @ts-expect-error FIXME(clean-deep): typings declare an ES `export default` but the package is CommonJS
|
|
117
|
+
cleanDeep(params);
|
|
142
118
|
// cleanDeep deeply strips keys with empty strings, but empty strings are valid environment
|
|
143
119
|
// variable values--a user can use an empty string to e.g. unset a variable only for a deploy.
|
|
144
120
|
// This would result in payloads with a missing `value` key, which the API would reject.
|
|
145
121
|
const deployParams = environment?.length
|
|
146
122
|
? { ...cleanedParams, body: { ...cleanedParams.body, environment } }
|
|
147
123
|
: cleanedParams;
|
|
148
|
-
|
|
124
|
+
// FIXME(@netlify/api): `id` and `required` are optional on the updated deploy
|
|
125
|
+
let deploy = (await api.updateSiteDeploy(
|
|
126
|
+
// @ts-expect-error FIXME(@netlify/api): `functions_config` rejects zip-it-and-ship-it's `BuildData`, route `methods` and `traffic_rules` strings
|
|
127
|
+
deployParams));
|
|
149
128
|
if (deployParams.body.async)
|
|
150
|
-
deploy = await waitForDiff(api, deploy.id, siteId, deployTimeout);
|
|
129
|
+
deploy = (await waitForDiff(api, deploy.id, siteId, deployTimeout));
|
|
151
130
|
const { required: requiredFiles, required_functions: requiredFns, required_edge_functions: requiredEdgeFns, required_server: requiredServer, } = deploy;
|
|
152
131
|
const newStats = buildStatsString([
|
|
153
132
|
requiredFiles.length > 0 && pluralize(requiredFiles.length, 'file'),
|
|
154
|
-
|
|
155
|
-
|
|
133
|
+
requiredFns != null && requiredFns.length > 0 && pluralize(requiredFns.length, 'function'),
|
|
134
|
+
requiredEdgeFns != null && requiredEdgeFns.length > 0 && pluralize(requiredEdgeFns.length, 'edge function'),
|
|
156
135
|
(requiredServer?.length ?? 0) > 0 && 'a server',
|
|
157
136
|
]);
|
|
158
137
|
statusCb({
|
|
@@ -171,18 +150,17 @@ For more information, visit https://ntl.fyi/cli-native-modules.`);
|
|
|
171
150
|
msg: 'Waiting for deploy to go live...',
|
|
172
151
|
phase: 'start',
|
|
173
152
|
});
|
|
174
|
-
|
|
153
|
+
const readyDeploy = await waitForDeploy(api, deployId, siteId, deployTimeout);
|
|
175
154
|
statusCb({
|
|
176
155
|
type: 'wait-for-deploy',
|
|
177
156
|
msg: draft ? 'Draft deploy is live!' : 'Deploy is live!',
|
|
178
157
|
phase: 'stop',
|
|
179
158
|
});
|
|
180
159
|
await rm(tmpDir, { force: true, recursive: true });
|
|
181
|
-
|
|
160
|
+
return {
|
|
182
161
|
deployId,
|
|
183
|
-
deploy,
|
|
162
|
+
deploy: readyDeploy,
|
|
184
163
|
uploadList,
|
|
185
164
|
};
|
|
186
|
-
return deployManifest;
|
|
187
165
|
};
|
|
188
166
|
//# sourceMappingURL=deploy-site.js.map
|
|
@@ -18,7 +18,13 @@ export interface DropApiError extends Error {
|
|
|
18
18
|
export declare const getDropToken: ({ apiBase, userAgent }: DropApiOptions) => Promise<string>;
|
|
19
19
|
export declare const createDropDeploy: ({ apiBase, userAgent }: DropApiOptions, files: Record<string, string>, token: string, createdVia?: string) => Promise<DropDeployInfo>;
|
|
20
20
|
export declare const uploadDropFile: ({ apiBase, userAgent }: DropApiOptions, deployId: string, filePath: string, body: fs.ReadStream | Buffer, token: string) => Promise<void>;
|
|
21
|
-
|
|
21
|
+
interface DropSiteDeploy {
|
|
22
|
+
state?: string;
|
|
23
|
+
error_message?: string;
|
|
24
|
+
ssl_url?: string;
|
|
25
|
+
url?: string;
|
|
26
|
+
}
|
|
27
|
+
export declare const waitForDropDeploy: ({ apiBase, userAgent }: DropApiOptions, siteId: string, deployId: string, timeout?: number) => Promise<DropSiteDeploy>;
|
|
22
28
|
export declare const claimDropSite: ({ apiBase, userAgent }: DropApiOptions, siteId: string, dropToken: string, authToken: string) => Promise<void>;
|
|
23
29
|
export interface UploadListItem {
|
|
24
30
|
normalizedPath: string;
|
|
@@ -44,8 +44,6 @@ export const createDropDeploy = async ({ apiBase, userAgent }, files, token, cre
|
|
|
44
44
|
};
|
|
45
45
|
// TODO: Migrate to @netlify/api when Drop endpoints are in the OpenAPI spec.
|
|
46
46
|
export const uploadDropFile = async ({ apiBase, userAgent }, deployId, filePath, body, token) => {
|
|
47
|
-
// Node.js fetch needs `duplex: 'half'` for streaming bodies which isn't in standard RequestInit
|
|
48
|
-
/* eslint-disable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any */
|
|
49
47
|
const normalizedFilePath = filePath.startsWith('/') ? filePath : `/${filePath}`;
|
|
50
48
|
const response = await fetch(`${apiBase}/deploys/${deployId}/files${encodeURI(normalizedFilePath)}`, {
|
|
51
49
|
method: 'PUT',
|
|
@@ -53,10 +51,10 @@ export const uploadDropFile = async ({ apiBase, userAgent }, deployId, filePath,
|
|
|
53
51
|
'Content-Type': 'application/octet-stream',
|
|
54
52
|
Authorization: `Bearer ${token}`,
|
|
55
53
|
}),
|
|
56
|
-
body
|
|
54
|
+
body,
|
|
55
|
+
// Node.js fetch requires this for streaming bodies
|
|
57
56
|
duplex: 'half',
|
|
58
57
|
});
|
|
59
|
-
/* eslint-enable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any */
|
|
60
58
|
if (!response.ok) {
|
|
61
59
|
const error = new Error(`Failed to upload file ${filePath}: ${String(response.status)} ${response.statusText}`);
|
|
62
60
|
error.status = response.status;
|
|
@@ -79,6 +77,7 @@ export const waitForDropDeploy = async ({ apiBase, userAgent }, siteId, deployId
|
|
|
79
77
|
return true;
|
|
80
78
|
}
|
|
81
79
|
if (data.state === 'error') {
|
|
80
|
+
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- an empty error message falls back to the generic one
|
|
82
81
|
throw new Error(data.error_message || `Deploy ${deployId} had an error`);
|
|
83
82
|
}
|
|
84
83
|
return false;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import walker from 'folder-walker';
|
|
2
2
|
export type OriginalFile = walker.Entry;
|
|
3
|
-
export type
|
|
3
|
+
export type HashedFile = OriginalFile & {
|
|
4
4
|
hash: string;
|
|
5
|
-
|
|
5
|
+
};
|
|
6
|
+
export type File = HashedFile & {
|
|
7
|
+
assetType: 'file';
|
|
6
8
|
normalizedPath: string;
|
|
7
9
|
};
|
|
8
10
|
//# sourceMappingURL=file.d.ts.map
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
+
import type { DeployConfig } from './types.js';
|
|
2
|
+
import type { InlineUploadFile } from './upload-files.js';
|
|
1
3
|
export declare const hashConfig: ({ config }: {
|
|
2
|
-
config:
|
|
3
|
-
}) => {
|
|
4
|
-
assetType: string;
|
|
5
|
-
body: string;
|
|
4
|
+
config: DeployConfig | undefined;
|
|
5
|
+
}) => InlineUploadFile & {
|
|
6
6
|
hash: string;
|
|
7
|
-
normalizedPath: string;
|
|
8
7
|
};
|
|
9
|
-
export declare const serializeToml: (object:
|
|
8
|
+
export declare const serializeToml: (object: DeployConfig) => string;
|
|
10
9
|
//# sourceMappingURL=hash-config.d.ts.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import tomlify from 'tomlify-j0.4';
|
|
3
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message
|
|
4
3
|
export const hashConfig = ({ config }) => {
|
|
5
4
|
if (!config)
|
|
6
5
|
throw new Error('Missing config option');
|
|
@@ -13,14 +12,12 @@ export const hashConfig = ({ config }) => {
|
|
|
13
12
|
normalizedPath: 'netlify.toml',
|
|
14
13
|
};
|
|
15
14
|
};
|
|
16
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'object' implicitly has an 'any' type.
|
|
17
15
|
export const serializeToml = function (object) {
|
|
18
16
|
return tomlify.toToml(object, { space: 2, replace: replaceTomlValue });
|
|
19
17
|
};
|
|
20
18
|
// `tomlify-j0.4` serializes integers as floats, e.g. `200.0`.
|
|
21
19
|
// This is a problem with `redirects[*].status`.
|
|
22
|
-
|
|
23
|
-
const replaceTomlValue = function (key, value) {
|
|
20
|
+
const replaceTomlValue = function (_key, value) {
|
|
24
21
|
return Number.isInteger(value) ? String(value) : false;
|
|
25
22
|
};
|
|
26
23
|
//# sourceMappingURL=hash-config.js.map
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { File } from './file.js';
|
|
2
|
+
import type { StatusCallback } from './status-cb.js';
|
|
2
3
|
declare const hashFiles: ({ assetType, concurrentHash, directories, filter, hashAlgorithm, normalizer, statusCb, }: {
|
|
3
|
-
assetType?:
|
|
4
|
-
concurrentHash:
|
|
5
|
-
directories:
|
|
6
|
-
filter:
|
|
4
|
+
assetType?: 'file' | undefined;
|
|
5
|
+
concurrentHash: number;
|
|
6
|
+
directories: string[];
|
|
7
|
+
filter: ((filename: string) => boolean) | undefined;
|
|
7
8
|
hashAlgorithm?: string | undefined;
|
|
8
|
-
normalizer?:
|
|
9
|
-
statusCb:
|
|
9
|
+
normalizer?: (file: File) => File;
|
|
10
|
+
statusCb: StatusCallback;
|
|
10
11
|
}) => Promise<{
|
|
11
12
|
files: Record<string, string>;
|
|
12
|
-
filesShaMap: Record<string,
|
|
13
|
+
filesShaMap: Record<string, File[]>;
|
|
13
14
|
}>;
|
|
14
15
|
export default hashFiles;
|
|
15
16
|
//# sourceMappingURL=hash-files.d.ts.map
|
|
@@ -1,9 +1,44 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import type {
|
|
1
|
+
import { type Config as FunctionsConfig, type FunctionResult, type TrafficRules } from '@netlify/zip-it-and-ship-it';
|
|
2
|
+
import type BaseCommand from '../../commands/base-command.js';
|
|
3
|
+
import type { StatusCallback } from './status-cb.js';
|
|
4
|
+
import type { FunctionUploadFile, ServerUploadFile } from './upload-files.js';
|
|
5
|
+
type HashedFunctionFile = FunctionUploadFile & {
|
|
6
|
+
hash: string;
|
|
7
|
+
relname: string;
|
|
8
|
+
};
|
|
9
|
+
declare const trafficRulesConfig: (trafficRules?: TrafficRules) => {
|
|
10
|
+
action: {
|
|
11
|
+
type: string;
|
|
12
|
+
config: {
|
|
13
|
+
rate_limit_config: {
|
|
14
|
+
algorithm: string;
|
|
15
|
+
window_size: number;
|
|
16
|
+
window_limit: number;
|
|
17
|
+
};
|
|
18
|
+
aggregate: {
|
|
19
|
+
keys: {
|
|
20
|
+
type: string;
|
|
21
|
+
}[];
|
|
22
|
+
};
|
|
23
|
+
to: string | undefined;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
} | undefined;
|
|
27
|
+
interface FunctionConfigPayload {
|
|
28
|
+
display_name: FunctionResult['displayName'];
|
|
29
|
+
excluded_routes: FunctionResult['excludedRoutes'];
|
|
30
|
+
generator: FunctionResult['generator'];
|
|
31
|
+
memory: FunctionResult['memory'];
|
|
32
|
+
region: FunctionResult['region'];
|
|
33
|
+
routes: FunctionResult['routes'];
|
|
34
|
+
build_data: FunctionResult['buildData'];
|
|
35
|
+
priority: FunctionResult['priority'];
|
|
36
|
+
traffic_rules: ReturnType<typeof trafficRulesConfig>;
|
|
37
|
+
vcpu: FunctionResult['vcpu'];
|
|
38
|
+
}
|
|
4
39
|
declare const hashFns: (command: BaseCommand, directories: string[], { concurrentHash, functionsConfig, hashAlgorithm, manifestPath, packagePath, rootDir, serverEnabled, serverManifestPath, skipFunctionsCache, statusCb, tmpDir, }: {
|
|
5
40
|
concurrentHash?: number;
|
|
6
|
-
functionsConfig?:
|
|
41
|
+
functionsConfig?: FunctionsConfig | undefined;
|
|
7
42
|
hashAlgorithm?: string | undefined;
|
|
8
43
|
manifestPath?: string | undefined;
|
|
9
44
|
packagePath?: string | undefined;
|
|
@@ -11,18 +46,18 @@ declare const hashFns: (command: BaseCommand, directories: string[], { concurren
|
|
|
11
46
|
serverEnabled?: boolean | undefined;
|
|
12
47
|
serverManifestPath?: string | undefined;
|
|
13
48
|
skipFunctionsCache?: boolean | undefined;
|
|
14
|
-
statusCb:
|
|
15
|
-
tmpDir
|
|
49
|
+
statusCb: StatusCallback;
|
|
50
|
+
tmpDir?: string | undefined;
|
|
16
51
|
}) => Promise<{
|
|
17
52
|
functionSchedules?: {
|
|
18
53
|
name: string;
|
|
19
54
|
cron: string;
|
|
20
55
|
}[] | undefined;
|
|
21
56
|
functions: Record<string, string>;
|
|
22
|
-
functionsWithNativeModules:
|
|
23
|
-
shaMap?: Record<string,
|
|
24
|
-
fnShaMap?: Record<string,
|
|
25
|
-
fnConfig?: Record<string,
|
|
57
|
+
functionsWithNativeModules: FunctionResult[];
|
|
58
|
+
shaMap?: Record<string, never> | undefined;
|
|
59
|
+
fnShaMap?: Record<string, HashedFunctionFile[]> | undefined;
|
|
60
|
+
fnConfig?: Record<string, FunctionConfigPayload> | undefined;
|
|
26
61
|
server?: {
|
|
27
62
|
sha: string;
|
|
28
63
|
region?: string;
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import { Transform, Writable } from 'node:stream';
|
|
2
|
-
import type { File
|
|
2
|
+
import type { File } from './file.js';
|
|
3
3
|
import type { StatusCallback } from './status-cb.js';
|
|
4
4
|
export declare const hasherCtor: ({ concurrentHash, hashAlgorithm }: {
|
|
5
|
-
concurrentHash
|
|
6
|
-
hashAlgorithm:
|
|
5
|
+
concurrentHash?: number;
|
|
6
|
+
hashAlgorithm: string;
|
|
7
7
|
}) => Transform;
|
|
8
8
|
export declare const fileNormalizerCtor: ({ assetType, normalizer: normalizeFunction, }: {
|
|
9
|
-
assetType:
|
|
10
|
-
normalizer?: (file:
|
|
9
|
+
assetType: 'file';
|
|
10
|
+
normalizer?: (file: File) => File;
|
|
11
11
|
}) => Transform;
|
|
12
|
-
export declare const manifestCollectorCtor:
|
|
12
|
+
export declare const manifestCollectorCtor: <T extends {
|
|
13
|
+
hash: string;
|
|
14
|
+
normalizedPath: string;
|
|
15
|
+
relname: string;
|
|
16
|
+
}>(filesObj: Record<string, string>, shaMap: Record<string, T[]>, { statusCb }: {
|
|
13
17
|
statusCb: StatusCallback;
|
|
14
18
|
}) => Writable;
|
|
15
19
|
export declare const fileFilterCtor: () => Transform;
|
|
@@ -11,7 +11,6 @@ const hashFile = async (filePath, algorithm) => {
|
|
|
11
11
|
};
|
|
12
12
|
// a parallel transform stream segment ctor that hashes fileObj's created by folder-walker
|
|
13
13
|
// TODO: use promises instead of callbacks
|
|
14
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'concurrentHash' implicitly has an... Remove this comment to see the full error message
|
|
15
14
|
export const hasherCtor = ({ concurrentHash, hashAlgorithm }) => {
|
|
16
15
|
if (!concurrentHash)
|
|
17
16
|
throw new Error('Missing required opts');
|
|
@@ -7,7 +7,7 @@ export declare const deployFileNormalizer: (workingDir: string, file: File) => {
|
|
|
7
7
|
stat: import("fs").Stats;
|
|
8
8
|
type: "file" | "directory";
|
|
9
9
|
hash: string;
|
|
10
|
-
assetType:
|
|
10
|
+
assetType: 'file';
|
|
11
11
|
normalizedPath: string;
|
|
12
12
|
};
|
|
13
13
|
export declare const getDeployConfigPathIfExists: (workingDir: string) => Promise<string | undefined>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { NetlifyConfig } from '@netlify/build';
|
|
2
|
+
import type { MinimalHeader } from '@netlify/headers-parser';
|
|
3
|
+
/**
|
|
4
|
+
* The parts of the resolved configuration a deploy reads and uploads. Satisfied both by the CLI's cached config and
|
|
5
|
+
* by the `NetlifyConfig` that `@netlify/build` hands to the deploy handler.
|
|
6
|
+
*/
|
|
7
|
+
export interface DeployConfig {
|
|
8
|
+
build: {
|
|
9
|
+
base: string;
|
|
10
|
+
publish?: string;
|
|
11
|
+
};
|
|
12
|
+
functions?: NetlifyConfig['functions'];
|
|
13
|
+
functionsDirectory?: string;
|
|
14
|
+
headers?: NetlifyConfig['headers'] | MinimalHeader[];
|
|
15
|
+
redirects?: unknown[];
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
1
|
import type { NetlifyAPI } from '@netlify/api';
|
|
3
2
|
import type { StatusCallback } from './status-cb.js';
|
|
4
3
|
export type UploadApi = Pick<NetlifyAPI, 'uploadDeployFile' | 'uploadDeployFunction' | 'uploadDeployEdgeFunction' | 'uploadDeployServer'>;
|
|
5
4
|
interface UploadFileBase {
|
|
6
5
|
filepath: string;
|
|
7
6
|
normalizedPath: string;
|
|
8
|
-
body?:
|
|
7
|
+
body?: undefined;
|
|
9
8
|
}
|
|
10
9
|
export interface StaticUploadFile extends UploadFileBase {
|
|
11
10
|
assetType: 'file';
|
|
12
11
|
}
|
|
12
|
+
export interface InlineUploadFile {
|
|
13
|
+
assetType: 'file';
|
|
14
|
+
body: string;
|
|
15
|
+
filepath?: undefined;
|
|
16
|
+
normalizedPath: string;
|
|
17
|
+
}
|
|
13
18
|
export interface FunctionUploadFile extends UploadFileBase {
|
|
14
19
|
assetType: 'function';
|
|
15
20
|
runtime?: string;
|
|
@@ -24,7 +29,7 @@ export interface ServerUploadFile extends UploadFileBase {
|
|
|
24
29
|
assetType: 'server';
|
|
25
30
|
hash: string;
|
|
26
31
|
}
|
|
27
|
-
export type UploadFile = StaticUploadFile | FunctionUploadFile | EdgeFunctionUploadFile | ServerUploadFile;
|
|
32
|
+
export type UploadFile = StaticUploadFile | InlineUploadFile | FunctionUploadFile | EdgeFunctionUploadFile | ServerUploadFile;
|
|
28
33
|
interface UploadFilesOptions {
|
|
29
34
|
concurrentUpload: number;
|
|
30
35
|
maxRetry: number;
|
|
@@ -23,7 +23,8 @@ const uploadFiles = async (api, deployId, uploadList, { concurrentUpload, maxRet
|
|
|
23
23
|
});
|
|
24
24
|
const uploadFile = async (fileObj, index) => {
|
|
25
25
|
const { body, filepath, normalizedPath } = fileObj;
|
|
26
|
-
|
|
26
|
+
// FIXME(@netlify/api): octet-stream `body` is typed as `ReadStream` only, but an inline string body works too
|
|
27
|
+
const readStreamCtor = () => (body ?? fs.createReadStream(filepath));
|
|
27
28
|
statusCb({
|
|
28
29
|
type: 'upload',
|
|
29
30
|
msg: `(${index}/${uploadList.length}) Uploading ${normalizedPath}...`,
|
|
@@ -131,12 +132,12 @@ const retryUpload = (uploadFn, maxRetry) => new Promise((resolve, reject) => {
|
|
|
131
132
|
// Do something when backoff starts, e.g. show to the
|
|
132
133
|
// user the delay before next reconnection attempt.
|
|
133
134
|
});
|
|
134
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
135
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises -- FIXME: the listener's promise is discarded
|
|
135
136
|
fibonacciBackoff.on('ready', tryUpload);
|
|
136
137
|
fibonacciBackoff.on('fail', () => {
|
|
137
138
|
reject(lastError);
|
|
138
139
|
});
|
|
139
|
-
tryUpload();
|
|
140
|
+
void tryUpload();
|
|
140
141
|
});
|
|
141
142
|
export default uploadFiles;
|
|
142
143
|
//# sourceMappingURL=upload-files.js.map
|
|
@@ -27,6 +27,7 @@ const DEFAULT_IGNORE_PATTERNS = [
|
|
|
27
27
|
'.tmp*',
|
|
28
28
|
'.temp*',
|
|
29
29
|
];
|
|
30
|
+
const isExecaError = (error) => error instanceof Error && 'command' in error;
|
|
30
31
|
const createSourceZip = async ({ sourceDir, filename, statusCb, }) => {
|
|
31
32
|
// Check for Windows - this feature is not supported on Windows
|
|
32
33
|
if (platform() === 'win32') {
|
|
@@ -54,13 +55,9 @@ const createSourceZip = async ({ sourceDir, filename, statusCb, }) => {
|
|
|
54
55
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
55
56
|
});
|
|
56
57
|
}
|
|
57
|
-
catch (
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const baseErr = _baseErr;
|
|
61
|
-
message = `${baseErr.shortMessage}\n\n${baseErr.all ?? ''}`;
|
|
62
|
-
}
|
|
63
|
-
throw new Error(message, { cause: _baseErr });
|
|
58
|
+
catch (error) {
|
|
59
|
+
const message = isExecaError(error) ? `${error.shortMessage}\n\n${error.all ?? ''}` : 'zip command failed';
|
|
60
|
+
throw new Error(message, { cause: error });
|
|
64
61
|
}
|
|
65
62
|
return zipPath;
|
|
66
63
|
};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import type { NetlifyAPI } from '@netlify/api';
|
|
1
2
|
export declare const pluralize: (amount: number, noun: string) => string;
|
|
3
|
+
export type Deploy = Awaited<ReturnType<NetlifyAPI['getSiteDeploy']>>;
|
|
4
|
+
export type ReadyDeploy = Deploy & Required<Pick<Deploy, 'id' | 'site_id' | 'name' | 'admin_url' | 'url' | 'ssl_url' | 'deploy_url' | 'deploy_ssl_url'>>;
|
|
2
5
|
export declare const normalizePath: (relname: string) => string;
|
|
3
|
-
export declare const waitForDiff: (api:
|
|
4
|
-
export declare const waitForDeploy: (api:
|
|
5
|
-
export declare const getUploadList: (required:
|
|
6
|
+
export declare const waitForDiff: (api: Pick<NetlifyAPI, 'getSiteDeploy'>, deployId: string, siteId: string, timeout: number) => Promise<Deploy>;
|
|
7
|
+
export declare const waitForDeploy: (api: Pick<NetlifyAPI, 'getSiteDeploy'>, deployId: string, siteId: string, timeout: number) => Promise<ReadyDeploy>;
|
|
8
|
+
export declare const getUploadList: <T>(required: string[] | undefined, shaMap: Record<string, T[]> | undefined) => T[];
|
|
6
9
|
//# sourceMappingURL=util.d.ts.map
|
|
@@ -10,17 +10,13 @@ export const normalizePath = (relname) => {
|
|
|
10
10
|
return relname.split(sep).join('/');
|
|
11
11
|
};
|
|
12
12
|
// poll an async deployId until its done diffing
|
|
13
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'api' implicitly has an 'any' type.
|
|
14
13
|
export const waitForDiff = async (api, deployId, siteId, timeout) => {
|
|
15
|
-
// capture ready deploy during poll
|
|
16
|
-
let deploy;
|
|
17
14
|
const loadDeploy = async () => {
|
|
18
15
|
const siteDeploy = await api.getSiteDeploy({ siteId, deployId });
|
|
19
16
|
switch (siteDeploy.state) {
|
|
20
17
|
// https://github.com/netlify/bitballoon/blob/master/app/models/deploy.rb#L21-L33
|
|
21
18
|
case 'error': {
|
|
22
19
|
const deployError = new Error(siteDeploy.error_message || `Deploy ${deployId} had an error`);
|
|
23
|
-
// @ts-expect-error TS(2339) FIXME: Property 'deploy' does not exist on type 'Error'.
|
|
24
20
|
deployError.deploy = siteDeploy;
|
|
25
21
|
throw deployError;
|
|
26
22
|
}
|
|
@@ -28,8 +24,7 @@ export const waitForDiff = async (api, deployId, siteId, timeout) => {
|
|
|
28
24
|
case 'uploading':
|
|
29
25
|
case 'uploaded':
|
|
30
26
|
case 'ready': {
|
|
31
|
-
|
|
32
|
-
return true;
|
|
27
|
+
return pWaitFor.resolveWith(siteDeploy);
|
|
33
28
|
}
|
|
34
29
|
case 'preparing':
|
|
35
30
|
default: {
|
|
@@ -37,7 +32,7 @@ export const waitForDiff = async (api, deployId, siteId, timeout) => {
|
|
|
37
32
|
}
|
|
38
33
|
}
|
|
39
34
|
};
|
|
40
|
-
await pWaitFor(loadDeploy, {
|
|
35
|
+
const deploy = await pWaitFor(loadDeploy, {
|
|
41
36
|
interval: DEPLOY_POLL,
|
|
42
37
|
timeout: {
|
|
43
38
|
milliseconds: timeout,
|
|
@@ -47,23 +42,18 @@ export const waitForDiff = async (api, deployId, siteId, timeout) => {
|
|
|
47
42
|
return deploy;
|
|
48
43
|
};
|
|
49
44
|
// Poll a deployId until its ready
|
|
50
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'api' implicitly has an 'any' type.
|
|
51
45
|
export const waitForDeploy = async (api, deployId, siteId, timeout) => {
|
|
52
|
-
// capture ready deploy during poll
|
|
53
|
-
let deploy;
|
|
54
46
|
const loadDeploy = async () => {
|
|
55
47
|
const siteDeploy = await api.getSiteDeploy({ siteId, deployId });
|
|
56
48
|
switch (siteDeploy.state) {
|
|
57
49
|
// https://github.com/netlify/bitballoon/blob/master/app/models/deploy.rb#L21-L33
|
|
58
50
|
case 'error': {
|
|
59
51
|
const deployError = new Error(siteDeploy.error_message || `Deploy ${deployId} had an error`);
|
|
60
|
-
// @ts-expect-error TS(2339) FIXME: Property 'deploy' does not exist on type 'Error'.
|
|
61
52
|
deployError.deploy = siteDeploy;
|
|
62
53
|
throw deployError;
|
|
63
54
|
}
|
|
64
55
|
case 'ready': {
|
|
65
|
-
|
|
66
|
-
return true;
|
|
56
|
+
return pWaitFor.resolveWith(siteDeploy);
|
|
67
57
|
}
|
|
68
58
|
case 'preparing':
|
|
69
59
|
case 'prepared':
|
|
@@ -74,7 +64,7 @@ export const waitForDeploy = async (api, deployId, siteId, timeout) => {
|
|
|
74
64
|
}
|
|
75
65
|
}
|
|
76
66
|
};
|
|
77
|
-
await pWaitFor(loadDeploy, {
|
|
67
|
+
const deploy = await pWaitFor(loadDeploy, {
|
|
78
68
|
interval: DEPLOY_POLL,
|
|
79
69
|
timeout: {
|
|
80
70
|
milliseconds: timeout,
|
|
@@ -84,11 +74,9 @@ export const waitForDeploy = async (api, deployId, siteId, timeout) => {
|
|
|
84
74
|
return deploy;
|
|
85
75
|
};
|
|
86
76
|
// Transform the fileShaMap and fnShaMap into a generic shaMap that file-uploader.js can use
|
|
87
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'required' implicitly has an 'any' type.
|
|
88
77
|
export const getUploadList = (required, shaMap) => {
|
|
89
78
|
if (!required || !shaMap)
|
|
90
79
|
return [];
|
|
91
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'sha' implicitly has an 'any' type.
|
|
92
80
|
return required.flatMap((sha) => shaMap[sha]);
|
|
93
81
|
};
|
|
94
82
|
//# sourceMappingURL=util.js.map
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@netlify/database": "latest",
|
|
13
|
-
"@netlify/functions": "^6.0.
|
|
13
|
+
"@netlify/functions": "^6.0.2",
|
|
14
14
|
"@types/node": "^22.0.0",
|
|
15
15
|
"typescript": "^4.5.5"
|
|
16
16
|
}
|
|
@@ -41,12 +41,12 @@
|
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
"node_modules/@netlify/functions": {
|
|
44
|
-
"version": "6.0.
|
|
45
|
-
"resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-6.0.
|
|
46
|
-
"integrity": "sha512-
|
|
44
|
+
"version": "6.0.2",
|
|
45
|
+
"resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-6.0.2.tgz",
|
|
46
|
+
"integrity": "sha512-JqbPgAOt2GAwzCEitdEWAHOn6AkZ0Rna401wdAyuDIBiDv9M03b3Cu5mGH7/eHOmIXfZIcN1pG35flHjfu6asQ==",
|
|
47
47
|
"license": "MIT",
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@netlify/types": "3.
|
|
49
|
+
"@netlify/types": "3.2.0"
|
|
50
50
|
},
|
|
51
51
|
"engines": {
|
|
52
52
|
"node": ">=22.12.0"
|
|
@@ -62,9 +62,9 @@
|
|
|
62
62
|
}
|
|
63
63
|
},
|
|
64
64
|
"node_modules/@netlify/types": {
|
|
65
|
-
"version": "3.
|
|
66
|
-
"resolved": "https://registry.npmjs.org/@netlify/types/-/types-3.
|
|
67
|
-
"integrity": "sha512-
|
|
65
|
+
"version": "3.2.0",
|
|
66
|
+
"resolved": "https://registry.npmjs.org/@netlify/types/-/types-3.2.0.tgz",
|
|
67
|
+
"integrity": "sha512-PVvY1EEN9i2Er0LQoiyNG7i/BnwnttLuZqIkBnhL2Jrcj3P5N/NcGkv1i20MJ2ngNGSPQcT7tagDmF3V6BsdWg==",
|
|
68
68
|
"license": "MIT",
|
|
69
69
|
"engines": {
|
|
70
70
|
"node": ">=22.12.0"
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@netlify/database": "latest",
|
|
13
|
-
"@netlify/functions": "^6.0.
|
|
13
|
+
"@netlify/functions": "^6.0.2",
|
|
14
14
|
"@types/node": "^22.0.0",
|
|
15
15
|
"drizzle-orm": "beta",
|
|
16
16
|
"typescript": "^4.5.5"
|
|
@@ -42,12 +42,12 @@
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"node_modules/@netlify/functions": {
|
|
45
|
-
"version": "6.0.
|
|
46
|
-
"resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-6.0.
|
|
47
|
-
"integrity": "sha512-
|
|
45
|
+
"version": "6.0.2",
|
|
46
|
+
"resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-6.0.2.tgz",
|
|
47
|
+
"integrity": "sha512-JqbPgAOt2GAwzCEitdEWAHOn6AkZ0Rna401wdAyuDIBiDv9M03b3Cu5mGH7/eHOmIXfZIcN1pG35flHjfu6asQ==",
|
|
48
48
|
"license": "MIT",
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@netlify/types": "3.
|
|
50
|
+
"@netlify/types": "3.2.0"
|
|
51
51
|
},
|
|
52
52
|
"engines": {
|
|
53
53
|
"node": ">=22.12.0"
|
|
@@ -63,9 +63,9 @@
|
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
65
|
"node_modules/@netlify/types": {
|
|
66
|
-
"version": "3.
|
|
67
|
-
"resolved": "https://registry.npmjs.org/@netlify/types/-/types-3.
|
|
68
|
-
"integrity": "sha512-
|
|
66
|
+
"version": "3.2.0",
|
|
67
|
+
"resolved": "https://registry.npmjs.org/@netlify/types/-/types-3.2.0.tgz",
|
|
68
|
+
"integrity": "sha512-PVvY1EEN9i2Er0LQoiyNG7i/BnwnttLuZqIkBnhL2Jrcj3P5N/NcGkv1i20MJ2ngNGSPQcT7tagDmF3V6BsdWg==",
|
|
69
69
|
"license": "MIT",
|
|
70
70
|
"engines": {
|
|
71
71
|
"node": ">=22.12.0"
|
|
@@ -9,28 +9,26 @@
|
|
|
9
9
|
"version": "1.0.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@netlify/functions": "^6.0.
|
|
12
|
+
"@netlify/functions": "^6.0.2",
|
|
13
13
|
"@types/node": "^22.0.0",
|
|
14
14
|
"typescript": "^4.0.0"
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
"node_modules/@netlify/functions": {
|
|
18
|
-
"version": "6.0.
|
|
19
|
-
"resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-6.0.
|
|
20
|
-
"integrity": "sha512-
|
|
21
|
-
"license": "MIT",
|
|
18
|
+
"version": "6.0.2",
|
|
19
|
+
"resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-6.0.2.tgz",
|
|
20
|
+
"integrity": "sha512-JqbPgAOt2GAwzCEitdEWAHOn6AkZ0Rna401wdAyuDIBiDv9M03b3Cu5mGH7/eHOmIXfZIcN1pG35flHjfu6asQ==",
|
|
22
21
|
"dependencies": {
|
|
23
|
-
"@netlify/types": "3.
|
|
22
|
+
"@netlify/types": "3.2.0"
|
|
24
23
|
},
|
|
25
24
|
"engines": {
|
|
26
25
|
"node": ">=22.12.0"
|
|
27
26
|
}
|
|
28
27
|
},
|
|
29
28
|
"node_modules/@netlify/types": {
|
|
30
|
-
"version": "3.
|
|
31
|
-
"resolved": "https://registry.npmjs.org/@netlify/types/-/types-3.
|
|
32
|
-
"integrity": "sha512-
|
|
33
|
-
"license": "MIT",
|
|
29
|
+
"version": "3.2.0",
|
|
30
|
+
"resolved": "https://registry.npmjs.org/@netlify/types/-/types-3.2.0.tgz",
|
|
31
|
+
"integrity": "sha512-PVvY1EEN9i2Er0LQoiyNG7i/BnwnttLuZqIkBnhL2Jrcj3P5N/NcGkv1i20MJ2ngNGSPQcT7tagDmF3V6BsdWg==",
|
|
34
32
|
"engines": {
|
|
35
33
|
"node": ">=22.12.0"
|
|
36
34
|
}
|
|
@@ -63,17 +61,17 @@
|
|
|
63
61
|
},
|
|
64
62
|
"dependencies": {
|
|
65
63
|
"@netlify/functions": {
|
|
66
|
-
"version": "6.0.
|
|
67
|
-
"resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-6.0.
|
|
68
|
-
"integrity": "sha512-
|
|
64
|
+
"version": "6.0.2",
|
|
65
|
+
"resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-6.0.2.tgz",
|
|
66
|
+
"integrity": "sha512-JqbPgAOt2GAwzCEitdEWAHOn6AkZ0Rna401wdAyuDIBiDv9M03b3Cu5mGH7/eHOmIXfZIcN1pG35flHjfu6asQ==",
|
|
69
67
|
"requires": {
|
|
70
|
-
"@netlify/types": "3.
|
|
68
|
+
"@netlify/types": "3.2.0"
|
|
71
69
|
}
|
|
72
70
|
},
|
|
73
71
|
"@netlify/types": {
|
|
74
|
-
"version": "3.
|
|
75
|
-
"resolved": "https://registry.npmjs.org/@netlify/types/-/types-3.
|
|
76
|
-
"integrity": "sha512-
|
|
72
|
+
"version": "3.2.0",
|
|
73
|
+
"resolved": "https://registry.npmjs.org/@netlify/types/-/types-3.2.0.tgz",
|
|
74
|
+
"integrity": "sha512-PVvY1EEN9i2Er0LQoiyNG7i/BnwnttLuZqIkBnhL2Jrcj3P5N/NcGkv1i20MJ2ngNGSPQcT7tagDmF3V6BsdWg=="
|
|
77
75
|
},
|
|
78
76
|
"@types/node": {
|
|
79
77
|
"version": "22.18.11",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "netlify-cli",
|
|
3
|
-
"version": "27.12.
|
|
3
|
+
"version": "27.12.1",
|
|
4
4
|
"description": "Netlify command line tool",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api",
|
|
@@ -152,7 +152,7 @@
|
|
|
152
152
|
"@bugsnag/js": "^8.6.0",
|
|
153
153
|
"@eslint/compat": "^1.4.1",
|
|
154
154
|
"@eslint/js": "^9.36.0",
|
|
155
|
-
"@netlify/functions": "^6.0.
|
|
155
|
+
"@netlify/functions": "^6.0.2",
|
|
156
156
|
"@netlify/types": "^3.2.0",
|
|
157
157
|
"@sindresorhus/slugify": "^3.0.0",
|
|
158
158
|
"@tsconfig/node22": "22.0.5",
|