esa-cli 0.0.2-beta.9 → 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/README.md +32 -149
- package/dist/commands/commit/index.js +49 -104
- package/dist/commands/commit/prodBuild.js +2 -3
- package/dist/commands/common/constant.js +4 -4
- package/dist/commands/common/utils.js +419 -0
- package/dist/commands/config.js +2 -2
- package/dist/commands/deploy/helper.js +51 -54
- package/dist/commands/deploy/index.js +51 -174
- package/dist/commands/deployments/delete.js +32 -22
- package/dist/commands/deployments/index.js +4 -4
- package/dist/commands/deployments/list.js +21 -34
- package/dist/commands/dev/build.js +3 -3
- package/dist/commands/dev/doProcess.js +5 -5
- package/dist/commands/dev/ew2/cacheService.js +33 -0
- package/dist/commands/dev/ew2/devEntry.js +2 -1
- package/dist/commands/dev/ew2/devPack.js +31 -20
- package/dist/commands/dev/ew2/kvService.js +50 -0
- package/dist/commands/dev/ew2/mock/cache.js +99 -15
- package/dist/commands/dev/ew2/mock/kv.js +142 -21
- package/dist/commands/dev/ew2/server.js +165 -29
- package/dist/commands/dev/index.js +17 -18
- package/dist/commands/dev/mockWorker/devPack.js +19 -10
- package/dist/commands/dev/mockWorker/server.js +7 -6
- package/dist/commands/domain/add.js +4 -4
- package/dist/commands/domain/delete.js +7 -7
- package/dist/commands/domain/index.js +4 -4
- package/dist/commands/domain/list.js +10 -10
- package/dist/commands/init/helper.js +654 -20
- package/dist/commands/init/index.js +88 -152
- package/dist/commands/init/snippets/nextjs/next.config.mjs +6 -0
- package/dist/commands/init/snippets/nextjs/next.config.ts +7 -0
- package/dist/commands/init/snippets/react-router/react-router.config.ts +7 -0
- package/dist/commands/init/template.jsonc +84 -0
- package/dist/commands/init/types.js +1 -0
- package/dist/commands/lang.js +2 -2
- package/dist/commands/login/index.js +74 -34
- package/dist/commands/logout.js +6 -6
- package/dist/commands/route/add.js +105 -49
- package/dist/commands/route/delete.js +33 -27
- package/dist/commands/route/helper.js +123 -0
- package/dist/commands/route/index.js +4 -4
- package/dist/commands/route/list.js +56 -17
- package/dist/commands/routine/delete.js +9 -8
- package/dist/commands/routine/index.js +6 -5
- package/dist/commands/routine/list.js +45 -39
- package/dist/commands/site/index.js +3 -3
- package/dist/commands/site/list.js +6 -7
- package/dist/commands/utils.js +61 -25
- package/dist/components/descriptionInput.js +1 -1
- package/dist/components/filterSelector.js +1 -1
- package/dist/components/mutiLevelSelect.js +19 -20
- package/dist/components/mutiSelectTable.js +1 -1
- package/dist/components/routeBuilder.js +68 -0
- package/dist/components/selectInput.js +2 -3
- package/dist/components/selectItem.js +1 -1
- package/dist/docs/Commands_en.md +164 -117
- package/dist/docs/Commands_zh_CN.md +155 -107
- package/dist/docs/Config_en.md +70 -0
- package/dist/docs/Config_zh_CN.md +68 -0
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/locales.json +447 -71
- package/dist/index.js +28 -13
- package/dist/libs/api.js +32 -9
- package/dist/libs/apiService.js +294 -73
- package/dist/libs/git/index.js +86 -9
- package/dist/libs/interface.js +0 -1
- package/dist/libs/logger.js +162 -10
- package/dist/libs/service.js +2 -2
- package/dist/libs/templates/index.js +1 -1
- package/dist/utils/checkAssetsExist.js +80 -0
- package/dist/utils/checkDevPort.js +5 -19
- package/dist/utils/checkEntryFileExist.js +10 -0
- package/dist/utils/checkIsRoutineCreated.js +27 -21
- package/dist/utils/checkVersion.js +119 -1
- package/dist/utils/command.js +149 -0
- package/dist/utils/compress.js +142 -0
- package/dist/utils/download.js +8 -8
- package/dist/utils/fileMd5.js +1 -1
- package/dist/utils/fileUtils/index.js +136 -45
- package/dist/utils/installDeno.js +4 -4
- package/dist/utils/installEw2.js +9 -9
- package/dist/utils/openInBrowser.js +1 -1
- package/dist/utils/prompt.js +97 -0
- package/package.json +24 -13
- package/zh_CN.md +29 -154
|
@@ -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.
|
|
2
|
+
constructor(port) {
|
|
3
|
+
this.port = port;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
12
|
-
|
|
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
|
|
16
|
-
|
|
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
|
-
|
|
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
|
-
|
|
24
|
-
|
|
105
|
+
normalizeKey(input) {
|
|
106
|
+
const url = input instanceof Request ? input.url : input;
|
|
107
|
+
return url.replace(/^https:/i, 'http:');
|
|
25
108
|
}
|
|
26
109
|
|
|
27
|
-
|
|
28
|
-
|
|
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
|
|
8
|
-
|
|
9
|
-
|
|
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
|
|
118
|
+
return fetchRes.text();
|
|
17
119
|
case 'json':
|
|
18
120
|
try {
|
|
19
|
-
|
|
121
|
+
const value = await fetchRes.text();
|
|
122
|
+
const userObject = JSON.parse(value);
|
|
123
|
+
return userObject;
|
|
20
124
|
} catch (error) {
|
|
21
|
-
throw new
|
|
125
|
+
throw new TypeError(`Invalid JSON: ${err.message}`);
|
|
22
126
|
}
|
|
23
127
|
case 'arrayBuffer':
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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(
|
|
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
|
|
40
|
-
|
|
41
|
-
|
|
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
|
|
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', (
|
|
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
|
-
|
|
129
|
+
var _a;
|
|
130
|
+
(_a = this.worker) === null || _a === void 0 ? void 0 : _a.kill();
|
|
123
131
|
});
|
|
124
132
|
});
|
|
125
133
|
}
|
|
@@ -128,38 +136,62 @@ class Ew2Server {
|
|
|
128
136
|
}
|
|
129
137
|
createServer() {
|
|
130
138
|
this.server = http.createServer((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
131
|
-
var _a;
|
|
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
|
+
}
|
|
132
166
|
try {
|
|
133
167
|
const host = req.headers.host;
|
|
134
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
|
+
}, {});
|
|
135
179
|
// @ts-ignore
|
|
136
180
|
const ew2Port = global.ew2Port;
|
|
137
181
|
// @ts-ignore
|
|
138
182
|
const localUpstream = global.localUpstream;
|
|
139
183
|
const workerRes = yield fetch(`http://${localUpstream ? localUpstream : host}${url}`, {
|
|
140
|
-
method
|
|
141
|
-
headers: {
|
|
142
|
-
|
|
143
|
-
'x-er-id': 'a.bA'
|
|
144
|
-
},
|
|
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,
|
|
145
187
|
agent: new HttpProxyAgent(`http://127.0.0.1:${ew2Port}`)
|
|
146
188
|
});
|
|
147
189
|
const workerHeaders = Object.fromEntries(workerRes.headers.entries());
|
|
148
|
-
//
|
|
190
|
+
// Solve gzip compatibility issue, prevent net::ERR_CONTENT_DECODING_FAILED
|
|
149
191
|
workerHeaders['content-encoding'] = 'identity';
|
|
150
192
|
if (workerRes.body) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
// 出现换行符之类会导致 content-length 不一致
|
|
154
|
-
workerHeaders['content-length'] =
|
|
155
|
-
Buffer.byteLength(text).toString();
|
|
156
|
-
res.writeHead(workerRes.status, workerHeaders);
|
|
157
|
-
res.end(text);
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
res.writeHead(workerRes.status, workerHeaders);
|
|
161
|
-
workerRes.body.pipe(res);
|
|
162
|
-
}
|
|
193
|
+
res.writeHead(workerRes.status, workerHeaders);
|
|
194
|
+
workerRes.body.pipe(res);
|
|
163
195
|
logger.log(`[ESA Dev] ${req.method} ${url} ${getColorForStatusCode(workerRes.status, workerRes.statusText)}`);
|
|
164
196
|
}
|
|
165
197
|
else {
|
|
@@ -175,6 +207,65 @@ class Ew2Server {
|
|
|
175
207
|
logger.log(`listening on port ${this.port}`);
|
|
176
208
|
});
|
|
177
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
|
+
}
|
|
178
269
|
stdoutHandler(chunk) {
|
|
179
270
|
logger.log(`${chalk.bgGreen('[Worker]')} ${chunk.toString().trim()}`);
|
|
180
271
|
}
|
|
@@ -188,17 +279,60 @@ class Ew2Server {
|
|
|
188
279
|
}
|
|
189
280
|
this.stop();
|
|
190
281
|
}
|
|
191
|
-
closeHandler(
|
|
282
|
+
closeHandler() {
|
|
192
283
|
if (this.restarting) {
|
|
193
284
|
this.restarting = false;
|
|
194
285
|
return;
|
|
195
286
|
}
|
|
196
287
|
this.stop().then(() => {
|
|
288
|
+
var _a;
|
|
197
289
|
logger.log(t('dev_server_closed').d('Worker server closed'));
|
|
198
290
|
logger.info('Worker server closed');
|
|
199
291
|
// @ts-ignore
|
|
200
292
|
global.port = undefined;
|
|
201
|
-
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);
|
|
202
336
|
});
|
|
203
337
|
}
|
|
204
338
|
runCommand(command) {
|
|
@@ -212,7 +346,7 @@ class Ew2Server {
|
|
|
212
346
|
resolve(false);
|
|
213
347
|
return;
|
|
214
348
|
}
|
|
215
|
-
const onExit = (
|
|
349
|
+
const onExit = () => {
|
|
216
350
|
this.worker = null;
|
|
217
351
|
resolve(true);
|
|
218
352
|
};
|
|
@@ -221,10 +355,12 @@ class Ew2Server {
|
|
|
221
355
|
(_a = this.server) === null || _a === void 0 ? void 0 : _a.close();
|
|
222
356
|
});
|
|
223
357
|
}
|
|
224
|
-
restart() {
|
|
358
|
+
restart(devPack) {
|
|
225
359
|
return __awaiter(this, void 0, void 0, function* () {
|
|
226
360
|
this.restarting = true;
|
|
361
|
+
console.clear();
|
|
227
362
|
yield this.stop();
|
|
363
|
+
yield devPack();
|
|
228
364
|
this.start();
|
|
229
365
|
logger.log(t('dev_server_restart').d('Worker server restarted'));
|
|
230
366
|
logger.info('Worker server restarted');
|