@opra/common 1.0.0-alpha.3 → 1.0.0-alpha.31

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 (187) hide show
  1. package/browser.js +6035 -5791
  2. package/cjs/document/api-document.js +11 -0
  3. package/cjs/document/common/api-base.js +1 -1
  4. package/cjs/document/common/document-element.js +4 -1
  5. package/cjs/document/data-type/api-field.js +12 -6
  6. package/cjs/document/data-type/complex-type-base.js +10 -3
  7. package/cjs/document/data-type/complex-type.js +6 -2
  8. package/cjs/document/data-type/data-type.js +2 -1
  9. package/cjs/document/data-type/enum-type.js +5 -2
  10. package/cjs/document/data-type/extended-types/base64.type.js +4 -0
  11. package/cjs/document/data-type/extended-types/date-string.type.js +6 -2
  12. package/cjs/document/data-type/extended-types/date-time-string.type.js +6 -2
  13. package/cjs/document/data-type/extended-types/date-time.type.js +6 -2
  14. package/cjs/document/data-type/extended-types/date.type.js +6 -2
  15. package/cjs/document/data-type/extended-types/email.type.js +6 -2
  16. package/cjs/document/data-type/extended-types/field-path.type.js +5 -3
  17. package/cjs/document/data-type/extended-types/filter.type.js +19 -17
  18. package/cjs/document/data-type/extended-types/object-id.type.js +4 -0
  19. package/cjs/document/data-type/extended-types/time.type.js +6 -2
  20. package/cjs/document/data-type/extended-types/url.type.js +6 -2
  21. package/cjs/document/data-type/extended-types/uuid.type.js +4 -0
  22. package/cjs/document/data-type/mapped-type.js +12 -5
  23. package/cjs/document/data-type/mixin-type.js +5 -1
  24. package/cjs/document/data-type/omit-type.js +7 -2
  25. package/cjs/document/data-type/partial-type.js +7 -2
  26. package/cjs/document/data-type/pick-type.js +1 -2
  27. package/cjs/document/data-type/primitive-types/bigint.type.js +4 -0
  28. package/cjs/document/data-type/primitive-types/boolean.type.js +4 -0
  29. package/cjs/document/data-type/primitive-types/integer.type.js +4 -0
  30. package/cjs/document/data-type/primitive-types/null.type.js +4 -0
  31. package/cjs/document/data-type/primitive-types/number.type.js +4 -0
  32. package/cjs/document/data-type/primitive-types/object.type.js +0 -3
  33. package/cjs/document/data-type/primitive-types/string.type.js +4 -0
  34. package/cjs/document/data-type/required-type.js +1 -2
  35. package/cjs/document/data-type/simple-type.js +17 -16
  36. package/cjs/document/data-type/utils/create-mapped-class.js +3 -3
  37. package/cjs/document/data-type/utils/get-is-inherited-predicate-fn.js +1 -2
  38. package/cjs/document/decorators/api-field-decorator.js +4 -6
  39. package/cjs/document/decorators/complex-type.decorator.js +1 -2
  40. package/cjs/document/decorators/http-controller.decorator.js +26 -2
  41. package/cjs/document/decorators/http-operation-entity.decorator.js +123 -93
  42. package/cjs/document/decorators/http-operation.decorator.js +12 -6
  43. package/cjs/document/decorators/simple-type.decorator.js +2 -3
  44. package/cjs/document/factory/api-document.factory.js +14 -11
  45. package/cjs/document/factory/data-type.factory.js +97 -56
  46. package/cjs/document/factory/http-api.factory.js +3 -1
  47. package/cjs/document/http/http-api.js +2 -3
  48. package/cjs/document/http/http-controller.js +26 -14
  49. package/cjs/document/http/http-media-type.js +21 -4
  50. package/cjs/document/http/http-operation-response.js +2 -2
  51. package/cjs/document/http/http-operation.js +28 -4
  52. package/cjs/document/http/http-parameter.js +4 -0
  53. package/cjs/document/http/http-request-body.js +0 -1
  54. package/cjs/document/http/http-status-range.js +6 -4
  55. package/cjs/document/index.js +5 -5
  56. package/cjs/document/utils/parse-regexp.util.js +1 -2
  57. package/cjs/document/utils/string-compare.util.js +1 -2
  58. package/cjs/exception/index.js +5 -5
  59. package/cjs/exception/opra-exception.js +1 -0
  60. package/cjs/filter/antlr/OpraFilterParser.js +28 -82
  61. package/cjs/filter/ast/index.js +1 -1
  62. package/cjs/filter/build.js +22 -25
  63. package/cjs/filter/filter-rules.js +4 -2
  64. package/cjs/filter/opra-filter.ns.js +2 -2
  65. package/cjs/filter/parse.js +2 -5
  66. package/cjs/filter/utils.js +2 -3
  67. package/cjs/helpers/function-utils.js +1 -2
  68. package/cjs/helpers/get-stack-filename.js +2 -3
  69. package/cjs/helpers/mixin-utils.js +4 -4
  70. package/cjs/helpers/monkey-patches.js +4 -2
  71. package/cjs/helpers/object-utils.js +5 -6
  72. package/cjs/helpers/parse-fields-projection.js +4 -6
  73. package/cjs/helpers/responsive-map.js +5 -4
  74. package/cjs/helpers/type-guards.js +10 -11
  75. package/cjs/i18n/i18n.js +4 -3
  76. package/cjs/i18n/index.js +1 -1
  77. package/cjs/i18n/string-utils.js +2 -3
  78. package/cjs/i18n/translate.js +1 -2
  79. package/cjs/index.js +1 -1
  80. package/cjs/schema/type-guards.js +7 -8
  81. package/esm/document/api-document.js +11 -0
  82. package/esm/document/common/api-base.js +1 -1
  83. package/esm/document/common/document-element.js +4 -1
  84. package/esm/document/data-type/api-field.js +12 -6
  85. package/esm/document/data-type/complex-type-base.js +10 -3
  86. package/esm/document/data-type/complex-type.js +6 -2
  87. package/esm/document/data-type/data-type.js +2 -1
  88. package/esm/document/data-type/enum-type.js +5 -2
  89. package/esm/document/data-type/extended-types/base64.type.js +4 -0
  90. package/esm/document/data-type/extended-types/date-string.type.js +6 -2
  91. package/esm/document/data-type/extended-types/date-time-string.type.js +6 -2
  92. package/esm/document/data-type/extended-types/date-time.type.js +6 -2
  93. package/esm/document/data-type/extended-types/date.type.js +6 -2
  94. package/esm/document/data-type/extended-types/email.type.js +6 -2
  95. package/esm/document/data-type/extended-types/field-path.type.js +5 -3
  96. package/esm/document/data-type/extended-types/filter.type.js +19 -17
  97. package/esm/document/data-type/extended-types/object-id.type.js +4 -0
  98. package/esm/document/data-type/extended-types/time.type.js +6 -2
  99. package/esm/document/data-type/extended-types/url.type.js +6 -2
  100. package/esm/document/data-type/extended-types/uuid.type.js +4 -0
  101. package/esm/document/data-type/mapped-type.js +12 -5
  102. package/esm/document/data-type/mixin-type.js +5 -1
  103. package/esm/document/data-type/omit-type.js +6 -0
  104. package/esm/document/data-type/partial-type.js +6 -0
  105. package/esm/document/data-type/primitive-types/bigint.type.js +4 -0
  106. package/esm/document/data-type/primitive-types/boolean.type.js +4 -0
  107. package/esm/document/data-type/primitive-types/integer.type.js +4 -0
  108. package/esm/document/data-type/primitive-types/null.type.js +4 -0
  109. package/esm/document/data-type/primitive-types/number.type.js +4 -0
  110. package/esm/document/data-type/primitive-types/object.type.js +0 -3
  111. package/esm/document/data-type/primitive-types/string.type.js +4 -0
  112. package/esm/document/data-type/simple-type.js +17 -16
  113. package/esm/document/data-type/utils/create-mapped-class.js +2 -1
  114. package/esm/document/decorators/api-field-decorator.js +1 -2
  115. package/esm/document/decorators/http-controller.decorator.js +25 -0
  116. package/esm/document/decorators/http-operation-entity.decorator.js +80 -50
  117. package/esm/document/decorators/http-operation.decorator.js +11 -4
  118. package/esm/document/factory/api-document.factory.js +14 -10
  119. package/esm/document/factory/data-type.factory.js +97 -56
  120. package/esm/document/factory/http-api.factory.js +3 -1
  121. package/esm/document/http/http-api.js +2 -3
  122. package/esm/document/http/http-controller.js +25 -14
  123. package/esm/document/http/http-media-type.js +20 -4
  124. package/esm/document/http/http-operation-response.js +2 -2
  125. package/esm/document/http/http-operation.js +27 -4
  126. package/esm/document/http/http-parameter.js +4 -0
  127. package/esm/document/http/http-request-body.js +0 -1
  128. package/esm/document/http/http-status-range.js +6 -4
  129. package/esm/document/index.js +5 -5
  130. package/esm/exception/index.js +5 -5
  131. package/esm/exception/opra-exception.js +1 -0
  132. package/esm/filter/antlr/OpraFilterParser.js +28 -82
  133. package/esm/filter/ast/index.js +1 -1
  134. package/esm/filter/build.js +1 -3
  135. package/esm/filter/filter-rules.js +4 -2
  136. package/esm/filter/opra-filter.ns.js +2 -2
  137. package/esm/filter/parse.js +1 -3
  138. package/esm/helpers/mixin-utils.js +2 -1
  139. package/esm/helpers/monkey-patches.js +4 -2
  140. package/esm/helpers/object-utils.js +2 -2
  141. package/esm/helpers/parse-fields-projection.js +1 -3
  142. package/esm/helpers/responsive-map.js +5 -4
  143. package/esm/i18n/i18n.js +4 -3
  144. package/esm/i18n/index.js +1 -1
  145. package/esm/index.js +1 -1
  146. package/package.json +12 -8
  147. package/types/document/api-document.d.ts +1 -0
  148. package/types/document/common/api-base.d.ts +1 -1
  149. package/types/document/common/document-element.d.ts +1 -0
  150. package/types/document/data-type/api-field.d.ts +12 -0
  151. package/types/document/data-type/complex-type-base.d.ts +1 -1
  152. package/types/document/data-type/complex-type.d.ts +1 -1
  153. package/types/document/data-type/data-type.d.ts +5 -2
  154. package/types/document/data-type/enum-type.d.ts +2 -2
  155. package/types/document/data-type/mapped-type.d.ts +3 -3
  156. package/types/document/data-type/mixin-type.d.ts +2 -2
  157. package/types/document/data-type/omit-type.d.ts +0 -6
  158. package/types/document/data-type/partial-type.d.ts +0 -6
  159. package/types/document/data-type/pick-type.d.ts +2 -2
  160. package/types/document/data-type/required-type.d.ts +7 -7
  161. package/types/document/data-type/simple-type.d.ts +4 -2
  162. package/types/document/decorators/http-controller.decorator.d.ts +1 -0
  163. package/types/document/decorators/http-operation-entity.decorator.d.ts +1 -0
  164. package/types/document/factory/data-type.factory.d.ts +5 -0
  165. package/types/document/http/http-api.d.ts +1 -1
  166. package/types/document/http/http-controller.d.ts +1 -0
  167. package/types/document/http/http-media-type.d.ts +2 -1
  168. package/types/document/http/http-operation.d.ts +5 -3
  169. package/types/document/http/http-parameter.d.ts +3 -2
  170. package/types/document/http/http-status-range.d.ts +2 -1
  171. package/types/document/index.d.ts +5 -5
  172. package/types/exception/index.d.ts +5 -5
  173. package/types/filter/ast/index.d.ts +1 -1
  174. package/types/filter/opra-filter.ns.d.ts +2 -2
  175. package/types/helpers/type-guards.d.ts +0 -2
  176. package/types/i18n/i18n.d.ts +21 -19
  177. package/types/index.d.ts +1 -1
  178. package/types/schema/data-type/data-type.interface.d.ts +1 -1
  179. package/types/schema/data-type/mapped-type.interface.d.ts +2 -2
  180. package/types/schema/data-type/simple-type.interface.d.ts +4 -0
  181. package/types/schema/data-type-container.interface.d.ts +1 -1
  182. package/types/schema/document.interface.d.ts +1 -1
  183. package/types/schema/http/http-controller.interface.d.ts +2 -2
  184. package/types/schema/http/http-media-type.interface.d.ts +1 -1
  185. package/types/schema/http/http-operation-response.interface.d.ts +2 -2
  186. package/types/schema/http/http-operation.interface.d.ts +8 -4
  187. package/types/schema/http/http-parameter.interface.d.ts +5 -1
