@zap-studio/fetch 0.4.7 → 0.5.1

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 (47) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/LICENSE +1 -1
  3. package/README.md +276 -32
  4. package/dist/constants.d.mts +8 -1
  5. package/dist/constants.d.mts.map +1 -1
  6. package/dist/constants.mjs +9 -2
  7. package/dist/constants.mjs.map +1 -1
  8. package/dist/errors.d.mts +29 -0
  9. package/dist/errors.d.mts.map +1 -1
  10. package/dist/errors.mjs +46 -2
  11. package/dist/errors.mjs.map +1 -0
  12. package/dist/headers.d.mts +26 -0
  13. package/dist/headers.d.mts.map +1 -0
  14. package/dist/headers.mjs +35 -0
  15. package/dist/headers.mjs.map +1 -0
  16. package/dist/index.d.mts +28 -10
  17. package/dist/index.d.mts.map +1 -1
  18. package/dist/index.mjs +25 -10
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/internal.d.mts +33 -0
  21. package/dist/internal.d.mts.map +1 -0
  22. package/dist/internal.mjs +73 -0
  23. package/dist/internal.mjs.map +1 -0
  24. package/dist/methods.d.mts +23 -0
  25. package/dist/methods.d.mts.map +1 -0
  26. package/dist/methods.mjs +58 -0
  27. package/dist/methods.mjs.map +1 -0
  28. package/dist/request.d.mts +31 -0
  29. package/dist/request.d.mts.map +1 -0
  30. package/dist/request.mjs +39 -0
  31. package/dist/request.mjs.map +1 -0
  32. package/dist/types.d.mts +71 -45
  33. package/dist/types.d.mts.map +1 -1
  34. package/dist/types.mjs +1 -1
  35. package/dist/url.d.mts +27 -0
  36. package/dist/url.d.mts.map +1 -0
  37. package/dist/url.mjs +56 -0
  38. package/dist/url.mjs.map +1 -0
  39. package/package.json +46 -53
  40. package/bin/intent.js +0 -4
  41. package/dist/errors-DQfwnwmz.mjs +0 -18
  42. package/dist/errors-DQfwnwmz.mjs.map +0 -1
  43. package/dist/utils.d.mts +0 -33
  44. package/dist/utils.d.mts.map +0 -1
  45. package/dist/utils.mjs +0 -180
  46. package/dist/utils.mjs.map +0 -1
  47. package/skills/zap-fetch-typed-http/SKILL.md +0 -152
package/dist/index.d.mts CHANGED
@@ -1,8 +1,7 @@
1
- import { $Fetch, ApiMethods, CreateFetchOptions, ExtendedRequestInit } from "./types.mjs";
2
- import { StandardSchemaV1 } from "@standard-schema/spec";
1
+ import { $Fetch, ApiMethods, ExtendedRequestInit, FetchDefaults, FetchInput } from "./types.mjs";
2
+ import { StandardSchemaV1 } from "@zap-studio/validation";
3
3
 
4
4
  //#region src/index.d.ts
5
-
6
5
  /**
7
6
  * Type-safe fetch wrapper with Standard Schema validation.
8
7
  *
@@ -12,8 +11,18 @@ import { StandardSchemaV1 } from "@standard-schema/spec";
12
11
  *
13
12
  * If no schema is provided, returns the raw `Response` object.
14
13
  *
15
- * @throws {FetchError} When `throwOnFetchError: true` and response is not ok
16
- * @throws {ValidationError} When `throwOnValidationError: true` and validation fails
14
+ * @throws {FetchError} When `throwOnFetchError` is `true` and the response is not ok.
15
+ * @throws {ValidationError} When a schema is provided, validation returns issues, and
16
+ * `throwOnValidationError` is `true`.
17
+ * @throws {TypeError} When both `body` and `json` are provided, when JSON request
18
+ * serialization fails, when request construction fails, when headers/search params are
19
+ * invalid, when `response.json()` cannot read the body, or when the runtime `fetch`
20
+ * implementation rejects network-level failures as `TypeError`.
21
+ * @throws {DOMException} When the runtime rejects an aborted request or response body read
22
+ * as an `AbortError` DOMException.
23
+ * @throws {SyntaxError} When a schema is provided and `response.json()` cannot parse the
24
+ * response body.
25
+ * @throws Any error thrown or rejected by the provided Standard Schema validator.
17
26
  *
18
27
  * @example
19
28
  * import { z } from "zod";
@@ -39,15 +48,21 @@ import { StandardSchemaV1 } from "@standard-schema/spec";
39
48
  * console.log("Validated user:", result.value);
40
49
  * }
41
50
  */
42
- declare function $fetch<TSchema extends StandardSchemaV1>(resource: string, schema: TSchema, options: ExtendedRequestInit<false>): Promise<StandardSchemaV1.Result<StandardSchemaV1.InferOutput<TSchema>>>;
43
- declare function $fetch<TSchema extends StandardSchemaV1>(resource: string, schema: TSchema, options?: ExtendedRequestInit<true | undefined>): Promise<StandardSchemaV1.InferOutput<TSchema>>;
44
- declare function $fetch(resource: string, options?: ExtendedRequestInit): Promise<Response>;
51
+ declare function $fetch<TSchema extends StandardSchemaV1>(input: FetchInput, schema: TSchema, options: ExtendedRequestInit & {
52
+ throwOnValidationError: false;
53
+ }): Promise<StandardSchemaV1.Result<StandardSchemaV1.InferOutput<TSchema>>>;
54
+ declare function $fetch<TSchema extends StandardSchemaV1>(input: FetchInput, schema: TSchema, options?: ExtendedRequestInit & {
55
+ throwOnValidationError?: true;
56
+ }): Promise<StandardSchemaV1.InferOutput<TSchema>>;
57
+ declare function $fetch(input: FetchInput, options?: ExtendedRequestInit): Promise<Response>;
45
58
  /**
46
59
  * Convenience methods for common HTTP verbs.
47
60
  *
48
61
  * These methods always require a schema for validation.
49
62
  * For raw responses without validation, use `$fetch` directly.
50
63
  *
64
+ * Each method has the same throw behavior as {@link $fetch}.
65
+ *
51
66
  * @example
52
67
  * import { z } from "zod";
53
68
  * import { api } from "@zap-studio/fetch";
@@ -70,6 +85,9 @@ declare const api: ApiMethods;
70
85
  * Use this factory to create API clients with a base URL, default headers,
71
86
  * and other shared configuration. Each instance is independent.
72
87
  *
88
+ * The returned `$fetch` and `api` methods have the same throw behavior as the
89
+ * top-level {@link $fetch} export.
90
+ *
73
91
  * @example
74
92
  * import { z } from "zod";
75
93
  * import { createFetch } from "@zap-studio/fetch";
@@ -86,9 +104,9 @@ declare const api: ApiMethods;
86
104
  * const user = await api.get("/users/1", UserSchema);
87
105
  *
88
106
  * // Or use $fetch directly
89
- * const response = await $fetch("/users", UserSchema, { method: "POST", body: { name: "John" } });
107
+ * const response = await $fetch("/users", UserSchema, { method: "POST", json: { name: "John" } });
90
108
  */
