Просмотр исходного кода

refactor(server): 改进 TypeORM 实体和迁移加载方式

- 使用明确包路径替代 glob 通配符加载实体
- 迁移文件改为从 index.ts 导入有序数组,保证执行顺序
- 添加 migrations 目录到 tsconfig.json

Co-Authored-By: Claude <noreply@anthropic.com>
yourname 6 дней назад
Родитель
Сommit
d4da670482

+ 4 - 4
allin-packages/company-module/src/index.ts

@@ -1,4 +1,4 @@
-export * from './routes/index.js';
-export * from './services/index.js';
-export * from './schemas/index.js';
-export { Company, Company as CompanyEntity } from './entities/index.js';
+export * from './routes/index';
+export * from './services/index';
+export * from './schemas/index';
+export { Company, Company as CompanyEntity } from './entities/index';

+ 4 - 4
allin-packages/platform-module/src/index.ts

@@ -1,8 +1,8 @@
 // 导出实体
-export { Platform } from './entities/index.js';
+export { Platform } from './entities/index';
 
 // 导出服务
-export { PlatformService } from './services/index.js';
+export { PlatformService } from './services/index';
 
 // 导出Schema和类型
 export {
@@ -18,7 +18,7 @@ export {
   type DeletePlatformDto,
   type PaginationQuery,
   type SearchPlatformQuery
-} from './schemas/index.js';
+} from './schemas/index';
 
 // 导出路由
-export { platformRoutes, platformRoutesDefault, platformCustomRoutes, platformCrudRoutes } from './routes/index.js';
+export { platformRoutes, platformRoutesDefault, platformCustomRoutes, platformCrudRoutes } from './routes/index';

+ 10 - 3
packages/server/migrations/index.ts

@@ -3,7 +3,14 @@
  *
  * 集中导出所有迁移文件,便于统一管理
  *
- * 添加新迁移时,在此处添加对应的导出语句:
- * export { NewMigrationClassName } from './NewMigrationClassName';
+ * 添加新迁移时,在此处添加:
+ * 1. import 语句
+ * 2. export 语句(保持向后兼容)
+ * 3. migrations 数组中添加(按时间戳顺序)
  */
-export { MigrateNotWorkingToPreWorking1737260000000 } from './MigrateNotWorkingToPreWorking1737260000000';
+import { MigrateNotWorkingToPreWorking1737260000000 } from './MigrateNotWorkingToPreWorking1737260000000';
+
+// 迁移文件必须按时间戳顺序执行
+export const migrations: any[] = [
+  MigrateNotWorkingToPreWorking1737260000000,
+]

+ 4 - 4
packages/server/package.json

@@ -27,10 +27,10 @@
     "test:coverage": "vitest --coverage",
     "test:typecheck": "tsc --noEmit",
     "typeorm": "npx typeorm-ts-node-esm",
