@opra/common 0.25.5 → 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 +1826 -1338
  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 +24 -22
  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/wrap-exception.js +2 -1
  41. package/cjs/helpers/responsive-map.js +3 -3
  42. package/cjs/http/opra-url-path.js +2 -1
  43. package/cjs/schema/document/document-base.interface.js +2 -0
  44. package/cjs/schema/document/type-document.interface.js +2 -0
  45. package/cjs/schema/opra-schema.ns.js +3 -1
  46. package/cjs/schema/type-guards.js +3 -3
  47. package/esm/document/api-document.js +16 -220
  48. package/esm/document/data-type/complex-type-class.js +40 -19
  49. package/esm/document/data-type/complex-type.js +1 -1
  50. package/esm/document/data-type/data-type.js +2 -1
  51. package/esm/document/data-type/enum-type-class.js +15 -12
  52. package/esm/document/data-type/enum-type.js +26 -12
  53. package/esm/document/data-type/field-class.js +20 -3
  54. package/esm/document/data-type/field-decorator.js +0 -19
  55. package/esm/document/data-type/mapped-type-class.js +9 -11
  56. package/esm/document/data-type/mapped-type.js +1 -1
  57. package/esm/document/data-type/simple-type-class.js +15 -6
  58. package/esm/document/data-type/simple-type.js +1 -1
  59. package/esm/document/data-type/union-type-class.js +11 -9
  60. package/esm/document/document-base.js +20 -0
  61. package/esm/document/factory/api-document-factory.js +227 -0
  62. package/esm/document/factory/type-document-factory.js +320 -0
  63. package/esm/document/index.js +7 -1
  64. package/esm/document/resource/action-decorator.js +23 -0
  65. package/esm/document/resource/collection-class.js +95 -44
  66. package/esm/document/resource/collection-decorator.js +178 -0
  67. package/esm/document/resource/collection.js +4 -4
  68. package/esm/document/resource/container-class.js +78 -0
  69. package/esm/document/resource/container-decorator.js +20 -0
  70. package/esm/document/resource/container.js +25 -0
  71. package/esm/document/resource/crud-resource.js +27 -0
  72. package/esm/document/resource/endpoint.js +22 -20
  73. package/esm/document/resource/operation-decorator.js +23 -0
  74. package/esm/document/resource/parameter.js +46 -0
  75. package/esm/document/resource/resource-decorator.js +28 -0
  76. package/esm/document/resource/resource.js +20 -5
  77. package/esm/document/resource/singleton-class.js +58 -38
  78. package/esm/document/resource/singleton-decorator.js +53 -0
  79. package/esm/document/resource/singleton.js +4 -4
  80. package/esm/document/resource/storage-class.js +9 -15
  81. package/esm/document/resource/storage-decorator.js +62 -0
  82. package/esm/document/resource/storage.js +3 -3
  83. package/esm/document/type-document.js +191 -0
  84. package/esm/exception/http-errors/internal-server.error.js +1 -0
  85. package/esm/exception/wrap-exception.js +2 -1
  86. package/esm/helpers/responsive-map.js +3 -3
  87. package/esm/http/opra-url-path.js +1 -1
  88. package/esm/schema/document/document-base.interface.js +1 -0
  89. package/esm/schema/document/type-document.interface.js +1 -0
  90. package/esm/schema/opra-schema.ns.js +3 -1
  91. package/esm/schema/type-guards.js +1 -1
  92. package/package.json +2 -2
  93. package/types/document/api-document.d.ts +32 -73
  94. package/types/document/data-type/complex-type-class.d.ts +5 -5
  95. package/types/document/data-type/complex-type.d.ts +8 -3
  96. package/types/document/{decorators → data-type}/complex-type.decorator.d.ts +1 -1
  97. package/types/document/data-type/data-type.d.ts +11 -1
  98. package/types/document/data-type/enum-type-class.d.ts +6 -6
  99. package/types/document/data-type/enum-type.d.ts +12 -6
  100. package/types/document/data-type/field-class.d.ts +9 -1
  101. package/types/document/data-type/field-decorator.d.ts +1 -1
  102. package/types/document/data-type/field.d.ts +4 -3
  103. package/types/document/data-type/mapped-type-class.d.ts +5 -9
  104. package/types/document/data-type/mapped-type.d.ts +6 -7
  105. package/types/document/data-type/simple-type-class.d.ts +6 -3
  106. package/types/document/{decorators → data-type}/simple-type.decorator.d.ts +1 -1
  107. package/types/document/data-type/union-type-class.d.ts +2 -8
  108. package/types/document/data-type/union-type.d.ts +7 -6
  109. package/types/document/document-base.d.ts +10 -0
  110. package/types/document/factory/api-document-factory.d.ts +50 -0
  111. package/types/document/factory/type-document-factory.d.ts +56 -0
  112. package/types/document/index.d.ts +7 -1
  113. package/types/document/resource/action-decorator.d.ts +6 -0
  114. package/types/document/resource/collection-class.d.ts +17 -12
  115. package/types/document/resource/collection-decorator.d.ts +192 -0
  116. package/types/document/resource/collection.d.ts +11 -19
  117. package/types/document/resource/container-class.d.ts +66 -0
  118. package/types/document/resource/container-decorator.d.ts +37 -0
  119. package/types/document/resource/container.d.ts +25 -0
  120. package/types/document/resource/crud-resource.d.ts +16 -0
  121. package/types/document/resource/endpoint.d.ts +21 -21
  122. package/types/document/resource/operation-decorator.d.ts +6 -0
  123. package/types/document/resource/parameter.d.ts +35 -0
  124. package/types/document/resource/resource-decorator.d.ts +32 -0
  125. package/types/document/resource/resource.d.ts +15 -13
  126. package/types/document/resource/singleton-class.d.ts +15 -14
  127. package/types/document/resource/singleton-decorator.d.ts +125 -0
  128. package/types/document/resource/singleton.d.ts +11 -16
  129. package/types/document/resource/storage-class.d.ts +13 -6
  130. package/types/document/resource/storage-decorator.d.ts +98 -0
  131. package/types/document/resource/storage.d.ts +9 -12
  132. package/types/document/type-document.d.ts +68 -0
  133. package/types/http/opra-url-path.d.ts +1 -1
  134. package/types/schema/data-type/complex-type.interface.d.ts +1 -1
  135. package/types/schema/data-type/data-type.interface.d.ts +3 -3
  136. package/types/schema/data-type/enum-type.interface.d.ts +6 -7
  137. package/types/schema/data-type/mapped-type.interface.d.ts +4 -3
  138. package/types/schema/data-type/simple-type.interface.d.ts +3 -3
  139. package/types/schema/data-type/union-type.interface.d.ts +6 -4
  140. package/types/schema/document/api-document.interface.d.ts +11 -0
  141. package/types/schema/document/document-base.interface.d.ts +24 -0
  142. package/types/schema/document/type-document.interface.d.ts +6 -0
  143. package/types/schema/opra-schema.ns.d.ts +3 -1
  144. package/types/schema/resource/collection.interface.d.ts +31 -31
  145. package/types/schema/resource/container.interface.d.ts +4 -3
  146. package/types/schema/resource/resource.interface.d.ts +1 -1
  147. package/types/schema/resource/singleton.interface.d.ts +15 -10
  148. package/types/schema/resource/storage.interface.d.ts +49 -45
  149. package/types/schema/type-guards.d.ts +3 -2
  150. package/cjs/document/decorators/build-operation-decorator.js +0 -27
  151. package/cjs/document/decorators/collection-decorator.js +0 -30
  152. package/cjs/document/decorators/singleton.decorator.js +0 -25
  153. package/cjs/document/decorators/storage.decorator.js +0 -27
  154. package/cjs/document/factory/add-references.js +0 -20
  155. package/cjs/document/factory/create-document.js +0 -83
  156. package/cjs/document/factory/factory.js +0 -66
  157. package/cjs/document/factory/import-resource-class.js +0 -54
  158. package/cjs/document/factory/import-type-class.js +0 -146
  159. package/cjs/document/factory/index.js +0 -4
  160. package/cjs/document/factory/process-resources.js +0 -70
  161. package/cjs/document/factory/process-types.js +0 -191
  162. package/cjs/document/utils/generate-codec.js +0 -39
  163. package/esm/document/decorators/build-operation-decorator.js +0 -23
  164. package/esm/document/decorators/collection-decorator.js +0 -26
  165. package/esm/document/decorators/resource.decorator.js +0 -33
  166. package/esm/document/decorators/singleton.decorator.js +0 -21
  167. package/esm/document/decorators/storage.decorator.js +0 -23
  168. package/esm/document/factory/add-references.js +0 -16
  169. package/esm/document/factory/create-document.js +0 -77
  170. package/esm/document/factory/factory.js +0 -62
  171. package/esm/document/factory/import-resource-class.js +0 -48
  172. package/esm/document/factory/import-type-class.js +0 -136
  173. package/esm/document/factory/index.js +0 -1
  174. package/esm/document/factory/process-resources.js +0 -63
  175. package/esm/document/factory/process-types.js +0 -185
  176. package/esm/document/utils/generate-codec.js +0 -33
  177. package/types/document/decorators/build-operation-decorator.d.ts +0 -13
  178. package/types/document/decorators/collection-decorator.d.ts +0 -33
  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 -25
  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
