edge-functions 1.1.0 → 1.3.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/.eslintrc.json +1 -1
- package/README.md +36 -0
- package/aliases.js +1 -1
- package/docs/overview.md +4 -3
- package/docs/presets.md +16 -4
- package/jsconfig.json +1 -1
- package/lib/build/dispatcher/dispatcher.js +62 -66
- package/lib/constants/framework-initializer.constants.js +51 -0
- package/lib/constants/index.js +4 -1
- package/lib/constants/messages/build.messages.js +2 -0
- package/lib/constants/messages/global.messages.js +4 -1
- package/lib/env/polyfills/FetchEvent.polyfills.js +13 -0
- package/lib/env/polyfills/fetch.polyfills.js +39 -0
- package/lib/env/polyfills/index.js +4 -0
- package/lib/env/runtime.env.js +9 -1
- package/lib/main.js +234 -94
- package/lib/platform/actions/core/propagation.actions.js +5 -4
- package/lib/presets/custom/angular/deliver/prebuild.js +6 -10
- package/lib/presets/custom/astro/deliver/prebuild.js +16 -20
- package/lib/presets/custom/hexo/deliver/prebuild.js +16 -20
- package/lib/presets/custom/next/deliver/prebuild.js +31 -35
- package/lib/presets/custom/react/deliver/prebuild.js +2 -6
- package/lib/presets/custom/vue/deliver/prebuild.js +28 -57
- package/lib/utils/exec/exec.utils.js +34 -24
- package/lib/utils/getAbsoluteLibDirPath/getAbsoluteLibDirPath.utils.js +1 -3
- package/lib/utils/getVulcanBuildId/getVulcanBuildId.utils.js +1 -1
- package/lib/utils/index.js +2 -2
- package/lib/utils/presets/index.js +3 -0
- package/lib/utils/presets/presets.utils.js +169 -0
- package/lib/utils/spinner/index.js +2 -2
- package/lib/utils/spinner/spinner.utils.js +1 -1
- package/package.json +10 -3
- package/lib/utils/getPresetsList/getPresetsList.utils.js +0 -68
- package/lib/utils/getPresetsList/index.js +0 -3
- /package/lib/utils/{getPresetsList/getPresetsList.utils.test.js → presets/presets.utils.test.js} +0 -0
package/.eslintrc.json
CHANGED
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
# Vulcan - Forging The Edge
|
|
3
|
+

