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.
Files changed (32) hide show
  1. package/dist/commands/deploy/deploy.js +28 -59
  2. package/dist/lib/spinner.d.ts +2 -2
  3. package/dist/lib/spinner.js +1 -1
  4. package/dist/utils/deploy/deploy-site.d.ts +32 -12
  5. package/dist/utils/deploy/deploy-site.js +18 -40
  6. package/dist/utils/deploy/drop-api.d.ts +7 -1
  7. package/dist/utils/deploy/drop-api.js +3 -4
  8. package/dist/utils/deploy/file.d.ts +4 -2
  9. package/dist/utils/deploy/hash-config.d.ts +5 -6
  10. package/dist/utils/deploy/hash-config.js +1 -4
  11. package/dist/utils/deploy/hash-files.d.ts +9 -8
  12. package/dist/utils/deploy/hash-fns.d.ts +45 -10
  13. package/dist/utils/deploy/hasher-segments.d.ts +10 -6
  14. package/dist/utils/deploy/hasher-segments.js +0 -1
  15. package/dist/utils/deploy/process-files.d.ts +1 -1
  16. package/dist/utils/deploy/process-files.js +1 -0
  17. package/dist/utils/deploy/types.d.ts +17 -0
  18. package/dist/utils/deploy/types.js +2 -0
  19. package/dist/utils/deploy/upload-files.d.ts +8 -3
  20. package/dist/utils/deploy/upload-files.js +4 -3
  21. package/dist/utils/deploy/upload-source-zip.js +4 -7
  22. package/dist/utils/deploy/util.d.ts +6 -3
  23. package/dist/utils/deploy/util.js +4 -16
  24. package/functions-templates/javascript/scheduled-function/package.json +1 -1
  25. package/functions-templates/typescript/database/package-lock.json +8 -8
  26. package/functions-templates/typescript/database/package.json +1 -1
  27. package/functions-templates/typescript/database-drizzle/package-lock.json +8 -8
  28. package/functions-templates/typescript/database-drizzle/package.json +1 -1
  29. package/functions-templates/typescript/hello-world/package-lock.json +15 -17
  30. package/functions-templates/typescript/hello-world/package.json +1 -1
  31. package/functions-templates/typescript/scheduled-function/package.json +1 -1
  32. 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
