@opra/common 0.18.4 → 0.19.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 (122) hide show
  1. package/browser.js +1225 -910
  2. package/cjs/document/api-document.js +55 -38
  3. package/cjs/document/data-type/api-field.js +5 -5
  4. package/cjs/document/data-type/builtin/any.type.js +3 -5
  5. package/cjs/document/data-type/builtin/base64.type.js +5 -28
  6. package/cjs/document/data-type/builtin/bigint.type.js +7 -25
  7. package/cjs/document/data-type/builtin/boolean.type.js +5 -18
  8. package/cjs/document/data-type/builtin/date.type.js +13 -9
  9. package/cjs/document/data-type/builtin/index.js +3 -1
  10. package/cjs/document/data-type/builtin/integer.type.js +5 -18
  11. package/cjs/document/data-type/builtin/number.type.js +5 -23
  12. package/cjs/document/data-type/builtin/object.type.js +4 -9
  13. package/cjs/document/data-type/builtin/string.type.js +5 -14
  14. package/cjs/document/data-type/builtin/time.type.js +11 -23
  15. package/cjs/document/data-type/builtin/timestamp.type.js +8 -20
  16. package/cjs/document/data-type/builtin/uuid.type.js +15 -0
  17. package/cjs/document/data-type/complex-type.js +151 -92
  18. package/cjs/document/data-type/data-type.js +32 -31
  19. package/cjs/document/data-type/enum-type.js +49 -43
  20. package/cjs/document/data-type/mapped-type.js +115 -70
  21. package/cjs/document/data-type/simple-type.js +46 -45
  22. package/cjs/document/data-type/union-type.js +69 -36
  23. package/cjs/document/factory/create-document.js +5 -3
  24. package/cjs/document/factory/factory.js +23 -20
  25. package/cjs/document/factory/import-type-class.js +13 -4
  26. package/cjs/document/resource/collection.js +55 -59
  27. package/cjs/document/resource/resource.js +10 -21
  28. package/cjs/document/resource/singleton.js +36 -39
  29. package/cjs/exception/common-errors/validation.error.js +11 -0
  30. package/cjs/exception/index.js +2 -1
  31. package/cjs/exception/{enums/issue-severity.enum.js → issue-severity.enum.js} +1 -1
  32. package/cjs/exception/opra-exception.js +2 -2
  33. package/cjs/filter/antlr/OpraFilterLexer.js +1 -1
  34. package/cjs/filter/antlr/OpraFilterParser.js +1 -1
  35. package/cjs/filter/errors.js +5 -0
  36. package/cjs/http/enums/http-headers-codes.enum.js +1 -1
  37. package/cjs/http/enums/http-status-codes.enum.js +1 -1
  38. package/cjs/http/http-request-message.js +1 -1
  39. package/cjs/http/http-response-message.js +1 -1
  40. package/cjs/schema/data-type/complex-type.interface.js +1 -1
  41. package/cjs/schema/data-type/enum-type.interface.js +1 -1
  42. package/cjs/schema/data-type/mapped-type.interface.js +1 -1
  43. package/cjs/schema/data-type/simple-type.interface.js +1 -1
  44. package/cjs/schema/data-type/union-type.interface.js +1 -1
  45. package/cjs/schema/index.js +3 -41
  46. package/cjs/schema/opra-schema.ns.js +18 -0
  47. package/cjs/schema/resource/collection.interface.js +1 -1
  48. package/cjs/schema/resource/container.interface.js +1 -1
  49. package/cjs/schema/resource/singleton.interface.js +1 -1
  50. package/esm/document/api-document.js +55 -38
  51. package/esm/document/data-type/api-field.js +5 -5
  52. package/esm/document/data-type/builtin/any.type.js +2 -4
  53. package/esm/document/data-type/builtin/base64.type.js +4 -27
  54. package/esm/document/data-type/builtin/bigint.type.js +6 -24
  55. package/esm/document/data-type/builtin/boolean.type.js +4 -17
  56. package/esm/document/data-type/builtin/date.type.js +12 -8
  57. package/esm/document/data-type/builtin/index.js +3 -1
  58. package/esm/document/data-type/builtin/integer.type.js +4 -17
  59. package/esm/document/data-type/builtin/number.type.js +4 -22
  60. package/esm/document/data-type/builtin/object.type.js +3 -8
  61. package/esm/document/data-type/builtin/string.type.js +4 -13
  62. package/esm/document/data-type/builtin/time.type.js +10 -22
  63. package/esm/document/data-type/builtin/timestamp.type.js +7 -19
  64. package/esm/document/data-type/builtin/uuid.type.js +12 -0
  65. package/esm/document/data-type/complex-type.js +151 -92
  66. package/esm/document/data-type/data-type.js +31 -31
  67. package/esm/document/data-type/enum-type.js +49 -43
  68. package/esm/document/data-type/mapped-type.js +114 -70
  69. package/esm/document/data-type/simple-type.js +45 -44
  70. package/esm/document/data-type/union-type.js +68 -36
  71. package/esm/document/factory/create-document.js +6 -4
  72. package/esm/document/factory/factory.js +23 -20
  73. package/esm/document/factory/import-type-class.js +13 -4
  74. package/esm/document/resource/collection.js +55 -59
  75. package/esm/document/resource/resource.js +9 -21
  76. package/esm/document/resource/singleton.js +36 -39
  77. package/esm/exception/common-errors/validation.error.js +7 -0
  78. package/esm/exception/index.js +2 -1
  79. package/esm/exception/opra-exception.js +2 -2
  80. package/esm/filter/antlr/OpraFilterLexer.js +2 -1
  81. package/esm/filter/antlr/OpraFilterParser.js +2 -1
  82. package/esm/filter/errors.js +5 -0
  83. package/esm/schema/index.js +2 -41
  84. package/esm/schema/opra-schema.ns.js +15 -0
  85. package/package.json +5 -3
  86. package/types/document/api-document.d.ts +3 -2
  87. package/types/document/data-type/builtin/base64.type.d.ts +0 -4
  88. package/types/document/data-type/builtin/bigint.type.d.ts +1 -5
  89. package/types/document/data-type/builtin/boolean.type.d.ts +0 -3
  90. package/types/document/data-type/builtin/date.type.d.ts +1 -3
  91. package/types/document/data-type/builtin/index.d.ts +3 -1
  92. package/types/document/data-type/builtin/integer.type.d.ts +1 -5
  93. package/types/document/data-type/builtin/number.type.d.ts +0 -4
  94. package/types/document/data-type/builtin/object.type.d.ts +0 -1
  95. package/types/document/data-type/builtin/string.type.d.ts +0 -3
  96. package/types/document/data-type/builtin/time.type.d.ts +1 -6
  97. package/types/document/data-type/builtin/timestamp.type.d.ts +0 -3
  98. package/types/document/data-type/builtin/uuid.type.d.ts +2 -0
  99. package/types/document/data-type/complex-type.d.ts +29 -16
  100. package/types/document/data-type/data-type.d.ts +19 -15
  101. package/types/document/data-type/enum-type.d.ts +15 -5
  102. package/types/document/data-type/mapped-type.d.ts +27 -5
  103. package/types/document/data-type/simple-type.d.ts +26 -12
  104. package/types/document/data-type/union-type.d.ts +20 -5
  105. package/types/document/factory/factory.d.ts +3 -2
  106. package/types/document/resource/collection.d.ts +11 -9
  107. package/types/document/resource/resource.d.ts +3 -9
  108. package/types/document/resource/singleton.d.ts +7 -5
  109. package/types/exception/common-errors/validation.error.d.ts +4 -0
  110. package/types/exception/error-issue.d.ts +1 -1
  111. package/types/exception/index.d.ts +2 -1
  112. package/types/exception/opra-exception.d.ts +4 -2
  113. package/types/filter/errors.d.ts +3 -0
  114. package/types/schema/data-type/enum-type.interface.d.ts +5 -5
  115. package/types/schema/data-type/simple-type.interface.d.ts +5 -11
  116. package/types/schema/index.d.ts +2 -51
  117. package/types/schema/opra-schema.ns.d.ts +15 -0
  118. package/cjs/document/data-type/builtin/guid.type.js +0 -35
  119. package/esm/document/data-type/builtin/guid.type.js +0 -32
  120. package/types/document/data-type/builtin/guid.type.d.ts +0 -7
  121. /package/esm/exception/{enums/issue-severity.enum.js → issue-severity.enum.js} +0 -0
  122. /package/types/exception/{enums/issue-severity.enum.d.ts → issue-severity.enum.d.ts} +0 -0
