Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): update to TypeScript 4.8 and improve EntityDTO type #3389

Merged
merged 1 commit into from
Aug 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"docusaurus-plugin-typedoc-api": "2.4.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"typescript": "4.7.4"
"typescript": "4.8.2"
},
"browserslist": {
"production": [
Expand Down
8 changes: 4 additions & 4 deletions docs/yarn.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
"sql-formatter": "8.0.2",
"ts-jest": "28.0.8",
"ts-node": "10.9.1",
"typescript": "4.7.4",
"typescript": "4.8.2",
"uuid": "8.3.2"
}
}
4 changes: 2 additions & 2 deletions packages/better-sqlite/src/BetterSqliteDriver.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { AnyEntity, Configuration, EntityDictionary, NativeInsertUpdateManyOptions, QueryResult } from '@mikro-orm/core';
import type { Configuration, EntityDictionary, NativeInsertUpdateManyOptions, QueryResult } from '@mikro-orm/core';
import { AbstractSqlDriver } from '@mikro-orm/knex';
import { BetterSqliteConnection } from './BetterSqliteConnection';
import { BetterSqlitePlatform } from './BetterSqlitePlatform';
Expand All @@ -9,7 +9,7 @@ export class BetterSqliteDriver extends AbstractSqlDriver<BetterSqliteConnection
super(config, new BetterSqlitePlatform(), BetterSqliteConnection, ['knex', 'better-sqlite3']);
}

