完整指南:glob 模式、调试与 barrel 导出)
后端【免费下载链接】mikro-ormTypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, MariaDB, MS SQL Server, PostgreSQL and SQLite/libSQL databases.项目地址https://gitcode.com/gh_mirrors/mi/mikro-orm点击查看免费下载导读MikroORM 7 允许开发者不必在配置中逐个罗列实体类而是通过 glob 模式让 ORM 自动扫描、动态导入并识别符合命名约定的实体文件。本指南以 docs/versioned_docs/version-7.2/folder-based-discovery.md 为核心骨架结合核心包源码与 CLI 实现系统讲解entities/entitiesTs配置、文件命名约定、glob 模式进阶用法、mikro-orm debug与mikro-orm discovery:export两个 CLI 命令以及显式引用与文件夹发现的取舍。读完本文你将能在大中型项目中正确配置自动发现、排查路径解析问题并借助 barrel 文件同时获得文件夹发现的便利性与显式引用的类型安全。为什么需要文件夹发现从显式列表到 glob 模式默认情况下MikroORM 的entities配置项接收一组实体类引用export default defineConfig({ entities: [User, Article, Tag, BaseEntity], });这种显式写法直观、类型安全但每当新增实体时都必须手动更新配置实体数量一多配置会变得冗长且容易遗漏。文件夹发现Folder-based Discovery正是为解决这一问题而设计用 glob 模式描述实体文件长什么样让 ORM 在启动时根据文件命名约定自动找出所有实体。其配置入口非常简单见 Configuration.ts 中对entities、entitiesTs两个配置项的源码注释import { defineConfig } from mikro-orm/sqlite; export default defineConfig({ // Glob patterns for compiled JavaScript files entities: [dist/**/*.entity.js], // Glob patterns for TypeScript source files (used in development) entitiesTs: [src/**/*.entity.ts], // ... });其中entities指向编译后的 JavaScript 实体文件用于生产运行entitiesTs指向TypeScript 源码实体文件用于开发期通过tsx、swc等工具直接运行 TS 的场合。工作原理preferTs判定与动态导入从源码看整个文件夹发现的流程可以拆成三步判定当前运行环境MikroORM.init()会计算preferTs值——orm.config.get(preferTs, Utils.detectTypeScriptSupport())见 MikroORM.ts。detectTypeScriptSupport()见 Utils.ts会检查多种信号ts-node、环境变量MIKRO_ORM_CLI_ALWAYS_ALLOW_TS、TS_JEST、VITEST、Bun、命令行参数中的.ts文件以及tsx、swc-node/register、oxc-node/core等加载器选择目标模式集合findEntities(preferTs)中执行const targets preferTs entitiesTs.length 0 ? entitiesTs : entities;见 MetadataDiscovery.ts——即运行在 TS 环境时优先用entitiesTs否则回退到entities动态导入并扫描当targets中存在字符串路径时调用mikro-orm/core/file-discovery模块的discoverEntities(paths, { baseDir })执行 glob 展开、逐文件动态导入并收集其中的实体类与EntitySchema。discoverEntities的实现在 discover-entities.ts几个值得注意的细节跳过.d.ts声明文件只处理.ts/.js/.mts/.mjs/.cts/.cjs等实际实现文件一个文件里既导出EntitySchema又导出其关联类实现时只保留 schema避免重复注册见getEntityClassOrSchemadiscover-entities.ts对装饰器实体通过MetadataStorage.isKnownEntity(item.name)判断是否为已知实体对defineEntity/EntitySchema实体则通过EntitySchema.REGISTRY查找已注册 schema所有文件以fs.dynamicImport方式异步导入这与下方同步初始化限制直接相关。重要约定entities必须指向编译后的 JS 文件entitiesTs必须指向 TS 源文件两者不可混用。若在运行编译产物时误把entities指向 TS 源码或反之都会导致实体加载失败或类型信息丢失。文件命名约定.entity.ts后缀文件夹发现依赖命名约定最常见的约定是.entity.ts后缀。典型项目结构如下src/ ├── modules/ │ ├── user/ │ │ └── user.entity.ts │ ├── article/ │ │ ├── article.entity.ts │ │ └── tag.entity.ts │ └── common/ │ └── base.entity.ts └── mikro-orm.config.ts配套配置为export default defineConfig({ entities: [dist/**/*.entity.js], entitiesTs: [src/**/*.entity.ts], });只要新实体文件按xxx.entity.ts命名并放入src目录就会自动被src/**/*.entity.ts匹配无需再改配置。官方测试 tests/MikroORM.test.ts 验证了基于complex-entities/**/*.entity.ts的 glob 能同时发现普通装饰器实体与defineEntity类实体。Glob 模式进阶多模式、负模式与 brace expansion 限制路径解析使用 Node.js 原生 glob 实现因此支持标准 glob 语法const orm await MikroORM.init({ // 递归匹配 dist 目录下所有 .entity.js 文件 entities: [./dist/**/*.entity.js], // 多个模式数组元素可叠加 entities: [./dist/modules/**/*.entity.js, ./dist/shared/**/*.entity.js], // 负模式negation排除特定文件 entities: [./dist/**/*.entity.js, !./dist/**/*.test.entity.js], });要点说明**递归匹配任意层级目录*匹配单层路径片段负模式以!开头可用于排除测试实体、临时文件等模式既可以写相对路径相对baseDir默认process.cwd()见 Configuration.ts也可以写绝对路径。:::note brace expansion 限制 Node.js 原生 glob不支持brace expansion 语法例如src/{entities,modules}/*.ts这类模式无法直接用于entities/entitiesTs。如果确实需要可以借助tinyglobby在配置加载阶段先展开成具体路径列表import { glob } from tinyglobby; export default defineConfig({ entities: await glob([src/{entities,modules}/*.ts]), });注意defineConfig接收的配置对象在顶层可以使用顶层 await在 ESM 配置文件中展开后的路径数组会作为普通字符串数组传入。 :::调试发现mikro-orm debug当文件夹发现表现不符合预期实体缺失、路径错误等时第一个排查手段是 CLI 的debug命令npx mikro-orm debug从 DebugCommand.ts 的实现看它会输出当前加载的 CLI 配置搜索过的配置文件路径、搜索的配置名contextName、TypeScript 支持状态与加载器driver 依赖及其版本如- postgresql 0.0.0之类的驱动包版本列表数据库连接结果成功或失败preferTs判定若显式设置了preferTs会打印提示will useentitiesTsarray或will useentitiesarray并提醒编译产物运行时应设为false实体路径解析结果分别统计entities与entitiesTs数组中的引用数实体类与路径数glob/文件夹并逐个检查路径是否存在标注(found)或(not found)。官方测试 tests/features/cli/DebugCommand.test.ts 展示了完整输出格式可用于对照你的实际输出。例如当配置entities: [./dist/entities-1, ./dist/entities-2]时输出中会明确显示每个路径是否存在——这能帮你快速定位glob 写对了但目录名/层级不对这类问题。显式引用 vs 文件夹发现如何选择原文档给出了一张完整的对比表这里原样保留并补充实践建议AspectExplicit (entities: [User])Folder-based (entities: [**/*.entity.js])Setup complexityMore codeLess codeRefactoringIDE-supportedManual pattern updatesBuild toolsWorks everywhereMay need configurationPerformanceFaster startupSlightly slower (file scanning)Error detectionCompile-timeRuntime何时使用显式引用中小型项目实体数量有限使用 webpack、esbuild 等打包器打包器无法处理运行时动态导入的 glob 路径需要最大化 IDE 支持与类型安全重命名实体时 IDE 可以同步更新引用使用defineEntity官方推荐的方式时显式引用是最稳妥的搭配。何时使用文件夹发现大型项目实体数量多且持续增长使用 ts-morph 元数据提供器TsMorphMetadataProvider的装饰器实体需要扫描源码做类型推断实体分散在多个模块目录中希望新增实体时完全不用改配置。从源码角度补充一点文件夹发现在启动期需要 glob 扫描 逐文件动态导入discoverEntities见 discover-entities.ts因此启动会略慢而显式引用直接处理已加载的类引用且编译期即可发现实体不存在/未导出等错误这正是表中启动速度与错误检测时机两行的依据。同步初始化限制new MikroORM()不支持文件夹发现文件夹发现依赖异步动态导入因此只有异步的MikroORM.init()支持文件夹发现同步构造函数new MikroORM()无法使用 glob 路径。这一点在源码中有两处印证MetadataDiscovery.tsdiscoverReferences遇到字符串路径直接抛出Folder based discovery requires the asyncMikroORM.init()method.MikroORM.ts同步构造函数的文档注释明确列出限制——folder-based discovery not supported、ORM extensions are not autoloaded。// 正确异步初始化支持文件夹发现 const orm await MikroORM.init({ entities: [dist/**/*.entity.js], }); // 错误同步构造必须使用显式实体引用 const orm new MikroORM({ entities: [dist/**/*.entity.js], // ✗ 不支持 // entities: [User, Article], // ✓ 只能这样写 });多个实体位置混合引用与 glob 模式entities与entitiesTs数组允许同时包含实体类引用和字符串路径用于需要优先加载基类实体或混合发现策略的场景import { BaseEntity } from ./entities/base.entity.js; export default defineConfig({ entities: [ BaseEntity, // 显式引用基类实体 dist/modules/**/*.entity.js, // glob 模式其余实体 ], entitiesTs: [ BaseEntity, src/modules/**/*.entity.ts, ], });这种做法在以下场景特别有用基类实体需要先于子类加载如BaseEntity作为抽象基类通过显式引用保证其元数据先行注册部分实体使用特殊命名无法被既有 glob 覆盖需要显式补充逐步迁移从全显式引用迁移到文件夹发现的过程中可以两者并存。源码层面findEntities会先把数组中的字符串路径收集进paths类引用收集进processed然后对路径执行discoverEntities后合并处理见 MetadataDiscovery.ts因此两种形式的顺序与混用都是安全的。生成 barrel 文件discovery:export文件夹发现虽然省事但失去了显式引用的类型安全与打包器兼容性。discovery:export命令提供了一种两全其美的中间方案扫描实体源码生成一个带显式导入的 TypeScript barrel 文件之后配置改为引用该文件中的entities数组。npx mikro-orm discovery:export命令会从配置的entitiesTs优先或entities数组中提取字符串路径也可用--path显式指定扫描并动态导入实体文件生成类似下面的文件// This file was generated by MikroORM CLI. Do not edit manually. // Re-run mikro-orm discovery:export to update. import { Article } from ./entities/Article.js; import { User } from ./entities/User.js; export const entities [ Article, User, ] as const;然后在配置中使用生成的文件import { entities } from ./entities.generated; export default defineConfig({ entities });这样你得到的是文件夹发现的便利性新增实体后重跑一次命令即可无需手写 import显式引用的好处对打包器友好无运行时动态导入、启动更快直接使用类引用、编译期检查实体未导出会报错。命令选项FlagTypeDescription-p, --pathstring[]实体源文件的 glob 模式可多个-o, --outstring输出文件路径默认生成在 ORM 配置文件同目录下的entities.generated.ts-d, --dumpboolean打印到 stdout 而不写文件实现细节见 DiscoveryExportCommand.ts路径解析顺序--path参数 配置entitiesTs中的字符串路径 配置entities中的字符串路径否则报错No entity paths found in config. Use --path to specify entity source locations.DiscoveryExportCommand.ts实体识别逻辑与运行时发现一致跳过__esModule、跳过与EntitySchema关联的类实现、按MetadataStorage.isKnownEntity判定装饰器实体DiscoveryExportCommand.ts生成的输出文件头部带由 CLI 生成、请勿手改的注释重新执行命令即可更新生成的entities数组带有as const可推导出Database实体元组类型切换配置后重跑需显式传--path一旦配置改为entities引用数组不再含字符串路径命令无法再从配置提取路径此时应显式指定npx mikro-orm discovery:export --path ./src/entities/*.ts与 Kysely 集成的类型增强discovery:export生成的 barrel 文件不仅是实体数组还会额外导出两个与 Kysely 类型集成相关的内容详见 kysely.md 的 Generating Entity Exports with the CLI 一节Database类型即typeof entities可用于MikroORMDriver, EM, Database等接受实体元组的泛型位置EntityManager类型与值一个绑定到驱动包、且携带实体元组信息通过幻影属性~entities嫁接的实体感知EntityManager别名。它同时以type和const形式导出既可作为 NestJS 等 DI 容器的注入令牌也可作为构造参数的类型标注确保em.getKysely(opts)能保持完整的表名、列名类型推断。如果你自定义了EntityManager子类可参考 kysely.md 的做法写一个紧邻的包装文件把生成的Database元组嫁接到自己的 EM 子类上再让服务从包装文件导入这样重跑discovery:export不会覆盖你的定制代码。常见问题与最佳实践小结entities与entitiesTs别混用编译产物跑entitiesTS 源码跑entitiesTs这是文件夹发现能正确工作的前提Vitest/ESM 下的ERR_UNKNOWN_FILE_EXTENSION在 ESM 项目中使用文件夹发现并配合 Vitest 等测试框架时可能遇到TypeError: Unknown file extension .ts。原因是 MikroORM 内部执行动态导入而 Vitest 无法自动转换这些导入。解决方式是覆盖dynamicImportProvider详见 guide/01-first-entity.md 的 ESM 提示export default defineConfig({ // ... dynamicImportProvider: id import(id), });排查顺序先npx mikro-orm debug确认加载了哪个配置文件、preferTs判定结果、每个实体路径是否存在再检查 glob 模式与命名约定是否一致元数据缓存注意使用文件夹发现时元数据缓存与运行环境相关——直接跑 TS 时生成的缓存对应 TS 文件生产环境需用mikro-orm cache:generate重新生成或改用预构建缓存详见 metadata-cache.md新增实体后的两种选择保持文件夹发现零配置或用discovery:export生成 barrel 后交给打包器更好的类型与性能特性。参考实现与测试入口核心配置项定义Configuration.tsentities/entitiesTs、Configuration.tspreferTs发现流程主逻辑MetadataDiscovery.tsfindEntities文件扫描与动态导入discover-entities.tsCLI 调试命令DebugCommand.tsCLI barrel 导出命令DiscoveryExportCommand.ts相关测试tests/MikroORM.test.ts、tests/features/cli/DebugCommand.test.ts、tests/features/cli/DiscoveryExportCommand.test.ts。综上文件夹发现是 MikroORM 7 面向大型项目提供的一等公民能力以命名约定 glob 模式换取零维护的实体注册同时通过debug与discovery:export两个命令补齐了可观测性与类型安全让开发者可以在纯文件夹发现与生成式显式引用之间按项目形态灵活选择。赞分享后端【免费下载链接】mikro-ormTypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, MariaDB, MS SQL Server, PostgreSQL and SQLite/libSQL databases.项目地址https://gitcode.com/gh_mirrors/mi/mikro-orm点击查看免费下载相关推荐MikroORM 基于文件夹的实体自动发现Folder-based Discovery完整指南MikroORM 基于文件夹的实体自动发现Folder based Discovery完整指南 导读 在 MikroORM 中实体既可以像 entitie后端MikroORM 文件夹式实体发现Folder-based Discovery完整指南MikroORM 文件夹式实体发现Folder based Discovery完整指南 MikroORM 允许你通过 glob 模式自动发现实体无需在配置后端MikroORM Folder-based Discovery 完全指南用 Glob 模式自动发现实体的原理与实战MikroORM Folder based Discovery 完全指南用 Glob 模式自动发现实体的原理与实战 导读 在 MikroORM 中你既可以在后端上一篇nats-server 账户导入导出如何用 subject 映射函数改写消息主题下一篇OpenChamber 服务端 TTS 模块深度解析OpenAI 语音合成、文本净化与 macOS say 语音能力创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考