@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.
Files changed (124) hide show
  1. package/browser/index.cjs +5 -5
  2. package/browser/index.mjs +5 -5
  3. package/cjs/document/api-document.js +12 -8
  4. package/cjs/document/common/api-base.js +2 -1
  5. package/cjs/document/common/document-node.js +24 -29
  6. package/cjs/document/common/value.js +6 -2
  7. package/cjs/document/constants.js +1 -2
  8. package/cjs/document/data-type/api-field.js +12 -8
  9. package/cjs/document/data-type/complex-type-base.js +22 -11
  10. package/cjs/document/data-type/complex-type.js +22 -8
  11. package/cjs/document/data-type/data-type.js +14 -1
  12. package/cjs/document/data-type/enum-type.js +13 -3
  13. package/cjs/document/data-type/extended-types/base64.type.js +1 -0
  14. package/cjs/document/data-type/extended-types/date-string.type.js +1 -0
  15. package/cjs/document/data-type/extended-types/date-time-string.type.js +1 -0
  16. package/cjs/document/data-type/extended-types/date-time.type.js +1 -0
  17. package/cjs/document/data-type/extended-types/date.type.js +1 -0
  18. package/cjs/document/data-type/extended-types/email.type.js +1 -0
  19. package/cjs/document/data-type/extended-types/field-path.type.js +10 -6
  20. package/cjs/document/data-type/extended-types/filter.type.js +11 -4
  21. package/cjs/document/data-type/extended-types/object-id.type.js +1 -0
  22. package/cjs/document/data-type/extended-types/operation-result.type.js +1 -0
  23. package/cjs/document/data-type/extended-types/time.type.js +1 -0
  24. package/cjs/document/data-type/extended-types/url.type.js +1 -0
  25. package/cjs/document/data-type/extended-types/uuid.type.js +1 -0
  26. package/cjs/document/data-type/mapped-type.js +12 -3
  27. package/cjs/document/data-type/mixin-type.js +17 -5
  28. package/cjs/document/data-type/primitive-types/any.type.js +1 -0
  29. package/cjs/document/data-type/primitive-types/bigint.type.js +1 -0
  30. package/cjs/document/data-type/primitive-types/boolean.type.js +1 -0
  31. package/cjs/document/data-type/primitive-types/integer.type.js +1 -0
  32. package/cjs/document/data-type/primitive-types/null.type.js +1 -0
  33. package/cjs/document/data-type/primitive-types/number.type.js +1 -0
  34. package/cjs/document/data-type/primitive-types/string.type.js +1 -0
  35. package/cjs/document/data-type/simple-type.js +13 -11
  36. package/cjs/document/decorators/api-field-decorator.js +37 -3
  37. package/cjs/document/decorators/complex-type.decorator.js +1 -1
  38. package/cjs/document/decorators/simple-type.decorator.js +3 -1
  39. package/cjs/document/http/http-api.js +2 -2
  40. package/cjs/document/http/http-controller.js +5 -5
  41. package/cjs/document/http/http-media-type.js +3 -3
  42. package/cjs/document/http/http-multipart-field.js +2 -2
  43. package/cjs/document/http/http-operation-response.js +3 -3
  44. package/cjs/document/http/http-operation.js +5 -5
  45. package/cjs/document/http/http-parameter.js +2 -2
  46. package/cjs/document/http/http-request-body.js +4 -2
  47. package/cjs/document/utils/test-scope-match.js +13 -0
  48. package/cjs/filter/filter-rules.js +6 -6
  49. package/esm/document/api-document.js +12 -8
  50. package/esm/document/common/api-base.js +2 -1
  51. package/esm/document/common/document-node.js +24 -29
  52. package/esm/document/common/value.js +6 -2
  53. package/esm/document/constants.js +0 -1
  54. package/esm/document/data-type/api-field.js +13 -9
  55. package/esm/document/data-type/complex-type-base.js +22 -11
  56. package/esm/document/data-type/complex-type.js +22 -8
  57. package/esm/document/data-type/data-type.js +14 -1
  58. package/esm/document/data-type/enum-type.js +13 -3
  59. package/esm/document/data-type/extended-types/base64.type.js +1 -0
  60. package/esm/document/data-type/extended-types/date-string.type.js +1 -0
  61. package/esm/document/data-type/extended-types/date-time-string.type.js +1 -0
  62. package/esm/document/data-type/extended-types/date-time.type.js +1 -0
  63. package/esm/document/data-type/extended-types/date.type.js +1 -0
  64. package/esm/document/data-type/extended-types/email.type.js +1 -0
  65. package/esm/document/data-type/extended-types/field-path.type.js +10 -6
  66. package/esm/document/data-type/extended-types/filter.type.js +11 -4
  67. package/esm/document/data-type/extended-types/object-id.type.js +1 -0
  68. package/esm/document/data-type/extended-types/operation-result.type.js +1 -0
  69. package/esm/document/data-type/extended-types/time.type.js +1 -0
  70. package/esm/document/data-type/extended-types/url.type.js +1 -0
  71. package/esm/document/data-type/extended-types/uuid.type.js +1 -0
  72. package/esm/document/data-type/mapped-type.js +12 -3
  73. package/esm/document/data-type/mixin-type.js +17 -5
  74. package/esm/document/data-type/primitive-types/any.type.js +1 -0
  75. package/esm/document/data-type/primitive-types/bigint.type.js +1 -0
  76. package/esm/document/data-type/primitive-types/boolean.type.js +1 -0
  77. package/esm/document/data-type/primitive-types/integer.type.js +1 -0
  78. package/esm/document/data-type/primitive-types/null.type.js +1 -0
  79. package/esm/document/data-type/primitive-types/number.type.js +1 -0
  80. package/esm/document/data-type/primitive-types/string.type.js +1 -0
  81. package/esm/document/data-type/simple-type.js +13 -11
  82. package/esm/document/decorators/api-field-decorator.js +36 -2
  83. package/esm/document/decorators/complex-type.decorator.js +2 -2
  84. package/esm/document/decorators/simple-type.decorator.js +4 -2
  85. package/esm/document/http/http-api.js +2 -2
  86. package/esm/document/http/http-controller.js +5 -5
  87. package/esm/document/http/http-media-type.js +3 -3
  88. package/esm/document/http/http-multipart-field.js +2 -2
  89. package/esm/document/http/http-operation-response.js +3 -3
  90. package/esm/document/http/http-operation.js +5 -5
  91. package/esm/document/http/http-parameter.js +2 -2
  92. package/esm/document/http/http-request-body.js +4 -2
  93. package/esm/document/utils/test-scope-match.js +10 -0
  94. package/esm/filter/filter-rules.js +6 -6
  95. package/package.json +1 -1
  96. package/types/document/api-document.d.ts +7 -2
  97. package/types/document/common/api-base.d.ts +1 -1
  98. package/types/document/common/document-init-context.d.ts +1 -0
  99. package/types/document/common/document-node.d.ts +8 -14
  100. package/types/document/common/value.d.ts +2 -1
  101. package/types/document/constants.d.ts +0 -1
  102. package/types/document/data-type/api-field.d.ts +42 -34
  103. package/types/document/data-type/complex-type-base.d.ts +4 -2
  104. package/types/document/data-type/complex-type.d.ts +3 -1
  105. package/types/document/data-type/data-type.d.ts +8 -2
  106. package/types/document/data-type/enum-type.d.ts +3 -1
  107. package/types/document/data-type/extended-types/field-path.type.d.ts +4 -3
  108. package/types/document/data-type/extended-types/filter.type.d.ts +2 -1
  109. package/types/document/data-type/mapped-type.d.ts +3 -1
  110. package/types/document/data-type/mixin-type.d.ts +3 -1
  111. package/types/document/data-type/simple-type.d.ts +3 -2
  112. package/types/document/decorators/api-field-decorator.d.ts +5 -3
  113. package/types/document/decorators/simple-type.decorator.d.ts +34 -0
  114. package/types/document/factory/api-document.factory.d.ts +1 -0
  115. package/types/document/http/http-api.d.ts +1 -1
  116. package/types/document/http/http-controller.d.ts +2 -1
  117. package/types/document/http/http-media-type.d.ts +2 -1
  118. package/types/document/http/http-multipart-field.d.ts +2 -1
  119. package/types/document/http/http-operation-response.d.ts +2 -1
  120. package/types/document/http/http-operation.d.ts +2 -1
  121. package/types/document/http/http-parameter.d.ts +2 -1
  122. package/types/document/http/http-request-body.d.ts +2 -1
  123. package/types/document/utils/test-scope-match.d.ts +1 -0
  124. 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
