Skip to content

Commit 4d8010a

Browse files
authored
Merge pull request #467 from instantcommerce/feat/v2
v2
2 parents da2c966 + 653a4c9 commit 4d8010a

14 files changed

+177
-55
lines changed

lib/createHandler.spec.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import 'reflect-metadata';
33
import express from 'express';
44
import request from 'supertest';
55
import { createHandler } from './createHandler';
6-
import { HttpVerb, HTTP_METHOD_TOKEN } from './decorators';
6+
import { HttpMethod, HTTP_METHOD_TOKEN } from './decorators';
77

88
describe('createHandler', () => {
99
it('Should return not found response when "req.url" is undefined', () => {
@@ -22,7 +22,11 @@ describe('createHandler', () => {
2222

2323
it('Should return not found when method is not found.', done => {
2424
class TestHandler {}
25-
Reflect.defineMetadata(HTTP_METHOD_TOKEN, [{ path: '/', verb: HttpVerb.GET, propertyKey: 'index' }], TestHandler);
25+
Reflect.defineMetadata(
26+
HTTP_METHOD_TOKEN,
27+
[{ path: '/', method: HttpMethod.GET, propertyKey: 'index' }],
28+
TestHandler
29+
);
2630

2731
const server = express();
2832
server.use(express.json());

lib/decorators/catch.decorator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { ClassConstructor } from 'class-transformer';
22
import type { NextApiRequest, NextApiResponse } from 'next';
33

4-
export const CATCH_TOKEN = Symbol('ams:next:catch');
4+
export const CATCH_TOKEN = Symbol('instant:next:catch');
55

66
type ExceptionHandlerFunction<T> = (error: T, req: NextApiRequest, res: NextApiResponse) => void | Promise<void>;
77

lib/decorators/download.decorator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export const HTTP_DOWNLOAD_TOKEN = Symbol('ams:next:download');
1+
export const HTTP_DOWNLOAD_TOKEN = Symbol('instant:next:download');
22

33
/**
44
* Marks the method as a download handler for the client, so the returned file can be downloaded by the browser.

lib/decorators/httpCode.decorator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export const HTTP_CODE_TOKEN = Symbol('ams:next:httpCode');
1+
export const HTTP_CODE_TOKEN = Symbol('instant:next:httpCode');
22

33
/**
44
* Defines the HTTP response code of the route.

lib/decorators/httpMethod.decorators.spec.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable @typescript-eslint/no-empty-function */
22
import 'reflect-metadata';
33
import * as lp from '../internals/loadPackage';
4-
import { Get, Post, Put, Delete, HttpVerb, HTTP_METHOD_TOKEN, Patch } from './httpMethod.decorators';
4+
import { Get, Post, Put, Delete, HttpMethod, HTTP_METHOD_TOKEN, Patch } from './httpMethod.decorators';
55

66
class Test {
77
@Get()
@@ -49,30 +49,34 @@ describe('HttpMethod decorator', () => {
4949
process.env = ENV;
5050
});
5151

52-
it('Should create all the verbs.', () => {
52+
it('Should create all the methods.', () => {
5353
const meta = Reflect.getMetadata(HTTP_METHOD_TOKEN, Test);
5454
expect(meta).toBeInstanceOf(Array);
5555
expect(meta).toMatchObject(
5656
expect.arrayContaining([
57-
{ path: '/', verb: HttpVerb.GET, propertyKey: 'get' },
58-
{ path: '/', verb: HttpVerb.POST, propertyKey: 'post' },
59-
{ path: '/', verb: HttpVerb.PUT, propertyKey: 'put' },
60-
{ path: '/', verb: HttpVerb.DELETE, propertyKey: 'delete' },
61-
{ path: '/', verb: HttpVerb.PATCH, propertyKey: 'patch' }
57+
{ path: '/', method: HttpMethod.GET, propertyKey: 'get' },
58+
{ path: '/', method: HttpMethod.POST, propertyKey: 'post' },
59+
{ path: '/', method: HttpMethod.PUT, propertyKey: 'put' },
60+
{ path: '/', method: HttpMethod.DELETE, propertyKey: 'delete' },
61+
{ path: '/', method: HttpMethod.PATCH, propertyKey: 'patch' }
6262
])
6363
);
6464
});
6565

66-
it('Should create the GET verb with paths', () => {
66+
it('Should create the GET method with paths', () => {
6767
const meta = Reflect.getMetadata(HTTP_METHOD_TOKEN, TestPath);
6868
expect(meta).toBeInstanceOf(Array);
6969
expect(meta).toMatchObject(
7070
expect.arrayContaining([
71-
{ path: '/', verb: HttpVerb.GET, propertyKey: 'index' },
72-
{ path: '/explore', verb: HttpVerb.GET, propertyKey: 'explore' },
73-
{ path: '/explore/:id', verb: HttpVerb.GET, propertyKey: 'exploreDetails' },
74-
{ path: '/explore/:id/comments', verb: HttpVerb.GET, propertyKey: 'exploreDetailsComments' },
75-
{ path: '/explore/:id/comments/:commentId', verb: HttpVerb.GET, propertyKey: 'exploreDetailsCommentDetails' }
71+
{ path: '/', method: HttpMethod.GET, propertyKey: 'index' },
72+
{ path: '/explore', method: HttpMethod.GET, propertyKey: 'explore' },
73+
{ path: '/explore/:id', method: HttpMethod.GET, propertyKey: 'exploreDetails' },
74+
{ path: '/explore/:id/comments', method: HttpMethod.GET, propertyKey: 'exploreDetailsComments' },
75+
{
76+
path: '/explore/:id/comments/:commentId',
77+
method: HttpMethod.GET,
78+
propertyKey: 'exploreDetailsCommentDetails'
79+
}
7680
])
7781
);
7882
});

lib/decorators/httpMethod.decorators.ts

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,61 @@
11
import { applyHandler } from '../internals/handler';
22
import { loadPackage } from '../internals/loadPackage';
33

4-
export enum HttpVerb {
4+
export enum HttpMethod {
55
GET = 'GET',
66
POST = 'POST',
77
PUT = 'PUT',
88
DELETE = 'DELETE',
9-
PATCH = 'PATCH'
9+
PATCH = 'PATCH',
10+
OPTIONS = 'OPTIONS',
11+
HEAD = 'HEAD',
12+
CONNECT = 'CONNECT',
13+
TRACE = 'TRACE'
1014
}
1115

1216
export interface HandlerMethod {
13-
verb: HttpVerb;
17+
method: HttpMethod;
18+
options?: HandlerOptions;
1419
path: string;
1520
propertyKey: string | symbol;
1621
}
1722

18-
export const HTTP_METHOD_TOKEN = Symbol('ams:next:httpMethod');
23+
interface HandlerOptions {
24+
extraMethods?: HttpMethod[];
25+
}
26+
27+
export const HTTP_METHOD_TOKEN = Symbol('instant:next:httpMethod');
1928

20-
function applyHttpMethod(verb: HttpVerb, path: string) {
29+
function applyHttpMethod({ method, path, options }: { method: HttpMethod; path: string; options?: HandlerOptions }) {
2130
if (process.env.NODE_ENV === 'development' && path !== '/') {
2231
loadPackage('path-to-regexp', {
23-
context: '@' + verb.charAt(0).toUpperCase() + verb.slice(1).toLowerCase(),
32+
context: '@' + method.charAt(0).toUpperCase() + method.slice(1).toLowerCase(),
2433
docsUrl: 'https://next-api-decorators.vercel.app/docs/routing/route-matching'
2534
});
2635
}
2736

2837
return function (target: object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<any>) {
2938
const methods: Array<HandlerMethod> = Reflect.getMetadata(HTTP_METHOD_TOKEN, target.constructor) ?? [];
3039

31-
methods.push({ path, verb, propertyKey });
40+
methods.push({ path, method, options, propertyKey });
3241

3342
Reflect.defineMetadata(HTTP_METHOD_TOKEN, methods, target.constructor);
3443

3544
return applyHandler(target, propertyKey, descriptor);
3645
};
3746
}
3847

48+
function getPath(pathOrOptions?: string | HandlerOptions) {
49+
return typeof pathOrOptions === 'string' ? pathOrOptions : '/';
50+
}
51+
52+
function getOptions(pathOrOptions?: string | HandlerOptions, options?: HandlerOptions) {
53+
return typeof pathOrOptions === 'object' ? pathOrOptions : options;
54+
}
55+
3956
/** Makes the method a GET request handler. */
4057
export function Get(): MethodDecorator;
58+
export function Get(options: HandlerOptions): MethodDecorator;
4159
/**
4260
* Makes the method for the defined path a GET request handler.
4361
*
@@ -49,12 +67,18 @@ export function Get(): MethodDecorator;
4967
* More information: [route matching](https://next-api-decorators.vercel.app/docs/routing/route-matching)
5068
*/
5169
export function Get(path: string): MethodDecorator;
52-
export function Get(path: string = '/'): MethodDecorator {
53-
return applyHttpMethod(HttpVerb.GET, path);
70+
export function Get(path: string, options: HandlerOptions): MethodDecorator;
71+
export function Get(pathOrOptions?: string | HandlerOptions, options?: HandlerOptions): MethodDecorator {
72+
return applyHttpMethod({
73+
method: HttpMethod.GET,
74+
path: getPath(pathOrOptions),
75+
options: getOptions(pathOrOptions, options)
76+
});
5477
}
5578

5679
/** Makes the method a POST request handler. */
5780
export function Post(): MethodDecorator;
81+
export function Post(options: HandlerOptions): MethodDecorator;
5882
/**
5983
* Makes the method for the defined path a POST request handler.
6084
*
@@ -66,12 +90,18 @@ export function Post(): MethodDecorator;
6690
* More information: [route matching](https://next-api-decorators.vercel.app/docs/routing/route-matching)
6791
*/
6892
export function Post(path: string): MethodDecorator;
69-
export function Post(path: string = '/'): MethodDecorator {
70-
return applyHttpMethod(HttpVerb.POST, path);
93+
export function Post(path: string, options: HandlerOptions): MethodDecorator;
94+
export function Post(pathOrOptions?: string | HandlerOptions, options?: HandlerOptions): MethodDecorator {
95+
return applyHttpMethod({
96+
method: HttpMethod.POST,
97+
path: getPath(pathOrOptions),
98+
options: getOptions(pathOrOptions, options)
99+
});
71100
}
72101

73102
/** Makes the method a PUT request handler. */
74103
export function Put(): MethodDecorator;
104+
export function Put(options: HandlerOptions): MethodDecorator;
75105
/**
76106
* Makes the method for the defined path a PUT request handler.
77107
*
@@ -83,12 +113,18 @@ export function Put(): MethodDecorator;
83113
* More information: [route matching](https://next-api-decorators.vercel.app/docs/routing/route-matching)
84114
*/
85115
export function Put(path: string): MethodDecorator;
86-
export function Put(path: string = '/'): MethodDecorator {
87-
return applyHttpMethod(HttpVerb.PUT, path);
116+
export function Put(path: string, options: HandlerOptions): MethodDecorator;
117+
export function Put(pathOrOptions?: string | HandlerOptions, options?: HandlerOptions): MethodDecorator {
118+
return applyHttpMethod({
119+
method: HttpMethod.PUT,
120+
path: getPath(pathOrOptions),
121+
options: getOptions(pathOrOptions, options)
122+
});
88123
}
89124

90125
/** Makes the method a DELETE request handler. */
91126
export function Delete(): MethodDecorator;
127+
export function Delete(options: HandlerOptions): MethodDecorator;
92128
/**
93129
* Makes the method for the defined path a DELETE request handler.
94130
*
@@ -100,12 +136,18 @@ export function Delete(): MethodDecorator;
100136
* More information: [route matching](https://next-api-decorators.vercel.app/docs/routing/route-matching)
101137
*/
102138
export function Delete(path: string): MethodDecorator;
103-
export function Delete(path: string = '/'): MethodDecorator {
104-
return applyHttpMethod(HttpVerb.DELETE, path);
139+
export function Delete(path: string, options: HandlerOptions): MethodDecorator;
140+
export function Delete(pathOrOptions?: string | HandlerOptions, options?: HandlerOptions): MethodDecorator {
141+
return applyHttpMethod({
142+
method: HttpMethod.DELETE,
143+
path: getPath(pathOrOptions),
144+
options: getOptions(pathOrOptions, options)
145+
});
105146
}
106147

107148
/** Makes the method a PATCH request handler. */
108149
export function Patch(): MethodDecorator;
150+
export function Patch(options: HandlerOptions): MethodDecorator;
109151
/**
110152
* Makes the method for the defined path a PATCH request handler.
111153
*
@@ -117,6 +159,11 @@ export function Patch(): MethodDecorator;
117159
* More information: [route matching](https://next-api-decorators.vercel.app/docs/routing/route-matching)
118160
*/
119161
export function Patch(path: string): MethodDecorator;
120-
export function Patch(path: string = '/'): MethodDecorator {
121-
return applyHttpMethod(HttpVerb.PATCH, path);
162+
export function Patch(path: string, options: HandlerOptions): MethodDecorator;
163+
export function Patch(pathOrOptions?: string | HandlerOptions, options?: HandlerOptions): MethodDecorator {
164+
return applyHttpMethod({
165+
method: HttpMethod.PATCH,
166+
path: getPath(pathOrOptions),
167+
options: getOptions(pathOrOptions, options)
168+
});
122169
}

lib/decorators/middleware.decorators.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { RequestHandler } from 'express';
22
import type { NextApiRequest, NextApiResponse } from 'next';
33

4-
export const MIDDLEWARE_TOKEN = Symbol('ams:next:middlewares');
4+
export const MIDDLEWARE_TOKEN = Symbol('instant:next:middlewares');
55

66
export type NextFunction = (err?: Error) => void;
77
export type NextMiddleware = (req: NextApiRequest, res: NextApiResponse, next: NextFunction) => void | Promise<void>;

lib/decorators/parameter.decorators.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export interface MetaParameter {
1111
fn?: ParamDecorator<any>;
1212
}
1313

14-
export const PARAMETER_TOKEN = Symbol('ams:next:parameters');
14+
export const PARAMETER_TOKEN = Symbol('instant:next:parameters');
1515

1616
function addParameter(
1717
location: MetaParameter['location'],

lib/decorators/setHeader.decorator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export const HEADER_TOKEN = Symbol('ams:next:header');
1+
export const HEADER_TOKEN = Symbol('instant:next:header');
22

33
/**
44
* Sets a header parameter into the response header.

lib/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export {
88
Get,
99
Header,
1010
HttpCode,
11-
HttpVerb,
11+
HttpMethod,
1212
Post,
1313
Put,
1414
Query,

0 commit comments

Comments
 (0)