@zimic/http 0.0.1-canary.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/LICENSE.md +16 -0
  2. package/README.md +230 -0
  3. package/dist/chunk-VHQRAQPQ.mjs +1371 -0
  4. package/dist/chunk-VHQRAQPQ.mjs.map +1 -0
  5. package/dist/chunk-VUDGONB5.js +1382 -0
  6. package/dist/chunk-VUDGONB5.js.map +1 -0
  7. package/dist/cli.js +116 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/cli.mjs +109 -0
  10. package/dist/cli.mjs.map +1 -0
  11. package/dist/index.d.ts +1306 -0
  12. package/dist/index.js +544 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/index.mjs +537 -0
  15. package/dist/index.mjs.map +1 -0
  16. package/dist/typegen.d.ts +86 -0
  17. package/dist/typegen.js +12 -0
  18. package/dist/typegen.js.map +1 -0
  19. package/dist/typegen.mjs +3 -0
  20. package/dist/typegen.mjs.map +1 -0
  21. package/index.d.ts +1 -0
  22. package/package.json +110 -0
  23. package/src/cli/cli.ts +92 -0
  24. package/src/cli/index.ts +4 -0
  25. package/src/cli/typegen/openapi.ts +24 -0
  26. package/src/formData/HttpFormData.ts +300 -0
  27. package/src/formData/types.ts +110 -0
  28. package/src/headers/HttpHeaders.ts +217 -0
  29. package/src/headers/types.ts +65 -0
  30. package/src/index.ts +55 -0
  31. package/src/pathParams/types.ts +67 -0
  32. package/src/searchParams/HttpSearchParams.ts +258 -0
  33. package/src/searchParams/types.ts +133 -0
  34. package/src/typegen/index.ts +12 -0
  35. package/src/typegen/namespace/TypegenNamespace.ts +18 -0
  36. package/src/typegen/openapi/generate.ts +168 -0
  37. package/src/typegen/openapi/transform/components.ts +481 -0
  38. package/src/typegen/openapi/transform/context.ts +67 -0
  39. package/src/typegen/openapi/transform/filters.ts +71 -0
  40. package/src/typegen/openapi/transform/imports.ts +15 -0
  41. package/src/typegen/openapi/transform/io.ts +86 -0
  42. package/src/typegen/openapi/transform/methods.ts +803 -0
  43. package/src/typegen/openapi/transform/operations.ts +120 -0
  44. package/src/typegen/openapi/transform/paths.ts +119 -0
  45. package/src/typegen/openapi/utils/types.ts +45 -0
  46. package/src/types/arrays.d.ts +4 -0
  47. package/src/types/json.ts +89 -0
  48. package/src/types/objects.d.ts +14 -0
  49. package/src/types/requests.ts +96 -0
  50. package/src/types/schema.ts +834 -0
  51. package/src/types/strings.d.ts +9 -0
  52. package/src/types/utils.ts +64 -0
  53. package/src/utils/console.ts +7 -0
  54. package/src/utils/data.ts +13 -0
  55. package/src/utils/files.ts +28 -0
  56. package/src/utils/imports.ts +12 -0
  57. package/src/utils/prettier.ts +13 -0
  58. package/src/utils/strings.ts +3 -0
  59. package/src/utils/time.ts +25 -0
  60. package/src/utils/urls.ts +52 -0
  61. package/typegen.d.ts +1 -0
