@isentinel/jest-roblox 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -2
- package/dist/cli.d.mts +1 -1
- package/dist/cli.mjs +284 -387
- package/dist/{executor-CNz6_04-.d.mts → executor-B2IDh6bH.d.mts} +176 -89
- package/dist/{game-output-C0KykXIi.mjs → game-output-CwmtpYhn.mjs} +531 -172
- package/dist/index.d.mts +301 -19
- package/dist/index.mjs +2 -2
- package/dist/sea/jest-roblox +0 -0
- package/dist/sea-entry.cjs +5123 -20005
- package/package.json +17 -13
- package/plugin/JestRobloxRunner.rbxm +0 -0
- package/plugin/out/shared/entry.luau +3 -2
- package/plugin/out/shared/promise.luau +2006 -0
- package/plugin/out/shared/runner.luau +69 -1
- package/plugin/out/shared/setup-timing.luau +89 -0
- package/plugin/src/init.server.luau +1 -1
- package/plugin/src/test-in-run-mode.server.luau +14 -4
|
@@ -57,7 +57,7 @@ type Argv = Partial<{
|
|
|
57
57
|
version: boolean;
|
|
58
58
|
}>;
|
|
59
59
|
//#endregion
|
|
60
|
-
//#region node_modules/.pnpm/type-fest@5.
|
|
60
|
+
//#region node_modules/.pnpm/type-fest@5.5.0/node_modules/type-fest/source/is-any.d.ts
|
|
61
61
|
/**
|
|
62
62
|
Returns a boolean for whether the given type is `any`.
|
|
63
63
|
|
|
@@ -72,8 +72,8 @@ import type {IsAny} from 'type-fest';
|
|
|
72
72
|
const typedObject = {a: 1, b: 2} as const;
|
|
73
73
|
const anyObject: any = {a: 1, b: 2};
|
|
74
74
|
|
|
75
|
-
function get<O extends (IsAny<O> extends true ? {} : Record<string, number>), K extends keyof O = keyof O>(
|
|
76
|
-
return
|
|
75
|
+
function get<O extends (IsAny<O> extends true ? {} : Record<string, number>), K extends keyof O = keyof O>(object: O, key: K) {
|
|
76
|
+
return object[key];
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
const typedA = get(typedObject, 'a');
|
|
@@ -88,7 +88,7 @@ const anyA = get(anyObject, 'a');
|
|
|
88
88
|
*/
|
|
89
89
|
type IsAny<T> = 0 extends 1 & NoInfer<T> ? true : false;
|
|
90
90
|
//#endregion
|
|
91
|
-
//#region node_modules/.pnpm/type-fest@5.
|
|
91
|
+
//#region node_modules/.pnpm/type-fest@5.5.0/node_modules/type-fest/source/is-optional-key-of.d.ts
|
|
92
92
|
/**
|
|
93
93
|
Returns a boolean for whether the given key is an optional key of type.
|
|
94
94
|
|
|
@@ -98,17 +98,17 @@ This is useful when writing utility types or schema validators that need to diff
|
|
|
98
98
|
```
|
|
99
99
|
import type {IsOptionalKeyOf} from 'type-fest';
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
type User = {
|
|
102
102
|
name: string;
|
|
103
103
|
surname: string;
|
|
104
104
|
|
|
105
105
|
luckyNumber?: number;
|
|
106
|
-
}
|
|
106
|
+
};
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
type Admin = {
|
|
109
109
|
name: string;
|
|
110
110
|
surname?: string;
|
|
111
|
-
}
|
|
111
|
+
};
|
|
112
112
|
|
|
113
113
|
type T1 = IsOptionalKeyOf<User, 'luckyNumber'>;
|
|
114
114
|
//=> true
|
|
@@ -131,7 +131,7 @@ type T5 = IsOptionalKeyOf<User | Admin, 'surname'>;
|
|
|
131
131
|
*/
|
|
132
132
|
type IsOptionalKeyOf<Type extends object, Key extends keyof Type> = IsAny<Type | Key> extends true ? never : Key extends keyof Type ? Type extends Record<Key, Type[Key]> ? false : true : false;
|
|
133
133
|
//#endregion
|
|
134
|
-
//#region node_modules/.pnpm/type-fest@5.
|
|
134
|
+
//#region node_modules/.pnpm/type-fest@5.5.0/node_modules/type-fest/source/optional-keys-of.d.ts
|
|
135
135
|
/**
|
|
136
136
|
Extract all optional keys from the given type.
|
|
137
137
|
|
|
@@ -141,12 +141,12 @@ This is useful when you want to create a new type that contains different type v
|
|
|
141
141
|
```
|
|
142
142
|
import type {OptionalKeysOf, Except} from 'type-fest';
|
|
143
143
|
|
|
144
|
-
|
|
144
|
+
type User = {
|
|
145
145
|
name: string;
|
|
146
146
|
surname: string;
|
|
147
147
|
|
|
148
148
|
luckyNumber?: number;
|
|
149
|
-
}
|
|
149
|
+
};
|
|
150
150
|
|
|
151
151
|
const REMOVE_FIELD = Symbol('remove field symbol');
|
|
152
152
|
type UpdateOperation<Entity extends object> = Except<Partial<Entity>, OptionalKeysOf<Entity>> & {
|
|
@@ -154,12 +154,12 @@ type UpdateOperation<Entity extends object> = Except<Partial<Entity>, OptionalKe
|
|
|
154
154
|
};
|
|
155
155
|
|
|
156
156
|
const update1: UpdateOperation<User> = {
|
|
157
|
-
name: 'Alice'
|
|
157
|
+
name: 'Alice',
|
|
158
158
|
};
|
|
159
159
|
|
|
160
160
|
const update2: UpdateOperation<User> = {
|
|
161
161
|
name: 'Bob',
|
|
162
|
-
luckyNumber: REMOVE_FIELD
|
|
162
|
+
luckyNumber: REMOVE_FIELD,
|
|
163
163
|
};
|
|
164
164
|
```
|
|
165
165
|
|
|
@@ -169,7 +169,7 @@ type OptionalKeysOf<Type extends object> = Type extends unknown // For distribut
|
|
|
169
169
|
? (keyof { [Key in keyof Type as IsOptionalKeyOf<Type, Key> extends false ? never : Key]: never }) & keyof Type // Intersect with `keyof Type` to ensure result of `OptionalKeysOf<Type>` is always assignable to `keyof Type`
|
|
170
170
|
: never;
|
|
171
171
|
//#endregion
|
|
172
|
-
//#region node_modules/.pnpm/type-fest@5.
|
|
172
|
+
//#region node_modules/.pnpm/type-fest@5.5.0/node_modules/type-fest/source/required-keys-of.d.ts
|
|
173
173
|
/**
|
|
174
174
|
Extract all required keys from the given type.
|
|
175
175
|
|
|
@@ -179,17 +179,23 @@ This is useful when you want to create a new type that contains different type v
|
|
|
179
179
|
```
|
|
180
180
|
import type {RequiredKeysOf} from 'type-fest';
|
|
181
181
|
|
|
182
|
-
declare function createValidation<
|
|
182
|
+
declare function createValidation<
|
|
183
|
+
Entity extends object,
|
|
184
|
+
Key extends RequiredKeysOf<Entity> = RequiredKeysOf<Entity>,
|
|
185
|
+
>(field: Key, validator: (value: Entity[Key]) => boolean): (entity: Entity) => boolean;
|
|
183
186
|
|
|
184
|
-
|
|
187
|
+
type User = {
|
|
185
188
|
name: string;
|
|
186
189
|
surname: string;
|
|
187
|
-
|
|
188
190
|
luckyNumber?: number;
|
|
189
|
-
}
|
|
191
|
+
};
|
|
190
192
|
|
|
191
193
|
const validator1 = createValidation<User>('name', value => value.length < 25);
|
|
192
194
|
const validator2 = createValidation<User>('surname', value => value.length < 25);
|
|
195
|
+
|
|
196
|
+
// @ts-expect-error
|
|
197
|
+
const validator3 = createValidation<User>('luckyNumber', value => value > 0);
|
|
198
|
+
// Error: Argument of type '"luckyNumber"' is not assignable to parameter of type '"name" | "surname"'.
|
|
193
199
|
```
|
|
194
200
|
|
|
195
201
|
@category Utilities
|
|
@@ -197,7 +203,7 @@ const validator2 = createValidation<User>('surname', value => value.length < 25)
|
|
|
197
203
|
type RequiredKeysOf<Type extends object> = Type extends unknown // For distributing `Type`
|
|
198
204
|
? Exclude<keyof Type, OptionalKeysOf<Type>> : never;
|
|
199
205
|
//#endregion
|
|
200
|
-
//#region node_modules/.pnpm/type-fest@5.
|
|
206
|
+
//#region node_modules/.pnpm/type-fest@5.5.0/node_modules/type-fest/source/is-never.d.ts
|
|
201
207
|
/**
|
|
202
208
|
Returns a boolean for whether the given type is `never`.
|
|
203
209
|
|
|
@@ -211,29 +217,41 @@ Useful in type utilities, such as checking if something does not occur.
|
|
|
211
217
|
```
|
|
212
218
|
import type {IsNever, And} from 'type-fest';
|
|
213
219
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
process.exit(0);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
220
|
+
type A = IsNever<never>;
|
|
221
|
+
//=> true
|
|
222
|
+
|
|
223
|
+
type B = IsNever<any>;
|
|
224
|
+
//=> false
|
|
225
|
+
|
|
226
|
+
type C = IsNever<unknown>;
|
|
227
|
+
//=> false
|
|
228
|
+
|
|
229
|
+
type D = IsNever<never[]>;
|
|
230
|
+
//=> false
|
|
231
|
+
|
|
232
|
+
type E = IsNever<object>;
|
|
233
|
+
//=> false
|
|
231
234
|
|
|
232
|
-
|
|
235
|
+
type F = IsNever<string>;
|
|
236
|
+
//=> false
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
@example
|
|
240
|
+
```
|
|
241
|
+
import type {IsNever} from 'type-fest';
|
|
242
|
+
|
|
243
|
+
type IsTrue<T> = T extends true ? true : false;
|
|
244
|
+
|
|
245
|
+
// When a distributive conditional is instantiated with `never`, the entire conditional results in `never`.
|
|
246
|
+
type A = IsTrue<never>;
|
|
233
247
|
//=> never
|
|
234
248
|
|
|
235
|
-
|
|
236
|
-
|
|
249
|
+
// If you don't want that behaviour, you can explicitly add an `IsNever` check before the distributive conditional.
|
|
250
|
+
type IsTrueFixed<T> =
|
|
251
|
+
IsNever<T> extends true ? false : T extends true ? true : false;
|
|
252
|
+
|
|
253
|
+
type B = IsTrueFixed<never>;
|
|
254
|
+
//=> false
|
|
237
255
|
```
|
|
238
256
|
|
|
239
257
|
@category Type Guard
|
|
@@ -241,7 +259,7 @@ endIfEqual('abc', '123');
|
|
|
241
259
|
*/
|
|
242
260
|
type IsNever<T> = [T] extends [never] ? true : false;
|
|
243
261
|
//#endregion
|
|
244
|
-
//#region node_modules/.pnpm/type-fest@5.
|
|
262
|
+
//#region node_modules/.pnpm/type-fest@5.5.0/node_modules/type-fest/source/if.d.ts
|
|
245
263
|
/**
|
|
246
264
|
An if-else-like type that resolves depending on whether the given `boolean` type is `true` or `false`.
|
|
247
265
|
|
|
@@ -254,7 +272,7 @@ Note:
|
|
|
254
272
|
|
|
255
273
|
@example
|
|
256
274
|
```
|
|
257
|
-
import {If} from 'type-fest';
|
|
275
|
+
import type {If} from 'type-fest';
|
|
258
276
|
|
|
259
277
|
type A = If<true, 'yes', 'no'>;
|
|
260
278
|
//=> 'yes'
|
|
@@ -274,7 +292,7 @@ type E = If<never, 'yes', 'no'>;
|
|
|
274
292
|
|
|
275
293
|
@example
|
|
276
294
|
```
|
|
277
|
-
import {If, IsAny, IsNever} from 'type-fest';
|
|
295
|
+
import type {If, IsAny, IsNever} from 'type-fest';
|
|
278
296
|
|
|
279
297
|
type A = If<IsAny<unknown>, 'is any', 'not any'>;
|
|
280
298
|
//=> 'not any'
|
|
@@ -285,7 +303,7 @@ type B = If<IsNever<never>, 'is never', 'not never'>;
|
|
|
285
303
|
|
|
286
304
|
@example
|
|
287
305
|
```
|
|
288
|
-
import {If, IsEqual} from 'type-fest';
|
|
306
|
+
import type {If, IsEqual} from 'type-fest';
|
|
289
307
|
|
|
290
308
|
type IfEqual<T, U, IfBranch, ElseBranch> = If<IsEqual<T, U>, IfBranch, ElseBranch>;
|
|
291
309
|
|
|
@@ -336,7 +354,7 @@ type Works = IncludesWithoutIf<HundredZeroes, '1'>;
|
|
|
336
354
|
*/
|
|
337
355
|
type If<Type extends boolean, IfBranch, ElseBranch> = IsNever<Type> extends true ? ElseBranch : Type extends true ? IfBranch : ElseBranch;
|
|
338
356
|
//#endregion
|
|
339
|
-
//#region node_modules/.pnpm/type-fest@5.
|
|
357
|
+
//#region node_modules/.pnpm/type-fest@5.5.0/node_modules/type-fest/source/simplify.d.ts
|
|
340
358
|
/**
|
|
341
359
|
Useful to flatten the type output to improve type hints shown in editors. And also to transform an interface into a type to aide with assignability.
|
|
342
360
|
|
|
@@ -382,10 +400,11 @@ const literal = {foo: 123, bar: 'hello', baz: 456};
|
|
|
382
400
|
const someType: SomeType = literal;
|
|
383
401
|
const someInterface: SomeInterface = literal;
|
|
384
402
|
|
|
385
|
-
function fn(object: Record<string, unknown>): void
|
|
403
|
+
declare function fn(object: Record<string, unknown>): void;
|
|
386
404
|
|
|
387
405
|
fn(literal); // Good: literal object type is sealed
|
|
388
406
|
fn(someType); // Good: type is sealed
|
|
407
|
+
// @ts-expect-error
|
|
389
408
|
fn(someInterface); // Error: Index signature for type 'string' is missing in type 'someInterface'. Because `interface` can be re-opened
|
|
390
409
|
fn(someInterface as Simplify<SomeInterface>); // Good: transform an `interface` into a `type`
|
|
391
410
|
```
|
|
@@ -396,7 +415,7 @@ fn(someInterface as Simplify<SomeInterface>); // Good: transform an `interface`
|
|
|
396
415
|
*/
|
|
397
416
|
type Simplify<T> = { [KeyType in keyof T]: T[KeyType] } & {};
|
|
398
417
|
//#endregion
|
|
399
|
-
//#region node_modules/.pnpm/type-fest@5.
|
|
418
|
+
//#region node_modules/.pnpm/type-fest@5.5.0/node_modules/type-fest/source/is-equal.d.ts
|
|
400
419
|
/**
|
|
401
420
|
Returns a boolean for whether the two given types are equal.
|
|
402
421
|
|
|
@@ -423,11 +442,11 @@ type Includes<Value extends readonly any[], Item> =
|
|
|
423
442
|
@category Type Guard
|
|
424
443
|
@category Utilities
|
|
425
444
|
*/
|
|
426
|
-
type IsEqual<A, B> = [A
|
|
445
|
+
type IsEqual<A, B> = [A] extends [B] ? [B] extends [A] ? _IsEqual<A, B> : false : false;
|
|
427
446
|
// This version fails the `equalWrappedTupleIntersectionToBeNeverAndNeverExpanded` test in `test-d/is-equal.ts`.
|
|
428
447
|
type _IsEqual<A, B> = (<G>() => G extends A & G | G ? 1 : 2) extends (<G>() => G extends B & G | G ? 1 : 2) ? true : false;
|
|
429
448
|
//#endregion
|
|
430
|
-
//#region node_modules/.pnpm/type-fest@5.
|
|
449
|
+
//#region node_modules/.pnpm/type-fest@5.5.0/node_modules/type-fest/source/omit-index-signature.d.ts
|
|
431
450
|
/**
|
|
432
451
|
Omit any index signatures from the given object type, leaving only explicitly defined properties.
|
|
433
452
|
|
|
@@ -445,8 +464,9 @@ It relies on the fact that an empty object (`{}`) is assignable to an object wit
|
|
|
445
464
|
```
|
|
446
465
|
const indexed: Record<string, unknown> = {}; // Allowed
|
|
447
466
|
|
|
467
|
+
// @ts-expect-error
|
|
448
468
|
const keyed: Record<'foo', unknown> = {}; // Error
|
|
449
|
-
//
|
|
469
|
+
// TS2739: Type '{}' is missing the following properties from type 'Record<"foo" | "bar", unknown>': foo, bar
|
|
450
470
|
```
|
|
451
471
|
|
|
452
472
|
Instead of causing a type error like the above, you can also use a [conditional type](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html) to test whether a type is assignable to another:
|
|
@@ -455,19 +475,21 @@ Instead of causing a type error like the above, you can also use a [conditional
|
|
|
455
475
|
type Indexed = {} extends Record<string, unknown>
|
|
456
476
|
? '✅ `{}` is assignable to `Record<string, unknown>`'
|
|
457
477
|
: '❌ `{}` is NOT assignable to `Record<string, unknown>`';
|
|
458
|
-
|
|
478
|
+
|
|
479
|
+
type IndexedResult = Indexed;
|
|
480
|
+
//=> '✅ `{}` is assignable to `Record<string, unknown>`'
|
|
459
481
|
|
|
460
482
|
type Keyed = {} extends Record<'foo' | 'bar', unknown>
|
|
461
|
-
?
|
|
462
|
-
:
|
|
463
|
-
|
|
483
|
+
? '✅ `{}` is assignable to `Record<\'foo\' | \'bar\', unknown>`'
|
|
484
|
+
: '❌ `{}` is NOT assignable to `Record<\'foo\' | \'bar\', unknown>`';
|
|
485
|
+
|
|
486
|
+
type KeyedResult = Keyed;
|
|
487
|
+
//=> '❌ `{}` is NOT assignable to `Record<\'foo\' | \'bar\', unknown>`'
|
|
464
488
|
```
|
|
465
489
|
|
|
466
490
|
Using a [mapped type](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#further-exploration), you can then check for each `KeyType` of `ObjectType`...
|
|
467
491
|
|
|
468
492
|
```
|
|
469
|
-
import type {OmitIndexSignature} from 'type-fest';
|
|
470
|
-
|
|
471
493
|
type OmitIndexSignature<ObjectType> = {
|
|
472
494
|
[KeyType in keyof ObjectType // Map each key of `ObjectType`...
|
|
473
495
|
]: ObjectType[KeyType]; // ...to its original value, i.e. `OmitIndexSignature<Foo> == Foo`.
|
|
@@ -477,14 +499,12 @@ type OmitIndexSignature<ObjectType> = {
|
|
|
477
499
|
...whether an empty object (`{}`) would be assignable to an object with that `KeyType` (`Record<KeyType, unknown>`)...
|
|
478
500
|
|
|
479
501
|
```
|
|
480
|
-
import type {OmitIndexSignature} from 'type-fest';
|
|
481
|
-
|
|
482
502
|
type OmitIndexSignature<ObjectType> = {
|
|
483
503
|
[KeyType in keyof ObjectType
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
504
|
+
// Is `{}` assignable to `Record<KeyType, unknown>`?
|
|
505
|
+
as {} extends Record<KeyType, unknown>
|
|
506
|
+
? never // ✅ `{}` is assignable to `Record<KeyType, unknown>`
|
|
507
|
+
: KeyType // ❌ `{}` is NOT assignable to `Record<KeyType, unknown>`
|
|
488
508
|
]: ObjectType[KeyType];
|
|
489
509
|
};
|
|
490
510
|
```
|
|
@@ -495,24 +515,24 @@ If `{}` is assignable, it means that `KeyType` is an index signature and we want
|
|
|
495
515
|
```
|
|
496
516
|
import type {OmitIndexSignature} from 'type-fest';
|
|
497
517
|
|
|
498
|
-
|
|
518
|
+
type Example = {
|
|
499
519
|
// These index signatures will be removed.
|
|
500
|
-
[x: string]: any
|
|
501
|
-
[x: number]: any
|
|
502
|
-
[x: symbol]: any
|
|
503
|
-
[x: `head-${string}`]: string
|
|
504
|
-
[x: `${string}-tail`]: string
|
|
505
|
-
[x: `head-${string}-tail`]: string
|
|
506
|
-
[x: `${bigint}`]: string
|
|
507
|
-
[x: `embedded-${number}`]: string
|
|
520
|
+
[x: string]: any;
|
|
521
|
+
[x: number]: any;
|
|
522
|
+
[x: symbol]: any;
|
|
523
|
+
[x: `head-${string}`]: string;
|
|
524
|
+
[x: `${string}-tail`]: string;
|
|
525
|
+
[x: `head-${string}-tail`]: string;
|
|
526
|
+
[x: `${bigint}`]: string;
|
|
527
|
+
[x: `embedded-${number}`]: string;
|
|
508
528
|
|
|
509
529
|
// These explicitly defined keys will remain.
|
|
510
530
|
foo: 'bar';
|
|
511
531
|
qux?: 'baz';
|
|
512
|
-
}
|
|
532
|
+
};
|
|
513
533
|
|
|
514
534
|
type ExampleWithoutIndexSignatures = OmitIndexSignature<Example>;
|
|
515
|
-
|
|
535
|
+
//=> {foo: 'bar'; qux?: 'baz'}
|
|
516
536
|
```
|
|
517
537
|
|
|
518
538
|
@see {@link PickIndexSignature}
|
|
@@ -520,7 +540,7 @@ type ExampleWithoutIndexSignatures = OmitIndexSignature<Example>;
|
|
|
520
540
|
*/
|
|
521
541
|
type OmitIndexSignature<ObjectType> = { [KeyType in keyof ObjectType as {} extends Record<KeyType, unknown> ? never : KeyType]: ObjectType[KeyType] };
|
|
522
542
|
//#endregion
|
|
523
|
-
//#region node_modules/.pnpm/type-fest@5.
|
|
543
|
+
//#region node_modules/.pnpm/type-fest@5.5.0/node_modules/type-fest/source/pick-index-signature.d.ts
|
|
524
544
|
/**
|
|
525
545
|
Pick only index signatures from the given object type, leaving out all explicitly defined properties.
|
|
526
546
|
|
|
@@ -568,22 +588,47 @@ type ExampleIndexSignature = PickIndexSignature<Example>;
|
|
|
568
588
|
*/
|
|
569
589
|
type PickIndexSignature<ObjectType> = { [KeyType in keyof ObjectType as {} extends Record<KeyType, unknown> ? KeyType : never]: ObjectType[KeyType] };
|
|
570
590
|
//#endregion
|
|
571
|
-
//#region node_modules/.pnpm/type-fest@5.
|
|
591
|
+
//#region node_modules/.pnpm/type-fest@5.5.0/node_modules/type-fest/source/merge.d.ts
|
|
572
592
|
// Merges two objects without worrying about index signatures.
|
|
573
|
-
type SimpleMerge<Destination, Source> = { [Key in keyof Destination as Key extends keyof Source ? never : Key]: Destination[Key] } & Source
|
|
593
|
+
type SimpleMerge<Destination, Source> = Simplify<{ [Key in keyof Destination as Key extends keyof Source ? never : Key]: Destination[Key] } & Source>;
|
|
574
594
|
/**
|
|
575
595
|
Merge two types into a new type. Keys of the second type overrides keys of the first type.
|
|
576
596
|
|
|
597
|
+
This is different from the TypeScript `&` (intersection) operator. With `&`, conflicting property types are intersected, which often results in `never`. For example, `{a: string} & {a: number}` makes `a` become `string & number`, which resolves to `never`. With `Merge`, the second type's keys cleanly override the first, so `Merge<{a: string}, {a: number}>` gives `{a: number}` as expected. `Merge` also produces a flattened type (via `Simplify`), making it more readable in IDE tooltips compared to `A & B`.
|
|
598
|
+
|
|
577
599
|
@example
|
|
578
600
|
```
|
|
579
601
|
import type {Merge} from 'type-fest';
|
|
580
602
|
|
|
581
|
-
|
|
603
|
+
type Foo = {
|
|
604
|
+
a: string;
|
|
605
|
+
b: number;
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
type Bar = {
|
|
609
|
+
a: number; // Conflicts with Foo['a']
|
|
610
|
+
c: boolean;
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
// With `&`, `a` becomes `string & number` which is `never`. Not what you want.
|
|
614
|
+
type WithIntersection = (Foo & Bar)['a'];
|
|
615
|
+
//=> never
|
|
616
|
+
|
|
617
|
+
// With `Merge`, `a` is cleanly overridden to `number`.
|
|
618
|
+
type WithMerge = Merge<Foo, Bar>['a'];
|
|
619
|
+
//=> number
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
@example
|
|
623
|
+
```
|
|
624
|
+
import type {Merge} from 'type-fest';
|
|
625
|
+
|
|
626
|
+
type Foo = {
|
|
582
627
|
[x: string]: unknown;
|
|
583
628
|
[x: number]: unknown;
|
|
584
629
|
foo: string;
|
|
585
630
|
bar: symbol;
|
|
586
|
-
}
|
|
631
|
+
};
|
|
587
632
|
|
|
588
633
|
type Bar = {
|
|
589
634
|
[x: number]: number;
|
|
@@ -593,7 +638,7 @@ type Bar = {
|
|
|
593
638
|
};
|
|
594
639
|
|
|
595
640
|
export type FooBar = Merge<Foo, Bar>;
|
|
596
|
-
|
|
641
|
+
//=> {
|
|
597
642
|
// [x: string]: unknown;
|
|
598
643
|
// [x: number]: number;
|
|
599
644
|
// [x: symbol]: unknown;
|
|
@@ -603,11 +648,19 @@ export type FooBar = Merge<Foo, Bar>;
|
|
|
603
648
|
// }
|
|
604
649
|
```
|
|
605
650
|
|
|
651
|
+
Note: If you want a merge type that more accurately reflects the runtime behavior of object spread or `Object.assign`, refer to the {@link ObjectMerge} type.
|
|
652
|
+
|
|
653
|
+
@see {@link ObjectMerge}
|
|
606
654
|
@category Object
|
|
607
655
|
*/
|
|
608
|
-
type Merge<Destination, Source> =
|
|
656
|
+
type Merge<Destination, Source> = Destination extends unknown // For distributing `Destination`
|
|
657
|
+
? Source extends unknown // For distributing `Source`
|
|
658
|
+
? If<IsEqual<Destination, Source>, Destination, _Merge<Destination, Source>> : never // Should never happen
|
|
659
|
+
: never;
|
|
660
|
+
// Should never happen
|
|
661
|
+
type _Merge<Destination, Source> = Simplify<SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>> & SimpleMerge<OmitIndexSignature<Destination>, OmitIndexSignature<Source>>>;
|
|
609
662
|
//#endregion
|
|
610
|
-
//#region node_modules/.pnpm/type-fest@5.
|
|
663
|
+
//#region node_modules/.pnpm/type-fest@5.5.0/node_modules/type-fest/source/internal/object.d.ts
|
|
611
664
|
/**
|
|
612
665
|
Merges user specified options with default options.
|
|
613
666
|
|
|
@@ -662,7 +715,7 @@ type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOp
|
|
|
662
715
|
*/
|
|
663
716
|
type ApplyDefaultOptions<Options extends object, Defaults extends Simplify<Omit<Required<Options>, RequiredKeysOf<Options>> & Partial<Record<RequiredKeysOf<Options>, never>>>, SpecifiedOptions extends Options> = If<IsAny<SpecifiedOptions>, Defaults, If<IsNever<SpecifiedOptions>, Defaults, Simplify<Merge<Defaults, { [Key in keyof SpecifiedOptions as Key extends OptionalKeysOf<Options> ? undefined extends SpecifiedOptions[Key] ? never : Key : Key]: SpecifiedOptions[Key] }> & Required<Options>>>>;
|
|
664
717
|
//#endregion
|
|
665
|
-
//#region node_modules/.pnpm/type-fest@5.
|
|
718
|
+
//#region node_modules/.pnpm/type-fest@5.5.0/node_modules/type-fest/source/except.d.ts
|
|
666
719
|
/**
|
|
667
720
|
Filter out keys from an object.
|
|
668
721
|
|
|
@@ -723,14 +776,16 @@ type Foo = {
|
|
|
723
776
|
type FooWithoutA = Except<Foo, 'a'>;
|
|
724
777
|
//=> {b: string}
|
|
725
778
|
|
|
779
|
+
// @ts-expect-error
|
|
726
780
|
const fooWithoutA: FooWithoutA = {a: 1, b: '2'};
|
|
727
|
-
|
|
781
|
+
// errors: 'a' does not exist in type '{ b: string; }'
|
|
728
782
|
|
|
729
783
|
type FooWithoutB = Except<Foo, 'b', {requireExactProps: true}>;
|
|
730
|
-
//=> {a: number} & Partial<Record<
|
|
784
|
+
//=> {a: number} & Partial<Record<'b', never>>
|
|
731
785
|
|
|
786
|
+
// @ts-expect-error
|
|
732
787
|
const fooWithoutB: FooWithoutB = {a: 1, b: '2'};
|
|
733
|
-
|
|
788
|
+
// errors at 'b': Type 'string' is not assignable to type 'undefined'.
|
|
734
789
|
|
|
735
790
|
// The `Omit` utility type doesn't work when omitting specific keys from objects containing index signatures.
|
|
736
791
|
|
|
@@ -745,12 +800,12 @@ type UserData = {
|
|
|
745
800
|
|
|
746
801
|
// `Omit` clearly doesn't behave as expected in this case:
|
|
747
802
|
type PostPayload = Omit<UserData, 'email'>;
|
|
748
|
-
//=>
|
|
803
|
+
//=> {[x: string]: string; [x: number]: string}
|
|
749
804
|
|
|
750
805
|
// In situations like this, `Except` works better.
|
|
751
806
|
// It simply removes the `email` key while preserving all the other keys.
|
|
752
|
-
type
|
|
753
|
-
//=>
|
|
807
|
+
type PostPayloadFixed = Except<UserData, 'email'>;
|
|
808
|
+
//=> {[x: string]: string; name: string; role: 'admin' | 'user'}
|
|
754
809
|
```
|
|
755
810
|
|
|
756
811
|
@category Object
|
|
@@ -825,6 +880,7 @@ interface Config extends Except<Argv, "projects" | "rootDir" | "setupFiles" | "s
|
|
|
825
880
|
gameOutput?: string;
|
|
826
881
|
jestPath?: string;
|
|
827
882
|
luauRoots?: Array<string>;
|
|
883
|
+
parallel?: "auto" | number;
|
|
828
884
|
passWithNoTests?: boolean;
|
|
829
885
|
placeFile?: string;
|
|
830
886
|
pollInterval?: number;
|
|
@@ -887,6 +943,7 @@ interface CliOptions {
|
|
|
887
943
|
gameOutput?: string;
|
|
888
944
|
help?: boolean;
|
|
889
945
|
outputFile?: string;
|
|
946
|
+
parallel?: "auto" | number;
|
|
890
947
|
passWithNoTests?: boolean;
|
|
891
948
|
pollInterval?: number;
|
|
892
949
|
port?: number;
|
|
@@ -1001,30 +1058,53 @@ interface ParseResult {
|
|
|
1001
1058
|
coverageData?: RawCoverageData;
|
|
1002
1059
|
luauTiming?: Record<string, number>;
|
|
1003
1060
|
result: JestResult;
|
|
1061
|
+
setupSeconds?: number;
|
|
1004
1062
|
snapshotWrites?: SnapshotWrites;
|
|
1005
1063
|
}
|
|
1006
1064
|
declare function extractJsonFromOutput(output: string): string | undefined;
|
|
1007
1065
|
declare function parseJestOutput(output: string): ParseResult;
|
|
1008
1066
|
//#endregion
|
|
1009
1067
|
//#region src/backends/interface.d.ts
|
|
1010
|
-
interface
|
|
1068
|
+
interface ProjectJob {
|
|
1011
1069
|
config: ResolvedConfig;
|
|
1070
|
+
displayColor?: string;
|
|
1071
|
+
displayName: string;
|
|
1012
1072
|
testFiles: Array<string>;
|
|
1013
1073
|
}
|
|
1074
|
+
interface BackendOptions {
|
|
1075
|
+
jobs: Array<ProjectJob>;
|
|
1076
|
+
/**
|
|
1077
|
+
* Open-Cloud-only: number of concurrent Open Cloud Luau execution sessions
|
|
1078
|
+
* to fire. Unset or 1 means one session carrying all jobs. `"auto"` resolves
|
|
1079
|
+
* to min(jobs.length, 3). Studio backend must error when this is set to
|
|
1080
|
+
* anything other than undefined/1 (Phase 4 enforces at the CLI layer).
|
|
1081
|
+
*/
|
|
1082
|
+
parallel?: "auto" | number;
|
|
1083
|
+
}
|
|
1014
1084
|
interface BackendTiming {
|
|
1015
1085
|
executionMs: number;
|
|
1016
1086
|
uploadCached?: boolean;
|
|
1017
1087
|
uploadMs?: number;
|
|
1018
1088
|
}
|
|
1019
|
-
interface
|
|
1089
|
+
interface ProjectBackendResult {
|
|
1020
1090
|
coverageData?: RawCoverageData;
|
|
1091
|
+
displayColor?: string;
|
|
1092
|
+
displayName: string;
|
|
1093
|
+
elapsedMs: number;
|
|
1021
1094
|
gameOutput?: string;
|
|
1022
1095
|
luauTiming?: Record<string, number>;
|
|
1023
1096
|
result: JestResult;
|
|
1097
|
+
setupMs?: number;
|
|
1024
1098
|
snapshotWrites?: SnapshotWrites;
|
|
1099
|
+
}
|
|
1100
|
+
interface BackendResult {
|
|
1101
|
+
results: Array<ProjectBackendResult>;
|
|
1025
1102
|
timing: BackendTiming;
|
|
1026
1103
|
}
|
|
1104
|
+
type BackendKind = "open-cloud" | "studio";
|
|
1027
1105
|
interface Backend {
|
|
1106
|
+
close?(): Promise<void> | void;
|
|
1107
|
+
readonly kind: BackendKind;
|
|
1028
1108
|
runTests(options: BackendOptions): Promise<BackendResult>;
|
|
1029
1109
|
}
|
|
1030
1110
|
//#endregion
|
|
@@ -1051,6 +1131,7 @@ interface SourceMapper {
|
|
|
1051
1131
|
interface TimingResult {
|
|
1052
1132
|
coverageMs?: number;
|
|
1053
1133
|
executionMs: number;
|
|
1134
|
+
setupMs?: number;
|
|
1054
1135
|
startTime: number;
|
|
1055
1136
|
testsMs: number;
|
|
1056
1137
|
totalMs: number;
|
|
@@ -1083,6 +1164,12 @@ interface FormatOutputOptions {
|
|
|
1083
1164
|
version: string;
|
|
1084
1165
|
}
|
|
1085
1166
|
declare function formatExecuteOutput(options: FormatOutputOptions): string;
|
|
1167
|
+
/**
|
|
1168
|
+
* Single-project convenience wrapper: builds a length-1 jobs array, fires
|
|
1169
|
+
* `executeBackend` once, and maps the single entry through
|
|
1170
|
+
* `processProjectResult`. Multi-project callers drive `executeBackend` +
|
|
1171
|
+
* `processProjectResult` directly from `cli.ts`.
|
|
1172
|
+
*/
|
|
1086
1173
|
declare function execute(options: ExecuteOptions): Promise<ExecuteResult>;
|
|
1087
1174
|
//#endregion
|
|
1088
1175
|
export { defineConfig as A, FormatterEntry as C, ROOT_ONLY_KEYS as D, ProjectTestConfig as E, Argv as M, ResolvedConfig as O, DisplayName as S, ProjectEntry as T, ResolvedProjectConfig as _, formatExecuteOutput as a, ConfigInput as b, Backend as c, extractJsonFromOutput as d, parseJestOutput as f, TestStatus as g, TestFileResult as h, execute as i, defineProject as j, SnapshotFormatOptions as k, BackendOptions as l, TestCaseResult as m, ExecuteResult as n, TimingResult as o, JestResult as p, FormatOutputOptions as r, SourceMapper as s, ExecuteOptions as t, BackendResult as u, CliOptions as v, InlineProjectConfig as w, DEFAULT_CONFIG as x, Config as y };
|