@opra/common 1.0.0-alpha.9 → 1.0.0-beta.2

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 (199) hide show
  1. package/browser/index.cjs +12 -0
  2. package/browser/index.mjs +12 -0
  3. package/cjs/document/api-document.js +11 -0
  4. package/cjs/document/common/api-base.js +1 -1
  5. package/cjs/document/common/document-element.js +2 -0
  6. package/cjs/document/data-type/api-field.js +8 -7
  7. package/cjs/document/data-type/complex-type-base.js +5 -3
  8. package/cjs/document/data-type/extended-types/date-string.type.js +2 -2
  9. package/cjs/document/data-type/extended-types/date-time-string.type.js +2 -2
  10. package/cjs/document/data-type/extended-types/date-time.type.js +2 -2
  11. package/cjs/document/data-type/extended-types/date.type.js +2 -2
  12. package/cjs/document/data-type/extended-types/email.type.js +2 -2
  13. package/cjs/document/data-type/extended-types/filter.type.js +1 -1
  14. package/cjs/document/data-type/extended-types/time.type.js +2 -2
  15. package/cjs/document/data-type/extended-types/url.type.js +2 -2
  16. package/cjs/document/data-type/omit-type.js +7 -2
  17. package/cjs/document/data-type/partial-type.js +7 -2
  18. package/cjs/document/data-type/pick-type.js +1 -2
  19. package/cjs/document/data-type/primitive-types/object.type.js +0 -3
  20. package/cjs/document/data-type/required-type.js +1 -2
  21. package/cjs/document/data-type/simple-type.js +1 -6
  22. package/cjs/document/data-type/utils/create-mapped-class.js +1 -2
  23. package/cjs/document/data-type/utils/get-is-inherited-predicate-fn.js +1 -2
  24. package/cjs/document/decorators/api-field-decorator.js +4 -6
  25. package/cjs/document/decorators/complex-type.decorator.js +1 -2
  26. package/cjs/document/decorators/http-controller.decorator.js +2 -3
  27. package/cjs/document/decorators/http-operation-entity.decorator.js +68 -74
  28. package/cjs/document/decorators/http-operation.decorator.js +4 -2
  29. package/cjs/document/decorators/simple-type.decorator.js +2 -3
  30. package/cjs/document/factory/api-document.factory.js +17 -8
  31. package/cjs/document/http/http-api.js +0 -1
  32. package/cjs/document/http/http-controller.js +4 -2
  33. package/cjs/document/http/http-media-type.js +17 -2
  34. package/cjs/document/http/http-multipart-field.js +0 -1
  35. package/cjs/document/http/http-operation-response.js +0 -1
  36. package/cjs/document/http/http-operation.js +12 -1
  37. package/cjs/document/http/http-parameter.js +2 -0
  38. package/cjs/document/http/http-request-body.js +0 -1
  39. package/cjs/document/http/http-status-range.js +5 -2
  40. package/cjs/document/utils/parse-regexp.util.js +1 -2
  41. package/cjs/document/utils/string-compare.util.js +1 -2
  42. package/cjs/exception/opra-exception.js +1 -0
  43. package/cjs/filter/build.js +21 -22
  44. package/cjs/filter/filter-rules.js +17 -16
  45. package/cjs/filter/parse.js +1 -2
  46. package/cjs/filter/utils.js +2 -3
  47. package/cjs/helpers/function-utils.js +1 -2
  48. package/cjs/helpers/get-stack-filename.js +2 -3
  49. package/cjs/helpers/index.js +1 -0
  50. package/cjs/helpers/mixin-utils.js +2 -3
  51. package/cjs/helpers/object-utils.js +5 -6
  52. package/cjs/helpers/parse-fields-projection.js +3 -3
  53. package/cjs/helpers/safe-json-stringify.js +16 -0
  54. package/cjs/helpers/type-guards.js +10 -11
  55. package/cjs/i18n/string-utils.js +2 -3
  56. package/cjs/i18n/translate.js +1 -2
  57. package/cjs/schema/index.js +2 -27
  58. package/cjs/schema/opra-schema.js +24 -0
  59. package/cjs/schema/type-guards.js +7 -8
  60. package/esm/document/api-document.js +11 -0
  61. package/esm/document/common/api-base.js +1 -1
  62. package/esm/document/common/document-element.js +2 -0
  63. package/esm/document/data-type/api-field.js +8 -7
  64. package/esm/document/data-type/complex-type-base.js +5 -3
  65. package/esm/document/data-type/extended-types/date-string.type.js +2 -2
  66. package/esm/document/data-type/extended-types/date-time-string.type.js +2 -2
  67. package/esm/document/data-type/extended-types/date-time.type.js +2 -2
  68. package/esm/document/data-type/extended-types/date.type.js +2 -2
  69. package/esm/document/data-type/extended-types/email.type.js +2 -2
  70. package/esm/document/data-type/extended-types/filter.type.js +1 -1
  71. package/esm/document/data-type/extended-types/time.type.js +2 -2
  72. package/esm/document/data-type/extended-types/url.type.js +2 -2
  73. package/esm/document/data-type/omit-type.js +6 -0
  74. package/esm/document/data-type/partial-type.js +6 -0
  75. package/esm/document/data-type/primitive-types/object.type.js +0 -3
  76. package/esm/document/data-type/simple-type.js +1 -6
  77. package/esm/document/decorators/api-field-decorator.js +1 -2
  78. package/esm/document/decorators/http-controller.decorator.js +1 -1
  79. package/esm/document/decorators/http-operation-entity.decorator.js +25 -31
  80. package/esm/document/decorators/http-operation.decorator.js +3 -0
  81. package/esm/document/factory/api-document.factory.js +17 -7
  82. package/esm/document/http/http-api.js +0 -1
  83. package/esm/document/http/http-controller.js +3 -2
  84. package/esm/document/http/http-media-type.js +16 -2
  85. package/esm/document/http/http-multipart-field.js +0 -1
  86. package/esm/document/http/http-operation-response.js +0 -1
  87. package/esm/document/http/http-operation.js +12 -1
  88. package/esm/document/http/http-parameter.js +2 -0
  89. package/esm/document/http/http-request-body.js +0 -1
  90. package/esm/document/http/http-status-range.js +5 -2
  91. package/esm/exception/opra-exception.js +1 -0
  92. package/esm/filter/filter-rules.js +10 -9
  93. package/esm/helpers/index.js +1 -0
  94. package/esm/helpers/object-utils.js +2 -2
  95. package/esm/helpers/safe-json-stringify.js +13 -0
  96. package/esm/package.json +3 -0
  97. package/esm/schema/index.js +2 -27
  98. package/esm/schema/opra-schema.js +21 -0
  99. package/package.json +47 -53
  100. package/types/document/api-document.d.ts +2 -1
  101. package/types/document/common/api-base.d.ts +2 -2
  102. package/types/document/common/data-type-map.d.ts +1 -1
  103. package/types/document/common/document-element.d.ts +1 -0
  104. package/types/document/common/document-node.d.ts +8 -8
  105. package/types/document/common/value.d.ts +1 -1
  106. package/types/document/data-type/api-field.d.ts +11 -1
  107. package/types/document/data-type/complex-type-base.d.ts +6 -7
  108. package/types/document/data-type/complex-type.d.ts +1 -1
  109. package/types/document/data-type/data-type.d.ts +3 -2
  110. package/types/document/data-type/enum-type.d.ts +2 -2
  111. package/types/document/data-type/extended-types/base64.type.d.ts +1 -1
  112. package/types/document/data-type/extended-types/date-string.type.d.ts +1 -1
  113. package/types/document/data-type/extended-types/date-time-string.type.d.ts +1 -1
  114. package/types/document/data-type/extended-types/date-time.type.d.ts +1 -1
  115. package/types/document/data-type/extended-types/date.type.d.ts +1 -1
  116. package/types/document/data-type/extended-types/email.type.d.ts +1 -1
  117. package/types/document/data-type/extended-types/field-path.type.d.ts +3 -3
  118. package/types/document/data-type/extended-types/filter.type.d.ts +3 -3
  119. package/types/document/data-type/extended-types/object-id.type.d.ts +1 -1
  120. package/types/document/data-type/extended-types/operation-result.type.d.ts +2 -2
  121. package/types/document/data-type/extended-types/time.type.d.ts +1 -1
  122. package/types/document/data-type/extended-types/url.type.d.ts +1 -1
  123. package/types/document/data-type/extended-types/uuid.type.d.ts +1 -1
  124. package/types/document/data-type/mapped-type.d.ts +3 -3
  125. package/types/document/data-type/mixin-type.d.ts +1 -1
  126. package/types/document/data-type/omit-type.d.ts +1 -7
  127. package/types/document/data-type/partial-type.d.ts +1 -7
  128. package/types/document/data-type/pick-type.d.ts +3 -3
  129. package/types/document/data-type/primitive-types/any.type.d.ts +1 -1
  130. package/types/document/data-type/primitive-types/bigint.type.d.ts +1 -1
  131. package/types/document/data-type/primitive-types/boolean.type.d.ts +1 -1
  132. package/types/document/data-type/primitive-types/integer.type.d.ts +1 -1
  133. package/types/document/data-type/primitive-types/null.type.d.ts +1 -1
  134. package/types/document/data-type/primitive-types/number.type.d.ts +1 -1
  135. package/types/document/data-type/primitive-types/string.type.d.ts +1 -1
  136. package/types/document/data-type/required-type.d.ts +8 -8
  137. package/types/document/data-type/simple-type.d.ts +2 -2
  138. package/types/document/data-type/utils/create-mapped-class.d.ts +2 -2
  139. package/types/document/decorators/api-field-decorator.d.ts +1 -1
  140. package/types/document/decorators/http-controller.decorator.d.ts +3 -3
  141. package/types/document/decorators/http-operation-entity.decorator.d.ts +5 -4
  142. package/types/document/decorators/http-operation.decorator.d.ts +1 -1
  143. package/types/document/factory/api-document.factory.d.ts +2 -1
  144. package/types/document/factory/data-type.factory.d.ts +1 -1
  145. package/types/document/factory/http-api.factory.d.ts +1 -1
  146. package/types/document/http/http-api.d.ts +2 -2
  147. package/types/document/http/http-controller.d.ts +1 -1
  148. package/types/document/http/http-media-type.d.ts +3 -2
  149. package/types/document/http/http-multipart-field.d.ts +1 -2
  150. package/types/document/http/http-operation-response.d.ts +1 -1
  151. package/types/document/http/http-operation.d.ts +6 -5
  152. package/types/document/http/http-parameter.d.ts +2 -2
  153. package/types/document/http/http-request-body.d.ts +1 -1
  154. package/types/document/http/http-status-range.d.ts +2 -1
  155. package/types/exception/http-errors/bad-request.error.d.ts +1 -1
  156. package/types/exception/http-errors/conflict.error.d.ts +1 -1
  157. package/types/exception/http-errors/failed-dependency.error.d.ts +1 -1
  158. package/types/exception/http-errors/forbidden.error.d.ts +1 -1
  159. package/types/exception/http-errors/internal-server.error.d.ts +1 -1
  160. package/types/exception/http-errors/method-not-allowed.error.d.ts +1 -1
  161. package/types/exception/http-errors/not-acceptable.error.d.ts +1 -1
  162. package/types/exception/http-errors/not-found.error.d.ts +1 -1
  163. package/types/exception/http-errors/permission.error.d.ts +1 -1
  164. package/types/exception/http-errors/unauthorized.error.d.ts +1 -1
  165. package/types/exception/http-errors/unprocessable-entity.error.d.ts +1 -1
  166. package/types/exception/opra-exception.d.ts +1 -1
  167. package/types/exception/opra-http-error.d.ts +1 -1
  168. package/types/filter/antlr/OpraFilterParser.d.ts +1 -1
  169. package/types/filter/ast/expressions/comparison-expression.d.ts +1 -1
  170. package/types/filter/errors.d.ts +3 -4
  171. package/types/filter/filter-rules.d.ts +5 -5
  172. package/types/filter/opra-error-listener.d.ts +1 -2
  173. package/types/helpers/function-utils.d.ts +1 -1
  174. package/types/helpers/index.d.ts +1 -0
  175. package/types/helpers/mixin-utils.d.ts +1 -1
  176. package/types/helpers/object-utils.d.ts +1 -1
  177. package/types/helpers/safe-json-stringify.d.ts +1 -0
  178. package/types/helpers/type-guards.d.ts +1 -3
  179. package/types/i18n/i18n.d.ts +2 -2
  180. package/types/i18n/translate.d.ts +1 -1
  181. package/types/index.d.cts +9 -0
  182. package/types/schema/{document.interface.d.ts → api-document.interface.d.ts} +4 -4
  183. package/types/schema/data-type/complex-type.interface.d.ts +1 -1
  184. package/types/schema/data-type/data-type.interface.d.ts +1 -1
  185. package/types/schema/data-type/enum-type.interface.d.ts +1 -1
  186. package/types/schema/data-type/mapped-type.interface.d.ts +3 -3
  187. package/types/schema/data-type/mixin-type.interface.d.ts +1 -1
  188. package/types/schema/data-type-container.interface.d.ts +1 -1
  189. package/types/schema/http/http-controller.interface.d.ts +2 -2
  190. package/types/schema/http/http-media-type.interface.d.ts +1 -1
  191. package/types/schema/http/http-operation-response.interface.d.ts +2 -2
  192. package/types/schema/http/http-operation.interface.d.ts +8 -4
  193. package/types/schema/http/http-parameter.interface.d.ts +2 -2
  194. package/types/schema/index.d.ts +2 -62
  195. package/types/schema/opra-schema.d.ts +21 -0
  196. package/types/schema/type-guards.d.ts +1 -1
  197. package/browser.js +0 -13393
  198. /package/cjs/schema/{document.interface.js → api-document.interface.js} +0 -0
  199. /package/esm/schema/{document.interface.js → api-document.interface.js} +0 -0