- // @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message
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(serhalp) -- Untyped in `@netlify/build`
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({ siteId, title, body: createDeployBody });
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 ? null : await getFunctionsManifestPath({ base: site.root, packagePath });
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 'CachedConfig' is not assignable to type 'Record<string, unknown>'.
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
- const siteData = await api.createSiteInTeam({
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
- const siteData = await api.createSiteInTeam({
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 = (deploy.ssl_url || deploy.url || `https://${deployInfo.subdomain}.netlify.app`);
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,
@@ -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
  /**
@@ -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 BaseCommand from '../../commands/base-command.js';
2
- import { type $TSFixMe } from '../../commands/types.js';
3
- import type { DeployEvent } from './status-cb.js';
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 declare const deploySite: (command: BaseCommand, api: $TSFixMe, siteId: any, dir: any, { assetType, branch, concurrentHash, concurrentUpload, config, deployId, deployTimeout, draft, environment, filter, fnDir, functionsConfig, hashAlgorithm, manifestPath, maxRetry, packagePath, serverEnabled, serverManifestPath, siteRoot, skipFunctionsCache, statusCb, syncFileLimit, tmpDir, workingDir, }: {
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
- statusCb?: (status: DeployEvent) => void;
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
- }) => Promise<{
22
- deployId: any;
23
- deploy: any;
24
- uploadList: any[];
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
- // @ts-expect-error TS(2349) This expression is not callable
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
- let deploy = await api.updateSiteDeploy(deployParams);
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
- (requiredFns?.length ?? 0) > 0 && pluralize(requiredFns.length, 'function'),
155
- (requiredEdgeFns?.length ?? 0) > 0 && pluralize(requiredEdgeFns.length, 'edge function'),
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
- deploy = await waitForDeploy(api, deployId, siteId, deployTimeout);
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
- const deployManifest = {
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
- export declare const waitForDropDeploy: ({ apiBase, userAgent }: DropApiOptions, siteId: string, deployId: string, timeout?: number) => Promise<Record<string, unknown>>;
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: 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 File = walker.Entry & {
3
+ export type HashedFile = OriginalFile & {
4
4
  hash: string;
5
- assetType: string;
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: any;
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: any) => string;
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
- // @ts-expect-error TS(7006) FIXME: Parameter 'key' implicitly has an 'any' type.
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 { $TSFixMe } from '../../commands/types.js';
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?: string | undefined;
4
- concurrentHash: $TSFixMe;
5
- directories: $TSFixMe;
6
- filter: $TSFixMe;
4
+ assetType?: 'file' | undefined;
5
+ concurrentHash: number;
6
+ directories: string[];
7
+ filter: ((filename: string) => boolean) | undefined;
7
8
  hashAlgorithm?: string | undefined;
8
- normalizer?: $TSFixMe;
9
- statusCb: $TSFixMe;
9
+ normalizer?: (file: File) => File;
10
+ statusCb: StatusCallback;
10
11
  }) => Promise<{
11
12
  files: Record<string, string>;
12
- filesShaMap: Record<string, $TSFixMe[]>;
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 BaseCommand from '../../commands/base-command.js';
2
- import { $TSFixMe } from '../../commands/types.js';
3
- import type { ServerUploadFile } from './upload-files.js';
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?: $TSFixMe;
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: $TSFixMe;
15
- tmpDir: $TSFixMe;
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: $TSFixMe[];
23
- shaMap?: Record<string, $TSFixMe> | undefined;
24
- fnShaMap?: Record<string, $TSFixMe[]> | undefined;
25
- fnConfig?: Record<string, $TSFixMe> | undefined;
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, OriginalFile } from './file.js';
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: any;
6
- hashAlgorithm: any;
5
+ concurrentHash?: number;
6
+ hashAlgorithm: string;
7
7
  }) => Transform;
8
8
  export declare const fileNormalizerCtor: ({ assetType, normalizer: normalizeFunction, }: {
9
- assetType: string;
10
- normalizer?: (file: OriginalFile) => File;
9
+ assetType: 'file';
10
+ normalizer?: (file: File) => File;
11
11
  }) => Transform;
12
- export declare const manifestCollectorCtor: (filesObj: Record<string, unknown>, shaMap: Record<string, unknown[]>, { statusCb }: {
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: string;
10
+ assetType: 'file';
11
11
  normalizedPath: string;
12
12
  };
13
13
  export declare const getDeployConfigPathIfExists: (workingDir: string) => Promise<string | undefined>;
@@ -39,6 +39,7 @@ const getDirectoryIfExists = async (directoryPath) => {
39
39
  catch {
40
40
  // no-op
41
41
  }
42
+ return undefined;
42
43
  };
43
44
  export const isEdgeFunctionFile = (filePath) => filePath.startsWith(`${PUBLIC_URL_PATH}/`);
44
45
  //# sourceMappingURL=process-files.js.map
@@ -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
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.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?: fs.ReadStream;
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
- const readStreamCtor = () => body ?? fs.createReadStream(filepath);
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 (_baseErr) {
58
- let message = 'zip command failed';
59
- if (_baseErr instanceof Error && 'command' in _baseErr) {
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: any, deployId: any, siteId: any, timeout: any) => Promise<undefined>;
4
- export declare const waitForDeploy: (api: any, deployId: any, siteId: any, timeout: any) => Promise<undefined>;
5
- export declare const getUploadList: (required: any, shaMap: any) => any;
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
- deploy = siteDeploy;
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
- deploy = siteDeploy;
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
@@ -15,6 +15,6 @@
15
15
  "test": "echo \"Error: no test specified\" && exit 1"
16
16
  },
17
17
  "dependencies": {
18
- "@netlify/functions": "^6.0.0"
18
+ "@netlify/functions": "^6.0.2"
19
19
  }
20
20
  }
@@ -10,7 +10,7 @@
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@netlify/database": "latest",
13
- "@netlify/functions": "^6.0.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.0",
45
- "resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-6.0.0.tgz",
46
- "integrity": "sha512-Pee+FoFnAtdejTkl62a7mZxj6Wx4eqVNuYyDc5T4XPJN9GaAWaUf4cZQFlf2m4Fqq0HoghjtcPKo+BZviVPPKA==",
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.0.0"
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.0.0",
66
- "resolved": "https://registry.npmjs.org/@netlify/types/-/types-3.0.0.tgz",
67
- "integrity": "sha512-zRCidsQgI4CZWrZB/kmwdPf0QbSNljakfNSLizFvrsSA3UcUrTWSBNMVKmZnob92/8ESeUN0ewXLOlffJU+ATQ==",
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"
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "@netlify/database": "latest",
19
- "@netlify/functions": "^6.0.0",
19
+ "@netlify/functions": "^6.0.2",
20
20
  "@types/node": "^22.0.0",
21
21
  "typescript": "^4.5.5"
22
22
  }
@@ -10,7 +10,7 @@
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@netlify/database": "latest",
13
- "@netlify/functions": "^6.0.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.0",
46
- "resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-6.0.0.tgz",
47
- "integrity": "sha512-Pee+FoFnAtdejTkl62a7mZxj6Wx4eqVNuYyDc5T4XPJN9GaAWaUf4cZQFlf2m4Fqq0HoghjtcPKo+BZviVPPKA==",
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.0.0"
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.0.0",
67
- "resolved": "https://registry.npmjs.org/@netlify/types/-/types-3.0.0.tgz",
68
- "integrity": "sha512-zRCidsQgI4CZWrZB/kmwdPf0QbSNljakfNSLizFvrsSA3UcUrTWSBNMVKmZnob92/8ESeUN0ewXLOlffJU+ATQ==",
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"
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@netlify/database": "latest",
20
- "@netlify/functions": "^6.0.0",
20
+ "@netlify/functions": "^6.0.2",
21
21
  "@types/node": "^22.0.0",
22
22
  "drizzle-orm": "beta",
23
23
  "typescript": "^4.5.5"
@@ -9,28 +9,26 @@
9
9
  "version": "1.0.0",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "@netlify/functions": "^6.0.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.0",
19
- "resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-6.0.0.tgz",
20
- "integrity": "sha512-Pee+FoFnAtdejTkl62a7mZxj6Wx4eqVNuYyDc5T4XPJN9GaAWaUf4cZQFlf2m4Fqq0HoghjtcPKo+BZviVPPKA==",
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.0.0"
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.0.0",
31
- "resolved": "https://registry.npmjs.org/@netlify/types/-/types-3.0.0.tgz",
32
- "integrity": "sha512-zRCidsQgI4CZWrZB/kmwdPf0QbSNljakfNSLizFvrsSA3UcUrTWSBNMVKmZnob92/8ESeUN0ewXLOlffJU+ATQ==",
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.0",
67
- "resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-6.0.0.tgz",
68
- "integrity": "sha512-Pee+FoFnAtdejTkl62a7mZxj6Wx4eqVNuYyDc5T4XPJN9GaAWaUf4cZQFlf2m4Fqq0HoghjtcPKo+BZviVPPKA==",
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.0.0"
68
+ "@netlify/types": "3.2.0"
71
69
  }
72
70
  },
73
71
  "@netlify/types": {
74
- "version": "3.0.0",
75
- "resolved": "https://registry.npmjs.org/@netlify/types/-/types-3.0.0.tgz",
76
- "integrity": "sha512-zRCidsQgI4CZWrZB/kmwdPf0QbSNljakfNSLizFvrsSA3UcUrTWSBNMVKmZnob92/8ESeUN0ewXLOlffJU+ATQ=="
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",
@@ -14,7 +14,7 @@
14
14
  "test": "echo \"Error: no test specified\" && exit 1"
15
15
  },
16
16
  "dependencies": {
17
- "@netlify/functions": "^6.0.0",
17
+ "@netlify/functions": "^6.0.2",
18
18
  "@types/node": "^22.0.0",
19
19
  "typescript": "^4.0.0"
20
20
  }
@@ -15,7 +15,7 @@
15
15
  "test": "echo \"Error: no test specified\" && exit 1"
16
16
  },
17
17
  "dependencies": {
18
- "@netlify/functions": "^6.0.0",
18
+ "@netlify/functions": "^6.0.2",
19
19
  "@types/node": "^22.0.0",
20
20
  "typescript": "^4.5.5"
21
21
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "netlify-cli",
3
- "version": "27.12.0",
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.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",