diff --git a/adonis-typings/response.ts b/adonis-typings/response.ts index 566c4f5..7f06e77 100644 --- a/adonis-typings/response.ts +++ b/adonis-typings/response.ts @@ -101,8 +101,9 @@ declare module '@ioc:Adonis/Core/Response' { plainCookie (key: string, value: any, options?: Partial): this clearCookie (key: string): this - abort (body: any, status?: number): void + abort (body: any, status?: number): never abortIf (conditional: any, body: any, status?: number): void + abortUnless (conditional: any, body: any, status?: number): asserts conditional finish (): void } diff --git a/src/Response/index.ts b/src/Response/index.ts index 972805e..2038752 100644 --- a/src/Response/index.ts +++ b/src/Response/index.ts @@ -819,7 +819,7 @@ export class Response extends Macroable implements ResponseContract { * Abort the request with custom body and a status code. 400 is * used when status is not defined */ - public abort (body: any, status?: number): void { + public abort (body: any, status?: number): never { throw HttpException.invoke(body, status || 400) } @@ -833,6 +833,16 @@ export class Response extends Macroable implements ResponseContract { } } + /** + * Abort the request with custom body and a status code when + * passed condition returns `false` + */ + public abortUnless (condition: any, body: any, status?: number): asserts condition { + if (!condition) { + this.abort(body, status) + } + } + /** * Set signed cookie as the response header. The inline options overrides * all options from the config (means they are not merged). diff --git a/test/response.spec.ts b/test/response.spec.ts index 8488f09..d275a13 100644 --- a/test/response.spec.ts +++ b/test/response.spec.ts @@ -1034,7 +1034,7 @@ test.group('Response', (group) => { assert.deepEqual(body, { message: 'Not allowed' }) }) - test('abort request when condition is truthy', async (assert) => { + test('abortIf: abort request when condition is truthy', async (assert) => { const server = createServer((req, res) => { const config = fakeConfig() const response = new Response(req, res, config) @@ -1051,7 +1051,7 @@ test.group('Response', (group) => { assert.deepEqual(body, { message: 'Not allowed' }) }) - test('do not abort request when condition is falsy', async () => { + test('abortIf: do not abort request when condition is falsy', async () => { const server = createServer((req, res) => { const config = fakeConfig() const response = new Response(req, res, config) @@ -1066,4 +1066,37 @@ test.group('Response', (group) => { await supertest(server).get('/').expect(200) }) + + test('abortUnless: abort request when condition is falsy', async (assert) => { + const server = createServer((req, res) => { + const config = fakeConfig() + const response: Response = new Response(req, res, config) + try { + response.abortUnless(false, { message: 'Not allowed' }, 401) + } catch (error) { + error.handle(error, { response }) + } + + response.finish() + }) + + const { body } = await supertest(server).get('/').expect(401) + assert.deepEqual(body, { message: 'Not allowed' }) + }) + + test('abortUnless: do not abort request when condition is truthy', async () => { + const server = createServer((req, res) => { + const config = fakeConfig() + const response: Response = new Response(req, res, config) + try { + response.abortUnless(true, { message: 'Not allowed' }, 401) + } catch (error) { + error.handle(error, { response }) + } + + response.finish() + }) + + await supertest(server).get('/').expect(200) + }) })