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

oprajs / opra / 19958387866

05 Dec 2025 09:19AM UTC coverage: 80.99% (-0.2%) from 81.23%
19958387866

push

github

erayhanoglu
chore: Updated deps

3534 of 4540 branches covered (77.84%)

Branch coverage included in aggregate %.

31111 of 38237 relevant lines covered (81.36%)

218.64 hits per line

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

89.58
/packages/common/src/document/api-document.ts
1
import { omitUndefined } from '@jsopen/objects';
1✔
2
import { md5 } from 'super-fast-md5';
1✔
3
import type { Mutable, Type } from 'ts-gems';
1✔
4
import { cloneObject, ResponsiveMap } from '../helpers/index.js';
1✔
5
import { OpraSchema } from '../schema/index.js';
1✔
6
import { DataTypeMap } from './common/data-type-map.js';
1✔
7
import { DocumentElement } from './common/document-element.js';
1✔
8
import {
1✔
9
  BUILTIN,
1✔
10
  kDataTypeMap,
1✔
11
  kTypeNSMap,
1✔
12
  NAMESPACE_PATTERN,
1✔
13
} from './constants.js';
1✔
14
import { DataType } from './data-type/data-type.js';
1✔
15
import type { EnumType } from './data-type/enum-type.js';
1✔
16
import { HttpApi } from './http/http-api.js';
1✔
17
import { MQApi } from './mq/mq-api.js';
1✔
18
import { WSApi } from './ws/ws-api.js';
1✔
19

1✔
20
/**
1✔
21
 *
1✔
22
 * @class ApiDocument
1✔
23
 */
