@e22m4u/ts-rest-router 0.0.2
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/.c8rc +9 -0
- package/.commitlintrc +5 -0
- package/.editorconfig +13 -0
- package/.husky/commit-msg +1 -0
- package/.husky/pre-commit +6 -0
- package/.mocharc.json +5 -0
- package/.prettierrc +7 -0
- package/LICENSE +21 -0
- package/README-ru.md +41 -0
- package/README.md +41 -0
- package/build-cjs.js +16 -0
- package/dist/cjs/index.cjs +692 -0
- package/dist/esm/controller-registry.d.ts +65 -0
- package/dist/esm/controller-registry.js +281 -0
- package/dist/esm/controller-registry.spec.d.ts +1 -0
- package/dist/esm/controller-registry.spec.js +719 -0
- package/dist/esm/debuggable-service.d.ts +18 -0
- package/dist/esm/debuggable-service.js +23 -0
- package/dist/esm/debuggable-service.spec.d.ts +1 -0
- package/dist/esm/debuggable-service.spec.js +16 -0
- package/dist/esm/decorators/action/action-decorator.d.ts +53 -0
- package/dist/esm/decorators/action/action-decorator.js +66 -0
- package/dist/esm/decorators/action/action-decorator.spec.d.ts +1 -0
- package/dist/esm/decorators/action/action-decorator.spec.js +59 -0
- package/dist/esm/decorators/action/action-metadata.d.ts +23 -0
- package/dist/esm/decorators/action/action-metadata.js +5 -0
- package/dist/esm/decorators/action/action-reflector.d.ts +22 -0
- package/dist/esm/decorators/action/action-reflector.js +29 -0
- package/dist/esm/decorators/action/action-reflector.spec.d.ts +1 -0
- package/dist/esm/decorators/action/action-reflector.spec.js +84 -0
- package/dist/esm/decorators/action/index.d.ts +3 -0
- package/dist/esm/decorators/action/index.js +3 -0
- package/dist/esm/decorators/controller/controller-decorator.d.ts +13 -0
- package/dist/esm/decorators/controller/controller-decorator.js +20 -0
- package/dist/esm/decorators/controller/controller-decorator.spec.d.ts +1 -0
- package/dist/esm/decorators/controller/controller-decorator.spec.js +53 -0
- package/dist/esm/decorators/controller/controller-metadata.d.ts +17 -0
- package/dist/esm/decorators/controller/controller-metadata.js +5 -0
- package/dist/esm/decorators/controller/controller-reflector.d.ts +20 -0
- package/dist/esm/decorators/controller/controller-reflector.js +24 -0
- package/dist/esm/decorators/controller/controller-reflector.spec.d.ts +1 -0
- package/dist/esm/decorators/controller/controller-reflector.spec.js +45 -0
- package/dist/esm/decorators/controller/index.d.ts +3 -0
- package/dist/esm/decorators/controller/index.js +3 -0
- package/dist/esm/decorators/index.d.ts +4 -0
- package/dist/esm/decorators/index.js +4 -0
- package/dist/esm/decorators/request-context/index.d.ts +3 -0
- package/dist/esm/decorators/request-context/index.js +3 -0
- package/dist/esm/decorators/request-context/request-context-decorator.d.ts +17 -0
- package/dist/esm/decorators/request-context/request-context-decorator.js +32 -0
- package/dist/esm/decorators/request-context/request-context-decorator.spec.d.ts +1 -0
- package/dist/esm/decorators/request-context/request-context-decorator.spec.js +59 -0
- package/dist/esm/decorators/request-context/request-context-metadata.d.ts +17 -0
- package/dist/esm/decorators/request-context/request-context-metadata.js +5 -0
- package/dist/esm/decorators/request-context/request-context-reflector.d.ts +24 -0
- package/dist/esm/decorators/request-context/request-context-reflector.js +31 -0
- package/dist/esm/decorators/request-context/request-context-reflector.spec.d.ts +1 -0
- package/dist/esm/decorators/request-context/request-context-reflector.spec.js +59 -0
- package/dist/esm/decorators/request-data/index.d.ts +3 -0
- package/dist/esm/decorators/request-data/index.js +3 -0
- package/dist/esm/decorators/request-data/request-data-decorator.d.ts +28 -0
- package/dist/esm/decorators/request-data/request-data-decorator.js +84 -0
- package/dist/esm/decorators/request-data/request-data-decorator.spec.d.ts +1 -0
- package/dist/esm/decorators/request-data/request-data-decorator.spec.js +534 -0
- package/dist/esm/decorators/request-data/request-data-metadata.d.ts +29 -0
- package/dist/esm/decorators/request-data/request-data-metadata.js +16 -0
- package/dist/esm/decorators/request-data/request-data-reflector.d.ts +24 -0
- package/dist/esm/decorators/request-data/request-data-reflector.js +31 -0
- package/dist/esm/decorators/request-data/request-data-reflector.spec.d.ts +1 -0
- package/dist/esm/decorators/request-data/request-data-reflector.spec.js +60 -0
- package/dist/esm/errors/index.d.ts +1 -0
- package/dist/esm/errors/index.js +1 -0
- package/dist/esm/errors/not-a-controller-error.d.ts +12 -0
- package/dist/esm/errors/not-a-controller-error.js +14 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/rest-router.d.ts +19 -0
- package/dist/esm/rest-router.js +24 -0
- package/dist/esm/types.d.ts +57 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/utils/capitalize.d.ts +6 -0
- package/dist/esm/utils/capitalize.js +8 -0
- package/dist/esm/utils/capitalize.spec.d.ts +1 -0
- package/dist/esm/utils/capitalize.spec.js +8 -0
- package/dist/esm/utils/create-debugger.d.ts +11 -0
- package/dist/esm/utils/create-debugger.js +15 -0
- package/dist/esm/utils/create-debugger.spec.d.ts +1 -0
- package/dist/esm/utils/create-debugger.spec.js +8 -0
- package/dist/esm/utils/create-error.d.ts +10 -0
- package/dist/esm/utils/create-error.js +13 -0
- package/dist/esm/utils/create-error.spec.d.ts +1 -0
- package/dist/esm/utils/create-error.spec.js +8 -0
- package/dist/esm/utils/index.d.ts +4 -0
- package/dist/esm/utils/index.js +4 -0
- package/dist/esm/utils/to-camel-case.d.ts +6 -0
- package/dist/esm/utils/to-camel-case.js +11 -0
- package/dist/esm/utils/to-camel-case.spec.d.ts +1 -0
- package/dist/esm/utils/to-camel-case.spec.js +10 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/eslint.config.js +43 -0
- package/package.json +74 -0
- package/src/controller-registry.spec.ts +592 -0
- package/src/controller-registry.ts +355 -0
- package/src/debuggable-service.spec.ts +18 -0
- package/src/debuggable-service.ts +27 -0
- package/src/decorators/action/action-decorator.spec.ts +42 -0
- package/src/decorators/action/action-decorator.ts +100 -0
- package/src/decorators/action/action-metadata.ts +28 -0
- package/src/decorators/action/action-reflector.spec.ts +84 -0
- package/src/decorators/action/action-reflector.ts +38 -0
- package/src/decorators/action/index.ts +3 -0
- package/src/decorators/controller/controller-decorator.spec.ts +41 -0
- package/src/decorators/controller/controller-decorator.ts +29 -0
- package/src/decorators/controller/controller-metadata.ts +21 -0
- package/src/decorators/controller/controller-reflector.spec.ts +45 -0
- package/src/decorators/controller/controller-reflector.ts +28 -0
- package/src/decorators/controller/index.ts +3 -0
- package/src/decorators/index.ts +4 -0
- package/src/decorators/request-context/index.ts +3 -0
- package/src/decorators/request-context/request-context-decorator.spec.ts +41 -0
- package/src/decorators/request-context/request-context-decorator.ts +57 -0
- package/src/decorators/request-context/request-context-metadata.ts +21 -0
- package/src/decorators/request-context/request-context-reflector.spec.ts +77 -0
- package/src/decorators/request-context/request-context-reflector.ts +57 -0
- package/src/decorators/request-data/index.ts +3 -0
- package/src/decorators/request-data/request-data-decorator.spec.ts +477 -0
- package/src/decorators/request-data/request-data-decorator.ts +106 -0
- package/src/decorators/request-data/request-data-metadata.ts +34 -0
- package/src/decorators/request-data/request-data-reflector.spec.ts +78 -0
- package/src/decorators/request-data/request-data-reflector.ts +57 -0
- package/src/errors/index.ts +1 -0
- package/src/errors/not-a-controller-error.ts +15 -0
- package/src/index.ts +5 -0
- package/src/rest-router.ts +31 -0
- package/src/types.ts +59 -0
- package/src/utils/capitalize.spec.ts +9 -0
- package/src/utils/capitalize.ts +8 -0
- package/src/utils/create-debugger.spec.ts +9 -0
- package/src/utils/create-debugger.ts +21 -0
- package/src/utils/create-error.spec.ts +9 -0
- package/src/utils/create-error.ts +19 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/to-camel-case.spec.ts +11 -0
- package/src/utils/to-camel-case.ts +11 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
+
import {expect} from 'chai';
|
|
3
|
+
import {DataType} from '@e22m4u/ts-data-schema';
|
|
4
|
+
import {body} from './request-data-decorator.js';
|
|
5
|
+
import {param} from './request-data-decorator.js';
|
|
6
|
+
import {query} from './request-data-decorator.js';
|
|
7
|
+
import {cookie} from './request-data-decorator.js';
|
|
8
|
+
import {header} from './request-data-decorator.js';
|
|
9
|
+
import {params} from './request-data-decorator.js';
|
|
10
|
+
import {queries} from './request-data-decorator.js';
|
|
11
|
+
import {cookies} from './request-data-decorator.js';
|
|
12
|
+
import {headers} from './request-data-decorator.js';
|
|
13
|
+
import {bodyParam} from './request-data-decorator.js';
|
|
14
|
+
import {requestData} from './request-data-decorator.js';
|
|
15
|
+
import {RequestDataSource} from './request-data-metadata.js';
|
|
16
|
+
import {RequestDataMetadata} from './request-data-metadata.js';
|
|
17
|
+
import {RequestDataReflector} from './request-data-reflector.js';
|
|
18
|
+
|
|
19
|
+
describe('requestData', function () {
|
|
20
|
+
it('sets a given argument to the target metadata', function () {
|
|
21
|
+
const md: RequestDataMetadata = {
|
|
22
|
+
source: RequestDataSource.PARAMS,
|
|
23
|
+
customOption: 'myOption',
|
|
24
|
+
};
|
|
25
|
+
class Target {
|
|
26
|
+
myMethod(
|
|
27
|
+
@requestData(md)
|
|
28
|
+
prop: unknown,
|
|
29
|
+
) {}
|
|
30
|
+
}
|
|
31
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
32
|
+
expect(res.get(0)).to.be.eql(md);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
describe('request data by a given source', function () {
|
|
36
|
+
describe('params', function () {
|
|
37
|
+
it('sets metadata with specified source and schema', function () {
|
|
38
|
+
class Target {
|
|
39
|
+
myMethod(
|
|
40
|
+
@params()
|
|
41
|
+
prop: unknown,
|
|
42
|
+
) {}
|
|
43
|
+
}
|
|
44
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
45
|
+
expect(res.get(0)).to.be.eql({
|
|
46
|
+
source: RequestDataSource.PARAMS,
|
|
47
|
+
schema: {type: DataType.OBJECT},
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('queries', function () {
|
|
53
|
+
it('sets metadata with specified source and schema', function () {
|
|
54
|
+
class Target {
|
|
55
|
+
myMethod(
|
|
56
|
+
@queries()
|
|
57
|
+
prop: unknown,
|
|
58
|
+
) {}
|
|
59
|
+
}
|
|
60
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
61
|
+
expect(res.get(0)).to.be.eql({
|
|
62
|
+
source: RequestDataSource.QUERY,
|
|
63
|
+
schema: {type: DataType.OBJECT},
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('headers', function () {
|
|
69
|
+
it('sets metadata with specified source and schema', function () {
|
|
70
|
+
class Target {
|
|
71
|
+
myMethod(
|
|
72
|
+
@headers()
|
|
73
|
+
prop: unknown,
|
|
74
|
+
) {}
|
|
75
|
+
}
|
|
76
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
77
|
+
expect(res.get(0)).to.be.eql({
|
|
78
|
+
source: RequestDataSource.HEADERS,
|
|
79
|
+
schema: {type: DataType.OBJECT},
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe('cookies', function () {
|
|
85
|
+
it('sets metadata with specified source and schema', function () {
|
|
86
|
+
class Target {
|
|
87
|
+
myMethod(
|
|
88
|
+
@cookies()
|
|
89
|
+
prop: unknown,
|
|
90
|
+
) {}
|
|
91
|
+
}
|
|
92
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
93
|
+
expect(res.get(0)).to.be.eql({
|
|
94
|
+
source: RequestDataSource.COOKIE,
|
|
95
|
+
schema: {type: DataType.OBJECT},
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe('body', function () {
|
|
101
|
+
it('sets metadata with specified source and schema', function () {
|
|
102
|
+
class Target {
|
|
103
|
+
myMethod(
|
|
104
|
+
@body()
|
|
105
|
+
prop: unknown,
|
|
106
|
+
) {}
|
|
107
|
+
}
|
|
108
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
109
|
+
expect(res.get(0)).to.be.eql({
|
|
110
|
+
source: RequestDataSource.BODY,
|
|
111
|
+
schema: {type: DataType.ANY},
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('sets a given DataType to the target metadata', function () {
|
|
116
|
+
class Target {
|
|
117
|
+
myMethod(
|
|
118
|
+
@body(DataType.STRING)
|
|
119
|
+
prop: unknown,
|
|
120
|
+
) {}
|
|
121
|
+
}
|
|
122
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
123
|
+
expect(res.get(0)).to.be.eql({
|
|
124
|
+
source: RequestDataSource.BODY,
|
|
125
|
+
schema: {type: DataType.STRING},
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('set a given DataSchema to the target metadata', function () {
|
|
130
|
+
const schema = {type: DataType.STRING, required: true};
|
|
131
|
+
class Target {
|
|
132
|
+
myMethod(
|
|
133
|
+
@body(schema)
|
|
134
|
+
prop: unknown,
|
|
135
|
+
) {}
|
|
136
|
+
}
|
|
137
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
138
|
+
expect(res.get(0)).to.be.eql({
|
|
139
|
+
source: RequestDataSource.BODY,
|
|
140
|
+
schema,
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
describe('request data piece by a given property key', function () {
|
|
147
|
+
describe('param', function () {
|
|
148
|
+
it('sets a given "propertyKey" to the target metadata', function () {
|
|
149
|
+
class Target {
|
|
150
|
+
myMethod(
|
|
151
|
+
@param('myPropertyKey')
|
|
152
|
+
prop: unknown,
|
|
153
|
+
) {}
|
|
154
|
+
}
|
|
155
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
156
|
+
expect(res.get(0)).to.be.eql({
|
|
157
|
+
source: RequestDataSource.PARAMS,
|
|
158
|
+
schema: {type: DataType.OBJECT},
|
|
159
|
+
property: 'myPropertyKey',
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('sets a given DataType as property type', function () {
|
|
164
|
+
const propertyKey = 'myPropertyKey';
|
|
165
|
+
const propertyType = DataType.STRING;
|
|
166
|
+
class Target {
|
|
167
|
+
myMethod(
|
|
168
|
+
@param(propertyKey, propertyType)
|
|
169
|
+
prop: unknown,
|
|
170
|
+
) {}
|
|
171
|
+
}
|
|
172
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
173
|
+
expect(res.get(0)).to.be.eql({
|
|
174
|
+
source: RequestDataSource.PARAMS,
|
|
175
|
+
schema: {
|
|
176
|
+
type: DataType.OBJECT,
|
|
177
|
+
properties: {
|
|
178
|
+
[propertyKey]: {
|
|
179
|
+
type: propertyType,
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
property: propertyKey,
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('sets a given DataSchema as property schema', function () {
|
|
188
|
+
const schema = {
|
|
189
|
+
type: DataType.STRING,
|
|
190
|
+
required: true,
|
|
191
|
+
};
|
|
192
|
+
const propertyKey = 'myPropertyKey';
|
|
193
|
+
class Target {
|
|
194
|
+
myMethod(
|
|
195
|
+
@param(propertyKey, schema)
|
|
196
|
+
prop: unknown,
|
|
197
|
+
) {}
|
|
198
|
+
}
|
|
199
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
200
|
+
expect(res.get(0)).to.be.eql({
|
|
201
|
+
source: RequestDataSource.PARAMS,
|
|
202
|
+
schema: {
|
|
203
|
+
type: DataType.OBJECT,
|
|
204
|
+
properties: {
|
|
205
|
+
[propertyKey]: schema,
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
property: propertyKey,
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
describe('query', function () {
|
|
214
|
+
it('sets a given "propertyKey" to the target metadata', function () {
|
|
215
|
+
class Target {
|
|
216
|
+
myMethod(
|
|
217
|
+
@query('myPropertyKey')
|
|
218
|
+
prop: unknown,
|
|
219
|
+
) {}
|
|
220
|
+
}
|
|
221
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
222
|
+
expect(res.get(0)).to.be.eql({
|
|
223
|
+
source: RequestDataSource.QUERY,
|
|
224
|
+
schema: {type: DataType.OBJECT},
|
|
225
|
+
property: 'myPropertyKey',
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it('sets a given DataType as property type', function () {
|
|
230
|
+
const propertyKey = 'myPropertyKey';
|
|
231
|
+
const propertyType = DataType.STRING;
|
|
232
|
+
class Target {
|
|
233
|
+
myMethod(
|
|
234
|
+
@query(propertyKey, propertyType)
|
|
235
|
+
prop: unknown,
|
|
236
|
+
) {}
|
|
237
|
+
}
|
|
238
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
239
|
+
expect(res.get(0)).to.be.eql({
|
|
240
|
+
source: RequestDataSource.QUERY,
|
|
241
|
+
schema: {
|
|
242
|
+
type: DataType.OBJECT,
|
|
243
|
+
properties: {
|
|
244
|
+
[propertyKey]: {
|
|
245
|
+
type: propertyType,
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
property: propertyKey,
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('sets a given DataSchema as property schema', function () {
|
|
254
|
+
const schema = {
|
|
255
|
+
type: DataType.STRING,
|
|
256
|
+
required: true,
|
|
257
|
+
};
|
|
258
|
+
const propertyKey = 'myPropertyKey';
|
|
259
|
+
class Target {
|
|
260
|
+
myMethod(
|
|
261
|
+
@query(propertyKey, schema)
|
|
262
|
+
prop: unknown,
|
|
263
|
+
) {}
|
|
264
|
+
}
|
|
265
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
266
|
+
expect(res.get(0)).to.be.eql({
|
|
267
|
+
source: RequestDataSource.QUERY,
|
|
268
|
+
schema: {
|
|
269
|
+
type: DataType.OBJECT,
|
|
270
|
+
properties: {
|
|
271
|
+
[propertyKey]: schema,
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
property: propertyKey,
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
describe('header', function () {
|
|
280
|
+
it('sets a given "propertyKey" to the target metadata', function () {
|
|
281
|
+
class Target {
|
|
282
|
+
myMethod(
|
|
283
|
+
@header('myPropertyKey')
|
|
284
|
+
prop: unknown,
|
|
285
|
+
) {}
|
|
286
|
+
}
|
|
287
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
288
|
+
expect(res.get(0)).to.be.eql({
|
|
289
|
+
source: RequestDataSource.HEADERS,
|
|
290
|
+
schema: {type: DataType.OBJECT},
|
|
291
|
+
property: 'myPropertyKey',
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('sets a given DataType as property type', function () {
|
|
296
|
+
const propertyKey = 'myPropertyKey';
|
|
297
|
+
const propertyType = DataType.STRING;
|
|
298
|
+
class Target {
|
|
299
|
+
myMethod(
|
|
300
|
+
@header(propertyKey, propertyType)
|
|
301
|
+
prop: unknown,
|
|
302
|
+
) {}
|
|
303
|
+
}
|
|
304
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
305
|
+
expect(res.get(0)).to.be.eql({
|
|
306
|
+
source: RequestDataSource.HEADERS,
|
|
307
|
+
schema: {
|
|
308
|
+
type: DataType.OBJECT,
|
|
309
|
+
properties: {
|
|
310
|
+
[propertyKey]: {
|
|
311
|
+
type: propertyType,
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
property: propertyKey,
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it('sets a given DataSchema as property schema', function () {
|
|
320
|
+
const schema = {
|
|
321
|
+
type: DataType.STRING,
|
|
322
|
+
required: true,
|
|
323
|
+
};
|
|
324
|
+
const propertyKey = 'myPropertyKey';
|
|
325
|
+
class Target {
|
|
326
|
+
myMethod(
|
|
327
|
+
@header(propertyKey, schema)
|
|
328
|
+
prop: unknown,
|
|
329
|
+
) {}
|
|
330
|
+
}
|
|
331
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
332
|
+
expect(res.get(0)).to.be.eql({
|
|
333
|
+
source: RequestDataSource.HEADERS,
|
|
334
|
+
schema: {
|
|
335
|
+
type: DataType.OBJECT,
|
|
336
|
+
properties: {
|
|
337
|
+
[propertyKey]: schema,
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
property: propertyKey,
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
describe('cookie', function () {
|
|
346
|
+
it('sets a given "propertyKey" to the target metadata', function () {
|
|
347
|
+
class Target {
|
|
348
|
+
myMethod(
|
|
349
|
+
@cookie('myPropertyKey')
|
|
350
|
+
prop: unknown,
|
|
351
|
+
) {}
|
|
352
|
+
}
|
|
353
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
354
|
+
expect(res.get(0)).to.be.eql({
|
|
355
|
+
source: RequestDataSource.COOKIE,
|
|
356
|
+
schema: {type: DataType.OBJECT},
|
|
357
|
+
property: 'myPropertyKey',
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
it('sets a given DataType as property type', function () {
|
|
362
|
+
const propertyKey = 'myPropertyKey';
|
|
363
|
+
const propertyType = DataType.STRING;
|
|
364
|
+
class Target {
|
|
365
|
+
myMethod(
|
|
366
|
+
@cookie(propertyKey, propertyType)
|
|
367
|
+
prop: unknown,
|
|
368
|
+
) {}
|
|
369
|
+
}
|
|
370
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
371
|
+
expect(res.get(0)).to.be.eql({
|
|
372
|
+
source: RequestDataSource.COOKIE,
|
|
373
|
+
schema: {
|
|
374
|
+
type: DataType.OBJECT,
|
|
375
|
+
properties: {
|
|
376
|
+
[propertyKey]: {
|
|
377
|
+
type: propertyType,
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
},
|
|
381
|
+
property: propertyKey,
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
it('sets a given DataSchema as property schema', function () {
|
|
386
|
+
const schema = {
|
|
387
|
+
type: DataType.STRING,
|
|
388
|
+
required: true,
|
|
389
|
+
};
|
|
390
|
+
const propertyKey = 'myPropertyKey';
|
|
391
|
+
class Target {
|
|
392
|
+
myMethod(
|
|
393
|
+
@cookie(propertyKey, schema)
|
|
394
|
+
prop: unknown,
|
|
395
|
+
) {}
|
|
396
|
+
}
|
|
397
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
398
|
+
expect(res.get(0)).to.be.eql({
|
|
399
|
+
source: RequestDataSource.COOKIE,
|
|
400
|
+
schema: {
|
|
401
|
+
type: DataType.OBJECT,
|
|
402
|
+
properties: {
|
|
403
|
+
[propertyKey]: schema,
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
property: propertyKey,
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
describe('bodyParam', function () {
|
|
412
|
+
it('sets a given "propertyKey" to the target metadata', function () {
|
|
413
|
+
class Target {
|
|
414
|
+
myMethod(
|
|
415
|
+
@bodyParam('myPropertyKey')
|
|
416
|
+
prop: unknown,
|
|
417
|
+
) {}
|
|
418
|
+
}
|
|
419
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
420
|
+
expect(res.get(0)).to.be.eql({
|
|
421
|
+
source: RequestDataSource.BODY,
|
|
422
|
+
schema: {type: DataType.OBJECT},
|
|
423
|
+
property: 'myPropertyKey',
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
it('sets a given DataType as property type', function () {
|
|
428
|
+
const propertyKey = 'myPropertyKey';
|
|
429
|
+
const propertyType = DataType.STRING;
|
|
430
|
+
class Target {
|
|
431
|
+
myMethod(
|
|
432
|
+
@bodyParam(propertyKey, propertyType)
|
|
433
|
+
prop: unknown,
|
|
434
|
+
) {}
|
|
435
|
+
}
|
|
436
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
437
|
+
expect(res.get(0)).to.be.eql({
|
|
438
|
+
source: RequestDataSource.BODY,
|
|
439
|
+
schema: {
|
|
440
|
+
type: DataType.OBJECT,
|
|
441
|
+
properties: {
|
|
442
|
+
[propertyKey]: {
|
|
443
|
+
type: propertyType,
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
property: propertyKey,
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it('sets a given DataSchema as property schema', function () {
|
|
452
|
+
const schema = {
|
|
453
|
+
type: DataType.STRING,
|
|
454
|
+
required: true,
|
|
455
|
+
};
|
|
456
|
+
const propertyKey = 'myPropertyKey';
|
|
457
|
+
class Target {
|
|
458
|
+
myMethod(
|
|
459
|
+
@bodyParam(propertyKey, schema)
|
|
460
|
+
prop: unknown,
|
|
461
|
+
) {}
|
|
462
|
+
}
|
|
463
|
+
const res = RequestDataReflector.getMetadata(Target, 'myMethod');
|
|
464
|
+
expect(res.get(0)).to.be.eql({
|
|
465
|
+
source: RequestDataSource.BODY,
|
|
466
|
+
schema: {
|
|
467
|
+
type: DataType.OBJECT,
|
|
468
|
+
properties: {
|
|
469
|
+
[propertyKey]: schema,
|
|
470
|
+
},
|
|
471
|
+
},
|
|
472
|
+
property: propertyKey,
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import {NoUndef} from '../../types.js';
|
|
2
|
+
import {Prototype} from '../../types.js';
|
|
3
|
+
import {Constructor} from '../../types.js';
|
|
4
|
+
import {DataType} from '@e22m4u/ts-data-schema';
|
|
5
|
+
import {DataSchema} from '@e22m4u/ts-data-schema';
|
|
6
|
+
import {DecoratorTargetType} from '@e22m4u/ts-reflector';
|
|
7
|
+
import {getDecoratorTargetType} from '@e22m4u/ts-reflector';
|
|
8
|
+
import {RequestDataSource} from './request-data-metadata.js';
|
|
9
|
+
import {RequestDataMetadata} from './request-data-metadata.js';
|
|
10
|
+
import {RequestDataReflector} from './request-data-reflector.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Request data decorator.
|
|
14
|
+
*
|
|
15
|
+
* @param metadata
|
|
16
|
+
*/
|
|
17
|
+
export function requestData<T extends object>(metadata: RequestDataMetadata) {
|
|
18
|
+
return function (
|
|
19
|
+
target: Prototype<T>,
|
|
20
|
+
propertyKey: string,
|
|
21
|
+
indexOrDescriptor: number,
|
|
22
|
+
) {
|
|
23
|
+
const decoratorType = getDecoratorTargetType(
|
|
24
|
+
target,
|
|
25
|
+
propertyKey,
|
|
26
|
+
indexOrDescriptor,
|
|
27
|
+
);
|
|
28
|
+
if (decoratorType !== DecoratorTargetType.INSTANCE_METHOD_PARAMETER)
|
|
29
|
+
throw new Error(
|
|
30
|
+
'@requestData decorator is only supported ' +
|
|
31
|
+
'on an instance method parameter.',
|
|
32
|
+
);
|
|
33
|
+
RequestDataReflector.setMetadata(
|
|
34
|
+
metadata,
|
|
35
|
+
target.constructor as Constructor<T>,
|
|
36
|
+
indexOrDescriptor,
|
|
37
|
+
propertyKey,
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Create data decorator.
|
|
44
|
+
*
|
|
45
|
+
* @param source
|
|
46
|
+
*/
|
|
47
|
+
function createDataDecorator(source: RequestDataSource) {
|
|
48
|
+
return function () {
|
|
49
|
+
const schema = {type: DataType.OBJECT};
|
|
50
|
+
return requestData({schema, source});
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Create property decorator.
|
|
56
|
+
*
|
|
57
|
+
* @param source
|
|
58
|
+
*/
|
|
59
|
+
function createPropertyDecorator(source: RequestDataSource) {
|
|
60
|
+
return function (propertyKey: string, schemaOrType?: DataSchema | DataType) {
|
|
61
|
+
const properties = {} as NoUndef<DataSchema['properties']>;
|
|
62
|
+
const rootSchema: DataSchema = {type: DataType.OBJECT};
|
|
63
|
+
if (typeof schemaOrType === 'object') {
|
|
64
|
+
properties[propertyKey] = schemaOrType;
|
|
65
|
+
rootSchema.properties = properties;
|
|
66
|
+
} else if (typeof schemaOrType === 'string') {
|
|
67
|
+
properties[propertyKey] = {type: schemaOrType};
|
|
68
|
+
rootSchema.properties = properties;
|
|
69
|
+
}
|
|
70
|
+
return requestData({
|
|
71
|
+
source: source,
|
|
72
|
+
schema: rootSchema,
|
|
73
|
+
property: propertyKey,
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Decorator aliases.
|
|
80
|
+
*/
|
|
81
|
+
export const params = createDataDecorator(RequestDataSource.PARAMS);
|
|
82
|
+
export const param = createPropertyDecorator(RequestDataSource.PARAMS);
|
|
83
|
+
export const queries = createDataDecorator(RequestDataSource.QUERY);
|
|
84
|
+
export const query = createPropertyDecorator(RequestDataSource.QUERY);
|
|
85
|
+
export const headers = createDataDecorator(RequestDataSource.HEADERS);
|
|
86
|
+
export const header = createPropertyDecorator(RequestDataSource.HEADERS);
|
|
87
|
+
export const cookies = createDataDecorator(RequestDataSource.COOKIE);
|
|
88
|
+
export const cookie = createPropertyDecorator(RequestDataSource.COOKIE);
|
|
89
|
+
export const bodyParam = createPropertyDecorator(RequestDataSource.BODY);
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Request body decorator.
|
|
93
|
+
*
|
|
94
|
+
* @param schemaOrType
|
|
95
|
+
*/
|
|
96
|
+
export function body(schemaOrType?: DataSchema | DataType) {
|
|
97
|
+
let schema: DataSchema;
|
|
98
|
+
if (typeof schemaOrType === 'object') {
|
|
99
|
+
schema = schemaOrType;
|
|
100
|
+
} else if (typeof schemaOrType === 'string') {
|
|
101
|
+
schema = {type: schemaOrType};
|
|
102
|
+
} else {
|
|
103
|
+
schema = {type: DataType.ANY};
|
|
104
|
+
}
|
|
105
|
+
return requestData({schema, source: RequestDataSource.BODY});
|
|
106
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {DataSchema} from '@e22m4u/ts-data-schema';
|
|
2
|
+
import {MetadataKey} from '@e22m4u/ts-reflector';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Request data source.
|
|
6
|
+
*/
|
|
7
|
+
export enum RequestDataSource {
|
|
8
|
+
PARAMS = 'params',
|
|
9
|
+
QUERY = 'query',
|
|
10
|
+
HEADERS = 'headers',
|
|
11
|
+
COOKIE = 'cookie',
|
|
12
|
+
BODY = 'body',
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Request data metadata.
|
|
17
|
+
*/
|
|
18
|
+
export type RequestDataMetadata = {
|
|
19
|
+
source: RequestDataSource;
|
|
20
|
+
schema?: DataSchema;
|
|
21
|
+
property?: string;
|
|
22
|
+
[option: string]: unknown | undefined;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Request data metadata map.
|
|
27
|
+
*/
|
|
28
|
+
export type RequestDataMetadataMap = Map<number, RequestDataMetadata>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Request data metadata key.
|
|
32
|
+
*/
|
|
33
|
+
export const REQUEST_DATA_METADATA_KEY =
|
|
34
|
+
new MetadataKey<RequestDataMetadataMap>('requestDataMetadataKey');
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {describe} from 'mocha';
|
|
3
|
+
import {Reflector} from '@e22m4u/ts-reflector';
|
|
4
|
+
import {RequestDataSource} from './request-data-metadata.js';
|
|
5
|
+
import {RequestDataMetadata} from './request-data-metadata.js';
|
|
6
|
+
import {RequestDataReflector} from './request-data-reflector.js';
|
|
7
|
+
import {REQUEST_DATA_METADATA_KEY} from './request-data-metadata.js';
|
|
8
|
+
|
|
9
|
+
describe('RequestDataReflector', function () {
|
|
10
|
+
describe('setMetadata', function () {
|
|
11
|
+
it('sets a given value as target metadata', function () {
|
|
12
|
+
class Target {}
|
|
13
|
+
const md1 = {source: RequestDataSource.PARAMS};
|
|
14
|
+
const md2 = {source: RequestDataSource.QUERY};
|
|
15
|
+
RequestDataReflector.setMetadata(md1, Target, 0, 'propertyKey');
|
|
16
|
+
RequestDataReflector.setMetadata(md2, Target, 1, 'propertyKey');
|
|
17
|
+
const res = Reflector.getOwnMetadata(
|
|
18
|
+
REQUEST_DATA_METADATA_KEY,
|
|
19
|
+
Target,
|
|
20
|
+
'propertyKey',
|
|
21
|
+
);
|
|
22
|
+
expect(res).to.be.instanceof(Map);
|
|
23
|
+
expect(res!.get(0)).to.be.eq(md1);
|
|
24
|
+
expect(res!.get(1)).to.be.eq(md2);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('overrides existing metadata', function () {
|
|
28
|
+
class Target {}
|
|
29
|
+
const md1 = {source: RequestDataSource.PARAMS};
|
|
30
|
+
const md2 = {source: RequestDataSource.QUERY};
|
|
31
|
+
RequestDataReflector.setMetadata(md1, Target, 0, 'propertyKey');
|
|
32
|
+
const res1 = Reflector.getOwnMetadata(
|
|
33
|
+
REQUEST_DATA_METADATA_KEY,
|
|
34
|
+
Target,
|
|
35
|
+
'propertyKey',
|
|
36
|
+
);
|
|
37
|
+
expect(res1).to.be.instanceof(Map);
|
|
38
|
+
expect(res1!.get(0)).to.be.eq(md1);
|
|
39
|
+
RequestDataReflector.setMetadata(md2, Target, 0, 'propertyKey');
|
|
40
|
+
const res2 = Reflector.getOwnMetadata(
|
|
41
|
+
REQUEST_DATA_METADATA_KEY,
|
|
42
|
+
Target,
|
|
43
|
+
'propertyKey',
|
|
44
|
+
);
|
|
45
|
+
expect(res2).to.be.instanceof(Map);
|
|
46
|
+
expect(res2!.get(0)).to.be.eq(md2);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('getMetadata', function () {
|
|
51
|
+
it('returns an existing metadata of the target', function () {
|
|
52
|
+
class Target {}
|
|
53
|
+
const md1 = {source: RequestDataSource.PARAMS};
|
|
54
|
+
const md2 = {source: RequestDataSource.QUERY};
|
|
55
|
+
const mdMap = new Map<number, RequestDataMetadata>([
|
|
56
|
+
[0, md1],
|
|
57
|
+
[1, md2],
|
|
58
|
+
]);
|
|
59
|
+
Reflector.defineMetadata(
|
|
60
|
+
REQUEST_DATA_METADATA_KEY,
|
|
61
|
+
mdMap,
|
|
62
|
+
Target,
|
|
63
|
+
'propertyKey',
|
|
64
|
+
);
|
|
65
|
+
const res = RequestDataReflector.getMetadata(Target, 'propertyKey');
|
|
66
|
+
expect(res).to.be.instanceof(Map);
|
|
67
|
+
expect(res!.get(0)).to.be.eq(md1);
|
|
68
|
+
expect(res!.get(1)).to.be.eq(md2);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('returns an empty map if no metadata', function () {
|
|
72
|
+
class Target {}
|
|
73
|
+
const res = RequestDataReflector.getMetadata(Target, 'propertyKey');
|
|
74
|
+
expect(res).to.be.instanceof(Map);
|
|
75
|
+
expect(res).to.be.empty;
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
});
|