@huanglangjian/specs 0.3.1 → 0.5.0

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/dist/index.d.mts CHANGED
@@ -1,4 +1,929 @@
1
- //#region ../../node_modules/.pnpm/type-fest@5.5.0/node_modules/type-fest/source/simplify.d.ts
1
+ //#region ../../node_modules/.pnpm/@standard-schema+spec@1.1.0/node_modules/@standard-schema/spec/dist/index.d.ts
2
+ /** The Standard Typed interface. This is a base type extended by other specs. */
3
+ interface StandardTypedV1<Input = unknown, Output = Input> {
4
+ /** The Standard properties. */
5
+ readonly "~standard": StandardTypedV1.Props<Input, Output>;
6
+ }
7
+ declare namespace StandardTypedV1 {
8
+ /** The Standard Typed properties interface. */
9
+ interface Props<Input = unknown, Output = Input> {
10
+ /** The version number of the standard. */
11
+ readonly version: 1;
12
+ /** The vendor name of the schema library. */
13
+ readonly vendor: string;
14
+ /** Inferred types associated with the schema. */
15
+ readonly types?: Types<Input, Output> | undefined;
16
+ }
17
+ /** The Standard Typed types interface. */
18
+ interface Types<Input = unknown, Output = Input> {
19
+ /** The input type of the schema. */
20
+ readonly input: Input;
21
+ /** The output type of the schema. */
22
+ readonly output: Output;
23
+ }
24
+ /** Infers the input type of a Standard Typed. */
25
+ type InferInput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["input"];
26
+ /** Infers the output type of a Standard Typed. */
27
+ type InferOutput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["output"];
28
+ }
29
+ /** The Standard Schema interface. */
30
+ //#endregion
31
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/primitive.d.ts
32
+ /**
33
+ Matches any [primitive value](https://developer.mozilla.org/en-US/docs/Glossary/Primitive).
34
+
35
+ @category Type
36
+ */
37
+ type Primitive = null | undefined | string | number | boolean | symbol | bigint;
38
+ //#endregion
39
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/is-any.d.ts
40
+ /**
41
+ Returns a boolean for whether the given type is `any`.
42
+
43
+ @link https://stackoverflow.com/a/49928360/1490091
44
+
45
+ Useful in type utilities, such as disallowing `any`s to be passed to a function.
46
+
47
+ @example
48
+ ```
49
+ import type {IsAny} from 'type-fest';
50
+
51
+ const typedObject = {a: 1, b: 2} as const;
52
+ const anyObject: any = {a: 1, b: 2};
53
+
54
+ function get<O extends (IsAny<O> extends true ? {} : Record<string, number>), K extends keyof O = keyof O>(object: O, key: K) {
55
+ return object[key];
56
+ }
57
+
58
+ const typedA = get(typedObject, 'a');
59
+ //=> 1
60
+
61
+ const anyA = get(anyObject, 'a');
62
+ //=> any
63
+ ```
64
+
65
+ @category Type Guard
66
+ @category Utilities
67
+ */
68
+ type IsAny<T> = 0 extends 1 & NoInfer<T> ? true : false;
69
+ //#endregion
70
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/is-optional-key-of.d.ts
71
+ /**
72
+ Returns a boolean for whether the given key is an optional key of type.
73
+
74
+ This is useful when writing utility types or schema validators that need to differentiate `optional` keys.
75
+
76
+ @example
77
+ ```
78
+ import type {IsOptionalKeyOf} from 'type-fest';
79
+
80
+ type User = {
81
+ name: string;
82
+ surname: string;
83
+
84
+ luckyNumber?: number;
85
+ };
86
+
87
+ type Admin = {
88
+ name: string;
89
+ surname?: string;
90
+ };
91
+
92
+ type T1 = IsOptionalKeyOf<User, 'luckyNumber'>;
93
+ //=> true
94
+
95
+ type T2 = IsOptionalKeyOf<User, 'name'>;
96
+ //=> false
97
+
98
+ type T3 = IsOptionalKeyOf<User, 'name' | 'luckyNumber'>;
99
+ //=> boolean
100
+
101
+ type T4 = IsOptionalKeyOf<User | Admin, 'name'>;
102
+ //=> false
103
+
104
+ type T5 = IsOptionalKeyOf<User | Admin, 'surname'>;
105
+ //=> boolean
106
+ ```
107
+
108
+ @category Type Guard
109
+ @category Utilities
110
+ */
111
+ 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;
112
+ //#endregion
113
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/optional-keys-of.d.ts
114
+ /**
115
+ Extract all optional keys from the given type.
116
+
117
+ This is useful when you want to create a new type that contains different type values for the optional keys only.
118
+
119
+ @example
120
+ ```
121
+ import type {OptionalKeysOf, Except} from 'type-fest';
122
+
123
+ type User = {
124
+ name: string;
125
+ surname: string;
126
+
127
+ luckyNumber?: number;
128
+ };
129
+
130
+ const REMOVE_FIELD = Symbol('remove field symbol');
131
+ type UpdateOperation<Entity extends object> = Except<Partial<Entity>, OptionalKeysOf<Entity>> & {
132
+ [Key in OptionalKeysOf<Entity>]?: Entity[Key] | typeof REMOVE_FIELD;
133
+ };
134
+
135
+ const update1: UpdateOperation<User> = {
136
+ name: 'Alice',
137
+ };
138
+
139
+ const update2: UpdateOperation<User> = {
140
+ name: 'Bob',
141
+ luckyNumber: REMOVE_FIELD,
142
+ };
143
+ ```
144
+
145
+ @category Utilities
146
+ */
147
+ type OptionalKeysOf<Type extends object> = Type extends unknown // For distributing `Type`
148
+ ? (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`
149
+ : never;
150
+ //#endregion
151
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/required-keys-of.d.ts
152
+ /**
153
+ Extract all required keys from the given type.
154
+
155
+ This is useful when you want to create a new type that contains different type values for the required keys only or use the list of keys for validation purposes, etc...
156
+
157
+ @example
158
+ ```
159
+ import type {RequiredKeysOf} from 'type-fest';
160
+
161
+ declare function createValidation<
162
+ Entity extends object,
163
+ Key extends RequiredKeysOf<Entity> = RequiredKeysOf<Entity>,
164
+ >(field: Key, validator: (value: Entity[Key]) => boolean): (entity: Entity) => boolean;
165
+
166
+ type User = {
167
+ name: string;
168
+ surname: string;
169
+ luckyNumber?: number;
170
+ };
171
+
172
+ const validator1 = createValidation<User>('name', value => value.length < 25);
173
+ const validator2 = createValidation<User>('surname', value => value.length < 25);
174
+
175
+ // @ts-expect-error
176
+ const validator3 = createValidation<User>('luckyNumber', value => value > 0);
177
+ // Error: Argument of type '"luckyNumber"' is not assignable to parameter of type '"name" | "surname"'.
178
+ ```
179
+
180
+ @category Utilities
181
+ */
182
+ type RequiredKeysOf<Type extends object> = Type extends unknown // For distributing `Type`
183
+ ? Exclude<keyof Type, OptionalKeysOf<Type>> : never;
184
+ //#endregion
185
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/is-never.d.ts
186
+ /**
187
+ Returns a boolean for whether the given type is `never`.
188
+
189
+ @link https://github.com/microsoft/TypeScript/issues/31751#issuecomment-498526919
190
+ @link https://stackoverflow.com/a/53984913/10292952
191
+ @link https://www.zhenghao.io/posts/ts-never
192
+
193
+ Useful in type utilities, such as checking if something does not occur.
194
+
195
+ @example
196
+ ```
197
+ import type {IsNever, And} from 'type-fest';
198
+
199
+ type A = IsNever<never>;
200
+ //=> true
201
+
202
+ type B = IsNever<any>;
203
+ //=> false
204
+
205
+ type C = IsNever<unknown>;
206
+ //=> false
207
+
208
+ type D = IsNever<never[]>;
209
+ //=> false
210
+
211
+ type E = IsNever<object>;
212
+ //=> false
213
+
214
+ type F = IsNever<string>;
215
+ //=> false
216
+ ```
217
+
218
+ @example
219
+ ```
220
+ import type {IsNever} from 'type-fest';
221
+
222
+ type IsTrue<T> = T extends true ? true : false;
223
+
224
+ // When a distributive conditional is instantiated with `never`, the entire conditional results in `never`.
225
+ type A = IsTrue<never>;
226
+ //=> never
227
+
228
+ // If you don't want that behaviour, you can explicitly add an `IsNever` check before the distributive conditional.
229
+ type IsTrueFixed<T> =
230
+ IsNever<T> extends true ? false : T extends true ? true : false;
231
+
232
+ type B = IsTrueFixed<never>;
233
+ //=> false
234
+ ```
235
+
236
+ @category Type Guard
237
+ @category Utilities
238
+ */
239
+ type IsNever<T> = [T] extends [never] ? true : false;
240
+ //#endregion
241
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/if.d.ts
242
+ /**
243
+ An if-else-like type that resolves depending on whether the given `boolean` type is `true` or `false`.
244
+
245
+ Use-cases:
246
+ - You can use this in combination with `Is*` types to create an if-else-like experience. For example, `If<IsAny<any>, 'is any', 'not any'>`.
247
+
248
+ Note:
249
+ - Returns a union of if branch and else branch if the given type is `boolean` or `any`. For example, `If<boolean, 'Y', 'N'>` will return `'Y' | 'N'`.
250
+ - Returns the else branch if the given type is `never`. For example, `If<never, 'Y', 'N'>` will return `'N'`.
251
+
252
+ @example
253
+ ```
254
+ import type {If} from 'type-fest';
255
+
256
+ type A = If<true, 'yes', 'no'>;
257
+ //=> 'yes'
258
+
259
+ type B = If<false, 'yes', 'no'>;
260
+ //=> 'no'
261
+
262
+ type C = If<boolean, 'yes', 'no'>;
263
+ //=> 'yes' | 'no'
264
+
265
+ type D = If<any, 'yes', 'no'>;
266
+ //=> 'yes' | 'no'
267
+
268
+ type E = If<never, 'yes', 'no'>;
269
+ //=> 'no'
270
+ ```
271
+
272
+ @example
273
+ ```
274
+ import type {If, IsAny, IsNever} from 'type-fest';
275
+
276
+ type A = If<IsAny<unknown>, 'is any', 'not any'>;
277
+ //=> 'not any'
278
+
279
+ type B = If<IsNever<never>, 'is never', 'not never'>;
280
+ //=> 'is never'
281
+ ```
282
+
283
+ @example
284
+ ```
285
+ import type {If, IsEqual} from 'type-fest';
286
+
287
+ type IfEqual<T, U, IfBranch, ElseBranch> = If<IsEqual<T, U>, IfBranch, ElseBranch>;
288
+
289
+ type A = IfEqual<string, string, 'equal', 'not equal'>;
290
+ //=> 'equal'
291
+
292
+ type B = IfEqual<string, number, 'equal', 'not equal'>;
293
+ //=> 'not equal'
294
+ ```
295
+
296
+ Note: Sometimes using the `If` type can make an implementation non–tail-recursive, which can impact performance. In such cases, it’s better to use a conditional directly. Refer to the following example:
297
+
298
+ @example
299
+ ```
300
+ import type {If, IsEqual, StringRepeat} from 'type-fest';
301
+
302
+ type HundredZeroes = StringRepeat<'0', 100>;
303
+
304
+ // The following implementation is not tail recursive
305
+ type Includes<S extends string, Char extends string> =
306
+ S extends `${infer First}${infer Rest}`
307
+ ? If<IsEqual<First, Char>,
308
+ 'found',
309
+ Includes<Rest, Char>>
310
+ : 'not found';
311
+
312
+ // Hence, instantiations with long strings will fail
313
+ // @ts-expect-error
314
+ type Fails = Includes<HundredZeroes, '1'>;
315
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
316
+ // Error: Type instantiation is excessively deep and possibly infinite.
317
+
318
+ // However, if we use a simple conditional instead of `If`, the implementation becomes tail-recursive
319
+ type IncludesWithoutIf<S extends string, Char extends string> =
320
+ S extends `${infer First}${infer Rest}`
321
+ ? IsEqual<First, Char> extends true
322
+ ? 'found'
323
+ : IncludesWithoutIf<Rest, Char>
324
+ : 'not found';
325
+
326
+ // Now, instantiations with long strings will work
327
+ type Works = IncludesWithoutIf<HundredZeroes, '1'>;
328
+ //=> 'not found'
329
+ ```
330
+
331
+ @category Type Guard
332
+ @category Utilities
333
+ */
334
+ type If<Type extends boolean, IfBranch, ElseBranch> = IsNever<Type> extends true ? ElseBranch : Type extends true ? IfBranch : ElseBranch;
335
+ //#endregion
336
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/internal/type.d.ts
337
+ /**
338
+ Matches any primitive, `void`, `Date`, or `RegExp` value.
339
+ */
340
+ type BuiltIns = Primitive | void | Date | RegExp;
341
+ /**
342
+ Returns a boolean for whether the given `boolean` is not `false`.
343
+ */
344
+ type IsNotFalse<T extends boolean> = [T] extends [false] ? false : true;
345
+ /**
346
+ Returns a boolean for whether the given type is primitive value or primitive type.
347
+
348
+ @example
349
+ ```
350
+ type A = IsPrimitive<'string'>;
351
+ //=> true
352
+
353
+ type B = IsPrimitive<string>;
354
+ //=> true
355
+
356
+ type C = IsPrimitive<Object>;
357
+ //=> false
358
+ ```
359
+ */
360
+ type IsPrimitive<T> = [T] extends [Primitive] ? true : false;
361
+ /**
362
+ An if-else-like type that resolves depending on whether the given type is `any` or `never`.
363
+
364
+ @example
365
+ ```
366
+ // When `T` is a NOT `any` or `never` (like `string`) => Returns `IfNotAnyOrNever` branch
367
+ type A = IfNotAnyOrNever<string, 'VALID', 'IS_ANY', 'IS_NEVER'>;
368
+ //=> 'VALID'
369
+
370
+ // When `T` is `any` => Returns `IfAny` branch
371
+ type B = IfNotAnyOrNever<any, 'VALID', 'IS_ANY', 'IS_NEVER'>;
372
+ //=> 'IS_ANY'
373
+
374
+ // When `T` is `never` => Returns `IfNever` branch
375
+ type C = IfNotAnyOrNever<never, 'VALID', 'IS_ANY', 'IS_NEVER'>;
376
+ //=> 'IS_NEVER'
377
+ ```
378
+
379
+ Note: Wrapping a tail-recursive type with `IfNotAnyOrNever` makes the implementation non-tail-recursive. To fix this, move the recursion into a helper type. Refer to the following example:
380
+
381
+ @example
382
+ ```ts
383
+ import type {StringRepeat} from 'type-fest';
384
+
385
+ type NineHundredNinetyNineSpaces = StringRepeat<' ', 999>;
386
+
387
+ // The following implementation is not tail recursive
388
+ type TrimLeft<S extends string> = IfNotAnyOrNever<S, S extends ` ${infer R}` ? TrimLeft<R> : S>;
389
+
390
+ // Hence, instantiations with long strings will fail
391
+ // @ts-expect-error
392
+ type T1 = TrimLeft<NineHundredNinetyNineSpaces>;
393
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
394
+ // Error: Type instantiation is excessively deep and possibly infinite.
395
+
396
+ // To fix this, move the recursion into a helper type
397
+ type TrimLeftOptimised<S extends string> = IfNotAnyOrNever<S, _TrimLeftOptimised<S>>;
398
+
399
+ type _TrimLeftOptimised<S extends string> = S extends ` ${infer R}` ? _TrimLeftOptimised<R> : S;
400
+
401
+ type T2 = TrimLeftOptimised<NineHundredNinetyNineSpaces>;
402
+ //=> ''
403
+ ```
404
+ */
405
+ type IfNotAnyOrNever<T, IfNotAnyOrNever, IfAny = any, IfNever = never> = If<IsAny<T>, IfAny, If<IsNever<T>, IfNever, IfNotAnyOrNever>>;
406
+ //#endregion
407
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/numeric.d.ts
408
+ type _Numeric = number | bigint;
409
+ //#endregion
410
+ //#region ../../node_modules/.pnpm/tagged-tag@1.0.0/node_modules/tagged-tag/index.d.ts
411
+ declare const tag: unique symbol;
412
+ //#endregion
413
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/tagged.d.ts
414
+ // eslint-disable-next-line type-fest/require-exported-types
415
+ type TagContainer<Token> = {
416
+ readonly [tag]: Token;
417
+ };
418
+ type Tag<Token extends PropertyKey, TagMetadata> = TagContainer<{ [K in Token]: TagMetadata }>;
419
+ /**
420
+ Create a [tagged type](https://medium.com/@KevinBGreene/surviving-the-typescript-ecosystem-branding-and-type-tagging-6cf6e516523d) that can support [multiple tags](https://github.com/sindresorhus/type-fest/issues/665) and [per-tag metadata](https://medium.com/@ethanresnick/advanced-typescript-tagged-types-improved-with-type-level-metadata-5072fc125fcf).
421
+
422
+ A type returned by `Tagged` can be passed to `Tagged` again, to create a type with multiple tags.
423
+
424
+ A tag's name is usually a string (and must be a string, number, or symbol), but each application of a tag can also contain an arbitrary type as its "metadata". See {@link GetTagMetadata} for examples and explanation.
425
+
426
+ A type `A` returned by `Tagged` is assignable to another type `B` returned by `Tagged` if and only if:
427
+ - the underlying (untagged) type of `A` is assignable to the underlying type of `B`;
428
+ - `A` contains at least all the tags `B` has;
429
+ - and the metadata type for each of `A`'s tags is assignable to the metadata type of `B`'s corresponding tag.
430
+
431
+ There have been several discussions about adding similar features to TypeScript. Unfortunately, nothing has (yet) moved forward:
432
+ - [Microsoft/TypeScript#202](https://github.com/microsoft/TypeScript/issues/202)
433
+ - [Microsoft/TypeScript#4895](https://github.com/microsoft/TypeScript/issues/4895)
434
+ - [Microsoft/TypeScript#33290](https://github.com/microsoft/TypeScript/pull/33290)
435
+
436
+ @example
437
+ ```
438
+ import type {Tagged} from 'type-fest';
439
+
440
+ type AccountNumber = Tagged<number, 'AccountNumber'>;
441
+ type AccountBalance = Tagged<number, 'AccountBalance'>;
442
+
443
+ function createAccountNumber(): AccountNumber {
444
+ // As you can see, casting from a `number` (the underlying type being tagged) is allowed.
445
+ return 2 as AccountNumber;
446
+ }
447
+
448
+ declare function getMoneyForAccount(accountNumber: AccountNumber): AccountBalance;
449
+
450
+ // This will compile successfully.
451
+ getMoneyForAccount(createAccountNumber());
452
+
453
+ // But this won't, because it has to be explicitly passed as an `AccountNumber` type!
454
+ // Critically, you could not accidentally use an `AccountBalance` as an `AccountNumber`.
455
+ // @ts-expect-error
456
+ getMoneyForAccount(2);
457
+
458
+ // You can also use tagged values like their underlying, untagged type.
459
+ // I.e., this will compile successfully because an `AccountNumber` can be used as a regular `number`.
460
+ // In this sense, the underlying base type is not hidden, which differentiates tagged types from opaque types in other languages.
461
+ const accountNumber = createAccountNumber() + 2;
462
+ ```
463
+
464
+ @example
465
+ ```
466
+ import type {Tagged} from 'type-fest';
467
+
468
+ // You can apply multiple tags to a type by using `Tagged` repeatedly.
469
+ type Url = Tagged<string, 'URL'>;
470
+ type SpecialCacheKey = Tagged<Url, 'SpecialCacheKey'>;
471
+
472
+ // You can also pass a union of tag names, so this is equivalent to the above, although it doesn't give you the ability to assign distinct metadata to each tag.
473
+ type SpecialCacheKey2 = Tagged<string, 'URL' | 'SpecialCacheKey'>;
474
+ ```
475
+
476
+ @category Type
477
+ */
478
+ type Tagged<Type, TagName extends PropertyKey, TagMetadata = never> = Type & Tag<TagName, TagMetadata>;
479
+ /**
480
+ Get the untagged portion of a tagged type created with `Tagged`.
481
+
482
+ Why is this necessary?
483
+
484
+ 1. Use a `Tagged` type as object keys
485
+ 2. Prevent TS4058 error: "Return type of exported function has or is using name X from external module Y but cannot be named"
486
+
487
+ @example
488
+ ```
489
+ import type {Tagged, UnwrapTagged} from 'type-fest';
490
+
491
+ type AccountType = Tagged<'SAVINGS' | 'CHECKING', 'AccountType'>;
492
+
493
+ const moneyByAccountType: Record<UnwrapTagged<AccountType>, number> = {
494
+ SAVINGS: 99,
495
+ CHECKING: 0.1,
496
+ };
497
+
498
+ // Without UnwrapTagged, the following expression would throw a type error.
499
+ const money = moneyByAccountType.SAVINGS; // TS error: Property 'SAVINGS' does not exist
500
+
501
+ // Attempting to pass a non-Tagged type to UnwrapTagged will raise a type error.
502
+ // @ts-expect-error
503
+ type WontWork = UnwrapTagged<string>;
504
+ ```
505
+
506
+ @category Type
507
+ */
508
+ type UnwrapTagged<TaggedType extends Tag<PropertyKey, any>> = RemoveAllTags<TaggedType>;
509
+ type RemoveAllTags<T> = T extends Tag<PropertyKey, any> ? { [ThisTag in keyof T[typeof tag]]: T extends Tagged<infer Type, ThisTag, T[typeof tag][ThisTag]> ? RemoveAllTags<Type> : never }[keyof T[typeof tag]] : T;
510
+ /**
511
+ Note: The `Opaque` type is deprecated in favor of `Tagged`.
512
+
513
+ Attach a "tag" to an arbitrary type. This allows you to create distinct types, that aren't assignable to one another, for runtime values that would otherwise have the same type. (See examples.)
514
+
515
+ The generic type parameters can be anything.
516
+
517
+ Note that `Opaque` is somewhat of a misnomer here, in that, unlike [some alternative implementations](https://github.com/microsoft/TypeScript/issues/4895#issuecomment-425132582), the original, untagged type is not actually hidden. (E.g., functions that accept the untagged type can still be called with the "opaque" version -- but not vice-versa.)
518
+
519
+ Also note that this implementation is limited to a single tag. If you want to allow multiple tags, use `Tagged` instead.
520
+
521
+ [Read more about tagged types.](https://medium.com/@KevinBGreene/surviving-the-typescript-ecosystem-branding-and-type-tagging-6cf6e516523d)
522
+
523
+ There have been several discussions about adding similar features to TypeScript. Unfortunately, nothing has (yet) moved forward:
524
+ - [Microsoft/TypeScript#202](https://github.com/microsoft/TypeScript/issues/202)
525
+ - [Microsoft/TypeScript#15408](https://github.com/Microsoft/TypeScript/issues/15408)
526
+ - [Microsoft/TypeScript#15807](https://github.com/Microsoft/TypeScript/issues/15807)
527
+
528
+ @example
529
+ ```
530
+ import type {Opaque} from 'type-fest';
531
+
532
+ type AccountNumber = Opaque<number, 'AccountNumber'>;
533
+ type AccountBalance = Opaque<number, 'AccountBalance'>;
534
+
535
+ // The `Token` parameter allows the compiler to differentiate between types, whereas "unknown" will not. For example, consider the following structures:
536
+ type ThingOne = Opaque<string>;
537
+ type ThingTwo = Opaque<string>;
538
+
539
+ // To the compiler, these types are allowed to be cast to each other as they have the same underlying type. They are both `string & { __opaque__: unknown }`.
540
+ // To avoid this behaviour, you would instead pass the "Token" parameter, like so.
541
+ type NewThingOne = Opaque<string, 'ThingOne'>;
542
+ type NewThingTwo = Opaque<string, 'ThingTwo'>;
543
+
544
+ // Now they're completely separate types, so the following will fail to compile.
545
+ function createNewThingOne(): NewThingOne {
546
+ // As you can see, casting from a string is still allowed. However, you may not cast NewThingOne to NewThingTwo, and vice versa.
547
+ return 'new thing one' as NewThingOne;
548
+ }
549
+
550
+ // This will fail to compile, as they are fundamentally different types.
551
+ // @ts-expect-error
552
+ const thingTwo = createNewThingOne() as NewThingTwo;
553
+
554
+ // Here's another example of opaque typing.
555
+ function createAccountNumber(): AccountNumber {
556
+ return 2 as AccountNumber;
557
+ }
558
+
559
+ declare function getMoneyForAccount(accountNumber: AccountNumber): AccountBalance;
560
+
561
+ // This will compile successfully.
562
+ getMoneyForAccount(createAccountNumber());
563
+
564
+ // But this won't, because it has to be explicitly passed as an `AccountNumber` type.
565
+ // @ts-expect-error
566
+ getMoneyForAccount(2);
567
+
568
+ // You can use opaque values like they aren't opaque too.
569
+ const accountNumber = createAccountNumber();
570
+
571
+ // This will compile successfully.
572
+ const newAccountNumber = accountNumber + 2;
573
+
574
+ // As a side note, you can (and should) use recursive types for your opaque types to make them stronger and hopefully easier to type.
575
+ type Person = {
576
+ id: Opaque<number, Person>;
577
+ name: string;
578
+ };
579
+ ```
580
+
581
+ @category Type
582
+ @deprecated Use {@link Tagged} instead
583
+ */
584
+ //#endregion
585
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/is-literal.d.ts
586
+ /**
587
+ Returns a boolean for whether the given type `T` is the specified `LiteralType`.
588
+
589
+ @link https://stackoverflow.com/a/52806744/10292952
590
+
591
+ @example
592
+ ```
593
+ type A = LiteralCheck<1, number>;
594
+ //=> true
595
+
596
+ type B = LiteralCheck<number, number>;
597
+ //=> false
598
+
599
+ type C = LiteralCheck<1, string>;
600
+ //=> false
601
+ ```
602
+ */
603
+ type LiteralCheck<T, LiteralType extends Primitive> = (IsNever<T> extends false // Must be wider than `never`
604
+ ? [T] extends [LiteralType & infer U] // Remove any branding
605
+ ? [U] extends [LiteralType] // Must be narrower than `LiteralType`
606
+ ? [LiteralType] extends [U] // Cannot be wider than `LiteralType`
607
+ ? false : true : false : false : false);
608
+ /**
609
+ Returns a boolean for whether the given type `T` is one of the specified literal types in `LiteralUnionType`.
610
+
611
+ @example
612
+ ```
613
+ type A = LiteralChecks<1, Numeric>;
614
+ //=> true
615
+
616
+ type B = LiteralChecks<1n, Numeric>;
617
+ //=> true
618
+
619
+ type C = LiteralChecks<bigint, Numeric>;
620
+ //=> false
621
+ ```
622
+ */
623
+ type LiteralChecks<T, LiteralUnionType> = (// Conditional type to force union distribution.
624
+ // If `T` is none of the literal types in the union `LiteralUnionType`, then `LiteralCheck<T, LiteralType>` will evaluate to `false` for the whole union.
625
+ // If `T` is one of the literal types in the union, it will evaluate to `boolean` (i.e. `true | false`)
626
+ IsNotFalse<LiteralUnionType extends Primitive ? LiteralCheck<T, LiteralUnionType> : never>);
627
+ /**
628
+ Returns a boolean for whether the given type is a `string` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
629
+
630
+ Useful for:
631
+ - providing strongly-typed string manipulation functions
632
+ - constraining strings to be a string literal
633
+ - type utilities, such as when constructing parsers and ASTs
634
+
635
+ The implementation of this type is inspired by the trick mentioned in this [StackOverflow answer](https://stackoverflow.com/a/68261113/420747).
636
+
637
+ @example
638
+ ```
639
+ import type {IsStringLiteral} from 'type-fest';
640
+
641
+ type CapitalizedString<T extends string> = IsStringLiteral<T> extends true ? Capitalize<T> : string;
642
+
643
+ // https://github.com/yankeeinlondon/native-dash/blob/master/src/capitalize.ts
644
+ function capitalize<T extends Readonly<string>>(input: T): CapitalizedString<T> {
645
+ return (input.slice(0, 1).toUpperCase() + input.slice(1)) as CapitalizedString<T>;
646
+ }
647
+
648
+ const output = capitalize('hello, world!');
649
+ //=> 'Hello, world!'
650
+ ```
651
+
652
+ @example
653
+ ```
654
+ // String types with infinite set of possible values return `false`.
655
+
656
+ import type {IsStringLiteral} from 'type-fest';
657
+
658
+ type AllUppercaseStrings = IsStringLiteral<Uppercase<string>>;
659
+ //=> false
660
+
661
+ type StringsStartingWithOn = IsStringLiteral<`on${string}`>;
662
+ //=> false
663
+
664
+ // This behaviour is particularly useful in string manipulation utilities, as infinite string types often require separate handling.
665
+
666
+ type Length<S extends string, Counter extends never[] = []> =
667
+ IsStringLiteral<S> extends false
668
+ ? number // return `number` for infinite string types
669
+ : S extends `${string}${infer Tail}`
670
+ ? Length<Tail, [...Counter, never]>
671
+ : Counter['length'];
672
+
673
+ type L1 = Length<Lowercase<string>>;
674
+ //=> number
675
+
676
+ type L2 = Length<`${number}`>;
677
+ //=> number
678
+ ```
679
+
680
+ @category Type Guard
681
+ @category Utilities
682
+ */
683
+ type IsStringLiteral<S> = IfNotAnyOrNever<S, _IsStringLiteral<CollapseLiterals<S extends TagContainer<any> ? UnwrapTagged<S> : S>>, false, false>;
684
+ type _IsStringLiteral<S> = // If `T` is an infinite string type (e.g., `on${string}`), `Record<T, never>` produces an index signature,
685
+ // and since `{}` extends index signatures, the result becomes `false`.
686
+ S extends string ? {} extends Record<S, never> ? false : true : false;
687
+ /**
688
+ Returns a boolean for whether the given type is a `number` or `bigint` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
689
+
690
+ Useful for:
691
+ - providing strongly-typed functions when given literal arguments
692
+ - type utilities, such as when constructing parsers and ASTs
693
+
694
+ @example
695
+ ```
696
+ import type {IsNumericLiteral, IsStringLiteral} from 'type-fest';
697
+
698
+ // https://github.com/inocan-group/inferred-types/blob/master/modules/types/src/boolean-logic/operators/EndsWith.ts
699
+ type EndsWith<TValue, TEndsWith extends string> =
700
+ TValue extends string
701
+ ? IsStringLiteral<TEndsWith> extends true
702
+ ? IsStringLiteral<TValue> extends true
703
+ ? TValue extends `${string}${TEndsWith}`
704
+ ? true
705
+ : false
706
+ : boolean
707
+ : boolean
708
+ : TValue extends number
709
+ ? IsNumericLiteral<TValue> extends true
710
+ ? EndsWith<`${TValue}`, TEndsWith>
711
+ : false
712
+ : false;
713
+
714
+ function endsWith<Input extends string | number, End extends string>(input: Input, end: End) {
715
+ return `${input}`.endsWith(end) as EndsWith<Input, End>;
716
+ }
717
+
718
+ endsWith('abc', 'c');
719
+ //=> true
720
+
721
+ endsWith(123_456, '456');
722
+ //=> true
723
+
724
+ const end = '123' as string;
725
+
726
+ endsWith('abc123', end);
727
+ //=> boolean
728
+ ```
729
+
730
+ @category Type Guard
731
+ @category Utilities
732
+ */
733
+ type IsNumericLiteral<T> = LiteralChecks<T, _Numeric>;
734
+ /**
735
+ Returns a boolean for whether the given type is a `true` or `false` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
736
+
737
+ Useful for:
738
+ - providing strongly-typed functions when given literal arguments
739
+ - type utilities, such as when constructing parsers and ASTs
740
+
741
+ @example
742
+ ```
743
+ import type {IsBooleanLiteral} from 'type-fest';
744
+
745
+ const id = 123;
746
+
747
+ type GetId<AsString extends boolean> =
748
+ IsBooleanLiteral<AsString> extends true
749
+ ? AsString extends true
750
+ ? `${typeof id}`
751
+ : typeof id
752
+ : number | string;
753
+
754
+ function getId<AsString extends boolean = false>(options?: {asString: AsString}) {
755
+ return (options?.asString ? `${id}` : id) as GetId<AsString>;
756
+ }
757
+
758
+ const numberId = getId();
759
+ //=> 123
760
+
761
+ const stringId = getId({asString: true});
762
+ //=> '123'
763
+
764
+ declare const runtimeBoolean: boolean;
765
+ const eitherId = getId({asString: runtimeBoolean});
766
+ //=> string | number
767
+ ```
768
+
769
+ @category Type Guard
770
+ @category Utilities
771
+ */
772
+ type IsBooleanLiteral<T> = LiteralCheck<T, boolean>;
773
+ /**
774
+ Returns a boolean for whether the given type is a `symbol` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
775
+
776
+ Useful for:
777
+ - providing strongly-typed functions when given literal arguments
778
+ - type utilities, such as when constructing parsers and ASTs
779
+
780
+ @example
781
+ ```
782
+ import type {IsSymbolLiteral} from 'type-fest';
783
+
784
+ type Get<Object_ extends Record<symbol, number>, Key extends keyof Object_> =
785
+ IsSymbolLiteral<Key> extends true
786
+ ? Object_[Key]
787
+ : number;
788
+
789
+ function get<Object_ extends Record<symbol, number>, Key extends keyof Object_>(o: Object_, key: Key) {
790
+ return o[key] as Get<Object_, Key>;
791
+ }
792
+
793
+ const symbolLiteral = Symbol('literal');
794
+ let symbolValue = Symbol('value1');
795
+ symbolValue = Symbol('value2');
796
+
797
+ get({[symbolLiteral]: 1} as const, symbolLiteral);
798
+ //=> 1
799
+
800
+ get({[symbolValue]: 1} as const, symbolValue);
801
+ //=> number
802
+ ```
803
+
804
+ @category Type Guard
805
+ @category Utilities
806
+ */
807
+ type IsSymbolLiteral<T> = LiteralCheck<T, symbol>;
808
+ /** Helper type for `IsLiteral`. */
809
+ type IsLiteralUnion<T> = IsStringLiteral<T> | IsNumericLiteral<T> | IsBooleanLiteral<T> | IsSymbolLiteral<T>;
810
+ /**
811
+ Returns a boolean for whether the given type is a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
812
+
813
+ Useful for:
814
+ - providing strongly-typed functions when given literal arguments
815
+ - type utilities, such as when constructing parsers and ASTs
816
+
817
+ @example
818
+ ```
819
+ import type {IsLiteral} from 'type-fest';
820
+
821
+ type A = IsLiteral<1>;
822
+ //=> true
823
+
824
+ type B = IsLiteral<number>;
825
+ //=> false
826
+
827
+ type C = IsLiteral<1n>;
828
+ //=> true
829
+
830
+ type D = IsLiteral<bigint>;
831
+ //=> false
832
+
833
+ type E = IsLiteral<'type-fest'>;
834
+ //=> true
835
+
836
+ type F = IsLiteral<string>;
837
+ //=> false
838
+
839
+ type G = IsLiteral<`on${string}`>;
840
+ //=> false
841
+
842
+ declare const symbolLiteral: unique symbol;
843
+ type H = IsLiteral<typeof symbolLiteral>;
844
+ //=> true
845
+
846
+ type I = IsLiteral<symbol>;
847
+ //=> false
848
+
849
+ type J = IsLiteral<true>;
850
+ //=> true
851
+
852
+ type K = IsLiteral<boolean>;
853
+ //=> false
854
+ ```
855
+
856
+ @category Type Guard
857
+ @category Utilities
858
+ */
859
+ type IsLiteral<T> = IsPrimitive<T> extends true ? IsNotFalse<IsLiteralUnion<T>> : false;
860
+ //#endregion
861
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/is-null.d.ts
862
+ /**
863
+ Returns a boolean for whether the given type is `null`.
864
+
865
+ @example
866
+ ```
867
+ import type {IsNull} from 'type-fest';
868
+
869
+ type NonNullFallback<T, Fallback> = IsNull<T> extends true ? Fallback : T;
870
+
871
+ type Example1 = NonNullFallback<null, string>;
872
+ //=> string
873
+
874
+ type Example2 = NonNullFallback<number, string>;
875
+ //=> number
876
+ ```
877
+
878
+ @category Type Guard
879
+ @category Utilities
880
+ */
881
+ type IsNull<T> = [T] extends [null] ? true : false;
882
+ //#endregion
883
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/is-unknown.d.ts
884
+ /**
885
+ Returns a boolean for whether the given type is `unknown`.
886
+
887
+ @link https://github.com/dsherret/conditional-type-checks/pull/16
888
+
889
+ Useful in type utilities, such as when dealing with unknown data from API calls.
890
+
891
+ @example
892
+ ```
893
+ import type {IsUnknown} from 'type-fest';
894
+
895
+ type A = IsUnknown<unknown>;
896
+ //=> true
897
+
898
+ type B = IsUnknown<any>;
899
+ //=> false
900
+
901
+ type C = IsUnknown<never>;
902
+ //=> false
903
+
904
+ type D = IsUnknown<unknown[]>;
905
+ //=> false
906
+
907
+ type E = IsUnknown<object>;
908
+ //=> false
909
+
910
+ type F = IsUnknown<string>;
911
+ //=> false
912
+ ```
913
+
914
+ @category Utilities
915
+ */
916
+ type IsUnknown<T> = (unknown extends T // `T` can be `unknown` or `any`
917
+ ? IsNull<T> extends false // `any` can be `null`, but `unknown` can't be
918
+ ? true : false : false);
919
+ //#endregion
920
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/internal/keys.d.ts
921
+ /**
922
+ Utility type to retrieve only literal keys from type.
923
+ */
924
+ type LiteralKeyOf<T> = keyof { [K in keyof T as IsLiteral<K> extends true ? K : never]-?: never };
925
+ //#endregion
926
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/simplify.d.ts
2
927
  /**
3
928
  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.
4
929
 
@@ -33,31 +958,671 @@ interface SomeInterface {
33
958
  bar?: string;
34
959
  baz: number | undefined;
35
960
  }
36
-
37
- type SomeType = {
38
- foo: number;
39
- bar?: string;
40
- baz: number | undefined;
41
- };
42
-
43
- const literal = {foo: 123, bar: 'hello', baz: 456};
44
- const someType: SomeType = literal;
45
- const someInterface: SomeInterface = literal;
46
-
47
- declare function fn(object: Record<string, unknown>): void;
48
-
49
- fn(literal); // Good: literal object type is sealed
50
- fn(someType); // Good: type is sealed
51
- // @ts-expect-error
52
- fn(someInterface); // Error: Index signature for type 'string' is missing in type 'someInterface'. Because `interface` can be re-opened
53
- fn(someInterface as Simplify<SomeInterface>); // Good: transform an `interface` into a `type`
54
- ```
55
-
56
- @link https://github.com/microsoft/TypeScript/issues/15300
57
- @see {@link SimplifyDeep}
58
- @category Object
59
- */
60
- type Simplify<T> = { [KeyType in keyof T]: T[KeyType] } & {};
961
+
962
+ type SomeType = {
963
+ foo: number;
964
+ bar?: string;
965
+ baz: number | undefined;
966
+ };
967
+
968
+ const literal = {foo: 123, bar: 'hello', baz: 456};
969
+ const someType: SomeType = literal;
970
+ const someInterface: SomeInterface = literal;
971
+
972
+ declare function fn(object: Record<string, unknown>): void;
973
+
974
+ fn(literal); // Good: literal object type is sealed
975
+ fn(someType); // Good: type is sealed
976
+ // @ts-expect-error
977
+ fn(someInterface); // Error: Index signature for type 'string' is missing in type 'someInterface'. Because `interface` can be re-opened
978
+ fn(someInterface as Simplify<SomeInterface>); // Good: transform an `interface` into a `type`
979
+ ```
980
+
981
+ @link https://github.com/microsoft/TypeScript/issues/15300
982
+ @see {@link SimplifyDeep}
983
+ @category Object
984
+ */
985
+ type Simplify<T> = { [KeyType in keyof T]: T[KeyType] } & {};
986
+ //#endregion
987
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/is-equal.d.ts
988
+ /**
989
+ Returns a boolean for whether the two given types are equal.
990
+
991
+ @link https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650
992
+ @link https://stackoverflow.com/questions/68961864/how-does-the-equals-work-in-typescript/68963796#68963796
993
+
994
+ Use-cases:
995
+ - If you want to make a conditional branch based on the result of a comparison of two types.
996
+
997
+ @example
998
+ ```
999
+ import type {IsEqual} from 'type-fest';
1000
+
1001
+ // This type returns a boolean for whether the given array includes the given item.
1002
+ // `IsEqual` is used to compare the given array at position 0 and the given item and then return true if they are equal.
1003
+ type Includes<Value extends readonly any[], Item> =
1004
+ Value extends readonly [Value[0], ...infer rest]
1005
+ ? IsEqual<Value[0], Item> extends true
1006
+ ? true
1007
+ : Includes<rest, Item>
1008
+ : false;
1009
+ ```
1010
+
1011
+ @category Type Guard
1012
+ @category Utilities
1013
+ */
1014
+ type IsEqual<A, B> = [A] extends [B] ? [B] extends [A] ? _IsEqual<A, B> : false : false;
1015
+ // This version fails the `equalWrappedTupleIntersectionToBeNeverAndNeverExpanded` test in `test-d/is-equal.ts`.
1016
+ type _IsEqual<A, B> = (<G>() => G extends A & G | G ? 1 : 2) extends (<G>() => G extends B & G | G ? 1 : 2) ? true : false;
1017
+ //#endregion
1018
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/omit-index-signature.d.ts
1019
+ /**
1020
+ Omit any index signatures from the given object type, leaving only explicitly defined properties.
1021
+
1022
+ This is the counterpart of `PickIndexSignature`.
1023
+
1024
+ Use-cases:
1025
+ - Remove overly permissive signatures from third-party types.
1026
+
1027
+ This type was taken from this [StackOverflow answer](https://stackoverflow.com/a/68261113/420747).
1028
+
1029
+ It relies on the fact that an empty object (`{}`) is assignable to an object with just an index signature, like `Record<string, unknown>`, but not to an object with explicitly defined keys, like `Record<'foo' | 'bar', unknown>`.
1030
+
1031
+ (The actual value type, `unknown`, is irrelevant and could be any type. Only the key type matters.)
1032
+
1033
+ ```
1034
+ const indexed: Record<string, unknown> = {}; // Allowed
1035
+
1036
+ // @ts-expect-error
1037
+ const keyed: Record<'foo', unknown> = {}; // Error
1038
+ // TS2739: Type '{}' is missing the following properties from type 'Record<"foo" | "bar", unknown>': foo, bar
1039
+ ```
1040
+
1041
+ 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:
1042
+
1043
+ ```
1044
+ type Indexed = {} extends Record<string, unknown>
1045
+ ? '✅ `{}` is assignable to `Record<string, unknown>`'
1046
+ : '❌ `{}` is NOT assignable to `Record<string, unknown>`';
1047
+
1048
+ type IndexedResult = Indexed;
1049
+ //=> '✅ `{}` is assignable to `Record<string, unknown>`'
1050
+
1051
+ type Keyed = {} extends Record<'foo' | 'bar', unknown>
1052
+ ? '✅ `{}` is assignable to `Record<\'foo\' | \'bar\', unknown>`'
1053
+ : '❌ `{}` is NOT assignable to `Record<\'foo\' | \'bar\', unknown>`';
1054
+
1055
+ type KeyedResult = Keyed;
1056
+ //=> '❌ `{}` is NOT assignable to `Record<\'foo\' | \'bar\', unknown>`'
1057
+ ```
1058
+
1059
+ 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`...
1060
+
1061
+ ```
1062
+ type OmitIndexSignature<ObjectType> = {
1063
+ [KeyType in keyof ObjectType // Map each key of `ObjectType`...
1064
+ ]: ObjectType[KeyType]; // ...to its original value, i.e. `OmitIndexSignature<Foo> == Foo`.
1065
+ };
1066
+ ```
1067
+
1068
+ ...whether an empty object (`{}`) would be assignable to an object with that `KeyType` (`Record<KeyType, unknown>`)...
1069
+
1070
+ ```
1071
+ type OmitIndexSignature<ObjectType> = {
1072
+ [KeyType in keyof ObjectType
1073
+ // Is `{}` assignable to `Record<KeyType, unknown>`?
1074
+ as {} extends Record<KeyType, unknown>
1075
+ ? never // ✅ `{}` is assignable to `Record<KeyType, unknown>`
1076
+ : KeyType // ❌ `{}` is NOT assignable to `Record<KeyType, unknown>`
1077
+ ]: ObjectType[KeyType];
1078
+ };
1079
+ ```
1080
+
1081
+ If `{}` is assignable, it means that `KeyType` is an index signature and we want to remove it. If it is not assignable, `KeyType` is a "real" key and we want to keep it.
1082
+
1083
+ @example
1084
+ ```
1085
+ import type {OmitIndexSignature} from 'type-fest';
1086
+
1087
+ type Example = {
1088
+ // These index signatures will be removed.
1089
+ [x: string]: any;
1090
+ [x: number]: any;
1091
+ [x: symbol]: any;
1092
+ [x: `head-${string}`]: string;
1093
+ [x: `${string}-tail`]: string;
1094
+ [x: `head-${string}-tail`]: string;
1095
+ [x: `${bigint}`]: string;
1096
+ [x: `embedded-${number}`]: string;
1097
+
1098
+ // These explicitly defined keys will remain.
1099
+ foo: 'bar';
1100
+ qux?: 'baz';
1101
+ };
1102
+
1103
+ type ExampleWithoutIndexSignatures = OmitIndexSignature<Example>;
1104
+ //=> {foo: 'bar'; qux?: 'baz'}
1105
+ ```
1106
+
1107
+ @see {@link PickIndexSignature}
1108
+ @category Object
1109
+ */
1110
+ type OmitIndexSignature<ObjectType> = { [KeyType in keyof ObjectType as {} extends Record<KeyType, unknown> ? never : KeyType]: ObjectType[KeyType] };
1111
+ //#endregion
1112
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/pick-index-signature.d.ts
1113
+ /**
1114
+ Pick only index signatures from the given object type, leaving out all explicitly defined properties.
1115
+
1116
+ This is the counterpart of `OmitIndexSignature`.
1117
+
1118
+ @example
1119
+ ```
1120
+ import type {PickIndexSignature} from 'type-fest';
1121
+
1122
+ declare const symbolKey: unique symbol;
1123
+
1124
+ type Example = {
1125
+ // These index signatures will remain.
1126
+ [x: string]: unknown;
1127
+ [x: number]: unknown;
1128
+ [x: symbol]: unknown;
1129
+ [x: `head-${string}`]: string;
1130
+ [x: `${string}-tail`]: string;
1131
+ [x: `head-${string}-tail`]: string;
1132
+ [x: `${bigint}`]: string;
1133
+ [x: `embedded-${number}`]: string;
1134
+
1135
+ // These explicitly defined keys will be removed.
1136
+ ['kebab-case-key']: string;
1137
+ [symbolKey]: string;
1138
+ foo: 'bar';
1139
+ qux?: 'baz';
1140
+ };
1141
+
1142
+ type ExampleIndexSignature = PickIndexSignature<Example>;
1143
+ // {
1144
+ // [x: string]: unknown;
1145
+ // [x: number]: unknown;
1146
+ // [x: symbol]: unknown;
1147
+ // [x: `head-${string}`]: string;
1148
+ // [x: `${string}-tail`]: string;
1149
+ // [x: `head-${string}-tail`]: string;
1150
+ // [x: `${bigint}`]: string;
1151
+ // [x: `embedded-${number}`]: string;
1152
+ // }
1153
+ ```
1154
+
1155
+ @see {@link OmitIndexSignature}
1156
+ @category Object
1157
+ */
1158
+ type PickIndexSignature<ObjectType> = { [KeyType in keyof ObjectType as {} extends Record<KeyType, unknown> ? KeyType : never]: ObjectType[KeyType] };
1159
+ //#endregion
1160
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/merge.d.ts
1161
+ // Merges two objects without worrying about index signatures.
1162
+ type SimpleMerge<Destination, Source> = Simplify<{ [Key in keyof Destination as Key extends keyof Source ? never : Key]: Destination[Key] } & Source>;
1163
+ /**
1164
+ Merge two types into a new type. Keys of the second type overrides keys of the first type.
1165
+
1166
+ 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`.
1167
+
1168
+ @example
1169
+ ```
1170
+ import type {Merge} from 'type-fest';
1171
+
1172
+ type Foo = {
1173
+ a: string;
1174
+ b: number;
1175
+ };
1176
+
1177
+ type Bar = {
1178
+ a: number; // Conflicts with Foo['a']
1179
+ c: boolean;
1180
+ };
1181
+
1182
+ // With `&`, `a` becomes `string & number` which is `never`. Not what you want.
1183
+ type WithIntersection = (Foo & Bar)['a'];
1184
+ //=> never
1185
+
1186
+ // With `Merge`, `a` is cleanly overridden to `number`.
1187
+ type WithMerge = Merge<Foo, Bar>['a'];
1188
+ //=> number
1189
+ ```
1190
+
1191
+ @example
1192
+ ```
1193
+ import type {Merge} from 'type-fest';
1194
+
1195
+ type Foo = {
1196
+ [x: string]: unknown;
1197
+ [x: number]: unknown;
1198
+ foo: string;
1199
+ bar: symbol;
1200
+ };
1201
+
1202
+ type Bar = {
1203
+ [x: number]: number;
1204
+ [x: symbol]: unknown;
1205
+ bar: Date;
1206
+ baz: boolean;
1207
+ };
1208
+
1209
+ export type FooBar = Merge<Foo, Bar>;
1210
+ //=> {
1211
+ // [x: string]: unknown;
1212
+ // [x: number]: number;
1213
+ // [x: symbol]: unknown;
1214
+ // foo: string;
1215
+ // bar: Date;
1216
+ // baz: boolean;
1217
+ // }
1218
+ ```
1219
+
1220
+ 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.
1221
+
1222
+ @see {@link ObjectMerge}
1223
+ @category Object
1224
+ */
1225
+ type Merge<Destination, Source> = Destination extends unknown // For distributing `Destination`
1226
+ ? Source extends unknown // For distributing `Source`
1227
+ ? If<IsEqual<Destination, Source>, Destination, _Merge<Destination, Source>> : never // Should never happen
1228
+ : never;
1229
+ // Should never happen
1230
+ type _Merge<Destination, Source> = Simplify<SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>> & SimpleMerge<OmitIndexSignature<Destination>, OmitIndexSignature<Source>>>;
1231
+ //#endregion
1232
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/internal/object.d.ts
1233
+ /**
1234
+ Merges user specified options with default options.
1235
+
1236
+ @example
1237
+ ```
1238
+ type PathsOptions = {maxRecursionDepth?: number; leavesOnly?: boolean};
1239
+ type DefaultPathsOptions = {maxRecursionDepth: 10; leavesOnly: false};
1240
+ type SpecifiedOptions = {leavesOnly: true};
1241
+
1242
+ type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOptions>;
1243
+ //=> {maxRecursionDepth: 10; leavesOnly: true}
1244
+ ```
1245
+
1246
+ @example
1247
+ ```
1248
+ // Complains if default values are not provided for optional options
1249
+
1250
+ type PathsOptions = {maxRecursionDepth?: number; leavesOnly?: boolean};
1251
+ type DefaultPathsOptions = {maxRecursionDepth: 10};
1252
+ type SpecifiedOptions = {};
1253
+
1254
+ type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOptions>;
1255
+ // ~~~~~~~~~~~~~~~~~~~
1256
+ // Property 'leavesOnly' is missing in type 'DefaultPathsOptions' but required in type '{ maxRecursionDepth: number; leavesOnly: boolean; }'.
1257
+ ```
1258
+
1259
+ @example
1260
+ ```
1261
+ // Complains if an option's default type does not conform to the expected type
1262
+
1263
+ type PathsOptions = {maxRecursionDepth?: number; leavesOnly?: boolean};
1264
+ type DefaultPathsOptions = {maxRecursionDepth: 10; leavesOnly: 'no'};
1265
+ type SpecifiedOptions = {};
1266
+
1267
+ type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOptions>;
1268
+ // ~~~~~~~~~~~~~~~~~~~
1269
+ // Types of property 'leavesOnly' are incompatible. Type 'string' is not assignable to type 'boolean'.
1270
+ ```
1271
+
1272
+ @example
1273
+ ```
1274
+ // Complains if an option's specified type does not conform to the expected type
1275
+
1276
+ type PathsOptions = {maxRecursionDepth?: number; leavesOnly?: boolean};
1277
+ type DefaultPathsOptions = {maxRecursionDepth: 10; leavesOnly: false};
1278
+ type SpecifiedOptions = {leavesOnly: 'yes'};
1279
+
1280
+ type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOptions>;
1281
+ // ~~~~~~~~~~~~~~~~
1282
+ // Types of property 'leavesOnly' are incompatible. Type 'string' is not assignable to type 'boolean'.
1283
+ ```
1284
+ */
1285
+ type ApplyDefaultOptions<Options extends object, Defaults extends Simplify<Omit<Required<Options>, RequiredKeysOf<Options>> & Partial<Record<RequiredKeysOf<Options>, never>>>, SpecifiedOptions extends Options> = _ApplyDefaultOptions<Options, Defaults, SpecifiedOptions> extends infer Result extends Required<Options> // `extends Required<Options>` ensures that `ApplyDefaultOptions<SomeOption, ...>` is always assignable to `Required<SomeOption>`
1286
+ ? Result : never;
1287
+ type _ApplyDefaultOptions<Options, Defaults, SpecifiedOptions> = If<IsAny<SpecifiedOptions>, Defaults, If<IsNever<SpecifiedOptions>, Defaults, Merge<Defaults, { [Key in keyof SpecifiedOptions as undefined extends Required<Options>[Key & keyof Options] ? Key : undefined extends SpecifiedOptions[Key] ? never : Key]: SpecifiedOptions[Key] }>>>;
1288
+ /**
1289
+ Collapses literal types in a union into their corresponding primitive types, when possible. For example, `CollapseLiterals<'foo' | 'bar' | (string & {})>` returns `string`.
1290
+
1291
+ Note: This doesn't collapse literals within tagged types. For example, `CollapseLiterals<Tagged<'foo' | (string & {}), 'Tag'>>` returns `("foo" & Tag<"Tag", never>) | (string & Tag<"Tag", never>)` and not `string & Tag<"Tag", never>`.
1292
+
1293
+ Use-case: For collapsing unions created using {@link LiteralUnion}.
1294
+
1295
+ @example
1296
+ ```
1297
+ import type {LiteralUnion} from 'type-fest';
1298
+
1299
+ type A = CollapseLiterals<'foo' | 'bar' | (string & {})>;
1300
+ //=> string
1301
+
1302
+ type B = CollapseLiterals<LiteralUnion<1 | 2 | 3, number>>;
1303
+ //=> number
1304
+
1305
+ type C = CollapseLiterals<LiteralUnion<'onClick' | 'onChange', `on${string}`>>;
1306
+ //=> `on${string}`
1307
+
1308
+ type D = CollapseLiterals<'click' | 'change' | (`on${string}` & {})>;
1309
+ //=> 'click' | 'change' | `on${string}`
1310
+
1311
+ type E = CollapseLiterals<LiteralUnion<'foo' | 'bar', string> | null | undefined>;
1312
+ //=> string | null | undefined
1313
+ ```
1314
+ */
1315
+ type CollapseLiterals<T> = {} extends T ? T : T extends infer U & {} ? U : T;
1316
+ //#endregion
1317
+ //#region ../../node_modules/.pnpm/type-fest@5.7.0/node_modules/type-fest/source/partial-on-undefined-deep.d.ts
1318
+ /**
1319
+ @see {@link PartialOnUndefinedDeep}
1320
+ */
1321
+ type PartialOnUndefinedDeepOptions = {
1322
+ /**
1323
+ Whether to affect the individual elements of arrays and tuples.
1324
+ @default false
1325
+ */
1326
+ readonly recurseIntoArrays?: boolean;
1327
+ };
1328
+ type DefaultPartialOnUndefinedDeepOptions = {
1329
+ recurseIntoArrays: false;
1330
+ };
1331
+ /**
1332
+ Create a deep version of another type where all keys accepting `undefined` type are set to optional.
1333
+
1334
+ This utility type is recursive, transforming at any level deep. By default, it does not affect arrays and tuples items unless you explicitly pass `{recurseIntoArrays: true}` as the second type argument.
1335
+
1336
+ Use-cases:
1337
+ - Make all properties of a type that can be undefined optional to not have to specify keys with undefined value.
1338
+
1339
+ @example
1340
+ ```
1341
+ import type {PartialOnUndefinedDeep} from 'type-fest';
1342
+
1343
+ type Settings = {
1344
+ optionA: string;
1345
+ optionB: number | undefined;
1346
+ subOption: {
1347
+ subOptionA: boolean;
1348
+ subOptionB: boolean | undefined;
1349
+ };
1350
+ };
1351
+
1352
+ const testSettings: PartialOnUndefinedDeep<Settings> = {
1353
+ optionA: 'foo',
1354
+ // 👉 optionB is now optional and can be omitted
1355
+ subOption: {
1356
+ subOptionA: true,
1357
+ // 👉 subOptionB is now optional as well and can be omitted
1358
+ },
1359
+ };
1360
+ ```
1361
+
1362
+ @category Object
1363
+ */
1364
+ type PartialOnUndefinedDeep<T, Options extends PartialOnUndefinedDeepOptions = {}> = _PartialOnUndefinedDeep<T, ApplyDefaultOptions<PartialOnUndefinedDeepOptions, DefaultPartialOnUndefinedDeepOptions, Options>>;
1365
+ type _PartialOnUndefinedDeep<T, Options extends Required<PartialOnUndefinedDeepOptions>> = T extends Record<any, any> | undefined ? { [KeyType in keyof T as undefined extends T[KeyType] ? If<IsUnknown<T[KeyType]>, never, KeyType> : never]?: PartialOnUndefinedDeepValue<T[KeyType], Options> } extends infer U // Make a partial type with all value types accepting undefined (and set them optional)
1366
+ ? Merge<{ [KeyType in keyof T as KeyType extends LiteralKeyOf<U> ? never : KeyType]: PartialOnUndefinedDeepValue<T[KeyType], Options> }, U> // Join all remaining keys not treated in U
1367
+ : never // Should not happen
1368
+ : T;
1369
+ /**
1370
+ Utility type to get the value type by key and recursively call `PartialOnUndefinedDeep` to transform sub-objects.
1371
+ */
1372
+ type PartialOnUndefinedDeepValue<T, Options extends Required<PartialOnUndefinedDeepOptions>> = T extends BuiltIns | ((...arguments_: any[]) => unknown) ? T : T extends ReadonlyArray<infer U> // Test if type is array or tuple
1373
+ ? Options['recurseIntoArrays'] extends true // Check if option is activated
1374
+ ? U[] extends T // Check if array not tuple
1375
+ ? readonly U[] extends T ? ReadonlyArray<_PartialOnUndefinedDeep<U, Options>> // Readonly array treatment
1376
+ : Array<_PartialOnUndefinedDeep<U, Options>> // Mutable array treatment
1377
+ : _PartialOnUndefinedDeep<{ [Key in keyof T]: _PartialOnUndefinedDeep<T[Key], Options> }, Options> // Tuple treatment
1378
+ : T : T extends Record<any, any> | undefined ? _PartialOnUndefinedDeep<T, Options> : unknown;
1379
+ //#endregion
1380
+ //#region src/types.d.ts
1381
+ interface BasicModel<T> {
1382
+ title?: string;
1383
+ description?: string;
1384
+ examples?: T[];
1385
+ schema?: StandardTypedV1<T, T>;
1386
+ }
1387
+ interface Int32Model extends BasicModel<number> {
1388
+ kind: "int32";
1389
+ }
1390
+ interface Float32Model extends BasicModel<number> {
1391
+ kind: "float32";
1392
+ }
1393
+ interface Float64Model extends BasicModel<number> {
1394
+ kind: "float64";
1395
+ }
1396
+ interface BooleanModel extends BasicModel<boolean> {
1397
+ kind: "boolean";
1398
+ }
1399
+ interface StringModel extends BasicModel<string> {
1400
+ kind: "string";
1401
+ }
1402
+ interface ArrayModel<T extends Models> extends BasicModel<InferModel<T>[]> {
1403
+ kind: "array";
1404
+ base: T;
1405
+ }
1406
+ interface SetModel<T extends Models> extends BasicModel<Set<InferModel<T>>> {
1407
+ kind: "set";
1408
+ base: T;
1409
+ }
1410
+ interface MapModel<T extends Models> extends BasicModel<Map<string, InferModel<T>>> {
1411
+ kind: "map";
1412
+ base: T;
1413
+ }
1414
+ interface RecordModel<T extends Record<string, Models>, R extends keyof T & string> extends BasicModel<PropertiesType<T, R>> {
1415
+ kind: "record";
1416
+ properties: T;
1417
+ required: R[];
1418
+ id: string;
1419
+ }
1420
+ type PropertiesType<T extends Record<string, Models>, R extends keyof T> = PartialOnUndefinedDeep<{ [key in keyof T]: key extends R ? InferModel<T[key]> : InferModel<T[key]> | undefined }>;
1421
+ interface UnionModel<T extends Record<string, Models>> extends BasicModel<InferUnion<T>> {
1422
+ kind: "union";
1423
+ variants: T;
1424
+ id: string;
1425
+ }
1426
+ type InferUnion<T extends Record<string, Models>> = { [key in keyof T]: { [k in key]: StandardTypedV1.InferOutput<NonNullable<T[key]["schema"]>> } }[keyof T];
1427
+ interface TaggedUnionModel<K extends string, D extends string, V extends Record<string, Models>> extends BasicModel<InferTaggedUnion<K, D, V>> {
1428
+ kind: "taggedUnion";
1429
+ variants: V;
1430
+ variantKey: K;
1431
+ payloadKey: D;
1432
+ id: string;
1433
+ }
1434
+ interface TaggedUnionModelOptions<K extends string, D extends string, V extends Record<string, Models>> extends Omit<TaggedUnionModel<K, D, V>, "kind"> {}
1435
+ type InferTaggedUnion<K extends string, D extends string, V extends Record<string, Models>> = { [key in keyof V]: { [k in K | D]: k extends K ? key : k extends D ? StandardTypedV1.InferOutput<NonNullable<V[key]["schema"]>> : never } }[keyof V];
1436
+ interface LiteralModel<T extends string | number | boolean> extends BasicModel<T> {
1437
+ kind: "literal";
1438
+ value: T;
1439
+ }
1440
+ interface NullModel extends BasicModel<undefined | null> {
1441
+ kind: "null";
1442
+ }
1443
+ type OptionsOf<T extends Models> = Omit<T, "kind">;
1444
+ interface EnumsModel<T extends {
1445
+ [key: string]: string;
1446
+ }> extends BasicModel<T[keyof T]> {
1447
+ kind: "enums";
1448
+ id: string;
1449
+ variants: T;
1450
+ }
1451
+ interface DatetimeModel extends BasicModel<string> {
1452
+ kind: "datetime";
1453
+ }
1454
+ interface DateModel extends BasicModel<string> {
1455
+ kind: "date";
1456
+ }
1457
+ interface DurationModel extends BasicModel<string> {
1458
+ kind: "duration";
1459
+ }
1460
+ type Models = Int32Model | Float32Model | Float64Model | BooleanModel | StringModel | ArrayModel<any> | SetModel<any> | MapModel<any> | RecordModel<Record<string, Models>, string> | UnionModel<Record<string, Models>> | TaggedUnionModel<string, string, Record<string, Models>> | LiteralModel<string | number | boolean> | NullModel | EnumsModel<{
1461
+ [key: string]: string;
1462
+ }> | DatetimeModel | DateModel | DurationModel;
1463
+ type InferModel<T> = T extends {
1464
+ schema?: StandardTypedV1<unknown, unknown>;
1465
+ } ? StandardTypedV1.InferOutput<NonNullable<T["schema"]>> : never;
1466
+ declare function int32(options?: OptionsOf<Int32Model>): Int32Model;
1467
+ declare function float32(options?: OptionsOf<Float32Model>): Float32Model;
1468
+ declare function float64(options?: OptionsOf<Float64Model>): Float64Model;
1469
+ declare function boolean(options?: OptionsOf<BooleanModel>): BooleanModel;
1470
+ declare function string(options?: OptionsOf<StringModel>): StringModel;
1471
+ declare function array<T extends Models>(options: OptionsOf<ArrayModel<T>>): ArrayModel<T>;
1472
+ declare function set<T extends Models>(options: OptionsOf<SetModel<T>>): SetModel<T>;
1473
+ declare function map<T extends Models>(options: OptionsOf<MapModel<T>>): MapModel<T>;
1474
+ declare function record<T extends Record<string, Models>, R extends keyof T & string>(options: OptionsOf<RecordModel<T, R>>): RecordModel<T, R>;
1475
+ declare function union<T extends Record<string, Models>>(options: OptionsOf<UnionModel<T>>): UnionModel<T>;
1476
+ declare function taggedUnion<K extends string, D extends string, V extends Record<string, Models>>(options: TaggedUnionModelOptions<K, D, V>): TaggedUnionModel<K, D, V>;
1477
+ declare function literal<const T extends string | boolean | number>(value: T): LiteralModel<T>;
1478
+ declare function nullLike(): NullModel;
1479
+ interface EnumsModelOptions<T extends {
1480
+ [key: string]: string;
1481
+ }> extends Omit<EnumsModel<T>, "kind"> {}
1482
+ declare function enums<const T extends {
1483
+ [key: string]: string;
1484
+ }>(options: EnumsModelOptions<T>): EnumsModel<T>;
1485
+ interface DatetimeModelOptions extends Omit<DatetimeModel, "kind"> {}
1486
+ declare function datetime(options?: DatetimeModelOptions): DatetimeModel;
1487
+ interface DateModelOptions extends Omit<DateModel, "kind"> {}
1488
+ declare function date(options?: DateModelOptions): DateModel;
1489
+ interface DurationModelOptions extends Omit<DurationModel, "kind"> {}
1490
+ declare function duration(options?: DurationModelOptions): DurationModel;
1491
+ //#endregion
1492
+ //#region src/utils/index.d.ts
1493
+ type ExtractPathParams<Path extends string> = string extends Path ? string : Path extends `${infer _Start}/{${infer Param}}/${infer Rest}` ? Param | ExtractPathParams<`/${Rest}`> : Path extends `${infer _Start}/{${infer Param}}` ? Param : never;
1494
+ //#endregion
1495
+ //#region src/api.d.ts
1496
+ type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD" | "TRACE";
1497
+ type SimpleType = Int32Model | Float32Model | Float64Model | StringModel | BooleanModel | DatetimeModel | DateModel | DurationModel;
1498
+ interface RouterModel {
1499
+ basePath?: string;
1500
+ name: string;
1501
+ routes: Record<string, RouteModel<string, Record<string, SimpleType>, Models, RecordModel<Record<string, Models>, string>, RecordModel<Record<string, Models>, string>, Record<number, ResponseModel<Models, RecordModel<Record<string, Models>, string>>>>>;
1502
+ }
1503
+ interface RouteModel<Path extends string, Variables extends Record<string, SimpleType>, Body extends Models, Queries extends RecordModel<Record<string, Models>, string>, Headers extends RecordModel<Record<string, Models>, string>, Responses extends Record<number, ResponseModel<Models, RecordModel<Record<string, Models>, string>>>> {
1504
+ kind: "route";
1505
+ method: HttpMethod;
1506
+ contentType?: string;
1507
+ summary?: string;
1508
+ description?: string;
1509
+ path: Path;
1510
+ variables?: Variables;
1511
+ body?: Body;
1512
+ headers?: Headers;
1513
+ queries?: Queries;
1514
+ responses: Responses;
1515
+ tags?: string[];
1516
+ }
1517
+ type ResponseModel<Body extends Models, Headers extends RecordModel<Record<string, Models>, string>> = JsonResponseModel<Body, Headers> | StreamResponseModel<Body, Headers> | SSEResponseModel<Body, Headers> | BinaryResponseModel<Headers>;
1518
+ interface JsonResponseModel<Body extends Models, Headers extends RecordModel<Record<string, Models>, string>> {
1519
+ kind: "json-response";
1520
+ contentType?: PlainTextLikeContentType | JsonLikeContentType;
1521
+ summary?: string;
1522
+ body?: Body;
1523
+ headers?: Headers;
1524
+ }
1525
+ interface StreamResponseModel<Body extends Models, Headers extends RecordModel<Record<string, Models>, string>> {
1526
+ kind: "stream-response";
1527
+ contentType?: JsonStreamLikeContentType;
1528
+ summary?: string;
1529
+ body?: Body;
1530
+ headers?: Headers;
1531
+ }
1532
+ interface SSEResponseModel<Body extends Models, Headers extends RecordModel<Record<string, Models>, string>> {
1533
+ kind: "sse-response";
1534
+ contentType?: PlainTextStreamLikeContentType;
1535
+ summary?: string;
1536
+ body?: Body;
1537
+ headers?: Headers;
1538
+ }
1539
+ interface BinaryResponseModel<Headers extends RecordModel<Record<string, Models>, string>> {
1540
+ kind: "binary";
1541
+ contentType?: BinaryLikeContentType;
1542
+ summary?: string;
1543
+ headers?: Headers;
1544
+ }
1545
+ interface RouteOptions<Path extends string, Variables extends Record<ExtractPathParams<Path>, SimpleType>, Body extends Models, Queries extends RecordModel<Record<string, Models>, string>, Headers extends RecordModel<Record<string, Models>, string>, Responses extends Record<string, ResponseModel<Models, RecordModel<Record<string, Models>, string>>>> extends Omit<RouteModel<string, Variables, Body, Queries, Headers, Responses>, "kind"> {}
1546
+ declare function route<Path extends string, Variables extends Record<ExtractPathParams<Path>, SimpleType>, Body extends Models, Queries extends RecordModel<Record<string, Models>, string>, Headers extends RecordModel<Record<string, Models>, string>, Responses extends Record<string, ResponseModel<Models, RecordModel<Record<string, Models>, string>>>>(options: RouteOptions<Path, Variables, Body, Queries, Headers, Responses>): RouteModel<Path, Variables, Body, Queries, Headers, Responses>;
1547
+ interface ResponseOptions<Body extends Models, Headers extends RecordModel<Record<string, Models>, string>> {
1548
+ contentType?: string;
1549
+ summary?: string;
1550
+ body?: Body;
1551
+ headers?: Headers;
1552
+ }
1553
+ declare function json<Body extends Models, Headers extends RecordModel<Record<string, Models>, string>>(options: ResponseOptions<Body, Headers>): JsonResponseModel<Body, Headers>;
1554
+ declare function jsonStream<Body extends Models, Headers extends RecordModel<Record<string, Models>, string>>(options: ResponseOptions<Body, Headers>): StreamResponseModel<Body, Headers>;
1555
+ declare function sseStream<Body extends Models, Headers extends RecordModel<Record<string, Models>, string>>(options: ResponseOptions<Body, Headers>): SSEResponseModel<Body, Headers>;
1556
+ interface BinaryResponseOptions<Headers extends RecordModel<Record<string, Models>, string>> {
1557
+ contentType?: BinaryLikeContentType;
1558
+ summary?: string;
1559
+ headers?: Headers;
1560
+ }
1561
+ declare function binary<Headers extends RecordModel<Record<string, Models>, string>>(options: BinaryResponseOptions<Headers>): BinaryResponseModel<Headers>;
1562
+ type PlainTextLikeContentType = (string & {}) | "text/plain" | "text/html" | "text/css" | "text/xml" | "text/markdown" | "text/csv";
1563
+ type JsonLikeContentType = (string & {}) | "application/json" | "application/json; charset=utf-8" | "application/ld+json" | "application/hal+json" | "application/vnd.api+json" | "application/problem+json" | "application/schema+json";
1564
+ type PlainTextStreamLikeContentType = (string & {}) | "text/event-stream";
1565
+ type JsonStreamLikeContentType = (string & {}) | "application/ndjson" | "application/x-ndjson" | "application/jsonl" | "application/json-seq" | "application/stream+json";
1566
+ type BinaryLikeContentType = (string & {}) | "application/octet-stream" | "application/pdf" | "application/zip" | "application/gzip" | "image/jpeg" | "image/png" | "image/gif" | "image/webp" | "image/svg+xml" | "audio/mpeg" | "audio/wav" | "video/mp4" | "video/webm";
1567
+ type FormLikeContentType = (string & {}) | "application/x-www-form-urlencoded" | "multipart/form-data";
1568
+ //#endregion
1569
+ //#region src/security.d.ts
1570
+ interface SecurityPolicyModel {
1571
+ name: string;
1572
+ /** key就是path的模式, 支持正则表达 */
1573
+ paths: Record<string, SecurityPolicyPathItem>;
1574
+ }
1575
+ interface SecurityPolicyPathItem {
1576
+ /** 如果没有设置, 则默认对所有http method生效 */
1577
+ methods?: HttpMethod[];
1578
+ /** 如果没有设置, 则忽略该规则 */
1579
+ pipeline?: SecurityApply[];
1580
+ }
1581
+ type SecurityComponent = ApikeySecurityComponent | OpenIdSecurityComponent;
1582
+ interface ApikeySecurityComponent {
1583
+ kind: "apikey";
1584
+ id: string;
1585
+ name: string;
1586
+ description?: string;
1587
+ }
1588
+ interface OpenIdSecurityComponent {
1589
+ kind: "openIdConnect";
1590
+ id: string;
1591
+ description?: string;
1592
+ scopes: string[];
1593
+ }
1594
+ interface SecurityApply {
1595
+ component: SecurityComponent;
1596
+ scopes: string[];
1597
+ }
1598
+ interface SecurityAppliable {
1599
+ apply: (...scopes: string[]) => SecurityApply;
1600
+ }
1601
+ interface ApikeySecurityComponentOptions {
1602
+ id: string;
1603
+ name: string;
1604
+ description?: string;
1605
+ }
1606
+ declare function apikey(options: ApikeySecurityComponentOptions): ApikeySecurityComponent & SecurityAppliable;
1607
+ interface OpenIdComponentOptions {
1608
+ id: string;
1609
+ description?: string;
1610
+ scopes: string[];
1611
+ }
1612
+ declare function openIdConnect(options: OpenIdComponentOptions): OpenIdSecurityComponent & SecurityAppliable;
1613
+ //#endregion
1614
+ //#region src/deployment.d.ts
1615
+ interface OpenIdDeployment {
1616
+ kind: "openIdConnectDeployment";
1617
+ component: OpenIdSecurityComponent;
1618
+ issuer: string;
1619
+ }
1620
+ interface OpenIdDeploymentOptions {
1621
+ component: OpenIdSecurityComponent;
1622
+ issuer: string;
1623
+ }
1624
+ declare function deployOpenIdConnect(options: OpenIdDeploymentOptions): OpenIdDeployment;
1625
+ type SecurityDeployment = OpenIdDeployment;
61
1626
  //#endregion
62
1627
  //#region src/schemas/json-schema-draft-2020-12.d.ts
63
1628
  interface JsonSchemaObject extends JsonSchemaCore, JsonSchemaApplicator, JsonSchemaUnevaluated, JsonSchemaValidation, JsonSchemaMetaData, JsonSchemaFormat, JsonSchemaContent {}
@@ -105,7 +1670,7 @@ interface JsonSchemaUnevaluated {
105
1670
  unevaluatedProperties?: JsonSchema;
106
1671
  }
107
1672
  interface JsonSchemaValidation {
108
- type?: SimpleType | SimpleType[];
1673
+ type?: SimpleType$1 | SimpleType$1[];
109
1674
  const?: any;
110
1675
  enum?: any[];
111
1676
  multipleOf?: number;
@@ -147,280 +1712,31 @@ interface JsonSchemaContent {
147
1712
  contentSchema?: JsonSchema;
148
1713
  }
149
1714
  declare const SimpleTypes: readonly ["array", "boolean", "integer", "null", "number", "object", "string"];
150
- type SimpleType = (typeof SimpleTypes)[number];
151
- //#endregion
152
- //#region src/schemas/schema-variants.d.ts
153
- interface StringSchema {
154
- maxLength?: number;
155
- minLength?: number;
156
- pattern?: string;
157
- format?: FormatVariants | (string & {});
158
- }
159
- interface NumberSchema {
160
- multipleOf?: number;
161
- maximum?: number;
162
- exclusiveMaximum?: number;
163
- minimum?: number;
164
- exclusiveMinimum?: number;
165
- }
166
- interface ArraySchema {
167
- maxItems?: number;
168
- minItems?: number;
169
- contains?: JsonSchemaObject;
170
- maxContains?: number;
171
- minContains?: number;
172
- }
173
- interface SetSchema {
174
- maxItems?: number;
175
- minItems?: number;
176
- contains?: JsonSchemaObject;
177
- maxContains?: number;
178
- minContains?: number;
179
- }
180
- interface MapSchema {
181
- maxProperties?: number;
182
- minProperties?: number;
183
- required?: string[];
184
- dependentRequired?: {
185
- [key: string]: string[];
186
- };
187
- }
1715
+ type SimpleType$1 = (typeof SimpleTypes)[number];
188
1716
  //#endregion
189
- //#region src/type-system/basic.d.ts
190
- interface BasicModel<T> {
191
- id?: string;
192
- title?: string;
193
- description?: string;
194
- examples?: T[];
195
- default?: T;
196
- deprecated?: boolean;
197
- }
198
- interface Int32Model extends BasicModel<number> {
199
- kind: "int32";
200
- schema?: NumberSchema;
201
- }
202
- interface Int32ModelOptions extends Omit<Int32Model, "kind"> {}
203
- declare function int32(options?: Int32ModelOptions): Int32Model;
204
- interface Int64Model extends BasicModel<string> {
205
- kind: "int64";
206
- schema?: StringSchema;
207
- }
208
- interface Int64ModelOptions extends Omit<Int64Model, "kind"> {}
209
- declare function int64(options?: Int64ModelOptions): Int64Model;
210
- interface Float32Model extends BasicModel<number> {
211
- kind: "float32";
212
- schema?: NumberSchema;
213
- }
214
- interface Float32ModelOptions extends Omit<Float32Model, "kind"> {}
215
- declare function float32(options?: Float32ModelOptions): Float32Model;
216
- interface Float64Model extends BasicModel<number> {
217
- kind: "float64";
218
- schema?: NumberSchema;
219
- }
220
- interface Float64ModelOptions extends Omit<Float64Model, "kind"> {}
221
- declare function float64(options?: Float64ModelOptions): Float64Model;
222
- interface BooleanModel extends BasicModel<boolean> {
223
- kind: "boolean";
224
- }
225
- interface BooleanModelOptions extends Omit<BooleanModel, "kind"> {}
226
- declare function boolean(options?: BooleanModelOptions): BooleanModel;
227
- interface StringModel extends BasicModel<string> {
228
- kind: "string";
229
- schema?: StringSchema;
230
- }
231
- interface StringModelOptions extends Omit<StringModel, "kind"> {}
232
- declare function string(options?: StringModelOptions): StringModel;
233
- interface LiteralModel<T extends string | number | boolean> extends BasicModel<T> {
234
- kind: "literal";
235
- value: T;
236
- }
237
- interface LiteralModelOptions<T extends string | number | boolean> extends Omit<LiteralModel<T>, "kind"> {}
238
- declare function literal<const T extends string | number | boolean>(options: LiteralModelOptions<T>): LiteralModel<T>;
239
- /**
240
- * 表示一个可选类型,代表"值可能存在也可能不存在"的语义。
241
- *
242
- * 设计理念:
243
- * - 统一"空白"语义:将 `null`、`undefined` 和缺失值等多种"空"的概念合并为单一语义,
244
- * 避免类型系统中存在多个含义模糊的"空"状态。
245
- * - 序列化到 JSON 时,`Optional` 可以表示为 `null` 或完全省略(取决于上下文)。
246
- * `InferModelJsonType<T> | null | undefined` 表示该值可以是基础类型、`null` 或 `undefined`。
247
- * - 如果需要区分"显式设置为空"和"从未设置"等细分语义,应当另行设计专用类型。
248
- *
249
- * @template T 基础模型类型
250
- */
251
- interface OptionalModel<T extends TypeModels> extends BasicModel<InferModelJsonType<T> | null | undefined> {
252
- kind: "optional";
253
- base: T;
254
- }
255
- /**
256
- * 将类型模型转换为可选类型。
257
- *
258
- * @template T 基础模型类型
259
- */
260
- type Optionalize<T extends TypeModels> = T extends TypeModels ? OptionalModel<T> : never;
261
- interface OptionalModelOptions<T extends TypeModels> extends Omit<OptionalModel<T>, "kind" | "base"> {}
262
- /**
263
- * 创建一个可选类型模型。
264
- *
265
- * @param base 基础模型类型
266
- * @param options 可选配置选项
267
- * @returns 可选类型模型
268
- */
269
- declare function optional<T extends TypeModels>(base: T, options?: OptionalModelOptions<T>): OptionalModel<T>;
270
- interface ArrayModel<T> extends BasicModel<InferModelJsonType<T>[]> {
271
- kind: "array";
272
- base: T;
273
- schema?: ArraySchema;
274
- }
275
- interface ArrayModelOptions<T extends TypeModels> extends Omit<ArrayModel<T>, "kind" | "base"> {}
276
- declare function array<T extends TypeModels>(base: T, options?: ArrayModelOptions<T>): ArrayModel<T>;
277
- interface SetModel<T extends TypeModels> extends BasicModel<InferModelJsonType<T>[]> {
278
- kind: "set";
279
- base: T;
280
- schema?: SetSchema;
281
- }
282
- interface SetModelOptions<T extends TypeModels> extends Omit<SetModel<T>, "kind" | "base"> {}
283
- declare function set<T extends TypeModels>(base: T, options?: SetModelOptions<T>): SetModel<T>;
284
- interface MapModel<T> extends BasicModel<{
285
- [key: string]: InferModelJsonType<T>;
286
- }> {
287
- kind: "map";
288
- base: T;
289
- schema?: MapSchema;
290
- }
291
- interface MapModelOptions<T extends TypeModels> extends Omit<MapModel<T>, "kind" | "base"> {}
292
- declare function map<T extends TypeModels>(base: T, options?: MapModelOptions<T>): MapModel<T>;
293
- interface RecordModel<T extends {
294
- [key: string]: TypeModels;
295
- }> extends BasicModel<InferRecordJsonType<T>> {
296
- kind: "record";
297
- id: string;
298
- properties: T;
299
- }
300
- type KeyOfOptional<T extends {
301
- [key: string]: TypeModels;
302
- }> = { [key in keyof T]: T[key] extends OptionalModel<any> ? key : never }[keyof T];
303
- type InferRecordJsonType<T extends {
304
- [key: string]: TypeModels;
305
- }, O extends KeyOfOptional<T> = KeyOfOptional<T>> = Simplify<{ [key in Exclude<keyof T, O>]: InferModelJsonType<T[key]> } & { [key in O]?: InferModelJsonType<T[key]> }>;
306
- interface RecordModelOptions<T extends {
307
- [key: string]: TypeModels;
308
- }> extends Omit<RecordModel<T>, "kind"> {}
309
- declare function record<const T extends {
310
- [key: string]: TypeModels;
311
- }>(options: RecordModelOptions<T>): RecordModel<T>;
312
- interface UnionModel<T extends {
313
- [key: string]: TypeModels;
314
- }> extends BasicModel<InferUnionJsonType<T>> {
315
- kind: "union";
316
- id: string;
317
- variants: T;
318
- }
319
- type InferUnionJsonType<T extends {
320
- [key: string]: TypeModels;
321
- }> = { [key in keyof T]: { [k in key]: InferModelJsonType<T[key]> } }[keyof T];
322
- interface UnionModelOptions<T extends {
323
- [key: string]: TypeModels;
324
- }> extends Omit<UnionModel<T>, "kind"> {}
325
- declare function union<const T extends {
326
- [key: string]: TypeModels;
327
- }>(options: UnionModelOptions<T>): UnionModel<T>;
328
- interface DatetimeModel extends BasicModel<string> {
329
- kind: "datetime";
330
- schema?: StringSchema;
331
- }
332
- interface DatetimeModelOptions extends Omit<DatetimeModel, "kind"> {}
333
- declare function datetime(options?: DatetimeModelOptions): DatetimeModel;
334
- interface DateModel extends BasicModel<string> {
335
- kind: "date";
336
- schema?: StringSchema;
337
- }
338
- interface DateModelOptions extends Omit<DateModel, "kind"> {}
339
- declare function date(options?: DateModelOptions): DateModel;
340
- interface DurationModel extends BasicModel<string> {
341
- kind: "duration";
342
- schema?: StringSchema;
343
- }
344
- interface DurationModelOptions extends Omit<DurationModel, "kind"> {}
345
- declare function duration(options?: DurationModelOptions): DurationModel;
346
- interface ErrorModel<Code extends string, Context extends {
347
- [key: string]: TypeModels;
348
- }> extends BasicModel<InferErrorModel<Code, Context>> {
349
- kind: "error";
350
- id: string;
351
- code: Code;
352
- context: Context;
353
- }
354
- type InferErrorModel<Code extends string, Context extends {
355
- [key: string]: TypeModels;
356
- }> = {
357
- code: Code;
358
- context: InferRecordJsonType<Context>;
359
- };
360
- interface ErrorModelOptions<Code extends string, Context extends {
361
- [key: string]: TypeModels;
362
- }> extends Omit<ErrorModel<Code, Context>, "kind"> {}
363
- declare function error<const Code extends string, Context extends {
364
- [key: string]: TypeModels;
365
- }>(options: ErrorModelOptions<Code, Context>): ErrorModel<Code, Context>;
366
- interface EnumsModel<T extends {
367
- [key: string]: string;
368
- }> extends BasicModel<T[keyof T]> {
1717
+ //#region src/generate-jsonschema.d.ts
1718
+ interface SchemaRegistry {
1719
+ getRef: (model: Models) => string | undefined;
1720
+ add: (id: string, model: Models) => SchemaRegistry;
1721
+ }
1722
+ interface GenerateJsonSchemaOptions {
1723
+ model: Models;
1724
+ registry?: SchemaRegistry;
1725
+ toJsonSchema?: (type?: StandardTypedV1) => JsonSchemaObject;
1726
+ }
1727
+ interface GenerateJsonSchemaResult {
1728
+ jsonSchema: JsonSchema;
1729
+ registry: SchemaRegistry;
1730
+ }
1731
+ declare function generateJsonSchema(options: GenerateJsonSchemaOptions): GenerateJsonSchemaResult;
1732
+ declare function createJsonSchemaRegistry(models?: Map<Models, {
369
1733
  id: string;
370
- kind: "enums";
371
- variants: T;
372
- }
373
- interface EnumsModelOptions<T extends {
374
- [key: string]: string;
375
- }> extends Omit<EnumsModel<T>, "kind"> {}
376
- declare function enums<const T extends {
377
- [key: string]: string;
378
- }>(options: EnumsModelOptions<T>): EnumsModel<T>;
379
- interface TaggedUnionModel<Tag extends string, Variants extends {
380
- [key: string]: RecordModel<{ [key in Tag]: LiteralModel<string> }>;
381
- }> extends BasicModel<InferTaggedUnionJsonType<Tag, Variants>> {
1734
+ schema: JsonSchema;
1735
+ }>): SchemaRegistry;
1736
+ declare function createOpenapiSchemaRegistry(models?: Map<Models, {
382
1737
  id: string;
383
- kind: "tagged-union";
384
- tag: Tag;
385
- variants: Variants;
386
- }
387
- type InferTaggedUnionJsonType<Tag extends string, Variants extends {
388
- [key: string]: RecordModel<{ [key in Tag]: LiteralModel<string> }>;
389
- }> = { [key in keyof Variants]: Variants[key] extends RecordModel<infer R> ? InferRecordJsonType<R> : never }[keyof Variants];
390
- interface TaggedUnionModelOptions<Tag extends string, Variants extends {
391
- [key: string]: RecordModel<{ [key in Tag]: LiteralModel<string> }>;
392
- }> extends Omit<TaggedUnionModel<Tag, Variants>, "kind"> {}
393
- declare function taggedUnion<const Tag extends string, Variants extends {
394
- [key: string]: RecordModel<{ [key in Tag]: LiteralModel<string> }>;
395
- }>(options: TaggedUnionModelOptions<Tag, Variants>): TaggedUnionModel<Tag, Variants>;
396
- type TypeModels = Int32Model | Int64Model | Float32Model | Float64Model | BooleanModel | StringModel | LiteralModel<string | number | boolean> | OptionalModel<TypeModels> | ArrayModel<TypeModels> | SetModel<TypeModels> | MapModel<TypeModels> | RecordModel<{
397
- [key: string]: TypeModels;
398
- }> | UnionModel<{
399
- [key: string]: TypeModels;
400
- }> | TaggedUnionModel<string, {
401
- [key: string]: any;
402
- }> | DatetimeModel | DateModel | DurationModel | ErrorModel<string, {
403
- [key: string]: TypeModels;
404
- }> | EnumsModel<{
405
- [key: string]: string;
406
- }>;
407
- type InferModelJsonType<T> = any extends T ? never : TypeModels extends T ? any : T extends Int32Model ? number : T extends Int64Model ? string : T extends Float32Model ? number : T extends Float64Model ? number : T extends BooleanModel ? boolean : T extends StringModel ? string : T extends LiteralModel<infer R> ? R : T extends OptionalModel<infer R> ? InferModelJsonType<R> | undefined | null : T extends ArrayModel<infer R> ? InferModelJsonType<R>[] : T extends SetModel<infer R> ? InferModelJsonType<R>[] : T extends MapModel<infer R> ? Record<string, InferModelJsonType<R>> : T extends RecordModel<infer R> ? InferRecordJsonType<R> : T extends UnionModel<infer R> ? InferUnionJsonType<R> : T extends TaggedUnionModel<infer Tag, infer Variants> ? InferTaggedUnionJsonType<Tag, Variants> : T extends DatetimeModel ? string : T extends DateModel ? string : T extends DurationModel ? string : T extends ErrorModel<infer Code, infer Context> ? InferErrorModel<Code, Context> : T extends EnumsModel<infer R> ? R[keyof R] : never;
408
- interface ModelToJsonSchemaOptions {
409
- model: TypeModels;
410
- target?: "draft-2020-12";
411
- reference?: "inline" | "json-schema" | "openapi";
412
- depth?: number;
413
- }
414
- declare function generateJsonSchema(options: ModelToJsonSchemaOptions): JsonSchemaObject;
415
- type NamedModel = RecordModel<{
416
- [key: string]: TypeModels;
417
- }> | EnumsModel<{
418
- [key: string]: string;
419
- }> | UnionModel<{
420
- [key: string]: TypeModels;
421
- }> | ErrorModel<string, {
422
- [key: string]: TypeModels;
423
- }>;
1738
+ schema: JsonSchema;
1739
+ }>): SchemaRegistry;
424
1740
  //#endregion
425
1741
  //#region src/schemas/openapi-schema.d.ts
426
1742
  interface OpenAPIObject {
@@ -716,204 +2032,133 @@ interface SecurityRequirementObject {
716
2032
  [key: string]: string[];
717
2033
  }
718
2034
  //#endregion
719
- //#region src/utils/index.d.ts
720
- type ExtractPathParams<Path extends string> = string extends Path ? string : Path extends `${infer _Start}/{${infer Param}}/${infer Rest}` ? Param | ExtractPathParams<`/${Rest}`> : Path extends `${infer _Start}/{${infer Param}}` ? Param : never;
721
- //#endregion
722
- //#region src/type-system/http.d.ts
723
- type AllowedHttpValue = StringModel | Int32Model | Int64Model | BooleanModel | LiteralModel<string | number | boolean> | Optionalize<StringModel | Int32Model | Int64Model | BooleanModel | LiteralModel<string | number | boolean>>;
724
- type PartialOf<T extends {
725
- [key: string]: any;
726
- }, K extends keyof T> = Simplify<{ [key in Exclude<keyof T, K>]: T[key] } & { [key in K]?: T[key] }>;
2035
+ //#region src/generate-openapi.d.ts
727
2036
  interface GenerateOpenapiOptions {
728
- info: OpenAPIObject["info"];
729
- routes: HttpRouteModel[];
730
- securitySchemes?: NonNullable<OpenAPIObject["components"]>["securitySchemes"];
731
- tags?: OpenAPIObject["tags"];
732
- servers?: OpenAPIObject["servers"];
733
- }
734
- declare function generateOpenapi(options: GenerateOpenapiOptions): OpenAPIObject;
735
- declare function collectModelFromRoutes(routes: HttpRouteModel[]): Map<string, TypeModels>;
736
- declare function collectModelDeep(model: TypeModels): Map<string, TypeModels>;
737
- interface HttpResponseModel {
738
- status: number;
739
- description?: string;
740
- content?: HttpContentModel;
741
- headers?: {
742
- [key: string]: AllowedHttpValue | OptionalModel<AllowedHttpValue>;
743
- };
744
- cookies?: {
745
- [key: string]: AllowedHttpValue | OptionalModel<AllowedHttpValue>;
746
- };
747
- }
748
- interface HttpRouteModel<Path extends string = string> {
749
- kind: "http-route";
750
- id: string;
751
- path: Path;
752
- method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD" | "TRACE";
753
- description?: string;
754
- summary?: string;
755
- variables: { [key in ExtractPathParams<Path>]: AllowedHttpValue };
756
- queries?: {
757
- [key: string]: AllowedHttpValue | OptionalModel<AllowedHttpValue>;
758
- };
759
- cookies?: {
760
- [key: string]: AllowedHttpValue | OptionalModel<AllowedHttpValue>;
761
- };
762
- headers?: {
763
- [key: string]: AllowedHttpValue | OptionalModel<AllowedHttpValue>;
764
- };
765
- content?: HttpContentModel;
766
- responses?: {
767
- [key: string]: HttpResponseModel;
768
- };
769
- tags?: string[];
2037
+ info: InfoObject;
2038
+ servers?: ServerObject[];
2039
+ routers: RouterModel[];
770
2040
  security?: {
771
- [key: string]: string[];
2041
+ policy?: SecurityPolicyModel;
2042
+ deployments?: Record<string, SecurityDeployment>;
772
2043
  };
773
2044
  }
774
- interface HttpRouteModelOptions<Path extends string> extends Omit<HttpRouteModel<Path>, "kind"> {}
775
- declare function route<const Path extends string>(options: HttpRouteModelOptions<Path>): HttpRouteModel<Path>;
776
- interface PlainTextContentModel {
777
- kind: "plain-text-content";
778
- type: PlainTextLikeContentType;
779
- model?: StringModel;
780
- }
781
- interface PlainTextContentOptions extends Omit<PlainTextContentModel, "kind"> {}
782
- declare function plainText(options: PlainTextContentOptions): PlainTextContentModel;
783
- interface JsonContentModel {
784
- kind: "json-content";
785
- type: JsonLikeContentType;
786
- model: TypeModels;
787
- }
788
- interface JsonContentOptions extends Omit<JsonContentModel, "kind"> {}
789
- declare function json(options: JsonContentOptions): JsonContentModel;
790
- interface PlainTextStreamContentModel {
791
- kind: "plain-text-stream-content";
792
- type: PlainTextLikeContentType;
793
- model?: StringModel;
794
- description?: string;
2045
+ interface GenerateOpenapiResult {
2046
+ openapi: OpenAPIObject;
2047
+ registry: SchemaRegistry;
795
2048
  }
796
- interface PlainTextStreamContentOptions extends Omit<PlainTextStreamContentModel, "kind"> {}
797
- declare function plainTextStream(options: PlainTextStreamContentOptions): PlainTextStreamContentModel;
798
- interface JsonStreamContentModel {
799
- kind: "json-stream-content";
800
- type: JsonStreamLikeContentType;
801
- model: TypeModels;
2049
+ declare function generateOpenapi(options: GenerateOpenapiOptions): GenerateOpenapiResult;
2050
+ //#endregion
2051
+ //#region src/codegen/descriptors.d.ts
2052
+ type AnyRouteModel = RouteModel<string, Record<string, SimpleType>, Models, RecordModel<Record<string, Models>, string>, RecordModel<Record<string, Models>, string>, Record<number, any>>;
2053
+ interface CollectOptions {
2054
+ /** 将 originalId 映射为标识符,默认 pascalCase */
2055
+ identifier?: (id: string) => string;
2056
+ /** 命名空间,如 "com.example" */
2057
+ namespace?: string;
2058
+ }
2059
+ interface ModelDescriptor {
2060
+ kind: string;
2061
+ originalId: string;
2062
+ identifier: string;
2063
+ namespace?: string;
2064
+ title?: string;
802
2065
  description?: string;
2066
+ deprecated?: boolean;
2067
+ examples?: unknown[];
2068
+ }
2069
+ interface RecordDescriptor extends ModelDescriptor {
2070
+ kind: "record";
2071
+ fields: FieldDescriptor[];
803
2072
  }
804
- interface JsonStreamContentOptions extends Omit<JsonStreamContentModel, "kind"> {}
805
- declare function jsonStream(options: JsonStreamContentOptions): JsonStreamContentModel;
806
- interface BinaryStreamContentModel {
807
- kind: "binary-stream-content";
808
- type: BinaryLikeContentType;
2073
+ interface FieldDescriptor {
2074
+ name: string;
2075
+ model: Models;
2076
+ required: boolean;
2077
+ title?: string;
809
2078
  description?: string;
2079
+ deprecated?: boolean;
810
2080
  }
811
- interface BinaryStreamContentOptions extends Omit<BinaryStreamContentModel, "kind"> {}
812
- declare function binary(options: BinaryStreamContentOptions): BinaryStreamContentModel;
813
- interface FormContentModel<T extends {
814
- [key: string]: AllowedHttpValue | OptionalModel<AllowedHttpValue>;
815
- }> {
816
- kind: "form-content";
817
- type: FormLikeContentType;
818
- model: RecordModel<T>;
819
- }
820
- interface FormContentOptions<T extends {
821
- [key: string]: AllowedHttpValue;
822
- }> extends Omit<FormContentModel<T>, "kind"> {}
823
- declare function form<T extends {
824
- [key: string]: AllowedHttpValue;
825
- }>(options: FormContentOptions<T>): FormContentModel<T>;
826
- type HttpContentModel = PlainTextContentModel | JsonContentModel | PlainTextStreamContentModel | JsonStreamContentModel | BinaryStreamContentModel | FormContentModel<{
827
- [key: string]: AllowedHttpValue;
828
- }>;
829
- type PlainTextLikeContentType = (string & {}) | "text/plain" | "text/html" | "text/css" | "text/xml" | "text/markdown" | "text/csv";
830
- type JsonLikeContentType = (string & {}) | "application/json" | "application/json; charset=utf-8" | "application/ld+json" | "application/hal+json" | "application/vnd.api+json" | "application/problem+json" | "application/schema+json";
831
- type PlainTextStreamLikeContentType = (string & {}) | "text/event-stream";
832
- type JsonStreamLikeContentType = (string & {}) | "application/ndjson" | "application/x-ndjson" | "application/jsonl" | "application/json-seq" | "application/stream+json";
833
- type BinaryLikeContentType = (string & {}) | "application/octet-stream" | "application/pdf" | "application/zip" | "application/gzip" | "image/jpeg" | "image/png" | "image/gif" | "image/webp" | "image/svg+xml" | "audio/mpeg" | "audio/wav" | "video/mp4" | "video/webm";
834
- type FormLikeContentType = (string & {}) | "application/x-www-form-urlencoded" | "multipart/form-data";
835
- //#endregion
836
- //#region src/generator/java.d.ts
837
- interface GenerateJavaClassOptions {
838
- package: string;
839
- model: NamedModel;
2081
+ interface EnumsDescriptor extends ModelDescriptor {
2082
+ kind: "enums";
2083
+ values: Record<string, string>;
840
2084
  }
841
- declare function generateJavaClass(options: GenerateJavaClassOptions): string;
842
- declare function formatJava(code: string): Promise<string>;
843
- interface GenerateJavaOptions {
844
- package: string;
845
- srcDir: string;
846
- routes?: HttpRouteModel[];
847
- models?: TypeModels[];
2085
+ interface UnionDescriptor extends ModelDescriptor {
2086
+ kind: "union";
2087
+ variants: Record<string, Models>;
2088
+ }
2089
+ interface TaggedUnionDescriptor extends ModelDescriptor {
2090
+ kind: "taggedUnion";
2091
+ variants: Record<string, Models>;
2092
+ variantKey: string;
2093
+ payloadKey: string;
848
2094
  }
849
- declare function generateJavaCodes(options: GenerateJavaOptions): Promise<{
2095
+ type AnyNamedDescriptor = RecordDescriptor | EnumsDescriptor | UnionDescriptor | TaggedUnionDescriptor;
2096
+ interface OperationDescriptor {
2097
+ id: string;
2098
+ group: string;
2099
+ method: HttpMethod;
850
2100
  path: string;
851
- code: string;
852
- }[]>;
853
- //#endregion
854
- //#region src/generator/rust.d.ts
855
- interface GenerateRustCodeOptions {
856
- module_name: string;
857
- model: RecordModel<{
858
- [key: string]: TypeModels;
859
- }> | UnionModel<{
860
- [key: string]: TypeModels;
861
- }> | EnumsModel<{
862
- [key: string]: string;
863
- }> | ErrorModel<string, {
864
- [key: string]: TypeModels;
2101
+ summary?: string;
2102
+ description?: string;
2103
+ tags?: string[];
2104
+ requestModel: Models | null;
2105
+ responses: Record<number, Models | null>;
2106
+ responseKinds: Record<number, string>;
2107
+ pathVariables: Record<string, {
2108
+ model: Models;
2109
+ name: string;
2110
+ }>;
2111
+ queries: Record<string, {
2112
+ model: Models;
2113
+ name: string;
2114
+ required: boolean;
2115
+ }>;
2116
+ headers: Record<string, {
2117
+ model: Models;
2118
+ name: string;
2119
+ required: boolean;
865
2120
  }>;
866
2121
  }
867
- declare function generateRustCode(options: GenerateRustCodeOptions): string;
868
- declare function formatRust(code: string): Promise<string>;
869
- interface GenerateRustOptions {
870
- module_name: string;
871
- srcDir: string;
872
- routes?: HttpRouteModel[];
873
- models?: TypeModels[];
874
- }
875
- declare function generateRustCodes(options: GenerateRustOptions): Promise<{
876
- path: string;
877
- code: string;
878
- }[]>;
879
- //#endregion
880
- //#region src/type-system/serialize.d.ts
881
- type InferDeserialized<T> = any extends T ? never : TypeModels extends T ? any : T extends Int32Model ? number : T extends Int64Model ? bigint : T extends Float32Model ? number : T extends Float64Model ? number : T extends BooleanModel ? boolean : T extends StringModel ? string : T extends LiteralModel<infer R> ? R : T extends OptionalModel<infer R> ? InferDeserialized<R> | undefined | null : T extends ArrayModel<infer R> ? InferDeserialized<R>[] : T extends SetModel<infer R> ? Set<InferDeserialized<R>> : T extends MapModel<infer R> ? Map<string, InferDeserialized<R>> : T extends RecordModel<infer R> ? InferDeserializedRecord<R> : T extends UnionModel<infer R> ? InferDeserializedUnion<R> : T extends TaggedUnionModel<infer _Tag, infer R> ? InferDeserializedTaggedUnion<R> : T extends DatetimeModel ? Temporal.Instant : T extends DateModel ? Temporal.Instant : T extends DurationModel ? Temporal.Duration : T extends ErrorModel<infer Code, infer Context> ? InferDeserializedError<Code, Context> : T extends EnumsModel<infer R> ? R[keyof R] : never;
882
- type InferDeserializedRecord<T extends {
883
- [key: string]: TypeModels;
884
- }, O extends KeyOfOptional<T> = KeyOfOptional<T>> = Simplify<{ [key in Exclude<keyof T, O>]: InferDeserialized<T[key]> } & { [key in O]?: InferDeserialized<T[key]> }>;
885
- type InferDeserializedUnion<T extends {
886
- [key: string]: TypeModels;
887
- }> = { [key in keyof T]: { [k in key]: InferDeserialized<T[key]> } }[keyof T];
888
- type InferDeserializedTaggedUnion<Variants extends {
889
- [key: string]: RecordModel<{
890
- [key: string]: TypeModels;
2122
+ interface SchemaInfo {
2123
+ kind: "record" | "enums" | "union" | "taggedUnion";
2124
+ fields?: Array<{
2125
+ name: string;
2126
+ model: Models;
2127
+ required: boolean;
891
2128
  }>;
892
- }> = { [key in keyof Variants]: InferDeserialized<Variants[key]> }[keyof Variants];
893
- type InferDeserializedError<Code extends string, Context extends {
894
- [key: string]: TypeModels;
895
- }> = [Context] extends [never] ? {
896
- code: Code;
897
- } : {
898
- code: Code;
899
- context: InferDeserializedRecord<Context>;
900
- };
901
- declare function deserialize<T extends TypeModels>(model: T, json: string): DeserializeResult<InferDeserialized<T>>;
902
- declare function deserializeInner<T extends TypeModels>(model: T, value: any): DeserializeResult<InferDeserialized<T>>;
903
- interface DeserializeSuccess<T> {
904
- isSuccess: true;
905
- value: T;
2129
+ variants?: Record<string, string>;
2130
+ unionVariants?: Record<string, Models>;
2131
+ variantKey?: string;
2132
+ payloadKey?: string;
906
2133
  }
907
- interface DeserializeFailed {
908
- isSuccess: false;
909
- code: "deserial-failed";
910
- context: {
911
- expect: TypeModels;
912
- receive: any;
913
- };
2134
+ type SchemaMap = Map<string, SchemaInfo>;
2135
+ //#endregion
2136
+ //#region src/codegen/collect.d.ts
2137
+ declare function collectNamedModels(models: Models[], options?: CollectOptions): AnyNamedDescriptor[];
2138
+ declare function collectOperations(routers: RouterModel[]): OperationDescriptor[];
2139
+ declare function collectSchemaMap(ops: OperationDescriptor[]): SchemaMap;
2140
+ declare function resolveNamedRoot(m: Models): {
2141
+ id: string;
2142
+ } | null;
2143
+ //#endregion
2144
+ //#region src/codegen/json-schema.d.ts
2145
+ declare function mergeJsonSchemas(schemas: Record<string, Models>): JsonSchemaObject;
2146
+ //#endregion
2147
+ //#region src/codegen/hono-server.d.ts
2148
+ interface HonoServerOptions {
2149
+ routers: RouterModel[];
2150
+ identifier?: (id: string) => string;
2151
+ namespace?: string;
2152
+ }
2153
+ declare function generateHonoServer(options: HonoServerOptions): Record<string, string>;
2154
+ //#endregion
2155
+ //#region src/codegen/ts-client.d.ts
2156
+ interface TsClientOptions {
2157
+ routers: RouterModel[];
2158
+ identifier?: (id: string) => string;
2159
+ namespace?: string;
914
2160
  }
915
- type DeserializeResult<T> = DeserializeSuccess<T> | DeserializeFailed;
916
- declare function serialize<T extends TypeModels>(model: T, value: InferDeserialized<T>): string;
2161
+ declare function generateTsClient(options: TsClientOptions): Record<string, string>;
917
2162
  //#endregion
918
- export { AllowedHttpValue, ArrayModel, ArrayModelOptions, BasicModel, BinaryLikeContentType, BinaryStreamContentModel, BinaryStreamContentOptions, BooleanModel, BooleanModelOptions, DateModel, DateModelOptions, DatetimeModel, DatetimeModelOptions, DeserializeFailed, DeserializeResult, DeserializeSuccess, DurationModel, DurationModelOptions, EnumsModel, EnumsModelOptions, ErrorModel, ErrorModelOptions, Float32Model, Float32ModelOptions, Float64Model, Float64ModelOptions, FormContentModel, FormContentOptions, FormLikeContentType, GenerateJavaClassOptions, GenerateJavaOptions, GenerateOpenapiOptions, GenerateRustCodeOptions, GenerateRustOptions, HttpContentModel, HttpResponseModel, HttpRouteModel, HttpRouteModelOptions, InferDeserialized, InferDeserializedError, InferDeserializedRecord, InferDeserializedTaggedUnion, InferDeserializedUnion, InferErrorModel, InferModelJsonType, InferRecordJsonType, InferTaggedUnionJsonType, InferUnionJsonType, Int32Model, Int32ModelOptions, Int64Model, Int64ModelOptions, JsonContentModel, JsonContentOptions, JsonLikeContentType, JsonStreamContentModel, JsonStreamContentOptions, JsonStreamLikeContentType, KeyOfOptional, LiteralModel, LiteralModelOptions, MapModel, MapModelOptions, ModelToJsonSchemaOptions, NamedModel, OptionalModel, OptionalModelOptions, Optionalize, PartialOf, PlainTextContentModel, PlainTextContentOptions, PlainTextLikeContentType, PlainTextStreamContentModel, PlainTextStreamContentOptions, PlainTextStreamLikeContentType, RecordModel, RecordModelOptions, SetModel, SetModelOptions, StringModel, StringModelOptions, TaggedUnionModel, TaggedUnionModelOptions, TypeModels, UnionModel, UnionModelOptions, array, binary, boolean, collectModelDeep, collectModelFromRoutes, date, datetime, deserialize, deserializeInner, duration, enums, error, float32, float64, form, formatJava, formatRust, generateJavaClass, generateJavaCodes, generateJsonSchema, generateOpenapi, generateRustCode, generateRustCodes, int32, int64, json, jsonStream, literal, map, optional, plainText, plainTextStream, record, route, serialize, set, string, taggedUnion, union };
2163
+ export { AnyNamedDescriptor, AnyRouteModel, ApikeySecurityComponent, ApikeySecurityComponentOptions, ArrayModel, BasicModel, BinaryLikeContentType, BinaryResponseModel, BinaryResponseOptions, BooleanModel, CollectOptions, DateModel, DateModelOptions, DatetimeModel, DatetimeModelOptions, DurationModel, DurationModelOptions, EnumsDescriptor, EnumsModel, EnumsModelOptions, FieldDescriptor, Float32Model, Float64Model, FormLikeContentType, GenerateJsonSchemaOptions, GenerateJsonSchemaResult, GenerateOpenapiOptions, GenerateOpenapiResult, HonoServerOptions, HttpMethod, InferModel, InferTaggedUnion, InferUnion, Int32Model, JsonLikeContentType, JsonResponseModel, JsonStreamLikeContentType, LiteralModel, MapModel, ModelDescriptor, Models, NullModel, OpenIdComponentOptions, OpenIdDeployment, OpenIdDeploymentOptions, OpenIdSecurityComponent, OperationDescriptor, OptionsOf, PlainTextLikeContentType, PlainTextStreamLikeContentType, PropertiesType, RecordDescriptor, RecordModel, ResponseModel, ResponseOptions, RouteModel, RouteOptions, RouterModel, SSEResponseModel, SchemaInfo, SchemaMap, SchemaRegistry, SecurityAppliable, SecurityApply, SecurityComponent, SecurityDeployment, SecurityPolicyModel, SecurityPolicyPathItem, SetModel, SimpleType, StreamResponseModel, StringModel, TaggedUnionDescriptor, TaggedUnionModel, TsClientOptions, UnionDescriptor, UnionModel, apikey, array, binary, boolean, collectNamedModels, collectOperations, collectSchemaMap, createJsonSchemaRegistry, createOpenapiSchemaRegistry, date, datetime, deployOpenIdConnect, duration, enums, float32, float64, generateHonoServer, generateJsonSchema, generateOpenapi, generateTsClient, int32, json, jsonStream, literal, map, mergeJsonSchemas, nullLike, openIdConnect, record, resolveNamedRoot, route, set, sseStream, string, taggedUnion, union };
919
2164
  //# sourceMappingURL=index.d.mts.map