@opra/common 1.5.0 → 1.5.1
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/api-document.js +2 -3
- package/cjs/document/common/document-init-context.js +0 -5
- package/cjs/document/common/document-node.js +2 -3
- package/cjs/document/data-type/api-field.js +9 -18
- package/cjs/document/data-type/complex-type-base.js +16 -14
- package/cjs/document/data-type/complex-type.js +14 -7
- package/cjs/document/data-type/data-type.js +12 -14
- package/cjs/document/data-type/enum-type.js +12 -9
- package/cjs/document/data-type/extended-types/field-path.type.js +7 -7
- package/cjs/document/data-type/extended-types/filter.type.js +5 -5
- package/cjs/document/data-type/mapped-type.js +10 -4
- package/cjs/document/data-type/mixin-type.js +13 -4
- package/cjs/document/data-type/simple-type.js +11 -16
- package/cjs/document/decorators/api-field-decorator.js +37 -3
- package/cjs/document/decorators/simple-type.decorator.js +2 -0
- package/cjs/document/factory/api-document.factory.js +0 -1
- package/cjs/document/utils/test-scope-match.js +13 -0
- package/cjs/filter/filter-rules.js +6 -7
- package/esm/document/api-document.js +2 -3
- package/esm/document/common/document-init-context.js +0 -5
- package/esm/document/common/document-node.js +2 -3
- package/esm/document/data-type/api-field.js +10 -19
- package/esm/document/data-type/complex-type-base.js +16 -14
- package/esm/document/data-type/complex-type.js +14 -7
- package/esm/document/data-type/data-type.js +12 -14
- package/esm/document/data-type/enum-type.js +12 -9
- package/esm/document/data-type/extended-types/field-path.type.js +7 -7
- package/esm/document/data-type/extended-types/filter.type.js +5 -5
- package/esm/document/data-type/mapped-type.js +10 -4
- package/esm/document/data-type/mixin-type.js +13 -4
- package/esm/document/data-type/simple-type.js +11 -16
- package/esm/document/decorators/api-field-decorator.js +36 -2
- package/esm/document/decorators/simple-type.decorator.js +2 -0
- package/esm/document/factory/api-document.factory.js +0 -1
- package/esm/document/utils/test-scope-match.js +10 -0
- package/esm/filter/filter-rules.js +6 -7
- package/package.json +1 -1
- package/types/document/api-document.d.ts +2 -3
- package/types/document/common/document-init-context.d.ts +0 -1
- package/types/document/common/document-node.d.ts +8 -8
- package/types/document/data-type/api-field.d.ts +40 -27
- package/types/document/data-type/complex-type-base.d.ts +4 -2
- package/types/document/data-type/complex-type.d.ts +1 -0
- package/types/document/data-type/data-type.d.ts +6 -5
- package/types/document/data-type/enum-type.d.ts +1 -0
- package/types/document/data-type/extended-types/field-path.type.d.ts +2 -2
- package/types/document/data-type/mapped-type.d.ts +1 -0
- package/types/document/data-type/mixin-type.d.ts +1 -0
- package/types/document/data-type/simple-type.d.ts +1 -1
- package/types/document/decorators/api-field-decorator.d.ts +5 -3
- package/types/document/decorators/simple-type.decorator.d.ts +34 -0
- package/types/document/factory/api-document.factory.d.ts +1 -1
- package/types/document/http/http-api.d.ts +1 -1
- package/types/document/utils/test-scope-match.d.ts +1 -0
- package/types/filter/filter-rules.d.ts +3 -3
|
@@ -74,7 +74,6 @@ class ApiDocument extends document_element_js_1.DocumentElement {
|
|
|
74
74
|
url: this.url,
|
|
75
75
|
info: (0, index_js_1.cloneObject)(this.info, true),
|
|
76
76
|
});
|
|
77
|
-
options = options || { scopes: this.scopes };
|
|
78
77
|
if (this.references.size) {
|
|
79
78
|
let i = 0;
|
|
80
79
|
const references = {};
|
|
@@ -94,7 +93,7 @@ class ApiDocument extends document_element_js_1.DocumentElement {
|
|
|
94
93
|
if (this.types.size) {
|
|
95
94
|
out.types = {};
|
|
96
95
|
for (const v of this.types.values()) {
|
|
97
|
-
if (!v.inScope(options
|
|
96
|
+
if (options?.scope && !v.inScope(options?.scope))
|
|
98
97
|
continue;
|
|
99
98
|
out.types[v.name] = v.toJSON(options);
|
|
100
99
|
}
|
|
@@ -113,7 +112,7 @@ class ApiDocument extends document_element_js_1.DocumentElement {
|
|
|
113
112
|
}
|
|
114
113
|
_findDataType(nameOrCtor, scope, visitedRefs) {
|
|
115
114
|
let result = this.types.get(nameOrCtor);
|
|
116
|
-
if (result && result.inScope(scope))
|
|
115
|
+
if (result && (!scope || result.inScope(scope)))
|
|
117
116
|
return result;
|
|
118
117
|
if (!this.references.size)
|
|
119
118
|
return;
|
|
@@ -9,11 +9,6 @@ class DocumentInitContext {
|
|
|
9
9
|
this.showErrorDetails = true;
|
|
10
10
|
this.maxErrors = options?.maxErrors || 0;
|
|
11
11
|
this.error.message = '';
|
|
12
|
-
this.scopes = options?.scopes
|
|
13
|
-
? Array.isArray(options.scopes)
|
|
14
|
-
? options?.scopes
|
|
15
|
-
: [options?.scopes]
|
|
16
|
-
: undefined;
|
|
17
12
|
}
|
|
18
13
|
addError(error) {
|
|
19
14
|
if (!this.error.details.length) {
|
|
@@ -25,9 +25,8 @@ class DocumentNode {
|
|
|
25
25
|
return !!this.findDataType(nameOrCtor, scope);
|
|
26
26
|
}
|
|
27
27
|
findDataType(nameOrCtor, scope) {
|
|
28
|
-
scope = scope || this.getDocument().scopes;
|
|
29
28
|
const dt = this[constants_js_1.kDataTypeMap]?.get(nameOrCtor);
|
|
30
|
-
if (dt && dt.inScope(scope))
|
|
29
|
+
if (dt && (!scope || dt.inScope(scope)))
|
|
31
30
|
return dt;
|
|
32
31
|
return this.parent
|
|
33
32
|
? this.parent.findDataType(nameOrCtor, scope)
|
|
@@ -38,7 +37,7 @@ class DocumentNode {
|
|
|
38
37
|
*/
|
|
39
38
|
getDataType(nameOrCtor, scope) {
|
|
40
39
|
const dt = this.findDataType(nameOrCtor);
|
|
41
|
-
if (dt && dt.inScope(scope))
|
|
40
|
+
if (dt && (!scope || dt.inScope(scope)))
|
|
42
41
|
return dt;
|
|
43
42
|
let name = '';
|
|
44
43
|
if (typeof nameOrCtor === 'function') {
|
|
@@ -6,9 +6,9 @@ const ts_gems_1 = require("ts-gems");
|
|
|
6
6
|
const document_element_js_1 = require("../common/document-element.js");
|
|
7
7
|
const constants_js_1 = require("../constants.js");
|
|
8
8
|
const api_field_decorator_js_1 = require("../decorators/api-field-decorator.js");
|
|
9
|
+
const test_scope_match_js_1 = require("../utils/test-scope-match.js");
|
|
9
10
|
const complex_type_base_js_1 = require("./complex-type-base.js");
|
|
10
11
|
/**
|
|
11
|
-
* @constructor ApiField
|
|
12
12
|
* @decorator ApiField
|
|
13
13
|
*/
|
|
14
14
|
exports.ApiField = function (...args) {
|
|
@@ -28,7 +28,7 @@ exports.ApiField = function (...args) {
|
|
|
28
28
|
throw new Error('Field origin should be one of ComplexType, MappedType or MixinType');
|
|
29
29
|
}
|
|
30
30
|
_this.origin = origin;
|
|
31
|
-
_this.
|
|
31
|
+
_this.scopePattern = initArgs.scopePattern;
|
|
32
32
|
_this.type = initArgs.type || owner.node.getDataType('any');
|
|
33
33
|
_this.description = initArgs.description;
|
|
34
34
|
_this.isArray = initArgs.isArray;
|
|
@@ -44,22 +44,13 @@ exports.ApiField = function (...args) {
|
|
|
44
44
|
_this.examples = initArgs.examples;
|
|
45
45
|
};
|
|
46
46
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
47
|
+
* The ApiFieldClass represents a descriptive metadata structure for API fields,
|
|
48
|
+
* supporting features like data type definition, scoping, localization, and constraints.
|
|
49
|
+
* This class extends DocumentElement, inheriting base document structure capabilities.
|
|
49
50
|
*/
|
|
50
51
|
class ApiFieldClass extends document_element_js_1.DocumentElement {
|
|
51
|
-
inScope(
|
|
52
|
-
|
|
53
|
-
return true;
|
|
54
|
-
/** this.scope should match all required scopes */
|
|
55
|
-
scopes = Array.isArray(scopes) ? scopes : [scopes];
|
|
56
|
-
for (const scope of scopes) {
|
|
57
|
-
if (!this.scopes.some(s => {
|
|
58
|
-
return typeof s === 'string' ? scope === s : s.test(scope);
|
|
59
|
-
}))
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
return true;
|
|
52
|
+
inScope(scope) {
|
|
53
|
+
return (0, test_scope_match_js_1.testScopeMatch)(scope, this.scopePattern);
|
|
63
54
|
}
|
|
64
55
|
toJSON(options) {
|
|
65
56
|
const typeName = this.type
|
|
@@ -83,5 +74,5 @@ class ApiFieldClass extends document_element_js_1.DocumentElement {
|
|
|
83
74
|
}
|
|
84
75
|
}
|
|
85
76
|
exports.ApiField.prototype = ApiFieldClass.prototype;
|
|
86
|
-
Object.assign(exports.ApiField, api_field_decorator_js_1.
|
|
87
|
-
exports.ApiField[constants_js_1.DECORATOR] = api_field_decorator_js_1.
|
|
77
|
+
Object.assign(exports.ApiField, api_field_decorator_js_1.ApiFieldDecoratorFactory);
|
|
78
|
+
exports.ApiField[constants_js_1.DECORATOR] = api_field_decorator_js_1.ApiFieldDecoratorFactory;
|
|
@@ -4,7 +4,6 @@ exports.ComplexTypeBase = exports.FIELD_PATH_PATTERN = void 0;
|
|
|
4
4
|
const ts_gems_1 = require("ts-gems");
|
|
5
5
|
const valgen_1 = require("valgen");
|
|
6
6
|
const index_js_1 = require("../../helpers/index.js");
|
|
7
|
-
const index_js_2 = require("../../i18n/index.js");
|
|
8
7
|
const data_type_js_1 = require("./data-type.js");
|
|
9
8
|
exports.FIELD_PATH_PATTERN = /^([+-])?([a-z$_][\w.]*)$/i;
|
|
10
9
|
/**
|
|
@@ -27,21 +26,29 @@ class ComplexTypeBaseClass extends data_type_js_1.DataType {
|
|
|
27
26
|
/**
|
|
28
27
|
*
|
|
29
28
|
*/
|
|
30
|
-
findField(nameOrPath) {
|
|
29
|
+
findField(nameOrPath, scope) {
|
|
31
30
|
if (nameOrPath.includes('.')) {
|
|
32
|
-
const fieldPath = this.parseFieldPath(nameOrPath);
|
|
31
|
+
const fieldPath = this.parseFieldPath(nameOrPath, { scope });
|
|
32
|
+
if (fieldPath.length === 0)
|
|
33
|
+
throw new Error(`Field "${nameOrPath}" does not exist in scope "${scope}"`);
|
|
33
34
|
const lastItem = fieldPath.pop();
|
|
34
35
|
return lastItem?.field;
|
|
35
36
|
}
|
|
36
|
-
|
|
37
|
+
const field = this.fields.get(nameOrPath);
|
|
38
|
+
if (field && scope && !field.inScope(scope))
|
|
39
|
+
return;
|
|
40
|
+
return field;
|
|
37
41
|
}
|
|
38
42
|
/**
|
|
39
43
|
*
|
|
40
44
|
*/
|
|
41
|
-
getField(nameOrPath) {
|
|
45
|
+
getField(nameOrPath, scope) {
|
|
42
46
|
const field = this.findField(nameOrPath);
|
|
43
|
-
if (!field)
|
|
44
|
-
throw new Error(
|
|
47
|
+
if (field && scope && !field.inScope(scope))
|
|
48
|
+
throw new Error(`Field "${nameOrPath}" does not exist in scope "${scope}"`);
|
|
49
|
+
if (!field) {
|
|
50
|
+
throw new Error(`Field (${nameOrPath}) does not exist`);
|
|
51
|
+
}
|
|
45
52
|
return field;
|
|
46
53
|
}
|
|
47
54
|
/**
|
|
@@ -72,7 +79,7 @@ class ComplexTypeBaseClass extends data_type_js_1.DataType {
|
|
|
72
79
|
}
|
|
73
80
|
if (dataType) {
|
|
74
81
|
if (dataType instanceof exports.ComplexTypeBase) {
|
|
75
|
-
field = dataType.
|
|
82
|
+
field = dataType.getField(item.fieldName, options?.scope);
|
|
76
83
|
if (field) {
|
|
77
84
|
item.fieldName = field.name;
|
|
78
85
|
item.field = field;
|
|
@@ -149,17 +156,12 @@ class ComplexTypeBaseClass extends data_type_js_1.DataType {
|
|
|
149
156
|
const schema = {};
|
|
150
157
|
const { currentPath, projection } = context;
|
|
151
158
|
const pickList = !!(projection && Object.values(projection).find(p => !p.sign));
|
|
152
|
-
const scope = context.scope
|
|
153
|
-
? Array.isArray(context.scope)
|
|
154
|
-
? context.scope
|
|
155
|
-
: [context.scope]
|
|
156
|
-
: undefined;
|
|
157
159
|
// Process fields
|
|
158
160
|
let fieldName;
|
|
159
161
|
for (const field of this.fields.values()) {
|
|
160
162
|
if (
|
|
161
163
|
/** Ignore field if required scope(s) do not match field scopes */
|
|
162
|
-
(scope && !field.inScope(scope)) ||
|
|
164
|
+
(context.scope && !field.inScope(context.scope)) ||
|
|
163
165
|
/** Ignore field if readonly and ignoreReadonlyFields option true */
|
|
164
166
|
(context.ignoreReadonlyFields && field.readonly) ||
|
|
165
167
|
/** Ignore field if writeonly and ignoreWriteonlyFields option true */
|
|
@@ -72,21 +72,19 @@ class ComplexTypeClass extends complex_type_base_js_1.ComplexTypeBase {
|
|
|
72
72
|
return !!this.base?.extendsFrom(baseType);
|
|
73
73
|
}
|
|
74
74
|
toJSON(options) {
|
|
75
|
+
const superJson = super.toJSON(options);
|
|
75
76
|
const baseName = this.base
|
|
76
77
|
? this.node.getDataTypeNameWithNs(this.base)
|
|
77
78
|
: undefined;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
`is not in required scope(s) [${options.scopes}`);
|
|
81
|
-
const out = (0, objects_1.omitUndefined)({
|
|
82
|
-
...complex_type_base_js_1.ComplexTypeBase.prototype.toJSON.call(this),
|
|
79
|
+
const out = {
|
|
80
|
+
...superJson,
|
|
83
81
|
kind: this.kind,
|
|
84
82
|
base: this.base
|
|
85
83
|
? baseName
|
|
86
84
|
? baseName
|
|
87
85
|
: this.base.toJSON(options)
|
|
88
86
|
: undefined,
|
|
89
|
-
}
|
|
87
|
+
};
|
|
90
88
|
if (this.additionalFields) {
|
|
91
89
|
if (this.additionalFields instanceof data_type_js_1.DataType) {
|
|
92
90
|
const typeName = this.node.getDataTypeNameWithNs(this.additionalFields);
|
|
@@ -101,7 +99,8 @@ class ComplexTypeClass extends complex_type_base_js_1.ComplexTypeBase {
|
|
|
101
99
|
const fields = {};
|
|
102
100
|
let i = 0;
|
|
103
101
|
for (const field of this.fields.values()) {
|
|
104
|
-
if (field.origin === this &&
|
|
102
|
+
if (field.origin === this &&
|
|
103
|
+
(!options?.scope || field.inScope(options?.scope))) {
|
|
105
104
|
fields[field.name] = field.toJSON(options);
|
|
106
105
|
i++;
|
|
107
106
|
}
|
|
@@ -111,6 +110,14 @@ class ComplexTypeClass extends complex_type_base_js_1.ComplexTypeBase {
|
|
|
111
110
|
}
|
|
112
111
|
return (0, objects_1.omitUndefined)(out);
|
|
113
112
|
}
|
|
113
|
+
_locateBase(callback) {
|
|
114
|
+
if (!this.base)
|
|
115
|
+
return;
|
|
116
|
+
if (callback(this.base))
|
|
117
|
+
return this.base;
|
|
118
|
+
if (this.base._locateBase)
|
|
119
|
+
return this.base._locateBase(callback);
|
|
120
|
+
}
|
|
114
121
|
}
|
|
115
122
|
exports.ComplexType.prototype = ComplexTypeClass.prototype;
|
|
116
123
|
Object.assign(exports.ComplexType, complex_type_decorator_js_1.ComplexTypeDecorator);
|
|
@@ -6,6 +6,7 @@ const ts_gems_1 = require("ts-gems");
|
|
|
6
6
|
const document_element_js_1 = require("../common/document-element.js");
|
|
7
7
|
const constants_js_1 = require("../constants.js");
|
|
8
8
|
const inspect_util_js_1 = require("../utils/inspect.util.js");
|
|
9
|
+
const test_scope_match_js_1 = require("../utils/test-scope-match.js");
|
|
9
10
|
/**
|
|
10
11
|
* DataType constructor
|
|
11
12
|
*/
|
|
@@ -20,7 +21,7 @@ context) {
|
|
|
20
21
|
document_element_js_1.DocumentElement.call(this, owner);
|
|
21
22
|
const _this = (0, ts_gems_1.asMutable)(this);
|
|
22
23
|
_this.kind = initArgs.kind;
|
|
23
|
-
_this.
|
|
24
|
+
_this.scopePattern = initArgs.scopePattern;
|
|
24
25
|
_this.name = initArgs.name;
|
|
25
26
|
_this.description = initArgs.description;
|
|
26
27
|
_this.abstract = initArgs.abstract;
|
|
@@ -34,21 +35,18 @@ class DataTypeClass extends document_element_js_1.DocumentElement {
|
|
|
34
35
|
get embedded() {
|
|
35
36
|
return !this.name;
|
|
36
37
|
}
|
|
37
|
-
inScope(
|
|
38
|
-
|
|
39
|
-
return true;
|
|
40
|
-
/** this.scope should match all required scopes */
|
|
41
|
-
scopes = Array.isArray(scopes) ? scopes : [scopes];
|
|
42
|
-
for (const scope of scopes) {
|
|
43
|
-
if (!this.scopes.some(s => {
|
|
44
|
-
return typeof s === 'string' ? scope === s : s.test(scope);
|
|
45
|
-
}))
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
return true;
|
|
38
|
+
inScope(scope) {
|
|
39
|
+
return (0, test_scope_match_js_1.testScopeMatch)(scope, this.scopePattern);
|
|
49
40
|
}
|
|
50
|
-
// eslint-disable-next-line
|
|
51
41
|
toJSON(options) {
|
|
42
|
+
if (options?.scope) {
|
|
43
|
+
/** Locate base model which is not available for given scope */
|
|
44
|
+
const outOfScope = this._locateBase(dt => !dt.inScope(options.scope));
|
|
45
|
+
if (outOfScope) {
|
|
46
|
+
const baseName = this.node.getDataTypeNameWithNs(outOfScope);
|
|
47
|
+
throw new TypeError(`"${baseName}" model is not available for "${options.scope}" scope`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
52
50
|
return (0, objects_1.omitUndefined)({
|
|
53
51
|
kind: this.kind,
|
|
54
52
|
description: this.description,
|
|
@@ -52,22 +52,25 @@ class EnumTypeClass extends data_type_js_1.DataType {
|
|
|
52
52
|
return valgen_1.vg.isEnum(Object.keys(this.attributes));
|
|
53
53
|
}
|
|
54
54
|
toJSON(options) {
|
|
55
|
+
const superJson = super.toJSON(options);
|
|
55
56
|
const baseName = this.base
|
|
56
57
|
? this.node.getDataTypeNameWithNs(this.base)
|
|
57
58
|
: undefined;
|
|
58
|
-
if (options?.scopes && !this.base?.inScope(options?.scopes))
|
|
59
|
-
throw new TypeError(`Base type ${baseName ? '(' + baseName + ')' : ''} of ${this.name ? +this.name : 'embedded'} type ` +
|
|
60
|
-
`is not in required scope(s) [${options.scopes}`);
|
|
61
59
|
return (0, objects_1.omitUndefined)({
|
|
62
|
-
...
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
? baseName
|
|
66
|
-
: this.base.toJSON(options)
|
|
67
|
-
: undefined,
|
|
60
|
+
...superJson,
|
|
61
|
+
kind: this.kind,
|
|
62
|
+
base: baseName,
|
|
68
63
|
attributes: (0, index_js_1.cloneObject)(this.ownAttributes),
|
|
69
64
|
});
|
|
70
65
|
}
|
|
66
|
+
_locateBase(callback) {
|
|
67
|
+
if (!this.base)
|
|
68
|
+
return;
|
|
69
|
+
if (callback(this.base))
|
|
70
|
+
return this.base;
|
|
71
|
+
if (this.base._locateBase)
|
|
72
|
+
return this.base._locateBase(callback);
|
|
73
|
+
}
|
|
71
74
|
}
|
|
72
75
|
exports.EnumType.prototype = EnumTypeClass.prototype;
|
|
73
76
|
Object.assign(exports.EnumType, EnumTypeClass);
|
|
@@ -4,33 +4,33 @@ exports.FieldPathType = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const valgen_1 = require("valgen");
|
|
6
6
|
const constants_js_1 = require("../../constants.js");
|
|
7
|
+
const data_type_js_1 = require("../data-type.js");
|
|
7
8
|
const simple_type_js_1 = require("../simple-type.js");
|
|
8
9
|
let FieldPathType = class FieldPathType {
|
|
9
10
|
constructor(attributes) {
|
|
10
11
|
if (attributes)
|
|
11
12
|
Object.assign(this, attributes);
|
|
12
13
|
}
|
|
13
|
-
[constants_js_1.DECODER](properties, element) {
|
|
14
|
+
[constants_js_1.DECODER](properties, element, scope) {
|
|
14
15
|
const dataType = properties.dataType
|
|
15
16
|
? element.node.getComplexType(properties.dataType)
|
|
16
17
|
: element.node.getComplexType('object');
|
|
17
18
|
const allowSigns = properties.allowSigns;
|
|
18
|
-
const decodeFieldPath = (0, valgen_1.validator)('decodeFieldPath', (input) => dataType.normalizeFieldPath(input, { allowSigns }));
|
|
19
|
+
const decodeFieldPath = (0, valgen_1.validator)('decodeFieldPath', (input) => dataType.normalizeFieldPath(input, { allowSigns, scope }));
|
|
19
20
|
return valgen_1.vg.pipe([valgen_1.toString, decodeFieldPath]);
|
|
20
21
|
}
|
|
21
|
-
[constants_js_1.ENCODER](properties, element) {
|
|
22
|
-
return this[constants_js_1.DECODER](properties, element);
|
|
22
|
+
[constants_js_1.ENCODER](properties, element, scope) {
|
|
23
|
+
return this[constants_js_1.DECODER](properties, element, scope);
|
|
23
24
|
}
|
|
24
25
|
toJSON(properties, element, options) {
|
|
25
26
|
const dataType = properties.dataType
|
|
26
27
|
? element.node.getComplexType(properties.dataType)
|
|
27
28
|
: element.node.getComplexType('object');
|
|
29
|
+
/** Test scope */
|
|
30
|
+
data_type_js_1.DataType.prototype.toJSON.call(dataType, options);
|
|
28
31
|
const typeName = dataType
|
|
29
32
|
? element.node.getDataTypeNameWithNs(dataType)
|
|
30
33
|
: undefined;
|
|
31
|
-
if (options?.scopes && !dataType.inScope(options?.scopes))
|
|
32
|
-
throw new TypeError(`Data type ${typeName ? '(' + typeName + ')' : ''} ` +
|
|
33
|
-
`is not in required scope(s) [${options.scopes}`);
|
|
34
34
|
return {
|
|
35
35
|
dataType: typeName ? typeName : dataType.toJSON(options),
|
|
36
36
|
allowSigns: properties.allowSigns,
|
|
@@ -6,6 +6,7 @@ const valgen_1 = require("valgen");
|
|
|
6
6
|
const filter_rules_js_1 = require("../../../filter/filter-rules.js");
|
|
7
7
|
const index_js_1 = require("../../../filter/index.js");
|
|
8
8
|
const constants_js_1 = require("../../constants.js");
|
|
9
|
+
const data_type_js_1 = require("../data-type.js");
|
|
9
10
|
const simple_type_js_1 = require("../simple-type.js");
|
|
10
11
|
let FilterType = class FilterType {
|
|
11
12
|
constructor(attributes) {
|
|
@@ -28,12 +29,11 @@ let FilterType = class FilterType {
|
|
|
28
29
|
const dataType = properties.dataType
|
|
29
30
|
? element.node.getComplexType(properties.dataType)
|
|
30
31
|
: element.node.getComplexType('object');
|
|
32
|
+
/** Test scope */
|
|
33
|
+
data_type_js_1.DataType.prototype.toJSON.call(dataType, options);
|
|
31
34
|
const typeName = dataType
|
|
32
35
|
? element.node.getDataTypeNameWithNs(dataType)
|
|
33
36
|
: undefined;
|
|
34
|
-
if (options?.scopes && !dataType.inScope(options?.scopes))
|
|
35
|
-
throw new TypeError(`Data type ${typeName ? '(' + typeName + ')' : ''} ` +
|
|
36
|
-
`is not in required scope(s) [${options.scopes}`);
|
|
37
37
|
return {
|
|
38
38
|
dataType: typeName ? typeName : dataType.toJSON(options),
|
|
39
39
|
rules: properties.rules,
|
|
@@ -65,12 +65,12 @@ exports.FilterType = FilterType = tslib_1.__decorate([
|
|
|
65
65
|
}),
|
|
66
66
|
tslib_1.__metadata("design:paramtypes", [Object])
|
|
67
67
|
], FilterType);
|
|
68
|
-
const decodeFilter = (dataType, rules,
|
|
68
|
+
const decodeFilter = (dataType, rules, scope) => (0, valgen_1.validator)('decodeFilter', (input, context, _this) => {
|
|
69
69
|
if (typeof input === 'string') {
|
|
70
70
|
try {
|
|
71
71
|
const filter = index_js_1.OpraFilter.parse(input);
|
|
72
72
|
if (rules)
|
|
73
|
-
return rules.normalizeFilter(filter, dataType,
|
|
73
|
+
return rules.normalizeFilter(filter, dataType, scope);
|
|
74
74
|
return filter;
|
|
75
75
|
}
|
|
76
76
|
catch (e) {
|
|
@@ -89,14 +89,12 @@ class MappedTypeClass extends complex_type_base_js_1.ComplexTypeBase {
|
|
|
89
89
|
return !!this.base?.extendsFrom(baseType);
|
|
90
90
|
}
|
|
91
91
|
toJSON(options) {
|
|
92
|
+
const superJson = super.toJSON(options);
|
|
92
93
|
const baseName = this.base
|
|
93
94
|
? this.node.getDataTypeNameWithNs(this.base)
|
|
94
95
|
: undefined;
|
|
95
|
-
if (options?.scopes && !this.base?.inScope(options?.scopes))
|
|
96
|
-
throw new TypeError(`Base type ${baseName ? '(' + baseName + ')' : ''} of ${this.name ? +this.name : 'embedded'} type ` +
|
|
97
|
-
`is not in required scope(s) [${options.scopes}`);
|
|
98
96
|
return (0, objects_1.omitUndefined)({
|
|
99
|
-
...
|
|
97
|
+
...superJson,
|
|
100
98
|
base: baseName ? baseName : this.base.toJSON(options),
|
|
101
99
|
kind: this.kind,
|
|
102
100
|
pick: this.pick,
|
|
@@ -105,6 +103,14 @@ class MappedTypeClass extends complex_type_base_js_1.ComplexTypeBase {
|
|
|
105
103
|
required: this.required,
|
|
106
104
|
});
|
|
107
105
|
}
|
|
106
|
+
_locateBase(callback) {
|
|
107
|
+
if (!this.base)
|
|
108
|
+
return;
|
|
109
|
+
if (callback(this.base))
|
|
110
|
+
return this.base;
|
|
111
|
+
if (this.base._locateBase)
|
|
112
|
+
return this.base._locateBase(callback);
|
|
113
|
+
}
|
|
108
114
|
}
|
|
109
115
|
exports.MappedType.prototype = MappedTypeClass.prototype;
|
|
110
116
|
exports.MappedType._applyMixin = () => undefined;
|
|
@@ -58,18 +58,27 @@ class MixinTypeClass extends complex_type_base_js_1.ComplexTypeBase {
|
|
|
58
58
|
return false;
|
|
59
59
|
}
|
|
60
60
|
toJSON(options) {
|
|
61
|
+
const superJson = super.toJSON(options);
|
|
61
62
|
return (0, objects_1.omitUndefined)({
|
|
62
|
-
...
|
|
63
|
+
...superJson,
|
|
63
64
|
kind: this.kind,
|
|
64
65
|
types: this.types.map(base => {
|
|
65
66
|
const baseName = this.node.getDataTypeNameWithNs(base);
|
|
66
|
-
if (options?.scopes && !base?.inScope(options?.scopes))
|
|
67
|
-
throw new TypeError(`Base type ${baseName ? '(' + baseName + ')' : ''} of ${this.name ? +this.name : 'embedded'} type ` +
|
|
68
|
-
`is not in required scope(s) [${options.scopes}`);
|
|
69
67
|
return baseName ? baseName : base.toJSON(options);
|
|
70
68
|
}),
|
|
71
69
|
});
|
|
72
70
|
}
|
|
71
|
+
_locateBase(callback) {
|
|
72
|
+
for (const t of this.types) {
|
|
73
|
+
if (callback(t))
|
|
74
|
+
return t;
|
|
75
|
+
if (t._locateBase) {
|
|
76
|
+
const x = t._locateBase(callback);
|
|
77
|
+
if (x)
|
|
78
|
+
return x;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
73
82
|
}
|
|
74
83
|
exports.MixinType.prototype = MixinTypeClass.prototype;
|
|
75
84
|
exports.MixinType[constants_js_1.DECORATOR] = MixinTypeFactory;
|
|
@@ -70,7 +70,7 @@ class SimpleTypeClass extends data_type_js_1.DataType {
|
|
|
70
70
|
let t = this;
|
|
71
71
|
while (t) {
|
|
72
72
|
if (t._generateDecoder)
|
|
73
|
-
return t._generateDecoder(prop, options?.documentElement || this.owner);
|
|
73
|
+
return t._generateDecoder(prop, options?.documentElement || this.owner, options?.scope);
|
|
74
74
|
t = this.base;
|
|
75
75
|
}
|
|
76
76
|
return valgen_1.isAny;
|
|
@@ -78,12 +78,16 @@ class SimpleTypeClass extends data_type_js_1.DataType {
|
|
|
78
78
|
let t = this;
|
|
79
79
|
while (t) {
|
|
80
80
|
if (t._generateEncoder)
|
|
81
|
-
return t._generateEncoder(prop, options?.documentElement || this.owner);
|
|
81
|
+
return t._generateEncoder(prop, options?.documentElement || this.owner, options?.scope);
|
|
82
82
|
t = this.base;
|
|
83
83
|
}
|
|
84
84
|
return valgen_1.isAny;
|
|
85
85
|
}
|
|
86
86
|
toJSON(options) {
|
|
87
|
+
const superJson = super.toJSON(options);
|
|
88
|
+
const baseName = this.base
|
|
89
|
+
? this.node.getDataTypeNameWithNs(this.base)
|
|
90
|
+
: undefined;
|
|
87
91
|
const attributes = (0, objects_1.omitUndefined)(this.ownAttributes);
|
|
88
92
|
let properties;
|
|
89
93
|
if (this.properties && typeof this.properties.toJSON === 'function') {
|
|
@@ -91,22 +95,13 @@ class SimpleTypeClass extends data_type_js_1.DataType {
|
|
|
91
95
|
}
|
|
92
96
|
else
|
|
93
97
|
properties = this.properties ? (0, index_js_1.cloneObject)(this.properties) : {};
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
:
|
|
97
|
-
|
|
98
|
-
throw new TypeError(`Base type ${baseName ? '(' + baseName + ')' : ''} of ${this.name ? +this.name : 'embedded'} type ` +
|
|
99
|
-
`is not in required scope(s) [${options.scopes}`);
|
|
100
|
-
const out = (0, objects_1.omitUndefined)({
|
|
101
|
-
...data_type_js_1.DataType.prototype.toJSON.apply(this),
|
|
102
|
-
base: this.base
|
|
103
|
-
? baseName
|
|
104
|
-
? baseName
|
|
105
|
-
: this.base.toJSON(options)
|
|
106
|
-
: undefined,
|
|
98
|
+
const out = {
|
|
99
|
+
...superJson,
|
|
100
|
+
kind: this.kind,
|
|
101
|
+
base: baseName,
|
|
107
102
|
attributes: attributes && Object.keys(attributes).length ? attributes : undefined,
|
|
108
103
|
properties: Object.keys(properties).length ? properties : undefined,
|
|
109
|
-
}
|
|
104
|
+
};
|
|
110
105
|
if (Object.keys(this.ownNameMappings).length)
|
|
111
106
|
out.nameMappings = { ...this.ownNameMappings };
|
|
112
107
|
return (0, objects_1.omitUndefined)(out, true);
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ApiFieldDecoratorFactory = ApiFieldDecoratorFactory;
|
|
4
|
+
// import { omitUndefined } from '@jsopen/objects';
|
|
5
|
+
// import { StrictOmit } from 'ts-gems';
|
|
4
6
|
const index_js_1 = require("../../schema/index.js");
|
|
5
7
|
const constants_js_1 = require("../constants.js");
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
+
function ApiFieldDecoratorFactory(options) {
|
|
9
|
+
const decoratorChain = [];
|
|
10
|
+
/**
|
|
11
|
+
*
|
|
12
|
+
*/
|
|
13
|
+
const decorator = function (target, propertyKey) {
|
|
8
14
|
if (typeof propertyKey !== 'string')
|
|
9
15
|
throw new TypeError(`Symbol properties can't be used as a field`);
|
|
10
16
|
const metadata = Reflect.getOwnMetadata(constants_js_1.DATATYPE_METADATA, target.constructor) ||
|
|
@@ -14,6 +20,11 @@ function ApiFieldDecorator(options) {
|
|
|
14
20
|
const designType = Reflect.getMetadata('design:type', target, propertyKey);
|
|
15
21
|
const elemMeta = (metadata.fields[propertyKey] = {
|
|
16
22
|
...options,
|
|
23
|
+
scopePattern: options?.scopePattern
|
|
24
|
+
? Array.isArray(options.scopePattern)
|
|
25
|
+
? options.scopePattern
|
|
26
|
+
: [options.scopePattern]
|
|
27
|
+
: undefined,
|
|
17
28
|
});
|
|
18
29
|
if (designType === Array) {
|
|
19
30
|
elemMeta.isArray = true;
|
|
@@ -21,5 +32,28 @@ function ApiFieldDecorator(options) {
|
|
|
21
32
|
else
|
|
22
33
|
elemMeta.type = elemMeta.type || designType;
|
|
23
34
|
Reflect.defineMetadata(constants_js_1.DATATYPE_METADATA, metadata, target.constructor);
|
|
35
|
+
for (const fn of decoratorChain)
|
|
36
|
+
fn(metadata, target);
|
|
24
37
|
};
|
|
38
|
+
// /**
|
|
39
|
+
// *
|
|
40
|
+
// */
|
|
41
|
+
// decorator.Override = (
|
|
42
|
+
// scopes: (string | RegExp) | (string | RegExp)[],
|
|
43
|
+
// opts: StrictOmit<ApiField.Options, 'isArray' | 'type' | 'scopePattern'>,
|
|
44
|
+
// ): any => {
|
|
45
|
+
// decoratorChain.push((meta: ApiField.Metadata): void => {
|
|
46
|
+
// meta.overrides = meta.overrides || [];
|
|
47
|
+
// meta.overrides.push(
|
|
48
|
+
// omitUndefined({
|
|
49
|
+
// ...opts,
|
|
50
|
+
// scopes: Array.isArray(scopes) ? scopes : [scopes],
|
|
51
|
+
// type: undefined,
|
|
52
|
+
// isArray: undefined,
|
|
53
|
+
// }),
|
|
54
|
+
// );
|
|
55
|
+
// });
|
|
56
|
+
// return decorator;
|
|
57
|
+
// };
|
|
58
|
+
return decorator;
|
|
25
59
|
}
|
|
@@ -28,6 +28,8 @@ function SimpleTypeDecoratorFactory(options) {
|
|
|
28
28
|
metadata.kind = index_js_1.OpraSchema.SimpleType.Kind;
|
|
29
29
|
metadata.name = name;
|
|
30
30
|
Reflect.defineMetadata(constants_js_1.DATATYPE_METADATA, metadata, target);
|
|
31
|
+
for (const fn of decoratorChain)
|
|
32
|
+
fn(metadata, target);
|
|
31
33
|
};
|
|
32
34
|
decorator.Example = (value, description) => {
|
|
33
35
|
decoratorChain.push((meta) => {
|
|
@@ -30,7 +30,6 @@ class ApiDocumentFactory {
|
|
|
30
30
|
: new document_init_context_js_1.DocumentInitContext(options);
|
|
31
31
|
try {
|
|
32
32
|
const document = new api_document_js_1.ApiDocument();
|
|
33
|
-
document.scopes = context.scopes;
|
|
34
33
|
await factory.initDocument(document, context, schemaOrUrl);
|
|
35
34
|
if (context.error.details.length)
|
|
36
35
|
throw context.error;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.testScopeMatch = testScopeMatch;
|
|
4
|
+
function testScopeMatch(scope, pattern) {
|
|
5
|
+
if (!(scope && pattern))
|
|
6
|
+
return true;
|
|
7
|
+
if (Array.isArray(pattern)) {
|
|
8
|
+
return pattern.some(x => {
|
|
9
|
+
return typeof x === 'string' ? scope === x : x.test(scope);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
return typeof pattern === 'string' ? scope === pattern : pattern.test(scope);
|
|
13
|
+
}
|
|
@@ -32,12 +32,11 @@ class FilterRules {
|
|
|
32
32
|
operators,
|
|
33
33
|
}));
|
|
34
34
|
}
|
|
35
|
-
normalizeFilter(filter, currentType,
|
|
35
|
+
normalizeFilter(filter, currentType, scope) {
|
|
36
36
|
const ast = typeof filter === 'string' ? (0, parse_js_1.parse)(filter) : filter;
|
|
37
|
-
|
|
38
|
-
return this.normalizeFilterAst(ast, [], currentType, doc?.scopes);
|
|
37
|
+
return this.normalizeFilterAst(ast, [], currentType, scope);
|
|
39
38
|
}
|
|
40
|
-
normalizeFilterAst(ast, stack, currentType,
|
|
39
|
+
normalizeFilterAst(ast, stack, currentType, scope) {
|
|
41
40
|
if (ast instanceof index_js_4.ComparisonExpression) {
|
|
42
41
|
stack.push(ast);
|
|
43
42
|
this.normalizeFilterAst(ast.left, stack, currentType);
|
|
@@ -100,8 +99,8 @@ class FilterRules {
|
|
|
100
99
|
return ast;
|
|
101
100
|
}
|
|
102
101
|
if (ast instanceof index_js_4.QualifiedIdentifier && currentType) {
|
|
103
|
-
ast.value = currentType.normalizeFieldPath(ast.value);
|
|
104
|
-
ast.field = currentType.getField(ast.value);
|
|
102
|
+
ast.value = currentType.normalizeFieldPath(ast.value, { scope });
|
|
103
|
+
ast.field = currentType.getField(ast.value, scope);
|
|
105
104
|
ast.dataType = ast.field.type;
|
|
106
105
|
return ast;
|
|
107
106
|
}
|
|
@@ -129,7 +128,7 @@ class FilterRules {
|
|
|
129
128
|
decoder = this._decoderCache.get(comp.left.field);
|
|
130
129
|
if (!decoder) {
|
|
131
130
|
decoder = comp.left.field.type.generateCodec('decode', {
|
|
132
|
-
scope
|
|
131
|
+
scope,
|
|
133
132
|
projection: '*',
|
|
134
133
|
ignoreWriteonlyFields: true,
|
|
135
134
|
coerce: true,
|