@lark-apaas/devtool-kits 1.0.5-alpha.3 → 1.0.5-alpha.4

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 CHANGED
@@ -108,6 +108,7 @@
108
108
 
109
109
  <script>
110
110
  // 全局错误对象
111
+ let clientBasePath = '{{.clientBasePath}}';
111
112
  let errorData = {
112
113
  message: `{{.errorData.message}}`,
113
114
  };
@@ -159,71 +160,60 @@
159
160
  // 探测服务是否恢复
160
161
  async function probeService() {
161
162
  try {
162
- // 获取当前 URL
163
- const currentUrl = window.location.pathname + window.location.search;
164
-
165
- console.log('[Probe] 探测服务状态:', currentUrl);
163
+ console.log('[Probe] 探测服务状态: /dev/health');
166
164
 
167
165
  // 使用 AbortController 实现超时控制
168
166
  const controller = new AbortController();
169
167
  const timeoutId = setTimeout(() => controller.abort(), PROBE_TIMEOUT);
170
168
 
171
- const response = await fetch(currentUrl, {
172
- method: 'GET', // 使用 GET 而不是 HEAD,获取完整响应
169
+ const response = await fetch(`${clientBasePath}/dev/health`, {
170
+ method: 'GET',
173
171
  cache: 'no-cache',
174
- redirect: 'manual', // 不自动跟随重定向,避免无限循环
175
- signal: controller.signal,
176
- headers: {
177
- 'X-Health-Check': 'true' // 标识这是健康检查请求
178
- }
172
+ redirect: 'manual', // 不自动跟随重定向
173
+ signal: controller.signal
179
174
  });
180
175
 
181
176
  clearTimeout(timeoutId);
182
177
 
183
- // 检查响应状态和响应头
184
- const contentType = response.headers.get('content-type') || '';
185
- const isErrorPage = response.headers.get('x-proxy-error-page') === 'true';
178
+ console.log('[Probe] 状态码:', response.status);
186
179
 
187
- console.log('[Probe] 状态码:', response.status, 'Content-Type:', contentType, '是否错误页面:', isErrorPage);
188
-
189
- // 如果收到 302/303 重定向,说明服务正在恢复中,继续探测
180
+ // 如果收到 302/303 重定向,说明代理层正在恢复中,继续探测
190
181
  if (response.status === 302 || response.status === 303) {
191
182
  console.log('[Probe] 收到重定向响应,服务可能正在恢复,继续探测');
192
183
  return;
193
184
  }
194
185
 
195
- // 如果是 502 或明确标记为错误页面,继续探测
196
- if (response.status === 502 || isErrorPage) {
197
- console.log('[Probe] 服务未恢复,继续探测');
186
+ // 如果是 502,说明代理遇到错误,继续探测
187
+ if (response.status === 502) {
188
+ console.log('[Probe] 服务未恢复(502),继续探测');
198
189
  return;
199
190
  }
200
191
 
201
- // 如果是 200,需要进一步验证不是错误页面
192
+ // 如果是 200,解析健康检查结果
202
193
  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;
194
+ try {
195
+ const data = await response.json();
196
+
197
+ // 检查健康状态
198
+ if (data.status === 'healthy') {
199
+ console.log('[Probe] 服务已恢复,响应时间:', data.responseTime, 'ms');
200
+ stopServiceProbe();
201
+
202
+ // 延迟一小段时间后刷新,让日志输出完整
203
+ setTimeout(() => {
204
+ console.log('[Probe] 刷新页面...');
205
+ const currentUrl = window.location.pathname + window.location.search;
206
+ window.location.href = currentUrl;
207
+ }, 300);
208
+ } else {
209
+ console.log('[Probe] 服务状态:', data.status, '错误:', data.error);
210
+ }
211
+ } catch (e) {
212
+ console.log('[Probe] 解析响应失败:', e.message, '继续探测');
216
213
  }
217
-
218
- // 通过所有检查,认为服务真正恢复
219
- console.log('[Probe] 服务已恢复,准备刷新页面');
220
- stopServiceProbe();
221
-
222
- // 延迟一小段时间后刷新,让日志输出完整
223
- setTimeout(() => {
224
- console.log('[Probe] 刷新页面...');
225
- window.location.href = currentUrl;
226
- }, 300);
214
+ } else if (response.status === 503) {
215
+ // 503 表示服务不健康,继续探测
216
+ console.log('[Probe] 服务不健康(503),继续探测');
227
217
  } else {
228
218
  console.log('[Probe] 收到非预期状态码:', response.status, '继续探测');
229
219
  }
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 http2 = require("http");
22323
+ var http3 = require("http");
22324
22324
  module2.exports = getCurrentNodeMethods() || getBasicNodeMethods();
22325
22325
  function getCurrentNodeMethods() {
22326
- return http2.METHODS && http2.METHODS.map(/* @__PURE__ */ __name(function lowerCaseMethod(method) {
22326
+ return http3.METHODS && http3.METHODS.map(/* @__PURE__ */ __name(function lowerCaseMethod(method) {
22327
22327
  return method.toLowerCase();
22328
22328
  }, "lowerCaseMethod"));
22329
22329
  }
@@ -25995,13 +25995,13 @@ var require_application = __commonJS({
25995
25995
  "../../../node_modules/express/lib/application.js"(exports2, module2) {
25996
25996
  "use strict";
25997
25997
  var finalhandler = require_finalhandler();
25998
- var Router = require_router();
25998
+ var Router2 = require_router();
25999
25999
  var methods = require_methods();
26000
26000
  var middleware = require_init();
26001
26001
  var query = require_query();
26002
26002
  var debug = require_src3()("express:application");
26003
26003
  var View = require_view();
26004
- var http2 = require("http");
26004
+ var http3 = require("http");
26005
26005
  var compileETag = require_utils2().compileETag;
26006
26006
  var compileQueryParser = require_utils2().compileQueryParser;
26007
26007
  var compileTrust = require_utils2().compileTrust;
@@ -26060,7 +26060,7 @@ var require_application = __commonJS({
26060
26060
  }, "defaultConfiguration");
26061
26061
  app.lazyrouter = /* @__PURE__ */ __name(function lazyrouter() {
26062
26062
  if (!this._router) {
26063
- this._router = new Router({
26063
+ this._router = new Router2({
26064
26064
  caseSensitive: this.enabled("case sensitive routing"),
26065
26065
  strict: this.enabled("strict routing")
26066
26066
  });
@@ -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 = http2.createServer(this);
26253
+ var server = http3.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 http2 = require("http");
26916
+ var http3 = 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(http2.IncomingMessage.prototype);
26921
+ var req = Object.create(http3.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 http2 = require("http");
27347
+ var http3 = 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(http2.ServerResponse.prototype);
27363
+ var res = Object.create(http3.ServerResponse.prototype);
27364
27364
  module2.exports = res;
27365
27365
  var charsetRegExp = /;\s*charset\s*=/;
27366
27366
  res.status = /* @__PURE__ */ __name(function status(code) {
@@ -28009,7 +28009,7 @@ var require_express = __commonJS({
28009
28009
  var mixin = require_merge_descriptors();
28010
28010
  var proto = require_application();
28011
28011
  var Route = require_route();
28012
- var Router = require_router();
28012
+ var Router2 = require_router();
28013
28013
  var req = require_request();
28014
28014
  var res = require_response();
28015
28015
  exports2 = module2.exports = createApplication;
@@ -28043,7 +28043,7 @@ var require_express = __commonJS({
28043
28043
  exports2.request = req;
28044
28044
  exports2.response = res;
28045
28045
  exports2.Route = Route;
28046
- exports2.Router = Router;
28046
+ exports2.Router = Router2;
28047
28047
  exports2.json = bodyParser.json;
28048
28048
  exports2.query = require_query();
28049
28049
  exports2.raw = bodyParser.raw;
@@ -28093,6 +28093,7 @@ var index_exports = {};
28093
28093
  __export(index_exports, {
28094
28094
  createCollectLogsMiddleware: () => createCollectLogsMiddleware,
28095
28095
  createDevLogsMiddleware: () => createDevLogsMiddleware,
28096
+ createHealthCheckMiddleware: () => createHealthCheckMiddleware,
28096
28097
  createOpenapiMiddleware: () => createOpenapiMiddleware,
28097
28098
  handleDevProxyError: () => handleDevProxyError,
28098
28099
  normalizeBasePath: () => normalizeBasePath,
@@ -28546,7 +28547,7 @@ async function readRecentErrorLogs(logDir, maxLogs, fileName) {
28546
28547
  };
28547
28548
  }
28548
28549
  __name(readRecentErrorLogs, "readRecentErrorLogs");
28549
- function injectErrorData(template, errorLogs) {
28550
+ function injectErrorData(template, errorLogs, clientBasePath) {
28550
28551
  let logsText = "";
28551
28552
  if (errorLogs.length > 0) {
28552
28553
  logsText = errorLogs.join("\n");
@@ -28554,11 +28555,12 @@ function injectErrorData(template, errorLogs) {
28554
28555
  logsText = "\u672A\u627E\u5230\u76F8\u5173\u9519\u8BEF\u65E5\u5FD7";
28555
28556
  }
28556
28557
  return template.replace("{{.errorData.message}}", `\u670D\u52A1\u542F\u52A8\u5F02\u5E38\uFF0C\u8BF7\u6839\u636E\u65E5\u5FD7\u4FEE\u590D\u76F8\u5173\u95EE\u9898
28557
- ${JSON.stringify(logsText)}`);
28558
+ ${JSON.stringify(logsText)}`).replace("{{.clientBasePath}}", clientBasePath);
28558
28559
  }
28559
28560
  __name(injectErrorData, "injectErrorData");
28560
28561
  function handleDevProxyError(err, req, res, options) {
28561
- const { logDir = import_node_path2.default.join(process.cwd(), "logs"), maxErrorLogs = 100, logFileName = "server.log", retryTimeout = 5e3, retryInterval = 500, target } = options || {};
28562
+ const { logDir = import_node_path2.default.join(process.cwd(), "logs"), maxErrorLogs = 100, logFileName = "server.log", retryTimeout = 5e3, retryInterval = 500, target, clientBasePath = process.env.CLIENT_BASE_PATH || "/" } = options || {};
28563
+ const clientBasePathWithoutSlash = normalizeBasePath(clientBasePath);
28562
28564
  console.error("[Proxy Error]:", err.message);
28563
28565
  if (res.headersSent) {
28564
28566
  console.error("[Proxy Error]: Headers already sent, cannot send error page");
@@ -28591,7 +28593,7 @@ function handleDevProxyError(err, req, res, options) {
28591
28593
  console.log("[Proxy Error]: Compile error or non-connection error, showing error page");
28592
28594
  }
28593
28595
  const template = getErrorHtmlTemplate();
28594
- const html = injectErrorData(template, errorLogs);
28596
+ const html = injectErrorData(template, errorLogs, clientBasePathWithoutSlash);
28595
28597
  res.writeHead(502, {
28596
28598
  "Content-Type": "text/html; charset=utf-8",
28597
28599
  "Cache-Control": "no-cache, no-store, must-revalidate",
@@ -28625,8 +28627,99 @@ __name(sendSimpleRedirect, "sendSimpleRedirect");
28625
28627
  // src/middlewares/index.ts
28626
28628
  var import_node_path8 = __toESM(require("path"), 1);
28627
28629
 
28628
- // src/middlewares/openapi/router.ts
28630
+ // src/middlewares/health-check/router.ts
28629
28631
  var import_express = __toESM(require_express2(), 1);
28632
+ var import_node_http2 = __toESM(require("http"), 1);
28633
+ function checkServiceHealth(host, port, timeout) {
28634
+ return new Promise((resolve) => {
28635
+ const startTime = Date.now();
28636
+ const req = import_node_http2.default.request({
28637
+ hostname: host,
28638
+ port,
28639
+ path: "/",
28640
+ method: "HEAD",
28641
+ timeout
28642
+ }, (_res) => {
28643
+ const responseTime = Date.now() - startTime;
28644
+ resolve({
28645
+ available: true,
28646
+ responseTime
28647
+ });
28648
+ });
28649
+ req.on("timeout", () => {
28650
+ req.destroy();
28651
+ resolve({
28652
+ available: false,
28653
+ error: "Request timeout"
28654
+ });
28655
+ });
28656
+ req.on("error", (err) => {
28657
+ resolve({
28658
+ available: false,
28659
+ error: err.message
28660
+ });
28661
+ });
28662
+ req.end();
28663
+ });
28664
+ }
28665
+ __name(checkServiceHealth, "checkServiceHealth");
28666
+ function createHealthCheckRouter(options = {}) {
28667
+ const { targetPort = Number(process.env.SERVER_PORT) || 3e3, targetHost = "localhost", timeout = 2e3 } = options;
28668
+ const router = (0, import_express.Router)();
28669
+ router.get("/", async (_req, res) => {
28670
+ try {
28671
+ const result = await checkServiceHealth(targetHost, targetPort, timeout);
28672
+ if (result.available) {
28673
+ res.status(200).json({
28674
+ status: "healthy",
28675
+ service: `${targetHost}:${targetPort}`,
28676
+ responseTime: result.responseTime,
28677
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
28678
+ });
28679
+ } else {
28680
+ res.status(503).json({
28681
+ status: "unhealthy",
28682
+ service: `${targetHost}:${targetPort}`,
28683
+ error: result.error,
28684
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
28685
+ });
28686
+ }
28687
+ } catch (error) {
28688
+ res.status(500).json({
28689
+ status: "error",
28690
+ service: `${targetHost}:${targetPort}`,
28691
+ error: error instanceof Error ? error.message : "Unknown error",
28692
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
28693
+ });
28694
+ }
28695
+ });
28696
+ return router;
28697
+ }
28698
+ __name(createHealthCheckRouter, "createHealthCheckRouter");
28699
+
28700
+ // src/middlewares/health-check/index.ts
28701
+ var HEALTH_CHECK_ROUTES = [
28702
+ {
28703
+ method: "GET",
28704
+ path: "/",
28705
+ description: "Check if target service is healthy and available"
28706
+ }
28707
+ ];
28708
+ function createHealthCheckMiddleware(options = {}) {
28709
+ return {
28710
+ name: "health-check",
28711
+ mountPath: "/dev/health",
28712
+ routes: HEALTH_CHECK_ROUTES,
28713
+ enabled: /* @__PURE__ */ __name((context) => context.isDev, "enabled"),
28714
+ createRouter: /* @__PURE__ */ __name((_context) => {
28715
+ return createHealthCheckRouter(options);
28716
+ }, "createRouter")
28717
+ };
28718
+ }
28719
+ __name(createHealthCheckMiddleware, "createHealthCheckMiddleware");
28720
+
28721
+ // src/middlewares/openapi/router.ts
28722
+ var import_express2 = __toESM(require_express2(), 1);
28630
28723
 
28631
28724
  // src/middlewares/openapi/controller.ts
28632
28725
  var import_promises = __toESM(require("fs/promises"), 1);
@@ -28873,7 +28966,7 @@ __name(createOpenapiHandler, "createOpenapiHandler");
28873
28966
  // src/middlewares/openapi/router.ts
28874
28967
  function createOpenapiRouter(options, context) {
28875
28968
  const { openapiFilePath, enableEnhancement, serverDir } = options;
28876
- const router = import_express.default.Router();
28969
+ const router = import_express2.default.Router();
28877
28970
  const handler = createOpenapiHandler(openapiFilePath, enableEnhancement, serverDir);
28878
28971
  router.get("/openapi.json", (req, res) => handler(req, res, context));
28879
28972
  return router;
@@ -28907,7 +29000,7 @@ function createOpenapiMiddleware(options) {
28907
29000
  __name(createOpenapiMiddleware, "createOpenapiMiddleware");
28908
29001
 
28909
29002
  // src/middlewares/dev-logs/router.ts
28910
- var import_express2 = __toESM(require_express2(), 1);
29003
+ var import_express3 = __toESM(require_express2(), 1);
28911
29004
 
28912
29005
  // src/middlewares/dev-logs/utils.ts
28913
29006
  var import_node_fs6 = require("fs");
@@ -29352,7 +29445,7 @@ __name(createGetLogFileHandler, "createGetLogFileHandler");
29352
29445
  // src/middlewares/dev-logs/router.ts
29353
29446
  function createDevLogRouter(options = {}) {
29354
29447
  const logDir = resolveLogDir(options.logDir);
29355
- const router = import_express2.default.Router();
29448
+ const router = import_express3.default.Router();
29356
29449
  router.get("/app/trace/:traceId", createGetTraceEntriesHandler(logDir));
29357
29450
  router.get("/trace/recent", createGetRecentTracesHandler(logDir));
29358
29451
  router.get("/files/:fileName", createGetLogFileHandler(logDir));
@@ -29395,7 +29488,7 @@ function createDevLogsMiddleware(options = {}) {
29395
29488
  __name(createDevLogsMiddleware, "createDevLogsMiddleware");
29396
29489
 
29397
29490
  // src/middlewares/collect-logs/router.ts
29398
- var import_express3 = __toESM(require_express2(), 1);
29491
+ var import_express4 = __toESM(require_express2(), 1);
29399
29492
 
29400
29493
  // src/middlewares/collect-logs/controller.ts
29401
29494
  var import_path = require("path");
@@ -29494,9 +29587,9 @@ __name(handleError2, "handleError");
29494
29587
  // src/middlewares/collect-logs/router.ts
29495
29588
  function createDevLogRouter2(options = {}) {
29496
29589
  const logDir = resolveLogDir2(options.logDir);
29497
- const router = import_express3.default.Router();
29498
- router.post("/collect", import_express3.default.json(), collectLogsHandler(logDir, options.fileName || "client.log"));
29499
- router.post("/collect-batch", import_express3.default.json(), collectLogsBatchHandler(logDir, options.fileName || "client.log"));
29590
+ const router = import_express4.default.Router();
29591
+ router.post("/collect", import_express4.default.json(), collectLogsHandler(logDir, options.fileName || "client.log"));
29592
+ router.post("/collect-batch", import_express4.default.json(), collectLogsBatchHandler(logDir, options.fileName || "client.log"));
29500
29593
  return router;
29501
29594
  }
29502
29595
  __name(createDevLogRouter2, "createDevLogRouter");
@@ -29579,7 +29672,15 @@ async function registerMiddlewares(server, middlewares, options) {
29579
29672
  rootDir: process.cwd(),
29580
29673
  ...options
29581
29674
  };
29582
- for (const middleware of middlewares) {
29675
+ const defaultMiddlewares = [];
29676
+ if (context.isDev) {
29677
+ defaultMiddlewares.push(createHealthCheckMiddleware());
29678
+ }
29679
+ const allMiddlewares = [
29680
+ ...defaultMiddlewares,
29681
+ ...middlewares
29682
+ ];
29683
+ for (const middleware of allMiddlewares) {
29583
29684
  if (middleware.enabled && !middleware.enabled(context)) {
29584
29685
  continue;
29585
29686
  }
@@ -29606,6 +29707,7 @@ __name(registerMiddlewares, "registerMiddlewares");
29606
29707
  0 && (module.exports = {
29607
29708
  createCollectLogsMiddleware,
29608
29709
  createDevLogsMiddleware,
29710
+ createHealthCheckMiddleware,
29609
29711
  createOpenapiMiddleware,
29610
29712
  handleDevProxyError,
29611
29713
  normalizeBasePath,