@@ -1,25 +1,12 @@
1
1
  import { __decorate } from "tslib";
2
- import { toBoolean } from 'putil-varhelpers';
2
+ import { isBoolean } from 'valgen';
3
3
  import { SimpleType } from '../simple-type.js';
4
- let BooleanType = class BooleanType {
5
- decode(v) {
6
- if (v == null)
7
- return v;
8
- return toBoolean(v);
9
- }
10
- encode(v) {
11
- if (v == null)
12
- return v;
13
- return toBoolean(v);
14
- }
15
- coerce(v) {
16
- return this.decode(v);
17
- }
4
+ export let BooleanType = class BooleanType {
18
5
  };
19
6
  BooleanType = __decorate([
20
7
  SimpleType({
21
8
  description: 'Simple true/false value',
22
- ctor: Boolean
9
+ decoder: isBoolean(),
10
+ encoder: isBoolean()
23
11
  })
24
12
  ], BooleanType);
25
- export { BooleanType };
@@ -1,15 +1,19 @@
1
1
  import { __decorate } from "tslib";
2
+ import { isDate, isDateString } from 'valgen';
2
3
  import { SimpleType } from '../simple-type.js';
3
- import { TimestampType } from './timestamp.type.js';
4
- let DateType = class DateType extends TimestampType {
5
- constructor() {
6
- super(...arguments);
7
- this.format = 'YYYY-MM-DD';
8
- }
4
+ export let DateType = class DateType {
9
5
  };
10
6
  DateType = __decorate([
11
7
  SimpleType({
12
- description: 'full-date notation as defined by RFC 3339, section 5.6, for example, 2021-04-18',
8
+ description: 'Date only string, for example, 2021-04-18',
9
+ decoder: isDate({
10
+ format: ['YYYY-MM-DD', 'YYYY',
11
+ 'YYYY-MM-DDTHH:mm:ss',
12
+ 'YYYY-MM-DDTHH:mm',
13
+ 'YYYY-MM-DD HH:mm:ss',
14
+ 'YYYY-MM-DD HH:mm'
15
+ ]
16
+ }),
17
+ encoder: isDateString({ format: 'YYYY-MM-DD' })
13
18
  })
14
19
  ], DateType);
15
- export { DateType };
@@ -3,8 +3,10 @@ export * from './base64.type.js';
3
3
  export * from './bigint.type.js';
4
4
  export * from './boolean.type.js';
5
5
  export * from './date.type.js';
6
- export * from './guid.type.js';
6
+ export * from './uuid.type.js';
7
7
  export * from './integer.type.js';
8
8
  export * from './number.type.js';
9
9
  export * from './object.type.js';
10
10
  export * from './string.type.js';
11
+ export * from './time.type.js';
12
+ export * from './timestamp.type.js';
@@ -1,25 +1,12 @@
1
1
  import { __decorate } from "tslib";
2
- import { toInt } from 'putil-varhelpers';
2
+ import { isInteger } from 'valgen';
3
3
  import { SimpleType } from '../simple-type.js';
4
- import { NumberType } from './number.type.js';
5
- let IntegerType = class IntegerType extends NumberType {
6
- decode(v) {
7
- if (v == null)
8
- return v;
9
- return toInt(super.decode(v));
10
- }
11
- encode(v) {
12
- if (v == null)
13
- return v;
14
- return toInt(super.encode(v));
15
- }
16
- coerce(v) {
17
- return this.decode(v);
18
- }
4
+ export let IntegerType = class IntegerType {
19
5
  };
20
6
  IntegerType = __decorate([
21
7
  SimpleType({
22
8
  description: 'An integer number',
9
+ decoder: isInteger(),
10
+ encoder: isInteger()
23
11
  })
24
12
  ], IntegerType);
25
- export { IntegerType };
@@ -1,30 +1,12 @@
1
1
  import { __decorate } from "tslib";
2
- import { toNumber } from 'putil-varhelpers';
2
+ import { isNumber } from 'valgen';
3
3
  import { SimpleType } from '../simple-type.js';
4
- let NumberType = class NumberType {
5
- decode(v) {
6
- if (v == null)
7
- return v;
8
- const x = toNumber(v);
9
- if (x)
10
- this.validate(x);
11
- return x;
12
- }
13
- encode(v) {
14
- return this.decode(v);
15
- }
16
- coerce(v) {
17
- return this.decode(v);
18
- }
19
- validate(v) {
20
- if (typeof v !== 'number' || isNaN(v))
21
- throw new TypeError(`Invalid number value "${v}"`);
22
- }
4
+ export let NumberType = class NumberType {
23
5
  };
24
6
  NumberType = __decorate([
25
7
  SimpleType({
26
8
  description: 'Both Integer as well as Floating-Point numbers',
27
- ctor: Number
9
+ decoder: isNumber(),
10
+ encoder: isNumber()
28
11
  })
29
12
  ], NumberType);
30
- export { NumberType };
@@ -1,17 +1,12 @@
1
1
  import { __decorate } from "tslib";
2
2
  import { ComplexType } from '../complex-type.js';
3
- let ObjectType = class ObjectType {
4
- coerce(v) {
5
- if (v == null)
6
- return v;
7
- return typeof v === 'object' ? v : {};
8
- }
3
+ export let ObjectType = class ObjectType {
9
4
  };
10
5
  ObjectType = __decorate([
11
6
  ComplexType({
12
7
  name: 'object',
13
8
  description: 'A non modelled object',
14
- additionalFields: true
9
+ additionalFields: true,
10
+ ctor: Object
15
11
  })
16
12
  ], ObjectType);
17
- export { ObjectType };
@@ -1,21 +1,12 @@
1
1
  import { __decorate } from "tslib";
2
- import { toString } from 'putil-varhelpers';
2
+ import { isString } from 'valgen';
3
3
  import { SimpleType } from '../simple-type.js';
4
- let StringType = class StringType {
5
- decode(v) {
6
- return toString(v);
7
- }
8
- encode(v) {
9
- return toString(v);
10
- }
11
- coerce(v) {
12
- return this.decode(v);
13
- }
4
+ export let StringType = class StringType {
14
5
  };
15
6
  StringType = __decorate([
16
7
  SimpleType({
17
8
  description: 'A sequence of characters',
18
- ctor: String
9
+ decoder: isString(),
10
+ encoder: isString(),
19
11
  })
20
12
  ], StringType);
21
- export { StringType };
@@ -1,29 +1,17 @@
1
1
  import { __decorate } from "tslib";
2
+ import { isDateString } from 'valgen';
2
3
  import { SimpleType } from '../simple-type.js';
3
- import { StringType } from './string.type.js';
4
- const TIME_PATTERN = /^([01][0-9]|2[0-3]):?([0-5][0-9]):?([0-5][0-9])?(?:\.(\d+))?$/;
5
- let TimeType = class TimeType extends StringType {
6
- decode(v) {
7
- if (v == null)
8
- return v;
9
- this.validate(v);
10
- return v;
11
- }
12
- encode(v) {
13
- return this.decode(v);
14
- }
15
- coerce(v) {
16
- return this.decode(v);
17
- }
18
- validate(v) {
19
- // noinspection SuspiciousTypeOfGuard
20
- if (typeof v === 'string' && !TIME_PATTERN.test(v))
21
- throw new TypeError(`Invalid Time value "${v}"`);
22
- }
4
+ export let TimeType = class TimeType {
23
5
  };
24
6
  TimeType = __decorate([
25
7
  SimpleType({
26
- description: 'Time formatted string',
8
+ description: 'Time string in 24h format, for example, 18:23:00',
9
+ decoder: isDateString({
10
+ format: ['HH:mm:ss', 'HH:mm'],
11
+ onFail: () => '{{label}} is not a valid time'
12
+ }),
13
+ encoder: isDateString({ format: ['HH:mm:ss', 'HH:mm'],
14
+ onFail: () => '{{label}} is not a valid time'
15
+ })
27
16
  })
28
17
  ], TimeType);
29
- export { TimeType };
@@ -1,26 +1,14 @@
1
1
  import { __decorate } from "tslib";
2
- import dayjs from 'dayjs';
2
+ import { isDate, isDateString } from 'valgen';
3
3
  import { SimpleType } from '../simple-type.js';
4
- let TimestampType = class TimestampType {
5
- constructor() {
6
- this.format = 'YYYY-MM-DDTHH:mm:ss';
7
- }
8
- decode(v) {
9
- return dayjs(v).toDate();
10
- }
11
- encode(v) {
12
- if (!v)
13
- return undefined;
14
- const d = dayjs(v);
15
- if (!d.isValid())
16
- throw new TypeError(`Invalid date value ${v}`);
17
- return dayjs(v).format(this.format);
18
- }
4
+ export let TimestampType = class TimestampType {
19
5
  };
20
6
  TimestampType = __decorate([
21
7
  SimpleType({
22
- description: 'date-time notation as defined by RFC 3339, section 5.6, for example, 2021-04-18T09:12:53',
23
- ctor: Date
8
+ description: 'Timestamp, for example, 2021-04-18T09:12:53',
9
+ decoder: isDate({
10
+ format: ['YYYY-MM-DDTHH:mm:ss', 'YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD', 'YYYY']
11
+ }),
12
+ encoder: isDateString({ format: 'YYYY-MM-DDTHH:mm:ss' })
24
13
  })
25
14
  ], TimestampType);
26
- export { TimestampType };
@@ -0,0 +1,12 @@
1
+ import { __decorate } from "tslib";
2
+ import { isUUID } from 'valgen';
3
+ import { SimpleType } from '../simple-type.js';
4
+ export let UuidType = class UuidType {
5
+ };
6
+ UuidType = __decorate([
7
+ SimpleType({
8
+ description: 'A Universal Unique Identifier (UUID) value',
9
+ decoder: isUUID(),
10
+ encoder: isUUID()
11
+ })
12
+ ], UuidType);
@@ -1,4 +1,6 @@
1
1
  import omit from 'lodash.omit';
2
+ import merge from 'putil-merge';
3
+ import * as vg from 'valgen';
2
4
  import { omitUndefined, ResponsiveMap } from '../../helpers/index.js';
3
5
  import { OpraSchema } from '../../schema/index.js';
4
6
  import { METADATA_KEY, TYPENAME_PATTERN } from '../constants.js';
@@ -7,106 +9,64 @@ import { DataType } from './data-type.js';
7
9
  /**
8
10
  * @class ComplexType
9
11
  */
10
- export const ComplexType = function (...args) {
11
- // ClassDecorator
12
- if (!this) {
13
- const [options] = args;
14
- return function (target) {
15
- const name = options?.name || target.name.match(TYPENAME_PATTERN)?.[1] || target.name;
16
- let metadata = Reflect.getOwnMetadata(METADATA_KEY, target);
17
- if (!metadata) {
18
- metadata = {};
19
- Reflect.defineMetadata(METADATA_KEY, metadata, target);
20
- }
21
- metadata.kind = OpraSchema.ComplexType.Kind;
22
- metadata.name = name;
23
- // Merge options
24
- if (options)
25
- Object.assign(metadata, omit(options, ['kind', 'name', 'base', 'ctor', 'fields']));
26
- };
27
- }
28
- // Constructor
29
- // call super()
30
- DataType.apply(this, args);
31
- const [, init] = args;
32
- const _this = this;
33
- const own = _this.own;
34
- own.ctor = init?.ctor;
35
- own.fields = new ResponsiveMap();
36
- own.abstract = init?.abstract;
37
- own.additionalFields = init?.additionalFields;
38
- _this.kind = OpraSchema.ComplexType.Kind;
39
- _this.base = init?.base;
40
- _this.ctor = own.ctor || Object;
41
- _this.abstract = own.abstract;
42
- _this.additionalFields = own.additionalFields;
43
- _this.fields = new ResponsiveMap();
44
- if (_this.base) {
45
- if (_this.additionalFields == null)
46
- _this.additionalFields = _this.base.additionalFields;
47
- if (own.ctor == null && _this.base instanceof ComplexType)
48
- _this.ctor = _this.base.ctor;
49
- if (_this.base.fields)
50
- for (const [k, el] of _this.base.fields.entries()) {
51
- const newEl = new ApiField(_this, el);
52
- _this.fields.set(k, newEl);
53
- }
54
- }
55
- };
56
- Object.setPrototypeOf(ComplexType.prototype, DataType.prototype);
57
- const proto = {
58
- extendsFrom(t) {
59
- const base = t instanceof DataType ? t : this.document.getDataType(t);
12
+ class ComplexTypeClass extends DataType {
13
+ constructor(document, init) {
14
+ super(document, init);
15
+ this.kind = OpraSchema.ComplexType.Kind;
16
+ const own = this.own = {};
17
+ own.ctor = init?.ctor;
18
+ own.abstract = init?.abstract;
19
+ own.additionalFields = init?.additionalFields;
20
+ own.fields = new ResponsiveMap();
21
+ this.kind = OpraSchema.ComplexType.Kind;
22
+ this.base = init?.base;
23
+ this.ctor = own.ctor || Object;
24
+ this.abstract = own.abstract;
25
+ this.additionalFields = own.additionalFields;
26
+ this.fields = new ResponsiveMap();
60
27
  if (this.base) {
61
- if (this.base === base)
62
- return true;
63
- return this.base.extendsFrom(base);
64
- }
65
- return false;
66
- },
67
- exportSchema() {
68
- const out = DataType.prototype.exportSchema.call(this);
69
- Object.assign(out, omitUndefined({
70
- base: this.base ?
71
- (this.base.name ? this.base.name : this.base.exportSchema()) : undefined,
72
- abstract: this.own.abstract,
73
- additionalFields: this.own.additionalFields
74
- }));
75
- if (this.own.fields.size) {
76
- const fields = out.fields = {};
77
- for (const field of this.own.fields.values()) {
78
- fields[field.name] = field.exportSchema();
79
- }
28
+ if (this.additionalFields == null)
29
+ this.additionalFields = this.base.additionalFields;
30
+ if (own.ctor == null && this.base instanceof ComplexType)
31
+ this.ctor = this.base.ctor;
32
+ if (this.base.fields)
33
+ for (const [k, el] of this.base.fields.entries()) {
34
+ const newEl = new ApiField(this, el);
35
+ this.fields.set(k, newEl);
36
+ }
80
37
  }
81
- return omitUndefined(out);
82
- },
38
+ }
83
39
  addField(init) {
84
40
  const field = new ApiField(this, init);
85
41
  this.own.fields.set(field.name, field);
86
42
  this.fields.set(field.name, field);
87
43
  return field;
88
- },
44
+ }
89
45
  findField(nameOrPath) {
90
46
  let field;
91
- for (const [, f] of this.iteratePath(nameOrPath, true)) {
92
- if (!f)
93
- return;
94
- field = f;
47
+ if (nameOrPath.includes('.')) {
48
+ for (const [, f] of this.iteratePath(nameOrPath, true)) {
49
+ if (!f)
50
+ return;
51
+ field = f;
52
+ }
53
+ return field;
95
54
  }
96
- return field;
97
- },
55
+ return this.fields.get(nameOrPath);
56
+ }
98
57
  getField(nameOrPath) {
99
58
  let field;
100
- for (const [, f, path] of this.iteratePath(nameOrPath)) {
101
- if (!f)
102
- throw new Error(`Invalid field definition "${path}"`);
103
- field = f;
59
+ if (nameOrPath.includes('.')) {
60
+ for (const [, f] of this.iteratePath(nameOrPath)) {
61
+ field = f;
62
+ }
104
63
  }
105
- /* istanbul ignore next */
64
+ else
65
+ field = this.fields.get(nameOrPath);
106
66
  if (!field)
107
- throw new Error(`Invalid field definition "${nameOrPath}"`);
67
+ throw new Error(`Unknown field "${nameOrPath}"`);
108
68
  return field;
109
- },
69
+ }
110
70
  iteratePath(path, silent) {
111
71
  const arr = path.split('.');
112
72
  const len = arr.length;
@@ -148,16 +108,115 @@ const proto = {
148
108
  };
149
109
  }
150
110
  };
151
- },
152
- normalizeFieldPath(path) {
153
- if (Array.isArray(path))
154
- return path.map((s) => this.normalizeFieldPath(s));
111
+ }
112
+ normalizeFieldPath(fieldPaths) {
113
+ if (Array.isArray(fieldPaths))
114
+ return fieldPaths.map((s) => this.normalizeFieldPath(s));
155
115
  let curPath = '';
156
- for (const [, , p] of this.iteratePath(path)) {
116
+ for (const [, , p] of this.iteratePath(fieldPaths)) {
157
117
  curPath = p;
158
118
  }
159
119
  return curPath;
160
120
  }
121
+ exportSchema() {
122
+ const out = super.exportSchema();
123
+ Object.assign(out, omitUndefined({
124
+ base: this.base ?
125
+ (this.base.name ? this.base.name : this.base.exportSchema()) : undefined,
126
+ abstract: this.own.abstract,
127
+ additionalFields: this.own.additionalFields
128
+ }));
129
+ if (this.own.fields.size) {
130
+ const fields = out.fields = {};
131
+ for (const field of this.own.fields.values()) {
132
+ fields[field.name] = field.exportSchema();
133
+ }
134
+ }
135
+ return omitUndefined(out);
136
+ }
137
+ isTypeOf(t) {
138
+ return t === this.own.ctor;
139
+ }
140
+ extendsFrom(t) {
141
+ const base = t instanceof DataType ? t : this.document.getDataType(t);
142
+ if (this.base) {
143
+ if (this.base === base)
144
+ return true;
145
+ return this.base.extendsFrom(base);
146
+ }
147
+ return false;
148
+ }
149
+ decode(v) {
150
+ return this._getDecoder()(v, { coerce: true });
151
+ }
152
+ encode(v) {
153
+ return this._getEncoder()(v, { coerce: true });
154
+ }
155
+ validate(v) {
156
+ return this._getEncoder()(v);
157
+ }
158
+ _getDecoder() {
159
+ if (this._decoder)
160
+ return this._decoder;
161
+ const schema = {};
162
+ for (const f of this.fields.values()) {
163
+ let t = f.type._getDecoder();
164
+ if (f.isArray)
165
+ t = vg.isArray(t);
166
+ schema[f.name] = f.required ? vg.required(t) : vg.optional(t);
167
+ }
168
+ this._decoder = vg.isObject(schema, {
169
+ ctor: this.ctor,
170
+ additionalFields: this.additionalFields ?? 'ignore',
171
+ name: this.name,
172
+ caseInSensitive: true,
173
+ });
174
+ return this._decoder;
175
+ }
176
+ _getEncoder() {
177
+ if (this._encoder)
178
+ return this._encoder;
179
+ const schema = {};
180
+ for (const f of this.fields.values()) {
181
+ let t = f.type._getEncoder();
182
+ if (f.isArray)
183
+ t = vg.isArray(t);
184
+ schema[f.name] = t;
185
+ }
186
+ this._encoder = vg.isObject(schema, {
187
+ ctor: this.ctor,
188
+ additionalFields: this.additionalFields,
189
+ name: this.name,
190
+ caseInSensitive: true,
191
+ detectCircular: true
192
+ });
193
+ return this._encoder;
194
+ }
195
+ }
196
+ /**
197
+ * @class ComplexType
198
+ */
199
+ export const ComplexType = function (...args) {
200
+ // Constructor
201
+ if (this) {
202
+ const [document, init] = args;
203
+ merge(this, new ComplexTypeClass(document, init), { descriptor: true });
204
+ return;
205
+ }
206
+ // ClassDecorator
207
+ const [options] = args;
208
+ return function (target) {
209
+ const name = options?.name || target.name.match(TYPENAME_PATTERN)?.[1] || target.name;
210
+ let metadata = Reflect.getOwnMetadata(METADATA_KEY, target);
211
+ if (!metadata) {
212
+ metadata = {};
213
+ Reflect.defineMetadata(METADATA_KEY, metadata, target);
214
+ }
215
+ metadata.kind = OpraSchema.ComplexType.Kind;
216
+ metadata.name = name;
217
+ // Merge options
218
+ if (options)
219
+ Object.assign(metadata, omit(options, ['kind', 'name', 'base', 'fields']));
220
+ };
161
221
  };
162
- Object.assign(ComplexType.prototype, proto);
163
- Object.setPrototypeOf(ComplexType.prototype, DataType.prototype);
222
+ ComplexType.prototype = ComplexTypeClass.prototype;
@@ -1,43 +1,43 @@
1
1
  import { omitUndefined } from '../../helpers/index.js';
2
2
  import { colorFgMagenta, colorFgYellow, colorReset, nodeInspectCustom } from '../utils/inspect.util.js';
3
- export const DataType = function (document, init) {
4
- if (!(this instanceof DataType)) {
5
- throw new TypeError(`Class constructor must be called with "new" keyword`);
6
- // noinspection UnreachableCodeJS
7
- return;
8
- }
9
- const _this = this;
10
- _this.document = document;
11
- _this.name = init?.name;
12
- _this.own = {
13
- description: init?.description
14
- };
15
- _this.description = init?.description;
16
- return this;
17
- };
18
- const proto = {
19
- get isAnonymous() {
20
- return !this.name;
21
- },
22
- coerce(value) {
23
- return value;
24
- },
25
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
26
- extendsFrom(t) {
27
- return false;
28
- },
3
+ export class DataType {
4
+ constructor(document, init) {
5
+ this.document = document;
6
+ this.name = init?.name;
7
+ this.own = {};
8
+ this.description = init?.description;
9
+ this.isAnonymous = !this.name;
10
+ }
11
+ decode(v) {
12
+ return this._getDecoder()(v, { coerce: true });
13
+ }
14
+ encode(v) {
15
+ return this._getEncoder()(v, { coerce: true });
16
+ }
17
+ validate(v) {
18
+ return this._getEncoder()(v);
19
+ }
29
20
  exportSchema() {
30
21
  return omitUndefined({
31
22
  kind: this.kind,
32
- description: this.own.description
23
+ description: this.description
33
24
  });
34
- },
25
+ }
26
+ extendsFrom(type) {
27
+ const dataType = type instanceof DataType ? type : this.document.getDataType(type);
28
+ let t = this.base;
29
+ while (t) {
30
+ if (t === dataType)
31
+ return true;
32
+ t = t.base;
33
+ }
34
+ return false;
35
+ }
35
36
  toString() {
36
37
  return `[${Object.getPrototypeOf(this).constructor.name} ${this.name || '#anonymous'}]`;
37
- },
38
+ }
38
39
  [nodeInspectCustom]() {
39
40
  return `[${colorFgYellow + Object.getPrototypeOf(this).constructor.name + colorReset}` +
40
41
  ` ${colorFgMagenta + this.name + colorReset}]`;
41
42
  }
42
- };
43
- Object.assign(DataType.prototype, proto);
43
+ }