@@ -0,0 +1,834 @@
1
+ import { IfAny, UnionToIntersection, UnionHasMoreThanOneType, Prettify, NonEmptyArray } from '@/types/utils';
2
+
3
+ import { HttpFormDataSchema, HttpFormDataSerialized } from '../formData/types';
4
+ import { HttpHeadersSchema, HttpHeadersSerialized } from '../headers/types';
5
+ import { HttpPathParamsSchema, HttpPathParamsSerialized } from '../pathParams/types';
6
+ import { HttpSearchParamsSchema, HttpSearchParamsSerialized } from '../searchParams/types';
7
+ import { HttpBody } from './requests';
8
+
9
+ export const HTTP_METHODS_WITH_REQUEST_BODY = Object.freeze(['POST', 'PUT', 'PATCH', 'DELETE'] as const);
10
+ export type HttpMethodWithRequestBody = (typeof HTTP_METHODS_WITH_REQUEST_BODY)[number];
11
+
12
+ export const HTTP_METHODS_WITH_RESPONSE_BODY = Object.freeze([
13
+ 'GET',
14
+ 'POST',
15
+ 'PUT',
16
+ 'PATCH',
17
+ 'DELETE',
18
+ 'OPTIONS',
19
+ ] as const);
20
+ export type HttpMethodWithResponseBody = (typeof HTTP_METHODS_WITH_RESPONSE_BODY)[number];
21
+
22
+ export const HTTP_METHODS = Object.freeze(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'] as const);
23
+ /**
24
+ * A type representing the currently supported
25
+ * {@link https://developer.mozilla.org/docs/Web/HTTP/Methods `HTTP methods`}.
26
+ */
27
+ export type HttpMethod = (typeof HTTP_METHODS)[number];
28
+
29
+ /**
30
+ * A schema representing the structure of an HTTP request.
31
+ *
32
+ * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐interceptor‐http‐schemas Declaring HTTP interceptor schemas}
33
+ */
34
+ export interface HttpRequestSchema {
35
+ headers?: HttpHeadersSchema.Loose;
36
+ searchParams?: HttpSearchParamsSchema.Loose;
37
+ body?: HttpBody.Loose;
38
+ }
39
+
40
+ type ConvertToStrictHttpRequestSchema<Schema> = {
41
+ [Key in keyof Schema]: Key extends 'headers'
42
+ ? HttpHeadersSerialized<Schema[Key]>
43
+ : Key extends 'searchParams'
44
+ ? HttpSearchParamsSerialized<Schema[Key]>
45
+ : Key extends 'body'
46
+ ? HttpBody.ConvertToStrict<Schema[Key]>
47
+ : Schema[Key];
48
+ };
49
+
50
+ /**
51
+ * A schema representing the structure of an HTTP response.
52
+ *
53
+ * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐interceptor‐http‐schemas Declaring HTTP interceptor schemas}
54
+ */
55
+ export interface HttpResponseSchema {
56
+ headers?: HttpHeadersSchema.Loose;
57
+ body?: HttpBody.Loose;
58
+ }
59
+
60
+ export namespace HttpResponseSchema {
61
+ /** A schema representing the structure of an HTTP response with no body. */
62
+ export interface NoBody extends Omit<HttpResponseSchema, 'body'> {
63
+ body?: null;
64
+ }
65
+ }
66
+
67
+ type ConvertToStrictHttpResponseSchema<Schema> = ConvertToStrictHttpRequestSchema<Schema>;
68
+
69
+ /**
70
+ * The status codes used in HTTP responses, as defined by
71
+ * {@link https://httpwg.org/specs/rfc9110.html#overview.of.status.codes RFC-9110}.
72
+ *
73
+ * - `HttpStatusCode.Information`: {@link https://developer.mozilla.org/docs/Web/HTTP/Status#information_responses `1XX`}
74
+ * - `HttpStatusCode.Success`: {@link https://developer.mozilla.org/docs/Web/HTTP/Status#successful_responses `2XX`}
75
+ * - `HttpStatusCode.Redirection`: {@link https://developer.mozilla.org/docs/Web/HTTP/Status#redirection_messages `3XX`}
76
+ * - `HttpStatusCode.ClientError`: {@link https://developer.mozilla.org/docs/Web/HTTP/Status#client_error_responses `4XX`}
77
+ * - `HttpStatusCode.ServerError`: {@link https://developer.mozilla.org/docs/Web/HTTP/Status#server_error_responses `5XX`}
78
+ */
79
+ export namespace HttpStatusCode {
80
+ /**
81
+ * An HTTP status code in the `1XX` range, representing an informational response.
82
+ *
83
+ * @see {@link https://developer.mozilla.org/docs/Web/HTTP/Status#information_responses `1XX`}
84
+ */
85
+ export type Information =
86
+ | 100 // Continue
87
+ | 101 // Switching Protocols
88
+ | 102 // Processing
89
+ | 103; // Early Hints
90
+
91
+ /**
92
+ * An HTTP status code in the `2XX` range, representing a successful response.
93
+ *
94
+ * @see {@link https://developer.mozilla.org/docs/Web/HTTP/Status#successful_responses `2XX`}
95
+ */
96
+ export type Success =
97
+ | 200 // OK
98
+ | 201 // Created
99
+ | 202 // Accepted
100
+ | 203 // Non-Authoritative Information
101
+ | 204 // No Content
102
+ | 205 // Reset Content
103
+ | 206 // Partial Content
104
+ | 207 // Multi-Status
105
+ | 208 // Already Reported
106
+ | 226; // IM Used
107
+
108
+ /**
109
+ * An HTTP status code in the `3XX` range, representing a redirection response.
110
+ *
111
+ * @see {@link https://developer.mozilla.org/docs/Web/HTTP/Status#redirection_messages `3XX`}
112
+ */
113
+ export type Redirection =
114
+ | 300 // Multiple Choices
115
+ | 301 // Moved Permanently
116
+ | 302 // Found
117
+ | 303 // See Other
118
+ | 304 // Not Modified
119
+ | 307 // Temporary Redirect
120
+ | 308; // Permanent Redirect
121
+
122
+ /**
123
+ * An HTTP status code in the `4XX` range, representing a client error response.
124
+ *
125
+ * @see {@link https://developer.mozilla.org/docs/Web/HTTP/Status#client_error_responses `4XX`}
126
+ */
127
+ export type ClientError =
128
+ | 400 // Bad Request
129
+ | 401 // Unauthorized
130
+ | 402 // Payment Required
131
+ | 403 // Forbidden
132
+ | 404 // Not Found
133
+ | 405 // Method Not Allowed
134
+ | 406 // Not Acceptable
135
+ | 407 // Proxy Authentication Required
136
+ | 408 // Request Timeout
137
+ | 409 // Conflict
138
+ | 410 // Gone
139
+ | 411 // Length Required
140
+ | 412 // Precondition Failed
141
+ | 413 // Content Too Large
142
+ | 414 // URI Too Long
143
+ | 415 // Unsupported Media Type
144
+ | 416 // Range Not Satisfiable
145
+ | 417 // Expectation Failed
146
+ | 418 // I'm a teapot
147
+ | 421 // Misdirected Request
148
+ | 422 // Unprocessable Content
149
+ | 423 // Locked
150
+ | 424 // Failed Dependency
151
+ | 425 // Too Early
152
+ | 426 // Upgrade Required
153
+ | 428 // Precondition Required
154
+ | 429 // Too Many Requests
155
+ | 431 // Request Header Fields Too Large
156
+ | 451; // Unavailable For Legal Reasons
157
+
158
+ /**
159
+ * An HTTP status code in the `5XX` range, representing a server error response.
160
+ *
161
+ * @see {@link https://developer.mozilla.org/docs/Web/HTTP/Status#server_error_responses `5XX`}
162
+ */
163
+ export type ServerError =
164
+ | 500 // Internal Server Error
165
+ | 501 // Not Implemented
166
+ | 502 // Bad Gateway
167
+ | 503 // Service Unavailable
168
+ | 504 // Gateway Timeout
169
+ | 505 // HTTP Version Not Supported
170
+ | 506 // Variant Also Negotiates
171
+ | 507 // Insufficient Storage
172
+ | 508 // Loop Detected
173
+ | 510 // Not Extended
174
+ | 511; // Network Authentication Required
175
+ }
176
+
177
+ export type HttpStatusCode =
178
+ | HttpStatusCode.Information
179
+ | HttpStatusCode.Success
180
+ | HttpStatusCode.Redirection
181
+ | HttpStatusCode.ClientError
182
+ | HttpStatusCode.ServerError;
183
+
184
+ export namespace HttpResponseSchemaByStatusCode {
185
+ /** A loose version of HTTP responses by status code. JSON values are not strictly typed. */
186
+ export type Loose = {
187
+ [StatusCode in HttpStatusCode]?: HttpResponseSchema;
188
+ };
189
+
190
+ /**
191
+ * Converts a possibly loose HTTP response schema by status code to be strictly typed. JSON values are serialized to
192
+ * their strict form.
193
+ */
194
+ export type ConvertToStrict<Schema extends Loose> = {
195
+ [StatusCode in keyof Schema]: StatusCode extends 204 ? HttpResponseSchema.NoBody : Schema[StatusCode];
196
+ };
197
+
198
+ /** A schema representing the structure of HTTP responses by status code with no body. */
199
+ export type NoBody = {
200
+ [StatusCode in HttpStatusCode]?: HttpResponseSchema.NoBody;
201
+ };
202
+ }
203
+
204
+ /**
205
+ * A schema representing the structure of HTTP responses by status code.
206
+ *
207
+ * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐interceptor‐http‐schemas Declaring HTTP interceptor schemas}
208
+ */
209
+ export type HttpResponseSchemaByStatusCode =
210
+ HttpResponseSchemaByStatusCode.ConvertToStrict<HttpResponseSchemaByStatusCode.Loose>;
211
+
212
+ type ConvertToStrictHttpResponseSchemaByStatusCode<Schema> = {
213
+ [Key in keyof Schema]: ConvertToStrictHttpResponseSchema<Schema[Key]>;
214
+ };
215
+
216
+ /**
217
+ * Extracts the status codes used in a response schema by status code.
218
+ *
219
+ * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐interceptor‐http‐schemas Declaring HTTP interceptor schemas}
220
+ */
221
+ export type HttpResponseSchemaStatusCode<ResponseSchemaByStatusCode extends HttpResponseSchemaByStatusCode> =
222
+ keyof ResponseSchemaByStatusCode & HttpStatusCode;
223
+
224
+ /**
225
+ * A schema representing the structure of an HTTP request and response for a given method.
226
+ *
227
+ * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐interceptor‐http‐schemas Declaring HTTP interceptor schemas}
228
+ */
229
+ export interface HttpMethodSchema {
230
+ request?: HttpRequestSchema;
231
+ response?: HttpResponseSchemaByStatusCode;
232
+ }
233
+
234
+ export namespace HttpMethodSchema {
235
+ /** A schema representing the structure of an HTTP request and response for a given method, having no request body. */
236
+ export interface NoRequestBody extends Omit<HttpMethodSchema, 'request'> {
237
+ request?: Omit<HttpRequestSchema, 'body'> & { body?: null };
238
+ }
239
+
240
+ /**
241
+ * A schema representing the structure of an HTTP request and response for a given method, having no request and
242
+ * response bodies.
243
+ */
244
+ export interface NoBody extends Omit<NoRequestBody, 'response'> {
245
+ response?: HttpResponseSchemaByStatusCode.NoBody;
246
+ }
247
+ }
248
+
249
+ type ConvertToStrictMethod<Schema> = {
250
+ [Key in keyof Schema]: Key extends 'request'
251
+ ? ConvertToStrictHttpRequestSchema<Schema[Key]>
252
+ : Key extends 'response'
253
+ ? ConvertToStrictHttpResponseSchemaByStatusCode<Schema[Key]>
254
+ : Schema[Key];
255
+ };
256
+
257
+ /**
258
+ * A schema representing the structure of HTTP request and response by method.
259
+ *
260
+ * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐interceptor‐http‐schemas Declaring HTTP interceptor schemas}
261
+ */
262
+ export interface HttpMethodsSchema {
263
+ GET?: HttpMethodSchema.NoRequestBody;
264
+ POST?: HttpMethodSchema;
265
+ PUT?: HttpMethodSchema;
266
+ PATCH?: HttpMethodSchema;
267
+ DELETE?: HttpMethodSchema;
268
+ HEAD?: HttpMethodSchema.NoBody;
269
+ OPTIONS?: HttpMethodSchema.NoRequestBody;
270
+ }
271
+
272
+ type ConvertToStrictHttpMethodsSchema<Schema> = {
273
+ [Method in keyof Schema]: ConvertToStrictMethod<Schema[Method]>;
274
+ };
275
+
276
+ interface BaseHttpSchema {
277
+ [path: string]: HttpMethodsSchema;
278
+ }
279
+
280
+ export type ConvertToStrictHttpSchema<Schema extends HttpSchema> = {
281
+ [Path in keyof Schema]: ConvertToStrictHttpMethodsSchema<Schema[Path]>;
282
+ };
283
+
284
+ /**
285
+ * Declares an HTTP service schema.
286
+ *
287
+ * **IMPORTANT**: the input of `HttpSchema` and all of its internal types, except bodies, must be declared inline or as
288
+ * a type aliases (`type`). Types other than bodies cannot be interfaces.
289
+ *
290
+ * @example
291
+ * import { type HttpSchema } from '@zimic/http';
292
+ *
293
+ * interface UserListHeaders {
294
+ * accept: string;
295
+ * }
296
+ *
297
+ * interface UserListSearchParams {
298
+ * name?: string;
299
+ * limit?: `${number}`;
300
+ * }
301
+ *
302
+ * type Schema = HttpSchema<{
303
+ * '/users': {
304
+ * GET: {
305
+ * request: {
306
+ * headers: UserListHeaders;
307
+ * searchParams: UserListSearchParams;
308
+ * };
309
+ * response: {
310
+ * 200: {
311
+ * // Inline headers declaration
312
+ * headers: { 'content-type': string };
313
+ * body: User[];
314
+ * };
315
+ * };
316
+ * };
317
+ * };
318
+ * }>;
319
+ *
320
+ * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐interceptor‐http‐schemas Declaring HTTP interceptor schemas}
321
+ */
322
+ export type HttpSchema<Schema extends BaseHttpSchema = BaseHttpSchema> = ConvertToStrictHttpSchema<Schema>;
323
+
324
+ export namespace HttpSchema {
325
+ /**
326
+ * Declares an HTTP service methods schema.
327
+ *
328
+ * **IMPORTANT**: the input of `HttpSchema.Methods` and all of its internal types, except bodies, must be declared
329
+ * inline or as a type aliases (`type`). Types other than bodies cannot be interfaces.
330
+ *
331
+ * @example
332
+ * import { type HttpSchema } from '@zimic/http';
333
+ *
334
+ * type UserMethods = HttpSchema.Methods<{
335
+ * GET: {
336
+ * response: {
337
+ * 200: { body: User[] };
338
+ * };
339
+ * };
340
+ * }>;
341
+ *
342
+ * type Schema = HttpSchema<{
343
+ * '/users': UserMethods;
344
+ * }>;
345
+ */
346
+ export type Methods<Schema extends HttpMethodsSchema> = ConvertToStrictHttpMethodsSchema<Schema>;
347
+
348
+ /**
349
+ * Declares an HTTP service method schema.
350
+ *
351
+ * **IMPORTANT**: the input of `HttpSchema.Method` and all of its internal types, except bodies, must be declared
352
+ * inline or as a type aliases (`type`). Types other than bodies cannot be interfaces.
353
+ *
354
+ * @example
355
+ * import { type HttpSchema } from '@zimic/http';
356
+ *
357
+ * type UserListMethod = HttpSchema.Method<{
358
+ * response: {
359
+ * 200: { body: User[] };
360
+ * };
361
+ * }>;
362
+ *
363
+ * type Schema = HttpSchema<{
364
+ * '/users': {
365
+ * GET: UserListMethod;
366
+ * };
367
+ * }>;
368
+ */
369
+ export type Method<Schema extends HttpMethodSchema> = ConvertToStrictMethod<Schema>;
370
+
371
+ /**
372
+ * Declares an HTTP service request schema.
373
+ *
374
+ * **IMPORTANT**: the input of `HttpSchema.Request` and all of its internal types, except bodies, must be declared
375
+ * inline or as a type aliases (`type`). Types other than bodies cannot be interfaces.
376
+ *
377
+ * @example
378
+ * import { type HttpSchema } from '@zimic/http';
379
+ *
380
+ * type UserCreationRequest = HttpSchema.Request<{
381
+ * headers: { 'content-type': 'application/json' };
382
+ * body: User;
383
+ * }>;
384
+ *
385
+ * type Schema = HttpSchema<{
386
+ * '/users': {
387
+ * POST: {
388
+ * request: UserCreationRequest;
389
+ * response: {
390
+ * 201: { body: User };
391
+ * };
392
+ * };
393
+ * };
394
+ * }>;
395
+ */
396
+ export type Request<Schema extends HttpRequestSchema> = ConvertToStrictHttpRequestSchema<Schema>;
397
+
398
+ /**
399
+ * Declares an HTTP service response schema by status code.
400
+ *
401
+ * **IMPORTANT**: the input of `HttpSchema.ResponseByStatusCode` and all of its internal types, except bodies, must be
402
+ * declared inline or as a type aliases (`type`). Types other than bodies cannot be interfaces.
403
+ *
404
+ * @example
405
+ * import { type HttpSchema } from '@zimic/http';
406
+ *
407
+ * type UserListResponseByStatusCode = HttpSchema.ResponseByStatusCode<{
408
+ * 200: { body: User[] };
409
+ * 400: { body: { message: string } };
410
+ * }>;
411
+ *
412
+ * type Schema = HttpSchema<{
413
+ * '/users': {
414
+ * GET: {
415
+ * response: UserListResponseByStatusCode;
416
+ * };
417
+ * };
418
+ * }>;
419
+ */
420
+ export type ResponseByStatusCode<Schema extends HttpResponseSchemaByStatusCode> =
421
+ ConvertToStrictHttpResponseSchemaByStatusCode<Schema>;
422
+
423
+ /**
424
+ * Declares an HTTP service response schema.
425
+ *
426
+ * **IMPORTANT**: the input of `HttpSchema.Response` and all of its internal types, except bodies, must be declared
427
+ * inline or as a type aliases (`type`). Types other than bodies cannot be interfaces.
428
+ *
429
+ * @example
430
+ * import { type HttpSchema } from '@zimic/http';
431
+ *
432
+ * type UserListSuccessResponse = HttpSchema.Response<{
433
+ * body: User[];
434
+ * }>;
435
+ *
436
+ * type Schema = HttpSchema<{
437
+ * '/users': {
438
+ * GET: {
439
+ * response: {
440
+ * 200: UserListSuccessResponse;
441
+ * };
442
+ * };
443
+ * };
444
+ * }>;
445
+ */
446
+ export type Response<Schema extends HttpResponseSchema> = ConvertToStrictHttpResponseSchema<Schema>;
447
+
448
+ /**
449
+ * Declares an HTTP body schema. JSON values are serialized to their strict form using
450
+ * {@link https://github.com/zimicjs/zimic/wiki/api‐zimic#jsonserialized `JSONSerialized`} if necessary.
451
+ *
452
+ * @example
453
+ * import { type HttpSchema } from '@zimic/http';
454
+ *
455
+ * type UserListSuccessResponseBody = HttpSchema.Body<User[]>;
456
+ *
457
+ * type Schema = HttpSchema<{
458
+ * '/users': {
459
+ * GET: {
460
+ * response: {
461
+ * 200: { body: UserListSuccessResponseBody };
462
+ * };
463
+ * };
464
+ * };
465
+ * }>;
466
+ */
467
+ export type Body<Schema extends HttpBody.Loose> = HttpBody.ConvertToStrict<Schema>;
468
+
469
+ /**
470
+ * Declares an HTTP headers schema. Headers are serialized to their strict form using
471
+ * {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐http#httpheadersserialized `HttpHeadersSerialized`} if
472
+ * necessary.
473
+ *
474
+ * @example
475
+ * import { type HttpSchema } from '@zimic/http';
476
+ *
477
+ * type UserListHeaders = HttpSchema.Headers<{
478
+ * accept: 'application/json';
479
+ * }>;
480
+ *
481
+ * type Schema = HttpSchema<{
482
+ * '/users': {
483
+ * GET: {
484
+ * request: {
485
+ * headers: UserListHeaders;
486
+ * };
487
+ * response: {
488
+ * 200: { body: User[] };
489
+ * };
490
+ * };
491
+ * };
492
+ * }>;
493
+ */
494
+ export type Headers<Schema extends HttpHeadersSchema.Loose> = HttpHeadersSerialized<Schema>;
495
+
496
+ /**
497
+ * Declares an HTTP search params schema. Search params are serialized to their strict form using
498
+ * {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐http#httpsearchparamsserialized `HttpSearchParamsSerialized`}
499
+ * if necessary.
500
+ *
501
+ * @example
502
+ * import { type HttpSchema } from '@zimic/http';
503
+ *
504
+ * type UserListSearchParams = HttpSchema.SearchParams<{
505
+ * limit: `${number}`;
506
+ * offset: `${number}`;
507
+ * }>;
508
+ *
509
+ * type Schema = HttpSchema<{
510
+ * '/users': {
511
+ * GET: {
512
+ * request: {
513
+ * searchParams: UserListSearchParams;
514
+ * };
515
+ * response: {
516
+ * 200: { body: User[] };
517
+ * };
518
+ * };
519
+ * };
520
+ * }>;
521
+ */
522
+ export type SearchParams<Schema extends HttpSearchParamsSchema.Loose> = HttpSearchParamsSerialized<Schema>;
523
+
524
+ /**
525
+ * Declares an HTTP path params schema. Path params are serialized to their strict form using
526
+ * {@link HttpPathParamsSerialized} if necessary.
527
+ *
528
+ * @example
529
+ * import { type HttpSchema, InferPathParams } from '@zimic/http';
530
+ *
531
+ * type Schema = HttpSchema<{
532
+ * '/users/:userId': {
533
+ * GET: {
534
+ * response: {
535
+ * 200: { body: User };
536
+ * };
537
+ * };
538
+ * };
539
+ * }>;
540
+ *
541
+ * type UserByIdPathParams = HttpSchema.PathParams<{
542
+ * userId: string;
543
+ * }>;
544
+ *
545
+ * // Or infer from the path string
546
+ * type UserByIdPathParams = InferPathParams<Schema, '/users/:userId'>;
547
+ */
548
+ export type PathParams<Schema extends HttpPathParamsSchema.Loose> = HttpPathParamsSerialized<Schema>;
549
+
550
+ /**
551
+ * Declares an HTTP form data schema. Form data is serialized to their strict form using
552
+ * {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐http#httpformdataserialized `HttpFormDataSerialized`} if
553
+ * necessary.
554
+ *
555
+ * @example
556
+ * import { HttpFormData, type HttpSchema } from '@zimic/http';
557
+ *
558
+ * type UserCreationFormData = HttpFormData<
559
+ * HttpSchema.FormData<{
560
+ * name: string;
561
+ * email: string;
562
+ * }>
563
+ * >;
564
+ *
565
+ * type Schema = HttpSchema<{
566
+ * '/users': {
567
+ * POST: {
568
+ * request: {
569
+ * body: UserCreationFormData;
570
+ * };
571
+ * response: {
572
+ * 201: { body: User };
573
+ * };
574
+ * };
575
+ * };
576
+ * }>;
577
+ */
578
+ export type FormData<Schema extends HttpFormDataSchema.Loose> = HttpFormDataSerialized<Schema>;
579
+ }
580
+
581
+ /**
582
+ * Extracts the methods from an HTTP service schema.
583
+ *
584
+ * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐interceptor‐http‐schemas Declaring HTTP interceptor schemas}
585
+ */
586
+ export type HttpSchemaMethod<Schema extends HttpSchema> = IfAny<
587
+ Schema,
588
+ any, // eslint-disable-line @typescript-eslint/no-explicit-any
589
+ keyof UnionToIntersection<Schema[keyof Schema]> & HttpMethod
590
+ >;
591
+
592
+ export type AllowAnyStringInPathParams<Path extends string> = Path extends `${infer Prefix}:${string}/${infer Suffix}`
593
+ ? `${Prefix}${string}/${AllowAnyStringInPathParams<Suffix>}`
594
+ : Path extends `${infer Prefix}:${string}`
595
+ ? `${Prefix}${string}`
596
+ : Path;
597
+
598
+ /**
599
+ * Extracts the paths from an HTTP service schema. Optionally receives a second argument with one or more methods to
600
+ * filter the paths with. Only the methods defined in the schema are allowed.
601
+ *
602
+ * @example
603
+ * import { type HttpSchema, type HttpSchemaPath } from '@zimic/http';
604
+ *
605
+ * type Schema = HttpSchema<{
606
+ * '/users': {
607
+ * GET: {
608
+ * response: { 200: { body: User[] } };
609
+ * };
610
+ * };
611
+ * '/users/:userId': {
612
+ * DELETE: {
613
+ * response: { 200: { body: User } };
614
+ * };
615
+ * };
616
+ * }>;
617
+ *
618
+ * type Path = HttpSchemaPath<Schema>;
619
+ * // "/users" | "/users/:userId" | "/users/${string}"
620
+ *
621
+ * type GetPath = HttpSchemaPath<Schema, 'GET'>;
622
+ * // "/users"
623
+ *
624
+ * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐interceptor‐http‐schemas Declaring HTTP interceptor schemas}
625
+ */
626
+ export namespace HttpSchemaPath {
627
+ type LooseLiteral<Schema extends HttpSchema, Method extends HttpMethod = HttpMethod> = {
628
+ [Path in keyof Schema & string]: Method extends keyof Schema[Path] ? Path : never;
629
+ }[keyof Schema & string];
630
+
631
+ /**
632
+ * Extracts the literal paths from an HTTP service schema. Optionally receives a second argument with one or more
633
+ * methods to filter the paths with. Only the methods defined in the schema are allowed.
634
+ *
635
+ * @example
636
+ * import { type HttpSchema, type HttpSchemaPath } from '@zimic/http';
637
+ *
638
+ * type Schema = HttpSchema<{
639
+ * '/users': {
640
+ * GET: {
641
+ * response: { 200: { body: User[] } };
642
+ * };
643
+ * };
644
+ * '/users/:userId': {
645
+ * DELETE: {
646
+ * response: { 200: { body: User } };
647
+ * };
648
+ * };
649
+ * }>;
650
+ *
651
+ * type LiteralPath = HttpSchemaPath.Literal<Schema>;
652
+ * // "/users" | "/users/:userId"
653
+ *
654
+ * type LiteralGetPath = HttpSchemaPath.Literal<Schema, 'GET'>;
655
+ * // "/users"
656
+ *
657
+ * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐interceptor‐http‐schemas Declaring HTTP interceptor schemas}
658
+ */
659
+ export type Literal<
660
+ Schema extends HttpSchema,
661
+ Method extends HttpSchemaMethod<Schema> = HttpSchemaMethod<Schema>,
662
+ > = LooseLiteral<Schema, Method>;
663
+
664
+ /**
665
+ * Extracts the non-literal paths from an HTTP service schema. Optionally receives a second argument with one or more
666
+ * methods to filter the paths with. Only the methods defined in the schema are allowed.
667
+ *
668
+ * @example
669
+ * import { type HttpSchema, type HttpSchemaPath } from '@zimic/http';
670
+ *
671
+ * type Schema = HttpSchema<{
672
+ * '/users': {
673
+ * GET: {
674
+ * response: { 200: { body: User[] } };
675
+ * };
676
+ * };
677
+ * '/users/:userId': {
678
+ * DELETE: {
679
+ * response: { 200: { body: User } };
680
+ * };
681
+ * };
682
+ * }>;
683
+ *
684
+ * type NonLiteralPath = HttpSchemaPath.NonLiteral<Schema>;
685
+ * // "/users" | "/users/${string}"
686
+ *
687
+ * type NonLiteralGetPath = HttpSchemaPath.NonLiteral<Schema, 'GET'>;
688
+ * // "/users"
689
+ *
690
+ * @see {@link https://github.com/zimicjs/zimic/wiki/api‐zimic‐interceptor‐http‐schemas Declaring HTTP interceptor schemas}
691
+ */
692
+ export type NonLiteral<
693
+ Schema extends HttpSchema,
694
+ Method extends HttpSchemaMethod<Schema> = HttpSchemaMethod<Schema>,
695
+ > = AllowAnyStringInPathParams<Literal<Schema, Method>>;
696
+ }
697
+
698
+ export type HttpSchemaPath<
699
+ Schema extends HttpSchema,
700
+ Method extends HttpSchemaMethod<Schema> = HttpSchemaMethod<Schema>,
701
+ > = HttpSchemaPath.Literal<Schema, Method> | HttpSchemaPath.NonLiteral<Schema, Method>;
702
+
703
+ type LargestPathPrefix<Path extends string> = Path extends `${infer Prefix}/${infer Suffix}`
704
+ ? `${Prefix}/${Suffix extends `${string}/${string}` ? LargestPathPrefix<Suffix> : ''}`
705
+ : Path;
706
+
707
+ type ExcludeNonLiteralPathsSupersededByLiteralPath<Path extends string> =
708
+ Path extends `${LargestPathPrefix<Path>}:${string}` ? never : Path;
709
+
710
+ export type PreferMostStaticLiteralPath<Path extends string> =
711
+ UnionHasMoreThanOneType<Path> extends true ? ExcludeNonLiteralPathsSupersededByLiteralPath<Path> : Path;
712
+
713
+ type RecursiveInferHttpSchemaPath<
714
+ Schema extends HttpSchema,
715
+ Method extends HttpSchemaMethod<Schema>,
716
+ NonLiteralPath extends string,
717
+ LiteralPath extends HttpSchemaPath.Literal<Schema, Method>,
718
+ > =
719
+ NonLiteralPath extends AllowAnyStringInPathParams<LiteralPath>
720
+ ? NonLiteralPath extends `${AllowAnyStringInPathParams<LiteralPath>}/${string}`
721
+ ? never
722
+ : LiteralPath
723
+ : never;
724
+
725
+ export type LiteralHttpSchemaPathFromNonLiteral<
726
+ Schema extends HttpSchema,
727
+ Method extends HttpSchemaMethod<Schema>,
728
+ NonLiteralPath extends string,
729
+ LiteralPath extends HttpSchemaPath.Literal<Schema, Method> = HttpSchemaPath.Literal<Schema, Method>,
730
+ > = PreferMostStaticLiteralPath<
731
+ LiteralPath extends LiteralPath ? RecursiveInferHttpSchemaPath<Schema, Method, NonLiteralPath, LiteralPath> : never
732
+ >;
733
+
734
+ type RecursiveInferPathParams<Path extends string> = Path extends `${infer _Prefix}:${infer ParamName}/${infer Suffix}`
735
+ ? { [Name in ParamName]: string } & RecursiveInferPathParams<Suffix>
736
+ : Path extends `${infer _Prefix}:${infer ParamName}`
737
+ ? { [Name in ParamName]: string }
738
+ : {};
739
+
740
+ /**
741
+ * Infers the path parameters schema from a path string, optionally validating it against an {@link HttpSchema}.
742
+ *
743
+ * If the first argument is a {@link HttpSchema} (recommended), the second argument is checked to be a valid path in that
744
+ * schema.
745
+ *
746
+ * @example
747
+ * import { HttpSchema, InferPathParams } from '@zimic/http';
748
+ *
749
+ * type MySchema = HttpSchema<{
750
+ * '/users/:userId': {
751
+ * GET: {
752
+ * response: { 200: { body: User } };
753
+ * };
754
+ * };
755
+ * }>;
756
+ *
757
+ * // Using a schema to validate the path (recommended):
758
+ * type PathParams = InferPathParams<MySchema, '/users/:userId'>;
759
+ * // { userId: string }
760
+ *
761
+ * @example
762
+ * import { InferPathParams } from '@zimic/http';
763
+ *
764
+ * // Without using a schema to validate the path (works as `PathParamsSchemaFromPath`):
765
+ * type PathParams = InferPathParams<'/users/:userId'>;
766
+ * // { userId: string }
767
+ */
768
+ export type InferPathParams<
769
+ PathOrSchema extends string | HttpSchema,
770
+ OptionalPath extends PathOrSchema extends HttpSchema ? HttpSchemaPath.Literal<PathOrSchema> : never = never,
771
+ > = Prettify<
772
+ RecursiveInferPathParams<
773
+ PathOrSchema extends HttpSchema ? OptionalPath : PathOrSchema extends string ? PathOrSchema : never
774
+ >
775
+ >;
776
+
777
+ type OmitPastHttpStatusCodes<
778
+ Schema extends HttpResponseSchemaByStatusCode.Loose,
779
+ PastSchemas extends HttpResponseSchemaByStatusCode.Loose[],
780
+ > =
781
+ PastSchemas extends NonEmptyArray<HttpResponseSchemaByStatusCode.Loose>
782
+ ? Omit<Schema, keyof UnionToIntersection<PastSchemas[number]>>
783
+ : Schema;
784
+
785
+ type RecursiveMergeHttpResponsesByStatusCode<
786
+ Schemas extends HttpResponseSchemaByStatusCode.Loose[],
787
+ PastSchemas extends HttpResponseSchemaByStatusCode.Loose[] = [],
788
+ > = Schemas extends [
789
+ infer FirstSchema extends HttpResponseSchemaByStatusCode.Loose,
790
+ ...infer RestSchemas extends HttpResponseSchemaByStatusCode.Loose[],
791
+ ]
792
+ ? RestSchemas extends NonEmptyArray<HttpResponseSchemaByStatusCode.Loose>
793
+ ? OmitPastHttpStatusCodes<FirstSchema, PastSchemas> &
794
+ RecursiveMergeHttpResponsesByStatusCode<RestSchemas, [...PastSchemas, FirstSchema]>
795
+ : OmitPastHttpStatusCodes<FirstSchema, PastSchemas>
796
+ : never;
797
+
798
+ /**
799
+ * Merges multiple HTTP response schemas by status code into a single schema. When there are duplicate status codes, the
800
+ * first declaration takes precedence.
801
+ *
802
+ * @example
803
+ * import { type HttpSchema, type HttpStatusCode, MergeHttpResponsesByStatusCode } from '@zimic/http';
804
+ *
805
+ * // Overriding the 400 status code with a more specific schema
806
+ * // and using a generic schema for all other client errors.
807
+ * type MergedResponseByStatusCode = MergeHttpResponsesByStatusCode<
808
+ * [
809
+ * {
810
+ * 400: { body: { message: string; issues: string[] } };
811
+ * },
812
+ * {
813
+ * [StatusCode in HttpStatusCode.ClientError]: { body: { message: string } };
814
+ * },
815
+ * ]
816
+ * >;
817
+ * // {
818
+ * // 400: { body: { message: string; issues: string[] } };
819
+ * // 401: { body: { message: string}; };
820
+ * // 402: { body: { message: string}; };
821
+ * // 403: { body: { message: string}; };
822
+ * // ...
823
+ * // }
824
+ *
825
+ * type Schema = HttpSchema<{
826
+ * '/users': {
827
+ * GET: { response: MergedResponseByStatusCode };
828
+ * };
829
+ * }>;
830
+ */
831
+ export type MergeHttpResponsesByStatusCode<
832
+ Schemas extends HttpResponseSchemaByStatusCode.Loose[],
833
+ PastSchemas extends HttpResponseSchemaByStatusCode.Loose[] = [],
834
+ > = HttpResponseSchemaByStatusCode.ConvertToStrict<RecursiveMergeHttpResponsesByStatusCode<Schemas, PastSchemas>>;