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

satisfactory-dev / ajv-utilities / 25136193506

29 Apr 2026 10:02PM UTC coverage: 98.787% (-1.1%) from 99.85%
25136193506

push

github

SignpostMarv
need to generate modified files on ci

491 of 497 branches covered (98.79%)

Branch coverage included in aggregate %.

3990 of 4039 relevant lines covered (98.79%)

20001.03 hits per line

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

90.41
/src/TypeScriptify/TypeReferences.ts
1
import type {
3✔
2
        ArrayTypeNode,
3✔
3
        ImportSpecifier,
3✔
4
        IndexedAccessTypeNode,
3✔
5
        TupleTypeNode,
3✔
6
        TypeReferenceNode,
3✔
7
} from 'typescript';
3✔
8
import {
3✔
9
        createPrinter,
3✔
10
        createSourceFile,
3✔
11
        EmitHint,
3✔
12
        factory,
3✔
13
        ScriptTarget,
3✔
14
} from 'typescript';
3✔
15

3✔
16
import type {
3✔
17
        as_array_config,
3✔
18
        specify_types_config,
3✔
19
} from './types.ts';
3✔
20

3✔
21
export type prepend_with_imports = {
3✔
22
        [key: string]: Types,
3✔
23
        ajv: Types,
3✔
24
        '@satisfactory-dev/ajv-utilities': Types,
3✔
25
};
3✔
26

3✔
27
interface HasOutput<
3✔
28
        TypeResult extends (
3✔
29
                | TypeReferenceNode
3✔
30
                | IndexedAccessTypeNode
3✔
31
                | TupleTypeNode
3✔
32
                | ArrayTypeNode
3✔
33
        ) = (
3✔
34
                | TypeReferenceNode
3✔
35
                | IndexedAccessTypeNode
3✔
36
                | TupleTypeNode
3✔
37
                | ArrayTypeNode
3✔
38
        ),
3✔
39
> {
3✔
40
        toTypeResult(): TypeResult;
3✔
41

3✔
42
        toString(): string;
3✔
43
}
3✔
44

3✔
45
function to_string(instance: HasOutput) {
16✔
46
        const printer = createPrinter({
16✔
47
                omitTrailingSemicolon: true,
16✔
48
        });
16✔
49

16✔
50
        return printer.printNode(
16✔
51
                EmitHint.Unspecified,
16✔
52
                instance.toTypeResult(),
16✔
53
                createSourceFile('foo.ts', '', ScriptTarget.ESNext),
16✔
54
        );
16✔
55
}
16✔
56

3✔
57
abstract class Type {
3✔
58
        readonly name: Exclude<string, ''>;
3✔
59

3,336✔
60
        #id: Exclude<string, ''> | undefined;
3✔
61

3✔
62
        get id(): Exclude<string, ''> {
3✔
63
                if (!this.#id) {
12,922✔
64
                        this.#id = this.toId();
3,307✔
65
                }
3,307✔
66

12,922✔
67
                return this.#id;
12,922✔
68
        }
12,922✔
69

3✔
70
        constructor(name: Exclude<string, ''>) {
3✔
71
                this.name = name;
3,336✔
72
        }
3,336✔
73

3✔
74
        protected abstract toId(): string;
3✔
75

3✔
76
        abstract toImportSpecifier(): ImportSpecifier;
3✔
77

3✔
78
        abstract withArgs(args: [string, ...string[]]): WithArgs;
3✔
79

3✔
80
        abstract withSubTypeChain(chain: [string, ...string[]]): WithSubTypeChain;
3✔
81

3✔
82
        abstract withArray(config: as_array_config): WithArray;
3✔
83
}
3✔
84