@@ -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,44 +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';
2
5
  /**
3
6
  *
4
7
  * @class Endpoint
5
8
  */
6
9
  export class Endpoint {
7
- 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();
8
15
  Object.assign(this, init);
9
16
  this.parameters = new ResponsiveMap();
10
17
  if (init.parameters) {
11
18
  for (const [n, p] of Object.entries(init.parameters)) {
12
- this.parameters.set(n, new EndpointParameter(p));
19
+ this.defineParameter(n, p);
13
20
  }
14
21
  }
15
22
  }
16
- 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) {
17
34
  const schema = omitUndefined({
18
35
  description: this.description
19
36
  });
20
37
  if (this.parameters.size) {
21
38
  schema.parameters = {};
22
39
  for (const [name, param] of this.parameters.entries()) {
23
- schema.parameters[name] = param.exportSchema();
40
+ if (!param.isBuiltin)
41
+ schema.parameters[name] = param.exportSchema(options);
24
42
  }
25
43
  }
26
44
  return schema;
27
45
  }
28
46
  }
29
- /**
30
- *
31
- * @class EndpointParameter
32
- */
33
- export class EndpointParameter {
34
- constructor(init) {
35
- Object.assign(this, init);
36
- }
37
- exportSchema() {
38
- return omitUndefined({
39
- type: typeof this.type === 'string' ? this.type : this.type.exportSchema(),
40
- description: this.description,
41
- isArray: this.isArray
42
- });
43
- }
44
- }
@@ -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
+ }
@@ -0,0 +1,28 @@
1
+ import omit from 'lodash.omit';
2
+ import merge from 'putil-merge';
3
+ import { RESOURCE_METADATA } from '../constants.js';
4
+ export function ResourceDecorator(kind, meta) {
5
+ const namePattern = new RegExp(`^(.*)(${kind}|Resource|Controller)$`);
6
+ return function (target) {
7
+ let name = meta?.name;
8
+ if (!name) {
9
+ name = namePattern.exec(target.name)?.[1] || target.name;
10
+ // Containers may start with lowercase
11
+ if (kind === 'Container')
12
+ name = name.charAt(0).toLowerCase() + name.substring(1);
13
+ }
14
+ const metadata = { kind, name };
15
+ const baseMetadata = Reflect.getOwnMetadata(RESOURCE_METADATA, Object.getPrototypeOf(target));
16
+ if (baseMetadata)
17
+ merge(metadata, baseMetadata, { deep: true });
18
+ const oldMetadata = Reflect.getOwnMetadata(RESOURCE_METADATA, target);
19
+ if (oldMetadata)
20
+ merge(metadata, oldMetadata, { deep: true });
21
+ merge(metadata, {
22
+ kind,
23
+ name,
24
+ ...omit(meta, ['kind', 'name', 'controller'])
25
+ }, { deep: true });
26
+ Reflect.defineMetadata(RESOURCE_METADATA, metadata, target);
27
+ };
28
+ }
@@ -3,19 +3,34 @@ import { omitUndefined } from '../../helpers/object-utils.js';
3
3
  import { colorFgMagenta, colorFgYellow, colorReset, nodeInspectCustom } from '../utils/inspect.util.js';