-    "migration:run": "npx typeorm-ts-node-esm migration:run -d src/data-source.ts",
-    "migration:generate": "npx typeorm-ts-node-esm migration:generate -d src/data-source.ts",
-    "migration:revert": "npx typeorm-ts-node-esm migration:revert -d src/data-source.ts",
-    "migration:show": "npx typeorm-ts-node-esm migration:show -d src/data-source.ts",
+    "migration:run": "npx typeorm-ts-node-esm migration:run -d src/data-source-cli.ts",
+    "migration:generate": "npx typeorm-ts-node-esm migration:generate -d src/data-source-cli.ts",
+    "migration:revert": "npx typeorm-ts-node-esm migration:revert -d src/data-source-cli.ts",
+    "migration:show": "npx typeorm-ts-node-esm migration:show -d src/data-source-cli.ts",
     "migration:create": "bash scripts/create-migration.sh"
   },
   "dependencies": {

+ 45 - 0
packages/server/src/data-source-cli.ts

@@ -0,0 +1,45 @@
+import "reflect-metadata"
+import { DataSource } from "typeorm"
+import process from 'node:process'
+
+/**
+ * TypeORM 迁移数据源配置
+ *
+ * 此文件专用于 TypeORM 迁移 CLI 命令:
+ * - pnpm migration:show
+ * - pnpm migration:run
+ * - pnpm migration:revert
+ *
+ * 注意:
+ * - 使用 glob 模式加载实体,避免循环依赖
+ * - 关闭自动同步(synchronize: false)
+ * - 迁移通过 glob 模式加载
+ */
+export const AppDataSource = new DataSource({
+  type: "postgres",
+  host: process.env.DB_HOST || "localhost",
+  port: parseInt(process.env.DB_PORT || "5432"),
+  username: process.env.DB_USERNAME || "postgres",
+  password: process.env.DB_PASSWORD || "",
+  database: process.env.DB_DATABASE || "postgres",
+  // 使用明确的包路径加载实体,避免循环依赖
+  entities: [
+    // allin-packages 中的模块
+    "../allin-packages/channel-module/src/entities/*.ts",
+    "../allin-packages/company-module/src/entities/*.ts",
+    "../allin-packages/disability-module/src/entities/*.ts",
+    "../allin-packages/order-module/src/entities/*.ts",
+    "../allin-packages/statistics-module/src/entities/*.ts",
+    "../allin-packages/platform-module/src/entities/*.ts",
+    "../allin-packages/salary-module/src/entities/*.ts",
+    // packages 中的模块
+    "../packages/core-module/src/entities/*.ts",
+    "../packages/geo-areas/src/entities/*.ts",
+    "../packages/bank-names-module/src/entities/*.ts",
+  ],
+  migrations: [
+    "./migrations/*[0-9].ts",  // 只匹配数字时间戳开头的迁移文件,排除 index.ts
+  ],
+  synchronize: false,  // 迁移时必须关闭自动同步
+  logging: process.env.DB_LOGGING === "true",
+})

+ 9 - 23
packages/server/src/data-source.ts

@@ -1,26 +1,12 @@
 import "reflect-metadata"
-import { DataSource } from "typeorm"
-import process from 'node:process'
 import * as entities from './entities'
+import { migrations } from '../migrations'
 
-/**
- * TypeORM 数据源配置
- *
- * 使用类导入方式加载实体,让 Vite SSR 正确处理 TypeScript 编译
- * 实体内部已使用字符串语法解决循环依赖问题
- */
-export const AppDataSource = new DataSource({
-  type: "postgres",
-  host: process.env.DB_HOST || "localhost",
-  port: parseInt(process.env.DB_PORT || "5432"),
-  username: process.env.DB_USERNAME || "postgres",
-  password: process.env.DB_PASSWORD || "",
-  database: process.env.DB_DATABASE || "postgres",
-  // 使用类导入方式,Vite SSR 会处理 TypeScript 编译
-  entities: Object.values(entities),
-  migrations: [
-    "./migrations/*[0-9].ts",  // 只匹配数字时间戳开头的迁移文件,排除 index.ts
-  ],
-  synchronize: false,  // 迁移时必须关闭自动同步
-  logging: process.env.DB_LOGGING === "true",
-})
+import { initializeDataSource } from '@d8d/shared-utils'
+
+import { AppDataSource } from '@d8d/shared-utils'
+
+initializeDataSource(Object.values(entities), migrations)
+export {
+  AppDataSource
+}

+ 9 - 10
packages/server/src/entities.ts

@@ -3,14 +3,13 @@
  *
  * 统一导出所有实体类,供 data-source.ts 使用
  * 只包含 packages/server 实际依赖的包中的实体
- * 使用 pnpm workspace 包名导入
- * 使用类导入而非 glob 模式,让 Vite SSR 正确处理 TypeScript 编译
+ * 使用 pnpm workspace 包名的子路径导入
  */
 
-// allin-packages 实体(使用 @d8d/allin-* 包名
-export { Platform } from '@d8d/allin-platform-module';
-export { Channel } from '@d8d/allin-channel-module';
-export { Company } from '@d8d/allin-company-module';
+// allin-packages 实体(使用 @d8d/allin-xxx/entities 子路径
+export { Platform } from '@d8d/allin-platform-module/entities';
+export { Channel } from '@d8d/allin-channel-module/entities';
+export { Company } from '@d8d/allin-company-module/entities';
 export {
   DisabledPerson,
   DisabledBankCard,
@@ -18,15 +17,15 @@ export {
   DisabledRemark,
   DisabledVisit,
   DisabledPersonGuardianPhone
-} from '@d8d/allin-disability-module';
+} from '@d8d/allin-disability-module/entities';
 export {
   OrderPerson,
   OrderPersonAsset,
   EmploymentOrder
-} from '@d8d/allin-order-module';
-export { SalaryLevel } from '@d8d/allin-salary-module';
+} from '@d8d/allin-order-module/entities';
+export { SalaryLevel } from '@d8d/allin-salary-module/entities';
 
-// packages 核心模块实体(使用 @d8d/core-module/xxx/entities)
+// packages 核心模块实体(使用 @d8d/core-module/xxx/entities 子路径
 export { UserEntity, Role } from '@d8d/core-module/user-module/entities';
 export { File } from '@d8d/core-module/file-module/entities';
 export { SystemConfig } from '@d8d/core-module/system-config-module/entities';

+ 2 - 1
packages/server/tsconfig.json

@@ -29,7 +29,8 @@
   },
   "include": [
     "src/**/*",
-    "tests/**/*"
+    "tests/**/*",
+    "migrations/**/*"
   ],
   "exclude": [
     "node_modules",