@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.
- package/dist/feature_flags.d.ts +2 -0
- package/dist/feature_flags.js +2 -0
- package/dist/main.d.ts +2 -2
- package/dist/main.js +14 -6
- package/dist/runtimes/index.d.ts +2 -2
- package/dist/runtimes/node/bundlers/esbuild/bundler.js +1 -0
- package/dist/runtimes/node/bundlers/esbuild/plugin_dynamic_imports.d.ts +3 -1
- package/dist/runtimes/node/bundlers/esbuild/plugin_dynamic_imports.js +2 -2
- package/dist/runtimes/node/bundlers/index.d.ts +2 -1
- package/dist/runtimes/node/bundlers/index.js +4 -5
- package/dist/runtimes/node/bundlers/nft/es_modules.d.ts +2 -1
- package/dist/runtimes/node/bundlers/nft/es_modules.js +5 -8
- package/dist/runtimes/node/bundlers/nft/index.js +4 -2
- package/dist/runtimes/node/bundlers/types.d.ts +1 -0
- package/dist/runtimes/node/in_source_config/index.d.ts +4 -1
- package/dist/runtimes/node/in_source_config/index.js +23 -6
- package/dist/runtimes/node/index.js +15 -10
- package/dist/runtimes/node/parser/exports.d.ts +6 -2
- package/dist/runtimes/node/parser/exports.js +66 -10
- package/dist/runtimes/node/parser/index.d.ts +5 -2
- package/dist/runtimes/node/parser/index.js +22 -8
- package/dist/runtimes/node/utils/entry_file.d.ts +6 -3
- package/dist/runtimes/node/utils/entry_file.js +14 -12
- package/dist/runtimes/node/utils/zip.d.ts +1 -0
- package/dist/runtimes/node/utils/zip.js +8 -5
- package/dist/runtimes/runtime.d.ts +1 -0
- package/package.json +3 -2
package/dist/feature_flags.d.ts
CHANGED
|
@@ -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;
|
package/dist/feature_flags.js
CHANGED
|
@@ -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
|
|
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
|
|
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({
|
|
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 }) {
|
package/dist/runtimes/index.d.ts
CHANGED
|
@@ -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
|
-
|
|
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 (
|
|
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 ||
|
|
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 (
|
|
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 {
|
|
6
|
+
import { getExports } from '../parser/exports.js';
|
|
7
7
|
import { getImports } from '../parser/imports.js';
|
|
8
|
-
import {
|
|
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
|
|
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
|
|
33
|
-
const
|
|
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 (
|
|
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
|
|
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
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
9
|
-
return
|
|
13
|
+
handlerExports.push(...esmExports);
|
|
14
|
+
return;
|
|
10
15
|
}
|
|
11
16
|
const cjsExports = getMainExportFromCJS(node);
|
|
12
17
|
if (cjsExports.length !== 0) {
|
|
13
|
-
|
|
14
|
-
return
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
const ast = parse(
|
|
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
|
|
102
|
+
export const safelyReadSource = async (path) => {
|
|
90
103
|
if (!path) {
|
|
91
104
|
return null;
|
|
92
105
|
}
|
|
93
106
|
try {
|
|
94
|
-
|
|
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 (
|
|
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 ||
|
|
50
|
+
if (featureFlags.zisi_unique_entry_file || runtimeAPIVersion === 2) {
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
|
-
if (!hasConflict &&
|
|
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 ||
|
|
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
|
-
|
|
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 (
|
|
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.
|
|
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",
|