4
4
  import { Endpoint } from './endpoint.js';
5
5
  export class Resource {
6
- constructor(document, init) {
6
+ constructor(parent, init) {
7
7
  this.actions = new ResponsiveMap();
8
- this.document = document;
8
+ if (parent instanceof Resource) {
9
+ this.document = parent.document;
10
+ this.parent = parent;
11
+ }
12
+ else
13
+ this.document = parent;
9
14
  this.name = init.name;
10
15
  this.description = init.description;
11
16
  this.controller = init.controller;
17
+ if (this.controller) {
18
+ this.ctor = Object.getPrototypeOf(this.controller).constructor;
19
+ }
20
+ else
21
+ this.ctor = init.ctor;
12
22
  if (init.actions) {
13
23
  for (const [name, meta] of Object.entries(init.actions)) {
14
- this.actions.set(name, new Endpoint({ ...meta, name }));
24
+ this.actions.set(name, new Endpoint(this, name, meta));
15
25
  }
16
26
  }
17
27
  }
18
- exportSchema() {
28
+ getFullPath() {
29
+ if (this.parent && this.parent.name)
30
+ return this.parent?.getFullPath() + '/' + this.name;
31
+ return this.name;
32
+ }
33
+ exportSchema(options) {
19
34
  const schema = omitUndefined({
20
35
  kind: this.kind,
21
36
  description: this.description,
@@ -23,7 +38,7 @@ export class Resource {
23
38
  if (this.actions.size) {
24
39
  schema.actions = {};
25
40
  for (const action of this.actions.values()) {
26
- schema.actions[action.name] = action.exportSchema();
41
+ schema.actions[action.name] = action.exportSchema(options);
27
42
  }
28
43
  }
29
44
  return schema;
@@ -1,49 +1,69 @@
1
- import { omitUndefined } from '../../helpers/index.js';
2
1
  import { OpraSchema } from '../../schema/index.js';
3
- import { generateCodec } from '../utils/generate-codec.js';
4
- import { Resource } from './resource.js';
5
- export class SingletonClass extends Resource {
6
- constructor(document, init) {
7
- super(document, init);
8
- this._decoders = {};
9
- this._encoders = {};
2
+ import { CrudResource } from './crud-resource.js';
3
+ export class SingletonClass extends CrudResource {
4
+ constructor(parent, init) {
5
+ super(parent, init);
10
6
  this.kind = OpraSchema.Singleton.Kind;
11
- this.controller = init.controller;
12
- this.operations = { ...init.operations };
13
7
  this.type = init.type;
8
+ // ------------------
9
+ let endpoint = this.operations.get('create');
10
+ if (endpoint) {
11
+ endpoint.returnType = this.type;
12
+ endpoint.decode = this.type.generateCodec('decode', {
13
+ partial: true,
14
+ pick: endpoint.inputPickFields,
15
+ omit: endpoint.inputOmitFields,
16
+ });
17
+ endpoint.encode = this.type.generateCodec('encode', {
18
+ partial: true,
19
+ pick: endpoint.outputPickFields,
20
+ omit: endpoint.outputOmitFields,
21
+ });
22
+ endpoint.defineParameter('pick', { type: 'string', isArray: true, isBuiltin: true });
23
+ endpoint.defineParameter('omit', { type: 'string', isArray: true, isBuiltin: true });
24
+ endpoint.defineParameter('include', { type: 'string', isArray: true, isBuiltin: true });
25
+ }
26
+ // ------------------
27
+ endpoint = this.operations.get('get');
28
+ if (endpoint) {
29
+ endpoint.returnType = this.type;
30
+ endpoint.encode = this.type.generateCodec('encode', {
31
+ partial: true,
32
+ pick: endpoint.outputPickFields,
33
+ omit: endpoint.outputOmitFields,
34
+ });
35
+ endpoint.defineParameter('pick', { type: 'string', isArray: true, isBuiltin: true });
36
+ endpoint.defineParameter('omit', { type: 'string', isArray: true, isBuiltin: true });
37
+ endpoint.defineParameter('include', { type: 'string', isArray: true, isBuiltin: true });
38
+ }
39
+ // ------------------
40
+ endpoint = this.operations.get('update');
41
+ if (endpoint) {
42
+ endpoint.returnType = this.type;
43
+ endpoint.decode = this.type.generateCodec('decode', {
44
+ pick: endpoint.inputPickFields,
45
+ omit: endpoint.inputOmitFields,
46
+ });
47
+ endpoint.encode = this.type.generateCodec('encode', {
48
+ partial: true,
49
+ pick: endpoint.outputPickFields,
50
+ omit: endpoint.outputOmitFields,
51
+ });
52
+ endpoint.defineParameter('pick', { type: 'string', isArray: true, isBuiltin: true });
53
+ endpoint.defineParameter('omit', { type: 'string', isArray: true, isBuiltin: true });
54
+ endpoint.defineParameter('include', { type: 'string', isArray: true, isBuiltin: true });
55
+ }
14
56
  }
15
- exportSchema() {
57
+ getOperation(name) {
58
+ return super.getOperation(name);
59
+ }
60
+ exportSchema(options) {
16
61
  return {
17
- ...super.exportSchema(),
18
- ...omitUndefined({
19
- type: this.type.name || 'any',
20
- operations: this.operations
21
- })
62
+ ...super.exportSchema(options),
63
+ type: this.type.name || 'any'
22
64
  };
23
65
  }
24
66
  normalizeFieldPath(path) {
25
67
  return this.type.normalizeFieldPath(path);
26
68
  }
27
- getDecoder(endpoint) {
28
- let decoder = this._decoders[endpoint];
29
- if (decoder)
30
- return decoder;
31
- const options = {
32
- partial: endpoint !== 'create'
33
- };
34
- decoder = generateCodec(this.type, 'decode', options);
35
- this._decoders[endpoint] = decoder;
36
- return decoder;
37
- }
38
- getEncoder(endpoint) {
39
- let encoder = this._encoders[endpoint];
40
- if (encoder)
41
- return encoder;
42
- const options = {
43
- partial: true
44
- };
45
- encoder = generateCodec(this.type, 'encode', options);
46
- this._encoders[endpoint] = encoder;
47
- return encoder;
48
- }
49
69
  }