async nativeInsertMany<T extends AnyEntity<T>>(entityName: string, data: EntityDictionary<T>[], options: NativeInsertUpdateManyOptions<T> = {}): Promise<QueryResult<T>> {
async nativeInsertMany<T extends object>(entityName: string, data: EntityDictionary<T>[], options: NativeInsertUpdateManyOptions<T> = {}): Promise<QueryResult<T>> {
options.processCollections ??= true;
const res = await super.nativeInsertMany(entityName, data, options);
const pks = this.getPrimaryKeyFields(entityName);
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/CreateSeederCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export class CreateSeederCommand<T> implements CommandModule<T, { seeder: string

command = 'seeder:create <seeder>';
describe = 'Create a new seeder class';
builder = (args: Argv) => {
builder = (args: Argv<T>) => {
args.positional('seeder', {
describe: 'Name for the seeder class. (e.g. "test" will generate "TestSeeder" or "TestSeeder" will generate "TestSeeder")',
});
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/DatabaseSeedCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export class DatabaseSeedCommand<T> implements CommandModule<T, { class: string

command = 'seeder:run';
describe = 'Seed the database using the seeder class';
builder = (args: Argv) => {
builder = (args: Argv<T>) => {
args.option('c', {
alias: 'class',
type: 'string',
Expand Down
104 changes: 52 additions & 52 deletions packages/core/src/EntityManager.ts

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/core/src/MikroORM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { Logger } from './logging';
import { Configuration, ConfigurationLoader, Utils } from './utils';
import { NullCacheAdapter } from './cache';
import type { EntityManager } from './EntityManager';
import type { AnyEntity, Constructor, IEntityGenerator, IMigrator, ISeedManager } from './typings';
import type { Constructor, IEntityGenerator, IMigrator, ISeedManager } from './typings';
import { colors } from './logging';

/**
Expand Down Expand Up @@ -136,7 +136,7 @@ export class MikroORM<D extends IDatabaseDriver = IDatabaseDriver> {
/**
* Allows dynamically discovering new entity by reference, handy for testing schema diffing.
*/
async discoverEntity<T>(entities: Constructor<T> | Constructor<AnyEntity>[]): Promise<void> {
async discoverEntity(entities: Constructor | Constructor[]): Promise<void> {
entities = Utils.asArray(entities);
const tmp = await this.discovery.discoverReferences(entities);
new MetadataValidator().validateDiscovered([...Object.values(this.metadata.getAll()), ...tmp], this.config.get('discovery').warnWhenNoEntities!);
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/connections/Connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { URL } from 'url';
import type { Configuration, ConnectionOptions, DynamicPassword } from '../utils';
import type { LogContext } from '../logging';
import type { MetadataStorage } from '../metadata';
import type { AnyEntity, ConnectionType, Dictionary, MaybePromise, Primary } from '../typings';
import type { ConnectionType, Dictionary, MaybePromise, Primary } from '../typings';
import type { Platform } from '../platforms/Platform';
import type { TransactionEventBroadcaster } from '../events/TransactionEventBroadcaster';
import type { IsolationLevel } from '../enums';
Expand Down Expand Up @@ -130,7 +130,7 @@ export abstract class Connection {

}

export interface QueryResult<T extends AnyEntity<T> = { id: number }> {
export interface QueryResult<T = { id: number }> {
affectedRows: number;
insertId: Primary<T>;
row?: Dictionary;
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/decorators/Indexed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { MetadataStorage } from '../metadata';
import type { AnyEntity, Dictionary } from '../typings';
import { Utils } from '../utils/Utils';

function createDecorator<T extends AnyEntity<T>>(options: IndexOptions<T> | UniqueOptions<T>, unique: boolean) {
function createDecorator<T>(options: IndexOptions<T> | UniqueOptions<T>, unique: boolean) {
return function (target: AnyEntity, propertyName?: string) {
const meta = MetadataStorage.getMetadataFromDecorator(propertyName ? target.constructor : target);
options.properties = options.properties || propertyName as keyof T;
Expand All @@ -25,13 +25,13 @@ export function Unique<T>(options: UniqueOptions<T> = {}) {
return createDecorator(options, true);
}

export interface UniqueOptions<T extends AnyEntity<T>> {
export interface UniqueOptions<T> {
name?: string;
properties?: keyof T | (keyof T)[];
options?: Dictionary;
}

export interface IndexOptions<T extends AnyEntity<T>> extends UniqueOptions<T> {
export interface IndexOptions<T> extends UniqueOptions<T> {
type?: string;
expression?: string;
}
43 changes: 22 additions & 21 deletions packages/core/src/drivers/DatabaseDriver.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import type { CountOptions, LockOptions, DeleteOptions, FindOneOptions, FindOptions, IDatabaseDriver, NativeInsertUpdateManyOptions, NativeInsertUpdateOptions, DriverMethodOptions } from './IDatabaseDriver';
import { EntityManagerType } from './IDatabaseDriver';
import type { AnyEntity, ConnectionType, Dictionary, EntityData, EntityDictionary, EntityMetadata, EntityProperty, FilterQuery, PopulateOptions, Primary } from '../typings';
import type { ConnectionType, Dictionary, EntityData, EntityDictionary, EntityMetadata, EntityProperty, FilterQuery, PopulateOptions, Primary } from '../typings';
import type { MetadataStorage } from '../metadata';
import type { Connection, QueryResult, Transaction } from '../connections';
import type { Configuration, ConnectionOptions } from '../utils';
import { EntityComparator, Utils } from '../utils';
import type { QueryOrderMap } from '../enums';
import { QueryOrder, ReferenceType } from '../enums';
import type { Platform } from '../platforms';
import type { Collection } from '../entity';
import type { Collection } from '../entity/Collection';
import { EntityManager } from '../EntityManager';
import { ValidationError } from '../errors';
import { DriverException } from '../exceptions';
import { helper } from '../entity/wrap';

export abstract class DatabaseDriver<C extends Connection> implements IDatabaseDriver<C> {

Expand All @@ -27,58 +28,58 @@ export abstract class DatabaseDriver<C extends Connection> implements IDatabaseD
protected constructor(readonly config: Configuration,
protected readonly dependencies: string[]) { }

abstract find<T, P extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOptions<T, P>): Promise<EntityData<T>[]>;
abstract find<T extends object, P extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOptions<T, P>): Promise<EntityData<T>[]>;

abstract findOne<T, P extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOneOptions<T, P>): Promise<EntityData<T> | null>;
abstract findOne<T extends object, P extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOneOptions<T, P>): Promise<EntityData<T> | null>;

abstract nativeInsert<T>(entityName: string, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
abstract nativeInsert<T extends object>(entityName: string, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;

abstract nativeInsertMany<T>(entityName: string, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
abstract nativeInsertMany<T extends object>(entityName: string, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;

abstract nativeUpdate<T>(entityName: string, where: FilterQuery<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
abstract nativeUpdate<T extends object>(entityName: string, where: FilterQuery<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;

async nativeUpdateMany<T>(entityName: string, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>> {
async nativeUpdateMany<T extends object>(entityName: string, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>> {
throw new Error(`Batch updates are not supported by ${this.constructor.name} driver`);
}

abstract nativeDelete<T>(entityName: string, where: FilterQuery<T>, options?: DeleteOptions<T>): Promise<QueryResult<T>>;
abstract nativeDelete<T extends object>(entityName: string, where: FilterQuery<T>, options?: DeleteOptions<T>): Promise<QueryResult<T>>;

abstract count<T extends AnyEntity<T>, P extends string = never>(entityName: string, where: FilterQuery<T>, options?: CountOptions<T, P>): Promise<number>;
abstract count<T extends object, P extends string = never>(entityName: string, where: FilterQuery<T>, options?: CountOptions<T, P>): Promise<number>;

createEntityManager<D extends IDatabaseDriver = IDatabaseDriver>(useContext?: boolean): D[typeof EntityManagerType] {
return new EntityManager(this.config, this, this.metadata, useContext) as unknown as EntityManager<D>;
}

/* istanbul ignore next */
async findVirtual<T>(entityName: string, where: FilterQuery<T>, options: FindOptions<T, any>): Promise<EntityData<T>[]> {
async findVirtual<T extends object>(entityName: string, where: FilterQuery<T>, options: FindOptions<T, any>): Promise<EntityData<T>[]> {
throw new Error(`Virtual entities are not supported by ${this.constructor.name} driver.`);
}

/* istanbul ignore next */
async countVirtual<T>(entityName: string, where: FilterQuery<T>, options: CountOptions<T>): Promise<number> {
async countVirtual<T extends object>(entityName: string, where: FilterQuery<T>, options: CountOptions<T>): Promise<number> {
throw new Error(`Counting virtual entities is not supported by ${this.constructor.name} driver.`);
}

async aggregate(entityName: string, pipeline: any[]): Promise<any[]> {
throw new Error(`Aggregations are not supported by ${this.constructor.name} driver`);
}

async loadFromPivotTable<T, O>(prop: EntityProperty, owners: Primary<O>[][], where?: FilterQuery<T>, orderBy?: QueryOrderMap<T>[], ctx?: Transaction, options?: FindOptions<T>): Promise<Dictionary<T[]>> {
async loadFromPivotTable<T extends object, O extends object>(prop: EntityProperty, owners: Primary<O>[][], where?: FilterQuery<any>, orderBy?: QueryOrderMap<T>[], ctx?: Transaction, options?: FindOptions<T, any>): Promise<Dictionary<T[]>> {
throw new Error(`${this.constructor.name} does not use pivot tables`);
}

async syncCollection<T, O>(coll: Collection<T, O>, options?: DriverMethodOptions): Promise<void> {
async syncCollection<T extends object, O extends object>(coll: Collection<T, O>, options?: DriverMethodOptions): Promise<void> {
const pk = coll.property.targetMeta!.primaryKeys[0];
const data = { [coll.property.name]: coll.getIdentifiers(pk) } as EntityData<T>;
await this.nativeUpdate<T>(coll.owner.constructor.name, coll.owner.__helper!.getPrimaryKey() as FilterQuery<T>, data, options);
await this.nativeUpdate<T>(coll.owner.constructor.name, helper(coll.owner).getPrimaryKey() as FilterQuery<T>, data, options);
}

mapResult<T>(result: EntityDictionary<T>, meta?: EntityMetadata<T>, populate: PopulateOptions<T>[] = []): EntityData<T> | null {
mapResult<T extends object>(result: EntityDictionary<T>, meta?: EntityMetadata<T>, populate: PopulateOptions<T>[] = []): EntityData<T> | null {
if (!result || !meta) {
return result ?? null;
}

return this.comparator.mapResult(meta.className, result);
return this.comparator.mapResult<T>(meta.className, result);
}

async connect(): Promise<C> {
Expand Down Expand Up @@ -144,7 +145,7 @@ export abstract class DatabaseDriver<C extends Connection> implements IDatabaseD
}

protected inlineEmbeddables<T>(meta: EntityMetadata<T>, data: T, where?: boolean): void {
Object.keys(data).forEach(k => {
Object.keys(data as Dictionary).forEach(k => {
if (Utils.isOperator(k)) {
Utils.asArray(data[k]).forEach(payload => this.inlineEmbeddables(meta, payload, where));
}
Expand All @@ -159,9 +160,9 @@ export abstract class DatabaseDriver<C extends Connection> implements IDatabaseD
const props = prop.embeddedProps;
let unknownProp = false;

Object.keys(data[prop.name]).forEach(kk => {
Object.keys(data[prop.name] as Dictionary).forEach(kk => {
// explicitly allow `$exists` operator here as it cant be misused this way
const operator = Object.keys(data[prop.name]).some(f => Utils.isOperator(f) && f !== '$exists');
const operator = Object.keys(data[prop.name] as Dictionary).some(f => Utils.isOperator(f) && f !== '$exists');

if (operator) {
throw ValidationError.cannotUseOperatorsInsideEmbeddables(meta.name!, prop.name, data);
Expand Down Expand Up @@ -246,7 +247,7 @@ export abstract class DatabaseDriver<C extends Connection> implements IDatabaseD
return ret;
}

async lockPessimistic<T extends AnyEntity<T>>(entity: T, options: LockOptions): Promise<void> {
async lockPessimistic<T>(entity: T, options: LockOptions): Promise<void> {
throw new Error(`Pessimistic locks are not supported by ${this.constructor.name} driver`);
}

Expand Down