@netlify/zip-it-and-ship-it 8.4.2 → 8.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/README.md +11 -7
- package/dist/feature_flags.js +2 -0
- package/dist/main.d.ts +7 -3
- package/dist/main.js +16 -8
- package/dist/runtimes/index.d.ts +2 -1
- package/dist/runtimes/index.js +26 -11
- package/dist/runtimes/node/utils/entry_file.d.ts +4 -1
- package/dist/runtimes/node/utils/entry_file.js +17 -1
- package/dist/runtimes/node/utils/zip.js +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ A directory or a list of directories containing the source files. If a string is
|
|
|
47
47
|
must exist. If an array of strings is provided, at least one directory must exist.
|
|
48
48
|
|
|
49
49
|
In Netlify, this directory is the
|
|
50
|
-
["Functions folder"](https://docs.netlify.com/functions/
|
|
50
|
+
["Functions folder"](https://docs.netlify.com/functions/optional-configuration/?fn-language=ts#directory).
|
|
51
51
|
|
|
52
52
|
A source folder can contain:
|
|
53
53
|
|
|
@@ -279,7 +279,7 @@ import { zipFunction } from '@netlify/zip-it-and-ship-it'
|
|
|
279
279
|
const archive = await zipFunction('functions/function.js', 'functions-dist')
|
|
280
280
|
```
|
|
281
281
|
|
|
282
|
-
This is like [`zipFunctions()`](#
|
|
282
|
+
This is like [`zipFunctions()`](#zipfunctionssrcfolders-destfolder-options) except it bundles a single Function.
|
|
283
283
|
|
|
284
284
|
The return value is `undefined` if the function is invalid.
|
|
285
285
|
|
|
@@ -315,6 +315,10 @@ Each object has the following properties:
|
|
|
315
315
|
Function's name. This is the one used in the Function URL. For example, if a Function is a `myFunc.js` regular file,
|
|
316
316
|
the `name` is `myFunc` and the URL is `https://{hostname}/.netlify/functions/myFunc`.
|
|
317
317
|
|
|
318
|
+
- `displayName` `string`
|
|
319
|
+
|
|
320
|
+
If there was a user-defined configuration object applied to the function, and it had a `name` defined. This will be returned here.
|
|
321
|
+
|
|
318
322
|
- `mainFile`: `string`
|
|
319
323
|
|
|
320
324
|
Absolute path to the Function's main file. If the Function is a Node.js directory, this is its `index.js` or
|
|
@@ -330,7 +334,7 @@ Each object has the following properties:
|
|
|
330
334
|
|
|
331
335
|
## listFunctionsFiles(srcFolders)
|
|
332
336
|
|
|
333
|
-
Like [`listFunctions()`](#
|
|
337
|
+
Like [`listFunctions()`](#listfunctionssrcfolders-options), except it returns not only the Functions main files, but also all
|
|
334
338
|
their required files. This is much slower.
|
|
335
339
|
|
|
336
340
|
```js
|
|
@@ -354,7 +358,7 @@ See [feature flags](#feature-flags).
|
|
|
354
358
|
|
|
355
359
|
### Return value
|
|
356
360
|
|
|
357
|
-
The return value is the same as [`listFunctions()`](#
|
|
361
|
+
The return value is the same as [`listFunctions()`](#listfunctionssrcfolders-options) but with the following additional
|
|
358
362
|
properties.
|
|
359
363
|
|
|
360
364
|
- `srcFile`: `string`
|
|
@@ -367,7 +371,7 @@ properties.
|
|
|
367
371
|
$ zip-it-and-ship-it srcFolder destFolder
|
|
368
372
|
```
|
|
369
373
|
|
|
370
|
-
The CLI performs the same logic as [`zipFunctions()`](#
|
|
374
|
+
The CLI performs the same logic as [`zipFunctions()`](#zipfunctionssrcfolders-destfolder-options). The archives are
|
|
371
375
|
printed on `stdout` as a JSON array.
|
|
372
376
|
|
|
373
377
|
# Bundling Node.js functions
|
|
@@ -425,7 +429,7 @@ These are supplied to each of the entrypoint functions (`zipFunction`, `zipFunct
|
|
|
425
429
|
`listFunctionsFiles`) as a named parameter called `featureFlags`. It consists of an object where each key is the name of
|
|
426
430
|
a feature flag and the values are Booleans indicating whether each feature flag is enabled or disabled.
|
|
427
431
|
|
|
428
|
-
The list of all feature flags currently being used can be found [here](src/feature_flags.
|
|
432
|
+
The list of all feature flags currently being used can be found [here](src/feature_flags.ts).
|
|
429
433
|
|
|
430
434
|
# Troubleshooting
|
|
431
435
|
|
|
@@ -464,7 +468,7 @@ In Netlify, this is done by ensuring that the following Node.js versions are the
|
|
|
464
468
|
- Build-time Node.js version: this defaults to Node `16`, but can be
|
|
465
469
|
[overridden with a `.nvmrc` or `NODE_VERSION` environment variable](https://docs.netlify.com/configure-builds/manage-dependencies/#node-js-and-javascript).
|
|
466
470
|
- Function runtime Node.js version: this defaults to `nodejs16.x` but can be
|
|
467
|
-
[overridden with a `AWS_LAMBDA_JS_RUNTIME` environment variable](https://docs.netlify.com/functions/
|
|
471
|
+
[overridden with a `AWS_LAMBDA_JS_RUNTIME` environment variable](https://docs.netlify.com/functions/optional-configuration/?fn-language=js#node-js-version-for-runtime-2).
|
|
468
472
|
|
|
469
473
|
Note that this problem might not apply for Node.js native modules using the [N-API](https://nodejs.org/api/n-api.html).
|
|
470
474
|
|
package/dist/feature_flags.js
CHANGED
|
@@ -16,6 +16,8 @@ export const defaultFlags = {
|
|
|
16
16
|
project_deploy_configuration_api_use_per_function_configuration_files: false,
|
|
17
17
|
// Output CJS file extension
|
|
18
18
|
zisi_output_cjs_extension: false,
|
|
19
|
+
// Do not allow ___netlify-entry-point as function or file name
|
|
20
|
+
zisi_disallow_new_entry_name: false,
|
|
19
21
|
};
|
|
20
22
|
// List of supported flags and their default value.
|
|
21
23
|
export const getFlags = (input = {}, flags = defaultFlags) => Object.entries(flags).reduce((result, [key, defaultValue]) => ({
|
package/dist/main.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export interface ListedFunction {
|
|
|
11
11
|
runtime: RuntimeType;
|
|
12
12
|
extension: string;
|
|
13
13
|
schedule?: string;
|
|
14
|
+
displayName?: string;
|
|
14
15
|
}
|
|
15
16
|
type ListedFunctionFile = ListedFunction & {
|
|
16
17
|
srcFile: string;
|
|
@@ -18,17 +19,20 @@ type ListedFunctionFile = ListedFunction & {
|
|
|
18
19
|
interface ListFunctionsOptions {
|
|
19
20
|
basePath?: string;
|
|
20
21
|
config?: Config;
|
|
22
|
+
configFileDirectories?: string[];
|
|
21
23
|
featureFlags?: FeatureFlags;
|
|
22
24
|
parseISC?: boolean;
|
|
23
25
|
}
|
|
24
|
-
export declare const listFunctions: (relativeSrcFolders: string | string[], { featureFlags: inputFeatureFlags, config, parseISC, }?: {
|
|
26
|
+
export declare const listFunctions: (relativeSrcFolders: string | string[], { featureFlags: inputFeatureFlags, config, configFileDirectories, parseISC, }?: {
|
|
25
27
|
featureFlags?: FeatureFlags | undefined;
|
|
26
28
|
config?: Config | undefined;
|
|
29
|
+
configFileDirectories?: string[] | undefined;
|
|
27
30
|
parseISC?: boolean | undefined;
|
|
28
31
|
}) => Promise<ListedFunction[]>;
|
|
29
|
-
export declare const listFunction: (path: string, { featureFlags: inputFeatureFlags, config, parseISC, }?: {
|
|
32
|
+
export declare const listFunction: (path: string, { featureFlags: inputFeatureFlags, config, configFileDirectories, parseISC, }?: {
|
|
30
33
|
featureFlags?: FeatureFlags | undefined;
|
|
31
34
|
config?: Config | undefined;
|
|
35
|
+
configFileDirectories?: string[] | undefined;
|
|
32
36
|
parseISC?: boolean | undefined;
|
|
33
37
|
}) => Promise<ListedFunction | undefined>;
|
|
34
|
-
export declare const listFunctionsFiles: (relativeSrcFolders: string | string[], { basePath, config, featureFlags: inputFeatureFlags, parseISC }?: ListFunctionsOptions) => Promise<ListedFunctionFile[]>;
|
|
38
|
+
export declare const listFunctionsFiles: (relativeSrcFolders: string | string[], { basePath, config, configFileDirectories, featureFlags: inputFeatureFlags, parseISC, }?: ListFunctionsOptions) => Promise<ListedFunctionFile[]>;
|
package/dist/main.js
CHANGED
|
@@ -6,7 +6,8 @@ import { RuntimeCache } from './utils/cache.js';
|
|
|
6
6
|
import { listFunctionsDirectories, resolveFunctionsDirectories } from './utils/fs.js';
|
|
7
7
|
export { zipFunction, zipFunctions } from './zip.js';
|
|
8
8
|
const augmentWithISC = async (func) => {
|
|
9
|
-
// ISC is currently only supported in JavaScript and TypeScript functions
|
|
9
|
+
// ISC is currently only supported in JavaScript and TypeScript functions
|
|
10
|
+
// and only supports scheduled functions.
|
|
10
11
|
if (func.runtime.name !== "js" /* RuntimeType.JAVASCRIPT */) {
|
|
11
12
|
return func;
|
|
12
13
|
}
|
|
@@ -14,21 +15,21 @@ const augmentWithISC = async (func) => {
|
|
|
14
15
|
return { ...func, inSourceConfig };
|
|
15
16
|
};
|
|
16
17
|
// List all Netlify Functions main entry files for a specific directory
|
|
17
|
-
export const listFunctions = async function (relativeSrcFolders, { featureFlags: inputFeatureFlags, config, parseISC = false, } = {}) {
|
|
18
|
+
export const listFunctions = async function (relativeSrcFolders, { featureFlags: inputFeatureFlags, config, configFileDirectories, parseISC = false, } = {}) {
|
|
18
19
|
const featureFlags = getFlags(inputFeatureFlags);
|
|
19
20
|
const srcFolders = resolveFunctionsDirectories(relativeSrcFolders);
|
|
20
21
|
const paths = await listFunctionsDirectories(srcFolders);
|
|
21
22
|
const cache = new RuntimeCache();
|
|
22
|
-
const functionsMap = await getFunctionsFromPaths(paths, { cache, config, featureFlags });
|
|
23
|
+
const functionsMap = await getFunctionsFromPaths(paths, { cache, config, configFileDirectories, featureFlags });
|
|
23
24
|
const functions = [...functionsMap.values()];
|
|
24
25
|
const augmentedFunctions = parseISC ? await Promise.all(functions.map(augmentWithISC)) : functions;
|
|
25
26
|
return augmentedFunctions.map(getListedFunction);
|
|
26
27
|
};
|
|
27
28
|
// Finds a function at a specific path.
|
|
28
|
-
export const listFunction = async function (path, { featureFlags: inputFeatureFlags, config, parseISC = false, } = {}) {
|
|
29
|
+
export const listFunction = async function (path, { featureFlags: inputFeatureFlags, config, configFileDirectories, parseISC = false, } = {}) {
|
|
29
30
|
const featureFlags = getFlags(inputFeatureFlags);
|
|
30
31
|
const cache = new RuntimeCache();
|
|
31
|
-
const func = await getFunctionFromPath(path, { cache, config, featureFlags });
|
|
32
|
+
const func = await getFunctionFromPath(path, { cache, config, configFileDirectories, featureFlags });
|
|
32
33
|
if (!func) {
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
@@ -36,19 +37,26 @@ export const listFunction = async function (path, { featureFlags: inputFeatureFl
|
|
|
36
37
|
return getListedFunction(augmentedFunction);
|
|
37
38
|
};
|
|
38
39
|
// List all Netlify Functions files for a specific directory
|
|
39
|
-
export const listFunctionsFiles = async function (relativeSrcFolders, { basePath, config, featureFlags: inputFeatureFlags, parseISC = false } = {}) {
|
|
40
|
+
export const listFunctionsFiles = async function (relativeSrcFolders, { basePath, config, configFileDirectories, featureFlags: inputFeatureFlags, parseISC = false, } = {}) {
|
|
40
41
|
const featureFlags = getFlags(inputFeatureFlags);
|
|
41
42
|
const srcFolders = resolveFunctionsDirectories(relativeSrcFolders);
|
|
42
43
|
const paths = await listFunctionsDirectories(srcFolders);
|
|
43
44
|
const cache = new RuntimeCache();
|
|
44
|
-
const functionsMap = await getFunctionsFromPaths(paths, { cache, config, featureFlags });
|
|
45
|
+
const functionsMap = await getFunctionsFromPaths(paths, { cache, config, configFileDirectories, featureFlags });
|
|
45
46
|
const functions = [...functionsMap.values()];
|
|
46
47
|
const augmentedFunctions = parseISC ? await Promise.all(functions.map(augmentWithISC)) : functions;
|
|
47
48
|
const listedFunctionsFiles = await Promise.all(augmentedFunctions.map((func) => getListedFunctionFiles(func, { basePath, featureFlags })));
|
|
48
49
|
return listedFunctionsFiles.flat();
|
|
49
50
|
};
|
|
50
51
|
const getListedFunction = function ({ runtime, name, mainFile, extension, config, inSourceConfig, }) {
|
|
51
|
-
return {
|
|
52
|
+
return {
|
|
53
|
+
name,
|
|
54
|
+
displayName: config.name,
|
|
55
|
+
mainFile,
|
|
56
|
+
runtime: runtime.name,
|
|
57
|
+
extension,
|
|
58
|
+
schedule: inSourceConfig?.schedule ?? config.schedule,
|
|
59
|
+
};
|
|
52
60
|
};
|
|
53
61
|
const getListedFunctionFiles = async function (func, options) {
|
|
54
62
|
const srcFiles = await getSrcFiles({ ...func, ...options });
|
package/dist/runtimes/index.d.ts
CHANGED
|
@@ -16,9 +16,10 @@ export declare const getFunctionsFromPaths: (paths: string[], { cache, config, c
|
|
|
16
16
|
/**
|
|
17
17
|
* Gets a list of functions found in a list of paths.
|
|
18
18
|
*/
|
|
19
|
-
export declare const getFunctionFromPath: (path: string, { cache, config, featureFlags }: {
|
|
19
|
+
export declare const getFunctionFromPath: (path: string, { cache, config, configFileDirectories, featureFlags, }: {
|
|
20
20
|
cache: RuntimeCache;
|
|
21
21
|
config?: Config | undefined;
|
|
22
|
+
configFileDirectories?: string[] | undefined;
|
|
22
23
|
featureFlags?: FeatureFlags | undefined;
|
|
23
24
|
}) => Promise<FunctionSource | undefined>;
|
|
24
25
|
export {};
|
package/dist/runtimes/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { extname, basename } from 'path';
|
|
2
2
|
import { getConfigForFunction } from '../config.js';
|
|
3
3
|
import { defaultFlags } from '../feature_flags.js';
|
|
4
|
+
import { FunctionBundlingUserError } from '../utils/error.js';
|
|
4
5
|
import goRuntime from './go/index.js';
|
|
5
6
|
import jsRuntime from './node/index.js';
|
|
7
|
+
import { ENTRY_FILE_NAME } from './node/utils/entry_file.js';
|
|
6
8
|
import rustRuntime from './rust/index.js';
|
|
7
9
|
/**
|
|
8
10
|
* Finds functions for a list of paths using a specific runtime. The return
|
|
@@ -17,15 +19,23 @@ const findFunctionsInRuntime = async function ({ cache, dedupe = false, featureF
|
|
|
17
19
|
// `srcPath`, so that both functions are returned.
|
|
18
20
|
const key = dedupe ? 'name' : 'srcPath';
|
|
19
21
|
// Augmenting the function objects with additional information.
|
|
20
|
-
const augmentedFunctions = functions.map((func) =>
|
|
21
|
-
func
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
const augmentedFunctions = functions.map((func) => {
|
|
23
|
+
if (featureFlags.zisi_disallow_new_entry_name && func.name === ENTRY_FILE_NAME) {
|
|
24
|
+
throw new FunctionBundlingUserError(`'${ENTRY_FILE_NAME}' is a reserved word and cannot be used as a function name.`, {
|
|
25
|
+
functionName: func.name,
|
|
26
|
+
runtime: runtime.name,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return [
|
|
30
|
+
func[key],
|
|
31
|
+
{
|
|
32
|
+
...func,
|
|
33
|
+
extension: extname(func.mainFile),
|
|
34
|
+
filename: basename(func.srcPath),
|
|
35
|
+
runtime,
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
});
|
|
29
39
|
const usedPaths = new Set(augmentedFunctions.map(([path]) => path));
|
|
30
40
|
const remainingPaths = paths.filter((path) => !usedPaths.has(path));
|
|
31
41
|
return { functions: augmentedFunctions, remainingPaths };
|
|
@@ -66,11 +76,16 @@ export const getFunctionsFromPaths = async (paths, { cache, config, configFileDi
|
|
|
66
76
|
/**
|
|
67
77
|
* Gets a list of functions found in a list of paths.
|
|
68
78
|
*/
|
|
69
|
-
export const getFunctionFromPath = async (path, { cache, config, featureFlags = defaultFlags }) => {
|
|
79
|
+
export const getFunctionFromPath = async (path, { cache, config, configFileDirectories, featureFlags = defaultFlags, }) => {
|
|
70
80
|
for (const runtime of RUNTIMES) {
|
|
71
81
|
const func = await runtime.findFunctionInPath({ path, cache, featureFlags });
|
|
72
82
|
if (func) {
|
|
73
|
-
const functionConfig = await getConfigForFunction({
|
|
83
|
+
const functionConfig = await getConfigForFunction({
|
|
84
|
+
config,
|
|
85
|
+
configFileDirectories,
|
|
86
|
+
func: { ...func, runtime },
|
|
87
|
+
featureFlags,
|
|
88
|
+
});
|
|
74
89
|
return {
|
|
75
90
|
...func,
|
|
76
91
|
runtime,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { FeatureFlags } from '../../../feature_flags.js';
|
|
2
2
|
import { ModuleFormat } from './module_format.js';
|
|
3
|
+
export declare const ENTRY_FILE_NAME = "___netlify-entry-point";
|
|
3
4
|
export interface EntryFile {
|
|
4
5
|
contents: string;
|
|
5
6
|
filename: string;
|
|
@@ -8,8 +9,10 @@ export declare const isNamedLikeEntryFile: (file: string, { basePath, filename,
|
|
|
8
9
|
basePath: string;
|
|
9
10
|
filename: string;
|
|
10
11
|
}) => boolean;
|
|
11
|
-
export declare const conflictsWithEntryFile: (srcFiles: string[], { basePath,
|
|
12
|
+
export declare const conflictsWithEntryFile: (srcFiles: string[], { basePath, extension, featureFlags, filename, mainFile, }: {
|
|
12
13
|
basePath: string;
|
|
14
|
+
extension: string;
|
|
15
|
+
featureFlags: FeatureFlags;
|
|
13
16
|
filename: string;
|
|
14
17
|
mainFile: string;
|
|
15
18
|
}) => boolean;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { basename, extname, resolve } from 'path';
|
|
2
|
+
import { FunctionBundlingUserError } from '../../../utils/error.js';
|
|
2
3
|
import { getFileExtensionForFormat } from './module_format.js';
|
|
3
4
|
import { normalizeFilePath } from './normalize_path.js';
|
|
5
|
+
export const ENTRY_FILE_NAME = '___netlify-entry-point';
|
|
4
6
|
const getEntryFileContents = (mainPath, moduleFormat) => {
|
|
5
7
|
const importPath = `.${mainPath.startsWith('/') ? mainPath : `/${mainPath}`}`;
|
|
6
8
|
if (moduleFormat === "cjs" /* ModuleFormat.COMMONJS */) {
|
|
@@ -17,7 +19,21 @@ export const isNamedLikeEntryFile = (file, { basePath, filename, }) => POSSIBLE_
|
|
|
17
19
|
return entryFilePath === file;
|
|
18
20
|
});
|
|
19
21
|
// Check if any src file (except the mainFile) is considered an entry file for AWS Lambda
|
|
20
|
-
export const conflictsWithEntryFile = (srcFiles, { basePath,
|
|
22
|
+
export const conflictsWithEntryFile = (srcFiles, { basePath, extension, featureFlags, filename, mainFile, }) => {
|
|
23
|
+
let hasConflict = false;
|
|
24
|
+
srcFiles.forEach((srcFile) => {
|
|
25
|
+
if (featureFlags.zisi_disallow_new_entry_name && srcFile.includes(ENTRY_FILE_NAME)) {
|
|
26
|
+
throw new FunctionBundlingUserError(`'${ENTRY_FILE_NAME}' is a reserved word and cannot be used as a file or directory name.`, {
|
|
27
|
+
functionName: basename(filename, extension),
|
|
28
|
+
runtime: "js" /* RuntimeType.JAVASCRIPT */,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
if (!hasConflict && isNamedLikeEntryFile(srcFile, { basePath, filename }) && srcFile !== mainFile) {
|
|
32
|
+
hasConflict = true;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
return hasConflict;
|
|
36
|
+
};
|
|
21
37
|
// Returns the name for the AWS Lambda entry file
|
|
22
38
|
// We do set the handler in AWS Lambda to `<func-name>.handler` and because of
|
|
23
39
|
// this it considers `<func-name>.(c|m)?js` as possible entry-points
|