@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
@@ -12,7 +12,8 @@ export class DataType {
12
12
  this.description = init?.description;
13
13
  this.isAnonymous = !this.name;
14
14
  }
15
- exportSchema() {
15
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
16
+ exportSchema(options) {
16
17
  return omitUndefined({
17
18
  kind: this.kind,
18
19
  description: this.description
@@ -6,22 +6,25 @@ export class EnumTypeClass extends DataType {
6
6
  constructor(document, init) {
7
7
  super(document, init);
8
8
  this.kind = OpraSchema.EnumType.Kind;
9
+ this.enumObject = init.enumObject;
9
10
  this.base = init.base;
10
- this.ownValues = init.values;
11
- this.ownMeanings = init.meanings || {};
11
+ this.ownValues = { ...init.values };
12
12
  this.values = { ...this.base?.values, ...this.ownValues };
13
- this.meanings = { ...this.base?.meanings, ...this.ownMeanings };
14
- this.decode = vg.isEnum(Object.values(this.values));
15
- this.encode = vg.isEnum(Object.values(this.values));
13
+ this.decode = vg.isEnum(Object.keys(this.values));
14
+ this.encode = vg.isEnum(Object.keys(this.values));
16
15
  }
17
16
  exportSchema() {
18
- const out = DataType.prototype.exportSchema.call(this);
19
- Object.assign(out, omitUndefined({
20
- base: this.base ?
21
- (this.base.name ? this.base.name : this.base.exportSchema()) : undefined,
22
- values: this.ownValues,
23
- meanings: this.ownMeanings
24
- }));
17
+ const out = super.exportSchema();
18
+ out.values = {};
19
+ Object.entries(this.values).forEach(([k, i]) => {
20
+ out.values[k] = omitUndefined({ key: i.key, description: i.description });
21
+ });
25
22
  return out;
26
23
  }
24
+ generateCodec(codec) {
25
+ if (codec === 'encode')
26
+ return this.encode;
27
+ else
28
+ return this.decode;
29
+ }
27
30
  }
@@ -1,6 +1,6 @@
1
1
  import 'reflect-metadata';
2
- import omit from 'lodash.omit';
3
2
  import merge from 'putil-merge';
3
+ import { omitUndefined } from '../../helpers/index.js';
4
4
  import { OpraSchema } from '../../schema/index.js';
5
5
  import { DATATYPE_METADATA } from '../constants.js';
6
6
  import { EnumTypeClass } from './enum-type-class.js';
@@ -11,20 +11,34 @@ export const EnumType = function (...args) {
11
11
  // Injector
12
12
  if (!this) {
13
13
  const [enumSource, options] = args;
14
- const values = Array.isArray(enumSource)
15
- ? enumSource.reduce((obj, v) => {
16
- obj[v] = v;
17
- return obj;
18
- }, {})
19
- : enumSource;
14
+ let values = {};
15
+ if (Array.isArray(enumSource)) {
16
+ values = {};
17
+ enumSource.forEach(k => {
18
+ const description = options?.meanings?.[k];
19
+ values[k] = omitUndefined({ description });
20
+ });
21
+ }
22
+ else {
23
+ Object.keys(enumSource).forEach(k => {
24
+ const description = options?.meanings?.[k];
25
+ values[enumSource[k]] = omitUndefined({ key: k, description });
26
+ });
27
+ }
20
28
  const metadata = {
21
29
  kind: OpraSchema.EnumType.Kind,
22
- values
30
+ values,
31
+ base: options?.base,
32
+ name: options?.name,
33
+ description: options?.description
23
34
  };
24
- if (options)
25
- Object.assign(metadata, omit(options, ['kind', 'values']));
26
- Reflect.defineMetadata(DATATYPE_METADATA, metadata, enumSource);
27
- return values;
35
+ Object.defineProperty(enumSource, DATATYPE_METADATA, {
36
+ value: metadata,
37
+ enumerable: false,
38
+ configurable: true,
39
+ writable: true
40
+ });
41
+ return metadata;
28
42
  }
29
43
  // Constructor
30
44
  const [document, init] = args;
@@ -1,10 +1,11 @@
1
+ import * as vg from 'valgen';
1
2
  import { omitUndefined } from '../../helpers/index.js';
2
3
  export class FieldClass {
3
4
  constructor(owner, init) {
4
5
  this.owner = owner;
5
- this.name = init.name;
6
6
  this.origin = init.origin || owner;
7
7
  this.type = init.type;
8
+ this.name = init.name;
8
9
  this.description = init.description;
9
10
  this.isArray = init.isArray;
10
11
  this.default = init.default;
@@ -14,9 +15,9 @@ export class FieldClass {
14
15
  this.deprecated = init.deprecated;
15
16
  this.examples = init.examples;
16
17
  }
17
- exportSchema() {
18
+ exportSchema(options) {
18
19
  return omitUndefined({
19
- type: this.type.name ? this.type.name : this.type.exportSchema(),
20
+ type: this.type.name ? this.type.name : this.type.exportSchema(options),
20
21
  description: this.description,
21
22
  isArray: this.isArray,
22
23
  default: this.default,
@@ -27,4 +28,20 @@ export class FieldClass {
27
28
  examples: this.examples
28
29
  });
29
30
  }
31
+ getDecoder() {
32
+ if (!this._decoder)
33
+ this._decoder = this.generateCodec('decode');
34
+ return this._decoder;
35
+ }
36
+ getEncoder() {
37
+ if (!this._encoder)
38
+ this._encoder = this.generateCodec('encode');
39
+ return this._encoder;
40
+ }
41
+ generateCodec(codec, options) {
42
+ let fn = this.type.generateCodec(codec, options);
43
+ if (this.isArray)
44
+ fn = vg.isArray(fn);
45
+ return !options?.partial && this.required ? vg.required(fn) : vg.optional(fn);
46
+ }
30
47
  }
@@ -1,7 +1,6 @@
1
1
  import { omitUndefined } from '../../helpers/index.js';
2
2
  import { OpraSchema } from '../../schema/index.js';
3
3
  import { DATATYPE_METADATA } from '../constants.js';
4
- import { EnumType } from './enum-type.js';
5
4
  export function FieldDecorator(options) {
6
5
  return function (target, propertyKey) {
7
6
  if (typeof propertyKey !== 'string')
@@ -12,30 +11,12 @@ export function FieldDecorator(options) {
12
11
  const designType = Reflect.getMetadata('design:type', target, propertyKey);
13
12
  const elemMeta = metadata.fields[propertyKey] = {
14
13
  ...options,
15
- enum: undefined,
16
14
  designType
17
15
  };
18
16
  if (designType === Array) {
19
17
  elemMeta.isArray = true;
20
18
  delete elemMeta.designType;
21
19
  }
22
- if (options?.enum) {
23
- elemMeta.type = undefined;
24
- if (Array.isArray(options.enum)) {
25
- const enumObj = options.enum.reduce((o, v) => {
26
- o[v] = v;
27
- return o;
28
- }, {});
29
- EnumType(enumObj);
30
- elemMeta.enum = enumObj;
31
- }
32
- else {
33
- const m = Reflect.getOwnMetadata(DATATYPE_METADATA, options?.enum);
34
- if (!OpraSchema.isEnumType(m))
35
- throw new TypeError(`Invalid "enum" value. Did you forget to set metadata using EnumType() method?`);
36
- elemMeta.enum = options.enum;
37
- }
38
- }
39
20
  Reflect.defineMetadata(DATATYPE_METADATA, omitUndefined(metadata), target.constructor);
40
21
  };
41
22
  }
@@ -1,7 +1,7 @@
1
- import { omitUndefined, ResponsiveMap } from '../../helpers/index.js';
1
+ import { omitUndefined } from '../../helpers/index.js';
2
2
  import { OpraSchema } from '../../schema/index.js';
3
- import { DataType } from './data-type.js';
4
- export class MappedTypeClass extends DataType {
3
+ import { ComplexTypeClass } from './complex-type-class.js';
4
+ export class MappedTypeClass extends ComplexTypeClass {
5
5
  constructor(document, init) {
6
6
  super(document, init);
7
7
  this.kind = OpraSchema.MappedType.Kind;
@@ -9,21 +9,19 @@ export class MappedTypeClass extends DataType {
9
9
  own.pick = init.pick;
10
10
  own.omit = init.omit;
11
11
  this.kind = OpraSchema.MappedType.Kind;
12
- this.type = init.type;
13
12
  this.pick = own.pick;
14
13
  this.omit = own.omit;
15
- this.fields = new ResponsiveMap();
16
- this.additionalFields = this.type.additionalFields;
17
14
  const isInheritedPredicate = getIsInheritedPredicateFn(init.pick, init.omit);
18
- for (const [elemName, elem] of this.type.fields.entries()) {
19
- if (isInheritedPredicate(elemName))
20
- this.fields.set(elemName, elem);
15
+ for (const fieldName of this.fields.keys()) {
16
+ if (!isInheritedPredicate(fieldName)) {
17
+ this.fields.delete(fieldName);
18
+ }
21
19
  }
22
20
  }
21
+ // @ts-ignore
23
22
  exportSchema() {
24
- const out = DataType.prototype.exportSchema.call(this);
23
+ const out = super.exportSchema();
25
24
  Object.assign(out, omitUndefined({
26
- type: this.type.name ? this.type.name : this.type.exportSchema(),
27
25
  pick: this.own.pick,
28
26
  omit: this.own.omit,
29
27
  }));
@@ -43,7 +43,7 @@ export const MappedType = function (...args) {
43
43
  throw new TypeError(`Class "${mappedSource}" is not a ${OpraSchema.ComplexType.Kind}`);
44
44
  const metadata = {
45
45
  kind: 'MappedType',
46
- type: mappedSource
46
+ base: mappedSource
47
47
  };
48
48
  if (options.pick)
49
49
  metadata.pick = options.pick;
@@ -1,4 +1,5 @@
1
1
  import * as vg from 'valgen';
2
+ import { omitUndefined } from '../../helpers/index.js';
2
3
  import { OpraSchema } from '../../schema/index.js';
3
4
  import { DataType } from './data-type.js';
4
5
  /**
@@ -12,13 +13,21 @@ export class SimpleTypeClass extends DataType {
12
13
  this.decode = init.decoder || init.base?.decode || vg.isAny();
13
14
  this.encode = init.encoder || init.base?.encode || vg.isAny();
14
15
  }
15
- exportSchema() {
16
+ exportSchema(options) {
16
17
  // noinspection UnnecessaryLocalVariableJS
17
- const out = super.exportSchema();
18
- // Object.assign(out, omitUndefined({
19
- // base: this.base ?
20
- // (this.base.name ? this.base.name : this.base.exportSchema()) : undefined,
21
- // }));
18
+ const out = super.exportSchema(options);
19
+ Object.assign(out, omitUndefined({
20
+ base: this.base ?
21
+ (this.base.name ? this.base.name : this.base.exportSchema(options)) : undefined,
22
+ decode: !options?.webSafe ? this.decode : undefined,
23
+ encode: !options?.webSafe ? this.encode : undefined
24
+ }));
22
25
  return out;
23
26
  }
27
+ generateCodec(codec) {
28
+ if (codec === 'encode')
29
+ return this.encode;
30
+ else
31
+ return this.decode;
32
+ }
24
33
  }
@@ -1,7 +1,7 @@
1
1
  import 'reflect-metadata';
2
2
  import merge from 'putil-merge';
3
3
  import { DECORATOR } from '../constants.js';
4
- import { SimpleTypeDecorator } from '../decorators/simple-type.decorator.js';
4
+ import { SimpleTypeDecorator } from './simple-type.decorator.js';
5
5
  import { SimpleTypeClass } from './simple-type-class.js';
6
6
  /**
7
7
  * @class SimpleType
@@ -1,13 +1,10 @@
1
- import { omitUndefined, ResponsiveMap } from '../../helpers/index.js';
2
1
  import { OpraSchema } from '../../schema/index.js';
3
2
  import { ComplexType } from './complex-type.js';
4
- import { DataType } from './data-type.js';
5
3
  import { MappedType } from './mapped-type.js';
6
- export class UnionTypeClass extends DataType {
4
+ export class UnionTypeClass extends ComplexType {
7
5
  constructor(document, init) {
8
6
  super(document, init);
9
7
  this.kind = OpraSchema.UnionType.Kind;
10
- this.fields = new ResponsiveMap();
11
8
  const own = this.own;
12
9
  own.types = [];
13
10
  const UnionType = Object.getPrototypeOf(this).constructor;
@@ -16,17 +13,22 @@ export class UnionTypeClass extends DataType {
16
13
  throw new TypeError(`${OpraSchema.UnionType.Kind} shall contain ${OpraSchema.ComplexType.Kind}, ` +
17
14
  `${OpraSchema.UnionType.Kind} of ${OpraSchema.MappedType.Kind} types.`);
18
15
  own.types.push(base);
19
- if (base.additionalFields)
20
- this.additionalFields = base.additionalFields;
16
+ if (base.additionalFields === true && this.additionalFields !== true) {
17
+ // @ts-ignore
18
+ this.additionalFields = true;
19
+ }
20
+ else if (base.additionalFields === 'error' && !this.additionalFields) {
21
+ // @ts-ignore
22
+ this.additionalFields = 'error';
23
+ }
21
24
  this.fields.setAll(base.fields);
22
25
  }
23
26
  this.types = [...own.types];
24
27
  }
28
+ // @ts-ignore
25
29
  exportSchema() {
26
30
  const out = super.exportSchema();
27
- Object.assign(out, omitUndefined({
28
- types: this.own.types.map(t => t.name ? t.name : t.exportSchema())
29
- }));
31
+ out.types = this.own.types.map(t => t.name ? t.name : t.exportSchema());
30
32
  return out;
31
33
  }
32
34
  }
@@ -0,0 +1,20 @@
1
+ import { cloneObject, omitUndefined } from '../helpers/index.js';
2
+ import { OpraSchema } from '../schema/index.js';
3
+ export class DocumentBase {
4
+ constructor() {
5
+ this.info = {
6
+ version: '',
7
+ title: ''
8
+ };
9
+ }
10
+ /**
11
+ * Export as OPRA schema definition object
12
+ */
13
+ exportSchema() {
14
+ return omitUndefined({
15
+ version: OpraSchema.SpecVersion,
16
+ url: this.url,
17
+ info: cloneObject(this.info, true)
18
+ });
19
+ }
20
+ }
@@ -0,0 +1,227 @@
1
+ import { cloneObject, resolveThunk, ResponsiveMap } from '../../helpers/index.js';
2
+ import { OpraSchema } from '../../schema/index.js';
3
+ import { ApiDocument } from '../api-document.js';
4
+ import { RESOURCE_METADATA } from '../constants.js';
5
+ import { ComplexType } from '../data-type/complex-type.js';
6
+ import { EnumType } from '../data-type/enum-type.js';
7
+ import { Collection } from '../resource/collection.js';
8
+ import { Container } from '../resource/container.js';
9
+ import { Singleton } from '../resource/singleton.js';
10
+ import { Storage } from '../resource/storage.js';
11
+ import { TypeDocumentFactory } from './type-document-factory.js';
12
+ /**
13
+ * @class ApiDocumentFactory
14
+ */
15
+ export class ApiDocumentFactory extends TypeDocumentFactory {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.resourceQueue = new ResponsiveMap();
19
+ }
20
+ /**
21
+ * Creates ApiDocument instance from given schema object
22
+ * @param init
23
+ */
24
+ static async createDocument(init) {
25
+ const factory = new ApiDocumentFactory();
26
+ const document = factory.document = new ApiDocument();
27
+ await factory.initDocument(init);
28
+ return document;
29
+ }
30
+ /**
31
+ * Downloads schema from the given URL and creates the document instance * @param url
32
+ */
33
+ static async createDocumentFromUrl(url) {
34
+ const factory = new ApiDocumentFactory();
35
+ const document = factory.document = new ApiDocument();
36
+ await factory.initDocumentFromUrl(url);
37
+ return document;
38
+ }
39
+ async initDocument(init) {
40
+ await super.initDocument(init);
41
+ const processContainer = async (container, containerInit) => {
42
+ if (!containerInit.resources)
43
+ return;
44
+ if (Array.isArray(containerInit.resources)) {
45
+ for (const thunk of containerInit.resources) {
46
+ const initArguments = await this.importResourceInstance(thunk);
47
+ container.resources.set(initArguments.name, await this.createResource(container, initArguments));
48
+ }
49
+ }
50
+ else
51
+ for (const [name, schema] of Object.entries(containerInit.resources)) {
52
+ const initArguments = await this.importResourceSchema(name, schema);
53
+ container.resources.set(initArguments.name, await this.createResource(container, initArguments));
54
+ }
55
+ container.resources.sort();
56
+ };
57
+ if (init.root) {
58
+ this.curPath.push('/root');
59
+ await processContainer(this.document.root, init.root);
60
+ this.curPath.pop();
61
+ this.document.invalidate();
62
+ }
63
+ return this.document;
64
+ }
65
+ async importResourceSchema(name, schema) {
66
+ const convertEndpoints = async (source) => {
67
+ if (!source)
68
+ return;
69
+ const output = {};
70
+ for (const [kA, oA] of Object.entries(source)) {
71
+ /* istanbul ignore next */
72
+ if (!oA)
73
+ continue;
74
+ let parameters;
75
+ if (oA.parameters) {
76
+ parameters = {};
77
+ for (const [kP, oP] of Object.entries(oA.parameters)) {
78
+ if (oP.enum) {
79
+ oP.type = EnumType(oP.enum, { name: kP + 'Enum' });
80
+ }
81
+ parameters[kP] = {
82
+ ...oP,
83
+ type: await this.importDataType(oP.type || 'any')
84
+ };
85
+ }
86
+ }
87
+ output[kA] = { ...oA[kA], parameters };
88
+ }
89
+ return output;
90
+ };
91
+ if (schema.kind === 'Collection') {
92
+ return {
93
+ ...schema,
94
+ kind: schema.kind,
95
+ name,
96
+ type: await this.importDataType(schema.type),
97
+ actions: await convertEndpoints(schema.actions),
98
+ operations: await convertEndpoints(schema.operations),
99
+ };
100
+ }
101
+ else if (schema.kind === 'Singleton') {
102
+ return {
103
+ ...schema,
104
+ kind: schema.kind,
105
+ name,
106
+ type: await this.importDataType(schema.type),
107
+ actions: await convertEndpoints(schema.actions),
108
+ operations: await convertEndpoints(schema.operations),
109
+ };
110
+ }
111
+ else if (schema.kind === 'Storage') {
112
+ return {
113
+ ...schema,
114
+ name,
115
+ actions: await convertEndpoints(schema.actions),
116
+ operations: await convertEndpoints(schema.operations),
117
+ };
118
+ }
119
+ else if (schema.kind === 'Container') {
120
+ const resources = [];
121
+ if (schema.resources) {
122
+ for (const [k, o] of Object.entries(schema.resources)) {
123
+ const rinit = await this.importResourceSchema(k, o);
124
+ resources.push(rinit);
125
+ }
126
+ }
127
+ return {
128
+ ...schema,
129
+ name,
130
+ resources,
131
+ actions: await convertEndpoints(schema.actions)
132
+ };
133
+ }
134
+ throw new TypeError(`Can not import resource schema (${schema.kind})`);
135
+ }
136
+ async importResourceInstance(thunk) {
137
+ thunk = await resolveThunk(thunk);
138
+ let ctor;
139
+ let metadata;
140
+ let instance;
141
+ if (typeof thunk === 'function') {
142
+ ctor = thunk;
143
+ }
144
+ else {
145
+ ctor = Object.getPrototypeOf(thunk).constructor;
146
+ instance = thunk;
147
+ if (!Reflect.hasMetadata(RESOURCE_METADATA, ctor) &&
148
+ OpraSchema.isResource(thunk) && typeof thunk.controller === 'object') {
149
+ ctor = Object.getPrototypeOf(thunk.controller).constructor;
150
+ metadata = thunk;
151
+ instance = thunk.controller;
152
+ }
153
+ }
154
+ metadata = metadata || Reflect.getMetadata(RESOURCE_METADATA, ctor);
155
+ if (!metadata && OpraSchema.isResource(metadata))
156
+ throw new TypeError(`Class "${ctor.name}" doesn't have a valid Resource metadata`);
157
+ const convertEndpoints = async (source) => {
158
+ if (!source)
159
+ return;
160
+ const output = {};
161
+ for (const [kA, oA] of Object.entries(source)) {
162
+ let parameters;
163
+ if (oA.parameters) {
164
+ parameters = {};
165
+ for (const [kP, oP] of Object.entries(oA.parameters)) {
166
+ if (oP.enum) {
167
+ oP.type = EnumType(oP.enum, { name: kP + 'Enum' });
168
+ }
169
+ parameters[kP] = {
170
+ ...oP,
171
+ type: await this.importDataType(oP.type || 'any')
172
+ };
173
+ }
174
+ }
175
+ output[kA] = { ...oA, parameters };
176
+ }
177
+ return output;
178
+ };
179
+ // Clone metadata to prevent changing its contents
180
+ const initArguments = cloneObject(metadata);
181
+ initArguments.controller = instance;
182
+ initArguments.ctor = ctor;
183
+ if (initArguments.actions)
184
+ initArguments.actions = await convertEndpoints(initArguments.actions);
185
+ if (initArguments.kind === 'Collection' || initArguments.kind === 'Singleton') {
186
+ const dataType = await this.importDataType((metadata).type);
187
+ if (!dataType)
188
+ throw new TypeError(`Unable to determine data type of "${initArguments.name}" resource`);
189
+ if (!(dataType instanceof ComplexType))
190
+ throw new TypeError(`Data type of "${initArguments.name}" resource is not a ComplexType`);
191
+ initArguments.type = dataType;
192
+ if (initArguments.operations)
193
+ initArguments.operations = await convertEndpoints(initArguments.operations);
194
+ }
195
+ else if (initArguments.kind === 'Container') {
196
+ const oldResources = initArguments.resources;
197
+ if (Array.isArray(oldResources)) {
198
+ initArguments.resources = [];
199
+ for (const t of oldResources) {
200
+ const rinit = await this.importResourceInstance(t);
201
+ initArguments.resources.push(rinit);
202
+ }
203
+ }
204
+ }
205
+ return initArguments;
206
+ }
207
+ async createResource(container, initArguments) {
208
+ if (initArguments.kind === 'Collection')
209
+ return new Collection(container, initArguments);
210
+ if (initArguments.kind === 'Singleton')
211
+ return new Singleton(container, initArguments);
212
+ if (initArguments.kind === 'Storage')
213
+ return new Storage(container, initArguments);
214
+ if (initArguments.kind === 'Container') {
215
+ const newContainer = new Container(container, { ...initArguments, resources: undefined });
216
+ if (initArguments.resources) {
217
+ for (const r of initArguments.resources) {
218
+ const res = await this.createResource(newContainer, r);
219
+ newContainer.resources.set(res.name, res);
220
+ }
221
+ }
222
+ return newContainer;
223
+ }
224
+ else
225
+ throw new Error(`Unknown resource type ${initArguments.kind}`);
226
+ }
227
+ }