esa-cli 0.0.1-beta.1

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 (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +175 -0
  3. package/bin/enter.cjs +52 -0
  4. package/dist/README.md +175 -0
  5. package/dist/bin/enter.cjs +52 -0
  6. package/dist/cliconfig.toml +6 -0
  7. package/dist/commands/commit/index.js +147 -0
  8. package/dist/commands/commit/prodBuild.js +50 -0
  9. package/dist/commands/common/constant.js +54 -0
  10. package/dist/commands/config.js +51 -0
  11. package/dist/commands/deploy/helper.js +108 -0
  12. package/dist/commands/deploy/index.js +217 -0
  13. package/dist/commands/deployments/delete.js +92 -0
  14. package/dist/commands/deployments/index.js +27 -0
  15. package/dist/commands/deployments/list.js +89 -0
  16. package/dist/commands/dev/config/devBuild.js +26 -0
  17. package/dist/commands/dev/config/devEntry.js +71 -0
  18. package/dist/commands/dev/config/mock/cache.js +31 -0
  19. package/dist/commands/dev/config/mock/kv.js +87 -0
  20. package/dist/commands/dev/devPack.js +113 -0
  21. package/dist/commands/dev/doProcess.js +73 -0
  22. package/dist/commands/dev/index.js +240 -0
  23. package/dist/commands/dev/server.js +100 -0
  24. package/dist/commands/domain/add.js +72 -0
  25. package/dist/commands/domain/delete.js +74 -0
  26. package/dist/commands/domain/index.js +29 -0
  27. package/dist/commands/domain/list.js +51 -0
  28. package/dist/commands/init/index.js +149 -0
  29. package/dist/commands/lang.js +32 -0
  30. package/dist/commands/login/index.js +108 -0
  31. package/dist/commands/logout.js +44 -0
  32. package/dist/commands/route/add.js +115 -0
  33. package/dist/commands/route/delete.js +74 -0
  34. package/dist/commands/route/index.js +29 -0
  35. package/dist/commands/route/list.js +63 -0
  36. package/dist/commands/routine/delete.js +54 -0
  37. package/dist/commands/routine/index.js +27 -0
  38. package/dist/commands/routine/list.js +101 -0
  39. package/dist/commands/site/index.js +25 -0
  40. package/dist/commands/site/list.js +47 -0
  41. package/dist/commands/utils.js +139 -0
  42. package/dist/components/descriptionInput.js +38 -0
  43. package/dist/components/filterSelector.js +132 -0
  44. package/dist/components/mutiSelectTable.js +95 -0
  45. package/dist/components/selectInput.js +17 -0
  46. package/dist/components/selectItem.js +6 -0
  47. package/dist/components/yesNoPrompt.js +9 -0
  48. package/dist/docs/Commands_en.md +224 -0
  49. package/dist/docs/Commands_zh_CN.md +224 -0
  50. package/dist/docs/dev.png +0 -0
  51. package/dist/i18n/index.js +27 -0
  52. package/dist/i18n/locales.json +766 -0
  53. package/dist/index.js +80 -0
  54. package/dist/libs/apiService.js +914 -0
  55. package/dist/libs/git/index.js +52 -0
  56. package/dist/libs/interface.js +21 -0
  57. package/dist/libs/logger.js +149 -0
  58. package/dist/libs/request.js +98 -0
  59. package/dist/libs/templates/index.js +16 -0
  60. package/dist/package.json +93 -0
  61. package/dist/utils/checkDevPort.js +113 -0
  62. package/dist/utils/checkIsRoutineCreated.js +56 -0
  63. package/dist/utils/checkVersion.js +26 -0
  64. package/dist/utils/debounce.js +18 -0
  65. package/dist/utils/fileUtils/index.js +219 -0
  66. package/dist/utils/fileUtils/interface.js +1 -0
  67. package/dist/utils/install/install.ps1 +33 -0
  68. package/dist/utils/install/install.sh +53 -0
  69. package/dist/utils/installRuntime.js +80 -0
  70. package/dist/utils/openInBrowser.js +24 -0
  71. package/dist/utils/sleep.js +6 -0
  72. package/dist/zh_CN.md +177 -0
  73. package/package.json +93 -0
@@ -0,0 +1,71 @@
1
+ import {
2
+ blue,
3
+ green,
4
+ yellow,
5
+ red,
6
+ magenta,
7
+ bold
8
+ } from 'https://deno.land/std@0.177.0/fmt/colors.ts';
9
+ import worker from '$userPath';
10
+ import Cache from './mock/cache.js';
11
+ import EdgeKV from './mock/kv.js';
12
+
13
+ const id = Deno.args[0];
14
+ const getColorForStatusCode = (statusCode, message) => {
15
+ if (statusCode >= 100 && statusCode < 200) {
16
+ return blue(`${statusCode} ${message}`);
17
+ } else if (statusCode >= 200 && statusCode < 300) {
18
+ return green(`${statusCode} ${message}`);
19
+ } else if (statusCode >= 300 && statusCode < 400) {
20
+ return yellow(`${statusCode} ${message}`);
21
+ } else if (statusCode >= 400 && statusCode < 500) {
22
+ return red(`${statusCode} ${message}`);
23
+ } else if (statusCode >= 500) {
24
+ return magenta(bold(`${statusCode} ${message}`));
25
+ } else {
26
+ return `${statusCode} ${message}`;
27
+ }
28
+ };
29
+ const dev = async () => {
30
+ try {
31
+ const configs = (await import('./devConfig.js')).default;
32
+ const config = configs[id] ?? {};
33
+ const cacheInstance = await Cache.init('mock');
34
+ globalThis.cache = cacheInstance;
35
+ globalThis.EdgeKV = EdgeKV;
36
+ if (!worker || !worker.fetch) {
37
+ throw new Error('Invalid ER code.');
38
+ }
39
+ Deno.serve({
40
+ port: config.port,
41
+ handler: async (request) => {
42
+ const url = new URL(request.url);
43
+ let nextRequest = request;
44
+ if (config.localUpstream) {
45
+ const nextUrl = `${config.localUpstream}${url.pathname}${url.search}${url.hash}`;
46
+ nextRequest = new Request(nextUrl, request);
47
+ }
48
+ try {
49
+ const res = await worker.fetch(nextRequest);
50
+ const status = res.status;
51
+ console.log(
52
+ `[Esa Dev] ${request.method} ${url.pathname} ${getColorForStatusCode(status, res.statusText)}`
53
+ );
54
+ return res;
55
+ } catch (err) {
56
+ console.error(err);
57
+ console.log(
58
+ `[Esa Dev] ${request.method} ${url.pathname} ${getColorForStatusCode(500, 'Internal Server Error')}`
59
+ );
60
+ return new Response('Internal Server Error', {
61
+ status: 500
62
+ });
63
+ }
64
+ }
65
+ });
66
+ } catch (err) {
67
+ console.log('\n');
68
+ console.error(red(err));
69
+ }
70
+ };
71
+ dev();
@@ -0,0 +1,31 @@
1
+ class MockCache {
2
+ constructor(instance) {
3
+ this.cache = instance;
4
+ }
5
+ static async init(cacheName) {
6
+ const instance = await MockCache.open(cacheName);
7
+ return new MockCache(instance);
8
+ }
9
+ static open(cacheName) {
10
+ return caches.open(cacheName);
11
+ }
12
+ static has(cacheName) {
13
+ return caches.has(cacheName);
14
+ }
15
+ static delete(cacheName) {
16
+ return caches.delete(cacheName);
17
+ }
18
+ match(reqOrUrl, options) {
19
+ return this.cache.match(reqOrUrl, options);
20
+ }
21
+ delete(reqOrUrl, options) {
22
+ return this.cache.delete(reqOrUrl, options);
23
+ }
24
+ put(reqOrUrl, response) {
25
+ return this.cache.put(reqOrUrl, response);
26
+ }
27
+ get(reqOrUrl, options) {
28
+ return this.match(reqOrUrl, options);
29
+ }
30
+ }
31
+ export default MockCache;
@@ -0,0 +1,87 @@
1
+ import * as path from 'https://deno.land/std/path/mod.ts';
2
+ class EdgeKV {
3
+ namespace;
4
+ filePath;
5
+ allData;
6
+ constructor(options) {
7
+ this.namespace = options.namespace;
8
+ this.filePath = path.join(this.getRoot(), '.dev/.kv');
9
+ this.allData = {};
10
+ }
11
+ getRoot(root) {
12
+ if (typeof root === 'undefined') {
13
+ root = Deno.cwd();
14
+ }
15
+ if (root === '/') {
16
+ return Deno.cwd();
17
+ }
18
+ const file = path.join(root, 'cliconfig.toml');
19
+ const prev = path.resolve(root, '../');
20
+ try {
21
+ const hasToml = fs.existsSync(file);
22
+ if (hasToml) {
23
+ return root;
24
+ } else {
25
+ return this.getRoot(prev);
26
+ }
27
+ } catch (err) {
28
+ return this.getRoot(prev);
29
+ }
30
+ }
31
+ async _loadData() {
32
+ try {
33
+ const fileData = await Deno.readTextFile(this.filePath);
34
+ this.allData = JSON.parse(fileData);
35
+ } catch (error) {
36
+ if (!(error instanceof Deno.errors.NotFound)) {
37
+ console.error('Error reading KV file:', error);
38
+ }
39
+ }
40
+ }
41
+
42
+ async get(key, options) {
43
+ await this._loadData();
44
+ const namespaceData = this.allData[this.namespace] || {};
45
+ if (!(key in namespaceData)) {
46
+ return undefined;
47
+ }
48
+ const value = namespaceData[key];
49
+ const type = options?.type || 'text';
50
+ switch (type) {
51
+ case 'text':
52
+ return value;
53
+ case 'json':
54
+ try {
55
+ return JSON.parse(value);
56
+ } catch (error) {
57
+ throw new Error('Failed to parse JSON');
58
+ }
59
+ case 'arrayBuffer':
60
+ const encoder = new TextEncoder();
61
+ const uint8Array = encoder.encode(value);
62
+ return uint8Array.buffer;
63
+ default:
64
+ throw new Error('Invalid type option');
65
+ }
66
+ }
67
+ async put(key, value) {
68
+ const namespaceData = this.allData[this.namespace] || {};
69
+ namespaceData[key] = value;
70
+ this.allData[this.namespace] = namespaceData;
71
+ await this._saveData();
72
+ }
73
+ async delete(key) {
74
+ const namespaceData = this.allData[this.namespace] || {};
75
+ delete namespaceData[key];
76
+ this.allData[this.namespace] = namespaceData;
77
+ await this._saveData();
78
+ }
79
+ async _saveData() {
80
+ try {
81
+ await Deno.writeTextFile(this.filePath, JSON.stringify(this.allData));
82
+ } catch (error) {
83
+ console.error('Error writing KV file:', error);
84
+ }
85
+ }
86
+ }
87
+ export default EdgeKV;
@@ -0,0 +1,113 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import path from 'path';
11
+ import fs from 'fs';
12
+ import logger from '../../libs/logger.js';
13
+ import devBuild from './config/devBuild.js';
14
+ import t from '../../i18n/index.js';
15
+ import { getDevConf, getRoot, getDirName } from '../../utils/fileUtils/index.js';
16
+ import { checkPort } from '../../utils/checkDevPort.js';
17
+ const generateEntry = (id, projectEntry, userRoot) => __awaiter(void 0, void 0, void 0, function* () {
18
+ const __dirname = getDirName(import.meta.url);
19
+ const devDir = path.resolve(userRoot, '.dev');
20
+ const devEntry = path.resolve(devDir, `devEntry-${id}.js`);
21
+ const devEntryTemp = path.resolve(__dirname, './config/devEntry.js');
22
+ const devEntryTempFile = fs.readFileSync(devEntryTemp, 'utf-8');
23
+ const mockDevDir = path.resolve(userRoot, '.dev/mock');
24
+ const mockDir = path.resolve(__dirname, './config/mock');
25
+ if (!fs.existsSync(devDir)) {
26
+ yield fs.promises.mkdir(devDir);
27
+ }
28
+ if (!fs.existsSync(mockDevDir)) {
29
+ yield fs.promises.mkdir(mockDevDir);
30
+ }
31
+ const entries = yield fs.promises.readdir(mockDir);
32
+ for (const file of entries) {
33
+ const srcPath = path.resolve(mockDir, file);
34
+ const destPath = path.resolve(mockDevDir, file);
35
+ yield fs.promises.copyFile(srcPath, destPath);
36
+ }
37
+ return fs.promises.writeFile(devEntry, devEntryTempFile.replace(/'\$userPath'/g, `'${projectEntry}'`));
38
+ });
39
+ const prepare = (configPath, entry, port, localUpstream, userRoot) => __awaiter(void 0, void 0, void 0, function* () {
40
+ const options = {};
41
+ const currentOptions = { entry, port, localUpstream };
42
+ const id = new Date().getTime().toString();
43
+ // @ts-ignore
44
+ global.id = id;
45
+ yield generateEntry(id, entry, userRoot);
46
+ if (fs.existsSync(configPath)) {
47
+ const currentConfig = fs
48
+ .readFileSync(configPath, 'utf-8')
49
+ .replace('export default ', '');
50
+ const currentConfigObj = JSON.parse(currentConfig);
51
+ const cIds = Object.keys(currentConfigObj);
52
+ if (cIds[0] && /^\d+$/.test(cIds[0])) {
53
+ for (let cid of cIds) {
54
+ const useful = yield checkPort(currentConfigObj[cid].port);
55
+ if (useful) {
56
+ const unusedEntry = path.resolve(userRoot, `.dev/index-${cid}.js`);
57
+ const unusedTemp = path.resolve(userRoot, `.dev/devEntry-${cid}.js`);
58
+ if (fs.existsSync(unusedEntry)) {
59
+ fs.rmSync(unusedEntry);
60
+ }
61
+ if (fs.existsSync(unusedTemp)) {
62
+ fs.rmSync(unusedTemp);
63
+ }
64
+ }
65
+ else {
66
+ options[cid] = currentConfigObj[cid];
67
+ }
68
+ }
69
+ }
70
+ }
71
+ return fs.promises.writeFile(configPath, `export default ${JSON.stringify(Object.assign(options, { [id]: currentOptions }))}`);
72
+ });
73
+ const devPack = () => __awaiter(void 0, void 0, void 0, function* () {
74
+ logger.ora.start('Processing...\n');
75
+ const userRoot = getRoot();
76
+ const configPath = path.resolve(userRoot, 'esa.toml');
77
+ let port, minify, localUpstream, entry;
78
+ let projectEntry = path.resolve(userRoot, 'src/index.js');
79
+ if (fs.existsSync(configPath)) {
80
+ port = getDevConf('port', 'dev', 18080);
81
+ minify = getDevConf('minify', 'dev', false);
82
+ localUpstream = getDevConf('localUpstream', 'dev', '');
83
+ entry = getDevConf('entry', '', '');
84
+ if (entry) {
85
+ projectEntry = path.resolve(userRoot, entry);
86
+ }
87
+ }
88
+ else {
89
+ logger.notInProject();
90
+ process.exit(0);
91
+ }
92
+ return prepare(path.resolve(userRoot, '.dev/devConfig.js'), projectEntry, port, localUpstream, userRoot)
93
+ .then(() => {
94
+ logger.ora.succeed(t('dev_pack_config_success').d('Config created successfully'));
95
+ return devBuild({
96
+ minify
97
+ });
98
+ })
99
+ .then(() => {
100
+ logger.ora.succeed(t('dev_pack_success').d('Build finished successfully'));
101
+ logger.ora.stop();
102
+ logger.block();
103
+ })
104
+ .catch((err) => {
105
+ logger.ora.fail('Build Failed');
106
+ logger.error(`${t('common_error_occurred').d('An error occurred')}: ${err}`);
107
+ if (err.toString().includes('EACCES')) {
108
+ logger.pathEacces(getDirName(import.meta.url));
109
+ }
110
+ process.exit(1);
111
+ });
112
+ });
113
+ export default devPack;
@@ -0,0 +1,73 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import React, { useEffect } from 'react';
11
+ import { Box, Text, useApp, useInput, render } from 'ink';
12
+ import chalk from 'chalk';
13
+ import logger from '../../libs/logger.js';
14
+ import openInBrowser from '../../utils/openInBrowser.js';
15
+ import { getDevOpenBrowserUrl } from '../../utils/fileUtils/index.js';
16
+ import t from '../../i18n/index.js';
17
+ const InteractionBox = ({ worker }) => {
18
+ const { exit } = useApp();
19
+ const inspectLink = chalk.underline.blue('chrome://inspect/#devices');
20
+ const remoteTarget = chalk.blue('Remote Target');
21
+ const inspect = chalk.blue('inspect');
22
+ /* eslint-disable no-unused-vars */
23
+ useInput((input) => __awaiter(void 0, void 0, void 0, function* () {
24
+ switch (input.toLowerCase()) {
25
+ case 'c':
26
+ console.clear();
27
+ logger.block();
28
+ break;
29
+ case 'b': {
30
+ yield openInBrowser(getDevOpenBrowserUrl());
31
+ break;
32
+ }
33
+ case 'd': {
34
+ logger.log(t('dev_input_inspect_tip1', { inspectLink }).d(`👉 Please visit ${inspectLink} in the Chrome browser`));
35
+ logger.log(t('dev_input_inspect_tip2', { inspect, remoteTarget }).d(`👉 See your debugger under ${remoteTarget} and click the ${inspect} button`));
36
+ break;
37
+ }
38
+ case 'x':
39
+ exit();
40
+ break;
41
+ default:
42
+ break;
43
+ }
44
+ }));
45
+ useEffect(() => {
46
+ return () => {
47
+ if (worker) {
48
+ worker.stop();
49
+ }
50
+ };
51
+ }, []);
52
+ return (React.createElement(React.Fragment, null,
53
+ React.createElement(Box, { borderStyle: "classic", paddingLeft: 1, paddingRight: 1 },
54
+ React.createElement(Text, { bold: true }, "[b]"),
55
+ React.createElement(Text, null, " open a browser, "),
56
+ React.createElement(React.Fragment, null,
57
+ React.createElement(Text, { bold: true }, "[d]"),
58
+ React.createElement(Text, null, " open Devtools, ")),
59
+ React.createElement(Text, { bold: true }, "[c]"),
60
+ React.createElement(Text, null, " clear console, "),
61
+ React.createElement(Text, { bold: true }, "[x]"),
62
+ React.createElement(Text, null, " to exit"))));
63
+ };
64
+ const doProcess = (worker) => {
65
+ const devElement = render(React.createElement(InteractionBox, { worker: worker }));
66
+ return {
67
+ devElement,
68
+ exit: () => {
69
+ devElement.unmount();
70
+ }
71
+ };
72
+ };
73
+ export default doProcess;
@@ -0,0 +1,240 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { exec } from 'child_process';
11
+ import chokidar from 'chokidar';
12
+ import doProcess from './doProcess.js';
13
+ import { getProjectConfig, getRoot, generateConfigFile, getDevConf } from '../../utils/fileUtils/index.js';
14
+ import SelectItems from '../../components/selectInput.js';
15
+ import logger from '../../libs/logger.js';
16
+ import devPack from './devPack.js';
17
+ import WorkerServer from './server.js';
18
+ import { preCheckRuntime } from '../../utils/installRuntime.js';
19
+ import debounce from '../../utils/debounce.js';
20
+ import t from '../../i18n/index.js';
21
+ import checkAndInputPort from '../../utils/checkDevPort.js';
22
+ let yargsIns;
23
+ const dev = {
24
+ command: 'dev [entry]',
25
+ describe: `💻 ${t('dev_describe').d('Start a local server for developing your routine')}`,
26
+ builder: (yargs) => {
27
+ yargsIns = yargs;
28
+ return yargs
29
+ .positional('entry', {
30
+ describe: t('dev_entry_describe').d('Entry file of the Routine'),
31
+ type: 'string',
32
+ demandOption: false
33
+ })
34
+ .option('refresh-command', {
35
+ describe: t('dev_refresh_command_describe').d('Provide a command to be executed before the auto-refresh on save'),
36
+ type: 'string'
37
+ })
38
+ .option('local-upstream', {
39
+ describe: t('dev_option_local_upstream').d('Host to act as origin in development'),
40
+ type: 'string'
41
+ })
42
+ .option('m', {
43
+ alias: 'minify',
44
+ describe: t('dev_option_minify').d('Minify code during development'),
45
+ type: 'boolean',
46
+ default: false
47
+ })
48
+ .option('inspect-port', {
49
+ describe: t('dev_inspect_port_describe').d('Chrome inspect devTool port'),
50
+ type: 'number'
51
+ })
52
+ .option('p', {
53
+ alias: 'port',
54
+ describe: t('dev_port_describe').d('Port to listen on'),
55
+ type: 'number'
56
+ });
57
+ },
58
+ handler: (argv) => __awaiter(void 0, void 0, void 0, function* () {
59
+ let { port, inspectPort } = argv;
60
+ let userFileRepacking = false; // flag of user code repack not .dev file change
61
+ const { entry, minify, refreshCommand, localUpstream, help } = argv;
62
+ if (yargsIns && help) {
63
+ yargsIns.showHelp('log');
64
+ return;
65
+ }
66
+ const projectConfig = getProjectConfig();
67
+ if (!projectConfig) {
68
+ if (entry) {
69
+ try {
70
+ yield selectToCreateConf(entry);
71
+ }
72
+ catch (_) {
73
+ logger.notInProject();
74
+ process.exit(1);
75
+ }
76
+ }
77
+ else {
78
+ return logger.notInProject();
79
+ }
80
+ }
81
+ else if (entry) {
82
+ // @ts-ignore
83
+ global.entry = entry;
84
+ }
85
+ if (port) {
86
+ if (Array.isArray(port)) {
87
+ port = Number(port[0]);
88
+ }
89
+ else {
90
+ port = Number(port);
91
+ if (isNaN(port)) {
92
+ logger.warn(t('dev_import_port_invalid').d('Invalid port entered, default port will be used.'));
93
+ }
94
+ }
95
+ // @ts-ignore
96
+ global.port = port;
97
+ }
98
+ if (inspectPort) {
99
+ inspectPort = Number(inspectPort);
100
+ // @ts-ignore
101
+ global.inspectPort = inspectPort;
102
+ }
103
+ if (minify) {
104
+ // @ts-ignore
105
+ global.minify = minify;
106
+ }
107
+ if (minify) {
108
+ // @ts-ignore
109
+ global.minify = minify;
110
+ }
111
+ if (localUpstream) {
112
+ // @ts-ignore
113
+ global.localUpstream = localUpstream;
114
+ }
115
+ const runtimeCommand = yield preCheckRuntime();
116
+ if (!runtimeCommand) {
117
+ return;
118
+ }
119
+ const speDenoPort = getDevConf('port', 'dev', 18080);
120
+ const speInspectPort = getDevConf('inspectPort', 'dev', 9229);
121
+ try {
122
+ const result = yield checkAndInputPort(speDenoPort, speInspectPort);
123
+ // @ts-ignore
124
+ global.port = result.denoPort;
125
+ // @ts-ignore
126
+ global.inspectPort = result.inspectPort;
127
+ }
128
+ catch (err) {
129
+ process.exit(1);
130
+ }
131
+ logger.info(`${t('dev_build_start').d('Starting build process')}...`);
132
+ yield devPack();
133
+ const worker = new WorkerServer({ command: runtimeCommand });
134
+ const ignored = (path) => {
135
+ return /(^|[\/\\])\.(?!dev($|[\/\\]))/.test(path);
136
+ };
137
+ const watcher = chokidar.watch([`${getRoot()}/src`, `${getRoot()}/.dev`], {
138
+ ignored,
139
+ persistent: true
140
+ });
141
+ watcher.on('change', debounce((path) => __awaiter(void 0, void 0, void 0, function* () {
142
+ if (path.includes('.dev')) {
143
+ if (userFileRepacking) {
144
+ userFileRepacking = false;
145
+ return;
146
+ }
147
+ worker.restart();
148
+ return;
149
+ }
150
+ logger.info(`${t('dev_repacking').d('Detected local file changes, re-packaging')}...`);
151
+ if (refreshCommand) {
152
+ try {
153
+ yield execRefreshCommand(refreshCommand);
154
+ }
155
+ catch (err) { }
156
+ }
157
+ userFileRepacking = true;
158
+ yield devPack();
159
+ yield worker.restart();
160
+ }), 500));
161
+ const { devElement } = doProcess(worker);
162
+ const { waitUntilExit } = devElement;
163
+ yield waitUntilExit();
164
+ watcher.close();
165
+ })
166
+ };
167
+ function execCommand(cmd) {
168
+ return new Promise((resolve, reject) => {
169
+ exec(cmd, (error, stdout, stderr) => {
170
+ logger.log(stdout);
171
+ if (error) {
172
+ reject({ error, stderr });
173
+ }
174
+ else {
175
+ resolve({ stdout, stderr });
176
+ }
177
+ });
178
+ });
179
+ }
180
+ function isSafeCommand(cmd) {
181
+ const dangerousPatterns = [
182
+ /[`;]/,
183
+ /\|\|/,
184
+ /&&/,
185
+ />|<|>>|<<|&/,
186
+ /\$(?=.*\()|=/
187
+ ];
188
+ return !dangerousPatterns.some((pattern) => pattern.test(cmd));
189
+ }
190
+ function execRefreshCommand(cmd) {
191
+ return __awaiter(this, void 0, void 0, function* () {
192
+ if (isSafeCommand(cmd)) {
193
+ logger.ora.start(`${t('dev_refresh_exec_start').d('Trying to execute command:')} ${cmd}`);
194
+ try {
195
+ const { stderr } = yield execCommand(cmd);
196
+ logger.ora.succeed(`${t('dev_refresh_exec_success').d('Command executed successfully.')}`);
197
+ if (stderr) {
198
+ logger.ora.fail();
199
+ logger.error(`Errors: ${stderr}`);
200
+ }
201
+ }
202
+ catch (err) {
203
+ logger.ora.fail();
204
+ logger.error(`${t('dev_refresh_exec_fail').d('Command execution failed:')} ${err.error.message}`);
205
+ if (err.stderr) {
206
+ logger.error(`Errors: ${err.stderr}`);
207
+ }
208
+ logger.warn('Jumped it.');
209
+ }
210
+ }
211
+ else {
212
+ logger.error(t('dev_refresh_exec_unsafe').d('Command execution failed: Invalid command'));
213
+ }
214
+ });
215
+ }
216
+ function selectToCreateConf(entry) {
217
+ return new Promise((resolve, reject) => {
218
+ logger.info(t('dev_create_config').d('Configuration file not found. Would you like to create one?'));
219
+ SelectItems({
220
+ items: [
221
+ { label: 'Yes', value: 'yes' },
222
+ { label: 'No', value: 'no' }
223
+ ],
224
+ handleSelect: (item) => __awaiter(this, void 0, void 0, function* () {
225
+ if (item.value === 'yes') {
226
+ yield generateConfigFile(undefined, {
227
+ dev: {
228
+ entry
229
+ }
230
+ });
231
+ resolve(true);
232
+ }
233
+ else {
234
+ reject(false);
235
+ }
236
+ })
237
+ });
238
+ });
239
+ }
240
+ export default dev;