esa-cli 0.0.5 → 1.0.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 (85) hide show
  1. package/README.md +34 -145
  2. package/dist/commands/commit/index.js +49 -104
  3. package/dist/commands/commit/prodBuild.js +2 -3
  4. package/dist/commands/common/constant.js +4 -4
  5. package/dist/commands/common/utils.js +419 -0
  6. package/dist/commands/config.js +2 -2
  7. package/dist/commands/deploy/helper.js +43 -49
  8. package/dist/commands/deploy/index.js +51 -174
  9. package/dist/commands/deployments/delete.js +32 -22
  10. package/dist/commands/deployments/index.js +4 -4
  11. package/dist/commands/deployments/list.js +21 -34
  12. package/dist/commands/dev/build.js +3 -3
  13. package/dist/commands/dev/doProcess.js +5 -5
  14. package/dist/commands/dev/ew2/cacheService.js +33 -0
  15. package/dist/commands/dev/ew2/devEntry.js +2 -1
  16. package/dist/commands/dev/ew2/devPack.js +31 -20
  17. package/dist/commands/dev/ew2/kvService.js +50 -0
  18. package/dist/commands/dev/ew2/mock/cache.js +99 -15
  19. package/dist/commands/dev/ew2/mock/kv.js +142 -21
  20. package/dist/commands/dev/ew2/server.js +163 -28
  21. package/dist/commands/dev/index.js +17 -18
  22. package/dist/commands/dev/mockWorker/devPack.js +19 -10
  23. package/dist/commands/dev/mockWorker/server.js +7 -6
  24. package/dist/commands/domain/add.js +4 -4
  25. package/dist/commands/domain/delete.js +3 -3
  26. package/dist/commands/domain/index.js +4 -4
  27. package/dist/commands/domain/list.js +7 -7
  28. package/dist/commands/init/helper.js +654 -21
  29. package/dist/commands/init/index.js +88 -152
  30. package/dist/commands/init/snippets/nextjs/next.config.mjs +6 -0
  31. package/dist/commands/init/snippets/nextjs/next.config.ts +7 -0
  32. package/dist/commands/init/snippets/react-router/react-router.config.ts +7 -0
  33. package/dist/commands/init/template.jsonc +84 -0
  34. package/dist/commands/init/types.js +1 -0
  35. package/dist/commands/lang.js +2 -2
  36. package/dist/commands/login/index.js +74 -34
  37. package/dist/commands/logout.js +6 -6
  38. package/dist/commands/route/add.js +101 -43
  39. package/dist/commands/route/delete.js +6 -6
  40. package/dist/commands/route/helper.js +9 -10
  41. package/dist/commands/route/index.js +4 -4
  42. package/dist/commands/route/list.js +4 -4
  43. package/dist/commands/routine/delete.js +9 -8
  44. package/dist/commands/routine/index.js +6 -5
  45. package/dist/commands/routine/list.js +45 -39
  46. package/dist/commands/site/index.js +3 -3
  47. package/dist/commands/site/list.js +6 -7
  48. package/dist/commands/utils.js +61 -25
  49. package/dist/components/descriptionInput.js +1 -1
  50. package/dist/components/filterSelector.js +1 -1
  51. package/dist/components/mutiLevelSelect.js +19 -20
  52. package/dist/components/mutiSelectTable.js +1 -1
  53. package/dist/components/routeBuilder.js +68 -0
  54. package/dist/components/selectInput.js +2 -3
  55. package/dist/components/selectItem.js +1 -1
  56. package/dist/docs/Commands_en.md +164 -117
  57. package/dist/docs/Commands_zh_CN.md +155 -107
  58. package/dist/docs/Config_en.md +70 -0
  59. package/dist/docs/Config_zh_CN.md +68 -0
  60. package/dist/i18n/index.js +2 -2
  61. package/dist/i18n/locales.json +418 -82
  62. package/dist/index.js +28 -13
  63. package/dist/libs/api.js +3 -6
  64. package/dist/libs/apiService.js +201 -70
  65. package/dist/libs/git/index.js +86 -9
  66. package/dist/libs/interface.js +0 -1
  67. package/dist/libs/logger.js +162 -10
  68. package/dist/libs/service.js +2 -2
  69. package/dist/libs/templates/index.js +1 -1
  70. package/dist/utils/checkAssetsExist.js +80 -0
  71. package/dist/utils/checkDevPort.js +5 -19
  72. package/dist/utils/checkEntryFileExist.js +10 -0
  73. package/dist/utils/checkIsRoutineCreated.js +27 -21
  74. package/dist/utils/checkVersion.js +119 -1
  75. package/dist/utils/command.js +149 -0
  76. package/dist/utils/compress.js +142 -0
  77. package/dist/utils/download.js +8 -8
  78. package/dist/utils/fileMd5.js +1 -1
  79. package/dist/utils/fileUtils/index.js +136 -45
  80. package/dist/utils/installDeno.js +4 -4
  81. package/dist/utils/installEw2.js +9 -9
  82. package/dist/utils/openInBrowser.js +1 -1
  83. package/dist/utils/prompt.js +97 -0
  84. package/package.json +23 -12
  85. package/zh_CN.md +31 -150
