@netlify/zip-it-and-ship-it 9.5.0 → 9.6.0

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.
@@ -8,6 +8,7 @@ export declare const defaultFlags: {
8
8
  readonly zisi_output_cjs_extension: false;
9
9
  readonly zisi_functions_api_v2: false;
10
10
  readonly zisi_unique_entry_file: false;
11
+ readonly zisi_use_latest_babel_version: false;
11
12
  };
12
13
  export type FeatureFlags = Partial<Record<keyof typeof defaultFlags, boolean>>;
13
14
  export declare const getFlags: (input?: Record<string, boolean>, flags?: {
@@ -20,4 +21,5 @@ export declare const getFlags: (input?: Record<string, boolean>, flags?: {
20
21
  readonly zisi_output_cjs_extension: false;
21
22
  readonly zisi_functions_api_v2: false;
22
23
  readonly zisi_unique_entry_file: false;
24
+ readonly zisi_use_latest_babel_version: false;
23
25
  }) => FeatureFlags;
@@ -20,6 +20,8 @@ export const defaultFlags = {
20
20
  zisi_functions_api_v2: false,
21
21
  // Create unique entry file instead of a file that is based on the function name.
22
22
  zisi_unique_entry_file: false,
23
+ // Uses the latest babel parser version
24
+ zisi_use_latest_babel_version: false,
23
25
  };
24
26
  // List of supported flags and their default value.
25
27
  export const getFlags = (input = {}, flags = defaultFlags) => Object.entries(flags).reduce((result, [key, defaultValue]) => ({
package/dist/main.d.ts CHANGED
@@ -27,13 +27,13 @@ interface ListFunctionsOptions {
27
27
  parseISC?: boolean;
28
28
  }
29
29
  export declare const listFunctions: (relativeSrcFolders: string | string[], { featureFlags: inputFeatureFlags, config, configFileDirectories, parseISC, }?: {
30
- featureFlags?: Partial<Record<"buildRustSource" | "parseWithEsbuild" | "traceWithNft" | "functions_inherit_build_nodejs_version" | "zisi_pure_esm" | "zisi_pure_esm_mjs" | "zisi_output_cjs_extension" | "zisi_functions_api_v2" | "zisi_unique_entry_file", boolean>> | undefined;
30
+ featureFlags?: Partial<Record<"buildRustSource" | "parseWithEsbuild" | "traceWithNft" | "functions_inherit_build_nodejs_version" | "zisi_pure_esm" | "zisi_pure_esm_mjs" | "zisi_output_cjs_extension" | "zisi_functions_api_v2" | "zisi_unique_entry_file" | "zisi_use_latest_babel_version", boolean>> | undefined;
31
31
  config?: Config | undefined;
32
32
  configFileDirectories?: string[] | undefined;
33
33
  parseISC?: boolean | undefined;
34
34
  }) => Promise<ListedFunction[]>;
35
35
  export declare const listFunction: (path: string, { featureFlags: inputFeatureFlags, config, configFileDirectories, parseISC, }?: {
36
- featureFlags?: Partial<Record<"buildRustSource" | "parseWithEsbuild" | "traceWithNft" | "functions_inherit_build_nodejs_version" | "zisi_pure_esm" | "zisi_pure_esm_mjs" | "zisi_output_cjs_extension" | "zisi_functions_api_v2" | "zisi_unique_entry_file", boolean>> | undefined;
36
+ featureFlags?: Partial<Record<"buildRustSource" | "parseWithEsbuild" | "traceWithNft" | "functions_inherit_build_nodejs_version" | "zisi_pure_esm" | "zisi_pure_esm_mjs" | "zisi_output_cjs_extension" | "zisi_functions_api_v2" | "zisi_unique_entry_file" | "zisi_use_latest_babel_version", boolean>> | undefined;
37
37
  config?: Config | undefined;
38
38
  configFileDirectories?: string[] | undefined;
39
39
  parseISC?: boolean | undefined;
package/dist/main.js CHANGED
@@ -10,13 +10,13 @@ export { ARCHIVE_FORMAT } from './archive.js';
10
10
  export { NODE_BUNDLER } from './runtimes/node/bundlers/types.js';
11
11
  export { RUNTIME } from './runtimes/runtime.js';
12
12
  export { MODULE_FORMAT } from './runtimes/node/utils/module_format.js';
13
- const augmentWithISC = async (func) => {
13
+ const augmentWithISC = async (func, featureFlags) => {
14
14
  // ISC is currently only supported in JavaScript and TypeScript functions
15
15
  // and only supports scheduled functions.
16
16
  if (func.runtime.name !== RUNTIME.JAVASCRIPT) {
17
17
  return func;
18
18
  }
19
- const inSourceConfig = await findISCDeclarationsInPath(func.mainFile, func.name);
19
+ const inSourceConfig = await findISCDeclarationsInPath(func.mainFile, func.name, featureFlags);
20
20
  return { ...func, inSourceConfig };
21
21
  };
22
22
  // List all Netlify Functions main entry files for a specific directory
@@ -27,7 +27,9 @@ export const listFunctions = async function (relativeSrcFolders, { featureFlags:
27
27
  const cache = new RuntimeCache();
28
28
  const functionsMap = await getFunctionsFromPaths(paths, { cache, config, configFileDirectories, featureFlags });
29
29
  const functions = [...functionsMap.values()];
30
- const augmentedFunctions = parseISC ? await Promise.all(functions.map(augmentWithISC)) : functions;
30
+ const augmentedFunctions = parseISC
31
+ ? await Promise.all(functions.map((func) => augmentWithISC(func, featureFlags)))
32
+ : functions;
31
33
  return augmentedFunctions.map(getListedFunction);
32
34
  };
33
35
  // Finds a function at a specific path.
@@ -38,7 +40,7 @@ export const listFunction = async function (path, { featureFlags: inputFeatureFl
38
40
  if (!func) {
39
41
  return;
40
42
  }
41
- const augmentedFunction = parseISC ? await augmentWithISC(func) : func;
43
+ const augmentedFunction = parseISC ? await augmentWithISC(func, featureFlags) : func;
42
44
  return getListedFunction(augmentedFunction);
43
45
  };
44
46
  // List all Netlify Functions files for a specific directory
@@ -49,7 +51,9 @@ export const listFunctionsFiles = async function (relativeSrcFolders, { basePath
49
51
  const cache = new RuntimeCache();
50
52
  const functionsMap = await getFunctionsFromPaths(paths, { cache, config, configFileDirectories, featureFlags });
51
53
  const functions = [...functionsMap.values()];
52
- const augmentedFunctions = parseISC ? await Promise.all(functions.map(augmentWithISC)) : functions;
54
+ const augmentedFunctions = parseISC
55
+ ? await Promise.all(functions.map((func) => augmentWithISC(func, featureFlags)))
56
+ : functions;
53
57
  const listedFunctionsFiles = await Promise.all(augmentedFunctions.map((func) => getListedFunctionFiles(func, { basePath, featureFlags })));
54
58
  return listedFunctionsFiles.flat();
55
59
  };
@@ -65,7 +69,11 @@ const getListedFunction = function ({ runtime, name, mainFile, extension, config
65
69
  };
66
70
  };
67
71
  const getListedFunctionFiles = async function (func, options) {
68
- const srcFiles = await getSrcFiles({ ...func, ...options });
72
+ const srcFiles = await getSrcFiles({
73
+ ...func,
74
+ ...options,
75
+ runtimeAPIVersion: func.inSourceConfig?.runtimeAPIVersion ?? 1,
76
+ });
69
77
  return srcFiles.map((srcFile) => ({ ...getListedFunction(func), srcFile, extension: extname(srcFile) }));
70
78
  };
71
79
  const getSrcFiles = async function ({ extension, runtime, srcPath, ...args }) {
@@ -11,7 +11,7 @@ export declare const getFunctionsFromPaths: (paths: string[], { cache, config, c
11
11
  config?: Config | undefined;
12
12
  configFileDirectories?: string[] | undefined;
13
13
  dedupe?: boolean | undefined;
14
- featureFlags?: Partial<Record<"buildRustSource" | "parseWithEsbuild" | "traceWithNft" | "functions_inherit_build_nodejs_version" | "zisi_pure_esm" | "zisi_pure_esm_mjs" | "zisi_output_cjs_extension" | "zisi_functions_api_v2" | "zisi_unique_entry_file", boolean>> | undefined;
14
+ featureFlags?: Partial<Record<"buildRustSource" | "parseWithEsbuild" | "traceWithNft" | "functions_inherit_build_nodejs_version" | "zisi_pure_esm" | "zisi_pure_esm_mjs" | "zisi_output_cjs_extension" | "zisi_functions_api_v2" | "zisi_unique_entry_file" | "zisi_use_latest_babel_version", boolean>> | undefined;
15
15
  }) => Promise<FunctionMap>;
16
16
  /**
17
17
  * Gets a list of functions found in a list of paths.
@@ -20,6 +20,6 @@ export declare const getFunctionFromPath: (path: string, { cache, config, config
20
20
  cache: RuntimeCache;
21
21
  config?: Config | undefined;
22
22
  configFileDirectories?: string[] | undefined;
23
- featureFlags?: Partial<Record<"buildRustSource" | "parseWithEsbuild" | "traceWithNft" | "functions_inherit_build_nodejs_version" | "zisi_pure_esm" | "zisi_pure_esm_mjs" | "zisi_output_cjs_extension" | "zisi_functions_api_v2" | "zisi_unique_entry_file", boolean>> | undefined;
23
+ featureFlags?: Partial<Record<"buildRustSource" | "parseWithEsbuild" | "traceWithNft" | "functions_inherit_build_nodejs_version" | "zisi_pure_esm" | "zisi_pure_esm_mjs" | "zisi_output_cjs_extension" | "zisi_functions_api_v2" | "zisi_unique_entry_file" | "zisi_use_latest_babel_version", boolean>> | undefined;
24
24
  }) => Promise<FunctionSource | undefined>;
25
25
  export {};
@@ -43,6 +43,7 @@ export const bundleJsFile = async function ({ additionalModulePaths, basePath, c
43
43
  moduleNames: nodeModulesWithDynamicImports,
44
44
  processImports: config.processDynamicNodeImports !== false,
45
45
  srcDir,
46
+ featureFlags,
46
47
  }),
47
48
  ];
48
49
  // The version of ECMAScript to use as the build target. This will determine
@@ -1,8 +1,10 @@
1
1
  import type { Plugin } from '@netlify/esbuild';
2
- export declare const getDynamicImportsPlugin: ({ basePath, includedPaths, moduleNames, processImports, srcDir, }: {
2
+ import type { FeatureFlags } from '../../../../feature_flags.js';
3
+ export declare const getDynamicImportsPlugin: ({ basePath, includedPaths, moduleNames, processImports, srcDir, featureFlags, }: {
3
4
  basePath?: string | undefined;
4
5
  includedPaths: Set<string>;
5
6
  moduleNames: Set<string>;
6
7
  processImports: boolean;
7
8
  srcDir: string;
9
+ featureFlags: FeatureFlags;
8
10
  }) => Plugin;
@@ -10,7 +10,7 @@ import { readPackageJson } from '../../utils/package_json.js';
10
10
  // issues. Secondly, it parses the dynamic expressions and tries to include in
11
11
  // the bundle all the files that are possibly needed to make the import work at
12
12
  // runtime. This is not always possible, but we do our best.
13
- export const getDynamicImportsPlugin = ({ basePath, includedPaths, moduleNames, processImports, srcDir, }) => ({
13
+ export const getDynamicImportsPlugin = ({ basePath, includedPaths, moduleNames, processImports, srcDir, featureFlags, }) => ({
14
14
  name: 'dynamic-imports',
15
15
  setup(build) {
16
16
  const cache = new Map();
@@ -21,7 +21,7 @@ export const getDynamicImportsPlugin = ({ basePath, includedPaths, moduleNames,
21
21
  // Also don't parse the expression if we're not interested in processing
22
22
  // the dynamic import expressions.
23
23
  if (basePath && processImports) {
24
- const { includedPathsGlob, type: expressionType } = parseExpression({ basePath, expression, resolveDir }) || {};
24
+ const { includedPathsGlob, type: expressionType } = parseExpression({ basePath, expression, resolveDir, featureFlags }) || {};
25
25
  if (includedPathsGlob) {
26
26
  // The parser has found a glob of paths that should be included in the
27
27
  // bundle to make this import work, so we add it to `includedPaths`.
@@ -2,9 +2,10 @@ import { FunctionConfig } from '../../../config.js';
2
2
  import { FeatureFlags } from '../../../feature_flags.js';
3
3
  import { NodeBundler, NodeBundlerName } from './types.js';
4
4
  export declare const getBundler: (name: NodeBundlerName) => NodeBundler;
5
- export declare const getBundlerName: ({ config: { nodeBundler }, extension, featureFlags, mainFile, }: {
5
+ export declare const getBundlerName: ({ config: { nodeBundler }, extension, featureFlags, mainFile, runtimeAPIVersion, }: {
6
6
  config: FunctionConfig;
7
7
  extension: string;
8
8
  featureFlags: FeatureFlags;
9
9
  mainFile: string;
10
+ runtimeAPIVersion: number;
10
11
  }) => Promise<NodeBundlerName>;
@@ -21,18 +21,17 @@ export const getBundler = (name) => {
21
21
  throw new Error(`Unsupported Node bundler: ${name}`);
22
22
  }
23
23
  };
24
- export const getBundlerName = async ({ config: { nodeBundler }, extension, featureFlags, mainFile, }) => {
24
+ export const getBundlerName = async ({ config: { nodeBundler }, extension, featureFlags, mainFile, runtimeAPIVersion, }) => {
25
25
  if (nodeBundler) {
26
26
  return nodeBundler;
27
27
  }
28
- return await getDefaultBundler({ extension, featureFlags, mainFile });
28
+ return await getDefaultBundler({ extension, featureFlags, mainFile, runtimeAPIVersion });
29
29
  };
30
30
  const ESBUILD_EXTENSIONS = new Set(['.mjs', '.ts', '.tsx', '.cts', '.mts']);
31
31
  // We use ZISI as the default bundler, except for certain extensions, for which
32
32
  // esbuild is the only option.
33
- const getDefaultBundler = async ({ extension, featureFlags, mainFile, }) => {
34
- if ((extension === MODULE_FILE_EXTENSION.MJS && featureFlags.zisi_pure_esm_mjs) ||
35
- featureFlags.zisi_functions_api_v2) {
33
+ const getDefaultBundler = async ({ extension, featureFlags, mainFile, runtimeAPIVersion, }) => {
34
+ if ((extension === MODULE_FILE_EXTENSION.MJS && featureFlags.zisi_pure_esm_mjs) || runtimeAPIVersion === 2) {
36
35
  return NODE_BUNDLER.NFT;
37
36
  }
38
37
  if (ESBUILD_EXTENSIONS.has(extension)) {
@@ -3,7 +3,7 @@ import type { FunctionConfig } from '../../../../config.js';
3
3
  import { FeatureFlags } from '../../../../feature_flags.js';
4
4
  import type { RuntimeCache } from '../../../../utils/cache.js';
5
5
  import { ModuleFormat } from '../../utils/module_format.js';
6
- export declare const processESM: ({ basePath, cache, config, esmPaths, featureFlags, mainFile, reasons, name, }: {
6
+ export declare const processESM: ({ basePath, cache, config, esmPaths, featureFlags, mainFile, reasons, name, runtimeAPIVersion, }: {
7
7
  basePath: string | undefined;
8
8
  cache: RuntimeCache;
9
9
  config: FunctionConfig;
@@ -12,6 +12,7 @@ export declare const processESM: ({ basePath, cache, config, esmPaths, featureFl
12
12
  mainFile: string;
13
13
  reasons: NodeFileTraceReasons;
14
14
  name: string;
15
+ runtimeAPIVersion: number;
15
16
  }) => Promise<{
16
17
  rewrites?: Map<string, string> | undefined;
17
18
  moduleFormat: ModuleFormat;
@@ -29,19 +29,18 @@ const patchESMPackage = async (path, cache) => {
29
29
  };
30
30
  return JSON.stringify(patchedPackageJson);
31
31
  };
32
- export const processESM = async ({ basePath, cache, config, esmPaths, featureFlags, mainFile, reasons, name, }) => {
32
+ export const processESM = async ({ basePath, cache, config, esmPaths, featureFlags, mainFile, reasons, name, runtimeAPIVersion, }) => {
33
33
  const extension = extname(mainFile);
34
34
  // If this is a .mjs file and we want to output pure ESM files, we don't need
35
35
  // to transpile anything.
36
- if (extension === MODULE_FILE_EXTENSION.MJS &&
37
- (featureFlags.zisi_pure_esm_mjs || featureFlags.zisi_functions_api_v2)) {
36
+ if (extension === MODULE_FILE_EXTENSION.MJS && (featureFlags.zisi_pure_esm_mjs || runtimeAPIVersion === 2)) {
38
37
  return {
39
38
  moduleFormat: MODULE_FORMAT.ESM,
40
39
  };
41
40
  }
42
41
  const entrypointIsESM = isEntrypointESM({ basePath, esmPaths, mainFile });
43
42
  if (!entrypointIsESM) {
44
- if (featureFlags.zisi_functions_api_v2) {
43
+ if (runtimeAPIVersion === 2) {
45
44
  throw new FunctionBundlingUserError(`The function '${name}' must use the ES module syntax. To learn more, visit https://ntl.fyi/esm.`, {
46
45
  functionName: name,
47
46
  runtime: RUNTIME.JAVASCRIPT,
@@ -54,14 +53,12 @@ export const processESM = async ({ basePath, cache, config, esmPaths, featureFla
54
53
  }
55
54
  const packageJson = await getPackageJsonIfAvailable(dirname(mainFile));
56
55
  const nodeSupport = getNodeSupportMatrix(config.nodeVersion);
57
- if ((featureFlags.zisi_pure_esm || featureFlags.zisi_functions_api_v2) &&
58
- packageJson.type === 'module' &&
59
- nodeSupport.esm) {
56
+ if ((featureFlags.zisi_pure_esm || runtimeAPIVersion === 2) && packageJson.type === 'module' && nodeSupport.esm) {
60
57
  return {
61
58
  moduleFormat: MODULE_FORMAT.ESM,
62
59
  };
63
60
  }
64
- if (featureFlags.zisi_functions_api_v2) {
61
+ if (runtimeAPIVersion === 2) {
65
62
  throw new FunctionBundlingUserError(`The function '${name}' must use the ES module syntax. To learn more, visit https://ntl.fyi/esm.`, {
66
63
  functionName: name,
67
64
  runtime: RUNTIME.JAVASCRIPT,
@@ -9,7 +9,7 @@ import { processESM } from './es_modules.js';
9
9
  // Paths that will be excluded from the tracing process.
10
10
  const ignore = ['node_modules/aws-sdk/**'];
11
11
  const appearsToBeModuleName = (name) => !name.startsWith('.');
12
- const bundle = async ({ basePath, cache, config, featureFlags, mainFile, name, pluginsModulesPath, repositoryRoot = basePath, }) => {
12
+ const bundle = async ({ basePath, cache, config, featureFlags, mainFile, name, pluginsModulesPath, repositoryRoot = basePath, runtimeAPIVersion, }) => {
13
13
  const { includedFiles = [], includedFilesBasePath } = config;
14
14
  const { excludePatterns, paths: includedFilePaths } = await getPathsOfIncludedFiles(includedFiles, includedFilesBasePath || basePath);
15
15
  const { moduleFormat, paths: dependencyPaths, rewrites, } = await traceFilesAndTranspile({
@@ -20,6 +20,7 @@ const bundle = async ({ basePath, cache, config, featureFlags, mainFile, name, p
20
20
  mainFile,
21
21
  pluginsModulesPath,
22
22
  name,
23
+ runtimeAPIVersion,
23
24
  });
24
25
  const includedPaths = filterExcludedPaths(includedFilePaths, excludePatterns);
25
26
  const filteredIncludedPaths = [...filterExcludedPaths(dependencyPaths, excludePatterns), ...includedPaths];
@@ -40,7 +41,7 @@ const ignoreFunction = (path) => {
40
41
  const shouldIgnore = ignore.some((expression) => minimatch(path, expression));
41
42
  return shouldIgnore;
42
43
  };
43
- const traceFilesAndTranspile = async function ({ basePath, cache, config, featureFlags, mainFile, pluginsModulesPath, name, }) {
44
+ const traceFilesAndTranspile = async function ({ basePath, cache, config, featureFlags, mainFile, pluginsModulesPath, name, runtimeAPIVersion, }) {
44
45
  const { fileList: dependencyPaths, esmFileList, reasons, } = await nodeFileTrace([mainFile], {
45
46
  // Default is 1024. Allowing double the fileIO in parallel makes nft faster, but uses a little more memory.
46
47
  fileIOConcurrency: 2048,
@@ -85,6 +86,7 @@ const traceFilesAndTranspile = async function ({ basePath, cache, config, featur
85
86
  mainFile,
86
87
  reasons,
87
88
  name,
89
+ runtimeAPIVersion,
88
90
  });
89
91
  return {
90
92
  moduleFormat,
@@ -23,6 +23,7 @@ export type BundleFunction = (args: {
23
23
  featureFlags: FeatureFlags;
24
24
  pluginsModulesPath?: string;
25
25
  repositoryRoot?: string;
26
+ runtimeAPIVersion: number;
26
27
  } & FunctionSource) => Promise<{
27
28
  aliases?: Map<string, string>;
28
29
  rewrites?: Map<string, string>;
@@ -1,11 +1,14 @@
1
1
  import type { ArgumentPlaceholder, Expression, SpreadElement, JSXNamespacedName } from '@babel/types';
2
+ import type { FeatureFlags } from '../../../feature_flags.js';
2
3
  import { InvocationMode } from '../../../function.js';
3
4
  export declare const IN_SOURCE_CONFIG_MODULE = "@netlify/functions";
4
5
  export type ISCValues = {
5
6
  invocationMode?: InvocationMode;
7
+ runtimeAPIVersion?: number;
6
8
  schedule?: string;
7
9
  };
8
- export declare const findISCDeclarationsInPath: (sourcePath: string, functionName: string) => Promise<ISCValues>;
10
+ export declare const findISCDeclarationsInPath: (sourcePath: string, functionName: string, featureFlags: FeatureFlags) => Promise<ISCValues>;
11
+ export declare const findISCDeclarations: (source: string, functionName: string, featureFlags: FeatureFlags) => ISCValues;
9
12
  export type ISCHandlerArg = ArgumentPlaceholder | Expression | SpreadElement | JSXNamespacedName;
10
13
  export interface ISCExport {
11
14
  local: string;
@@ -3,9 +3,9 @@ import { FunctionBundlingUserError } from '../../../utils/error.js';
3
3
  import { nonNullable } from '../../../utils/non_nullable.js';
4
4
  import { RUNTIME } from '../../runtime.js';
5
5
  import { createBindingsMethod } from '../parser/bindings.js';
6
- import { getMainExport } from '../parser/exports.js';
6
+ import { getExports } from '../parser/exports.js';
7
7
  import { getImports } from '../parser/imports.js';
8
- import { safelyParseFile } from '../parser/index.js';
8
+ import { safelyParseSource, safelyReadSource } from '../parser/index.js';
9
9
  import { parse as parseSchedule } from './properties/schedule.js';
10
10
  export const IN_SOURCE_CONFIG_MODULE = '@netlify/functions';
11
11
  const validateScheduleFunction = (functionFound, scheduleFound, functionName) => {
@@ -19,8 +19,15 @@ const validateScheduleFunction = (functionFound, scheduleFound, functionName) =>
19
19
  // Parses a JS/TS file and looks for in-source config declarations. It returns
20
20
  // an array of all declarations found, with `property` indicating the name of
21
21
  // the property and `data` its value.
22
- export const findISCDeclarationsInPath = async (sourcePath, functionName) => {
23
- const ast = await safelyParseFile(sourcePath);
22
+ export const findISCDeclarationsInPath = async (sourcePath, functionName, featureFlags) => {
23
+ const source = await safelyReadSource(sourcePath);
24
+ if (source === null) {
25
+ return {};
26
+ }
27
+ return findISCDeclarations(source, functionName, featureFlags);
28
+ };
29
+ export const findISCDeclarations = (source, functionName, featureFlags) => {
30
+ const ast = safelyParseSource(source, featureFlags);
24
31
  if (ast === null) {
25
32
  return {};
26
33
  }
@@ -29,8 +36,18 @@ export const findISCDeclarationsInPath = async (sourcePath, functionName) => {
29
36
  let scheduledFunctionFound = false;
30
37
  let scheduleFound = false;
31
38
  const getAllBindings = createBindingsMethod(ast.body);
32
- const mainExports = getMainExport(ast.body, getAllBindings);
33
- const iscExports = mainExports
39
+ const { configExport, defaultExport, handlerExports } = getExports(ast.body, getAllBindings);
40
+ const isV2API = handlerExports.length === 0 && defaultExport !== undefined;
41
+ if (featureFlags.zisi_functions_api_v2 && isV2API) {
42
+ const config = {
43
+ runtimeAPIVersion: 2,
44
+ };
45
+ if (typeof configExport.schedule === 'string') {
46
+ config.schedule = configExport.schedule;
47
+ }
48
+ return config;
49
+ }
50
+ const iscExports = handlerExports
34
51
  .map(({ args, local: exportName }) => {
35
52
  const matchingImport = imports.find(({ local: importName }) => importName === exportName);
36
53
  if (matchingImport === undefined) {
@@ -12,34 +12,38 @@ import { createAliases as createPluginsModulesPathAliases, getPluginsModulesPath
12
12
  import { zipNodeJs } from './utils/zip.js';
13
13
  // A proxy for the `getSrcFiles` that calls `getSrcFiles` on the bundler
14
14
  const getSrcFilesWithBundler = async (parameters) => {
15
- const { config, extension, featureFlags, mainFile, srcDir } = parameters;
15
+ const { config, extension, featureFlags, mainFile, runtimeAPIVersion, srcDir } = parameters;
16
16
  const pluginsModulesPath = await getPluginsModulesPath(srcDir);
17
17
  const bundlerName = await getBundlerName({
18
18
  config,
19
19
  extension,
20
20
  featureFlags,
21
21
  mainFile,
22
+ runtimeAPIVersion,
22
23
  });
23
24
  const bundler = getBundler(bundlerName);
24
25
  const result = await bundler.getSrcFiles({ ...parameters, pluginsModulesPath });
25
26
  return result.srcFiles;
26
27
  };
27
28
  const zipFunction = async function ({ archiveFormat, basePath, cache, config = {}, destFolder, extension, featureFlags, filename, mainFile, name, repositoryRoot, runtime, srcDir, srcPath, stat, isInternal, }) {
29
+ // If the file is a zip, we assume the function is bundled and ready to go.
30
+ // We simply copy it to the destination path with no further processing.
31
+ if (extension === '.zip') {
32
+ const destPath = join(destFolder, filename);
33
+ await copyFile(srcPath, destPath);
34
+ return { config, path: destPath };
35
+ }
36
+ const inSourceConfig = await findISCDeclarationsInPath(mainFile, name, featureFlags);
37
+ const runtimeAPIVersion = inSourceConfig.runtimeAPIVersion === 2 ? 2 : 1;
28
38
  const pluginsModulesPath = await getPluginsModulesPath(srcDir);
29
39
  const bundlerName = await getBundlerName({
30
40
  config,
31
41
  extension,
32
42
  featureFlags,
33
43
  mainFile,
44
+ runtimeAPIVersion,
34
45
  });
35
46
  const bundler = getBundler(bundlerName);
36
- // If the file is a zip, we assume the function is bundled and ready to go.
37
- // We simply copy it to the destination path with no further processing.
38
- if (extension === '.zip') {
39
- const destPath = join(destFolder, filename);
40
- await copyFile(srcPath, destPath);
41
- return { config, path: destPath };
42
- }
43
47
  const { aliases = new Map(), cleanupFunction, basePath: finalBasePath, bundlerWarnings, includedFiles, inputs, mainFile: finalMainFile = mainFile, moduleFormat, nativeNodeModules, nodeModulesWithDynamicImports, rewrites, srcFiles, } = await bundler.bundle({
44
48
  basePath,
45
49
  cache,
@@ -52,11 +56,11 @@ const zipFunction = async function ({ archiveFormat, basePath, cache, config = {
52
56
  pluginsModulesPath,
53
57
  repositoryRoot,
54
58
  runtime,
59
+ runtimeAPIVersion,
55
60
  srcDir,
56
61
  srcPath,
57
62
  stat,
58
63
  });
59
- const inSourceConfig = await findISCDeclarationsInPath(mainFile, name);
60
64
  createPluginsModulesPathAliases(srcFiles, pluginsModulesPath, aliases, finalBasePath);
61
65
  const zipPath = await zipNodeJs({
62
66
  aliases,
@@ -70,6 +74,7 @@ const zipFunction = async function ({ archiveFormat, basePath, cache, config = {
70
74
  mainFile: finalMainFile,
71
75
  moduleFormat,
72
76
  rewrites,
77
+ runtimeAPIVersion,
73
78
  srcFiles,
74
79
  });
75
80
  await cleanupFunction?.();
@@ -77,7 +82,7 @@ const zipFunction = async function ({ archiveFormat, basePath, cache, config = {
77
82
  // `stream` helper.
78
83
  let { invocationMode } = inSourceConfig;
79
84
  // If we're using the V2 API, force the invocation to "stream".
80
- if (featureFlags.zisi_functions_api_v2) {
85
+ if (runtimeAPIVersion === 2) {
81
86
  invocationMode = INVOCATION_MODE.Stream;
82
87
  }
83
88
  return {
@@ -1,4 +1,8 @@
1
- import type { Statement } from '@babel/types';
1
+ import type { ExportDefaultDeclaration, Statement } from '@babel/types';
2
2
  import type { ISCExport } from '../in_source_config/index.js';
3
3
  import type { BindingMethod } from './bindings.js';
4
- export declare const getMainExport: (nodes: Statement[], getAllBindings: BindingMethod) => ISCExport[];
4
+ export declare const getExports: (nodes: Statement[], getAllBindings: BindingMethod) => {
5
+ configExport: Record<string, unknown>;
6
+ defaultExport: ExportDefaultDeclaration | undefined;
7
+ handlerExports: ISCExport[];
8
+ };
@@ -1,21 +1,33 @@
1
1
  import { isModuleExports } from './helpers.js';
2
- // Finds the main handler export in an AST.
3
- export const getMainExport = (nodes, getAllBindings) => {
4
- let handlerExport = [];
5
- nodes.find((node) => {
2
+ // Finds and returns the following types of exports in an AST:
3
+ // 1. Named `handler` function exports
4
+ // 2. Default function export
5
+ // 3. Named `config` object export
6
+ export const getExports = (nodes, getAllBindings) => {
7
+ const handlerExports = [];
8
+ let configExport = {};
9
+ let defaultExport;
10
+ nodes.forEach((node) => {
6
11
  const esmExports = getMainExportFromESM(node, getAllBindings);
7
12
  if (esmExports.length !== 0) {
8
- handlerExport = esmExports;
9
- return true;
13
+ handlerExports.push(...esmExports);
14
+ return;
10
15
  }
11
16
  const cjsExports = getMainExportFromCJS(node);
12
17
  if (cjsExports.length !== 0) {
13
- handlerExport = cjsExports;
14
- return true;
18
+ handlerExports.push(...cjsExports);
19
+ return;
20
+ }
21
+ if (isDefaultExport(node)) {
22
+ defaultExport = node;
23
+ return;
24
+ }
25
+ const config = parseConfigExport(node);
26
+ if (config !== undefined) {
27
+ configExport = config;
15
28
  }
16
- return false;
17
29
  });
18
- return handlerExport;
30
+ return { configExport, defaultExport, handlerExports };
19
31
  };
20
32
  // Finds the main handler export in a CJS AST.
21
33
  const getMainExportFromCJS = (node) => {
@@ -58,6 +70,50 @@ const isHandlerExport = (node) => {
58
70
  ((exported.type === 'Identifier' && exported.name === 'handler') ||
59
71
  (exported.type === 'StringLiteral' && exported.value === 'handler')));
60
72
  };
73
+ // Returns whether a given node is a default export declaration.
74
+ const isDefaultExport = (node) => node.type === 'ExportDefaultDeclaration';
75
+ // Finds a `config` named export that maps to an object variable declaration,
76
+ // like:
77
+ //
78
+ // export const config = { prop1: "value 1" }
79
+ const parseConfigExport = (node) => {
80
+ if (node.type === 'ExportNamedDeclaration' &&
81
+ node.declaration?.type === 'VariableDeclaration' &&
82
+ node.declaration.declarations[0].type === 'VariableDeclarator' &&
83
+ node.declaration.declarations[0].id.type === 'Identifier' &&
84
+ node.declaration.declarations[0].id.name === 'config' &&
85
+ node.declaration.declarations[0].init?.type === 'ObjectExpression') {
86
+ return parseObject(node.declaration.declarations[0].init);
87
+ }
88
+ };
89
+ // Takes an object expression node and returns the object resulting from the
90
+ // subtree. The following types are accepted as values, and any others will
91
+ // be ignored and excluded from the resulting object:
92
+ //
93
+ // - boolean
94
+ // - number
95
+ // - object
96
+ // - string
97
+ const parseObject = (node) => node.properties.reduce((acc, property) => {
98
+ if (property.type !== 'ObjectProperty' || property.key.type !== 'Identifier') {
99
+ return acc;
100
+ }
101
+ if (property.value.type === 'BooleanLiteral' ||
102
+ property.value.type === 'NumericLiteral' ||
103
+ property.value.type === 'StringLiteral') {
104
+ return {
105
+ ...acc,
106
+ [property.key.name]: property.value.value,
107
+ };
108
+ }
109
+ if (property.value.type === 'ObjectExpression') {
110
+ return {
111
+ ...acc,
112
+ [property.key.name]: parseObject(property.value),
113
+ };
114
+ }
115
+ return acc;
116
+ }, {});
61
117
  // Tries to resolve the export from a binding (variable)
62
118
  // for example `let handler; handler = () => {}; export { handler }` would
63
119
  // resolve correctly to the handler function
@@ -1,9 +1,12 @@
1
- export declare const parseExpression: ({ basePath, expression: rawExpression, resolveDir, }: {
1
+ import type { FeatureFlags } from '../../../feature_flags.js';
2
+ export declare const parseExpression: ({ basePath, expression: rawExpression, resolveDir, featureFlags, }: {
2
3
  basePath: string;
3
4
  expression: string;
4
5
  resolveDir: string;
6
+ featureFlags: FeatureFlags;
5
7
  }) => {
6
8
  includedPathsGlob: string | null | undefined;
7
9
  type: string;
8
10
  } | undefined;
9
- export declare const safelyParseFile: (path: string) => Promise<import("@babel/types").Program | null>;
11
+ export declare const safelyParseSource: (source: string, featureFlags: FeatureFlags) => import("@babel/types").Program | null;
12
+ export declare const safelyReadSource: (path: string) => Promise<string | null>;
@@ -1,6 +1,7 @@
1
1
  import { promises as fs } from 'fs';
2
2
  import { join, relative, resolve } from 'path';
3
- import { parse } from '@babel/parser';
3
+ import { parse as parseOld } from '@babel/parser';
4
+ import { parse as parseLatest } from '@babel/parser_latest';
4
5
  import { nonNullable } from '../../../utils/non_nullable.js';
5
6
  const GLOB_WILDCARD = '**';
6
7
  // Transforms an array of glob nodes into a glob string including an absolute
@@ -44,10 +45,12 @@ const getWildcardFromASTNode = (node) => {
44
45
  throw new Error('Expression member not supported');
45
46
  }
46
47
  };
48
+ const getParser = (featureFlags) => (featureFlags.zisi_use_latest_babel_version ? parseOld : parseLatest);
47
49
  // Tries to parse an expression, returning an object with:
48
50
  // - `includedPathsGlob`: A glob with the files to be included in the bundle
49
51
  // - `type`: The expression type (e.g. "require", "import")
50
- export const parseExpression = ({ basePath, expression: rawExpression, resolveDir, }) => {
52
+ export const parseExpression = ({ basePath, expression: rawExpression, resolveDir, featureFlags, }) => {
53
+ const parse = getParser(featureFlags);
51
54
  const { program } = parse(rawExpression, {
52
55
  sourceType: 'module',
53
56
  });
@@ -71,10 +74,10 @@ export const parseExpression = ({ basePath, expression: rawExpression, resolveDi
71
74
  }
72
75
  }
73
76
  };
74
- // Parses a JS/TS file and returns the resulting AST.
75
- const parseFile = async (path) => {
76
- const code = await fs.readFile(path, 'utf8');
77
- const ast = parse(code, {
77
+ // Parses a JS/TS source and returns the resulting AST.
78
+ const parseSource = (source, featureFlags) => {
79
+ const parse = getParser(featureFlags);
80
+ const ast = parse(source, {
78
81
  plugins: ['typescript'],
79
82
  sourceType: 'module',
80
83
  // disable tokens, ranges and comments for performance and we do not use them
@@ -84,14 +87,25 @@ const parseFile = async (path) => {
84
87
  });
85
88
  return ast.program;
86
89
  };
90
+ // Parses a JS/TS source and returns the resulting AST. If there is a parsing
91
+ // error, it will get swallowed and `null` will be returned.
92
+ export const safelyParseSource = (source, featureFlags) => {
93
+ try {
94
+ return parseSource(source, featureFlags);
95
+ }
96
+ catch {
97
+ return null;
98
+ }
99
+ };
87
100
  // Attempts to parse a JS/TS file at the given path, returning its AST if
88
101
  // successful, or `null` if not.
89
- export const safelyParseFile = async (path) => {
102
+ export const safelyReadSource = async (path) => {
90
103
  if (!path) {
91
104
  return null;
92
105
  }
93
106
  try {
94
- return await parseFile(path);
107
+ const source = await fs.readFile(path, 'utf8');
108
+ return source;
95
109
  }
96
110
  catch {
97
111
  return null;
@@ -6,23 +6,26 @@ export interface EntryFile {
6
6
  contents: string;
7
7
  filename: string;
8
8
  }
9
- export declare const isNamedLikeEntryFile: (file: string, { basePath, featureFlags, filename, }: {
9
+ export declare const isNamedLikeEntryFile: (file: string, { basePath, featureFlags, filename, runtimeAPIVersion, }: {
10
10
  basePath: string;
11
11
  featureFlags: FeatureFlags;
12
12
  filename: string;
13
+ runtimeAPIVersion: number;
13
14
  }) => boolean;
14
- export declare const conflictsWithEntryFile: (srcFiles: string[], { basePath, extension, featureFlags, filename, mainFile, }: {
15
+ export declare const conflictsWithEntryFile: (srcFiles: string[], { basePath, extension, featureFlags, filename, mainFile, runtimeAPIVersion, }: {
15
16
  basePath: string;
16
17
  extension: string;
17
18
  featureFlags: FeatureFlags;
18
19
  filename: string;
19
20
  mainFile: string;
21
+ runtimeAPIVersion: number;
20
22
  }) => boolean;
21
- export declare const getEntryFile: ({ commonPrefix, featureFlags, filename, mainFile, moduleFormat, userNamespace, }: {
23
+ export declare const getEntryFile: ({ commonPrefix, featureFlags, filename, mainFile, moduleFormat, userNamespace, runtimeAPIVersion, }: {
22
24
  commonPrefix: string;
23
25
  featureFlags: FeatureFlags;
24
26
  filename: string;
25
27
  mainFile: string;
26
28
  moduleFormat: ModuleFormat;
27
29
  userNamespace: string;
30
+ runtimeAPIVersion: number;
28
31
  }) => EntryFile;
@@ -5,9 +5,9 @@ import { getFileExtensionForFormat, MODULE_FILE_EXTENSION, MODULE_FORMAT, } from
5
5
  import { normalizeFilePath } from './normalize_path.js';
6
6
  export const ENTRY_FILE_NAME = '___netlify-entry-point';
7
7
  export const BOOTSTRAP_FILE_NAME = '___netlify-bootstrap.mjs';
8
- const getEntryFileContents = (mainPath, moduleFormat, featureFlags) => {
8
+ const getEntryFileContents = (mainPath, moduleFormat, featureFlags, runtimeAPIVersion) => {
9
9
  const importPath = `.${mainPath.startsWith('/') ? mainPath : `/${mainPath}`}`;
10
- if (featureFlags.zisi_functions_api_v2) {
10
+ if (runtimeAPIVersion === 2) {
11
11
  return [
12
12
  `import * as func from '${importPath}'`,
13
13
  `import { getLambdaHandler } from './${BOOTSTRAP_FILE_NAME}'`,
@@ -30,13 +30,13 @@ const POSSIBLE_LAMBDA_ENTRY_EXTENSIONS = [
30
30
  MODULE_FILE_EXTENSION.CJS,
31
31
  ];
32
32
  // checks if the file is considered a entry-file in AWS Lambda
33
- export const isNamedLikeEntryFile = (file, { basePath, featureFlags, filename, }) => POSSIBLE_LAMBDA_ENTRY_EXTENSIONS.some((extension) => {
34
- const entryFilename = getEntryFileName({ extension, featureFlags, filename });
33
+ export const isNamedLikeEntryFile = (file, { basePath, featureFlags, filename, runtimeAPIVersion, }) => POSSIBLE_LAMBDA_ENTRY_EXTENSIONS.some((extension) => {
34
+ const entryFilename = getEntryFileName({ extension, featureFlags, filename, runtimeAPIVersion });
35
35
  const entryFilePath = resolve(basePath, entryFilename);
36
36
  return entryFilePath === file;
37
37
  });
38
38
  // Check if any src file (except the mainFile) is considered an entry file for AWS Lambda
39
- export const conflictsWithEntryFile = (srcFiles, { basePath, extension, featureFlags, filename, mainFile, }) => {
39
+ export const conflictsWithEntryFile = (srcFiles, { basePath, extension, featureFlags, filename, mainFile, runtimeAPIVersion, }) => {
40
40
  let hasConflict = false;
41
41
  srcFiles.forEach((srcFile) => {
42
42
  if (srcFile.includes(ENTRY_FILE_NAME)) {
@@ -47,10 +47,12 @@ export const conflictsWithEntryFile = (srcFiles, { basePath, extension, featureF
47
47
  }
48
48
  // If we're generating a unique entry file, we know we don't have a conflict
49
49
  // at this point.
50
- if (featureFlags.zisi_unique_entry_file || featureFlags.zisi_functions_api_v2) {
50
+ if (featureFlags.zisi_unique_entry_file || runtimeAPIVersion === 2) {
51
51
  return;
52
52
  }
53
- if (!hasConflict && isNamedLikeEntryFile(srcFile, { basePath, featureFlags, filename }) && srcFile !== mainFile) {
53
+ if (!hasConflict &&
54
+ isNamedLikeEntryFile(srcFile, { basePath, featureFlags, filename, runtimeAPIVersion }) &&
55
+ srcFile !== mainFile) {
54
56
  hasConflict = true;
55
57
  }
56
58
  });
@@ -59,17 +61,17 @@ export const conflictsWithEntryFile = (srcFiles, { basePath, extension, featureF
59
61
  // Returns the name for the AWS Lambda entry file
60
62
  // We do set the handler in AWS Lambda to `<func-name>.handler` and because of
61
63
  // this it considers `<func-name>.(c|m)?js` as possible entry-points
62
- const getEntryFileName = ({ extension, featureFlags, filename, }) => {
63
- if (featureFlags.zisi_unique_entry_file || featureFlags.zisi_functions_api_v2) {
64
+ const getEntryFileName = ({ extension, featureFlags, filename, runtimeAPIVersion, }) => {
65
+ if (featureFlags.zisi_unique_entry_file || runtimeAPIVersion === 2) {
64
66
  return `${ENTRY_FILE_NAME}.mjs`;
65
67
  }
66
68
  return `${basename(filename, extname(filename))}${extension}`;
67
69
  };
68
- export const getEntryFile = ({ commonPrefix, featureFlags, filename, mainFile, moduleFormat, userNamespace, }) => {
70
+ export const getEntryFile = ({ commonPrefix, featureFlags, filename, mainFile, moduleFormat, userNamespace, runtimeAPIVersion, }) => {
69
71
  const mainPath = normalizeFilePath({ commonPrefix, path: mainFile, userNamespace });
70
72
  const extension = getFileExtensionForFormat(moduleFormat, featureFlags);
71
- const entryFilename = getEntryFileName({ extension, featureFlags, filename });
72
- const contents = getEntryFileContents(mainPath, moduleFormat, featureFlags);
73
+ const entryFilename = getEntryFileName({ extension, featureFlags, filename, runtimeAPIVersion });
74
+ const contents = getEntryFileContents(mainPath, moduleFormat, featureFlags, runtimeAPIVersion);
73
75
  return {
74
76
  contents,
75
77
  filename: entryFilename,
@@ -13,6 +13,7 @@ interface ZipNodeParameters {
13
13
  mainFile: string;
14
14
  moduleFormat: ModuleFormat;
15
15
  rewrites?: Map<string, string>;
16
+ runtimeAPIVersion: number;
16
17
  srcFiles: string[];
17
18
  }
18
19
  export declare const zipNodeJs: ({ archiveFormat, ...options }: ZipNodeParameters & {
@@ -14,7 +14,7 @@ const COPY_FILE_CONCURRENCY = os.cpus().length === 0 ? 2 : os.cpus().length * 2;
14
14
  // Sub-directory to place all user-defined files (i.e. everything other than
15
15
  // the entry file generated by zip-it-and-ship-it).
16
16
  const DEFAULT_USER_SUBDIRECTORY = 'src';
17
- const createDirectory = async function ({ aliases = new Map(), basePath, destFolder, extension, featureFlags, filename, mainFile, moduleFormat, rewrites = new Map(), srcFiles, }) {
17
+ const createDirectory = async function ({ aliases = new Map(), basePath, destFolder, extension, featureFlags, filename, mainFile, moduleFormat, rewrites = new Map(), runtimeAPIVersion, srcFiles, }) {
18
18
  const { contents: entryContents, filename: entryFilename } = getEntryFile({
19
19
  commonPrefix: basePath,
20
20
  featureFlags,
@@ -22,6 +22,7 @@ const createDirectory = async function ({ aliases = new Map(), basePath, destFol
22
22
  mainFile,
23
23
  moduleFormat,
24
24
  userNamespace: DEFAULT_USER_SUBDIRECTORY,
25
+ runtimeAPIVersion,
25
26
  });
26
27
  const functionFolder = join(destFolder, basename(filename, extension));
27
28
  // Deleting the functions directory in case it exists before creating it.
@@ -45,7 +46,7 @@ const createDirectory = async function ({ aliases = new Map(), basePath, destFol
45
46
  }, { concurrency: COPY_FILE_CONCURRENCY });
46
47
  return functionFolder;
47
48
  };
48
- const createZipArchive = async function ({ aliases = new Map(), basePath, cache, destFolder, extension, featureFlags, filename, mainFile, moduleFormat, rewrites, srcFiles, }) {
49
+ const createZipArchive = async function ({ aliases = new Map(), basePath, cache, destFolder, extension, featureFlags, filename, mainFile, moduleFormat, rewrites, runtimeAPIVersion, srcFiles, }) {
49
50
  const destPath = join(destFolder, `${basename(filename, extension)}.zip`);
50
51
  const { archive, output } = startZip(destPath);
51
52
  // There is a naming conflict with the entry file if one of the supporting
@@ -57,13 +58,14 @@ const createZipArchive = async function ({ aliases = new Map(), basePath, cache,
57
58
  featureFlags,
58
59
  filename,
59
60
  mainFile,
61
+ runtimeAPIVersion,
60
62
  });
61
63
  // We don't need an entry file if it would end up with the same path as the
62
64
  // function's main file. Unless we have a file conflict and need to move everything into a subfolder
63
65
  const needsEntryFile = featureFlags.zisi_unique_entry_file ||
64
- featureFlags.zisi_functions_api_v2 ||
66
+ runtimeAPIVersion === 2 ||
65
67
  hasEntryFileConflict ||
66
- !isNamedLikeEntryFile(mainFile, { basePath, featureFlags, filename });
68
+ !isNamedLikeEntryFile(mainFile, { basePath, featureFlags, filename, runtimeAPIVersion });
67
69
  // If there is a naming conflict, we move all user files (everything other
68
70
  // than the entry file) to its own sub-directory.
69
71
  const userNamespace = hasEntryFileConflict ? DEFAULT_USER_SUBDIRECTORY : '';
@@ -75,10 +77,11 @@ const createZipArchive = async function ({ aliases = new Map(), basePath, cache,
75
77
  moduleFormat,
76
78
  userNamespace,
77
79
  featureFlags,
80
+ runtimeAPIVersion,
78
81
  });
79
82
  addEntryFileToZip(archive, entryFile);
80
83
  }
81
- if (featureFlags.zisi_functions_api_v2) {
84
+ if (runtimeAPIVersion === 2) {
82
85
  // This is the path to the file that contains all the code for the v2
83
86
  // functions API. We add it to the list of source files and create an
84
87
  // alias so that it's written as `BOOTSTRAP_FILE_NAME` in the ZIP.
@@ -27,6 +27,7 @@ export type GetSrcFilesFunction = (args: {
27
27
  config: FunctionConfig;
28
28
  featureFlags: FeatureFlags;
29
29
  repositoryRoot?: string;
30
+ runtimeAPIVersion: number;
30
31
  } & FunctionSource) => Promise<string[]>;
31
32
  export interface ZipFunctionResult {
32
33
  bundler?: NodeBundlerName;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netlify/zip-it-and-ship-it",
3
- "version": "9.5.0",
3
+ "version": "9.6.0",
4
4
  "description": "Zip it and ship it",
5
5
  "main": "./dist/main.js",
6
6
  "type": "module",
@@ -54,6 +54,7 @@
54
54
  "url": "https://github.com/netlify/zip-it-and-ship-it/issues"
55
55
  },
56
56
  "dependencies": {
57
+ "@babel/parser_latest": "npm:@babel/parser@7.21.8",
57
58
  "@babel/parser": "7.16.8",
58
59
  "@netlify/binary-info": "^1.0.0",
59
60
  "@netlify/esbuild": "0.14.39",
@@ -88,6 +89,7 @@
88
89
  "devDependencies": {
89
90
  "@babel/types": "^7.15.6",
90
91
  "@netlify/eslint-config-node": "^7.0.1",
92
+ "@skn0tt/lambda-local": "^2.0.3",
91
93
  "@types/archiver": "^5.1.1",
92
94
  "@types/glob": "^8.1.0",
93
95
  "@types/is-ci": "^3.0.0",
@@ -104,7 +106,6 @@
104
106
  "get-stream": "^6.0.0",
105
107
  "husky": "^8.0.0",
106
108
  "is-ci": "^3.0.1",
107
- "lambda-local": "^2.0.3",
108
109
  "npm-run-all": "^4.1.5",
109
110
  "source-map-support": "^0.5.21",
110
111
  "typescript": "^5.0.0",