@netlify/zip-it-and-ship-it 8.2.0 → 8.4.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/README.md +22 -3
- package/dist/config.d.ts +1 -0
- package/dist/feature_flags.js +2 -6
- package/dist/manifest.d.ts +3 -0
- package/dist/manifest.js +4 -1
- package/dist/runtimes/go/index.js +7 -2
- 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/index.js +3 -1
- 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 +24 -18
- package/dist/runtimes/runtime.d.ts +3 -0
- package/dist/runtimes/rust/index.js +7 -2
- package/dist/zip.d.ts +4 -2
- package/dist/zip.js +7 -2
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -150,6 +150,10 @@ The following properties are accepted:
|
|
|
150
150
|
The `[name]` placeholder will be replaced by the name of the function, allowing you to use it to construct the path to
|
|
151
151
|
the target directory.
|
|
152
152
|
|
|
153
|
+
- `name`
|
|
154
|
+
|
|
155
|
+
A name to use when displaying the function in the Netlify UI. Populates the `displayName` property in the functions manifest for the specified function.
|
|
156
|
+
|
|
153
157
|
#### `featureFlags`
|
|
154
158
|
|
|
155
159
|
See [feature flags](#feature-flags).
|
|
@@ -159,7 +163,7 @@ See [feature flags](#feature-flags).
|
|
|
159
163
|
- _Type_: `string`
|
|
160
164
|
- _Default value_: `undefined`
|
|
161
165
|
|
|
162
|
-
Defines the path for
|
|
166
|
+
Defines the full path, including the file name, to use for the manifest file that will be created with the functions bundling results. For example, `path/to/manifest.json`. This file is a
|
|
163
167
|
JSON-formatted string with the following properties:
|
|
164
168
|
|
|
165
169
|
- `functions`: An array with the functions created, in the same format as returned by `zipFunctions`
|
|
@@ -172,11 +176,18 @@ JSON-formatted string with the following properties:
|
|
|
172
176
|
|
|
173
177
|
#### `parallelLimit`
|
|
174
178
|
|
|
175
|
-
- _Type_: `number
|
|
179
|
+
- _Type_: `number`
|
|
176
180
|
- _Default value_: `5`
|
|
177
181
|
|
|
178
182
|
Maximum number of functions to bundle at the same time.
|
|
179
183
|
|
|
184
|
+
#### `internalSrcFolder`
|
|
185
|
+
|
|
186
|
+
- _Type_: `string`
|
|
187
|
+
- _Default value_: `undefined`
|
|
188
|
+
|
|
189
|
+
Defines the path to the folder with internal functions. Used to populate a function's `isInternal` property, if its path is within this specified internal functions folder.
|
|
190
|
+
|
|
180
191
|
### Return value
|
|
181
192
|
|
|
182
193
|
This returns a `Promise` resolving to an array of objects describing each archive. Every object has the following
|
|
@@ -202,6 +213,14 @@ properties.
|
|
|
202
213
|
|
|
203
214
|
The size of the generated archive, in bytes.
|
|
204
215
|
|
|
216
|
+
- `isInternal` `boolean`
|
|
217
|
+
|
|
218
|
+
If the function path has a match with the `internalSrcFolder` property, this boolean will be true.
|
|
219
|
+
|
|
220
|
+
- `displayName` `string`
|
|
221
|
+
|
|
222
|
+
If there was a user-defined configuration object applied to the function, and it had a `name` defined. This will be returned here.
|
|
223
|
+
|
|
205
224
|
Additionally, the following properties also exist for Node.js functions:
|
|
206
225
|
|
|
207
226
|
- `bundler`: `string`
|
|
@@ -257,7 +276,7 @@ Additionally, the following properties also exist for Node.js functions:
|
|
|
257
276
|
```js
|
|
258
277
|
import { zipFunction } from '@netlify/zip-it-and-ship-it'
|
|
259
278
|
|
|
260
|
-
const archive = await
|
|
279
|
+
const archive = await zipFunction('functions/function.js', 'functions-dist')
|
|
261
280
|
```
|
|
262
281
|
|
|
263
282
|
This is like [`zipFunctions()`](#zipfunctionssrcfolder-destfolder-options) except it bundles a single Function.
|
package/dist/config.d.ts
CHANGED
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]) => ({
|
package/dist/manifest.d.ts
CHANGED
package/dist/manifest.js
CHANGED
|
@@ -12,11 +12,14 @@ export const createManifest = async ({ functions, path }) => {
|
|
|
12
12
|
};
|
|
13
13
|
await fs.writeFile(path, JSON.stringify(payload));
|
|
14
14
|
};
|
|
15
|
-
const formatFunctionForManifest = ({ mainFile, name, path, runtime, schedule }) => ({
|
|
15
|
+
const formatFunctionForManifest = ({ mainFile, name, path, runtime, schedule, displayName, bundler, isInternal, }) => ({
|
|
16
16
|
mainFile,
|
|
17
17
|
name,
|
|
18
18
|
path: resolve(path),
|
|
19
19
|
runtime,
|
|
20
20
|
schedule,
|
|
21
|
+
displayName,
|
|
22
|
+
bundler,
|
|
23
|
+
isInternal,
|
|
21
24
|
});
|
|
22
25
|
//# sourceMappingURL=manifest.js.map
|
|
@@ -66,7 +66,7 @@ const processSource = async ({ cache, mainFile, path, }) => {
|
|
|
66
66
|
stat,
|
|
67
67
|
};
|
|
68
68
|
};
|
|
69
|
-
const zipFunction = async function ({ config, destFolder, filename, mainFile, srcDir, srcPath, stat }) {
|
|
69
|
+
const zipFunction = async function ({ config, destFolder, filename, mainFile, srcDir, srcPath, stat, isInternal, }) {
|
|
70
70
|
const destPath = join(destFolder, filename);
|
|
71
71
|
const isSource = extname(mainFile) === '.go';
|
|
72
72
|
let binary = {
|
|
@@ -100,7 +100,12 @@ const zipFunction = async function ({ config, destFolder, filename, mainFile, sr
|
|
|
100
100
|
if (!isSource) {
|
|
101
101
|
await copyFile(binary.path, destPath);
|
|
102
102
|
}
|
|
103
|
-
return {
|
|
103
|
+
return {
|
|
104
|
+
config,
|
|
105
|
+
path: destPath,
|
|
106
|
+
displayName: config?.name,
|
|
107
|
+
isInternal,
|
|
108
|
+
};
|
|
104
109
|
};
|
|
105
110
|
const runtime = { findFunctionsInPaths, findFunctionInPath, name: "go" /* RuntimeType.GO */, zipFunction };
|
|
106
111
|
export default runtime;
|
|
@@ -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 {
|
|
@@ -19,7 +19,7 @@ const getSrcFilesWithBundler = async (parameters) => {
|
|
|
19
19
|
const result = await bundler.getSrcFiles({ ...parameters, pluginsModulesPath });
|
|
20
20
|
return result.srcFiles;
|
|
21
21
|
};
|
|
22
|
-
const zipFunction = async function ({ archiveFormat, basePath, cache, config = {}, destFolder, extension, featureFlags, filename, mainFile, name, repositoryRoot, runtime, srcDir, srcPath, stat, }) {
|
|
22
|
+
const zipFunction = async function ({ archiveFormat, basePath, cache, config = {}, destFolder, extension, featureFlags, filename, mainFile, name, repositoryRoot, runtime, srcDir, srcPath, stat, isInternal, }) {
|
|
23
23
|
const pluginsModulesPath = await getPluginsModulesPath(srcDir);
|
|
24
24
|
const bundlerName = await getBundlerName({
|
|
25
25
|
config,
|
|
@@ -78,6 +78,8 @@ const zipFunction = async function ({ archiveFormat, basePath, cache, config = {
|
|
|
78
78
|
nativeNodeModules,
|
|
79
79
|
nodeModulesWithDynamicImports,
|
|
80
80
|
path: zipPath,
|
|
81
|
+
displayName: config?.name,
|
|
82
|
+
isInternal,
|
|
81
83
|
};
|
|
82
84
|
};
|
|
83
85
|
const zipWithFunctionWithFallback = async ({ config = {}, ...parameters }) => {
|
|
@@ -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
|
-
// We don't need an entry file if it would end up with the same path as the
|
|
57
|
-
// function's main file.
|
|
58
|
-
const needsEntryFile = entryFilePath !== mainFile;
|
|
59
51
|
// There is a naming conflict with the entry file if one of the supporting
|
|
60
52
|
// files (i.e. not the main file) has the path that the entry file needs to
|
|
61
53
|
// take.
|
|
62
|
-
const hasEntryFileConflict = srcFiles
|
|
54
|
+
const hasEntryFileConflict = conflictsWithEntryFile(srcFiles, {
|
|
55
|
+
basePath,
|
|
56
|
+
filename,
|
|
57
|
+
mainFile,
|
|
58
|
+
});
|
|
59
|
+
// We don't need an entry file if it would end up with the same path as the
|
|
60
|
+
// function's main file. Unless we have a file conflict and need to move everything into a subfolder
|
|
61
|
+
const needsEntryFile = hasEntryFileConflict || !isNamedLikeEntryFile(mainFile, { basePath, filename });
|
|
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
|
};
|
|
@@ -37,6 +37,8 @@ export interface ZipFunctionResult {
|
|
|
37
37
|
nativeNodeModules?: object;
|
|
38
38
|
nodeModulesWithDynamicImports?: string[];
|
|
39
39
|
path: string;
|
|
40
|
+
isInternal?: boolean;
|
|
41
|
+
displayName?: string;
|
|
40
42
|
}
|
|
41
43
|
export type ZipFunction = (args: {
|
|
42
44
|
archiveFormat: ArchiveFormat;
|
|
@@ -46,6 +48,7 @@ export type ZipFunction = (args: {
|
|
|
46
48
|
destFolder: string;
|
|
47
49
|
featureFlags: FeatureFlags;
|
|
48
50
|
repositoryRoot?: string;
|
|
51
|
+
isInternal?: boolean;
|
|
49
52
|
} & FunctionSource) => Promise<ZipFunctionResult>;
|
|
50
53
|
export interface Runtime {
|
|
51
54
|
findFunctionsInPaths: FindFunctionsInPathsFunction;
|
|
@@ -80,7 +80,7 @@ const processSource = async ({ cache, mainFile, path, }) => {
|
|
|
80
80
|
// The name of the binary inside the zip file must always be `bootstrap`
|
|
81
81
|
// because they include the Lambda runtime, and that's the name that AWS
|
|
82
82
|
// expects for those kind of functions.
|
|
83
|
-
const zipFunction = async function ({ cache, config, destFolder, filename, mainFile, runtime, srcDir, srcPath, stat, }) {
|
|
83
|
+
const zipFunction = async function ({ cache, config, destFolder, filename, mainFile, runtime, srcDir, srcPath, stat, isInternal, }) {
|
|
84
84
|
const destPath = join(destFolder, `${filename}.zip`);
|
|
85
85
|
const isSource = extname(mainFile) === '.rs';
|
|
86
86
|
const zipOptions = {
|
|
@@ -98,7 +98,12 @@ const zipFunction = async function ({ cache, config, destFolder, filename, mainF
|
|
|
98
98
|
else {
|
|
99
99
|
await zipBinary({ ...zipOptions, srcPath, stat });
|
|
100
100
|
}
|
|
101
|
-
return {
|
|
101
|
+
return {
|
|
102
|
+
config,
|
|
103
|
+
path: destPath,
|
|
104
|
+
displayName: config?.name,
|
|
105
|
+
isInternal,
|
|
106
|
+
};
|
|
102
107
|
};
|
|
103
108
|
const runtime = { findFunctionsInPaths, findFunctionInPath, name: "rs" /* RuntimeType.RUST */, zipFunction };
|
|
104
109
|
export default runtime;
|
package/dist/zip.d.ts
CHANGED
|
@@ -11,15 +11,17 @@ interface ZipFunctionOptions {
|
|
|
11
11
|
zipGo?: boolean;
|
|
12
12
|
systemLog?: LogFunction;
|
|
13
13
|
debug?: boolean;
|
|
14
|
+
internalSrcFolder?: string;
|
|
14
15
|
}
|
|
15
16
|
export type ZipFunctionsOptions = ZipFunctionOptions & {
|
|
16
17
|
configFileDirectories?: string[];
|
|
17
18
|
manifest?: string;
|
|
18
19
|
parallelLimit?: number;
|
|
20
|
+
internalSrcFolder?: string;
|
|
19
21
|
};
|
|
20
|
-
export declare const zipFunctions: (relativeSrcFolders: string | string[], destFolder: string, { archiveFormat, basePath, config, configFileDirectories, featureFlags: inputFeatureFlags, manifest, parallelLimit, repositoryRoot, systemLog, debug, }?: ZipFunctionsOptions) => Promise<(Omit<import("./function.js").FunctionArchive, "runtime"> & {
|
|
22
|
+
export declare const zipFunctions: (relativeSrcFolders: string | string[], destFolder: string, { archiveFormat, basePath, config, configFileDirectories, featureFlags: inputFeatureFlags, manifest, parallelLimit, repositoryRoot, systemLog, debug, internalSrcFolder, }?: ZipFunctionsOptions) => Promise<(Omit<import("./function.js").FunctionArchive, "runtime"> & {
|
|
21
23
|
runtime: import("./main.js").RuntimeType;
|
|
22
24
|
schedule?: string | undefined;
|
|
23
25
|
})[]>;
|
|
24
|
-
export declare const zipFunction: (relativeSrcPath: string, destFolder: string, { archiveFormat, basePath, config: inputConfig, featureFlags: inputFeatureFlags, repositoryRoot, systemLog, debug, }?: ZipFunctionOptions) => Promise<import("./utils/format_result.js").FunctionResult | undefined>;
|
|
26
|
+
export declare const zipFunction: (relativeSrcPath: string, destFolder: string, { archiveFormat, basePath, config: inputConfig, featureFlags: inputFeatureFlags, repositoryRoot, systemLog, debug, internalSrcFolder, }?: ZipFunctionOptions) => Promise<import("./utils/format_result.js").FunctionResult | undefined>;
|
|
25
27
|
export {};
|
package/dist/zip.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { promises as fs } from 'fs';
|
|
2
2
|
import { resolve } from 'path';
|
|
3
|
+
import isPathInside from 'is-path-inside';
|
|
3
4
|
import pMap from 'p-map';
|
|
4
5
|
import { getFlags } from './feature_flags.js';
|
|
5
6
|
import { createManifest } from './manifest.js';
|
|
@@ -20,12 +21,13 @@ const validateArchiveFormat = (archiveFormat) => {
|
|
|
20
21
|
};
|
|
21
22
|
// Zip `srcFolder/*` (Node.js or Go files) to `destFolder/*.zip` so it can be
|
|
22
23
|
// used by AWS Lambda
|
|
23
|
-
export const zipFunctions = async function (relativeSrcFolders, destFolder, { archiveFormat = 'zip', basePath, config = {}, configFileDirectories, featureFlags: inputFeatureFlags, manifest, parallelLimit = DEFAULT_PARALLEL_LIMIT, repositoryRoot = basePath, systemLog, debug, } = {}) {
|
|
24
|
+
export const zipFunctions = async function (relativeSrcFolders, destFolder, { archiveFormat = 'zip', basePath, config = {}, configFileDirectories, featureFlags: inputFeatureFlags, manifest, parallelLimit = DEFAULT_PARALLEL_LIMIT, repositoryRoot = basePath, systemLog, debug, internalSrcFolder, } = {}) {
|
|
24
25
|
validateArchiveFormat(archiveFormat);
|
|
25
26
|
const logger = getLogger(systemLog, debug);
|
|
26
27
|
const cache = new RuntimeCache();
|
|
27
28
|
const featureFlags = getFlags(inputFeatureFlags);
|
|
28
29
|
const srcFolders = resolveFunctionsDirectories(relativeSrcFolders);
|
|
30
|
+
const internalFunctionsPath = internalSrcFolder && resolve(internalSrcFolder);
|
|
29
31
|
const [paths] = await Promise.all([listFunctionsDirectories(srcFolders), fs.mkdir(destFolder, { recursive: true })]);
|
|
30
32
|
const functions = await getFunctionsFromPaths(paths, {
|
|
31
33
|
cache,
|
|
@@ -58,6 +60,7 @@ export const zipFunctions = async function (relativeSrcFolders, destFolder, { ar
|
|
|
58
60
|
srcDir: func.srcDir,
|
|
59
61
|
srcPath: func.srcPath,
|
|
60
62
|
stat: func.stat,
|
|
63
|
+
isInternal: Boolean(internalFunctionsPath && isPathInside(func.srcPath, internalFunctionsPath)),
|
|
61
64
|
});
|
|
62
65
|
const durationNs = endTimer(startIntervalTime);
|
|
63
66
|
const logObject = {
|
|
@@ -81,13 +84,14 @@ export const zipFunctions = async function (relativeSrcFolders, destFolder, { ar
|
|
|
81
84
|
return formattedResults;
|
|
82
85
|
};
|
|
83
86
|
// eslint-disable-next-line max-statements
|
|
84
|
-
export const zipFunction = async function (relativeSrcPath, destFolder, { archiveFormat = 'zip', basePath, config: inputConfig = {}, featureFlags: inputFeatureFlags, repositoryRoot = basePath, systemLog, debug, } = {}) {
|
|
87
|
+
export const zipFunction = async function (relativeSrcPath, destFolder, { archiveFormat = 'zip', basePath, config: inputConfig = {}, featureFlags: inputFeatureFlags, repositoryRoot = basePath, systemLog, debug, internalSrcFolder, } = {}) {
|
|
85
88
|
validateArchiveFormat(archiveFormat);
|
|
86
89
|
const logger = getLogger(systemLog, debug);
|
|
87
90
|
const featureFlags = getFlags(inputFeatureFlags);
|
|
88
91
|
const srcPath = resolve(relativeSrcPath);
|
|
89
92
|
const cache = new RuntimeCache();
|
|
90
93
|
const functions = await getFunctionsFromPaths([srcPath], { cache, config: inputConfig, dedupe: true, featureFlags });
|
|
94
|
+
const internalFunctionsPath = internalSrcFolder && resolve(internalSrcFolder);
|
|
91
95
|
if (functions.size === 0) {
|
|
92
96
|
return;
|
|
93
97
|
}
|
|
@@ -116,6 +120,7 @@ export const zipFunction = async function (relativeSrcPath, destFolder, { archiv
|
|
|
116
120
|
srcDir,
|
|
117
121
|
srcPath,
|
|
118
122
|
stat: stats,
|
|
123
|
+
isInternal: Boolean(internalFunctionsPath && isPathInside(srcPath, internalFunctionsPath)),
|
|
119
124
|
});
|
|
120
125
|
const durationNs = endTimer(startIntervalTime);
|
|
121
126
|
const logObject = {
|
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.4.0",
|
|
4
4
|
"description": "Zip it and ship it",
|
|
5
5
|
"main": "./dist/main.js",
|
|
6
6
|
"type": "module",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"prepublishOnly": "npm ci && npm test",
|
|
17
17
|
"prepack": "npm run build",
|
|
18
18
|
"build": "tsc",
|
|
19
|
+
"build:dev": "tsc -w",
|
|
19
20
|
"benchmark": "./benchmarks/run.sh",
|
|
20
21
|
"format": "run-s build format:check-fix:*",
|
|
21
22
|
"format:ci": "run-s build format:check:*",
|
|
@@ -97,7 +98,7 @@
|
|
|
97
98
|
"@types/tmp": "^0.2.3",
|
|
98
99
|
"@types/unixify": "^1.0.0",
|
|
99
100
|
"@types/yargs": "^17.0.4",
|
|
100
|
-
"@vitest/coverage-c8": "^0.
|
|
101
|
+
"@vitest/coverage-c8": "^0.27.0",
|
|
101
102
|
"cpy": "^9.0.0",
|
|
102
103
|
"deepmerge": "^4.2.2",
|
|
103
104
|
"get-stream": "^6.0.0",
|
|
@@ -108,7 +109,7 @@
|
|
|
108
109
|
"throat": "^6.0.1",
|
|
109
110
|
"typescript": "^4.8.4",
|
|
110
111
|
"vite": "^4.0.0",
|
|
111
|
-
"vitest": "^0.
|
|
112
|
+
"vitest": "^0.27.0"
|
|
112
113
|
},
|
|
113
114
|
"engines": {
|
|
114
115
|
"node": "^14.16.0 || >=16.0.0"
|