3✔
85
export class NameOnly extends Type implements HasOutput<TypeReferenceNode> {
3✔
86
        protected toId(): string {
3✔
87
                return this.name;
3,315✔
88
        }
3,315✔
89

3✔
90
        toImportSpecifier(): ImportSpecifier {
3✔
91
                return factory.createImportSpecifier(
93✔
92
                        false,
93✔
93
                        undefined,
93✔
94
                        factory.createIdentifier(this.name),
93✔
95
                );
93✔
96
        }
93✔
97

3✔
98
        toTypeResult(): TypeReferenceNode {
3✔
99
                return factory.createTypeReferenceNode(this.name);
34✔
100
        }
34✔
101

3✔
102
        withArgs(args: [string, ...string[]]): WithArgs {
3✔
103
                return new WithArgs(this.name, args);
9✔
104
        }
9✔
105

3✔
106
        withSubTypeChain(
3✔
107
                sub_type_chain: [string, ...string[]],
1✔
108
        ): WithSubTypeChain {
1✔
109
                return new WithSubTypeChain(
1✔
110
                        this,
1✔
111
                        sub_type_chain,
1✔
112
                );
1✔
113
        }
1✔
114

3✔
115
        withArray(
3✔
116
                config: as_array_config,
1✔
117
        ): WithArray {
1✔
118
                return new WithArray(
1✔
119
                        this,
1✔
120
                        config,
1✔
121
                );
1✔
122
        }
1✔
123

3✔
124
        toString() {
3✔
125
                return to_string(this);
6✔
126
        }
6✔
127
}
3✔
128

3✔
129
export class Aliased extends Type implements HasOutput<TypeReferenceNode> {
3✔
130
        readonly as: Exclude<string, ''>;
3✔
131

3✔
132
        constructor(name: Aliased['name'], as: Aliased['as']) {
3✔
133
                super(name);
10✔
134

10✔
135
                this.as = as;
10✔
136
        }
10✔
137

3✔
138
        protected toId(): string {
3✔
139
                return `${this.name} as ${this.as}`;
8✔
140
        }
8✔
141

3✔
142
        toImportSpecifier(): ImportSpecifier {
3✔
143
                return factory.createImportSpecifier(
4✔
144
                        false,
4✔
145
                        factory.createIdentifier(this.name),
4✔
146
                        factory.createIdentifier(this.as),
4✔
147
                );
4✔
148
        }
4✔
149

3✔
150
        toTypeResult(): TypeReferenceNode {
3✔
151
                return factory.createTypeReferenceNode(this.as);
6✔
152
        }
6✔
153

3✔
154
        withArgs(args: [string, ...string[]]): WithArgs {
3✔
155
                return new WithArgs(this.name, args, this.as);
4✔
156
        }
4✔
157

3✔
158
        withSubTypeChain(
3✔
159
                sub_type_chain: [string, ...string[]],
×
160
        ): WithSubTypeChain {
×
161
                return new WithSubTypeChain(
×
162
                        this,
×
163
                        sub_type_chain,
×
164
                );
×
165
        }
×
166

3✔
167
        withArray(
3✔
168
                config: as_array_config,
×
169
        ): WithArray {
×
170
                return new WithArray(
×
171
                        this,
×
172
                        config,
×
173
                );
×
174
        }
×
175

3✔
176
        toString() {
3✔
177
                return to_string(this);
4✔
178
        }
4✔
179
}
3✔
180