@@ -23,8 +23,9 @@ export function createMappedClass(source, config, options) {
23
23
  throw new TypeError(`Class "${source}" doesn't have datatype metadata information`);
24
24
  if (!(m.kind === OpraSchema.ComplexType.Kind ||
25
25
  m.kind === OpraSchema.MappedType.Kind ||
26
- m.kind === OpraSchema.MixinType.Kind))
26
+ m.kind === OpraSchema.MixinType.Kind)) {
27
27
  throw new TypeError(`Class "${source}" is not a ${OpraSchema.ComplexType.Kind}`);
28
+ }
28
29
  }
29
30
  const metadata = {
30
31
  ...options,
@@ -1,4 +1,3 @@
1
- import { omitUndefined } from '../../helpers/index.js';
2
1
  import { OpraSchema } from '../../schema/index.js';
3
2
  import { DATATYPE_METADATA } from '../constants.js';
4
3
  export function ApiFieldDecorator(options) {
@@ -17,6 +16,6 @@ export function ApiFieldDecorator(options) {
17
16
  }
18
17
  else
19
18
  elemMeta.type = elemMeta.type || designType;
20
- Reflect.defineMetadata(DATATYPE_METADATA, omitUndefined(metadata), target.constructor);
19
+ Reflect.defineMetadata(DATATYPE_METADATA, metadata, target.constructor);
21
20
  };
22
21
  }
