@netlify/edge-bundler 3.0.0 → 3.1.0
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.
- package/dist/node/bundler.test.js +2 -2
- package/dist/node/config.js +1 -0
- package/dist/node/config.test.js +3 -3
- package/dist/node/formats/javascript.js +2 -2
- package/dist/node/server/server.d.ts +6 -1
- package/dist/node/server/server.js +12 -4
- package/dist/node/{serving.test.d.ts → server/server.test.d.ts} +0 -0
- package/dist/node/server/server.test.js +41 -0
- package/dist/node/stage_2.test.js +2 -2
- package/package.json +4 -4
- package/dist/node/serving.test.js +0 -31
|
@@ -2,7 +2,7 @@ import { promises as fs } from 'fs';
|
|
|
2
2
|
import { join, resolve } from 'path';
|
|
3
3
|
import process from 'process';
|
|
4
4
|
import { pathToFileURL } from 'url';
|
|
5
|
-
import
|
|
5
|
+
import { deleteAsync } from 'del';
|
|
6
6
|
import tmp from 'tmp-promise';
|
|
7
7
|
import { test, expect } from 'vitest';
|
|
8
8
|
import { fixturesDir } from '../test/util.js';
|
|
@@ -277,5 +277,5 @@ test('Ignores any user-defined `deno.json` files', async () => {
|
|
|
277
277
|
},
|
|
278
278
|
],
|
|
279
279
|
})).not.toThrow();
|
|
280
|
-
await
|
|
280
|
+
await deleteAsync([tmpDir.path, denoConfigPath, importMapFile.path], { force: true });
|
|
281
281
|
});
|
package/dist/node/config.js
CHANGED
|
@@ -34,6 +34,7 @@ export const getFunctionConfig = async (func, importMap, deno, log) => {
|
|
|
34
34
|
// the exit code to know exactly what happened and guide people accordingly.
|
|
35
35
|
const { exitCode, stderr, stdout } = await deno.run([
|
|
36
36
|
'run',
|
|
37
|
+
'--allow-env',
|
|
37
38
|
'--allow-net',
|
|
38
39
|
'--allow-read',
|
|
39
40
|
`--allow-write=${collector.path}`,
|
package/dist/node/config.test.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { promises as fs } from 'fs';
|
|
2
2
|
import { join, resolve } from 'path';
|
|
3
3
|
import { pathToFileURL } from 'url';
|
|
4
|
-
import
|
|
4
|
+
import { deleteAsync } from 'del';
|
|
5
5
|
import { stub } from 'sinon';
|
|
6
6
|
import tmp from 'tmp-promise';
|
|
7
7
|
import { test, expect } from 'vitest';
|
|
@@ -66,7 +66,7 @@ test('`getFunctionConfig` extracts configuration properties from function file',
|
|
|
66
66
|
name: 'func5',
|
|
67
67
|
source: `
|
|
68
68
|
export default async () => new Response("Hello from function two")
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
export const config = () => {
|
|
71
71
|
throw new Error('uh-oh')
|
|
72
72
|
}
|
|
@@ -118,7 +118,7 @@ test('`getFunctionConfig` extracts configuration properties from function file',
|
|
|
118
118
|
expect(logger.user.callCount).toBe(0);
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
|
-
await
|
|
121
|
+
await deleteAsync(tmpDir, { force: true });
|
|
122
122
|
});
|
|
123
123
|
test('Ignores function paths from the in-source `config` function if the feature flag is off', async () => {
|
|
124
124
|
const userDirectory = resolve(fixturesDir, 'with_config', 'netlify', 'edge-functions');
|
|
@@ -2,7 +2,7 @@ import { promises as fs } from 'fs';
|
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { env } from 'process';
|
|
4
4
|
import { pathToFileURL } from 'url';
|
|
5
|
-
import
|
|
5
|
+
import { deleteAsync } from 'del';
|
|
6
6
|
import { wrapBundleError } from '../bundle_error.js';
|
|
7
7
|
import { getFileHash } from '../utils/sha256.js';
|
|
8
8
|
const BOOTSTRAP_LATEST = 'https://633ac6453c579c0008ede8d8--edge.netlify.com/bootstrap/index-combined.ts';
|
|
@@ -27,7 +27,7 @@ const bundleJS = async ({ buildID, debug, deno, distDirectory, functions, import
|
|
|
27
27
|
const defaultFormatExportTypeError = (name) => `The Edge Function "${name}" has failed to load. Does it have a function as the default export?`;
|
|
28
28
|
const defaultFormatImpoortError = (name) => `There was an error with Edge Function "${name}".`;
|
|
29
29
|
const generateStage2 = async ({ distDirectory, fileName, formatExportTypeError, formatImportError, functions, type = 'production', }) => {
|
|
30
|
-
await
|
|
30
|
+
await deleteAsync(distDirectory, { force: true });
|
|
31
31
|
await fs.mkdir(distDirectory, { recursive: true });
|
|
32
32
|
const entryPoint = type === 'local'
|
|
33
33
|
? getLocalEntryPoint(functions, { formatExportTypeError, formatImportError })
|
|
@@ -4,10 +4,14 @@
|
|
|
4
4
|
/// <reference types="node" />
|
|
5
5
|
/// <reference types="node" />
|
|
6
6
|
import { OnAfterDownloadHook, OnBeforeDownloadHook } from '../bridge.js';
|
|
7
|
+
import { FunctionConfig } from '../config.js';
|
|
7
8
|
import type { EdgeFunction } from '../edge_function.js';
|
|
8
9
|
import { ImportMapFile } from '../import_map.js';
|
|
9
10
|
import { LogFunction } from '../logger.js';
|
|
10
11
|
declare type FormatFunction = (name: string) => string;
|
|
12
|
+
interface StartServerOptions {
|
|
13
|
+
getFunctionsConfig?: boolean;
|
|
14
|
+
}
|
|
11
15
|
interface InspectSettings {
|
|
12
16
|
enabled: boolean;
|
|
13
17
|
pause: boolean;
|
|
@@ -26,7 +30,8 @@ interface ServeOptions {
|
|
|
26
30
|
port: number;
|
|
27
31
|
systemLogger?: LogFunction;
|
|
28
32
|
}
|
|
29
|
-
declare const serve: ({ certificatePath, debug, distImportMapPath, inspectSettings, formatExportTypeError, formatImportError, importMaps, onAfterDownload, onBeforeDownload, port, systemLogger, }: ServeOptions) => Promise<(
|
|
33
|
+
declare const serve: ({ certificatePath, debug, distImportMapPath, inspectSettings, formatExportTypeError, formatImportError, importMaps, onAfterDownload, onBeforeDownload, port, systemLogger, }: ServeOptions) => Promise<(functions: EdgeFunction[], env?: NodeJS.ProcessEnv, options?: StartServerOptions) => Promise<{
|
|
34
|
+
functionsConfig: FunctionConfig[];
|
|
30
35
|
graph: any;
|
|
31
36
|
success: boolean;
|
|
32
37
|
}>>;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { tmpName } from 'tmp-promise';
|
|
2
2
|
import { DenoBridge } from '../bridge.js';
|
|
3
|
+
import { getFunctionConfig } from '../config.js';
|
|
3
4
|
import { generateStage2 } from '../formats/javascript.js';
|
|
4
5
|
import { ImportMap } from '../import_map.js';
|
|
5
6
|
import { getLogger } from '../logger.js';
|
|
6
7
|
import { ensureLatestTypes } from '../types.js';
|
|
7
8
|
import { killProcess, waitForServer } from './util.js';
|
|
8
|
-
const prepareServer = ({ deno, distDirectory, flags: denoFlags, formatExportTypeError, formatImportError, port, }) => {
|
|
9
|
+
const prepareServer = ({ deno, distDirectory, flags: denoFlags, formatExportTypeError, formatImportError, importMap, logger, port, }) => {
|
|
9
10
|
const processRef = {};
|
|
10
|
-
const
|
|
11
|
+
const startServer = async (functions, env = {}, options = {}) => {
|
|
11
12
|
if ((processRef === null || processRef === void 0 ? void 0 : processRef.ps) !== undefined) {
|
|
12
13
|
await killProcess(processRef.ps);
|
|
13
14
|
}
|
|
@@ -15,7 +16,7 @@ const prepareServer = ({ deno, distDirectory, flags: denoFlags, formatExportType
|
|
|
15
16
|
const stage2Path = await generateStage2({
|
|
16
17
|
distDirectory,
|
|
17
18
|
fileName: 'dev.js',
|
|
18
|
-
functions
|
|
19
|
+
functions,
|
|
19
20
|
formatExportTypeError,
|
|
20
21
|
formatImportError,
|
|
21
22
|
type: 'local',
|
|
@@ -40,13 +41,18 @@ const prepareServer = ({ deno, distDirectory, flags: denoFlags, formatExportType
|
|
|
40
41
|
env,
|
|
41
42
|
extendEnv: false,
|
|
42
43
|
});
|
|
44
|
+
let functionsConfig = [];
|
|
45
|
+
if (options.getFunctionsConfig) {
|
|
46
|
+
functionsConfig = await Promise.all(functions.map((func) => getFunctionConfig(func, importMap, deno, logger)));
|
|
47
|
+
}
|
|
43
48
|
const success = await waitForServer(port, processRef.ps);
|
|
44
49
|
return {
|
|
50
|
+
functionsConfig,
|
|
45
51
|
graph,
|
|
46
52
|
success,
|
|
47
53
|
};
|
|
48
54
|
};
|
|
49
|
-
return
|
|
55
|
+
return startServer;
|
|
50
56
|
};
|
|
51
57
|
const serve = async ({ certificatePath, debug, distImportMapPath, inspectSettings, formatExportTypeError, formatImportError, importMaps, onAfterDownload, onBeforeDownload, port, systemLogger, }) => {
|
|
52
58
|
const logger = getLogger(systemLogger, debug);
|
|
@@ -96,6 +102,8 @@ const serve = async ({ certificatePath, debug, distImportMapPath, inspectSetting
|
|
|
96
102
|
flags,
|
|
97
103
|
formatExportTypeError,
|
|
98
104
|
formatImportError,
|
|
105
|
+
importMap,
|
|
106
|
+
logger,
|
|
99
107
|
port,
|
|
100
108
|
});
|
|
101
109
|
if (distImportMapPath) {
|
|
File without changes
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import getPort from 'get-port';
|
|
3
|
+
import fetch from 'node-fetch';
|
|
4
|
+
import { test, expect } from 'vitest';
|
|
5
|
+
import { fixturesDir } from '../../test/util.js';
|
|
6
|
+
import { serve } from '../index.js';
|
|
7
|
+
test('Starts a server and serves requests for edge functions', async () => {
|
|
8
|
+
const port = await getPort();
|
|
9
|
+
const server = await serve({
|
|
10
|
+
port,
|
|
11
|
+
});
|
|
12
|
+
const functionPath = join(fixturesDir, 'serve_test', 'echo_env.ts');
|
|
13
|
+
const functions = [
|
|
14
|
+
{
|
|
15
|
+
name: 'echo_env',
|
|
16
|
+
path: functionPath,
|
|
17
|
+
},
|
|
18
|
+
];
|
|
19
|
+
const options = {
|
|
20
|
+
getFunctionsConfig: true,
|
|
21
|
+
};
|
|
22
|
+
const { functionsConfig, graph, success } = await server(functions, {
|
|
23
|
+
very_secret_secret: 'i love netlify',
|
|
24
|
+
}, options);
|
|
25
|
+
expect(success).toBe(true);
|
|
26
|
+
expect(functionsConfig).toEqual([{ path: '/my-function' }]);
|
|
27
|
+
const graphEntry = graph === null || graph === void 0 ? void 0 : graph.modules.some(
|
|
28
|
+
// @ts-expect-error TODO: Module graph is currently not typed
|
|
29
|
+
({ kind, mediaType, local }) => kind === 'esm' && mediaType === 'TypeScript' && local === functionPath);
|
|
30
|
+
expect(graphEntry).toBe(true);
|
|
31
|
+
const response = await fetch(`http://0.0.0.0:${port}/foo`, {
|
|
32
|
+
headers: {
|
|
33
|
+
'x-deno-functions': 'echo_env',
|
|
34
|
+
'x-deno-pass': 'passthrough',
|
|
35
|
+
'X-NF-Request-ID': 'foo',
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
expect(response.status).toBe(200);
|
|
39
|
+
const body = (await response.json());
|
|
40
|
+
expect(body.very_secret_secret).toBe('i love netlify');
|
|
41
|
+
});
|
|
@@ -2,7 +2,7 @@ import { promises as fs } from 'fs';
|
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import process from 'process';
|
|
4
4
|
import { pathToFileURL } from 'url';
|
|
5
|
-
import
|
|
5
|
+
import { deleteAsync } from 'del';
|
|
6
6
|
import { execa } from 'execa';
|
|
7
7
|
import tmp from 'tmp-promise';
|
|
8
8
|
import { test, expect } from 'vitest';
|
|
@@ -43,6 +43,6 @@ test('`getLocalEntryPoint` returns a valid stage 2 file for local development',
|
|
|
43
43
|
expect(responses[func.name]).toBe(func.response);
|
|
44
44
|
expect(metadata.functions[func.name].url).toBe(pathToFileURL(func.path).toString());
|
|
45
45
|
}
|
|
46
|
-
await
|
|
46
|
+
await deleteAsync(tmpDir, { force: true });
|
|
47
47
|
delete process.env.NETLIFY_EDGE_BOOTSTRAP;
|
|
48
48
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/edge-bundler",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Intelligently prepare Netlify Edge Functions for deployment",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/node/index.js",
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"test": "test/node"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@commitlint/cli": "^
|
|
53
|
-
"@commitlint/config-conventional": "^
|
|
52
|
+
"@commitlint/cli": "^17.0.0",
|
|
53
|
+
"@commitlint/config-conventional": "^17.0.0",
|
|
54
54
|
"@netlify/eslint-config-node": "^4.1.7",
|
|
55
55
|
"@types/glob-to-regexp": "^0.4.1",
|
|
56
56
|
"@types/node": "^14.18.32",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"dependencies": {
|
|
74
74
|
"@import-maps/resolve": "^1.0.1",
|
|
75
75
|
"common-path-prefix": "^3.0.0",
|
|
76
|
-
"del": "^
|
|
76
|
+
"del": "^7.0.0",
|
|
77
77
|
"env-paths": "^3.0.0",
|
|
78
78
|
"execa": "^6.0.0",
|
|
79
79
|
"find-up": "^6.3.0",
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { join } from 'path';
|
|
2
|
-
import getPort from 'get-port';
|
|
3
|
-
import fetch from 'node-fetch';
|
|
4
|
-
import { test, expect } from 'vitest';
|
|
5
|
-
import { fixturesDir } from '../test/util.js';
|
|
6
|
-
import { serve } from './index.js';
|
|
7
|
-
test('bundler serving functionality', async () => {
|
|
8
|
-
const port = await getPort();
|
|
9
|
-
const server = await serve({
|
|
10
|
-
port,
|
|
11
|
-
});
|
|
12
|
-
const { success } = await server([
|
|
13
|
-
{
|
|
14
|
-
name: 'echo_env',
|
|
15
|
-
path: join(fixturesDir, 'serve_test', 'echo_env.ts'),
|
|
16
|
-
},
|
|
17
|
-
], {
|
|
18
|
-
very_secret_secret: 'i love netlify',
|
|
19
|
-
});
|
|
20
|
-
expect(success).toBe(true);
|
|
21
|
-
const response = await fetch(`http://0.0.0.0:${port}/foo`, {
|
|
22
|
-
headers: {
|
|
23
|
-
'x-deno-functions': 'echo_env',
|
|
24
|
-
'x-deno-pass': 'passthrough',
|
|
25
|
-
'X-NF-Request-ID': 'foo',
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
expect(response.status).toBe(200);
|
|
29
|
-
const body = (await response.json());
|
|
30
|
-
expect(body.very_secret_secret).toBe('i love netlify');
|
|
31
|
-
});
|