@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.
- package/browser.js +1826 -1338
- package/cjs/document/api-document.js +16 -220
- package/cjs/document/data-type/complex-type-class.js +41 -19
- package/cjs/document/data-type/complex-type.js +1 -1
- package/cjs/document/data-type/data-type.js +2 -1
- package/cjs/document/data-type/enum-type-class.js +15 -12
- package/cjs/document/data-type/enum-type.js +28 -14
- package/cjs/document/data-type/field-class.js +21 -3
- package/cjs/document/data-type/field-decorator.js +0 -19
- package/cjs/document/data-type/mapped-type-class.js +8 -10
- package/cjs/document/data-type/mapped-type.js +1 -1
- package/cjs/document/data-type/simple-type-class.js +17 -8
- package/cjs/document/data-type/simple-type.js +1 -1
- package/cjs/document/data-type/union-type-class.js +15 -13
- package/cjs/document/document-base.js +24 -0
- package/cjs/document/factory/api-document-factory.js +231 -0
- package/cjs/document/factory/type-document-factory.js +324 -0
- package/cjs/document/index.js +7 -1
- package/cjs/document/resource/action-decorator.js +27 -0
- package/cjs/document/resource/collection-class.js +95 -44
- package/cjs/document/resource/collection-decorator.js +182 -0
- package/cjs/document/resource/collection.js +4 -4
- package/cjs/document/resource/container-class.js +82 -0
- package/cjs/document/resource/container-decorator.js +24 -0
- package/cjs/document/resource/container.js +29 -0
- package/cjs/document/resource/crud-resource.js +31 -0
- package/cjs/document/resource/endpoint.js +24 -22
- package/cjs/document/resource/operation-decorator.js +27 -0
- package/cjs/document/resource/parameter.js +51 -0
- package/cjs/document/{decorators/resource.decorator.js → resource/resource-decorator.js} +9 -14
- package/cjs/document/resource/resource.js +20 -5
- package/cjs/document/resource/singleton-class.js +60 -40
- package/cjs/document/resource/singleton-decorator.js +57 -0
- package/cjs/document/resource/singleton.js +4 -4
- package/cjs/document/resource/storage-class.js +11 -17
- package/cjs/document/resource/storage-decorator.js +66 -0
- package/cjs/document/resource/storage.js +3 -3
- package/cjs/document/type-document.js +195 -0
- package/cjs/exception/http-errors/internal-server.error.js +1 -0
- package/cjs/exception/wrap-exception.js +2 -1
- package/cjs/helpers/responsive-map.js +3 -3
- package/cjs/http/opra-url-path.js +2 -1
- package/cjs/schema/document/document-base.interface.js +2 -0
- package/cjs/schema/document/type-document.interface.js +2 -0
- package/cjs/schema/opra-schema.ns.js +3 -1
- package/cjs/schema/type-guards.js +3 -3
- package/esm/document/api-document.js +16 -220
- package/esm/document/data-type/complex-type-class.js +40 -19
- package/esm/document/data-type/complex-type.js +1 -1
- package/esm/document/data-type/data-type.js +2 -1
- package/esm/document/data-type/enum-type-class.js +15 -12
- package/esm/document/data-type/enum-type.js +26 -12
- package/esm/document/data-type/field-class.js +20 -3
- package/esm/document/data-type/field-decorator.js +0 -19
- package/esm/document/data-type/mapped-type-class.js +9 -11
- package/esm/document/data-type/mapped-type.js +1 -1
- package/esm/document/data-type/simple-type-class.js +15 -6
- package/esm/document/data-type/simple-type.js +1 -1
- package/esm/document/data-type/union-type-class.js +11 -9
- package/esm/document/document-base.js +20 -0
- package/esm/document/factory/api-document-factory.js +227 -0
- package/esm/document/factory/type-document-factory.js +320 -0
- package/esm/document/index.js +7 -1
- package/esm/document/resource/action-decorator.js +23 -0
- package/esm/document/resource/collection-class.js +95 -44
- package/esm/document/resource/collection-decorator.js +178 -0
- package/esm/document/resource/collection.js +4 -4
- package/esm/document/resource/container-class.js +78 -0
- package/esm/document/resource/container-decorator.js +20 -0
- package/esm/document/resource/container.js +25 -0
- package/esm/document/resource/crud-resource.js +27 -0
- package/esm/document/resource/endpoint.js +22 -20
- package/esm/document/resource/operation-decorator.js +23 -0
- package/esm/document/resource/parameter.js +46 -0
- package/esm/document/resource/resource-decorator.js +28 -0
- package/esm/document/resource/resource.js +20 -5
- package/esm/document/resource/singleton-class.js +58 -38
- package/esm/document/resource/singleton-decorator.js +53 -0
- package/esm/document/resource/singleton.js +4 -4
- package/esm/document/resource/storage-class.js +9 -15
- package/esm/document/resource/storage-decorator.js +62 -0
- package/esm/document/resource/storage.js +3 -3
- package/esm/document/type-document.js +191 -0
- package/esm/exception/http-errors/internal-server.error.js +1 -0
- package/esm/exception/wrap-exception.js +2 -1
- package/esm/helpers/responsive-map.js +3 -3
- package/esm/http/opra-url-path.js +1 -1
- package/esm/schema/document/document-base.interface.js +1 -0
- package/esm/schema/document/type-document.interface.js +1 -0
- package/esm/schema/opra-schema.ns.js +3 -1
- package/esm/schema/type-guards.js +1 -1
- package/package.json +2 -2
- package/types/document/api-document.d.ts +32 -73
- package/types/document/data-type/complex-type-class.d.ts +5 -5
- package/types/document/data-type/complex-type.d.ts +8 -3
- package/types/document/{decorators → data-type}/complex-type.decorator.d.ts +1 -1
- package/types/document/data-type/data-type.d.ts +11 -1
- package/types/document/data-type/enum-type-class.d.ts +6 -6
- package/types/document/data-type/enum-type.d.ts +12 -6
- package/types/document/data-type/field-class.d.ts +9 -1
- package/types/document/data-type/field-decorator.d.ts +1 -1
- package/types/document/data-type/field.d.ts +4 -3
- package/types/document/data-type/mapped-type-class.d.ts +5 -9
- package/types/document/data-type/mapped-type.d.ts +6 -7
- package/types/document/data-type/simple-type-class.d.ts +6 -3
- package/types/document/{decorators → data-type}/simple-type.decorator.d.ts +1 -1
- package/types/document/data-type/union-type-class.d.ts +2 -8
- package/types/document/data-type/union-type.d.ts +7 -6
- package/types/document/document-base.d.ts +10 -0
- package/types/document/factory/api-document-factory.d.ts +50 -0
- package/types/document/factory/type-document-factory.d.ts +56 -0
- package/types/document/index.d.ts +7 -1
- package/types/document/resource/action-decorator.d.ts +6 -0
- package/types/document/resource/collection-class.d.ts +17 -12
- package/types/document/resource/collection-decorator.d.ts +192 -0
- package/types/document/resource/collection.d.ts +11 -19
- package/types/document/resource/container-class.d.ts +66 -0
- package/types/document/resource/container-decorator.d.ts +37 -0
- package/types/document/resource/container.d.ts +25 -0
- package/types/document/resource/crud-resource.d.ts +16 -0
- package/types/document/resource/endpoint.d.ts +21 -21
- package/types/document/resource/operation-decorator.d.ts +6 -0
- package/types/document/resource/parameter.d.ts +35 -0
- package/types/document/resource/resource-decorator.d.ts +32 -0
- package/types/document/resource/resource.d.ts +15 -13
- package/types/document/resource/singleton-class.d.ts +15 -14
- package/types/document/resource/singleton-decorator.d.ts +125 -0
- package/types/document/resource/singleton.d.ts +11 -16
- package/types/document/resource/storage-class.d.ts +13 -6
- package/types/document/resource/storage-decorator.d.ts +98 -0
- package/types/document/resource/storage.d.ts +9 -12
- package/types/document/type-document.d.ts +68 -0
- package/types/http/opra-url-path.d.ts +1 -1
- package/types/schema/data-type/complex-type.interface.d.ts +1 -1
- package/types/schema/data-type/data-type.interface.d.ts +3 -3
- package/types/schema/data-type/enum-type.interface.d.ts +6 -7
- package/types/schema/data-type/mapped-type.interface.d.ts +4 -3
- package/types/schema/data-type/simple-type.interface.d.ts +3 -3
- package/types/schema/data-type/union-type.interface.d.ts +6 -4
- package/types/schema/document/api-document.interface.d.ts +11 -0
- package/types/schema/document/document-base.interface.d.ts +24 -0
- package/types/schema/document/type-document.interface.d.ts +6 -0
- package/types/schema/opra-schema.ns.d.ts +3 -1
- package/types/schema/resource/collection.interface.d.ts +31 -31
- package/types/schema/resource/container.interface.d.ts +4 -3
- package/types/schema/resource/resource.interface.d.ts +1 -1
- package/types/schema/resource/singleton.interface.d.ts +15 -10
- package/types/schema/resource/storage.interface.d.ts +49 -45
- package/types/schema/type-guards.d.ts +3 -2
- package/cjs/document/decorators/build-operation-decorator.js +0 -27
- package/cjs/document/decorators/collection-decorator.js +0 -30
- package/cjs/document/decorators/singleton.decorator.js +0 -25
- package/cjs/document/decorators/storage.decorator.js +0 -27
- package/cjs/document/factory/add-references.js +0 -20
- package/cjs/document/factory/create-document.js +0 -83
- package/cjs/document/factory/factory.js +0 -66
- package/cjs/document/factory/import-resource-class.js +0 -54
- package/cjs/document/factory/import-type-class.js +0 -146
- package/cjs/document/factory/index.js +0 -4
- package/cjs/document/factory/process-resources.js +0 -70
- package/cjs/document/factory/process-types.js +0 -191
- package/cjs/document/utils/generate-codec.js +0 -39
- package/esm/document/decorators/build-operation-decorator.js +0 -23
- package/esm/document/decorators/collection-decorator.js +0 -26
- package/esm/document/decorators/resource.decorator.js +0 -33
- package/esm/document/decorators/singleton.decorator.js +0 -21
- package/esm/document/decorators/storage.decorator.js +0 -23
- package/esm/document/factory/add-references.js +0 -16
- package/esm/document/factory/create-document.js +0 -77
- package/esm/document/factory/factory.js +0 -62
- package/esm/document/factory/import-resource-class.js +0 -48
- package/esm/document/factory/import-type-class.js +0 -136
- package/esm/document/factory/index.js +0 -1
- package/esm/document/factory/process-resources.js +0 -63
- package/esm/document/factory/process-types.js +0 -185
- package/esm/document/utils/generate-codec.js +0 -33
- package/types/document/decorators/build-operation-decorator.d.ts +0 -13
- package/types/document/decorators/collection-decorator.d.ts +0 -33
- package/types/document/decorators/resource.decorator.d.ts +0 -9
- package/types/document/decorators/singleton.decorator.d.ts +0 -25
- package/types/document/decorators/storage.decorator.d.ts +0 -25
- package/types/document/factory/add-references.d.ts +0 -4
- package/types/document/factory/create-document.d.ts +0 -12
- package/types/document/factory/factory.d.ts +0 -63
- package/types/document/factory/import-resource-class.d.ts +0 -10
- package/types/document/factory/import-type-class.d.ts +0 -17
- package/types/document/factory/index.d.ts +0 -1
- package/types/document/factory/process-resources.d.ts +0 -9
- package/types/document/factory/process-types.d.ts +0 -6
- package/types/document/utils/generate-codec.d.ts +0 -10
- package/types/schema/document.interface.d.ts +0 -34
- /package/cjs/document/{decorators → data-type}/complex-type.decorator.js +0 -0
- /package/cjs/document/{decorators → data-type}/simple-type.decorator.js +0 -0
- /package/cjs/schema/{document.interface.js → document/api-document.interface.js} +0 -0
- /package/esm/document/{decorators → data-type}/complex-type.decorator.js +0 -0
- /package/esm/document/{decorators → data-type}/simple-type.decorator.js +0 -0
- /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
|
-
|
|
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.
|
|
14
|
-
this.
|
|
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 =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
|
1
|
+
import { omitUndefined } from '../../helpers/index.js';
|
|
2
2
|
import { OpraSchema } from '../../schema/index.js';
|
|
3
|
-
import {
|
|
4
|
-
export class MappedTypeClass extends
|
|
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
|
|
19
|
-
if (isInheritedPredicate(
|
|
20
|
-
this.fields.
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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 '
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
}
|