@e22m4u/ts-rest-router 0.5.5 → 0.6.0
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/dist/cjs/index.cjs +36 -22
- package/dist/esm/controller-registry.js +11 -3
- package/dist/esm/data-schema-types.d.ts +15 -0
- package/dist/esm/data-schema-types.js +1 -0
- package/dist/esm/decorators/before-action/before-action-reflector.spec.js +15 -15
- package/dist/esm/decorators/request-data/request-data-decorator.d.ts +11 -12
- package/dist/esm/decorators/request-data/request-data-decorator.js +20 -12
- package/dist/esm/decorators/request-data/request-data-decorator.spec.js +183 -1
- package/dist/esm/decorators/request-data/request-data-metadata.d.ts +2 -2
- package/dist/esm/decorators/response-body/response-body-decorator.d.ts +2 -3
- package/dist/esm/decorators/response-body/response-body-decorator.js +7 -7
- package/dist/esm/decorators/response-body/response-body-decorator.spec.js +21 -1
- package/dist/esm/decorators/response-body/response-body-metadata.d.ts +2 -2
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/package.json +1 -1
- package/src/controller-registry.spec.ts +174 -1
- package/src/controller-registry.ts +11 -7
- package/src/data-schema-types.ts +18 -0
- package/src/decorators/before-action/before-action-reflector.spec.ts +15 -15
- package/src/decorators/request-data/request-data-decorator.spec.ts +174 -1
- package/src/decorators/request-data/request-data-decorator.ts +22 -13
- package/src/decorators/request-data/request-data-metadata.ts +2 -2
- package/src/decorators/response-body/response-body-decorator.spec.ts +17 -1
- package/src/decorators/response-body/response-body-decorator.ts +9 -11
- package/src/decorators/response-body/response-body-metadata.ts +2 -2
- package/src/index.ts +1 -0
package/dist/cjs/index.cjs
CHANGED
@@ -294,12 +294,12 @@ function requestData(options) {
|
|
294
294
|
}
|
295
295
|
__name(requestData, "requestData");
|
296
296
|
function createRequestDataDecoratorWithSource(source) {
|
297
|
-
return function(
|
297
|
+
return function(schemaInput) {
|
298
298
|
let schema;
|
299
|
-
if (typeof
|
300
|
-
schema =
|
301
|
-
} else if (typeof
|
302
|
-
schema = { type:
|
299
|
+
if (typeof schemaInput === "function" || typeof schemaInput === "object") {
|
300
|
+
schema = schemaInput;
|
301
|
+
} else if (typeof schemaInput === "string") {
|
302
|
+
schema = { type: schemaInput };
|
303
303
|
} else {
|
304
304
|
schema = { type: import_ts_data_schema.DataType.ANY };
|
305
305
|
}
|
@@ -308,14 +308,21 @@ function createRequestDataDecoratorWithSource(source) {
|
|
308
308
|
}
|
309
309
|
__name(createRequestDataDecoratorWithSource, "createRequestDataDecoratorWithSource");
|
310
310
|
function createRequestDataPropertyDecoratorWithSource(source) {
|
311
|
-
return function(propertyKey,
|
312
|
-
const properties = {};
|
311
|
+
return function(propertyKey, schemaInput) {
|
313
312
|
const rootSchema = { type: import_ts_data_schema.DataType.OBJECT };
|
314
|
-
|
315
|
-
|
313
|
+
const properties = {};
|
314
|
+
let schemaOrFactory = rootSchema;
|
315
|
+
if (typeof schemaInput === "function") {
|
316
|
+
schemaOrFactory = /* @__PURE__ */ __name((container) => {
|
317
|
+
properties[propertyKey] = schemaInput(container);
|
318
|
+
rootSchema.properties = properties;
|
319
|
+
return rootSchema;
|
320
|
+
}, "schemaOrFactory");
|
321
|
+
} else if (typeof schemaInput === "object") {
|
322
|
+
properties[propertyKey] = schemaInput;
|
316
323
|
rootSchema.properties = properties;
|
317
|
-
} else if (typeof
|
318
|
-
properties[propertyKey] = { type:
|
324
|
+
} else if (typeof schemaInput === "string") {
|
325
|
+
properties[propertyKey] = { type: schemaInput };
|
319
326
|
rootSchema.properties = properties;
|
320
327
|
} else {
|
321
328
|
properties[propertyKey] = { type: import_ts_data_schema.DataType.ANY };
|
@@ -323,7 +330,7 @@ function createRequestDataPropertyDecoratorWithSource(source) {
|
|
323
330
|
}
|
324
331
|
return requestData({
|
325
332
|
source,
|
326
|
-
schema:
|
333
|
+
schema: schemaOrFactory,
|
327
334
|
property: propertyKey
|
328
335
|
});
|
329
336
|
};
|
@@ -478,18 +485,18 @@ __name(_ResponseBodyReflector, "ResponseBodyReflector");
|
|
478
485
|
var ResponseBodyReflector = _ResponseBodyReflector;
|
479
486
|
|
480
487
|
// dist/esm/decorators/response-body/response-body-decorator.js
|
481
|
-
function responseBody(
|
488
|
+
function responseBody(schemaInput) {
|
482
489
|
return function(target, propertyKey, descriptor) {
|
483
490
|
const decoratorType = (0, import_ts_reflector20.getDecoratorTargetType)(target, propertyKey, descriptor);
|
484
491
|
if (decoratorType !== import_ts_reflector19.DecoratorTargetType.INSTANCE_METHOD)
|
485
492
|
throw new Error("@responseBody decorator is only supported on an instance method.");
|
486
|
-
let
|
487
|
-
if (typeof
|
488
|
-
|
489
|
-
} else if (typeof
|
490
|
-
|
493
|
+
let schemaOrFactory;
|
494
|
+
if (typeof schemaInput === "function" || typeof schemaInput === "object") {
|
495
|
+
schemaOrFactory = schemaInput;
|
496
|
+
} else if (typeof schemaInput === "string") {
|
497
|
+
schemaOrFactory = { type: schemaInput };
|
491
498
|
}
|
492
|
-
ResponseBodyReflector.setMetadata(
|
499
|
+
ResponseBodyReflector.setMetadata(schemaOrFactory ? { schema: schemaOrFactory } : {}, target.constructor, propertyKey);
|
493
500
|
};
|
494
501
|
}
|
495
502
|
__name(responseBody, "responseBody");
|
@@ -935,14 +942,21 @@ var _ControllerRegistry = class _ControllerRegistry extends DebuggableService {
|
|
935
942
|
}
|
936
943
|
debug("Request data source is %v.", requestDataMd.source);
|
937
944
|
if (requestDataMd.schema) {
|
938
|
-
|
945
|
+
let dataSchema;
|
946
|
+
if (typeof requestDataMd.schema === "function") {
|
947
|
+
dataSchema = requestDataMd.schema(this.container);
|
948
|
+
debug("Data schema extracted from factory function.");
|
949
|
+
} else {
|
950
|
+
dataSchema = requestDataMd.schema;
|
951
|
+
}
|
952
|
+
data = defaultsApplier.applyDefaultValuesIfNeeded(data, dataSchema, requestDataMd.source);
|
939
953
|
debug("Default values applied.");
|
940
|
-
data = dataTypeCaster.cast(data,
|
954
|
+
data = dataTypeCaster.cast(data, dataSchema, {
|
941
955
|
noTypeCastError: true,
|
942
956
|
sourcePath: requestDataMd.source
|
943
957
|
});
|
944
958
|
debug("Data type casting applied.");
|
945
|
-
dataValidator.validate(data,
|
959
|
+
dataValidator.validate(data, dataSchema, requestDataMd.source);
|
946
960
|
debug("Data validation passed.");
|
947
961
|
}
|
948
962
|
if (requestDataMd.property == null) {
|
@@ -384,14 +384,22 @@ export class ControllerRegistry extends DebuggableService {
|
|
384
384
|
// по умолчанию, выполняется конвертация входящего
|
385
385
|
// значения и валидация согласно схеме
|
386
386
|
if (requestDataMd.schema) {
|
387
|
-
|
387
|
+
let dataSchema;
|
388
|
+
if (typeof requestDataMd.schema === 'function') {
|
389
|
+
dataSchema = requestDataMd.schema(this.container);
|
390
|
+
debug('Data schema extracted from factory function.');
|
391
|
+
}
|
392
|
+
else {
|
393
|
+
dataSchema = requestDataMd.schema;
|
394
|
+
}
|
395
|
+
data = defaultsApplier.applyDefaultValuesIfNeeded(data, dataSchema, requestDataMd.source);
|
388
396
|
debug('Default values applied.');
|
389
|
-
data = dataTypeCaster.cast(data,
|
397
|
+
data = dataTypeCaster.cast(data, dataSchema, {
|
390
398
|
noTypeCastError: true,
|
391
399
|
sourcePath: requestDataMd.source,
|
392
400
|
});
|
393
401
|
debug('Data type casting applied.');
|
394
|
-
dataValidator.validate(data,
|
402
|
+
dataValidator.validate(data, dataSchema, requestDataMd.source);
|
395
403
|
debug('Data validation passed.');
|
396
404
|
}
|
397
405
|
// если свойство данных не определено,
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { DataType } from '@e22m4u/ts-data-schema';
|
2
|
+
import { DataSchema } from '@e22m4u/ts-data-schema';
|
3
|
+
import { ServiceContainer } from '@e22m4u/js-service';
|
4
|
+
/**
|
5
|
+
* Data schema factory.
|
6
|
+
*/
|
7
|
+
export type DataSchemaFactory = (container: ServiceContainer) => DataSchema;
|
8
|
+
/**
|
9
|
+
* Data schema or factory.
|
10
|
+
*/
|
11
|
+
export type DataSchemaOrFactory = DataSchema | DataSchemaFactory;
|
12
|
+
/**
|
13
|
+
* Data schema input.
|
14
|
+
*/
|
15
|
+
export type DataSchemaInput = DataSchemaOrFactory | DataType;
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -2,17 +2,17 @@ import { expect } from 'chai';
|
|
2
2
|
import { Reflector } from '@e22m4u/ts-reflector';
|
3
3
|
import { BeforeActionReflector } from './before-action-reflector.js';
|
4
4
|
import { BEFORE_ACTION_METADATA_KEY } from './before-action-metadata.js';
|
5
|
-
const
|
6
|
-
const
|
7
|
-
const
|
5
|
+
const HOOK_1 = () => undefined;
|
6
|
+
const HOOK_2 = () => undefined;
|
7
|
+
const HOOK_3 = () => undefined;
|
8
8
|
describe('BeforeActionReflector', function () {
|
9
9
|
describe('class target', function () {
|
10
10
|
describe('addMetadata', function () {
|
11
11
|
it('adds a given value to the target metadata', function () {
|
12
12
|
class Target {
|
13
13
|
}
|
14
|
-
const md1 = { hook:
|
15
|
-
const md2 = { hook: [
|
14
|
+
const md1 = { hook: HOOK_1 };
|
15
|
+
const md2 = { hook: [HOOK_2, HOOK_3] };
|
16
16
|
BeforeActionReflector.addMetadata(md1, Target);
|
17
17
|
BeforeActionReflector.addMetadata(md2, Target);
|
18
18
|
const res = Reflector.getOwnMetadata(BEFORE_ACTION_METADATA_KEY, Target);
|
@@ -29,8 +29,8 @@ describe('BeforeActionReflector', function () {
|
|
29
29
|
it('returns existing metadata by the target', function () {
|
30
30
|
class Target {
|
31
31
|
}
|
32
|
-
const md1 = { hook:
|
33
|
-
const md2 = { hook: [
|
32
|
+
const md1 = { hook: HOOK_1 };
|
33
|
+
const md2 = { hook: [HOOK_2, HOOK_3] };
|
34
34
|
const mdArray = [md1, md2];
|
35
35
|
Reflector.defineMetadata(BEFORE_ACTION_METADATA_KEY, mdArray, Target);
|
36
36
|
const res = BeforeActionReflector.getMetadata(Target);
|
@@ -43,8 +43,8 @@ describe('BeforeActionReflector', function () {
|
|
43
43
|
it('adds a given value to the target metadata', function () {
|
44
44
|
class Target {
|
45
45
|
}
|
46
|
-
const md1 = { hook:
|
47
|
-
const md2 = { hook: [
|
46
|
+
const md1 = { hook: HOOK_1 };
|
47
|
+
const md2 = { hook: [HOOK_2, HOOK_3] };
|
48
48
|
BeforeActionReflector.addMetadata(md1, Target, 'prop');
|
49
49
|
BeforeActionReflector.addMetadata(md2, Target, 'prop');
|
50
50
|
const res = Reflector.getOwnMetadata(BEFORE_ACTION_METADATA_KEY, Target, 'prop');
|
@@ -61,8 +61,8 @@ describe('BeforeActionReflector', function () {
|
|
61
61
|
it('returns existing metadata by the target', function () {
|
62
62
|
class Target {
|
63
63
|
}
|
64
|
-
const md1 = { hook:
|
65
|
-
const md2 = { hook: [
|
64
|
+
const md1 = { hook: HOOK_1 };
|
65
|
+
const md2 = { hook: [HOOK_2, HOOK_3] };
|
66
66
|
const mdArray = [md1, md2];
|
67
67
|
Reflector.defineMetadata(BEFORE_ACTION_METADATA_KEY, mdArray, Target, 'prop');
|
68
68
|
const res = BeforeActionReflector.getMetadata(Target, 'prop');
|
@@ -74,8 +74,8 @@ describe('BeforeActionReflector', function () {
|
|
74
74
|
it('can distinguish class and method metadata', function () {
|
75
75
|
class Target {
|
76
76
|
}
|
77
|
-
const md1 = { hook:
|
78
|
-
const md2 = { hook:
|
77
|
+
const md1 = { hook: HOOK_1 };
|
78
|
+
const md2 = { hook: HOOK_2 };
|
79
79
|
BeforeActionReflector.addMetadata(md1, Target);
|
80
80
|
BeforeActionReflector.addMetadata(md2, Target, 'prop');
|
81
81
|
const res1 = Reflector.getOwnMetadata(BEFORE_ACTION_METADATA_KEY, Target);
|
@@ -88,8 +88,8 @@ describe('BeforeActionReflector', function () {
|
|
88
88
|
it('can distinguish class and method metadata', function () {
|
89
89
|
class Target {
|
90
90
|
}
|
91
|
-
const md1 = { hook:
|
92
|
-
const md2 = { hook:
|
91
|
+
const md1 = { hook: HOOK_1 };
|
92
|
+
const md2 = { hook: HOOK_2 };
|
93
93
|
Reflector.defineMetadata(BEFORE_ACTION_METADATA_KEY, [md1], Target);
|
94
94
|
Reflector.defineMetadata(BEFORE_ACTION_METADATA_KEY, [md2], Target, 'prop');
|
95
95
|
const res1 = BeforeActionReflector.getMetadata(Target);
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import { Prototype } from '../../types.js';
|
2
|
-
import {
|
3
|
-
import { DataSchema } from '@e22m4u/ts-data-schema';
|
2
|
+
import { DataSchemaInput } from '../../data-schema-types.js';
|
4
3
|
import { RequestDataMetadata } from './request-data-metadata.js';
|
5
4
|
/**
|
6
5
|
* Request data options.
|
@@ -15,13 +14,13 @@ export declare function requestData<T extends object>(options: RequestDataOption
|
|
15
14
|
/**
|
16
15
|
* Decorator aliases.
|
17
16
|
*/
|
18
|
-
export declare const requestParams: (
|
19
|
-
export declare const requestParam: (propertyKey: string,
|
20
|
-
export declare const requestQueries: (
|
21
|
-
export declare const requestQuery: (propertyKey: string,
|
22
|
-
export declare const requestHeaders: (
|
23
|
-
export declare const requestHeader: (propertyKey: string,
|
24
|
-
export declare const requestCookies: (
|
25
|
-
export declare const requestCookie: (propertyKey: string,
|
26
|
-
export declare const requestBody: (
|
27
|
-
export declare const requestField: (propertyKey: string,
|
17
|
+
export declare const requestParams: (schemaInput?: DataSchemaInput) => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
18
|
+
export declare const requestParam: (propertyKey: string, schemaInput?: DataSchemaInput) => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
19
|
+
export declare const requestQueries: (schemaInput?: DataSchemaInput) => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
20
|
+
export declare const requestQuery: (propertyKey: string, schemaInput?: DataSchemaInput) => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
21
|
+
export declare const requestHeaders: (schemaInput?: DataSchemaInput) => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
22
|
+
export declare const requestHeader: (propertyKey: string, schemaInput?: DataSchemaInput) => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
23
|
+
export declare const requestCookies: (schemaInput?: DataSchemaInput) => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
24
|
+
export declare const requestCookie: (propertyKey: string, schemaInput?: DataSchemaInput) => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
25
|
+
export declare const requestBody: (schemaInput?: DataSchemaInput) => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
26
|
+
export declare const requestField: (propertyKey: string, schemaInput?: DataSchemaInput) => (target: Prototype<object>, propertyKey: string, index: number) => void;
|
@@ -23,13 +23,13 @@ export function requestData(options) {
|
|
23
23
|
* @param source
|
24
24
|
*/
|
25
25
|
function createRequestDataDecoratorWithSource(source) {
|
26
|
-
return function (
|
26
|
+
return function (schemaInput) {
|
27
27
|
let schema;
|
28
|
-
if (typeof
|
29
|
-
schema =
|
28
|
+
if (typeof schemaInput === 'function' || typeof schemaInput === 'object') {
|
29
|
+
schema = schemaInput;
|
30
30
|
}
|
31
|
-
else if (typeof
|
32
|
-
schema = { type:
|
31
|
+
else if (typeof schemaInput === 'string') {
|
32
|
+
schema = { type: schemaInput };
|
33
33
|
}
|
34
34
|
else {
|
35
35
|
schema = { type: DataType.ANY };
|
@@ -43,15 +43,23 @@ function createRequestDataDecoratorWithSource(source) {
|
|
43
43
|
* @param source
|
44
44
|
*/
|
45
45
|
function createRequestDataPropertyDecoratorWithSource(source) {
|
46
|
-
return function (propertyKey,
|
47
|
-
const properties = {};
|
46
|
+
return function (propertyKey, schemaInput) {
|
48
47
|
const rootSchema = { type: DataType.OBJECT };
|
49
|
-
|
50
|
-
|
48
|
+
const properties = {};
|
49
|
+
let schemaOrFactory = rootSchema;
|
50
|
+
if (typeof schemaInput === 'function') {
|
51
|
+
schemaOrFactory = container => {
|
52
|
+
properties[propertyKey] = schemaInput(container);
|
53
|
+
rootSchema.properties = properties;
|
54
|
+
return rootSchema;
|
55
|
+
};
|
56
|
+
}
|
57
|
+
else if (typeof schemaInput === 'object') {
|
58
|
+
properties[propertyKey] = schemaInput;
|
51
59
|
rootSchema.properties = properties;
|
52
60
|
}
|
53
|
-
else if (typeof
|
54
|
-
properties[propertyKey] = { type:
|
61
|
+
else if (typeof schemaInput === 'string') {
|
62
|
+
properties[propertyKey] = { type: schemaInput };
|
55
63
|
rootSchema.properties = properties;
|
56
64
|
}
|
57
65
|
else {
|
@@ -60,7 +68,7 @@ function createRequestDataPropertyDecoratorWithSource(source) {
|
|
60
68
|
}
|
61
69
|
return requestData({
|
62
70
|
source: source,
|
63
|
-
schema:
|
71
|
+
schema: schemaOrFactory,
|
64
72
|
property: propertyKey,
|
65
73
|
});
|
66
74
|
};
|
@@ -164,7 +164,7 @@ describe('requestData', function () {
|
|
164
164
|
schema: { type: DataType.STRING },
|
165
165
|
});
|
166
166
|
});
|
167
|
-
it('
|
167
|
+
it('sets a given DataSchema to the target metadata', function () {
|
168
168
|
const schema = { type: DataType.STRING, required: true };
|
169
169
|
class Target {
|
170
170
|
myMethod(prop) { }
|
@@ -181,6 +181,23 @@ describe('requestData', function () {
|
|
181
181
|
schema,
|
182
182
|
});
|
183
183
|
});
|
184
|
+
it('sets a given DataSchemaFactory to the target metadata', function () {
|
185
|
+
const factory = () => ({ type: DataType.STRING, required: true });
|
186
|
+
class Target {
|
187
|
+
myMethod(prop) { }
|
188
|
+
}
|
189
|
+
__decorate([
|
190
|
+
__param(0, requestBody(factory)),
|
191
|
+
__metadata("design:type", Function),
|
192
|
+
__metadata("design:paramtypes", [Object]),
|
193
|
+
__metadata("design:returntype", void 0)
|
194
|
+
], Target.prototype, "myMethod", null);
|
195
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
196
|
+
expect(res.get(0)).to.be.eql({
|
197
|
+
source: RequestDataSource.BODY,
|
198
|
+
schema: factory,
|
199
|
+
});
|
200
|
+
});
|
184
201
|
});
|
185
202
|
});
|
186
203
|
describe('request data piece by a given property key', function () {
|
@@ -263,6 +280,39 @@ describe('requestData', function () {
|
|
263
280
|
property: propertyKey,
|
264
281
|
});
|
265
282
|
});
|
283
|
+
it('sets a given DataSchemaFactory to the target metadata', function () {
|
284
|
+
const container = {};
|
285
|
+
const factory = sc => {
|
286
|
+
expect(sc).to.be.eq(container);
|
287
|
+
return { type: DataType.STRING, required: true };
|
288
|
+
};
|
289
|
+
const propertyKey = 'myPropertyKey';
|
290
|
+
class Target {
|
291
|
+
myMethod(prop) { }
|
292
|
+
}
|
293
|
+
__decorate([
|
294
|
+
__param(0, requestParam(propertyKey, factory)),
|
295
|
+
__metadata("design:type", Function),
|
296
|
+
__metadata("design:paramtypes", [Object]),
|
297
|
+
__metadata("design:returntype", void 0)
|
298
|
+
], Target.prototype, "myMethod", null);
|
299
|
+
const mdMap = RequestDataReflector.getMetadata(Target, 'myMethod');
|
300
|
+
const md = mdMap.get(0);
|
301
|
+
expect(md.source).to.be.eq(RequestDataSource.PARAMS);
|
302
|
+
expect(md.schema).to.be.a('function');
|
303
|
+
expect(md.property).to.be.eq(propertyKey);
|
304
|
+
const res1 = md.schema;
|
305
|
+
const res2 = res1(container);
|
306
|
+
expect(res2).to.be.eql({
|
307
|
+
type: DataType.OBJECT,
|
308
|
+
properties: {
|
309
|
+
[propertyKey]: {
|
310
|
+
type: DataType.STRING,
|
311
|
+
required: true,
|
312
|
+
},
|
313
|
+
},
|
314
|
+
});
|
315
|
+
});
|
266
316
|
});
|
267
317
|
describe('query', function () {
|
268
318
|
it('sets a given "propertyKey" to the target metadata', function () {
|
@@ -343,6 +393,39 @@ describe('requestData', function () {
|
|
343
393
|
property: propertyKey,
|
344
394
|
});
|
345
395
|
});
|
396
|
+
it('sets a given DataSchemaFactory to the target metadata', function () {
|
397
|
+
const container = {};
|
398
|
+
const factory = sc => {
|
399
|
+
expect(sc).to.be.eq(container);
|
400
|
+
return { type: DataType.STRING, required: true };
|
401
|
+
};
|
402
|
+
const propertyKey = 'myPropertyKey';
|
403
|
+
class Target {
|
404
|
+
myMethod(prop) { }
|
405
|
+
}
|
406
|
+
__decorate([
|
407
|
+
__param(0, requestQuery(propertyKey, factory)),
|
408
|
+
__metadata("design:type", Function),
|
409
|
+
__metadata("design:paramtypes", [Object]),
|
410
|
+
__metadata("design:returntype", void 0)
|
411
|
+
], Target.prototype, "myMethod", null);
|
412
|
+
const mdMap = RequestDataReflector.getMetadata(Target, 'myMethod');
|
413
|
+
const md = mdMap.get(0);
|
414
|
+
expect(md.source).to.be.eq(RequestDataSource.QUERY);
|
415
|
+
expect(md.schema).to.be.a('function');
|
416
|
+
expect(md.property).to.be.eq(propertyKey);
|
417
|
+
const res1 = md.schema;
|
418
|
+
const res2 = res1(container);
|
419
|
+
expect(res2).to.be.eql({
|
420
|
+
type: DataType.OBJECT,
|
421
|
+
properties: {
|
422
|
+
[propertyKey]: {
|
423
|
+
type: DataType.STRING,
|
424
|
+
required: true,
|
425
|
+
},
|
426
|
+
},
|
427
|
+
});
|
428
|
+
});
|
346
429
|
});
|
347
430
|
describe('header', function () {
|
348
431
|
it('sets a given "propertyKey" to the target metadata', function () {
|
@@ -423,6 +506,39 @@ describe('requestData', function () {
|
|
423
506
|
property: propertyKey,
|
424
507
|
});
|
425
508
|
});
|
509
|
+
it('sets a given DataSchemaFactory to the target metadata', function () {
|
510
|
+
const container = {};
|
511
|
+
const factory = sc => {
|
512
|
+
expect(sc).to.be.eq(container);
|
513
|
+
return { type: DataType.STRING, required: true };
|
514
|
+
};
|
515
|
+
const propertyKey = 'myPropertyKey';
|
516
|
+
class Target {
|
517
|
+
myMethod(prop) { }
|
518
|
+
}
|
519
|
+
__decorate([
|
520
|
+
__param(0, requestHeader(propertyKey, factory)),
|
521
|
+
__metadata("design:type", Function),
|
522
|
+
__metadata("design:paramtypes", [Object]),
|
523
|
+
__metadata("design:returntype", void 0)
|
524
|
+
], Target.prototype, "myMethod", null);
|
525
|
+
const mdMap = RequestDataReflector.getMetadata(Target, 'myMethod');
|
526
|
+
const md = mdMap.get(0);
|
527
|
+
expect(md.source).to.be.eq(RequestDataSource.HEADERS);
|
528
|
+
expect(md.schema).to.be.a('function');
|
529
|
+
expect(md.property).to.be.eq(propertyKey);
|
530
|
+
const res1 = md.schema;
|
531
|
+
const res2 = res1(container);
|
532
|
+
expect(res2).to.be.eql({
|
533
|
+
type: DataType.OBJECT,
|
534
|
+
properties: {
|
535
|
+
[propertyKey]: {
|
536
|
+
type: DataType.STRING,
|
537
|
+
required: true,
|
538
|
+
},
|
539
|
+
},
|
540
|
+
});
|
541
|
+
});
|
426
542
|
});
|
427
543
|
describe('cookie', function () {
|
428
544
|
it('sets a given "propertyKey" to the target metadata', function () {
|
@@ -503,6 +619,39 @@ describe('requestData', function () {
|
|
503
619
|
property: propertyKey,
|
504
620
|
});
|
505
621
|
});
|
622
|
+
it('sets a given DataSchemaFactory to the target metadata', function () {
|
623
|
+
const container = {};
|
624
|
+
const factory = sc => {
|
625
|
+
expect(sc).to.be.eq(container);
|
626
|
+
return { type: DataType.STRING, required: true };
|
627
|
+
};
|
628
|
+
const propertyKey = 'myPropertyKey';
|
629
|
+
class Target {
|
630
|
+
myMethod(prop) { }
|
631
|
+
}
|
632
|
+
__decorate([
|
633
|
+
__param(0, requestCookie(propertyKey, factory)),
|
634
|
+
__metadata("design:type", Function),
|
635
|
+
__metadata("design:paramtypes", [Object]),
|
636
|
+
__metadata("design:returntype", void 0)
|
637
|
+
], Target.prototype, "myMethod", null);
|
638
|
+
const mdMap = RequestDataReflector.getMetadata(Target, 'myMethod');
|
639
|
+
const md = mdMap.get(0);
|
640
|
+
expect(md.source).to.be.eq(RequestDataSource.COOKIE);
|
641
|
+
expect(md.schema).to.be.a('function');
|
642
|
+
expect(md.property).to.be.eq(propertyKey);
|
643
|
+
const res1 = md.schema;
|
644
|
+
const res2 = res1(container);
|
645
|
+
expect(res2).to.be.eql({
|
646
|
+
type: DataType.OBJECT,
|
647
|
+
properties: {
|
648
|
+
[propertyKey]: {
|
649
|
+
type: DataType.STRING,
|
650
|
+
required: true,
|
651
|
+
},
|
652
|
+
},
|
653
|
+
});
|
654
|
+
});
|
506
655
|
});
|
507
656
|
describe('field', function () {
|
508
657
|
it('sets a given "propertyKey" to the target metadata', function () {
|
@@ -583,6 +732,39 @@ describe('requestData', function () {
|
|
583
732
|
property: propertyKey,
|
584
733
|
});
|
585
734
|
});
|
735
|
+
it('sets a given DataSchemaFactory to the target metadata', function () {
|
736
|
+
const container = {};
|
737
|
+
const factory = sc => {
|
738
|
+
expect(sc).to.be.eq(container);
|
739
|
+
return { type: DataType.STRING, required: true };
|
740
|
+
};
|
741
|
+
const propertyKey = 'myPropertyKey';
|
742
|
+
class Target {
|
743
|
+
myMethod(prop) { }
|
744
|
+
}
|
745
|
+
__decorate([
|
746
|
+
__param(0, requestField(propertyKey, factory)),
|
747
|
+
__metadata("design:type", Function),
|
748
|
+
__metadata("design:paramtypes", [Object]),
|
749
|
+
__metadata("design:returntype", void 0)
|
750
|
+
], Target.prototype, "myMethod", null);
|
751
|
+
const mdMap = RequestDataReflector.getMetadata(Target, 'myMethod');
|
752
|
+
const md = mdMap.get(0);
|
753
|
+
expect(md.source).to.be.eq(RequestDataSource.BODY);
|
754
|
+
expect(md.schema).to.be.a('function');
|
755
|
+
expect(md.property).to.be.eq(propertyKey);
|
756
|
+
const res1 = md.schema;
|
757
|
+
const res2 = res1(container);
|
758
|
+
expect(res2).to.be.eql({
|
759
|
+
type: DataType.OBJECT,
|
760
|
+
properties: {
|
761
|
+
[propertyKey]: {
|
762
|
+
type: DataType.STRING,
|
763
|
+
required: true,
|
764
|
+
},
|
765
|
+
},
|
766
|
+
});
|
767
|
+
});
|
586
768
|
});
|
587
769
|
});
|
588
770
|
});
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { MetadataKey } from '@e22m4u/ts-reflector';
|
2
|
-
import {
|
2
|
+
import { DataSchemaOrFactory } from '../../data-schema-types.js';
|
3
3
|
/**
|
4
4
|
* Request data source.
|
5
5
|
*/
|
@@ -15,7 +15,7 @@ export declare enum RequestDataSource {
|
|
15
15
|
*/
|
16
16
|
export type RequestDataMetadata = {
|
17
17
|
source: RequestDataSource;
|
18
|
-
schema?:
|
18
|
+
schema?: DataSchemaOrFactory;
|
19
19
|
property?: string;
|
20
20
|
};
|
21
21
|
/**
|
@@ -1,9 +1,8 @@
|
|
1
1
|
import { Prototype } from '../../types.js';
|
2
|
-
import {
|
3
|
-
import { DataSchema } from '@e22m4u/ts-data-schema';
|
2
|
+
import { DataSchemaInput } from '../../data-schema-types.js';
|
4
3
|
/**
|
5
4
|
* Response body decorator.
|
6
5
|
*
|
7
6
|
* @param schemaOrType
|
8
7
|
*/
|
9
|
-
export declare function responseBody<T extends object>(
|
8
|
+
export declare function responseBody<T extends object>(schemaInput?: DataSchemaInput): (target: Prototype<T>, propertyKey: string, descriptor: PropertyDescriptor) => void;
|
@@ -6,18 +6,18 @@ import { ResponseBodyReflector } from './response-body-reflector.js';
|
|
6
6
|
*
|
7
7
|
* @param schemaOrType
|
8
8
|
*/
|
9
|
-
export function responseBody(
|
9
|
+
export function responseBody(schemaInput) {
|
10
10
|
return function (target, propertyKey, descriptor) {
|
11
11
|
const decoratorType = getDecoratorTargetType(target, propertyKey, descriptor);
|
12
12
|
if (decoratorType !== DecoratorTargetType.INSTANCE_METHOD)
|
13
13
|
throw new Error('@responseBody decorator is only supported on an instance method.');
|
14
|
-
let
|
15
|
-
if (typeof
|
16
|
-
|
14
|
+
let schemaOrFactory;
|
15
|
+
if (typeof schemaInput === 'function' || typeof schemaInput === 'object') {
|
16
|
+
schemaOrFactory = schemaInput;
|
17
17
|
}
|
18
|
-
else if (typeof
|
19
|
-
|
18
|
+
else if (typeof schemaInput === 'string') {
|
19
|
+
schemaOrFactory = { type: schemaInput };
|
20
20
|
}
|
21
|
-
ResponseBodyReflector.setMetadata(
|
21
|
+
ResponseBodyReflector.setMetadata(schemaOrFactory ? { schema: schemaOrFactory } : {}, target.constructor, propertyKey);
|
22
22
|
};
|
23
23
|
}
|
@@ -38,7 +38,7 @@ describe('responseBody', function () {
|
|
38
38
|
const res = ResponseBodyReflector.getMetadata(Target);
|
39
39
|
expect(res.get('myMethod')).to.be.eql({ schema: { type: DataType.STRING } });
|
40
40
|
});
|
41
|
-
it('sets the given
|
41
|
+
it('sets the given DataSchema to the target metadata', function () {
|
42
42
|
const schema = {
|
43
43
|
type: DataType.OBJECT,
|
44
44
|
properties: {
|
@@ -58,4 +58,24 @@ describe('responseBody', function () {
|
|
58
58
|
const res = ResponseBodyReflector.getMetadata(Target);
|
59
59
|
expect(res.get('myMethod')).to.be.eql({ schema });
|
60
60
|
});
|
61
|
+
it('sets the given DataSchemaFactory to the target metadata', function () {
|
62
|
+
const factory = () => ({
|
63
|
+
type: DataType.OBJECT,
|
64
|
+
properties: {
|
65
|
+
foo: { type: DataType.STRING },
|
66
|
+
bar: { type: DataType.NUMBER },
|
67
|
+
},
|
68
|
+
});
|
69
|
+
class Target {
|
70
|
+
myMethod() { }
|
71
|
+
}
|
72
|
+
__decorate([
|
73
|
+
responseBody(factory),
|
74
|
+
__metadata("design:type", Function),
|
75
|
+
__metadata("design:paramtypes", []),
|
76
|
+
__metadata("design:returntype", void 0)
|
77
|
+
], Target.prototype, "myMethod", null);
|
78
|
+
const res = ResponseBodyReflector.getMetadata(Target);
|
79
|
+
expect(res.get('myMethod')).to.be.eql({ schema: factory });
|
80
|
+
});
|
61
81
|
});
|
@@ -1,10 +1,10 @@
|
|
1
1
|
import { MetadataKey } from '@e22m4u/ts-reflector';
|
2
|
-
import {
|
2
|
+
import { DataSchemaOrFactory } from '../../data-schema-types.js';
|
3
3
|
/**
|
4
4
|
* Response body metadata.
|
5
5
|
*/
|
6
6
|
export type ResponseBodyMetadata = {
|
7
|
-
schema?:
|
7
|
+
schema?: DataSchemaOrFactory;
|
8
8
|
};
|
9
9
|
/**
|
10
10
|
* Response body metadata map.
|