@lark-apaas/devtool-kits 1.0.5-alpha.1 → 1.0.5-alpha.3
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/dist/error.html +47 -19
- package/dist/index.cjs +59 -77
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -2
- package/dist/index.d.ts +0 -2
- package/dist/index.js +59 -77
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/error.html
CHANGED
|
@@ -159,8 +159,8 @@
|
|
|
159
159
|
// 探测服务是否恢复
|
|
160
160
|
async function probeService() {
|
|
161
161
|
try {
|
|
162
|
-
// 获取当前 URL
|
|
163
|
-
const currentUrl =
|
|
162
|
+
// 获取当前 URL
|
|
163
|
+
const currentUrl = window.location.pathname + window.location.search;
|
|
164
164
|
|
|
165
165
|
console.log('[Probe] 探测服务状态:', currentUrl);
|
|
166
166
|
|
|
@@ -169,15 +169,53 @@
|
|
|
169
169
|
const timeoutId = setTimeout(() => controller.abort(), PROBE_TIMEOUT);
|
|
170
170
|
|
|
171
171
|
const response = await fetch(currentUrl, {
|
|
172
|
-
method: '
|
|
172
|
+
method: 'GET', // 使用 GET 而不是 HEAD,获取完整响应
|
|
173
173
|
cache: 'no-cache',
|
|
174
|
-
|
|
174
|
+
redirect: 'manual', // 不自动跟随重定向,避免无限循环
|
|
175
|
+
signal: controller.signal,
|
|
176
|
+
headers: {
|
|
177
|
+
'X-Health-Check': 'true' // 标识这是健康检查请求
|
|
178
|
+
}
|
|
175
179
|
});
|
|
176
180
|
|
|
177
181
|
clearTimeout(timeoutId);
|
|
178
182
|
|
|
179
|
-
//
|
|
180
|
-
|
|
183
|
+
// 检查响应状态和响应头
|
|
184
|
+
const contentType = response.headers.get('content-type') || '';
|
|
185
|
+
const isErrorPage = response.headers.get('x-proxy-error-page') === 'true';
|
|
186
|
+
|
|
187
|
+
console.log('[Probe] 状态码:', response.status, 'Content-Type:', contentType, '是否错误页面:', isErrorPage);
|
|
188
|
+
|
|
189
|
+
// 如果收到 302/303 重定向,说明服务正在恢复中,继续探测
|
|
190
|
+
if (response.status === 302 || response.status === 303) {
|
|
191
|
+
console.log('[Probe] 收到重定向响应,服务可能正在恢复,继续探测');
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// 如果是 502 或明确标记为错误页面,继续探测
|
|
196
|
+
if (response.status === 502 || isErrorPage) {
|
|
197
|
+
console.log('[Probe] 服务未恢复,继续探测');
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// 如果是 200,需要进一步验证不是错误页面
|
|
202
|
+
if (response.status === 200) {
|
|
203
|
+
// 检查响应头是否明确标记为错误页面
|
|
204
|
+
if (isErrorPage) {
|
|
205
|
+
console.log('[Probe] 收到 200 但是错误页面,继续探测');
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// 读取响应文本,检查是否包含错误页面的特征
|
|
210
|
+
const text = await response.text();
|
|
211
|
+
|
|
212
|
+
// 检查是否是当前的错误页面(通过检查特定的标识字符串)
|
|
213
|
+
if (text.includes('哎呀,写错代码了') || text.includes('X-Proxy-Error-Page')) {
|
|
214
|
+
console.log('[Probe] 响应内容包含错误页面标识,继续探测');
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// 通过所有检查,认为服务真正恢复
|
|
181
219
|
console.log('[Probe] 服务已恢复,准备刷新页面');
|
|
182
220
|
stopServiceProbe();
|
|
183
221
|
|
|
@@ -187,7 +225,7 @@
|
|
|
187
225
|
window.location.href = currentUrl;
|
|
188
226
|
}, 300);
|
|
189
227
|
} else {
|
|
190
|
-
console.log('[Probe]
|
|
228
|
+
console.log('[Probe] 收到非预期状态码:', response.status, '继续探测');
|
|
191
229
|
}
|
|
192
230
|
} catch (error) {
|
|
193
231
|
// 网络错误、超时或服务未恢复
|
|
@@ -200,17 +238,6 @@
|
|
|
200
238
|
}
|
|
201
239
|
}
|
|
202
240
|
|
|
203
|
-
// 获取当前 URL(去掉 _retry_count 参数)
|
|
204
|
-
function getCurrentUrlWithoutRetryCount() {
|
|
205
|
-
try {
|
|
206
|
-
const url = new URL(window.location.href);
|
|
207
|
-
url.searchParams.delete('_retry_count');
|
|
208
|
-
return url.pathname + url.search;
|
|
209
|
-
} catch (e) {
|
|
210
|
-
return window.location.pathname;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
241
|
// 复制错误信息到剪贴板
|
|
215
242
|
async function handleCopy() {
|
|
216
243
|
if (!errorData) {
|
|
@@ -250,6 +277,7 @@
|
|
|
250
277
|
|
|
251
278
|
// 告诉妙搭修复
|
|
252
279
|
function handleRepair() {
|
|
280
|
+
console.log('[Render Error Repair] 告诉妙搭修复错误:', errorData);
|
|
253
281
|
sendPostMessage({
|
|
254
282
|
type: 'RenderErrorRepair',
|
|
255
283
|
data: errorData,
|
|
@@ -346,7 +374,7 @@
|
|
|
346
374
|
class="error-image"
|
|
347
375
|
/>
|
|
348
376
|
<p class="title">哎呀,写错代码了</p>
|
|
349
|
-
<p class="description"
|
|
377
|
+
<p class="description">可复制错误信息,或告诉妙搭进行修复。</p>
|
|
350
378
|
<div class="button-group">
|
|
351
379
|
<button class="button button-copy" id="copyBtn" onclick="handleCopy()">
|
|
352
380
|
复制错误信息
|
package/dist/index.cjs
CHANGED
|
@@ -22320,10 +22320,10 @@ var require_layer = __commonJS({
|
|
|
22320
22320
|
var require_methods = __commonJS({
|
|
22321
22321
|
"../../../node_modules/methods/index.js"(exports2, module2) {
|
|
22322
22322
|
"use strict";
|
|
22323
|
-
var
|
|
22323
|
+
var http2 = require("http");
|
|
22324
22324
|
module2.exports = getCurrentNodeMethods() || getBasicNodeMethods();
|
|
22325
22325
|
function getCurrentNodeMethods() {
|
|
22326
|
-
return
|
|
22326
|
+
return http2.METHODS && http2.METHODS.map(/* @__PURE__ */ __name(function lowerCaseMethod(method) {
|
|
22327
22327
|
return method.toLowerCase();
|
|
22328
22328
|
}, "lowerCaseMethod"));
|
|
22329
22329
|
}
|
|
@@ -26001,7 +26001,7 @@ var require_application = __commonJS({
|
|
|
26001
26001
|
var query = require_query();
|
|
26002
26002
|
var debug = require_src3()("express:application");
|
|
26003
26003
|
var View = require_view();
|
|
26004
|
-
var
|
|
26004
|
+
var http2 = require("http");
|
|
26005
26005
|
var compileETag = require_utils2().compileETag;
|
|
26006
26006
|
var compileQueryParser = require_utils2().compileQueryParser;
|
|
26007
26007
|
var compileTrust = require_utils2().compileTrust;
|
|
@@ -26250,7 +26250,7 @@ var require_application = __commonJS({
|
|
|
26250
26250
|
tryRender(view, renderOptions, done);
|
|
26251
26251
|
}, "render");
|
|
26252
26252
|
app.listen = /* @__PURE__ */ __name(function listen() {
|
|
26253
|
-
var server =
|
|
26253
|
+
var server = http2.createServer(this);
|
|
26254
26254
|
return server.listen.apply(server, arguments);
|
|
26255
26255
|
}, "listen");
|
|
26256
26256
|
function logerror(err) {
|
|
@@ -26913,12 +26913,12 @@ var require_request = __commonJS({
|
|
|
26913
26913
|
var deprecate = require_depd()("express");
|
|
26914
26914
|
var isIP = require("net").isIP;
|
|
26915
26915
|
var typeis = require_type_is();
|
|
26916
|
-
var
|
|
26916
|
+
var http2 = require("http");
|
|
26917
26917
|
var fresh = require_fresh();
|
|
26918
26918
|
var parseRange = require_range_parser();
|
|
26919
26919
|
var parse = require_parseurl();
|
|
26920
26920
|
var proxyaddr = require_proxy_addr();
|
|
26921
|
-
var req = Object.create(
|
|
26921
|
+
var req = Object.create(http2.IncomingMessage.prototype);
|
|
26922
26922
|
module2.exports = req;
|
|
26923
26923
|
req.get = req.header = /* @__PURE__ */ __name(function header(name) {
|
|
26924
26924
|
if (!name) {
|
|
@@ -27344,7 +27344,7 @@ var require_response = __commonJS({
|
|
|
27344
27344
|
var deprecate = require_depd()("express");
|
|
27345
27345
|
var encodeUrl = require_encodeurl();
|
|
27346
27346
|
var escapeHtml = require_escape_html();
|
|
27347
|
-
var
|
|
27347
|
+
var http2 = require("http");
|
|
27348
27348
|
var isAbsolute3 = require_utils2().isAbsolute;
|
|
27349
27349
|
var onFinished = require_on_finished();
|
|
27350
27350
|
var path6 = require("path");
|
|
@@ -27360,7 +27360,7 @@ var require_response = __commonJS({
|
|
|
27360
27360
|
var mime = send.mime;
|
|
27361
27361
|
var resolve = path6.resolve;
|
|
27362
27362
|
var vary = require_vary();
|
|
27363
|
-
var res = Object.create(
|
|
27363
|
+
var res = Object.create(http2.ServerResponse.prototype);
|
|
27364
27364
|
module2.exports = res;
|
|
27365
27365
|
var charsetRegExp = /;\s*charset\s*=/;
|
|
27366
27366
|
res.status = /* @__PURE__ */ __name(function status(code) {
|
|
@@ -28407,7 +28407,8 @@ var import_node_fs2 = __toESM(require("fs"), 1);
|
|
|
28407
28407
|
var import_node_path2 = __toESM(require("path"), 1);
|
|
28408
28408
|
var import_node_fs3 = require("fs");
|
|
28409
28409
|
var import_node_readline = require("readline");
|
|
28410
|
-
var
|
|
28410
|
+
var import_node_http = __toESM(require("http"), 1);
|
|
28411
|
+
var import_node_https = __toESM(require("https"), 1);
|
|
28411
28412
|
var errorHtmlTemplate = null;
|
|
28412
28413
|
function isConnectionError(err) {
|
|
28413
28414
|
const code = err.code;
|
|
@@ -28421,30 +28422,40 @@ function isConnectionError(err) {
|
|
|
28421
28422
|
return connectionErrorCodes.includes(code || "");
|
|
28422
28423
|
}
|
|
28423
28424
|
__name(isConnectionError, "isConnectionError");
|
|
28424
|
-
function checkServiceAvailable(
|
|
28425
|
+
function checkServiceAvailable(targetUrl, timeout = 1e3) {
|
|
28425
28426
|
return new Promise((resolve) => {
|
|
28426
|
-
|
|
28427
|
-
|
|
28428
|
-
|
|
28429
|
-
|
|
28430
|
-
|
|
28431
|
-
|
|
28432
|
-
|
|
28433
|
-
|
|
28434
|
-
|
|
28435
|
-
|
|
28436
|
-
|
|
28437
|
-
|
|
28438
|
-
|
|
28427
|
+
try {
|
|
28428
|
+
const url = new URL(targetUrl);
|
|
28429
|
+
const isHttps = url.protocol === "https:";
|
|
28430
|
+
const httpModule = isHttps ? import_node_https.default : import_node_http.default;
|
|
28431
|
+
const req = httpModule.request({
|
|
28432
|
+
hostname: url.hostname,
|
|
28433
|
+
port: url.port || (isHttps ? 443 : 80),
|
|
28434
|
+
path: "/",
|
|
28435
|
+
method: "HEAD",
|
|
28436
|
+
timeout
|
|
28437
|
+
}, (res) => {
|
|
28438
|
+
const available = res.statusCode !== 502 && !res.headers["x-proxy-error-page"];
|
|
28439
|
+
resolve(available);
|
|
28440
|
+
});
|
|
28441
|
+
req.on("timeout", () => {
|
|
28442
|
+
req.destroy();
|
|
28443
|
+
resolve(false);
|
|
28444
|
+
});
|
|
28445
|
+
req.on("error", () => {
|
|
28446
|
+
resolve(false);
|
|
28447
|
+
});
|
|
28448
|
+
req.end();
|
|
28449
|
+
} catch (e) {
|
|
28439
28450
|
resolve(false);
|
|
28440
|
-
}
|
|
28451
|
+
}
|
|
28441
28452
|
});
|
|
28442
28453
|
}
|
|
28443
28454
|
__name(checkServiceAvailable, "checkServiceAvailable");
|
|
28444
|
-
async function waitForServiceRecovery(
|
|
28455
|
+
async function waitForServiceRecovery(targetUrl, timeout, interval) {
|
|
28445
28456
|
const startTime = Date.now();
|
|
28446
28457
|
while (Date.now() - startTime < timeout) {
|
|
28447
|
-
const isAvailable = await checkServiceAvailable(
|
|
28458
|
+
const isAvailable = await checkServiceAvailable(targetUrl, 2e3);
|
|
28448
28459
|
if (isAvailable) {
|
|
28449
28460
|
return true;
|
|
28450
28461
|
}
|
|
@@ -28547,7 +28558,7 @@ function injectErrorData(template, errorLogs) {
|
|
|
28547
28558
|
}
|
|
28548
28559
|
__name(injectErrorData, "injectErrorData");
|
|
28549
28560
|
function handleDevProxyError(err, req, res, options) {
|
|
28550
|
-
const { logDir = import_node_path2.default.join(process.cwd(), "logs"), maxErrorLogs = 100, logFileName = "server.log", retryTimeout = 5e3, retryInterval = 500, target
|
|
28561
|
+
const { logDir = import_node_path2.default.join(process.cwd(), "logs"), maxErrorLogs = 100, logFileName = "server.log", retryTimeout = 5e3, retryInterval = 500, target } = options || {};
|
|
28551
28562
|
console.error("[Proxy Error]:", err.message);
|
|
28552
28563
|
if (res.headersSent) {
|
|
28553
28564
|
console.error("[Proxy Error]: Headers already sent, cannot send error page");
|
|
@@ -28559,33 +28570,32 @@ function handleDevProxyError(err, req, res, options) {
|
|
|
28559
28570
|
const { logs: errorLogs, hasCompileError } = await readRecentErrorLogs(logDir, maxErrorLogs, logFileName);
|
|
28560
28571
|
if (isConnError && !hasCompileError && target) {
|
|
28561
28572
|
console.log("[Proxy Error]: Connection error without compile errors, possibly server restarting...");
|
|
28562
|
-
let targetUrl = null;
|
|
28563
28573
|
try {
|
|
28564
|
-
|
|
28574
|
+
new URL(target);
|
|
28565
28575
|
} catch (e) {
|
|
28566
28576
|
console.error("[Proxy Error]: Invalid target URL:", target);
|
|
28577
|
+
console.log("[Proxy Error]: Showing error page due to invalid target");
|
|
28567
28578
|
}
|
|
28568
|
-
|
|
28569
|
-
|
|
28570
|
-
|
|
28571
|
-
console.log(
|
|
28572
|
-
|
|
28573
|
-
|
|
28574
|
-
console.log("[Proxy Error]: Service recovered, sending retry response");
|
|
28575
|
-
} else {
|
|
28576
|
-
console.log("[Proxy Error]: Service did not recover within timeout, sending retry response");
|
|
28577
|
-
}
|
|
28579
|
+
console.log(`[Proxy Error]: Waiting for service recovery at ${target} (timeout: ${retryTimeout}ms)...`);
|
|
28580
|
+
const recovered = await waitForServiceRecovery(target, retryTimeout, retryInterval);
|
|
28581
|
+
if (recovered) {
|
|
28582
|
+
console.log("[Proxy Error]: Service recovered within timeout, sending 302 redirect");
|
|
28583
|
+
sendSimpleRedirect(req, res);
|
|
28584
|
+
return;
|
|
28578
28585
|
}
|
|
28579
|
-
|
|
28580
|
-
|
|
28581
|
-
|
|
28586
|
+
console.log("[Proxy Error]: Service did not recover within timeout, showing error page with probe");
|
|
28587
|
+
}
|
|
28588
|
+
if (isConnError && !hasCompileError) {
|
|
28589
|
+
console.log("[Proxy Error]: Showing error page with auto-refresh probe");
|
|
28590
|
+
} else {
|
|
28591
|
+
console.log("[Proxy Error]: Compile error or non-connection error, showing error page");
|
|
28582
28592
|
}
|
|
28583
|
-
console.log("[Proxy Error]: Compile error or non-connection error, showing error page");
|
|
28584
28593
|
const template = getErrorHtmlTemplate();
|
|
28585
28594
|
const html = injectErrorData(template, errorLogs);
|
|
28586
28595
|
res.writeHead(502, {
|
|
28587
28596
|
"Content-Type": "text/html; charset=utf-8",
|
|
28588
|
-
"Cache-Control": "no-cache, no-store, must-revalidate"
|
|
28597
|
+
"Cache-Control": "no-cache, no-store, must-revalidate",
|
|
28598
|
+
"X-Proxy-Error-Page": "true"
|
|
28589
28599
|
});
|
|
28590
28600
|
res.end(html);
|
|
28591
28601
|
} catch (error) {
|
|
@@ -28600,45 +28610,17 @@ function handleDevProxyError(err, req, res, options) {
|
|
|
28600
28610
|
})();
|
|
28601
28611
|
}
|
|
28602
28612
|
__name(handleDevProxyError, "handleDevProxyError");
|
|
28603
|
-
function
|
|
28604
|
-
|
|
28605
|
-
const urlObj = new URL(url, "http://localhost");
|
|
28606
|
-
const retryCount = urlObj.searchParams.get("_retry_count");
|
|
28607
|
-
return retryCount ? parseInt(retryCount, 10) : 0;
|
|
28608
|
-
} catch {
|
|
28609
|
-
return 0;
|
|
28610
|
-
}
|
|
28611
|
-
}
|
|
28612
|
-
__name(getRedirectCount, "getRedirectCount");
|
|
28613
|
-
function addRedirectCount(url, count) {
|
|
28614
|
-
try {
|
|
28615
|
-
const urlObj = new URL(url, "http://localhost");
|
|
28616
|
-
urlObj.searchParams.set("_retry_count", String(count));
|
|
28617
|
-
return urlObj.pathname + urlObj.search;
|
|
28618
|
-
} catch {
|
|
28619
|
-
return url;
|
|
28620
|
-
}
|
|
28621
|
-
}
|
|
28622
|
-
__name(addRedirectCount, "addRedirectCount");
|
|
28623
|
-
function sendSimpleRetryResponse(req, res, maxRedirects) {
|
|
28624
|
-
if (res.headersSent) return true;
|
|
28613
|
+
function sendSimpleRedirect(req, res) {
|
|
28614
|
+
if (res.headersSent) return;
|
|
28625
28615
|
const originalUrl = req.url || "/";
|
|
28626
|
-
|
|
28627
|
-
if (currentCount >= maxRedirects) {
|
|
28628
|
-
console.log(`[Proxy Error]: Max redirects (${maxRedirects}) reached, will show detailed error page`);
|
|
28629
|
-
return false;
|
|
28630
|
-
}
|
|
28631
|
-
const nextCount = currentCount + 1;
|
|
28632
|
-
const redirectUrl = addRedirectCount(originalUrl, nextCount);
|
|
28633
|
-
console.log(`[Proxy Error]: Redirecting (attempt ${nextCount}/${maxRedirects}) to ${redirectUrl}`);
|
|
28616
|
+
console.log("[Proxy Error]: Sending 302 redirect to", originalUrl);
|
|
28634
28617
|
res.writeHead(302, {
|
|
28635
|
-
"Location":
|
|
28618
|
+
"Location": originalUrl,
|
|
28636
28619
|
"Cache-Control": "no-cache, no-store, must-revalidate"
|
|
28637
28620
|
});
|
|
28638
28621
|
res.end();
|
|
28639
|
-
return true;
|
|
28640
28622
|
}
|
|
28641
|
-
__name(
|
|
28623
|
+
__name(sendSimpleRedirect, "sendSimpleRedirect");
|
|
28642
28624
|
|
|
28643
28625
|
// src/middlewares/index.ts
|
|
28644
28626
|
var import_node_path8 = __toESM(require("path"), 1);
|