• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

oprajs / opra / 14419802659

12 Apr 2025 12:55PM UTC coverage: 82.088% (+4.2%) from 77.908%
14419802659

push

github

web-flow
Merge pull request #27 from oprajs/dev

Dev

3458 of 4432 branches covered (78.02%)

Branch coverage included in aggregate %.

16 of 16 new or added lines in 10 files covered. (100.0%)

1793 existing lines in 129 files now uncovered.

29424 of 35625 relevant lines covered (82.59%)

183.2 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.8
/packages/common/src/document/data-type/complex-type.ts
1
import 'reflect-metadata';
1✔
2
import { omitUndefined } from '@jsopen/objects';
1✔
3
import type { Combine, Type, TypeThunkAsync } from 'ts-gems';
1✔
4
import { asMutable } from 'ts-gems';
1✔
5
import { OpraSchema } from '../../schema/index.js';
1✔
6
import type { ApiDocument } from '../api-document.js';
1✔
7
import type { DocumentElement } from '../common/document-element.js';
1✔
8
import { DocumentInitContext } from '../common/document-init-context.js';
1✔
9
import { DECORATOR } from '../constants.js';
1✔
10
import { ComplexTypeDecorator } from '../decorators/complex-type.decorator.js';
1✔
11
import { ApiField } from './api-field.js';
1✔
12
import { ComplexTypeBase } from './complex-type-base.js';
1✔
13
import { DataType } from './data-type.js';
1✔
14
import type { MappedType } from './mapped-type.js';
1✔
15
import type { MixinType } from './mixin-type.js';
1✔
16

1✔
17
/**
1✔
18
 * @namespace ComplexType
1✔
19
 */
1✔
20
export namespace ComplexType {
1✔
21
  export interface Metadata
1✔
22
    extends Combine<
1✔
23
      {
1✔
24
        kind: OpraSchema.ComplexType.Kind;
1✔
25
        fields?: Record<string, ApiField.Metadata>;
1✔
26
        additionalFields?:
1✔
27
          | boolean
1✔
28
          | string
1✔
29
          | TypeThunkAsync
1✔
30
          | ['error']
1✔
31
          | ['error', string];
1✔
32
      },
1✔
33
      DataType.Metadata,
1✔
34
      OpraSchema.ComplexType
1✔
35
    > {}
1✔
36

1✔
37
  export interface Options
1✔
38
    extends Combine<
1✔
39
      Pick<Metadata, 'additionalFields' | 'keyField'>,
1✔
40
      DataType.Options,
1✔
41
      Pick<OpraSchema.ComplexType, 'abstract'>
1✔
42
    > {}
1✔
43

1✔
44
  export interface InitArguments
1✔
45
    extends Combine<
1✔
46
      {
1✔
47
        kind: OpraSchema.ComplexType.Kind;
1✔
48
        base?: ComplexType | MappedType | MixinType;
1✔
49
        fields?: Record<string, ApiField.InitArguments | ApiField>;
1✔
50
        additionalFields?: boolean | DataType | ['error'] | ['error', string];
1✔
51
      },
1✔
52
      DataType.InitArguments,
1✔
53
      ComplexType.Metadata
1✔
54
    > {}
1✔
55

1✔
56
  export interface ParsedFieldPath {
1✔
57
    fieldName: string;
1✔
58
    dataType: DataType;
1✔
59
    field?: ApiField;
1✔
60
    additionalField?: boolean;
1✔
61
    sign?: '+' | '-';
1✔
62
  }
1✔
63
}
1✔
64

1✔
65
/**
1✔
66
 * Type definition for MixinType
1✔
67
 * @class ComplexType
1✔
68
 */
1✔
69
export interface ComplexTypeStatic {
1✔
70
  /**
1✔
71
   * Class constructor of ComplexType
1✔
72
   *
1✔
73
   * @param owner
1✔
74
   * @param args
1✔
75
   * @param context
1✔
76
   * @constructor
1✔
77
   */
1✔
78
  new (
1✔
79
    owner: DocumentElement,
1✔
80
    args?: ComplexType.InitArguments,
1✔
81
    context?: DocumentInitContext,
1✔
82
  ): ComplexType;
1✔
83

1✔
84
  (options?: ComplexType.Options): ClassDecorator;
1✔
85

1✔
86
  prototype: ComplexType;
1✔
87

1✔
88
  extend<T extends Type>(
1✔
89
    typeClass: T,
1✔
90
    fields: Record<string, ApiField.Options>,
1✔
91
  ): T;
1✔
92
}
1✔
93

1✔
94
/**
1✔
95
 * Type definition of ComplexType prototype
1✔
96
 * @interface ComplexType
1✔
97
 */
1✔
98
export interface ComplexType extends ComplexTypeClass {}
1✔
99

1✔
100
/**
1✔
101
 * ComplexType constructor
1✔
102
 */
