@netlify/zip-it-and-ship-it 15.0.1 → 15.1.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.
@@ -7,7 +7,7 @@ const packageFilter = /^([^./]*)$/;
7
7
  const packageName = /^([^@][^/]*|@[^/]*\/[^/]+)(?:\/|$)/;
8
8
  const findNativeModule = (packageJsonPath, cache) => {
9
9
  if (cache[packageJsonPath] === undefined) {
10
- cache[packageJsonPath] = readPackageJson(packageJsonPath).then((data) => [Boolean(isNativeModule(data)), data], () => [undefined, {}]);
10
+ cache[packageJsonPath] = readPackageJson(packageJsonPath).then((data) => [isNativeModule(data), data], () => [undefined, {}]);
11
11
  }
12
12
  return cache[packageJsonPath];
13
13
  };
@@ -1,6 +1,6 @@
1
1
  import { FunctionConfig } from '../../../config.js';
2
2
  import { FeatureFlags } from '../../../feature_flags.js';
3
- import { NodeBundler, NodeBundlerName } from './types.js';
3
+ import type { BundlerReason, NodeBundler, NodeBundlerName } from './types.js';
4
4
  export declare const getBundler: (name: NodeBundlerName) => NodeBundler;
5
5
  export declare const getBundlerName: ({ config: { nodeBundler }, extension, featureFlags, mainFile, runtimeAPIVersion, }: {
6
6
  config: FunctionConfig;
@@ -8,4 +8,7 @@ export declare const getBundlerName: ({ config: { nodeBundler }, extension, feat
8
8
  featureFlags: FeatureFlags;
9
9
  mainFile: string;
10
10
  runtimeAPIVersion: number;
11
- }) => Promise<NodeBundlerName>;
11
+ }) => Promise<{
12
+ name: NodeBundlerName;
13
+ reason: BundlerReason;
14
+ }>;
@@ -4,7 +4,7 @@ import { MODULE_FILE_EXTENSION } from '../utils/module_format.js';
4
4
  import esbuildBundler from './esbuild/index.js';
5
5
  import nftBundler from './nft/index.js';
6
6
  import noBundler from './none/index.js';
7
- import { NODE_BUNDLER } from './types.js';
7
+ import { BUNDLER_REASON, NODE_BUNDLER } from './types.js';
8
8
  import zisiBundler from './zisi/index.js';
