Skip to content

Commit

Permalink
chore: implement jsonapi error object
Browse files Browse the repository at this point in the history
Signed-off-by: Husen <[email protected]>
  • Loading branch information
heyhusen committed Feb 4, 2024
1 parent b9a9cdc commit bd25994
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 127 deletions.
5 changes: 1 addition & 4 deletions backend/node/__tests__/app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,9 @@ describe('GET /404', () => {
jsonapi: {
version: '1.1',
},
links: {
self: '/404',
},
errors: [
{
status: StatusCodes.NOT_FOUND,
status: StatusCodes.NOT_FOUND.toString(),
title: ReasonPhrases.NOT_FOUND,
detail: 'Resource not found.',
},
Expand Down
97 changes: 20 additions & 77 deletions backend/node/__tests__/user.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,9 @@ describe('POST /users', () => {
jsonapi: {
version: '1.1',
},
links: {
self: '/users',
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('data.required'),
},
Expand Down Expand Up @@ -66,12 +63,9 @@ describe('POST /users', () => {
jsonapi: {
version: '1.1',
},
links: {
self: '/users',
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('data.attributes.email.format'),
},
Expand Down Expand Up @@ -101,12 +95,9 @@ describe('POST /users', () => {
jsonapi: {
version: '1.1',
},
links: {
self: '/users',
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('email.unique'),
},
Expand Down Expand Up @@ -188,12 +179,9 @@ describe('GET /users', () => {
jsonapi: {
version: '1.1',
},
links: {
self: '/users',
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('page.required'),
},
Expand All @@ -216,12 +204,9 @@ describe('GET /users', () => {
jsonapi: {
version: '1.1',
},
links: {
self: '/users',
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('page.type'),
},
Expand All @@ -246,12 +231,9 @@ describe('GET /users', () => {
jsonapi: {
version: '1.1',
},
links: {
self: '/users',
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('page.number.required'),
},
Expand All @@ -276,12 +258,9 @@ describe('GET /users', () => {
jsonapi: {
version: '1.1',
},
links: {
self: '/users',
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('page.size.required'),
},
Expand All @@ -307,17 +286,14 @@ describe('GET /users', () => {
jsonapi: {
version: '1.1',
},
links: {
self: '/users',
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('page.number.type'),
},
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('page.size.type'),
},
Expand Down Expand Up @@ -392,12 +368,9 @@ describe('GET /users/{id}', () => {
jsonapi: {
version: '1.1',
},
links: {
self: '/users/invalid-id',
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('id.format'),
},
Expand All @@ -417,12 +390,9 @@ describe('GET /users/{id}', () => {
jsonapi: {
version: '1.1',
},
links: {
self: '/users/60677a98-a65e-4abc-831c-45dd76e8f990',
},
errors: [
{
status: StatusCodes.NOT_FOUND,
status: StatusCodes.NOT_FOUND.toString(),
title: ReasonPhrases.NOT_FOUND,
detail: getErrorMessage('user.exist'),
},
Expand Down Expand Up @@ -493,12 +463,9 @@ describe('PATCH /users/{id}', () => {
jsonapi: {
version: '1.1',
},
links: {
self: '/users/invalid-id',
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('id.format'),
},
Expand All @@ -523,12 +490,9 @@ describe('PATCH /users/{id}', () => {
jsonapi: {
version: '1.1',
},
links: {
self: '/users/60677a98-a65e-4abc-831c-45dd76e8f990',
},
errors: [
{
status: StatusCodes.NOT_FOUND,
status: StatusCodes.NOT_FOUND.toString(),
title: ReasonPhrases.NOT_FOUND,
detail: getErrorMessage('user.exist'),
},
Expand Down Expand Up @@ -556,12 +520,9 @@ describe('PATCH /users/{id}', () => {
jsonapi: {
version: '1.1',
},
links: {
self: `/users/${user.id}`,
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('data.attributes.first_name.type'),
},
Expand Down Expand Up @@ -589,12 +550,9 @@ describe('PATCH /users/{id}', () => {
jsonapi: {
version: '1.1',
},
links: {
self: `/users/${user.id}`,
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('data.attributes.first_name.minLength'),
},
Expand Down Expand Up @@ -622,12 +580,9 @@ describe('PATCH /users/{id}', () => {
jsonapi: {
version: '1.1',
},
links: {
self: `/users/${user.id}`,
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('data.attributes.first_name.type'),
},
Expand Down Expand Up @@ -771,12 +726,9 @@ describe('PATCH /users/{id}', () => {
jsonapi: {
version: '1.1',
},
links: {
self: `/users/${user.id}`,
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('data.attributes.email.type'),
},
Expand Down Expand Up @@ -804,12 +756,9 @@ describe('PATCH /users/{id}', () => {
jsonapi: {
version: '1.1',
},
links: {
self: `/users/${user.id}`,
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('data.attributes.email.format'),
},
Expand Down Expand Up @@ -837,12 +786,9 @@ describe('PATCH /users/{id}', () => {
jsonapi: {
version: '1.1',
},
links: {
self: `/users/${user.id}`,
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('data.attributes.email.type'),
},
Expand Down Expand Up @@ -870,12 +816,9 @@ describe('PATCH /users/{id}', () => {
jsonapi: {
version: '1.1',
},
links: {
self: `/users/${user.id}`,
},
errors: [
{
status: StatusCodes.BAD_REQUEST,
status: StatusCodes.BAD_REQUEST.toString(),
title: ReasonPhrases.BAD_REQUEST,
detail: getErrorMessage('data.attributes.email.format'),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ describe('uniqueUserEmailController', () => {
});

test('should throw error when email is not unique', async () => {
request = { ...request, body: dto };
request = {
...request,
body: dto,
};

await expect(controller(request)).rejects.toThrow(
new BadRequestException('The email has already been taken.')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getErrorMessage } from '../../core/entities/validation.entity';
import { BadRequestException } from '../../core/exceptions/bad-request.exception';
import type { RequestIdParams } from '../interfaces/common.interface';
import type { HttpRequestParams } from '../interfaces/http.interface';
Expand All @@ -22,9 +23,7 @@ describe('validateUuidController', () => {

expect(() => {
validateUuidController(request);
}).toThrow(
new BadRequestException('Validation failed (uuid v4 is expected).')
);
}).toThrow(new BadRequestException(getErrorMessage('id.format')));
});

test('should return true when id is valid uuid', () => {
Expand Down
37 changes: 8 additions & 29 deletions backend/node/src/adapters/interfaces/http.interface.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { DataDocument, Dictionary, ErrorDocument, JapiError } from 'ts-japi';
import Resource from 'ts-japi/lib/models/resource.model';
import type { File } from '../../core/entities/common.entity';

export interface HttpRequest<
Expand Down Expand Up @@ -33,38 +35,15 @@ export type HttpRequestCookie<T = Record<string, unknown>> = HttpRequest<
T
>;

export interface JsonApi {
jsonapi: {
version: string;
};
links: {
self: string;
};
}

export interface JsonApiDataObject<Attributes = Record<string, unknown>> {
type: string;
id: string;
attributes: Attributes;
}

export interface JsonApiData<Attributes = Record<string, unknown>>
extends JsonApi {
data: JsonApiDataObject<Attributes>;
}

export interface JsonApiErrorObject {
status: number;
title: string;
detail: string;
source?: {
pointer?: string;
parameter?: string;
export interface JsonApiData<Entity extends Dictionary<any>>

Check warning on line 38 in backend/node/src/adapters/interfaces/http.interface.ts

View workflow job for this annotation

GitHub Actions / Build (Node v20)

Unexpected any. Specify a different type

Check warning on line 38 in backend/node/src/adapters/interfaces/http.interface.ts

View workflow job for this annotation

GitHub Actions / Build (Node v21)

Unexpected any. Specify a different type
extends Omit<DataDocument<Entity>, 'data'> {
data: Omit<Resource<Entity>, 'attributes'> & {
attributes: Entity;
};
}

export interface JsonApiError extends JsonApi {
errors: JsonApiErrorObject[];
export interface JsonApiError extends Omit<ErrorDocument, 'errors'> {
errors: Omit<JapiError, 'stack'>[];
}

export interface JsonApiPagination {
Expand Down
Loading

0 comments on commit bd25994

Please sign in to comment.