@netlify/zip-it-and-ship-it 9.37.1 → 9.37.2

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.
@@ -67,6 +67,7 @@ const zipFunction = async function ({ archiveFormat, basePath, cache, config = {
67
67
  stat,
68
68
  });
69
69
  createPluginsModulesPathAliases(srcFiles, pluginsModulesPath, aliases, finalBasePath);
70
+ const generator = mergedConfig?.generator || getInternalValue(isInternal);
70
71
  const zipPath = await zipNodeJs({
71
72
  aliases,
72
73
  archiveFormat,
@@ -83,6 +84,7 @@ const zipFunction = async function ({ archiveFormat, basePath, cache, config = {
83
84
  rewrites,
84
85
  runtimeAPIVersion,
85
86
  srcFiles,
87
+ generator,
86
88
  });
87
89
  await cleanupFunction?.();
88
90
  // Getting the invocation mode from ISC, in case the function is using the
@@ -105,7 +107,7 @@ const zipFunction = async function ({ archiveFormat, basePath, cache, config = {
105
107
  config: mergedConfig,
106
108
  displayName: mergedConfig?.name,
107
109
  entryFilename: zipPath.entryFilename,
108
- generator: mergedConfig?.generator || getInternalValue(isInternal),
110
+ generator,
109
111
  timeout: mergedConfig?.timeout,
110
112
  inputs,
111
113
  includedFiles,
@@ -7,6 +7,12 @@ export interface EntryFile {
7
7
  contents: string;
8
8
  filename: string;
9
9
  }
10
+ /**
11
+ * A minimal implementation of kebab-case.
12
+ * It is used to transform the generator name into a service name for the telemetry file.
13
+ * As DataDog has a special handling for the service name, we need to make sure it is kebab-case.
14
+ */
15
+ export declare const kebabCase: (input: string) => string;
10
16
  export declare const isNamedLikeEntryFile: (file: string, { basePath, featureFlags, filename, runtimeAPIVersion, }: {
11
17
  basePath: string;
12
18
  featureFlags: FeatureFlags;
@@ -21,7 +27,7 @@ export declare const conflictsWithEntryFile: (srcFiles: string[], { basePath, ex
21
27
  mainFile: string;
22
28
  runtimeAPIVersion: number;
23
29
  }) => boolean;
24
- export declare const getTelemetryFile: () => EntryFile;
30
+ export declare const getTelemetryFile: (generator?: string) => EntryFile;
25
31
  export declare const getEntryFile: ({ commonPrefix, featureFlags, filename, mainFile, moduleFormat, userNamespace, runtimeAPIVersion, }: {
26
32
  commonPrefix: string;
27
33
  featureFlags: FeatureFlags;
@@ -9,6 +9,18 @@ export const ENTRY_FILE_NAME = '___netlify-entry-point';
9
9
  export const BOOTSTRAP_FILE_NAME = '___netlify-bootstrap.mjs';
10
10
  export const TELEMETRY_FILE_NAME = '___netlify-telemetry.mjs';
11
11
  const require = createRequire(import.meta.url);
12
+ /**
13
+ * A minimal implementation of kebab-case.
14
+ * It is used to transform the generator name into a service name for the telemetry file.
15
+ * As DataDog has a special handling for the service name, we need to make sure it is kebab-case.
16
+ */
17
+ export const kebabCase = (input) => input
18
+ .replace(/([a-z])([A-Z])/g, '$1 $2')
19
+ .replace(/[@#//$\s_\\.-]+/g, ' ')
20
+ .trim()
21
+ .toLowerCase()
22
+ .split(' ')
23
+ .join('-');
12
24
  const getEntryFileContents = (mainPath, moduleFormat, featureFlags, runtimeAPIVersion) => {
13
25
  const importPath = `.${mainPath.startsWith('/') ? mainPath : `/${mainPath}`}`;
14
26
  if (runtimeAPIVersion === 2) {
@@ -73,10 +85,32 @@ const getEntryFileName = ({ extension, featureFlags, filename, runtimeAPIVersion
73
85
  }
74
86
  return `${basename(filename, extname(filename))}${extension}`;
75
87
  };
76
- export const getTelemetryFile = () => {
88
+ export const getTelemetryFile = (generator) => {
77
89
  // TODO: switch with import.meta.resolve once we drop support for Node 16.x
78
90
  const filePath = require.resolve('@netlify/serverless-functions-api/instrumentation.js');
79
- const contents = readFileSync(filePath, 'utf8');
91
+ let serviceName;
92
+ let serviceVersion;
93
+ if (generator) {
94
+ // the generator can be something like: `@netlify/plugin-nextjs@14.13.2`
95
+ // following the convention of name@version but it must not have a version.
96
+ // split the generator by the @ sign to separate name and version.
97
+ // pop the last part (the version) and join the rest with a @ again.
98
+ const versionSepPos = generator.lastIndexOf('@');
99
+ if (versionSepPos > 1) {
100
+ const name = generator.substring(0, versionSepPos);
101
+ const version = generator.substring(versionSepPos + 1);
102
+ serviceVersion = version;
103
+ serviceName = kebabCase(name);
104
+ }
105
+ else {
106
+ serviceName = kebabCase(generator);
107
+ }
108
+ }
109
+ const contents = `
110
+ var SERVICE_NAME = ${JSON.stringify(serviceName)};
111
+ var SERVICE_VERSION = ${JSON.stringify(serviceVersion)};
112
+ ${readFileSync(filePath, 'utf8')}
113
+ `;
80
114
  return {
81
115
  contents,
82
116
  filename: TELEMETRY_FILE_NAME,
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,35 @@
1
+ import { test, expect } from 'vitest';
2
+ import { getTelemetryFile, kebabCase } from './entry_file.js';
3
+ test('kebab-case', () => {
4
+ expect(kebabCase('hello-world')).toBe('hello-world');
5
+ expect(kebabCase('hello World')).toBe('hello-world');
6
+ expect(kebabCase('--Hello--World--')).toBe('hello-world');
7
+ expect(kebabCase('Next.js Runtime')).toBe('next-js-runtime');
8
+ expect(kebabCase('@netlify/plugin-nextjs@14')).toBe('netlify-plugin-nextjs-14');
9
+ expect(kebabCase('CamelCaseShould_Be_transformed')).toBe('camel-case-should-be-transformed');
10
+ expect(kebabCase('multiple spaces')).toBe('multiple-spaces');
11
+ });
12
+ test('getTelemetryFile should handle no defined generator', () => {
13
+ const telemetryFile = getTelemetryFile();
14
+ expect(telemetryFile.filename).toBe('___netlify-telemetry.mjs');
15
+ expect(telemetryFile.contents).toContain('var SERVICE_NAME = undefined;');
16
+ expect(telemetryFile.contents).toContain('var SERVICE_VERSION = undefined;');
17
+ });
18
+ test('getTelemetryFile should handle internalFunc generator', () => {
19
+ const telemetryFile = getTelemetryFile('internalFunc');
20
+ expect(telemetryFile.filename).toBe('___netlify-telemetry.mjs');
21
+ expect(telemetryFile.contents).toContain('var SERVICE_NAME = "internal-func";');
22
+ expect(telemetryFile.contents).toContain('var SERVICE_VERSION = undefined;');
23
+ });
24
+ test('getTelemetryFile should handle generator with version', () => {
25
+ const telemetryFile = getTelemetryFile('@netlify/plugin-nextjs@14.13.2');
26
+ expect(telemetryFile.filename).toBe('___netlify-telemetry.mjs');
27
+ expect(telemetryFile.contents).toContain('var SERVICE_NAME = "netlify-plugin-nextjs";');
28
+ expect(telemetryFile.contents).toContain('var SERVICE_VERSION = "14.13.2";');
29
+ });
30
+ test('getTelemetryFile should handle generator without version', () => {
31
+ const telemetryFile = getTelemetryFile('@netlify/plugin-nextjs');
32
+ expect(telemetryFile.filename).toBe('___netlify-telemetry.mjs');
33
+ expect(telemetryFile.contents).toContain('var SERVICE_NAME = "netlify-plugin-nextjs";');
34
+ expect(telemetryFile.contents).toContain('var SERVICE_VERSION = undefined;');
35
+ });
@@ -17,6 +17,7 @@ interface ZipNodeParameters {
17
17
  rewrites?: Map<string, string>;
18
18
  runtimeAPIVersion: number;
19
19
  srcFiles: string[];
20
+ generator?: string;
20
21
  }
21
22
  export declare const zipNodeJs: ({ archiveFormat, ...options }: ZipNodeParameters & {
22
23
  archiveFormat: ArchiveFormat;
@@ -94,7 +94,7 @@ const createDirectory = async function ({ aliases = new Map(), basePath, cache,
94
94
  });
95
95
  return { path: functionFolder, entryFilename };
96
96
  };
97
- const createZipArchive = async function ({ aliases = new Map(), basePath, cache, destFolder, extension, featureFlags, filename, mainFile, moduleFormat, rewrites, runtimeAPIVersion, srcFiles, }) {
97
+ const createZipArchive = async function ({ aliases = new Map(), basePath, cache, destFolder, extension, featureFlags, filename, mainFile, moduleFormat, rewrites, runtimeAPIVersion, srcFiles, generator, }) {
98
98
  const destPath = join(destFolder, `${basename(filename, extension)}.zip`);
99
99
  const { archive, output } = startZip(destPath);
100
100
  // There is a naming conflict with the entry file if one of the supporting
@@ -131,7 +131,7 @@ const createZipArchive = async function ({ aliases = new Map(), basePath, cache,
131
131
  entryFilename = entryFile.filename;
132
132
  addEntryFileToZip(archive, entryFile);
133
133
  }
134
- const telemetryFile = getTelemetryFile();
134
+ const telemetryFile = getTelemetryFile(generator);
135
135
  if (featureFlags.zisi_add_instrumentation_loader === true) {
136
136
  addEntryFileToZip(archive, telemetryFile);
137
137
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netlify/zip-it-and-ship-it",
3
- "version": "9.37.1",
3
+ "version": "9.37.2",
4
4
  "description": "Zip it and ship it",
5
5
  "main": "./dist/main.js",
6
6
  "type": "module",
@@ -44,7 +44,7 @@
44
44
  "@babel/parser": "^7.22.5",
45
45
  "@babel/types": "7.24.6",
46
46
  "@netlify/binary-info": "^1.0.0",
47
- "@netlify/serverless-functions-api": "^1.18.4",
47
+ "@netlify/serverless-functions-api": "^1.18.5",
48
48
  "@vercel/nft": "^0.27.1",
49
49
  "archiver": "^7.0.0",
50
50
  "common-path-prefix": "^3.0.0",
@@ -105,5 +105,5 @@
105
105
  "engines": {
106
106
  "node": "^14.18.0 || >=16.0.0"
107
107
  },
108
- "gitHead": "bcf99673bb311e1e86fe44e8902875328e90cf88"
108
+ "gitHead": "73b6616a85923ed3c436747b5d69353400236a71"
109
109
  }