@lark-apaas/devtool-kits 1.2.24 → 1.2.25-alpha.20260819082505

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/index.cjs CHANGED
@@ -31,16 +31,21 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.ts
32
32
  var index_exports = {};
33
33
  __export(index_exports, {
34
+ HEALTH_ENDPOINT: () => HEALTH_ENDPOINT,
34
35
  buildFullPath: () => buildFullPath,
35
36
  calculateFileHash: () => calculateFileHash,
36
37
  createCollectLogsMiddleware: () => createCollectLogsMiddleware,
37
38
  createDevLogsMiddleware: () => createDevLogsMiddleware,
39
+ createHealthHandler: () => createHealthHandler,
40
+ createHealthProbe: () => createHealthProbe,
38
41
  createOpenapiMiddleware: () => createOpenapiMiddleware,
39
42
  evaluateTemplateLiteral: () => evaluateTemplateLiteral,
40
43
  extractPageRouteInfo: () => extractPageRouteInfo,
44
+ getHealthPayload: () => getHealthPayload,
41
45
  getQuery: () => getQuery,
42
46
  getQueryParam: () => getQueryParam,
43
47
  handleDevProxyError: () => handleDevProxyError,
48
+ isPidAlive: () => isPidAlive,
44
49
  isRouteComponent: () => isRouteComponent,
45
50
  normalizeBasePath: () => normalizeBasePath,
46
51
  parseAndGenerateNestResourceTemplate: () => parseAndGenerateNestResourceTemplate,
@@ -48,6 +53,8 @@ __export(index_exports, {
48
53
  parseRoutesFromFile: () => parseRoutesFromFile,
49
54
  postprocessDrizzleSchema: () => postprocessDrizzleSchema,
50
55
  registerMiddlewares: () => registerMiddlewares,
56
+ resolveHealth: () => resolveHealth,
57
+ resolveServerLiveness: () => resolveServerLiveness,
51
58
  routeParserLog: () => routeParserLog,
52
59
  sendError: () => sendError,
53
60
  sendJson: () => sendJson,
@@ -1991,8 +1998,8 @@ function hasSpecialPatterns(pattern) {
1991
1998
  return /[{*]/.test(pattern);
1992
1999
  }
1993
2000
  __name(hasSpecialPatterns, "hasSpecialPatterns");
1994
- function normalizePathForMatching(path8) {
1995
- return path8.replace(/\/+/g, "/").replace(/\/+$/, "");
2001
+ function normalizePathForMatching(path11) {
2002
+ return path11.replace(/\/+/g, "/").replace(/\/+$/, "");
1996
2003
  }
1997
2004
  __name(normalizePathForMatching, "normalizePathForMatching");
1998
2005
 
@@ -2541,7 +2548,7 @@ __name(readLogsBySource, "readLogsBySource");
2541
2548
  // src/middlewares/dev-logs/services/trigger.service.ts
2542
2549
  var import_node_fs9 = require("fs");
2543
2550
  var import_node_readline3 = require("readline");
2544
- async function readTriggerList(filePath, trigger, path8, limit, triggerID) {
2551
+ async function readTriggerList(filePath, trigger, path11, limit, triggerID) {
2545
2552
  if (!await fileExists(filePath)) {
2546
2553
  return void 0;
2547
2554
  }
@@ -2567,7 +2574,7 @@ async function readTriggerList(filePath, trigger, path8, limit, triggerID) {
2567
2574
  if (alreadyAdded) {
2568
2575
  return false;
2569
2576
  }
2570
- const isAutomationTrigger = builder.path?.endsWith(path8);
2577
+ const isAutomationTrigger = builder.path?.endsWith(path11);
2571
2578
  if (!isAutomationTrigger) {
2572
2579
  return false;
2573
2580
  }
@@ -2650,7 +2657,7 @@ async function readTriggerList(filePath, trigger, path8, limit, triggerID) {
2650
2657
  };
2651
2658
  }
2652
2659
  __name(readTriggerList, "readTriggerList");
2653
- async function readTriggerDetail(filePath, path8, instanceID) {
2660
+ async function readTriggerDetail(filePath, path11, instanceID) {
2654
2661
  const exists = await fileExists(filePath);
2655
2662
  if (!exists) {
2656
2663
  return void 0;
@@ -2666,7 +2673,7 @@ async function readTriggerDetail(filePath, path8, instanceID) {
2666
2673
  for await (const line of rl) {
2667
2674
  const entry = parseLogLine(line);
2668
2675
  if (!entry) continue;
2669
- const isAutomationTrigger = entry.path?.endsWith(path8);
2676
+ const isAutomationTrigger = entry.path?.endsWith(path11);
2670
2677
  const hasInstanceID = entry.instance_id === instanceID && entry.trigger;
2671
2678
  if (!isAutomationTrigger || !hasInstanceID) continue;
2672
2679
  matches.push(entry);
@@ -2920,16 +2927,16 @@ function createGetTriggerListHandler(logDir) {
2920
2927
  });
2921
2928
  }
2922
2929
  const triggerID = typeof req.query.triggerID === "string" ? req.query.triggerID.trim() : void 0;
2923
- const path8 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
2930
+ const path11 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
2924
2931
  const limit = parseLimit(req.query.limit, 10, 200);
2925
2932
  try {
2926
- const result = await readTriggerList(traceLogPath, trigger, path8, limit, triggerID);
2933
+ const result = await readTriggerList(traceLogPath, trigger, path11, limit, triggerID);
2927
2934
  if (!result) {
2928
2935
  return handleNotFound(res, traceLogPath);
2929
2936
  }
2930
2937
  res.json({
2931
2938
  file: getRelativePath(traceLogPath),
2932
- path: path8,
2939
+ path: path11,
2933
2940
  ...result
2934
2941
  });
2935
2942
  } catch (error) {
@@ -2947,9 +2954,9 @@ function createGetTriggerDetailHandler(logDir) {
2947
2954
  message: "instanceID is required"
2948
2955
  });
2949
2956
  }
2950
- const path8 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
2957
+ const path11 = typeof req.query.path === "string" ? req.query.path.trim() : "/__innerapi__/automation/invoke";
2951
2958
  try {
2952
- const result = await readTriggerDetail(traceLogPath, path8, instanceID);
2959
+ const result = await readTriggerDetail(traceLogPath, path11, instanceID);
2953
2960
  if (!result) {
2954
2961
  return handleNotFound(res, traceLogPath);
2955
2962
  }
@@ -3575,8 +3582,8 @@ __name(createSSEHandler, "createSSEHandler");
3575
3582
 
3576
3583
  // src/middlewares/dev-logs/api-list-handler.ts
3577
3584
  var SERVER_PORT = process.env.SERVER_PORT || "3000";
3578
- function extractModuleFromPath(path8) {
3579
- const segments = path8.split("/").filter(Boolean);
3585
+ function extractModuleFromPath(path11) {
3586
+ const segments = path11.split("/").filter(Boolean);
3580
3587
  let startIndex = 0;
3581
3588
  if (segments[0] === "api") {
3582
3589
  startIndex = 1;
@@ -3591,8 +3598,8 @@ function extractModuleFromPath(path8) {
3591
3598
  return moduleName;
3592
3599
  }
3593
3600
  __name(extractModuleFromPath, "extractModuleFromPath");
3594
- function generateRouteId(method, path8) {
3595
- const cleanPath = path8.replace(/[/:]/g, "_").replace(/^_+|_+$/g, "");
3601
+ function generateRouteId(method, path11) {
3602
+ const cleanPath = path11.replace(/[/:]/g, "_").replace(/^_+|_+$/g, "");
3596
3603
  return `${method.toLowerCase()}_${cleanPath}`;
3597
3604
  }
3598
3605
  __name(generateRouteId, "generateRouteId");
@@ -4067,9 +4074,204 @@ function registerMiddlewares(server, middlewares, options) {
4067
4074
  }
4068
4075
  __name(registerMiddlewares, "registerMiddlewares");
4069
4076
 
4077
+ // src/health/resolve.ts
4078
+ var import_node_fs12 = __toESM(require("fs"), 1);
4079
+ var import_node_path11 = __toESM(require("path"), 1);
4080
+
4081
+ // src/health/server-liveness.ts
4082
+ var import_node_fs11 = __toESM(require("fs"), 1);
4083
+ var import_node_path10 = __toESM(require("path"), 1);
4084
+ var TAIL_BYTES = 64 * 1024;
4085
+ function isListenMarker(line) {
4086
+ const message = String(line.message ?? "");
4087
+ if (line.context === "Bootstrap" && message.startsWith("Server running on")) {
4088
+ return true;
4089
+ }
4090
+ return line.context === "PlatformHealth" && message.startsWith("listening");
4091
+ }
4092
+ __name(isListenMarker, "isListenMarker");
4093
+ function readLastListenMarker(logFile) {
4094
+ let fd;
4095
+ try {
4096
+ const size = import_node_fs11.default.statSync(logFile).size;
4097
+ if (size === 0) return null;
4098
+ const length = Math.min(size, TAIL_BYTES);
4099
+ const buf = Buffer.alloc(length);
4100
+ fd = import_node_fs11.default.openSync(logFile, "r");
4101
+ import_node_fs11.default.readSync(fd, buf, 0, length, size - length);
4102
+ const lines = buf.toString("utf8").split("\n");
4103
+ for (let i = lines.length - 1; i >= 0; i--) {
4104
+ const raw = lines[i].trim();
4105
+ if (!raw.startsWith("{")) continue;
4106
+ try {
4107
+ const parsed = JSON.parse(raw);
4108
+ if (isListenMarker(parsed)) return parsed;
4109
+ } catch {
4110
+ }
4111
+ }
4112
+ } catch {
4113
+ } finally {
4114
+ if (fd !== void 0) {
4115
+ try {
4116
+ import_node_fs11.default.closeSync(fd);
4117
+ } catch {
4118
+ }
4119
+ }
4120
+ }
4121
+ return null;
4122
+ }
4123
+ __name(readLastListenMarker, "readLastListenMarker");
4124
+ function isPidAlive(pid) {
4125
+ if (!Number.isInteger(pid) || pid <= 0) return false;
4126
+ try {
4127
+ process.kill(pid, 0);
4128
+ return true;
4129
+ } catch (err) {
4130
+ return err?.code === "EPERM";
4131
+ }
4132
+ }
4133
+ __name(isPidAlive, "isPidAlive");
4134
+ function resolveServerLiveness(logDir, sessionStartedAt) {
4135
+ const marker = readLastListenMarker(import_node_path10.default.join(logDir, "server.log"));
4136
+ if (!marker || typeof marker.pid !== "number") {
4137
+ return {
4138
+ alive: false,
4139
+ pid: null,
4140
+ listenAt: null
4141
+ };
4142
+ }
4143
+ const listenAt = typeof marker.time === "string" ? marker.time : null;
4144
+ if (sessionStartedAt && listenAt) {
4145
+ const markerMs = Date.parse(listenAt);
4146
+ if (Number.isFinite(markerMs) && markerMs < sessionStartedAt - 5e3) {
4147
+ return {
4148
+ alive: false,
4149
+ pid: marker.pid,
4150
+ listenAt
4151
+ };
4152
+ }
4153
+ }
4154
+ return {
4155
+ alive: isPidAlive(marker.pid),
4156
+ pid: marker.pid,
4157
+ listenAt
4158
+ };
4159
+ }
4160
+ __name(resolveServerLiveness, "resolveServerLiveness");
4161
+
4162
+ // src/health/resolve.ts
4163
+ var DEFAULT_TIMEOUT_MS = 5 * 60 * 1e3;
4164
+ function resolveHealth(options) {
4165
+ const { rootDir, hasServer, clientReady, firstStartedAt, logDir = import_node_path11.default.join(rootDir, "logs"), serverEntry = import_node_path11.default.join(rootDir, "dist", "server", "main.js"), timeoutMs = DEFAULT_TIMEOUT_MS, now = Date.now, sessionStartedAt = null, onServerAlive } = options;
4166
+ if (!hasServer) {
4167
+ return {
4168
+ ready: clientReady,
4169
+ failed: false
4170
+ };
4171
+ }
4172
+ const liveness = resolveServerLiveness(logDir, sessionStartedAt);
4173
+ if (liveness.alive) {
4174
+ onServerAlive?.();
4175
+ return {
4176
+ ready: clientReady,
4177
+ failed: false
4178
+ };
4179
+ }
4180
+ const elapsed = firstStartedAt ? now() - firstStartedAt : 0;
4181
+ if (!firstStartedAt || elapsed <= timeoutMs) {
4182
+ return {
4183
+ ready: false,
4184
+ failed: false
4185
+ };
4186
+ }
4187
+ const seconds = Math.round(elapsed / 1e3);
4188
+ const compiled = safeExists(serverEntry);
4189
+ const message = compiled ? `\u540E\u7AEF\u670D\u52A1\u542F\u52A8\u8D85\u65F6\uFF08\u5DF2\u7B49\u5F85 ${seconds}s\uFF09\uFF1A\u7F16\u8BD1\u4EA7\u7269\u5DF2\u751F\u6210\u4F46\u670D\u52A1\u672A\u76D1\u542C\uFF0C\u8BF7\u67E5\u770B ${import_node_path11.default.join(logDir, "server.std.log")}` : `\u540E\u7AEF\u670D\u52A1\u7F16\u8BD1\u672A\u901A\u8FC7\uFF08\u5DF2\u7B49\u5F85 ${seconds}s\uFF09\uFF1A\u672A\u751F\u6210 ${import_node_path11.default.relative(rootDir, serverEntry)}\uFF0C\u8BF7\u67E5\u770B ${import_node_path11.default.join(logDir, "server.std.log")}`;
4190
+ return {
4191
+ ready: false,
4192
+ failed: true,
4193
+ message
4194
+ };
4195
+ }
4196
+ __name(resolveHealth, "resolveHealth");
4197
+ function safeExists(file) {
4198
+ try {
4199
+ return import_node_fs12.default.existsSync(file);
4200
+ } catch {
4201
+ return false;
4202
+ }
4203
+ }
4204
+ __name(safeExists, "safeExists");
4205
+
4206
+ // src/health/handler.ts
4207
+ var import_node_fs13 = __toESM(require("fs"), 1);
4208
+ var import_node_path12 = __toESM(require("path"), 1);
4209
+ var HEALTH_ENDPOINT = "/dev/health";
4210
+ function resolveTimeoutMs(explicit) {
4211
+ if (typeof explicit === "number") return explicit;
4212
+ const raw = Number(process.env.MIAODA_HEALTH_TIMEOUT_MS);
4213
+ return Number.isFinite(raw) && raw > 0 ? raw : void 0;
4214
+ }
4215
+ __name(resolveTimeoutMs, "resolveTimeoutMs");
4216
+ function readSessionStartedAt(logDir) {
4217
+ try {
4218
+ const raw = import_node_fs13.default.readFileSync(import_node_path12.default.join(logDir, "dev-status.json"), "utf8");
4219
+ const parsed = JSON.parse(raw);
4220
+ return typeof parsed.firstStartedAt === "number" ? parsed.firstStartedAt : null;
4221
+ } catch {
4222
+ return null;
4223
+ }
4224
+ }
4225
+ __name(readSessionStartedAt, "readSessionStartedAt");
4226
+ function createHealthProbe(options) {
4227
+ const logDir = options.logDir ?? import_node_path12.default.join(options.rootDir, "logs");
4228
+ let lastAliveAt = null;
4229
+ return /* @__PURE__ */ __name(function probe() {
4230
+ try {
4231
+ const sessionStartedAt = readSessionStartedAt(logDir);
4232
+ const since = lastAliveAt !== null && (sessionStartedAt === null || lastAliveAt > sessionStartedAt) ? lastAliveAt : sessionStartedAt;
4233
+ const payload = resolveHealth({
4234
+ rootDir: options.rootDir,
4235
+ logDir,
4236
+ hasServer: options.hasServer,
4237
+ clientReady: options.isClientReady(),
4238
+ firstStartedAt: since,
4239
+ timeoutMs: resolveTimeoutMs(options.timeoutMs),
4240
+ onServerAlive: /* @__PURE__ */ __name(() => {
4241
+ lastAliveAt = Date.now();
4242
+ }, "onServerAlive")
4243
+ });
4244
+ return payload;
4245
+ } catch {
4246
+ return {
4247
+ ready: false,
4248
+ failed: false
4249
+ };
4250
+ }
4251
+ }, "probe");
4252
+ }
4253
+ __name(createHealthProbe, "createHealthProbe");
4254
+ function getHealthPayload(options) {
4255
+ return createHealthProbe(options)();
4256
+ }
4257
+ __name(getHealthPayload, "getHealthPayload");
4258
+ function createHealthHandler(options) {
4259
+ const probe = createHealthProbe(options);
4260
+ return /* @__PURE__ */ __name(function healthHandler(req, res, next) {
4261
+ if (req.method && req.method !== "GET" && next) {
4262
+ return next();
4263
+ }
4264
+ res.setHeader("Content-Type", "application/json");
4265
+ res.setHeader("Cache-Control", "no-store");
4266
+ res.statusCode = 200;
4267
+ res.end(JSON.stringify(probe()));
4268
+ }, "healthHandler");
4269
+ }
4270
+ __name(createHealthHandler, "createHealthHandler");
4271
+
4070
4272
  // src/route-parser.ts
4071
- var fs12 = __toESM(require("fs"), 1);
4072
- var path7 = __toESM(require("path"), 1);
4273
+ var fs15 = __toESM(require("fs"), 1);
4274
+ var path10 = __toESM(require("path"), 1);
4073
4275
  var crypto3 = __toESM(require("crypto"), 1);
4074
4276
  var import_parser = require("@babel/parser");
4075
4277
  var import_traverse = __toESM(require("@babel/traverse"), 1);
@@ -4095,7 +4297,7 @@ function routeParserLog(level, message, ...args) {
4095
4297
  __name(routeParserLog, "routeParserLog");
4096
4298
  function calculateFileHash(filePath) {
4097
4299
  try {
4098
- const content = fs12.readFileSync(filePath, "utf-8");
4300
+ const content = fs15.readFileSync(filePath, "utf-8");
4099
4301
  return crypto3.createHash("md5").update(content).digest("hex");
4100
4302
  } catch (error) {
4101
4303
  routeParserLog("warn", "Failed to calculate file hash:", error.message);
@@ -4179,11 +4381,11 @@ function parseRoutesFromFile(appPath, basePath, options = {}) {
4179
4381
  const { applyBasePath = true } = options;
4180
4382
  const defaultPath = applyBasePath && basePath ? `${basePath}/` : "/";
4181
4383
  try {
4182
- const appFilePath = path7.resolve(process.cwd(), appPath);
4183
- if (!fs12.existsSync(appFilePath)) {
4384
+ const appFilePath = path10.resolve(process.cwd(), appPath);
4385
+ if (!fs15.existsSync(appFilePath)) {
4184
4386
  throw new Error(`App file does not exist: ${appFilePath}`);
4185
4387
  }
4186
- const sourceCode = fs12.readFileSync(appFilePath, "utf-8");
4388
+ const sourceCode = fs15.readFileSync(appFilePath, "utf-8");
4187
4389
  const ast = (0, import_parser.parse)(sourceCode, {
4188
4390
  sourceType: "module",
4189
4391
  plugins: [
@@ -4243,16 +4445,21 @@ function parseRoutesFromFile(appPath, basePath, options = {}) {
4243
4445
  __name(parseRoutesFromFile, "parseRoutesFromFile");
4244
4446
  // Annotate the CommonJS export names for ESM import in node:
4245
4447
  0 && (module.exports = {
4448
+ HEALTH_ENDPOINT,
4246
4449
  buildFullPath,
4247
4450
  calculateFileHash,
4248
4451
  createCollectLogsMiddleware,
4249
4452
  createDevLogsMiddleware,
4453
+ createHealthHandler,
4454
+ createHealthProbe,
4250
4455
  createOpenapiMiddleware,
4251
4456
  evaluateTemplateLiteral,
4252
4457
  extractPageRouteInfo,
4458
+ getHealthPayload,
4253
4459
  getQuery,
4254
4460
  getQueryParam,
4255
4461
  handleDevProxyError,
4462
+ isPidAlive,
4256
4463
  isRouteComponent,
4257
4464
  normalizeBasePath,
4258
4465
  parseAndGenerateNestResourceTemplate,
@@ -4260,6 +4467,8 @@ __name(parseRoutesFromFile, "parseRoutesFromFile");
4260
4467
  parseRoutesFromFile,
4261
4468
  postprocessDrizzleSchema,
4262
4469
  registerMiddlewares,
4470
+ resolveHealth,
4471
+ resolveServerLiveness,
4263
4472
  routeParserLog,
4264
4473
  sendError,
4265
4474
  sendJson,