1✔
103
export const ComplexType = function (this: ComplexType | void, ...args: any[]) {
1✔
104
  // Decorator
574✔
105
  if (!this) return ComplexType[DECORATOR].apply(undefined, args);
574✔
106
  // Constructor
487✔
107
  const [owner, initArgs] = args as [
487✔
108
    DocumentElement,
487✔
109
    ComplexType.InitArguments,
487✔
110
  ];
487✔
111
  const context: DocumentInitContext =
487✔
112
    args[2] || new DocumentInitContext({ maxErrors: 0 });
487✔
113
  ComplexTypeBase.call(this, owner, initArgs, context);
574✔
114
  const _this = asMutable(this);
574✔
115
  _this.kind = OpraSchema.ComplexType.Kind;
574✔
116
  if (initArgs.base) {
574✔
117
    context.enter('.base', () => {
85✔
118
      // noinspection SuspiciousTypeOfGuard
85✔
119
      if (!(initArgs.base instanceof ComplexTypeBase)) {
85!
120
        throw new TypeError(
×
UNCOV
121
          `"${(initArgs.base! as DataType).kind}" can't be set as base for a "${this.kind}"`,
×
UNCOV
122
        );
×
UNCOV
123
      }
×
124
      _this.base = initArgs.base;
85✔
125
      _this.additionalFields = _this.base.additionalFields;
85✔
126
      _this.keyField = _this.base.keyField;
85✔
127

85✔
128
      /** Copy fields from base */
85✔
129
      for (const v of _this.base.fields('*')) {
85✔
130
        (_this as any)._fields.set(v.name, new ApiField(this, v));
466✔
131
      }
466✔
132
    });
85✔
133
  }
85✔
134
  if (initArgs.additionalFields !== undefined)
487✔
135
    _this.additionalFields = initArgs.additionalFields;
574✔
136
  if (initArgs.keyField !== undefined) _this.keyField = initArgs.keyField;
574✔
137
  _this.ctor = initArgs.ctor || _this.base?.ctor;
574✔
138

574✔
139
  /** Add own fields */
574✔
140
  if (initArgs.fields) {
574✔
141
    context.enter('.fields', () => {
487✔
142
      for (const [k, v] of Object.entries(initArgs.fields!)) {
487✔
143
        const field = new ApiField(this, {
1,632✔
144
          ...v,
1,632✔
145
          name: k,
1,632✔
146
        });
1,632✔
147
        (this as any)._fields.set(field.name, field);
1,632✔
148
      }
1,632✔
149
    });
487✔
150
  }
487✔
151
} as Function as ComplexTypeStatic;
574✔
152

1✔
153
/**
1✔
154
 *
1✔
155
 * @class ComplexType
1✔
156
 */
1✔
157
abstract class ComplexTypeClass extends ComplexTypeBase {
1✔
158
  declare readonly kind: OpraSchema.ComplexType.Kind;
1✔
159
  readonly base?: ComplexType | MappedType | MixinType;
1✔
160
  declare readonly ctor?: Type;
1✔
161

1✔
162
  extendsFrom(baseType: DataType | string | Type | object): boolean {
1✔
163
    if (!(baseType instanceof DataType))
348✔
164
      baseType = this.node.getDataType(baseType);
348!
165
    if (!(baseType instanceof ComplexTypeBase)) return false;
348!
166
    if (baseType === this) return true;
348!
167
    return !!this.base?.extendsFrom(baseType);
348✔
168
  }
348✔
169

1✔
170
  toJSON(options?: ApiDocument.ExportOptions): OpraSchema.ComplexType {
1✔
171
    const superJson = super.toJSON(options);
513✔
172
    const baseName = this.base
513✔
173
      ? this.node.getDataTypeNameWithNs(this.base)
92✔
174
      : undefined;
421✔
175
    const out: OpraSchema.ComplexType = {
513✔
176
      ...superJson,
513✔
177
      kind: this.kind,
513✔
178
      base: this.base
513✔
179
        ? baseName
92✔
180
          ? baseName
41✔
181
          : this.base.toJSON(options)
51✔
182
        : undefined,
421✔
183
    };
513✔
184
    if (this.additionalFields) {
513✔
185
      if (this.additionalFields instanceof DataType) {
172✔
186
        const typeName = this.node.getDataTypeNameWithNs(this.additionalFields);
1✔
187
        out.additionalFields = typeName
1✔
188
          ? typeName
1!
UNCOV
189
          : (this.additionalFields.toJSON(options) as OpraSchema.DataType);
×
190
      } else out.additionalFields = this.additionalFields;
172✔
191
    }
172✔
192
    if (this._fields.size) {
513✔
193
      const fields = {};
378✔
194
      let i = 0;
378✔
195
      for (const field of this._fields.values()) {
378✔
196
        if (field.origin === this && field.inScope(options?.scope)) {
2,296✔
197
          fields[field.name] = field.toJSON(options);
1,759✔
198
          i++;
1,759✔
199
        }
1,759✔
200
      }
2,296✔
201
      if (i) out.fields = fields;
378✔
202
    }
378✔
203
    return omitUndefined(out);
513✔
204
  }
513✔
205

1✔
206
  protected _locateBase(
1✔
207
    callback: (base: ComplexTypeBase) => boolean,
2,043✔
208
  ): ComplexTypeBase | undefined {
2,043✔
209
    if (!this.base) return;
2,043✔
210
    if (callback(this.base)) return this.base;
2,043!
211
    if ((this.base as any)._locateBase)
451✔
212
      return (this.base as any)._locateBase(callback);
451✔
213
  }
2,043✔
214
}
1✔
215

1✔
216
ComplexType.prototype = ComplexTypeClass.prototype;
1✔
217
Object.assign(ComplexType, ComplexTypeDecorator);
1✔
218
ComplexType[DECORATOR] = ComplexTypeDecorator;
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc