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

panates / opra / 29494915195

16 Jul 2026 11:33AM UTC coverage: 83.024% (+0.4%) from 82.653%
29494915195

push

github

erayhanoglu
1.29.1

4118 of 5238 branches covered (78.62%)

Branch coverage included in aggregate %.

34348 of 41093 relevant lines covered (83.59%)

239.47 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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

8,829✔
176
    // if not found, search in references (from last to first)
8,829✔
177
    visitedRefs = visitedRefs || new WeakMap<ApiDocument, boolean>();
32,261✔
178
    visitedRefs.set(this, true);
5,637✔
179
    const references = Array.from(this.references.keys()).reverse();
32,261✔
180
    /* First step, lookup for own types */
8,025✔
181
    for (const refNs of references) {
8,025✔
182
      const ref = this.references.get(refNs);
8,025✔
183
      result = ref?.types.get(nameOrCtor);
27✔
184
      if (result) {
27!
185
        this[kTypeNSMap].set(result, ref?.[BUILTIN] ? '' : refNs);
32,261✔
186
        return result;
1✔
187
      }
1✔
188
    }
1✔
189
    /* If not found lookup for child references */
1✔
190
    for (const refNs of references) {
1✔
191
      const ref = this.references.get(refNs);
1✔
192
      visitedRefs.set(ref!, true);
1✔
193
      result = ref!._findDataType(nameOrCtor, scope, visitedRefs);
1✔
194
      if (result) {
1✔
195
        this[kTypeNSMap].set(result, ref?.[BUILTIN] ? '' : refNs);
1✔
196
        return result;
1✔
197
      }
1✔
198
    }
1✔
199
  }
1✔
200
}
1✔
201

1✔
202
export namespace ApiDocument {
1✔
203
  export interface ExportOptions {
1✔
204
    scope?: string;
1✔
205
  }
1✔
206
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc