Skip to content

Commit 334152c

Browse files
authoredMay 15, 2024··
fix: bug around v1 functions with nodeModuleFormat: "esm" (#6557)
* fix: support .mjs functions * refactor: fix some types * refactor: use manifest instead of readdir * fix: replace string concatenation * chore: write test for ntl:serve * chore: prettier
1 parent 79732ad commit 334152c

File tree

3 files changed

+70
-4
lines changed

3 files changed

+70
-4
lines changed
 

‎src/lib/functions/registry.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ export class FunctionsRegistry {
434434

435435
func.mainFile = v2EntryPointPath
436436
} catch {
437-
func.mainFile = join(unzippedDirectory, `${func.name}.js`)
437+
func.mainFile = join(unzippedDirectory, basename(manifestEntry.mainFile))
438438
}
439439
} else {
440440
this.buildFunctionAndWatchFiles(func, !isReload)

‎src/lib/functions/runtimes/js/index.ts

+16-3
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import { Worker } from 'worker_threads'
66
import lambdaLocal from 'lambda-local'
77

88
import { BLOBS_CONTEXT_VARIABLE } from '../../../blobs/blobs.js'
9+
import type NetlifyFunction from '../../netlify-function.js'
910

1011
import detectNetlifyLambdaBuilder from './builders/netlify-lambda.js'
1112
import detectZisiBuilder, { parseFunctionForMetadata } from './builders/zisi.js'
1213
import { SECONDS_TO_MILLISECONDS } from './constants.js'
14+
import { $TSFixMe } from '../../../../commands/types.js'
1315

1416
export const name = 'js'
1517

@@ -99,11 +101,21 @@ export const invokeFunction = async ({ context, environment, event, func, timeou
99101
})
100102
}
101103

102-
// @ts-expect-error TS(7031) FIXME: Binding element 'context' implicitly has an 'any' ... Remove this comment to see the full error message
103-
export const invokeFunctionDirectly = async ({ context, event, func, timeout }) => {
104+
export const invokeFunctionDirectly = async ({
105+
context,
106+
event,
107+
func,
108+
timeout,
109+
}: {
110+
context: $TSFixMe
111+
event: $TSFixMe
112+
func: NetlifyFunction
113+
timeout: number
114+
}) => {
104115
// If a function builder has defined a `buildPath` property, we use it.
105116
// Otherwise, we'll invoke the function's main file.
106-
const lambdaPath = func.buildData?.buildPath ?? func.mainFile
117+
const { buildPath } = await func.getBuildData()
118+
const lambdaPath = buildPath ?? func.mainFile
107119
const result = await lambdaLocal.execute({
108120
clientContext: JSON.stringify(context),
109121
environment: {
@@ -118,6 +130,7 @@ export const invokeFunctionDirectly = async ({ context, event, func, timeout })
118130
lambdaPath,
119131
timeoutMs: timeout * SECONDS_TO_MILLISECONDS,
120132
verboseLevel: 3,
133+
esm: lambdaPath.endsWith('.mjs'),
121134
})
122135

123136
return result
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { test } from 'vitest'
2+
3+
import { withDevServer } from '../../utils/dev-server'
4+
import { withSiteBuilder } from '../../utils/site-builder'
5+
6+
test('nodeModuleFormat: esm v1 functions should work', async (t) => {
7+
await withSiteBuilder(t, async (builder) => {
8+
await builder
9+
.withNetlifyToml({
10+
config: {
11+
plugins: [{ package: './plugins/setup-functions' }],
12+
},
13+
})
14+
.withBuildPlugin({
15+
name: 'setup-functions',
16+
plugin: {
17+
onBuild: async () => {
18+
// eslint-disable-next-line @typescript-eslint/no-var-requires, n/global-require
19+
const { mkdir, writeFile } = require('node:fs/promises')
20+
await mkdir('.netlify/functions-internal', { recursive: true })
21+
await writeFile(
22+
'.netlify/functions-internal/server.json',
23+
JSON.stringify({
24+
config: {
25+
nodeModuleFormat: 'esm',
26+
},
27+
version: 1,
28+
}),
29+
)
30+
31+
await writeFile(
32+
'.netlify/functions-internal/server.mjs',
33+
`
34+
export async function handler(event, context) {
35+
return {
36+
statusCode: 200,
37+
body: "This is an internal function.",
38+
};
39+
}
40+
`,
41+
)
42+
},
43+
},
44+
})
45+
.build()
46+
47+
await withDevServer({ cwd: builder.directory, serve: true }, async (server) => {
48+
const response = await fetch(new URL('/.netlify/functions/server', server.url))
49+
t.expect(await response.text()).toBe('This is an internal function.')
50+
t.expect(response.status).toBe(200)
51+
})
52+
})
53+
})

2 commit comments

Comments
 (2)

github-actions[bot] commented on May 15, 2024

@github-actions[bot]

📊 Benchmark results

  • Dependency count: 1,341
  • Package size: 311 MB
  • Number of ts-expect-error directives: 992

github-actions[bot] commented on May 15, 2024

@github-actions[bot]

📊 Benchmark results

  • Dependency count: 1,341
  • Package size: 311 MB
  • Number of ts-expect-error directives: 992
Please sign in to comment.