3✔
181
class WithArgs implements HasOutput<TypeReferenceNode> {
3✔
182
        readonly name: Exclude<string, ''>;
3✔
183

13✔
184
        readonly as: Exclude<string, ''> | undefined;
13✔
185

13✔
186
        readonly args: [string, ...string[]];
3✔
187

3✔
188
        constructor(
3✔
189
                name: WithArgs['name'],
13✔
190
                args: WithArgs['args'],
13✔
191
                as?: Exclude<WithArgs['as'], undefined>,
13✔
192
        ) {
13✔
193
                this.name = name;
13✔
194
                this.args = args;
13✔
195
                this.as = as;
13✔
196
        }
13✔
197

3✔
198
        toTypeResult() {
3✔
199
                return factory.createTypeReferenceNode(
13✔
200
                        this.as || this.name,
13✔
201
                        this.args.map((value) => factory.createLiteralTypeNode(
13✔
202
                                factory.createStringLiteral(value),
30✔
203
                        )),
13✔
204
                );
13✔
205
        }
13✔
206

3✔
207
        toString() {
3✔
208
                return to_string(this);
6✔
209
        }
6✔
210

3✔
211
        withSubTypeChain(
3✔
212
                sub_type_chain: [string, ...string[]],
×
213
        ): WithSubTypeChain {
×
214
                return new WithSubTypeChain(
×
215
                        this,
×
216
                        sub_type_chain,
×
217
                );
×
218
        }
×
219

3✔
220
        withArray(
3✔
221
                config: as_array_config,
×
222
        ): WithArray {
×
223
                return new WithArray(
×
224
                        this,
×
225
                        config,
×
226
                );
×
227
        }
×
228
}
3✔
229

