edge-functions 2.0.0 → 2.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.
Files changed (34) hide show
  1. package/.commitlintrc.json +40 -0
  2. package/.husky/commit-msg +5 -0
  3. package/.husky/pre-commit +4 -0
  4. package/.prettierignore +2 -1
  5. package/CHANGELOG.md +62 -0
  6. package/jest.global.setup.js +20 -0
  7. package/lib/build/bundlers/esbuild/plugins/node-polyfills/index.js +10 -1
  8. package/lib/build/bundlers/esbuild/plugins/node-polyfills/node-pollyfills-paths.test.js +40 -0
  9. package/lib/build/dispatcher/dispatcher.js +21 -69
  10. package/lib/build/dispatcher/dispatcher.test.js +121 -8
  11. package/lib/build/dispatcher/helpers/helpers.js +64 -0
  12. package/lib/commands/build.commands.js +1 -1
  13. package/lib/commands/init.commands.js +48 -5
  14. package/lib/constants/framework-initializer.constants.js +100 -17
  15. package/lib/constants/index.js +11 -2
  16. package/lib/env/env.test.js +145 -0
  17. package/lib/env/polyfills/fetch.polyfills.test.js +46 -0
  18. package/lib/env/server.env.js +6 -6
  19. package/lib/env/vulcan.env.js +1 -1
  20. package/lib/presets/custom/astro/deliver/prebuild.js +7 -1
  21. package/lib/presets/custom/next/compute/config.js +3 -0
  22. package/lib/presets/custom/next/compute/node/index.js +22 -1
  23. package/lib/utils/generateManifest/generateManifest.utils.js +30 -0
  24. package/lib/utils/generateManifest/index.js +3 -0
  25. package/lib/utils/generateWebpackBanner/generateWebpackBanner.utils.test.js +22 -0
  26. package/lib/utils/getExportedFunctionBody/getExportedFunctionBody.utils.test.js +2 -1
  27. package/lib/utils/getUrlFromResource/getUrlFromResource.utils.test.js +43 -0
  28. package/lib/utils/getVulcanBuildId/getVulcanBuildId.utils.test.js +5 -25
  29. package/lib/utils/index.js +2 -0
  30. package/lib/utils/injectFilesInMem/injectFilesInMem.utils.test.js +2 -2
  31. package/lib/utils/relocateImportsAndRequires/relocateImportsAndRequires.utils.test.js +43 -0
  32. package/lib/utils/vercel/vercel.utils.test.js +110 -0
  33. package/package.json +21 -4
  34. package/verdaccio/config/config.yaml +50 -0
@@ -1,3 +1,33 @@
1
+ import { exec } from '#utils';
2
+ import { writeFileSync, mkdirSync } from 'fs';
3
+ import { join } from 'path';
4
+
5
+ const FrameworksDefaultVersions = {
6
+ Angular: {
7
+ options: [{ value: 'latest', message: 'static supported' }],
8
+ },
9
+ Astro: {
10
+ options: [{ value: 'latest', message: 'static supported' }],
11
+ },
12
+ Hexo: {
13
+ options: [{ value: 'latest', message: 'static supported' }],
14
+ },
15
+ Next: {
16
+ options: [
17
+ { value: '12.3.1', message: 'SSR supported' },
18
+ { value: 'latest', message: 'static supported' },
19
+ ],
20
+ },
21
+ React: {
22
+ options: [{ value: 'latest', message: 'static supported' }],
23
+ },
24
+ Vue: {
25
+ options: [{ value: 'latest', message: 'static supported' }],
26
+ },
27
+ Vite: {
28
+ options: [{ value: 'latest', message: 'static supported' }],
29
+ },
30
+ };
1
31
  /**
2
32
  * FrameworkInitializer contains various methods to initialize new projects
3
33
  * in different JavaScript frameworks.
@@ -22,30 +52,83 @@
22
52
  * // Initialize a new React project called 'myReactProject'
23
53
  * await React('myReactProject');
24
54
  */
