@netlify/zip-it-and-ship-it 8.2.0 → 8.3.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.js +2 -6
- package/dist/runtimes/node/bundlers/esbuild/bundler.d.ts +2 -2
- package/dist/runtimes/node/bundlers/esbuild/bundler.js +6 -8
- package/dist/runtimes/node/bundlers/esbuild/bundler_target.d.ts +1 -1
- package/dist/runtimes/node/bundlers/esbuild/index.js +1 -1
- package/dist/runtimes/node/bundlers/nft/index.js +2 -2
- package/dist/runtimes/node/utils/entry_file.d.ts +18 -2
- package/dist/runtimes/node/utils/entry_file.js +27 -2
- package/dist/runtimes/node/utils/module_format.js +3 -0
- package/dist/runtimes/node/utils/zip.js +22 -16
- package/package.json +3 -3
package/dist/feature_flags.js
CHANGED
|
@@ -14,12 +14,8 @@ export const defaultFlags = {
|
|
|
14
14
|
zisi_pure_esm_mjs: false,
|
|
15
15
|
// Load configuration from per-function JSON files.
|
|
16
16
|
project_deploy_configuration_api_use_per_function_configuration_files: false,
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
// Raise file IO limit for NFT
|
|
20
|
-
zisi_nft_higher_fileio_limit: false,
|
|
21
|
-
// Provide banner to esbuild which allows requires in ESM output
|
|
22
|
-
zisi_esbuild_require_banner: false,
|
|
17
|
+
// Output CJS file extension
|
|
18
|
+
zisi_output_cjs_extension: false,
|
|
23
19
|
};
|
|
24
20
|
// List of supported flags and their default value.
|
|
25
21
|
export const getFlags = (input = {}, flags = defaultFlags) => Object.entries(flags).reduce((result, [key, defaultValue]) => ({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { FunctionConfig } from '../../../../config.js';
|
|
2
2
|
import { FeatureFlags } from '../../../../feature_flags.js';
|
|
3
|
-
import {
|
|
3
|
+
import { ModuleFormat } from '../../utils/module_format.js';
|
|
4
4
|
export declare const ESBUILD_LOG_LIMIT = 10;
|
|
5
5
|
export declare const bundleJsFile: ({ additionalModulePaths, basePath, config, externalModules, featureFlags, ignoredModules, mainFile, name, srcDir, srcFile, }: {
|
|
6
6
|
additionalModulePaths?: string[] | undefined;
|
|
@@ -17,10 +17,10 @@ export declare const bundleJsFile: ({ additionalModulePaths, basePath, config, e
|
|
|
17
17
|
additionalPaths: string[];
|
|
18
18
|
bundlePaths: Map<string, string>;
|
|
19
19
|
cleanTempFiles: () => Promise<void>;
|
|
20
|
-
extension: ModuleFileExtension;
|
|
21
20
|
inputs: string[];
|
|
22
21
|
moduleFormat: ModuleFormat;
|
|
23
22
|
nativeNodeModules: {};
|
|
24
23
|
nodeModulesWithDynamicImports: string[];
|
|
24
|
+
outputExtension: import("../../utils/module_format.js").ModuleFileExtension;
|
|
25
25
|
warnings: import("@netlify/esbuild").Message[];
|
|
26
26
|
}>;
|
|
@@ -56,9 +56,7 @@ export const bundleJsFile = async function ({ additionalModulePaths, basePath, c
|
|
|
56
56
|
// to a `package.json` with {"type": "module"} in case of an ESM function.
|
|
57
57
|
const { includedFiles: includedFilesFromModuleDetection, moduleFormat } = await getModuleFormat(srcDir, featureFlags, extname(mainFile), config.nodeVersion);
|
|
58
58
|
// The extension of the output file.
|
|
59
|
-
const
|
|
60
|
-
// When outputting an ESM file, configure esbuild to produce a `.mjs` file.
|
|
61
|
-
const outExtension = moduleFormat === "esm" /* ModuleFormat.ESM */ ? { [".js" /* ModuleFileExtension.JS */]: ".mjs" /* ModuleFileExtension.MJS */ } : undefined;
|
|
59
|
+
const outputExtension = getFileExtensionForFormat(moduleFormat, featureFlags);
|
|
62
60
|
// We add this banner so that calls to require() still work in ESM modules, especially when importing node built-ins
|
|
63
61
|
// We have to do this until this is fixed in esbuild: https://github.com/evanw/esbuild/pull/2067
|
|
64
62
|
const esmJSBanner = `
|
|
@@ -71,7 +69,7 @@ export const bundleJsFile = async function ({ additionalModulePaths, basePath, c
|
|
|
71
69
|
`;
|
|
72
70
|
try {
|
|
73
71
|
const { metafile = { inputs: {}, outputs: {} }, warnings } = await build({
|
|
74
|
-
banner: moduleFormat === "esm" /* ModuleFormat.ESM */
|
|
72
|
+
banner: moduleFormat === "esm" /* ModuleFormat.ESM */ ? { js: esmJSBanner } : undefined,
|
|
75
73
|
bundle: true,
|
|
76
74
|
entryPoints: [srcFile],
|
|
77
75
|
external,
|
|
@@ -80,8 +78,8 @@ export const bundleJsFile = async function ({ additionalModulePaths, basePath, c
|
|
|
80
78
|
logLimit: ESBUILD_LOG_LIMIT,
|
|
81
79
|
metafile: true,
|
|
82
80
|
nodePaths: additionalModulePaths,
|
|
83
|
-
outExtension,
|
|
84
81
|
outdir: targetDirectory,
|
|
82
|
+
outExtension: { '.js': outputExtension },
|
|
85
83
|
platform: 'node',
|
|
86
84
|
plugins,
|
|
87
85
|
resolveExtensions: RESOLVE_EXTENSIONS,
|
|
@@ -91,9 +89,9 @@ export const bundleJsFile = async function ({ additionalModulePaths, basePath, c
|
|
|
91
89
|
});
|
|
92
90
|
const bundlePaths = getBundlePaths({
|
|
93
91
|
destFolder: targetDirectory,
|
|
94
|
-
extension,
|
|
95
92
|
outputs: metafile.outputs,
|
|
96
93
|
srcFile,
|
|
94
|
+
outputExtension,
|
|
97
95
|
});
|
|
98
96
|
const inputs = Object.keys(metafile.inputs).map((path) => resolve(path));
|
|
99
97
|
const cleanTempFiles = getCleanupFunction([...bundlePaths.keys()]);
|
|
@@ -102,11 +100,11 @@ export const bundleJsFile = async function ({ additionalModulePaths, basePath, c
|
|
|
102
100
|
additionalPaths,
|
|
103
101
|
bundlePaths,
|
|
104
102
|
cleanTempFiles,
|
|
105
|
-
extension,
|
|
106
103
|
inputs,
|
|
107
104
|
moduleFormat,
|
|
108
105
|
nativeNodeModules,
|
|
109
106
|
nodeModulesWithDynamicImports: [...nodeModulesWithDynamicImports],
|
|
107
|
+
outputExtension,
|
|
110
108
|
warnings,
|
|
111
109
|
};
|
|
112
110
|
}
|
|
@@ -122,7 +120,7 @@ export const bundleJsFile = async function ({ additionalModulePaths, basePath, c
|
|
|
122
120
|
// absolute paths of the generated files as keys, and the paths that those
|
|
123
121
|
// files should take in the generated bundle as values. This is compatible
|
|
124
122
|
// with the `aliases` format used upstream.
|
|
125
|
-
const getBundlePaths = ({ destFolder,
|
|
123
|
+
const getBundlePaths = ({ destFolder, outputExtension, outputs, srcFile, }) => {
|
|
126
124
|
const bundleFilename = basename(srcFile, extname(srcFile)) + outputExtension;
|
|
127
125
|
const mainFileDirectory = dirname(srcFile);
|
|
128
126
|
const bundlePaths = new Map();
|
|
@@ -9,7 +9,7 @@ declare const versionMap: {
|
|
|
9
9
|
readonly '16.x': "node16";
|
|
10
10
|
readonly '18.x': "node18";
|
|
11
11
|
};
|
|
12
|
-
type VersionValues = typeof versionMap[keyof typeof versionMap];
|
|
12
|
+
type VersionValues = (typeof versionMap)[keyof typeof versionMap];
|
|
13
13
|
declare const getBundlerTarget: (suppliedVersion?: NodeVersionString) => VersionValues;
|
|
14
14
|
declare const getModuleFormat: (srcDir: string, featureFlags: FeatureFlags, extension: string, configVersion?: string) => Promise<{
|
|
15
15
|
includedFiles: string[];
|
|
@@ -28,7 +28,7 @@ const getExternalAndIgnoredModules = async ({ config, srcDir }) => {
|
|
|
28
28
|
};
|
|
29
29
|
const bundle = async ({ basePath, config = {}, extension, featureFlags, filename, mainFile, name, pluginsModulesPath, repositoryRoot, runtime, srcDir, srcPath, stat, }) => {
|
|
30
30
|
const { externalModules, ignoredModules } = await getExternalAndIgnoredModules({ config, srcDir });
|
|
31
|
-
const { additionalPaths, bundlePaths, cleanTempFiles,
|
|
31
|
+
const { additionalPaths, bundlePaths, cleanTempFiles, inputs, moduleFormat, nativeNodeModules = {}, nodeModulesWithDynamicImports, outputExtension, warnings, } = await bundleJsFile({
|
|
32
32
|
additionalModulePaths: pluginsModulesPath ? [pluginsModulesPath] : [],
|
|
33
33
|
basePath,
|
|
34
34
|
config,
|
|
@@ -43,9 +43,9 @@ const ignoreFunction = (path) => {
|
|
|
43
43
|
const traceFilesAndTranspile = async function ({ basePath, cache, config, featureFlags, mainFile, pluginsModulesPath, name, }) {
|
|
44
44
|
const { fileList: dependencyPaths, esmFileList, reasons, } = await nodeFileTrace([mainFile], {
|
|
45
45
|
// Default is 1024. Allowing double the fileIO in parallel makes nft faster, but uses a little more memory.
|
|
46
|
-
fileIOConcurrency:
|
|
46
|
+
fileIOConcurrency: 2048,
|
|
47
47
|
base: basePath,
|
|
48
|
-
cache:
|
|
48
|
+
cache: cache.nftCache,
|
|
49
49
|
ignore: ignoreFunction,
|
|
50
50
|
readFile: async (path) => {
|
|
51
51
|
try {
|
|
@@ -1,7 +1,23 @@
|
|
|
1
|
+
import type { FeatureFlags } from '../../../feature_flags.js';
|
|
1
2
|
import { ModuleFormat } from './module_format.js';
|
|
2
|
-
export
|
|
3
|
+
export interface EntryFile {
|
|
4
|
+
contents: string;
|
|
5
|
+
filename: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const isNamedLikeEntryFile: (file: string, { basePath, filename, }: {
|
|
8
|
+
basePath: string;
|
|
9
|
+
filename: string;
|
|
10
|
+
}) => boolean;
|
|
11
|
+
export declare const conflictsWithEntryFile: (srcFiles: string[], { basePath, mainFile, filename, }: {
|
|
12
|
+
basePath: string;
|
|
13
|
+
filename: string;
|
|
14
|
+
mainFile: string;
|
|
15
|
+
}) => boolean;
|
|
16
|
+
export declare const getEntryFile: ({ commonPrefix, featureFlags, filename, mainFile, moduleFormat, userNamespace, }: {
|
|
3
17
|
commonPrefix: string;
|
|
18
|
+
featureFlags: FeatureFlags;
|
|
19
|
+
filename: string;
|
|
4
20
|
mainFile: string;
|
|
5
21
|
moduleFormat: ModuleFormat;
|
|
6
22
|
userNamespace: string;
|
|
7
|
-
}) =>
|
|
23
|
+
}) => EntryFile;
|
|
@@ -1,10 +1,35 @@
|
|
|
1
|
+
import { basename, extname, resolve } from 'path';
|
|
2
|
+
import { getFileExtensionForFormat } from './module_format.js';
|
|
1
3
|
import { normalizeFilePath } from './normalize_path.js';
|
|
2
|
-
|
|
3
|
-
const mainPath = normalizeFilePath({ commonPrefix, path: mainFile, userNamespace });
|
|
4
|
+
const getEntryFileContents = (mainPath, moduleFormat) => {
|
|
4
5
|
const importPath = `.${mainPath.startsWith('/') ? mainPath : `/${mainPath}`}`;
|
|
5
6
|
if (moduleFormat === "cjs" /* ModuleFormat.COMMONJS */) {
|
|
6
7
|
return `module.exports = require('${importPath}')`;
|
|
7
8
|
}
|
|
8
9
|
return `export { handler } from '${importPath}'`;
|
|
9
10
|
};
|
|
11
|
+
// They are in the order that AWS Lambda will try to find the entry point
|
|
12
|
+
const POSSIBLE_LAMBDA_ENTRY_EXTENSIONS = [".js" /* ModuleFileExtension.JS */, ".mjs" /* ModuleFileExtension.MJS */, ".cjs" /* ModuleFileExtension.CJS */];
|
|
13
|
+
// checks if the file is considered a entry-file in AWS Lambda
|
|
14
|
+
export const isNamedLikeEntryFile = (file, { basePath, filename, }) => POSSIBLE_LAMBDA_ENTRY_EXTENSIONS.some((extension) => {
|
|
15
|
+
const entryFilename = getEntryFileName({ extension, filename });
|
|
16
|
+
const entryFilePath = resolve(basePath, entryFilename);
|
|
17
|
+
return entryFilePath === file;
|
|
18
|
+
});
|
|
19
|
+
// Check if any src file (except the mainFile) is considered an entry file for AWS Lambda
|
|
20
|
+
export const conflictsWithEntryFile = (srcFiles, { basePath, mainFile, filename, }) => srcFiles.some((srcFile) => isNamedLikeEntryFile(srcFile, { basePath, filename }) && srcFile !== mainFile);
|
|
21
|
+
// Returns the name for the AWS Lambda entry file
|
|
22
|
+
// We do set the handler in AWS Lambda to `<func-name>.handler` and because of
|
|
23
|
+
// this it considers `<func-name>.(c|m)?js` as possible entry-points
|
|
24
|
+
const getEntryFileName = ({ extension, filename }) => `${basename(filename, extname(filename))}${extension}`;
|
|
25
|
+
export const getEntryFile = ({ commonPrefix, featureFlags, filename, mainFile, moduleFormat, userNamespace, }) => {
|
|
26
|
+
const mainPath = normalizeFilePath({ commonPrefix, path: mainFile, userNamespace });
|
|
27
|
+
const extension = getFileExtensionForFormat(moduleFormat, featureFlags);
|
|
28
|
+
const entryFilename = getEntryFileName({ extension, filename });
|
|
29
|
+
const contents = getEntryFileContents(mainPath, moduleFormat);
|
|
30
|
+
return {
|
|
31
|
+
contents,
|
|
32
|
+
filename: entryFilename,
|
|
33
|
+
};
|
|
34
|
+
};
|
|
10
35
|
//# sourceMappingURL=entry_file.js.map
|
|
@@ -2,6 +2,9 @@ export const getFileExtensionForFormat = (moduleFormat, featureFlags) => {
|
|
|
2
2
|
if (moduleFormat === "esm" /* ModuleFormat.ESM */ && featureFlags.zisi_pure_esm_mjs) {
|
|
3
3
|
return ".mjs" /* ModuleFileExtension.MJS */;
|
|
4
4
|
}
|
|
5
|
+
if (featureFlags.zisi_output_cjs_extension && moduleFormat === "cjs" /* ModuleFormat.COMMONJS */) {
|
|
6
|
+
return ".cjs" /* ModuleFileExtension.CJS */;
|
|
7
|
+
}
|
|
5
8
|
return ".js" /* ModuleFileExtension.JS */;
|
|
6
9
|
};
|
|
7
10
|
//# sourceMappingURL=module_format.js.map
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { Buffer } from 'buffer';
|
|
2
2
|
import { promises as fs } from 'fs';
|
|
3
3
|
import os from 'os';
|
|
4
|
-
import { basename, join
|
|
4
|
+
import { basename, join } from 'path';
|
|
5
5
|
import { copyFile } from 'cp-file';
|
|
6
6
|
import { deleteAsync as deleteFiles } from 'del';
|
|
7
7
|
import pMap from 'p-map';
|
|
8
8
|
import { startZip, addZipFile, addZipContent, endZip } from '../../../archive.js';
|
|
9
9
|
import { cachedLstat, mkdirAndWriteFile } from '../../../utils/fs.js';
|
|
10
|
-
import { getEntryFile } from './entry_file.js';
|
|
11
|
-
import { getFileExtensionForFormat } from './module_format.js';
|
|
10
|
+
import { conflictsWithEntryFile, getEntryFile, isNamedLikeEntryFile } from './entry_file.js';
|
|
12
11
|
import { normalizeFilePath } from './normalize_path.js';
|
|
13
12
|
// Taken from https://www.npmjs.com/package/cpy.
|
|
14
13
|
const COPY_FILE_CONCURRENCY = os.cpus().length === 0 ? 2 : os.cpus().length * 2;
|
|
@@ -16,21 +15,20 @@ const COPY_FILE_CONCURRENCY = os.cpus().length === 0 ? 2 : os.cpus().length * 2;
|
|
|
16
15
|
// the entry file generated by zip-it-and-ship-it).
|
|
17
16
|
const DEFAULT_USER_SUBDIRECTORY = 'src';
|
|
18
17
|
const createDirectory = async function ({ aliases = new Map(), basePath, destFolder, extension, featureFlags, filename, mainFile, moduleFormat, rewrites = new Map(), srcFiles, }) {
|
|
19
|
-
const
|
|
18
|
+
const { contents: entryContents, filename: entryFilename } = getEntryFile({
|
|
20
19
|
commonPrefix: basePath,
|
|
20
|
+
featureFlags,
|
|
21
|
+
filename,
|
|
21
22
|
mainFile,
|
|
22
23
|
moduleFormat,
|
|
23
24
|
userNamespace: DEFAULT_USER_SUBDIRECTORY,
|
|
24
25
|
});
|
|
25
|
-
const entryFileExtension = getFileExtensionForFormat(moduleFormat, featureFlags);
|
|
26
|
-
const entryFilename = basename(filename, extension) + entryFileExtension;
|
|
27
26
|
const functionFolder = join(destFolder, basename(filename, extension));
|
|
28
|
-
const entryFilePath = resolve(functionFolder, entryFilename);
|
|
29
27
|
// Deleting the functions directory in case it exists before creating it.
|
|
30
28
|
await deleteFiles(functionFolder, { force: true });
|
|
31
29
|
await fs.mkdir(functionFolder, { recursive: true });
|
|
32
30
|
// Writing entry file.
|
|
33
|
-
await fs.writeFile(
|
|
31
|
+
await fs.writeFile(join(functionFolder, entryFilename), entryContents);
|
|
34
32
|
// Copying source files.
|
|
35
33
|
await pMap(srcFiles, (srcFile) => {
|
|
36
34
|
const destPath = aliases.get(srcFile) || srcFile;
|
|
@@ -50,22 +48,30 @@ const createDirectory = async function ({ aliases = new Map(), basePath, destFol
|
|
|
50
48
|
const createZipArchive = async function ({ aliases, basePath, cache, destFolder, extension, featureFlags, filename, mainFile, moduleFormat, rewrites, srcFiles, }) {
|
|
51
49
|
const destPath = join(destFolder, `${basename(filename, extension)}.zip`);
|
|
52
50
|
const { archive, output } = startZip(destPath);
|
|
53
|
-
const entryFileExtension = getFileExtensionForFormat(moduleFormat, featureFlags);
|
|
54
|
-
const entryFilename = basename(filename, extension) + entryFileExtension;
|
|
55
|
-
const entryFilePath = resolve(basePath, entryFilename);
|
|
56
51
|
// We don't need an entry file if it would end up with the same path as the
|
|
57
52
|
// function's main file.
|
|
58
|
-
const needsEntryFile =
|
|
53
|
+
const needsEntryFile = !isNamedLikeEntryFile(mainFile, { basePath, filename });
|
|
59
54
|
// There is a naming conflict with the entry file if one of the supporting
|
|
60
55
|
// files (i.e. not the main file) has the path that the entry file needs to
|
|
61
56
|
// take.
|
|
62
|
-
const hasEntryFileConflict = srcFiles
|
|
57
|
+
const hasEntryFileConflict = conflictsWithEntryFile(srcFiles, {
|
|
58
|
+
basePath,
|
|
59
|
+
filename,
|
|
60
|
+
mainFile,
|
|
61
|
+
});
|
|
63
62
|
// If there is a naming conflict, we move all user files (everything other
|
|
64
63
|
// than the entry file) to its own sub-directory.
|
|
65
64
|
const userNamespace = hasEntryFileConflict ? DEFAULT_USER_SUBDIRECTORY : '';
|
|
66
65
|
if (needsEntryFile) {
|
|
67
|
-
const entryFile = getEntryFile({
|
|
68
|
-
|
|
66
|
+
const entryFile = getEntryFile({
|
|
67
|
+
commonPrefix: basePath,
|
|
68
|
+
filename,
|
|
69
|
+
mainFile,
|
|
70
|
+
moduleFormat,
|
|
71
|
+
userNamespace,
|
|
72
|
+
featureFlags,
|
|
73
|
+
});
|
|
74
|
+
addEntryFileToZip(archive, entryFile);
|
|
69
75
|
}
|
|
70
76
|
const srcFilesInfos = await Promise.all(srcFiles.map((file) => addStat(cache, file)));
|
|
71
77
|
// We ensure this is not async, so that the archive's checksum is
|
|
@@ -90,7 +96,7 @@ export const zipNodeJs = function ({ archiveFormat, ...options }) {
|
|
|
90
96
|
}
|
|
91
97
|
return createDirectory(options);
|
|
92
98
|
};
|
|
93
|
-
const addEntryFileToZip = function (archive, contents, filename) {
|
|
99
|
+
const addEntryFileToZip = function (archive, { contents, filename }) {
|
|
94
100
|
const contentBuffer = Buffer.from(contents);
|
|
95
101
|
addZipContent(archive, contentBuffer, filename);
|
|
96
102
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/zip-it-and-ship-it",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.3.0",
|
|
4
4
|
"description": "Zip it and ship it",
|
|
5
5
|
"main": "./dist/main.js",
|
|
6
6
|
"type": "module",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"@types/tmp": "^0.2.3",
|
|
98
98
|
"@types/unixify": "^1.0.0",
|
|
99
99
|
"@types/yargs": "^17.0.4",
|
|
100
|
-
"@vitest/coverage-c8": "^0.
|
|
100
|
+
"@vitest/coverage-c8": "^0.27.0",
|
|
101
101
|
"cpy": "^9.0.0",
|
|
102
102
|
"deepmerge": "^4.2.2",
|
|
103
103
|
"get-stream": "^6.0.0",
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
"throat": "^6.0.1",
|
|
109
109
|
"typescript": "^4.8.4",
|
|
110
110
|
"vite": "^4.0.0",
|
|
111
|
-
"vitest": "^0.
|
|
111
|
+
"vitest": "^0.27.0"
|
|
112
112
|
},
|
|
113
113
|
"engines": {
|
|
114
114
|
"node": "^14.16.0 || >=16.0.0"
|