diff --git a/packages/framework/src/orm-browser/controller.ts b/packages/framework/src/orm-browser/controller.ts index d9ec6053e..41c13cff3 100644 --- a/packages/framework/src/orm-browser/controller.ts +++ b/packages/framework/src/orm-browser/controller.ts @@ -1,5 +1,5 @@ import { isArray, isObject } from '@deepkit/core'; -import { Database, DatabaseAdapter } from '@deepkit/orm'; +import { Database, DatabaseAdapter, MigrateOptions } from '@deepkit/orm'; import { BrowserControllerInterface, DatabaseCommit, @@ -114,7 +114,7 @@ export class OrmBrowserController implements BrowserControllerInterface { async getMigrations(name: string): Promise<{ [name: string]: { sql: string[], diff: string } }> { const db = this.findDatabase(name); if (db.adapter instanceof SQLDatabaseAdapter) { - return db.adapter.getMigrations(db.entityRegistry); + return db.adapter.getMigrations(new MigrateOptions(), db.entityRegistry); } return {}; } diff --git a/packages/mongo/src/adapter.ts b/packages/mongo/src/adapter.ts index 2f506c077..bb0feb42e 100644 --- a/packages/mongo/src/adapter.ts +++ b/packages/mongo/src/adapter.ts @@ -8,7 +8,17 @@ * You should have received a copy of the MIT License along with this program. */ -import { DatabaseAdapter, DatabaseAdapterQueryFactory, DatabaseEntityRegistry, DatabaseSession, FindQuery, ItemNotFound, OrmEntity, RawFactory } from '@deepkit/orm'; +import { + DatabaseAdapter, + DatabaseAdapterQueryFactory, + DatabaseEntityRegistry, + DatabaseSession, + FindQuery, + ItemNotFound, + MigrateOptions, + OrmEntity, + RawFactory +} from '@deepkit/orm'; import { AbstractClassType, ClassType, isArray } from '@deepkit/core'; import { MongoDatabaseQuery } from './query.js'; import { MongoPersistence } from './persistence.js'; @@ -143,22 +153,22 @@ export class MongoDatabaseAdapter extends DatabaseAdapter { await this.client.execute(new DeleteCommand(this.ormSequences)); } - async migrate(entityRegistry: DatabaseEntityRegistry) { + async migrate(options: MigrateOptions, entityRegistry: DatabaseEntityRegistry) { await this.client.connect(); //manually connect to catch connection errors let withOrmSequences = true; for (const schema of entityRegistry.forMigration()) { - await this.migrateClassSchema(schema); + await this.migrateClassSchema(options, schema); for (const property of schema.getProperties()) { if (property.isAutoIncrement()) withOrmSequences = true; } } if (withOrmSequences) { - await this.migrateClassSchema(this.ormSequences); + await this.migrateClassSchema(options, this.ormSequences); } }; - async migrateClassSchema(schema: ReflectionClass) { + async migrateClassSchema(options: MigrateOptions, schema: ReflectionClass) { try { await this.client.execute(new CreateCollectionCommand(schema)); } catch (error) { diff --git a/packages/orm/src/database-adapter.ts b/packages/orm/src/database-adapter.ts index 4385af451..440426763 100644 --- a/packages/orm/src/database-adapter.ts +++ b/packages/orm/src/database-adapter.ts @@ -44,6 +44,47 @@ export class RawFactory> { } } +export class MigrateOptions { + /** + * Whether drop statements should be issued, like DROP TABLE, DROP INDEX, etc. + * + * Default false. + */ + drop: boolean = false; + + /** + * Whether drop statements should be issued for indexes/uniques, like DROP INDEX. + */ + dropIndex: boolean = false; + + /** + * Whether create/drop statements should be issued for indexes/uniques, like CREATE/ INDEX/DROP INDEX. + */ + skipIndex: boolean = false; + + /** + * Whether foreign key constraints should be created/dropped. + */ + skipForeignKey: boolean = false; + + isDropIndex() { + if (this.skipIndex) return false; + return this.skipIndex || this.dropIndex || this.drop; + } + + isIndex() { + return !this.skipIndex; + } + + isForeignKey() { + return !this.skipForeignKey; + } + + isDropSchema() { + return this.drop; + } +} + /** * A generic database adapter you can use if the API of `Query` is sufficient. * @@ -62,8 +103,11 @@ export abstract class DatabaseAdapter { abstract disconnect(force?: boolean): void; - abstract migrate(entityRegistry: DatabaseEntityRegistry): Promise; + abstract migrate(options: MigrateOptions, entityRegistry: DatabaseEntityRegistry): Promise; + /** + * Unique adapter name to be used in DatabaseField to apply certain adapter specific behavior per field. + */ abstract getName(): string; abstract getSchemaName(): string; diff --git a/packages/orm/src/database-session.ts b/packages/orm/src/database-session.ts index 12081d6b9..e650f2f03 100644 --- a/packages/orm/src/database-session.ts +++ b/packages/orm/src/database-session.ts @@ -316,7 +316,9 @@ export class DatabaseSession { //we cannot use arrow functions, since they can't have ReceiveType function query(type?: ReceiveType | ClassType | AbstractClassType | ReflectionClass) { - return queryFactory.createQuery(type); + const result = queryFactory.createQuery(type); + result.model.adapterName = adapter.getName(); + return result; } this.query = query as any; diff --git a/packages/orm/src/database.ts b/packages/orm/src/database.ts index 83c727a57..bf9fa10f1 100644 --- a/packages/orm/src/database.ts +++ b/packages/orm/src/database.ts @@ -21,7 +21,7 @@ import { resolveReceiveType, Type } from '@deepkit/type'; -import { DatabaseAdapter, DatabaseEntityRegistry } from './database-adapter.js'; +import { DatabaseAdapter, DatabaseEntityRegistry, MigrateOptions } from './database-adapter.js'; import { DatabaseSession } from './database-session.js'; import { DatabaseLogger } from './logger.js'; import { Query } from './query.js'; @@ -332,8 +332,10 @@ export class Database { * WARNING: DON'T USE THIS IN PRODUCTION AS THIS CAN CAUSE EASILY DATA LOSS. * SEE THE MIGRATION DOCUMENTATION TO UNDERSTAND ITS IMPLICATIONS. */ - async migrate() { - await this.adapter.migrate(this.entityRegistry); + async migrate(options: Partial = {}) { + const o = new MigrateOptions(); + Object.assign(o, options); + await this.adapter.migrate(o, this.entityRegistry); } /** diff --git a/packages/orm/src/memory-db.ts b/packages/orm/src/memory-db.ts index 809cc01dd..660097043 100644 --- a/packages/orm/src/memory-db.ts +++ b/packages/orm/src/memory-db.ts @@ -12,7 +12,7 @@ import { DatabaseSession, DatabaseTransaction } from './database-session.js'; import { DatabaseQueryModel, GenericQueryResolver, Query } from './query.js'; import { Changes, getSerializeFunction, ReceiveType, ReflectionClass, resolvePath, serialize, Serializer } from '@deepkit/type'; import { AbstractClassType, deletePathValue, getPathValue, setPathValue } from '@deepkit/core'; -import { DatabaseAdapter, DatabaseAdapterQueryFactory, DatabaseEntityRegistry, DatabasePersistence, DatabasePersistenceChangeSet } from './database-adapter.js'; +import { DatabaseAdapter, DatabaseAdapterQueryFactory, DatabaseEntityRegistry, DatabasePersistence, DatabasePersistenceChangeSet, MigrateOptions } from './database-adapter.js'; import { DeleteResult, OrmEntity, PatchResult } from './type.js'; import { findQueryList } from './utils.js'; import { convertQueryFilter } from './query-filter.js'; @@ -246,7 +246,7 @@ export class MemoryDatabaseTransaction extends DatabaseTransaction { export class MemoryDatabaseAdapter extends DatabaseAdapter { protected store = new Map, SimpleStore>(); - async migrate(entityRegistry: DatabaseEntityRegistry) { + async migrate(options: MigrateOptions, entityRegistry: DatabaseEntityRegistry) { } isNativeForeignKeyConstraintSupported(): boolean { diff --git a/packages/orm/src/query.ts b/packages/orm/src/query.ts index 2eb61e229..2e6a8bfad 100644 --- a/packages/orm/src/query.ts +++ b/packages/orm/src/query.ts @@ -105,6 +105,11 @@ export class DatabaseQueryModel; } diff --git a/packages/sql/src/schema/table.ts b/packages/sql/src/schema/table.ts index 168547ed9..11e70550a 100644 --- a/packages/sql/src/schema/table.ts +++ b/packages/sql/src/schema/table.ts @@ -17,7 +17,10 @@ export class DatabaseModel { public schemaMap = new Map, Table>(); - constructor(public tables: Table[] = []) { + constructor( + public tables: Table[] = [], + public adapterName: string = '' + ) { } getTableForClass(schema: ReflectionClass): Table { diff --git a/packages/sql/src/sql-adapter.ts b/packages/sql/src/sql-adapter.ts index 8fdb94081..b4a3098cc 100644 --- a/packages/sql/src/sql-adapter.ts +++ b/packages/sql/src/sql-adapter.ts @@ -25,7 +25,7 @@ import { FilterQuery, FindQuery, GenericQueryResolver, - ItemNotFound, + ItemNotFound, MigrateOptions, OrmEntity, PatchResult, Query, @@ -626,7 +626,7 @@ export abstract class SQLDatabaseAdapter extends DatabaseAdapter { public async createTables(entityRegistry: DatabaseEntityRegistry): Promise { const connection = await this.connectionPool.getConnection(); try { - const database = new DatabaseModel(); + const database = new DatabaseModel([], this.getName()); database.schemaName = this.getSchemaName(); this.platform.createTables(entityRegistry, database); const DDLs = this.platform.getAddTablesDDL(database); @@ -638,18 +638,18 @@ export abstract class SQLDatabaseAdapter extends DatabaseAdapter { } } - public async getMigrations(entityRegistry: DatabaseEntityRegistry): Promise<{ [name: string]: { sql: string[], diff: string } }> { + public async getMigrations(options: MigrateOptions, entityRegistry: DatabaseEntityRegistry): Promise<{ [name: string]: { sql: string[], diff: string } }> { const migrations: { [name: string]: { sql: string[], diff: string } } = {}; const connection = await this.connectionPool.getConnection(); try { - const databaseModel = new DatabaseModel(); + const databaseModel = new DatabaseModel([], this.getName()); databaseModel.schemaName = this.getSchemaName(); this.platform.createTables(entityRegistry, databaseModel); const schemaParser = new this.platform.schemaParserType(connection, this.platform); - const parsedDatabaseModel = new DatabaseModel(); + const parsedDatabaseModel = new DatabaseModel([], this.getName()); parsedDatabaseModel.schemaName = this.getSchemaName(); await schemaParser.parse(parsedDatabaseModel); parsedDatabaseModel.removeUnknownTables(databaseModel); @@ -662,7 +662,7 @@ export abstract class SQLDatabaseAdapter extends DatabaseAdapter { databaseDiff.forTable(table); const diff = databaseDiff.getDiff(table); - const upSql = this.platform.getModifyDatabaseDDL(databaseDiff); + const upSql = this.platform.getModifyDatabaseDDL(databaseDiff, options); if (upSql.length) { migrations[entity.getName()] = { sql: upSql, diff: diff ? diff.toString() : '' }; } @@ -675,17 +675,17 @@ export abstract class SQLDatabaseAdapter extends DatabaseAdapter { return migrations; } - public async migrate(entityRegistry: DatabaseEntityRegistry): Promise { - const migrations = await this.getMigrations(entityRegistry); + public async migrate(options: MigrateOptions, entityRegistry: DatabaseEntityRegistry): Promise { + const migrations = await this.getMigrations(options, entityRegistry); const connection = await this.connectionPool.getConnection(); try { - const databaseModel = new DatabaseModel(); + const databaseModel = new DatabaseModel([], this.getName()); databaseModel.schemaName = this.getSchemaName(); this.platform.createTables(entityRegistry, databaseModel); const schemaParser = new this.platform.schemaParserType(connection, this.platform); - const parsedDatabaseModel = new DatabaseModel(); + const parsedDatabaseModel = new DatabaseModel([], this.getName()); parsedDatabaseModel.schemaName = this.getSchemaName(); await schemaParser.parse(parsedDatabaseModel); parsedDatabaseModel.removeUnknownTables(databaseModel); diff --git a/packages/sql/src/sql-builder.ts b/packages/sql/src/sql-builder.ts index e7ae42d72..c371a2742 100644 --- a/packages/sql/src/sql-builder.ts +++ b/packages/sql/src/sql-builder.ts @@ -118,6 +118,7 @@ export class SqlBuilder { } else { for (const property of properties) { if (property.isBackReference()) continue; + if (property.isDatabaseSkipped(model.adapterName)) continue; if (model.isLazyLoaded(property.name)) continue; this.sqlSelect.push(tableName + '.' + this.platform.quoteIdentifier(property.name)); @@ -135,6 +136,7 @@ export class SqlBuilder { for (const property of properties) { if (property.isBackReference()) continue; if (model.isLazyLoaded(property.name)) continue; + if (property.isDatabaseSkipped(model.adapterName)) continue; result.fields.push(property); const as = this.platform.quoteIdentifier(this.sqlSelect.length + ''); diff --git a/packages/sql/src/test.ts b/packages/sql/src/test.ts index 49561bae4..70af734e8 100644 --- a/packages/sql/src/test.ts +++ b/packages/sql/src/test.ts @@ -5,7 +5,7 @@ import { Database, DatabaseEntityRegistry } from '@deepkit/orm'; import { ReflectionClass, Type } from '@deepkit/type'; export async function schemaMigrationRoundTrip(types: (Type | ClassType | ReflectionClass)[], adapter: SQLDatabaseAdapter) { - const originDatabaseModel = new DatabaseModel; + const originDatabaseModel = new DatabaseModel([], adapter.getName()); adapter.platform.createTables(DatabaseEntityRegistry.from(types), originDatabaseModel); const db = new Database(adapter, types); @@ -20,7 +20,7 @@ export async function schemaMigrationRoundTrip(types: (Type | ClassType | Reflec result = adapter.platform.getAddTablesDDL(originDatabaseModel).join('\n'); // console.log(result); - const readDatabaseModel = new DatabaseModel(); + const readDatabaseModel = new DatabaseModel([], adapter.getName()); await schemaParser.parse(readDatabaseModel, originDatabaseModel.getTableNames()); if (readDatabaseModel.tables.length !== types.length) throw new Error(`Read wrong table count, ${readDatabaseModel.tables.length} !== ${types.length}`); diff --git a/packages/sql/tests/inheritance.spec.ts b/packages/sql/tests/inheritance.spec.ts index c3f6dd6c8..0312c750a 100644 --- a/packages/sql/tests/inheritance.spec.ts +++ b/packages/sql/tests/inheritance.spec.ts @@ -1,4 +1,4 @@ -import { AutoIncrement, entity, PrimaryKey, ReflectionKind } from '@deepkit/type'; +import { AutoIncrement, DatabaseField, entity, PrimaryKey, ReflectionKind } from '@deepkit/type'; import { SchemaParser } from '../src/reverse/schema-parser.js'; import { DatabaseModel } from '../src/schema/table.js'; import { DefaultPlatform } from '../src/platform/default-platform.js'; @@ -27,7 +27,7 @@ class Freelance extends Person { } class MySchemaParser extends SchemaParser { - parse(database: DatabaseModel, limitTableNames?: string[]): void { + async parse(database: DatabaseModel, limitTableNames?: string[]) { } } diff --git a/packages/sql/tests/migration.spec.ts b/packages/sql/tests/migration.spec.ts index 910bf39d8..2f65a6c41 100644 --- a/packages/sql/tests/migration.spec.ts +++ b/packages/sql/tests/migration.spec.ts @@ -1,9 +1,9 @@ import { expect, test } from '@jest/globals'; -import { AutoIncrement, entity, Index, PrimaryKey, Reference, ReflectionClass, ReflectionKind, Unique } from '@deepkit/type'; -import { DatabaseModel, IndexModel, TableComparator } from '../src/schema/table.js'; +import { AutoIncrement, DatabaseField, entity, Index, PrimaryKey, Reference, ReflectionClass, ReflectionKind, Unique } from '@deepkit/type'; +import { DatabaseComparator, DatabaseModel, IndexModel, TableComparator } from '../src/schema/table.js'; import { DefaultPlatform } from '../src/platform/default-platform.js'; import { SchemaParser } from '../src/reverse/schema-parser.js'; -import { DatabaseEntityRegistry } from '@deepkit/orm'; +import { DatabaseEntityRegistry, MigrateOptions } from '@deepkit/orm'; @entity.name('user') .index(['deleted'], {unique: true}) @@ -27,7 +27,7 @@ class Post { } class MySchemaParser extends SchemaParser { - parse(database: DatabaseModel, limitTableNames?: string[]): void { + async parse(database: DatabaseModel, limitTableNames?: string[]) { } } @@ -96,6 +96,87 @@ test('add and remove column', async () => { const db2 = platform.createTables(DatabaseEntityRegistry.from([Leagues2, Organisation])); const diff = TableComparator.computeDiff(db1[0], db2[0]); - const sql = platform.getModifyTableDDL(diff!); + const sql = platform.getModifyTableDDL(diff!, new MigrateOptions()); expect(sql).toContain('ALTER TABLE "leagues" ADD "organisation" integer NULL, DROP COLUMN "dayOfWeek"'); }); + +test('skip index', async () => { + const platform = new MyPlatform(); + + @entity.name('leagues') + class Leagues1 { + id!: number & PrimaryKey; + dayOfWeek!: number & Index<{name: 'dayindex'}>; + } + + const db = new DatabaseModel(); + platform.createTables(DatabaseEntityRegistry.from([Leagues1]), db); + const diff = DatabaseComparator.computeDiff(new DatabaseModel(), db); + + { + const options = new MigrateOptions(); + const sql = platform.getModifyDatabaseDDL(diff!, options); + expect(sql).toEqual([`CREATE TABLE "leagues" ( + "id" integer NOT NULL, + "dayOfWeek" integer NOT NULL, + PRIMARY KEY ("id") +)`, `CREATE INDEX "dayindex" ON "leagues" ("dayOfWeek")`]); + } + + { + const options = new MigrateOptions(); + options.skipIndex = true; + const sql = platform.getModifyDatabaseDDL(diff!, options); + expect(sql).toEqual([`CREATE TABLE "leagues" ( + "id" integer NOT NULL, + "dayOfWeek" integer NOT NULL, + PRIMARY KEY ("id") +)`]); + } +}); + +test('no drop per default', () => { + const platform = new MyPlatform(); + + @entity.name('leagues') + class Leagues1 { + id!: number & PrimaryKey; + dayOfWeek!: number & Index<{name: 'dayindex'}>; + } + + const db = new DatabaseModel(); + platform.createTables(DatabaseEntityRegistry.from([Leagues1]), db); + const diff = DatabaseComparator.computeDiff(db, new DatabaseModel()); + + { + const options = new MigrateOptions(); + const sql = platform.getModifyDatabaseDDL(diff!, options); + expect(sql).toEqual([]); + } + + { + const options = new MigrateOptions(); + options.drop = true; + const sql = platform.getModifyDatabaseDDL(diff!, options); + expect(sql).toEqual([`DROP TABLE IF EXISTS "leagues"`]); + } +}); + +test('skip property', () => { + class Entity { + id: PrimaryKey & number = 0; + firstName?: string; + firstName_tsvector: any & DatabaseField<{ skip: true }> = ''; + anotherone: any & DatabaseField<{ skipMigration: true }> = ''; + } + + const platform = new MyPlatform(); + const tables = platform.createTables(DatabaseEntityRegistry.from([Entity])); + + expect(tables.length).toBe(1); + const table = tables[0]; + + expect(table.columns.map(v => v.name)).toEqual([ + 'id', 'firstName' + ]); +}); diff --git a/packages/sql/tests/sql-query.spec.ts b/packages/sql/tests/sql-query.spec.ts index 94ce46f05..dc54075e3 100644 --- a/packages/sql/tests/sql-query.spec.ts +++ b/packages/sql/tests/sql-query.spec.ts @@ -1,5 +1,5 @@ import { expect, test } from '@jest/globals'; -import { entity, ReflectionClass, ReflectionKind, serializer } from '@deepkit/type'; +import { DatabaseField, entity, PrimaryKey, ReflectionClass, ReflectionKind, serializer } from '@deepkit/type'; import { SQLFilterBuilder } from '../src/sql-filter-builder.js'; import { escape } from 'sqlstring'; import { splitDotPath, sql, SQLQueryModel } from '../src/sql-adapter.js'; @@ -13,7 +13,7 @@ function quoteId(value: string): string { } class MySchemaParser extends SchemaParser { - parse(database: DatabaseModel, limitTableNames?: string[]): void { + async parse(database: DatabaseModel, limitTableNames?: string[]) { } } @@ -69,6 +69,21 @@ test('select', () => { } }); +test('skip property', () => { + class Entity { + id: PrimaryKey & number = 0; + firstName?: string; + firstName_tsvector: any & DatabaseField<{ skip: true }> = ''; + anotherone: any & DatabaseField<{ skipMigration: true }> = ''; + } + + const builder = new SqlBuilder(new MyPlatform()); + const model = new SQLQueryModel(); + model.adapterName = 'mongo'; + const builtSQL = builder.select(ReflectionClass.from(Entity), model); + expect(builtSQL.sql).toBe(`SELECT "Entity"."id", "Entity"."firstName", "Entity"."anotherone" FROM "Entity"`); +}); + test('QueryToSql', () => { class User { id!: number; diff --git a/packages/sqlite/src/sqlite-platform.ts b/packages/sqlite/src/sqlite-platform.ts index 83015401c..87907e686 100644 --- a/packages/sqlite/src/sqlite-platform.ts +++ b/packages/sqlite/src/sqlite-platform.ts @@ -15,6 +15,7 @@ import { sqliteSerializer } from './sqlite-serializer.js'; import { SQLiteFilterBuilder } from './sql-filter-builder.sqlite.js'; import { isArray, isObject } from '@deepkit/core'; import sqlstring from 'sqlstring-sqlite'; +import { MigrateOptions } from '@deepkit/orm'; export function isJsonLike(type: Type): boolean { if (isSetType(type) || isMapType(type) || isDateType(type)) return false; @@ -69,7 +70,7 @@ export class SQLitePlatform extends DefaultPlatform { return `${table ? table + '.' : ''}${this.quoteIdentifier(column)}->${this.quoteValue(path)}`; } - getModifyTableDDL(diff: TableDiff): string[] { + getModifyTableDDL(diff: TableDiff, options: MigrateOptions): string[] { let changeViaMigrationTableNeeded = false || diff.modifiedFKs.length > 0 @@ -107,13 +108,13 @@ export class SQLitePlatform extends DefaultPlatform { } if (changeViaMigrationTableNeeded) { - return this.getMigrationTableDDL(diff); + return this.getMigrationTableDDL(diff, options); } - return super.getModifyTableDDL(diff); + return super.getModifyTableDDL(diff, options); } - protected getMigrationTableDDL(diff: TableDiff): string[] { + protected getMigrationTableDDL(diff: TableDiff, options: MigrateOptions): string[] { const lines: string[] = []; // const tempName = diff.to.getName() + '__temp__' + (Math.floor(Math.random() * 10000)); @@ -123,7 +124,7 @@ export class SQLitePlatform extends DefaultPlatform { const tempToName = oldToName + '__temp_new__' + (Math.floor(Math.random() * 10000)); diff.to.name = tempToName; lines.push(this.getDropTableDDL(diff.to)); - lines.push(...this.getAddTableDDL(diff.to)); + lines.push(...this.getAddTableDDL(diff.to, options.isForeignKey())); diff.to.name = oldToName; // lines.push(`CREATE TABLE ${this.quoteIdentifier(tempName)} AS SELECT ${select.join(',')} FROM ${this.getIdentifier(diff.to)}`); @@ -151,7 +152,9 @@ export class SQLitePlatform extends DefaultPlatform { lines.push(`DROP TABLE ${this.getIdentifier(diff.from)}`); lines.push(`ALTER TABLE ${this.quoteIdentifier(tempToName)} RENAME TO ${this.getIdentifier(diff.to)}`); - lines.push(...this.getAddIndicesDDL(diff.to)); + if (options.isIndex()) { + lines.push(...this.getAddIndicesDDL(diff.to)); + } return lines.filter(isSet); } diff --git a/packages/type/src/reflection/reflection.ts b/packages/type/src/reflection/reflection.ts index 17137fb16..388d7f03c 100644 --- a/packages/type/src/reflection/reflection.ts +++ b/packages/type/src/reflection/reflection.ts @@ -524,6 +524,14 @@ export class ReflectionProperty { return isBackReferenceType(this.getType()); } + isDatabaseSkipped(database: string): boolean { + return databaseAnnotation.getDatabase(this.getType(), database)?.skip === true; + } + + isDatabaseMigrationSkipped(database: string): boolean { + return this.isDatabaseSkipped(database) || databaseAnnotation.getDatabase(this.getType(), database)?.skipMigration === true; + } + getBackReference(): BackReferenceOptionsResolved { return getBackReferenceType(this.getType()); } diff --git a/packages/type/src/reflection/type.ts b/packages/type/src/reflection/type.ts index c30aaef12..6c1ae5771 100644 --- a/packages/type/src/reflection/type.ts +++ b/packages/type/src/reflection/type.ts @@ -1768,6 +1768,17 @@ export interface DatabaseFieldOptions { * e.g. `field: string & MySQL<{noDefault: true}> = ''` */ noDefault?: true; + + /** + * Skip this property in all queries and database migration files. + */ + skip?: true; + + /** + * Skip this property in database migration files. This excludes the property from the database, but + * keeps it in the queries. + */ + skipMigration?: true; } export interface MySQLOptions extends DatabaseFieldOptions {