Skip to content

Commit

Permalink
chore: update to TypeScript 4.8
Browse files Browse the repository at this point in the history
This required quite a lot of refactoring and might end up semi breaking on type level.
  • Loading branch information
B4nan committed Aug 13, 2022
1 parent 0f66d3b commit ddc8201
Show file tree
Hide file tree
Showing 54 changed files with 575 additions and 556 deletions.
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.7",
"ts-node": "10.9.1",
"typescript": "4.7.4",
"typescript": "4.8.1-rc",
"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>(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
94 changes: 47 additions & 47 deletions packages/core/src/EntityManager.ts

Large diffs are not rendered by default.

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;
}
16 changes: 8 additions & 8 deletions packages/core/src/drivers/DatabaseDriver.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
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';
Expand Down Expand Up @@ -43,7 +43,7 @@ export abstract class DatabaseDriver<C extends Connection> implements IDatabaseD

abstract nativeDelete<T>(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, 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>;
Expand All @@ -58,7 +58,7 @@ export abstract class DatabaseDriver<C extends Connection> implements IDatabaseD
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, O>(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`);
}

Expand All @@ -73,7 +73,7 @@ export abstract class DatabaseDriver<C extends Connection> implements IDatabaseD
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 @@ -139,7 +139,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 @@ -154,9 +154,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 @@ -241,7 +241,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
22 changes: 11 additions & 11 deletions packages/core/src/drivers/IDatabaseDriver.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {
ConnectionType, EntityData, EntityMetadata, EntityProperty, AnyEntity, FilterQuery, Primary, Dictionary, QBFilterQuery,
ConnectionType, EntityData, EntityMetadata, EntityProperty, FilterQuery, Primary, Dictionary, QBFilterQuery,
IPrimaryKey, PopulateOptions, EntityDictionary, ExpandProperty, AutoPath, ObjectQuery,
} from '../typings';
import type { Connection, QueryResult, Transaction } from '../connections';
Expand Down Expand Up @@ -31,28 +31,28 @@ export interface IDatabaseDriver<C extends Connection = Connection> {
/**
* Finds selection of entities
*/
find<T extends AnyEntity<T>, P extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOptions<T, P>): Promise<EntityData<T>[]>;
find<T, P extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOptions<T, P>): Promise<EntityData<T>[]>;

/**
* Finds single entity (table row, document)
*/
findOne<T extends AnyEntity<T>, P extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOneOptions<T, P>): Promise<EntityData<T> | null>;
findOne<T, P extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOneOptions<T, P>): Promise<EntityData<T> | null>;

findVirtual<T>(entityName: string, where: FilterQuery<T>, options: FindOptions<T, any>): Promise<EntityData<T>[]>;

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

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

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

nativeUpdateMany<T extends AnyEntity<T>>(entityName: string, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
nativeUpdateMany<T>(entityName: string, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;

nativeDelete<T extends AnyEntity<T>>(entityName: string, where: FilterQuery<T>, options?: NativeDeleteOptions<T>): Promise<QueryResult<T>>;
nativeDelete<T>(entityName: string, where: FilterQuery<T>, options?: NativeDeleteOptions<T>): Promise<QueryResult<T>>;

syncCollection<T, O>(collection: Collection<T, O>, options?: DriverMethodOptions): Promise<void>;

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

aggregate(entityName: string, pipeline: any[]): Promise<any[]>;

Expand All @@ -61,7 +61,7 @@ export interface IDatabaseDriver<C extends Connection = Connection> {
/**
* When driver uses pivot tables for M:N, this method will load identifiers for given collections from them
*/
loadFromPivotTable<T extends AnyEntity<T>, O extends AnyEntity<O>>(prop: EntityProperty, owners: Primary<O>[][], where?: FilterQuery<T>, orderBy?: QueryOrderMap<T>[], ctx?: Transaction, options?: FindOptions<T>): Promise<Dictionary<T[]>>;
loadFromPivotTable<T, O>(prop: EntityProperty, owners: Primary<O>[][], where?: FilterQuery<T>, orderBy?: QueryOrderMap<T>[], ctx?: Transaction, options?: FindOptions<T, any>): Promise<Dictionary<T[]>>;

getPlatform(): Platform;

Expand All @@ -77,7 +77,7 @@ export interface IDatabaseDriver<C extends Connection = Connection> {
*/
getDependencies(): string[];

lockPessimistic<T extends AnyEntity<T>>(entity: T, options: LockOptions): Promise<void>;
lockPessimistic<T>(entity: T, options: LockOptions): Promise<void>;

/**
* Converts native db errors to standardized driver exceptions
Expand Down
20 changes: 10 additions & 10 deletions packages/core/src/entity/ArrayCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class ArrayCollection<T, O> {
protected _count?: number;
private _property?: EntityProperty;

constructor(readonly owner: O & AnyEntity<O>, items?: T[]) {
constructor(readonly owner: O & AnyEntity, items?: T[]) {
/* istanbul ignore next */
if (items) {
let i = 0;
Expand Down Expand Up @@ -64,9 +64,9 @@ export class ArrayCollection<T, O> {
}) as unknown as U[];
}

add(...items: (T | Reference<T>)[]): void {
add(...items: (T | Reference<T & AnyEntity>)[]): void {
for (const item of items) {
const entity = Reference.unwrapReference(item);
const entity = Reference.unwrapReference(item as AnyEntity) as T;

if (!this.contains(entity, false)) {
this.incrementCount(1);
Expand All @@ -77,7 +77,7 @@ export class ArrayCollection<T, O> {
}
}

set(items: (T | Reference<T>)[]): void {
set(items: (T | Reference<T & AnyEntity>)[]): void {
this.remove(...this.items);
this.add(...items);
}
Expand All @@ -101,13 +101,13 @@ export class ArrayCollection<T, O> {
* is not the same as `em.remove()`. If we want to delete the entity by removing it from collection, we need to enable `orphanRemoval: true`,
* which tells the ORM we don't want orphaned entities to exist, so we know those should be removed.
*/
remove(...items: (T | Reference<T>)[]): void {
remove(...items: (T | Reference<T & AnyEntity>)[]): void {
for (const item of items) {
if (!item) {
continue;
}

const entity = Reference.unwrapReference(item);
const entity = Reference.unwrapReference(item as AnyEntity) as T;

if (this.items.delete(entity)) {
this.incrementCount(-1);
Expand Down Expand Up @@ -141,8 +141,8 @@ export class ArrayCollection<T, O> {
Object.assign(this, [...this.items]);
}

contains(item: T | Reference<T>, check?: boolean): boolean {
const entity = Reference.unwrapReference(item);
contains(item: T | Reference<T & AnyEntity>, check?: boolean): boolean {
const entity = Reference.unwrapReference(item as AnyEntity) as T;
return this.items.has(entity);
}

Expand All @@ -152,7 +152,7 @@ export class ArrayCollection<T, O> {

isInitialized(fully = false): boolean {
if (fully) {
return this.initialized && [...this.items].every((item: AnyEntity<T>) => item.__helper!.__initialized);
return this.initialized && [...this.items].every((item: T) => (item as AnyEntity).__helper!.__initialized);
}

return this.initialized;
Expand All @@ -179,7 +179,7 @@ export class ArrayCollection<T, O> {
/**
* @internal
*/
get property(): EntityProperty<T> {
get property(): EntityProperty<T & AnyEntity> {
if (!this._property) {
const meta = this.owner.__meta;

Expand Down
19 changes: 10 additions & 9 deletions packages/core/src/entity/BaseEntity.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,53 @@
import { Reference } from './Reference';
import type { AnyEntity, EntityData, EntityDTO, IWrappedEntity, Loaded } from '../typings';
import type { EntityData, EntityDTO, IWrappedEntity, Loaded } from '../typings';
import type { AssignOptions } from './EntityAssigner';
import { EntityAssigner } from './EntityAssigner';
import { helper } from './wrap';

export abstract class BaseEntity<T, PK extends keyof T, P extends string = never> implements IWrappedEntity<T, PK, P> {

isInitialized(): boolean {
return (this as unknown as AnyEntity<T>).__helper!.__initialized;
return helper(this as unknown as T).__initialized;
}

isTouched(): boolean {
return (this as unknown as AnyEntity<T>).__helper!.__touched;
return helper(this as unknown as T).__touched;
}

populated(populated = true): void {
(this as unknown as AnyEntity<T>).__helper!.populated(populated);
helper(this as unknown as T).populated(populated);
}

toReference() {
return Reference.create(this) as any; // maintain the type from IWrappedEntity
}

toObject(ignoreFields: string[] = []): EntityDTO<T> {
return (this as unknown as AnyEntity<T>).__helper!.toObject(ignoreFields);
return helper(this as unknown as T).toObject(ignoreFields);
}

toJSON(...args: any[]): EntityDTO<T> {
return this.toObject(...args);
}

toPOJO(): EntityDTO<T> {
return (this as unknown as AnyEntity<T>).__helper!.toPOJO();
return helper(this as unknown as T).toPOJO();
}

assign(data: EntityData<T>, options?: AssignOptions): T {
return EntityAssigner.assign(this as unknown as T, data, options);
}

init<P extends string = never>(populated = true): Promise<Loaded<T, P>> {
return (this as unknown as AnyEntity<T>).__helper!.init<P>(populated);
return helper(this as unknown as T).init<P>(populated);
}

getSchema(): string | undefined {
return (this as unknown as AnyEntity<T>).__helper!.getSchema();
return helper(this as unknown as T).getSchema();
}

setSchema(schema?: string): void {
(this as unknown as AnyEntity<T>).__helper!.setSchema(schema);
helper(this as unknown as T).setSchema(schema);
}

}
Expand Down
Loading

0 comments on commit ddc8201

Please sign in to comment.