@zap-studio/fetch 2.1.1 → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,39 +4,45 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [2.1.2]
8
+
9
+ ### Fixed
10
+
11
+ The `@opentelemetry/api` peer dependency was published as the raw pnpm `catalog:` protocol string instead of a resolved version range, an invalid semver range. This release republishes with it resolved.
12
+
7
13
  ## [2.1.1]
8
14
 
9
15
  ### Changed
10
16
 
11
- Reverted the `@zap-studio/monads` dependency and the `$fetchResult`/`apiResult`/`createFetch(...).​$fetchResult`/`createFetch(...).​apiResult` exports added in 2.1.0 they added a dependency and bundle size cost for a use case consumers can already cover themselves by wrapping `$fetch`/`api` with `@zap-studio/monads`'s `fromPromise`. See the README's "Using with `@zap-studio/monads`" section. 2.1.0 is deprecated on npm in favor of this release.
17
+ Reverted the `@zap-studio/monads` dependency and the `$fetchResult`/`apiResult`/`createFetch(...).​$fetchResult`/`createFetch(...).​apiResult` exports added in 2.1.0. They added a dependency and more bundle size for something you can already do yourself: wrap `$fetch`/`api` with `@zap-studio/monads`'s `fromPromise`. See the README's "Using with `@zap-studio/monads`" section. 2.1.0 is now deprecated on npm. Use this release instead.
12
18
 
13
19
  ## [2.1.0] (deprecated — see 2.1.1)
14
20
 
15
21
  ### Added
16
22
 
17
- - Added `$fetchResult`/`apiResult`, `Result`/`ResultAsync`-returning counterparts to `$fetch`/`api`, backed by the new `@zap-studio/monads` dependency. `createFetch(...)` instances also get `$fetchResult`/`apiResult` alongside the existing `$fetch`/`api`. Additive and opt-in `$fetch`, `api`, and `createFetch(...)` are unchanged. No `throwOnFetchError`/`throwOnValidationError` option; a non-ok response and validation issues both become `Err`, and a malformed schema or request still throws.
23
+ - Added `$fetchResult`/`apiResult`: versions of `$fetch`/`api` that return `Result`/`ResultAsync` instead of throwing. They use the new `@zap-studio/monads` dependency. `createFetch(...)` instances also get `$fetchResult`/`apiResult`, next to the existing `$fetch`/`api`. This is opt-in: `$fetch`, `api`, and `createFetch(...)` do not change. There is no `throwOnFetchError`/`throwOnValidationError` option here. A non-ok response and a validation issue both become `Err`. A malformed schema or request still throws.
18
24
 
19
25
  ## [2.0.0]
20
26
 
21
27
  ### Added
22
28
 
