Use built-ins first
Before defining a new table for users, branches, partners, currency, tags, notifications, or media, import the matching entity (and its service) from shared-backend-core. Register your own tables only for domain-specific data.
- Import entities from @quan-erp/shared-backend-core
- Extend BaseEntity on every entity (builtin and yours)
- Join with ManyToOne + JoinColumn; type relations as InstanceType<typeof EntityName>
Domains
- BaseEntity — create/update/soft-delete/version columns
- Identity — UserEntity, RoleEntity, BranchEntity
- Partner — PartnerEntity + shipping addresses
- Currency — CurrencyEntity, CurrencyExchangeRateEnity
- Units — UnitCategoryEntity, UnitEntity, conversions
- Operations — NotifcationEntity, AuditLogEntity, TagEntity
- Config — SettingEntity, EnvEntity, DeveloperConfigEntity
- Plugins — PluginEntity, PluginRouteEntity, DataSeedHistoryEntity
- Files — FileEntity
Join from a plugin entity
Reference core entities with TypeORM relations. Prefer InstanceType<typeof …> for relation types to avoid circular-import issues.
1import {
2 BaseEntity,
3 BranchEntity,
4 UserEntity,
5} from "@quan-erp/shared-backend-core";
6import {
7 Column,
8 Entity,
9 JoinColumn,
10 ManyToOne,
11 PrimaryGeneratedColumn,
12} from "typeorm";
13import metadata from "../../../../module.metadata.json" with { type: "json" };
14
15@Entity(`${metadata.name}_order`)
16export class OrderEntity extends BaseEntity {
17 @PrimaryGeneratedColumn()
18 id: number;
19
20 @ManyToOne(() => UserEntity)
21 @JoinColumn({ name: "userId" })
22 user: InstanceType<typeof UserEntity>;
23
24 @Column()
25 userId: number;
26
27 @ManyToOne(() => BranchEntity)
28 @JoinColumn({ name: "branchId" })
29 branch: InstanceType<typeof BranchEntity>;
30
31 @Column()
32 branchId: number;
33}Your plugin tables
When you need a domain table, define a TypeORM entity (prefix with metadata.name, extend BaseEntity), register it on the module under plugin: "default", and evolve schema with migrations. See Database and Migrations.