@opra/common 1.7.4 → 1.9.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/browser/index.cjs +5 -5
- package/browser/index.mjs +5 -5
- package/cjs/document/data-type/api-field.js +2 -0
- package/cjs/document/data-type/enum-type.js +2 -2
- package/cjs/document/decorators/api-field-decorator.js +1 -0
- package/cjs/document/decorators/http-operation-entity-create.decorator.js +58 -0
- package/cjs/document/decorators/http-operation-entity-delete-many.decorator.js +41 -0
- package/cjs/document/decorators/http-operation-entity-delete.decorator.js +41 -0
- package/cjs/document/decorators/http-operation-entity-find-many.decorator.js +85 -0
- package/cjs/document/decorators/http-operation-entity-get.decorator.js +56 -0
- package/cjs/document/decorators/http-operation-entity-replace.decorator.js +56 -0
- package/cjs/document/decorators/http-operation-entity-update-many.decorator.js +50 -0
- package/cjs/document/decorators/http-operation-entity-update.decorator.js +66 -0
- package/cjs/document/decorators/http-operation-entity.decorator.js +83 -525
- package/cjs/document/http/http-parameter.js +1 -0
- package/cjs/document/index.js +9 -1
- package/cjs/filter/antlr/OpraFilterLexer.js +212 -347
- package/cjs/filter/antlr/OpraFilterListener.js +1 -1
- package/cjs/filter/antlr/OpraFilterParser.js +198 -227
- package/cjs/filter/antlr/OpraFilterVisitor.js +1 -1
- package/cjs/filter/ast/index.js +1 -0
- package/cjs/filter/ast/terms/date-time-literal.js +27 -0
- package/cjs/filter/build.js +3 -1
- package/cjs/filter/filter-rules.js +2 -1
- package/cjs/filter/filter-tree-visitor.js +1 -1
- package/esm/document/data-type/api-field.js +2 -0
- package/esm/document/data-type/enum-type.js +2 -2
- package/esm/document/decorators/api-field-decorator.js +1 -0
- package/esm/document/decorators/http-operation-entity-create.decorator.js +56 -0
- package/esm/document/decorators/http-operation-entity-delete-many.decorator.js +39 -0
- package/esm/document/decorators/http-operation-entity-delete.decorator.js +39 -0
- package/esm/document/decorators/http-operation-entity-find-many.decorator.js +83 -0
- package/esm/document/decorators/http-operation-entity-get.decorator.js +54 -0
- package/esm/document/decorators/http-operation-entity-replace.decorator.js +54 -0
- package/esm/document/decorators/http-operation-entity-update-many.decorator.js +48 -0
- package/esm/document/decorators/http-operation-entity-update.decorator.js +64 -0
- package/esm/document/decorators/http-operation-entity.decorator.js +79 -525
- package/esm/document/http/http-parameter.js +1 -0
- package/esm/document/index.js +9 -1
- package/esm/filter/antlr/OpraFilterLexer.js +213 -348
- package/esm/filter/antlr/OpraFilterListener.js +2 -2
- package/esm/filter/antlr/OpraFilterParser.js +198 -227
- package/esm/filter/antlr/OpraFilterVisitor.js +1 -1
- package/esm/filter/ast/index.js +1 -0
- package/esm/filter/ast/terms/date-time-literal.js +23 -0
- package/esm/filter/build.js +3 -1
- package/esm/filter/filter-rules.js +2 -1
- package/esm/filter/filter-tree-visitor.js +2 -2
- package/package.json +2 -2
- package/types/document/data-type/api-field.d.ts +2 -1
- package/types/document/data-type/enum-type.d.ts +3 -3
- package/types/document/decorators/api-field-decorator.d.ts +2 -2
- package/types/document/decorators/http-operation-entity-create.decorator.d.ts +1 -0
- package/types/document/decorators/http-operation-entity-delete-many.decorator.d.ts +1 -0
- package/types/document/decorators/http-operation-entity-delete.decorator.d.ts +1 -0
- package/types/document/decorators/http-operation-entity-find-many.decorator.d.ts +1 -0
- package/types/document/decorators/http-operation-entity-get.decorator.d.ts +1 -0
- package/types/document/decorators/http-operation-entity-replace.decorator.d.ts +1 -0
- package/types/document/decorators/http-operation-entity-update-many.decorator.d.ts +1 -0
- package/types/document/decorators/http-operation-entity-update.decorator.d.ts +1 -0
- package/types/document/decorators/http-operation-entity.decorator.d.ts +32 -4
- package/types/document/http/http-parameter.d.ts +3 -0
- package/types/document/index.d.ts +9 -1
- package/types/filter/antlr/OpraFilterLexer.d.ts +1 -1
- package/types/filter/antlr/OpraFilterListener.d.ts +36 -10
- package/types/filter/antlr/OpraFilterParser.d.ts +1 -1
- package/types/filter/antlr/OpraFilterVisitor.d.ts +31 -5
- package/types/filter/ast/expressions/comparison-expression.d.ts +1 -0
- package/types/filter/ast/index.d.ts +1 -0
- package/types/filter/ast/terms/date-time-literal.d.ts +6 -0
- package/types/filter/filter-rules.d.ts +1 -0
- package/types/filter/filter-tree-visitor.d.ts +2 -2
- package/types/schema/data-type/field.interface.d.ts +16 -1
|
@@ -1,92 +1,30 @@
|
|
|
1
|
-
import { HttpStatusCode, MimeTypes } from '../../enums/index.js';
|
|
2
1
|
import { FilterRules } from '../../filter/filter-rules.js';
|
|
3
2
|
import { DATATYPE_METADATA } from '../constants.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { FIELD_PATH_PATTERN } from '../data-type/complex-type-base.js';
|
|
4
|
+
import { EnumType } from '../data-type/enum-type.js';
|
|
5
|
+
import { FilterType } from '../data-type/extended-types/index.js';
|
|
6
6
|
import { HttpOperation } from '../http/http-operation.js';
|
|
7
|
-
import { HttpOperationDecoratorFactory, } from './http-operation.decorator.js';
|
|
8
7
|
/** Implementation **/
|
|
9
8
|
HttpOperation.Entity = {};
|
|
10
9
|
/**
|
|
11
|
-
*
|
|
10
|
+
*
|
|
11
|
+
* @param typ
|
|
12
12
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
method: 'POST',
|
|
24
|
-
...args,
|
|
25
|
-
composition: 'Entity.Create',
|
|
26
|
-
requestBody: {
|
|
27
|
-
immediateFetch: true,
|
|
28
|
-
...args.requestBody,
|
|
29
|
-
required: true,
|
|
30
|
-
},
|
|
31
|
-
});
|
|
32
|
-
decorator
|
|
33
|
-
.QueryParam('projection', {
|
|
34
|
-
description: 'Determines fields projection',
|
|
35
|
-
type: new FieldPathType({
|
|
36
|
-
dataType: args.type,
|
|
37
|
-
allowSigns: 'each',
|
|
38
|
-
}),
|
|
39
|
-
isArray: true,
|
|
40
|
-
arraySeparator: ',',
|
|
41
|
-
})
|
|
42
|
-
.RequestContent(args.requestBody?.type || args.type)
|
|
43
|
-
.Response(HttpStatusCode.CREATED, {
|
|
44
|
-
description: 'Operation is successful. Returns OperationResult with "payload" field that contains the created resource.',
|
|
45
|
-
contentType: MimeTypes.opra_response_json,
|
|
46
|
-
type: args.type,
|
|
47
|
-
partial: 'deep',
|
|
48
|
-
})
|
|
49
|
-
.Response(HttpStatusCode.UNPROCESSABLE_ENTITY, {
|
|
50
|
-
description: 'The request was well-formed but was unable to process operation due to one or many errors.',
|
|
51
|
-
contentType: MimeTypes.opra_response_json,
|
|
52
|
-
});
|
|
53
|
-
decoratorChain.push((operationMeta) => {
|
|
54
|
-
const compositionOptions = (operationMeta.compositionOptions =
|
|
55
|
-
operationMeta.compositionOptions || {});
|
|
56
|
-
compositionOptions.type = getDataTypeName(args.type);
|
|
57
|
-
});
|
|
58
|
-
return decorator;
|
|
59
|
-
};
|
|
13
|
+
export function getDataTypeName(typ) {
|
|
14
|
+
if (typeof typ === 'string')
|
|
15
|
+
return typ;
|
|
16
|
+
const metadata = Reflect.getMetadata(DATATYPE_METADATA, typ);
|
|
17
|
+
if (!metadata)
|
|
18
|
+
throw new TypeError(`Type (${typ}) is not decorated with any datatype decorators`);
|
|
19
|
+
if (metadata?.name)
|
|
20
|
+
return metadata.name;
|
|
21
|
+
throw new TypeError(`You should provide named data type but embedded one found`);
|
|
22
|
+
}
|
|
60
23
|
/**
|
|
61
|
-
*
|
|
24
|
+
*
|
|
62
25
|
*/
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (typeof arg0 === 'object' && !arg0[DATATYPE_METADATA]) {
|
|
66
|
-
args = arg0;
|
|
67
|
-
}
|
|
68
|
-
else
|
|
69
|
-
args = { ...arg1, type: arg0 };
|
|
70
|
-
/** Initialize the decorator and the chain */
|
|
71
|
-
const decoratorChain = [];
|
|
72
|
-
const decorator = HttpOperationDecoratorFactory(decoratorChain, {
|
|
73
|
-
method: 'DELETE',
|
|
74
|
-
...args,
|
|
75
|
-
composition: 'Entity.Delete',
|
|
76
|
-
});
|
|
77
|
-
decorator
|
|
78
|
-
.Response(HttpStatusCode.OK, {
|
|
79
|
-
description: 'Operation is successful. Returns OperationResult with "affected" field.',
|
|
80
|
-
contentType: MimeTypes.opra_response_json,
|
|
81
|
-
})
|
|
82
|
-
.Response(HttpStatusCode.UNPROCESSABLE_ENTITY, {
|
|
83
|
-
description: 'The request was well-formed but was unable to process operation due to one or many errors.',
|
|
84
|
-
contentType: MimeTypes.opra_response_json,
|
|
85
|
-
});
|
|
86
|
-
/**
|
|
87
|
-
*
|
|
88
|
-
*/
|
|
89
|
-
decorator.KeyParam = (name, prmOptions) => {
|
|
26
|
+
export function createKeyParamDecorator(decorator, decoratorChain) {
|
|
27
|
+
return (name, prmOptions) => {
|
|
90
28
|
const paramMeta = typeof prmOptions === 'string' || typeof prmOptions === 'function'
|
|
91
29
|
? {
|
|
92
30
|
name,
|
|
@@ -108,468 +46,84 @@ HttpOperation.Entity.Delete = function (arg0, arg1) {
|
|
|
108
46
|
});
|
|
109
47
|
return decorator;
|
|
110
48
|
};
|
|
111
|
-
|
|
112
|
-
const compositionOptions = (operationMeta.compositionOptions =
|
|
113
|
-
operationMeta.compositionOptions || {});
|
|
114
|
-
compositionOptions.type = getDataTypeName(args.type);
|
|
115
|
-
});
|
|
116
|
-
return decorator;
|
|
117
|
-
};
|
|
118
|
-
/**
|
|
119
|
-
* HttpOperation.Entity.DeleteMany
|
|
120
|
-
*/
|
|
121
|
-
HttpOperation.Entity.DeleteMany = function (arg0, arg1) {
|
|
122
|
-
let args;
|
|
123
|
-
if (typeof arg0 === 'object' && !arg0[DATATYPE_METADATA]) {
|
|
124
|
-
args = arg0;
|
|
125
|
-
}
|
|
126
|
-
else
|
|
127
|
-
args = { ...arg1, type: arg0 };
|
|
128
|
-
/** Initialize the decorator and the chain */
|
|
129
|
-
const decoratorChain = [];
|
|
130
|
-
const filterRules = new FilterRules();
|
|
131
|
-
const filterType = new FilterType({ dataType: args.type });
|
|
132
|
-
filterType.rules = {};
|
|
133
|
-
const decorator = HttpOperationDecoratorFactory(decoratorChain, {
|
|
134
|
-
method: 'DELETE',
|
|
135
|
-
...args,
|
|
136
|
-
composition: 'Entity.DeleteMany',
|
|
137
|
-
});
|
|
138
|
-
decorator
|
|
139
|
-
.Response(HttpStatusCode.OK, {
|
|
140
|
-
description: 'Operation is successful. Returns OperationResult with "affected" field.',
|
|
141
|
-
contentType: MimeTypes.opra_response_json,
|
|
142
|
-
})
|
|
143
|
-
.Response(HttpStatusCode.UNPROCESSABLE_ENTITY, {
|
|
144
|
-
description: 'The request was well-formed but was unable to process operation due to one or many errors.',
|
|
145
|
-
contentType: MimeTypes.opra_response_json,
|
|
146
|
-
})
|
|
147
|
-
.QueryParam('filter', {
|
|
148
|
-
type: filterType,
|
|
149
|
-
description: 'Determines filter fields',
|
|
150
|
-
});
|
|
151
|
-
decoratorChain.push((operationMeta) => {
|
|
152
|
-
const compositionOptions = (operationMeta.compositionOptions =
|
|
153
|
-
operationMeta.compositionOptions || {});
|
|
154
|
-
compositionOptions.type = getDataTypeName(args.type);
|
|
155
|
-
});
|
|
156
|
-
decorator.Filter = (field, operators, description) => {
|
|
157
|
-
decoratorChain.push(() => {
|
|
158
|
-
filterRules.set(field, { operators, description });
|
|
159
|
-
filterType.rules = filterRules.toJSON();
|
|
160
|
-
});
|
|
161
|
-
return decorator;
|
|
162
|
-
};
|
|
163
|
-
return decorator;
|
|
164
|
-
};
|
|
49
|
+
}
|
|
165
50
|
/**
|
|
166
|
-
*
|
|
51
|
+
*
|
|
167
52
|
*/
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
contentType: MimeTypes.opra_response_json,
|
|
196
|
-
})
|
|
197
|
-
.QueryParam('limit', {
|
|
198
|
-
description: 'Determines number of returning instances',
|
|
199
|
-
type: new IntegerType({ minValue: 1, maxValue: args.maxLimit }),
|
|
200
|
-
})
|
|
201
|
-
.QueryParam('skip', {
|
|
202
|
-
description: 'Determines number of returning instances',
|
|
203
|
-
type: new IntegerType({ minValue: 1 }),
|
|
204
|
-
})
|
|
205
|
-
.QueryParam('count', {
|
|
206
|
-
description: 'Counts all matching instances if enabled',
|
|
207
|
-
type: Boolean,
|
|
208
|
-
})
|
|
209
|
-
.QueryParam('projection', {
|
|
210
|
-
description: 'Determines fields projection',
|
|
211
|
-
type: new FieldPathType({
|
|
212
|
-
dataType: args.type,
|
|
213
|
-
allowSigns: 'each',
|
|
214
|
-
}),
|
|
215
|
-
isArray: true,
|
|
216
|
-
arraySeparator: ',',
|
|
217
|
-
})
|
|
218
|
-
.QueryParam('filter', {
|
|
219
|
-
type: filterType,
|
|
220
|
-
description: 'Determines filter fields',
|
|
221
|
-
})
|
|
222
|
-
.QueryParam('sort', {
|
|
223
|
-
description: 'Determines sort fields',
|
|
224
|
-
type: new FieldPathType({
|
|
225
|
-
dataType: args.type,
|
|
226
|
-
allowSigns: 'first',
|
|
227
|
-
}),
|
|
228
|
-
isArray: true,
|
|
229
|
-
arraySeparator: ',',
|
|
230
|
-
});
|
|
231
|
-
decoratorChain.push((operationMeta) => {
|
|
232
|
-
const compositionOptions = (operationMeta.compositionOptions =
|
|
233
|
-
operationMeta.compositionOptions || {});
|
|
234
|
-
compositionOptions.type = getDataTypeName(args.type);
|
|
235
|
-
if (args.defaultLimit)
|
|
236
|
-
compositionOptions.defaultLimit = args.defaultLimit;
|
|
237
|
-
if (args.defaultProjection)
|
|
238
|
-
compositionOptions.defaultProjection = args.defaultProjection;
|
|
239
|
-
if (args.maxLimit)
|
|
240
|
-
compositionOptions.maxLimit = args.maxLimit;
|
|
241
|
-
});
|
|
242
|
-
decorator.DefaultSort = (...fields) => {
|
|
243
|
-
decoratorChain.push((operationMeta) => {
|
|
244
|
-
const compositionOptions = (operationMeta.compositionOptions =
|
|
245
|
-
operationMeta.compositionOptions || {});
|
|
246
|
-
compositionOptions.defaultSort = fields;
|
|
247
|
-
});
|
|
248
|
-
return decorator;
|
|
249
|
-
};
|
|
250
|
-
decorator.SortFields = (...fields) => {
|
|
53
|
+
export function createSortFieldsDecorator(decorator, decoratorChain) {
|
|
54
|
+
return (...varargs) => {
|
|
55
|
+
const defObj = typeof varargs[0] === 'object'
|
|
56
|
+
? varargs[0]
|
|
57
|
+
: varargs.reduce((acc, k) => {
|
|
58
|
+
const a = k.split(':');
|
|
59
|
+
acc[a[0]] = a[1] || a[0];
|
|
60
|
+
return acc;
|
|
61
|
+
}, {});
|
|
62
|
+
const fieldsMap = Object.keys(defObj).reduce((acc, k) => {
|
|
63
|
+
const m1 = FIELD_PATH_PATTERN.exec(k);
|
|
64
|
+
const m2 = FIELD_PATH_PATTERN.exec(defObj[k]);
|
|
65
|
+
if (m1 && m2) {
|
|
66
|
+
acc[m1[2]] = m2[2];
|
|
67
|
+
}
|
|
68
|
+
return acc;
|
|
69
|
+
}, {});
|
|
70
|
+
const prmEnum = Object.keys(defObj).reduce((acc, k) => {
|
|
71
|
+
const m = FIELD_PATH_PATTERN.exec(k);
|
|
72
|
+
if (m) {
|
|
73
|
+
if (m[1] != '-')
|
|
74
|
+
acc[m[2]] = m[2];
|
|
75
|
+
if (m[1] != '+')
|
|
76
|
+
acc['-' + m[2]] = '-' + m[2];
|
|
77
|
+
}
|
|
78
|
+
return acc;
|
|
79
|
+
}, {});
|
|
251
80
|
decoratorChain.push((operationMeta) => {
|
|
252
81
|
const compositionOptions = (operationMeta.compositionOptions =
|
|
253
82
|
operationMeta.compositionOptions || {});
|
|
254
|
-
compositionOptions.sortFields =
|
|
83
|
+
compositionOptions.sortFields = fieldsMap;
|
|
255
84
|
});
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
85
|
+
decorator.QueryParam('sort', {
|
|
86
|
+
description: 'Determines sort fields',
|
|
87
|
+
type: EnumType(prmEnum),
|
|
88
|
+
isArray: true,
|
|
89
|
+
arraySeparator: ',',
|
|
90
|
+
parser: (v) => v.map(x => {
|
|
91
|
+
const m = FIELD_PATH_PATTERN.exec(x);
|
|
92
|
+
return m ? (m[1] || '') + fieldsMap[m[2]] : x;
|
|
93
|
+
}),
|
|
262
94
|
});
|
|
263
95
|
return decorator;
|
|
264
96
|
};
|
|
265
|
-
|
|
266
|
-
};
|
|
267
|
-
/**
|
|
268
|
-
* HttpOperation.Entity.Get
|
|
269
|
-
*/
|
|
270
|
-
HttpOperation.Entity.Get = function (arg0, arg1) {
|
|
271
|
-
let args;
|
|
272
|
-
if (typeof arg0 === 'object' && !arg0[DATATYPE_METADATA]) {
|
|
273
|
-
args = arg0;
|
|
274
|
-
}
|
|
275
|
-
else
|
|
276
|
-
args = { ...arg1, type: arg0 };
|
|
277
|
-
/** Initialize the decorator and the chain */
|
|
278
|
-
const decoratorChain = [];
|
|
279
|
-
const decorator = HttpOperationDecoratorFactory(decoratorChain, {
|
|
280
|
-
method: 'GET',
|
|
281
|
-
...args,
|
|
282
|
-
composition: 'Entity.Get',
|
|
283
|
-
});
|
|
284
|
-
decorator
|
|
285
|
-
.QueryParam('projection', {
|
|
286
|
-
description: 'Determines fields projection',
|
|
287
|
-
type: new FieldPathType({
|
|
288
|
-
dataType: args.type,
|
|
289
|
-
allowSigns: 'each',
|
|
290
|
-
}),
|
|
291
|
-
isArray: true,
|
|
292
|
-
arraySeparator: ',',
|
|
293
|
-
})
|
|
294
|
-
.Response(HttpStatusCode.OK, {
|
|
295
|
-
description: 'Operation is successful. Returns OperationResult with "payload" field that contains the resource asked for.',
|
|
296
|
-
contentType: MimeTypes.opra_response_json,
|
|
297
|
-
type: args.type,
|
|
298
|
-
partial: 'deep',
|
|
299
|
-
})
|
|
300
|
-
.Response(HttpStatusCode.NO_CONTENT, {
|
|
301
|
-
description: 'Operation is successful but no resource found',
|
|
302
|
-
})
|
|
303
|
-
.Response(HttpStatusCode.UNPROCESSABLE_ENTITY, {
|
|
304
|
-
description: 'The request was well-formed but was unable to process operation due to one or many errors.',
|
|
305
|
-
contentType: MimeTypes.opra_response_json,
|
|
306
|
-
});
|
|
307
|
-
/**
|
|
308
|
-
*
|
|
309
|
-
*/
|
|
310
|
-
decorator.KeyParam = (name, prmOptions) => {
|
|
311
|
-
const paramMeta = typeof prmOptions === 'string' || typeof prmOptions === 'function'
|
|
312
|
-
? {
|
|
313
|
-
name,
|
|
314
|
-
location: 'path',
|
|
315
|
-
type: prmOptions,
|
|
316
|
-
keyParam: true,
|
|
317
|
-
}
|
|
318
|
-
: {
|
|
319
|
-
...prmOptions,
|
|
320
|
-
name,
|
|
321
|
-
location: 'path',
|
|
322
|
-
keyParam: true,
|
|
323
|
-
};
|
|
324
|
-
decorator.PathParam(name, paramMeta);
|
|
325
|
-
decoratorChain.push((meta) => {
|
|
326
|
-
if (!meta.path?.includes(':' + name))
|
|
327
|
-
meta.path = (meta.path || '') + '@:' + name;
|
|
328
|
-
meta.mergePath = true;
|
|
329
|
-
});
|
|
330
|
-
return decorator;
|
|
331
|
-
};
|
|
332
|
-
decoratorChain.push((operationMeta) => {
|
|
333
|
-
const compositionOptions = (operationMeta.compositionOptions =
|
|
334
|
-
operationMeta.compositionOptions || {});
|
|
335
|
-
compositionOptions.type = getDataTypeName(args.type);
|
|
336
|
-
});
|
|
337
|
-
return decorator;
|
|
338
|
-
};
|
|
97
|
+
}
|
|
339
98
|
/**
|
|
340
|
-
*
|
|
99
|
+
*
|
|
341
100
|
*/
|
|
342
|
-
|
|
343
|
-
let
|
|
344
|
-
if (
|
|
345
|
-
|
|
101
|
+
export function createFilterDecorator(decorator, decoratorChain, dataType) {
|
|
102
|
+
let filterRules = Reflect.getMetadata('FilterRules', decorator);
|
|
103
|
+
if (!filterRules) {
|
|
104
|
+
filterRules = new FilterRules();
|
|
105
|
+
Reflect.defineMetadata('FilterRules', filterRules, decorator);
|
|
346
106
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
method: 'POST',
|
|
353
|
-
...args,
|
|
354
|
-
composition: 'Entity.Replace',
|
|
355
|
-
});
|
|
356
|
-
decorator
|
|
357
|
-
.QueryParam('projection', {
|
|
358
|
-
description: 'Determines fields projection',
|
|
359
|
-
type: new FieldPathType({
|
|
360
|
-
dataType: args.type,
|
|
361
|
-
allowSigns: 'each',
|
|
362
|
-
}),
|
|
363
|
-
isArray: true,
|
|
364
|
-
arraySeparator: ',',
|
|
365
|
-
})
|
|
366
|
-
.Response(HttpStatusCode.OK, {
|
|
367
|
-
description: 'Operation is successful. Returns OperationResult with "payload" field that contains the resource asked for.',
|
|
368
|
-
contentType: MimeTypes.opra_response_json,
|
|
369
|
-
type: args.type,
|
|
370
|
-
partial: 'deep',
|
|
371
|
-
})
|
|
372
|
-
.Response(HttpStatusCode.NO_CONTENT, {
|
|
373
|
-
description: 'Operation is successful but no resource found',
|
|
374
|
-
})
|
|
375
|
-
.Response(HttpStatusCode.UNPROCESSABLE_ENTITY, {
|
|
376
|
-
description: 'The request was well-formed but was unable to process operation due to one or many errors.',
|
|
377
|
-
contentType: MimeTypes.opra_response_json,
|
|
378
|
-
});
|
|
379
|
-
/**
|
|
380
|
-
*
|
|
381
|
-
*/
|
|
382
|
-
decorator.KeyParam = (name, prmOptions) => {
|
|
383
|
-
const paramMeta = typeof prmOptions === 'string' || typeof prmOptions === 'function'
|
|
384
|
-
? {
|
|
385
|
-
name,
|
|
386
|
-
location: 'path',
|
|
387
|
-
type: prmOptions,
|
|
388
|
-
keyParam: true,
|
|
389
|
-
}
|
|
390
|
-
: {
|
|
391
|
-
...prmOptions,
|
|
392
|
-
name,
|
|
393
|
-
location: 'path',
|
|
394
|
-
keyParam: true,
|
|
395
|
-
};
|
|
396
|
-
decorator.PathParam(name, paramMeta);
|
|
397
|
-
decoratorChain.push((meta) => {
|
|
398
|
-
if (!meta.path?.includes(':' + name))
|
|
399
|
-
meta.path = (meta.path || '') + '@:' + name;
|
|
400
|
-
meta.mergePath = true;
|
|
401
|
-
});
|
|
402
|
-
return decorator;
|
|
403
|
-
};
|
|
404
|
-
decoratorChain.push((operationMeta) => {
|
|
405
|
-
const compositionOptions = (operationMeta.compositionOptions =
|
|
406
|
-
operationMeta.compositionOptions || {});
|
|
407
|
-
compositionOptions.type = getDataTypeName(args.type);
|
|
408
|
-
});
|
|
409
|
-
return decorator;
|
|
410
|
-
};
|
|
411
|
-
/**
|
|
412
|
-
* HttpOperation.Entity.UpdateMany
|
|
413
|
-
*/
|
|
414
|
-
HttpOperation.Entity.UpdateMany = function (arg0, arg1) {
|
|
415
|
-
let args;
|
|
416
|
-
if (typeof arg0 === 'object' && !arg0[DATATYPE_METADATA]) {
|
|
417
|
-
args = arg0;
|
|
107
|
+
let filterType = Reflect.getMetadata('FilterType', decorator);
|
|
108
|
+
if (!filterType) {
|
|
109
|
+
filterType = new FilterType({ dataType });
|
|
110
|
+
filterType.rules = {};
|
|
111
|
+
Reflect.defineMetadata('FilterType', filterType, decorator);
|
|
418
112
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
const filterRules = new FilterRules();
|
|
426
|
-
const decorator = HttpOperationDecoratorFactory(decoratorChain, {
|
|
427
|
-
method: 'PATCH',
|
|
428
|
-
...args,
|
|
429
|
-
composition: 'Entity.UpdateMany',
|
|
430
|
-
requestBody: {
|
|
431
|
-
immediateFetch: true,
|
|
432
|
-
partial: 'deep',
|
|
433
|
-
allowPatchOperators: true,
|
|
434
|
-
keepKeyFields: true,
|
|
435
|
-
...args.requestBody,
|
|
436
|
-
required: true,
|
|
437
|
-
},
|
|
438
|
-
});
|
|
439
|
-
decorator
|
|
440
|
-
.RequestContent(args.requestBody?.type || args.type)
|
|
441
|
-
.Response(HttpStatusCode.OK, {
|
|
442
|
-
description: 'Operation is successful. Returns OperationResult with "affected" field.',
|
|
443
|
-
contentType: MimeTypes.opra_response_json,
|
|
444
|
-
})
|
|
445
|
-
.Response(HttpStatusCode.UNPROCESSABLE_ENTITY, {
|
|
446
|
-
description: 'The request was well-formed but was unable to process operation due to one or many errors.',
|
|
447
|
-
contentType: MimeTypes.opra_response_json,
|
|
448
|
-
})
|
|
449
|
-
.QueryParam('filter', {
|
|
450
|
-
type: filterType,
|
|
451
|
-
description: 'Determines filter fields',
|
|
452
|
-
});
|
|
453
|
-
decoratorChain.push((operationMeta) => {
|
|
454
|
-
const compositionOptions = (operationMeta.compositionOptions =
|
|
455
|
-
operationMeta.compositionOptions || {});
|
|
456
|
-
compositionOptions.type = getDataTypeName(args.type);
|
|
457
|
-
});
|
|
458
|
-
decorator.Filter = (field, operators, description) => {
|
|
113
|
+
return (field, arg0) => {
|
|
114
|
+
const filterOptions = (Array.isArray(arg0)
|
|
115
|
+
? { operators: arg0 }
|
|
116
|
+
: typeof arg0 === 'string'
|
|
117
|
+
? { operators: [arg0] }
|
|
118
|
+
: arg0) || {};
|
|
459
119
|
decoratorChain.push(() => {
|
|
460
|
-
filterRules.set(field,
|
|
120
|
+
filterRules.set(field, filterOptions);
|
|
461
121
|
filterType.rules = filterRules.toJSON();
|
|
462
122
|
});
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
};
|
|
467
|
-
/**
|
|
468
|
-
* HttpOperation.Entity.Update
|
|
469
|
-
*/
|
|
470
|
-
HttpOperation.Entity.Update = function (arg0, arg1) {
|
|
471
|
-
let args;
|
|
472
|
-
if (typeof arg0 === 'object' && !arg0[DATATYPE_METADATA]) {
|
|
473
|
-
args = arg0;
|
|
474
|
-
}
|
|
475
|
-
else
|
|
476
|
-
args = { ...arg1, type: arg0 };
|
|
477
|
-
/** Initialize the decorator and the chain */
|
|
478
|
-
const decoratorChain = [];
|
|
479
|
-
const filterRules = new FilterRules();
|
|
480
|
-
const filterType = new FilterType({ dataType: args.type });
|
|
481
|
-
filterType.rules = {};
|
|
482
|
-
const decorator = HttpOperationDecoratorFactory(decoratorChain, {
|
|
483
|
-
method: 'PATCH',
|
|
484
|
-
...args,
|
|
485
|
-
composition: 'Entity.Update',
|
|
486
|
-
requestBody: {
|
|
487
|
-
partial: 'deep',
|
|
488
|
-
immediateFetch: true,
|
|
489
|
-
allowPatchOperators: true,
|
|
490
|
-
keepKeyFields: true,
|
|
491
|
-
...args.requestBody,
|
|
492
|
-
required: true,
|
|
493
|
-
},
|
|
494
|
-
});
|
|
495
|
-
decorator
|
|
496
|
-
.QueryParam('projection', {
|
|
497
|
-
description: 'Determines fields projection',
|
|
498
|
-
type: new FieldPathType({
|
|
499
|
-
dataType: args.type,
|
|
500
|
-
allowSigns: 'each',
|
|
501
|
-
}),
|
|
502
|
-
isArray: true,
|
|
503
|
-
arraySeparator: ',',
|
|
504
|
-
})
|
|
505
|
-
.QueryParam('filter', {
|
|
506
|
-
type: filterType,
|
|
507
|
-
description: 'Determines filter fields',
|
|
508
|
-
})
|
|
509
|
-
.RequestContent(args.requestBody?.type || args.type)
|
|
510
|
-
.Response(HttpStatusCode.OK, {
|
|
511
|
-
description: 'Operation is successful. Returns OperationResult with "payload" field that contains updated resource.',
|
|
512
|
-
contentType: MimeTypes.opra_response_json,
|
|
513
|
-
type: args.type,
|
|
514
|
-
partial: 'deep',
|
|
515
|
-
})
|
|
516
|
-
.Response(HttpStatusCode.NO_CONTENT, {
|
|
517
|
-
description: 'Operation is successful but no resource found',
|
|
518
|
-
})
|
|
519
|
-
.Response(HttpStatusCode.UNPROCESSABLE_ENTITY, {
|
|
520
|
-
description: 'The request was well-formed but was unable to process operation due to one or many errors.',
|
|
521
|
-
contentType: MimeTypes.opra_response_json,
|
|
522
|
-
});
|
|
523
|
-
/**
|
|
524
|
-
*
|
|
525
|
-
*/
|
|
526
|
-
decorator.KeyParam = (name, prmOptions) => {
|
|
527
|
-
const paramMeta = typeof prmOptions === 'string' || typeof prmOptions === 'function'
|
|
528
|
-
? {
|
|
529
|
-
name,
|
|
530
|
-
location: 'path',
|
|
531
|
-
type: prmOptions,
|
|
532
|
-
keyParam: true,
|
|
533
|
-
}
|
|
534
|
-
: {
|
|
535
|
-
...prmOptions,
|
|
536
|
-
name,
|
|
537
|
-
location: 'path',
|
|
538
|
-
keyParam: true,
|
|
539
|
-
};
|
|
540
|
-
decorator.PathParam(name, paramMeta);
|
|
541
|
-
decoratorChain.push((meta) => {
|
|
542
|
-
if (!meta.path?.includes(':' + name))
|
|
543
|
-
meta.path = (meta.path || '') + '@:' + name;
|
|
544
|
-
meta.mergePath = true;
|
|
123
|
+
decorator.QueryParam('filter', {
|
|
124
|
+
type: filterType,
|
|
125
|
+
description: 'Determines filter fields',
|
|
545
126
|
});
|
|
546
127
|
return decorator;
|
|
547
128
|
};
|
|
548
|
-
decoratorChain.push((operationMeta) => {
|
|
549
|
-
const compositionOptions = (operationMeta.compositionOptions =
|
|
550
|
-
operationMeta.compositionOptions || {});
|
|
551
|
-
compositionOptions.type = getDataTypeName(args.type);
|
|
552
|
-
});
|
|
553
|
-
decorator.Filter = (field, operators, description) => {
|
|
554
|
-
decoratorChain.push(() => {
|
|
555
|
-
filterRules.set(field, { operators, description });
|
|
556
|
-
filterType.rules = filterRules.toJSON();
|
|
557
|
-
});
|
|
558
|
-
return decorator;
|
|
559
|
-
};
|
|
560
|
-
return decorator;
|
|
561
|
-
};
|
|
562
|
-
/**
|
|
563
|
-
*
|
|
564
|
-
* @param typ
|
|
565
|
-
*/
|
|
566
|
-
function getDataTypeName(typ) {
|
|
567
|
-
if (typeof typ === 'string')
|
|
568
|
-
return typ;
|
|
569
|
-
const metadata = Reflect.getMetadata(DATATYPE_METADATA, typ);
|
|
570
|
-
if (!metadata)
|
|
571
|
-
throw new TypeError(`Type (${typ}) is not decorated with any datatype decorators`);
|
|
572
|
-
if (metadata?.name)
|
|
573
|
-
return metadata.name;
|
|
574
|
-
throw new TypeError(`You should provide named data type but embedded one found`);
|
|
575
129
|
}
|
package/esm/document/index.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
|
+
import './decorators/http-operation-entity.decorator.js';
|
|
3
|
+
import './decorators/http-operation-entity-create.decorator.js';
|
|
4
|
+
import './decorators/http-operation-entity-delete.decorator.js';
|
|
5
|
+
import './decorators/http-operation-entity-delete-many.decorator.js';
|
|
6
|
+
import './decorators/http-operation-entity-find-many.decorator.js';
|
|
7
|
+
import './decorators/http-operation-entity-get.decorator.js';
|
|
8
|
+
import './decorators/http-operation-entity-replace.decorator.js';
|
|
9
|
+
import './decorators/http-operation-entity-update.decorator.js';
|
|
10
|
+
import './decorators/http-operation-entity-update-many.decorator.js';
|
|
2
11
|
import * as RpcControllerDecorator_ from './decorators/rpc-controller.decorator.js';
|
|
3
12
|
import * as RpcOperationDecorator_ from './decorators/rpc-operation.decorator.js';
|
|
4
13
|
import * as DataTypeFactory_ from './factory/data-type.factory.js';
|
|
@@ -24,7 +33,6 @@ export * from './data-type/pick-type.js';
|
|
|
24
33
|
export * from './data-type/primitive-types/index.js';
|
|
25
34
|
export * from './data-type/required-type.js';
|
|
26
35
|
export * from './data-type/simple-type.js';
|
|
27
|
-
export * from './decorators/http-operation-entity.decorator.js';
|
|
28
36
|
export * from './factory/api-document.factory.js';
|
|
29
37
|
export * from './http/http-api.js';
|
|
30
38
|
export * from './http/http-controller.js';
|