@@ -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,7 +19,7 @@ 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({
22
+ const decorator = HttpOperationDecoratorFactory(decoratorChain, {
24
23
  method: 'POST',
25
24
  ...args,
26
25
  composition: 'Entity.Create',
@@ -29,7 +28,7 @@ HttpOperation.Entity.Create = function (arg0, arg1) {
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({
71
+ const decorator = HttpOperationDecoratorFactory(decoratorChain, {
75
72
  method: 'DELETE',
76
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,8 +82,6 @@ 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
  */
@@ -108,6 +103,7 @@ HttpOperation.Entity.Delete = function (arg0, arg1) {
108
103
  decoratorChain.push((meta) => {
109
104
  if (!meta.path?.includes(':' + name))
110
105
  meta.path = (meta.path || '') + '@:' + name;
106
+ meta.mergePath = true;
111
107
  });
112
108
  return decorator;
113
109
  };
@@ -132,11 +128,11 @@ HttpOperation.Entity.DeleteMany = function (arg0, arg1) {
132
128
  const filterRules = new FilterRules();
133
129
  const filterType = new FilterType({ dataType: args.type });
134
130
  filterType.rules = {};
135
- const decorator = HttpOperationDecoratorFactory(decoratorChain, omitUndefined({
131
+ const decorator = HttpOperationDecoratorFactory(decoratorChain, {
136
132
  method: 'DELETE',
137
133
  ...args,
138
134
  composition: 'Entity.DeleteMany',
139
- }));
135
+ });
140
136
  decorator
141
137
  .Response(HttpStatusCode.OK, {
142
138
  description: 'Operation is successful. Returns OperationResult with "affected" field.',
@@ -150,8 +146,6 @@ HttpOperation.Entity.DeleteMany = function (arg0, arg1) {
150
146
  type: filterType,
151
147
  description: 'Determines filter fields',
152
148
  });
153
- if (typeof args.type === 'function')
154
- decorator.UseType(args.type);
155
149
  decoratorChain.push((operationMeta) => {
156
150
  const compositionOptions = (operationMeta.compositionOptions = operationMeta.compositionOptions || {});
157
151
  compositionOptions.type = getDataTypeName(args.type);
@@ -180,11 +174,11 @@ HttpOperation.Entity.FindMany = function (arg0, arg1) {
180
174
  const filterRules = new FilterRules();
181
175
  const filterType = new FilterType({ dataType: args.type });
182
176
  filterType.rules = {};
183
- const decorator = HttpOperationDecoratorFactory(decoratorChain, omitUndefined({
177
+ const decorator = HttpOperationDecoratorFactory(decoratorChain, {
184
178
  method: 'GET',
185
179
  ...args,
186
180
  composition: 'Entity.FindMany',
187
- }));
181
+ });
188
182
  decorator
189
183
  .Response(HttpStatusCode.OK, {
190
184
  description: 'Operation is successful. Returns OperationResult with "payload" field that contains list of resources.',
@@ -199,7 +193,7 @@ HttpOperation.Entity.FindMany = function (arg0, arg1) {
199
193
  })
200
194
  .QueryParam('limit', {
201
195
  description: 'Determines number of returning instances',
202
- type: new IntegerType({ minValue: 1 }),
196
+ type: new IntegerType({ minValue: 1, maxValue: args.maxLimit }),
203
197
  })
204
198
  .QueryParam('skip', {
205
199
  description: 'Determines number of returning instances',
@@ -231,11 +225,15 @@ HttpOperation.Entity.FindMany = function (arg0, arg1) {
231
225
  isArray: true,
232
226
  arraySeparator: ',',
233
227
  });
234
- if (typeof args.type === 'function')
235
- decorator.UseType(args.type);
236
228
  decoratorChain.push((operationMeta) => {
237
229
  const compositionOptions = (operationMeta.compositionOptions = operationMeta.compositionOptions || {});
238
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;
239
237
  });
240
238
  decorator.DefaultSort = (...fields) => {
241
239
  decoratorChain.push((operationMeta) => {
@@ -272,11 +270,11 @@ HttpOperation.Entity.Get = function (arg0, arg1) {
272
270
  args = { ...arg1, type: arg0 };
273
271
  /** Initialize the decorator and the chain */
274
272
  const decoratorChain = [];
275
- const decorator = HttpOperationDecoratorFactory(decoratorChain, omitUndefined({
273
+ const decorator = HttpOperationDecoratorFactory(decoratorChain, {
276
274
  method: 'GET',
277
275
  ...args,
278
276
  composition: 'Entity.Get',
279
- }));
277
+ });
280
278
  decorator
281
279
  .QueryParam('projection', {
282
280
  description: 'Determines fields projection',
@@ -300,8 +298,6 @@ HttpOperation.Entity.Get = function (arg0, arg1) {
300
298
  description: 'The request was well-formed but was unable to process operation due to one or many errors.',
301
299
  contentType: MimeTypes.opra_response_json,
302
300
  });
303
- if (typeof args.type === 'function')
304
- decorator.UseType(args.type);
305
301
  /**
306
302
  *
307
303
  */
@@ -323,6 +319,7 @@ HttpOperation.Entity.Get = function (arg0, arg1) {
323
319
  decoratorChain.push((meta) => {
324
320
  if (!meta.path?.includes(':' + name))
325
321
  meta.path = (meta.path || '') + '@:' + name;
322
+ meta.mergePath = true;
326
323
  });
327
324
  return decorator;
328
325
  };
@@ -347,7 +344,7 @@ HttpOperation.Entity.UpdateMany = function (arg0, arg1) {
347
344
  const filterType = new FilterType({ dataType: args.type });
348
345
  filterType.rules = {};
349
346
  const filterRules = new FilterRules();
350
- const decorator = HttpOperationDecoratorFactory(decoratorChain, omitUndefined({
347
+ const decorator = HttpOperationDecoratorFactory(decoratorChain, {
351
348
  method: 'PATCH',
352
349
  ...args,
353
350
  composition: 'Entity.UpdateMany',
@@ -357,11 +354,9 @@ HttpOperation.Entity.UpdateMany = function (arg0, arg1) {
357
354
  ...args.requestBody,
358
355
  required: true,
359
356
  },
360
- }));
361
- decorator.RequestContent(args.requestBody?.type || args.type);
362
- if (typeof args.type === 'function')
363
- decorator.UseType(args.type);
357
+ });
364
358
  decorator
359
+ .RequestContent(args.requestBody?.type || args.type)
365
360
  .Response(HttpStatusCode.OK, {
366
361
  description: 'Operation is successful. Returns OperationResult with "affected" field.',
367
362
  contentType: MimeTypes.opra_response_json,
@@ -402,7 +397,7 @@ HttpOperation.Entity.Update = function (arg0, arg1) {
402
397
  const filterRules = new FilterRules();
403
398
  const filterType = new FilterType({ dataType: args.type });
404
399
  filterType.rules = {};
405
- const decorator = HttpOperationDecoratorFactory(decoratorChain, omitUndefined({
400
+ const decorator = HttpOperationDecoratorFactory(decoratorChain, {
406
401
  method: 'PATCH',
407
402
  ...args,
408
403
  composition: 'Entity.Update',
@@ -412,7 +407,7 @@ HttpOperation.Entity.Update = function (arg0, arg1) {
412
407
  ...args.requestBody,
413
408
  required: true,
414
409
  },
415
- }));
410
+ });
416
411
  decorator
417
412
  .QueryParam('projection', {
418
413
  description: 'Determines fields projection',
@@ -441,8 +436,6 @@ HttpOperation.Entity.Update = function (arg0, arg1) {
441
436
  description: 'The request was well-formed but was unable to process operation due to one or many errors.',
442
437
  contentType: MimeTypes.opra_response_json,
443
438
  });
444
- if (typeof args.type === 'function')
445
- decorator.UseType(args.type);
446
439
  /**
447
440
  *
448
441
  */
@@ -464,6 +457,7 @@ HttpOperation.Entity.Update = function (arg0, arg1) {
464
457
  decoratorChain.push((meta) => {
465
458
  if (!meta.path?.includes(':' + name))
466
459
  meta.path = (meta.path || '') + '@:' + name;
460
+ meta.mergePath = true;
467
461
  });
468
462
  return decorator;
469
463
  };
@@ -114,6 +114,9 @@ export function HttpOperationDecoratorFactory(decoratorChain, options) {
114
114
  responseMeta.contentType = responseMeta.contentType || MimeTypes.opra_response_json;
115
115
  responseMeta.contentEncoding = responseMeta.contentEncoding || 'utf-8';
116
116
  }
117
+ if (responseMeta.contentType === MimeTypes.opra_response_json) {
118
+ responseMeta.contentEncoding = responseMeta.contentEncoding || 'utf-8';
119
+ }
117
120
  decoratorChain.push((meta) => {
118
121
  meta.responses = meta.responses || [];
119
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';
@@ -15,6 +13,9 @@ const OPRA_SPEC_URL = 'https://oprajs.com/spec/v' + OpraSchema.SpecVersion;
15
13
  * @class ApiDocumentFactory
16
14
  */
17
15
  export class ApiDocumentFactory {
16
+ constructor() {
17
+ this._allDocuments = {};
18
+ }
18
19
  /**
19
20
  * Creates ApiDocument instance from given schema object
20
21
  */
@@ -64,9 +65,14 @@ export class ApiDocumentFactory {
64
65
  else
65
66
  init = schemaOrUrl;
66
67
  // Add builtin data types if this document is the root
68
+ let builtinDocument;
67
69
  if (!document[BUILTIN]) {
68
- const builtinDocument = await this.createBuiltinDocument(context);
69
- document.references.set('opra', builtinDocument);
70
+ const t = document.node.findDataType('string');
71
+ builtinDocument = t?.node.getDocument();
72
+ if (!builtinDocument) {
73
+ builtinDocument = await this.createBuiltinDocument(context);
74
+ document.references.set('opra', builtinDocument);
75
+ }
70
76
  }
71
77
  init.spec = init.spec || OpraSchema.SpecVersion;
72
78
  document.url = init.url;
@@ -87,8 +93,10 @@ export class ApiDocumentFactory {
87
93
  return;
88
94
  }
89
95
  const refDoc = new ApiDocument();
96
+ if (builtinDocument)
97
+ refDoc.references.set('opra', builtinDocument);
90
98
  await this.initDocument(refDoc, context, r);
91
- document.references.set(ns, refDoc);
99
+ document.references.set(ns, this._allDocuments[refDoc.id]);
92
100
  });
93
101
  }
94
102
  });
@@ -109,8 +117,10 @@ export class ApiDocumentFactory {
109
117
  context.addError(`Unknown service protocol (${init.api.protocol})`);
110
118
  });
111
119
  }
112
- const x = document.export();
113
- asMutable(document).id = crypto.createHash('md5').update(JSON.stringify(x)).digest('base64url');
120
+ document.invalidate();
121
+ /** Add document to global registry */
122
+ if (!this._allDocuments[document.id])
123
+ this._allDocuments[document.id] = document;
114
124
  }
115
125
  /**
116
126
  *
@@ -7,7 +7,6 @@ import { HttpController } from './http-controller.js';
7
7
  export class HttpApi extends ApiBase {
8
8
  constructor(owner) {
9
9
  super(owner);
10
- this.owner = owner;
11
10
  // noinspection JSUnusedGlobalSymbols
12
11
  this._controllerReverseMap = new WeakMap();
13
12
  this.protocol = 'http';
@@ -1,3 +1,4 @@
1
+ import nodePath from 'node:path';
1
2
  import { asMutable } from 'ts-gems';
2
3
  import { omitUndefined, ResponsiveMap } from '../../helpers/index.js';
3
4
  import { OpraSchema } from '../../schema/index.js';
@@ -26,7 +27,7 @@ export const HttpController = function (...args) {
26
27
  _this.parameters = [];
27
28
  _this.name = initArgs.name;
28
29
  _this.description = initArgs.description;
29
- _this.path = initArgs.path || initArgs.name;
30
+ _this.path = initArgs.path ?? initArgs.name;
30
31
  _this.instance = initArgs.instance;
31
32
  _this.ctor = initArgs.ctor;
32
33
  _this._controllerReverseMap = new WeakMap();
@@ -97,7 +98,7 @@ class HttpControllerClass extends DocumentElement {
97
98
  }
98
99
  }
99
100
  getFullUrl() {
100
- return (this.owner instanceof HttpController ? this.owner.getFullUrl() : '/') + this.path;
101
+ return nodePath.posix.join(this.owner instanceof HttpController ? this.owner.getFullUrl() : '/', this.path);
101
102
  }
102
103
  /**
103
104
  *
@@ -1,4 +1,6 @@
1
+ import typeIs from '@browsery/type-is';
1
2
  import { asMutable } from 'ts-gems';
3
+ import { isAny, vg } from 'valgen';
2
4
  import { omitUndefined } from '../../helpers/index.js';
3
5
  import { DocumentElement } from '../common/document-element.js';
4
6
  import { DataType } from '../data-type/data-type.js';
@@ -21,7 +23,6 @@ export const HttpMediaType = function (owner, initArgs) {
21
23
  _this.maxFiles = initArgs.maxFiles;
22
24
  _this.maxFileSize = initArgs.maxFileSize;
23
25
  _this.maxTotalFileSize = initArgs.maxTotalFileSize;
24
- _this.minFileSize = initArgs.minFileSize;
25
26
  if (initArgs?.type) {
26
27
  _this.type = initArgs?.type instanceof DataType ? initArgs.type : _this.owner.node.getDataType(initArgs.type);
27
28
  }
@@ -56,12 +57,25 @@ class HttpMediaTypeClass extends DocumentElement {
56
57
  maxFiles: this.maxFiles,
57
58
  maxFileSize: this.maxFileSize,
58
59
  maxTotalFileSize: this.maxTotalFileSize,
59
- minFileSize: this.minFileSize,
60
60
  });
61
61
  if (this.multipartFields?.length) {
62
62
  out.multipartFields = this.multipartFields.map(x => x.toJSON());
63
63
  }
64
64
  return out;
65
65
  }
66
+ generateCodec(codec, options) {
67
+ let fn;
68
+ if (this.type) {
69
+ fn = this.type.generateCodec(codec, options);
70
+ }
71
+ else if (this.contentType) {
72
+ const arr = Array.isArray(this.contentType) ? this.contentType : [this.contentType];
73
+ if (arr.find(ct => typeIs.is(ct, ['json']))) {
74
+ fn = this.node.findDataType('object').generateCodec(codec);
75
+ }
76
+ }
77
+ fn = fn || isAny;
78
+ return this.isArray ? vg.isArray(fn) : fn;
79
+ }
66
80
  }
67
81
  HttpMediaType.prototype = HttpMediaTypeClass.prototype;
@@ -8,7 +8,6 @@ import { HttpMediaType } from './http-media-type.js';
8
8
  export class HttpMultipartField extends HttpMediaType {
9
9
  constructor(owner, initArgs) {
10
10
  super(owner, initArgs);
11
- this.owner = owner;
12
11
  this.fieldName =
13
12
  initArgs.fieldName instanceof RegExp
14
13
  ? initArgs.fieldName
@@ -7,7 +7,6 @@ import { HttpStatusRange } from './http-status-range.js';
7
7
  export class HttpOperationResponse extends HttpMediaType {
8
8
  constructor(owner, init) {
9
9
  super(owner, init);
10
- this.owner = owner;
11
10
  this.parameters = [];
12
11
  this.statusCode = (Array.isArray(init.statusCode) ? init.statusCode : [init.statusCode]).map(x => typeof x === 'object' ? new HttpStatusRange(x.start, x.end) : new HttpStatusRange(x));
13
12
  this.partial = init.partial;
@@ -27,6 +27,7 @@ export const HttpOperation = function (...args) {
27
27
  _this.types = _this.node[kDataTypeMap] = new DataTypeMap();
28
28
  _this.name = initArgs.name;
29
29
  _this.path = initArgs.path;
30
+ _this.mergePath = initArgs.mergePath;
30
31
  _this.method = initArgs.method || 'GET';
31
32
  _this.description = initArgs.description;
32
33
  _this.composition = initArgs.composition;
@@ -53,13 +54,23 @@ class HttpOperationClass extends DocumentElement {
53
54
  }
54
55
  getFullUrl() {
55
56
  const out = this.owner.getFullUrl();
56
- return out ? (this.path ? nodePath.posix.join(out, this.path) : out) : this.path || '/';
57
+ if (out) {
58
+ if (this.path) {
59
+ if (this.mergePath)
60
+ return out + this.path;
61
+ return nodePath.posix.join(out, this.path);
62
+ }
63
+ return out;
64
+ }
65
+ return this.path || '/';
57
66
  }
58
67
  toJSON() {
59
68
  const out = omitUndefined({
60
69
  kind: OpraSchema.HttpOperation.Kind,
61
70
  description: this.description,
62
71
  method: this.method,
72
+ path: this.path,
73
+ mergePath: this.mergePath,
63
74
  composition: this.composition,
64
75
  requestBody: this.requestBody?.toJSON(),
65
76
  });
@@ -21,6 +21,8 @@ export const HttpParameter = function (owner, initArgs) {
21
21
  _this.location = initArgs.location;
22
22
  _this.deprecated = initArgs.deprecated;
23
23
  _this.required = initArgs.required;
24
+ if (_this.required == null && initArgs.location === 'path')
25
+ _this.required = true;
24
26
  _this.arraySeparator = initArgs.arraySeparator;
25
27
  _this.keyParam = initArgs.keyParam;
26
28
  };
@@ -6,7 +6,6 @@ import { DocumentElement } from '../common/document-element.js';
6
6
  export class HttpRequestBody extends DocumentElement {
7
7
  constructor(owner) {
8
8
  super(owner);
9
- this.owner = owner;
10
9
  this.content = [];
11
10
  }
12
11
  toJSON() {
@@ -22,8 +22,11 @@ export class HttpStatusRange {
22
22
  this.end = m[2] ? parseInt(m[2], 10) : this.start;
23
23
  }
24
24
  }
25
- get distance() {
26
- return this.end - this.start;
25
+ includes(statusCode) {
26
+ return statusCode >= this.start && statusCode <= this.end;
27
+ }
28
+ intersects(start, end) {
29
+ return end >= this.start && start <= this.end;
27
30
  }
28
31
  toString() {
29
32
  if (this.start === this.end)
@@ -6,6 +6,7 @@ import { i18n } from '../i18n/index.js';
6
6
  export class OpraException extends Error {
7
7
  constructor(issue, cause) {
8
8
  super('Unknown error');
9
+ this.severity = 'error';
9
10
  cause = cause || (issue instanceof Error ? issue : undefined);
10
11
  if (issue instanceof Error)
11
12
  cause = issue;
@@ -1,7 +1,8 @@
1
1
  import { OpraException } from '../exception/index.js';
2
- import { OpraFilter } from '../filter/index.js';
3
2
  import { omitUndefined, ResponsiveMap } from '../helpers/index.js';
4
3
  import { translate } from '../i18n/index.js';
4
+ import { ArithmeticExpression, ArrayExpression, ComparisonExpression, LogicalExpression, ParenthesizedExpression, QualifiedIdentifier, } from './ast/index.js';
5
+ import { parse } from './parse.js';
5
6
  export class FilterRules {
6
7
  constructor(rules, options) {
7
8
  this._rules = new ResponsiveMap();
@@ -27,10 +28,10 @@ export class FilterRules {
27
28
  normalizeFilter(filter, dataType) {
28
29
  if (!filter)
29
30
  return;
30
- const ast = typeof filter === 'string' ? OpraFilter.parse(filter) : filter;
31
- if (ast instanceof OpraFilter.ComparisonExpression) {
31
+ const ast = typeof filter === 'string' ? parse(filter) : filter;
32
+ if (ast instanceof ComparisonExpression) {
32
33
  this.normalizeFilter(ast.left, dataType);
33
- if (!(ast.left instanceof OpraFilter.QualifiedIdentifier && ast.left.field)) {
34
+ if (!(ast.left instanceof QualifiedIdentifier && ast.left.field)) {
34
35
  throw new TypeError(`Invalid filter query. Left side should be a data field.`);
35
36
  }
36
37
  // Check if filtering accepted for given field
@@ -59,23 +60,23 @@ export class FilterRules {
59
60
  this.normalizeFilter(ast.right, dataType);
60
61
  return ast;
61
62
  }
62
- if (ast instanceof OpraFilter.LogicalExpression) {
63
+ if (ast instanceof LogicalExpression) {
63
64
  ast.items.forEach(item => this.normalizeFilter(item, dataType));
64
65
  return ast;
65
66
  }
66
- if (ast instanceof OpraFilter.ArithmeticExpression) {
67
+ if (ast instanceof ArithmeticExpression) {
67
68
  ast.items.forEach(item => this.normalizeFilter(item.expression, dataType));
68
69
  return ast;
69
70
  }
70
- if (ast instanceof OpraFilter.ArrayExpression) {
71
+ if (ast instanceof ArrayExpression) {
71
72
  ast.items.forEach(item => this.normalizeFilter(item, dataType));
72
73
  return ast;
73
74
  }
74
- if (ast instanceof OpraFilter.ParenthesizedExpression) {
75
+ if (ast instanceof ParenthesizedExpression) {
75
76
  this.normalizeFilter(ast.expression, dataType);
76
77
  return ast;
77
78
  }
78
- if (ast instanceof OpraFilter.QualifiedIdentifier && dataType) {
79
+ if (ast instanceof QualifiedIdentifier && dataType) {
79
80
  ast.value = dataType.normalizeFieldPath(ast.value);
80
81
  ast.field = dataType.getField(ast.value);
81
82
  ast.dataType = ast.field.type;
@@ -5,4 +5,5 @@ export * from './mixin-utils.js';
5
5
  export * from './object-utils.js';
6
6
  export * from './parse-fields-projection.js';
7
7
  export * from './responsive-map.js';
8
+ export * from './safe-json-stringify.js';
8
9
  export * from './type-guards.js';
@@ -4,10 +4,10 @@ import { DATATYPE_METADATA } from '../document/constants.js';
4
4
  export function cloneObject(obj, jsonOnly) {
5
5
  return merge({}, obj, {
6
6
  deep: v => isPlainObject(v) && !v[DATATYPE_METADATA],
7
+ descriptor: true,
7
8
  filter: (source, key) => {
8
9
  const v = source[key];
9
- return ((v != null && !jsonOnly) ||
10
- (typeof v !== 'function' && (typeof v !== 'object' || isPlainObject(v) || Array.isArray(v))));
10
+ return !jsonOnly || (typeof v !== 'function' && (typeof v !== 'object' || isPlainObject(v) || Array.isArray(v)));
11
11
  },
12
12
  });
13
13
  }
@@ -0,0 +1,13 @@
1
+ export function safeJsonStringify(value, replacer, space) {
2
+ const seen = new WeakSet();
3
+ return JSON.stringify(value, (k, v) => {
4
+ if (v !== null && typeof v === 'object') {
5
+ if (seen.has(v))
6
+ return;
7
+ seen.add(v);
8
+ }
9
+ if (replacer)
10
+ return replacer(k, v);
11
+ return v;
12
+ }, space);
13
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -1,27 +1,2 @@
1
- import * as constants_ from './constants.js';
2
- import * as complexType_ from './data-type/complex-type.interface.js';
3
- import * as enumType_ from './data-type/enum-type.interface.js';
4
- import * as mappedType_ from './data-type/mapped-type.interface.js';
5
- import * as mixinType_ from './data-type/mixin-type.interface.js';
6
- import * as simpleType_ from './data-type/simple-type.interface.js';
7
- import * as controller_ from './http/http-controller.interface.js';
8
- import * as operation_ from './http/http-operation.interface.js';
9
- import * as typeGuards_ from './type-guards.js';
10
- export var OpraSchema;
11
- (function (OpraSchema) {
12
- OpraSchema.SpecVersion = constants_.SpecVersion;
13
- OpraSchema.ComplexType = complexType_.ComplexType;
14
- OpraSchema.EnumType = enumType_.EnumType;
15
- OpraSchema.MappedType = mappedType_.MappedType;
16
- OpraSchema.MixinType = mixinType_.MixinType;
17
- OpraSchema.SimpleType = simpleType_.SimpleType;
18
- OpraSchema.HttpController = controller_.HttpController;
19
- OpraSchema.HttpOperation = operation_.HttpOperation;
20
- OpraSchema.isComplexType = typeGuards_.isComplexType;
21
- OpraSchema.isDataType = typeGuards_.isDataType;
22
- OpraSchema.isSimpleType = typeGuards_.isSimpleType;
23
- OpraSchema.isMixinType = typeGuards_.isMixinType;
24
- OpraSchema.isMappedType = typeGuards_.isMappedType;
25
- OpraSchema.isEnumType = typeGuards_.isEnumType;
26
- OpraSchema.isHttpController = typeGuards_.isHttpController;
27
- })(OpraSchema || (OpraSchema = {}));
1
+ import * as OpraSchema from './opra-schema.js';
2
+ export { OpraSchema };
@@ -0,0 +1,21 @@
1
+ export * from './api-document.interface.js';
2
+ export * from './constants.js';
3
+ export * from './data-type/complex-type.interface.js';
4
+ export * from './data-type/data-type.interface.js';
5
+ export * from './data-type/enum-type.interface.js';
6
+ export * from './data-type/field.interface.js';
7
+ export * from './data-type/mapped-type.interface.js';
8
+ export * from './data-type/mixin-type.interface.js';
9
+ export * from './data-type/simple-type.interface.js';
10
+ export * from './data-type-container.interface.js';
11
+ export * from './http/http-controller.interface.js';
12
+ export * from './http/http-media-type.interface.js';
13
+ export * from './http/http-multipart-field.interface.js';
14
+ export * from './http/http-operation.interface.js';
15
+ export * from './http/http-operation-response.interface.js';
16
+ export * from './http/http-parameter.interface.js';
17
+ export * from './http/http-request-body.interface.js';
18
+ export * from './http/http-status-range.interface.js';
19
+ export * from './type-guards.js';
20
+ export * from './types.js';
21
+ export * from './value.interface.js';