docs/versioned_docs/version-7.1/folder-based-discovery.md
Instead of explicitly listing all entities, you can use glob patterns to discover entities automatically based on file naming conventions.
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'],
// ...
});
entitiesTs patternsentities patternsIt is important that
entitiespoints to the compiled JS files, andentitiesTspoints to the TS source files. You should not mix those.
A common convention is to use the .entity.ts suffix:
src/
├── modules/
│ ├── user/
│ │ └── user.entity.ts
│ ├── article/
│ │ ├── article.entity.ts
│ │ └── tag.entity.ts
│ └── common/
│ └── base.entity.ts
└── mikro-orm.config.ts
The paths are resolved using native Node.js glob, so you can use standard globbing patterns:
const orm = await MikroORM.init({
// All .entity.js files in dist folder recursively
entities: ['./dist/**/*.entity.js'],
// Multiple patterns
entities: ['./dist/modules/**/*.entity.js', './dist/shared/**/*.entity.js'],
// Negative patterns to exclude files
entities: ['./dist/**/*.entity.js', '!./dist/**/*.test.entity.js'],
});
:::note Brace expansion
Native Node.js glob does not support brace expansion patterns like src/{entities,modules}/*.ts. If you need this feature, use tinyglobby directly:
import { glob } from 'tinyglobby';
export default defineConfig({
entities: await glob(['src/{entities,modules}/*.ts']),
});
:::
If you are experiencing problems with folder-based discovery, use the mikro-orm debug CLI command to check what paths are actually being used:
npx mikro-orm debug
This will show you:
| Aspect | Explicit (entities: [User]) | Folder-based (entities: ['**/*.entity.js']) |
|---|---|---|
| Setup complexity | More code | Less code |
| Refactoring | IDE-supported | Manual pattern updates |
| Build tools | Works everywhere | May need configuration |
| Performance | Faster startup | Slightly slower (file scanning) |
| Error detection | Compile-time | Runtime |
defineEntity (recommended approach)When using the synchronous new MikroORM() constructor instead of MikroORM.init(), folder-based discovery is not supported:
// This works - async initialization supports folder-based discovery
const orm = await MikroORM.init({
entities: ['dist/**/*.entity.js'],
});
// This does NOT work - must use explicit entity references
const orm = new MikroORM({
entities: ['dist/**/*.entity.js'],
// use explicit references only with sync init
// entities: [User, Article],
});
You can combine multiple patterns and explicit references:
import { BaseEntity } from './entities/base.entity.js';
export default defineConfig({
entities: [
BaseEntity, // explicit reference
'dist/modules/**/*.entity.js', // glob pattern
],
entitiesTs: [
BaseEntity,
'src/modules/**/*.entity.ts',
],
});
This is useful when you have base entities that need to be loaded first, or when mixing discovery approaches.
discovery:exportInstead of manually maintaining entity arrays or relying on folder-based discovery at runtime, you can use the discovery:export CLI command to generate a TypeScript barrel file with explicit entity imports:
npx mikro-orm discovery:export
This scans your entity source files (using entitiesTs or entities paths from your config) and generates a file like:
import { Article } from './entities/Article.js';
import { User } from './entities/User.js';
export const entities = [
Article,
User,
] as const;
You can then use the generated file in your config:
import { entities } from './entities.generated';
export default defineConfig({ entities });
This gives you the convenience of folder-based discovery (no manual updates when adding entities) with the benefits of explicit references (works with bundlers, faster startup, compile-time checking). The command also generates a Database type for use with Kysely integration.
See the Kysely guide for the full command options.