@lark-apaas/fullstack-nestjs-core 1.1.23-alpha.6 → 1.1.23-alpha.7

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
@@ -47,8 +47,8 @@ __export(index_exports, {
47
47
  module.exports = __toCommonJS(index_exports);
48
48
 
49
49
  // src/modules/platform/module.ts
50
- var import_common10 = require("@nestjs/common");
51
- var import_core2 = require("@nestjs/core");
50
+ var import_common11 = require("@nestjs/common");
51
+ var import_core3 = require("@nestjs/core");
52
52
  var import_nestjs_common5 = require("@lark-apaas/nestjs-common");
53
53
  var import_config2 = require("@nestjs/config");
54
54
  var import_nestjs_observable = require("@lark-apaas/nestjs-observable");
@@ -576,17 +576,7 @@ var FrameworkDebugMiddleware = class {
576
576
  constructor(httpAdapterHost) {
577
577
  this.httpAdapterHost = httpAdapterHost;
578
578
  }
579
- use(req, res) {
580
- const origin = req.headers.origin;
581
- if (origin) {
582
- res.setHeader("Access-Control-Allow-Origin", origin);
583
- res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
584
- res.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
585
- }
586
- if (req.method === "OPTIONS") {
587
- res.status(204).end();
588
- return;
589
- }
579
+ use(_req, res) {
590
580
  res.json(this.getDebugInfo());
591
581
  }
592
582
  getDebugInfo() {
@@ -1200,6 +1190,11 @@ FileService = _ts_decorate9([
1200
1190
 
1201
1191
  // src/modules/platform/module.ts
1202
1192
  var import_nestjs_authzpaas = require("@lark-apaas/nestjs-authzpaas");
1193
+
1194
+ // src/controllers/dev-api-routes.controller.ts
1195
+ var import_common10 = require("@nestjs/common");
1196
+ var import_core2 = require("@nestjs/core");
1197
+ var import_swagger = require("@nestjs/swagger");
1203
1198
  function _ts_decorate10(decorators, target, key, desc) {
1204
1199
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1205
1200
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1207,6 +1202,151 @@ function _ts_decorate10(decorators, target, key, desc) {
1207
1202
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1208
1203
  }
1209
1204
  __name(_ts_decorate10, "_ts_decorate");
1205
+ function _ts_metadata7(k, v) {
1206
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1207
+ }
1208
+ __name(_ts_metadata7, "_ts_metadata");
1209
+ var DevApiRoutesController = class {
1210
+ static {
1211
+ __name(this, "DevApiRoutesController");
1212
+ }
1213
+ httpAdapterHost;
1214
+ constructor(httpAdapterHost) {
1215
+ this.httpAdapterHost = httpAdapterHost;
1216
+ }
1217
+ /**
1218
+ * 获取 API 路由列表
1219
+ *
1220
+ * GET /dev/api-routes
1221
+ *
1222
+ * 返回预处理后的 API 路由数据,按模块分组
1223
+ */
1224
+ getApiRoutes() {
1225
+ const routes = this.extractRoutes();
1226
+ const groups = this.groupRoutesByModule(routes);
1227
+ return {
1228
+ groups,
1229
+ total: routes.length
1230
+ };
1231
+ }
1232
+ /**
1233
+ * 从 Express 路由栈中提取 API 路由
1234
+ */
1235
+ extractRoutes() {
1236
+ const server = this.httpAdapterHost.httpAdapter;
1237
+ const router = server.getInstance()._router;
1238
+ if (!router?.stack) {
1239
+ return [];
1240
+ }
1241
+ const routes = [];
1242
+ const seenRoutes = /* @__PURE__ */ new Set();
1243
+ router.stack.forEach((layer) => {
1244
+ if (layer.route) {
1245
+ const path = layer.route.path;
1246
+ if (!path.startsWith("/api/") || path.includes("__framework__") || path.includes("__innerapi__")) {
1247
+ return;
1248
+ }
1249
+ const methods = Object.keys(layer.route.methods).filter((m) => layer.route.methods[m]);
1250
+ methods.forEach((method) => {
1251
+ const upperMethod = method.toUpperCase();
1252
+ const routeKey = `${upperMethod}:${path}`;
1253
+ if (seenRoutes.has(routeKey)) {
1254
+ return;
1255
+ }
1256
+ seenRoutes.add(routeKey);
1257
+ const moduleId = this.extractModuleFromPath(path);
1258
+ const id = this.generateRouteId(upperMethod, path);
1259
+ routes.push({
1260
+ id,
1261
+ path,
1262
+ method: upperMethod,
1263
+ module: moduleId
1264
+ });
1265
+ });
1266
+ }
1267
+ });
1268
+ return routes;
1269
+ }
1270
+ /**
1271
+ * 从路径中提取模块名
1272
+ * /api/users/... -> users
1273
+ * /api/v1/orders/... -> orders
1274
+ */
1275
+ extractModuleFromPath(path) {
1276
+ const segments = path.split("/").filter(Boolean);
1277
+ let startIndex = 0;
1278
+ if (segments[0] === "api") {
1279
+ startIndex = 1;
1280
+ }
1281
+ if (segments[startIndex]?.match(/^v\d+$/)) {
1282
+ startIndex++;
1283
+ }
1284
+ const moduleName = segments[startIndex];
1285
+ if (!moduleName || moduleName.startsWith(":")) {
1286
+ return "default";
1287
+ }
1288
+ return moduleName;
1289
+ }
1290
+ /**
1291
+ * 生成路由唯一标识
1292
+ */
1293
+ generateRouteId(method, path) {
1294
+ const cleanPath = path.replace(/[/:]/g, "_").replace(/^_+|_+$/g, "");
1295
+ return `${method.toLowerCase()}_${cleanPath}`;
1296
+ }
1297
+ /**
1298
+ * 按模块分组路由
1299
+ */
1300
+ groupRoutesByModule(routes) {
1301
+ const groupMap = /* @__PURE__ */ new Map();
1302
+ routes.forEach((route) => {
1303
+ const existing = groupMap.get(route.module) || [];
1304
+ existing.push(route);
1305
+ groupMap.set(route.module, existing);
1306
+ });
1307
+ const groups = [];
1308
+ groupMap.forEach((apis, moduleName) => {
1309
+ groups.push({
1310
+ id: moduleName,
1311
+ name: this.formatModuleName(moduleName),
1312
+ apis: apis.sort((a, b) => a.path.localeCompare(b.path))
1313
+ });
1314
+ });
1315
+ return groups.sort((a, b) => a.name.localeCompare(b.name));
1316
+ }
1317
+ /**
1318
+ * 格式化模块名用于显示
1319
+ */
1320
+ formatModuleName(moduleName) {
1321
+ return moduleName.charAt(0).toUpperCase() + moduleName.slice(1);
1322
+ }
1323
+ };
1324
+ _ts_decorate10([
1325
+ (0, import_common10.Get)(),
1326
+ (0, import_common10.Header)("Access-Control-Allow-Origin", "*"),
1327
+ (0, import_common10.Header)("Access-Control-Allow-Methods", "GET, OPTIONS"),
1328
+ (0, import_common10.Header)("Access-Control-Allow-Headers", "Content-Type, Accept"),
1329
+ _ts_metadata7("design:type", Function),
1330
+ _ts_metadata7("design:paramtypes", []),
1331
+ _ts_metadata7("design:returntype", Object)
1332
+ ], DevApiRoutesController.prototype, "getApiRoutes", null);
1333
+ DevApiRoutesController = _ts_decorate10([
1334
+ (0, import_swagger.ApiExcludeController)(),
1335
+ (0, import_common10.Controller)("dev/api-routes"),
1336
+ _ts_metadata7("design:type", Function),
1337
+ _ts_metadata7("design:paramtypes", [
1338
+ typeof import_core2.HttpAdapterHost === "undefined" ? Object : import_core2.HttpAdapterHost
1339
+ ])
1340
+ ], DevApiRoutesController);
1341
+
1342
+ // src/modules/platform/module.ts
1343
+ function _ts_decorate11(decorators, target, key, desc) {
1344
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1345
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1346
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1347
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1348
+ }
1349
+ __name(_ts_decorate11, "_ts_decorate");
1210
1350
  var PLATFORM_MODULE_OPTIONS = /* @__PURE__ */ Symbol("PLATFORM_MODULE_OPTIONS");
1211
1351
  var PlatformModule = class _PlatformModule {
1212
1352
  static {
@@ -1217,6 +1357,9 @@ var PlatformModule = class _PlatformModule {
1217
1357
  _PlatformModule.moduleOptions = options;
1218
1358
  return {
1219
1359
  module: _PlatformModule,
1360
+ controllers: process.env.NODE_ENV === "development" ? [
1361
+ DevApiRoutesController
1362
+ ] : [],
1220
1363
  imports: [
1221
1364
  import_config2.ConfigModule.forRoot({
1222
1365
  isGlobal: true,
@@ -1280,8 +1423,8 @@ var PlatformModule = class _PlatformModule {
1280
1423
  useValue: options
1281
1424
  },
1282
1425
  {
1283
- provide: import_core2.APP_PIPE,
1284
- useValue: new import_common10.ValidationPipe({
1426
+ provide: import_core3.APP_PIPE,
1427
+ useValue: new import_common11.ValidationPipe({
1285
1428
  transform: true,
1286
1429
  transformOptions: {
1287
1430
  enableImplicitConversion: true
@@ -1302,7 +1445,7 @@ var PlatformModule = class _PlatformModule {
1302
1445
  },
1303
1446
  HttpInterceptorService,
1304
1447
  {
1305
- provide: import_core2.APP_INTERCEPTOR,
1448
+ provide: import_core3.APP_INTERCEPTOR,
1306
1449
  useClass: import_nestjs_observable.TraceInterceptor
1307
1450
  },
1308
1451
  FileService
@@ -1343,9 +1486,9 @@ var PlatformModule = class _PlatformModule {
1343
1486
  }
1344
1487
  }
1345
1488
  };
1346
- PlatformModule = _ts_decorate10([
1347
- (0, import_common10.Global)(),
1348
- (0, import_common10.Module)({})
1489
+ PlatformModule = _ts_decorate11([
1490
+ (0, import_common11.Global)(),
1491
+ (0, import_common11.Module)({})
1349
1492
  ], PlatformModule);
1350
1493
 
1351
1494
  // src/setup.ts
package/dist/index.d.cts CHANGED
@@ -169,4 +169,29 @@ declare class FileService {
169
169
  private _getFileMetadata;
170
170
  }
171
171
 
172
- export { type ApiNotFoundResponse, CsrfMiddleware, CsrfTokenMiddleware, FileService, type PlatformHttpClientOptions, PlatformModule, type PlatformModuleOptions, UserContextMiddleware, ViewContextMiddleware, configureApp };
172
+ /**
173
+ * API 路由信息(已处理)
174
+ */
175
+ interface ApiRouteInfo {
176
+ /** 唯一标识 */
177
+ id: string;
178
+ /** 路由路径 */
179
+ path: string;
180
+ /** HTTP 方法 */
181
+ method: string;
182
+ /** 所属模块(从路径提取) */
183
+ module: string;
184
+ }
185
+ /**
186
+ * API 路由分组
187
+ */
188
+ interface ApiRouteGroup {
189
+ /** 分组 ID */
190
+ id: string;
191
+ /** 分组名称 */
192
+ name: string;
193
+ /** 该分组下的 API 列表 */
194
+ apis: ApiRouteInfo[];
195
+ }
196
+
197
+ export { type ApiNotFoundResponse, type ApiRouteGroup, type ApiRouteInfo, CsrfMiddleware, CsrfTokenMiddleware, FileService, type PlatformHttpClientOptions, PlatformModule, type PlatformModuleOptions, UserContextMiddleware, ViewContextMiddleware, configureApp };
package/dist/index.d.ts CHANGED
@@ -169,4 +169,29 @@ declare class FileService {
169
169
  private _getFileMetadata;
170
170
  }
171
171
 
172
- export { type ApiNotFoundResponse, CsrfMiddleware, CsrfTokenMiddleware, FileService, type PlatformHttpClientOptions, PlatformModule, type PlatformModuleOptions, UserContextMiddleware, ViewContextMiddleware, configureApp };
172
+ /**
173
+ * API 路由信息(已处理)
174
+ */
175
+ interface ApiRouteInfo {
176
+ /** 唯一标识 */
177
+ id: string;
178
+ /** 路由路径 */
179
+ path: string;
180
+ /** HTTP 方法 */
181
+ method: string;
182
+ /** 所属模块(从路径提取) */
183
+ module: string;
184
+ }
185
+ /**
186
+ * API 路由分组
187
+ */
188
+ interface ApiRouteGroup {
189
+ /** 分组 ID */
190
+ id: string;
191
+ /** 分组名称 */
192
+ name: string;
193
+ /** 该分组下的 API 列表 */
194
+ apis: ApiRouteInfo[];
195
+ }
196
+
197
+ export { type ApiNotFoundResponse, type ApiRouteGroup, type ApiRouteInfo, CsrfMiddleware, CsrfTokenMiddleware, FileService, type PlatformHttpClientOptions, PlatformModule, type PlatformModuleOptions, UserContextMiddleware, ViewContextMiddleware, configureApp };
package/dist/index.js CHANGED
@@ -531,17 +531,7 @@ var FrameworkDebugMiddleware = class {
531
531
  constructor(httpAdapterHost) {
532
532
  this.httpAdapterHost = httpAdapterHost;
533
533
  }
534
- use(req, res) {
535
- const origin = req.headers.origin;
536
- if (origin) {
537
- res.setHeader("Access-Control-Allow-Origin", origin);
538
- res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
539
- res.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
540
- }
541
- if (req.method === "OPTIONS") {
542
- res.status(204).end();
543
- return;
544
- }
534
+ use(_req, res) {
545
535
  res.json(this.getDebugInfo());
546
536
  }
547
537
  getDebugInfo() {
@@ -1155,6 +1145,11 @@ FileService = _ts_decorate9([
1155
1145
 
1156
1146
  // src/modules/platform/module.ts
1157
1147
  import { AuthZPaasModule } from "@lark-apaas/nestjs-authzpaas";
1148
+
1149
+ // src/controllers/dev-api-routes.controller.ts
1150
+ import { Controller, Get, Header } from "@nestjs/common";
1151
+ import { HttpAdapterHost as HttpAdapterHost2 } from "@nestjs/core";
1152
+ import { ApiExcludeController } from "@nestjs/swagger";
1158
1153
  function _ts_decorate10(decorators, target, key, desc) {
1159
1154
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1160
1155
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1162,6 +1157,151 @@ function _ts_decorate10(decorators, target, key, desc) {
1162
1157
  return c > 3 && r && Object.defineProperty(target, key, r), r;
1163
1158
  }
1164
1159
  __name(_ts_decorate10, "_ts_decorate");
1160
+ function _ts_metadata7(k, v) {
1161
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1162
+ }
1163
+ __name(_ts_metadata7, "_ts_metadata");
1164
+ var DevApiRoutesController = class {
1165
+ static {
1166
+ __name(this, "DevApiRoutesController");
1167
+ }
1168
+ httpAdapterHost;
1169
+ constructor(httpAdapterHost) {
1170
+ this.httpAdapterHost = httpAdapterHost;
1171
+ }
1172
+ /**
1173
+ * 获取 API 路由列表
1174
+ *
1175
+ * GET /dev/api-routes
1176
+ *
1177
+ * 返回预处理后的 API 路由数据,按模块分组
1178
+ */
1179
+ getApiRoutes() {
1180
+ const routes = this.extractRoutes();
1181
+ const groups = this.groupRoutesByModule(routes);
1182
+ return {
1183
+ groups,
1184
+ total: routes.length
1185
+ };
1186
+ }
1187
+ /**
1188
+ * 从 Express 路由栈中提取 API 路由
1189
+ */
1190
+ extractRoutes() {
1191
+ const server = this.httpAdapterHost.httpAdapter;
1192
+ const router = server.getInstance()._router;
1193
+ if (!router?.stack) {
1194
+ return [];
1195
+ }
1196
+ const routes = [];
1197
+ const seenRoutes = /* @__PURE__ */ new Set();
1198
+ router.stack.forEach((layer) => {
1199
+ if (layer.route) {
1200
+ const path = layer.route.path;
1201
+ if (!path.startsWith("/api/") || path.includes("__framework__") || path.includes("__innerapi__")) {
1202
+ return;
1203
+ }
1204
+ const methods = Object.keys(layer.route.methods).filter((m) => layer.route.methods[m]);
1205
+ methods.forEach((method) => {
1206
+ const upperMethod = method.toUpperCase();
1207
+ const routeKey = `${upperMethod}:${path}`;
1208
+ if (seenRoutes.has(routeKey)) {
1209
+ return;
1210
+ }
1211
+ seenRoutes.add(routeKey);
1212
+ const moduleId = this.extractModuleFromPath(path);
1213
+ const id = this.generateRouteId(upperMethod, path);
1214
+ routes.push({
1215
+ id,
1216
+ path,
1217
+ method: upperMethod,
1218
+ module: moduleId
1219
+ });
1220
+ });
1221
+ }
1222
+ });
1223
+ return routes;
1224
+ }
1225
+ /**
1226
+ * 从路径中提取模块名
1227
+ * /api/users/... -> users
1228
+ * /api/v1/orders/... -> orders
1229
+ */
1230
+ extractModuleFromPath(path) {
1231
+ const segments = path.split("/").filter(Boolean);
1232
+ let startIndex = 0;
1233
+ if (segments[0] === "api") {
1234
+ startIndex = 1;
1235
+ }
1236
+ if (segments[startIndex]?.match(/^v\d+$/)) {
1237
+ startIndex++;
1238
+ }
1239
+ const moduleName = segments[startIndex];
1240
+ if (!moduleName || moduleName.startsWith(":")) {
1241
+ return "default";
1242
+ }
1243
+ return moduleName;
1244
+ }
1245
+ /**
1246
+ * 生成路由唯一标识
1247
+ */
1248
+ generateRouteId(method, path) {
1249
+ const cleanPath = path.replace(/[/:]/g, "_").replace(/^_+|_+$/g, "");
1250
+ return `${method.toLowerCase()}_${cleanPath}`;
1251
+ }
1252
+ /**
1253
+ * 按模块分组路由
1254
+ */
1255
+ groupRoutesByModule(routes) {
1256
+ const groupMap = /* @__PURE__ */ new Map();
1257
+ routes.forEach((route) => {
1258
+ const existing = groupMap.get(route.module) || [];
1259
+ existing.push(route);
1260
+ groupMap.set(route.module, existing);
1261
+ });
1262
+ const groups = [];
1263
+ groupMap.forEach((apis, moduleName) => {
1264
+ groups.push({
1265
+ id: moduleName,
1266
+ name: this.formatModuleName(moduleName),
1267
+ apis: apis.sort((a, b) => a.path.localeCompare(b.path))
1268
+ });
1269
+ });
1270
+ return groups.sort((a, b) => a.name.localeCompare(b.name));
1271
+ }
1272
+ /**
1273
+ * 格式化模块名用于显示
1274
+ */
1275
+ formatModuleName(moduleName) {
1276
+ return moduleName.charAt(0).toUpperCase() + moduleName.slice(1);
1277
+ }
1278
+ };
1279
+ _ts_decorate10([
1280
+ Get(),
1281
+ Header("Access-Control-Allow-Origin", "*"),
1282
+ Header("Access-Control-Allow-Methods", "GET, OPTIONS"),
1283
+ Header("Access-Control-Allow-Headers", "Content-Type, Accept"),
1284
+ _ts_metadata7("design:type", Function),
1285
+ _ts_metadata7("design:paramtypes", []),
1286
+ _ts_metadata7("design:returntype", Object)
1287
+ ], DevApiRoutesController.prototype, "getApiRoutes", null);
1288
+ DevApiRoutesController = _ts_decorate10([
1289
+ ApiExcludeController(),
1290
+ Controller("dev/api-routes"),
1291
+ _ts_metadata7("design:type", Function),
1292
+ _ts_metadata7("design:paramtypes", [
1293
+ typeof HttpAdapterHost2 === "undefined" ? Object : HttpAdapterHost2
1294
+ ])
1295
+ ], DevApiRoutesController);
1296
+
1297
+ // src/modules/platform/module.ts
1298
+ function _ts_decorate11(decorators, target, key, desc) {
1299
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1300
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1301
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1302
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1303
+ }
1304
+ __name(_ts_decorate11, "_ts_decorate");
1165
1305
  var PLATFORM_MODULE_OPTIONS = /* @__PURE__ */ Symbol("PLATFORM_MODULE_OPTIONS");
1166
1306
  var PlatformModule = class _PlatformModule {
1167
1307
  static {
@@ -1172,6 +1312,9 @@ var PlatformModule = class _PlatformModule {
1172
1312
  _PlatformModule.moduleOptions = options;
1173
1313
  return {
1174
1314
  module: _PlatformModule,
1315
+ controllers: process.env.NODE_ENV === "development" ? [
1316
+ DevApiRoutesController
1317
+ ] : [],
1175
1318
  imports: [
1176
1319
  ConfigModule.forRoot({
1177
1320
  isGlobal: true,
@@ -1298,7 +1441,7 @@ var PlatformModule = class _PlatformModule {
1298
1441
  }
1299
1442
  }
1300
1443
  };
1301
- PlatformModule = _ts_decorate10([
1444
+ PlatformModule = _ts_decorate11([
1302
1445
  Global(),
1303
1446
  Module({})
1304
1447
  ], PlatformModule);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/fullstack-nestjs-core",
3
- "version": "1.1.23-alpha.6",
3
+ "version": "1.1.23-alpha.7",
4
4
  "description": "FullStack Nestjs Core",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -46,7 +46,7 @@
46
46
  "@lark-apaas/nestjs-capability": "^0.1.3",
47
47
  "@lark-apaas/nestjs-common": "^0.1.3",
48
48
  "@lark-apaas/nestjs-datapaas": "^1.0.9",
49
- "@lark-apaas/nestjs-logger": "1.0.10-alpha.5",
49
+ "@lark-apaas/nestjs-logger": "1.0.10-alpha.6",
50
50
  "@lark-apaas/nestjs-observable": "^0.0.4",
51
51
  "@lark-apaas/nestjs-openapi-devtools": "^1.0.9",
52
52
  "@lark-apaas/nestjs-trigger": "^0.0.2",