diff --git a/package.json b/package.json index 28ee85e5..8d909120 100644 --- a/package.json +++ b/package.json @@ -62,4 +62,4 @@ }, "types": "./lib/index.d.ts", "version": "6.4.3" -} \ No newline at end of file +} diff --git a/src/base_http_controller.ts b/src/base_http_controller.ts index 9f67b72b..468baf6e 100644 --- a/src/base_http_controller.ts +++ b/src/base_http_controller.ts @@ -61,10 +61,10 @@ export class BaseHttpController { return new StatusCodeResult(statusCode); } - protected json( - content: unknown, + protected json>( + content: T | T[], statusCode: number = StatusCodes.OK - ): JsonResult { + ): JsonResult { return new JsonResult(content, statusCode); } } diff --git a/src/content/httpContent.ts b/src/content/httpContent.ts index 70134797..24da91c2 100644 --- a/src/content/httpContent.ts +++ b/src/content/httpContent.ts @@ -7,5 +7,7 @@ export abstract class HttpContent { return this._headers; } - public abstract readAsStringAsync(): Promise; + public abstract readAsync(): Promise< + string | Record | Record[] + >; } diff --git a/src/content/jsonContent.ts b/src/content/jsonContent.ts index 4d5e3691..7376b6fe 100644 --- a/src/content/jsonContent.ts +++ b/src/content/jsonContent.ts @@ -2,18 +2,16 @@ import { HttpContent } from './httpContent'; const DEFAULT_MEDIA_TYPE = 'application/json'; -export class JsonContent extends HttpContent { - private content: string; - - constructor(content: unknown) { +export class JsonContent< + T extends Record +> extends HttpContent { + constructor(private content: T | T[]) { super(); - this.content = JSON.stringify(content); - this.headers['content-type'] = DEFAULT_MEDIA_TYPE; } - public readAsStringAsync(): Promise { + public readAsync(): Promise { return Promise.resolve(this.content); } } diff --git a/src/content/stringContent.ts b/src/content/stringContent.ts index 2b0602af..c724515d 100644 --- a/src/content/stringContent.ts +++ b/src/content/stringContent.ts @@ -9,7 +9,7 @@ export class StringContent extends HttpContent { this.headers['content-type'] = DEFAULT_MEDIA_TYPE; } - public readAsStringAsync(): Promise { + public readAsync(): Promise { return Promise.resolve(this.content); } } diff --git a/src/results/JsonResult.ts b/src/results/JsonResult.ts index 12e11ab5..79639252 100644 --- a/src/results/JsonResult.ts +++ b/src/results/JsonResult.ts @@ -1,16 +1,18 @@ -import { HttpResponseMessage } from '../httpResponseMessage'; import { JsonContent } from '../content/jsonContent'; +import { HttpResponseMessage } from '../httpResponseMessage'; import type { IHttpActionResult } from '../interfaces'; -export class JsonResult implements IHttpActionResult { +export class JsonResult< + T extends Record +> implements IHttpActionResult { constructor( - public readonly json: unknown, + public readonly json: T | T[], public readonly statusCode: number ) { } public async executeAsync(): Promise { const response = new HttpResponseMessage(this.statusCode); - response.content = new JsonContent(this.json); + response.content = new JsonContent(this.json); return Promise.resolve(response); } } diff --git a/src/server.ts b/src/server.ts index a714f1a3..d580e597 100644 --- a/src/server.ts +++ b/src/server.ts @@ -234,7 +234,7 @@ export class InversifyExpressServer { res.status(message.statusCode) // If the content is a number, ensure we change it to a string, else our content is // treated as a statusCode rather than as the content of the Response - .send(await message.content.readAsStringAsync()); + .send(await message.content.readAsync()); } else { res.sendStatus(message.statusCode); } diff --git a/test/action_result.test.ts b/test/action_result.test.ts index 4217bdce..34d5e771 100644 --- a/test/action_result.test.ts +++ b/test/action_result.test.ts @@ -22,7 +22,7 @@ describe('ActionResults', () => { expect(responseMessage.statusCode).toBe(StatusCodes.OK); expect( - await responseMessage.content.readAsStringAsync(), + await responseMessage.content.readAsync(), ).toBe(JSON.stringify(content)); }); }); @@ -43,7 +43,7 @@ describe('ActionResults', () => { const responseMessage = await actionResult.executeAsync(); expect(responseMessage.statusCode).toBe(StatusCodes.BAD_REQUEST); - expect(await responseMessage.content.readAsStringAsync()).toBe(message); + expect(await responseMessage.content.readAsync()).toBe(message); }); }); @@ -68,7 +68,7 @@ describe('ActionResults', () => { expect(responseMessage.statusCode).toBe(StatusCodes.CREATED); expect( - await responseMessage.content.readAsStringAsync(), + await responseMessage.content.readAsync(), ).toBe(JSON.stringify(content)); expect(responseMessage.headers['location']).toBe(uri); }); @@ -85,7 +85,7 @@ describe('ActionResults', () => { .toBe(StatusCodes.INTERNAL_SERVER_ERROR); expect(await responseMessage.content - .readAsStringAsync()) + .readAsync()) .toBe('Error: foo'); }); }); diff --git a/test/content/jsonContent.test.ts b/test/content/jsonContent.test.ts index fabe4818..1c8d64b5 100644 --- a/test/content/jsonContent.test.ts +++ b/test/content/jsonContent.test.ts @@ -6,7 +6,7 @@ describe('JsonContent', () => { expect(content.headers['content-type']).toBe('application/json'); }); - it('should respond with the stringified version of the object', done => { + it('should respond with the original object', done => { const mockObject = { count: 6, success: true, @@ -15,8 +15,8 @@ describe('JsonContent', () => { const content = new JsonContent(mockObject); - void content.readAsStringAsync().then(value => { - expect(value).toBe(JSON.stringify(mockObject)); + void content.readAsync().then(value => { + expect(value).toBe(mockObject); done(); }); });