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.
Files changed (35) hide show
  1. package/.eslintrc.json +1 -1
  2. package/README.md +36 -0
  3. package/aliases.js +1 -1
  4. package/docs/overview.md +4 -3
  5. package/docs/presets.md +16 -4
  6. package/jsconfig.json +1 -1
  7. package/lib/build/dispatcher/dispatcher.js +62 -66
  8. package/lib/constants/framework-initializer.constants.js +51 -0
  9. package/lib/constants/index.js +4 -1
  10. package/lib/constants/messages/build.messages.js +2 -0
  11. package/lib/constants/messages/global.messages.js +4 -1
  12. package/lib/env/polyfills/FetchEvent.polyfills.js +13 -0
  13. package/lib/env/polyfills/fetch.polyfills.js +39 -0
  14. package/lib/env/polyfills/index.js +4 -0
  15. package/lib/env/runtime.env.js +9 -1
  16. package/lib/main.js +234 -94
  17. package/lib/platform/actions/core/propagation.actions.js +5 -4
  18. package/lib/presets/custom/angular/deliver/prebuild.js +6 -10
  19. package/lib/presets/custom/astro/deliver/prebuild.js +16 -20
  20. package/lib/presets/custom/hexo/deliver/prebuild.js +16 -20
  21. package/lib/presets/custom/next/deliver/prebuild.js +31 -35
  22. package/lib/presets/custom/react/deliver/prebuild.js +2 -6
  23. package/lib/presets/custom/vue/deliver/prebuild.js +28 -57
  24. package/lib/utils/exec/exec.utils.js +34 -24
  25. package/lib/utils/getAbsoluteLibDirPath/getAbsoluteLibDirPath.utils.js +1 -3
  26. package/lib/utils/getVulcanBuildId/getVulcanBuildId.utils.js +1 -1
  27. package/lib/utils/index.js +2 -2
  28. package/lib/utils/presets/index.js +3 -0
  29. package/lib/utils/presets/presets.utils.js +169 -0
  30. package/lib/utils/spinner/index.js +2 -2
  31. package/lib/utils/spinner/spinner.utils.js +1 -1
  32. package/package.json +10 -3
  33. package/lib/utils/getPresetsList/getPresetsList.utils.js +0 -68
  34. package/lib/utils/getPresetsList/index.js +0 -3
  35. /package/lib/utils/{getPresetsList/getPresetsList.utils.test.js → presets/presets.utils.test.js} +0 -0
@@ -1,7 +1,7 @@
1
- import { exec, feedback, getPackageManager } from '#utils';
2
1
  import {
3
- copyFile, mkdir, readdir, lstat, readFile,
4
- } from 'fs/promises';
2
+ exec, getPackageManager, copyDirectory,
3
+ } from '#utils';
4
+ import { lstat, readFile, rm } from 'fs/promises';
5
5
  import { join } from 'path';
6
6
 
7
7
  const packageManager = await getPackageManager();
@@ -34,71 +34,42 @@ async function readViteConfig() {
34
34
  }
35
35
  }
36
36
 
37
- /**
38
- * Copy files and directories from one directory to another.
39
- * @param {string} srcDir - Source directory.
40
- * @param {string} destDir - Destination directory.
41
- */
42
- async function copyFiles(srcDir, destDir) {
43
- const files = await readdir(srcDir);
44
-
45
- await Promise.all(files.map(async (file) => {
46
- const srcPath = join(srcDir, file);
47
- const destPath = join(destDir, file);
48
- const stats = await lstat(srcPath);
49
-
50
- if (stats.isFile()) {
51
- await copyFile(srcPath, destPath);
52
- } else if (stats.isDirectory()) {
53
- await mkdir(destPath, { recursive: true });
54
- await copyFiles(srcPath, destPath);
55
- }
56
- }));
57
- }
58
-
59
37
  /**
60
38
  * Runs custom prebuild actions.
61
39
  */
