@deepkit/http 1.0.1-alpha.57 → 1.0.1-alpha.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/coverage/clover.xml +1086 -0
- package/coverage/coverage-final.json +12 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +79 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +126 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +170 -0
- package/coverage/lcov-report/src/controllers.ts.html +113 -0
- package/coverage/lcov-report/src/decorator.ts.html +1280 -0
- package/coverage/lcov-report/src/filter.ts.html +734 -0
- package/coverage/lcov-report/src/http.ts.html +2192 -0
- package/coverage/lcov-report/src/index.html +246 -0
- package/coverage/lcov-report/src/kernel.ts.html +260 -0
- package/coverage/lcov-report/src/middleware.ts.html +428 -0
- package/coverage/lcov-report/src/model.ts.html +937 -0
- package/coverage/lcov-report/src/module.config.ts.html +89 -0
- package/coverage/lcov-report/src/module.ts.html +245 -0
- package/coverage/lcov-report/src/router.ts.html +2318 -0
- package/coverage/lcov-report/tests/index.html +111 -0
- package/coverage/lcov-report/tests/utils.ts.html +176 -0
- package/coverage/lcov.info +2225 -0
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/src/controllers.d.ts +4 -4
- package/dist/cjs/src/controllers.js +3 -0
- package/dist/cjs/src/controllers.js.map +1 -1
- package/dist/cjs/src/decorator.d.ts +29 -94
- package/dist/cjs/src/decorator.js +53 -118
- package/dist/cjs/src/decorator.js.map +1 -1
- package/dist/cjs/src/filter.d.ts +1 -0
- package/dist/cjs/src/filter.js +11 -17
- package/dist/cjs/src/filter.js.map +1 -1
- package/dist/cjs/src/http.d.ts +5 -3
- package/dist/cjs/src/http.js +100 -56
- package/dist/cjs/src/http.js.map +1 -1
- package/dist/cjs/src/kernel.d.ts +3 -3
- package/dist/cjs/src/kernel.js +9 -28
- package/dist/cjs/src/kernel.js.map +1 -1
- package/dist/cjs/src/logger.d.ts +2 -2
- package/dist/cjs/src/logger.js +4 -8
- package/dist/cjs/src/logger.js.map +1 -1
- package/dist/cjs/src/middleware.d.ts +5 -1
- package/dist/cjs/src/middleware.js +15 -3
- package/dist/cjs/src/middleware.js.map +1 -1
- package/dist/cjs/src/model.d.ts +67 -0
- package/dist/cjs/src/model.js +95 -24
- package/dist/cjs/src/model.js.map +1 -1
- package/dist/cjs/src/module.config.d.ts +3 -4
- package/dist/cjs/src/module.config.js +8 -6
- package/dist/cjs/src/module.config.js.map +1 -1
- package/dist/cjs/src/module.d.ts +2 -3
- package/dist/cjs/src/module.js +4 -2
- package/dist/cjs/src/module.js.map +1 -1
- package/dist/cjs/src/router.d.ts +25 -54
- package/dist/cjs/src/router.js +162 -186
- package/dist/cjs/src/router.js.map +1 -1
- package/dist/cjs/src/static-serving.d.ts +1 -0
- package/dist/cjs/src/static-serving.js +38 -34
- package/dist/cjs/src/static-serving.js.map +1 -1
- package/dist/cjs/src/utils.js +1 -0
- package/dist/cjs/tests/filter.spec.js +61 -47
- package/dist/cjs/tests/filter.spec.js.map +1 -1
- package/dist/cjs/tests/middleware.spec.d.ts +1 -1
- package/dist/cjs/tests/middleware.spec.js +157 -145
- package/dist/cjs/tests/middleware.spec.js.map +1 -1
- package/dist/cjs/tests/model.spec.js +4 -4
- package/dist/cjs/tests/model.spec.js.map +1 -1
- package/dist/cjs/tests/module.spec.js +4 -3
- package/dist/cjs/tests/module.spec.js.map +1 -1
- package/dist/cjs/tests/router.spec.d.ts +1 -1
- package/dist/cjs/tests/router.spec.js +329 -296
- package/dist/cjs/tests/router.spec.js.map +1 -1
- package/dist/cjs/tests/utils.js +5 -2
- package/dist/cjs/tests/utils.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/src/controllers.d.ts +4 -4
- package/dist/esm/src/controllers.js +3 -0
- package/dist/esm/src/controllers.js.map +1 -1
- package/dist/esm/src/decorator.d.ts +29 -94
- package/dist/esm/src/decorator.js +49 -114
- package/dist/esm/src/decorator.js.map +1 -1
- package/dist/esm/src/filter.d.ts +1 -0
- package/dist/esm/src/filter.js +11 -18
- package/dist/esm/src/filter.js.map +1 -1
- package/dist/esm/src/http.d.ts +5 -3
- package/dist/esm/src/http.js +98 -56
- package/dist/esm/src/http.js.map +1 -1
- package/dist/esm/src/kernel.d.ts +3 -3
- package/dist/esm/src/kernel.js +10 -30
- package/dist/esm/src/kernel.js.map +1 -1
- package/dist/esm/src/logger.d.ts +2 -2
- package/dist/esm/src/logger.js +4 -9
- package/dist/esm/src/logger.js.map +1 -1
- package/dist/esm/src/middleware.d.ts +5 -1
- package/dist/esm/src/middleware.js +12 -0
- package/dist/esm/src/middleware.js.map +1 -1
- package/dist/esm/src/model.d.ts +67 -0
- package/dist/esm/src/model.js +91 -23
- package/dist/esm/src/model.js.map +1 -1
- package/dist/esm/src/module.config.d.ts +3 -4
- package/dist/esm/src/module.config.js +6 -5
- package/dist/esm/src/module.config.js.map +1 -1
- package/dist/esm/src/module.d.ts +2 -3
- package/dist/esm/src/module.js +5 -3
- package/dist/esm/src/module.js.map +1 -1
- package/dist/esm/src/router.d.ts +25 -54
- package/dist/esm/src/router.js +159 -183
- package/dist/esm/src/router.js.map +1 -1
- package/dist/esm/src/static-serving.d.ts +1 -0
- package/dist/esm/src/static-serving.js +29 -25
- package/dist/esm/src/static-serving.js.map +1 -1
- package/dist/esm/src/utils.js +1 -0
- package/dist/esm/tests/filter.spec.js +14 -0
- package/dist/esm/tests/filter.spec.js.map +1 -1
- package/dist/esm/tests/middleware.spec.d.ts +1 -1
- package/dist/esm/tests/middleware.spec.js +60 -48
- package/dist/esm/tests/middleware.spec.js.map +1 -1
- package/dist/esm/tests/module.spec.js +1 -0
- package/dist/esm/tests/module.spec.js.map +1 -1
- package/dist/esm/tests/router.spec.d.ts +1 -1
- package/dist/esm/tests/router.spec.js +206 -173
- package/dist/esm/tests/router.spec.js.map +1 -1
- package/dist/esm/tests/utils.js +4 -1
- package/dist/esm/tests/utils.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/index.ts +1 -0
- package/package.json +14 -15
- package/src/controllers.ts +3 -3
- package/src/decorator.ts +42 -131
- package/src/filter.ts +0 -2
- package/src/http.ts +40 -33
- package/src/kernel.ts +8 -8
- package/src/logger.ts +2 -4
- package/src/middleware.ts +2 -1
- package/src/model.ts +83 -5
- package/src/module.config.ts +3 -6
- package/src/module.ts +2 -2
- package/src/router.ts +147 -193
- package/src/static-serving.ts +2 -4
- package/tests/middleware.spec.ts +0 -1
- package/tests/router.spec.ts +163 -106
- package/tsconfig.json +2 -1
package/src/static-serving.ts
CHANGED
|
@@ -15,14 +15,12 @@ import { HtmlResponse, httpWorkflow } from './http';
|
|
|
15
15
|
import { AppModule } from '@deepkit/app';
|
|
16
16
|
import { normalizeDirectory } from './utils';
|
|
17
17
|
import { ClassType, urlJoin } from '@deepkit/core';
|
|
18
|
-
import { injectable } from '@deepkit/injector';
|
|
19
18
|
import { HttpRequest, HttpResponse } from './model';
|
|
20
19
|
import send from 'send';
|
|
21
20
|
import { eventDispatcher } from '@deepkit/event';
|
|
22
21
|
import { RouteConfig, Router } from './router';
|
|
23
22
|
|
|
24
23
|
export function serveStaticListener(module: AppModule<any>, path: string, localPath: string = path): ClassType {
|
|
25
|
-
@injectable
|
|
26
24
|
class HttpRequestStaticServingListener {
|
|
27
25
|
serve(path: string, request: HttpRequest, response: HttpResponse) {
|
|
28
26
|
return new Promise((resolve, reject) => {
|
|
@@ -133,7 +131,7 @@ export function registerStaticHttpController(module: AppModule<any>, options: St
|
|
|
133
131
|
methodName: 'serveIndex'
|
|
134
132
|
});
|
|
135
133
|
route1.groups = groups;
|
|
136
|
-
module.setupGlobalProvider(
|
|
134
|
+
module.setupGlobalProvider<Router>().addRoute(route1);
|
|
137
135
|
|
|
138
136
|
const route2 = new RouteConfig('static', ['GET'], normalizeDirectory(options.path).slice(0, -1), {
|
|
139
137
|
controller: StaticController,
|
|
@@ -141,7 +139,7 @@ export function registerStaticHttpController(module: AppModule<any>, options: St
|
|
|
141
139
|
methodName: 'serveIndex'
|
|
142
140
|
});
|
|
143
141
|
route2.groups = groups;
|
|
144
|
-
module.setupGlobalProvider(
|
|
142
|
+
module.setupGlobalProvider<Router>().addRoute(route2);
|
|
145
143
|
|
|
146
144
|
module.addProvider(StaticController);
|
|
147
145
|
module.addListener(serveStaticListener(module, normalizeDirectory(options.path), options.localPath));
|
package/tests/middleware.spec.ts
CHANGED
package/tests/router.spec.ts
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { expect, test } from '@jest/globals';
|
|
2
|
-
import '
|
|
3
|
-
import { dotToUrlPath, RouteParameterResolverContext, Router } from '../src/router';
|
|
2
|
+
import { dotToUrlPath, RouteParameterResolverContext, Router, UploadedFile } from '../src/router';
|
|
4
3
|
import { http, httpClass } from '../src/decorator';
|
|
5
|
-
import {
|
|
6
|
-
import { httpWorkflow, JSONResponse } from '../src/http';
|
|
4
|
+
import { HttpBadRequestError, httpWorkflow, JSONResponse } from '../src/http';
|
|
7
5
|
import { eventDispatcher } from '@deepkit/event';
|
|
8
|
-
import {
|
|
9
|
-
import { HttpRequest } from '../src/model';
|
|
6
|
+
import { HttpBody, HttpBodyValidation, HttpQueries, HttpQuery, HttpRegExp, HttpRequest } from '../src/model';
|
|
10
7
|
import { getClassName, sleep } from '@deepkit/core';
|
|
11
8
|
import { createHttpKernel } from './utils';
|
|
9
|
+
import { Group, MinLength } from '@deepkit/type';
|
|
12
10
|
|
|
13
11
|
test('router', async () => {
|
|
14
12
|
class Controller {
|
|
@@ -62,7 +60,6 @@ test('any', async () => {
|
|
|
62
60
|
expect((await router.resolve('OPTIONS', '/any'))!.routeConfig.action.methodName).toEqual('any');
|
|
63
61
|
});
|
|
64
62
|
|
|
65
|
-
|
|
66
63
|
test('router parameters', async () => {
|
|
67
64
|
class Controller {
|
|
68
65
|
@http.GET('/user/:name')
|
|
@@ -80,8 +77,8 @@ test('router parameters', async () => {
|
|
|
80
77
|
return new JSONResponse(yes);
|
|
81
78
|
}
|
|
82
79
|
|
|
83
|
-
@http.GET(':path')
|
|
84
|
-
any(path: string) {
|
|
80
|
+
@http.GET(':path')
|
|
81
|
+
any(path: HttpRegExp<string, '.*'>) {
|
|
85
82
|
return new JSONResponse(path);
|
|
86
83
|
}
|
|
87
84
|
}
|
|
@@ -93,7 +90,7 @@ test('router parameters', async () => {
|
|
|
93
90
|
|
|
94
91
|
expect((await httpKernel.request(HttpRequest.GET('/user/peter'))).json).toBe('peter');
|
|
95
92
|
expect((await httpKernel.request(HttpRequest.GET('/user-id/123'))).json).toBe(123);
|
|
96
|
-
expect((await httpKernel.request(HttpRequest.GET('/user-id/asd'))).json).toMatchObject({ message: 'Validation
|
|
93
|
+
expect((await httpKernel.request(HttpRequest.GET('/user-id/asd'))).json).toMatchObject({ message: 'Validation error:\nid(type): Cannot convert asd to number' });
|
|
97
94
|
expect((await httpKernel.request(HttpRequest.GET('/boolean/1'))).json).toBe(true);
|
|
98
95
|
expect((await httpKernel.request(HttpRequest.GET('/boolean/false'))).json).toBe(false);
|
|
99
96
|
|
|
@@ -103,8 +100,8 @@ test('router parameters', async () => {
|
|
|
103
100
|
|
|
104
101
|
test('router HttpRequest', async () => {
|
|
105
102
|
class Controller {
|
|
106
|
-
@http.GET(':path')
|
|
107
|
-
anyReq(req: HttpRequest, path: string) {
|
|
103
|
+
@http.GET(':path')
|
|
104
|
+
anyReq(req: HttpRequest, path: HttpRegExp<string, '.*'>) {
|
|
108
105
|
return [req.url, path];
|
|
109
106
|
}
|
|
110
107
|
}
|
|
@@ -246,14 +243,14 @@ test('router parameter resolver by name', async () => {
|
|
|
246
243
|
expect((await httpKernel.request(HttpRequest.GET('/nonClass'))).json).toEqual(['auth', 'MyAuth']);
|
|
247
244
|
});
|
|
248
245
|
|
|
249
|
-
test('router body', async () => {
|
|
246
|
+
test('router body class', async () => {
|
|
250
247
|
class Body {
|
|
251
|
-
|
|
248
|
+
username!: string;
|
|
252
249
|
}
|
|
253
250
|
|
|
254
251
|
class Controller {
|
|
255
252
|
@http.POST()
|
|
256
|
-
anyReq(
|
|
253
|
+
anyReq(body: HttpBody<Body>, req: HttpRequest) {
|
|
257
254
|
return [body.username, body instanceof Body, req.url];
|
|
258
255
|
}
|
|
259
256
|
}
|
|
@@ -263,15 +260,54 @@ test('router body', async () => {
|
|
|
263
260
|
expect((await httpKernel.request(HttpRequest.POST('/').json({ username: 'Peter' }))).json).toEqual(['Peter', true, '/']);
|
|
264
261
|
});
|
|
265
262
|
|
|
263
|
+
test('router body is safe for simultaneous requests', async () => {
|
|
264
|
+
class Body {
|
|
265
|
+
username!: string;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
class Controller {
|
|
269
|
+
@http.POST()
|
|
270
|
+
anyReq(body: HttpBody<Body>, req: HttpRequest) {
|
|
271
|
+
return [body.username, body instanceof Body, req.url];
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const httpKernel = createHttpKernel([Controller]);
|
|
276
|
+
|
|
277
|
+
const makeReq = () => httpKernel.request(HttpRequest.POST('/').json({ username: 'Peter' }));
|
|
278
|
+
|
|
279
|
+
const results = await Promise.all([...new Array(100)].map(() => makeReq().then(res => res.json)));
|
|
280
|
+
|
|
281
|
+
expect(results).toEqual(
|
|
282
|
+
results.map(() => ['Peter', true, '/']),
|
|
283
|
+
)
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
test('router body interface', async () => {
|
|
287
|
+
interface Body {
|
|
288
|
+
username: string;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
class Controller {
|
|
292
|
+
@http.POST()
|
|
293
|
+
anyReq(body: HttpBody<Body>, req: HttpRequest) {
|
|
294
|
+
return [body.username, typeof body.username, req.url];
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const httpKernel = createHttpKernel([Controller]);
|
|
299
|
+
|
|
300
|
+
expect((await httpKernel.request(HttpRequest.POST('/').json({ username: 'Peter' }))).json).toEqual(['Peter', 'string', '/']);
|
|
301
|
+
});
|
|
266
302
|
|
|
267
303
|
test('router body double', async () => {
|
|
268
304
|
class Body {
|
|
269
|
-
|
|
305
|
+
username!: string;
|
|
270
306
|
}
|
|
271
307
|
|
|
272
308
|
class Controller {
|
|
273
309
|
@http.POST()
|
|
274
|
-
anyReq(
|
|
310
|
+
anyReq(body: HttpBody<Body>, body2: HttpBody<Body>, req: HttpRequest) {
|
|
275
311
|
return [body2.username, body2 instanceof Body && body instanceof Body, req.url];
|
|
276
312
|
}
|
|
277
313
|
}
|
|
@@ -281,10 +317,6 @@ test('router body double', async () => {
|
|
|
281
317
|
const action = [...httpData.getActions()][0];
|
|
282
318
|
expect(action.methodName).toBe('anyReq');
|
|
283
319
|
expect(action.httpMethods).toEqual(['POST']);
|
|
284
|
-
expect(action.parameters['body']).not.toBeUndefined();
|
|
285
|
-
expect(action.parameters['body'].name).toBe('body');
|
|
286
|
-
expect(action.parameters['body2']).not.toBeUndefined();
|
|
287
|
-
expect(action.parameters['body2'].name).toBe('body2');
|
|
288
320
|
|
|
289
321
|
const httpKernel = createHttpKernel([Controller]);
|
|
290
322
|
|
|
@@ -341,7 +373,7 @@ test('router groups', async () => {
|
|
|
341
373
|
test('router query', async () => {
|
|
342
374
|
class Controller {
|
|
343
375
|
@http.GET('my-action')
|
|
344
|
-
anyReq(
|
|
376
|
+
anyReq(test?: HttpQuery<number>) {
|
|
345
377
|
return test;
|
|
346
378
|
}
|
|
347
379
|
}
|
|
@@ -351,9 +383,6 @@ test('router query', async () => {
|
|
|
351
383
|
const action = [...httpData.getActions()][0];
|
|
352
384
|
expect(action.methodName).toBe('anyReq');
|
|
353
385
|
expect(action.httpMethods).toEqual(['GET']);
|
|
354
|
-
expect(action.parameters['test']).not.toBeUndefined();
|
|
355
|
-
expect(action.parameters['test'].name).toBe('test');
|
|
356
|
-
expect(action.parameters['test'].type).toBe('query');
|
|
357
386
|
|
|
358
387
|
const httpKernel = createHttpKernel([Controller]);
|
|
359
388
|
|
|
@@ -363,14 +392,14 @@ test('router query', async () => {
|
|
|
363
392
|
|
|
364
393
|
test('router query all', async () => {
|
|
365
394
|
class AnyReqQuery {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
395
|
+
test?: string;
|
|
396
|
+
filter?: string;
|
|
397
|
+
page?: number;
|
|
369
398
|
}
|
|
370
399
|
|
|
371
400
|
class Controller {
|
|
372
401
|
@http.GET('my-action')
|
|
373
|
-
anyReq(
|
|
402
|
+
anyReq(anyReqQuery: HttpQueries<AnyReqQuery>) {
|
|
374
403
|
return anyReqQuery;
|
|
375
404
|
}
|
|
376
405
|
}
|
|
@@ -384,14 +413,13 @@ test('router query all', async () => {
|
|
|
384
413
|
|
|
385
414
|
test('serializer options', async () => {
|
|
386
415
|
class User {
|
|
387
|
-
|
|
388
|
-
|
|
416
|
+
username!: string;
|
|
417
|
+
password!: string & Group<'sensitive'>;
|
|
389
418
|
}
|
|
390
419
|
|
|
391
420
|
class Controller {
|
|
392
421
|
@http.GET().serialization({ groupsExclude: ['sensitive'] })
|
|
393
|
-
|
|
394
|
-
anyReq() {
|
|
422
|
+
anyReq(): User {
|
|
395
423
|
return { username: 'Peter', password: 'secret' };
|
|
396
424
|
}
|
|
397
425
|
}
|
|
@@ -403,14 +431,13 @@ test('serializer options', async () => {
|
|
|
403
431
|
|
|
404
432
|
test('hook after serializer', async () => {
|
|
405
433
|
class User {
|
|
406
|
-
|
|
407
|
-
|
|
434
|
+
username!: string;
|
|
435
|
+
password!: string & Group<'sensitive'>;
|
|
408
436
|
}
|
|
409
437
|
|
|
410
438
|
class Controller {
|
|
411
439
|
@http.GET().serialization({ groupsExclude: ['sensitive'] })
|
|
412
|
-
|
|
413
|
-
async anyReq() {
|
|
440
|
+
async anyReq(): Promise<User> {
|
|
414
441
|
await sleep(0.1);
|
|
415
442
|
return { username: 'Peter', password: 'secret' };
|
|
416
443
|
}
|
|
@@ -438,10 +465,9 @@ test('invalid route definition', async () => {
|
|
|
438
465
|
}
|
|
439
466
|
|
|
440
467
|
const httpKernel = createHttpKernel([Controller]);
|
|
441
|
-
expect((await httpKernel.request(HttpRequest.GET('/'))).bodyString).toEqual('
|
|
468
|
+
expect((await httpKernel.request(HttpRequest.GET('/'))).bodyString).toEqual('Internal error');
|
|
442
469
|
});
|
|
443
470
|
|
|
444
|
-
|
|
445
471
|
test('inject request storage ClassType', async () => {
|
|
446
472
|
class User {
|
|
447
473
|
constructor(public username: string) {
|
|
@@ -455,7 +481,7 @@ test('inject request storage ClassType', async () => {
|
|
|
455
481
|
}
|
|
456
482
|
|
|
457
483
|
@http.GET('optional')
|
|
458
|
-
doItOptional(
|
|
484
|
+
doItOptional(user?: User) {
|
|
459
485
|
return { isUser: user instanceof User };
|
|
460
486
|
}
|
|
461
487
|
}
|
|
@@ -471,7 +497,7 @@ test('inject request storage ClassType', async () => {
|
|
|
471
497
|
|
|
472
498
|
const httpKernel = createHttpKernel([Controller], [
|
|
473
499
|
{
|
|
474
|
-
provide: User, scope: 'http',
|
|
500
|
+
provide: User, scope: 'http', useFactory(request: HttpRequest) {
|
|
475
501
|
return request.store.user;
|
|
476
502
|
}
|
|
477
503
|
}
|
|
@@ -483,40 +509,6 @@ test('inject request storage ClassType', async () => {
|
|
|
483
509
|
expect((await httpKernel.request(HttpRequest.GET('/optional').headers({ authorization: 'no' }))).json).toEqual({ isUser: false });
|
|
484
510
|
});
|
|
485
511
|
|
|
486
|
-
|
|
487
|
-
test('inject request storage @inject', async () => {
|
|
488
|
-
class User {
|
|
489
|
-
constructor(public username: string) {
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
class Controller {
|
|
494
|
-
@http.GET()
|
|
495
|
-
doIt(@inject('user') user: any) {
|
|
496
|
-
return { isUser: user instanceof User, username: user.username };
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
class Listener {
|
|
501
|
-
@eventDispatcher.listen(httpWorkflow.onAuth)
|
|
502
|
-
onAuth(event: typeof httpWorkflow.onAuth.event) {
|
|
503
|
-
event.request.store.user = new User('bar');
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
const httpKernel = createHttpKernel([Controller], [
|
|
508
|
-
{
|
|
509
|
-
provide: 'user', scope: 'http', deps: [HttpRequest], useFactory(request: HttpRequest) {
|
|
510
|
-
return request.store.user;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
], [Listener]);
|
|
514
|
-
|
|
515
|
-
const result = (await httpKernel.request(HttpRequest.GET('/'))).json;
|
|
516
|
-
expect(result.isUser).toBe(true);
|
|
517
|
-
expect(result.username).toBe('bar');
|
|
518
|
-
});
|
|
519
|
-
|
|
520
512
|
test('custom request handling', async () => {
|
|
521
513
|
class Listener {
|
|
522
514
|
@eventDispatcher.listen(httpWorkflow.onRouteNotFound)
|
|
@@ -590,9 +582,8 @@ test('promise serializer', async () => {
|
|
|
590
582
|
}
|
|
591
583
|
|
|
592
584
|
@http.GET('2')
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
return 1;
|
|
585
|
+
async anyReq2(): Promise<string> {
|
|
586
|
+
return 1 as any;
|
|
596
587
|
}
|
|
597
588
|
}
|
|
598
589
|
|
|
@@ -602,20 +593,31 @@ test('promise serializer', async () => {
|
|
|
602
593
|
expect((await httpKernel.request(HttpRequest.GET('/2'))).json).toBe('1');
|
|
603
594
|
});
|
|
604
595
|
|
|
605
|
-
|
|
606
596
|
test('unions', async () => {
|
|
607
597
|
class Controller {
|
|
608
598
|
@http.GET('/list')
|
|
609
|
-
list(
|
|
599
|
+
list(page: HttpQuery<number | boolean>) {
|
|
610
600
|
return page;
|
|
611
601
|
}
|
|
612
602
|
}
|
|
613
603
|
|
|
614
604
|
const httpKernel = createHttpKernel([Controller]);
|
|
615
605
|
|
|
606
|
+
expect((await httpKernel.request(HttpRequest.GET('/list?page=0'))).json).toEqual(0);
|
|
616
607
|
expect((await httpKernel.request(HttpRequest.GET('/list?page=1'))).json).toEqual(1);
|
|
617
608
|
expect((await httpKernel.request(HttpRequest.GET('/list?page=2222'))).json).toEqual(2222);
|
|
618
609
|
expect((await httpKernel.request(HttpRequest.GET('/list?page=false'))).json).toEqual(false);
|
|
610
|
+
expect((await httpKernel.request(HttpRequest.GET('/list?page=true'))).json).toEqual(true);
|
|
611
|
+
|
|
612
|
+
expect((await httpKernel.request(HttpRequest.GET('/list?page=asdasdc'))).json).toMatchObject({
|
|
613
|
+
'errors': [
|
|
614
|
+
{
|
|
615
|
+
'code': 'type',
|
|
616
|
+
'message': 'No value given',
|
|
617
|
+
'path': 'page'
|
|
618
|
+
}
|
|
619
|
+
],
|
|
620
|
+
});
|
|
619
621
|
});
|
|
620
622
|
|
|
621
623
|
test('router dotToUrlPath', () => {
|
|
@@ -627,9 +629,9 @@ test('router dotToUrlPath', () => {
|
|
|
627
629
|
|
|
628
630
|
test('router url resolve', async () => {
|
|
629
631
|
class AnyReqQuery {
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
632
|
+
test?: string;
|
|
633
|
+
filter?: string;
|
|
634
|
+
page?: number;
|
|
633
635
|
}
|
|
634
636
|
|
|
635
637
|
class Controller {
|
|
@@ -644,22 +646,22 @@ test('router url resolve', async () => {
|
|
|
644
646
|
}
|
|
645
647
|
|
|
646
648
|
@http.GET('').name('secondQuery')
|
|
647
|
-
secondQuery(
|
|
649
|
+
secondQuery(peter: HttpQuery<string>) {
|
|
648
650
|
return '';
|
|
649
651
|
}
|
|
650
652
|
|
|
651
653
|
@http.GET('').name('secondQuery2')
|
|
652
|
-
secondQuery2(
|
|
654
|
+
secondQuery2(peter: HttpQuery<string, { name: 'changed' }>) {
|
|
653
655
|
return '';
|
|
654
656
|
}
|
|
655
657
|
|
|
656
658
|
@http.GET('third').name('third')
|
|
657
|
-
third(
|
|
659
|
+
third(params: HttpQueries<AnyReqQuery>) {
|
|
658
660
|
return params;
|
|
659
661
|
}
|
|
660
662
|
|
|
661
663
|
@http.GET('third2').name('third2')
|
|
662
|
-
third2(
|
|
664
|
+
third2(params: HttpQueries<AnyReqQuery, { name: 'deep' }>) {
|
|
663
665
|
return params;
|
|
664
666
|
}
|
|
665
667
|
}
|
|
@@ -680,15 +682,14 @@ test('router url resolve', async () => {
|
|
|
680
682
|
});
|
|
681
683
|
|
|
682
684
|
test('destructing params', async () => {
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
@t.required title!: string;
|
|
685
|
+
interface DTO {
|
|
686
|
+
name: string;
|
|
687
|
+
title: string;
|
|
687
688
|
}
|
|
688
689
|
|
|
689
690
|
class Controller {
|
|
690
691
|
@http.GET('')
|
|
691
|
-
first(
|
|
692
|
+
first({ name, title }: HttpBody<DTO>) {
|
|
692
693
|
return [name, title];
|
|
693
694
|
}
|
|
694
695
|
}
|
|
@@ -698,27 +699,83 @@ test('destructing params', async () => {
|
|
|
698
699
|
expect((await httpKernel.request(HttpRequest.GET('/').json({ name: 'Peter', title: 'CTO' }))).json).toEqual(['Peter', 'CTO']);
|
|
699
700
|
});
|
|
700
701
|
|
|
701
|
-
test('
|
|
702
|
-
|
|
702
|
+
test('use http.response for serialization', async () => {
|
|
703
|
+
interface DefaultResponse {
|
|
704
|
+
title: string;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
interface ErrorResponse {
|
|
708
|
+
message: string;
|
|
709
|
+
}
|
|
710
|
+
|
|
703
711
|
class Controller {
|
|
704
|
-
@http.GET('
|
|
705
|
-
|
|
706
|
-
return [
|
|
712
|
+
@http.GET('/action1')
|
|
713
|
+
action1(): DefaultResponse[] {
|
|
714
|
+
return [{ title: 'a' }, { title: '1' }];
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
@http.GET('/action2').response<DefaultResponse[]>(200, `List`)
|
|
718
|
+
action2() {
|
|
719
|
+
return [{ title: 'a' }, { title: 1 }];
|
|
707
720
|
}
|
|
708
721
|
|
|
709
|
-
@http.GET('
|
|
710
|
-
|
|
711
|
-
|
|
722
|
+
@http.GET('/action3')
|
|
723
|
+
.response<DefaultResponse[]>(200, `List`)
|
|
724
|
+
.response<ErrorResponse[]>(400, `Error`)
|
|
725
|
+
action3() {
|
|
726
|
+
return new JSONResponse([{ message: 'error' }, { message: 1 }]).status(400);
|
|
712
727
|
}
|
|
713
728
|
}
|
|
714
729
|
|
|
715
|
-
const
|
|
716
|
-
expect(
|
|
717
|
-
expect(
|
|
718
|
-
expect(
|
|
730
|
+
const httpKernel = createHttpKernel([Controller]);
|
|
731
|
+
expect((await httpKernel.request(HttpRequest.GET('/action1'))).json).toEqual([{ title: 'a' }, { title: '1' }]);
|
|
732
|
+
expect((await httpKernel.request(HttpRequest.GET('/action2'))).json).toEqual([{ title: 'a' }, { title: '1' }]);
|
|
733
|
+
expect((await httpKernel.request(HttpRequest.GET('/action3'))).json).toEqual([{ message: 'error' }, { message: '1' }]);
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
test('BodyValidation', async () => {
|
|
737
|
+
class User {
|
|
738
|
+
username!: string & MinLength<3>;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
class AddUserDto extends User {
|
|
742
|
+
imageUpload?: UploadedFile;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
class Controller {
|
|
746
|
+
@http.POST('/action1')
|
|
747
|
+
action1(user: HttpBody<User>): any {
|
|
748
|
+
return user;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
@http.POST('/action2')
|
|
752
|
+
action2(user: HttpBodyValidation<User>): User {
|
|
753
|
+
if (user.valid()) {
|
|
754
|
+
return user.value;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
throw new HttpBadRequestError('Invalid: ' + user.error.getErrorMessageForPath('username'));
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
@http.POST('/action3')
|
|
761
|
+
action3(user: HttpBodyValidation<AddUserDto>): User {
|
|
762
|
+
if (user.valid()) {
|
|
763
|
+
return user.value;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
throw new HttpBadRequestError('Invalid: ' + user.error.getErrorMessageForPath('username'));
|
|
767
|
+
}
|
|
768
|
+
}
|
|
719
769
|
|
|
720
770
|
const httpKernel = createHttpKernel([Controller]);
|
|
771
|
+
expect((await httpKernel.request(HttpRequest.POST('/action1').json({ username: 'Peter' }))).json).toEqual({ username: 'Peter' });
|
|
772
|
+
expect((await httpKernel.request(HttpRequest.POST('/action1').json({ username: 'Pe' }))).json).toEqual({
|
|
773
|
+
errors: [{ code: 'minLength', message: 'Min length is 3', path: 'username' }], message: 'Validation error:\nusername(minLength): Min length is 3'
|
|
774
|
+
});
|
|
775
|
+
|
|
776
|
+
expect((await httpKernel.request(HttpRequest.POST('/action2').json({ username: 'Peter' }))).json).toEqual({ username: 'Peter' });
|
|
777
|
+
expect((await httpKernel.request(HttpRequest.POST('/action2').json({ username: 'Pe' }))).bodyString).toEqual(`{"message":"Invalid: Min length is 3"}`);
|
|
721
778
|
|
|
722
|
-
expect((await httpKernel.request(HttpRequest.
|
|
723
|
-
expect((await httpKernel.request(HttpRequest.
|
|
779
|
+
expect((await httpKernel.request(HttpRequest.POST('/action3').json({ username: 'Peter' }))).json).toEqual({ username: 'Peter' });
|
|
780
|
+
expect((await httpKernel.request(HttpRequest.POST('/action3').json({ username: 'Pe' }))).bodyString).toEqual(`{"message":"Invalid: Min length is 3"}`);
|
|
724
781
|
});
|