From 6d262539ca212a11cc1f674cbaa13d650e5d31a9 Mon Sep 17 00:00:00 2001 From: Aleksandar Stanisic Date: Sat, 24 Oct 2020 21:34:00 +0200 Subject: [PATCH 1/4] Add generics for ItemsService --- api/src/services/items.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/api/src/services/items.ts b/api/src/services/items.ts index cb28ca0607..344692bb2e 100644 --- a/api/src/services/items.ts +++ b/api/src/services/items.ts @@ -6,7 +6,7 @@ import { Action, Accountability, PermissionsAction, - Item, + Item as AnyItem, Query, PrimaryKey, AbstractService, @@ -26,7 +26,7 @@ import getDefaultValue from '../utils/get-default-value'; import { InvalidPayloadException } from '../exceptions'; import { ForbiddenException } from '../exceptions'; -export class ItemsService implements AbstractService { +export class ItemsService implements AbstractService { collection: string; knex: Knex; accountability: Accountability | null; @@ -52,7 +52,7 @@ export class ItemsService implements AbstractService { const primaryKeyField = await this.schemaInspector.primary(this.collection); const columns = await this.schemaInspector.columns(this.collection); - let payloads = clone(toArray(data)); + let payloads: AnyItem[] = clone(toArray(data)); const savedPrimaryKeys = await this.knex.transaction(async (trx) => { const payloadService = new PayloadService(this.collection, { @@ -210,7 +210,7 @@ export class ItemsService implements AbstractService { } const records = await runAST(ast, { knex: this.knex }); - return records; + return records as Item | Item[] | null; } readByKey( @@ -260,7 +260,7 @@ export class ItemsService implements AbstractService { if (result === null) throw new ForbiddenException(); - return result; + return result as Item | Item[] | null; } update(data: Partial, keys: PrimaryKey[]): Promise; @@ -277,7 +277,7 @@ export class ItemsService implements AbstractService { if (data && key) { const keys = toArray(key); - let payload = clone(data); + let payload: Partial | Partial[] = clone(data); const customProcessed = await emitter.emitAsync( `${this.eventScope}.update.before`, From 498233c09a4434fc88f40360adf074c1de47e652 Mon Sep 17 00:00:00 2001 From: Aleksandar Stanisic Date: Mon, 26 Oct 2020 18:38:33 +0100 Subject: [PATCH 2/4] Add generics per method --- api/src/services/items.ts | 53 +++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/api/src/services/items.ts b/api/src/services/items.ts index 344692bb2e..1791badc47 100644 --- a/api/src/services/items.ts +++ b/api/src/services/items.ts @@ -46,9 +46,11 @@ export class ItemsService implements AbstractService { return this; } - async create(data: Partial[]): Promise; - async create(data: Partial): Promise; - async create(data: Partial | Partial[]): Promise { + async create>(data: T[]): Promise; + async create>(data: T): Promise; + async create>( + data: T | T[] + ): Promise { const primaryKeyField = await this.schemaInspector.primary(this.collection); const columns = await this.schemaInspector.columns(this.collection); @@ -194,7 +196,7 @@ export class ItemsService implements AbstractService { return Array.isArray(data) ? savedPrimaryKeys : savedPrimaryKeys[0]; } - async readByQuery(query: Query): Promise { + async readByQuery(query: Query): Promise { const authorizationService = new AuthorizationService({ accountability: this.accountability, knex: this.knex, @@ -210,20 +212,24 @@ export class ItemsService implements AbstractService { } const records = await runAST(ast, { knex: this.knex }); - return records as Item | Item[] | null; + return records as T | T[] | null; } - readByKey( + readByKey( keys: PrimaryKey[], query?: Query, action?: PermissionsAction - ): Promise; - readByKey(key: PrimaryKey, query?: Query, action?: PermissionsAction): Promise; - async readByKey( + ): Promise; + readByKey( + key: PrimaryKey, + query?: Query, + action?: PermissionsAction + ): Promise; + async readByKey( key: PrimaryKey | PrimaryKey[], query: Query = {}, action: PermissionsAction = 'read' - ): Promise { + ): Promise { query = clone(query); const primaryKeyField = await this.schemaInspector.primary(this.collection); const keys = toArray(key); @@ -260,14 +266,14 @@ export class ItemsService implements AbstractService { if (result === null) throw new ForbiddenException(); - return result as Item | Item[] | null; + return result as T | T[] | null; } - update(data: Partial, keys: PrimaryKey[]): Promise; - update(data: Partial, key: PrimaryKey): Promise; - update(data: Partial[]): Promise; - async update( - data: Partial | Partial[], + update>(data: T, keys: PrimaryKey[]): Promise; + update>(data: T, key: PrimaryKey): Promise; + update>(data: T[]): Promise; + async update>( + data: T | T[], key?: PrimaryKey | PrimaryKey[] ): Promise { const primaryKeyField = await this.schemaInspector.primary(this.collection); @@ -428,7 +434,10 @@ export class ItemsService implements AbstractService { return keys; } - async updateByQuery(data: Partial, query: Query): Promise { + async updateByQuery>( + data: T, + query: Query + ): Promise { const primaryKeyField = await this.schemaInspector.primary(this.collection); const readQuery = cloneDeep(query); readQuery.fields = [primaryKeyField]; @@ -446,9 +455,11 @@ export class ItemsService implements AbstractService { return await this.update(data, keys); } - upsert(data: Partial[]): Promise; - upsert(data: Partial): Promise; - async upsert(data: Partial | Partial[]): Promise { + upsert>(data: T[]): Promise; + upsert>(data: T): Promise; + async upsert>( + data: T | T[] + ): Promise { const primaryKeyField = await this.schemaInspector.primary(this.collection); const payloads = toArray(data); const primaryKeys: PrimaryKey[] = []; @@ -570,7 +581,7 @@ export class ItemsService implements AbstractService { return record; } - async upsertSingleton(data: Partial) { + async upsertSingleton>(data: T) { const primaryKeyField = await this.schemaInspector.primary(this.collection); const record = await this.knex From 9130c1b0b8188f321047bd4564a71ad17db2128c Mon Sep 17 00:00:00 2001 From: Aleksandar Stanisic Date: Mon, 26 Oct 2020 18:52:52 +0100 Subject: [PATCH 3/4] Add types to readSingleton --- api/src/services/items.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/services/items.ts b/api/src/services/items.ts index 1791badc47..c7cf21d9c2 100644 --- a/api/src/services/items.ts +++ b/api/src/services/items.ts @@ -561,11 +561,11 @@ export class ItemsService implements AbstractService { return await this.delete(keys); } - async readSingleton(query: Query) { + async readSingleton(query: Query): Promise { query = clone(query); query.single = true; - const record = (await this.readByQuery(query)) as Item; + const record = (await this.readByQuery(query)) as T; if (!record) { const columns = await this.schemaInspector.columnInfo(this.collection); @@ -575,7 +575,7 @@ export class ItemsService implements AbstractService { defaults[column.name] = getDefaultValue(column); } - return defaults; + return defaults as T; } return record; From c30a5fcb0cc387bf3987fc5371327b9bd15c590c Mon Sep 17 00:00:00 2001 From: Aleksandar Stanisic Date: Mon, 26 Oct 2020 21:32:04 +0100 Subject: [PATCH 4/4] Simplify generics --- api/src/services/items.ts | 59 +++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/api/src/services/items.ts b/api/src/services/items.ts index c7cf21d9c2..0f94f8d1e6 100644 --- a/api/src/services/items.ts +++ b/api/src/services/items.ts @@ -26,7 +26,7 @@ import getDefaultValue from '../utils/get-default-value'; import { InvalidPayloadException } from '../exceptions'; import { ForbiddenException } from '../exceptions'; -export class ItemsService implements AbstractService { +export class ItemsService implements AbstractService { collection: string; knex: Knex; accountability: Accountability | null; @@ -46,11 +46,9 @@ export class ItemsService implements AbstractService { return this; } - async create>(data: T[]): Promise; - async create>(data: T): Promise; - async create>( - data: T | T[] - ): Promise { + async create(data: Partial[]): Promise; + async create(data: Partial): Promise; + async create(data: Partial | Partial[]): Promise { const primaryKeyField = await this.schemaInspector.primary(this.collection); const columns = await this.schemaInspector.columns(this.collection); @@ -196,7 +194,7 @@ export class ItemsService implements AbstractService { return Array.isArray(data) ? savedPrimaryKeys : savedPrimaryKeys[0]; } - async readByQuery(query: Query): Promise { + async readByQuery(query: Query): Promise | Partial[]> { const authorizationService = new AuthorizationService({ accountability: this.accountability, knex: this.knex, @@ -212,24 +210,24 @@ export class ItemsService implements AbstractService { } const records = await runAST(ast, { knex: this.knex }); - return records as T | T[] | null; + return records as Partial | Partial[] | null; } - readByKey( + readByKey( keys: PrimaryKey[], query?: Query, action?: PermissionsAction - ): Promise; - readByKey( + ): Promise[]>; + readByKey( key: PrimaryKey, query?: Query, action?: PermissionsAction - ): Promise; - async readByKey( + ): Promise>; + async readByKey( key: PrimaryKey | PrimaryKey[], query: Query = {}, action: PermissionsAction = 'read' - ): Promise { + ): Promise | Partial[]> { query = clone(query); const primaryKeyField = await this.schemaInspector.primary(this.collection); const keys = toArray(key); @@ -266,14 +264,14 @@ export class ItemsService implements AbstractService { if (result === null) throw new ForbiddenException(); - return result as T | T[] | null; + return result as Partial | Partial[] | null; } - update>(data: T, keys: PrimaryKey[]): Promise; - update>(data: T, key: PrimaryKey): Promise; - update>(data: T[]): Promise; - async update>( - data: T | T[], + update(data: Partial, keys: PrimaryKey[]): Promise; + update(data: Partial, key: PrimaryKey): Promise; + update(data: Partial[]): Promise; + async update( + data: Partial | Partial[], key?: PrimaryKey | PrimaryKey[] ): Promise { const primaryKeyField = await this.schemaInspector.primary(this.collection); @@ -434,10 +432,7 @@ export class ItemsService implements AbstractService { return keys; } - async updateByQuery>( - data: T, - query: Query - ): Promise { + async updateByQuery(data: Partial, query: Query): Promise { const primaryKeyField = await this.schemaInspector.primary(this.collection); const readQuery = cloneDeep(query); readQuery.fields = [primaryKeyField]; @@ -455,11 +450,9 @@ export class ItemsService implements AbstractService { return await this.update(data, keys); } - upsert>(data: T[]): Promise; - upsert>(data: T): Promise; - async upsert>( - data: T | T[] - ): Promise { + upsert(data: Partial[]): Promise; + upsert(data: Partial): Promise; + async upsert(data: Partial | Partial[]): Promise { const primaryKeyField = await this.schemaInspector.primary(this.collection); const payloads = toArray(data); const primaryKeys: PrimaryKey[] = []; @@ -561,11 +554,11 @@ export class ItemsService implements AbstractService { return await this.delete(keys); } - async readSingleton(query: Query): Promise { + async readSingleton(query: Query): Promise> { query = clone(query); query.single = true; - const record = (await this.readByQuery(query)) as T; + const record = (await this.readByQuery(query)) as Partial; if (!record) { const columns = await this.schemaInspector.columnInfo(this.collection); @@ -575,13 +568,13 @@ export class ItemsService implements AbstractService { defaults[column.name] = getDefaultValue(column); } - return defaults as T; + return defaults as Partial; } return record; } - async upsertSingleton>(data: T) { + async upsertSingleton(data: Partial) { const primaryKeyField = await this.schemaInspector.primary(this.collection); const record = await this.knex