@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
@@ -67,7 +67,7 @@ class ApiDocument extends document_element_js_1.DocumentElement {
67
67
  /**
68
68
  * Export as Opra schema definition object
69
69
  */
70
- export() {
70
+ export(options) {
71
71
  const out = (0, objects_1.omitUndefined)({
72
72
  spec: index_js_2.OpraSchema.SpecVersion,
73
73
  id: this.id,
@@ -93,25 +93,29 @@ class ApiDocument extends document_element_js_1.DocumentElement {
93
93
  if (this.types.size) {
94
94
  out.types = {};
95
95
  for (const v of this.types.values()) {
96
- out.types[v.name] = v.toJSON();
96
+ if (options?.scope && !v.inScope(options?.scope))
97
+ continue;
98
+ out.types[v.name] = v.toJSON(options);
97
99
  }
98
100
  }
99
101
  if (this.api)
100
- out.api = this.api.toJSON();
102
+ out.api = this.api.toJSON(options);
101
103
  return out;
102
104
  }
103
105
  invalidate() {
104
106
  /** Generate id */
105
- const x = this.export();
107
+ const x = this.export({});
106
108
  delete x.id;
107
109
  this.id = (0, super_fast_md5_1.md5)(JSON.stringify(x));
108
110
  /** Clear [kTypeNSMap] */
109
111
  this[constants_js_1.kTypeNSMap] = new WeakMap();
110
112
  }
111
- _findDataType(nameOrCtor, visitedRefs) {
113
+ _findDataType(nameOrCtor, scope, visitedRefs) {
112
114
  let result = this.types.get(nameOrCtor);
113
- if (result || !this.references.size)
115
+ if (result && (!scope || result.inScope(scope)))
114
116
  return result;
117
+ if (!this.references.size)
118
+ return;
115
119
  // Lookup for references
116
120
  if (typeof nameOrCtor === 'string') {
117
121
  // If given string has namespace pattern (ns:type_name)
@@ -125,7 +129,7 @@ class ApiDocument extends document_element_js_1.DocumentElement {
125
129
  visitedRefs = visitedRefs || new WeakMap();
126
130
  visitedRefs.set(this, true);
127
131
  visitedRefs.set(ref, true);
128
- return ref._findDataType(m[2], visitedRefs);
132
+ return ref._findDataType(m[2], scope, visitedRefs);
129
133
  }
130
134
  nameOrCtor = m[2];
131
135
  }
@@ -147,7 +151,7 @@ class ApiDocument extends document_element_js_1.DocumentElement {
147
151
  for (const refNs of references) {
148
152
  const ref = this.references.get(refNs);
149
153
  visitedRefs.set(ref, true);
150
- result = ref._findDataType(nameOrCtor, visitedRefs);
154
+ result = ref._findDataType(nameOrCtor, scope, visitedRefs);
151
155
  if (result) {
152
156
  this[constants_js_1.kTypeNSMap].set(result, ref?.[constants_js_1.BUILTIN] ? '' : refNs);
153
157
  return result;
@@ -11,7 +11,8 @@ class ApiBase extends document_element_js_1.DocumentElement {
11
11
  this.name = init.name;
12
12
  this.description = init.description;
13
13
  }
14
- toJSON() {
14
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
15
+ toJSON(options) {
15
16
  return (0, objects_1.omitUndefined)({
16
17
  transport: this.transport,
17
18
  name: this.name,
@@ -21,25 +21,23 @@ class DocumentNode {
21
21
  // istanbul ignore next
22
22
  throw new Error('ApiDocument not found in document tree');
23
23
  }
24
- hasDataType(nameOrCtor) {
25
- const result = this[constants_js_1.kDataTypeMap]?.has(nameOrCtor);
26
- if (result)
27
- return result;
28
- return this.parent ? this.parent.hasDataType(nameOrCtor) : false;
24
+ hasDataType(nameOrCtor, scope) {
25
+ return !!this.findDataType(nameOrCtor, scope);
29
26
  }
30
- findDataType(nameOrCtor) {
31
- const result = this[constants_js_1.kDataTypeMap]?.get(nameOrCtor);
32
- if (result)
33
- return result;
34
- return this.parent ? this.parent.findDataType(nameOrCtor) : undefined;
27
+ findDataType(nameOrCtor, scope) {
28
+ const dt = this[constants_js_1.kDataTypeMap]?.get(nameOrCtor);
29
+ if (dt && (!scope || dt.inScope(scope)))
30
+ return dt;
31
+ return this.parent
32
+ ? this.parent.findDataType(nameOrCtor, scope)
33
+ : undefined;
35
34
  }
36
35
  /**
37
36
  * Returns DataType instance by name or Constructor. Returns undefined if not found
38
- * @param nameOrCtor
39
37
  */
40
- getDataType(nameOrCtor) {
38
+ getDataType(nameOrCtor, scope) {
41
39
  const dt = this.findDataType(nameOrCtor);
42
- if (dt)
40
+ if (dt && (!scope || dt.inScope(scope)))
43
41
  return dt;
44
42
  let name = '';
45
43
  if (typeof nameOrCtor === 'function') {
@@ -56,7 +54,9 @@ class DocumentNode {
56
54
  else if (typeof nameOrCtor === 'function')
57
55
  name = nameOrCtor.name;
58
56
  }
59
- throw new TypeError(`Unknown data type` + (name ? ' (' + name + ')' : ''));
57
+ if (dt)
58
+ throw new TypeError(`Data type${name ? ' (' + name + ')' : ''} is not in requested scope (${scope})`);
59
+ throw new TypeError(`Unknown data type${name ? ' (' + name + ')' : ''}`);
60
60
  }
61
61
  getDataTypeNameWithNs(dataType) {
62
62
  if (!dataType.name)
@@ -68,10 +68,9 @@ class DocumentNode {
68
68
  * Returns ComplexType instance by name or Constructor.
69
69
  * Returns undefined if not found
70
70
  * Throws error if data type is not a ComplexType
71
- * @param nameOrCtor
72
71
  */
73
- getComplexType(nameOrCtor) {
74
- const t = this.getDataType(nameOrCtor);
72
+ getComplexType(nameOrCtor, scope) {
73
+ const t = this.getDataType(nameOrCtor, scope);
75
74
  if (t.kind === index_js_1.OpraSchema.ComplexType.Kind)
76
75
  return t;
77
76
  throw new TypeError(`Data type "${t.name}" is not a ComplexType`);
@@ -80,10 +79,9 @@ class DocumentNode {
80
79
  * Returns SimpleType instance by name or Constructor.
81
80
  * Returns undefined if not found
82
81
  * Throws error if data type is not a SimpleType
83
- * @param nameOrCtor
84
82
  */
85
- getSimpleType(nameOrCtor) {
86
- const t = this.getDataType(nameOrCtor);
83
+ getSimpleType(nameOrCtor, scope) {
84
+ const t = this.getDataType(nameOrCtor, scope);
87
85
  if (t.kind === index_js_1.OpraSchema.SimpleType.Kind)
88
86
  return t;
89
87
  throw new TypeError(`Data type "${t.name || t}" is not a SimpleType`);
@@ -92,10 +90,9 @@ class DocumentNode {
92
90
  * Returns EnumType instance by name or Constructor.
93
91
  * Returns undefined if not found
94
92
  * Throws error if data type is not a EnumType
95
- * @param nameOrCtor
96
93
  */
97
- getEnumType(nameOrCtor) {
98
- const t = this.getDataType(nameOrCtor);
94
+ getEnumType(nameOrCtor, scope) {
95
+ const t = this.getDataType(nameOrCtor, scope);
99
96
  if (t.kind === index_js_1.OpraSchema.EnumType.Kind)
100
97
  return t;
101
98
  throw new TypeError(`Data type "${t.name || t}" is not a EnumType`);
@@ -104,10 +101,9 @@ class DocumentNode {
104
101
  * Returns EnumType instance by name or Constructor.
105
102
  * Returns undefined if not found
106
103
  * Throws error if data type is not a MappedType
107
- * @param nameOrCtor
108
104
  */
109
- getMappedType(nameOrCtor) {
110
- const t = this.getDataType(nameOrCtor);
105
+ getMappedType(nameOrCtor, scope) {
106
+ const t = this.getDataType(nameOrCtor, scope);
111
107
  if (t.kind === index_js_1.OpraSchema.MappedType.Kind)
112
108
  return t;
113
109
  throw new TypeError(`Data type "${t.name || t}" is not a MappedType`);
@@ -116,10 +112,9 @@ class DocumentNode {
116
112
  * Returns EnumType instance by name or Constructor.
117
113
  * Returns undefined if not found
118
114
  * Throws error if data type is not a MixinType
119
- * @param nameOrCtor
120
115
  */
121
- getMixinType(nameOrCtor) {
122
- const t = this.getDataType(nameOrCtor);
116
+ getMixinType(nameOrCtor, scope) {
117
+ const t = this.getDataType(nameOrCtor, scope);
123
118
  if (t.kind === index_js_1.OpraSchema.MixinType.Kind)
124
119
  return t;
125
120
  throw new TypeError(`Data type "${t.name || t}" is not a MixinType`);
@@ -20,12 +20,16 @@ exports.Value = function (owner, initArgs) {
20
20
  * @class Value
21
21
  */
22
22
  class ValueClass extends document_element_js_1.DocumentElement {
23
- toJSON() {
23
+ toJSON(options) {
24
24
  const typeName = this.type
25
25
  ? this.node.getDataTypeNameWithNs(this.type)
26
26
  : undefined;
27
27
  return (0, objects_1.omitUndefined)({
28
- type: this.type ? (typeName ? typeName : this.type.toJSON()) : 'any',
28
+ type: this.type
29
+ ? typeName
30
+ ? typeName
31
+ : this.type.toJSON(options)
32
+ : 'any',
29
33
  description: this.description,
30
34
  isArray: this.isArray,
31
35
  examples: this.examples,
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.kTypeNSMap = exports.kCtorMap = exports.kDataTypeMap = exports.EXTRACT_TYPENAME_PATTERN = exports.CLASS_NAME_PATTERN = exports.NAMESPACE_PATTERN = exports.BUILTIN = exports.DECORATOR = exports.ENCODER = exports.DECODER = exports.RPC_CONTROLLER_METADATA = exports.HTTP_CONTROLLER_METADATA = exports.DATATYPE_METADATA = void 0;
3
+ exports.kTypeNSMap = exports.kCtorMap = exports.kDataTypeMap = exports.CLASS_NAME_PATTERN = exports.NAMESPACE_PATTERN = exports.BUILTIN = exports.DECORATOR = exports.ENCODER = exports.DECODER = exports.RPC_CONTROLLER_METADATA = exports.HTTP_CONTROLLER_METADATA = exports.DATATYPE_METADATA = void 0;
4
4
  exports.DATATYPE_METADATA = Symbol.for('opra.type.metadata');
5
5
  exports.HTTP_CONTROLLER_METADATA = Symbol('opra.http-controller.metadata');
6
6
  exports.RPC_CONTROLLER_METADATA = Symbol('opra.rpc-controller.metadata');
@@ -10,7 +10,6 @@ exports.DECORATOR = Symbol.for('DECORATOR');
10
10
  exports.BUILTIN = Symbol.for('BUILTIN');
11
11
  exports.NAMESPACE_PATTERN = /([a-z$_]\w+):(.+)/i;
12
12
  exports.CLASS_NAME_PATTERN = /^[a-z][\w_]*$/i;
13
- exports.EXTRACT_TYPENAME_PATTERN = /^(.*)Type(\d*)$/;
14
13
  exports.kDataTypeMap = Symbol.for('kDataTypeMap');
15
14
  exports.kCtorMap = Symbol.for('kCtorMap');
16
15
  exports.kTypeNSMap = Symbol.for('kTypeNSMap');
@@ -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,6 +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.scopePattern = initArgs.scopePattern;
31
32
  _this.type = initArgs.type || owner.node.getDataType('any');
32
33
  _this.description = initArgs.description;
33
34
  _this.isArray = initArgs.isArray;
@@ -41,19 +42,22 @@ exports.ApiField = function (...args) {
41
42
  _this.readonly = initArgs.readonly;
42
43
  _this.writeonly = initArgs.writeonly;
43
44
  _this.examples = initArgs.examples;
44
- _this.hidden = initArgs.hidden;
45
45
  };
46
46
  /**
47
- *
48
- * @class ApiField
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
- toJSON() {
52
+ inScope(scope) {
53
+ return (0, test_scope_match_js_1.testScopeMatch)(scope, this.scopePattern);
54
+ }
55
+ toJSON(options) {
52
56
  const typeName = this.type
53
57
  ? this.node.getDataTypeNameWithNs(this.type)
54
58
  : undefined;
55
59
  return (0, objects_1.omitUndefined)({
56
- type: typeName ? typeName : this.type?.toJSON(),
60
+ type: typeName ? typeName : this.type?.toJSON(options),
57
61
  description: this.description,
58
62
  isArray: this.isArray || undefined,
59
63
  default: this.default,
@@ -70,5 +74,5 @@ class ApiFieldClass extends document_element_js_1.DocumentElement {
70
74
  }
71
75
  }
72
76
  exports.ApiField.prototype = ApiFieldClass.prototype;
73
- Object.assign(exports.ApiField, api_field_decorator_js_1.ApiFieldDecorator);
74
- exports.ApiField[constants_js_1.DECORATOR] = api_field_decorator_js_1.ApiFieldDecorator;
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
- return this.fields.get(nameOrPath);
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((0, index_js_2.translate)('error:UNKNOWN_FIELD', { field: nameOrPath }));
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.fields.get(item.fieldName);
82
+ field = dataType.getField(item.fieldName, options?.scope);
76
83
  if (field) {
77
84
  item.fieldName = field.name;
78
85
  item.field = field;
@@ -152,9 +159,13 @@ class ComplexTypeBaseClass extends data_type_js_1.DataType {
152
159
  // Process fields
153
160
  let fieldName;
154
161
  for (const field of this.fields.values()) {
155
- if ((context.ignoreReadonlyFields && field.readonly) ||
156
- (context.ignoreWriteonlyFields && field.writeonly) ||
157
- (context.ignoreHiddenFields && field.hidden)) {
162
+ if (
163
+ /** Ignore field if required scope(s) do not match field scopes */
164
+ (context.scope && !field.inScope(context.scope)) ||
165
+ /** Ignore field if readonly and ignoreReadonlyFields option true */
166
+ (context.ignoreReadonlyFields && field.readonly) ||
167
+ /** Ignore field if writeonly and ignoreWriteonlyFields option true */
168
+ (context.ignoreWriteonlyFields && field.writeonly)) {
158
169
  schema[field.name] = valgen_1.vg.isUndefined({ coerce: true });
159
170
  continue;
160
171
  }
@@ -71,21 +71,26 @@ class ComplexTypeClass extends complex_type_base_js_1.ComplexTypeBase {
71
71
  return true;
72
72
  return !!this.base?.extendsFrom(baseType);
73
73
  }
74
- toJSON() {
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
- const out = (0, objects_1.omitUndefined)({
79
- ...complex_type_base_js_1.ComplexTypeBase.prototype.toJSON.call(this),
79
+ const out = {
80
+ ...superJson,
80
81
  kind: this.kind,
81
- base: this.base ? (baseName ? baseName : this.base.toJSON()) : undefined,
82
- });
82
+ base: this.base
83
+ ? baseName
84
+ ? baseName
85
+ : this.base.toJSON(options)
86
+ : undefined,
87
+ };
83
88
  if (this.additionalFields) {
84
89
  if (this.additionalFields instanceof data_type_js_1.DataType) {
85
90
  const typeName = this.node.getDataTypeNameWithNs(this.additionalFields);
86
91
  out.additionalFields = typeName
87
92
  ? typeName
88
- : this.additionalFields.toJSON();
93
+ : this.additionalFields.toJSON(options);
89
94
  }
90
95
  else
91
96
  out.additionalFields = this.additionalFields;
@@ -94,8 +99,9 @@ class ComplexTypeClass extends complex_type_base_js_1.ComplexTypeBase {
94
99
  const fields = {};
95
100
  let i = 0;
96
101
  for (const field of this.fields.values()) {
97
- if (field.origin === this) {
98
- fields[field.name] = field.toJSON();
102
+ if (field.origin === this &&
103
+ (!options?.scope || field.inScope(options?.scope))) {
104
+ fields[field.name] = field.toJSON(options);
99
105
  i++;
100
106
  }
101
107
  }
@@ -104,6 +110,14 @@ class ComplexTypeClass extends complex_type_base_js_1.ComplexTypeBase {
104
110
  }
105
111
  return (0, objects_1.omitUndefined)(out);
106
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
+ }
107
121
  }
108
122
  exports.ComplexType.prototype = ComplexTypeClass.prototype;
109
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,6 +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;
24
+ _this.scopePattern = initArgs.scopePattern;
23
25
  _this.name = initArgs.name;
24
26
  _this.description = initArgs.description;
25
27
  _this.abstract = initArgs.abstract;
@@ -33,7 +35,18 @@ class DataTypeClass extends document_element_js_1.DocumentElement {
33
35
  get embedded() {
34
36
  return !this.name;
35
37
  }
36
- toJSON() {
38
+ inScope(scope) {
39
+ return (0, test_scope_match_js_1.testScopeMatch)(scope, this.scopePattern);
40
+ }
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
+ }
37
50
  return (0, objects_1.omitUndefined)({
38
51
  kind: this.kind,
39
52
  description: this.description,
@@ -51,16 +51,26 @@ class EnumTypeClass extends data_type_js_1.DataType {
51
51
  generateCodec() {
52
52
  return valgen_1.vg.isEnum(Object.keys(this.attributes));
53
53
  }
54
- toJSON() {
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
59
  return (0, objects_1.omitUndefined)({
59
- ...data_type_js_1.DataType.prototype.toJSON.call(this),
60
- base: this.base ? (baseName ? baseName : this.base.toJSON()) : undefined,
60
+ ...superJson,
61
+ kind: this.kind,
62
+ base: baseName,
61
63
  attributes: (0, index_js_1.cloneObject)(this.ownAttributes),
62
64
  });
63
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
+ }
64
74
  }
65
75
  exports.EnumType.prototype = EnumTypeClass.prototype;
66
76
  Object.assign(exports.EnumType, EnumTypeClass);
@@ -20,6 +20,7 @@ let Base64Type = class Base64Type {
20
20
  exports.Base64Type = Base64Type;
21
21
  exports.Base64Type = Base64Type = tslib_1.__decorate([
22
22
  (0, simple_type_js_1.SimpleType)({
23
+ name: 'base64',
23
24
  description: 'A stream of bytes, base64 encoded',
24
25
  nameMappings: {
25
26
  js: 'string',
@@ -38,6 +38,7 @@ tslib_1.__decorate([
38
38
  ], DateStringType.prototype, "maxValue", void 0);
39
39
  exports.DateStringType = DateStringType = tslib_1.__decorate([
40
40
  ((0, simple_type_js_1.SimpleType)({
41
+ name: 'datestring',
41
42
  description: 'Date string value',
42
43
  nameMappings: {
43
44
  js: 'string',
@@ -38,6 +38,7 @@ tslib_1.__decorate([
38
38
  ], DateTimeStringType.prototype, "maxValue", void 0);
39
39
  exports.DateTimeStringType = DateTimeStringType = tslib_1.__decorate([
40
40
  ((0, simple_type_js_1.SimpleType)({
41
+ name: 'datetimestring',
41
42
  description: 'DateTime string value',
42
43
  nameMappings: {
43
44
  js: 'string',
@@ -56,6 +56,7 @@ tslib_1.__decorate([
56
56
  ], DateTimeType.prototype, "maxValue", void 0);
57
57
  exports.DateTimeType = DateTimeType = tslib_1.__decorate([
58
58
  ((0, simple_type_js_1.SimpleType)({
59
+ name: 'datetime',
59
60
  description: 'A full datetime value',
60
61
  nameMappings: {
61
62
  js: 'string',
@@ -56,6 +56,7 @@ tslib_1.__decorate([
56
56
  ], DateType.prototype, "maxValue", void 0);
57
57
  exports.DateType = DateType = tslib_1.__decorate([
58
58
  ((0, simple_type_js_1.SimpleType)({
59
+ name: 'date',
59
60
  description: 'A date without time',
60
61
  nameMappings: {
61
62
  js: 'Date',
@@ -84,6 +84,7 @@ tslib_1.__decorate([
84
84
  ], EmailType.prototype, "blacklistedChars", void 0);
85
85
  exports.EmailType = EmailType = tslib_1.__decorate([
86
86
  ((0, simple_type_js_1.SimpleType)({
87
+ name: 'email',
87
88
  description: 'An email value',
88
89
  nameMappings: {
89
90
  js: 'string',
@@ -4,32 +4,35 @@ 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
- 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
+ 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
34
  return {
32
- dataType: typeName ? typeName : dataType.toJSON(),
35
+ dataType: typeName ? typeName : dataType.toJSON(options),
33
36
  allowSigns: properties.allowSigns,
34
37
  };
35
38
  }
@@ -51,6 +54,7 @@ tslib_1.__decorate([
51
54
  ], FieldPathType.prototype, "allowSigns", void 0);
52
55
  exports.FieldPathType = FieldPathType = tslib_1.__decorate([
53
56
  (0, simple_type_js_1.SimpleType)({
57
+ name: 'fieldpath',
54
58
  description: 'Field path',
55
59
  nameMappings: {
56
60
  js: 'string',
@@ -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) {
@@ -24,12 +25,17 @@ let FilterType = class FilterType {
24
25
  [constants_js_1.ENCODER]() {
25
26
  return encodeFilter;
26
27
  }
27
- toJSON(properties, element) {
28
+ toJSON(properties, element, options) {
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);
34
+ const typeName = dataType
35
+ ? element.node.getDataTypeNameWithNs(dataType)
36
+ : undefined;
31
37
  return {
32
- dataType: dataType.name ? dataType.name : dataType.toJSON(),
38
+ dataType: typeName ? typeName : dataType.toJSON(options),
33
39
  rules: properties.rules,
34
40
  };
35
41
  }
@@ -50,6 +56,7 @@ tslib_1.__decorate([
50
56
  ], FilterType.prototype, "rules", void 0);
51
57
  exports.FilterType = FilterType = tslib_1.__decorate([
52
58
  (0, simple_type_js_1.SimpleType)({
59
+ name: 'filter',
53
60
  description: 'A query filter',
54
61
  nameMappings: {
55
62
  js: 'object',
@@ -58,12 +65,12 @@ exports.FilterType = FilterType = tslib_1.__decorate([
58
65
  }),
59
66
  tslib_1.__metadata("design:paramtypes", [Object])
60
67
  ], FilterType);
61
- const decodeFilter = (dataType, rules) => (0, valgen_1.validator)('decodeFilter', (input, context, _this) => {
68
+ const decodeFilter = (dataType, rules, scope) => (0, valgen_1.validator)('decodeFilter', (input, context, _this) => {
62
69
  if (typeof input === 'string') {
63
70
  try {
64
71
  const filter = index_js_1.OpraFilter.parse(input);
65
72
  if (rules)
66
- return rules.normalizeFilter(filter, dataType);
73
+ return rules.normalizeFilter(filter, dataType, scope);
67
74
  return filter;
68
75
  }
69
76
  catch (e) {
@@ -20,6 +20,7 @@ let ObjectIdType = class ObjectIdType {
20
20
  exports.ObjectIdType = ObjectIdType;
21
21
  exports.ObjectIdType = ObjectIdType = tslib_1.__decorate([
22
22
  (0, simple_type_js_1.SimpleType)({
23
+ name: 'ObjectId',
23
24
  description: 'A MongoDB ObjectID value',
24
25
  nameMappings: {
25
26
  js: 'object',
@@ -41,6 +41,7 @@ tslib_1.__decorate([
41
41
  ], OperationResult.prototype, "errors", void 0);
42
42
  exports.OperationResult = OperationResult = tslib_1.__decorate([
43
43
  (0, complex_type_js_1.ComplexType)({
44
+ name: 'OperationResult',
44
45
  description: 'Operation result',
45
46
  }),
46
47
  tslib_1.__metadata("design:paramtypes", [Object])
@@ -42,6 +42,7 @@ tslib_1.__decorate([
42
42
  ], TimeType.prototype, "maxValue", void 0);
43
43
  exports.TimeType = TimeType = tslib_1.__decorate([
44
44
  ((0, simple_type_js_1.SimpleType)({
45
+ name: 'time',
45
46
  description: 'Time string in 24h format',
46
47
  nameMappings: {
47
48
  js: 'string',