Skip to content

Commit c1cafc2

Browse files
committed
fix(json-api-nestjs-microorm): add format for mikroorm error
1 parent 0ace3ce commit c1cafc2

File tree

3 files changed

+125
-1
lines changed

3 files changed

+125
-1
lines changed

libs/json-api/json-api-nestjs-microorm/src/lib/micro-orm-json-api.module.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
PrepareParams,
55
MODULE_OPTIONS_TOKEN,
66
NestProvider,
7+
ErrorFormatService,
78
} from '@klerick/json-api-nestjs';
89
import { MicroOrmParam } from './type';
910

@@ -18,7 +19,7 @@ import {
1819
CheckRelationNameFactory,
1920
FindOneRowEntityFactory,
2021
} from './factory';
21-
import { MicroOrmUtilService } from './service/micro-orm-util.service';
22+
import { MicroOrmUtilService, MikroOrmFormatErrorService } from './service';
2223

2324
export class MicroOrmJsonApiModule {
2425
static forRoot(options: PrepareParams<MicroOrmParam>): DynamicModule {
@@ -40,6 +41,10 @@ export class MicroOrmJsonApiModule {
4041
CurrentEntityMetadata(),
4142
RunInTransactionFactory(),
4243
EntityPropsMap(options.entities),
44+
{
45+
provide: ErrorFormatService,
46+
useClass: MikroOrmFormatErrorService,
47+
},
4348
];
4449

4550
const currentImport = [
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
export * from './microorm-service';
2+
export * from './mikro-orm-format.error.service';
3+
export * from './micro-orm-util.service';
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import {
2+
ErrorFormatService,
3+
ValidateQueryError,
4+
PrepareParams,
5+
MODULE_OPTIONS_TOKEN,
6+
} from '@klerick/json-api-nestjs';
7+
import {
8+
BadRequestException,
9+
ConflictException,
10+
HttpException,
11+
Inject,
12+
HttpExceptionOptions,
13+
} from '@nestjs/common';
14+
15+
import {
16+
DriverException,
17+
EntityManager,
18+
UniqueConstraintViolationException,
19+
ValidationError,
20+
} from '@mikro-orm/core';
21+
22+
import { CURRENT_ENTITY_MANAGER_TOKEN } from '../constants';
23+
24+
const duplicateItems = (
25+
errorText: string,
26+
options: HttpExceptionOptions,
27+
detail?: string
28+
) => {
29+
errorText = 'Duplicate value';
30+
if (detail) {
31+
const matches = detail.match(/(?<=\().+?(?=\))/gm);
32+
if (matches) {
33+
errorText = `Duplicate value in the "${matches[0]}"`;
34+
}
35+
}
36+
37+
const error: ValidateQueryError = {
38+
code: 'invalid_arguments',
39+
message: errorText,
40+
path: ['data', 'attributes'],
41+
};
42+
43+
return new ConflictException([error], options);
44+
};
45+
46+
export class MikroOrmFormatErrorService extends ErrorFormatService {
47+
@Inject(CURRENT_ENTITY_MANAGER_TOKEN) em!: EntityManager;
48+
@Inject(MODULE_OPTIONS_TOKEN)
49+
private mainConfig!: PrepareParams;
50+
51+
private errorMsg = 'Internal Server Error';
52+
53+
override formatError(error: unknown): HttpException {
54+
try {
55+
if (error instanceof ValidationError) {
56+
return this.formatValidationError(error);
57+
}
58+
if (error instanceof DriverException) {
59+
return this.prepareDataBaseError(error);
60+
}
61+
return super.formatError(error);
62+
} catch (error) {
63+
return super.formatError(error);
64+
}
65+
}
66+
67+
private formatValidationError(error: ValidationError) {
68+
const { message } = error;
69+
70+
const entity = error.getEntity();
71+
const errorObject: ValidateQueryError = {
72+
code: 'invalid_arguments',
73+
message: message.split('\n').at(0) || message,
74+
path: [],
75+
};
76+
if (entity) {
77+
errorObject['path'] = ['data', 'attributes'];
78+
}
79+
80+
const descriptionOrOptions: HttpExceptionOptions = this.mainConfig.options
81+
.debug
82+
? { cause: error }
83+
: {};
84+
85+
return new BadRequestException([errorObject], descriptionOrOptions);
86+
}
87+
88+
private prepareDataBaseError(error: DriverException) {
89+
if (
90+
!this.em
91+
.getPlatform()
92+
.getConfig()
93+
.getDriver()
94+
.constructor.name.startsWith('Postgre')
95+
) {
96+
return super.formatError(error);
97+
}
98+
99+
const { errorCode, errorMsg, detail, table } = {
100+
errorCode: error.code,
101+
errorMsg: error.message,
102+
detail: Reflect.get(error, 'detail') as string,
103+
table: Reflect.get(error, 'table') as string,
104+
};
105+
const descriptionOrOptions: HttpExceptionOptions = this.mainConfig.options
106+
.debug
107+
? { cause: error }
108+
: {};
109+
110+
switch (error.constructor) {
111+
case UniqueConstraintViolationException:
112+
return duplicateItems(errorMsg, descriptionOrOptions, detail);
113+
default:
114+
return super.formatError(error);
115+
}
116+
}
117+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy