Skip to content

Commit 0666593

Browse files
fix: fix edge functions workers (#298)
* fix: fix edge functions workers * chore: downgrade execa * chore: update lock file * chore: add Deno to CI steps * chore: format * refactor: remote `bootstrapURL` param * chore: lint-ignore file
1 parent e6d53e1 commit 0666593

File tree

15 files changed

+86
-30
lines changed

15 files changed

+86
-30
lines changed

.github/workflows/lint.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ jobs:
2222
node-version: lts/*
2323
cache: 'npm'
2424

25+
- name: Setup Deno
26+
uses: denoland/setup-deno@v1
27+
with:
28+
deno-version: 2.2.4
29+
2530
- name: Install dependencies
2631
run: npm ci --no-audit
2732

.github/workflows/publint.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ jobs:
2222
with:
2323
node-version: lts/*
2424
cache: 'npm'
25+
- name: Setup Deno
26+
uses: denoland/setup-deno@v1
27+
with:
28+
deno-version: 2.2.4
2529
- name: Install dependencies
2630
run: npm ci
2731
- name: Build

eslint.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export default tseslint.config(
3030

3131
// TODO: Move this to `edge-functions` package.
3232
{
33-
ignores: ['packages/**/deno'],
33+
ignores: ['packages/**/deno', 'packages/edge-functions/bootstrap-bundle.mjs'],
3434
},
3535

3636
// JavaScript-specific rules

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/edge-functions/.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
dist
2-
dist-dev
2+
dist-dev
3+
dev/deno/bootstrap.mjs
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import * as esbuild from 'npm:esbuild'
2+
import { denoPlugins } from 'jsr:@luca/esbuild-deno-loader@^0.11.1'
3+
4+
const [entryPoint, outfile] = Deno.args
5+
6+
await esbuild.build({
7+
bundle: true,
8+
entryPoints: [entryPoint],
9+
format: 'esm',
10+
minify: true,
11+
outfile,
12+
plugins: denoPlugins(),
13+
})
14+
15+
await esbuild.stop()

packages/edge-functions/dev/deno/invoke.mjs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// @ts-check
22

33
/**
4-
* @typedef {import('./workers/types.js').Message} Message
4+
* @typedef {import('./workers/types.ts').Message} Message
55
*/
66