9
9
  export const getBundler = (name) => {
10
10
  switch (name) {
@@ -25,10 +25,12 @@ export const getBundlerName = async ({ config: { nodeBundler }, extension, featu
25
25
  // For V2 functions, we force the bundler to NFT. The only exception is when
26
26
  // a `none` override was provided.
27
27
  if (runtimeAPIVersion === 2) {
28
- return nodeBundler === NODE_BUNDLER.NONE ? NODE_BUNDLER.NONE : NODE_BUNDLER.NFT;
28
+ return nodeBundler === NODE_BUNDLER.NONE
29
+ ? { name: NODE_BUNDLER.NONE, reason: BUNDLER_REASON.NoneOverride }
30
+ : { name: NODE_BUNDLER.NFT, reason: BUNDLER_REASON.V2Default };
29
31
  }
30
32
  if (nodeBundler) {
31
- return nodeBundler;
33
+ return { name: nodeBundler, reason: BUNDLER_REASON.ConfigOverride };
32
34
  }
33
35
  return await getDefaultBundler({ extension, featureFlags, mainFile });
34
36
  };
@@ -37,14 +39,16 @@ const ESBUILD_EXTENSIONS = new Set(['.mjs', '.ts', '.tsx', '.cts', '.mts']);
37
39
  // esbuild is the only option.
38
40
  const getDefaultBundler = async ({ extension, featureFlags, mainFile, }) => {
39
41
  if (extension === MODULE_FILE_EXTENSION.MJS && featureFlags.zisi_pure_esm_mjs) {
40
- return NODE_BUNDLER.NFT;
42
+ return { name: NODE_BUNDLER.NFT, reason: BUNDLER_REASON.MjsPureEsm };
41
43
  }
42
44
  if (ESBUILD_EXTENSIONS.has(extension)) {
43
- return NODE_BUNDLER.ESBUILD;
45
+ return { name: NODE_BUNDLER.ESBUILD, reason: BUNDLER_REASON.EsbuildExtension };
44
46
  }
45
47
  if (featureFlags.traceWithNft) {
46
- return NODE_BUNDLER.NFT;
48
+ return { name: NODE_BUNDLER.NFT, reason: BUNDLER_REASON.FlagForcedNft };
47
49
  }
48
50
  const functionIsESM = extname(mainFile) !== MODULE_FILE_EXTENSION.CJS && (await detectEsModule({ mainFile }));
49
- return functionIsESM ? NODE_BUNDLER.NFT : NODE_BUNDLER.ZISI;
51
+ return functionIsESM
52
+ ? { name: NODE_BUNDLER.NFT, reason: BUNDLER_REASON.EsmDefault }
53
+ : { name: NODE_BUNDLER.ZISI, reason: BUNDLER_REASON.ZisiDefault };
50
54
  };
@@ -4,6 +4,7 @@ import type { FunctionConfig } from '../../../config.js';
4
4
  import type { FeatureFlags } from '../../../feature_flags.js';
5
5
  import type { FunctionSource } from '../../../function.js';
6
6
  import type { RuntimeCache } from '../../../utils/cache.js';
7
+ import type { ObjectValues } from '../../../types/utils.js';
7
8
  import { Logger } from '../../../utils/logger.js';
8
9
  import type { ModuleFormat } from '../utils/module_format.js';
9
10
  export declare const NODE_BUNDLER: {
@@ -21,6 +22,17 @@ export declare const nodeBundler: z.ZodNativeEnum<{
21
22
  readonly NONE: "none";
22
23
  }>;
23
24
  export type NodeBundlerName = z.infer<typeof nodeBundler>;
25
+ export declare const BUNDLER_REASON: {
26
+ readonly ConfigOverride: "config-override";
27
+ readonly NoneOverride: "none-override";
28
+ readonly V2Default: "v2-nft";
29
+ readonly MjsPureEsm: "mjs-pure-esm";
30
+ readonly EsbuildExtension: "esbuild-ext";
31
+ readonly EsmDefault: "esm-default";
32
+ readonly FlagForcedNft: "flag-forced-nft";
33
+ readonly ZisiDefault: "zisi-default";
34
+ };
35
+ export type BundlerReason = ObjectValues<typeof BUNDLER_REASON>;
24
36
  type BundlerWarning = Message;
25
37
  type CleanupFunction = () => Promise<void>;
26
38
  export type NativeNodeModules = Record<string, Record<string, string | undefined>>;
@@ -7,3 +7,14 @@ export const NODE_BUNDLER = {
7
7
  NONE: 'none',
8
8
  };
9
9
  export const nodeBundler = z.nativeEnum(NODE_BUNDLER);
10
+ /* Why a bundler was used to bundle a given function */
11
+ export const BUNDLER_REASON = {
12
+ ConfigOverride: 'config-override', // explicit `config.nodeBundler`
13
+ NoneOverride: 'none-override', // explicit `config.nodeBundler === 'none'`
14
+ V2Default: 'v2-nft', // runtimeAPIVersion === 2 forces nft
15
+ MjsPureEsm: 'mjs-pure-esm', // `.mjs` + `zisi_pure_esm_mjs`
16
+ EsbuildExtension: 'esbuild-ext', // `.ts`/`.tsx`/`.cts`/`.mts`/`.mjs`
17
+ EsmDefault: 'esm-default', // detected ESM `.js` → nft
18
+ FlagForcedNft: 'flag-forced-nft', // `traceWithNft` flipped a CJS function to nft
19
+ ZisiDefault: 'zisi-default', // CJS `.js`, `traceWithNft` flag off
20
+ };
@@ -1,10 +1,7 @@
1
1
  import { createRequire } from 'module';
2
2
  import { findUp } from 'find-up';
3
3
  import { pathExists } from 'path-exists';
4
- // @ts-expect-error doesnt export async
5
4
  import { async as asyncResolve } from 'resolve';
6
- // The types do not include the mjs api of resolve
7
- const resolveLib = asyncResolve;
8
5
  const require = createRequire(import.meta.url);
9
6
  const BACKSLASH_REGEXP = /\\/g;
10
7
  // Find the path to a module's `package.json`
@@ -39,7 +36,7 @@ export const resolvePackage = async function (moduleName, baseDirs) {
39
36
  // https://github.com/browserify/resolve/issues/151#issuecomment-368210310
40
37
  const resolvePathPreserveSymlinksForDir = function (path, basedir) {
41
38
  return new Promise((resolve, reject) => {
42
- resolveLib(path, { basedir, preserveSymlinks: true }, (error, resolvedLocation) => {
39
+ asyncResolve(path, { basedir, preserveSymlinks: true }, (error, resolvedLocation) => {
43
40
  if (error || resolvedLocation === undefined) {
44
41
  return reject(error);
45
42
  }
@@ -1,5 +1,7 @@
1
1
  import { dirname, extname, join } from 'path';
2
2
  import { copyFile } from 'copy-file';
3
+ import { trace } from '@opentelemetry/api';
4
+ import { wrapTracer } from '@opentelemetry/api/experimental';
3
5
  import { INVOCATION_MODE } from '../../function.js';
4
6
  import { Priority } from '../../priority.js';
5
7
  import { getTrafficRulesConfig } from '../../rate_limit.js';
@@ -12,12 +14,14 @@ import { augmentFunctionConfig, parseFile } from './in_source_config/index.js';
12
14
  import { MODULE_FORMAT, MODULE_FILE_EXTENSION } from './utils/module_format.js';
13
15
  import { getNodeRuntime, getNodeRuntimeForV2 } from './utils/node_runtime.js';
14
16
  import { createAliases as createPluginsModulesPathAliases, getPluginsModulesPath } from './utils/plugin_modules_path.js';
17
+ import { getBundleResultSpanAttributes, getFunctionBundleSpanAttributes } from './utils/span_attributes.js';
15
18
  import { zipNodeJs } from './utils/zip.js';
19
+ import { getArchiveSize } from '../../utils/archive_size.js';
16
20
  // A proxy for the `getSrcFiles` that calls `getSrcFiles` on the bundler
17
21
  const getSrcFilesWithBundler = async (parameters) => {
18
22
  const { config, extension, featureFlags, mainFile, runtimeAPIVersion, srcDir } = parameters;
19
23
  const pluginsModulesPath = await getPluginsModulesPath(srcDir);
20
- const bundlerName = await getBundlerName({
24
+ const { name: bundlerName } = await getBundlerName({
21
25
  config,
22
26
  extension,
23
27
  featureFlags,
@@ -28,7 +32,7 @@ const getSrcFilesWithBundler = async (parameters) => {
28
32
  const result = await bundler.getSrcFiles({ ...parameters, pluginsModulesPath });
29
33
  return result.srcFiles;
30
34
  };
31
- const zipFunction = async function ({ archiveFormat, basePath, branch, cache, config = {}, destFolder, extension, featureFlags, filename, isInternal, logger, mainFile, name, repositoryRoot, runtime, srcDir, srcPath, stat, }) {
35
+ const zipFunction = async function ({ archiveFormat, basePath, branch, cache, config = {}, destFolder, extension, featureFlags, filename, isInternal, logger, mainFile, name, repositoryRoot, runtime, span, srcDir, srcPath, stat, }) {
32
36
  // If the file is a zip, we assume the function is bundled and ready to go.
33
37
  // We simply copy it to the destination path with no further processing.
34
38
  if (extension === '.zip') {
@@ -50,13 +54,23 @@ const zipFunction = async function ({ archiveFormat, basePath, branch, cache, co
50
54
  const staticAnalysisResult = await parseFile(mainFile, { functionName: name });
51
55
  const runtimeAPIVersion = staticAnalysisResult.runtimeAPIVersion === 2 ? 2 : 1;
52
56
  const mergedConfig = augmentFunctionConfig(mainFile, config, staticAnalysisResult.config);
53
- const bundlerName = await getBundlerName({
57
+ const { name: bundlerName, reason: bundlerReason } = await getBundlerName({
54
58
  config: mergedConfig,
55
59
  extension,
56
60
  featureFlags,
57
61
  mainFile,
58
62
  runtimeAPIVersion,
59
63
  });
64
+ const generator = mergedConfig?.generator || getInternalValue(isInternal);
65
+ span?.setAttributes(getFunctionBundleSpanAttributes({
66
+ featureFlags,
67
+ name,
68
+ generator,
69
+ runtimeName: runtime.name,
70
+ runtimeAPIVersion,
71
+ bundlerName,
72
+ bundlerReason,
73
+ }));
60
74
  const bundler = getBundler(bundlerName);
61
75
  const { aliases = new Map(), cleanupFunction, basePath: basePathFromBundler, bundlerWarnings, includedFiles, inputs, mainFile: finalMainFile = mainFile, moduleFormat, nativeNodeModules, rewrites = new Map(), srcFiles, } = await bundler.bundle({
62
76
  basePath,
@@ -82,7 +96,6 @@ const zipFunction = async function ({ archiveFormat, basePath, branch, cache, co
82
96
  // common path prefix and that will break module resolution, as the modules
83
97
  // will no longer be inside a `node_modules` directory.
84
98
  const finalBasePath = isInPluginsModulesPath ? basePath : basePathFromBundler;
85
- const generator = mergedConfig?.generator || getInternalValue(isInternal);
86
99
  const zipResult = await zipNodeJs({
87
100
  aliases,
88
101
  archiveFormat,
@@ -129,6 +142,7 @@ const zipFunction = async function ({ archiveFormat, basePath, branch, cache, co
129
142
  return {
130
143
  bootstrapVersion: zipResult.bootstrapVersion,
131
144
  bundler: bundlerName,
145
+ bundlerReason,
132
146
  bundlerWarnings,
133
147
  config: mergedConfig,
134
148
  displayName: mergedConfig?.name,
@@ -150,24 +164,42 @@ const zipFunction = async function ({ archiveFormat, basePath, branch, cache, co
150
164
  };
151
165
  };
152
166
  const zipWithFunctionWithFallback = async ({ config = {}, ...parameters }) => {
153
- // If a specific JS bundler version is specified, we'll use it.
154
- if (config.nodeBundler !== NODE_BUNDLER.ESBUILD_ZISI) {
155
- return zipFunction({ ...parameters, config });
156
- }
157
- // Otherwise, we'll try to bundle with esbuild and, if that fails, fallback
158
- // to zisi.
159
- try {
160
- return await zipFunction({ ...parameters, config: { ...config, nodeBundler: NODE_BUNDLER.ESBUILD } });
161
- }
162
- catch (esbuildError) {
167
+ const tracer = wrapTracer(trace.getTracer('zip-it-and-ship-it'));
168
+ return tracer.withActiveSpan('function.bundle', async (span) => {
169
+ // If a specific JS bundler version is specified, we'll use it.
170
+ if (config.nodeBundler !== NODE_BUNDLER.ESBUILD_ZISI) {
171
+ const result = await zipFunction({ ...parameters, config, span });
172
+ await trackBundlerResult(span, result);
173
+ return result;
174
+ }
175
+ // Otherwise, we'll try to bundle with esbuild and, if that fails, fallback
176
+ // to zisi.
163
177
  try {
164
- const data = await zipFunction({ ...parameters, config: { ...config, nodeBundler: NODE_BUNDLER.ZISI } });
165
- return { ...data, bundlerErrors: esbuildError.errors };
178
+ const result = await zipFunction({
179
+ ...parameters,
180
+ config: { ...config, nodeBundler: NODE_BUNDLER.ESBUILD },
181
+ span,
182
+ });
183
+ await trackBundlerResult(span, result);
184
+ return result;
166
185
  }
167
- catch {
168
- throw esbuildError;
186
+ catch (esbuildError) {
187
+ try {
188
+ const data = await zipFunction({ ...parameters, config: { ...config, nodeBundler: NODE_BUNDLER.ZISI }, span });
189
+ const result = { ...data, bundlerErrors: esbuildError.errors };
190
+ await trackBundlerResult(span, result);
191
+ span.recordException(esbuildError);
192
+ return result;
193
+ }
194
+ catch (zisiError) {
195
+ span.recordException(zisiError);
196
+ throw esbuildError;
197
+ }
169
198
  }
170
- }
199
+ });
200
+ };
201
+ const trackBundlerResult = async (span, result) => {
202
+ span.setAttributes(getBundleResultSpanAttributes(result, await getArchiveSize(result.path)));
171
203
  };
172
204
  const runtime = {
173
205
  findFunctionsInPaths,
@@ -202,9 +202,9 @@ const parsePrimitive = (exp) => {
202
202
  const getExportsFromBindings = (specifiers, name, getAllBindings) => {
203
203
  const specifier = specifiers.find((node) => isNamedExport(node, name));
204
204
  // If there's no named export with the given name, check if there's a default
205
- if (!specifier || specifier.type !== 'ExportSpecifier') {
205
+ if (specifier?.type !== 'ExportSpecifier') {
206
206
  const defaultExport = specifiers.find((node) => isDefaultExport(node));
207
- if (defaultExport && defaultExport.type === 'ExportSpecifier') {
207
+ if (defaultExport?.type === 'ExportSpecifier') {
208
208
  const binding = getAllBindings().get(defaultExport.local.name);
209
209
  if (binding?.type === 'ArrowFunctionExpression' ||
210
210
  binding?.type === 'FunctionDeclaration' ||
@@ -229,7 +229,7 @@ const getCJSDefaultExpression = (node) => {
229
229
  // Resolves the expression for `export { x as default }` by looking up `x` in bindings.
230
230
  const getESMReexportedDefaultExpression = (node, getAllBindings) => {
231
231
  const defaultSpecifier = node.specifiers.find((spec) => spec.type === 'ExportSpecifier' && spec.exported.type === 'Identifier' && spec.exported.name === 'default');
232
- if (defaultSpecifier && defaultSpecifier.type === 'ExportSpecifier') {
232
+ if (defaultSpecifier?.type === 'ExportSpecifier') {
233
233
  return getAllBindings().get(defaultSpecifier.local.name);
234
234
  }
235
235
  return undefined;
@@ -22,7 +22,7 @@ export const isModuleExports = (node, dotExpression = ['module', 'exports']) =>
22
22
  node.expression.left.type === 'MemberExpression' &&
23
23
  isDotExpression(node.expression.left, dotExpression);
24
24
  export const isRequire = (node, requirePath) => {
25
- if (!node || node.type !== 'CallExpression') {
25
+ if (node?.type !== 'CallExpression') {
26
26
  return false;
27
27
  }
28
28
  const { arguments: args, callee } = node;
@@ -16,7 +16,7 @@ const getImportsFromCJS = (node, importPath) => {
16
16
  }
17
17
  const { declarations } = node;
18
18
  const requireDeclaration = declarations.find((declaration) => declaration.type === 'VariableDeclarator' && isRequire(declaration.init, importPath));
19
- if (requireDeclaration === undefined || requireDeclaration.id.type !== 'ObjectPattern') {
19
+ if (requireDeclaration?.id.type !== 'ObjectPattern') {
20
20
  return [];
21
21
  }
22
22
  const imports = requireDeclaration.id.properties
@@ -0,0 +1,14 @@
1
+ import type { Attributes } from '@opentelemetry/api';
2
+ import type { FeatureFlags } from '../../../feature_flags.js';
3
+ import type { ZipFunctionResult } from '../../runtime.js';
4
+ import type { BundlerReason, NodeBundlerName } from '../bundlers/types.js';
5
+ export declare const getFunctionBundleSpanAttributes: ({ featureFlags, name, generator, runtimeName, runtimeAPIVersion, bundlerName, bundlerReason, }: {
6
+ featureFlags: FeatureFlags;
7
+ name: string;
8
+ generator: string | undefined;
9
+ runtimeName: string;
10
+ runtimeAPIVersion: number;
11
+ bundlerName: NodeBundlerName;
12
+ bundlerReason: BundlerReason;
13
+ }) => Attributes;
14
+ export declare const getBundleResultSpanAttributes: (result: ZipFunctionResult, sizeBytes: number | undefined) => Attributes;
@@ -0,0 +1,16 @@
1
+ /* Span attributes describing a function and how it is bundled */
2
+ export const getFunctionBundleSpanAttributes = ({ featureFlags, name, generator, runtimeName, runtimeAPIVersion, bundlerName, bundlerReason, }) => ({
3
+ feature_flags: JSON.stringify(featureFlags),
4
+ 'function.name': name,
5
+ 'function.generator': generator,
6
+ 'function.runtime': runtimeName,
7
+ 'function.runtime_api_version': runtimeAPIVersion,
8
+ 'bundler.name': bundlerName,
9
+ 'bundler.reason': bundlerReason,
10
+ });
11
+ /* Span attributes known only once bundling has finished */
12
+ export const getBundleResultSpanAttributes = (result, sizeBytes) => ({
13
+ 'bundler.warnings_count': result.bundlerWarnings?.length ?? 0,
14
+ 'bundler.errors_count': result.bundlerErrors?.length ?? 0,
15
+ 'bundle.size_bytes': sizeBytes,
16
+ });
@@ -1,3 +1,4 @@
1
+ import type { Span } from '@opentelemetry/api';
1
2
  import type { ArchiveFormat } from '../archive.js';
2
3
  import type { FunctionConfig } from '../config.js';
3
4
  import type { FeatureFlags } from '../feature_flags.js';
@@ -7,7 +8,7 @@ import type { TrafficRules } from '../rate_limit.js';
7
8
  import { ObjectValues } from '../types/utils.js';
8
9
  import type { RuntimeCache } from '../utils/cache.js';
9
10
  import { Logger } from '../utils/logger.js';
10
- import type { NodeBundlerName } from './node/bundlers/types.js';
11
+ import type { BundlerReason, NodeBundlerName } from './node/bundlers/types.js';
11
12
  import type { StaticAnalysisResult } from './node/in_source_config/index.js';
12
13
  export declare const RUNTIME: {
13
14
  readonly GO: "go";
@@ -34,6 +35,7 @@ export type GetSrcFilesFunction = (args: {
34
35
  } & FunctionSource) => Promise<string[]>;
35
36
  export interface ZipFunctionResult {
36
37
  bundler?: NodeBundlerName;
38
+ bundlerReason?: BundlerReason;
37
39
  bundlerErrors?: object[];
38
40
  bundlerWarnings?: object[];
39
41
  config: FunctionConfig;
@@ -64,6 +66,7 @@ export type ZipFunction = (args: {
64
66
  isInternal: boolean;
65
67
  logger: Logger;
66
68
  repositoryRoot?: string;
69
+ span?: Span;
67
70
  } & FunctionSource) => Promise<ZipFunctionResult>;
68
71
  export interface Runtime {
69
72
  findFunctionsInPaths: FindFunctionsInPathsFunction;
@@ -1,2 +1,27 @@
1
1
  import type { FunctionArchive } from '../function.js';
2
- export declare const addArchiveSize: (result: FunctionArchive) => Promise<FunctionArchive>;
2
+ export declare const getArchiveSize: (path: string) => Promise<number | undefined>;
3
+ export declare const addArchiveSize: (result: FunctionArchive) => Promise<{
4
+ size: number | undefined;
5
+ bundler?: import("../main.js").NodeBundlerName;
6
+ bundlerReason?: import("../runtimes/node/bundlers/types.js").BundlerReason;
7
+ bundlerErrors?: object[];
8
+ bundlerWarnings?: object[];
9
+ config: import("../config.js").FunctionConfig;
10
+ displayName?: string;
11
+ generator?: string;
12
+ timeout?: number;
13
+ inputs?: string[];
14
+ includedFiles?: string[];
15
+ invocationMode?: import("../function.js").InvocationMode;
16
+ outputModuleFormat?: import("../main.js").ModuleFormat;
17
+ nativeNodeModules?: object;
18
+ path: string;
19
+ priority?: number;
20
+ trafficRules?: import("../rate_limit.js").TrafficRules;
21
+ runtimeVersion?: string;
22
+ staticAnalysisResult?: import("../runtimes/node/in_source_config/index.js").StaticAnalysisResult;
23
+ entryFilename: string;
24
+ mainFile: string;
25
+ name: string;
26
+ runtime: import("../runtimes/runtime.js").Runtime;
27
+ }>;
@@ -2,11 +2,14 @@ import { promises as fs } from 'fs';
2
2
  import { extname } from 'path';
3
3
  // Returns the input object with an additional `size` property containing the
4
4
  // size of the file at `path` when it is a ZIP archive.
5
- export const addArchiveSize = async (result) => {
6
- const { path } = result;
5
+ export const getArchiveSize = async (path) => {
7
6
  if (extname(path) !== '.zip') {
8
- return result;
7
+ return;
9
8
  }
10
9
  const { size } = await fs.stat(path);
10
+ return size;
11
+ };
12
+ export const addArchiveSize = async (result) => {
13
+ const size = await getArchiveSize(result.path);
11
14
  return { ...result, size };
12
15
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netlify/zip-it-and-ship-it",
3
- "version": "15.0.1",
3
+ "version": "15.1.0",
4
4
  "description": "Zip it and ship it",
5
5
  "main": "./dist/main.js",
6
6
  "type": "module",
@@ -45,6 +45,7 @@
45
45
  "@babel/types": "^7.28.5",
46
46
  "@netlify/binary-info": "^1.0.0",
47
47
  "@netlify/serverless-functions-api": "2.16.0",
48
+ "@opentelemetry/api": "~1.8.0",
48
49
  "@vercel/nft": "0.29.4",
49
50
  "archiver": "^7.0.0",
50
51
  "common-path-prefix": "^3.0.0",
@@ -76,9 +77,10 @@
76
77
  },
77
78
  "devDependencies": {
78
79
  "@netlify/types": "2.7.0",
80
+ "@opentelemetry/sdk-trace-base": "~1.24.0",
79
81
  "@types/archiver": "6.0.4",
80
82
  "@types/is-ci": "3.0.4",
81
- "@types/node": "20.19.33",
83
+ "@types/node": "^22.12.0",
82
84
  "@types/normalize-path": "3.0.2",
83
85
  "@types/resolve": "1.20.6",
84
86
  "@types/semver": "7.7.1",
@@ -100,5 +102,5 @@
100
102
  "engines": {
101
103
  "node": ">=22.12.0"
102
104
  },
103
- "gitHead": "fea99309ebbb7fb595311ccbab6c6a91c4a9eb87"
105
+ "gitHead": "677f1bd6db4429d70ce3d207f00c7d603ae2d1bf"
104
106
  }