@opra/common 0.25.4 → 0.26.0

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 (197) hide show
  1. package/browser.js +1843 -1355
  2. package/cjs/document/api-document.js +16 -220
  3. package/cjs/document/data-type/complex-type-class.js +41 -19
  4. package/cjs/document/data-type/complex-type.js +1 -1
  5. package/cjs/document/data-type/data-type.js +2 -1
  6. package/cjs/document/data-type/enum-type-class.js +15 -12
  7. package/cjs/document/data-type/enum-type.js +28 -14
  8. package/cjs/document/data-type/field-class.js +21 -3
  9. package/cjs/document/data-type/field-decorator.js +0 -19
  10. package/cjs/document/data-type/mapped-type-class.js +8 -10
  11. package/cjs/document/data-type/mapped-type.js +1 -1
  12. package/cjs/document/data-type/simple-type-class.js +17 -8
  13. package/cjs/document/data-type/simple-type.js +1 -1
  14. package/cjs/document/data-type/union-type-class.js +15 -13
  15. package/cjs/document/document-base.js +24 -0
  16. package/cjs/document/factory/api-document-factory.js +231 -0
  17. package/cjs/document/factory/type-document-factory.js +324 -0
  18. package/cjs/document/index.js +7 -1
  19. package/cjs/document/resource/action-decorator.js +27 -0
  20. package/cjs/document/resource/collection-class.js +95 -44
  21. package/cjs/document/resource/collection-decorator.js +182 -0
  22. package/cjs/document/resource/collection.js +4 -4
  23. package/cjs/document/resource/container-class.js +82 -0
  24. package/cjs/document/resource/container-decorator.js +24 -0
  25. package/cjs/document/resource/container.js +29 -0
  26. package/cjs/document/resource/crud-resource.js +31 -0
  27. package/cjs/document/resource/endpoint.js +28 -21
  28. package/cjs/document/resource/operation-decorator.js +27 -0
  29. package/cjs/document/resource/parameter.js +51 -0
  30. package/cjs/document/{decorators/resource.decorator.js → resource/resource-decorator.js} +9 -14
  31. package/cjs/document/resource/resource.js +20 -5
  32. package/cjs/document/resource/singleton-class.js +60 -40
  33. package/cjs/document/resource/singleton-decorator.js +57 -0
  34. package/cjs/document/resource/singleton.js +4 -4
  35. package/cjs/document/resource/storage-class.js +11 -17
  36. package/cjs/document/resource/storage-decorator.js +66 -0
  37. package/cjs/document/resource/storage.js +3 -3
  38. package/cjs/document/type-document.js +195 -0
  39. package/cjs/exception/http-errors/internal-server.error.js +1 -0
  40. package/cjs/exception/opra-exception.js +18 -12
  41. package/cjs/exception/wrap-exception.js +2 -1
  42. package/cjs/helpers/responsive-map.js +3 -3
  43. package/cjs/http/opra-url-path.js +5 -1
  44. package/cjs/schema/document/document-base.interface.js +2 -0
  45. package/cjs/schema/document/type-document.interface.js +2 -0
  46. package/cjs/schema/opra-schema.ns.js +3 -1
  47. package/cjs/schema/type-guards.js +3 -3
  48. package/esm/document/api-document.js +16 -220
  49. package/esm/document/data-type/complex-type-class.js +40 -19
  50. package/esm/document/data-type/complex-type.js +1 -1
  51. package/esm/document/data-type/data-type.js +2 -1
  52. package/esm/document/data-type/enum-type-class.js +15 -12
  53. package/esm/document/data-type/enum-type.js +26 -12
  54. package/esm/document/data-type/field-class.js +20 -3
  55. package/esm/document/data-type/field-decorator.js +0 -19
  56. package/esm/document/data-type/mapped-type-class.js +9 -11
  57. package/esm/document/data-type/mapped-type.js +1 -1
  58. package/esm/document/data-type/simple-type-class.js +15 -6
  59. package/esm/document/data-type/simple-type.js +1 -1
  60. package/esm/document/data-type/union-type-class.js +11 -9
  61. package/esm/document/document-base.js +20 -0
  62. package/esm/document/factory/api-document-factory.js +227 -0
  63. package/esm/document/factory/type-document-factory.js +320 -0
  64. package/esm/document/index.js +7 -1
  65. package/esm/document/resource/action-decorator.js +23 -0
  66. package/esm/document/resource/collection-class.js +95 -44
  67. package/esm/document/resource/collection-decorator.js +178 -0
  68. package/esm/document/resource/collection.js +4 -4
  69. package/esm/document/resource/container-class.js +78 -0
  70. package/esm/document/resource/container-decorator.js +20 -0
  71. package/esm/document/resource/container.js +25 -0
  72. package/esm/document/resource/crud-resource.js +27 -0
  73. package/esm/document/resource/endpoint.js +27 -21
  74. package/esm/document/resource/operation-decorator.js +23 -0
  75. package/esm/document/resource/parameter.js +46 -0
  76. package/esm/document/resource/resource-decorator.js +28 -0
  77. package/esm/document/resource/resource.js +20 -5
  78. package/esm/document/resource/singleton-class.js +58 -38
  79. package/esm/document/resource/singleton-decorator.js +53 -0
  80. package/esm/document/resource/singleton.js +4 -4
  81. package/esm/document/resource/storage-class.js +9 -15
  82. package/esm/document/resource/storage-decorator.js +62 -0
  83. package/esm/document/resource/storage.js +3 -3
  84. package/esm/document/type-document.js +191 -0
  85. package/esm/exception/http-errors/internal-server.error.js +1 -0
  86. package/esm/exception/opra-exception.js +18 -12
  87. package/esm/exception/wrap-exception.js +2 -1
  88. package/esm/helpers/responsive-map.js +3 -3
  89. package/esm/http/opra-url-path.js +4 -1
  90. package/esm/schema/document/document-base.interface.js +1 -0
  91. package/esm/schema/document/type-document.interface.js +1 -0
  92. package/esm/schema/opra-schema.ns.js +3 -1
  93. package/esm/schema/type-guards.js +1 -1
  94. package/package.json +2 -2
  95. package/types/document/api-document.d.ts +32 -73
  96. package/types/document/data-type/complex-type-class.d.ts +5 -5
  97. package/types/document/data-type/complex-type.d.ts +8 -3
  98. package/types/document/{decorators → data-type}/complex-type.decorator.d.ts +1 -1
  99. package/types/document/data-type/data-type.d.ts +11 -1
  100. package/types/document/data-type/enum-type-class.d.ts +6 -6
  101. package/types/document/data-type/enum-type.d.ts +12 -6
  102. package/types/document/data-type/field-class.d.ts +9 -1
  103. package/types/document/data-type/field-decorator.d.ts +1 -1
  104. package/types/document/data-type/field.d.ts +4 -3
  105. package/types/document/data-type/mapped-type-class.d.ts +5 -9
  106. package/types/document/data-type/mapped-type.d.ts +6 -7
  107. package/types/document/data-type/simple-type-class.d.ts +6 -3
  108. package/types/document/{decorators → data-type}/simple-type.decorator.d.ts +1 -1
  109. package/types/document/data-type/union-type-class.d.ts +2 -8
  110. package/types/document/data-type/union-type.d.ts +7 -6
  111. package/types/document/document-base.d.ts +10 -0
  112. package/types/document/factory/api-document-factory.d.ts +50 -0
  113. package/types/document/factory/type-document-factory.d.ts +56 -0
  114. package/types/document/index.d.ts +7 -1
  115. package/types/document/resource/action-decorator.d.ts +6 -0
  116. package/types/document/resource/collection-class.d.ts +17 -12
  117. package/types/document/resource/collection-decorator.d.ts +192 -0
  118. package/types/document/resource/collection.d.ts +11 -19
  119. package/types/document/resource/container-class.d.ts +66 -0
  120. package/types/document/resource/container-decorator.d.ts +37 -0
  121. package/types/document/resource/container.d.ts +25 -0
  122. package/types/document/resource/crud-resource.d.ts +16 -0
  123. package/types/document/resource/endpoint.d.ts +26 -19
  124. package/types/document/resource/operation-decorator.d.ts +6 -0
  125. package/types/document/resource/parameter.d.ts +35 -0
  126. package/types/document/resource/resource-decorator.d.ts +32 -0
  127. package/types/document/resource/resource.d.ts +15 -13
  128. package/types/document/resource/singleton-class.d.ts +15 -14
  129. package/types/document/resource/singleton-decorator.d.ts +125 -0
  130. package/types/document/resource/singleton.d.ts +11 -16
  131. package/types/document/resource/storage-class.d.ts +13 -6
  132. package/types/document/resource/storage-decorator.d.ts +98 -0
  133. package/types/document/resource/storage.d.ts +9 -12
  134. package/types/document/type-document.d.ts +68 -0
  135. package/types/exception/opra-exception.d.ts +1 -1
  136. package/types/http/opra-url-path.d.ts +2 -1
  137. package/types/schema/data-type/complex-type.interface.d.ts +1 -1
  138. package/types/schema/data-type/data-type.interface.d.ts +3 -3
  139. package/types/schema/data-type/enum-type.interface.d.ts +6 -7
  140. package/types/schema/data-type/mapped-type.interface.d.ts +4 -3
  141. package/types/schema/data-type/simple-type.interface.d.ts +3 -3
  142. package/types/schema/data-type/union-type.interface.d.ts +6 -4
  143. package/types/schema/document/api-document.interface.d.ts +11 -0
  144. package/types/schema/document/document-base.interface.d.ts +24 -0
  145. package/types/schema/document/type-document.interface.d.ts +6 -0
  146. package/types/schema/opra-schema.ns.d.ts +3 -1
  147. package/types/schema/resource/collection.interface.d.ts +31 -31
  148. package/types/schema/resource/container.interface.d.ts +4 -3
  149. package/types/schema/resource/resource.interface.d.ts +1 -1
  150. package/types/schema/resource/singleton.interface.d.ts +15 -10
  151. package/types/schema/resource/storage.interface.d.ts +49 -45
  152. package/types/schema/type-guards.d.ts +3 -2
  153. package/cjs/document/decorators/collection-decorator.js +0 -38
  154. package/cjs/document/decorators/singleton.decorator.js +0 -36
  155. package/cjs/document/decorators/storage.decorator.js +0 -35
  156. package/cjs/document/factory/add-references.js +0 -20
  157. package/cjs/document/factory/create-document.js +0 -83
  158. package/cjs/document/factory/factory.js +0 -66
  159. package/cjs/document/factory/import-resource-class.js +0 -54
  160. package/cjs/document/factory/import-type-class.js +0 -146
  161. package/cjs/document/factory/index.js +0 -4
  162. package/cjs/document/factory/process-resources.js +0 -70
  163. package/cjs/document/factory/process-types.js +0 -191
  164. package/cjs/document/utils/generate-codec.js +0 -39
  165. package/esm/document/decorators/collection-decorator.js +0 -34
  166. package/esm/document/decorators/resource.decorator.js +0 -33
  167. package/esm/document/decorators/singleton.decorator.js +0 -32
  168. package/esm/document/decorators/storage.decorator.js +0 -31
  169. package/esm/document/factory/add-references.js +0 -16
  170. package/esm/document/factory/create-document.js +0 -77
  171. package/esm/document/factory/factory.js +0 -62
  172. package/esm/document/factory/import-resource-class.js +0 -48
  173. package/esm/document/factory/import-type-class.js +0 -136
  174. package/esm/document/factory/index.js +0 -1
  175. package/esm/document/factory/process-resources.js +0 -63
  176. package/esm/document/factory/process-types.js +0 -185
  177. package/esm/document/utils/generate-codec.js +0 -33
  178. package/types/document/decorators/collection-decorator.d.ts +0 -30
  179. package/types/document/decorators/resource.decorator.d.ts +0 -9
  180. package/types/document/decorators/singleton.decorator.d.ts +0 -25
  181. package/types/document/decorators/storage.decorator.d.ts +0 -22
  182. package/types/document/factory/add-references.d.ts +0 -4
  183. package/types/document/factory/create-document.d.ts +0 -12
  184. package/types/document/factory/factory.d.ts +0 -63
  185. package/types/document/factory/import-resource-class.d.ts +0 -10
  186. package/types/document/factory/import-type-class.d.ts +0 -17
  187. package/types/document/factory/index.d.ts +0 -1
  188. package/types/document/factory/process-resources.d.ts +0 -9
  189. package/types/document/factory/process-types.d.ts +0 -6
  190. package/types/document/utils/generate-codec.d.ts +0 -10
  191. package/types/schema/document.interface.d.ts +0 -34
  192. /package/cjs/document/{decorators → data-type}/complex-type.decorator.js +0 -0
  193. /package/cjs/document/{decorators → data-type}/simple-type.decorator.js +0 -0
  194. /package/cjs/schema/{document.interface.js → document/api-document.interface.js} +0 -0
  195. /package/esm/document/{decorators → data-type}/complex-type.decorator.js +0 -0
  196. /package/esm/document/{decorators → data-type}/simple-type.decorator.js +0 -0
  197. /package/esm/schema/{document.interface.js → document/api-document.interface.js} +0 -0