@@ -98,6 +98,31 @@ export function HttpControllerDecoratorFactory(options) {
98
98
  });
99
99
  return decorator;
100
100
  };
101
+ /**
102
+ *
103
+ */
104
+ decorator.KeyParam = (name, arg1) => {
105
+ decoratorChain.push((meta) => {
106
+ if (!meta.path?.includes(':' + name))
107
+ meta.path = (meta.path || '') + '@:' + name;
108
+ const paramMeta = typeof arg1 === 'string' || typeof arg1 === 'function'
109
+ ? {
110
+ name,
111
+ location: 'path',
112
+ type: arg1,
113
+ keyParam: true,
114
+ }
115
+ : {
116
+ ...arg1,
117
+ name,
118
+ location: 'path',
119
+ keyParam: true,
120
+ };
121
+ meta.parameters = meta.parameters || [];
122
+ meta.parameters.push(paramMeta);
123
+ });
124
+ return decorator;
125
+ };
101
126
  /**
102
127
  *
103
128
  */
@@ -1,5 +1,4 @@
1
1
  import { FilterRules } from '../../filter/filter-rules.js';
2
- import { omitUndefined } from '../../helpers/index.js';
3
2
  import { HttpStatusCode, MimeTypes } from '../../http/index.js';
4
3
  import { DATATYPE_METADATA } from '../constants.js';
