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

satisfactory-dev / ajv-utilities / 25253400832

02 May 2026 01:50PM UTC coverage: 98.75% (-0.06%) from 98.808%
25253400832

push

github

SignpostMarv
drop support for config options that rely on things that ajv will change based on config

566 of 584 branches covered (96.92%)

Branch coverage included in aggregate %.

4727 of 4776 relevant lines covered (98.97%)

18432.73 hits per line

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

93.33
/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

3✔
43
export function to_string(instance: HasOutput) {
3✔
44
        const printer = createPrinter({
21✔
45
                omitTrailingSemicolon: true,
21✔
46
        });
21✔
47

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

3✔
55
abstract class AbstractOutput<
3✔
56
        TypeResult extends (
3✔
57
                | TypeReferenceNode
3✔
58
                | IndexedAccessTypeNode
3✔
59
                | TupleTypeNode
3✔
60
                | ArrayTypeNode
3✔
61
        ),
3✔
62
> implements HasOutput<TypeResult> {
3✔
63
        abstract toTypeResult(): TypeResult;
3✔
64

3✔
65
        withSubTypeChain(
3✔
66
                sub_type_chain: [string, ...string[]],
2✔
67
        ): WithSubTypeChain {
2✔
68
                return new WithSubTypeChain(
2✔
69
                        this,
2✔
70
                        sub_type_chain,
2✔
71
                );
2✔
72
        }
2✔
73

3✔
74
        withArray(
3✔
75
                config: as_array_config,
1✔
76
        ): WithArray {
1✔
77
                return new WithArray(
1✔
78
                        this,
1✔
79
                        config,
1✔
80
                );
1✔
81
        }
1✔
82
}
3✔
83

3✔
84
export class Type<
3✔
85
        As extends (
3✔
86
                Exclude<string, ''> | undefined
3✔
87
        ) = (
3✔
88
                Exclude<string, ''> | undefined
3✔
89
        ),
3✔
90
> extends AbstractOutput<TypeReferenceNode> {
3✔
91
        readonly name: Exclude<string, ''>;
3✔
92

3,353✔
93
        readonly args: [string, ...string[]] | undefined;
3,353✔
94

3,353✔
95
        readonly as: As;
3✔
96

3✔
97
        get id(): Exclude<string, ''> {
3✔
98
                return this.as ? `${this.name} as ${this.as}` : this.name;
7,014✔
99
        }
7,014✔
100

3✔
101
        constructor(
3✔
102
                name: Exclude<string, ''>,
3,353✔
103
                as: As,
3,353✔
104
                args?: [string, ...string[]],
3,353✔
105
        ) {
3,353✔
106
                super();
3,353✔
107

3,353✔
108
                this.name = name;
3,353✔
109
                this.as = as;
3,353✔
110
                this.args = args;
3,353✔
111
        }
3,353✔
112

3✔
113
        toImportSpecifier(): ImportSpecifier {
3✔
114
                if (this.as) {
96✔
115
                        return factory.createImportSpecifier(
4✔
116
                                false,
4✔
117
                                factory.createIdentifier(this.name),
4✔
118
                                factory.createIdentifier(this.as),
4✔
119
                        );
4✔
120
                }
4✔
121

92✔
122
                return factory.createImportSpecifier(
92✔
123
                        false,
92✔
124
                        undefined,
92✔
125
                        factory.createIdentifier(this.name),
92✔
126
                );
92✔
127
        }
96✔
128

3✔
129
        toTypeResult(): TypeReferenceNode {
3✔
130
                return factory.createTypeReferenceNode(
57✔
131
                        this.as || this.name,
57✔
132
                        this.args?.map((value) => factory.createLiteralTypeNode(
57✔
133
                                factory.createStringLiteral(value),
30✔
134
                        )),
57✔
135
                );
57✔
136
        }
57✔
137

3✔
138
        withArgs(args: [string, ...string[]]) {
3✔
139
                return new Type(this.name, this.as, args);
13✔
140
        }
13✔
141
}
3✔
142

3✔
143
class WithSubTypeChain extends AbstractOutput<IndexedAccessTypeNode> {
3✔
144
        #parent: HasOutput;
3✔
145

2✔
146
        readonly sub_type_chain: [string, ...string[]];
3✔
147

3✔
148
        constructor(
3✔
149
                parent: HasOutput,
2✔
150
                sub_type_chain: [string, ...string[]],
2✔
151
        ) {
2✔
152
                super();
2✔
153

2✔
154
                this.#parent = parent;
2✔
155
                this.sub_type_chain = sub_type_chain;
2✔
156
        }
2✔
157

3✔
158
        toTypeResult() {
3✔
159
                const [
2✔
160
                        first,
2✔
161
                        ...remaining
2✔
162
                ] = this.sub_type_chain;
2✔
163

2✔
164
                let access = factory.createIndexedAccessTypeNode(
2✔
165
                        this.#parent.toTypeResult(),
2✔
166
                        factory.createLiteralTypeNode(factory.createStringLiteral(
2✔
167
                                first,
2✔
168
                        )),
2✔
169
                );
2✔
170

2✔
171
                for (const sub_type of remaining) {
2!
172
                        access = factory.createIndexedAccessTypeNode(
×
173
                                access,
×
174
                                factory.createLiteralTypeNode(factory.createStringLiteral(
×
175
                                        sub_type,
×
176
                                )),
×
177
                        );
×
178
                }
×
179

2✔
180
                return access;
2✔
181
        }
2✔
182
}
3✔
183

3✔
184
class WithArray extends AbstractOutput<TupleTypeNode | ArrayTypeNode> {
3✔
185
        #parent: HasOutput;
3✔
186

1✔
187
        readonly as_array: as_array_config;
3✔
188

3✔
189
        constructor(
3✔
190
                parent: HasOutput,
1✔
191
                as_array: as_array_config,
1✔
192
        ) {
1✔
193
                super();
1✔
194

1✔
195
                this.#parent = parent;
1✔
196
                this.as_array = as_array;
1✔
197
        }
1✔
198

3✔
199
        toTypeResult() {
3✔
200
                if (true === this.as_array || this.as_array.minimum < 1) {
1✔
201
                        return factory.createArrayTypeNode(this.#parent.toTypeResult());
1✔
202
                }
1!
203

×
204
                const args: ReturnType<HasOutput['toTypeResult']>[] = [];
×
205

×
206
                const minimum = Math.max(1, this.as_array.minimum);
×
207

×
208
                for (let i = 0; i < minimum; ++i) {
×
209
                        args.push(this.#parent.toTypeResult());
×
210
                }
×
211

×
212
                return factory.createTupleTypeNode(
×
213
                        [
×
214
                                ...args,
×
215
                                factory.createRestTypeNode(
×
216
                                        factory.createArrayTypeNode(this.#parent.toTypeResult()),
×
217
                                ),
×
218
                        ],
×
219
                );
×
220
        }
1✔
221
}
3✔
222

3✔
223
export class Types {
3✔
224
        list_of_types: [
3✔
225
                (
83✔
226
                        | Type<Exclude<string, ''>>
83✔
227
                        | Type<undefined>
83✔
228
                ),
83✔
229
                ...(
83✔
230
                        | Type<Exclude<string, ''>>
83✔
231
                        | Type<undefined>
83✔
232
                )[],
83✔
233
        ] | undefined = undefined;
3✔
234

3✔
235
        get size() {
3✔
236
                return this.list_of_types ? this.list_of_types.length : 0;
68✔
237
        }
68✔
238

3✔
239
        static #is_object_type(
3✔
240
                type: specify_types_config,
3,340✔
241
        ): type is Exclude<specify_types_config, string> {
3,340✔
242
                return 'string' !== typeof type;
3,340✔
243
        }
3,340✔
244

3✔
245
        add<T extends specify_types_config>(type: T) {
3✔
246
                return Types.toObject(
3,338✔
247
                        type,
3,338✔
248
                        (as_object) => {
3,338✔
249
                                if (undefined === this.list_of_types) {
3,338✔
250
                                        this.list_of_types = [as_object];
58✔
251
                                } else {
8✔
252
                                        const maybe = this.list_of_types.find((
3,264✔
253
                                                maybe,
3,451✔
254
                                        ) => maybe.id === as_object.id);
3,264✔
255

3,264✔
256
                                        if (!maybe) {
3,264✔
257
                                                this.list_of_types.push(as_object);
3,264✔
258
                                        } else {
3,264✔
259
                                                as_object = maybe;
3,264✔
260
                                        }
3,264✔
261
                                }
3,264✔
262

3,338✔
263
                                return as_object;
3,338✔
264
                        },
3,338✔
265
                );
3,338✔
266
        }
3,338✔
267

3✔
268
        * [Symbol.iterator]() {
3✔
269
                if (!this.list_of_types) {
59✔
270
                        return;
59✔
271
                }
59✔
272

59✔
273
                for (const type of this.list_of_types) {
59✔
274
                        yield type;
96✔
275
                }
96✔
276
        }
59✔
277

3✔
278
        static toObject(
3✔
279
                type: specify_types_config,
3,340✔
280
                juggle?: (as_object: (
3,340✔
281
                        | Type<Exclude<string, ''>>
3,340✔
282
                        | Type<undefined>
3,340✔
283
                )) => (
3,340✔
284
                        | Type<Exclude<string, ''>>
3,340✔
285
                        | Type<undefined>
3,340✔
286
                ),
3,340✔
287
        ) {
3,340✔
288
                const is_object = this.#is_object_type(type);
3,340✔
289

3,340✔
290
                let as_object: (
3,340✔
291
                        | Type<Exclude<string, ''>>
3,340✔
292
                        | Type<undefined>
3,340✔
293
                ) = (
3,340✔
294
                        !is_object
3,340✔
295
                                ? new Type(type, undefined)
3,340✔
296
                                : (
3,340✔
297
                                        'as' in type && type.as
22✔
298
                                                ? new Type(type.name, type.as)
22✔
299
                                                : new Type(type.name, undefined)
22✔
300
                                )
22✔
301
                );
3,340✔
302

3,340✔
303
                if (juggle) {
3,340✔
304
                        as_object = juggle(as_object);
3,322✔
305
                }
3,322✔
306

3,340✔
307
                if (is_object) {
3,340✔
308
                        let result: (
22✔
309
                                | Type
22✔
310
                                | WithSubTypeChain
22✔
311
                                | WithArray
22✔
312
                        ) = as_object;
22✔
313

22✔
314
                        if ('args' in type) {
22✔
315
                                result = result.withArgs(type.args);
13✔
316
                        }
13✔
317

22✔
318
                        if ('sub_type_chain' in type && !!type.sub_type_chain) {
22✔
319
                                result = result.withSubTypeChain(type.sub_type_chain);
2✔
320
                        }
2✔
321

22✔
322
                        if ('as_array' in type && !!type.as_array) {
22✔
323
                                result = result.withArray(type.as_array);
1✔
324
                        }
1✔
325

22✔
326
                        return result;
22✔
327
                }
22✔
328

3,318✔
329
                return as_object;
3,318✔
330
        }
3,340✔
331
}
3✔
332

3✔
333
export type {
3✔
334
        WithSubTypeChain,
3✔
335
        WithArray,
3✔
336
};
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