77
/**
@@ -10,11 +10,10 @@
1010
* construct a `Response`.
1111
*
1212
* @param {Request} req
13-
* @param {string} bootstrapURL
1413
* @param {Record<string, string>} functions
1514
* @param {number} requestTimeout
1615
*/
17-
export function invoke(req, bootstrapURL, functions, requestTimeout) {
16+
export function invoke(req, functions, requestTimeout) {
1817
return new Promise((resolve, reject) => {
1918
const worker = new Worker(new URL('./workers/runner.mjs', import.meta.url).href, {
2019
type: 'module',
@@ -43,7 +42,6 @@ export function invoke(req, bootstrapURL, functions, requestTimeout) {
4342
type: 'request',
4443
data: {
4544
body: await req.arrayBuffer(),
46-
bootstrapURL,
4745
functions,
4846
headers: Object.fromEntries(req.headers.entries()),
4947
method: req.method,

packages/edge-functions/dev/deno/server.mjs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { invoke } from './invoke.mjs'
1515
*
1616
* @param {RunOptions} options
1717
*/
18-
export const serveLocal = ({ bootstrapURL, denoPort: port, requestTimeout }) => {
18+
export const serveLocal = ({ denoPort: port, requestTimeout }) => {
1919
const serveOptions = {
2020
// Adding a no-op listener to avoid the default one, which prints a message
2121
// we don't want.
@@ -37,11 +37,11 @@ export const serveLocal = ({ bootstrapURL, denoPort: port, requestTimeout }) =>
3737
// the Deno server take a list of functions, import them, and return their
3838
// configs.
3939
if (method === 'NETLIFYCONFIG') {
40+
const functionsParam = url.searchParams.get('functions')
41+
4042
// This is the list of all the functions found in the project.
4143
/** @type {Record<string, string>} */
42-
const availableFunctions = url.searchParams.has('functions')
43-
? JSON.parse(decodeURIComponent(url.searchParams.get('functions')))
44-
: {}
44+
const availableFunctions = functionsParam ? JSON.parse(decodeURIComponent(functionsParam)) : {}
4545

4646
functions = availableFunctions
4747

@@ -59,7 +59,7 @@ export const serveLocal = ({ bootstrapURL, denoPort: port, requestTimeout }) =>
5959
}
6060

6161
try {
62-
return await invoke(request, bootstrapURL, functions, requestTimeout)
62+
return await invoke(request, functions, requestTimeout)
6363
} catch (error) {
6464
return getErrorResponse(error)
6565
}

packages/edge-functions/dev/deno/workers/config.mjs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
// @ts-check
2+
/// <reference lib="deno.worker" />
23

34
/**
45
* @typedef {import('../../shared/types.ts').SerializedError} SerializedError
5-
* @typedef {import('./types.js').ConfigResponseMessage} ConfigResponseMessage
6+
* @typedef {import('./types.ts').ConfigResponseMessage} ConfigResponseMessage
67
* @typedef {import('./types.ts').Message} Message
78
*/
89

9-
self.onmessage = async (e) => {
10+
/** @type {DedicatedWorkerGlobalScope} */
11+
// @ts-ignore We are inside a worker, so the global scope is `DedicatedWorkerGlobalScope`.
12+
const worker = globalThis
13+
14+
worker.addEventListener('message', async (e) => {
1015
const message = /** @type {Message} */ (e.data)
1116

1217
if (message.type === 'configRequest') {
@@ -38,10 +43,10 @@ self.onmessage = async (e) => {
3843

3944
await Promise.allSettled(imports)
4045

41-
self.postMessage(/** @type {ConfigResponseMessage} */ ({ type: 'configResponse', data: { configs, errors } }))
46+
worker.postMessage(/** @type {ConfigResponseMessage} */ ({ type: 'configResponse', data: { configs, errors } }))
4247

4348
return
4449
}
4550

4651
throw new Error('Unsupported message')
47-
}
52+
})

packages/edge-functions/dev/deno/workers/runner.mjs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
// @ts-check
2+
/// <reference lib="deno.worker" />
3+
import { handleRequest } from '../bootstrap.mjs'
24

35
/**
4-
* @typedef {import('./types.js').Message} Message
5-
* @typedef {import('./types.js').RunResponseStartMessage} RunResponseStartMessage
6-
* @typedef {import('./types.js').RunResponseChunkMessage} RunResponseChunkMessage
7-
* @typedef {import('./types.js').RunResponseEndMessage} RunResponseEndMessage
6+
* @typedef {import('./types.ts').Message} Message
7+
* @typedef {import('./types.ts').RunResponseStartMessage} RunResponseStartMessage
8+
* @typedef {import('./types.ts').RunResponseChunkMessage} RunResponseChunkMessage
9+
* @typedef {import('./types.ts').RunResponseEndMessage} RunResponseEndMessage
810
*/
911

1012
const consoleLog = globalThis.console.log
1113
/** @type {Map<string, string>} */
1214
const fetchRewrites = new Map()
1315

14-
self.onmessage = async (e) => {
16+
/** @type {DedicatedWorkerGlobalScope} */
17+
// @ts-ignore We are inside a worker, so the global scope is `DedicatedWorkerGlobalScope`.
18+
const worker = globalThis
19+
20+
worker.addEventListener('message', async (e) => {
1521
const message = /** @type {Message} */ (e.data)
1622

1723
if (message.type === 'request') {
18-
const { handleRequest } = await import(message.data.bootstrapURL)
1924
const body = message.data.method === 'GET' || message.data.method === 'HEAD' ? undefined : message.data.body
2025
const req = new Request(message.data.url, {
2126
body,
@@ -35,12 +40,14 @@ self.onmessage = async (e) => {
3540
await Promise.allSettled(imports)
3641

3742
const res = await handleRequest(req, functions, {
43+
// @ts-ignore TODO: Figure out why `fetchRewrites` is not being picked up
44+
// as part of the type.
3845
fetchRewrites,
3946
rawLogger: consoleLog,
4047
requestTimeout: message.data.timeout,
4148
})
4249

43-
self.postMessage(
50+
worker.postMessage(
4451
/** @type {RunResponseStartMessage} */ ({
4552
type: 'responseStart',
4653
data: {
@@ -58,7 +65,8 @@ self.onmessage = async (e) => {
5865
break
5966
}
6067

61-
self.postMessage(
68+
// @ts-expect-error TODO: Figure out type mismatch.
69+
worker.postMessage(
6270
/** @type {RunResponseChunkMessage} */ ({
6371
type: 'responseChunk',
6472
data: { chunk: value },
@@ -68,10 +76,10 @@ self.onmessage = async (e) => {
6876
}
6977
}
7078

71-
self.postMessage(/** @type {RunResponseEndMessage} */ ({ type: 'responseEnd' }))
79+
worker.postMessage(/** @type {RunResponseEndMessage} */ ({ type: 'responseEnd' }))
7280

7381
return
7482
}
7583

7684
throw new Error('Unsupported message')
77-
}
85+
})

0 commit comments

Comments
 (0)