From b8be0adb586708e7a5451182547d9d2fa277a47d Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Mon, 6 May 2024 13:12:49 +0200 Subject: [PATCH 1/7] feat: add support to ISC parser --- src/runtimes/node/in_source_config/index.ts | 10 ++++++++++ .../unit/runtimes/node/in_source_config.test.ts | 16 ++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/runtimes/node/in_source_config/index.ts b/src/runtimes/node/in_source_config/index.ts index 6def38757..ebb2c1d23 100644 --- a/src/runtimes/node/in_source_config/index.ts +++ b/src/runtimes/node/in_source_config/index.ts @@ -23,6 +23,8 @@ export type ISCValues = { schedule?: string methods?: string[] trafficRules?: TrafficRules + name?: string + generator?: string } export interface StaticAnalysisResult extends ISCValues { @@ -177,6 +179,14 @@ export const parseSource = (source: string, { functionName }: FindISCDeclaration result.schedule = configExport.schedule } + if (typeof configExport.name === 'string') { + result.name = configExport.name + } + + if (typeof configExport.generator === 'string') { + result.generator = configExport.generator + } + if (configExport.method !== undefined) { result.methods = normalizeMethods(configExport.method, functionName) } diff --git a/tests/unit/runtimes/node/in_source_config.test.ts b/tests/unit/runtimes/node/in_source_config.test.ts index 09edc4fb6..0a9d02f7a 100644 --- a/tests/unit/runtimes/node/in_source_config.test.ts +++ b/tests/unit/runtimes/node/in_source_config.test.ts @@ -2,6 +2,7 @@ import { describe, expect, test } from 'vitest' import { parseSource } from '../../../../src/runtimes/node/in_source_config/index.js' import { getLogger } from '../../../../src/utils/logger.js' +import { generate } from 'fast-glob/out/managers/tasks.js' describe('`schedule` helper', () => { const options = { functionName: 'func1', featureFlags: {}, logger: getLogger() } @@ -703,4 +704,19 @@ describe('V2 API', () => { expect(routes).toEqual([{ pattern: '/products', literal: '/products', methods: [], prefer_static: true }]) }) }) + + test('Understands name and generator', () => { + const source = ` + export default async () => new Response("Hello!") + export const config = { name: "foo", generator: "bar@1.2.3" }` + + const isc = parseSource(source, options) + expect(isc).toEqual({ + inputModuleFormat: 'esm', + routes: [], + runtimeAPIVersion: 2, + name: 'foo', + generator: 'bar@1.2.3', + }) + }) }) From cf45f3e73208c679533a950ccf67f53ba5d133ec Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Mon, 6 May 2024 13:19:22 +0200 Subject: [PATCH 2/7] feat: use parsed values --- src/runtimes/node/index.ts | 6 +++--- tests/fixtures-esm/v2-api-with-path/with-literal.mjs | 2 ++ tests/v2api.test.ts | 4 +++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/runtimes/node/index.ts b/src/runtimes/node/index.ts index f6008640d..e9c02c7ad 100644 --- a/src/runtimes/node/index.ts +++ b/src/runtimes/node/index.ts @@ -141,7 +141,7 @@ const zipFunction: ZipFunction = async function ({ invocationMode = INVOCATION_MODE.Background } - const { trafficRules } = staticAnalysisResult + const { trafficRules, generator: staticAnalysisGenerator, name: staticAnalysisName } = staticAnalysisResult const outputModuleFormat = extname(finalMainFile) === MODULE_FILE_EXTENSION.MJS ? MODULE_FORMAT.ESM : MODULE_FORMAT.COMMONJS @@ -151,9 +151,9 @@ const zipFunction: ZipFunction = async function ({ bundler: bundlerName, bundlerWarnings, config, - displayName: config?.name, + displayName: config?.name ?? staticAnalysisName, entryFilename: zipPath.entryFilename, - generator: config?.generator || getInternalValue(isInternal), + generator: config?.generator ?? staticAnalysisGenerator ?? getInternalValue(isInternal), inputs, includedFiles, staticAnalysisResult, diff --git a/tests/fixtures-esm/v2-api-with-path/with-literal.mjs b/tests/fixtures-esm/v2-api-with-path/with-literal.mjs index 55bc537b9..9dee5e8fd 100644 --- a/tests/fixtures-esm/v2-api-with-path/with-literal.mjs +++ b/tests/fixtures-esm/v2-api-with-path/with-literal.mjs @@ -8,4 +8,6 @@ export default async () => export const config = { path: '/products', method: ['GET', 'POST'], + name: 'Product List', + generator: 'foo@1.2.3', } diff --git a/tests/v2api.test.ts b/tests/v2api.test.ts index 4454b8521..dffd29639 100644 --- a/tests/v2api.test.ts +++ b/tests/v2api.test.ts @@ -396,11 +396,13 @@ describe.runIf(semver.gte(nodeVersion, '18.13.0'))('V2 functions API', () => { }, }) - expect.assertions(files.length + 2) + expect.assertions(files.length + 4) for (const file of files) { switch (file.name) { case 'with-literal': + expect(file.generator).toBe("foo@1.2.3") + expect(file.displayName).toBe("Product List") expect(file.routes).toEqual([{ pattern: '/products', literal: '/products', methods: ['GET', 'POST'] }]) break From 4b5cb6973a6ffd22f9be612c4c17cdddd6ba374a Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Mon, 6 May 2024 13:24:38 +0200 Subject: [PATCH 3/7] chore: remove unneeded import --- tests/unit/runtimes/node/in_source_config.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/runtimes/node/in_source_config.test.ts b/tests/unit/runtimes/node/in_source_config.test.ts index 0a9d02f7a..5f7a3d188 100644 --- a/tests/unit/runtimes/node/in_source_config.test.ts +++ b/tests/unit/runtimes/node/in_source_config.test.ts @@ -2,7 +2,6 @@ import { describe, expect, test } from 'vitest' import { parseSource } from '../../../../src/runtimes/node/in_source_config/index.js' import { getLogger } from '../../../../src/utils/logger.js' -import { generate } from 'fast-glob/out/managers/tasks.js' describe('`schedule` helper', () => { const options = { functionName: 'func1', featureFlags: {}, logger: getLogger() } From 347e99f3ace63eb59ca47c591a196b9b1f6bc3f7 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Mon, 6 May 2024 13:25:06 +0200 Subject: [PATCH 4/7] chore: prettier --- tests/v2api.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/v2api.test.ts b/tests/v2api.test.ts index dffd29639..09cd0b77c 100644 --- a/tests/v2api.test.ts +++ b/tests/v2api.test.ts @@ -401,8 +401,8 @@ describe.runIf(semver.gte(nodeVersion, '18.13.0'))('V2 functions API', () => { for (const file of files) { switch (file.name) { case 'with-literal': - expect(file.generator).toBe("foo@1.2.3") - expect(file.displayName).toBe("Product List") + expect(file.generator).toBe('foo@1.2.3') + expect(file.displayName).toBe('Product List') expect(file.routes).toEqual([{ pattern: '/products', literal: '/products', methods: ['GET', 'POST'] }]) break From 14ac467e6b4ae3cff7f805cd01e432d19ea3d4d6 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Tue, 7 May 2024 13:37:30 +0200 Subject: [PATCH 5/7] fix: flip precedence and extract to own test --- src/runtimes/node/index.ts | 4 +-- .../.netlify/functions-internal/server.json | 7 +++++ .../.netlify/functions-internal/server.mjs | 6 +++++ .../v2-api-with-path/with-literal.mjs | 2 -- tests/v2api.test.ts | 26 ++++++++++++++++--- 5 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 tests/fixtures-esm/v2-api-name-generator/.netlify/functions-internal/server.json create mode 100644 tests/fixtures-esm/v2-api-name-generator/.netlify/functions-internal/server.mjs diff --git a/src/runtimes/node/index.ts b/src/runtimes/node/index.ts index e9c02c7ad..0b2e79e70 100644 --- a/src/runtimes/node/index.ts +++ b/src/runtimes/node/index.ts @@ -151,9 +151,9 @@ const zipFunction: ZipFunction = async function ({ bundler: bundlerName, bundlerWarnings, config, - displayName: config?.name ?? staticAnalysisName, + displayName: staticAnalysisName ?? config?.name, entryFilename: zipPath.entryFilename, - generator: config?.generator ?? staticAnalysisGenerator ?? getInternalValue(isInternal), + generator: staticAnalysisGenerator ?? config?.generator ?? getInternalValue(isInternal), inputs, includedFiles, staticAnalysisResult, diff --git a/tests/fixtures-esm/v2-api-name-generator/.netlify/functions-internal/server.json b/tests/fixtures-esm/v2-api-name-generator/.netlify/functions-internal/server.json new file mode 100644 index 000000000..12f3a216b --- /dev/null +++ b/tests/fixtures-esm/v2-api-name-generator/.netlify/functions-internal/server.json @@ -0,0 +1,7 @@ +{ + "config": { + "name": "should not be respected, ISC takes precedence", + "generator": "should not be respected, ISC takes precedence" + }, + "version": 1 +} \ No newline at end of file diff --git a/tests/fixtures-esm/v2-api-name-generator/.netlify/functions-internal/server.mjs b/tests/fixtures-esm/v2-api-name-generator/.netlify/functions-internal/server.mjs new file mode 100644 index 000000000..ce36dc12c --- /dev/null +++ b/tests/fixtures-esm/v2-api-name-generator/.netlify/functions-internal/server.mjs @@ -0,0 +1,6 @@ +export default () => new Response("hello world") + +export const config = { + name: 'SSR Function', + generator: 'next-runtime@1.2.3', +} diff --git a/tests/fixtures-esm/v2-api-with-path/with-literal.mjs b/tests/fixtures-esm/v2-api-with-path/with-literal.mjs index 9dee5e8fd..55bc537b9 100644 --- a/tests/fixtures-esm/v2-api-with-path/with-literal.mjs +++ b/tests/fixtures-esm/v2-api-with-path/with-literal.mjs @@ -8,6 +8,4 @@ export default async () => export const config = { path: '/products', method: ['GET', 'POST'], - name: 'Product List', - generator: 'foo@1.2.3', } diff --git a/tests/v2api.test.ts b/tests/v2api.test.ts index 09cd0b77c..66910e41b 100644 --- a/tests/v2api.test.ts +++ b/tests/v2api.test.ts @@ -396,13 +396,11 @@ describe.runIf(semver.gte(nodeVersion, '18.13.0'))('V2 functions API', () => { }, }) - expect.assertions(files.length + 4) + expect.assertions(files.length + 2) for (const file of files) { switch (file.name) { case 'with-literal': - expect(file.generator).toBe('foo@1.2.3') - expect(file.displayName).toBe('Product List') expect(file.routes).toEqual([{ pattern: '/products', literal: '/products', methods: ['GET', 'POST'] }]) break @@ -530,4 +528,26 @@ describe.runIf(semver.gte(nodeVersion, '18.13.0'))('V2 functions API', () => { expect(body).toBe('foo!bar') }) }) + + test('Name and Generator are taken from ISC and take precedence over deploy config', async () => { + const { path: tmpDir } = await getTmpDir({ prefix: 'zip-it-test' }) + const manifestPath = join(tmpDir, 'manifest.json') + + const fixtureName = 'v2-api-name-generator' + const pathInternal = join(fixtureName, '.netlify', 'functions-internal') + + const { + files: [func], + } = await zipFixture(pathInternal, { + fixtureDir: FIXTURES_ESM_DIR, + length: 1, + opts: { + manifest: manifestPath, + configFileDirectories: [join(FIXTURES_ESM_DIR, fixtureName)], + }, + }) + + expect(func.displayName).toBe('SSR Function') + expect(func.generator).toBe('next-runtime@1.2.3') + }) }) From f6af1d6553fc366cdb5f34e379a2f513c4689250 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Tue, 7 May 2024 13:37:56 +0200 Subject: [PATCH 6/7] fix: fmt --- .../.netlify/functions-internal/server.json | 2 +- .../.netlify/functions-internal/server.mjs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fixtures-esm/v2-api-name-generator/.netlify/functions-internal/server.json b/tests/fixtures-esm/v2-api-name-generator/.netlify/functions-internal/server.json index 12f3a216b..27f7bfdc7 100644 --- a/tests/fixtures-esm/v2-api-name-generator/.netlify/functions-internal/server.json +++ b/tests/fixtures-esm/v2-api-name-generator/.netlify/functions-internal/server.json @@ -4,4 +4,4 @@ "generator": "should not be respected, ISC takes precedence" }, "version": 1 -} \ No newline at end of file +} diff --git a/tests/fixtures-esm/v2-api-name-generator/.netlify/functions-internal/server.mjs b/tests/fixtures-esm/v2-api-name-generator/.netlify/functions-internal/server.mjs index ce36dc12c..fd82de5f8 100644 --- a/tests/fixtures-esm/v2-api-name-generator/.netlify/functions-internal/server.mjs +++ b/tests/fixtures-esm/v2-api-name-generator/.netlify/functions-internal/server.mjs @@ -1,4 +1,4 @@ -export default () => new Response("hello world") +export default () => new Response('hello world') export const config = { name: 'SSR Function', From 530bdc7c5ccf1da9805af097bb89fdad019ac3ab Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Tue, 7 May 2024 14:47:59 +0200 Subject: [PATCH 7/7] fix: switch back to logical or --- src/runtimes/node/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtimes/node/index.ts b/src/runtimes/node/index.ts index 0b2e79e70..286ba3fa4 100644 --- a/src/runtimes/node/index.ts +++ b/src/runtimes/node/index.ts @@ -151,9 +151,9 @@ const zipFunction: ZipFunction = async function ({ bundler: bundlerName, bundlerWarnings, config, - displayName: staticAnalysisName ?? config?.name, + displayName: staticAnalysisName || config?.name, entryFilename: zipPath.entryFilename, - generator: staticAnalysisGenerator ?? config?.generator ?? getInternalValue(isInternal), + generator: staticAnalysisGenerator || config?.generator || getInternalValue(isInternal), inputs, includedFiles, staticAnalysisResult,