91
- declare function createFetch(factoryOptions?: CreateFetchOptions): {
109
+ declare function createFetch(factoryOptions?: Partial<FetchDefaults>): {
92
110
  $fetch: $Fetch;
93
111
  api: ApiMethods;
94
112
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":["api: ApiMethods"],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;AAgDA;;;;;;;;;AAMA;;;;;;;;AAMA;;;;;AAsCA;AAgCA;;;;;;;;;;;iBAlFsB,uBAAuB,4CAEnC,kBACC,6BACR,QAAQ,gBAAA,CAAiB,OAAO,gBAAA,CAAiB,YAAY;iBAE1C,uBAAuB,4CAEnC,mBACE,wCACT,QAAQ,gBAAA,CAAiB,YAAY;iBAElB,MAAA,6BAEV,sBACT,QAAQ;;;;;;;;;;;;;;;;;;;;;;cAmCEA,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;iBAgCF,WAAA,kBAA4B;UAClC;OACH"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA4EA;;;;;;;;;;;;;;;;;;;;;;;;iBANsB,MAAA,iBAAuB,gBAAA,CAAA,CAC3C,KAAA,EAAO,UAAA,EACP,MAAA,EAAQ,OAAA,EACR,OAAA,EAAS,mBAAA;EAAwB,sBAAA;AAAA,IAChC,OAAA,CAAQ,gBAAA,CAAiB,MAAA,CAAO,gBAAA,CAAiB,WAAA,CAAY,OAAA;AAAA,iBAE1C,MAAA,iBAAuB,gBAAA,CAAA,CAC3C,KAAA,EAAO,UAAA,EACP,MAAA,EAAQ,OAAA,EACR,OAAA,GAAU,mBAAA;EAAwB,sBAAA;AAAA,IACjC,OAAA,CAAQ,gBAAA,CAAiB,WAAA,CAAY,OAAA;AAAA,iBAElB,MAAA,CAAO,KAAA,EAAO,UAAA,EAAY,OAAA,GAAU,mBAAA,GAAsB,OAAA,CAAQ,QAAA;;;;;;;;;;;;;;AAqCxF;;;;;AAmCA;;;;;cAnCa,GAAA,EAAK,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmCF,WAAA,CAAY,cAAA,GAAgB,OAAA,CAAQ,aAAA;EAClD,MAAA,EAAQ,MAAA;EACR,GAAA,EAAK,UAAA;AAAA"}
package/dist/index.mjs CHANGED
@@ -1,11 +1,21 @@
1
1
  import { GLOBAL_DEFAULTS } from "./constants.mjs";
2
- import { createMethod, fetchInternal } from "./utils.mjs";
2
+ import { fetchInternal } from "./internal.mjs";
3
+ import { createMethod } from "./methods.mjs";
3
4
  import { isStandardSchema } from "@zap-studio/validation";
4
-
5
5
  //#region src/index.ts
6
- async function $fetch(resource, schemaOrOptions, optionsOrUndefined) {
6
+ /**
7
+ * Public entrypoint for the fetch package.
8
+ *
9
+ * Exposes:
10
+ * - `$fetch` low-level typed fetch function
11
+ * - `api` method shortcuts
12
+ * - `createFetch` instance factory
13
+ *
14
+ * @module
15
+ */
16
+ async function $fetch(input, schemaOrOptions, optionsOrUndefined) {
7
17
  const [schema, options] = isStandardSchema(schemaOrOptions) ? [schemaOrOptions, optionsOrUndefined] : [void 0, schemaOrOptions];
8
- return await fetchInternal(resource, schema, options, GLOBAL_DEFAULTS);
18
+ return await fetchInternal(input, schema, options, GLOBAL_DEFAULTS);
9
19
  }
10
20
  /**
11
21
  * Convenience methods for common HTTP verbs.
@@ -13,6 +23,8 @@ async function $fetch(resource, schemaOrOptions, optionsOrUndefined) {
13
23
  * These methods always require a schema for validation.
14
24
  * For raw responses without validation, use `$fetch` directly.
15
25
  *
26
+ * Each method has the same throw behavior as {@link $fetch}.
27
+ *
16
28
  * @example
17
29
  * import { z } from "zod";
18
30
  * import { api } from "@zap-studio/fetch";
@@ -41,6 +53,9 @@ const api = {
41
53
  * Use this factory to create API clients with a base URL, default headers,
42
54
  * and other shared configuration. Each instance is independent.
43
55
  *
56
+ * The returned `$fetch` and `api` methods have the same throw behavior as the
57
+ * top-level {@link $fetch} export.
58
+ *
44
59
  * @example
45
60
  * import { z } from "zod";
46
61
  * import { createFetch } from "@zap-studio/fetch";
@@ -57,19 +72,19 @@ const api = {
57
72
  * const user = await api.get("/users/1", UserSchema);
58
73
  *
59
74
  * // Or use $fetch directly
60
- * const response = await $fetch("/users", UserSchema, { method: "POST", body: { name: "John" } });
75
+ * const response = await $fetch("/users", UserSchema, { method: "POST", json: { name: "John" } });
61
76
  */
62
77
  function createFetch(factoryOptions = {}) {
63
78
  const defaults = {
64
79
  baseURL: factoryOptions.baseURL ?? "",
65
- headers: factoryOptions.headers,
66
- searchParams: factoryOptions.searchParams,
67
80
  throwOnFetchError: factoryOptions.throwOnFetchError ?? true,
68
81
  throwOnValidationError: factoryOptions.throwOnValidationError ?? true
69
82
  };
70
- async function customFetch(resource, schemaOrOptions, optionsOrUndefined) {
83
+ if (factoryOptions.headers !== void 0) defaults.headers = factoryOptions.headers;
84
+ if (factoryOptions.searchParams !== void 0) defaults.searchParams = factoryOptions.searchParams;
85
+ async function customFetch(input, schemaOrOptions, optionsOrUndefined) {
71
86
  const [schema, options] = isStandardSchema(schemaOrOptions) ? [schemaOrOptions, optionsOrUndefined] : [void 0, schemaOrOptions];
72
- return await fetchInternal(resource, schema, options, defaults);
87
+ return await fetchInternal(input, schema, options, defaults);
73
88
  }
74
89
  return {
75
90
  $fetch: customFetch,
@@ -82,7 +97,7 @@ function createFetch(factoryOptions = {}) {
82
97
  }
83
98
  };
84
99
  }
85
-
86
100
  //#endregion
87
101
  export { $fetch, api, createFetch };
102
+
88
103
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["api: ApiMethods","defaults: FetchDefaults"],"sources":["../src/index.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { isStandardSchema } from \"@zap-studio/validation\";\nimport { GLOBAL_DEFAULTS } from \"./constants\";\nimport type {\n $Fetch,\n ApiMethods,\n CreateFetchOptions,\n ExtendedRequestInit,\n FetchDefaults,\n} from \"./types\";\nimport { createMethod, fetchInternal } from \"./utils\";\n\n/**\n * Type-safe fetch wrapper with Standard Schema validation.\n *\n * - When `throwOnValidationError: true`: validated data of type `TSchema`\n * - When `throwOnValidationError: false`: Standard Schema Result object `{ value?, issues? }`\n * - When `throwOnFetchError: true`: throws `FetchError` on non-ok responses\n *\n * If no schema is provided, returns the raw `Response` object.\n *\n * @throws {FetchError} When `throwOnFetchError: true` and response is not ok\n * @throws {ValidationError} When `throwOnValidationError: true` and validation fails\n *\n * @example\n * import { z } from \"zod\";\n * import { $fetch } from \"@zap-studio/fetch\";\n *\n * const UserSchema = z.object({ id: z.number(), name: z.string() });\n *\n * // Basic usage (schema validation)\n * const user = await $fetch(\"/api/users/1\", UserSchema, { headers: { \"Authorization\": \"Bearer token\" } });\n * console.log(\"Validated user:\", user);\n *\n * // Raw usage (no schema validation and typed Response object)\n * const result = await $fetch(\"/api/data\", { method: \"POST\", body: JSON.stringify({ key: \"value\" }) });\n * const json = await result.json() as ResultType;\n * console.log(\"Raw response data:\", json);\n *\n * // Usage with validation errors returned instead of thrown\n * const result = await $fetch(\"/api/users/1\", UserSchema, { throwOnValidationError: false });\n *\n * if (result.issues) {\n * console.error(\"Validation errors:\", result.issues);\n * } else {\n * console.log(\"Validated user:\", result.value);\n * }\n */\nexport async function $fetch<TSchema extends StandardSchemaV1>(\n resource: string,\n schema: TSchema,\n options: ExtendedRequestInit<false>\n): Promise<StandardSchemaV1.Result<StandardSchemaV1.InferOutput<TSchema>>>;\n\nexport async function $fetch<TSchema extends StandardSchemaV1>(\n resource: string,\n schema: TSchema,\n options?: ExtendedRequestInit<true | undefined>\n): Promise<StandardSchemaV1.InferOutput<TSchema>>;\n\nexport async function $fetch(\n resource: string,\n options?: ExtendedRequestInit\n): Promise<Response>;\n\nexport async function $fetch(\n resource: string,\n schemaOrOptions?: StandardSchemaV1 | ExtendedRequestInit,\n optionsOrUndefined?: ExtendedRequestInit\n): Promise<unknown> {\n const [schema, options] = isStandardSchema(schemaOrOptions)\n ? [schemaOrOptions, optionsOrUndefined]\n : [undefined, schemaOrOptions];\n\n return await fetchInternal(resource, schema, options, GLOBAL_DEFAULTS);\n}\n\n/**\n * Convenience methods for common HTTP verbs.\n *\n * These methods always require a schema for validation.\n * For raw responses without validation, use `$fetch` directly.\n *\n * @example\n * import { z } from \"zod\";\n * import { api } from \"@zap-studio/fetch\";\n *\n * const PostSchema = z.object({\n * id: z.number(),\n * title: z.string(),\n * content: z.string(),\n * });\n *\n * async function fetchPost(postId: number) {\n * const post = await api.get(`https://api.example.com/posts/${postId}`, PostSchema);\n * return post; // post is typed as { id: number; title: string; content: string; }\n * }\n */\nexport const api: ApiMethods = {\n get: createMethod($fetch, \"GET\"),\n post: createMethod($fetch, \"POST\"),\n put: createMethod($fetch, \"PUT\"),\n patch: createMethod($fetch, \"PATCH\"),\n delete: createMethod($fetch, \"DELETE\"),\n};\n\n/**\n * Creates a custom fetch instance with pre-configured defaults.\n *\n * Use this factory to create API clients with a base URL, default headers,\n * and other shared configuration. Each instance is independent.\n *\n * @example\n * import { z } from \"zod\";\n * import { createFetch } from \"@zap-studio/fetch\";\n *\n * // Create a configured instance\n * const { $fetch, api } = createFetch({\n * baseURL: \"https://api.example.com\",\n * headers: { \"Authorization\": \"Bearer token\" },\n * });\n *\n * const UserSchema = z.object({ id: z.number(), name: z.string() });\n *\n * // Now use relative paths - baseURL is prepended automatically\n * const user = await api.get(\"/users/1\", UserSchema);\n *\n * // Or use $fetch directly\n * const response = await $fetch(\"/users\", UserSchema, { method: \"POST\", body: { name: \"John\" } });\n */\nexport function createFetch(factoryOptions: CreateFetchOptions = {}): {\n $fetch: $Fetch;\n api: ApiMethods;\n} {\n const defaults: FetchDefaults = {\n baseURL: factoryOptions.baseURL ?? \"\",\n headers: factoryOptions.headers,\n searchParams: factoryOptions.searchParams,\n throwOnFetchError: factoryOptions.throwOnFetchError ?? true,\n throwOnValidationError: factoryOptions.throwOnValidationError ?? true,\n };\n\n async function customFetch<TSchema extends StandardSchemaV1>(\n resource: string,\n schema: TSchema,\n options: ExtendedRequestInit<false>\n ): Promise<StandardSchemaV1.Result<StandardSchemaV1.InferOutput<TSchema>>>;\n\n async function customFetch<TSchema extends StandardSchemaV1>(\n resource: string,\n schema: TSchema,\n options?: ExtendedRequestInit<true | undefined>\n ): Promise<StandardSchemaV1.InferOutput<TSchema>>;\n\n async function customFetch(\n resource: string,\n options?: ExtendedRequestInit\n ): Promise<Response>;\n\n async function customFetch(\n resource: string,\n schemaOrOptions?: StandardSchemaV1 | ExtendedRequestInit,\n optionsOrUndefined?: ExtendedRequestInit\n ): Promise<unknown> {\n const [schema, options] = isStandardSchema(schemaOrOptions)\n ? [schemaOrOptions, optionsOrUndefined]\n : [undefined, schemaOrOptions];\n\n return await fetchInternal(resource, schema, options, defaults);\n }\n\n const customApi = {\n get: createMethod(customFetch, \"GET\"),\n post: createMethod(customFetch, \"POST\"),\n put: createMethod(customFetch, \"PUT\"),\n patch: createMethod(customFetch, \"PATCH\"),\n delete: createMethod(customFetch, \"DELETE\"),\n };\n\n return {\n $fetch: customFetch,\n api: customApi,\n };\n}\n"],"mappings":";;;;;AAiEA,eAAsB,OACpB,UACA,iBACA,oBACkB;CAClB,MAAM,CAAC,QAAQ,WAAW,iBAAiB,gBAAgB,GACvD,CAAC,iBAAiB,mBAAmB,GACrC,CAAC,QAAW,gBAAgB;AAEhC,QAAO,MAAM,cAAc,UAAU,QAAQ,SAAS,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;AAwBxE,MAAaA,MAAkB;CAC7B,KAAK,aAAa,QAAQ,MAAM;CAChC,MAAM,aAAa,QAAQ,OAAO;CAClC,KAAK,aAAa,QAAQ,MAAM;CAChC,OAAO,aAAa,QAAQ,QAAQ;CACpC,QAAQ,aAAa,QAAQ,SAAS;CACvC;;;;;;;;;;;;;;;;;;;;;;;;;AA0BD,SAAgB,YAAY,iBAAqC,EAAE,EAGjE;CACA,MAAMC,WAA0B;EAC9B,SAAS,eAAe,WAAW;EACnC,SAAS,eAAe;EACxB,cAAc,eAAe;EAC7B,mBAAmB,eAAe,qBAAqB;EACvD,wBAAwB,eAAe,0BAA0B;EAClE;CAmBD,eAAe,YACb,UACA,iBACA,oBACkB;EAClB,MAAM,CAAC,QAAQ,WAAW,iBAAiB,gBAAgB,GACvD,CAAC,iBAAiB,mBAAmB,GACrC,CAAC,QAAW,gBAAgB;AAEhC,SAAO,MAAM,cAAc,UAAU,QAAQ,SAAS,SAAS;;AAWjE,QAAO;EACL,QAAQ;EACR,KAVgB;GAChB,KAAK,aAAa,aAAa,MAAM;GACrC,MAAM,aAAa,aAAa,OAAO;GACvC,KAAK,aAAa,aAAa,MAAM;GACrC,OAAO,aAAa,aAAa,QAAQ;GACzC,QAAQ,aAAa,aAAa,SAAS;GAC5C;EAKA"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * Public entrypoint for the fetch package.\n *\n * Exposes:\n * - `$fetch` low-level typed fetch function\n * - `api` method shortcuts\n * - `createFetch` instance factory\n *\n * @module\n */\n\nimport { isStandardSchema, type StandardSchemaV1 } from \"@zap-studio/validation\";\n\nimport { GLOBAL_DEFAULTS } from \"./constants.js\";\nimport { fetchInternal } from \"./internal.js\";\nimport { createMethod } from \"./methods.js\";\nimport type {\n $Fetch,\n ApiMethods,\n ExtendedRequestInit,\n FetchDefaults,\n FetchInput,\n} from \"./types.js\";\n\n/**\n * Type-safe fetch wrapper with Standard Schema validation.\n *\n * - When `throwOnValidationError: true`: validated data of type `TSchema`\n * - When `throwOnValidationError: false`: Standard Schema Result object `{ value?, issues? }`\n * - When `throwOnFetchError: true`: throws `FetchError` on non-ok responses\n *\n * If no schema is provided, returns the raw `Response` object.\n *\n * @throws {FetchError} When `throwOnFetchError` is `true` and the response is not ok.\n * @throws {ValidationError} When a schema is provided, validation returns issues, and\n * `throwOnValidationError` is `true`.\n * @throws {TypeError} When both `body` and `json` are provided, when JSON request\n * serialization fails, when request construction fails, when headers/search params are\n * invalid, when `response.json()` cannot read the body, or when the runtime `fetch`\n * implementation rejects network-level failures as `TypeError`.\n * @throws {DOMException} When the runtime rejects an aborted request or response body read\n * as an `AbortError` DOMException.\n * @throws {SyntaxError} When a schema is provided and `response.json()` cannot parse the\n * response body.\n * @throws Any error thrown or rejected by the provided Standard Schema validator.\n *\n * @example\n * import { z } from \"zod\";\n * import { $fetch } from \"@zap-studio/fetch\";\n *\n * const UserSchema = z.object({ id: z.number(), name: z.string() });\n *\n * // Basic usage (schema validation)\n * const user = await $fetch(\"/api/users/1\", UserSchema, { headers: { \"Authorization\": \"Bearer token\" } });\n * console.log(\"Validated user:\", user);\n *\n * // Raw usage (no schema validation and typed Response object)\n * const result = await $fetch(\"/api/data\", { method: \"POST\", body: JSON.stringify({ key: \"value\" }) });\n * const json = await result.json() as ResultType;\n * console.log(\"Raw response data:\", json);\n *\n * // Usage with validation errors returned instead of thrown\n * const result = await $fetch(\"/api/users/1\", UserSchema, { throwOnValidationError: false });\n *\n * if (result.issues) {\n * console.error(\"Validation errors:\", result.issues);\n * } else {\n * console.log(\"Validated user:\", result.value);\n * }\n */\nexport async function $fetch<TSchema extends StandardSchemaV1>(\n input: FetchInput,\n schema: TSchema,\n options: ExtendedRequestInit & { throwOnValidationError: false },\n): Promise<StandardSchemaV1.Result<StandardSchemaV1.InferOutput<TSchema>>>;\n\nexport async function $fetch<TSchema extends StandardSchemaV1>(\n input: FetchInput,\n schema: TSchema,\n options?: ExtendedRequestInit & { throwOnValidationError?: true },\n): Promise<StandardSchemaV1.InferOutput<TSchema>>;\n\nexport async function $fetch(input: FetchInput, options?: ExtendedRequestInit): Promise<Response>;\n\nexport async function $fetch(\n input: FetchInput,\n schemaOrOptions?: StandardSchemaV1 | ExtendedRequestInit,\n optionsOrUndefined?: ExtendedRequestInit,\n): Promise<unknown> {\n const [schema, options] = isStandardSchema(schemaOrOptions)\n ? [schemaOrOptions, optionsOrUndefined]\n : [undefined, schemaOrOptions];\n\n return await fetchInternal(input, schema, options, GLOBAL_DEFAULTS);\n}\n\n/**\n * Convenience methods for common HTTP verbs.\n *\n * These methods always require a schema for validation.\n * For raw responses without validation, use `$fetch` directly.\n *\n * Each method has the same throw behavior as {@link $fetch}.\n *\n * @example\n * import { z } from \"zod\";\n * import { api } from \"@zap-studio/fetch\";\n *\n * const PostSchema = z.object({\n * id: z.number(),\n * title: z.string(),\n * content: z.string(),\n * });\n *\n * async function fetchPost(postId: number) {\n * const post = await api.get(`https://api.example.com/posts/${postId}`, PostSchema);\n * return post; // post is typed as { id: number; title: string; content: string; }\n * }\n */\nexport const api: ApiMethods = {\n get: createMethod($fetch, \"GET\"),\n post: createMethod($fetch, \"POST\"),\n put: createMethod($fetch, \"PUT\"),\n patch: createMethod($fetch, \"PATCH\"),\n delete: createMethod($fetch, \"DELETE\"),\n};\n\n/**\n * Creates a custom fetch instance with pre-configured defaults.\n *\n * Use this factory to create API clients with a base URL, default headers,\n * and other shared configuration. Each instance is independent.\n *\n * The returned `$fetch` and `api` methods have the same throw behavior as the\n * top-level {@link $fetch} export.\n *\n * @example\n * import { z } from \"zod\";\n * import { createFetch } from \"@zap-studio/fetch\";\n *\n * // Create a configured instance\n * const { $fetch, api } = createFetch({\n * baseURL: \"https://api.example.com\",\n * headers: { \"Authorization\": \"Bearer token\" },\n * });\n *\n * const UserSchema = z.object({ id: z.number(), name: z.string() });\n *\n * // Now use relative paths - baseURL is prepended automatically\n * const user = await api.get(\"/users/1\", UserSchema);\n *\n * // Or use $fetch directly\n * const response = await $fetch(\"/users\", UserSchema, { method: \"POST\", json: { name: \"John\" } });\n */\nexport function createFetch(factoryOptions: Partial<FetchDefaults> = {}): {\n $fetch: $Fetch;\n api: ApiMethods;\n} {\n const defaults: FetchDefaults = {\n baseURL: factoryOptions.baseURL ?? \"\",\n throwOnFetchError: factoryOptions.throwOnFetchError ?? true,\n throwOnValidationError: factoryOptions.throwOnValidationError ?? true,\n };\n\n if (factoryOptions.headers !== undefined) {\n defaults.headers = factoryOptions.headers;\n }\n\n if (factoryOptions.searchParams !== undefined) {\n defaults.searchParams = factoryOptions.searchParams;\n }\n\n async function customFetch<TSchema extends StandardSchemaV1>(\n input: FetchInput,\n schema: TSchema,\n options: ExtendedRequestInit & { throwOnValidationError: false },\n ): Promise<StandardSchemaV1.Result<StandardSchemaV1.InferOutput<TSchema>>>;\n\n async function customFetch<TSchema extends StandardSchemaV1>(\n input: FetchInput,\n schema: TSchema,\n options?: ExtendedRequestInit & {\n throwOnValidationError?: true;\n },\n ): Promise<StandardSchemaV1.InferOutput<TSchema>>;\n\n async function customFetch(input: FetchInput, options?: ExtendedRequestInit): Promise<Response>;\n\n async function customFetch(\n input: FetchInput,\n schemaOrOptions?: StandardSchemaV1 | ExtendedRequestInit,\n optionsOrUndefined?: ExtendedRequestInit,\n ): Promise<unknown> {\n const [schema, options] = isStandardSchema(schemaOrOptions)\n ? [schemaOrOptions, optionsOrUndefined]\n : [undefined, schemaOrOptions];\n\n return await fetchInternal(input, schema, options, defaults);\n }\n\n const customApi = {\n get: createMethod(customFetch, \"GET\"),\n post: createMethod(customFetch, \"POST\"),\n put: createMethod(customFetch, \"PUT\"),\n patch: createMethod(customFetch, \"PATCH\"),\n delete: createMethod(customFetch, \"DELETE\"),\n };\n\n return {\n $fetch: customFetch,\n api: customApi,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;AAoFA,eAAsB,OACpB,OACA,iBACA,oBACkB;CAClB,MAAM,CAAC,QAAQ,WAAW,iBAAiB,gBAAgB,GACvD,CAAC,iBAAiB,mBAAmB,GACrC,CAAC,KAAA,GAAW,gBAAgB;AAEhC,QAAO,MAAM,cAAc,OAAO,QAAQ,SAAS,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;AA0BrE,MAAa,MAAkB;CAC7B,KAAK,aAAa,QAAQ,MAAM;CAChC,MAAM,aAAa,QAAQ,OAAO;CAClC,KAAK,aAAa,QAAQ,MAAM;CAChC,OAAO,aAAa,QAAQ,QAAQ;CACpC,QAAQ,aAAa,QAAQ,SAAS;CACvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BD,SAAgB,YAAY,iBAAyC,EAAE,EAGrE;CACA,MAAM,WAA0B;EAC9B,SAAS,eAAe,WAAW;EACnC,mBAAmB,eAAe,qBAAqB;EACvD,wBAAwB,eAAe,0BAA0B;EAClE;AAED,KAAI,eAAe,YAAY,KAAA,EAC7B,UAAS,UAAU,eAAe;AAGpC,KAAI,eAAe,iBAAiB,KAAA,EAClC,UAAS,eAAe,eAAe;CAmBzC,eAAe,YACb,OACA,iBACA,oBACkB;EAClB,MAAM,CAAC,QAAQ,WAAW,iBAAiB,gBAAgB,GACvD,CAAC,iBAAiB,mBAAmB,GACrC,CAAC,KAAA,GAAW,gBAAgB;AAEhC,SAAO,MAAM,cAAc,OAAO,QAAQ,SAAS,SAAS;;AAW9D,QAAO;EACL,QAAQ;EACR,KAVgB;GAChB,KAAK,aAAa,aAAa,MAAM;GACrC,MAAM,aAAa,aAAa,OAAO;GACvC,KAAK,aAAa,aAAa,MAAM;GACrC,OAAO,aAAa,aAAa,QAAQ;GACzC,QAAQ,aAAa,aAAa,SAAS;GAC5C;EAKA"}
@@ -0,0 +1,33 @@
1
+ import { ExtendedRequestInit, FetchDefaults, FetchInput } from "./types.mjs";
2
+ import { StandardSchemaV1 } from "@zap-studio/validation";
3
+
4
+ //#region src/internal.d.ts
5
+ /**
6
+ * Internal fetch implementation used by both $fetch and createFetch.
7
+ *
8
+ * This function normalizes request input, resolves final URL + query params,
9
+ * executes `fetch`, optionally throws `FetchError`, and optionally validates
10
+ * JSON response payloads using Standard Schema.
11
+ *
12
+ * @param input - Request URL, path, or Request object.
13
+ * @param schema - Optional Standard Schema for response validation.
14
+ * @param options - Optional request options and package-specific flags.
15
+ * @param defaults - Effective client defaults.
16
+ * @returns Raw `Response` when no schema is provided; otherwise validated output.
17
+ * @throws {FetchError} When `throwOnFetchError` is `true` and the response is not ok.
18
+ * @throws {ValidationError} When a schema is provided, validation returns issues, and
19
+ * `throwOnValidationError` is `true`.
20
+ * @throws {TypeError} When both `body` and `json` are provided, when JSON request
21
+ * serialization fails, when request construction fails, when headers/search params are
22
+ * invalid, when `response.json()` cannot read the body, or when the runtime `fetch`
23
+ * implementation rejects network-level failures as `TypeError`.
24
+ * @throws {DOMException} When the runtime rejects an aborted request or response body read
25
+ * as an `AbortError` DOMException.
26
+ * @throws {SyntaxError} When a schema is provided and `response.json()` cannot parse the
27
+ * response body.
28
+ * @throws Any error thrown or rejected by the provided Standard Schema validator.
29
+ */
30
+ declare function fetchInternal(input: FetchInput, schema: StandardSchemaV1 | undefined, options: ExtendedRequestInit | undefined, defaults: FetchDefaults): Promise<unknown>;
31
+ //#endregion
32
+ export { fetchInternal };
33
+ //# sourceMappingURL=internal.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.d.mts","names":[],"sources":["../src/internal.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwCsB,aAAA,CACpB,KAAA,EAAO,UAAA,EACP,MAAA,EAAQ,gBAAA,cACR,OAAA,EAAS,mBAAA,cACT,QAAA,EAAU,aAAA,GACT,OAAA"}
@@ -0,0 +1,73 @@
1
+ import { FetchError } from "./errors.mjs";
2
+ import { mergeHeaders } from "./headers.mjs";
3
+ import { normalizeRequest } from "./request.mjs";
4
+ import { resolveRequestUrl } from "./url.mjs";
5
+ import { standardValidate } from "@zap-studio/validation";
6
+ //#region src/internal.ts
7
+ /**
8
+ * Internal fetch implementation used by both $fetch and createFetch.
9
+ *
10
+ * This function normalizes request input, resolves final URL + query params,
11
+ * executes `fetch`, optionally throws `FetchError`, and optionally validates
12
+ * JSON response payloads using Standard Schema.
13
+ *
14
+ * @param input - Request URL, path, or Request object.
15
+ * @param schema - Optional Standard Schema for response validation.
16
+ * @param options - Optional request options and package-specific flags.
17
+ * @param defaults - Effective client defaults.
18
+ * @returns Raw `Response` when no schema is provided; otherwise validated output.
19
+ * @throws {FetchError} When `throwOnFetchError` is `true` and the response is not ok.
20
+ * @throws {ValidationError} When a schema is provided, validation returns issues, and
21
+ * `throwOnValidationError` is `true`.
22
+ * @throws {TypeError} When both `body` and `json` are provided, when JSON request
23
+ * serialization fails, when request construction fails, when headers/search params are
24
+ * invalid, when `response.json()` cannot read the body, or when the runtime `fetch`
25
+ * implementation rejects network-level failures as `TypeError`.
26
+ * @throws {DOMException} When the runtime rejects an aborted request or response body read
27
+ * as an `AbortError` DOMException.
28
+ * @throws {SyntaxError} When a schema is provided and `response.json()` cannot parse the
29
+ * response body.
30
+ * @throws Any error thrown or rejected by the provided Standard Schema validator.
31
+ */
32
+ async function fetchInternal(input, schema, options, defaults) {
33
+ const request = normalizeRequest(input, options);
34
+ const { init, searchParams, throwOnFetchError, throwOnValidationError } = prepareRequestInit(request.options, defaults);
35
+ const url = resolveRequestUrl(request.url, defaults, searchParams);
36
+ const response = request.request ? await fetch(new Request(url, request.request), init) : await fetch(url, init);
37
+ if (throwOnFetchError && !response.ok) throw new FetchError(`HTTP ${response.status}: ${response.statusText}`, response);
38
+ if (!schema) return response;
39
+ const raw = await response.json();
40
+ if (throwOnValidationError) return standardValidate(schema, raw, { throwOnError: true });
41
+ return standardValidate(schema, raw, { throwOnError: false });
42
+ }
43
+ /**
44
+ * Normalizes request-level options into a final RequestInit payload and runtime flags.
45
+ *
46
+ * @param options - Request-level options.
47
+ * @param defaults - Client-level defaults.
48
+ * @returns Fully merged request init payload and effective runtime flags.
49
+ */
50
+ function prepareRequestInit(options, defaults) {
51
+ const { headers, json, searchParams, throwOnFetchError = defaults.throwOnFetchError, throwOnValidationError = defaults.throwOnValidationError, ...rest } = options;
52
+ const init = {
53
+ ...rest,
54
+ headers: mergeHeaders(defaults.headers, headers)
55
+ };
56
+ if (json !== void 0) {
57
+ if (init.body != null) throw new TypeError("Cannot provide both `body` and `json`.");
58
+ init.body = JSON.stringify(json);
59
+ const headers = new Headers(init.headers);
60
+ if (!headers.has("Content-Type")) headers.set("Content-Type", "application/json");
61
+ init.headers = headers;
62
+ }
63
+ return {
64
+ init,
65
+ searchParams,
66
+ throwOnFetchError,
67
+ throwOnValidationError
68
+ };
69
+ }
70
+ //#endregion
71
+ export { fetchInternal };
72
+
73
+ //# sourceMappingURL=internal.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.mjs","names":[],"sources":["../src/internal.ts"],"sourcesContent":["/**\n * Internal request execution and option preparation utilities.\n *\n * @module\n */\n\nimport type { StandardSchemaV1 } from \"@zap-studio/validation\";\nimport { standardValidate } from \"@zap-studio/validation\";\n\nimport { FetchError } from \"./errors.js\";\nimport { mergeHeaders } from \"./headers.js\";\nimport { normalizeRequest } from \"./request.js\";\nimport type { ExtendedRequestInit, FetchDefaults, FetchInput } from \"./types.js\";\nimport { resolveRequestUrl } from \"./url.js\";\n\n/**\n * Internal fetch implementation used by both $fetch and createFetch.\n *\n * This function normalizes request input, resolves final URL + query params,\n * executes `fetch`, optionally throws `FetchError`, and optionally validates\n * JSON response payloads using Standard Schema.\n *\n * @param input - Request URL, path, or Request object.\n * @param schema - Optional Standard Schema for response validation.\n * @param options - Optional request options and package-specific flags.\n * @param defaults - Effective client defaults.\n * @returns Raw `Response` when no schema is provided; otherwise validated output.\n * @throws {FetchError} When `throwOnFetchError` is `true` and the response is not ok.\n * @throws {ValidationError} When a schema is provided, validation returns issues, and\n * `throwOnValidationError` is `true`.\n * @throws {TypeError} When both `body` and `json` are provided, when JSON request\n * serialization fails, when request construction fails, when headers/search params are\n * invalid, when `response.json()` cannot read the body, or when the runtime `fetch`\n * implementation rejects network-level failures as `TypeError`.\n * @throws {DOMException} When the runtime rejects an aborted request or response body read\n * as an `AbortError` DOMException.\n * @throws {SyntaxError} When a schema is provided and `response.json()` cannot parse the\n * response body.\n * @throws Any error thrown or rejected by the provided Standard Schema validator.\n */\nexport async function fetchInternal(\n input: FetchInput,\n schema: StandardSchemaV1 | undefined,\n options: ExtendedRequestInit | undefined,\n defaults: FetchDefaults,\n): Promise<unknown> {\n const request = normalizeRequest(input, options);\n const { init, searchParams, throwOnFetchError, throwOnValidationError } = prepareRequestInit(\n request.options,\n defaults,\n );\n const url = resolveRequestUrl(request.url, defaults, searchParams);\n const response = request.request\n ? await fetch(new Request(url, request.request), init)\n : await fetch(url, init);\n\n if (throwOnFetchError && !response.ok) {\n throw new FetchError(`HTTP ${response.status}: ${response.statusText}`, response);\n }\n\n if (!schema) {\n return response;\n }\n\n const raw = await response.json();\n if (throwOnValidationError) {\n return standardValidate(schema, raw, { throwOnError: true });\n }\n return standardValidate(schema, raw, { throwOnError: false });\n}\n\n/**\n * Normalizes request-level options into a final RequestInit payload and runtime flags.\n *\n * @param options - Request-level options.\n * @param defaults - Client-level defaults.\n * @returns Fully merged request init payload and effective runtime flags.\n */\nfunction prepareRequestInit(\n options: ExtendedRequestInit,\n defaults: FetchDefaults,\n): {\n init: RequestInit;\n searchParams: ExtendedRequestInit[\"searchParams\"] | undefined;\n throwOnFetchError: boolean;\n throwOnValidationError: boolean;\n} {\n const {\n headers,\n json,\n searchParams,\n throwOnFetchError = defaults.throwOnFetchError,\n throwOnValidationError = defaults.throwOnValidationError,\n ...rest\n } = options;\n\n const init = {\n ...rest,\n headers: mergeHeaders(defaults.headers, headers),\n } as RequestInit;\n\n if (json !== undefined) {\n if (init.body != null) {\n throw new TypeError(\"Cannot provide both `body` and `json`.\");\n }\n\n init.body = JSON.stringify(json);\n const headers = new Headers(init.headers);\n if (!headers.has(\"Content-Type\")) {\n headers.set(\"Content-Type\", \"application/json\");\n }\n init.headers = headers;\n }\n\n return {\n init,\n searchParams,\n throwOnFetchError,\n throwOnValidationError,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,eAAsB,cACpB,OACA,QACA,SACA,UACkB;CAClB,MAAM,UAAU,iBAAiB,OAAO,QAAQ;CAChD,MAAM,EAAE,MAAM,cAAc,mBAAmB,2BAA2B,mBACxE,QAAQ,SACR,SACD;CACD,MAAM,MAAM,kBAAkB,QAAQ,KAAK,UAAU,aAAa;CAClE,MAAM,WAAW,QAAQ,UACrB,MAAM,MAAM,IAAI,QAAQ,KAAK,QAAQ,QAAQ,EAAE,KAAK,GACpD,MAAM,MAAM,KAAK,KAAK;AAE1B,KAAI,qBAAqB,CAAC,SAAS,GACjC,OAAM,IAAI,WAAW,QAAQ,SAAS,OAAO,IAAI,SAAS,cAAc,SAAS;AAGnF,KAAI,CAAC,OACH,QAAO;CAGT,MAAM,MAAM,MAAM,SAAS,MAAM;AACjC,KAAI,uBACF,QAAO,iBAAiB,QAAQ,KAAK,EAAE,cAAc,MAAM,CAAC;AAE9D,QAAO,iBAAiB,QAAQ,KAAK,EAAE,cAAc,OAAO,CAAC;;;;;;;;;AAU/D,SAAS,mBACP,SACA,UAMA;CACA,MAAM,EACJ,SACA,MACA,cACA,oBAAoB,SAAS,mBAC7B,yBAAyB,SAAS,wBAClC,GAAG,SACD;CAEJ,MAAM,OAAO;EACX,GAAG;EACH,SAAS,aAAa,SAAS,SAAS,QAAQ;EACjD;AAED,KAAI,SAAS,KAAA,GAAW;AACtB,MAAI,KAAK,QAAQ,KACf,OAAM,IAAI,UAAU,yCAAyC;AAG/D,OAAK,OAAO,KAAK,UAAU,KAAK;EAChC,MAAM,UAAU,IAAI,QAAQ,KAAK,QAAQ;AACzC,MAAI,CAAC,QAAQ,IAAI,eAAe,CAC9B,SAAQ,IAAI,gBAAgB,mBAAmB;AAEjD,OAAK,UAAU;;AAGjB,QAAO;EACL;EACA;EACA;EACA;EACD"}
@@ -0,0 +1,23 @@
1
+ import { $Fetch } from "./types.mjs";
2
+
3
+ //#region src/methods.d.ts
4
+ /**
5
+ * Creates an HTTP method helper bound to a fetch function.
6
+ *
7
+ * The returned function mirrors `$Fetch` overloads but forces the provided
8
+ * HTTP method (`GET`, `POST`, etc.) into request options.
9
+ *
10
+ * @param fetchFn - Fetch function to wrap.
11
+ * @param method - HTTP method to enforce.
12
+ * @returns Method-bound fetch function.
13
+ * @throws Any error thrown or rejected by `fetchFn` when the returned method-bound
14
+ * fetch function is called.
15
+ *
16
+ * @example
17
+ * const get = createMethod($fetch, "GET");
18
+ * const user = await get("/users/1", UserSchema);
19
+ */
20
+ declare function createMethod<TFetch extends $Fetch>(fetchFn: TFetch, method: string): $Fetch;
21
+ //#endregion
22
+ export { createMethod };
23
+ //# sourceMappingURL=methods.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"methods.d.mts","names":[],"sources":["../src/methods.ts"],"mappings":";;;;;AA0BA;;;;;;;;;;;;;;iBAAgB,YAAA,gBAA4B,MAAA,CAAA,CAAQ,OAAA,EAAS,MAAA,EAAQ,MAAA,WAAiB,MAAA"}
@@ -0,0 +1,58 @@
1
+ import { isStandardSchema } from "@zap-studio/validation";
2
+ //#region src/methods.ts
3
+ /**
4
+ * Method helper factories used to build verb-specific fetch functions.
5
+ *
6
+ * @module
7
+ */
8
+ /**
9
+ * Creates an HTTP method helper bound to a fetch function.
10
+ *
11
+ * The returned function mirrors `$Fetch` overloads but forces the provided
12
+ * HTTP method (`GET`, `POST`, etc.) into request options.
13
+ *
14
+ * @param fetchFn - Fetch function to wrap.
15
+ * @param method - HTTP method to enforce.
16
+ * @returns Method-bound fetch function.
17
+ * @throws Any error thrown or rejected by `fetchFn` when the returned method-bound
18
+ * fetch function is called.
19
+ *
20
+ * @example
21
+ * const get = createMethod($fetch, "GET");
22
+ * const user = await get("/users/1", UserSchema);
23
+ */
24
+ function createMethod(fetchFn, method) {
25
+ /**
26
+ * Method-bound `$Fetch` implementation.
27
+ *
28
+ * Resolves schema/option overloads and injects the configured HTTP method.
29
+ */
30
+ function methodFetch(input, schemaOrOptions, optionsOrUndefined) {
31
+ if (isStandardSchema(schemaOrOptions)) {
32
+ if (optionsOrUndefined?.throwOnValidationError === false) return fetchFn(input, schemaOrOptions, {
33
+ ...optionsOrUndefined,
34
+ method,
35
+ throwOnValidationError: false
36
+ });
37
+ const { throwOnValidationError, ...restOptions } = optionsOrUndefined ?? {};
38
+ if (throwOnValidationError === true) return fetchFn(input, schemaOrOptions, {
39
+ ...restOptions,
40
+ method,
41
+ throwOnValidationError: true
42
+ });
43
+ return fetchFn(input, schemaOrOptions, {
44
+ ...restOptions,
45
+ method
46
+ });
47
+ }
48
+ return fetchFn(input, {
49
+ ...schemaOrOptions,
50
+ method
51
+ });
52
+ }
53
+ return methodFetch;
54
+ }
55
+ //#endregion
56
+ export { createMethod };
57
+
58
+ //# sourceMappingURL=methods.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"methods.mjs","names":[],"sources":["../src/methods.ts"],"sourcesContent":["/**\n * Method helper factories used to build verb-specific fetch functions.\n *\n * @module\n */\n\nimport { isStandardSchema, type StandardSchemaV1 } from \"@zap-studio/validation\";\n\nimport type { $Fetch, ExtendedRequestInit, FetchInput } from \"./types.js\";\n\n/**\n * Creates an HTTP method helper bound to a fetch function.\n *\n * The returned function mirrors `$Fetch` overloads but forces the provided\n * HTTP method (`GET`, `POST`, etc.) into request options.\n *\n * @param fetchFn - Fetch function to wrap.\n * @param method - HTTP method to enforce.\n * @returns Method-bound fetch function.\n * @throws Any error thrown or rejected by `fetchFn` when the returned method-bound\n * fetch function is called.\n *\n * @example\n * const get = createMethod($fetch, \"GET\");\n * const user = await get(\"/users/1\", UserSchema);\n */\nexport function createMethod<TFetch extends $Fetch>(fetchFn: TFetch, method: string): $Fetch {\n function methodFetch<TSchema extends StandardSchemaV1>(\n input: FetchInput,\n schema: TSchema,\n options: ExtendedRequestInit & {\n throwOnValidationError: false;\n },\n ): Promise<StandardSchemaV1.Result<StandardSchemaV1.InferOutput<TSchema>>>;\n\n function methodFetch<TSchema extends StandardSchemaV1>(\n input: FetchInput,\n schema: TSchema,\n options?: ExtendedRequestInit & {\n throwOnValidationError?: true;\n },\n ): Promise<StandardSchemaV1.InferOutput<TSchema>>;\n\n function methodFetch(input: FetchInput, options?: ExtendedRequestInit): Promise<Response>;\n\n /**\n * Method-bound `$Fetch` implementation.\n *\n * Resolves schema/option overloads and injects the configured HTTP method.\n */\n function methodFetch(\n input: FetchInput,\n schemaOrOptions?: StandardSchemaV1 | ExtendedRequestInit,\n optionsOrUndefined?: ExtendedRequestInit,\n ): Promise<unknown> {\n if (isStandardSchema(schemaOrOptions)) {\n if (optionsOrUndefined?.throwOnValidationError === false) {\n return fetchFn(input, schemaOrOptions, {\n ...optionsOrUndefined,\n method,\n throwOnValidationError: false,\n });\n }\n\n const { throwOnValidationError, ...restOptions } = optionsOrUndefined ?? {};\n\n if (throwOnValidationError === true) {\n return fetchFn(input, schemaOrOptions, {\n ...restOptions,\n method,\n throwOnValidationError: true,\n });\n }\n\n return fetchFn(input, schemaOrOptions, {\n ...restOptions,\n method,\n });\n }\n\n return fetchFn(input, {\n ...schemaOrOptions,\n method,\n });\n }\n\n return methodFetch;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,aAAoC,SAAiB,QAAwB;;;;;;CAwB3F,SAAS,YACP,OACA,iBACA,oBACkB;AAClB,MAAI,iBAAiB,gBAAgB,EAAE;AACrC,OAAI,oBAAoB,2BAA2B,MACjD,QAAO,QAAQ,OAAO,iBAAiB;IACrC,GAAG;IACH;IACA,wBAAwB;IACzB,CAAC;GAGJ,MAAM,EAAE,wBAAwB,GAAG,gBAAgB,sBAAsB,EAAE;AAE3E,OAAI,2BAA2B,KAC7B,QAAO,QAAQ,OAAO,iBAAiB;IACrC,GAAG;IACH;IACA,wBAAwB;IACzB,CAAC;AAGJ,UAAO,QAAQ,OAAO,iBAAiB;IACrC,GAAG;IACH;IACD,CAAC;;AAGJ,SAAO,QAAQ,OAAO;GACpB,GAAG;GACH;GACD,CAAC;;AAGJ,QAAO"}
@@ -0,0 +1,31 @@
1
+ import { ExtendedRequestInit, FetchInput } from "./types.mjs";
2
+
3
+ //#region src/request.d.ts
4
+ /**
5
+ * Normalized representation used by internal request execution.
6
+ *
7
+ * - `url`: resolved string URL from the input (string or `URL`; `Request` uses `request.url`)
8
+ * - `request`: original Request clone when input is a Request
9
+ * - `options`: normalized request options merged with Request headers
10
+ */
11
+ interface NormalizedRequest {
12
+ url: string;
13
+ request?: Request;
14
+ options: ExtendedRequestInit;
15
+ }
16
+ /**
17
+ * Normalizes fetch `input` and request-level options into a consistent internal shape.
18
+ *
19
+ * @param input - Request URL/path or Request instance.
20
+ * @param options - Optional request options.
21
+ * @returns A normalized request structure for internal processing.
22
+ * @throws {TypeError} When cloning a `Request` fails or the merged headers are invalid.
23
+ *
24
+ * @example
25
+ * const normalized = normalizeRequest("/users", { method: "GET" });
26
+ * console.log(normalized.url); // "/users"
27
+ */
28
+ declare function normalizeRequest(input: FetchInput, options?: ExtendedRequestInit): NormalizedRequest;
29
+ //#endregion
30
+ export { NormalizedRequest, normalizeRequest };
31
+ //# sourceMappingURL=request.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.d.mts","names":[],"sources":["../src/request.ts"],"mappings":";;;;;AAgBA;;;;;UAAiB,iBAAA;EACf,GAAA;EACA,OAAA,GAAU,OAAA;EACV,OAAA,EAAS,mBAAA;AAAA;;AAeX;;;;;;;;;;;iBAAgB,gBAAA,CACd,KAAA,EAAO,UAAA,EACP,OAAA,GAAU,mBAAA,GACT,iBAAA"}
@@ -0,0 +1,39 @@
1
+ import { mergeHeaders } from "./headers.mjs";
2
+ //#region src/request.ts
3
+ /**
4
+ * Request normalization helpers for fetch `input` values.
5
+ *
6
+ * @module
7
+ */
8
+ /**
9
+ * Normalizes fetch `input` and request-level options into a consistent internal shape.
10
+ *
11
+ * @param input - Request URL/path or Request instance.
12
+ * @param options - Optional request options.
13
+ * @returns A normalized request structure for internal processing.
14
+ * @throws {TypeError} When cloning a `Request` fails or the merged headers are invalid.
15
+ *
16
+ * @example
17
+ * const normalized = normalizeRequest("/users", { method: "GET" });
18
+ * console.log(normalized.url); // "/users"
19
+ */
20
+ function normalizeRequest(input, options) {
21
+ if (!(input instanceof Request)) return {
22
+ url: input instanceof URL ? input.href : input,
23
+ options: options ?? {}
24
+ };
25
+ const request = new Request(input);
26
+ const { headers, ...rest } = options || {};
27
+ const mergedHeaders = mergeHeaders(request.headers, headers);
28
+ const normalizedOptions = { ...rest };
29
+ if (mergedHeaders) normalizedOptions.headers = mergedHeaders;
30
+ return {
31
+ url: request.url,
32
+ request,
33
+ options: normalizedOptions
34
+ };
35
+ }
36
+ //#endregion
37
+ export { normalizeRequest };
38
+
39
+ //# sourceMappingURL=request.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.mjs","names":[],"sources":["../src/request.ts"],"sourcesContent":["/**\n * Request normalization helpers for fetch `input` values.\n *\n * @module\n */\n\nimport { mergeHeaders } from \"./headers.js\";\nimport type { ExtendedRequestInit, FetchInput } from \"./types.js\";\n\n/**\n * Normalized representation used by internal request execution.\n *\n * - `url`: resolved string URL from the input (string or `URL`; `Request` uses `request.url`)\n * - `request`: original Request clone when input is a Request\n * - `options`: normalized request options merged with Request headers\n */\nexport interface NormalizedRequest {\n url: string;\n request?: Request;\n options: ExtendedRequestInit;\n}\n\n/**\n * Normalizes fetch `input` and request-level options into a consistent internal shape.\n *\n * @param input - Request URL/path or Request instance.\n * @param options - Optional request options.\n * @returns A normalized request structure for internal processing.\n * @throws {TypeError} When cloning a `Request` fails or the merged headers are invalid.\n *\n * @example\n * const normalized = normalizeRequest(\"/users\", { method: \"GET\" });\n * console.log(normalized.url); // \"/users\"\n */\nexport function normalizeRequest(\n input: FetchInput,\n options?: ExtendedRequestInit,\n): NormalizedRequest {\n if (!(input instanceof Request)) {\n const url = input instanceof URL ? input.href : input;\n return {\n url,\n options: options ?? {},\n };\n }\n\n const request = new Request(input);\n const { headers, ...rest } = options || {};\n const mergedHeaders = mergeHeaders(request.headers, headers);\n const normalizedOptions = { ...rest } as ExtendedRequestInit;\n\n if (mergedHeaders) {\n normalizedOptions.headers = mergedHeaders;\n }\n\n return {\n url: request.url,\n request,\n options: normalizedOptions,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAkCA,SAAgB,iBACd,OACA,SACmB;AACnB,KAAI,EAAE,iBAAiB,SAErB,QAAO;EACL,KAFU,iBAAiB,MAAM,MAAM,OAAO;EAG9C,SAAS,WAAW,EAAE;EACvB;CAGH,MAAM,UAAU,IAAI,QAAQ,MAAM;CAClC,MAAM,EAAE,SAAS,GAAG,SAAS,WAAW,EAAE;CAC1C,MAAM,gBAAgB,aAAa,QAAQ,SAAS,QAAQ;CAC5D,MAAM,oBAAoB,EAAE,GAAG,MAAM;AAErC,KAAI,cACF,mBAAkB,UAAU;AAG9B,QAAO;EACL,KAAK,QAAQ;EACb;EACA,SAAS;EACV"}