3✔
230
class WithSubTypeChain implements HasOutput<IndexedAccessTypeNode> {
3✔
231
        #parent: HasOutput;
3✔
232

1✔
233
        readonly sub_type_chain: [string, ...string[]];
3✔
234

3✔
235
        constructor(
3✔
236
                parent: HasOutput,
1✔
237
                sub_type_chain: [string, ...string[]],
1✔
238
        ) {
1✔
239
                this.#parent = parent;
1✔
240
                this.sub_type_chain = sub_type_chain;
1✔
241
        }
1✔
242

3✔
243
        withArray(config: as_array_config): WithArray {
3✔
244
                return new WithArray(this.#parent, config);
×
245
        }
×
246

3✔
247
        toTypeResult() {
3✔
248
                const [
1✔
249
                        first,
1✔
250
                        ...remaining
1✔
251
                ] = this.sub_type_chain;
1✔
252

1✔
253
                let access = factory.createIndexedAccessTypeNode(
1✔
254
                        this.#parent.toTypeResult(),
1✔
255
                        factory.createLiteralTypeNode(factory.createStringLiteral(
1✔
256
                                first,
1✔
257
                        )),
1✔
258
                );
1✔
259

1✔
260
                for (const sub_type of remaining) {
1!
261
                        access = factory.createIndexedAccessTypeNode(
×
262
                                access,
×
263
                                factory.createLiteralTypeNode(factory.createStringLiteral(
×
264
                                        sub_type,
×
265
                                )),
×
266
                        );
×
267
                }
×
268

1✔
269
                return access;
1✔
270
        }
1✔
271

3✔
272
        toString() {
3✔
273
                return to_string(this);
×
274
        }
×
275
}
3✔
276

3✔
277
class WithArray implements HasOutput<TupleTypeNode | ArrayTypeNode> {
3✔
278
        #parent: HasOutput;
3✔
279

1✔
280
        readonly as_array: as_array_config;
3✔
281

3✔
282
        constructor(
3✔
283
                parent: HasOutput,
1✔
284
                as_array: as_array_config,
1✔
285
        ) {
1✔
286
                this.#parent = parent;
1✔
287
                this.as_array = as_array;
1✔
288
        }
1✔
289

3✔
290
        toTypeResult() {
3✔
291
                if (true === this.as_array || this.as_array.minimum < 1) {
1!
292
                        return factory.createArrayTypeNode(this.#parent.toTypeResult());
×
293
                }
×
294

1✔
295
                const args: ReturnType<HasOutput['toTypeResult']>[] = [];
1✔
296

1✔
297
                const minimum = Math.max(1, this.as_array.minimum);
1✔
298

1✔
299
                for (let i = 0; i < minimum; ++i) {
1✔
300
                        args.push(this.#parent.toTypeResult());
1✔
301
                }
1✔
302

1✔
303
                return factory.createTupleTypeNode(
1✔
304
                        [
1✔
305
                                ...args,
1✔
306
                                factory.createRestTypeNode(
1✔
307
                                        factory.createArrayTypeNode(this.#parent.toTypeResult()),
1✔
308
                                ),
1✔
309
                        ],
1✔
310
                );
1✔
311
        }
1✔
312

3✔
313
        toString() {
3✔
314
                return to_string(this);
×
315
        }
×
316
}
3✔
317

3✔
318
export class Types {
3✔
319
        list_of_types: [
3✔
320
                (
83✔
321
                        | NameOnly
83✔
322
                        | Aliased
83✔
323
                ),
83✔
324
                ...(
83✔
325
                        | NameOnly
83✔
326
                        | Aliased
83✔
327
                )[],
83✔
328
        ] | undefined = undefined;
3✔
329

3✔
330
        get size() {
3✔
331
                return this.list_of_types ? this.list_of_types.length : 0;
68✔
332
        }
68✔
333

3✔
334
        #is_object_type(
3✔
335
                type: specify_types_config,
3,336✔
336
        ): type is Exclude<specify_types_config, string> {
3,336✔
337
                return 'string' !== typeof type;
3,336✔
338
        }
3,336✔
339

3✔
340
        add<T extends specify_types_config>(type: T) {
3✔
341
                const is_object = this.#is_object_type(type);
3,336✔
342

3,336✔
343
                let as_object = (
3,336✔
344
                        !is_object
3,336✔
345
                                ? new NameOnly(type)
3,336✔
346
                                : (
3,336✔
347
                                        'as' in type && type.as
21✔
348
                                                ? new Aliased(type.name, type.as)
21✔
349
                                                : new NameOnly(type.name)
21✔
350
                                )
21✔
351
                );
3,336✔
352

3,336✔
353
                if (undefined === this.list_of_types) {
3,336✔
354
                        this.list_of_types = [as_object];
60✔
355
                } else {
8✔
356
                        const maybe = this.list_of_types.find((
3,260✔
357
                                maybe,
6,402✔
358
                        ) => maybe.id === as_object.id);
3,260✔
359

3,260✔
360
                        if (!maybe) {
3,260✔
361
                                this.list_of_types.push(as_object);
3,260✔
362
                        } else {
3,260✔
363
                                as_object = maybe;
3,260✔
364
                        }
3,260✔
365
                }
3,260✔
366

3,336✔
367
                if (is_object) {
3,336✔
368
                        let result: (
21✔
369
                                | Aliased
21✔
370
                                | NameOnly
21✔
371
                                | WithArgs
21✔
372
                                | WithSubTypeChain
21✔
373
                                | WithArray
21✔
374
                        ) = as_object;
21✔
375

21✔
376
                        if ('args' in type) {
21✔
377
                                result = result.withArgs(type.args);
13✔
378
                        }
13✔
379

21✔
380
                        if ('sub_type_chain' in type && !!type.sub_type_chain) {
21✔
381
                                result = result.withSubTypeChain(type.sub_type_chain);
1✔
382
                        }
1✔
383

21✔
384
                        if ('as_array' in type && !!type.as_array) {
21✔
385
                                result = result.withArray(type.as_array);
1✔
386
                        }
1✔
387

21✔
388
                        return result;
21✔
389
                }
21✔
390

3,315✔
391
                return as_object;
3,315✔
392
        }
3,336✔
393

3✔
394
        * [Symbol.iterator]() {
3✔
395
                if (!this.list_of_types) {
61✔
396
                        return;
61✔
397
                }
61✔
398

61✔
399
                for (const type of this.list_of_types) {
61✔
400
                        yield type;
97✔
401
                }
97✔
402
        }
61✔
403
}
3✔
404

3✔
405
export type {
3✔
406
        WithArgs,
3✔
407
        WithSubTypeChain,
3✔
408
        WithArray,
3✔
409
};
3✔
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