edge-functions 1.0.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 (230) hide show
  1. package/.babelrc +13 -0
  2. package/.eslintignore +3 -0
  3. package/.eslintrc.json +42 -0
  4. package/.github/workflows/major.yml +28 -0
  5. package/.github/workflows/minor.yml +31 -0
  6. package/.vscode/settings.json +20 -0
  7. package/CODEOWNERS +2 -0
  8. package/CODE_OF_CONDUCT.md +73 -0
  9. package/CONTRIBUTING.md +90 -0
  10. package/LICENSE.md +21 -0
  11. package/README.md +60 -0
  12. package/aliases.js +13 -0
  13. package/docs/overview.md +36 -0
  14. package/docs/presets.md +115 -0
  15. package/examples/angular-static/.editorconfig +16 -0
  16. package/examples/angular-static/README.md +27 -0
  17. package/examples/angular-static/angular.json +98 -0
  18. package/examples/angular-static/package.json +39 -0
  19. package/examples/angular-static/src/app/app-routing.module.ts +10 -0
  20. package/examples/angular-static/src/app/app.component.css +0 -0
  21. package/examples/angular-static/src/app/app.component.html +484 -0
  22. package/examples/angular-static/src/app/app.component.spec.ts +29 -0
  23. package/examples/angular-static/src/app/app.component.ts +10 -0
  24. package/examples/angular-static/src/app/app.module.ts +18 -0
  25. package/examples/angular-static/src/assets/.gitkeep +0 -0
  26. package/examples/angular-static/src/favicon.ico +0 -0
  27. package/examples/angular-static/src/index.html +13 -0
  28. package/examples/angular-static/src/main.ts +7 -0
  29. package/examples/angular-static/src/styles.css +1 -0
  30. package/examples/angular-static/tsconfig.app.json +14 -0
  31. package/examples/angular-static/tsconfig.json +33 -0
  32. package/examples/angular-static/tsconfig.spec.json +14 -0
  33. package/examples/astro-static/README.md +55 -0
  34. package/examples/astro-static/astro.config.mjs +5 -0
  35. package/examples/astro-static/package.json +15 -0
  36. package/examples/astro-static/public/favicon.svg +9 -0
  37. package/examples/astro-static/src/components/Card.astro +63 -0
  38. package/examples/astro-static/src/env.d.ts +1 -0
  39. package/examples/astro-static/src/layouts/Layout.astro +36 -0
  40. package/examples/astro-static/src/pages/edge/index.astro +55 -0
  41. package/examples/astro-static/src/pages/index.astro +81 -0
  42. package/examples/astro-static/tsconfig.json +3 -0
  43. package/examples/hexo-static/.github/dependabot.yml +7 -0
  44. package/examples/hexo-static/_config.landscape.yml +0 -0
  45. package/examples/hexo-static/_config.yml +105 -0
  46. package/examples/hexo-static/package.json +26 -0
  47. package/examples/hexo-static/scaffolds/draft.md +4 -0
  48. package/examples/hexo-static/scaffolds/page.md +4 -0
  49. package/examples/hexo-static/scaffolds/post.md +5 -0
  50. package/examples/hexo-static/source/_posts/hello-world.md +38 -0
  51. package/examples/hexo-static/source/_posts/other-page.md +62 -0
  52. package/examples/hexo-static/themes/.gitkeep +0 -0
  53. package/examples/hexo-static/yarn.lock +1625 -0
  54. package/examples/next-12-static/.babelrc +3 -0
  55. package/examples/next-12-static/README.md +21 -0
  56. package/examples/next-12-static/components/post.jsx +27 -0
  57. package/examples/next-12-static/package-lock.json +6191 -0
  58. package/examples/next-12-static/package.json +18 -0
  59. package/examples/next-12-static/pages/index.jsx +34 -0
  60. package/examples/next-12-static/pages/post/[id].jsx +63 -0
  61. package/examples/next-static/README.md +34 -0
  62. package/examples/next-static/jsconfig.json +7 -0
  63. package/examples/next-static/next.config.js +9 -0
  64. package/examples/next-static/package.json +16 -0
  65. package/examples/next-static/public/next.svg +1 -0
  66. package/examples/next-static/public/vercel.svg +1 -0
  67. package/examples/next-static/src/app/blog/[slug]/page.js +27 -0
  68. package/examples/next-static/src/app/favicon.ico +0 -0
  69. package/examples/next-static/src/app/globals.css +107 -0
  70. package/examples/next-static/src/app/layout.js +17 -0
  71. package/examples/next-static/src/app/misty-mountains/moria/page.js +15 -0
  72. package/examples/next-static/src/app/page.js +96 -0
  73. package/examples/next-static/src/app/page.module.css +229 -0
  74. package/examples/next-static/yarn.lock +199 -0
  75. package/examples/react-static/README.md +70 -0
  76. package/examples/react-static/package.json +38 -0
  77. package/examples/react-static/public/favicon.ico +0 -0
  78. package/examples/react-static/public/index.html +43 -0
  79. package/examples/react-static/public/logo192.png +0 -0
  80. package/examples/react-static/public/logo512.png +0 -0
  81. package/examples/react-static/public/manifest.json +25 -0
  82. package/examples/react-static/public/robots.txt +3 -0
  83. package/examples/react-static/src/App.css +38 -0
  84. package/examples/react-static/src/App.js +25 -0
  85. package/examples/react-static/src/App.test.js +8 -0
  86. package/examples/react-static/src/index.css +13 -0
  87. package/examples/react-static/src/index.js +17 -0
  88. package/examples/react-static/src/logo.svg +1 -0
  89. package/examples/react-static/src/reportWebVitals.js +13 -0
  90. package/examples/react-static/src/setupTests.js +5 -0
  91. package/examples/simple-js-esm/main.js +14 -0
  92. package/examples/simple-js-esm/messages.js +7 -0
  93. package/examples/simple-js-node/main.js +18 -0
  94. package/examples/vue-static/README.md +24 -0
  95. package/examples/vue-static/babel.config.js +5 -0
  96. package/examples/vue-static/jsconfig.json +19 -0
  97. package/examples/vue-static/package.json +45 -0
  98. package/examples/vue-static/public/favicon.ico +0 -0
  99. package/examples/vue-static/public/index.html +17 -0
  100. package/examples/vue-static/src/App.vue +16 -0
  101. package/examples/vue-static/src/assets/logo.png +0 -0
  102. package/examples/vue-static/src/components/HelloWorld.vue +58 -0
  103. package/examples/vue-static/src/main.js +28 -0
  104. package/examples/vue-static/src/views/Home.vue +14 -0
  105. package/examples/vue-static/vue.config.js +4 -0
  106. package/jest.config.js +6 -0
  107. package/jsconfig.json +40 -0
  108. package/jsdoc.json +52 -0
  109. package/lib/build/bundlers/index.js +4 -0
  110. package/lib/build/bundlers/webpack/index.js +40 -0
  111. package/lib/build/bundlers/webpack/webpack.config.js +38 -0
  112. package/lib/build/dispatcher/dispatcher.js +211 -0
  113. package/lib/build/dispatcher/dispatcher.test.js +0 -0
  114. package/lib/build/dispatcher/index.js +3 -0
  115. package/lib/build/polyfills/index.js +0 -0
  116. package/lib/constants/azion-edges.constants.js +98 -0
  117. package/lib/constants/index.js +5 -0
  118. package/lib/constants/messages/build.messages.js +23 -0
  119. package/lib/constants/messages/env.messages.js +38 -0
  120. package/lib/constants/messages/global.messages.js +19 -0
  121. package/lib/constants/messages/index.js +10 -0
  122. package/lib/constants/messages/platform.messages.js +84 -0
  123. package/lib/constants/runtime-apis.constants.js +118 -0
  124. package/lib/env/index.js +5 -0
  125. package/lib/env/runtime.env.js +69 -0
  126. package/lib/env/server.env.js +90 -0
  127. package/lib/env/vulcan.env.js +93 -0
  128. package/lib/main.js +260 -0
  129. package/lib/notations/namespaces.js +30 -0
  130. package/lib/notations/typedef.js +10 -0
  131. package/lib/platform/actions/application/createApplication.actions.js +33 -0
  132. package/lib/platform/actions/application/enableEdgeFunctions.actions.js +34 -0
  133. package/lib/platform/actions/application/instantiateFunction.actions.js +37 -0
  134. package/lib/platform/actions/application/setFunctionAsDefaultRule.actions.js +33 -0
  135. package/lib/platform/actions/core/auth.actions.js +67 -0
  136. package/lib/platform/actions/core/deploy.actions.js +73 -0
  137. package/lib/platform/actions/core/propagation.actions.js +75 -0
  138. package/lib/platform/actions/core/storage.actions.js +84 -0
  139. package/lib/platform/actions/domain/createDomain.actions.js +42 -0
  140. package/lib/platform/actions/function/createFunction.actions.js +79 -0
  141. package/lib/platform/actions/function/showFunctionLogs.actions.js +149 -0
  142. package/lib/platform/edgehooks/ErrorHTML/ErrorHTML.hooks.js +101 -0
  143. package/lib/platform/edgehooks/ErrorHTML/index.js +3 -0
  144. package/lib/platform/edgehooks/index.js +5 -0
  145. package/lib/platform/edgehooks/mountSPA/index.js +3 -0
  146. package/lib/platform/edgehooks/mountSPA/mountSPA.hooks.js +55 -0
  147. package/lib/platform/edgehooks/mountSPA/mountSPA.hooks.test.js +19 -0
  148. package/lib/platform/edgehooks/mountSSG/index.js +3 -0
  149. package/lib/platform/edgehooks/mountSSG/mountSSG.hooks.js +61 -0
  150. package/lib/platform/edgehooks/mountSSG/mountSSG.hooks.test.js +0 -0
  151. package/lib/platform/index.js +65 -0
  152. package/lib/platform/services/application.service.js +140 -0
  153. package/lib/platform/services/base.service.js +200 -0
  154. package/lib/platform/services/domain.service.js +80 -0
  155. package/lib/platform/services/events.service.js +65 -0
  156. package/lib/platform/services/function.service.js +105 -0
  157. package/lib/platform/services/index.js +8 -0
  158. package/lib/platform/services/storage.service.js +59 -0
  159. package/lib/platform/services/tokens.service.js +55 -0
  160. package/lib/presets/custom/angular/deliver/config.js +12 -0
  161. package/lib/presets/custom/angular/deliver/handler.js +8 -0
  162. package/lib/presets/custom/angular/deliver/prebuild.js +20 -0
  163. package/lib/presets/custom/astro/deliver/config.js +12 -0
  164. package/lib/presets/custom/astro/deliver/handler.js +8 -0
  165. package/lib/presets/custom/astro/deliver/prebuild.js +37 -0
  166. package/lib/presets/custom/hexo/deliver/config.js +12 -0
  167. package/lib/presets/custom/hexo/deliver/handler.js +8 -0
  168. package/lib/presets/custom/hexo/deliver/prebuild.js +37 -0
  169. package/lib/presets/custom/next/deliver/config.js +14 -0
  170. package/lib/presets/custom/next/deliver/handler.js +9 -0
  171. package/lib/presets/custom/next/deliver/prebuild.js +193 -0
  172. package/lib/presets/custom/react/deliver/config.js +12 -0
  173. package/lib/presets/custom/react/deliver/handler.js +8 -0
  174. package/lib/presets/custom/react/deliver/prebuild.js +16 -0
  175. package/lib/presets/custom/vue/deliver/config.js +12 -0
  176. package/lib/presets/custom/vue/deliver/handler.js +8 -0
  177. package/lib/presets/custom/vue/deliver/prebuild.js +20 -0
  178. package/lib/presets/default/html/deliver/config.js +13 -0
  179. package/lib/presets/default/html/deliver/handler.js +9 -0
  180. package/lib/presets/default/html/deliver/prebuild.js +15 -0
  181. package/lib/presets/default/javascript/compute/config.js +13 -0
  182. package/lib/presets/default/javascript/compute/handler.js +5 -0
  183. package/lib/presets/default/javascript/compute/prebuild.js +6 -0
  184. package/lib/presets/default/typescript/compute/config.js +0 -0
  185. package/lib/presets/default/typescript/compute/handler.js +0 -0
  186. package/lib/presets/default/typescript/compute/prebuild.js +0 -0
  187. package/lib/providers/azion/worker.js +12 -0
  188. package/lib/utils/copyDirectory/copyDirectory.utils.js +54 -0
  189. package/lib/utils/copyDirectory/copyDirectory.utils.test.js +43 -0
  190. package/lib/utils/copyDirectory/index.js +3 -0
  191. package/lib/utils/debug/debug.utils.js +36 -0
  192. package/lib/utils/debug/debug.utils.test.js +43 -0
  193. package/lib/utils/debug/index.js +3 -0
  194. package/lib/utils/exec/exec.utils.js +58 -0
  195. package/lib/utils/exec/exec.utils.test.js +84 -0
  196. package/lib/utils/exec/index.js +3 -0
  197. package/lib/utils/feedback/feedback.utils.js +81 -0
  198. package/lib/utils/feedback/feedback.utils.test.js +11 -0
  199. package/lib/utils/feedback/index.js +3 -0
  200. package/lib/utils/generateTimestamp/generateTimestamp.utils.js +25 -0
  201. package/lib/utils/generateTimestamp/generateTimestamp.utils.test.js +10 -0
  202. package/lib/utils/generateTimestamp/index.js +3 -0
  203. package/lib/utils/getAbsoluteLibDirPath/getAbsoluteLibDirPath.utils.js +21 -0
  204. package/lib/utils/getAbsoluteLibDirPath/getAbsoluteLibDirPath.utils.test.js +13 -0
  205. package/lib/utils/getAbsoluteLibDirPath/index.js +3 -0
  206. package/lib/utils/getPackageManager/getPackageManager.utils.js +118 -0
  207. package/lib/utils/getPackageManager/getPackageManager.utils.test.js +35 -0
  208. package/lib/utils/getPackageManager/index.js +3 -0
  209. package/lib/utils/getPackageVersion/getPackageVersion.utils.js +25 -0
  210. package/lib/utils/getPackageVersion/getPackageVersion.utils.test.js +48 -0
  211. package/lib/utils/getPackageVersion/index.js +3 -0
  212. package/lib/utils/getPresetsList/getPresetsList.utils.js +50 -0
  213. package/lib/utils/getPresetsList/getPresetsList.utils.test.js +19 -0
  214. package/lib/utils/getPresetsList/index.js +3 -0
  215. package/lib/utils/getProjectJsonFile/getProjectJsonFile.utils.js +21 -0
  216. package/lib/utils/getProjectJsonFile/getProjectJsonFile.utils.test.js +39 -0
  217. package/lib/utils/getProjectJsonFile/index.js +3 -0
  218. package/lib/utils/getVulcanBuildId/getVulcanBuildId.utils.js +49 -0
  219. package/lib/utils/getVulcanBuildId/getVulcanBuildId.utils.test.js +36 -0
  220. package/lib/utils/getVulcanBuildId/index.js +3 -0
  221. package/lib/utils/index.js +29 -0
  222. package/lib/utils/overrideStaticOutputPath/index.js +3 -0
  223. package/lib/utils/overrideStaticOutputPath/overrideStaticOutputPath.utils.js +47 -0
  224. package/lib/utils/overrideStaticOutputPath/overrideStaticOutputPath.utils.test.js +35 -0
  225. package/lib/utils/readWorkerFile/index.js +3 -0
  226. package/lib/utils/readWorkerFile/readWorkerFile.utils.js +36 -0
  227. package/lib/utils/readWorkerFile/readWorkerFile.utils.test.js +24 -0
  228. package/package.json +99 -0
  229. package/releaserc.json +87 -0
  230. package/tasks/sync-aliases.js +115 -0
