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.
- package/.babelrc +13 -0
- package/.eslintignore +3 -0
- package/.eslintrc.json +42 -0
- package/.github/workflows/major.yml +28 -0
- package/.github/workflows/minor.yml +31 -0
- package/.vscode/settings.json +20 -0
- package/CODEOWNERS +2 -0
- package/CODE_OF_CONDUCT.md +73 -0
- package/CONTRIBUTING.md +90 -0
- package/LICENSE.md +21 -0
- package/README.md +60 -0
- package/aliases.js +13 -0
- package/docs/overview.md +36 -0
- package/docs/presets.md +115 -0
- package/examples/angular-static/.editorconfig +16 -0
- package/examples/angular-static/README.md +27 -0
- package/examples/angular-static/angular.json +98 -0
- package/examples/angular-static/package.json +39 -0
- package/examples/angular-static/src/app/app-routing.module.ts +10 -0
- package/examples/angular-static/src/app/app.component.css +0 -0
- package/examples/angular-static/src/app/app.component.html +484 -0
- package/examples/angular-static/src/app/app.component.spec.ts +29 -0
- package/examples/angular-static/src/app/app.component.ts +10 -0
- package/examples/angular-static/src/app/app.module.ts +18 -0
- package/examples/angular-static/src/assets/.gitkeep +0 -0
- package/examples/angular-static/src/favicon.ico +0 -0
- package/examples/angular-static/src/index.html +13 -0
- package/examples/angular-static/src/main.ts +7 -0
- package/examples/angular-static/src/styles.css +1 -0
- package/examples/angular-static/tsconfig.app.json +14 -0
- package/examples/angular-static/tsconfig.json +33 -0
- package/examples/angular-static/tsconfig.spec.json +14 -0
- package/examples/astro-static/README.md +55 -0
- package/examples/astro-static/astro.config.mjs +5 -0
- package/examples/astro-static/package.json +15 -0
- package/examples/astro-static/public/favicon.svg +9 -0
- package/examples/astro-static/src/components/Card.astro +63 -0
- package/examples/astro-static/src/env.d.ts +1 -0
- package/examples/astro-static/src/layouts/Layout.astro +36 -0
- package/examples/astro-static/src/pages/edge/index.astro +55 -0
- package/examples/astro-static/src/pages/index.astro +81 -0
- package/examples/astro-static/tsconfig.json +3 -0
- package/examples/hexo-static/.github/dependabot.yml +7 -0
- package/examples/hexo-static/_config.landscape.yml +0 -0
- package/examples/hexo-static/_config.yml +105 -0
- package/examples/hexo-static/package.json +26 -0
- package/examples/hexo-static/scaffolds/draft.md +4 -0
- package/examples/hexo-static/scaffolds/page.md +4 -0
- package/examples/hexo-static/scaffolds/post.md +5 -0
- package/examples/hexo-static/source/_posts/hello-world.md +38 -0
- package/examples/hexo-static/source/_posts/other-page.md +62 -0
- package/examples/hexo-static/themes/.gitkeep +0 -0
- package/examples/hexo-static/yarn.lock +1625 -0
- package/examples/next-12-static/.babelrc +3 -0
- package/examples/next-12-static/README.md +21 -0
- package/examples/next-12-static/components/post.jsx +27 -0
- package/examples/next-12-static/package-lock.json +6191 -0
- package/examples/next-12-static/package.json +18 -0
- package/examples/next-12-static/pages/index.jsx +34 -0
- package/examples/next-12-static/pages/post/[id].jsx +63 -0
- package/examples/next-static/README.md +34 -0
- package/examples/next-static/jsconfig.json +7 -0
- package/examples/next-static/next.config.js +9 -0
- package/examples/next-static/package.json +16 -0
- package/examples/next-static/public/next.svg +1 -0
- package/examples/next-static/public/vercel.svg +1 -0
- package/examples/next-static/src/app/blog/[slug]/page.js +27 -0
- package/examples/next-static/src/app/favicon.ico +0 -0
- package/examples/next-static/src/app/globals.css +107 -0
- package/examples/next-static/src/app/layout.js +17 -0
- package/examples/next-static/src/app/misty-mountains/moria/page.js +15 -0
- package/examples/next-static/src/app/page.js +96 -0
- package/examples/next-static/src/app/page.module.css +229 -0
- package/examples/next-static/yarn.lock +199 -0
- package/examples/react-static/README.md +70 -0
- package/examples/react-static/package.json +38 -0
- package/examples/react-static/public/favicon.ico +0 -0
- package/examples/react-static/public/index.html +43 -0
- package/examples/react-static/public/logo192.png +0 -0
- package/examples/react-static/public/logo512.png +0 -0
- package/examples/react-static/public/manifest.json +25 -0
- package/examples/react-static/public/robots.txt +3 -0
- package/examples/react-static/src/App.css +38 -0
- package/examples/react-static/src/App.js +25 -0
- package/examples/react-static/src/App.test.js +8 -0
- package/examples/react-static/src/index.css +13 -0
- package/examples/react-static/src/index.js +17 -0
- package/examples/react-static/src/logo.svg +1 -0
- package/examples/react-static/src/reportWebVitals.js +13 -0
- package/examples/react-static/src/setupTests.js +5 -0
- package/examples/simple-js-esm/main.js +14 -0
- package/examples/simple-js-esm/messages.js +7 -0
- package/examples/simple-js-node/main.js +18 -0
- package/examples/vue-static/README.md +24 -0
- package/examples/vue-static/babel.config.js +5 -0
- package/examples/vue-static/jsconfig.json +19 -0
- package/examples/vue-static/package.json +45 -0
- package/examples/vue-static/public/favicon.ico +0 -0
- package/examples/vue-static/public/index.html +17 -0
- package/examples/vue-static/src/App.vue +16 -0
- package/examples/vue-static/src/assets/logo.png +0 -0
- package/examples/vue-static/src/components/HelloWorld.vue +58 -0
- package/examples/vue-static/src/main.js +28 -0
- package/examples/vue-static/src/views/Home.vue +14 -0
- package/examples/vue-static/vue.config.js +4 -0
- package/jest.config.js +6 -0
- package/jsconfig.json +40 -0
- package/jsdoc.json +52 -0
- package/lib/build/bundlers/index.js +4 -0
- package/lib/build/bundlers/webpack/index.js +40 -0
- package/lib/build/bundlers/webpack/webpack.config.js +38 -0
- package/lib/build/dispatcher/dispatcher.js +211 -0
- package/lib/build/dispatcher/dispatcher.test.js +0 -0
- package/lib/build/dispatcher/index.js +3 -0
- package/lib/build/polyfills/index.js +0 -0
- package/lib/constants/azion-edges.constants.js +98 -0
- package/lib/constants/index.js +5 -0
- package/lib/constants/messages/build.messages.js +23 -0
- package/lib/constants/messages/env.messages.js +38 -0
- package/lib/constants/messages/global.messages.js +19 -0
- package/lib/constants/messages/index.js +10 -0
- package/lib/constants/messages/platform.messages.js +84 -0
- package/lib/constants/runtime-apis.constants.js +118 -0
- package/lib/env/index.js +5 -0
- package/lib/env/runtime.env.js +69 -0
- package/lib/env/server.env.js +90 -0
- package/lib/env/vulcan.env.js +93 -0
- package/lib/main.js +260 -0
- package/lib/notations/namespaces.js +30 -0
- package/lib/notations/typedef.js +10 -0
- package/lib/platform/actions/application/createApplication.actions.js +33 -0
- package/lib/platform/actions/application/enableEdgeFunctions.actions.js +34 -0
- package/lib/platform/actions/application/instantiateFunction.actions.js +37 -0
- package/lib/platform/actions/application/setFunctionAsDefaultRule.actions.js +33 -0
- package/lib/platform/actions/core/auth.actions.js +67 -0
- package/lib/platform/actions/core/deploy.actions.js +73 -0
- package/lib/platform/actions/core/propagation.actions.js +75 -0
- package/lib/platform/actions/core/storage.actions.js +84 -0
- package/lib/platform/actions/domain/createDomain.actions.js +42 -0
- package/lib/platform/actions/function/createFunction.actions.js +79 -0
- package/lib/platform/actions/function/showFunctionLogs.actions.js +149 -0
- package/lib/platform/edgehooks/ErrorHTML/ErrorHTML.hooks.js +101 -0
- package/lib/platform/edgehooks/ErrorHTML/index.js +3 -0
- package/lib/platform/edgehooks/index.js +5 -0
- package/lib/platform/edgehooks/mountSPA/index.js +3 -0
- package/lib/platform/edgehooks/mountSPA/mountSPA.hooks.js +55 -0
- package/lib/platform/edgehooks/mountSPA/mountSPA.hooks.test.js +19 -0
- package/lib/platform/edgehooks/mountSSG/index.js +3 -0
- package/lib/platform/edgehooks/mountSSG/mountSSG.hooks.js +61 -0
- package/lib/platform/edgehooks/mountSSG/mountSSG.hooks.test.js +0 -0
- package/lib/platform/index.js +65 -0
- package/lib/platform/services/application.service.js +140 -0
- package/lib/platform/services/base.service.js +200 -0
- package/lib/platform/services/domain.service.js +80 -0
- package/lib/platform/services/events.service.js +65 -0
- package/lib/platform/services/function.service.js +105 -0
- package/lib/platform/services/index.js +8 -0
- package/lib/platform/services/storage.service.js +59 -0
- package/lib/platform/services/tokens.service.js +55 -0
- package/lib/presets/custom/angular/deliver/config.js +12 -0
- package/lib/presets/custom/angular/deliver/handler.js +8 -0
- package/lib/presets/custom/angular/deliver/prebuild.js +20 -0
- package/lib/presets/custom/astro/deliver/config.js +12 -0
- package/lib/presets/custom/astro/deliver/handler.js +8 -0
- package/lib/presets/custom/astro/deliver/prebuild.js +37 -0
- package/lib/presets/custom/hexo/deliver/config.js +12 -0
- package/lib/presets/custom/hexo/deliver/handler.js +8 -0
- package/lib/presets/custom/hexo/deliver/prebuild.js +37 -0
- package/lib/presets/custom/next/deliver/config.js +14 -0
- package/lib/presets/custom/next/deliver/handler.js +9 -0
- package/lib/presets/custom/next/deliver/prebuild.js +193 -0
- package/lib/presets/custom/react/deliver/config.js +12 -0
- package/lib/presets/custom/react/deliver/handler.js +8 -0
- package/lib/presets/custom/react/deliver/prebuild.js +16 -0
- package/lib/presets/custom/vue/deliver/config.js +12 -0
- package/lib/presets/custom/vue/deliver/handler.js +8 -0
- package/lib/presets/custom/vue/deliver/prebuild.js +20 -0
- package/lib/presets/default/html/deliver/config.js +13 -0
- package/lib/presets/default/html/deliver/handler.js +9 -0
- package/lib/presets/default/html/deliver/prebuild.js +15 -0
- package/lib/presets/default/javascript/compute/config.js +13 -0
- package/lib/presets/default/javascript/compute/handler.js +5 -0
- package/lib/presets/default/javascript/compute/prebuild.js +6 -0
- package/lib/presets/default/typescript/compute/config.js +0 -0
- package/lib/presets/default/typescript/compute/handler.js +0 -0
- package/lib/presets/default/typescript/compute/prebuild.js +0 -0
- package/lib/providers/azion/worker.js +12 -0
- package/lib/utils/copyDirectory/copyDirectory.utils.js +54 -0
- package/lib/utils/copyDirectory/copyDirectory.utils.test.js +43 -0
- package/lib/utils/copyDirectory/index.js +3 -0
- package/lib/utils/debug/debug.utils.js +36 -0
- package/lib/utils/debug/debug.utils.test.js +43 -0
- package/lib/utils/debug/index.js +3 -0
- package/lib/utils/exec/exec.utils.js +58 -0
- package/lib/utils/exec/exec.utils.test.js +84 -0
- package/lib/utils/exec/index.js +3 -0
- package/lib/utils/feedback/feedback.utils.js +81 -0
- package/lib/utils/feedback/feedback.utils.test.js +11 -0
- package/lib/utils/feedback/index.js +3 -0
- package/lib/utils/generateTimestamp/generateTimestamp.utils.js +25 -0
- package/lib/utils/generateTimestamp/generateTimestamp.utils.test.js +10 -0
- package/lib/utils/generateTimestamp/index.js +3 -0
- package/lib/utils/getAbsoluteLibDirPath/getAbsoluteLibDirPath.utils.js +21 -0
- package/lib/utils/getAbsoluteLibDirPath/getAbsoluteLibDirPath.utils.test.js +13 -0
- package/lib/utils/getAbsoluteLibDirPath/index.js +3 -0
- package/lib/utils/getPackageManager/getPackageManager.utils.js +118 -0
- package/lib/utils/getPackageManager/getPackageManager.utils.test.js +35 -0
- package/lib/utils/getPackageManager/index.js +3 -0
- package/lib/utils/getPackageVersion/getPackageVersion.utils.js +25 -0
- package/lib/utils/getPackageVersion/getPackageVersion.utils.test.js +48 -0
- package/lib/utils/getPackageVersion/index.js +3 -0
- package/lib/utils/getPresetsList/getPresetsList.utils.js +50 -0
- package/lib/utils/getPresetsList/getPresetsList.utils.test.js +19 -0
- package/lib/utils/getPresetsList/index.js +3 -0
- package/lib/utils/getProjectJsonFile/getProjectJsonFile.utils.js +21 -0
- package/lib/utils/getProjectJsonFile/getProjectJsonFile.utils.test.js +39 -0
- package/lib/utils/getProjectJsonFile/index.js +3 -0
- package/lib/utils/getVulcanBuildId/getVulcanBuildId.utils.js +49 -0
- package/lib/utils/getVulcanBuildId/getVulcanBuildId.utils.test.js +36 -0
- package/lib/utils/getVulcanBuildId/index.js +3 -0
- package/lib/utils/index.js +29 -0
- package/lib/utils/overrideStaticOutputPath/index.js +3 -0
- package/lib/utils/overrideStaticOutputPath/overrideStaticOutputPath.utils.js +47 -0
- package/lib/utils/overrideStaticOutputPath/overrideStaticOutputPath.utils.test.js +35 -0
- package/lib/utils/readWorkerFile/index.js +3 -0
- package/lib/utils/readWorkerFile/readWorkerFile.utils.js +36 -0
- package/lib/utils/readWorkerFile/readWorkerFile.utils.test.js +24 -0
- package/package.json +99 -0
- package/releaserc.json +87 -0
- package/tasks/sync-aliases.js +115 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
mkdtempSync, writeFileSync, mkdirSync, rmdirSync, existsSync, readFileSync,
|
|
3
|
+
} from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
|
|
6
|
+
import copyDirectory from './index.js';
|
|
7
|
+
|
|
8
|
+
describe('copyDirectory utils', () => {
|
|
9
|
+
let sourceDir;
|
|
10
|
+
let targetDir;
|
|
11
|
+
|
|
12
|
+
beforeAll(async () => {
|
|
13
|
+
sourceDir = mkdtempSync(join(__dirname, 'tmp-source'));
|
|
14
|
+
targetDir = mkdtempSync(join(__dirname, 'tmp-target'));
|
|
15
|
+
|
|
16
|
+
writeFileSync(join(sourceDir, 'file1.txt'), 'Test example 1.');
|
|
17
|
+
mkdirSync(join(sourceDir, 'subdir'));
|
|
18
|
+
writeFileSync(join(sourceDir, 'subdir', 'file2.txt'), 'Text example 2.');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
afterAll(() => {
|
|
22
|
+
rmdirSync(sourceDir, { recursive: true });
|
|
23
|
+
rmdirSync(targetDir, { recursive: true });
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('Should recursively copy a directory to the target directory.', async () => {
|
|
27
|
+
copyDirectory(sourceDir, targetDir);
|
|
28
|
+
|
|
29
|
+
const copiedFile1 = existsSync(join(targetDir, 'file1.txt'));
|
|
30
|
+
const copiedFile2 = existsSync(join(targetDir, 'subdir', 'file2.txt'));
|
|
31
|
+
|
|
32
|
+
expect(copiedFile1).toBeTruthy();
|
|
33
|
+
expect(copiedFile2).toBeTruthy();
|
|
34
|
+
|
|
35
|
+
const originalFile1Contents = readFileSync(join(sourceDir, 'file1.txt'), 'utf-8');
|
|
36
|
+
const originalFile2Contents = readFileSync(join(sourceDir, 'subdir', 'file2.txt'), 'utf-8');
|
|
37
|
+
const copiedFile1Contents = readFileSync(join(targetDir, 'file1.txt'), 'utf-8');
|
|
38
|
+
const copiedFile2Contents = readFileSync(join(targetDir, 'subdir', 'file2.txt'), 'utf-8');
|
|
39
|
+
|
|
40
|
+
expect(copiedFile1Contents).toBe(originalFile1Contents);
|
|
41
|
+
expect(copiedFile2Contents).toBe(originalFile2Contents);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug method that conditionally logs based on process.env.DEBUG.
|
|
3
|
+
* Inherits all methods from console.log.
|
|
4
|
+
* @function
|
|
5
|
+
* @name debug
|
|
6
|
+
* @memberof utils
|
|
7
|
+
* @param {...*} args - Arguments to be logged.
|
|
8
|
+
* @description By default, process.env.DEBUG is set to false.
|
|
9
|
+
* When enabled, this method overrides console.log and allows you to log debug messages during
|
|
10
|
+
* development without showing them to the end user. It provides a convenient way to debug your
|
|
11
|
+
* code without the need to manually remove console.log statements.
|
|
12
|
+
* @example
|
|
13
|
+
* // Enable debug mode by setting process.env.DEBUG to true
|
|
14
|
+
* process.env.DEBUG = true;
|
|
15
|
+
*
|
|
16
|
+
* // Log a debug message
|
|
17
|
+
* debug.log('This is a debug message');
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const debug = {};
|
|
21
|
+
const debugEnabled = process.env.DEBUG === 'true';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Iterate over the console methods and create corresponding debug methods.
|
|
25
|
+
*/
|
|
26
|
+
Object.keys(console).forEach((method) => {
|
|
27
|
+
if (typeof console[method] === 'function') {
|
|
28
|
+
debug[method] = (...args) => {
|
|
29
|
+
if (debugEnabled) {
|
|
30
|
+
console[method](...args);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export default debug;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
describe('debug utils', () => {
|
|
2
|
+
let originalDebugValue;
|
|
3
|
+
|
|
4
|
+
beforeAll(() => {
|
|
5
|
+
originalDebugValue = process.env.DEBUG;
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
afterAll(() => {
|
|
9
|
+
process.env.DEBUG = originalDebugValue;
|
|
10
|
+
jest.restoreAllMocks();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test('Should log if debug flag is enabled', async () => {
|
|
14
|
+
process.env.DEBUG = 'true';
|
|
15
|
+
jest.resetModules();
|
|
16
|
+
|
|
17
|
+
const { default: debug } = await import('./index.js');
|
|
18
|
+
|
|
19
|
+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
|
|
20
|
+
|
|
21
|
+
debug.error('test');
|
|
22
|
+
|
|
23
|
+
expect(consoleSpy).toHaveBeenCalledTimes(1);
|
|
24
|
+
expect(consoleSpy.mock.calls[0][0]).toBe('test');
|
|
25
|
+
|
|
26
|
+
consoleSpy.mockRestore();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('Should NOT log if debug flag is disabled', async () => {
|
|
30
|
+
process.env.DEBUG = 'false';
|
|
31
|
+
jest.resetModules();
|
|
32
|
+
|
|
33
|
+
const { default: debug } = await import('./index.js');
|
|
34
|
+
|
|
35
|
+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
|
|
36
|
+
|
|
37
|
+
debug.error('test');
|
|
38
|
+
|
|
39
|
+
expect(consoleSpy).not.toHaveBeenCalled();
|
|
40
|
+
|
|
41
|
+
consoleSpy.mockRestore();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import signale from 'signale';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Execute a command asynchronously and retrieve the standard output and standard error.
|
|
6
|
+
* @function
|
|
7
|
+
* @name exec
|
|
8
|
+
* @memberof utils
|
|
9
|
+
* @param {string} command - The command to be executed.
|
|
10
|
+
* @param {string} [scope='Process'] - Log scope. The default is 'Process'.
|
|
11
|
+
* @param {boolean} [verbose=false] - Whether to display the output in real-time.
|
|
12
|
+
* @returns {Promise<void>} A promise that resolves when the command completes successfully.
|
|
13
|
+
* @example
|
|
14
|
+
* // Executing a command without verbose output
|
|
15
|
+
* await exec('npm install');
|
|
16
|
+
*
|
|
17
|
+
* // Executing a command with verbose output
|
|
18
|
+
* await exec('npm run build', 'Build', true);
|
|
19
|
+
*/
|
|
20
|
+
async function exec(command, scope = 'Process', verbose = false) {
|
|
21
|
+
const stream = new signale.Signale({ interactive: true, scope: ['Process', scope] });
|
|
22
|
+
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
const args = command.split(' ');
|
|
25
|
+
const cmd = args.shift();
|
|
26
|
+
|
|
27
|
+
const buildProcess = spawn(cmd, args, { shell: true });
|
|
28
|
+
|
|
29
|
+
if (verbose) {
|
|
30
|
+
buildProcess.stdout.on('data', (data) => {
|
|
31
|
+
stream.info(data.toString());
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
buildProcess.stderr.on('data', (data) => {
|
|
35
|
+
// Some tools and libraries choose to use stderr for process logging or informational messages.
|
|
36
|
+
const dataStr = data.toString();
|
|
37
|
+
if (dataStr.toLowerCase().includes('error')) {
|
|
38
|
+
stream.error(dataStr);
|
|
39
|
+
} else {
|
|
40
|
+
stream.info(dataStr);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
buildProcess.on('error', (error) => {
|
|
46
|
+
reject(error);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
buildProcess.on('close', (code) => {
|
|
50
|
+
if (code === 0) {
|
|
51
|
+
resolve();
|
|
52
|
+
} else {
|
|
53
|
+
reject(new Error(`Command '${command}' failed with code ${code}`));
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
export default exec;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import signale from 'signale';
|
|
3
|
+
|
|
4
|
+
import exec from './index.js';
|
|
5
|
+
|
|
6
|
+
jest.mock('child_process');
|
|
7
|
+
jest.mock('signale');
|
|
8
|
+
|
|
9
|
+
describe('exec utils', () => {
|
|
10
|
+
let mockSignaleInstance;
|
|
11
|
+
let mockChildProcess;
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
mockSignaleInstance = {
|
|
15
|
+
info: jest.fn(),
|
|
16
|
+
error: jest.fn(),
|
|
17
|
+
};
|
|
18
|
+
signale.Signale.mockReturnValue(mockSignaleInstance);
|
|
19
|
+
|
|
20
|
+
mockChildProcess = {
|
|
21
|
+
stdout: { on: jest.fn() },
|
|
22
|
+
stderr: { on: jest.fn() },
|
|
23
|
+
on: jest.fn(),
|
|
24
|
+
};
|
|
25
|
+
spawn.mockReturnValue(mockChildProcess);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('Should resolve when process closes with code 0', async () => {
|
|
29
|
+
mockChildProcess.on.mockImplementation((event, callback) => {
|
|
30
|
+
if (event === 'close') {
|
|
31
|
+
callback(0);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
await expect(exec('echo test')).resolves.toBeUndefined();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('Should reject when process closes with non-zero code', async () => {
|
|
39
|
+
mockChildProcess.on.mockImplementation((event, callback) => {
|
|
40
|
+
if (event === 'close') {
|
|
41
|
+
callback(1);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
await expect(exec('echo test')).rejects.toThrow('Command \'echo test\' failed with code 1');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('Should reject when process emits an error', async () => {
|
|
49
|
+
const error = new Error('Test error');
|
|
50
|
+
|
|
51
|
+
mockChildProcess.on.mockImplementation((event, callback) => {
|
|
52
|
+
if (event === 'error') {
|
|
53
|
+
callback(error);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
await expect(exec('echo test')).rejects.toEqual(error);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('Should log stdout and stderr when verbose is true', async () => {
|
|
61
|
+
mockChildProcess.on.mockImplementation((event, callback) => {
|
|
62
|
+
if (event === 'close') {
|
|
63
|
+
callback(0);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
mockChildProcess.stdout.on.mockImplementation((event, callback) => {
|
|
68
|
+
if (event === 'data') {
|
|
69
|
+
callback('Test stdout');
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
mockChildProcess.stderr.on.mockImplementation((event, callback) => {
|
|
74
|
+
if (event === 'data') {
|
|
75
|
+
callback('Test stderr');
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
await exec('echo test', 'Test', true);
|
|
80
|
+
|
|
81
|
+
expect(mockSignaleInstance.info).toHaveBeenCalledWith('Test stdout');
|
|
82
|
+
expect(mockSignaleInstance.error).toHaveBeenCalledWith('Test stderr');
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import signale from 'signale';
|
|
2
|
+
|
|
3
|
+
const cleanOutputEnabled = process.env.CLEAN_OUTPUT_MODE === 'true';
|
|
4
|
+
const cleanOutputConfig = {
|
|
5
|
+
displayScope: false,
|
|
6
|
+
displayBadge: false,
|
|
7
|
+
displayDate: false,
|
|
8
|
+
displayFilename: false,
|
|
9
|
+
displayLabel: false,
|
|
10
|
+
displayTimestamp: false,
|
|
11
|
+
underlineLabel: false,
|
|
12
|
+
underlineMessage: false,
|
|
13
|
+
underlinePrefix: false,
|
|
14
|
+
underlineSuffix: false,
|
|
15
|
+
uppercaseLabel: false,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Helper function to create a custom interactive logger object.
|
|
20
|
+
* @param {object} options - Configuration options for the logger.
|
|
21
|
+
* @returns {object} A custom logger object.
|
|
22
|
+
*/
|
|
23
|
+
const getLogger = (options = {}) => {
|
|
24
|
+
const logger = new signale.Signale({ ...options });
|
|
25
|
+
if (cleanOutputEnabled) {
|
|
26
|
+
logger.config(cleanOutputConfig);
|
|
27
|
+
}
|
|
28
|
+
return Object.assign(logger, {
|
|
29
|
+
breakInteractiveChain: () => console.log(),
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const methods = {
|
|
34
|
+
deployed: {
|
|
35
|
+
badge: '🚀',
|
|
36
|
+
color: 'green',
|
|
37
|
+
label: 'forged',
|
|
38
|
+
logLevel: 'info',
|
|
39
|
+
},
|
|
40
|
+
option: {
|
|
41
|
+
badge: '🟣',
|
|
42
|
+
color: 'magenta',
|
|
43
|
+
label: 'option',
|
|
44
|
+
logLevel: 'info',
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const global = new signale.Signale({ interactive: false, scope: 'Vulcan', types: methods });
|
|
49
|
+
|
|
50
|
+
if (cleanOutputEnabled) {
|
|
51
|
+
global.config(cleanOutputConfig);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Predefined log scopes.
|
|
56
|
+
* @type {object}
|
|
57
|
+
*/
|
|
58
|
+
const scopes = {
|
|
59
|
+
...global,
|
|
60
|
+
prebuild: { ...global.scope('Vulcan', 'Pre Build'), interactive: getLogger({ interactive: true, scope: ['Vulcan', 'Pre Build'], types: methods }) },
|
|
61
|
+
build: { ...global.scope('Vulcan', 'Build'), interactive: getLogger({ interactive: true, scope: ['Vulcan', 'Build'], types: methods }) },
|
|
62
|
+
platform: { ...global.scope('Vulcan', 'Platform'), interactive: getLogger({ interactive: true, scope: ['Vulcan', 'Plataform'], types: methods }) },
|
|
63
|
+
statics: { ...global.scope('Vulcan', 'Statics'), interactive: getLogger({ interactive: true, scope: ['Vulcan', 'Statics'], types: methods }) },
|
|
64
|
+
propagation: { ...global.scope('Azion', 'Edge Network'), interactive: getLogger({ interactive: true, scope: ['Vulcan', 'Azion Network'], types: methods }) },
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* @name feedback
|
|
68
|
+
* @memberof utils
|
|
69
|
+
* @description
|
|
70
|
+
* Feedback object that facilitates log display.
|
|
71
|
+
* It includes all logging methods provided by 'signale'.
|
|
72
|
+
* If the environment variable CLEAN_OUTPUT_MODE is set to 'true', all log methods use console.log,
|
|
73
|
+
* providing cleaner and unstyled output. This is particularly useful
|
|
74
|
+
* for other clients intending to use Vulcan
|
|
75
|
+
* in the background, where stylized console output may be less desirable.
|
|
76
|
+
* For more information about the Signale logging methods, refer to its documentation (https://github.com/klaussinani/signale).
|
|
77
|
+
* @type {object}
|
|
78
|
+
*/
|
|
79
|
+
const feedback = { ...scopes };
|
|
80
|
+
|
|
81
|
+
export default feedback;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import feedback from './index.js';
|
|
2
|
+
|
|
3
|
+
describe('feedback utils', () => {
|
|
4
|
+
test('Should create a feedback object that facilitates log display.', async () => {
|
|
5
|
+
const prebuildInfo = feedback.prebuild.info;
|
|
6
|
+
const prebuildError = feedback.prebuild.error;
|
|
7
|
+
|
|
8
|
+
expect(typeof prebuildInfo).toBe('function');
|
|
9
|
+
expect(typeof prebuildError).toBe('function');
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates a timestamp string in the format "YYYYMMDDHHmmss".
|
|
3
|
+
* @function
|
|
4
|
+
* @name generateTimestamp
|
|
5
|
+
* @memberof utils
|
|
6
|
+
* @returns {string} The generated timestamp.
|
|
7
|
+
* @example
|
|
8
|
+
*
|
|
9
|
+
* // Example usage:
|
|
10
|
+
* const timestamp = generateTimestamp();
|
|
11
|
+
* console.log(timestamp); // "20220623123456"
|
|
12
|
+
*/
|
|
13
|
+
function generateTimestamp() {
|
|
14
|
+
const now = new Date();
|
|
15
|
+
const year = now.getFullYear();
|
|
16
|
+
const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
17
|
+
const day = String(now.getDate()).padStart(2, '0');
|
|
18
|
+
const hours = String(now.getHours()).padStart(2, '0');
|
|
19
|
+
const minutes = String(now.getMinutes()).padStart(2, '0');
|
|
20
|
+
const seconds = String(now.getSeconds()).padStart(2, '0');
|
|
21
|
+
|
|
22
|
+
return `${year}${month}${day}${hours}${minutes}${seconds}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default generateTimestamp;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import generateTimestamp from './index.js';
|
|
2
|
+
|
|
3
|
+
describe('generateTimestamp utils', () => {
|
|
4
|
+
test('Should generate a timestamp string in the format "YYYYMMDDHHmmss".', async () => {
|
|
5
|
+
const timestamp = generateTimestamp();
|
|
6
|
+
const regex = /^\d{14}$/;
|
|
7
|
+
|
|
8
|
+
expect(timestamp).toMatch(regex);
|
|
9
|
+
});
|
|
10
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the absolute path of the lib directory based on the current module.
|
|
3
|
+
* @function
|
|
4
|
+
* @name getAbsoluteLibDirPath
|
|
5
|
+
* @memberof utils
|
|
6
|
+
* @returns {string} The full path to the lib directory.
|
|
7
|
+
* @example
|
|
8
|
+
*
|
|
9
|
+
* // Example usage:
|
|
10
|
+
* const libDirPath = getAbsoluteLibDirPath();
|
|
11
|
+
* console.log(libDirPath); // "lib/full/path/to/directory"
|
|
12
|
+
*/
|
|
13
|
+
function getAbsoluteLibDirPath() {
|
|
14
|
+
const currentModuleFullPath = import.meta.url;
|
|
15
|
+
let baselibPath = currentModuleFullPath.match(/(.*lib)(.*)/)[1];
|
|
16
|
+
baselibPath = baselibPath.replace('file://', '');
|
|
17
|
+
|
|
18
|
+
return baselibPath;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default getAbsoluteLibDirPath;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
|
|
3
|
+
import getAbsoluteLibDirPath from './index.js';
|
|
4
|
+
|
|
5
|
+
describe('getAbsoluteLibDirPath utils', () => {
|
|
6
|
+
test('Should get the absolute path of the lib directory based on the current module.', async () => {
|
|
7
|
+
const expectedOutput = join(process.cwd(), 'lib');
|
|
8
|
+
|
|
9
|
+
const result = getAbsoluteLibDirPath();
|
|
10
|
+
|
|
11
|
+
expect(result).toBe(expectedOutput);
|
|
12
|
+
});
|
|
13
|
+
});
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { exec } from 'child_process';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @function
|
|
7
|
+
* @name pathExists
|
|
8
|
+
* @description Checks if a path exists.
|
|
9
|
+
* @param {string} p - The path to check.
|
|
10
|
+
* @returns {Promise<boolean>} A Promise that resolves to `true`
|
|
11
|
+
* if the path exists, `false` otherwise.
|
|
12
|
+
*/
|
|
13
|
+
async function pathExists(p) {
|
|
14
|
+
try {
|
|
15
|
+
await fs.access(p);
|
|
16
|
+
return true;
|
|
17
|
+
} catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const cache = new Map();
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Check if a global package manager (PM) is available.
|
|
26
|
+
* @param {string} pm - The package manager to check (e.g., "npm", "yarn", "pnpm").
|
|
27
|
+
* @returns {Promise<boolean>} A Promise that resolves to true if the global PM is available,
|
|
28
|
+
* false otherwise.
|
|
29
|
+
*/
|
|
30
|
+
async function hasGlobalInstallation(pm) {
|
|
31
|
+
const key = `has_global_${pm}`;
|
|
32
|
+
if (cache.has(key)) {
|
|
33
|
+
return cache.get(key);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return new Promise((resolve) => {
|
|
37
|
+
exec(`${pm} --version`, (error, stdout) => {
|
|
38
|
+
if (error) {
|
|
39
|
+
resolve(false);
|
|
40
|
+
} else {
|
|
41
|
+
const isAvailable = /^\d+\.\d+\.\d+$/.test(stdout);
|
|
42
|
+
cache.set(key, isAvailable);
|
|
43
|
+
resolve(isAvailable);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get the type of lock file (npm, yarn, pnpm) in a specific directory.
|
|
51
|
+
* @param {string} [cwd] - The directory to check. Defaults to the current working directory.
|
|
52
|
+
* @returns {Promise<string|null>} A Promise that resolves to the type of lock file
|
|
53
|
+
* (npm, yarn, pnpm), or null if no lock file is found.
|
|
54
|
+
*/
|
|
55
|
+
async function getTypeofLockFile(cwd = '.') {
|
|
56
|
+
const key = `lockfile_${cwd}`;
|
|
57
|
+
if (cache.has(key)) {
|
|
58
|
+
return cache.get(key);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const isYarn = await pathExists(path.resolve(cwd, 'yarn.lock'));
|
|
62
|
+
const isNpm = await pathExists(path.resolve(cwd, 'package-lock.json'));
|
|
63
|
+
const isPnpm = await pathExists(path.resolve(cwd, 'pnpm-lock.yaml'));
|
|
64
|
+
|
|
65
|
+
let value = null;
|
|
66
|
+
if (isYarn) {
|
|
67
|
+
value = 'yarn';
|
|
68
|
+
} else if (isPnpm) {
|
|
69
|
+
value = 'pnpm';
|
|
70
|
+
} else if (isNpm) {
|
|
71
|
+
value = 'npm';
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
cache.set(key, value);
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Detects the package manager (npm, yarn, pnpm) being used.
|
|
80
|
+
* @async
|
|
81
|
+
* @function
|
|
82
|
+
* @name getPackageManager
|
|
83
|
+
* @memberof utils
|
|
84
|
+
* @param {object} options - Options for detecting the package manager.
|
|
85
|
+
* @param {string} [options.cwd] - The directory to check.
|
|
86
|
+
* Defaults to the current working directory.
|
|
87
|
+
* @returns {Promise<string>} A Promise that resolves to the detected
|
|
88
|
+
* package manager (npm, yarn, pnpm).
|
|
89
|
+
* @example
|
|
90
|
+
*
|
|
91
|
+
* // Example usage:
|
|
92
|
+
* getPackageManager({ cwd: './my-project' })
|
|
93
|
+
* .then(pm => console.log(pm)) // Logs: 'yarn', 'npm', or 'pnpm'
|
|
94
|
+
* .catch(err => console.error(err));
|
|
95
|
+
*/
|
|
96
|
+
async function getPackageManager({ cwd } = {}) {
|
|
97
|
+
const type = await getTypeofLockFile(cwd);
|
|
98
|
+
if (type) {
|
|
99
|
+
return type;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const [hasYarn, hasPnpm] = await Promise.all([
|
|
103
|
+
hasGlobalInstallation('yarn'),
|
|
104
|
+
hasGlobalInstallation('pnpm'),
|
|
105
|
+
]);
|
|
106
|
+
|
|
107
|
+
if (hasYarn) {
|
|
108
|
+
return 'yarn';
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (hasPnpm) {
|
|
112
|
+
return 'pnpm';
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return 'npm';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export default getPackageManager;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { writeFileSync } from 'fs';
|
|
2
|
+
import { tmpdir } from 'os';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
|
|
5
|
+
import getPackageManager from './index.js';
|
|
6
|
+
|
|
7
|
+
const FILE_NAME = 'yarn.lock';
|
|
8
|
+
const CURRENT_DIR = process.cwd();
|
|
9
|
+
const TMP_DIR = tmpdir();
|
|
10
|
+
const FILE_PATH = join(TMP_DIR, FILE_NAME);
|
|
11
|
+
|
|
12
|
+
describe('getPackageManager utils', () => {
|
|
13
|
+
beforeAll(() => {
|
|
14
|
+
writeFileSync(FILE_PATH, `
|
|
15
|
+
{
|
|
16
|
+
"name": "next",
|
|
17
|
+
"version": "0.1.0"
|
|
18
|
+
}
|
|
19
|
+
`);
|
|
20
|
+
|
|
21
|
+
process.chdir(TMP_DIR);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
afterAll(() => {
|
|
25
|
+
process.chdir(CURRENT_DIR);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('Should detect the package manager (npm, yarn, pnpm) being used.', async () => {
|
|
29
|
+
const expectedOutput = 'yarn';
|
|
30
|
+
|
|
31
|
+
const result = await getPackageManager();
|
|
32
|
+
|
|
33
|
+
expect(result).toBe(expectedOutput);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Get package version from user project.
|
|
6
|
+
* @param {string} packageName - The depency name.
|
|
7
|
+
* @returns {string} The package version.
|
|
8
|
+
*/
|
|
9
|
+
function getPackageVersion(packageName) {
|
|
10
|
+
if (!packageName || packageName === '' || packageName === ' ') {
|
|
11
|
+
throw new Error('Invalid package name!');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const packageJsonPath = join(process.cwd(), 'package.json');
|
|
15
|
+
const packageJsonContent = readFileSync(packageJsonPath, 'utf8');
|
|
16
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
17
|
+
|
|
18
|
+
if (!packageJson.dependencies || !packageJson.dependencies[packageName]) {
|
|
19
|
+
throw new Error(`'${packageName}' not detected in project dependencies!`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return packageJson.dependencies[packageName];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default getPackageVersion;
|