23
- Native OpenTelemetry support. Every request gets a `CLIENT` span (`http.request.method`, `url.full`, `http.response.status_code`), and the trace context is injected into the outgoing request's headers so the call continues the caller's distributed trace. On failure — a non-2xx response or a thrown error — the span is marked `ERROR`, with thrown errors also recorded as span exceptions. See [OpenTelemetry](https://www.zapstudio.dev/fetch/opentelemetry).
29
+ Native OpenTelemetry support. Every request now gets a `CLIENT` span (`http.request.method`, `url.full`, `http.response.status_code`). The trace context is added to the outgoing request's headers, so the call stays part of the caller's trace. On failure — a non-2xx response or a thrown error — the span is marked `ERROR`, and a thrown error is also recorded on the span. See [OpenTelemetry](https://www.zapstudio.dev/fetch/opentelemetry).
24
30
 
25
31
  ### Changed
26
32
 
27
- **Breaking:** `@opentelemetry/api` is now a required peer dependency. It's tiny, side-effect-free, and a no-op until an app registers a real SDK, so nothing changes at runtime for consumers who don't set one up but the package won't resolve without it installed: `npm install @opentelemetry/api`.
33
+ **Breaking:** `@opentelemetry/api` is now a required peer dependency. It is small, has no side effects, and does nothing until an app sets up a real SDK. So nothing changes at runtime if you don't use one. But you must install it for the package to work: `npm install @opentelemetry/api`.
28
34
 
29
35
  ## [1.1.1]
30
36
 
31
37
  ### Changed
32
38
 
33
- `@zap-studio/logger` is now an optional peer dependency instead of a regular dependency. Every import from it is type-only (`import type { Logger }`), so it was never pulled in at runtime pass any object matching the `Logger` shape (including `pino`) with no install required. Existing consumers of `logger?: Logger` are unaffected.
39
+ `@zap-studio/logger` is now an optional peer dependency, not a regular one. Every import from it is type-only (`import type { Logger }`), so it was never loaded at runtime. You can pass any object with the `Logger` shape (`pino` included) with no install needed. If you already use `logger?: Logger`, nothing changes for you.
34
40
 
35
41
  ## [1.1.0]
36
42
 
37
43
  ### Added
38
44
 
39
- `createFetch(...)` gains an optional `logger?: Logger` option (from `@zap-studio/logger`). When provided, it logs outgoing requests at `debug`, response status at `debug` (2xx) or `warn` (non-2xx), and schema validation failures at `error`. Omitting it keeps zero logging overhead. See [Logging](https://www.zapstudio.dev/fetch/logging).
45
+ `createFetch(...)` now has an optional `logger?: Logger` option (from `@zap-studio/logger`). When you pass one, it logs outgoing requests at `debug`, the response status at `debug` (2xx) or `warn` (non-2xx), and schema validation failures at `error`. Leave it out and there is no logging cost at all. See [Logging](https://www.zapstudio.dev/fetch/logging).
40
46
 
41
47
  ## [1.0.0]
42
48
 
@@ -46,16 +52,16 @@ Native OpenTelemetry support. Every request gets a `CLIENT` span (`http.request.
46
52
 
47
53
  ### Removed
48
54
 
49
- Collapsed the internal request pipeline (`_internal.ts`, `_methods.ts`, `constants.ts`, `headers.ts`, `request.ts`, `url.ts`) into implementation-only files. `mergeHeaders`, `normalizeRequest`, and `resolveRequestUrl` are no longer public API they were pipeline internals, not meant for standalone use.
55
+ Collapsed the internal request pipeline (`_internal.ts`, `_methods.ts`, `constants.ts`, `headers.ts`, `request.ts`, `url.ts`) into implementation-only files. `mergeHeaders`, `normalizeRequest`, and `resolveRequestUrl` are no longer public API. They were internal pipeline pieces, not made for standalone use.
50
56
 
51
57
  - Removed the `./constants`, `./headers`, `./request`, `./url`, and `./fetch` subpath exports. Use the root `@zap-studio/fetch` entry instead.
52
- - `GLOBAL_DEFAULTS`, `FetchError`, `$fetch`, `api`, `createFetch`, and all public types are unaffected and still exported from `.`; `./errors` and `./types` subpaths are unaffected.
58
+ - `GLOBAL_DEFAULTS`, `FetchError`, `$fetch`, `api`, `createFetch`, and all public types still work the same, still exported from `.`. The `./errors` and `./types` subpaths still work too.
53
59
 
54
60
  ## [0.5.6]
55
61
 
56
62
  ### Added
57
63
 
58
- The package root now re-exports the full public API, so everything can be imported from `@zap-studio/fetch` directly (`$fetch`, `api`, `createFetch`, `FetchError`, `mergeHeaders`, `GLOBAL_DEFAULTS`, `normalizeRequest`, `resolveRequestUrl`, and all public types). All exports are side-effect free and tree-shakeable; granular subpath imports keep working.
64
+ The package root now re-exports the full public API. So you can import everything straight from `@zap-studio/fetch` (`$fetch`, `api`, `createFetch`, `FetchError`, `mergeHeaders`, `GLOBAL_DEFAULTS`, `normalizeRequest`, `resolveRequestUrl`, and all public types). All exports are side-effect free and tree-shakeable. The narrower subpath imports still work too.
59
65
 
60
66
  - The `$fetch`/`api`/`createFetch` implementation moved from the entrypoint into its own module, available as the new `./fetch` subpath.
61
67
 
@@ -111,7 +117,7 @@ Internal formatting and lint cleanup only. No public API or behavior change.
111
117
 
112
118
  - **Breaking:** Request bodies are no longer auto-serialized from plain objects; use the explicit `json` option (or set `body` yourself). `body` and `json` are mutually exclusive at the type level and enforced at runtime.
113
119
  - Simplified the request API around web platform types.
114
- - The first argument is named `input` and typed as `FetchInput` (`Parameters<typeof fetch>[0]` from `lib.dom`), exported from `@zap-studio/fetch/types`, so allowed inputs track global `fetch` when DOM typings change.
120
+ - The first argument is now named `input` and typed as `FetchInput` (`Parameters<typeof fetch>[0]` from `lib.dom`), exported from `@zap-studio/fetch/types`. This means the allowed inputs update on their own when the DOM types for `fetch` change.
115
121
  - Non-`Request` values (including `URL`) are normalized to a string URL before query merge.
116
122
  - `ExtendedRequestInit` now extends native `RequestInit` directly instead of redefining request options.
117
123
  - `searchParams` now accepts the same input shape as `new URLSearchParams(...)`.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;;;;;;;;;cA2Da,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwbR,OAAO,gBAAgB,kBAC3C,OAAO,YACP,QAAQ,SACR,SAAS;EAAwB;IAChC,QAAQ,iBAAiB,OAAO,iBAAiB,YAAY;iBAE1C,OAAO,gBAAgB,kBAC3C,OAAO,YACP,QAAQ,SACR,UAAU;EAAwB;IACjC,QAAQ,iBAAiB,YAAY;iBAElB,OAAO,OAAO,YAAY,UAAU,sBAAsB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;cAqC3E,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAmCL,cAAe,iBAAgB,QAAQ,mBAAsB"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;;;;;;;;;cA2Da,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsbR,OAAO,gBAAgB,kBAC3C,OAAO,YACP,QAAQ,SACR,SAAS;EAAwB;IAChC,QAAQ,iBAAiB,OAAO,iBAAiB,YAAY;iBAE1C,OAAO,gBAAgB,kBAC3C,OAAO,YACP,QAAQ,SACR,UAAU;EAAwB;IACjC,QAAQ,iBAAiB,YAAY;iBAElB,OAAO,OAAO,YAAY,UAAU,sBAAsB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;cAqC3E,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAmCL,cAAe,iBAAgB,QAAQ,mBAAsB"}
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import { isStandardSchema, standardValidate } from "@zap-studio/validation";
8
8
  * `TracerProvider`; a no-op provider (the default until an app registers an
9
9
  * SDK) makes every span/propagation call below a no-op too.
10
10
  */
11
- const tracer = trace.getTracer("@zap-studio/fetch", "2.1.1");
11
+ const tracer = trace.getTracer("@zap-studio/fetch", "2.1.2");
12
12
  /**
13
13
  * `TextMapSetter` for the Web `Headers` API, used to inject `traceparent`
14
14
  * (and any other registered propagator fields) into the outgoing request.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["pkg.name","pkg.version","otelContext"],"sources":["../package.json","../src/_otel.ts","../src/index.ts"],"sourcesContent":["","/**\n * Internal OpenTelemetry wiring for the fetch package: tracer resolution,\n * the `Headers` propagation carrier, and span error recording. Kept out of\n * `index.ts` so request logic doesn't get tangled with tracing concerns.\n *\n * @module @zap-studio/fetch/otel\n */\n\nimport type { Span, TextMapSetter, Tracer } from \"@opentelemetry/api\";\n\nimport { SpanStatusCode, trace } from \"@opentelemetry/api\";\n\nimport pkg from \"../package.json\" with { type: \"json\" };\n\n/**\n * OpenTelemetry tracer for this package. Resolved once against the global\n * `TracerProvider`; a no-op provider (the default until an app registers an\n * SDK) makes every span/propagation call below a no-op too.\n */\nexport const tracer: Tracer = trace.getTracer(pkg.name, pkg.version);\n\n/**\n * `TextMapSetter` for the Web `Headers` API, used to inject `traceparent`\n * (and any other registered propagator fields) into the outgoing request.\n */\nexport const HEADERS_SETTER: TextMapSetter<Headers> = {\n set(carrier, key, value) {\n carrier.set(key, value);\n },\n};\n\n/**\n * Records `error` on `span` and marks it as failed. `recordException` only\n * accepts an `Error` or `string`, so other thrown values just get the\n * `ERROR` status without an attached exception event.\n */\nexport const recordSpanError = (span: Span, error: unknown): void => {\n if (error instanceof Error || typeof error === \"string\") {\n span.recordException(error);\n }\n span.setStatus({ code: SpanStatusCode.ERROR });\n};\n","/**\n * Public entrypoint for the fetch package.\n *\n * Exports `$fetch`, `api`, `createFetch`, `FetchError`, `GLOBAL_DEFAULTS`,\n * and the public type contracts. `FetchError` and the type contracts are\n * also available from dedicated subpaths (`@zap-studio/fetch/errors`,\n * `@zap-studio/fetch/types`) for consumers who prefer granular imports. All\n * exports are side-effect free and tree-shakeable.\n *\n * @module @zap-studio/fetch\n */\n\nimport type { Logger } from \"@zap-studio/logger\";\nimport type { StandardSchemaV1 } from \"@zap-studio/validation\";\n\nimport {\n SpanKind,\n SpanStatusCode,\n context as otelContext,\n propagation,\n trace,\n} from \"@opentelemetry/api\";\nimport { isStandardSchema, standardValidate } from \"@zap-studio/validation\";\n\nimport type {\n $Fetch,\n ApiMethods,\n ExtendedRequestInit,\n FetchDefaults,\n FetchInput,\n FetchInstance,\n NormalizedRequest,\n} from \"./types.ts\";\n\nimport { HEADERS_SETTER, recordSpanError, tracer } from \"./_otel.ts\";\nimport { FetchError } from \"./errors.ts\";\n\nexport { FetchError } from \"./errors.ts\";\nexport type {\n $Fetch,\n ApiMethods,\n ExtendedRequestInit,\n FetchDefaults,\n FetchInput,\n FetchInstance,\n NormalizedRequest,\n} from \"./types.ts\";\n\n/**\n * Default options for the global $fetch\n *\n * These defaults are used by the top-level `$fetch` export.\n * Use `createFetch(...)` when you need per-client defaults.\n *\n * @example\n * import { GLOBAL_DEFAULTS } from \"@zap-studio/fetch\";\n *\n * console.log(GLOBAL_DEFAULTS.throwOnFetchError); // true\n */\nexport const GLOBAL_DEFAULTS: FetchDefaults = {\n baseURL: \"\",\n throwOnFetchError: true,\n throwOnValidationError: true,\n};\n\n/**\n * Merges two HeadersInit objects, with the second one taking precedence.\n *\n * @param base - Base/default headers.\n * @param override - Request-level override headers.\n * @returns A merged `Headers` object, or `undefined` when both inputs are empty.\n * @throws {TypeError} When either header input contains invalid header names or values.\n */\nconst mergeHeaders = (base?: HeadersInit, override?: HeadersInit): Headers | undefined => {\n if (base === undefined && override === undefined) {\n return undefined;\n }\n\n const merged = new Headers(base);\n for (const [key, value] of new Headers(override).entries()) {\n merged.set(key, value);\n }\n return merged;\n};\n\n// SAFETY: Every property of `ExtendedRequestInit` is optional, so `{}` is already a structurally valid value; the cast only pins the type.\nconst EMPTY_OPTIONS = {} as ExtendedRequestInit;\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 */\nconst normalizeRequest = (input: FetchInput, options?: ExtendedRequestInit): NormalizedRequest => {\n if (!(input instanceof Request)) {\n const url = input instanceof URL ? input.href : input;\n return {\n options: options ?? EMPTY_OPTIONS,\n url,\n };\n }\n\n const request = new Request(input);\n const { headers, ...rest } = options ?? {};\n const mergedHeaders = mergeHeaders(request.headers, headers);\n // SAFETY: `rest` is `options` with only the `headers` key removed, so it's already structurally an `ExtendedRequestInit` minus `headers`, which is set below.\n const normalizedOptions = { ...rest } as ExtendedRequestInit;\n\n if (mergedHeaders !== undefined) {\n normalizedOptions.headers = mergedHeaders;\n }\n\n return {\n options: normalizedOptions,\n request,\n url: request.url,\n };\n};\n\n/**\n * Copies search params into target, overriding duplicate keys.\n */\nconst mergeSearchParams = (\n target: URLSearchParams,\n source: ExtendedRequestInit[\"searchParams\"] | undefined,\n): void => {\n for (const [key, value] of new URLSearchParams(source)) {\n target.set(key, value);\n }\n};\n\n/**\n * Ensures a URL has a trailing slash for relative URL resolution.\n */\nconst ensureTrailingSlash = (url: string): string => (url.endsWith(\"/\") ? url : `${url}/`);\n\n/**\n * Resolves search params by applying default params, URL params, then request params.\n */\nconst resolveSearchParams = (\n url: string,\n defaultSearchParams: FetchDefaults[\"searchParams\"] | undefined,\n searchParams: ExtendedRequestInit[\"searchParams\"] | undefined,\n): string => {\n if (defaultSearchParams === undefined && searchParams === undefined) {\n return url;\n }\n\n const hashIndex = url.indexOf(\"#\");\n const hasFragment = hashIndex !== -1;\n const urlWithoutHash = hasFragment ? url.slice(0, hashIndex) : url;\n const hash = hasFragment ? url.slice(hashIndex + 1) : \"\";\n const queryIndex = urlWithoutHash.indexOf(\"?\");\n const pathname = queryIndex === -1 ? urlWithoutHash : urlWithoutHash.slice(0, queryIndex);\n const urlSearchParams = queryIndex === -1 ? undefined : urlWithoutHash.slice(queryIndex + 1);\n const resolvedSearchParams = new URLSearchParams();\n\n mergeSearchParams(resolvedSearchParams, defaultSearchParams);\n mergeSearchParams(resolvedSearchParams, urlSearchParams);\n mergeSearchParams(resolvedSearchParams, searchParams);\n\n const resolvedSearch = resolvedSearchParams.toString();\n const fragmentSuffix = hasFragment ? `#${hash}` : \"\";\n\n if (resolvedSearch.length === 0) {\n return `${pathname}${fragmentSuffix}`;\n }\n\n return `${pathname}?${resolvedSearch}${fragmentSuffix}`;\n};\n\n/**\n * Resolves final request URL by applying baseURL and layered search params.\n *\n * Search param precedence:\n * 1. `defaults.searchParams`\n * 2. search params already present in `resourceUrl`\n * 3. per-request `searchParams`\n *\n * @throws {TypeError} When `baseURL` and `resourceUrl` cannot be resolved by\n * `URL`, or when default/per-request search params cannot be converted by\n * `URLSearchParams`.\n */\nconst resolveRequestUrl = (\n resourceUrl: string,\n defaults: FetchDefaults,\n searchParams?: ExtendedRequestInit[\"searchParams\"],\n): string => {\n const url = defaults.baseURL\n ? new URL(resourceUrl, ensureTrailingSlash(defaults.baseURL)).toString()\n : resourceUrl;\n\n return resolveSearchParams(url, defaults.searchParams, searchParams);\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 */\nconst prepareRequestInit = (options: ExtendedRequestInit, defaults: FetchDefaults) => {\n const {\n headers,\n json,\n searchParams,\n throwOnFetchError = defaults.throwOnFetchError,\n throwOnValidationError = defaults.throwOnValidationError,\n ...rest\n } = options;\n\n const init: RequestInit = { ...rest };\n const mergedHeaders = mergeHeaders(defaults.headers, headers);\n if (mergedHeaders !== undefined) {\n init.headers = mergedHeaders;\n }\n\n if (json !== undefined) {\n if (init.body !== undefined && init.body !== null) {\n throw new TypeError(\"Cannot provide both `body` and `json`.\");\n }\n\n init.body = JSON.stringify(json);\n const requestHeaders = new Headers(init.headers);\n if (!requestHeaders.has(\"Content-Type\")) {\n requestHeaders.set(\"Content-Type\", \"application/json\");\n }\n init.headers = requestHeaders;\n }\n\n return {\n init,\n searchParams,\n throwOnFetchError,\n throwOnValidationError,\n };\n};\n\n/**\n * Logs a fetch response: `debug` for 2xx, `warn` otherwise.\n */\nconst logResponse = (\n logger: Logger | undefined,\n method: string,\n url: string,\n response: Response,\n): void => {\n const context = { method, status: response.status, url };\n if (response.ok) {\n logger?.debug(\"fetch response\", context);\n } else {\n logger?.warn(\"fetch response\", context);\n }\n};\n\n/**\n * Validates the raw JSON payload against `schema`, logging a `fetch\n * validation failed` message at `error` on failure regardless of throw mode.\n *\n * @throws {unknown} Any error thrown by `standardValidate` in throw mode.\n */\nconst validateResponse = async (\n raw: unknown,\n schema: StandardSchemaV1,\n throwOnValidationError: boolean,\n logger: Logger | undefined,\n url: string,\n): Promise<unknown> => {\n if (throwOnValidationError) {\n try {\n return await standardValidate(raw, schema, { throwOnError: true });\n } catch (error) {\n logger?.error(\"fetch validation failed\", { error, url });\n throw error;\n }\n }\n\n const result = await standardValidate(raw, schema, { throwOnError: false });\n if (result.issues) {\n logger?.error(\"fetch validation failed\", { issues: result.issues, url });\n }\n return result;\n};\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 {unknown} Any error thrown or rejected by the provided Standard Schema validator.\n */\nconst fetchInternal = async (\n input: FetchInput,\n schema: StandardSchemaV1 | undefined,\n options: ExtendedRequestInit | undefined,\n defaults: FetchDefaults,\n): Promise<unknown> => {\n const { logger } = defaults;\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 method = init.method ?? \"GET\";\n\n logger?.debug(\"fetch request\", { method, url });\n\n const span = tracer.startSpan(method, {\n attributes: {\n \"http.request.method\": method,\n \"url.full\": url,\n },\n kind: SpanKind.CLIENT,\n });\n const spanContext = trace.setSpan(otelContext.active(), span);\n\n try {\n return await otelContext.with(spanContext, async () => {\n const headers = new Headers(init.headers);\n propagation.inject(spanContext, headers, HEADERS_SETTER);\n init.headers = headers;\n\n const response = request.request\n ? await fetch(new Request(url, request.request), init)\n : await fetch(url, init);\n\n logResponse(logger, method, url, response);\n span.setAttribute(\"http.response.status_code\", response.status);\n if (!response.ok) {\n span.setStatus({ code: SpanStatusCode.ERROR });\n }\n\n if (throwOnFetchError && !response.ok) {\n throw new FetchError(`HTTP ${response.status}: ${response.statusText}`, response);\n }\n\n if (schema === undefined) {\n return response;\n }\n\n const raw: unknown = await response.json();\n return await validateResponse(raw, schema, throwOnValidationError, logger, url);\n });\n } catch (error) {\n recordSpanError(span, error);\n throw error;\n } finally {\n span.end();\n }\n};\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 {unknown} 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 */\nconst createMethod = (fetchFn: $Fetch, 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 async 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 await 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 await fetchFn(input, schemaOrOptions, {\n ...restOptions,\n method,\n throwOnValidationError: true,\n });\n }\n\n return await fetchFn(input, schemaOrOptions, {\n ...restOptions,\n method,\n });\n }\n\n return await fetchFn(input, {\n ...schemaOrOptions,\n method,\n });\n }\n\n return methodFetch;\n};\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 {unknown} 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 delete: createMethod($fetch, \"DELETE\"),\n get: createMethod($fetch, \"GET\"),\n patch: createMethod($fetch, \"PATCH\"),\n post: createMethod($fetch, \"POST\"),\n put: createMethod($fetch, \"PUT\"),\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 const createFetch = (factoryOptions: Partial<FetchDefaults> = {}): FetchInstance => {\n const defaults: FetchDefaults = {\n ...GLOBAL_DEFAULTS,\n ...factoryOptions,\n baseURL: factoryOptions.baseURL ?? GLOBAL_DEFAULTS.baseURL,\n throwOnFetchError: factoryOptions.throwOnFetchError ?? GLOBAL_DEFAULTS.throwOnFetchError,\n throwOnValidationError:\n factoryOptions.throwOnValidationError ?? GLOBAL_DEFAULTS.throwOnValidationError,\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 delete: createMethod(customFetch, \"DELETE\"),\n get: createMethod(customFetch, \"GET\"),\n patch: createMethod(customFetch, \"PATCH\"),\n post: createMethod(customFetch, \"POST\"),\n put: createMethod(customFetch, \"PUT\"),\n };\n\n return {\n $fetch: customFetch,\n api: customApi,\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["pkg.name","pkg.version","otelContext"],"sources":["../package.json","../src/_otel.ts","../src/index.ts"],"sourcesContent":["","/**\n * Internal OpenTelemetry wiring for the fetch package: tracer resolution,\n * the `Headers` propagation carrier, and span error recording. Kept out of\n * `index.ts` so request logic doesn't get tangled with tracing concerns.\n *\n * @module @zap-studio/fetch/otel\n */\n\nimport type { Span, TextMapSetter, Tracer } from \"@opentelemetry/api\";\n\nimport { SpanStatusCode, trace } from \"@opentelemetry/api\";\n\nimport pkg from \"../package.json\" with { type: \"json\" };\n\n/**\n * OpenTelemetry tracer for this package. Resolved once against the global\n * `TracerProvider`; a no-op provider (the default until an app registers an\n * SDK) makes every span/propagation call below a no-op too.\n */\nexport const tracer: Tracer = trace.getTracer(pkg.name, pkg.version);\n\n/**\n * `TextMapSetter` for the Web `Headers` API, used to inject `traceparent`\n * (and any other registered propagator fields) into the outgoing request.\n */\nexport const HEADERS_SETTER: TextMapSetter<Headers> = {\n set(carrier, key, value) {\n carrier.set(key, value);\n },\n};\n\n/**\n * Records `error` on `span` and marks it as failed. `recordException` only\n * accepts an `Error` or `string`, so other thrown values just get the\n * `ERROR` status without an attached exception event.\n */\nexport const recordSpanError = (span: Span, error: unknown): void => {\n if (error instanceof Error || typeof error === \"string\") {\n span.recordException(error);\n }\n span.setStatus({ code: SpanStatusCode.ERROR });\n};\n","/**\n * Public entrypoint for the fetch package.\n *\n * Exports `$fetch`, `api`, `createFetch`, `FetchError`, `GLOBAL_DEFAULTS`,\n * and the public type contracts. `FetchError` and the type contracts are\n * also available from dedicated subpaths (`@zap-studio/fetch/errors`,\n * `@zap-studio/fetch/types`) for consumers who prefer granular imports. All\n * exports are side-effect free and tree-shakeable.\n *\n * @module @zap-studio/fetch\n */\n\nimport type { Logger } from \"@zap-studio/logger\";\nimport type { StandardSchemaV1 } from \"@zap-studio/validation\";\n\nimport {\n SpanKind,\n SpanStatusCode,\n context as otelContext,\n propagation,\n trace,\n} from \"@opentelemetry/api\";\nimport { isStandardSchema, standardValidate } from \"@zap-studio/validation\";\n\nimport type {\n $Fetch,\n ApiMethods,\n ExtendedRequestInit,\n FetchDefaults,\n FetchInput,\n FetchInstance,\n NormalizedRequest,\n} from \"./types.ts\";\n\nimport { HEADERS_SETTER, recordSpanError, tracer } from \"./_otel.ts\";\nimport { FetchError } from \"./errors.ts\";\n\nexport { FetchError } from \"./errors.ts\";\nexport type {\n $Fetch,\n ApiMethods,\n ExtendedRequestInit,\n FetchDefaults,\n FetchInput,\n FetchInstance,\n NormalizedRequest,\n} from \"./types.ts\";\n\n/**\n * Default options for the global $fetch\n *\n * These defaults are used by the top-level `$fetch` export.\n * Use `createFetch(...)` when you need per-client defaults.\n *\n * @example\n * import { GLOBAL_DEFAULTS } from \"@zap-studio/fetch\";\n *\n * console.log(GLOBAL_DEFAULTS.throwOnFetchError); // true\n */\nexport const GLOBAL_DEFAULTS: FetchDefaults = {\n baseURL: \"\",\n throwOnFetchError: true,\n throwOnValidationError: true,\n};\n\n/**\n * Merges two HeadersInit objects, with the second one taking precedence.\n *\n * @param base - Base/default headers.\n * @param override - Request-level override headers.\n * @returns A merged `Headers` object, or `undefined` when both inputs are empty.\n * @throws {TypeError} When either header input contains invalid header names or values.\n */\nconst mergeHeaders = (base?: HeadersInit, override?: HeadersInit): Headers | undefined => {\n if (base === undefined && override === undefined) {\n return undefined;\n }\n\n const merged = new Headers(base);\n for (const [key, value] of new Headers(override).entries()) {\n merged.set(key, value);\n }\n return merged;\n};\n\nconst EMPTY_OPTIONS: ExtendedRequestInit = {};\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 */\nconst normalizeRequest = (input: FetchInput, options?: ExtendedRequestInit): NormalizedRequest => {\n if (!(input instanceof Request)) {\n const url = input instanceof URL ? input.href : input;\n return {\n options: options ?? EMPTY_OPTIONS,\n url,\n };\n }\n\n const request = new Request(input);\n const { headers, ...rest } = options ?? {};\n const mergedHeaders = mergeHeaders(request.headers, headers);\n const normalizedOptions: ExtendedRequestInit = { ...rest };\n\n if (mergedHeaders !== undefined) {\n normalizedOptions.headers = mergedHeaders;\n }\n\n return {\n options: normalizedOptions,\n request,\n url: request.url,\n };\n};\n\n/**\n * Copies search params into target, overriding duplicate keys.\n */\nconst mergeSearchParams = (\n target: URLSearchParams,\n source: ExtendedRequestInit[\"searchParams\"] | undefined,\n): void => {\n for (const [key, value] of new URLSearchParams(source)) {\n target.set(key, value);\n }\n};\n\n/**\n * Ensures a URL has a trailing slash for relative URL resolution.\n */\nconst ensureTrailingSlash = (url: string): string => (url.endsWith(\"/\") ? url : `${url}/`);\n\n/**\n * Resolves search params by applying default params, URL params, then request params.\n */\nconst resolveSearchParams = (\n url: string,\n defaultSearchParams: FetchDefaults[\"searchParams\"] | undefined,\n searchParams: ExtendedRequestInit[\"searchParams\"] | undefined,\n): string => {\n if (defaultSearchParams === undefined && searchParams === undefined) {\n return url;\n }\n\n const hashIndex = url.indexOf(\"#\");\n const hasFragment = hashIndex !== -1;\n const urlWithoutHash = hasFragment ? url.slice(0, hashIndex) : url;\n const hash = hasFragment ? url.slice(hashIndex + 1) : \"\";\n const queryIndex = urlWithoutHash.indexOf(\"?\");\n const pathname = queryIndex === -1 ? urlWithoutHash : urlWithoutHash.slice(0, queryIndex);\n const urlSearchParams = queryIndex === -1 ? undefined : urlWithoutHash.slice(queryIndex + 1);\n const resolvedSearchParams = new URLSearchParams();\n\n mergeSearchParams(resolvedSearchParams, defaultSearchParams);\n mergeSearchParams(resolvedSearchParams, urlSearchParams);\n mergeSearchParams(resolvedSearchParams, searchParams);\n\n const resolvedSearch = resolvedSearchParams.toString();\n const fragmentSuffix = hasFragment ? `#${hash}` : \"\";\n\n if (resolvedSearch.length === 0) {\n return `${pathname}${fragmentSuffix}`;\n }\n\n return `${pathname}?${resolvedSearch}${fragmentSuffix}`;\n};\n\n/**\n * Resolves final request URL by applying baseURL and layered search params.\n *\n * Search param precedence:\n * 1. `defaults.searchParams`\n * 2. search params already present in `resourceUrl`\n * 3. per-request `searchParams`\n *\n * @throws {TypeError} When `baseURL` and `resourceUrl` cannot be resolved by\n * `URL`, or when default/per-request search params cannot be converted by\n * `URLSearchParams`.\n */\nconst resolveRequestUrl = (\n resourceUrl: string,\n defaults: FetchDefaults,\n searchParams?: ExtendedRequestInit[\"searchParams\"],\n): string => {\n const url = defaults.baseURL\n ? new URL(resourceUrl, ensureTrailingSlash(defaults.baseURL)).toString()\n : resourceUrl;\n\n return resolveSearchParams(url, defaults.searchParams, searchParams);\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 */\nconst prepareRequestInit = (options: ExtendedRequestInit, defaults: FetchDefaults) => {\n const {\n headers,\n json,\n searchParams,\n throwOnFetchError = defaults.throwOnFetchError,\n throwOnValidationError = defaults.throwOnValidationError,\n ...rest\n } = options;\n\n const init: RequestInit = { ...rest };\n const mergedHeaders = mergeHeaders(defaults.headers, headers);\n if (mergedHeaders !== undefined) {\n init.headers = mergedHeaders;\n }\n\n if (json !== undefined) {\n if (init.body !== undefined && init.body !== null) {\n throw new TypeError(\"Cannot provide both `body` and `json`.\");\n }\n\n init.body = JSON.stringify(json);\n const requestHeaders = new Headers(init.headers);\n if (!requestHeaders.has(\"Content-Type\")) {\n requestHeaders.set(\"Content-Type\", \"application/json\");\n }\n init.headers = requestHeaders;\n }\n\n return {\n init,\n searchParams,\n throwOnFetchError,\n throwOnValidationError,\n };\n};\n\n/**\n * Logs a fetch response: `debug` for 2xx, `warn` otherwise.\n */\nconst logResponse = (\n logger: Logger | undefined,\n method: string,\n url: string,\n response: Response,\n): void => {\n const context = { method, status: response.status, url };\n if (response.ok) {\n logger?.debug(\"fetch response\", context);\n } else {\n logger?.warn(\"fetch response\", context);\n }\n};\n\n/**\n * Validates the raw JSON payload against `schema`, logging a `fetch\n * validation failed` message at `error` on failure regardless of throw mode.\n *\n * @throws {unknown} Any error thrown by `standardValidate` in throw mode.\n */\nconst validateResponse = async (\n raw: unknown,\n schema: StandardSchemaV1,\n throwOnValidationError: boolean,\n logger: Logger | undefined,\n url: string,\n): Promise<unknown> => {\n if (throwOnValidationError) {\n try {\n return await standardValidate(raw, schema, { throwOnError: true });\n } catch (error) {\n logger?.error(\"fetch validation failed\", { error, url });\n throw error;\n }\n }\n\n const result = await standardValidate(raw, schema, { throwOnError: false });\n if (result.issues) {\n logger?.error(\"fetch validation failed\", { issues: result.issues, url });\n }\n return result;\n};\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 {unknown} Any error thrown or rejected by the provided Standard Schema validator.\n */\nconst fetchInternal = async (\n input: FetchInput,\n schema: StandardSchemaV1 | undefined,\n options: ExtendedRequestInit | undefined,\n defaults: FetchDefaults,\n): Promise<unknown> => {\n const { logger } = defaults;\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 method = init.method ?? \"GET\";\n\n logger?.debug(\"fetch request\", { method, url });\n\n const span = tracer.startSpan(method, {\n attributes: {\n \"http.request.method\": method,\n \"url.full\": url,\n },\n kind: SpanKind.CLIENT,\n });\n const spanContext = trace.setSpan(otelContext.active(), span);\n\n try {\n return await otelContext.with(spanContext, async () => {\n const headers = new Headers(init.headers);\n propagation.inject(spanContext, headers, HEADERS_SETTER);\n init.headers = headers;\n\n const response = request.request\n ? await fetch(new Request(url, request.request), init)\n : await fetch(url, init);\n\n logResponse(logger, method, url, response);\n span.setAttribute(\"http.response.status_code\", response.status);\n if (!response.ok) {\n span.setStatus({ code: SpanStatusCode.ERROR });\n }\n\n if (throwOnFetchError && !response.ok) {\n throw new FetchError(`HTTP ${response.status}: ${response.statusText}`, response);\n }\n\n if (schema === undefined) {\n return response;\n }\n\n const raw: unknown = await response.json();\n return await validateResponse(raw, schema, throwOnValidationError, logger, url);\n });\n } catch (error) {\n recordSpanError(span, error);\n throw error;\n } finally {\n span.end();\n }\n};\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 {unknown} 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 */\nconst createMethod = (fetchFn: $Fetch, 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 async 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 await 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 await fetchFn(input, schemaOrOptions, {\n ...restOptions,\n method,\n throwOnValidationError: true,\n });\n }\n\n return await fetchFn(input, schemaOrOptions, {\n ...restOptions,\n method,\n });\n }\n\n return await fetchFn(input, {\n ...schemaOrOptions,\n method,\n });\n }\n\n return methodFetch;\n};\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 {unknown} 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 delete: createMethod($fetch, \"DELETE\"),\n get: createMethod($fetch, \"GET\"),\n patch: createMethod($fetch, \"PATCH\"),\n post: createMethod($fetch, \"POST\"),\n put: createMethod($fetch, \"PUT\"),\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 const createFetch = (factoryOptions: Partial<FetchDefaults> = {}): FetchInstance => {\n const defaults: FetchDefaults = {\n ...GLOBAL_DEFAULTS,\n ...factoryOptions,\n baseURL: factoryOptions.baseURL ?? GLOBAL_DEFAULTS.baseURL,\n throwOnFetchError: factoryOptions.throwOnFetchError ?? GLOBAL_DEFAULTS.throwOnFetchError,\n throwOnValidationError:\n factoryOptions.throwOnValidationError ?? GLOBAL_DEFAULTS.throwOnValidationError,\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 delete: createMethod(customFetch, \"DELETE\"),\n get: createMethod(customFetch, \"GET\"),\n patch: createMethod(customFetch, \"PATCH\"),\n post: createMethod(customFetch, \"POST\"),\n put: createMethod(customFetch, \"PUT\"),\n };\n\n return {\n $fetch: customFetch,\n api: customApi,\n };\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zap-studio/fetch",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "private": false,
5
5
  "description": "A type-safe, tree-shakeable fetch wrapper for HTTP requests with runtime schema validation.",
6
6
  "keywords": [
@@ -49,22 +49,22 @@
49
49
  "@zap-studio/validation": "1.1.1"
50
50
  },
51
51
  "devDependencies": {
52
- "@opentelemetry/api": "^1.9.0",
52
+ "@opentelemetry/api": "^1.9.1",
53
53
  "@opentelemetry/context-async-hooks": "^2.10.0",
54
54
  "@opentelemetry/core": "^2.10.0",
55
55
  "@opentelemetry/sdk-trace-base": "^2.10.0",
56
+ "@zap-studio/logger": "2.1.0",
57
+ "@zap-studio/typescript": "0.0.0",
56
58
  "arktype": "^2.2.3",
57
59
  "tsdown": "^0.22.14",
58
60
  "typescript": "^7.0.2",
59
61
  "valibot": "^1.4.2",
60
- "vitest": "^4.1.10",
61
- "zod": "^4.4.3",
62
- "@zap-studio/logger": "2.0.0",
63
- "@zap-studio/typescript": "0.0.0"
62
+ "vitest": "^4.1.11",
63
+ "zod": "^4.5.4"
64
64
  },
65
65
  "peerDependencies": {
66
- "@opentelemetry/api": "^1.9.0",
67
- "@zap-studio/logger": "2.0.0"
66
+ "@opentelemetry/api": "^1.9.1",
67
+ "@zap-studio/logger": "2.1.0"
68
68
  },
69
69
  "peerDependenciesMeta": {
70
70
  "@zap-studio/logger": {
@@ -73,5 +73,6 @@
73
73
  },
74
74
  "engines": {
75
75
  "node": ">=18.0.0"
76
- }
76
+ },
77
+ "scripts": {}
77
78
  }