|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
Vulcan is a powerful tool designed to streamline the development and deployment of JavaScript applications and frameworks. This powerful utility automates polyfills for Edge Computing, significantly simplifying the process of creating Workers, particularly for the Azion platform.
|
|
5
7
|
|
|
@@ -45,6 +47,40 @@ Follow these steps to start using Vulcan:
|
|
|
45
47
|
|
|
46
48
|
5. Start developing: Once the project is set up, you can start developing your JavaScript applications or frameworks using the power of Vulcan. Leverage the automated polyfills, Worker creation assistance, and other features provided by Vulcan to enhance your development workflow.
|
|
47
49
|
|
|
50
|
+
## Using Vulcan
|
|
51
|
+
|
|
52
|
+
See some examples below:
|
|
53
|
+
|
|
54
|
+
* Build a JavaScript/Node project (back-end)
|
|
55
|
+
|
|
56
|
+
```shell
|
|
57
|
+
vulcan build
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
* Build a TypeScript/Node (back-end)
|
|
61
|
+
|
|
62
|
+
```shell
|
|
63
|
+
vulcan build --preset typescript
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
* Build a Static Next.js project
|
|
67
|
+
|
|
68
|
+
```shell
|
|
69
|
+
vulcan build --preset next --mode deliver
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
* Build a Static Astro.js project
|
|
73
|
+
|
|
74
|
+
```shell
|
|
75
|
+
vulcan build --preset astro --mode deliver
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
* Test your project locally (after build)
|
|
79
|
+
|
|
80
|
+
```shell
|
|
81
|
+
vulcan dev
|
|
82
|
+
```
|
|
83
|
+
|
|
48
84
|
|
|
49
85
|
## Docs
|
|
50
86
|
* [Overview](docs/overview.md)
|
package/aliases.js
CHANGED
|
@@ -2,7 +2,7 @@ export default [
|
|
|
2
2
|
['#root/*', './'],
|
|
3
3
|
['#lib/*', './lib'],
|
|
4
4
|
['#utils', './lib/utils/index.js'],
|
|
5
|
-
['#polyfills', './lib/polyfills/index.js'],
|
|
5
|
+
['#polyfills', './lib/env/polyfills/index.js'],
|
|
6
6
|
['#build', './lib/build/dispatcher/index.js'],
|
|
7
7
|
['#bundlers', './lib/build/bundlers/index.js'],
|
|
8
8
|
['#notations/*', './lib/notations'],
|
package/docs/overview.md
CHANGED
|
@@ -31,6 +31,7 @@ Polyfills can be used to generate the worker(s) file(s).
|
|
|
31
31
|
Some configs can be passed to the builder but if user tries to override `azion worker configs` this passed configs will be ignored.
|
|
32
32
|
|
|
33
33
|
### Artifacts
|
|
34
|
-
Files generated to run
|
|
35
|
-
*
|
|
36
|
-
*
|
|
34
|
+
The **'.edge'** folder will be generated representing the edge locally. Files generated to run on the infrastructure:
|
|
35
|
+
* JS worker(s) => '.edge/workers.js';
|
|
36
|
+
* Assets => '.edge/storage/*';
|
|
37
|
+
* Environment variables => '.edge/.env'.
|
package/docs/presets.md
CHANGED
|
@@ -9,8 +9,9 @@ Vulcan is an extensible platform that allows you to easily create new presets fo
|
|
|
9
9
|
To add a new preset, you need to create appropriate folders in two directories: `presets/default` or `presets/custom`. The folder representing your framework or library will automatically be included in the preset listings. Each preset has two modes, represented by folders of the same name: `compute` and `deliver`.
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
https://github.com/aziontech/vulcan/assets/12740219/84c7d7a1-4167-4e7e-993f-41a6eb653758
|
|
13
|
+
|
|
12
14
|
|
|
13
|
-
https://github.com/aziontech/vulcan/assets/12740219/06edb9a0-26cd-4055-bd2e-d400b6a06f3c
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
|
|
@@ -54,7 +55,18 @@ Each preset is made up of three primary files: `config.js`, `prebuild.js`, and `
|
|
|
54
55
|
|
|
55
56
|
Here's a step-by-step guide on how to add a new preset in Vulcan:
|
|
56
57
|
|
|
57
|
-
|
|
58
|
+
## **Use the command to automatic creation:**
|
|
59
|
+
|
|
60
|
+
vulcan presets create
|
|
61
|
+
|
|
62
|
+
https://github.com/aziontech/vulcan/assets/12740219/9ca7371e-713a-4b29-a99b-c1a18d28bc67
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
### Or do it manually:
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
## 1. **Create a folder inside `./lib/presets/custom`:**
|
|
58
70
|
https://github.com/aziontech/vulcan/assets/12740219/abb1b2cc-5f74-473d-b731-c0b7157cb95e
|
|
59
71
|
|
|
60
72
|
- The name of this folder should represent the name of your framework or library.
|
|
@@ -65,7 +77,7 @@ Here's a step-by-step guide on how to add a new preset in Vulcan:
|
|
|
65
77
|
|
|
66
78
|
- **Deliver**: This mode should be used when you intend to use the worker only for routing requests and delivering static files that will be computed on the client side.
|
|
67
79
|
|
|
68
|
-
|
|
80
|
+
2. ## **Create the following files in your preset's folder:**
|
|
69
81
|
|
|
70
82
|
## handler.js
|
|
71
83
|
This file contains the code that is executed within the worker in the edge function. Essentially, it is the code that runs directly on the edge. In the context of the `deliver` mode, this may simply act as a router. However, in cases where computation is needed, it can be designed to perform more complex tasks. Remember, the capabilities of your handler.js are dependent on your use case and the mode of operation you've chosen for your preset.
|
|
@@ -112,4 +124,4 @@ For `deliver` mode:
|
|
|
112
124
|
|
|
113
125
|
vulcan build --preset <name> --mode deliver
|
|
114
126
|
|
|
115
|
-
Replace `<name>` with the name of your preset. This will initiate Vulcan's build process for your preset, allowing you to verify its functionality.
|
|
127
|
+
Replace `<name>` with the name of your preset. This will initiate Vulcan's build process for your preset, allowing you to verify its functionality.
|
package/jsconfig.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { join, resolve } from 'path';
|
|
2
2
|
import {
|
|
3
|
-
readFileSync,
|
|
3
|
+
readFileSync, existsSync, mkdirSync, writeFileSync, rmSync,
|
|
4
4
|
} from 'fs';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
6
|
import { Esbuild, Webpack } from '#bundlers';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
feedback, debug, generateTimestamp, getAbsoluteLibDirPath, presets,
|
|
9
|
+
} from '#utils';
|
|
8
10
|
import { Messages } from '#constants';
|
|
9
11
|
|
|
10
12
|
const vulcanLibPath = getAbsoluteLibDirPath();
|
|
@@ -12,26 +14,10 @@ const vulcanRootPath = resolve(vulcanLibPath, '..');
|
|
|
12
14
|
const isWindows = process.platform === 'win32';
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
|
-
* Get the
|
|
16
|
-
*
|
|
17
|
-
* @returns {string
|
|
17
|
+
* Get the path corresponding to a specific alias defined in the package.json.
|
|
18
|
+
* @param {string} alias - The desired alias.
|
|
19
|
+
* @returns {string} The path corresponding to the alias.
|
|
18
20
|
*/
|
|
19
|
-
function getValidPresets() {
|
|
20
|
-
const types = ['default', 'custom'];
|
|
21
|
-
const validPresets = [];
|
|
22
|
-
|
|
23
|
-
types.forEach((type) => {
|
|
24
|
-
const presetsPath = join(vulcanLibPath, 'presets', type);
|
|
25
|
-
const directories = readdirSync(presetsPath, { withFileTypes: true })
|
|
26
|
-
.filter((dirent) => dirent.isDirectory())
|
|
27
|
-
.map((dirent) => dirent.name);
|
|
28
|
-
|
|
29
|
-
validPresets.push(...directories);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
return validPresets;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
21
|
/**
|
|
36
22
|
* Get the path corresponding to a specific alias defined in the package.json.
|
|
37
23
|
* @param {string} alias - The desired alias.
|
|
@@ -83,13 +69,13 @@ function fixImportsAndRequestsPlace(entryContent) {
|
|
|
83
69
|
* @returns {any} The context that will be used in build.
|
|
84
70
|
*/
|
|
85
71
|
async function loadBuildContext(preset, entry, mode) {
|
|
86
|
-
const VALID_BUILD_PRESETS =
|
|
72
|
+
const VALID_BUILD_PRESETS = presets.getKeys();
|
|
73
|
+
|
|
87
74
|
const validPreset = VALID_BUILD_PRESETS.includes(preset);
|
|
88
75
|
|
|
89
76
|
if (!validPreset) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
);
|
|
77
|
+
feedback.build.error(Messages.build.error.invalid_preset);
|
|
78
|
+
process.exit(1);
|
|
93
79
|
}
|
|
94
80
|
|
|
95
81
|
let configFilePath;
|
|
@@ -112,7 +98,7 @@ async function loadBuildContext(preset, entry, mode) {
|
|
|
112
98
|
prebuildFilePath = join(modePath, 'prebuild.js');
|
|
113
99
|
handlerFilePath = join(modePath, 'handler.js');
|
|
114
100
|
} else {
|
|
115
|
-
feedback.build.error(
|
|
101
|
+
feedback.build.error(Messages.build.error.invalid_preset_mode(mode, preset));
|
|
116
102
|
process.exit(1);
|
|
117
103
|
}
|
|
118
104
|
|
|
@@ -139,9 +125,15 @@ async function loadBuildContext(preset, entry, mode) {
|
|
|
139
125
|
newEntryContent = newEntryContent.replace('#edge', edgehooksPath);
|
|
140
126
|
|
|
141
127
|
if ((preset === 'javascript' || preset === 'typescript') && (mode === 'compute')) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
128
|
+
try {
|
|
129
|
+
const filePath = join(process.cwd(), entry);
|
|
130
|
+
const entryContent = readFileSync(filePath, 'utf-8');
|
|
131
|
+
newEntryContent = newEntryContent.replace('__JS_CODE__', entryContent);
|
|
132
|
+
} catch (error) {
|
|
133
|
+
feedback.build.error(Messages.errors.file_doesnt_exist(entry));
|
|
134
|
+
debug.error(error);
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
145
137
|
}
|
|
146
138
|
|
|
147
139
|
newEntryContent = fixImportsAndRequestsPlace(newEntryContent);
|
|
@@ -201,8 +193,6 @@ class Dispatcher {
|
|
|
201
193
|
*/
|
|
202
194
|
run = async () => {
|
|
203
195
|
// Load Context based on preset
|
|
204
|
-
feedback.prebuild.info(Messages.build.info.prebuild_starting);
|
|
205
|
-
|
|
206
196
|
const { entryContent, prebuild, config } = await loadBuildContext(
|
|
207
197
|
this.preset,
|
|
208
198
|
this.entry,
|
|
@@ -223,42 +213,48 @@ class Dispatcher {
|
|
|
223
213
|
};
|
|
224
214
|
|
|
225
215
|
// Run prebuild actions
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
216
|
+
try {
|
|
217
|
+
feedback.prebuild.info(Messages.build.info.prebuild_starting);
|
|
218
|
+
await prebuild(buildContext);
|
|
219
|
+
feedback.prebuild.success(Messages.build.success.prebuild_succeeded);
|
|
220
|
+
|
|
221
|
+
feedback.build.info(Messages.build.info.vulcan_build_starting);
|
|
222
|
+
// create tmp entrypoint
|
|
223
|
+
const currentDir = process.cwd();
|
|
224
|
+
let tempEntryFile = `vulcan-${buildId}.temp.`;
|
|
225
|
+
tempEntryFile += (this.preset === 'typescript') ? 'ts' : 'js';
|
|
226
|
+
const tempBuilderEntryPath = join(currentDir, tempEntryFile);
|
|
227
|
+
|
|
228
|
+
writeFileSync(tempBuilderEntryPath, entryContent);
|
|
229
|
+
|
|
230
|
+
// builder entry
|
|
231
|
+
config.entry = tempBuilderEntryPath;
|
|
232
|
+
config.buildId = buildId;
|
|
233
|
+
config.useNodePolyfills = this.useNodePolyfills;
|
|
234
|
+
|
|
235
|
+
let builder;
|
|
236
|
+
switch (config.builder) {
|
|
237
|
+
case 'webpack':
|
|
238
|
+
builder = new Webpack(config);
|
|
239
|
+
break;
|
|
240
|
+
case 'esbuild':
|
|
241
|
+
builder = new Esbuild(config);
|
|
242
|
+
break;
|
|
243
|
+
default:
|
|
244
|
+
builder = new Webpack(config);
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Run common build
|
|
249
|
+
await builder.run();
|
|
250
|
+
|
|
251
|
+
// delete .temp files
|
|
252
|
+
rmSync(tempBuilderEntryPath);
|
|
253
|
+
feedback.build.success(Messages.build.success.vulcan_build_succeeded);
|
|
254
|
+
} catch (error) {
|
|
255
|
+
debug.error(error);
|
|
256
|
+
process.exit(1);
|
|
254
257
|
}
|
|
255
|
-
|
|
256
|
-
// Run common build
|
|
257
|
-
await builder.run();
|
|
258
|
-
|
|
259
|
-
// delete .temp files
|
|
260
|
-
rmSync(tempBuilderEntryPath);
|
|
261
|
-
feedback.build.success(Messages.build.success.vulcan_build_succeeded);
|
|
262
258
|
};
|
|
263
259
|
}
|
|
264
260
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FrameworkInitializer contains various methods to initialize new projects
|
|
3
|
+
* in different JavaScript frameworks.
|
|
4
|
+
*
|
|
5
|
+
* Each method is an asynchronous function that takes a `projectName` as an argument.
|
|
6
|
+
* This `projectName` is then used to initialize a new project in the respective framework.
|
|
7
|
+
* @namespace FrameworkInitializer
|
|
8
|
+
* @typedef {object} FrameworkInitializer
|
|
9
|
+
* @property {Function} Angular - Initializes a new Angular project.
|
|
10
|
+
* @property {Function} Astro - Initializes a new Astro project.
|
|
11
|
+
* @property {Function} Hexo - Initializes a new Hexo project.
|
|
12
|
+
* @property {Function} Next - Initializes a new Next.js project.
|
|
13
|
+
* @property {Function} React - Initializes a new React project.
|
|
14
|
+
* @property {Function} Vue - Initializes a new Vue project.
|
|
15
|
+
* @property {Function} Vite - Initializes a new Vue project with Vite.
|
|
16
|
+
* @example
|
|
17
|
+
* const { Angular, React } = FrameworkInitializer;
|
|
18
|
+
*
|
|
19
|
+
* // Initialize a new Angular project called 'myAngularProject'
|
|
20
|
+
* await Angular('myAngularProject');
|
|
21
|
+
*
|
|
22
|
+
* // Initialize a new React project called 'myReactProject'
|
|
23
|
+
* await React('myReactProject');
|
|
24
|
+
*/
|
|
25
|
+
import { exec } from '#utils';
|
|
26
|
+
|
|
27
|
+
const FrameworkInitializer = {
|
|
28
|
+
Angular: async (projectName) => {
|
|
29
|
+
await exec(`npx ng new ${projectName}`, 'Angular', false, true);
|
|
30
|
+
},
|
|
31
|
+
Astro: async (projectName) => {
|
|
32
|
+
await exec(`npx create-astro ${projectName}`, 'Astro', false, true);
|
|
33
|
+
},
|
|
34
|
+
Hexo: async (projectName) => {
|
|
35
|
+
await exec(`npx hexo init ${projectName}`, 'Hexo', false, true);
|
|
36
|
+
},
|
|
37
|
+
Next: async (projectName) => {
|
|
38
|
+
await exec(`npx create-next-app ${projectName}`, 'Next', false, true);
|
|
39
|
+
},
|
|
40
|
+
React: async (projectName) => {
|
|
41
|
+
await exec(`npx create-react-app ${projectName}`, 'React', false, true);
|
|
42
|
+
},
|
|
43
|
+
Vue: async (projectName) => {
|
|
44
|
+
await exec(`npx vue create ${projectName}`, 'Vue', false, true);
|
|
45
|
+
},
|
|
46
|
+
Vite: async (projectName) => {
|
|
47
|
+
await exec(`npx create-vue ${projectName}`, 'Vue/Vite', false, true);
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export default FrameworkInitializer;
|
package/lib/constants/index.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
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
5
|
|
|
5
|
-
export {
|
|
6
|
+
export {
|
|
7
|
+
AzionEdges, RuntimeApis, Messages, FrameworkInitializer,
|
|
8
|
+
};
|
|
@@ -16,6 +16,8 @@ const build = {
|
|
|
16
16
|
},
|
|
17
17
|
error: {
|
|
18
18
|
vulcan_build_failed: 'Vulcan build failed.',
|
|
19
|
+
invalid_preset: 'Invalid build preset. Run "vulcan preset ls" to view available presets.',
|
|
20
|
+
invalid_preset_mode: (mode, preset) => `Mode '${mode}' does not exists in preset '${preset}'. Try 'deliver' or 'compute'.`,
|
|
19
21
|
},
|
|
20
22
|
|
|
21
23
|
};
|
|
@@ -6,9 +6,12 @@ Global messages object.
|
|
|
6
6
|
*/
|
|
7
7
|
const global = {
|
|
8
8
|
success: {},
|
|
9
|
-
info: {
|
|
9
|
+
info: {
|
|
10
|
+
name_required: 'A name is required.',
|
|
11
|
+
},
|
|
10
12
|
errors: {
|
|
11
13
|
unknown_error: 'An error occurred.',
|
|
14
|
+
invalid_choice: 'Invalid choice.',
|
|
12
15
|
folder_creation_failed: (folder) => `An error occurred while creating the ${folder} folder.`,
|
|
13
16
|
write_file_failed: (file) => `An error occurred while writing the ${file} file.`,
|
|
14
17
|
file_doesnt_exist: (file) => `An error occurred while reading the ${file} file.`,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import primitives from '@edge-runtime/primitives';
|
|
2
|
+
import { feedback } from '#utils';
|
|
3
|
+
|
|
4
|
+
class FetchEventPolyfill extends primitives.FetchEvent {
|
|
5
|
+
constructor(request) {
|
|
6
|
+
super(request);
|
|
7
|
+
this.console = {
|
|
8
|
+
log: (log) => feedback.server.log(log),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default FetchEventPolyfill;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
3
|
+
import mime from 'mime-types';
|
|
4
|
+
import { EdgeRuntime } from 'edge-runtime';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A custom fetch implementation that adds an additional path to the URL if it starts with 'file://'.
|
|
8
|
+
* This function is used to simulate the local edge environment. When a 'file://' request is made,
|
|
9
|
+
* it behaves as if the request is made from within the edge itself. In this case, an additional
|
|
10
|
+
* '.edge/storage' folder is appended to the URL to represent the edge environment.
|
|
11
|
+
* @param {EdgeRuntime} context - VMContext
|
|
12
|
+
* @param {URL} url - The URL to fetch.
|
|
13
|
+
* @param {object} [options] - The fetch options.
|
|
14
|
+
* @returns {Promise<Response>} A Promise that resolves to the Response object.
|
|
15
|
+
*/
|
|
16
|
+
async function fetchPolyfill(context, url, options) {
|
|
17
|
+
const {
|
|
18
|
+
URL, Headers, Response,
|
|
19
|
+
} = context;
|
|
20
|
+
|
|
21
|
+
const urlOBJ = new URL(url);
|
|
22
|
+
if (urlOBJ.href.startsWith('file://')) {
|
|
23
|
+
// url pathname = /VERSION_ID/filePath
|
|
24
|
+
const file = url.pathname.slice(15);
|
|
25
|
+
const filePath = join(process.cwd(), '.edge', 'storage', file);
|
|
26
|
+
const fileContent = readFileSync(filePath);
|
|
27
|
+
const contentType = mime.lookup(filePath) || 'application/octet-stream';
|
|
28
|
+
|
|
29
|
+
const headers = new Headers();
|
|
30
|
+
headers.append('Content-Type', contentType);
|
|
31
|
+
|
|
32
|
+
const response = new Response(fileContent, { headers, ...options });
|
|
33
|
+
return response;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return fetch(url, options);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default fetchPolyfill;
|
package/lib/env/runtime.env.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EdgeRuntime } from 'edge-runtime';
|
|
2
2
|
|
|
3
|
-
import { fetchPolyfill, FetchEventPolyfill } from '
|
|
3
|
+
import { fetchPolyfill, FetchEventPolyfill } from './polyfills/index.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Executes the specified JavaScript code within a sandbox environment,
|
|
@@ -39,6 +39,14 @@ function runtime(code) {
|
|
|
39
39
|
context.fetch = (url, options) => fetchPolyfill(context, url, options);
|
|
40
40
|
context.FetchEvent = FetchEventPolyfill;
|
|
41
41
|
context.FirewallEvent = {}; // TODO: Firewall Event
|
|
42
|
+
/*
|
|
43
|
+
* According to the Vercel documentation at https://vercel.com/docs/concepts/functions/edge-functions/edge-runtime#unsupported-apis,
|
|
44
|
+
* the default runtime doesn't support `eval`.
|
|
45
|
+
* However, in our Runtime environment (Cells Runtime/Azion)
|
|
46
|
+
* we've enabled and support its functionality.
|
|
47
|
+
*/
|
|
48
|
+
// eslint-disable-next-line no-eval
|
|
49
|
+
context.eval = eval;
|
|
42
50
|
|
|
43
51
|
/* ==== Cells Runtime/Azion does not have this interface ==== */
|
|
44
52
|
context.File = undefined;
|