@@ -1,20 +1,14 @@
1
1
  import * as vg from 'valgen';
2
2
  import { BadRequestError } from '../../exception/index.js';
3
3
  import { OpraFilter } from '../../filter/index.js';
4
- import { omitUndefined } from '../../helpers/object-utils.js';
5
4
  import { translate } from '../../i18n/index.js';
6
5
  import { OpraSchema } from '../../schema/index.js';
7
6
  import { SimpleType } from '../data-type/simple-type.js';
8
- import { generateCodec } from '../utils/generate-codec.js';
9
- import { Resource } from './resource.js';
10
- export class CollectionClass extends Resource {
11
- constructor(document, init) {
12
- super(document, init);
13
- this._decoders = {};
14
- this._encoders = {};
7
+ import { CrudResource } from './crud-resource.js';
8
+ export class CollectionClass extends CrudResource {
9
+ constructor(parent, init) {
10
+ super(parent, init);
15
11
  this.kind = OpraSchema.Collection.Kind;
16
- this.controller = init.controller;
17
- this.operations = { ...init.operations };
18
12
  const dataType = this.type = init.type;
19
13
  // Validate key fields
20
14
  this.primaryKey = init.primaryKey
@@ -27,15 +21,98 @@ export class CollectionClass extends Resource {
27
21
  if (!(field?.type instanceof SimpleType))
28
22
  throw new TypeError(`Only Simple type allowed for primary keys but "${f}" is a ${field.type.kind}`);
29
23
  });
24
+ // ------------------
25
+ let endpoint = this.operations.get('create');
26
+ if (endpoint) {
27
+ endpoint.returnType = this.type;
28
+ endpoint.decode = this.type.generateCodec('decode', {
29
+ partial: true,
30
+ pick: endpoint.inputPickFields,
31
+ omit: endpoint.inputOmitFields,
32
+ });
33
+ endpoint.encode = this.type.generateCodec('encode', {
34
+ partial: true,
35
+ pick: endpoint.outputPickFields,
36
+ omit: endpoint.outputOmitFields,
37
+ });
38
+ endpoint.defineParameter('pick', { type: 'string', isArray: true, isBuiltin: true });
39
+ endpoint.defineParameter('omit', { type: 'string', isArray: true, isBuiltin: true });
40
+ endpoint.defineParameter('include', { type: 'string', isArray: true, isBuiltin: true });
41
+ }
42
+ // ------------------
43
+ endpoint = this.operations.get('deleteMany');
44
+ if (endpoint) {
45
+ endpoint.defineParameter('filter', { type: 'string', isBuiltin: true });
46
+ }
47
+ // ------------------
48
+ endpoint = this.operations.get('get');
49
+ if (endpoint) {
50
+ endpoint.returnType = this.type;
51
+ endpoint.encode = this.type.generateCodec('encode', {
52
+ partial: true,
53
+ pick: endpoint.outputPickFields,
54
+ omit: endpoint.outputOmitFields,
55
+ });
56
+ endpoint.defineParameter('pick', { type: 'string', isArray: true, isBuiltin: true });
57
+ endpoint.defineParameter('omit', { type: 'string', isArray: true, isBuiltin: true });
58
+ endpoint.defineParameter('include', { type: 'string', isArray: true, isBuiltin: true });
59
+ }
60
+ // ------------------
61
+ endpoint = this.operations.get('findMany');
62
+ if (endpoint) {
63
+ endpoint.returnType = this.type;
64
+ endpoint.encode = vg.isArray(this.type.generateCodec('encode', {
65
+ partial: true,
66
+ pick: endpoint.outputPickFields,
67
+ omit: endpoint.outputOmitFields,
68
+ }));
69
+ endpoint.defineParameter('pick', { type: 'string', isArray: true, isBuiltin: true });
70
+ endpoint.defineParameter('omit', { type: 'string', isArray: true, isBuiltin: true });
71
+ endpoint.defineParameter('include', { type: 'string', isArray: true, isBuiltin: true });
72
+ endpoint.defineParameter('sort', { type: 'string', isArray: true, isBuiltin: true });
73
+ endpoint.defineParameter('filter', { type: 'string', isBuiltin: true });
74
+ endpoint.defineParameter('limit', { type: 'integer', isBuiltin: true });
75
+ endpoint.defineParameter('skip', { type: 'integer', isBuiltin: true });
76
+ endpoint.defineParameter('distinct', { type: 'boolean', isBuiltin: true });
77
+ endpoint.defineParameter('count', { type: 'boolean', isBuiltin: true });
78
+ }
79
+ // ------------------
80
+ endpoint = this.operations.get('update');
81
+ if (endpoint) {
82
+ endpoint.returnType = this.type;
83
+ endpoint.decode = this.type.generateCodec('decode', {
84
+ pick: endpoint.inputPickFields,
85
+ omit: endpoint.inputOmitFields,
86
+ });
87
+ endpoint.encode = this.type.generateCodec('encode', {
88
+ partial: true,
89
+ pick: endpoint.outputPickFields,
90
+ omit: endpoint.outputOmitFields,
91
+ });
92
+ endpoint.defineParameter('pick', { type: 'string', isArray: true, isBuiltin: true });
93
+ endpoint.defineParameter('omit', { type: 'string', isArray: true, isBuiltin: true });
94
+ endpoint.defineParameter('include', { type: 'string', isArray: true, isBuiltin: true });
95
+ }
96
+ // ------------------
97
+ endpoint = this.operations.get('updateMany');
98
+ if (endpoint) {
99
+ endpoint.decode = this.type.generateCodec('decode', {
100
+ pick: endpoint.inputPickFields,
101
+ omit: endpoint.inputOmitFields,
102
+ });
103
+ endpoint.defineParameter('filter', { type: 'string', isBuiltin: true });
104
+ }
30
105
  }
31
- exportSchema() {
106
+ getOperation(name) {
107
+ return super.getOperation(name);
108
+ }
109
+ exportSchema(options) {
32
110
  return {
33
- ...super.exportSchema(),
34
- ...omitUndefined({
35
- type: this.type.name || 'object',
36
- operations: this.operations,
111
+ ...super.exportSchema(options),
112
+ type: this.type.name || 'object',
113
+ ...{
37
114
  primaryKey: this.primaryKey
38
- })
115
+ }
39
116
  };
40
117
  }
41
118
  parseKeyValue(value) {
@@ -79,7 +156,7 @@ export class CollectionClass extends Resource {
79
156
  const normalized = this.type.normalizeFieldPath(fields);
80
157
  if (!normalized)
81
158
  return;
82
- const findManyOp = this.operations.findMany;
159
+ const findManyOp = this.getOperation('findMany');
83
160
  const sortFields = findManyOp && findManyOp.sortFields;
84
161
  (Array.isArray(normalized) ? normalized : [normalized]).forEach(field => {
85
162
  if (!sortFields?.find(x => x === field))
@@ -98,7 +175,7 @@ export class CollectionClass extends Resource {
98
175
  if (!(ast.left instanceof OpraFilter.QualifiedIdentifier && ast.left.field))
99
176
  throw new TypeError(`Invalid filter query. Left side should be a data field.`);
100
177
  // Check if filtering accepted for given field
101
- const findManyOp = this.operations.findMany;
178
+ const findManyOp = this.getOperation('findMany');
102
179
  const fieldLower = ast.left.value.toLowerCase();
103
180
  const filterDef = (findManyOp && findManyOp.filters || [])
104
181
  .find(f => f.field.toLowerCase() === fieldLower);
@@ -140,30 +217,4 @@ export class CollectionClass extends Resource {
140
217
  }
141
218
  return ast;
142
219
  }
143
- getDecoder(endpoint) {
144
- let decoder = this._decoders[endpoint];
145
- if (decoder)
146
- return decoder;
147
- const options = {
148
- partial: endpoint !== 'create'
149
- };
150
- if (endpoint !== 'create')
151
- options.omit = [...this.primaryKey];
152
- decoder = generateCodec(this.type, 'decode', options);
153
- this._decoders[endpoint] = decoder;
154
- return decoder;
155
- }
156
- getEncoder(endpoint) {
157
- let encoder = this._encoders[endpoint];
158
- if (encoder)
159
- return encoder;
160
- const options = {
161
- partial: true
162
- };
163
- encoder = generateCodec(this.type, 'encode', options);
164
- if (endpoint === 'findMany')
165
- return vg.isArray(encoder);
166
- this._encoders[endpoint] = encoder;
167
- return encoder;
168
- }
169
220
  }
@@ -0,0 +1,178 @@
1
+ import { omitUndefined } from '../../helpers/index.js';
2
+ import { OpraSchema } from '../../schema/index.js';
3
+ import { createActionDecorator } from './action-decorator.js';
4
+ import { createOperationDecorator } from './operation-decorator.js';
5
+ import { ResourceDecorator } from './resource-decorator.js';
6
+ const operationProperties = ['create', 'delete', 'deleteMany', 'get', 'findMany', 'update', 'updateMany'];
7
+ export function CollectionDecorator(type, options) {
8
+ return ResourceDecorator(OpraSchema.Collection.Kind, { ...options, type });
9
+ }
10
+ Object.assign(CollectionDecorator, ResourceDecorator);
11
+ /*
12
+ * Action PropertyDecorator
13
+ */
14
+ (function (CollectionDecorator) {
15
+ /**
16
+ * Action PropertyDecorator
17
+ */
18
+ function Action(options) {
19
+ const list = [];
20
+ return createActionDecorator(options, operationProperties, list);
21
+ }
22
+ CollectionDecorator.Action = Action;
23
+ function Create(options) {
24
+ const list = [];
25
+ const decorator = createOperationDecorator('create', options, list);
26
+ decorator.InputMaxContentSize = (sizeInBytes) => {
27
+ list.push(operationMeta => operationMeta.inputMaxContentSize = sizeInBytes);
28
+ return decorator;
29
+ };
30
+ decorator.InputPickFields = (...fields) => {
31
+ list.push(operationMeta => operationMeta.inputPickFields = fields);
32
+ return decorator;
33
+ };
34
+ decorator.InputOmitFields = (...fields) => {
35
+ list.push(operationMeta => operationMeta.inputOmitFields = fields);
36
+ return decorator;
37
+ };
38
+ decorator.OutputPickFields = (...fields) => {
39
+ list.push(operationMeta => operationMeta.outputPickFields = fields);
40
+ return decorator;
41
+ };
42
+ decorator.OutputOmitFields = (...fields) => {
43
+ list.push(operationMeta => operationMeta.outputOmitFields = fields);
44
+ return decorator;
45
+ };
46
+ return decorator;
47
+ }
48
+ CollectionDecorator.Create = Create;
49
+ function Delete(options) {
50
+ const list = [];
51
+ return createOperationDecorator('delete', options, list);
52
+ }
53
+ CollectionDecorator.Delete = Delete;
54
+ function DeleteMany(options) {
55
+ const list = [];
56
+ const decorator = createOperationDecorator('deleteMany', options, list);
57
+ decorator.Filter = (field, operators, notes) => {
58
+ if (typeof operators === 'string')
59
+ operators = operators.split(/\s*[,| ]\s*/);
60
+ list.push(operationMeta => {
61
+ operationMeta.filters = operationMeta.filters || [];
62
+ operationMeta.filters.push(omitUndefined({ field, operators, notes }));
63
+ });
64
+ return decorator;
65
+ };
66
+ return decorator;
67
+ }
68
+ CollectionDecorator.DeleteMany = DeleteMany;
69
+ function Get(options) {
70
+ const list = [];
71
+ const decorator = createOperationDecorator('get', options, list);
72
+ decorator.OutputPickFields = (...fields) => {
73
+ list.push(operationMeta => operationMeta.outputPickFields = fields);
74
+ return decorator;
75
+ };
76
+ decorator.OutputOmitFields = (...fields) => {
77
+ list.push(operationMeta => operationMeta.outputOmitFields = fields);
78
+ return decorator;
79
+ };
80
+ return decorator;
81
+ }
82
+ CollectionDecorator.Get = Get;
83
+ function FindMany(options) {
84
+ const list = [];
85
+ const decorator = createOperationDecorator('findMany', options, list);
86
+ decorator.SortFields = (...fields) => {
87
+ list.push(operationMeta => operationMeta.sortFields = fields);
88
+ return decorator;
89
+ };
90
+ decorator.DefaultSort = (...fields) => {
91
+ list.push(operationMeta => operationMeta.defaultSort = fields);
92
+ return decorator;
93
+ };
94
+ decorator.Filter = (field, operators, notes) => {
95
+ if (typeof operators === 'string')
96
+ operators = operators.split(/\s*[,| ]\s*/);
97
+ list.push(operationMeta => {
98
+ operationMeta.filters = operationMeta.filters || [];
99
+ operationMeta.filters.push(omitUndefined({ field, operators, notes }));
100
+ });
101
+ return decorator;
102
+ };
103
+ decorator.OutputPickFields = (...fields) => {
104
+ list.push(operationMeta => operationMeta.outputPickFields = fields);
105
+ return decorator;
106
+ };
107
+ decorator.OutputOmitFields = (...fields) => {
108
+ list.push(operationMeta => operationMeta.outputOmitFields = fields);
109
+ return decorator;
110
+ };
111
+ return decorator;
112
+ }
113
+ CollectionDecorator.FindMany = FindMany;
114
+ })(CollectionDecorator || (CollectionDecorator = {}));
115
+ /*
116
+ * Update PropertyDecorator
117
+ */
118
+ (function (CollectionDecorator) {
119
+ function Update(options) {
120
+ const list = [];
121
+ const decorator = createOperationDecorator('update', options, list);
122
+ decorator.InputMaxContentSize = (sizeInBytes) => {
123
+ list.push(operationMeta => operationMeta.inputMaxContentSize = sizeInBytes);
124
+ return decorator;
125
+ };
126
+ decorator.InputPickFields = (...fields) => {
127
+ list.push(operationMeta => operationMeta.inputPickFields = fields);
128
+ return decorator;
129
+ };
130
+ decorator.InputOmitFields = (...fields) => {
131
+ list.push(operationMeta => operationMeta.inputOmitFields = fields);
132
+ return decorator;
133
+ };
134
+ decorator.OutputPickFields = (...fields) => {
135
+ list.push(operationMeta => operationMeta.outputPickFields = fields);
136
+ return decorator;
137
+ };
138
+ decorator.OutputOmitFields = (...fields) => {
139
+ list.push(operationMeta => operationMeta.outputOmitFields = fields);
140
+ return decorator;
141
+ };
142
+ return decorator;
143
+ }
144
+ CollectionDecorator.Update = Update;
145
+ })(CollectionDecorator || (CollectionDecorator = {}));
146
+ /*
147
+ * UpdateMany PropertyDecorator
148
+ */
149
+ (function (CollectionDecorator) {
150
+ function UpdateMany(arg0) {
151
+ const list = [];
152
+ const options = typeof arg0 === 'string' ? { description: arg0 } : { ...arg0 };
153
+ const decorator = createOperationDecorator('updateMany', options, list);
154
+ decorator.InputMaxContentSize = (sizeInBytes) => {
155
+ list.push(operationMeta => operationMeta.inputMaxContentSize = sizeInBytes);
156
+ return decorator;
157
+ };
158
+ decorator.InputPickFields = (...fields) => {
159
+ list.push(operationMeta => operationMeta.inputPickFields = fields);
160
+ return decorator;
161
+ };
162
+ decorator.InputOmitFields = (...fields) => {
163
+ list.push(operationMeta => operationMeta.inputOmitFields = fields);
164
+ return decorator;
165
+ };
166
+ decorator.Filter = (field, operators, notes) => {
167
+ if (typeof operators === 'string')
168
+ operators = operators.split(/\s*[,| ]\s*/);
169
+ list.push(operationMeta => {
170
+ operationMeta.filters = operationMeta.filters || [];
171
+ operationMeta.filters.push(omitUndefined({ field, operators, notes }));
172
+ });
173
+ return decorator;
174
+ };
175
+ return decorator;
176
+ }
177
+ CollectionDecorator.UpdateMany = UpdateMany;
178
+ })(CollectionDecorator || (CollectionDecorator = {}));
@@ -1,20 +1,20 @@
1
1
  import merge from 'putil-merge';
2
2
  import { DECORATOR } from '../constants.js';
3
- import { CollectionDecorator } from '../decorators/collection-decorator.js';
4
3
  import { CollectionClass } from './collection-class.js';
4
+ import { CollectionDecorator } from './collection-decorator.js';
5
5
  /**
6
6
  * @class Collection
7
7
  * @decorator Collection
8
8
  */
9
9
  export const Collection = function (...args) {
10
- // Decorator
10
+ // ClassDecorator
11
11
  if (!this) {
12
12
  const [type, options] = args;
13
13
  return Collection[DECORATOR].call(undefined, type, options);
14
14
  }
15
15
  // Constructor
16
- const [document, init] = args;
17
- merge(this, new CollectionClass(document, init), { descriptor: true });
16
+ const [parent, init] = args;
17
+ merge(this, new CollectionClass(parent, init), { descriptor: true });
18
18
  };
19
19
  Collection.prototype = CollectionClass.prototype;
20
20
  Object.assign(Collection, CollectionDecorator);
@@ -0,0 +1,78 @@
1
+ import { NotAcceptableError, ResourceNotFoundError } from '../../exception/index.js';
2
+ import { ResponsiveMap } from '../../helpers/index.js';
3
+ import { OpraSchema } from '../../schema/index.js';
4
+ import { Resource } from './resource.js';
5
+ export class ContainerClass extends Resource {
6
+ constructor(owner, init) {
7
+ super(owner instanceof ContainerClass ? owner.document : owner, init);
8
+ this.kind = OpraSchema.Container.Kind;
9
+ this.resources = new ResponsiveMap();
10
+ this.parent = owner instanceof ContainerClass ? owner : undefined;
11
+ }
12
+ exportSchema(options) {
13
+ const schema = super.exportSchema(options);
14
+ if (this.resources.size) {
15
+ const resources = schema.resources = {};
16
+ for (const [name, r] of this.resources.entries()) {
17
+ resources[name] = r.exportSchema(options);
18
+ }
19
+ }
20
+ return schema;
21
+ }
22
+ getResource(path, silent) {
23
+ let resource;
24
+ if (path.includes('/')) {
25
+ const arr = path.split('/');
26
+ let i;
27
+ const l = arr.length;
28
+ let container = this;
29
+ for (i = 0; i < l; i++) {
30
+ resource = container.resources.get(arr[i]);
31
+ if (resource instanceof ContainerClass)
32
+ container = resource;
33
+ else
34
+ break;
35
+ }
36
+ // If no resource found or walking through path not completed
37
+ if (!resource || i < l - 1)
38
+ resource = undefined;
39
+ }
40
+ else
41
+ resource = this.resources.get(path);
42
+ if (resource || silent)
43
+ return resource;
44
+ throw new ResourceNotFoundError(path);
45
+ }
46
+ getContainer(path, silent) {
47
+ const t = this.getResource(path);
48
+ if (!t && silent)
49
+ return;
50
+ if (t && t.kind === OpraSchema.Container.Kind)
51
+ return t;
52
+ throw new NotAcceptableError(`Resource type "${t.name}" is not a Container`);
53
+ }
54
+ getCollection(path, silent) {
55
+ const t = this.getResource(path);
56
+ if (!t && silent)
57
+ return;
58
+ if (t && t.kind === OpraSchema.Collection.Kind)
59
+ return t;
60
+ throw new NotAcceptableError(`Resource type "${t.name}" is not a Collection`);
61
+ }
62
+ getSingleton(path, silent) {
63
+ const t = this.getResource(path);
64
+ if (!t && silent)
65
+ return;
66
+ if (t && t.kind === OpraSchema.Singleton.Kind)
67
+ return t;
68
+ throw new NotAcceptableError(`Resource type "${t.name}" is not a Singleton`);
69
+ }
70
+ getStorage(path, silent) {
71
+ const t = this.getResource(path);
72
+ if (!t && silent)
73
+ return;
74
+ if (t && t.kind === OpraSchema.Storage.Kind)
75
+ return t;
76
+ throw new NotAcceptableError(`Resource type "${t.name}" is not a Storage`);
77
+ }
78
+ }
@@ -0,0 +1,20 @@
1
+ import { OpraSchema } from '../../schema/index.js';
2
+ import { createActionDecorator } from './action-decorator.js';
3
+ import { ResourceDecorator } from './resource-decorator.js';
4
+ export function ContainerDecorator(options) {
5
+ return ResourceDecorator(OpraSchema.Container.Kind, options);
6
+ }
7
+ Object.assign(ContainerDecorator, ResourceDecorator);
8
+ /*
9
+ * Action PropertyDecorator
10
+ */
11
+ (function (ContainerDecorator) {
12
+ /**
13
+ * Action PropertyDecorator
14
+ */
15
+ function Action(options) {
16
+ const list = [];
17
+ return createActionDecorator(options, [], list);
18
+ }
19
+ ContainerDecorator.Action = Action;
20
+ })(ContainerDecorator || (ContainerDecorator = {}));
@@ -0,0 +1,25 @@
1
+ import merge from 'putil-merge';
2
+ import { DECORATOR } from '../constants.js';
3
+ import { ContainerClass } from './container-class.js';
4
+ import { ContainerDecorator } from './container-decorator.js';
5
+ /**
6
+ * @class Container
7
+ * @decorator Container
8
+ */
9
+ export const Container = function (...args) {
10
+ // ClassDecorator
11
+ if (!this) {
12
+ const [options] = args;
13
+ return Container[DECORATOR].call(undefined, options);
14
+ }
15
+ // Constructor
16
+ const [parent, init] = args;
17
+ merge(this, new ContainerClass(parent, init), { descriptor: true });
18
+ if (init.resources) {
19
+ const container = this;
20
+ init.resources.forEach(r => container.resources.set(r.name, r));
21
+ }
22
+ };
23
+ Container.prototype = ContainerClass.prototype;
24
+ Object.assign(Container, ContainerDecorator);
25
+ Container[DECORATOR] = ContainerDecorator;
@@ -0,0 +1,27 @@
1
+ import { ResponsiveMap } from '../../helpers/index.js';
2
+ import { Endpoint } from './endpoint.js';
3
+ import { Resource } from './resource.js';
4
+ export class CrudResource extends Resource {
5
+ constructor(parent, init) {
6
+ super(parent, init);
7
+ this.operations = new ResponsiveMap();
8
+ if (init.operations) {
9
+ for (const [name, meta] of Object.entries(init.operations)) {
10
+ this.operations.set(name, new Endpoint(this, name, meta));
11
+ }
12
+ }
13
+ }
14
+ getOperation(name) {
15
+ return this.operations.get(name);
16
+ }
17
+ exportSchema(options) {
18
+ const schema = super.exportSchema(options);
19
+ if (this.operations.size) {
20
+ schema.operations = {};
21
+ for (const operation of this.operations.values()) {
22
+ schema.operations[operation.name] = operation.exportSchema(options);
23
+ }
24
+ }
25
+ return schema;
26
+ }
27
+ }
@@ -1,40 +1,46 @@
1
+ import * as vg from 'valgen';
1
2
  import { omitUndefined, ResponsiveMap } from '../../helpers/index.js';
3
+ import { DataType } from '../data-type/data-type.js';
4
+ import { Parameter } from './parameter.js';
5
+ /**
6
+ *
7
+ * @class Endpoint
8
+ */
2
9
  export class Endpoint {
3
- constructor(init) {
10
+ constructor(resource, name, init) {
11
+ this.resource = resource;
12
+ this.name = name;
13
+ this.decode = vg.isAny();
14
+ this.encode = vg.isAny();
15
+ Object.assign(this, init);
4
16
  this.parameters = new ResponsiveMap();
5
- this.name = init.name;
6
- this.description = init.description;
7
17
  if (init.parameters) {
8
18
  for (const [n, p] of Object.entries(init.parameters)) {
9
- this.parameters.set(n, new Endpoint.Parameter(p));
19
+ this.defineParameter(n, p);
10
20
  }
11
21
  }
12
22
  }
13
- exportSchema() {
23
+ defineParameter(name, init) {
24
+ const type = init.type && init.type instanceof DataType
25
+ ? init.type : this.resource.document.getDataType(init.type || 'any');
26
+ const prm = new Parameter(name, {
27
+ ...init,
28
+ type
29
+ });
30
+ this.parameters.set(prm.name, prm);
31
+ return prm;
32
+ }
33
+ exportSchema(options) {
14
34
  const schema = omitUndefined({
15
35
  description: this.description
16
36
  });
17
37
  if (this.parameters.size) {
18
38
  schema.parameters = {};
19
39
  for (const [name, param] of this.parameters.entries()) {
20
- schema.parameters[name] = param.exportSchema();
40
+ if (!param.isBuiltin)
41
+ schema.parameters[name] = param.exportSchema(options);
21
42
  }
22
43
  }
23
44
  return schema;
24
45
  }
25
46
  }
26
- (function (Endpoint) {
27
- class Parameter {
28
- constructor(init) {
29
- Object.assign(this, init);
30
- }
31
- exportSchema() {
32
- return omitUndefined({
33
- type: typeof this.type === 'string' ? this.type : this.type.exportSchema(),
34
- description: this.description,
35
- isArray: this.isArray
36
- });
37
- }
38
- }
39
- Endpoint.Parameter = Parameter;
40
- })(Endpoint || (Endpoint = {}));
@@ -0,0 +1,23 @@
1
+ import { RESOURCE_METADATA } from '../constants.js';
2
+ export function createOperationDecorator(operation, options, list) {
3
+ const decorator = ((target, propertyKey) => {
4
+ if (propertyKey !== operation)
5
+ throw new TypeError(`Name of the handler name should be '${operation}'`);
6
+ const resourceMetadata = (Reflect.getOwnMetadata(RESOURCE_METADATA, target.constructor) || {});
7
+ resourceMetadata.operations = resourceMetadata.operations || {};
8
+ const operationMeta = { ...options };
9
+ resourceMetadata.operations[operation] = operationMeta;
10
+ for (const fn of list)
11
+ fn(operationMeta, target, propertyKey);
12
+ Reflect.defineMetadata(RESOURCE_METADATA, resourceMetadata, target.constructor);
13
+ });
14
+ decorator.Parameter = (name, arg0) => {
15
+ const parameterOptions = typeof arg0 === 'string' || typeof arg0 === 'function' ? { type: arg0 } : { ...arg0 };
16
+ list.push((operationMeta) => {
17
+ operationMeta.parameters = operationMeta.parameters || {};
18
+ operationMeta.parameters[name] = { ...parameterOptions };
19
+ });
20
+ return decorator;
21
+ };
22
+ return decorator;
23
+ }
@@ -0,0 +1,46 @@
1
+ import * as vg from 'valgen';
2
+ import { omitUndefined } from '../../helpers/index.js';
3
+ /**
4
+ *
5
+ * @class Parameter
6
+ */
7
+ export class Parameter {
8
+ constructor(name, init) {
9
+ this.name = name;
10
+ this.type = init.type;
11
+ this.description = init.description;
12
+ this.isArray = init.isArray;
13
+ this.default = init.default;
14
+ this.required = init.required;
15
+ this.deprecated = init.deprecated;
16
+ this.examples = init.examples;
17
+ this.isBuiltin = init.isBuiltin;
18
+ }
19
+ exportSchema(options) {
20
+ return omitUndefined({
21
+ type: this.type.name ? this.type.name : this.type.exportSchema(options),
22
+ description: this.description,
23
+ isArray: this.isArray,
24
+ default: this.default,
25
+ required: this.required,
26
+ deprecated: this.deprecated,
27
+ examples: this.examples
28
+ });
29
+ }
30
+ getDecoder() {
31
+ if (!this._decoder)
32
+ this._decoder = this.generateCodec('decode');
33
+ return this._decoder;
34
+ }
35
+ getEncoder() {
36
+ if (!this._encoder)
37
+ this._encoder = this.generateCodec('encode');
38
+ return this._encoder;
39
+ }
40
+ generateCodec(codec, options) {
41
+ let fn = this.type.generateCodec(codec, options);
42
+ if (this.isArray)
43
+ fn = vg.stringSplit(',');
44
+ return !options?.partial && this.required ? vg.required(fn) : vg.optional(fn);
45
+ }
46
+ }