62
40
  async function prebuild() {
63
- try {
64
- let outDir = defaultViteOutDir;
65
- let destPath = edgeStorageDir;
66
-
67
- const isViteProject = await viteConfigExists();
68
- if (isViteProject) {
69
- const config = await readViteConfig();
41
+ const npmArgsForward = packageManager === 'npm' ? '--' : '';
70
42
 
71
- if (config?.build?.outDir) {
72
- outDir = config.build.outDir;
73
- }
43
+ let outDir = defaultViteOutDir;
44
+ let destPath = edgeStorageDir;
74
45
 
75
- const srcPath = join('.', outDir);
76
- destPath = join(edgeStorageDir);
46
+ const isViteProject = await viteConfigExists();
77
47
 
78
- await mkdir(destPath, { recursive: true });
79
- await copyFiles(srcPath, destPath);
80
- }
48
+ if (isViteProject) {
49
+ await exec(
50
+ `${packageManager} run build ${npmArgsForward}`,
51
+ 'Vue/Vite',
52
+ true,
53
+ );
81
54
 
82
- const npmArgsForward = packageManager === 'npm' ? '--' : '';
55
+ const config = await readViteConfig();
83
56
 
84
- // support npm, yarn, pnpm
85
- if (isViteProject) {
86
- await exec(
87
- `${packageManager} run build ${npmArgsForward}`,
88
- 'Vue/Vite',
89
- true,
90
- );
57
+ if (config?.build?.outDir) {
58
+ outDir = config.build.outDir;
91
59
  }
92
60
 
93
- if (!isViteProject) {
94
- await exec(
95
- `${packageManager} run build ${npmArgsForward} --dest ${destPath}`,
96
- 'Vue',
97
- true,
98
- );
99
- }
100
- } catch (error) {
101
- feedback.prebuild.error(error);
61
+ const srcPath = join('.', outDir);
62
+ destPath = join(edgeStorageDir);
63
+ copyDirectory(outDir, srcPath);
64
+ rm(outDir, { recursive: true, force: true });
65
+ }
66
+
67
+ if (!isViteProject) {
68
+ await exec(
69
+ `${packageManager} run build ${npmArgsForward} --dest ${destPath}`,
70
+ 'Vue',
71
+ true,
72
+ );
102
73
  }
103
74
  }
104
75
 
@@ -9,51 +9,61 @@ import signale from 'signale';
9
9
  * @param {string} command - The command to be executed.
10
10
  * @param {string} [scope='Process'] - Log scope. The default is 'Process'.
11
11
  * @param {boolean} [verbose=false] - Whether to display the output in real-time.
12
+ * @param {boolean} [interactive=false] - Whether to allow user
13
+ * interaction with the running process.
12
14
  * @returns {Promise<void>} A promise that resolves when the command completes successfully.
15
+ * @throws Will throw an error if the command exits with a non-zero status code.
13
16
  * @example
14
17
  * // Executing a command without verbose output
15
18
  * await exec('npm install');
16
19
  *
17
20
  * // Executing a command with verbose output
18
21
  * await exec('npm run build', 'Build', true);
22
+ *
23
+ * // Executing an interactive command
24
+ * await exec('npx vue create my-project', 'Vue', false, true);
19
25
  */
20
- async function exec(command, scope = 'Process', verbose = false) {
26
+ async function exec(command, scope = 'Process', verbose = false, interactive = false) {
21
27
  const stream = new signale.Signale({ interactive: true, scope: ['Process', scope] });
22
28
 
23
29
  return new Promise((resolve, reject) => {
24
30
  const args = command.split(' ');
25
31
  const cmd = args.shift();
26
32
 
27
- const buildProcess = spawn(cmd, args, { shell: true });
33
+ const execProcess = spawn(cmd, args, {
34
+ shell: true,
35
+ stdio: interactive ? 'inherit' : 'pipe',
36
+ });
37
+
38
+ if (!interactive) {
39
+ if (verbose) {
40
+ execProcess.stdout.on('data', (data) => {
41
+ stream.info(data.toString());
42
+ });
28
43
 
29
- if (verbose) {
30
- buildProcess.stdout.on('data', (data) => {
31
- stream.info(data.toString());
44
+ execProcess.stderr.on('data', (data) => {
45
+ const dataStr = data.toString();
46
+ if (dataStr.toLowerCase().includes('error')) {
47
+ stream.error(dataStr);
48
+ } else {
49
+ stream.info(dataStr);
50
+ }
51
+ });
52
+ }
53
+
54
+ execProcess.on('error', (error) => {
55
+ reject(error);
32
56
  });
33
57
 
34
- buildProcess.stderr.on('data', (data) => {
35
- // Some tools and libraries choose to use
36
- // stderr for process logging or informational messages.
37
- const dataStr = data.toString();
38
- if (dataStr.toLowerCase().includes('error')) {
39
- stream.error(dataStr);
58
+ execProcess.on('close', (code) => {
59
+ if (code === 0) {
60
+ resolve();
40
61
  } else {
41
- stream.info(dataStr);
62
+ reject(new Error(`Command '${command}' failed with code ${code}`));
42
63
  }
43
64
  });
44
65
  }
45
-
46
- buildProcess.on('error', (error) => {
47
- reject(error);
48
- });
49
-
50
- buildProcess.on('close', (code) => {
51
- if (code === 0) {
52
- resolve();
53
- } else {
54
- reject(new Error(`Command '${command}' failed with code ${code}`));
55
- }
56
- });
57
66
  });
58
67
  }
68
+
59
69
  export default exec;
@@ -1,3 +1,4 @@
1
+ const isWindows = process.platform === 'win32';
1
2
  /**
2
3
  * Get the absolute path of the lib directory based on the current module.
3
4
  * @function
@@ -10,9 +11,6 @@
10
11
  * const libDirPath = getAbsoluteLibDirPath();
11
12
  * console.log(libDirPath); // 'lib/full/path/to/directory'
12
13
  */
13
-
14
- const isWindows = process.platform === 'win32';
15
-
16
14
  function getAbsoluteLibDirPath() {
17
15
  const currentModuleFullPath = import.meta.url;
18
16
  let baselibPath = currentModuleFullPath.match(/(.*lib)(.*)/)[1];
@@ -2,7 +2,7 @@ import { readFileSync, existsSync } from 'fs';
2
2
  import { join } from 'path';
3
3
 
4
4
  /**
5
- * @namespace Utils
5
+ * @memberof utils
6
6
  * @function
7
7
  * @name getVulcanBuildId
8
8
  * @description Fetches the unique build ID for the current project from the
@@ -6,7 +6,7 @@ import generateTimestamp from './generateTimestamp/index.js';
6
6
  import getAbsoluteLibDirPath from './getAbsoluteLibDirPath/index.js';
7
7
  import getVulcanBuildId from './getVulcanBuildId/index.js';
8
8
  import getPackageManager from './getPackageManager/index.js';
9
- import getPresetsList from './getPresetsList/index.js';
9
+ import presets from './presets/index.js';
10
10
  import readWorkerFile from './readWorkerFile/index.js';
11
11
  import overrideStaticOutputPath from './overrideStaticOutputPath/index.js';
12
12
  import getProjectJsonFile from './getProjectJsonFile/index.js';
@@ -24,7 +24,7 @@ export {
24
24
  getPackageVersion,
25
25
  getProjectJsonFile,
26
26
  getVulcanBuildId,
27
- getPresetsList,
27
+ presets,
28
28
  overrideStaticOutputPath,
29
29
  readWorkerFile,
30
30
  Spinner,
@@ -0,0 +1,3 @@
1
+ import presets from './presets.utils.js';
2
+
3
+ export default presets;
@@ -0,0 +1,169 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+ const isWindows = process.platform === 'win32';
5
+ const currentModuleFullPath = import.meta.url;
6
+ let baselibPath = currentModuleFullPath.match(/(.*lib)(.*)/)[1];
7
+
8
+ if (isWindows) {
9
+ baselibPath = new URL(baselibPath).pathname;
10
+ if (baselibPath.startsWith('/')) {
11
+ baselibPath = baselibPath.slice(1);
12
+ }
13
+ }
14
+ if (!isWindows) {
15
+ baselibPath = baselibPath.replace('file://', '');
16
+ }
17
+
18
+ /**
19
+ * Retrieves a list of presets from 'default' and 'custom' directories in a beautified format.
20
+ * Unlike `getKeys`, this method returns preset names formatted
21
+ * for display and includes modes like '(Static)' or '(Server)'.
22
+ * @function
23
+ * @memberof presets
24
+ * @name getBeautify
25
+ * @param {string[]} [types=['default', 'custom']] - The types of presets to list.
26
+ * Each type corresponds to a folder in the 'presets' directory.
27
+ * @returns {string[]} The list of presets with modes like '(Static)' or '(Server)' if applicable.
28
+ * @example
29
+ * const presetsList = getBeautify(['default', 'custom']);
30
+ * console.log(presetsList);
31
+ * // Output might be: ['Angular (Static)', 'React (Server)', 'Vue (Static)']
32
+ */
33
+ function getBeautify(types = ['default', 'custom']) {
34
+ const presets = [];
35
+
36
+ types.forEach((type) => {
37
+ const presetsDir = path.join(baselibPath, `presets/${type}`);
38
+ const folders = fs
39
+ .readdirSync(presetsDir, { withFileTypes: true })
40
+
41
+ .filter((dirent) => dirent.isDirectory())
42
+ .flatMap((dirent) => {
43
+ const presetName = dirent.name;
44
+ const subDirs = fs
45
+ .readdirSync(path.join(presetsDir, presetName), {
46
+ withFileTypes: true,
47
+ })
48
+ .filter((subDirent) => subDirent.isDirectory());
49
+
50
+ if (subDirs.length === 0) {
51
+ return [presetName.charAt(0).toUpperCase() + presetName.slice(1)];
52
+ }
53
+
54
+ return subDirs.map((subDir) => {
55
+ const subDirName = subDir.name.charAt(0).toUpperCase() + subDir.name.slice(1);
56
+ return `${
57
+ presetName.charAt(0).toUpperCase() + presetName.slice(1)
58
+ } (${subDirName})`;
59
+ });
60
+ });
61
+
62
+ presets.push(...folders);
63
+ });
64
+
65
+ return presets;
66
+ }
67
+
68
+ /**
69
+ * Retrieves an array of valid preset keys by scanning through
70
+ * the preset directories 'default' and 'custom'.
71
+ * Each folder name in these directories is considered as a valid preset key.
72
+ * Unlike `getBeautify`, this method returns raw preset names without any formatting or modes.
73
+ * @function
74
+ * @memberof presets
75
+ * @name getKeys
76
+ * @returns {string[]} An array of valid build presets.
77
+ * @example
78
+ * const validPresetsKeys = getKeys();
79
+ * console.log(validKeys);
80
+ * // Output might be: ['angular', 'react', 'vue']
81
+ * @throws {Error} Throws an error if unable to read the directory.
82
+ */
83
+ function getKeys() {
84
+ const types = ['default', 'custom'];
85
+ const validPresets = [];
86
+
87
+ types.forEach((type) => {
88
+ const presetsPath = path.join(baselibPath, 'presets', type);
89
+ const directories = fs
90
+ .readdirSync(presetsPath, { withFileTypes: true })
91
+ .filter((dirent) => dirent.isDirectory())
92
+ .map((dirent) => dirent.name);
93
+
94
+ validPresets.push(...directories);
95
+ });
96
+
97
+ return validPresets;
98
+ }
99
+
100
+ /**
101
+ * Creates a new preset in the lib/presets/custom/${mode} directory.
102
+ * Also generates three required files: handler.js, prebuild.js, and config.js.
103
+ * @function
104
+ * @memberof utils
105
+ * @name set
106
+ * @param {string} name - The name of the new preset.
107
+ * @param {'compute'|'deliver'} mode - The mode for the preset, either 'compute' or 'deliver'.
108
+ * @throws {Error} Throws an error if a preset with the same name
109
+ * already exists or if mode is invalid.
110
+ * @example
111
+ *
112
+ * // Create a new preset named 'MyPreset' in 'compute' mode
113
+ * presets.set('MyPreset', 'compute');
114
+ */
115
+ function set(name, mode) {
116
+ const presetPath = path.join(baselibPath, 'presets', 'custom', name, mode);
117
+ fs.mkdirSync(presetPath, { recursive: true });
118
+
119
+ if (mode === 'compute') {
120
+ const defaultFilesPath = path.join(
121
+ baselibPath,
122
+ 'presets',
123
+ 'default',
124
+ 'javascript',
125
+ 'compute',
126
+ );
127
+ const filesToCopy = ['handler.js', 'config.js', 'prebuild.js'];
128
+
129
+ filesToCopy.forEach((file) => {
130
+ const srcPath = path.join(defaultFilesPath, file);
131
+ const destPath = path.join(presetPath, file);
132
+ fs.copyFileSync(srcPath, destPath);
133
+ });
134
+ }
135
+ if (mode === 'deliver') {
136
+ // TODO: Create template for 'deliver' mode init
137
+ fs.writeFileSync(path.join(presetPath, 'handler.js'), '');
138
+ fs.writeFileSync(path.join(presetPath, 'prebuild.js'), '');
139
+ fs.writeFileSync(path.join(presetPath, 'config.js'), '');
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Presets object containing utility functions for working with build presets.
145
+ * @memberof utils
146
+ * @property {Function} getKeys - Function to retrieve an array of valid preset keys.
147
+ * These keys are raw and do not include any modes or formatting.
148
+ * @property {Function} getBeautify - Function to retrieve a list of presets in a beautified format.
149
+ * Unlike `getKeys`, the names are formatted and include modes like '(Static)' or '(Server)'.
150
+ * @property {Function} set - Function to create a new preset along with its required files.
151
+ * @example
152
+ * import { presets } from '#utils';
153
+ *
154
+ * // Get raw preset keys
155
+ * const rawKeys = presets.getKeys();
156
+ *
157
+ * // Get beautified preset names
158
+ * const beautifiedNames = presets.getBeautify();
159
+ *
160
+ * // Create a new preset
161
+ * presets.set('MyNewPreset', 'compute');
162
+ */
163
+ const presets = {
164
+ getKeys,
165
+ getBeautify,
166
+ set,
167
+ };
168
+
169
+ export default presets;
@@ -1,3 +1,3 @@
1
- import spinner from './spinner.utils.js';
1
+ import Spinner from './spinner.utils.js';
2
2
 
3
- export default spinner;
3
+ export default Spinner;
@@ -9,7 +9,7 @@ class Spinner {
9
9
  }
10
10
 
11
11
  start() {
12
- signale.pending(`Starting ${this.action} ...`);
12
+ signale.pending(`Starting ${this.action}...`);
13
13
 
14
14
  this.intervalId = setInterval(() => {
15
15
  const frame = this.frames[this.currentFrameIndex];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "edge-functions",
3
3
  "type": "module",
4
- "version": "1.1.0",
4
+ "version": "1.3.0",
5
5
  "description": "Tool to launch and build JavaScript/Frameworks. This tool automates polyfills for Edge Computing and assists in creating Workers, notably for the Azion platform.",
6
6
  "main": "lib/main.js",
7
7
  "bin": {
@@ -34,6 +34,7 @@
34
34
  ],
35
35
  "license": "MIT",
36
36
  "dependencies": {
37
+ "@angular/cli": "^16.2.0",
37
38
  "@edge-runtime/node-utils": "^2.1.1",
38
39
  "@edge-runtime/primitives": "^3.0.4",
39
40
  "@semantic-release/changelog": "^6.0.3",
@@ -41,15 +42,21 @@
41
42
  "@semantic-release/git": "^10.0.1",
42
43
  "@semantic-release/npm": "^10.0.4",
43
44
  "@semantic-release/release-notes-generator": "^11.0.4",
45
+ "@vue/cli": "^5.0.8",
44
46
  "bottleneck": "^2.19.5",
45
47
  "chokidar": "^3.5.3",
46
48
  "commander": "^10.0.1",
47
49
  "conventional-changelog-conventionalcommits": "^6.1.0",
50
+ "create-astro": "^3.2.2",
51
+ "create-next-app": "^13.4.19",
52
+ "create-react-app": "^5.0.1",
53
+ "create-vue": "^3.7.3",
48
54
  "deepmerge": "^4.3.1",
49
55
  "edge-runtime": "^2.4.5",
50
56
  "esbuild": "^0.18.11",
51
57
  "escape-string-regexp": "^5.0.0",
52
58
  "form-data": "^4.0.0",
59
+ "hexo": "^7.0.0-rc2",
53
60
  "inquirer": "^9.2.7",
54
61
  "install": "^0.13.0",
55
62
  "lodash": "^4.17.21",
@@ -85,7 +92,7 @@
85
92
  "#root/*": "./",
86
93
  "#lib/*": "./lib",
87
94
  "#utils": "./lib/utils/index.js",
88
- "#polyfills": "./lib/polyfills/index.js",
95
+ "#polyfills": "./lib/env/polyfills/index.js",
89
96
  "#build": "./lib/build/dispatcher/index.js",
90
97
  "#bundlers": "./lib/build/bundlers/index.js",
91
98
  "#notations/*": "./lib/notations",
@@ -102,4 +109,4 @@
102
109
  "url": "https://github.com/aziontech/vulcan/issues"
103
110
  },
104
111
  "homepage": "https://github.com/aziontech/vulcan#readme"
105
- }
112
+ }
@@ -1,68 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
-
4
- /**
5
- * Get the list of presets.
6
- * @function
7
- * @name getPresetsList
8
- * @memberof utils
9
- * @param {string[]} [types=['default', 'custom']] - The types of presets to list.
10
- * Each type corresponds to a folder in the 'presets' directory.
11
- * @returns {string[]} The list of presets with '(Static)' or '(Server)' suffixes when applicable.
12
- * @example
13
- * const presetsList = getPresetsList(['default', 'custom']);
14
- * console.log(presetsList);
15
- * // Output: ['Next (Static)', 'Next (Server)', 'Frodo (Nine Fingers)']
16
- */
17
-
18
- const isWindows = process.platform === 'win32';
19
-
20
- function getPresetsList(types = ['default', 'custom']) {
21
- const currentModuleFullPath = import.meta.url;
22
- let baselibPath = currentModuleFullPath.match(/(.*lib)(.*)/)[1];
23
- if (isWindows) {
24
- baselibPath = new URL(baselibPath).pathname;
25
- if (baselibPath.startsWith('/')) {
26
- baselibPath = baselibPath.slice(1);
27
- }
28
- }
29
- if (!isWindows) {
30
- baselibPath = baselibPath.replace('file://', '');
31
- }
32
-
33
- const presets = [];
34
-
35
- types.forEach((type) => {
36
- const presetsDir = path.join(baselibPath, `presets/${type}`);
37
- const folders = fs
38
- .readdirSync(presetsDir, { withFileTypes: true })
39
-
40
- .filter((dirent) => dirent.isDirectory())
41
- .flatMap((dirent) => {
42
- const presetName = dirent.name;
43
- const subDirs = fs
44
- .readdirSync(path.join(presetsDir, presetName), {
45
- withFileTypes: true,
46
- })
47
- .filter((subDirent) => subDirent.isDirectory());
48
-
49
- if (subDirs.length === 0) {
50
- return [presetName.charAt(0).toUpperCase() + presetName.slice(1)];
51
- }
52
-
53
- return subDirs.map((subDir) => {
54
- const subDirName =
55
- subDir.name.charAt(0).toUpperCase() + subDir.name.slice(1);
56
- return `${
57
- presetName.charAt(0).toUpperCase() + presetName.slice(1)
58
- } (${subDirName})`;
59
- });
60
- });
61
-
62
- presets.push(...folders);
63
- });
64
-
65
- return presets;
66
- }
67
-
68
- export default getPresetsList;
@@ -1,3 +0,0 @@
1
- import getPresetsList from './getPresetsList.utils.js';
2
-
3
- export default getPresetsList;