- const result = this[kDataTypeMap]?.has(nameOrCtor);
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 result = this[kDataTypeMap]?.get(nameOrCtor);
29
- if (result)
30
- return result;
31
- return this.parent ? this.parent.findDataType(nameOrCtor) : undefined;
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
- throw new TypeError(`Unknown data type` + (name ? ' (' + name + ')' : ''));
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 ? (typeName ? typeName : this.type.toJSON()) : 'any',
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 { ApiFieldDecorator } from '../decorators/api-field-decorator.js';
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
- * @class ApiField
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
- toJSON() {
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, ApiFieldDecorator);
71
- ApiField[DECORATOR] = ApiFieldDecorator;
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
- return this.fields.get(nameOrPath);
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(translate('error:UNKNOWN_FIELD', { field: nameOrPath }));
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.fields.get(item.fieldName);
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 ((context.ignoreReadonlyFields && field.readonly) ||
153
- (context.ignoreWriteonlyFields && field.writeonly) ||
154
- (context.ignoreHiddenFields && field.hidden)) {
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 = omitUndefined({
76
- ...ComplexTypeBase.prototype.toJSON.call(this),
76
+ const out = {
77
+ ...superJson,
77
78
  kind: this.kind,
78
- base: this.base ? (baseName ? baseName : this.base.toJSON()) : undefined,
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
- fields[field.name] = field.toJSON();
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
- toJSON() {
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
- ...DataType.prototype.toJSON.call(this),
57
- base: this.base ? (baseName ? baseName : this.base.toJSON()) : undefined,
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);
@@ -16,6 +16,7 @@ let Base64Type = class Base64Type {
16
16
  };
17
17
  Base64Type = __decorate([
18
18
  SimpleType({
19
+ name: 'base64',
19
20
  description: 'A stream of bytes, base64 encoded',
20
21
  nameMappings: {
21
22
  js: 'string',
@@ -34,6 +34,7 @@ __decorate([
34
34
  ], DateStringType.prototype, "maxValue", void 0);
35
35
  DateStringType = __decorate([
36
36
  (SimpleType({
37
+ name: 'datestring',
37
38
  description: 'Date string value',
38
39
  nameMappings: {
39
40
  js: 'string',
@@ -34,6 +34,7 @@ __decorate([
34
34
  ], DateTimeStringType.prototype, "maxValue", void 0);
35
35
  DateTimeStringType = __decorate([
36
36
  (SimpleType({
37
+ name: 'datetimestring',
37
38
  description: 'DateTime string value',
38
39
  nameMappings: {
39
40
  js: 'string',
@@ -52,6 +52,7 @@ __decorate([
52
52
  ], DateTimeType.prototype, "maxValue", void 0);
53
53
  DateTimeType = __decorate([
54
54
  (SimpleType({
55
+ name: 'datetime',
55
56
  description: 'A full datetime value',
56
57
  nameMappings: {
57
58
  js: 'string',
@@ -52,6 +52,7 @@ __decorate([
52
52
  ], DateType.prototype, "maxValue", void 0);
53
53
  DateType = __decorate([
54
54
  (SimpleType({
55
+ name: 'date',
55
56
  description: 'A date without time',
56
57
  nameMappings: {
57
58
  js: 'Date',
@@ -80,6 +80,7 @@ __decorate([
80
80
  ], EmailType.prototype, "blacklistedChars", void 0);
81
81
  EmailType = __decorate([
82
82
  (SimpleType({
83
+ name: 'email',
83
84
  description: 'An email value',
84
85
  nameMappings: {
85
86
  js: 'string',
@@ -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: dataType.name ? dataType.name : dataType.toJSON(),
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) {
@@ -16,6 +16,7 @@ let ObjectIdType = class ObjectIdType {
16
16
  };
17
17
  ObjectIdType = __decorate([
18
18
  SimpleType({
19
+ name: 'ObjectId',
19
20
  description: 'A MongoDB ObjectID value',
20
21
  nameMappings: {
21
22
  js: 'object',
@@ -37,6 +37,7 @@ __decorate([
37
37
  ], OperationResult.prototype, "errors", void 0);
38
38
  OperationResult = __decorate([
39
39
  ComplexType({
40
+ name: 'OperationResult',
40
41
  description: 'Operation result',
41
42
  }),
42
43
  __metadata("design:paramtypes", [Object])
@@ -38,6 +38,7 @@ __decorate([
38
38
  ], TimeType.prototype, "maxValue", void 0);
39
39
  TimeType = __decorate([
40
40
  (SimpleType({
41
+ name: 'time',
41
42
  description: 'Time string in 24h format',
42
43
  nameMappings: {
43
44
  js: 'string',
@@ -16,6 +16,7 @@ let UrlType = class UrlType {
16
16
  };
17
17
  UrlType = __decorate([
18
18
  (SimpleType({
19
+ name: 'url',
19
20
  description: 'A Uniform Resource Identifier Reference (RFC 3986 icon) value',
20
21
  nameMappings: {
21
22
  js: 'string',
@@ -22,6 +22,7 @@ __decorate([
22
22
  ], UuidType.prototype, "version", void 0);
23
23
  UuidType = __decorate([
24
24
  SimpleType({
25
+ name: 'uuid',
25
26
  description: 'A Universal Unique Identifier (UUID) value',
26
27
  nameMappings: {
27
28
  js: 'string',
@@ -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
- ...ComplexTypeBase.prototype.toJSON.call(this),
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
- ...ComplexTypeBase.prototype.toJSON.call(this),
60
+ ...superJson,
60
61
  kind: this.kind,
61
- types: this.types.map(t => {
62
- const baseName = this.node.getDataTypeNameWithNs(t);
63
- return baseName ? baseName : t.toJSON();
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;