@@ -0,0 +1,50 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import t from '../../../i18n/index.js';
4
+ import { getRoot } from '../../../utils/fileUtils/base.js';
5
+ class EdgeKV {
6
+ constructor() {
7
+ const root = getRoot();
8
+ const kvPath = path.join(root, 'kv.json');
9
+ if (fs.existsSync(kvPath)) {
10
+ try {
11
+ const kvJson = fs.readFileSync(kvPath, 'utf8');
12
+ const kvJsonObj = JSON.parse(kvJson);
13
+ Object.keys(kvJsonObj).forEach((namespace) => {
14
+ const childMap = new Map();
15
+ Object.keys(kvJsonObj[namespace]).forEach((key) => {
16
+ childMap.set(key, JSON.stringify(kvJsonObj[namespace][key]));
17
+ });
18
+ EdgeKV.store.set(namespace, childMap);
19
+ });
20
+ }
21
+ catch (err) {
22
+ console.log(t('kv_parse_failed').d('kv.json parse failed, use empty local kv store.'));
23
+ }
24
+ }
25
+ }
26
+ get(key, namespace) {
27
+ const store = EdgeKV.store.get(namespace);
28
+ if (!store || !store.has(key)) {
29
+ return;
30
+ }
31
+ return store.get(key);
32
+ }
33
+ put(key, value, namespace) {
34
+ let store = EdgeKV.store.get(namespace);
35
+ if (!store) {
36
+ EdgeKV.store.set(namespace, new Map([[key, value]]));
37
+ }
38
+ else {
39
+ store.set(key, value);
40
+ }
41
+ }
42
+ delete(key, namespace) {
43
+ const store = EdgeKV.store.get(namespace);
44
+ if (!store)
45
+ return false;
46
+ return store.delete(key);
47
+ }
48
+ }
49
+ EdgeKV.store = new Map();
50
+ export default EdgeKV;
@@ -1,31 +1,115 @@
1
1
  class MockCache {
2
- constructor() {
3
- this.cache = new Map();
2
+ constructor(port) {
3
+ this.port = port;
4
4
  }
5
5
 
6
- static async init(cacheName) {
7
- const instance = await MockCache.open(cacheName);
8
- return new MockCache(instance);
9
- }
6
+ async put(reqOrUrl, response) {
7
+ if (arguments.length < 2) {
8
+ throw new TypeError(
9
+ `Failed to execute 'put' on 'cache': 2 arguments required, but only ${arguments.length} present.`
10
+ );
11
+ }
12
+ if (!reqOrUrl) {
13
+ throw new TypeError(
14
+ "Failed to execute 'put' on 'cache': 2 arguments required, but only 0 present."
15
+ );
16
+ }
17
+ if (!(response instanceof Response)) {
18
+ throw new TypeError(
19
+ "Failed to execute 'put' on 'cache': Argument 2 is not of type Response."
20
+ );
21
+ }
22
+
23
+ try {
24
+ const body = await response.clone().text();
25
+ const headers = {};
26
+ response.headers.forEach((v, k) => (headers[k] = v));
27
+
28
+ const cacheControl = response.headers.get('Cache-Control') || '';
29
+ const ttl = this.parseTTL(cacheControl);
10
30
 
11
- static async open(cacheName) {
12
- return new Map();
31
+ const key = this.normalizeKey(reqOrUrl);
32
+ const fetchRes = await fetch(
33
+ `http://localhost:${this.port}/mock_cache/put`,
34
+ {
35
+ method: 'POST',
36
+ headers: { 'Content-Type': 'application/json' },
37
+ body: JSON.stringify({
38
+ key,
39
+ response: {
40
+ status: response.status,
41
+ headers,
42
+ body
43
+ },
44
+ ttl
45
+ })
46
+ }
47
+ );
48
+ if (!fetchRes.ok) {
49
+ const error = await fetchRes.json();
50
+ throw new Error(error.error);
51
+ }
52
+ return undefined;
53
+ } catch (err) {
54
+ throw new Error(`Cache put failed: ${err.message}`);
55
+ }
13
56
  }
14
57
 
15
- async match(reqOrUrl) {
16
- return this.cache.get(reqOrUrl) || null;
58
+ async get(reqOrUrl) {
59
+ const key = this.normalizeKey(reqOrUrl);
60
+ const fetchRes = await fetch(
61
+ `http://localhost:${this.port}/mock_cache/get`,
62
+ {
63
+ method: 'POST',
64
+ headers: { 'Content-Type': 'application/json' },
65
+ body: JSON.stringify({
66
+ key
67
+ })
68
+ }
69
+ );
70
+ if (!fetchRes.ok) {
71
+ const error = await fetchRes.json();
72
+ throw new Error(error.error);
73
+ }
74
+ const res = await fetchRes.json();
75
+ if (res && res.success) {
76
+ return new Response(res.data.response.body, {
77
+ status: res.data.response.status,
78
+ headers: new Headers(res.data.response.headers)
79
+ });
80
+ } else {
81
+ return undefined;
82
+ }
17
83
  }
18
84
 
19
85
  async delete(reqOrUrl) {
20
- return this.cache.delete(reqOrUrl);
86
+ const key = this.normalizeKey(reqOrUrl);
87
+ const fetchRes = await fetch(
88
+ `http://localhost:${this.port}/mock_cache/delete`,
89
+ {
90
+ method: 'POST',
91
+ headers: { 'Content-Type': 'application/json' },
92
+ body: JSON.stringify({
93
+ key
94
+ })
95
+ }
96
+ );
97
+ if (!fetchRes.ok) {
98
+ const error = await fetchRes.json();
99
+ throw new Error(error.error);
100
+ }
101
+ const res = await fetchRes.json();
102
+ return res.success;
21
103
  }
22
104
 
23
- async put(reqOrUrl, response) {
24
- this.cache.set(reqOrUrl, response);
105
+ normalizeKey(input) {
106
+ const url = input instanceof Request ? input.url : input;
107
+ return url.replace(/^https:/i, 'http:');
25
108
  }
26
109
 
27
- async get(reqOrUrl) {
28
- return this.match(reqOrUrl);
110
+ parseTTL(cacheControl) {
111
+ const maxAgeMatch = cacheControl.match(/max-age=(\d+)/);
112
+ return maxAgeMatch ? parseInt(maxAgeMatch[1]) : 3600;
29
113
  }
30
114
  }
31
115
 
@@ -1,44 +1,165 @@
1
1
  class EdgeKV {
2
+ static port = 0;
3
+ JS_RESPONSE_BUFFER_THRESHOLD = 64 * 1024;
2
4
  constructor(options) {
5
+ if (!options || (!options.namespace && !options.namespaceId)) {
6
+ throw new TypeError(
7
+ 'The argument to `EdgeKV` must be an object with a `namespace` or `namespaceId` field'
8
+ );
9
+ }
3
10
  this.namespace = options.namespace;
4
- this.allData = {};
5
11
  }
6
12
 
7
- async get(key, options) {
8
- const namespaceData = this.allData[this.namespace] || {};
9
- if (!(key in namespaceData)) {
13
+ async put(key, value) {
14
+ if (arguments.length < 2) {
15
+ throw new TypeError(
16
+ `Failed to execute 'put' on 'EdgeKV': 2 arguments required, but only ${arguments.length} present.`
17
+ );
18
+ }
19
+ if (!key) {
20
+ throw new TypeError(
21
+ "Failed to execute 'put' on 'EdgeKV': 2 arguments required, but only 0 present."
22
+ );
23
+ }
24
+ if (typeof key !== 'string') {
25
+ throw new TypeError(
26
+ `Failed to execute 'put' on 'EdgeKV': 1th argument must be a string.`
27
+ );
28
+ }
29
+
30
+ try {
31
+ let body;
32
+ if (typeof value === 'string') {
33
+ if (value.length > this.JS_RESPONSE_BUFFER_THRESHOLD) {
34
+ const encoder = new TextEncoder();
35
+ const encodedValue = encoder.encode(value);
36
+
37
+ body = new ReadableStream({
38
+ start(controller) {
39
+ controller.enqueue(encodedValue);
40
+ controller.close();
41
+ }
42
+ });
43
+ } else {
44
+ body = value;
45
+ }
46
+ } else if (value instanceof Response) {
47
+ const resBody = await value.clone().text();
48
+ const headers = {};
49
+ value.headers.forEach((v, k) => (headers[k] = v));
50
+ body = JSON.stringify({
51
+ body: resBody,
52
+ headers,
53
+ status: value.status
54
+ });
55
+ } else if (
56
+ value instanceof ReadableStream ||
57
+ value instanceof ArrayBuffer ||
58
+ ArrayBuffer.isView(value)
59
+ ) {
60
+ body = value;
61
+ } else {
62
+ throw new TypeError(
63
+ `Failed to execute 'put' on 'EdgeKV': 2nd argument should be one of string/Response/ArrayBuffer/ArrayBufferView/ReadableStream`
64
+ );
65
+ }
66
+
67
+ const fetchRes = await fetch(
68
+ `http://localhost:${EdgeKV.port}/mock_kv/put?key=${key}&namespace=${this.namespace}`,
69
+ {
70
+ method: 'POST',
71
+ headers: { 'Content-Type': 'application/json' },
72
+ body
73
+ }
74
+ );
75
+ if (!fetchRes.ok) {
76
+ const error = await fetchRes.json();
77
+ throw new Error(error.error);
78
+ }
10
79
  return undefined;
80
+ } catch (err) {
81
+ throw new Error(`Cache put failed: ${err.message}`);
82
+ }
83
+ }
84
+
85
+ async get(key, options) {
86
+ const isTypeValid = (ty) =>
87
+ typeof ty === 'string' &&
88
+ (ty === 'text' ||
89
+ ty === 'json' ||
90
+ ty === 'stream' ||
91
+ ty === 'arrayBuffer');
92
+
93
+ if (options && !isTypeValid(options?.type)) {
94
+ throw new TypeError(
95
+ "EdgeKV.get: 2nd optional argument must be an object with a 'type' field. The 'type' field specifies the format of the return value and must be a string of 'text', 'json', 'stream' or 'arrayBuffer'"
96
+ );
11
97
  }
12
- const value = namespaceData[key];
13
98
  const type = options?.type || 'text';
99
+ const fetchRes = await fetch(
100
+ `http://localhost:${EdgeKV.port}/mock_kv/get?key=${key}&namespace=${this.namespace}`,
101
+ {
102
+ method: 'POST',
103
+ headers: { 'Content-Type': 'application/json' }
104
+ }
105
+ );
106
+ // Check if key exists
107
+ let isGetFailed = false;
108
+ fetchRes.headers.forEach((v, k) => {
109
+ if (k === 'kv-get-empty') {
110
+ isGetFailed = true;
111
+ }
112
+ });
113
+ if (isGetFailed) {
114
+ return undefined;
115
+ }
14
116
  switch (type) {
15
117
  case 'text':
16
- return value;
118
+ return fetchRes.text();
17
119
  case 'json':
18
120
  try {
19
- return JSON.parse(value);
121
+ const value = await fetchRes.text();
122
+ const userObject = JSON.parse(value);
123
+ return userObject;
20
124
  } catch (error) {
21
- throw new Error('Failed to parse JSON');
125
+ throw new TypeError(`Invalid JSON: ${err.message}`);
22
126
  }
23
127
  case 'arrayBuffer':
24
- const encoder = new TextEncoder();
25
- const uint8Array = encoder.encode(value);
26
- return uint8Array.buffer;
128
+ try {
129
+ const buffer = await fetchRes.arrayBuffer();
130
+ return buffer;
131
+ } catch (error) {
132
+ throw new TypeError(
133
+ `Failed to read the response body into an ArrayBuffer: ${error.message}`
134
+ );
135
+ }
136
+ case 'stream':
137
+ const value = await fetchRes.text();
138
+ return new ReadableStream({
139
+ start(controller) {
140
+ controller.enqueue(new TextEncoder().encode(value));
141
+ controller.close();
142
+ }
143
+ });
27
144
  default:
28
- throw new Error('Invalid type option');
145
+ throw new Error(`Unsupported type: ${type}`);
29
146
  }
30
147
  }
31
148
 
32
- async put(key, value) {
33
- const namespaceData = this.allData[this.namespace] || {};
34
- namespaceData[key] = value;
35
- this.allData[this.namespace] = namespaceData;
36
- }
37
-
38
149
  async delete(key) {
39
- const namespaceData = this.allData[this.namespace] || {};
40
- delete namespaceData[key];
41
- this.allData[this.namespace] = namespaceData;
150
+ const fetchRes = await fetch(
151
+ `http://localhost:${EdgeKV.port}/mock_kv/delete?key=${key}&namespace=${this.namespace}`,
152
+ {
153
+ method: 'POST',
154
+ headers: { 'Content-Type': 'application/json' }
155
+ }
156
+ );
157
+ if (!fetchRes.ok) {
158
+ const error = await fetchRes.json();
159
+ throw new Error(error.error);
160
+ }
161
+ const res = await fetchRes.json();
162
+ return res.success;
42
163
  }
43
164
  }
44
165
 
@@ -8,15 +8,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import * as http from 'http';
11
+ import chalk from 'chalk';
11
12
  import spawn from 'cross-spawn';
13
+ import { HttpProxyAgent } from 'http-proxy-agent';
12
14
  import fetch from 'node-fetch';
15
+ import t from '../../../i18n/index.js';
13
16
  import logger from '../../../libs/logger.js';
14
17
  import { getRoot } from '../../../utils/fileUtils/base.js';
15
18
  import { EW2BinPath } from '../../../utils/installEw2.js';
16
- import { HttpProxyAgent } from 'http-proxy-agent';
17
- import chalk from 'chalk';
18
- import t from '../../../i18n/index.js';
19
19
  import sleep from '../../../utils/sleep.js';
20
+ import CacheService from './cacheService.js';
21
+ import EdgeKV from './kvService.js';
20
22
  const getColorForStatusCode = (statusCode, message) => {
21
23
  if (statusCode >= 100 && statusCode < 200) {
22
24
  return chalk.blue(`${statusCode} ${message}`);
@@ -40,6 +42,8 @@ const getColorForStatusCode = (statusCode, message) => {
40
42
  class Ew2Server {
41
43
  constructor(props) {
42
44
  this.worker = null;
45
+ this.cache = null;
46
+ this.kv = null;
43
47
  this.startingWorker = false;
44
48
  this.workerStartTimeout = undefined;
45
49
  this.server = null;
@@ -57,6 +61,8 @@ class Ew2Server {
57
61
  return __awaiter(this, void 0, void 0, function* () {
58
62
  this.startingWorker = true;
59
63
  const result = yield this.openEdgeWorker();
64
+ this.cache = new CacheService();
65
+ this.kv = new EdgeKV();
60
66
  if (!result) {
61
67
  throw new Error('Worker start failed');
62
68
  }
@@ -81,8 +87,9 @@ class Ew2Server {
81
87
  stdio: ['pipe', 'pipe', 'pipe']
82
88
  });
83
89
  this.workerStartTimeout = setTimeout(() => {
90
+ var _a;
84
91
  reject(new Error(t('dev_worker_timeout').d('Worker start timeout')));
85
- this.worker && this.worker.kill();
92
+ (_a = this.worker) === null || _a === void 0 ? void 0 : _a.kill();
86
93
  }, 60000);
87
94
  const sendToRuntime = () => {
88
95
  return new Promise((resolveStart) => {
@@ -96,7 +103,7 @@ class Ew2Server {
96
103
  const req = http.get(options, (res) => {
97
104
  resolveStart(res.statusCode);
98
105
  });
99
- req.on('error', (err) => {
106
+ req.on('error', () => {
100
107
  resolveStart(null);
101
108
  });
102
109
  req.end();
@@ -119,7 +126,8 @@ class Ew2Server {
119
126
  this.worker.on('close', this.closeHandler.bind(this));
120
127
  this.worker.on('error', this.errorHandler.bind(this));
121
128
  process.on('SIGTERM', () => {
122
- this.worker && this.worker.kill();
129
+ var _a;
130
+ (_a = this.worker) === null || _a === void 0 ? void 0 : _a.kill();
123
131
  });
124
132
  });
125
133
  }
@@ -128,37 +136,60 @@ class Ew2Server {
128
136
  }
129
137
  createServer() {
130
138
  this.server = http.createServer((req, res) => __awaiter(this, void 0, void 0, function* () {
139
+ var _a, _b, _c;
140
+ if (req.url === '/favicon.ico') {
141
+ res.writeHead(204, {
142
+ 'Content-Type': 'image/x-icon',
143
+ 'Content-Length': 0
144
+ });
145
+ return res.end();
146
+ }
147
+ if ((_a = req.url) === null || _a === void 0 ? void 0 : _a.includes('/mock_cache')) {
148
+ const cacheResult = yield this.handleCache(req);
149
+ return res.end(JSON.stringify(cacheResult));
150
+ }
151
+ if ((_b = req.url) === null || _b === void 0 ? void 0 : _b.includes('/mock_kv')) {
152
+ const kvResult = yield this.handleKV(req);
153
+ if ((_c = req.url) === null || _c === void 0 ? void 0 : _c.includes('/get')) {
154
+ if (kvResult.success) {
155
+ return res.end(kvResult.value);
156
+ }
157
+ else {
158
+ res.setHeader('Kv-Get-Empty', 'true');
159
+ return res.end();
160
+ }
161
+ }
162
+ else {
163
+ return res.end(JSON.stringify(kvResult));
164
+ }
165
+ }
131
166
  try {
132
167
  const host = req.headers.host;
133
168
  const url = req.url;
169
+ const method = req.method;
170
+ const headers = Object.entries(req.headers).reduce((acc, [key, value]) => {
171
+ if (Array.isArray(value)) {
172
+ acc[key] = value.join(', ');
173
+ }
174
+ else {
175
+ acc[key] = value;
176
+ }
177
+ return acc;
178
+ }, {});
134
179
  // @ts-ignore
135
180
  const ew2Port = global.ew2Port;
136
181
  // @ts-ignore
137
182
  const localUpstream = global.localUpstream;
138
183
  const workerRes = yield fetch(`http://${localUpstream ? localUpstream : host}${url}`, {
139
- method: 'GET',
140
- headers: {
141
- 'x-er-context': 'eyJzaXRlX2lkIjogIjYyMjcxODQ0NjgwNjA4IiwgInNpdGVfbmFtZSI6ICJjb21wdXRlbHguYWxpY2RuLXRlc3QuY29tIiwgInNpdGVfcmVjb3JkIjogIm1vY2hlbi1uY2RuLmNvbXB1dGVseC5hbGljZG4tdGVzdC5jb20iLCAiYWxpdWlkIjogIjEzMjI0OTI2ODY2NjU2MDgiLCAic2NoZW1lIjoiaHR0cCIsICAiaW1hZ2VfZW5hYmxlIjogdHJ1ZX0=',
142
- 'x-er-id': 'a.bA'
143
- },
184
+ method,
185
+ headers: Object.assign(Object.assign({}, headers), { 'x-er-context': 'eyJzaXRlX2lkIjogIjYyMjcxODQ0NjgwNjA4IiwgInNpdGVfbmFtZSI6ICJjb21wdXRlbHguYWxpY2RuLXRlc3QuY29tIiwgInNpdGVfcmVjb3JkIjogIm1vY2hlbi1uY2RuLmNvbXB1dGVseC5hbGljZG4tdGVzdC5jb20iLCAiYWxpdWlkIjogIjEzMjI0OTI2ODY2NjU2MDgiLCAic2NoZW1lIjoiaHR0cCIsICAiaW1hZ2VfZW5hYmxlIjogdHJ1ZX0=', 'x-er-id': 'a.bA' }),
186
+ body: req.method === 'GET' ? undefined : req,
144
187
  agent: new HttpProxyAgent(`http://127.0.0.1:${ew2Port}`)
145
188
  });
146
189
  const workerHeaders = Object.fromEntries(workerRes.headers.entries());
147
- // 解决 gzip 兼容性问题,防止net::ERR_CONTENT_DECODING_FAILED
190
+ // Solve gzip compatibility issue, prevent net::ERR_CONTENT_DECODING_FAILED
148
191
  workerHeaders['content-encoding'] = 'identity';
149
192
  if (workerRes.body) {
150
- // if (workerRes.headers.get('content-type')?.includes('text/')) {
151
- // const text = await workerRes.text();
152
- // // 出现换行符之类会导致 content-length 不一致
153
- // workerHeaders['content-length'] =
154
- // Buffer.byteLength(text).toString();
155
- // console.log(workerHeaders['content-length']);
156
- // res.writeHead(workerRes.status, workerHeaders);
157
- // res.end(text);
158
- // } else {
159
- // res.writeHead(workerRes.status, workerHeaders);
160
- // workerRes.body.pipe(res);
161
- // }
162
193
  res.writeHead(workerRes.status, workerHeaders);
163
194
  workerRes.body.pipe(res);
164
195
  logger.log(`[ESA Dev] ${req.method} ${url} ${getColorForStatusCode(workerRes.status, workerRes.statusText)}`);
@@ -176,6 +207,65 @@ class Ew2Server {
176
207
  logger.log(`listening on port ${this.port}`);
177
208
  });
178
209
  }
210
+ handleCache(req) {
211
+ return __awaiter(this, void 0, void 0, function* () {
212
+ var _a, _b, _c, _d, _e, _f;
213
+ const body = yield this.parseCacheBody(req);
214
+ if ((_a = req.url) === null || _a === void 0 ? void 0 : _a.includes('/put')) {
215
+ (_b = this.cache) === null || _b === void 0 ? void 0 : _b.put(body.key, body);
216
+ return { success: true };
217
+ }
218
+ if ((_c = req.url) === null || _c === void 0 ? void 0 : _c.includes('/get')) {
219
+ const res = (_d = this.cache) === null || _d === void 0 ? void 0 : _d.get(body.key);
220
+ if (!res) {
221
+ return { success: false, key: body.key };
222
+ }
223
+ return { success: true, key: body.key, data: res === null || res === void 0 ? void 0 : res.serializedResponse };
224
+ }
225
+ if ((_e = req.url) === null || _e === void 0 ? void 0 : _e.includes('/delete')) {
226
+ const res = (_f = this.cache) === null || _f === void 0 ? void 0 : _f.delete(body.key);
227
+ return { success: !!res };
228
+ }
229
+ return { success: false };
230
+ });
231
+ }
232
+ handleKV(req) {
233
+ return __awaiter(this, void 0, void 0, function* () {
234
+ var _a, _b, _c, _d, _e, _f;
235
+ const url = new URL(req.url, 'http://localhost');
236
+ const key = url.searchParams.get('key');
237
+ const namespace = url.searchParams.get('namespace');
238
+ const body = yield this.parseKVBody(req);
239
+ if (!key || !namespace) {
240
+ return {
241
+ success: false
242
+ };
243
+ }
244
+ if ((_a = req.url) === null || _a === void 0 ? void 0 : _a.includes('/put')) {
245
+ (_b = this.kv) === null || _b === void 0 ? void 0 : _b.put(key, body, namespace);
246
+ return {
247
+ success: true
248
+ };
249
+ }
250
+ if ((_c = req.url) === null || _c === void 0 ? void 0 : _c.includes('/get')) {
251
+ const res = (_d = this.kv) === null || _d === void 0 ? void 0 : _d.get(key, namespace);
252
+ const params = { success: true, value: res };
253
+ if (!res) {
254
+ params.success = false;
255
+ }
256
+ return params;
257
+ }
258
+ if ((_e = req.url) === null || _e === void 0 ? void 0 : _e.includes('/delete')) {
259
+ const res = (_f = this.kv) === null || _f === void 0 ? void 0 : _f.delete(key, namespace);
260
+ return {
261
+ success: res
262
+ };
263
+ }
264
+ return {
265
+ success: false
266
+ };
267
+ });
268
+ }
179
269
  stdoutHandler(chunk) {
180
270
  logger.log(`${chalk.bgGreen('[Worker]')} ${chunk.toString().trim()}`);
181
271
  }
@@ -189,17 +279,60 @@ class Ew2Server {
189
279
  }
190
280
  this.stop();
191
281
  }
192
- closeHandler(code, signal) {
282
+ closeHandler() {
193
283
  if (this.restarting) {
194
284
  this.restarting = false;
195
285
  return;
196
286
  }
197
287
  this.stop().then(() => {
288
+ var _a;
198
289
  logger.log(t('dev_server_closed').d('Worker server closed'));
199
290
  logger.info('Worker server closed');
200
291
  // @ts-ignore
201
292
  global.port = undefined;
202
- this.onClose && this.onClose();
293
+ (_a = this.onClose) === null || _a === void 0 ? void 0 : _a.call(this);
294
+ });
295
+ }
296
+ parseCacheBody(req) {
297
+ return new Promise((resolve, reject) => {
298
+ const chunks = [];
299
+ let totalLength = 0;
300
+ req.on('data', (chunk) => {
301
+ chunks.push(chunk);
302
+ totalLength += chunk.length;
303
+ });
304
+ req.on('end', () => {
305
+ try {
306
+ const buffer = Buffer.concat(chunks, totalLength);
307
+ const rawBody = buffer.toString('utf8');
308
+ resolve(rawBody ? JSON.parse(rawBody) : {});
309
+ }
310
+ catch (err) {
311
+ reject(new Error(`Invalid JSON: ${err.message}`));
312
+ }
313
+ });
314
+ req.on('error', reject);
315
+ });
316
+ }
317
+ parseKVBody(req) {
318
+ return new Promise((resolve, reject) => {
319
+ const chunks = [];
320
+ let totalLength = 0;
321
+ req.on('data', (chunk) => {
322
+ chunks.push(chunk);
323
+ totalLength += chunk.length;
324
+ });
325
+ req.on('end', () => {
326
+ try {
327
+ const buffer = Buffer.concat(chunks, totalLength);
328
+ const rawBody = buffer.toString();
329
+ resolve(rawBody);
330
+ }
331
+ catch (err) {
332
+ reject(new Error(`Invalid JSON: ${err.message}`));
333
+ }
334
+ });
335
+ req.on('error', reject);
203
336
  });
204
337
  }
205
338
  runCommand(command) {
@@ -213,7 +346,7 @@ class Ew2Server {
213
346
  resolve(false);
214
347
  return;
215
348
  }
216
- const onExit = (code, signal) => {
349
+ const onExit = () => {
217
350
  this.worker = null;
218
351
  resolve(true);
219
352
  };
@@ -222,10 +355,12 @@ class Ew2Server {
222
355
  (_a = this.server) === null || _a === void 0 ? void 0 : _a.close();
223
356
  });
224
357
  }
225
- restart() {
358
+ restart(devPack) {
226
359
  return __awaiter(this, void 0, void 0, function* () {
227
360
  this.restarting = true;
361
+ console.clear();
228
362
  yield this.stop();
363
+ yield devPack();
229
364
  this.start();
230
365
  logger.log(t('dev_server_restart').d('Worker server restarted'));
231
366
  logger.info('Worker server restarted');