5
4
  import { FieldPathType, FilterType } from '../data-type/extended-types/index.js';
@@ -20,16 +19,16 @@ HttpOperation.Entity.Create = function (arg0, arg1) {
20
19
  args = { ...arg1, type: arg0 };
21
20
  /** Initialize the decorator and the chain */
22
21
  const decoratorChain = [];
23
- const decorator = HttpOperationDecoratorFactory(decoratorChain, omitUndefined({
24
- description: args.description,
22
+ const decorator = HttpOperationDecoratorFactory(decoratorChain, {
25
23
  method: 'POST',
24
+ ...args,
26
25
  composition: 'Entity.Create',
27
26
  requestBody: {
28
27
  immediateFetch: true,
29
28
  ...args.requestBody,
30
29
  required: true,
31
30
  },
32
- }));
31
+ });
33
32
  decorator
34
33
  .QueryParam('projection', {
35
34
  description: 'Determines fields projection',
@@ -51,8 +50,6 @@ HttpOperation.Entity.Create = function (arg0, arg1) {
51
50
  description: 'The request was well-formed but was unable to process operation due to one or many errors.',
52
51
  contentType: MimeTypes.opra_response_json,
53
52
  });
54
- if (typeof args.type === 'function')
55
- decorator.UseType(args.type);
56
53
  decoratorChain.push((operationMeta) => {
57
54
  const compositionOptions = (operationMeta.compositionOptions = operationMeta.compositionOptions || {});
58
55
  compositionOptions.type = getDataTypeName(args.type);
@@ -71,11 +68,11 @@ HttpOperation.Entity.Delete = function (arg0, arg1) {
71
68
  args = { ...arg1, type: arg0 };
72
69
  /** Initialize the decorator and the chain */
73
70
  const decoratorChain = [];
74
- const decorator = HttpOperationDecoratorFactory(decoratorChain, omitUndefined({
75
- description: args.description,
71
+ const decorator = HttpOperationDecoratorFactory(decoratorChain, {
76
72
  method: 'DELETE',
73
+ ...args,
77
74
  composition: 'Entity.Delete',
78
- }));
75
+ });
79
76
  decorator
80
77
  .Response(HttpStatusCode.OK, {
81
78
  description: 'Operation is successful. Returns OperationResult with "affected" field.',
@@ -85,17 +82,28 @@ HttpOperation.Entity.Delete = function (arg0, arg1) {
85
82
  description: 'The request was well-formed but was unable to process operation due to one or many errors.',
86
83
  contentType: MimeTypes.opra_response_json,
87
84
  });
88
- if (typeof args.type === 'function')
89
- decorator.UseType(args.type);
90
85
  /**
91
86
  *
92
87
  */
93
88
  decorator.KeyParam = (name, prmOptions) => {
94
- decorator.PathParam(name, prmOptions);
89
+ const paramMeta = typeof prmOptions === 'string' || typeof prmOptions === 'function'
90
+ ? {
91
+ name,
92
+ location: 'path',
93
+ type: prmOptions,
94
+ keyParam: true,
95
+ }
96
+ : {
97
+ ...prmOptions,
98
+ name,
99
+ location: 'path',
100
+ keyParam: true,
101
+ };
102
+ decorator.PathParam(name, paramMeta);
95
103
  decoratorChain.push((meta) => {
96
- meta.path = (meta.path || '') + '@:' + name;
97
- meta.compositionOptions = meta.compositionOptions || {};
98
- meta.compositionOptions.keyParameter = name;
104
+ if (!meta.path?.includes(':' + name))
105
+ meta.path = (meta.path || '') + '@:' + name;
106
+ meta.mergePath = true;
99
107
  });
100
108
  return decorator;
101
109
  };
@@ -120,11 +128,11 @@ HttpOperation.Entity.DeleteMany = function (arg0, arg1) {
120
128
  const filterRules = new FilterRules();
121
129
  const filterType = new FilterType({ dataType: args.type });
122
130
  filterType.rules = {};
123
- const decorator = HttpOperationDecoratorFactory(decoratorChain, omitUndefined({
124
- description: args.description,
131
+ const decorator = HttpOperationDecoratorFactory(decoratorChain, {
125
132
  method: 'DELETE',
133
+ ...args,
126
134
  composition: 'Entity.DeleteMany',
127
- }));
135
+ });
128
136
  decorator
129
137
  .Response(HttpStatusCode.OK, {
130
138
  description: 'Operation is successful. Returns OperationResult with "affected" field.',
@@ -138,8 +146,6 @@ HttpOperation.Entity.DeleteMany = function (arg0, arg1) {
138
146
  type: filterType,
139
147
  description: 'Determines filter fields',
140
148
  });
141
- if (typeof args.type === 'function')
142
- decorator.UseType(args.type);
143
149
  decoratorChain.push((operationMeta) => {
144
150
  const compositionOptions = (operationMeta.compositionOptions = operationMeta.compositionOptions || {});
145
151
  compositionOptions.type = getDataTypeName(args.type);
@@ -168,11 +174,11 @@ HttpOperation.Entity.FindMany = function (arg0, arg1) {
168
174
  const filterRules = new FilterRules();
169
175
  const filterType = new FilterType({ dataType: args.type });
170
176
  filterType.rules = {};
171
- const decorator = HttpOperationDecoratorFactory(decoratorChain, omitUndefined({
172
- description: args.description,
177
+ const decorator = HttpOperationDecoratorFactory(decoratorChain, {
173
178
  method: 'GET',
179
+ ...args,
174
180
  composition: 'Entity.FindMany',
175
- }));
181
+ });
176
182
  decorator
177
183
  .Response(HttpStatusCode.OK, {
178
184
  description: 'Operation is successful. Returns OperationResult with "payload" field that contains list of resources.',
@@ -187,7 +193,7 @@ HttpOperation.Entity.FindMany = function (arg0, arg1) {
187
193
  })
188
194
  .QueryParam('limit', {
189
195
  description: 'Determines number of returning instances',
190
- type: new IntegerType({ minValue: 1 }),
196
+ type: new IntegerType({ minValue: 1, maxValue: args.maxLimit }),
191
197
  })
192
198
  .QueryParam('skip', {
193
199
  description: 'Determines number of returning instances',
@@ -219,11 +225,15 @@ HttpOperation.Entity.FindMany = function (arg0, arg1) {
219
225
  isArray: true,
220
226
  arraySeparator: ',',
221
227
  });
222
- if (typeof args.type === 'function')
223
- decorator.UseType(args.type);
224
228
  decoratorChain.push((operationMeta) => {
225
229
  const compositionOptions = (operationMeta.compositionOptions = operationMeta.compositionOptions || {});
226
230
  compositionOptions.type = getDataTypeName(args.type);
231
+ if (args.defaultLimit)
232
+ compositionOptions.defaultLimit = args.defaultLimit;
233
+ if (args.defaultProjection)
234
+ compositionOptions.defaultProjection = args.defaultProjection;
235
+ if (args.maxLimit)
236
+ compositionOptions.maxLimit = args.maxLimit;
227
237
  });
228
238
  decorator.DefaultSort = (...fields) => {
229
239
  decoratorChain.push((operationMeta) => {
@@ -260,11 +270,11 @@ HttpOperation.Entity.Get = function (arg0, arg1) {
260
270
  args = { ...arg1, type: arg0 };
261
271
  /** Initialize the decorator and the chain */
262
272
  const decoratorChain = [];
263
- const decorator = HttpOperationDecoratorFactory(decoratorChain, omitUndefined({
264
- description: args.description,
273
+ const decorator = HttpOperationDecoratorFactory(decoratorChain, {
265
274
  method: 'GET',
275
+ ...args,
266
276
  composition: 'Entity.Get',
267
- }));
277
+ });
268
278
  decorator
269
279
  .QueryParam('projection', {
270
280
  description: 'Determines fields projection',
@@ -288,17 +298,28 @@ HttpOperation.Entity.Get = function (arg0, arg1) {
288
298
  description: 'The request was well-formed but was unable to process operation due to one or many errors.',
289
299
  contentType: MimeTypes.opra_response_json,
290
300
  });
291
- if (typeof args.type === 'function')
292
- decorator.UseType(args.type);
293
301
  /**
294
302
  *
295
303
  */
296
304
  decorator.KeyParam = (name, prmOptions) => {
297
- decorator.PathParam(name, prmOptions);
305
+ const paramMeta = typeof prmOptions === 'string' || typeof prmOptions === 'function'
306
+ ? {
307
+ name,
308
+ location: 'path',
309
+ type: prmOptions,
310
+ keyParam: true,
311
+ }
312
+ : {
313
+ ...prmOptions,
314
+ name,
315
+ location: 'path',
316
+ keyParam: true,
317
+ };
318
+ decorator.PathParam(name, paramMeta);
298
319
  decoratorChain.push((meta) => {
299
- meta.path = (meta.path || '') + '@:' + name;
300
- meta.compositionOptions = meta.compositionOptions || {};
301
- meta.compositionOptions.keyParameter = name;
320
+ if (!meta.path?.includes(':' + name))
321
+ meta.path = (meta.path || '') + '@:' + name;
322
+ meta.mergePath = true;
302
323
  });
303
324
  return decorator;
304
325
  };
@@ -323,9 +344,9 @@ HttpOperation.Entity.UpdateMany = function (arg0, arg1) {
323
344
  const filterType = new FilterType({ dataType: args.type });
324
345
  filterType.rules = {};
325
346
  const filterRules = new FilterRules();
326
- const decorator = HttpOperationDecoratorFactory(decoratorChain, omitUndefined({
327
- description: args.description,
347
+ const decorator = HttpOperationDecoratorFactory(decoratorChain, {
328
348
  method: 'PATCH',
349
+ ...args,
329
350
  composition: 'Entity.UpdateMany',
330
351
  requestBody: {
331
352
  immediateFetch: true,
@@ -333,11 +354,9 @@ HttpOperation.Entity.UpdateMany = function (arg0, arg1) {
333
354
  ...args.requestBody,
334
355
  required: true,
335
356
  },
336
- }));
337
- decorator.RequestContent(args.requestBody?.type || args.type);
338
- if (typeof args.type === 'function')
339
- decorator.UseType(args.type);
357
+ });
340
358
  decorator
359
+ .RequestContent(args.requestBody?.type || args.type)
341
360
  .Response(HttpStatusCode.OK, {
342
361
  description: 'Operation is successful. Returns OperationResult with "affected" field.',
343
362
  contentType: MimeTypes.opra_response_json,
@@ -378,9 +397,9 @@ HttpOperation.Entity.Update = function (arg0, arg1) {
378
397
  const filterRules = new FilterRules();
379
398
  const filterType = new FilterType({ dataType: args.type });
380
399
  filterType.rules = {};
381
- const decorator = HttpOperationDecoratorFactory(decoratorChain, omitUndefined({
382
- description: args.description,
400
+ const decorator = HttpOperationDecoratorFactory(decoratorChain, {
383
401
  method: 'PATCH',
402
+ ...args,
384
403
  composition: 'Entity.Update',
385
404
  requestBody: {
386
405
  partial: 'deep',
@@ -388,7 +407,7 @@ HttpOperation.Entity.Update = function (arg0, arg1) {
388
407
  ...args.requestBody,
389
408
  required: true,
390
409
  },
391
- }));
410
+ });
392
411
  decorator
393
412
  .QueryParam('projection', {
394
413
  description: 'Determines fields projection',
@@ -417,17 +436,28 @@ HttpOperation.Entity.Update = function (arg0, arg1) {
417
436
  description: 'The request was well-formed but was unable to process operation due to one or many errors.',
418
437
  contentType: MimeTypes.opra_response_json,
419
438
  });
420
- if (typeof args.type === 'function')
421
- decorator.UseType(args.type);
422
439
  /**
423
440
  *
424
441
  */
425
442
  decorator.KeyParam = (name, prmOptions) => {
426
- decorator.PathParam(name, prmOptions);
443
+ const paramMeta = typeof prmOptions === 'string' || typeof prmOptions === 'function'
444
+ ? {
445
+ name,
446
+ location: 'path',
447
+ type: prmOptions,
448
+ keyParam: true,
449
+ }
450
+ : {
451
+ ...prmOptions,
452
+ name,
453
+ location: 'path',
454
+ keyParam: true,
455
+ };
456
+ decorator.PathParam(name, paramMeta);
427
457
  decoratorChain.push((meta) => {
428
- meta.path = (meta.path || '') + '@:' + name;
429
- meta.compositionOptions = meta.compositionOptions || {};
430
- meta.compositionOptions.keyParameter = name;
458
+ if (!meta.path?.includes(':' + name))
459
+ meta.path = (meta.path || '') + '@:' + name;
460
+ meta.mergePath = true;
431
461
  });
432
462
  return decorator;
433
463
  };
@@ -33,8 +33,9 @@ export function HttpOperationDecoratorFactory(decoratorChain, options) {
33
33
  type: arg1,
34
34
  }
35
35
  : { ...arg1, name, location: 'cookie' };
36
- if (meta.parameters)
36
+ if (meta.parameters) {
37
37
  meta.parameters = meta.parameters.filter(p => !(p.location === 'cookie' && String(p.name) === String(name)));
38
+ }
38
39
  else
39
40
  meta.parameters = [];
40
41
  meta.parameters.push(paramMeta);
@@ -53,8 +54,9 @@ export function HttpOperationDecoratorFactory(decoratorChain, options) {
53
54
  type: arg1,
54
55
  }
55
56
  : { ...arg1, name, location: 'header' };
56
- if (meta.parameters)
57
+ if (meta.parameters) {
57
58
  meta.parameters = meta.parameters.filter(p => !(p.location === 'header' && String(p.name) === String(name)));
59
+ }
58
60
  else
59
61
  meta.parameters = [];
60
62
  meta.parameters.push(paramMeta);
@@ -73,8 +75,9 @@ export function HttpOperationDecoratorFactory(decoratorChain, options) {
73
75
  type: arg1,
74
76
  }
75
77
  : { ...arg1, name, location: 'query' };
76
- if (meta.parameters)
78
+ if (meta.parameters) {
77
79
  meta.parameters = meta.parameters.filter(p => !(p.location === 'query' && String(p.name) === String(name)));
80
+ }
78
81
  else
79
82
  meta.parameters = [];
80
83
  meta.parameters.push(paramMeta);
@@ -93,8 +96,9 @@ export function HttpOperationDecoratorFactory(decoratorChain, options) {
93
96
  type: arg1,
94
97
  }
95
98
  : { ...arg1, name, location: 'path' };
96
- if (meta.parameters)
99
+ if (meta.parameters) {
97
100
  meta.parameters = meta.parameters.filter(p => !(p.location === 'path' && String(p.name) === String(name)));
101
+ }
98
102
  else
99
103
  meta.parameters = [];
100
104
  meta.parameters.push(paramMeta);
@@ -110,6 +114,9 @@ export function HttpOperationDecoratorFactory(decoratorChain, options) {
110
114
  responseMeta.contentType = responseMeta.contentType || MimeTypes.opra_response_json;
111
115
  responseMeta.contentEncoding = responseMeta.contentEncoding || 'utf-8';
112
116
  }
117
+ if (responseMeta.contentType === MimeTypes.opra_response_json) {
118
+ responseMeta.contentEncoding = responseMeta.contentEncoding || 'utf-8';
119
+ }
113
120
  decoratorChain.push((meta) => {
114
121
  meta.responses = meta.responses || [];
115
122
  meta.responses.push(responseMeta);
@@ -1,5 +1,3 @@
1
- import crypto from 'node:crypto';
2
- import { asMutable } from 'ts-gems';
3
1
  import { resolveThunk } from '../../helpers/index.js';
4
2
  import { OpraSchema } from '../../schema/index.js';
5
3
  import { ApiDocument } from '../api-document.js';
@@ -42,9 +40,7 @@ export class ApiDocumentFactory {
42
40
  context.error.message = `(${l}) error${l > 1 ? 's' : ''} found in document schema.`;
43
41
  if (context.showErrorDetails) {
44
42
  context.error.message += context.error.details
45
- .map(d => {
46
- return `\n\n - ${d.message}` + (d.path ? `\n @${d.path}` : '');
47
- })
43
+ .map(d => `\n\n - ${d.message}` + (d.path ? `\n @${d.path}` : ''))
48
44
  .join('');
49
45
  }
50
46
  }
@@ -66,9 +62,14 @@ export class ApiDocumentFactory {
66
62
  else
67
63
  init = schemaOrUrl;
68
64
  // Add builtin data types if this document is the root
65
+ let builtinDocument;
69
66
  if (!document[BUILTIN]) {
70
- const builtinDocument = await this.createBuiltinDocument(context);
71
- document.references.set('opra', builtinDocument);
67
+ const t = document.node.findDataType('string');
68
+ builtinDocument = t?.node.getDocument();
69
+ if (!builtinDocument) {
70
+ builtinDocument = await this.createBuiltinDocument(context);
71
+ document.references.set('opra', builtinDocument);
72
+ }
72
73
  }
73
74
  init.spec = init.spec || OpraSchema.SpecVersion;
74
75
  document.url = init.url;
@@ -89,8 +90,12 @@ export class ApiDocumentFactory {
89
90
  return;
90
91
  }
91
92
  const refDoc = new ApiDocument();
93
+ if (builtinDocument)
94
+ refDoc.references.set('opra', builtinDocument);
92
95
  await this.initDocument(refDoc, context, r);
93
- document.references.set(ns, refDoc);
96
+ /** If same document already exists in document tree, we use it except the new one */
97
+ const preDoc = document.findDocument(refDoc.id);
98
+ document.references.set(ns, preDoc || refDoc);
94
99
  });
95
100
  }
96
101
  });
@@ -111,8 +116,7 @@ export class ApiDocumentFactory {
111
116
  context.addError(`Unknown service protocol (${init.api.protocol})`);
112
117
  });
113
118
  }
114
- const x = document.export();
115
- asMutable(document).id = crypto.createHash('md5').update(JSON.stringify(x)).digest('base64url');
119
+ document.invalidate();
116
120
  }
117
121
  /**
118
122
  *