@opra/common 1.4.4 → 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 +12 -8
- package/cjs/document/common/api-base.js +2 -1
- package/cjs/document/common/document-node.js +24 -29
- package/cjs/document/common/value.js +6 -2
- package/cjs/document/constants.js +1 -2
- package/cjs/document/data-type/api-field.js +12 -8
- package/cjs/document/data-type/complex-type-base.js +22 -11
- package/cjs/document/data-type/complex-type.js +22 -8
- package/cjs/document/data-type/data-type.js +14 -1
- package/cjs/document/data-type/enum-type.js +13 -3
- package/cjs/document/data-type/extended-types/base64.type.js +1 -0
- package/cjs/document/data-type/extended-types/date-string.type.js +1 -0
- package/cjs/document/data-type/extended-types/date-time-string.type.js +1 -0
- package/cjs/document/data-type/extended-types/date-time.type.js +1 -0
- package/cjs/document/data-type/extended-types/date.type.js +1 -0
- package/cjs/document/data-type/extended-types/email.type.js +1 -0
- package/cjs/document/data-type/extended-types/field-path.type.js +10 -6
- package/cjs/document/data-type/extended-types/filter.type.js +11 -4
- package/cjs/document/data-type/extended-types/object-id.type.js +1 -0
- package/cjs/document/data-type/extended-types/operation-result.type.js +1 -0
- package/cjs/document/data-type/extended-types/time.type.js +1 -0
- package/cjs/document/data-type/extended-types/url.type.js +1 -0
- package/cjs/document/data-type/extended-types/uuid.type.js +1 -0
- package/cjs/document/data-type/mapped-type.js +12 -3
- package/cjs/document/data-type/mixin-type.js +17 -5
- package/cjs/document/data-type/primitive-types/any.type.js +1 -0
- package/cjs/document/data-type/primitive-types/bigint.type.js +1 -0
- package/cjs/document/data-type/primitive-types/boolean.type.js +1 -0
- package/cjs/document/data-type/primitive-types/integer.type.js +1 -0
- package/cjs/document/data-type/primitive-types/null.type.js +1 -0
- package/cjs/document/data-type/primitive-types/number.type.js +1 -0
- package/cjs/document/data-type/primitive-types/string.type.js +1 -0
- package/cjs/document/data-type/simple-type.js +13 -11
- package/cjs/document/decorators/api-field-decorator.js +37 -3
- package/cjs/document/decorators/complex-type.decorator.js +1 -1
- package/cjs/document/decorators/simple-type.decorator.js +3 -1
- package/cjs/document/http/http-api.js +2 -2
- package/cjs/document/http/http-controller.js +5 -5
- package/cjs/document/http/http-media-type.js +3 -3
- package/cjs/document/http/http-multipart-field.js +2 -2
- package/cjs/document/http/http-operation-response.js +3 -3
- package/cjs/document/http/http-operation.js +5 -5
- package/cjs/document/http/http-parameter.js +2 -2
- package/cjs/document/http/http-request-body.js +4 -2
- package/cjs/document/utils/test-scope-match.js +13 -0
- package/cjs/filter/filter-rules.js +6 -6
- package/esm/document/api-document.js +12 -8
- package/esm/document/common/api-base.js +2 -1
- package/esm/document/common/document-node.js +24 -29
- package/esm/document/common/value.js +6 -2
- package/esm/document/constants.js +0 -1
- package/esm/document/data-type/api-field.js +13 -9
- package/esm/document/data-type/complex-type-base.js +22 -11
- package/esm/document/data-type/complex-type.js +22 -8
- package/esm/document/data-type/data-type.js +14 -1
- package/esm/document/data-type/enum-type.js +13 -3
- package/esm/document/data-type/extended-types/base64.type.js +1 -0
- package/esm/document/data-type/extended-types/date-string.type.js +1 -0
- package/esm/document/data-type/extended-types/date-time-string.type.js +1 -0
- package/esm/document/data-type/extended-types/date-time.type.js +1 -0
- package/esm/document/data-type/extended-types/date.type.js +1 -0
- package/esm/document/data-type/extended-types/email.type.js +1 -0
- package/esm/document/data-type/extended-types/field-path.type.js +10 -6
- package/esm/document/data-type/extended-types/filter.type.js +11 -4
- package/esm/document/data-type/extended-types/object-id.type.js +1 -0
- package/esm/document/data-type/extended-types/operation-result.type.js +1 -0
- package/esm/document/data-type/extended-types/time.type.js +1 -0
- package/esm/document/data-type/extended-types/url.type.js +1 -0
- package/esm/document/data-type/extended-types/uuid.type.js +1 -0
- package/esm/document/data-type/mapped-type.js +12 -3
- package/esm/document/data-type/mixin-type.js +17 -5
- package/esm/document/data-type/primitive-types/any.type.js +1 -0
- package/esm/document/data-type/primitive-types/bigint.type.js +1 -0
- package/esm/document/data-type/primitive-types/boolean.type.js +1 -0
- package/esm/document/data-type/primitive-types/integer.type.js +1 -0
- package/esm/document/data-type/primitive-types/null.type.js +1 -0
- package/esm/document/data-type/primitive-types/number.type.js +1 -0
- package/esm/document/data-type/primitive-types/string.type.js +1 -0
- package/esm/document/data-type/simple-type.js +13 -11
- package/esm/document/decorators/api-field-decorator.js +36 -2
- package/esm/document/decorators/complex-type.decorator.js +2 -2
- package/esm/document/decorators/simple-type.decorator.js +4 -2
- package/esm/document/http/http-api.js +2 -2
- package/esm/document/http/http-controller.js +5 -5
- package/esm/document/http/http-media-type.js +3 -3
- package/esm/document/http/http-multipart-field.js +2 -2
- package/esm/document/http/http-operation-response.js +3 -3
- package/esm/document/http/http-operation.js +5 -5
- package/esm/document/http/http-parameter.js +2 -2
- package/esm/document/http/http-request-body.js +4 -2
- package/esm/document/utils/test-scope-match.js +10 -0
- package/esm/filter/filter-rules.js +6 -6
- package/package.json +1 -1
- package/types/document/api-document.d.ts +7 -2
- package/types/document/common/api-base.d.ts +1 -1
- package/types/document/common/document-init-context.d.ts +1 -0
- package/types/document/common/document-node.d.ts +8 -14
- package/types/document/common/value.d.ts +2 -1
- package/types/document/constants.d.ts +0 -1
- package/types/document/data-type/api-field.d.ts +42 -34
- package/types/document/data-type/complex-type-base.d.ts +4 -2
- package/types/document/data-type/complex-type.d.ts +3 -1
- package/types/document/data-type/data-type.d.ts +8 -2
- package/types/document/data-type/enum-type.d.ts +3 -1
- package/types/document/data-type/extended-types/field-path.type.d.ts +4 -3
- package/types/document/data-type/extended-types/filter.type.d.ts +2 -1
- package/types/document/data-type/mapped-type.d.ts +3 -1
- package/types/document/data-type/mixin-type.d.ts +3 -1
- package/types/document/data-type/simple-type.d.ts +3 -2
- 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 -0
- package/types/document/http/http-api.d.ts +1 -1
- package/types/document/http/http-controller.d.ts +2 -1
- package/types/document/http/http-media-type.d.ts +2 -1
- package/types/document/http/http-multipart-field.d.ts +2 -1
- package/types/document/http/http-operation-response.d.ts +2 -1
- package/types/document/http/http-operation.d.ts +2 -1
- package/types/document/http/http-parameter.d.ts +2 -1
- package/types/document/http/http-request-body.d.ts +2 -1
- package/types/document/utils/test-scope-match.d.ts +1 -0
- package/types/filter/filter-rules.d.ts +2 -2
|
@@ -18,25 +18,23 @@ export class DocumentNode {
|
|
|
18
18
|
// istanbul ignore next
|
|
19
19
|
throw new Error('ApiDocument not found in document tree');
|
|
20
20
|
}
|
|
21
|
-
hasDataType(nameOrCtor) {
|
|
22
|
-
|
|
23
|
-
if (result)
|
|
24
|
-
return result;
|
|
25
|
-
return this.parent ? this.parent.hasDataType(nameOrCtor) : false;
|
|
21
|
+
hasDataType(nameOrCtor, scope) {
|
|
22
|
+
return !!this.findDataType(nameOrCtor, scope);
|
|
26
23
|
}
|
|
27
|
-
findDataType(nameOrCtor) {
|
|
28
|
-
const
|
|
29
|
-
if (
|
|
30
|
-
return
|
|
31
|
-
return this.parent
|
|
24
|
+
findDataType(nameOrCtor, scope) {
|
|
25
|
+
const dt = this[kDataTypeMap]?.get(nameOrCtor);
|
|
26
|
+
if (dt && (!scope || dt.inScope(scope)))
|
|
27
|
+
return dt;
|
|
28
|
+
return this.parent
|
|
29
|
+
? this.parent.findDataType(nameOrCtor, scope)
|
|
30
|
+
: undefined;
|
|
32
31
|
}
|
|
33
32
|
/**
|
|
34
33
|
* Returns DataType instance by name or Constructor. Returns undefined if not found
|
|
35
|
-
* @param nameOrCtor
|
|
36
34
|
*/
|
|
37
|
-
getDataType(nameOrCtor) {
|
|
35
|
+
getDataType(nameOrCtor, scope) {
|
|
38
36
|
const dt = this.findDataType(nameOrCtor);
|
|
39
|
-
if (dt)
|
|
37
|
+
if (dt && (!scope || dt.inScope(scope)))
|
|
40
38
|
return dt;
|
|
41
39
|
let name = '';
|
|
42
40
|
if (typeof nameOrCtor === 'function') {
|
|
@@ -53,7 +51,9 @@ export class DocumentNode {
|
|
|
53
51
|
else if (typeof nameOrCtor === 'function')
|
|
54
52
|
name = nameOrCtor.name;
|
|
55
53
|
}
|
|
56
|
-
|
|
54
|
+
if (dt)
|
|
55
|
+
throw new TypeError(`Data type${name ? ' (' + name + ')' : ''} is not in requested scope (${scope})`);
|
|
56
|
+
throw new TypeError(`Unknown data type${name ? ' (' + name + ')' : ''}`);
|
|
57
57
|
}
|
|
58
58
|
getDataTypeNameWithNs(dataType) {
|
|
59
59
|
if (!dataType.name)
|
|
@@ -65,10 +65,9 @@ export class DocumentNode {
|
|
|
65
65
|
* Returns ComplexType instance by name or Constructor.
|
|
66
66
|
* Returns undefined if not found
|
|
67
67
|
* Throws error if data type is not a ComplexType
|
|
68
|
-
* @param nameOrCtor
|
|
69
68
|
*/
|
|
70
|
-
getComplexType(nameOrCtor) {
|
|
71
|
-
const t = this.getDataType(nameOrCtor);
|
|
69
|
+
getComplexType(nameOrCtor, scope) {
|
|
70
|
+
const t = this.getDataType(nameOrCtor, scope);
|
|
72
71
|
if (t.kind === OpraSchema.ComplexType.Kind)
|
|
73
72
|
return t;
|
|
74
73
|
throw new TypeError(`Data type "${t.name}" is not a ComplexType`);
|
|
@@ -77,10 +76,9 @@ export class DocumentNode {
|
|
|
77
76
|
* Returns SimpleType instance by name or Constructor.
|
|
78
77
|
* Returns undefined if not found
|
|
79
78
|
* Throws error if data type is not a SimpleType
|
|
80
|
-
* @param nameOrCtor
|
|
81
79
|
*/
|
|
82
|
-
getSimpleType(nameOrCtor) {
|
|
83
|
-
const t = this.getDataType(nameOrCtor);
|
|
80
|
+
getSimpleType(nameOrCtor, scope) {
|
|
81
|
+
const t = this.getDataType(nameOrCtor, scope);
|
|
84
82
|
if (t.kind === OpraSchema.SimpleType.Kind)
|
|
85
83
|
return t;
|
|
86
84
|
throw new TypeError(`Data type "${t.name || t}" is not a SimpleType`);
|
|
@@ -89,10 +87,9 @@ export class DocumentNode {
|
|
|
89
87
|
* Returns EnumType instance by name or Constructor.
|
|
90
88
|
* Returns undefined if not found
|
|
91
89
|
* Throws error if data type is not a EnumType
|
|
92
|
-
* @param nameOrCtor
|
|
93
90
|
*/
|
|
94
|
-
getEnumType(nameOrCtor) {
|
|
95
|
-
const t = this.getDataType(nameOrCtor);
|
|
91
|
+
getEnumType(nameOrCtor, scope) {
|
|
92
|
+
const t = this.getDataType(nameOrCtor, scope);
|
|
96
93
|
if (t.kind === OpraSchema.EnumType.Kind)
|
|
97
94
|
return t;
|
|
98
95
|
throw new TypeError(`Data type "${t.name || t}" is not a EnumType`);
|
|
@@ -101,10 +98,9 @@ export class DocumentNode {
|
|
|
101
98
|
* Returns EnumType instance by name or Constructor.
|
|
102
99
|
* Returns undefined if not found
|
|
103
100
|
* Throws error if data type is not a MappedType
|
|
104
|
-
* @param nameOrCtor
|
|
105
101
|
*/
|
|
106
|
-
getMappedType(nameOrCtor) {
|
|
107
|
-
const t = this.getDataType(nameOrCtor);
|
|
102
|
+
getMappedType(nameOrCtor, scope) {
|
|
103
|
+
const t = this.getDataType(nameOrCtor, scope);
|
|
108
104
|
if (t.kind === OpraSchema.MappedType.Kind)
|
|
109
105
|
return t;
|
|
110
106
|
throw new TypeError(`Data type "${t.name || t}" is not a MappedType`);
|
|
@@ -113,10 +109,9 @@ export class DocumentNode {
|
|
|
113
109
|
* Returns EnumType instance by name or Constructor.
|
|
114
110
|
* Returns undefined if not found
|
|
115
111
|
* Throws error if data type is not a MixinType
|
|
116
|
-
* @param nameOrCtor
|
|
117
112
|
*/
|
|
118
|
-
getMixinType(nameOrCtor) {
|
|
119
|
-
const t = this.getDataType(nameOrCtor);
|
|
113
|
+
getMixinType(nameOrCtor, scope) {
|
|
114
|
+
const t = this.getDataType(nameOrCtor, scope);
|
|
120
115
|
if (t.kind === OpraSchema.MixinType.Kind)
|
|
121
116
|
return t;
|
|
122
117
|
throw new TypeError(`Data type "${t.name || t}" is not a MixinType`);
|
|
@@ -17,12 +17,16 @@ export const Value = function (owner, initArgs) {
|
|
|
17
17
|
* @class Value
|
|
18
18
|
*/
|
|
19
19
|
class ValueClass extends DocumentElement {
|
|
20
|
-
toJSON() {
|
|
20
|
+
toJSON(options) {
|
|
21
21
|
const typeName = this.type
|
|
22
22
|
? this.node.getDataTypeNameWithNs(this.type)
|
|
23
23
|
: undefined;
|
|
24
24
|
return omitUndefined({
|
|
25
|
-
type: this.type
|
|
25
|
+
type: this.type
|
|
26
|
+
? typeName
|
|
27
|
+
? typeName
|
|
28
|
+
: this.type.toJSON(options)
|
|
29
|
+
: 'any',
|
|
26
30
|
description: this.description,
|
|
27
31
|
isArray: this.isArray,
|
|
28
32
|
examples: this.examples,
|
|
@@ -7,7 +7,6 @@ export const DECORATOR = Symbol.for('DECORATOR');
|
|
|
7
7
|
export const BUILTIN = Symbol.for('BUILTIN');
|
|
8
8
|
export const NAMESPACE_PATTERN = /([a-z$_]\w+):(.+)/i;
|
|
9
9
|
export const CLASS_NAME_PATTERN = /^[a-z][\w_]*$/i;
|
|
10
|
-
export const EXTRACT_TYPENAME_PATTERN = /^(.*)Type(\d*)$/;
|
|
11
10
|
export const kDataTypeMap = Symbol.for('kDataTypeMap');
|
|
12
11
|
export const kCtorMap = Symbol.for('kCtorMap');
|
|
13
12
|
export const kTypeNSMap = Symbol.for('kTypeNSMap');
|
|
@@ -2,10 +2,10 @@ import { omitUndefined } from '@jsopen/objects';
|
|
|
2
2
|
import { asMutable } from 'ts-gems';
|
|
3
3
|
import { DocumentElement } from '../common/document-element.js';
|
|
4
4
|
import { DECORATOR } from '../constants.js';
|
|
5
|
-
import {
|
|
5
|
+
import { ApiFieldDecoratorFactory } from '../decorators/api-field-decorator.js';
|
|
6
|
+
import { testScopeMatch } from '../utils/test-scope-match.js';
|
|
6
7
|
import { ComplexTypeBase } from './complex-type-base.js';
|
|
7
8
|
/**
|
|
8
|
-
* @constructor ApiField
|
|
9
9
|
* @decorator ApiField
|
|
10
10
|
*/
|
|
11
11
|
export const ApiField = function (...args) {
|
|
@@ -25,6 +25,7 @@ export const ApiField = function (...args) {
|
|
|
25
25
|
throw new Error('Field origin should be one of ComplexType, MappedType or MixinType');
|
|
26
26
|
}
|
|
27
27
|
_this.origin = origin;
|
|
28
|
+
_this.scopePattern = initArgs.scopePattern;
|
|
28
29
|
_this.type = initArgs.type || owner.node.getDataType('any');
|
|
29
30
|
_this.description = initArgs.description;
|
|
30
31
|
_this.isArray = initArgs.isArray;
|
|
@@ -38,19 +39,22 @@ export const ApiField = function (...args) {
|
|
|
38
39
|
_this.readonly = initArgs.readonly;
|
|
39
40
|
_this.writeonly = initArgs.writeonly;
|
|
40
41
|
_this.examples = initArgs.examples;
|
|
41
|
-
_this.hidden = initArgs.hidden;
|
|
42
42
|
};
|
|
43
43
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
44
|
+
* The ApiFieldClass represents a descriptive metadata structure for API fields,
|
|
45
|
+
* supporting features like data type definition, scoping, localization, and constraints.
|
|
46
|
+
* This class extends DocumentElement, inheriting base document structure capabilities.
|
|
46
47
|
*/
|
|
47
48
|
class ApiFieldClass extends DocumentElement {
|
|
48
|
-
|
|
49
|
+
inScope(scope) {
|
|
50
|
+
return testScopeMatch(scope, this.scopePattern);
|
|
51
|
+
}
|
|
52
|
+
toJSON(options) {
|
|
49
53
|
const typeName = this.type
|
|
50
54
|
? this.node.getDataTypeNameWithNs(this.type)
|
|
51
55
|
: undefined;
|
|
52
56
|
return omitUndefined({
|
|
53
|
-
type: typeName ? typeName : this.type?.toJSON(),
|
|
57
|
+
type: typeName ? typeName : this.type?.toJSON(options),
|
|
54
58
|
description: this.description,
|
|
55
59
|
isArray: this.isArray || undefined,
|
|
56
60
|
default: this.default,
|
|
@@ -67,5 +71,5 @@ class ApiFieldClass extends DocumentElement {
|
|
|
67
71
|
}
|
|
68
72
|
}
|
|
69
73
|
ApiField.prototype = ApiFieldClass.prototype;
|
|
70
|
-
Object.assign(ApiField,
|
|
71
|
-
ApiField[DECORATOR] =
|
|
74
|
+
Object.assign(ApiField, ApiFieldDecoratorFactory);
|
|
75
|
+
ApiField[DECORATOR] = ApiFieldDecoratorFactory;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { asMutable } from 'ts-gems';
|
|
2
2
|
import { validator, vg } from 'valgen';
|
|
3
3
|
import { parseFieldsProjection, ResponsiveMap, } from '../../helpers/index.js';
|
|
4
|
-
import { translate } from '../../i18n/index.js';
|
|
5
4
|
import { DataType } from './data-type.js';
|
|
6
5
|
export const FIELD_PATH_PATTERN = /^([+-])?([a-z$_][\w.]*)$/i;
|
|
7
6
|
/**
|
|
@@ -24,21 +23,29 @@ class ComplexTypeBaseClass extends DataType {
|
|
|
24
23
|
/**
|
|
25
24
|
*
|
|
26
25
|
*/
|
|
27
|
-
findField(nameOrPath) {
|
|
26
|
+
findField(nameOrPath, scope) {
|
|
28
27
|
if (nameOrPath.includes('.')) {
|
|
29
|
-
const fieldPath = this.parseFieldPath(nameOrPath);
|
|
28
|
+
const fieldPath = this.parseFieldPath(nameOrPath, { scope });
|
|
29
|
+
if (fieldPath.length === 0)
|
|
30
|
+
throw new Error(`Field "${nameOrPath}" does not exist in scope "${scope}"`);
|
|
30
31
|
const lastItem = fieldPath.pop();
|
|
31
32
|
return lastItem?.field;
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
+
const field = this.fields.get(nameOrPath);
|
|
35
|
+
if (field && scope && !field.inScope(scope))
|
|
36
|
+
return;
|
|
37
|
+
return field;
|
|
34
38
|
}
|
|
35
39
|
/**
|
|
36
40
|
*
|
|
37
41
|
*/
|
|
38
|
-
getField(nameOrPath) {
|
|
42
|
+
getField(nameOrPath, scope) {
|
|
39
43
|
const field = this.findField(nameOrPath);
|
|
40
|
-
if (!field)
|
|
41
|
-
throw new Error(
|
|
44
|
+
if (field && scope && !field.inScope(scope))
|
|
45
|
+
throw new Error(`Field "${nameOrPath}" does not exist in scope "${scope}"`);
|
|
46
|
+
if (!field) {
|
|
47
|
+
throw new Error(`Field (${nameOrPath}) does not exist`);
|
|
48
|
+
}
|
|
42
49
|
return field;
|
|
43
50
|
}
|
|
44
51
|
/**
|
|
@@ -69,7 +76,7 @@ class ComplexTypeBaseClass extends DataType {
|
|
|
69
76
|
}
|
|
70
77
|
if (dataType) {
|
|
71
78
|
if (dataType instanceof ComplexTypeBase) {
|
|
72
|
-
field = dataType.
|
|
79
|
+
field = dataType.getField(item.fieldName, options?.scope);
|
|
73
80
|
if (field) {
|
|
74
81
|
item.fieldName = field.name;
|
|
75
82
|
item.field = field;
|
|
@@ -149,9 +156,13 @@ class ComplexTypeBaseClass extends DataType {
|
|
|
149
156
|
// Process fields
|
|
150
157
|
let fieldName;
|
|
151
158
|
for (const field of this.fields.values()) {
|
|
152
|
-
if (
|
|
153
|
-
|
|
154
|
-
|
|
159
|
+
if (
|
|
160
|
+
/** Ignore field if required scope(s) do not match field scopes */
|
|
161
|
+
(context.scope && !field.inScope(context.scope)) ||
|
|
162
|
+
/** Ignore field if readonly and ignoreReadonlyFields option true */
|
|
163
|
+
(context.ignoreReadonlyFields && field.readonly) ||
|
|
164
|
+
/** Ignore field if writeonly and ignoreWriteonlyFields option true */
|
|
165
|
+
(context.ignoreWriteonlyFields && field.writeonly)) {
|
|
155
166
|
schema[field.name] = vg.isUndefined({ coerce: true });
|
|
156
167
|
continue;
|
|
157
168
|
}
|
|
@@ -68,21 +68,26 @@ class ComplexTypeClass extends ComplexTypeBase {
|
|
|
68
68
|
return true;
|
|
69
69
|
return !!this.base?.extendsFrom(baseType);
|
|
70
70
|
}
|
|
71
|
-
toJSON() {
|
|
71
|
+
toJSON(options) {
|
|
72
|
+
const superJson = super.toJSON(options);
|
|
72
73
|
const baseName = this.base
|
|
73
74
|
? this.node.getDataTypeNameWithNs(this.base)
|
|
74
75
|
: undefined;
|
|
75
|
-
const out =
|
|
76
|
-
...
|
|
76
|
+
const out = {
|
|
77
|
+
...superJson,
|
|
77
78
|
kind: this.kind,
|
|
78
|
-
base: this.base
|
|
79
|
-
|
|
79
|
+
base: this.base
|
|
80
|
+
? baseName
|
|
81
|
+
? baseName
|
|
82
|
+
: this.base.toJSON(options)
|
|
83
|
+
: undefined,
|
|
84
|
+
};
|
|
80
85
|
if (this.additionalFields) {
|
|
81
86
|
if (this.additionalFields instanceof DataType) {
|
|
82
87
|
const typeName = this.node.getDataTypeNameWithNs(this.additionalFields);
|
|
83
88
|
out.additionalFields = typeName
|
|
84
89
|
? typeName
|
|
85
|
-
: this.additionalFields.toJSON();
|
|
90
|
+
: this.additionalFields.toJSON(options);
|
|
86
91
|
}
|
|
87
92
|
else
|
|
88
93
|
out.additionalFields = this.additionalFields;
|
|
@@ -91,8 +96,9 @@ class ComplexTypeClass extends ComplexTypeBase {
|
|
|
91
96
|
const fields = {};
|
|
92
97
|
let i = 0;
|
|
93
98
|
for (const field of this.fields.values()) {
|
|
94
|
-
if (field.origin === this
|
|
95
|
-
|
|
99
|
+
if (field.origin === this &&
|
|
100
|
+
(!options?.scope || field.inScope(options?.scope))) {
|
|
101
|
+
fields[field.name] = field.toJSON(options);
|
|
96
102
|
i++;
|
|
97
103
|
}
|
|
98
104
|
}
|
|
@@ -101,6 +107,14 @@ class ComplexTypeClass extends ComplexTypeBase {
|
|
|
101
107
|
}
|
|
102
108
|
return omitUndefined(out);
|
|
103
109
|
}
|
|
110
|
+
_locateBase(callback) {
|
|
111
|
+
if (!this.base)
|
|
112
|
+
return;
|
|
113
|
+
if (callback(this.base))
|
|
114
|
+
return this.base;
|
|
115
|
+
if (this.base._locateBase)
|
|
116
|
+
return this.base._locateBase(callback);
|
|
117
|
+
}
|
|
104
118
|
}
|
|
105
119
|
ComplexType.prototype = ComplexTypeClass.prototype;
|
|
106
120
|
Object.assign(ComplexType, ComplexTypeDecorator);
|
|
@@ -3,6 +3,7 @@ import { asMutable } from 'ts-gems';
|
|
|
3
3
|
import { DocumentElement } from '../common/document-element.js';
|
|
4
4
|
import { CLASS_NAME_PATTERN } from '../constants.js';
|
|
5
5
|
import { colorFgMagenta, colorFgYellow, colorReset, nodeInspectCustom, } from '../utils/inspect.util.js';
|
|
6
|
+
import { testScopeMatch } from '../utils/test-scope-match.js';
|
|
6
7
|
/**
|
|
7
8
|
* DataType constructor
|
|
8
9
|
*/
|
|
@@ -17,6 +18,7 @@ context) {
|
|
|
17
18
|
DocumentElement.call(this, owner);
|
|
18
19
|
const _this = asMutable(this);
|
|
19
20
|
_this.kind = initArgs.kind;
|
|
21
|
+
_this.scopePattern = initArgs.scopePattern;
|
|
20
22
|
_this.name = initArgs.name;
|
|
21
23
|
_this.description = initArgs.description;
|
|
22
24
|
_this.abstract = initArgs.abstract;
|
|
@@ -30,7 +32,18 @@ class DataTypeClass extends DocumentElement {
|
|
|
30
32
|
get embedded() {
|
|
31
33
|
return !this.name;
|
|
32
34
|
}
|
|
33
|
-
|
|
35
|
+
inScope(scope) {
|
|
36
|
+
return testScopeMatch(scope, this.scopePattern);
|
|
37
|
+
}
|
|
38
|
+
toJSON(options) {
|
|
39
|
+
if (options?.scope) {
|
|
40
|
+
/** Locate base model which is not available for given scope */
|
|
41
|
+
const outOfScope = this._locateBase(dt => !dt.inScope(options.scope));
|
|
42
|
+
if (outOfScope) {
|
|
43
|
+
const baseName = this.node.getDataTypeNameWithNs(outOfScope);
|
|
44
|
+
throw new TypeError(`"${baseName}" model is not available for "${options.scope}" scope`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
34
47
|
return omitUndefined({
|
|
35
48
|
kind: this.kind,
|
|
36
49
|
description: this.description,
|
|
@@ -48,16 +48,26 @@ class EnumTypeClass extends DataType {
|
|
|
48
48
|
generateCodec() {
|
|
49
49
|
return vg.isEnum(Object.keys(this.attributes));
|
|
50
50
|
}
|
|
51
|
-
toJSON() {
|
|
51
|
+
toJSON(options) {
|
|
52
|
+
const superJson = super.toJSON(options);
|
|
52
53
|
const baseName = this.base
|
|
53
54
|
? this.node.getDataTypeNameWithNs(this.base)
|
|
54
55
|
: undefined;
|
|
55
56
|
return omitUndefined({
|
|
56
|
-
...
|
|
57
|
-
|
|
57
|
+
...superJson,
|
|
58
|
+
kind: this.kind,
|
|
59
|
+
base: baseName,
|
|
58
60
|
attributes: cloneObject(this.ownAttributes),
|
|
59
61
|
});
|
|
60
62
|
}
|
|
63
|
+
_locateBase(callback) {
|
|
64
|
+
if (!this.base)
|
|
65
|
+
return;
|
|
66
|
+
if (callback(this.base))
|
|
67
|
+
return this.base;
|
|
68
|
+
if (this.base._locateBase)
|
|
69
|
+
return this.base._locateBase(callback);
|
|
70
|
+
}
|
|
61
71
|
}
|
|
62
72
|
EnumType.prototype = EnumTypeClass.prototype;
|
|
63
73
|
Object.assign(EnumType, EnumTypeClass);
|
|
@@ -1,32 +1,35 @@
|
|
|
1
1
|
import { __decorate, __metadata } from "tslib";
|
|
2
2
|
import { toString, validator, vg } from 'valgen';
|
|
3
3
|
import { DECODER, ENCODER } from '../../constants.js';
|
|
4
|
+
import { DataType } from '../data-type.js';
|
|
4
5
|
import { SimpleType } from '../simple-type.js';
|
|
5
6
|
let FieldPathType = class FieldPathType {
|
|
6
7
|
constructor(attributes) {
|
|
7
8
|
if (attributes)
|
|
8
9
|
Object.assign(this, attributes);
|
|
9
10
|
}
|
|
10
|
-
[DECODER](properties, element) {
|
|
11
|
+
[DECODER](properties, element, scope) {
|
|
11
12
|
const dataType = properties.dataType
|
|
12
13
|
? element.node.getComplexType(properties.dataType)
|
|
13
14
|
: element.node.getComplexType('object');
|
|
14
15
|
const allowSigns = properties.allowSigns;
|
|
15
|
-
const decodeFieldPath = validator('decodeFieldPath', (input) => dataType.normalizeFieldPath(input, { allowSigns }));
|
|
16
|
+
const decodeFieldPath = validator('decodeFieldPath', (input) => dataType.normalizeFieldPath(input, { allowSigns, scope }));
|
|
16
17
|
return vg.pipe([toString, decodeFieldPath]);
|
|
17
18
|
}
|
|
18
|
-
[ENCODER](properties, element) {
|
|
19
|
-
return this[DECODER](properties, element);
|
|
19
|
+
[ENCODER](properties, element, scope) {
|
|
20
|
+
return this[DECODER](properties, element, scope);
|
|
20
21
|
}
|
|
21
|
-
toJSON(properties, element) {
|
|
22
|
+
toJSON(properties, element, options) {
|
|
22
23
|
const dataType = properties.dataType
|
|
23
24
|
? element.node.getComplexType(properties.dataType)
|
|
24
25
|
: element.node.getComplexType('object');
|
|
26
|
+
/** Test scope */
|
|
27
|
+
DataType.prototype.toJSON.call(dataType, options);
|
|
25
28
|
const typeName = dataType
|
|
26
29
|
? element.node.getDataTypeNameWithNs(dataType)
|
|
27
30
|
: undefined;
|
|
28
31
|
return {
|
|
29
|
-
dataType: typeName ? typeName : dataType.toJSON(),
|
|
32
|
+
dataType: typeName ? typeName : dataType.toJSON(options),
|
|
30
33
|
allowSigns: properties.allowSigns,
|
|
31
34
|
};
|
|
32
35
|
}
|
|
@@ -47,6 +50,7 @@ __decorate([
|
|
|
47
50
|
], FieldPathType.prototype, "allowSigns", void 0);
|
|
48
51
|
FieldPathType = __decorate([
|
|
49
52
|
SimpleType({
|
|
53
|
+
name: 'fieldpath',
|
|
50
54
|
description: 'Field path',
|
|
51
55
|
nameMappings: {
|
|
52
56
|
js: 'string',
|
|
@@ -3,6 +3,7 @@ import { validator } from 'valgen';
|
|
|
3
3
|
import { FilterRules } from '../../../filter/filter-rules.js';
|
|
4
4
|
import { OpraFilter } from '../../../filter/index.js';
|
|
5
5
|
import { DECODER, ENCODER } from '../../constants.js';
|
|
6
|
+
import { DataType } from '../data-type.js';
|
|
6
7
|
import { SimpleType } from '../simple-type.js';
|
|
7
8
|
let FilterType = class FilterType {
|
|
8
9
|
constructor(attributes) {
|
|
@@ -21,12 +22,17 @@ let FilterType = class FilterType {
|
|
|
21
22
|
[ENCODER]() {
|
|
22
23
|
return encodeFilter;
|
|
23
24
|
}
|
|
24
|
-
toJSON(properties, element) {
|
|
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
|
+
DataType.prototype.toJSON.call(dataType, options);
|
|
31
|
+
const typeName = dataType
|
|
32
|
+
? element.node.getDataTypeNameWithNs(dataType)
|
|
33
|
+
: undefined;
|
|
28
34
|
return {
|
|
29
|
-
dataType:
|
|
35
|
+
dataType: typeName ? typeName : dataType.toJSON(options),
|
|
30
36
|
rules: properties.rules,
|
|
31
37
|
};
|
|
32
38
|
}
|
|
@@ -46,6 +52,7 @@ __decorate([
|
|
|
46
52
|
], FilterType.prototype, "rules", void 0);
|
|
47
53
|
FilterType = __decorate([
|
|
48
54
|
SimpleType({
|
|
55
|
+
name: 'filter',
|
|
49
56
|
description: 'A query filter',
|
|
50
57
|
nameMappings: {
|
|
51
58
|
js: 'object',
|
|
@@ -55,12 +62,12 @@ FilterType = __decorate([
|
|
|
55
62
|
__metadata("design:paramtypes", [Object])
|
|
56
63
|
], FilterType);
|
|
57
64
|
export { FilterType };
|
|
58
|
-
const decodeFilter = (dataType, rules) => validator('decodeFilter', (input, context, _this) => {
|
|
65
|
+
const decodeFilter = (dataType, rules, scope) => validator('decodeFilter', (input, context, _this) => {
|
|
59
66
|
if (typeof input === 'string') {
|
|
60
67
|
try {
|
|
61
68
|
const filter = OpraFilter.parse(input);
|
|
62
69
|
if (rules)
|
|
63
|
-
return rules.normalizeFilter(filter, dataType);
|
|
70
|
+
return rules.normalizeFilter(filter, dataType, scope);
|
|
64
71
|
return filter;
|
|
65
72
|
}
|
|
66
73
|
catch (e) {
|
|
@@ -85,13 +85,14 @@ class MappedTypeClass extends ComplexTypeBase {
|
|
|
85
85
|
return true;
|
|
86
86
|
return !!this.base?.extendsFrom(baseType);
|
|
87
87
|
}
|
|
88
|
-
toJSON() {
|
|
88
|
+
toJSON(options) {
|
|
89
|
+
const superJson = super.toJSON(options);
|
|
89
90
|
const baseName = this.base
|
|
90
91
|
? this.node.getDataTypeNameWithNs(this.base)
|
|
91
92
|
: undefined;
|
|
92
93
|
return omitUndefined({
|
|
93
|
-
...
|
|
94
|
-
base: baseName ? baseName : this.base.toJSON(),
|
|
94
|
+
...superJson,
|
|
95
|
+
base: baseName ? baseName : this.base.toJSON(options),
|
|
95
96
|
kind: this.kind,
|
|
96
97
|
pick: this.pick,
|
|
97
98
|
omit: this.omit,
|
|
@@ -99,6 +100,14 @@ class MappedTypeClass extends ComplexTypeBase {
|
|
|
99
100
|
required: this.required,
|
|
100
101
|
});
|
|
101
102
|
}
|
|
103
|
+
_locateBase(callback) {
|
|
104
|
+
if (!this.base)
|
|
105
|
+
return;
|
|
106
|
+
if (callback(this.base))
|
|
107
|
+
return this.base;
|
|
108
|
+
if (this.base._locateBase)
|
|
109
|
+
return this.base._locateBase(callback);
|
|
110
|
+
}
|
|
102
111
|
}
|
|
103
112
|
MappedType.prototype = MappedTypeClass.prototype;
|
|
104
113
|
MappedType._applyMixin = () => undefined;
|
|
@@ -54,16 +54,28 @@ class MixinTypeClass extends ComplexTypeBase {
|
|
|
54
54
|
}
|
|
55
55
|
return false;
|
|
56
56
|
}
|
|
57
|
-
toJSON() {
|
|
57
|
+
toJSON(options) {
|
|
58
|
+
const superJson = super.toJSON(options);
|
|
58
59
|
return omitUndefined({
|
|
59
|
-
...
|
|
60
|
+
...superJson,
|
|
60
61
|
kind: this.kind,
|
|
61
|
-
types: this.types.map(
|
|
62
|
-
const baseName = this.node.getDataTypeNameWithNs(
|
|
63
|
-
return baseName ? baseName :
|
|
62
|
+
types: this.types.map(base => {
|
|
63
|
+
const baseName = this.node.getDataTypeNameWithNs(base);
|
|
64
|
+
return baseName ? baseName : base.toJSON(options);
|
|
64
65
|
}),
|
|
65
66
|
});
|
|
66
67
|
}
|
|
68
|
+
_locateBase(callback) {
|
|
69
|
+
for (const t of this.types) {
|
|
70
|
+
if (callback(t))
|
|
71
|
+
return t;
|
|
72
|
+
if (t._locateBase) {
|
|
73
|
+
const x = t._locateBase(callback);
|
|
74
|
+
if (x)
|
|
75
|
+
return x;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
67
79
|
}
|
|
68
80
|
MixinType.prototype = MixinTypeClass.prototype;
|
|
69
81
|
MixinType[DECORATOR] = MixinTypeFactory;
|