1✔
24
export class ApiDocument extends DocumentElement {
1✔
25
  protected [kTypeNSMap] = new WeakMap<DataType, string>();
1✔
26
  readonly id: string = '';
1✔
27
  url?: string;
1✔
28
  info: OpraSchema.DocumentInfo = {};
1✔
29
  references = new ResponsiveMap<ApiDocument>();
1✔
30
  types = new DataTypeMap();
1✔
31
  api?: HttpApi | MQApi | WSApi;
1✔
32

1✔
33
  constructor() {
1✔
34
    super(null as any);
302✔
35
    this.node[kDataTypeMap] = this.types;
302✔
36
    this.node.findDataType = this._findDataType.bind(this);
302✔
37
  }
302✔
38

1✔
39
  /**
1✔
40
   * Returns NS of datatype. Returns undefined if not found
1✔
41
   * @param nameOrCtor
1✔
42
   */
1✔
43
  getDataTypeNs(
1✔
44
    nameOrCtor:
5,118✔
45
      | string
5,118✔
46
      | Type
5,118✔
47
      | Function
5,118✔
48
      | EnumType.EnumArray
5,118✔
49
      | EnumType.EnumObject
5,118✔
50
      | DataType,
5,118✔
51
  ): string | undefined {
5,118✔
52
    const dt =
5,118✔
53
      nameOrCtor instanceof DataType
5,118✔
54
        ? this._findDataType(nameOrCtor.name || '')
5,115!
55
        : this._findDataType(nameOrCtor);
3✔
56
    if (dt) return this[kTypeNSMap].get(dt);
5,118✔
57
  }
5,118✔
58

1✔
59
  findDocument(id: string): ApiDocument | undefined {
1✔
60
    if (this.id === id) return this;
2!
61
    for (const doc of this.references.values()) {
2✔
62
      if (doc.id === id) return doc;
2✔
63
      const d = doc.findDocument(id);
1✔
64
      if (d) return d;
2!
65
    }
2✔
66
  }
1✔
67

1✔
68
  get httpApi(): HttpApi | undefined {
1✔
69
    if (this.api && this.api instanceof HttpApi) return this.api as HttpApi;
×
70
  }
×
71

1✔
72
  get mqApi(): MQApi | undefined {
1✔
73
    if (this.api && this.api instanceof MQApi) return this.api as MQApi;
×
74
  }
×
75

1✔
76
  get wsApi(): WSApi | undefined {
1✔
77
    if (this.api && this.api instanceof WSApi) return this.api as WSApi;
×
78
  }
×
79

1✔
80
  getHttpApi(): HttpApi {
1✔
81
    if (!(this.api && this.api instanceof HttpApi)) {
106!
82
      throw new TypeError('The document do not contains HttpApi instance');
×
83
    }
×
84
    return this.api as HttpApi;
106✔
85
  }
106✔
86

1✔
87
  getMqApi(): MQApi {
1✔
88
    if (!(this.api && this.api instanceof MQApi)) {
23!
89
      throw new TypeError('The document do not contains MQApi instance');
×
90
    }
×
91
    return this.api as MQApi;
23✔
92
  }
23✔
93

1✔
94
  getWsApi(): WSApi {
1✔
95
    if (!(this.api && this.api instanceof WSApi)) {
×
96
      throw new TypeError('The document do not contains WSApi instance');
×
97
    }
×
98
    return this.api as WSApi;
×
99
  }
×
100

1✔
101
  toJSON(): OpraSchema.ApiDocument {
1✔
102
    return this.export();
×
103
  }
×
104

1✔
105
  /**
1✔
106
   * Export as Opra schema definition object
1✔
107
   */
1✔
108
  export(options?: ApiDocument.ExportOptions): OpraSchema.ApiDocument {
1✔
109
    const out = omitUndefined<OpraSchema.ApiDocument>({
309✔
110
      spec: OpraSchema.SpecVersion,
309✔
111
      id: this.id,
309✔
112
      url: this.url,
309✔
113
      info: cloneObject(this.info, true),
309✔
114
    });
309✔
115
    if (this.references.size) {
309✔
116
      let i = 0;
159✔
117
      const references: Record<string, OpraSchema.DocumentReference> = {};
159✔
118
      for (const [ns, doc] of this.references.entries()) {
159✔
119
        if (doc[BUILTIN]) continue;
216✔
120
        references[ns] = {
57✔
121
          id: doc.id,
57✔
122
          url: doc.url,
57✔
123
          info: cloneObject(doc.info, true),
57✔
124
        };
57✔
125
        i++;
57✔
126
      }
57✔
127
      if (i) out.references = references;
159✔
128
    }
159✔
129
    if (this.types.size) {
309✔
130
      out.types = {};
250✔
131
      for (const v of this.types.values()) {
250✔
132
        if (!v.inScope(options?.scope)) continue;
3,451✔
133
        out.types[v.name!] = v.toJSON(options);
3,441✔
134
      }
3,441✔
135
    }
250✔
136
    if (this.api) out.api = this.api.toJSON(options);
309✔
137
    return out;
309✔
138
  }
309✔
139

1✔
140
  invalidate(): void {
1✔
141
    /** Generate id */
302✔
142
    const x = this.export({});
302✔
143
    delete (x as any).id;
302✔
144
    (this as Mutable<ApiDocument>).id = md5(JSON.stringify(x));
302✔
145
    /** Clear [kTypeNSMap] */
302✔
146
    this[kTypeNSMap] = new WeakMap<DataType, string>();
302✔
147
  }
302✔
148

1✔
149
  protected _findDataType(
1✔
150
    nameOrCtor:
31,336✔
151
      | string
31,336✔
152
      | Type
31,336✔
153
      | Function
31,336✔
154
      | EnumType.EnumArray
31,336✔
155
      | EnumType.EnumObject,
31,336✔
156
    scope?: string,
31,336✔
157
    visitedRefs?: WeakMap<ApiDocument, boolean>,
31,336✔
158
  ): DataType | undefined {
31,336✔
159
    let result = this.types.get(nameOrCtor);
31,336✔
160
    if (result && result.inScope(scope)) return result;
31,336✔
161
    if (!this.references.size) return;
31,336✔
162
    // Lookup for references
14,199✔
163
    if (typeof nameOrCtor === 'string') {
31,336✔
164
      // If given string has namespace pattern (ns:type_name)
8,304✔
165
      const m = NAMESPACE_PATTERN.exec(nameOrCtor);
8,304✔
166
      if (m) {
8,304✔
167
        const ns = m[1];
17✔
168
        if (ns) {
17✔
169
          const ref = this.references.get(ns);
17✔
170
          if (!ref) return;
17!
171
          visitedRefs = visitedRefs || new WeakMap<ApiDocument, boolean>();
17✔
172
          visitedRefs.set(this, true);
17✔
173
          visitedRefs.set(ref, true);
17✔
174
          return ref._findDataType(m[2], scope, visitedRefs);
17✔
175
        }
17!
176
        nameOrCtor = m[2];
×
177
      }
×
178
    }
8,304✔
179

14,182✔
180
    // if not found, search in references (from last to first)
14,182✔
181
    visitedRefs = visitedRefs || new WeakMap<ApiDocument, boolean>();
31,336✔
182
    visitedRefs.set(this, true);
31,336✔
183
    const references = Array.from(this.references.keys()).reverse();
31,336✔
184
    /** First step, lookup for own types */
31,336✔
185
    for (const refNs of references) {
31,336✔
186
      const ref = this.references.get(refNs);
19,956✔
187
      result = ref?.types.get(nameOrCtor);
19,956✔
188
      if (result) {
19,956✔
189
        this[kTypeNSMap].set(result, ref?.[BUILTIN] ? '' : refNs);
8,633✔
190
        return result;
8,633✔
191
      }
8,633✔
192
    }
19,956✔
193
    /** If not found lookup for child references */
5,549✔
194
    for (const refNs of references) {
31,336✔
195
      const ref = this.references.get(refNs);
7,906✔
196
      visitedRefs.set(ref!, true);
7,906✔
197
      result = ref!._findDataType(nameOrCtor, scope, visitedRefs);
7,906✔
198
      if (result) {
7,906✔
199
        this[kTypeNSMap].set(result, ref?.[BUILTIN] ? '' : refNs);
27!
200
        return result;
27✔
201
      }
27✔
202
    }
7,906✔
203
  }
5,522✔
204
}
1✔
205

1✔
206
export namespace ApiDocument {
1✔
207
  export interface ExportOptions {
1✔
208
    scope?: string;
1✔
209
  }
1✔
210
}
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