package/lib/main.js ADDED
@@ -0,0 +1,260 @@
1
+ #! /usr/bin/env node
2
+ import path from 'path';
3
+ import { Command } from 'commander';
4
+ import { createPromptModule } from 'inquirer';
5
+ import { satisfies } from 'semver';
6
+ import { feedback, debug } from '#utils';
7
+ import { Messages } from '#constants';
8
+
9
+ const MIN_NODE_VERSION = '18.0.0';
10
+
11
+ const debugEnabled = process.env.DEBUG === 'true';
12
+ const version = process.env.npm_package_version;
13
+ const program = new Command();
14
+ const prompt = createPromptModule();
15
+
16
+ /**
17
+ * Validates if user is using the minimum Node version
18
+ * @returns {boolean} - indicates if is a valid version
19
+ */
20
+ function validateNodeMinVersion() {
21
+ const isAValidVersion = satisfies(process.version, `>= ${MIN_NODE_VERSION}`);
22
+
23
+ return isAValidVersion;
24
+ }
25
+
26
+ /**
27
+ * Sets the global Vulcan environment.
28
+ *
29
+ * Validates the ENV value and sets it as the environment in the global 'vulcan' object.
30
+ * If the ENV value is invalid, it throws an error and terminates the process.
31
+ * @throws {Error} If ENV is not one of 'production', 'stage', 'dev'.
32
+ * @example
33
+ * setVulcanEnvironment();
34
+ */
35
+ function setVulcanEnvironment() {
36
+ const ENV = process.env.AZION_ENV || 'production';
37
+ if (!['production', 'stage', 'local'].includes(ENV)) {
38
+ feedback.error(Messages.env.errors.invalid_environment);
39
+ process.exit(1);
40
+ } else {
41
+ globalThis.vulcan = { env: ENV };
42
+ }
43
+ }
44
+ /**
45
+ * Starts the command-line interface program.
46
+ * @example
47
+ * startProgram();
48
+ */
49
+ function startVulcanProgram() {
50
+ program.version(version);
51
+
52
+ if (debugEnabled) {
53
+ program
54
+ .command('auth')
55
+ .option(
56
+ '--password <username>:<password>',
57
+ 'Authenticate using username and password',
58
+ )
59
+ .option('--token <token>', 'Authenticate using personal token')
60
+ .description('Authenticate the CLI')
61
+ .action(async (options) => {
62
+ const { core } = await import('#platform');
63
+
64
+ const authOptions = [
65
+ {
66
+ name: 'Username and Password',
67
+ value: 'password',
68
+ },
69
+ {
70
+ name: 'Personal Token',
71
+ value: 'token',
72
+ },
73
+ ];
74
+
75
+ if (options.password) {
76
+ const [username, password] = options.password.split(':');
77
+ core.actions.auth('password', { username, password });
78
+ }
79
+
80
+ if (options.token) {
81
+ const { token } = options;
82
+ core.actions.auth('token', { token });
83
+ }
84
+
85
+ if (!options.token && !options.password) {
86
+ const { authOption } = await prompt([
87
+ {
88
+ type: 'list',
89
+ name: 'authOption',
90
+ message: 'Choose your login option:',
91
+ choices: authOptions.map((option) => option.name),
92
+ },
93
+ ]);
94
+
95
+ if (authOption === 'Username and Password') {
96
+ const { username, password } = await prompt([
97
+ {
98
+ type: 'input',
99
+ name: 'username',
100
+ message: 'Enter your username:',
101
+ },
102
+ {
103
+ type: 'password',
104
+ name: 'password',
105
+ message: 'Enter your password:',
106
+ },
107
+ ]);
108
+ core.actions.auth('password', { username, password });
109
+ }
110
+ if (authOption === 'Personal Token') {
111
+ const { token } = await prompt([
112
+ {
113
+ type: 'password',
114
+ name: 'token',
115
+ message: 'Enter your personal token:',
116
+ },
117
+ ]);
118
+ core.actions.auth('token', { token });
119
+ }
120
+ }
121
+ });
122
+
123
+ program
124
+ .command('run')
125
+ .description('Run Edge Function')
126
+ .arguments('<file>')
127
+ .option('-p, --port <port>', 'Specify the port', '3000')
128
+ .action(async (file, options) => {
129
+ const { port } = options;
130
+ const parsedPort = parseInt(port, 10);
131
+ const { server } = await import('#env');
132
+ const entryPoint = file || path.join(process.cwd(), '.edge/woker.js');
133
+ server(entryPoint, parsedPort);
134
+ });
135
+
136
+ program
137
+ .command('logs <type> [id]')
138
+ .description('Perform operations on function or application logs')
139
+ .option('-w, --watch', 'Show real-time logs')
140
+ .action(async (type, id, options) => {
141
+ const { functions } = await import('#platform');
142
+ const { watch } = options;
143
+
144
+ if (!['function', 'application'].includes(type)) {
145
+ feedback.error(Messages.platform.logs.errors.invalid_log_type);
146
+ return;
147
+ }
148
+
149
+ if (type === 'function') {
150
+ functions.actions.showFunctionLogs(id, watch);
151
+ }
152
+ if (type === 'application') {
153
+ feedback.info(Messages.platform.logs.info.unsupported_log_type);
154
+ }
155
+ });
156
+
157
+ program
158
+ .command('storage sync')
159
+ .description(
160
+ 'Synchronize local .edge/statics with the Edge Function storage',
161
+ )
162
+ .action(async () => {
163
+ const { core } = await import('#platform');
164
+ const { getVulcanBuildId } = await import('#utils');
165
+
166
+ const versionId = getVulcanBuildId();
167
+ const basePath = path.join(process.cwd(), '.edge/statics/');
168
+ await core.actions.uploadStatics(versionId, basePath);
169
+ });
170
+
171
+ program
172
+ .command('deploy')
173
+ .description('Create and deploy an application with a function')
174
+ .action(async () => {
175
+ const { core } = await import('#platform');
176
+ const { getVulcanBuildId } = await import('#utils');
177
+
178
+ const versionId = getVulcanBuildId();
179
+ const staticsPath = path.join(process.cwd(), '/.edge/statics');
180
+
181
+ const answers = await prompt([
182
+ {
183
+ type: 'input',
184
+ name: 'applicationName',
185
+ message:
186
+ 'Enter the name of the application (optional, leave empty for random name):',
187
+ },
188
+ {
189
+ type: 'input',
190
+ name: 'functionName',
191
+ message:
192
+ 'Enter the name of the function (optional, leave empty for random name):',
193
+ },
194
+ ]);
195
+
196
+ const { applicationName, functionName } = answers;
197
+
198
+ await core.actions.uploadStatics(versionId, staticsPath);
199
+ const domain = await core.actions.deploy(applicationName, functionName);
200
+ core.actions.watchPropagation(domain);
201
+ });
202
+ }
203
+
204
+ program
205
+ .command('build')
206
+ .description('Build a project for edge deployment')
207
+ .option(
208
+ '--preset <type>',
209
+ 'Preset of build target (e.g., vue, next, javascript)',
210
+ 'javascript',
211
+ )
212
+ .option(
213
+ '--mode <type>',
214
+ 'Mode of build target (e.g., deliver, compute)',
215
+ 'compute',
216
+ )
217
+ .option(
218
+ '--entry <string>',
219
+ 'Code entrypoint (default: ./main.js)',
220
+ './main.js',
221
+ )
222
+ .action(async ({
223
+ preset, mode, entry, versionId,
224
+ }) => {
225
+ // TODO: generate versionID in dispatcher (currently generated for webpackconfig)
226
+ const BuildDispatcher = (await import('#build')).default;
227
+ const buildDispatcher = new BuildDispatcher(
228
+ preset,
229
+ mode,
230
+ entry,
231
+ versionId,
232
+ );
233
+ await buildDispatcher.run();
234
+ });
235
+
236
+ program
237
+ .command('presets <type>')
238
+ .description('Create or use defined project presets for Edge.')
239
+ .action(async (type) => {
240
+ const { getPresetsList } = await import('#utils');
241
+ const presets = getPresetsList();
242
+
243
+ if (type === 'ls') {
244
+ presets.forEach((preset) => feedback.option(preset));
245
+ }
246
+ });
247
+ program.parse(process.argv);
248
+ }
249
+
250
+ try {
251
+ if (validateNodeMinVersion()) {
252
+ setVulcanEnvironment();
253
+ startVulcanProgram();
254
+ } else {
255
+ feedback.error(Messages.errors.invalid_node_version(MIN_NODE_VERSION));
256
+ }
257
+ } catch (error) {
258
+ feedback.error(Messages.errors.unknown_error);
259
+ debug.error(error);
260
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @namespace utils
3
+ * @description Provides utility functions for various tasks.
4
+ */
5
+
6
+ /**
7
+ * @namespace platform
8
+ * @description Contains functions and actions to interact with the edge platform (Azion).
9
+ */
10
+
11
+ /**
12
+ * @namespace build
13
+ * @description Represents the structure responsible for pre-build and build processes for the edge.
14
+ */
15
+
16
+ /**
17
+ * @namespace env
18
+ * @description Contains codes and functions responsible for managing the local environment.
19
+ */
20
+
21
+ /**
22
+ * @namespace presets
23
+ * @description Contains presets with pre-configured workers and
24
+ * Presets available to run on the edge.
25
+ */
26
+
27
+ /**
28
+ * @namespace edge
29
+ * @description Contains imported and computer-ready functions for use on the edge.
30
+ */
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @typedef {object} FetchEvent
3
+ * @property {Request} request - This interface represents a resource request.
4
+ * @property {Promise<Response>} respondWith - This interface prevents the browser's
5
+ * default fetch handling, and allows you to provide a promise for a Response yourself.
6
+ * @property {function(): void} waitUntil - his interface is used to inform the browser
7
+ * not to terminate the Service Worker until
8
+ * the promise passed to `waitUntil` is either resolved or rejected.
9
+ * @description Represents an event that is dispatched to a worker when a fetch event occurs.
10
+ */
@@ -0,0 +1,33 @@
1
+ import { debug } from '#utils';
2
+ import ApplicationService from '../../services/application.service.js';
3
+ /**
4
+ * @function
5
+ * @memberof platform
6
+ * @name createApplication
7
+ * @description Creates a new application using the specified application name.
8
+ * @param {string} applicationName - The name of the new application.
9
+ * @returns {Promise<object>} A promise that resolves to the newly created application object.
10
+ * @throws Will throw an error if the creation process fails.
11
+ * @example
12
+ * try {
13
+ * const newApp = await createApplication('My New Application');
14
+ * console.log(newApp);
15
+ * } catch (error) {
16
+ * console.error(error);
17
+ * }
18
+ */
19
+ async function createApplication(applicationName) {
20
+ try {
21
+ const payload = {
22
+ name: applicationName,
23
+ delivery_protocol: 'http,https',
24
+ };
25
+ const response = await (await ApplicationService.create(payload)).json();
26
+ return response.results;
27
+ } catch (error) {
28
+ debug.error(error);
29
+ throw error;
30
+ }
31
+ }
32
+
33
+ export default createApplication;
@@ -0,0 +1,34 @@
1
+ import { debug } from '#utils';
2
+ import ApplicationService from '../../services/application.service.js';
3
+ /**
4
+ * @function
5
+ * @memberof platform
6
+ * @name enableEdgeFunctions
7
+ * @description Enables edge functions for the specified application.
8
+ * @param {number} applicationId - The unique identifier of the application.
9
+ * @returns {Promise<object>} A promise that resolves to the updated application
10
+ * object with edge functions enabled.
11
+ * @throws Will throw an error if the update process fails.
12
+ * @example
13
+ * try {
14
+ * const updatedApp = await enableEdgeFunctions(12345);
15
+ * console.log(updatedApp);
16
+ * } catch (error) {
17
+ * console.error(error);
18
+ * }
19
+ */
20
+ async function enableEdgeFunctions(applicationId) {
21
+ try {
22
+ const payload = {
23
+ edge_functions: true,
24
+ };
25
+
26
+ const response = await (await ApplicationService.update(applicationId, payload)).json();
27
+ return response.results;
28
+ } catch (error) {
29
+ debug.error(error);
30
+ throw error;
31
+ }
32
+ }
33
+
34
+ export default enableEdgeFunctions;
@@ -0,0 +1,37 @@
1
+ import { debug } from '#utils';
2
+ import ApplicationService from '../../services/application.service.js';
3
+
4
+ /**
5
+ * @function
6
+ * @memberof platform
7
+ * @name instantiateFunction
8
+ * @description Instantiates an edge function in the specified application.
9
+ * @param {string} functionName - The name of the function to be instantiated.
10
+ * @param {number} functionId - The unique identifier of the function to be instantiated.
11
+ * @param {number} applicationId - The unique identifier of the application.
12
+ * @returns {Promise<object>} A promise that resolves to the instantiated edge function object.
13
+ * @throws Will throw an error if the instantiation process fails.
14
+ * @example
15
+ * try {
16
+ * const instantiatedFunc = await instantiateFunction('My Function', 123, 456);
17
+ * console.log(instantiatedFunc);
18
+ * } catch (error) {
19
+ * console.error(error);
20
+ * }
21
+ */
22
+ async function instantiateFunction(functionName, functionId, applicationId) {
23
+ const payload = {
24
+ name: functionName,
25
+ edge_function_id: functionId,
26
+ args: {},
27
+ };
28
+ try {
29
+ const response = await (await ApplicationService.instantiate(applicationId, payload)).json();
30
+ return response.results;
31
+ } catch (error) {
32
+ debug.error(error);
33
+ throw error;
34
+ }
35
+ }
36
+
37
+ export default instantiateFunction;
@@ -0,0 +1,33 @@
1
+ import { debug } from '#utils';
2
+ import ApplicationService from '../../services/application.service.js';
3
+ /**
4
+ * Sets a function as the default rule in an application's rules engine.
5
+ * @param {number} applicationId - The ID of the application.
6
+ * @param {number} functionInstanceId - The ID of the edge function instance.
7
+ * @returns {Promise<object>} The updated rules engine rules.
8
+ */
9
+ async function setFunctionAsDefaultRule(applicationId, functionInstanceId) {
10
+ try {
11
+ const rulesResponse = await (await ApplicationService.getRules(applicationId)).json();
12
+ const defaultRuleId = rulesResponse.results[0].id;
13
+
14
+ const payload = {
15
+ behaviors: [
16
+ {
17
+ name: 'run_function',
18
+ target: functionInstanceId,
19
+ },
20
+ ],
21
+ };
22
+
23
+ const response = await
24
+ (await ApplicationService.updateRule(applicationId, defaultRuleId, payload))
25
+ .json();
26
+ return response.results;
27
+ } catch (error) {
28
+ debug.error(error);
29
+ throw error;
30
+ }
31
+ }
32
+
33
+ export default setFunctionAsDefaultRule;
@@ -0,0 +1,67 @@
1
+ import { vulcan } from '#env';
2
+ import { Messages } from '#constants';
3
+ import { feedback, debug } from '#utils';
4
+ import TokensService from '../../services/tokens.service.js';
5
+ import FunctionService from '../../services/function.service.js';
6
+
7
+ /**
8
+ * @function
9
+ * @memberof platform
10
+ * @name auth
11
+ * @description Authenticates the user with the provided credentials.
12
+ * @param {string} loginOption - The chosen login method. Valid values are
13
+ * 'username/password' and 'token'.
14
+ * @param {object} credentials - The user credentials required for authentication.
15
+ * @param {string} [credentials.username] - Required for 'username/password' option.
16
+ * Represents the username for password-based authentication.
17
+ * @param {string} [credentials.password] - Required for 'username/password' option.
18
+ * Represents the password for password-based authentication.
19
+ * @param {string} [credentials.token] - Required for 'token' option.
20
+ * Represents the personal token for token-based authentication.
21
+ * @returns {void}
22
+ * @throws Will throw an error if the authentication process fails.
23
+ * @example
24
+ * // For 'username/password' option
25
+ * try {
26
+ * await auth('password', { username: 'exampleUser', password: 'examplePass' });
27
+ * } catch (error) {
28
+ * console.error(error);
29
+ * }
30
+ * // For 'token' option
31
+ * try {
32
+ * await auth('token', { token: 'exampleToken' });
33
+ * } catch (error) {
34
+ * console.error(error);
35
+ * }
36
+ */
37
+ async function auth(loginOption, credentials) {
38
+ try {
39
+ if (loginOption === 'password') {
40
+ const response = await TokensService.create(credentials.username, credentials.password);
41
+ const responseJSON = await response.json();
42
+
43
+ if (!responseJSON.token) {
44
+ feedback.error(responseJSON);
45
+ }
46
+ if (responseJSON.token) {
47
+ await vulcan.createVulcanEnv('API_TOKEN', responseJSON.token);
48
+ feedback.success(Messages.platform.auth.success.api_auth_success);
49
+ }
50
+ }
51
+ if (loginOption === 'token') {
52
+ await vulcan.createVulcanEnv('API_TOKEN', credentials.token);
53
+ const validateTokenJSON = await (await FunctionService.getAll()).json();
54
+ if (validateTokenJSON.results) {
55
+ feedback.success(Messages.platform.auth.success.auth_success);
56
+ }
57
+ if (!validateTokenJSON.results) {
58
+ throw new Error(JSON.stringify(validateTokenJSON));
59
+ }
60
+ }
61
+ } catch (error) {
62
+ debug.error(error);
63
+ feedback.success(Messages.platform.auth.error.auth_failed);
64
+ }
65
+ }
66
+
67
+ export default auth;
@@ -0,0 +1,73 @@
1
+ import { feedback, generateTimestamp, debug } from '#utils';
2
+ import { Messages } from '#constants';
3
+
4
+ import createApplication from '../application/createApplication.actions.js';
5
+
6
+ import instantiateFunction from '../application/instantiateFunction.actions.js';
7
+ import enableEdgeFunctions from '../application/enableEdgeFunctions.actions.js';
8
+ import setFunctionAsDefaultRule from '../application/setFunctionAsDefaultRule.actions.js';
9
+ import createDomain from '../domain/createDomain.actions.js';
10
+ import createFunction from '../function/createFunction.actions.js';
11
+
12
+ /**
13
+ * @function
14
+ * @memberof platform
15
+ * @name deploy
16
+ * @description Creates a new application from scratch, performing several steps including
17
+ * function creation, application creation, enabling edge functions, function instantiation,
18
+ * rule setting, and domain creation. If names are not provided, they will be auto-generated
19
+ * using a timestamp.
20
+ * @param {string} [applicationName] - The name of the application to be created. If not provided,
21
+ * it will be auto-generated as `vulcan-${generateTimestamp()}`.
22
+ * @param {string} [functionName] - The name of the function to be instantiated. If not provided,
23
+ * it will be auto-generated as `vulcan-${generateTimestamp()}`.
24
+ * @param {string} [domainName] - The name of the domain to be created. If not provided, it will be
25
+ * auto-generated as `vulcan-${generateTimestamp()}`.
26
+ * @returns {Promise<string>} A promise that resolves to the domain of the newly
27
+ * created application.
28
+ * @throws Will throw an error if any step in the deployment process fails.
29
+ * @example
30
+ * try {
31
+ * const domain = await deploy('myApplication', 'myFunction', 'myDomain');
32
+ * console.log('Domain of the new application:', domain);
33
+ * } catch (error) {
34
+ * console.error(error);
35
+ * }
36
+ */
37
+ async function deploy(applicationName, functionName, domainName) {
38
+ try {
39
+ const timestamp = generateTimestamp();
40
+ const deployId = `vulcan-${timestamp}`;
41
+
42
+ feedback.platform.interactive.await(`[%d/6] - ${Messages.platform.deploy.info.creating_edge_function}`, 1);
43
+ const generatedFunctionName = functionName || deployId;
44
+ const edgeFunctionId = (await createFunction(generatedFunctionName)).id;
45
+
46
+ feedback.platform.interactive.await(`[%d/6] - ${Messages.platform.deploy.info.creating_edge_application}`, 2);
47
+ const generatedApplicationName = applicationName || deployId;
48
+ const edgeApplicationId = (await createApplication(generatedApplicationName)).id;
49
+
50
+ feedback.platform.interactive.await(`[%d/6] - ${Messages.platform.deploy.info.activating_edge_function}`, 3);
51
+ await enableEdgeFunctions(edgeApplicationId);
52
+
53
+ feedback.platform.interactive.await(`[%d/6] - ${Messages.platform.deploy.info.instantiating_edge_function}`, 4);
54
+ const functionInstanceId = (await
55
+ instantiateFunction(generatedFunctionName, edgeFunctionId, edgeApplicationId)).id;
56
+
57
+ feedback.platform.interactive.await(`[%d/6] - ${Messages.platform.deploy.info.creating_rule_engine}`, 5);
58
+ await setFunctionAsDefaultRule(edgeApplicationId, functionInstanceId);
59
+
60
+ feedback.platform.interactive.await(`[%d/6] - ${Messages.platform.deploy.info.creating_domain}`, 6);
61
+ const generatedDomainName = domainName || deployId;
62
+ const domain = (await createDomain(generatedDomainName, edgeApplicationId)).domain_name;
63
+ feedback.platform.interactive.complete(Messages.platform.deploy.success.deploy_finished);
64
+ feedback.platform.interactive.breakInteractiveChain();
65
+
66
+ return domain;
67
+ } catch (error) {
68
+ feedback.platform.error(Messages.platform.deploy.error.deploy_failed);
69
+ debug.error(error);
70
+ throw error;
71
+ }
72
+ }
73
+ export default deploy;
@@ -0,0 +1,75 @@
1
+ import { AzionEdges, Messages } from '#constants';
2
+ import { feedback, debug } from '#utils';
3
+ import open from 'open';
4
+ /**
5
+ * @function
6
+ * @memberof platform
7
+ * @name watchPropagation
8
+ * @description Monitors the propagation of a domain across the edge networks after the FIRST
9
+ * deployment. This function fetches the specified domain at regular intervals to check for
10
+ * propagation status. It interprets a 404 response as indicating that the domain is still
11
+ * propagating. Any other response is taken to mean that the domain has successfully
12
+ * propagated to the edge networks and is ready for access.
13
+ * @param {string} domain - The domain to monitor for propagation across the edge networks.
14
+ * @throws Will throw an error if there is a failure during the monitoring process.
15
+ * @example
16
+ * try {
17
+ * watchPropagation('myDomain.com');
18
+ * } catch (error) {
19
+ * console.error(error);
20
+ * }
21
+ */
22
+ function watchPropagation(domain) {
23
+ let currentEdgeIndex = 0;
24
+ let intervalId = null;
25
+ const f = feedback.propagation; // TODO: workaround -> improve
26
+
27
+ const performFetch = async () => {
28
+ try {
29
+ const response = await fetch(`https://${domain}`);
30
+ if (response.status === 404) {
31
+ f.interactive.await(
32
+ Messages.platform.propagation.info.propagating(
33
+ AzionEdges[currentEdgeIndex],
34
+ ),
35
+ );
36
+ currentEdgeIndex = (currentEdgeIndex + 1) % AzionEdges.length;
37
+ } else {
38
+ clearInterval(intervalId);
39
+
40
+ let remainingEdgeIndex = currentEdgeIndex + 1;
41
+ const remainingEdgesIntervalId = setInterval(() => {
42
+ if (remainingEdgeIndex >= AzionEdges.length) {
43
+ clearInterval(remainingEdgesIntervalId);
44
+ f.interactive.complete(
45
+ Messages.platform.propagation.success.propagation_complete,
46
+ );
47
+ open(`https://${domain}`);
48
+ process.exit(0);
49
+ } else {
50
+ const remainingEdge = AzionEdges[remainingEdgeIndex];
51
+ f.interactive.await(
52
+ Messages.platform.propagation.info.propagating(remainingEdge),
53
+ );
54
+ // eslint-disable-next-line no-plusplus
55
+ remainingEdgeIndex++;
56
+ }
57
+ }, 150);
58
+ }
59
+ } catch (error) {
60
+ debug.error(error);
61
+ f.interactive.fatal(
62
+ Messages.propagation.errors.watch_propagation_failed,
63
+ );
64
+ }
65
+ };
66
+
67
+ // Perform the first fetch immediately
68
+ performFetch();
69
+
70
+ // Start the interval
71
+ intervalId = setInterval(performFetch, 10000);
72
+ }
73
+
74
+ // eslint-disable-next-line import/prefer-default-export
75
+ export { watchPropagation };