@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 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 a manifest file to be created with the results of the functions bundling. This file is a
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 zipFunctions('functions/function.js', 'functions-dist')
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
@@ -15,6 +15,7 @@ interface FunctionConfig {
15
15
  rustTargetDirectory?: string;
16
16
  schedule?: string;
17
17
  zipGo?: boolean;
18
+ name?: string;
18
19
  nodeModuleFormat?: ModuleFormat;
19
20
  }
20
21
  type GlobPattern = string;
@@ -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
- // Enable runtime cache for NFT
18
- zisi_nft_use_cache: false,
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]) => ({
@@ -5,6 +5,9 @@ interface ManifestFunction {
5
5
  path: string;
6
6
  runtime: string;
7
7
  schedule?: string;
8
+ displayName?: string;
9
+ bundler?: string;
10
+ isInternal?: boolean;
8
11
  }
9
12
  export interface Manifest {
10
13
  functions: ManifestFunction[];
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 { config, path: destPath };
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 { ModuleFileExtension, ModuleFormat } from '../../utils/module_format.js';
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 extension = getFileExtensionForFormat(moduleFormat, featureFlags);
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 */ && featureFlags.zisi_esbuild_require_banner ? { js: esmJSBanner } : undefined,
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, extension: outputExtension, outputs, srcFile, }) => {
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, extension: outputExtension, inputs, moduleFormat, nativeNodeModules = {}, nodeModulesWithDynamicImports, warnings, } = await bundleJsFile({
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: featureFlags.zisi_nft_higher_fileio_limit ? 2048 : 1024,
46
+ fileIOConcurrency: 2048,
47
47
  base: basePath,
48
- cache: featureFlags.zisi_nft_use_cache ? cache.nftCache : undefined,
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 declare const getEntryFile: ({ commonPrefix, mainFile, moduleFormat, userNamespace, }: {
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
- }) => string;
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
- export const getEntryFile = ({ commonPrefix, mainFile, moduleFormat, userNamespace, }) => {
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, resolve } from 'path';
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 entryFile = getEntryFile({
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(entryFilePath, entryFile);
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.some((srcFile) => srcFile === entryFilePath && srcFile !== mainFile);
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({ commonPrefix: basePath, mainFile, moduleFormat, userNamespace });
68
- addEntryFileToZip(archive, entryFile, basename(entryFilePath));
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 { config, path: destPath };
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.2.0",
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.25.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.25.0"
112
+ "vitest": "^0.27.0"
112
113
  },
113
114
  "engines": {
114
115
  "node": "^14.16.0 || >=16.0.0"