25
- import { exec } from '#utils';
26
-
27
55
  const FrameworkInitializer = {
28
- Angular: async (projectName) => {
29
- await exec(`npx @angular/cli new ${projectName}`, 'Angular', false, true);
56
+ JavaScript: async (projectName) => {
57
+ const projectPath = join(process.cwd(), projectName);
58
+ mkdirSync(projectPath);
59
+
60
+ const workerContent = `
61
+ export default function myWorker(event) {
62
+ return new Response('Hello World');
63
+ }
64
+ `;
65
+
66
+ writeFileSync(join(projectPath, 'main.js'), workerContent.trim());
67
+ },
68
+ TypeScript: async (projectName) => {
69
+ const projectPath = join(process.cwd(), projectName);
70
+ mkdirSync(projectPath);
71
+
72
+ const content = `
73
+ export default function myWorker(event: FetchEvent): Response {
74
+ return new Response('Hello World');
75
+ }`;
76
+ const vulcanFile = `preset=typescript\nentry=main.ts\n`;
77
+
78
+ writeFileSync(join(projectPath, '.vulcan'), vulcanFile);
79
+ writeFileSync(join(projectPath, 'main.ts'), content.trim());
80
+ },
81
+ Angular: async (projectName, version = FrameworksDefaultVersions.Angular) => {
82
+ await exec(
83
+ `npx @angular/cli@${version} new ${projectName}`,
84
+ 'Angular',
85
+ false,
86
+ true,
87
+ );
30
88
  },
31
- Astro: async (projectName) => {
32
- await exec(`npx create-astro ${projectName}`, 'Astro', false, true);
89
+ Astro: async (projectName, version = FrameworksDefaultVersions.Astro) => {
90
+ await exec(
91
+ `npx create-astro@${version} ${projectName}`,
92
+ 'Astro',
93
+ false,
94
+ true,
95
+ );
33
96
  },
34
- Hexo: async (projectName) => {
35
- await exec(`npx hexo init ${projectName}`, 'Hexo', false, true);
97
+ Hexo: async (projectName, version = FrameworksDefaultVersions.Hexo) => {
98
+ await exec(`npx hexo@${version} init ${projectName}`, 'Hexo', false, true);
36
99
  },
37
- Next: async (projectName) => {
38
- await exec(`npx create-next-app ${projectName}`, 'Next', false, true);
100
+ Next: async (projectName, version = FrameworksDefaultVersions.Next) => {
101
+ await exec(
102
+ `npx create-next-app@${version} ${projectName} && cd ${projectName} && npm i next@${version}`,
103
+ 'Next',
104
+ false,
105
+ true,
106
+ );
39
107
  },
40
- React: async (projectName) => {
41
- await exec(`npx create-react-app ${projectName}`, 'React', false, true);
108
+ React: async (projectName, version = FrameworksDefaultVersions.React) => {
109
+ await exec(
110
+ `npx create-react-app@${version} ${projectName}`,
111
+ 'React',
112
+ false,
113
+ true,
114
+ );
42
115
  },
43
- Vue: async (projectName) => {
44
- await exec(`npx @vue/cli create ${projectName}`, 'Vue', false, true);
116
+ Vue: async (projectName, version = FrameworksDefaultVersions.Vue) => {
117
+ await exec(
118
+ `npx @vue/cli@${version} create ${projectName}`,
119
+ 'Vue',
120
+ false,
121
+ true,
122
+ );
45
123
  },
46
- Vite: async (projectName) => {
47
- await exec(`npx create-vue ${projectName}`, 'Vue/Vite', false, true);
124
+ Vite: async (projectName, version = FrameworksDefaultVersions.Vite) => {
125
+ await exec(
126
+ `npx create-vue@${version} ${projectName}`,
127
+ 'Vue/Vite',
128
+ false,
129
+ true,
130
+ );
48
131
  },
49
132
  };
50
133
 
51
- export default FrameworkInitializer;
134
+ export { FrameworkInitializer, FrameworksDefaultVersions };
@@ -1,6 +1,15 @@
1
1
  import RuntimeApis from './runtime-apis.constants.js';
2
2
  import AzionEdges from './azion-edges.constants.js';
3
3
  import Messages from './messages/index.js';
4
- import FrameworkInitializer from './framework-initializer.constants.js';
4
+ import {
5
+ FrameworkInitializer,
6
+ FrameworksDefaultVersions,
7
+ } from './framework-initializer.constants.js';
5
8
 
6
- export { AzionEdges, RuntimeApis, Messages, FrameworkInitializer };
9
+ export {
10
+ AzionEdges,
11
+ RuntimeApis,
12
+ Messages,
13
+ FrameworkInitializer,
14
+ FrameworksDefaultVersions,
15
+ };
@@ -0,0 +1,145 @@
1
+ import { afterEach, beforeEach, describe, expect } from '@jest/globals';
2
+ import mockFs from 'mock-fs';
3
+ import fs from 'fs';
4
+ import runtime from './runtime.env.js';
5
+ import vulcanEnv from './vulcan.env.js';
6
+
7
+ describe('runtime env', () => {
8
+ it('Should instantiate a edge runtime', () => {
9
+ const code = `
10
+ addEventListener('fetch', event => {
11
+ const { searchParams } = new URL(event.request.url)
12
+ const url = searchParams.get('url')
13
+ return event.respondWith(fetch(url))
14
+ })`;
15
+ const edgeRuntime = runtime(code);
16
+
17
+ expect(edgeRuntime).toBeDefined();
18
+ });
19
+ });
20
+
21
+ describe('vulcan env', () => {
22
+ const { env } = process;
23
+ beforeEach(() => {
24
+ jest.resetModules();
25
+ process.env = { HOME: '/home/user' };
26
+ process.cwd = jest.fn(() => '/');
27
+ });
28
+
29
+ afterEach(() => {
30
+ process.env = env;
31
+ });
32
+
33
+ it('Should create a vulcan env with global scope', async () => {
34
+ mockFs({});
35
+ await vulcanEnv.createVulcanEnv(
36
+ { API_KEY: 'abc123', ANOTHER_KEY: 'xyz' },
37
+ 'global',
38
+ );
39
+
40
+ const vulcanEnvContent = fs.readFileSync(
41
+ '/home/user/.azion/.vulcan',
42
+ 'utf8',
43
+ );
44
+
45
+ expect(vulcanEnvContent.trim()).toEqual(
46
+ `API_KEY=abc123
47
+ ANOTHER_KEY=xyz`,
48
+ );
49
+ mockFs.restore();
50
+ });
51
+
52
+ it('Should create a vulcan env with default scope', async () => {
53
+ mockFs({});
54
+ await vulcanEnv.createVulcanEnv({ API_KEY: 'abc123', ANOTHER_KEY: 'xyz' });
55
+
56
+ const vulcanEnvContent = fs.readFileSync(
57
+ '/home/user/.azion/.vulcan',
58
+ 'utf8',
59
+ );
60
+
61
+ expect(vulcanEnvContent.trim()).toEqual(
62
+ `API_KEY=abc123
63
+ ANOTHER_KEY=xyz`,
64
+ );
65
+ mockFs.restore();
66
+ });
67
+
68
+ it('Should create a vulcan env with local scope', async () => {
69
+ mockFs({});
70
+ await vulcanEnv.createVulcanEnv(
71
+ { API_KEY: 'abc123', ANOTHER_KEY: 'xyz' },
72
+ 'local',
73
+ );
74
+
75
+ const vulcanEnvContent = fs.readFileSync('/.vulcan', 'utf8');
76
+
77
+ expect(vulcanEnvContent.trim()).toEqual(
78
+ `API_KEY=abc123
79
+ ANOTHER_KEY=xyz`,
80
+ );
81
+ mockFs.restore();
82
+ });
83
+
84
+ it('Should update a vulcan env with local scope', async () => {
85
+ mockFs({
86
+ '/.vulcan': `API_KEY=abc123`,
87
+ });
88
+ await vulcanEnv.createVulcanEnv({ API_KEY: 'abc456' }, 'local');
89
+
90
+ const vulcanEnvContent = fs.readFileSync('/.vulcan', 'utf8');
91
+
92
+ expect(vulcanEnvContent.trim()).toEqual(`API_KEY=abc456`);
93
+ mockFs.restore();
94
+ });
95
+
96
+ it('Should read a vulcan env with default scope', async () => {
97
+ mockFs({
98
+ '/home/user/.azion/.vulcan': `API_KEY=abc123`,
99
+ });
100
+ const envContent = await vulcanEnv.readVulcanEnv();
101
+
102
+ expect(envContent).toMatchObject({ API_KEY: 'abc123' });
103
+ mockFs.restore();
104
+ });
105
+
106
+ it('Should read a vulcan env with global scope', async () => {
107
+ mockFs({
108
+ '/home/user/.azion/.vulcan': `API_KEY=abc123`,
109
+ });
110
+ const envContent = await vulcanEnv.readVulcanEnv('global');
111
+
112
+ expect(envContent).toMatchObject({ API_KEY: 'abc123' });
113
+ mockFs.restore();
114
+ });
115
+
116
+ it('Should read a vulcan env with local scope', async () => {
117
+ mockFs({
118
+ '/.vulcan': `API_KEY=abc123`,
119
+ });
120
+ const envContent = await vulcanEnv.readVulcanEnv('local');
121
+
122
+ expect(envContent).toMatchObject({ API_KEY: 'abc123' });
123
+ mockFs.restore();
124
+ });
125
+
126
+ it('Should read a vulcanconfig file', async () => {
127
+ mockFs({
128
+ '/vulcan.config.js': `module.exports = {
129
+ memoryFS: {
130
+ injectionDirs: ['.faststore/@generated/graphql'],
131
+ removePathPrefix: '.faststore/',
132
+ }
133
+ };`,
134
+ });
135
+ const expectedContent = {
136
+ memoryFS: {
137
+ injectionDirs: ['.faststore/@generated/graphql'],
138
+ removePathPrefix: '.faststore/',
139
+ },
140
+ };
141
+ const vulcaConfigFileContent = await vulcanEnv.loadVulcanConfigFile();
142
+ expect(vulcaConfigFileContent).toEqual(expectedContent);
143
+ mockFs.restore();
144
+ });
145
+ });
@@ -0,0 +1,46 @@
1
+ import mockFS from 'mock-fs';
2
+ import { Headers, Response, Request, URL } from '@edge-runtime/primitives';
3
+ import { expect } from '@jest/globals';
4
+ import fetchPolyfill from './fetch.polyfills.js';
5
+
6
+ describe('fetchPolyfill', () => {
7
+ it('should call the global fetch function for non-file URLs', async () => {
8
+ const resource = 'https://example.com/api/data';
9
+ const options = { method: 'GET' };
10
+ const mockContext = {
11
+ Headers,
12
+ Response,
13
+ Request,
14
+ URL,
15
+ RESERVED_FETCH: () => {
16
+ const response = '{ "statusText": "Not Found" }';
17
+ return JSON.parse(response);
18
+ },
19
+ };
20
+
21
+ const response = await fetchPolyfill(mockContext, resource, options);
22
+
23
+ expect(response.statusText).toBe('Not Found');
24
+ });
25
+
26
+ it('should return a response when the begin with file://', async () => {
27
+ mockFS({
28
+ '.edge': {
29
+ '.env': 'VERSION_ID=123456',
30
+ storage: {
31
+ data: { build: { 'file.js': "console.log('ops')" } },
32
+ },
33
+ },
34
+ });
35
+
36
+ const resource = 'file:///data/build/file.js';
37
+ const options = { method: 'GET' };
38
+ const mockContext = { Headers, Response };
39
+
40
+ const response = await fetchPolyfill(mockContext, resource, options);
41
+
42
+ expect(response.headers.get('Content-Type')).toBe('application/javascript');
43
+ expect(response.status).toBe(200);
44
+ mockFS.restore();
45
+ });
46
+ });
@@ -1,12 +1,10 @@
1
1
  import { debug, readWorkerFile, feedback, exec } from '#utils';
2
2
  import { Messages } from '#constants';
3
- import edgeRuntimePackage from 'edge-runtime';
3
+ import { runServer, EdgeRuntime } from 'edge-runtime';
4
4
  import chokidar from 'chokidar';
5
5
  import runtime from './runtime.env.js';
6
6
  import vulcan from './vulcan.env.js';
7
7
 
8
- const { runServer, EdgeRuntimeServer } = edgeRuntimePackage;
9
-
10
8
  let currentServer;
11
9
  let isChangeHandlerRunning = false;
12
10
 
@@ -32,11 +30,11 @@ async function readWorkerCode(workerPath) {
32
30
  * Initialize and run the server with the given port and worker code.
33
31
  * @param {number} port - The port number.
34
32
  * @param {string} workerCode - The worker code.
35
- * @returns {Promise<EdgeRuntimeServer>} - The initialized server.
33
+ * @returns {Promise<EdgeRuntime>} - The initialized server.
36
34
  */
37
35
  async function initializeServer(port, workerCode) {
38
36
  const execution = runtime(workerCode);
39
- return runServer({ port, host: 'localhost', runtime: execution });
37
+ return runServer({ port, host: '0.0.0.0', runtime: execution });
40
38
  }
41
39
 
42
40
  /**
@@ -55,7 +53,9 @@ async function manageServer(workerPath, port) {
55
53
  try {
56
54
  currentServer = await initializeServer(port, workerCode);
57
55
  feedback.server.success(
58
- Messages.env.server.success.server_running(`http://localhost:${port}`),
56
+ Messages.env.server.success.server_running(
57
+ `0.0.0.0:${port}, url: http://localhost:${port}`,
58
+ ),
59
59
  );
60
60
  } catch (error) {
61
61
  if (error.code === 'EADDRINUSE') {
@@ -147,7 +147,7 @@ async function loadVulcanConfigFile() {
147
147
  let vulcanCustomConfig = null;
148
148
 
149
149
  if (fs.existsSync(buildConfigPath)) {
150
- const vulcanCustomConfigModule = await import(`file://${buildConfigPath}`);
150
+ const vulcanCustomConfigModule = await import(buildConfigPath);
151
151
  vulcanCustomConfig = vulcanCustomConfigModule.default || {};
152
152
  }
153
153
 
@@ -1,5 +1,10 @@
1
1
  import { rm, readFile } from 'fs/promises';
2
- import { exec, getPackageManager, copyDirectory } from '#utils';
2
+ import {
3
+ exec,
4
+ getPackageManager,
5
+ copyDirectory,
6
+ generateManifest,
7
+ } from '#utils';
3
8
 
4
9
  const packageManager = await getPackageManager();
5
10
 
@@ -25,6 +30,7 @@ async function prebuild() {
25
30
 
26
31
  // move files to vulcan default path
27
32
  copyDirectory(outDir, newOutDir);
33
+ generateManifest('*', '*', 'deliver');
28
34
  rm(outDir, { recursive: true, force: true });
29
35
  }
30
36
 
@@ -68,6 +68,9 @@ const config = {
68
68
  async_hooks: false,
69
69
  tls: false,
70
70
  net: false,
71
+ child_process: false,
72
+ https: require.resolve('https-browserify'),
73
+ tty: require.resolve('tty-browserify'),
71
74
  http: require.resolve('stream-http'),
72
75
  buffer: require.resolve('buffer/'),
73
76
  crypto: require.resolve('crypto-browserify/'),
@@ -5,6 +5,22 @@ import fs from 'fs';
5
5
  import { copyDirectory, feedback, getAbsoluteLibDirPath } from '#utils';
6
6
  import BuildStatic from './prebuild/index.js';
7
7
 
8
+ /**
9
+ * If a relative path exists, copy public path to root
10
+ * @param {string} pathPrefix - prefix
11
+ * @param {string} rootDir - application root dir
12
+ */
13
+ function handlePublicDir(pathPrefix, rootDir) {
14
+ const validPathPrefix =
15
+ pathPrefix && typeof pathPrefix === 'string' && pathPrefix !== '';
16
+
17
+ if (validPathPrefix) {
18
+ const srcPublicDir = path.resolve(pathPrefix, 'public');
19
+ const destPublicDir = path.resolve(rootDir, 'public');
20
+ copyDirectory(srcPublicDir, destPublicDir);
21
+ }
22
+ }
23
+
8
24
  /**
9
25
  * Run actions to build next for node runtime.
10
26
  * @param {string} nextVersion - project next version in package.json
@@ -50,10 +66,15 @@ async function run(nextVersion, buildContext) {
50
66
  }
51
67
 
52
68
  // STATICS
69
+ // copy to root public dir if necessary
70
+ if (buildContext.memoryFS) {
71
+ handlePublicDir(buildContext.memoryFS.removePathPrefix, rootDir);
72
+ }
73
+
53
74
  const buildStatic = new BuildStatic({
54
75
  rootDir,
55
76
  includeDirs: ['./.next', './public'],
56
- staticDirs: ['public', '.next/static'],
77
+ staticDirs: ['./public', '.next/static'],
57
78
  excludeDirs: ['./.next/cache', 'node_modules'],
58
79
  out: OUT_DIR_CUSTOM_SERVER,
59
80
  versionId: buildContext.buildId,
@@ -0,0 +1,30 @@
1
+ import { join } from 'path';
2
+ import { writeFileSync } from 'fs';
3
+ import { Utils } from '#namespaces';
4
+
5
+ /**
6
+ * @function
7
+ * @memberof Utils
8
+ * @description Generates manifest object and writes it to a file.
9
+ * @param {string} route - the route to be used, or all represented by '*'
10
+ * @param {string} filePath - the file path for the route, or all represented by '*'
11
+ * @param {string} mode - The mode of the operation, either 'compute', 'deliver', or both represented by '*'.
12
+ */
13
+ function generateManifest(route, filePath, mode) {
14
+ const manifestPath = join(process.cwd(), '.edge/manifest.json');
15
+ const manifest = { routes: {} };
16
+
17
+ // Check the mode and add the route to the manifest appropriately.
18
+ if (mode === 'compute' || mode === 'deliver' || mode === '*') {
19
+ manifest.routes[mode] = {};
20
+ manifest.routes[mode][route] = filePath;
21
+ } else {
22
+ throw new Error('Invalid mode. Must be "compute", "deliver", or "*".');
23
+ }
24
+
25
+ // Write the new manifest back to the file.
26
+ writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf8');
27
+ console.log(`New manifest created with ${mode} information.`);
28
+ }
29
+
30
+ export default generateManifest;
@@ -0,0 +1,3 @@
1
+ import generateManifest from './generateManifest.utils.js';
2
+
3
+ export default generateManifest;
@@ -0,0 +1,22 @@
1
+ import mockFS from 'mock-fs';
2
+ import generateWebpackBanner from './generateWebpackBanner.utils.js';
3
+
4
+ describe('generateWebpackBanner', () => {
5
+ it('should generate a webpack banner', () => {
6
+ const arrayOfPaths = ['path/to/file1.js', 'path/to/file2.js'];
7
+ const expectedBanner = 'file-1-content\nfile-2-content\n';
8
+ mockFS({
9
+ path: {
10
+ to: {
11
+ 'file1.js': 'file-1-content',
12
+ 'file2.js': 'file-2-content',
13
+ },
14
+ },
15
+ });
16
+
17
+ const bannerArray = generateWebpackBanner(arrayOfPaths);
18
+
19
+ expect(bannerArray).toBe(expectedBanner);
20
+ mockFS.restore();
21
+ });
22
+ });
@@ -1,6 +1,7 @@
1
+ /* eslint-disable jest/no-disabled-tests */
1
2
  import getExportedFunctionBody from './getExportedFunctionBody.utils.js';
2
3
 
3
- describe('getExportedFunctionBody', () => {
4
+ describe.skip('getExportedFunctionBody', () => {
4
5
  it('should extract the body from a default exported function declaration', () => {
5
6
  const inputCode = `
6
7
  export default function test() {
@@ -0,0 +1,43 @@
1
+ import { URL, Request } from '@edge-runtime/primitives';
2
+ import getUrlFromResource from './getUrlFromResource.utils.js';
3
+
4
+ describe('getUrlFromResource', () => {
5
+ it('should return a URL when passed a valid string', () => {
6
+ const urlString = 'https://example.com/';
7
+ const context = { Request, URL };
8
+ const result = getUrlFromResource(context, urlString);
9
+ expect(result).toBeInstanceOf(URL);
10
+ expect(result.href).toBe(urlString);
11
+ });
12
+
13
+ it('should return a URL when passed a Request object', () => {
14
+ const request = new Request('https://example.com');
15
+ const context = { Request, URL };
16
+ const result = getUrlFromResource(context, request);
17
+ expect(result).toBeInstanceOf(URL);
18
+ expect(result.href).toBe(request.url);
19
+ });
20
+
21
+ it('should return the same URL when passed a URL object', () => {
22
+ const url = new URL('https://example.com');
23
+ const context = { Request, URL };
24
+ const result = getUrlFromResource(context, url);
25
+ expect(result).toBe(url);
26
+ });
27
+
28
+ it('should throw an error when passed an invalid url', () => {
29
+ const invalidInput = 'example.com'; // Invalid input (not a string, Request, or URL)
30
+ const context = { Request, URL };
31
+ expect(() => getUrlFromResource(context, invalidInput)).toThrow(
32
+ 'Invalid URL',
33
+ );
34
+ });
35
+
36
+ it('should throw an error when passed an invalid input', () => {
37
+ const invalidInput = 123; // Invalid input (not a string, Request, or URL)
38
+ const context = { Request, URL };
39
+ expect(() => getUrlFromResource(context, invalidInput)).toThrow(
40
+ "Invalid resource input. 'resource' must be 'URL', 'Request' or 'string'.",
41
+ );
42
+ });
43
+ });
@@ -1,36 +1,16 @@
1
- import { writeFileSync, mkdirSync, rmSync } from 'fs';
2
- import { tmpdir } from 'os';
3
- import { join } from 'path';
4
-
1
+ import mockFs from 'mock-fs';
5
2
  import getVulcanBuildId from './index.js';
6
3
 
7
- const FILE_NAME = '.env';
8
- const FILE_DIR = '.edge';
9
- const CURRENT_DIR = process.cwd();
10
- const TMP_DIR = tmpdir();
11
- const DIR_PATH = join(TMP_DIR, FILE_DIR);
12
- const FILE_PATH = join(TMP_DIR, FILE_DIR, FILE_NAME);
13
-
14
4
  describe('getVulcanBuildId utils', () => {
15
- beforeAll(() => {
16
- process.chdir(TMP_DIR);
17
-
18
- mkdirSync(DIR_PATH);
19
-
20
- writeFileSync(FILE_PATH, 'VERSION_ID=20230627142534');
21
- });
22
-
23
- afterAll(() => {
24
- process.chdir(CURRENT_DIR);
25
-
26
- rmSync(DIR_PATH, { recursive: true, force: true });
27
- });
28
-
29
5
  test('Should fetch the unique build ID for the current project', async () => {
6
+ mockFs({
7
+ '.edge': { '.env': 'VERSION_ID=20230627142534' },
8
+ });
30
9
  const expectedOutput = '20230627142534';
31
10
 
32
11
  const result = getVulcanBuildId();
33
12
 
34
13
  expect(result).toBe(expectedOutput);
14
+ mockFs.restore();
35
15
  });
36
16
  });
@@ -18,6 +18,7 @@ import generateWebpackBanner from './generateWebpackBanner/index.js';
18
18
  import relocateImportsAndRequires from './relocateImportsAndRequires/index.js';
19
19
  import getExportedFunctionBody from './getExportedFunctionBody/index.js';
20
20
  import injectFilesInMem from './injectFilesInMem/index.js';
21
+ import generateManifest from './generateManifest/index.js';
21
22
 
22
23
  export {
23
24
  copyDirectory,
@@ -40,4 +41,5 @@ export {
40
41
  generateWebpackBanner,
41
42
  relocateImportsAndRequires,
42
43
  injectFilesInMem,
44
+ generateManifest,
43
45
  };
@@ -26,10 +26,10 @@ describe('injectFilesInMem', () => {
26
26
  '/path/to/dir2',
27
27
  ]);
28
28
 
29
- expect(codeToInject).toContain('globalThis.__FILES__');
29
+ expect(codeToInject).toContain('globalThis.vulcan.__FILES__');
30
30
 
31
31
  const strData = codeToInject
32
- .replace('globalThis.__FILES__=', '')
32
+ .replace('globalThis.vulcan.__FILES__=', '')
33
33
  .replace('};', '}');
34
34
  const data = JSON.parse(strData);
35
35