@lark-apaas/devtool-kits 1.2.17-alpha.8 → 1.2.17

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 CHANGED
@@ -92,6 +92,17 @@ import {
92
92
  } from '@apaas/fullstack-toolkits';
93
93
  ```
94
94
 
95
+ ### 兼容工具函数 (Compat)
96
+ ```typescript
97
+ import {
98
+ sendJson, // 发送 JSON 响应(兼容 Express/Connect)
99
+ sendError, // 发送错误响应
100
+ sendSuccess, // 发送成功响应
101
+ getQuery, // 获取所有查询参数
102
+ getQueryParam, // 获取单个查询参数
103
+ } from '@apaas/fullstack-toolkits';
104
+ ```
105
+
95
106
  ### 类型定义 (Types)
96
107
  ```typescript
97
108
  import type {
@@ -171,6 +182,38 @@ export default {
171
182
  - 全局中间件应放在路由中间件之前
172
183
  - 路由中间件仅处理匹配其挂载路径的请求
173
184
 
185
+ ### Vite/Connect 兼容性
186
+
187
+ 本工具包原生支持 Vite 开发服务器。`registerMiddlewares` 会自动检测 Vite/Connect 环境,并添加必要的 Express API 兼容层:
188
+
189
+ - `res.status()` - 设置响应状态码
190
+ - `res.json()` - 发送 JSON 响应
191
+ - `res.send()` - 发送响应
192
+ - `req.query` - 解析后的查询参数
193
+
194
+ 这意味着您可以直接在 Vite 中使用本工具包,无需额外配置。
195
+
196
+ **兼容工具函数(可选):**
197
+
198
+ 如果您正在编写自定义中间件并希望同时支持 Express 和 Vite,可以使用导出的兼容工具函数:
199
+
200
+ ```typescript
201
+ import { sendJson, sendError, sendSuccess, getQuery, getQueryParam } from '@lark-apaas/devtool-kits';
202
+
203
+ // 发送 JSON 响应(自动检测 Express/Connect)
204
+ sendJson(res, { data: 'value' }, 200);
205
+
206
+ // 发送错误响应
207
+ sendError(res, 'Not found', error, 404);
208
+
209
+ // 发送成功响应
210
+ sendSuccess(res, { id: 123 });
211
+
212
+ // 获取查询参数(自动解析 URL 或使用 req.query)
213
+ const query = getQuery(req);
214
+ const page = getQueryParam(req, 'page');
215
+ ```
216
+
174
217
  ## 中间件详细说明
175
218
  ### Dev Logs 中间件
176
219
 
package/dist/index.cjs CHANGED
@@ -31,15 +31,19 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.ts
32
32
  var index_exports = {};
33
33
  __export(index_exports, {
34
- createApiRoutesMiddleware: () => createApiRoutesMiddleware,
35
34
  createCollectLogsMiddleware: () => createCollectLogsMiddleware,
36
35
  createDevLogsMiddleware: () => createDevLogsMiddleware,
37
36
  createOpenapiMiddleware: () => createOpenapiMiddleware,
37
+ getQuery: () => getQuery,
38
+ getQueryParam: () => getQueryParam,
38
39
  handleDevProxyError: () => handleDevProxyError,
39
40
  normalizeBasePath: () => normalizeBasePath,
40
41
  parseAndGenerateNestResourceTemplate: () => parseAndGenerateNestResourceTemplate,
41
42
  postprocessDrizzleSchema: () => postprocessDrizzleSchema,
42
- registerMiddlewares: () => registerMiddlewares
43
+ registerMiddlewares: () => registerMiddlewares,
44
+ sendError: () => sendError,
45
+ sendJson: () => sendJson,
46
+ sendSuccess: () => sendSuccess
43
47
  });
44
48
  module.exports = __toCommonJS(index_exports);
45
49
 
@@ -1936,10 +1940,8 @@ function parsePinoLog(line, source) {
1936
1940
  statusCode: pinoLog.status_code,
1937
1941
  durationMs: pinoLog.duration_ms,
1938
1942
  ip: pinoLog.ip,
1939
- referer: pinoLog.referer,
1940
1943
  requestBody: pinoLog.request_body,
1941
- responseBody: pinoLog.response_body,
1942
- queryParams: pinoLog.query_params
1944
+ responseBody: pinoLog.response_body
1943
1945
  },
1944
1946
  tags: [
1945
1947
  source
@@ -2844,8 +2846,7 @@ function parsePinoLog2(line, source) {
2844
2846
  durationMs: pinoLog.duration_ms,
2845
2847
  ip: pinoLog.ip,
2846
2848
  requestBody: pinoLog.request_body,
2847
- responseBody: pinoLog.response_body,
2848
- queryParams: pinoLog.query_params
2849
+ responseBody: pinoLog.response_body
2849
2850
  },
2850
2851
  tags: [
2851
2852
  source
@@ -3494,151 +3495,100 @@ function createCollectLogsMiddleware(options = {}) {
3494
3495
  }
3495
3496
  __name(createCollectLogsMiddleware, "createCollectLogsMiddleware");
3496
3497
 
3497
- // src/middlewares/api-routes/router.ts
3498
- var import_express4 = __toESM(require("express"), 1);
3499
- function extractModuleFromPath(path7) {
3500
- const segments = path7.split("/").filter(Boolean);
3501
- let startIndex = 0;
3502
- if (segments[0] === "api") {
3503
- startIndex = 1;
3504
- }
3505
- if (segments[startIndex]?.match(/^v\d+$/)) {
3506
- startIndex++;
3507
- }
3508
- const moduleName = segments[startIndex];
3509
- if (!moduleName || moduleName.startsWith(":")) {
3510
- return "default";
3511
- }
3512
- return moduleName;
3513
- }
3514
- __name(extractModuleFromPath, "extractModuleFromPath");
3515
- function generateRouteId(method, path7) {
3516
- const cleanPath = path7.replace(/[/:]/g, "_").replace(/^_+|_+$/g, "");
3517
- return `${method.toLowerCase()}_${cleanPath}`;
3518
- }
3519
- __name(generateRouteId, "generateRouteId");
3520
- function capitalize(str) {
3521
- return str.charAt(0).toUpperCase() + str.slice(1);
3522
- }
3523
- __name(capitalize, "capitalize");
3524
- function extractRoutes(app) {
3525
- const router = app._router;
3526
- if (!router?.stack) {
3527
- return [];
3498
+ // src/middlewares/compat.ts
3499
+ function sendJson(res, data, statusCode = 200) {
3500
+ const statusFn = res.status;
3501
+ const jsonFn = res.json;
3502
+ if (typeof statusFn === "function" && typeof jsonFn === "function") {
3503
+ statusFn.call(res, statusCode);
3504
+ jsonFn.call(res, data);
3505
+ } else {
3506
+ res.statusCode = statusCode;
3507
+ res.setHeader("Content-Type", "application/json");
3508
+ res.end(JSON.stringify(data));
3528
3509
  }
3529
- const routes = [];
3530
- const seenRoutes = /* @__PURE__ */ new Set();
3531
- const processLayer = /* @__PURE__ */ __name((layer, basePath = "") => {
3532
- if (layer.route) {
3533
- const path7 = basePath + layer.route.path;
3534
- if (!path7.includes("/api/") || path7.includes("__framework__") || path7.includes("__innerapi__")) {
3535
- return;
3536
- }
3537
- const methods = Object.keys(layer.route.methods).filter((m) => layer.route.methods[m]);
3538
- methods.forEach((method) => {
3539
- const upperMethod = method.toUpperCase();
3540
- const routeKey = `${upperMethod}:${path7}`;
3541
- if (seenRoutes.has(routeKey)) {
3542
- return;
3543
- }
3544
- seenRoutes.add(routeKey);
3545
- const apiPathMatch = path7.match(/\/api\/.*/);
3546
- const apiPath = apiPathMatch ? apiPathMatch[0] : path7;
3547
- routes.push({
3548
- id: generateRouteId(upperMethod, apiPath),
3549
- path: apiPath,
3550
- method: upperMethod,
3551
- module: extractModuleFromPath(apiPath)
3552
- });
3553
- });
3554
- }
3555
- if (layer.name === "router" && layer.handle?.stack) {
3556
- let prefix = basePath;
3557
- if (layer.regexp) {
3558
- const pattern = new RegExp("^\\^\\\\?(.*?)(?:\\\\/\\?|$)");
3559
- const match = layer.regexp.source.match(pattern);
3560
- if (match) {
3561
- prefix = basePath + match[1].replace(/\\\//g, "/");
3562
- }
3563
- }
3564
- layer.handle.stack.forEach((subLayer) => processLayer(subLayer, prefix));
3565
- }
3566
- }, "processLayer");
3567
- router.stack.forEach((layer) => processLayer(layer));
3568
- return routes;
3569
- }
3570
- __name(extractRoutes, "extractRoutes");
3571
- function groupRoutesByModule(routes) {
3572
- const groupMap = /* @__PURE__ */ new Map();
3573
- routes.forEach((route) => {
3574
- const existing = groupMap.get(route.module) || [];
3575
- existing.push(route);
3576
- groupMap.set(route.module, existing);
3577
- });
3578
- const groups = [];
3579
- groupMap.forEach((apis, moduleName) => {
3580
- groups.push({
3581
- id: moduleName,
3582
- name: capitalize(moduleName),
3583
- apis: apis.sort((a, b) => a.path.localeCompare(b.path))
3584
- });
3585
- });
3586
- return groups.sort((a, b) => a.name.localeCompare(b.name));
3587
- }
3588
- __name(groupRoutesByModule, "groupRoutesByModule");
3589
- function createApiRoutesRouter() {
3590
- const router = import_express4.default.Router();
3591
- router.use((_req, res, next) => {
3592
- res.header("Access-Control-Allow-Origin", "*");
3593
- res.header("Access-Control-Allow-Methods", "GET, OPTIONS");
3594
- res.header("Access-Control-Allow-Headers", "Content-Type, Accept");
3595
- next();
3596
- });
3597
- router.options("/", (_req, res) => {
3598
- res.status(204).end();
3599
- });
3600
- router.get("/", (req, res) => {
3601
- try {
3602
- const routes = extractRoutes(req.app);
3603
- const groups = groupRoutesByModule(routes);
3604
- res.json({
3605
- groups,
3606
- total: routes.length
3607
- });
3608
- } catch (error) {
3609
- console.error("[api-routes] Failed to extract routes:", error);
3610
- res.status(500).json({
3611
- error: "Failed to extract routes",
3612
- message: error instanceof Error ? error.message : "Unknown error"
3613
- });
3614
- }
3615
- });
3616
- return router;
3617
3510
  }
3618
- __name(createApiRoutesRouter, "createApiRoutesRouter");
3619
-
3620
- // src/middlewares/api-routes/index.ts
3621
- var API_ROUTES_ROUTES = [
3622
- {
3623
- method: "GET",
3624
- path: "/",
3625
- description: "Get all API routes grouped by module"
3511
+ __name(sendJson, "sendJson");
3512
+ function sendError(res, message, error, statusCode = 500) {
3513
+ const errorData = {
3514
+ message,
3515
+ ...error ? {
3516
+ error: serializeError3(error)
3517
+ } : {}
3518
+ };
3519
+ sendJson(res, errorData, statusCode);
3520
+ }
3521
+ __name(sendError, "sendError");
3522
+ function sendSuccess(res, data) {
3523
+ sendJson(res, {
3524
+ success: true,
3525
+ ...data
3526
+ }, 200);
3527
+ }
3528
+ __name(sendSuccess, "sendSuccess");
3529
+ function getQuery(req) {
3530
+ if (req.query) {
3531
+ return req.query;
3532
+ }
3533
+ const url = new URL(req.url || "", `http://${req.headers.host}`);
3534
+ return Object.fromEntries(url.searchParams.entries());
3535
+ }
3536
+ __name(getQuery, "getQuery");
3537
+ function getQueryParam(req, key) {
3538
+ const query = getQuery(req);
3539
+ return query[key];
3540
+ }
3541
+ __name(getQueryParam, "getQueryParam");
3542
+ function serializeError3(error) {
3543
+ if (error instanceof Error) {
3544
+ return {
3545
+ name: error.name,
3546
+ message: error.message,
3547
+ stack: error.stack
3548
+ };
3626
3549
  }
3627
- ];
3628
- function createApiRoutesMiddleware() {
3629
3550
  return {
3630
- name: "api-routes",
3631
- mountPath: "/dev/api-routes",
3632
- routes: API_ROUTES_ROUTES,
3633
- enabled: /* @__PURE__ */ __name((context) => context.isDev, "enabled"),
3634
- createRouter: /* @__PURE__ */ __name((_context) => {
3635
- return createApiRoutesRouter();
3636
- }, "createRouter")
3551
+ message: String(error)
3637
3552
  };
3638
3553
  }
3639
- __name(createApiRoutesMiddleware, "createApiRoutesMiddleware");
3554
+ __name(serializeError3, "serializeError");
3640
3555
 
3641
3556
  // src/middlewares/index.ts
3557
+ function enhanceForCompat(req, res) {
3558
+ if (!res.status) {
3559
+ res.status = function(code) {
3560
+ res.statusCode = code;
3561
+ return res;
3562
+ };
3563
+ }
3564
+ if (!res.json) {
3565
+ res.json = function(data) {
3566
+ res.setHeader("Content-Type", "application/json");
3567
+ res.end(JSON.stringify(data));
3568
+ return res;
3569
+ };
3570
+ }
3571
+ if (!res.send) {
3572
+ res.send = function(data) {
3573
+ if (typeof data === "object" && data !== null) {
3574
+ res.setHeader("Content-Type", "application/json");
3575
+ res.end(JSON.stringify(data));
3576
+ } else {
3577
+ res.end(String(data));
3578
+ }
3579
+ return res;
3580
+ };
3581
+ }
3582
+ if (!req.query) {
3583
+ const url = new URL(req.url || "", `http://${req.headers.host || "localhost"}`);
3584
+ req.query = Object.fromEntries(url.searchParams.entries());
3585
+ }
3586
+ }
3587
+ __name(enhanceForCompat, "enhanceForCompat");
3588
+ function isConnectServer(server) {
3589
+ return typeof server === "function" && !("set" in server) && !("engine" in server);
3590
+ }
3591
+ __name(isConnectServer, "isConnectServer");
3642
3592
  function isRouteMiddleware(middleware) {
3643
3593
  return "createRouter" in middleware && middleware.createRouter !== void 0;
3644
3594
  }
@@ -3691,6 +3641,13 @@ async function registerMiddlewares(server, middlewares, options) {
3691
3641
  rootDir: process.cwd(),
3692
3642
  ...options
3693
3643
  };
3644
+ if (isConnectServer(server)) {
3645
+ server.use((req, res, next) => {
3646
+ enhanceForCompat(req, res);
3647
+ next();
3648
+ });
3649
+ console.log("[Middleware] Registered Express compatibility layer for Connect/Vite");
3650
+ }
3694
3651
  const allMiddlewares = [
3695
3652
  ...middlewares
3696
3653
  ];
@@ -3719,14 +3676,18 @@ async function registerMiddlewares(server, middlewares, options) {
3719
3676
  __name(registerMiddlewares, "registerMiddlewares");
3720
3677
  // Annotate the CommonJS export names for ESM import in node:
3721
3678
  0 && (module.exports = {
3722
- createApiRoutesMiddleware,
3723
3679
  createCollectLogsMiddleware,
3724
3680
  createDevLogsMiddleware,
3725
3681
  createOpenapiMiddleware,
3682
+ getQuery,
3683
+ getQueryParam,
3726
3684
  handleDevProxyError,
3727
3685
  normalizeBasePath,
3728
3686
  parseAndGenerateNestResourceTemplate,
3729
3687
  postprocessDrizzleSchema,
3730
- registerMiddlewares
3688
+ registerMiddlewares,
3689
+ sendError,
3690
+ sendJson,
3691
+ sendSuccess
3731
3692
  });
3732
3693
  //# sourceMappingURL=index.cjs.map