Skip to content

Commit a6c39fc

Browse files
author
Lukas Holzer
committed
fix: use new version of serverless functions api
provide the service name and version as variables to it.
1 parent 1b70920 commit a6c39fc

File tree

5 files changed

+82
-6
lines changed

5 files changed

+82
-6
lines changed

packages/zip-it-and-ship-it/src/runtimes/node/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ const zipFunction: ZipFunction = async function ({
108108

109109
createPluginsModulesPathAliases(srcFiles, pluginsModulesPath, aliases, finalBasePath)
110110

111+
const generator = mergedConfig?.generator || getInternalValue(isInternal)
111112
const zipPath = await zipNodeJs({
112113
aliases,
113114
archiveFormat,
@@ -124,6 +125,7 @@ const zipFunction: ZipFunction = async function ({
124125
rewrites,
125126
runtimeAPIVersion,
126127
srcFiles,
128+
generator,
127129
})
128130

129131
await cleanupFunction?.()
@@ -153,7 +155,7 @@ const zipFunction: ZipFunction = async function ({
153155
config: mergedConfig,
154156
displayName: mergedConfig?.name,
155157
entryFilename: zipPath.entryFilename,
156-
generator: mergedConfig?.generator || getInternalValue(isInternal),
158+
generator,
157159
timeout: mergedConfig?.timeout,
158160
inputs,
159161
includedFiles,
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { test, expect } from 'vitest'
2+
3+
import { getTelemetryFile, kebabCase } from './entry_file.js'
4+
5+
test('kebab-case', () => {
6+
expect(kebabCase('hello-world')).toBe('hello-world')
7+
expect(kebabCase('hello World')).toBe('hello-world')
8+
expect(kebabCase('--Hello--World--')).toBe('hello-world')
9+
expect(kebabCase('Next.js Runtime')).toBe('next-js-runtime')
10+
expect(kebabCase('@netlify/plugin-nextjs@14')).toBe('netlify-plugin-nextjs-14')
11+
expect(kebabCase('CamelCaseShould_Be_transformed')).toBe('camel-case-should-be-transformed')
12+
expect(kebabCase('multiple spaces')).toBe('multiple-spaces')
13+
})
14+
15+
test('getTelemetryFile should handle no defined generator', () => {
16+
const telemetryFile = getTelemetryFile()
17+
expect(telemetryFile.filename).toBe('___netlify-telemetry.mjs')
18+
expect(telemetryFile.contents).toContain('var SERVICE_NAME = undefined;')
19+
expect(telemetryFile.contents).toContain('var SERVICE_VERSION = undefined;')
20+
})
21+
22+
test('getTelemetryFile should handle internalFunc generator', () => {
23+
const telemetryFile = getTelemetryFile('internalFunc')
24+
expect(telemetryFile.filename).toBe('___netlify-telemetry.mjs')
25+
expect(telemetryFile.contents).toContain('var SERVICE_NAME = "internal-func";')
26+
expect(telemetryFile.contents).toContain('var SERVICE_VERSION = undefined;')
27+
})
28+
29+
test('getTelemetryFile should handle generator with version', () => {
30+
const telemetryFile = getTelemetryFile('@netlify/[email protected]')
31+
expect(telemetryFile.filename).toBe('___netlify-telemetry.mjs')
32+
expect(telemetryFile.contents).toContain('var SERVICE_NAME = "netlify-plugin-nextjs";')
33+
expect(telemetryFile.contents).toContain('var SERVICE_VERSION = "14.13.2";')
34+
})

packages/zip-it-and-ship-it/src/runtimes/node/utils/entry_file.ts

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,20 @@ export interface EntryFile {
2626
filename: string
2727
}
2828

29+
/**
30+
* A minimal implementation of kebab-case.
31+
* It is used to transform the generator name into a service name for the telemetry file.
32+
* As DataDog has a special handling for the service name, we need to make sure it is kebab-case.
33+
*/
34+
export const kebabCase = (input: string): string =>
35+
input
36+
.replace(/([a-z])([A-Z])/g, '$1 $2')
37+
.replace(/[@#//$\s_\\.-]+/g, ' ')
38+
.trim()
39+
.toLowerCase()
40+
.split(' ')
41+
.join('-')
42+
2943
const getEntryFileContents = (
3044
mainPath: string,
3145
moduleFormat: string,
@@ -158,10 +172,31 @@ const getEntryFileName = ({
158172
return `${basename(filename, extname(filename))}${extension}`
159173
}
160174

161-
export const getTelemetryFile = (): EntryFile => {
175+
export const getTelemetryFile = (generator?: string): EntryFile => {
162176
// TODO: switch with import.meta.resolve once we drop support for Node 16.x
163177
const filePath = require.resolve('@netlify/serverless-functions-api/instrumentation.js')
164-
const contents = readFileSync(filePath, 'utf8')
178+
let serviceName: string | undefined
179+
let serviceVersion: string | undefined
180+
181+
if (generator) {
182+
// the generator can be something like: `@netlify/[email protected]`
183+
// following the convention of name@version but it must not have a version.
184+
// split the generator by the @ sign to seperate name and version.
185+
// pop the last part (the version) and join the rest with a @ again.
186+
const parts = generator.split('@')
187+
if (parts.length > 1) {
188+
serviceVersion = parts.pop()
189+
serviceName = kebabCase(parts.join('@'))
190+
} else {
191+
serviceName = kebabCase(parts[0])
192+
}
193+
}
194+
195+
const contents = `
196+
var SERVICE_NAME = ${JSON.stringify(serviceName)};
197+
var SERVICE_VERSION = ${JSON.stringify(serviceVersion)};
198+
${readFileSync(filePath, 'utf8')}
199+
`
165200

166201
return {
167202
contents,

packages/zip-it-and-ship-it/src/runtimes/node/utils/zip.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ interface ZipNodeParameters {
5454
rewrites?: Map<string, string>
5555
runtimeAPIVersion: number
5656
srcFiles: string[]
57+
generator?: string
5758
}
5859

5960
const addBootstrapFile = function (srcFiles: string[], aliases: Map<string, string>) {
@@ -188,6 +189,7 @@ const createZipArchive = async function ({
188189
rewrites,
189190
runtimeAPIVersion,
190191
srcFiles,
192+
generator,
191193
}: ZipNodeParameters) {
192194
const destPath = join(destFolder, `${basename(filename, extension)}.zip`)
193195
const { archive, output } = startZip(destPath)
@@ -233,7 +235,7 @@ const createZipArchive = async function ({
233235

234236
addEntryFileToZip(archive, entryFile)
235237
}
236-
const telemetryFile = getTelemetryFile()
238+
const telemetryFile = getTelemetryFile(generator)
237239

238240
if (featureFlags.zisi_add_instrumentation_loader === true) {
239241
addEntryFileToZip(archive, telemetryFile)
@@ -268,7 +270,10 @@ const createZipArchive = async function ({
268270
export const zipNodeJs = function ({
269271
archiveFormat,
270272
...options
271-
}: ZipNodeParameters & { archiveFormat: ArchiveFormat }): Promise<{ path: string; entryFilename: string }> {
273+
}: ZipNodeParameters & { archiveFormat: ArchiveFormat }): Promise<{
274+
path: string
275+
entryFilename: string
276+
}> {
272277
if (archiveFormat === ARCHIVE_FORMAT.ZIP) {
273278
return createZipArchive(options)
274279
}

packages/zip-it-and-ship-it/vitest.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { defineConfig } from 'vitest/config'
55
export default defineConfig({
66
test: {
77
setupFiles: ['./tests/helpers/vitest_setup.ts'],
8-
include: ['tests/**/*.test.ts'],
8+
include: ['tests/**/*.test.ts', 'src/**/*.test.ts'],
99
testTimeout: 90_000,
1010
deps: {
1111
// Disable vitest handling of imports to these paths, especially the tmpdir is important as we extract functions to there

0 commit comments

Comments
 (0)