Skip to content

Commit

Permalink
fix: allow auto refresh after upsert
Browse files Browse the repository at this point in the history
  • Loading branch information
etienne-bechara committed Apr 23, 2021
1 parent 515f9c4 commit 5269392
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 17 deletions.
2 changes: 2 additions & 0 deletions source/orm/orm.interface/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
export * from './orm.controller.options';
export * from './orm.create.options';
export * from './orm.module.options';
export * from './orm.paginated.response';
export * from './orm.read.options';
export * from './orm.read.params';
export * from './orm.request.validation';
export * from './orm.service.options';
export * from './orm.update.options';
export * from './orm.upsert.options';
export * from './orm.validation.data';
3 changes: 3 additions & 0 deletions source/orm/orm.interface/orm.create.options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface OrmCreateOptions {
disableRefresh?: boolean;
}
3 changes: 3 additions & 0 deletions source/orm/orm.interface/orm.update.options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface OrmUpdateOptions {
disableRefresh?: boolean;
}
6 changes: 4 additions & 2 deletions source/orm/orm.interface/orm.upsert.options.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export interface OrmUpsertOptions {
import { OrmUpdateOptions } from './orm.update.options';

export interface OrmUpsertOptions extends OrmUpdateOptions{
uniqueKey?: string[];
allowUpdate?: boolean;
disallowRetry?: boolean;
disableRetry?: boolean;
}
63 changes: 48 additions & 15 deletions source/orm/orm.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { BadRequestException, ConflictException, InternalServerErrorException, N
import { EntityData, EntityRepository, FilterQuery } from '@mikro-orm/core';

import { OrmQueryOrder } from './orm.enum';
import { OrmPaginatedResponse, OrmReadOptions, OrmReadParams, OrmServiceOptions, OrmUpsertOptions } from './orm.interface';
import { OrmCreateOptions, OrmPaginatedResponse, OrmReadOptions, OrmReadParams, OrmServiceOptions, OrmUpdateOptions, OrmUpsertOptions } from './orm.interface';

/**
* Creates an abstract service tied with a repository.
Expand All @@ -16,6 +16,30 @@ export abstract class OrmService<Entity> {
protected readonly serviceOptions: OrmServiceOptions<Entity> = { },
) { }

/**
* Update target entities according to configuration.
* @param entities
* @param options
*/
public async refresh(entities: Entity[], options: OrmReadOptions<Entity> = { }): Promise<Entity[]> {
const entityIds = entities.map((e) => e['id']);
const orderedEntities: Entity[] = [ ];

const refreshedEntities = await this.read(entityIds, options);

for (const id of entityIds) {
for (const [ index, entity ] of refreshedEntities.entries()) {
if (entity['id'] === id) {
orderedEntities.push(entity);
refreshedEntities.splice(index, 1);
continue;
}
}
}

return orderedEntities;
}

/**
* Read entities matching given criteria, allowing pagination
* and population options.
Expand Down Expand Up @@ -146,8 +170,9 @@ export abstract class OrmService<Entity> {
/**
* Create multiple entities based on provided data.
* @param data
* @param options
*/
public async create(data: EntityData<Entity>): Promise<Entity[]> {
public async create(data: EntityData<Entity>, options: OrmCreateOptions = { }): Promise<Entity[]> {
if (Array.isArray(data) && data.length > 0 && this.serviceOptions.disableBatchCreate) {
throw new NotImplementedException('creating multiple entities is disabled');
}
Expand All @@ -162,15 +187,18 @@ export abstract class OrmService<Entity> {
this.queryExceptionHandler(e, newEntities);
}

return newEntities;
return options.disableRefresh
? newEntities
: this.refresh(newEntities);
}

/**
* Create a single entity based on provided data.
* @param data
* @param options
*/
public async createOne(data: EntityData<Entity>): Promise<Entity> {
const [ createdEntity ] = await this.create(data);
public async createOne(data: EntityData<Entity>, options: OrmCreateOptions = { }): Promise<Entity> {
const [ createdEntity ] = await this.create(data, options);
return createdEntity;
}

Expand All @@ -179,8 +207,9 @@ export abstract class OrmService<Entity> {
* In cane of multiple, target amount must match data amount.
* @param entities
* @param data
* @param options
*/
public async update(entities: Entity | Entity[], data: EntityData<Entity>): Promise<Entity[]> {
public async update(entities: Entity | Entity[], data: EntityData<Entity>, options: OrmUpdateOptions = { }): Promise<Entity[]> {
if (Array.isArray(entities) && entities.length > 0 && this.serviceOptions.disableBatchUpdate) {
throw new NotImplementedException('updating multiple entities is disabled');
}
Expand Down Expand Up @@ -216,27 +245,31 @@ export abstract class OrmService<Entity> {
this.queryExceptionHandler(e, entities);
}

return updatedEntities;
return options.disableRefresh
? updatedEntities
: this.refresh(updatedEntities);
}

/**
* Update a singles entity by its ID.
* @param id
* @param data
* @param options
*/
public async updateById(id: string, data: EntityData<Entity>): Promise<Entity> {
public async updateById(id: string, data: EntityData<Entity>, options: OrmUpdateOptions = { }): Promise<Entity> {
const target = await this.readById(id);
const updatedEntity = await this.update(target, data);
const updatedEntity = await this.update(target, data, options);
return updatedEntity[0];
}

/**
* Updates a single entity based on provided data.
* @param entity
* @param data
* @param options
*/
public async updateOne(entity: Entity, data: EntityData<Entity>): Promise<Entity> {
const [ updatedEntity ] = await this.update(entity, data);
public async updateOne(entity: Entity, data: EntityData<Entity>, options: OrmUpdateOptions = { }): Promise<Entity> {
const [ updatedEntity ] = await this.update(entity, data, options);
return updatedEntity;
}

Expand Down Expand Up @@ -297,15 +330,15 @@ export abstract class OrmService<Entity> {
let createdEntities: Entity[];

try {
createdEntities = await this.create(createData);
createdEntities = await this.create(createData, options);
}
catch (e) {
if (options.disallowRetry) throw e;
options.disallowRetry = true;
if (options.disableRetry) throw e;
options.disableRetry = true;
return this.readCreateOrUpdate(data, options);
}

const updatedEntities = await this.update(updateTargets, updateData);
const updatedEntities = await this.update(updateTargets, updateData, options);

const resultEntities = resultMap.map((i) => {
switch (i.target) {
Expand Down

0 comments on commit 5269392

Please sign in to comment.