@opra/common 0.28.1 → 0.29.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.js +200 -100
- package/cjs/document/data-type/complex-type-class.js +36 -13
- package/cjs/document/factory/api-document-factory.js +26 -3
- package/cjs/document/factory/type-document-factory.js +6 -3
- package/cjs/document/index.js +1 -1
- package/cjs/document/resource/collection-class.js +31 -27
- package/cjs/document/resource/collection-decorator.js +61 -33
- package/cjs/document/resource/{operation-decorator.js → crud-operation-decorator.js} +3 -2
- package/cjs/document/resource/crud-operation.js +49 -0
- package/cjs/document/resource/crud-resource.js +2 -2
- package/cjs/document/resource/endpoint.js +11 -3
- package/cjs/document/resource/singleton-class.js +20 -15
- package/cjs/document/resource/storage-decorator.js +10 -10
- package/esm/document/data-type/complex-type-class.js +36 -13
- package/esm/document/factory/api-document-factory.js +26 -3
- package/esm/document/factory/type-document-factory.js +6 -3
- package/esm/document/index.js +1 -1
- package/esm/document/resource/collection-class.js +31 -27
- package/esm/document/resource/collection-decorator.js +54 -26
- package/esm/document/resource/{operation-decorator.js → crud-operation-decorator.js} +3 -2
- package/esm/document/resource/crud-operation.js +44 -0
- package/esm/document/resource/crud-resource.js +2 -2
- package/esm/document/resource/endpoint.js +11 -3
- package/esm/document/resource/singleton-class.js +20 -15
- package/esm/document/resource/storage-decorator.js +7 -7
- package/package.json +3 -2
- package/types/document/data-type/complex-type-class.d.ts +1 -1
- package/types/document/data-type/complex-type.d.ts +7 -3
- package/types/document/data-type/data-type.d.ts +3 -0
- package/types/document/data-type/field-class.d.ts +0 -2
- package/types/document/index.d.ts +1 -1
- package/types/document/resource/collection-class.d.ts +0 -9
- package/types/document/resource/collection-decorator.d.ts +12 -0
- package/types/document/resource/crud-operation-decorator.d.ts +6 -0
- package/types/document/resource/{operation.d.ts → crud-operation.d.ts} +12 -4
- package/types/document/resource/crud-resource.d.ts +3 -3
- package/types/document/resource/endpoint.d.ts +1 -1
- package/types/document/resource/resource-decorator.d.ts +3 -2
- package/types/document/resource/resource.d.ts +2 -2
- package/types/document/resource/singleton-class.d.ts +5 -5
- package/types/document/resource/singleton-decorator.d.ts +6 -0
- package/types/document/resource/storage-class.d.ts +4 -4
- package/types/schema/data-type/complex-type.interface.d.ts +1 -1
- package/types/schema/resource/collection.interface.d.ts +7 -7
- package/types/schema/resource/endpoint.interface.d.ts +2 -1
- package/types/schema/resource/singleton.interface.d.ts +0 -2
- package/cjs/document/resource/operation.js +0 -25
- package/esm/document/resource/operation.js +0 -20
- package/types/document/resource/operation-decorator.d.ts +0 -6
|
@@ -16,16 +16,18 @@ class SingletonClass extends crud_resource_js_1.CrudResource {
|
|
|
16
16
|
endpoint.defineParameter('include', { type: 'string', isArray: true, isBuiltin: true });
|
|
17
17
|
endpoint.decodeInput = this.type.generateCodec('decode', {
|
|
18
18
|
partial: true,
|
|
19
|
-
pick: endpoint.inputPickFields,
|
|
20
|
-
omit: endpoint.inputOmitFields,
|
|
21
|
-
operation: 'write'
|
|
19
|
+
pick: endpoint.options.inputPickFields,
|
|
20
|
+
omit: endpoint.options.inputOmitFields,
|
|
21
|
+
operation: 'write',
|
|
22
|
+
overwriteFields: endpoint.inputOverwriteFields
|
|
22
23
|
});
|
|
23
24
|
endpoint.returnType = this.type;
|
|
24
25
|
endpoint.encodeReturning = endpoint.returnType.generateCodec('encode', {
|
|
25
26
|
partial: true,
|
|
26
|
-
pick: endpoint.outputPickFields,
|
|
27
|
-
omit: endpoint.outputOmitFields,
|
|
28
|
-
operation: 'read'
|
|
27
|
+
pick: endpoint.options.outputPickFields,
|
|
28
|
+
omit: endpoint.options.outputOmitFields,
|
|
29
|
+
operation: 'read',
|
|
30
|
+
overwriteFields: endpoint.outputOverwriteFields
|
|
29
31
|
});
|
|
30
32
|
}
|
|
31
33
|
// ------------------
|
|
@@ -37,9 +39,10 @@ class SingletonClass extends crud_resource_js_1.CrudResource {
|
|
|
37
39
|
endpoint.returnType = this.type;
|
|
38
40
|
endpoint.encodeReturning = endpoint.returnType.generateCodec('encode', {
|
|
39
41
|
partial: true,
|
|
40
|
-
pick: endpoint.outputPickFields,
|
|
41
|
-
omit: endpoint.outputOmitFields,
|
|
42
|
-
operation: 'read'
|
|
42
|
+
pick: endpoint.options.outputPickFields,
|
|
43
|
+
omit: endpoint.options.outputOmitFields,
|
|
44
|
+
operation: 'read',
|
|
45
|
+
overwriteFields: endpoint.outputOverwriteFields
|
|
43
46
|
});
|
|
44
47
|
}
|
|
45
48
|
// ------------------
|
|
@@ -49,16 +52,18 @@ class SingletonClass extends crud_resource_js_1.CrudResource {
|
|
|
49
52
|
endpoint.defineParameter('omit', { type: 'string', isArray: true, isBuiltin: true });
|
|
50
53
|
endpoint.defineParameter('include', { type: 'string', isArray: true, isBuiltin: true });
|
|
51
54
|
endpoint.decodeInput = this.type.generateCodec('decode', {
|
|
52
|
-
pick: endpoint.inputPickFields,
|
|
53
|
-
omit: endpoint.inputOmitFields,
|
|
54
|
-
operation: 'write'
|
|
55
|
+
pick: endpoint.options.inputPickFields,
|
|
56
|
+
omit: endpoint.options.inputOmitFields,
|
|
57
|
+
operation: 'write',
|
|
58
|
+
overwriteFields: endpoint.inputOverwriteFields
|
|
55
59
|
});
|
|
56
60
|
endpoint.returnType = this.type;
|
|
57
61
|
endpoint.encodeReturning = endpoint.returnType.generateCodec('encode', {
|
|
58
62
|
partial: true,
|
|
59
|
-
pick: endpoint.outputPickFields,
|
|
60
|
-
omit: endpoint.outputOmitFields,
|
|
61
|
-
operation: 'read'
|
|
63
|
+
pick: endpoint.options.outputPickFields,
|
|
64
|
+
omit: endpoint.options.outputOmitFields,
|
|
65
|
+
operation: 'read',
|
|
66
|
+
overwriteFields: endpoint.outputOverwriteFields
|
|
62
67
|
});
|
|
63
68
|
}
|
|
64
69
|
}
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.StorageDecorator = void 0;
|
|
4
4
|
const index_js_1 = require("../../schema/index.js");
|
|
5
5
|
const action_decorator_js_1 = require("./action-decorator.js");
|
|
6
|
-
const
|
|
6
|
+
const crud_operation_decorator_js_1 = require("./crud-operation-decorator.js");
|
|
7
7
|
const resource_decorator_js_1 = require("./resource-decorator.js");
|
|
8
8
|
const operationProperties = ['delete', 'get', 'post'];
|
|
9
9
|
function StorageDecorator(options) {
|
|
@@ -25,39 +25,39 @@ Object.assign(StorageDecorator, resource_decorator_js_1.ResourceDecorator);
|
|
|
25
25
|
StorageDecorator.Action = Action;
|
|
26
26
|
function Delete(options) {
|
|
27
27
|
const list = [];
|
|
28
|
-
return (0,
|
|
28
|
+
return (0, crud_operation_decorator_js_1.createOperationDecorator)('delete', options, list);
|
|
29
29
|
}
|
|
30
30
|
StorageDecorator.Delete = Delete;
|
|
31
31
|
function Get(options) {
|
|
32
32
|
const list = [];
|
|
33
|
-
return (0,
|
|
33
|
+
return (0, crud_operation_decorator_js_1.createOperationDecorator)('get', options, list);
|
|
34
34
|
}
|
|
35
35
|
StorageDecorator.Get = Get;
|
|
36
36
|
function Post(options) {
|
|
37
37
|
const list = [];
|
|
38
|
-
const decorator = (0,
|
|
38
|
+
const decorator = (0, crud_operation_decorator_js_1.createOperationDecorator)('post', options, list);
|
|
39
39
|
decorator.MaxFields = (amount) => {
|
|
40
|
-
list.push(operationMeta => operationMeta.maxFields = amount);
|
|
40
|
+
list.push(operationMeta => operationMeta.options.maxFields = amount);
|
|
41
41
|
return decorator;
|
|
42
42
|
};
|
|
43
43
|
decorator.MaxFieldSize = (amount) => {
|
|
44
|
-
list.push(operationMeta => operationMeta.maxFieldsSize = amount);
|
|
44
|
+
list.push(operationMeta => operationMeta.options.maxFieldsSize = amount);
|
|
45
45
|
return decorator;
|
|
46
46
|
};
|
|
47
47
|
decorator.MaxFiles = (amount) => {
|
|
48
|
-
list.push(operationMeta => operationMeta.maxFiles = amount);
|
|
48
|
+
list.push(operationMeta => operationMeta.options.maxFiles = amount);
|
|
49
49
|
return decorator;
|
|
50
50
|
};
|
|
51
51
|
decorator.MaxFileSize = (sizeInBytes) => {
|
|
52
|
-
list.push(operationMeta => operationMeta.maxFileSize = sizeInBytes);
|
|
52
|
+
list.push(operationMeta => operationMeta.options.maxFileSize = sizeInBytes);
|
|
53
53
|
return decorator;
|
|
54
54
|
};
|
|
55
55
|
decorator.MaxTotalFileSize = (sizeInBytes) => {
|
|
56
|
-
list.push(operationMeta => operationMeta.maxTotalFileSize = sizeInBytes);
|
|
56
|
+
list.push(operationMeta => operationMeta.options.maxTotalFileSize = sizeInBytes);
|
|
57
57
|
return decorator;
|
|
58
58
|
};
|
|
59
59
|
decorator.MinFileSize = (sizeInBytes) => {
|
|
60
|
-
list.push(operationMeta => operationMeta.minFileSize = sizeInBytes);
|
|
60
|
+
list.push(operationMeta => operationMeta.options.minFileSize = sizeInBytes);
|
|
61
61
|
return decorator;
|
|
62
62
|
};
|
|
63
63
|
return decorator;
|
|
@@ -11,6 +11,7 @@ export class ComplexTypeClass extends DataType {
|
|
|
11
11
|
constructor(document, init) {
|
|
12
12
|
super(document, init);
|
|
13
13
|
this.kind = OpraSchema.ComplexType.Kind;
|
|
14
|
+
this.fields = new ResponsiveMap();
|
|
14
15
|
const own = this.own = {};
|
|
15
16
|
own.ctor = init.ctor;
|
|
16
17
|
if (init.base) {
|
|
@@ -29,7 +30,6 @@ export class ComplexTypeClass extends DataType {
|
|
|
29
30
|
this.additionalFields = true;
|
|
30
31
|
else if (this.base?.additionalFields === 'error' && !this.additionalFields)
|
|
31
32
|
this.additionalFields = 'error';
|
|
32
|
-
this.fields = new ResponsiveMap();
|
|
33
33
|
if (this.base) {
|
|
34
34
|
if (this.base.fields)
|
|
35
35
|
for (const [k, el] of this.base.fields.entries()) {
|
|
@@ -130,7 +130,11 @@ export class ComplexTypeClass extends DataType {
|
|
|
130
130
|
base: this.base ?
|
|
131
131
|
(this.base.name ? this.base.name : this.base.exportSchema(options)) : undefined,
|
|
132
132
|
abstract: this.abstract,
|
|
133
|
-
additionalFields: this.own.additionalFields
|
|
133
|
+
additionalFields: this.own.additionalFields instanceof DataType
|
|
134
|
+
? (this.own.additionalFields.name
|
|
135
|
+
? this.own.additionalFields.name
|
|
136
|
+
: this.own.additionalFields.exportSchema(options))
|
|
137
|
+
: this.own.additionalFields
|
|
134
138
|
}));
|
|
135
139
|
if (this.own.fields.size) {
|
|
136
140
|
const fields = out.fields = {};
|
|
@@ -154,9 +158,12 @@ export class ComplexTypeClass extends DataType {
|
|
|
154
158
|
}
|
|
155
159
|
generateCodec(codec, options) {
|
|
156
160
|
const schema = this._generateCodecSchema(codec, options);
|
|
161
|
+
const additionalFields = this.additionalFields instanceof DataType
|
|
162
|
+
? this.additionalFields.generateCodec(codec, options)
|
|
163
|
+
: this.additionalFields;
|
|
157
164
|
return vg.isObject(schema, {
|
|
158
165
|
ctor: this.ctor,
|
|
159
|
-
additionalFields
|
|
166
|
+
additionalFields,
|
|
160
167
|
name: this.name,
|
|
161
168
|
caseInSensitive: !options?.caseSensitive
|
|
162
169
|
});
|
|
@@ -165,20 +172,36 @@ export class ComplexTypeClass extends DataType {
|
|
|
165
172
|
const schema = {};
|
|
166
173
|
const pickOption = (options?.pick || []).map(x => x.toLowerCase());
|
|
167
174
|
const omitOption = (options?.omit || []).map(x => x.toLowerCase());
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
175
|
+
const dedupedFieldNames = (options?.overwriteFields
|
|
176
|
+
? Array.from(new Set([...this.fields.keys(), ...options?.overwriteFields.keys()]))
|
|
177
|
+
: Array.from(this.fields.keys())).map(x => x.toLocaleString());
|
|
178
|
+
for (const nameLower of dedupedFieldNames) {
|
|
179
|
+
const overwriteField = options?.overwriteFields?.get(nameLower);
|
|
180
|
+
const field = this.fields.get(nameLower);
|
|
181
|
+
/* istanbul ignore next */
|
|
182
|
+
if (!(field || overwriteField))
|
|
171
183
|
continue;
|
|
172
|
-
if (
|
|
184
|
+
if (!overwriteField &&
|
|
185
|
+
(omitOption.find(x => x === nameLower) ||
|
|
186
|
+
(pickOption.length && !pickOption.find(x => x === nameLower || x.startsWith(nameLower + '.')))))
|
|
173
187
|
continue;
|
|
188
|
+
let f;
|
|
189
|
+
if (overwriteField) {
|
|
190
|
+
f = { ...overwriteField };
|
|
191
|
+
Object.setPrototypeOf(f, field || ApiField.prototype);
|
|
192
|
+
}
|
|
193
|
+
else
|
|
194
|
+
f = field;
|
|
174
195
|
schema[f.name] = f.generateCodec(codec, {
|
|
175
196
|
...options,
|
|
176
|
-
pick:
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
197
|
+
pick: overwriteField ? [] :
|
|
198
|
+
pickOption
|
|
199
|
+
.filter(x => x.startsWith(nameLower + '.'))
|
|
200
|
+
.map(x => x.substring(x.indexOf('.') + 1)),
|
|
201
|
+
omit: overwriteField ? [] :
|
|
202
|
+
omitOption
|
|
203
|
+
.filter(x => x.startsWith(nameLower + '.'))
|
|
204
|
+
.map(x => x.substring(x.indexOf('.') + 1)),
|
|
182
205
|
});
|
|
183
206
|
}
|
|
184
207
|
return schema;
|
|
@@ -159,9 +159,9 @@ export class ApiDocumentFactory extends TypeDocumentFactory {
|
|
|
159
159
|
return;
|
|
160
160
|
const output = {};
|
|
161
161
|
for (const [kA, oA] of Object.entries(source)) {
|
|
162
|
-
|
|
162
|
+
const o = output[kA] = { ...oA };
|
|
163
163
|
if (oA.parameters) {
|
|
164
|
-
parameters = {};
|
|
164
|
+
const parameters = o.parameters = {};
|
|
165
165
|
for (const [kP, oP] of Object.entries(oA.parameters)) {
|
|
166
166
|
if (oP.enum) {
|
|
167
167
|
oP.type = EnumType(oP.enum, { name: kP + 'Enum' });
|
|
@@ -172,7 +172,30 @@ export class ApiDocumentFactory extends TypeDocumentFactory {
|
|
|
172
172
|
};
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
|
-
|
|
175
|
+
if (oA.options?.inputOverwriteFields) {
|
|
176
|
+
const inputOverwriteFields = {};
|
|
177
|
+
for (const [kP, oP] of Object.entries(oA.options.inputOverwriteFields)) {
|
|
178
|
+
if (oP.enum) {
|
|
179
|
+
oP.type = EnumType(oP.enum, { name: kP + 'Enum' });
|
|
180
|
+
}
|
|
181
|
+
inputOverwriteFields[kP] = { ...oP, };
|
|
182
|
+
if (oP.type)
|
|
183
|
+
inputOverwriteFields[kP].type = await this.importDataType(oP.type);
|
|
184
|
+
}
|
|
185
|
+
o.options.inputOverwriteFields = inputOverwriteFields;
|
|
186
|
+
}
|
|
187
|
+
if (oA.options?.outputOverwriteFields) {
|
|
188
|
+
const outputOverwriteFields = {};
|
|
189
|
+
for (const [kP, oP] of Object.entries(oA.options.outputOverwriteFields)) {
|
|
190
|
+
if (oP.enum) {
|
|
191
|
+
oP.type = EnumType(oP.enum, { name: kP + 'Enum' });
|
|
192
|
+
}
|
|
193
|
+
outputOverwriteFields[kP] = { ...oP };
|
|
194
|
+
if (oP.type)
|
|
195
|
+
outputOverwriteFields[kP].type = await this.importDataType(oP.type);
|
|
196
|
+
}
|
|
197
|
+
o.options.outputOverwriteFields = outputOverwriteFields;
|
|
198
|
+
}
|
|
176
199
|
}
|
|
177
200
|
return output;
|
|
178
201
|
};
|
|
@@ -139,7 +139,7 @@ export class TypeDocumentFactory {
|
|
|
139
139
|
return dataType;
|
|
140
140
|
throw new TypeError(`Class "${thunk.name}" doesn't have a valid DataType metadata`);
|
|
141
141
|
}
|
|
142
|
-
name = metadata.name;
|
|
142
|
+
name = metadata.anonymous ? undefined : metadata.name;
|
|
143
143
|
initArguments = cloneObject(metadata);
|
|
144
144
|
ctor = thunk;
|
|
145
145
|
}
|
|
@@ -154,7 +154,7 @@ export class TypeDocumentFactory {
|
|
|
154
154
|
const metadata = thunk[DATATYPE_METADATA];
|
|
155
155
|
if (!metadata)
|
|
156
156
|
throw new TypeError(`No EnumType metadata found for object ${JSON.stringify(thunk).substring(0, 20)}...`);
|
|
157
|
-
name = metadata.name;
|
|
157
|
+
name = metadata.anonymous ? undefined : metadata.name;
|
|
158
158
|
initArguments = cloneObject(metadata);
|
|
159
159
|
initArguments.enumObject = thunk;
|
|
160
160
|
}
|
|
@@ -186,8 +186,11 @@ export class TypeDocumentFactory {
|
|
|
186
186
|
if (name)
|
|
187
187
|
this.document.types.set(name, instance);
|
|
188
188
|
await this.prepareDataTypeInitArguments(initArguments, ctor);
|
|
189
|
-
if (initArguments.kind === 'ComplexType')
|
|
189
|
+
if (initArguments.kind === 'ComplexType') {
|
|
190
|
+
if (typeof initArguments.additionalFields === 'function')
|
|
191
|
+
initArguments.additionalFields = await this.importDataType(initArguments.additionalFields);
|
|
190
192
|
ComplexType.apply(instance, [this.document, initArguments]);
|
|
193
|
+
}
|
|
191
194
|
else if (initArguments.kind === 'SimpleType')
|
|
192
195
|
SimpleType.apply(instance, [this.document, initArguments]);
|
|
193
196
|
else if (initArguments.kind === 'EnumType')
|
package/esm/document/index.js
CHANGED
|
@@ -16,7 +16,7 @@ export * from './resource/collection.js';
|
|
|
16
16
|
export * from './resource/container.js';
|
|
17
17
|
export * from './resource/crud-resource.js';
|
|
18
18
|
export * from './resource/endpoint.js';
|
|
19
|
-
export * from './resource/operation.js';
|
|
19
|
+
export * from './resource/crud-operation.js';
|
|
20
20
|
export * from './resource/parameter.js';
|
|
21
21
|
export * from './resource/resource.js';
|
|
22
22
|
export * from './resource/singleton.js';
|
|
@@ -30,16 +30,18 @@ export class CollectionClass extends CrudResource {
|
|
|
30
30
|
endpoint.defineParameter('include', { type: 'string', isArray: true, isBuiltin: true });
|
|
31
31
|
endpoint.decodeInput = this.type.generateCodec('decode', {
|
|
32
32
|
partial: true,
|
|
33
|
-
pick: endpoint.inputPickFields,
|
|
34
|
-
omit: endpoint.inputOmitFields,
|
|
35
|
-
operation: 'write'
|
|
33
|
+
pick: endpoint.options.inputPickFields,
|
|
34
|
+
omit: endpoint.options.inputOmitFields,
|
|
35
|
+
operation: 'write',
|
|
36
|
+
overwriteFields: endpoint.inputOverwriteFields
|
|
36
37
|
});
|
|
37
38
|
endpoint.returnType = this.type;
|
|
38
39
|
endpoint.encodeReturning = endpoint.returnType.generateCodec('encode', {
|
|
39
40
|
partial: true,
|
|
40
|
-
pick: endpoint.outputPickFields,
|
|
41
|
-
omit: endpoint.outputOmitFields,
|
|
42
|
-
operation: 'read'
|
|
41
|
+
pick: endpoint.options.outputPickFields,
|
|
42
|
+
omit: endpoint.options.outputOmitFields,
|
|
43
|
+
operation: 'read',
|
|
44
|
+
overwriteFields: endpoint.outputOverwriteFields
|
|
43
45
|
});
|
|
44
46
|
}
|
|
45
47
|
// ------------------
|
|
@@ -58,9 +60,10 @@ export class CollectionClass extends CrudResource {
|
|
|
58
60
|
endpoint.returnType = this.type;
|
|
59
61
|
endpoint.encodeReturning = endpoint.returnType.generateCodec('encode', {
|
|
60
62
|
partial: true,
|
|
61
|
-
pick: endpoint.outputPickFields,
|
|
62
|
-
omit: endpoint.outputOmitFields,
|
|
63
|
-
operation: 'read'
|
|
63
|
+
pick: endpoint.options.outputPickFields,
|
|
64
|
+
omit: endpoint.options.outputOmitFields,
|
|
65
|
+
operation: 'read',
|
|
66
|
+
overwriteFields: endpoint.outputOverwriteFields
|
|
64
67
|
});
|
|
65
68
|
}
|
|
66
69
|
// ------------------
|
|
@@ -79,9 +82,10 @@ export class CollectionClass extends CrudResource {
|
|
|
79
82
|
endpoint.returnType = this.type;
|
|
80
83
|
endpoint.encodeReturning = vg.isArray(this.type.generateCodec('encode', {
|
|
81
84
|
partial: true,
|
|
82
|
-
pick: endpoint.outputPickFields,
|
|
83
|
-
omit: endpoint.outputOmitFields,
|
|
84
|
-
operation: 'read'
|
|
85
|
+
pick: endpoint.options.outputPickFields,
|
|
86
|
+
omit: endpoint.options.outputOmitFields,
|
|
87
|
+
operation: 'read',
|
|
88
|
+
overwriteFields: endpoint.outputOverwriteFields
|
|
85
89
|
}));
|
|
86
90
|
}
|
|
87
91
|
// ------------------
|
|
@@ -92,16 +96,18 @@ export class CollectionClass extends CrudResource {
|
|
|
92
96
|
endpoint.defineParameter('omit', { type: 'string', isArray: true, isBuiltin: true });
|
|
93
97
|
endpoint.defineParameter('include', { type: 'string', isArray: true, isBuiltin: true });
|
|
94
98
|
endpoint.decodeInput = this.type.generateCodec('decode', {
|
|
95
|
-
pick: endpoint.inputPickFields,
|
|
96
|
-
omit: endpoint.inputOmitFields,
|
|
97
|
-
operation: 'write'
|
|
99
|
+
pick: endpoint.options.inputPickFields,
|
|
100
|
+
omit: endpoint.options.inputOmitFields,
|
|
101
|
+
operation: 'write',
|
|
102
|
+
overwriteFields: endpoint.inputOverwriteFields
|
|
98
103
|
});
|
|
99
104
|
endpoint.returnType = this.type;
|
|
100
105
|
endpoint.encodeReturning = endpoint.returnType.generateCodec('encode', {
|
|
101
106
|
partial: true,
|
|
102
|
-
pick: endpoint.outputPickFields,
|
|
103
|
-
omit: endpoint.outputOmitFields,
|
|
104
|
-
operation: 'read'
|
|
107
|
+
pick: endpoint.options.outputPickFields,
|
|
108
|
+
omit: endpoint.options.outputOmitFields,
|
|
109
|
+
operation: 'read',
|
|
110
|
+
overwriteFields: endpoint.outputOverwriteFields
|
|
105
111
|
});
|
|
106
112
|
}
|
|
107
113
|
// ------------------
|
|
@@ -110,15 +116,13 @@ export class CollectionClass extends CrudResource {
|
|
|
110
116
|
// endpoint.defineParameter('metadata', {enum: MetadataMode, isBuiltin: true, default: 'minimal'});
|
|
111
117
|
endpoint.defineParameter('filter', { type: 'string', isBuiltin: true });
|
|
112
118
|
endpoint.decodeInput = this.type.generateCodec('decode', {
|
|
113
|
-
pick: endpoint.inputPickFields,
|
|
114
|
-
omit: endpoint.inputOmitFields,
|
|
115
|
-
operation: 'write'
|
|
119
|
+
pick: endpoint.options.inputPickFields,
|
|
120
|
+
omit: endpoint.options.inputOmitFields,
|
|
121
|
+
operation: 'write',
|
|
122
|
+
overwriteFields: endpoint.inputOverwriteFields
|
|
116
123
|
});
|
|
117
124
|
}
|
|
118
125
|
}
|
|
119
|
-
getOperation(name) {
|
|
120
|
-
return super.getOperation(name);
|
|
121
|
-
}
|
|
122
126
|
exportSchema(options) {
|
|
123
127
|
return {
|
|
124
128
|
...super.exportSchema(options),
|
|
@@ -170,7 +174,7 @@ export class CollectionClass extends CrudResource {
|
|
|
170
174
|
if (!normalized)
|
|
171
175
|
return;
|
|
172
176
|
const findManyOp = this.getOperation('findMany');
|
|
173
|
-
const sortFields = findManyOp && findManyOp.sortFields;
|
|
177
|
+
const sortFields = findManyOp && findManyOp.options.sortFields;
|
|
174
178
|
(Array.isArray(normalized) ? normalized : [normalized]).forEach(field => {
|
|
175
179
|
if (!sortFields?.find(x => x === field))
|
|
176
180
|
throw new BadRequestError({
|
|
@@ -190,7 +194,7 @@ export class CollectionClass extends CrudResource {
|
|
|
190
194
|
// Check if filtering accepted for given field
|
|
191
195
|
const findManyOp = this.getOperation('findMany');
|
|
192
196
|
const fieldLower = ast.left.value.toLowerCase();
|
|
193
|
-
const filterDef = (findManyOp && findManyOp.filters || [])
|
|
197
|
+
const filterDef = (findManyOp && findManyOp.options.filters || [])
|
|
194
198
|
.find(f => f.field.toLowerCase() === fieldLower);
|
|
195
199
|
if (!filterDef) {
|
|
196
200
|
throw new BadRequestError({
|
|
@@ -198,7 +202,7 @@ export class CollectionClass extends CrudResource {
|
|
|
198
202
|
});
|
|
199
203
|
}
|
|
200
204
|
// Check if filtering endpoint accepted for given field
|
|
201
|
-
if (!filterDef.operators
|
|
205
|
+
if (filterDef.operators && !filterDef.operators.includes(ast.op))
|
|
202
206
|
throw new BadRequestError({
|
|
203
207
|
message: translate('error:UNACCEPTED_FILTER_OPERATION', { field: ast.left.value }),
|
|
204
208
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { omitUndefined } from '../../helpers/index.js';
|
|
2
2
|
import { OpraSchema } from '../../schema/index.js';
|
|
3
3
|
import { createActionDecorator } from './action-decorator.js';
|
|
4
|
-
import { createOperationDecorator } from './operation-decorator.js';
|
|
4
|
+
import { createOperationDecorator } from './crud-operation-decorator.js';
|
|
5
5
|
import { ResourceDecorator } from './resource-decorator.js';
|
|
6
6
|
const operationProperties = ['create', 'delete', 'deleteMany', 'get', 'findMany', 'update', 'updateMany'];
|
|
7
7
|
export function CollectionDecorator(type, options) {
|
|
@@ -24,23 +24,31 @@ Object.assign(CollectionDecorator, ResourceDecorator);
|
|
|
24
24
|
const list = [];
|
|
25
25
|
const decorator = createOperationDecorator('create', options, list);
|
|
26
26
|
decorator.InputMaxContentSize = (sizeInBytes) => {
|
|
27
|
-
list.push(operationMeta => operationMeta.inputMaxContentSize = sizeInBytes);
|
|
27
|
+
list.push(operationMeta => operationMeta.options.inputMaxContentSize = sizeInBytes);
|
|
28
28
|
return decorator;
|
|
29
29
|
};
|
|
30
30
|
decorator.InputPickFields = (...fields) => {
|
|
31
|
-
list.push(operationMeta => operationMeta.inputPickFields = fields);
|
|
31
|
+
list.push(operationMeta => operationMeta.options.inputPickFields = fields);
|
|
32
32
|
return decorator;
|
|
33
33
|
};
|
|
34
34
|
decorator.InputOmitFields = (...fields) => {
|
|
35
|
-
list.push(operationMeta => operationMeta.inputOmitFields = fields);
|
|
35
|
+
list.push(operationMeta => operationMeta.options.inputOmitFields = fields);
|
|
36
|
+
return decorator;
|
|
37
|
+
};
|
|
38
|
+
decorator.InputOverwriteFields = (fields) => {
|
|
39
|
+
list.push(operationMeta => operationMeta.options.inputOverwriteFields = fields);
|
|
36
40
|
return decorator;
|
|
37
41
|
};
|
|
38
42
|
decorator.OutputPickFields = (...fields) => {
|
|
39
|
-
list.push(operationMeta => operationMeta.outputPickFields = fields);
|
|
43
|
+
list.push(operationMeta => operationMeta.options.outputPickFields = fields);
|
|
40
44
|
return decorator;
|
|
41
45
|
};
|
|
42
46
|
decorator.OutputOmitFields = (...fields) => {
|
|
43
|
-
list.push(operationMeta => operationMeta.outputOmitFields = fields);
|
|
47
|
+
list.push(operationMeta => operationMeta.options.outputOmitFields = fields);
|
|
48
|
+
return decorator;
|
|
49
|
+
};
|
|
50
|
+
decorator.OutputOverwriteFields = (fields) => {
|
|
51
|
+
list.push(operationMeta => operationMeta.options.outputOverwriteFields = fields);
|
|
44
52
|
return decorator;
|
|
45
53
|
};
|
|
46
54
|
return decorator;
|
|
@@ -58,8 +66,8 @@ Object.assign(CollectionDecorator, ResourceDecorator);
|
|
|
58
66
|
if (typeof operators === 'string')
|
|
59
67
|
operators = operators.split(/\s*[,| ]\s*/);
|
|
60
68
|
list.push(operationMeta => {
|
|
61
|
-
operationMeta.filters = operationMeta.filters || [];
|
|
62
|
-
operationMeta.filters.push(omitUndefined({ field, operators, notes }));
|
|
69
|
+
operationMeta.options.filters = operationMeta.options.filters || [];
|
|
70
|
+
operationMeta.options.filters.push(omitUndefined({ field, operators, notes }));
|
|
63
71
|
});
|
|
64
72
|
return decorator;
|
|
65
73
|
};
|
|
@@ -70,11 +78,15 @@ Object.assign(CollectionDecorator, ResourceDecorator);
|
|
|
70
78
|
const list = [];
|
|
71
79
|
const decorator = createOperationDecorator('get', options, list);
|
|
72
80
|
decorator.OutputPickFields = (...fields) => {
|
|
73
|
-
list.push(operationMeta => operationMeta.outputPickFields = fields);
|
|
81
|
+
list.push(operationMeta => operationMeta.options.outputPickFields = fields);
|
|
74
82
|
return decorator;
|
|
75
83
|
};
|
|
76
84
|
decorator.OutputOmitFields = (...fields) => {
|
|
77
|
-
list.push(operationMeta => operationMeta.outputOmitFields = fields);
|
|
85
|
+
list.push(operationMeta => operationMeta.options.outputOmitFields = fields);
|
|
86
|
+
return decorator;
|
|
87
|
+
};
|
|
88
|
+
decorator.OutputOverwriteFields = (fields) => {
|
|
89
|
+
list.push(operationMeta => operationMeta.options.outputOverwriteFields = fields);
|
|
78
90
|
return decorator;
|
|
79
91
|
};
|
|
80
92
|
return decorator;
|
|
@@ -84,28 +96,32 @@ Object.assign(CollectionDecorator, ResourceDecorator);
|
|
|
84
96
|
const list = [];
|
|
85
97
|
const decorator = createOperationDecorator('findMany', options, list);
|
|
86
98
|
decorator.SortFields = (...fields) => {
|
|
87
|
-
list.push(operationMeta => operationMeta.sortFields = fields);
|
|
99
|
+
list.push(operationMeta => operationMeta.options.sortFields = fields);
|
|
88
100
|
return decorator;
|
|
89
101
|
};
|
|
90
102
|
decorator.DefaultSort = (...fields) => {
|
|
91
|
-
list.push(operationMeta => operationMeta.defaultSort = fields);
|
|
103
|
+
list.push(operationMeta => operationMeta.options.defaultSort = fields);
|
|
92
104
|
return decorator;
|
|
93
105
|
};
|
|
94
106
|
decorator.Filter = (field, operators, notes) => {
|
|
95
107
|
if (typeof operators === 'string')
|
|
96
108
|
operators = operators.split(/\s*[,| ]\s*/);
|
|
97
109
|
list.push(operationMeta => {
|
|
98
|
-
operationMeta.filters = operationMeta.filters || [];
|
|
99
|
-
operationMeta.filters.push(omitUndefined({ field, operators, notes }));
|
|
110
|
+
operationMeta.options.filters = operationMeta.options.filters || [];
|
|
111
|
+
operationMeta.options.filters.push(omitUndefined({ field, operators, notes }));
|
|
100
112
|
});
|
|
101
113
|
return decorator;
|
|
102
114
|
};
|
|
103
115
|
decorator.OutputPickFields = (...fields) => {
|
|
104
|
-
list.push(operationMeta => operationMeta.outputPickFields = fields);
|
|
116
|
+
list.push(operationMeta => operationMeta.options.outputPickFields = fields);
|
|
105
117
|
return decorator;
|
|
106
118
|
};
|
|
107
119
|
decorator.OutputOmitFields = (...fields) => {
|
|
108
|
-
list.push(operationMeta => operationMeta.outputOmitFields = fields);
|
|
120
|
+
list.push(operationMeta => operationMeta.options.outputOmitFields = fields);
|
|
121
|
+
return decorator;
|
|
122
|
+
};
|
|
123
|
+
decorator.OutputOverwriteFields = (fields) => {
|
|
124
|
+
list.push(operationMeta => operationMeta.options.outputOverwriteFields = fields);
|
|
109
125
|
return decorator;
|
|
110
126
|
};
|
|
111
127
|
return decorator;
|
|
@@ -120,23 +136,31 @@ Object.assign(CollectionDecorator, ResourceDecorator);
|
|
|
120
136
|
const list = [];
|
|
121
137
|
const decorator = createOperationDecorator('update', options, list);
|
|
122
138
|
decorator.InputMaxContentSize = (sizeInBytes) => {
|
|
123
|
-
list.push(operationMeta => operationMeta.inputMaxContentSize = sizeInBytes);
|
|
139
|
+
list.push(operationMeta => operationMeta.options.inputMaxContentSize = sizeInBytes);
|
|
124
140
|
return decorator;
|
|
125
141
|
};
|
|
126
142
|
decorator.InputPickFields = (...fields) => {
|
|
127
|
-
list.push(operationMeta => operationMeta.inputPickFields = fields);
|
|
143
|
+
list.push(operationMeta => operationMeta.options.inputPickFields = fields);
|
|
128
144
|
return decorator;
|
|
129
145
|
};
|
|
130
146
|
decorator.InputOmitFields = (...fields) => {
|
|
131
|
-
list.push(operationMeta => operationMeta.inputOmitFields = fields);
|
|
147
|
+
list.push(operationMeta => operationMeta.options.inputOmitFields = fields);
|
|
148
|
+
return decorator;
|
|
149
|
+
};
|
|
150
|
+
decorator.InputOverwriteFields = (fields) => {
|
|
151
|
+
list.push(operationMeta => operationMeta.options.inputOverwriteFields = fields);
|
|
132
152
|
return decorator;
|
|
133
153
|
};
|
|
134
154
|
decorator.OutputPickFields = (...fields) => {
|
|
135
|
-
list.push(operationMeta => operationMeta.outputPickFields = fields);
|
|
155
|
+
list.push(operationMeta => operationMeta.options.outputPickFields = fields);
|
|
136
156
|
return decorator;
|
|
137
157
|
};
|
|
138
158
|
decorator.OutputOmitFields = (...fields) => {
|
|
139
|
-
list.push(operationMeta => operationMeta.outputOmitFields = fields);
|
|
159
|
+
list.push(operationMeta => operationMeta.options.outputOmitFields = fields);
|
|
160
|
+
return decorator;
|
|
161
|
+
};
|
|
162
|
+
decorator.OutputOverwriteFields = (fields) => {
|
|
163
|
+
list.push(operationMeta => operationMeta.options.outputOverwriteFields = fields);
|
|
140
164
|
return decorator;
|
|
141
165
|
};
|
|
142
166
|
return decorator;
|
|
@@ -152,23 +176,27 @@ Object.assign(CollectionDecorator, ResourceDecorator);
|
|
|
152
176
|
const options = typeof arg0 === 'string' ? { description: arg0 } : { ...arg0 };
|
|
153
177
|
const decorator = createOperationDecorator('updateMany', options, list);
|
|
154
178
|
decorator.InputMaxContentSize = (sizeInBytes) => {
|
|
155
|
-
list.push(operationMeta => operationMeta.inputMaxContentSize = sizeInBytes);
|
|
179
|
+
list.push(operationMeta => operationMeta.options.inputMaxContentSize = sizeInBytes);
|
|
156
180
|
return decorator;
|
|
157
181
|
};
|
|
158
182
|
decorator.InputPickFields = (...fields) => {
|
|
159
|
-
list.push(operationMeta => operationMeta.inputPickFields = fields);
|
|
183
|
+
list.push(operationMeta => operationMeta.options.inputPickFields = fields);
|
|
160
184
|
return decorator;
|
|
161
185
|
};
|
|
162
186
|
decorator.InputOmitFields = (...fields) => {
|
|
163
|
-
list.push(operationMeta => operationMeta.inputOmitFields = fields);
|
|
187
|
+
list.push(operationMeta => operationMeta.options.inputOmitFields = fields);
|
|
188
|
+
return decorator;
|
|
189
|
+
};
|
|
190
|
+
decorator.InputOverwriteFields = (fields) => {
|
|
191
|
+
list.push(operationMeta => operationMeta.options.inputOverwriteFields = fields);
|
|
164
192
|
return decorator;
|
|
165
193
|
};
|
|
166
194
|
decorator.Filter = (field, operators, notes) => {
|
|
167
195
|
if (typeof operators === 'string')
|
|
168
196
|
operators = operators.split(/\s*[,| ]\s*/);
|
|
169
197
|
list.push(operationMeta => {
|
|
170
|
-
operationMeta.filters = operationMeta.filters || [];
|
|
171
|
-
operationMeta.filters.push(omitUndefined({ field, operators, notes }));
|
|
198
|
+
operationMeta.options.filters = operationMeta.options.filters || [];
|
|
199
|
+
operationMeta.options.filters.push(omitUndefined({ field, operators, notes }));
|
|
172
200
|
});
|
|
173
201
|
return decorator;
|
|
174
202
|
};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { RESOURCE_METADATA } from '../constants.js';
|
|
2
|
-
export function createOperationDecorator(operation,
|
|
2
|
+
export function createOperationDecorator(operation, init, list) {
|
|
3
3
|
const decorator = ((target, propertyKey) => {
|
|
4
4
|
if (propertyKey !== operation)
|
|
5
5
|
throw new TypeError(`Name of the handler name should be '${operation}'`);
|
|
6
6
|
const resourceMetadata = (Reflect.getOwnMetadata(RESOURCE_METADATA, target.constructor) || {});
|
|
7
7
|
resourceMetadata.operations = resourceMetadata.operations || {};
|
|
8
|
-
const operationMeta = { ...
|
|
8
|
+
const operationMeta = { ...init };
|
|
9
|
+
operationMeta.options = operationMeta.options || {};
|
|
9
10
|
resourceMetadata.operations[operation] = operationMeta;
|
|
10
11
|
for (const fn of list)
|
|
11
12
|
fn(operationMeta, target, propertyKey);
|