@gcmdev/faxios 0.1.0 → 0.2.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 (210) hide show
  1. package/LICENSE +1 -0
  2. package/README.md +40 -1774
  3. package/dist/index.d.ts +9 -6
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/lib/adapters/fetch-helpers.d.ts +1 -0
  7. package/dist/lib/adapters/fetch-helpers.d.ts.map +1 -0
  8. package/dist/lib/adapters/fetch.d.ts +1 -0
  9. package/dist/lib/adapters/fetch.d.ts.map +1 -0
  10. package/dist/lib/adapters/fetch.js +23 -3
  11. package/dist/lib/adapters/fetch.js.map +1 -1
  12. package/dist/lib/cancel/CanceledError.d.ts +1 -0
  13. package/dist/lib/cancel/CanceledError.d.ts.map +1 -0
  14. package/dist/lib/cancel/isCancel.d.ts +3 -1
  15. package/dist/lib/cancel/isCancel.d.ts.map +1 -0
  16. package/dist/lib/cancel/isCancel.js +3 -0
  17. package/dist/lib/cancel/isCancel.js.map +1 -1
  18. package/dist/lib/core/Faxios.d.ts +6 -17
  19. package/dist/lib/core/Faxios.d.ts.map +1 -0
  20. package/dist/lib/core/Faxios.js +144 -76
  21. package/dist/lib/core/Faxios.js.map +1 -1
  22. package/dist/lib/core/FaxiosError.d.ts +19 -6
  23. package/dist/lib/core/FaxiosError.d.ts.map +1 -0
  24. package/dist/lib/core/FaxiosError.js +16 -1
  25. package/dist/lib/core/FaxiosError.js.map +1 -1
  26. package/dist/lib/core/FaxiosHeaders.d.ts +12 -8
  27. package/dist/lib/core/FaxiosHeaders.d.ts.map +1 -0
  28. package/dist/lib/core/FaxiosHeaders.js +1 -0
  29. package/dist/lib/core/FaxiosHeaders.js.map +1 -1
  30. package/dist/lib/core/buildFullPath.d.ts +1 -0
  31. package/dist/lib/core/buildFullPath.d.ts.map +1 -0
  32. package/dist/lib/core/define.d.ts +19 -2
  33. package/dist/lib/core/define.d.ts.map +1 -0
  34. package/dist/lib/core/define.js.map +1 -1
  35. package/dist/lib/core/dispatchRequest.d.ts +1 -0
  36. package/dist/lib/core/dispatchRequest.d.ts.map +1 -0
  37. package/dist/lib/core/dispatchRequest.js +4 -0
  38. package/dist/lib/core/dispatchRequest.js.map +1 -1
  39. package/dist/lib/core/mergeConfig.d.ts +1 -0
  40. package/dist/lib/core/mergeConfig.d.ts.map +1 -0
  41. package/dist/lib/core/prepareRequest.d.ts +1 -0
  42. package/dist/lib/core/prepareRequest.d.ts.map +1 -0
  43. package/dist/lib/core/prepareRequest.js +1 -20
  44. package/dist/lib/core/prepareRequest.js.map +1 -1
  45. package/dist/lib/core/route.d.ts +11 -2
  46. package/dist/lib/core/route.d.ts.map +1 -0
  47. package/dist/lib/core/route.js.map +1 -1
  48. package/dist/lib/core/settle.d.ts +1 -0
  49. package/dist/lib/core/settle.d.ts.map +1 -0
  50. package/dist/lib/core/transformData.d.ts +1 -0
  51. package/dist/lib/core/transformData.d.ts.map +1 -0
  52. package/dist/lib/core/validateSchema.d.ts +1 -0
  53. package/dist/lib/core/validateSchema.d.ts.map +1 -0
  54. package/dist/lib/defaults/index.d.ts +1 -0
  55. package/dist/lib/defaults/index.d.ts.map +1 -0
  56. package/dist/lib/defaults/index.js +3 -3
  57. package/dist/lib/defaults/index.js.map +1 -1
  58. package/dist/lib/defaults/transitional.d.ts +1 -1
  59. package/dist/lib/defaults/transitional.d.ts.map +1 -0
  60. package/dist/lib/defaults/transitional.js +0 -1
  61. package/dist/lib/defaults/transitional.js.map +1 -1
  62. package/dist/lib/env/data.d.ts +2 -1
  63. package/dist/lib/env/data.d.ts.map +1 -0
  64. package/dist/lib/env/data.js +1 -1
  65. package/dist/lib/env/data.js.map +1 -1
  66. package/dist/lib/faxios.d.ts +115 -48
  67. package/dist/lib/faxios.d.ts.map +1 -0
  68. package/dist/lib/faxios.js +14 -2
  69. package/dist/lib/faxios.js.map +1 -1
  70. package/dist/lib/helpers/FaxiosURLSearchParams.d.ts +3 -1
  71. package/dist/lib/helpers/FaxiosURLSearchParams.d.ts.map +1 -0
  72. package/dist/lib/helpers/FaxiosURLSearchParams.js.map +1 -1
  73. package/dist/lib/helpers/HttpStatusCode.d.ts +1 -0
  74. package/dist/lib/helpers/HttpStatusCode.d.ts.map +1 -0
  75. package/dist/lib/helpers/buildURL.d.ts +1 -0
  76. package/dist/lib/helpers/buildURL.d.ts.map +1 -0
  77. package/dist/lib/helpers/buildURL.js +7 -1
  78. package/dist/lib/helpers/buildURL.js.map +1 -1
  79. package/dist/lib/helpers/cloneConfig.d.ts +4 -0
  80. package/dist/lib/helpers/cloneConfig.d.ts.map +1 -0
  81. package/dist/lib/helpers/cloneConfig.js +21 -0
  82. package/dist/lib/helpers/cloneConfig.js.map +1 -0
  83. package/dist/lib/helpers/combineURLs.d.ts +1 -0
  84. package/dist/lib/helpers/combineURLs.d.ts.map +1 -0
  85. package/dist/lib/helpers/composeSignals.d.ts +1 -0
  86. package/dist/lib/helpers/composeSignals.d.ts.map +1 -0
  87. package/dist/lib/helpers/composeSignals.js +8 -1
  88. package/dist/lib/helpers/composeSignals.js.map +1 -1
  89. package/dist/lib/helpers/cookies.d.ts +1 -0
  90. package/dist/lib/helpers/cookies.d.ts.map +1 -0
  91. package/dist/lib/helpers/estimateDataURLDecodedBytes.d.ts +1 -0
  92. package/dist/lib/helpers/estimateDataURLDecodedBytes.d.ts.map +1 -0
  93. package/dist/lib/helpers/formDataToJSON.d.ts +1 -0
  94. package/dist/lib/helpers/formDataToJSON.d.ts.map +1 -0
  95. package/dist/lib/helpers/isAbsoluteURL.d.ts +1 -0
  96. package/dist/lib/helpers/isAbsoluteURL.d.ts.map +1 -0
  97. package/dist/lib/helpers/isFaxiosError.d.ts +8 -2
  98. package/dist/lib/helpers/isFaxiosError.d.ts.map +1 -0
  99. package/dist/lib/helpers/isFaxiosError.js +5 -1
  100. package/dist/lib/helpers/isFaxiosError.js.map +1 -1
  101. package/dist/lib/helpers/isURLSameOrigin.d.ts +1 -0
  102. package/dist/lib/helpers/isURLSameOrigin.d.ts.map +1 -0
  103. package/dist/lib/helpers/parseHeaders.d.ts +1 -0
  104. package/dist/lib/helpers/parseHeaders.d.ts.map +1 -0
  105. package/dist/lib/helpers/progressEventReducer.d.ts +1 -0
  106. package/dist/lib/helpers/progressEventReducer.d.ts.map +1 -0
  107. package/dist/lib/helpers/sanitizeHeaderValue.d.ts +1 -0
  108. package/dist/lib/helpers/sanitizeHeaderValue.d.ts.map +1 -0
  109. package/dist/lib/helpers/speedometer.d.ts +1 -0
  110. package/dist/lib/helpers/speedometer.d.ts.map +1 -0
  111. package/dist/lib/helpers/substitutePathParams.d.ts +1 -0
  112. package/dist/lib/helpers/substitutePathParams.d.ts.map +1 -0
  113. package/dist/lib/helpers/throttle.d.ts +1 -0
  114. package/dist/lib/helpers/throttle.d.ts.map +1 -0
  115. package/dist/lib/helpers/toFormData.d.ts +1 -0
  116. package/dist/lib/helpers/toFormData.d.ts.map +1 -0
  117. package/dist/lib/helpers/toURLEncodedForm.d.ts +1 -0
  118. package/dist/lib/helpers/toURLEncodedForm.d.ts.map +1 -0
  119. package/dist/lib/helpers/trackStream.d.ts +1 -0
  120. package/dist/lib/helpers/trackStream.d.ts.map +1 -0
  121. package/dist/lib/helpers/validator.d.ts +1 -0
  122. package/dist/lib/helpers/validator.d.ts.map +1 -0
  123. package/dist/lib/platform.d.ts +2 -1
  124. package/dist/lib/platform.d.ts.map +1 -0
  125. package/dist/lib/plugins/attempt.d.ts +2 -0
  126. package/dist/lib/plugins/attempt.d.ts.map +1 -0
  127. package/dist/lib/plugins/attempt.js +4 -0
  128. package/dist/lib/plugins/attempt.js.map +1 -0
  129. package/dist/lib/plugins/authBearer.d.ts +31 -0
  130. package/dist/lib/plugins/authBearer.d.ts.map +1 -0
  131. package/dist/lib/plugins/authBearer.js +99 -0
  132. package/dist/lib/plugins/authBearer.js.map +1 -0
  133. package/dist/lib/plugins/definePlugin.d.ts +22 -0
  134. package/dist/lib/plugins/definePlugin.d.ts.map +1 -0
  135. package/dist/lib/plugins/definePlugin.js +14 -0
  136. package/dist/lib/plugins/definePlugin.js.map +1 -0
  137. package/dist/lib/plugins/retry.d.ts +66 -0
  138. package/dist/lib/plugins/retry.d.ts.map +1 -0
  139. package/dist/lib/plugins/retry.js +168 -0
  140. package/dist/lib/plugins/retry.js.map +1 -0
  141. package/dist/lib/plugins/timing.d.ts +32 -0
  142. package/dist/lib/plugins/timing.d.ts.map +1 -0
  143. package/dist/lib/plugins/timing.js +53 -0
  144. package/dist/lib/plugins/timing.js.map +1 -0
  145. package/dist/lib/types/standard-schema.d.ts +1 -0
  146. package/dist/lib/types/standard-schema.d.ts.map +1 -0
  147. package/dist/lib/types.d.ts +125 -34
  148. package/dist/lib/types.d.ts.map +1 -0
  149. package/dist/lib/utils.d.ts +1 -0
  150. package/dist/lib/utils.d.ts.map +1 -0
  151. package/package.json +42 -19
  152. package/skills/configure-requests/SKILL.md +380 -0
  153. package/skills/configure-requests/references/axios-differences.md +67 -0
  154. package/skills/configure-requests/references/plugins.md +127 -0
  155. package/src/index.ts +57 -0
  156. package/src/lib/adapters/fetch-helpers.ts +167 -0
  157. package/src/lib/adapters/fetch.ts +810 -0
  158. package/src/lib/cancel/CanceledError.ts +23 -0
  159. package/src/lib/cancel/isCancel.ts +10 -0
  160. package/src/lib/core/Faxios.ts +513 -0
  161. package/src/lib/core/FaxiosError.ts +283 -0
  162. package/src/lib/core/FaxiosHeaders.ts +529 -0
  163. package/src/lib/core/buildFullPath.ts +51 -0
  164. package/src/lib/core/define.ts +127 -0
  165. package/src/lib/core/dispatchRequest.ts +171 -0
  166. package/src/lib/core/mergeConfig.ts +175 -0
  167. package/src/lib/core/prepareRequest.ts +155 -0
  168. package/src/lib/core/route.ts +68 -0
  169. package/src/lib/core/settle.ts +20 -0
  170. package/src/lib/core/transformData.ts +23 -0
  171. package/src/lib/core/validateSchema.ts +53 -0
  172. package/src/lib/defaults/index.ts +221 -0
  173. package/src/lib/defaults/transitional.ts +9 -0
  174. package/src/lib/env/data.ts +1 -0
  175. package/src/lib/faxios.ts +306 -0
  176. package/src/lib/helpers/FaxiosURLSearchParams.ts +52 -0
  177. package/src/lib/helpers/HttpStatusCode.ts +77 -0
  178. package/src/lib/helpers/buildURL.ts +77 -0
  179. package/src/lib/helpers/cloneConfig.ts +23 -0
  180. package/src/lib/helpers/combineURLs.ts +11 -0
  181. package/src/lib/helpers/composeSignals.ts +74 -0
  182. package/src/lib/helpers/cookies.ts +68 -0
  183. package/src/lib/helpers/deprecatedMethod.ts +32 -0
  184. package/src/lib/helpers/estimateDataURLDecodedBytes.ts +95 -0
  185. package/src/lib/helpers/formDataToJSON.ts +122 -0
  186. package/src/lib/helpers/isAbsoluteURL.ts +13 -0
  187. package/src/lib/helpers/isFaxiosError.ts +19 -0
  188. package/src/lib/helpers/isURLSameOrigin.ts +16 -0
  189. package/src/lib/helpers/parseHeaders.ts +76 -0
  190. package/src/lib/helpers/progressEventReducer.ts +57 -0
  191. package/src/lib/helpers/sanitizeHeaderValue.ts +61 -0
  192. package/src/lib/helpers/speedometer.ts +55 -0
  193. package/src/lib/helpers/substitutePathParams.ts +13 -0
  194. package/src/lib/helpers/throttle.ts +45 -0
  195. package/src/lib/helpers/toFormData.ts +296 -0
  196. package/src/lib/helpers/toURLEncodedForm.ts +14 -0
  197. package/src/lib/helpers/trackStream.ts +123 -0
  198. package/src/lib/helpers/validator.ts +114 -0
  199. package/src/lib/platform.ts +44 -0
  200. package/src/lib/plugins/attempt.ts +3 -0
  201. package/src/lib/plugins/authBearer.ts +124 -0
  202. package/src/lib/plugins/definePlugin.ts +34 -0
  203. package/src/lib/plugins/retry.ts +245 -0
  204. package/src/lib/plugins/timing.ts +76 -0
  205. package/src/lib/types/standard-schema.ts +58 -0
  206. package/src/lib/types.ts +496 -0
  207. package/src/lib/utils.ts +932 -0
  208. package/dist/lib/core/InterceptorManager.d.ts +0 -9
  209. package/dist/lib/core/InterceptorManager.js +0 -28
  210. package/dist/lib/core/InterceptorManager.js.map +0 -1
@@ -0,0 +1,380 @@
1
+ ---
2
+ name: configure-requests
3
+ description: >
4
+ Use when writing, reviewing or porting code that sends HTTP requests with @gcmdev/faxios:
5
+ creating an instance with baseURL, headers or timeout; cancelling requests; handling
6
+ FaxiosError codes; validating responses with a schema; adding auth, retry or timing with
7
+ .use() middleware and the built-in plugins; or replacing Axios interceptors, CancelToken,
8
+ adapters or proxy options. Not for Axios itself or for other fetch wrappers.
9
+ metadata:
10
+ purpose: >
11
+ Teach agents the request surface faxios actually implements (one fetch transport, .use()
12
+ middleware, AbortSignal cancellation, Standard Schema validation) and stop them from
13
+ generating Axios APIs that faxios removed or never verified.
14
+ type: core
15
+ library: '@gcmdev/faxios'
16
+ library_version: '0.2.1'
17
+ sources:
18
+ - src/index.ts
19
+ - src/lib/faxios.ts
20
+ - src/lib/core/Faxios.ts
21
+ - src/lib/core/mergeConfig.ts
22
+ - src/lib/core/buildFullPath.ts
23
+ - src/lib/core/dispatchRequest.ts
24
+ - src/lib/core/FaxiosError.ts
25
+ - src/lib/core/define.ts
26
+ - src/lib/core/route.ts
27
+ - src/lib/types.ts
28
+ - src/lib/adapters/fetch.ts
29
+ - src/lib/helpers/composeSignals.ts
30
+ - src/lib/plugins/definePlugin.ts
31
+ - src/lib/plugins/authBearer.ts
32
+ - src/lib/plugins/retry.ts
33
+ - src/lib/plugins/timing.ts
34
+ - package.json
35
+ - adrianbrowning/faxios:packages/tests/unit/api.test.ts
36
+ - adrianbrowning/faxios:packages/tests/unit/core/middleware.test.ts
37
+ - adrianbrowning/faxios:packages/tests/unit/plugins/*.test.ts
38
+ - adrianbrowning/faxios:MIGRATION_GUIDE.md
39
+ ---
40
+
41
+ # Configure faxios requests
42
+
43
+ faxios is a promise-based HTTP client with an Axios-like call shape and one transport: the
44
+ runtime's `fetch`. It runs in browsers, Node 24+, Deno and Bun, and ships as ESM only.
45
+ Assume nothing from Axios that this skill or the installed package's types do not show.
46
+ When the installed `@gcmdev/faxios` types disagree with this file, follow the types and report
47
+ the mismatch.
48
+
49
+ ## Setup
50
+
51
+ ```ts
52
+ import faxios from "@gcmdev/faxios";
53
+
54
+ const api = faxios.create({
55
+ baseURL: "https://api.example.com/v1",
56
+ timeout: 5000,
57
+ headers: { common: { "X-Client": "web" } },
58
+ });
59
+
60
+ const { data, status } = await api.get<{ id: number; name: string }>("/users/1");
61
+ ```
62
+
63
+ - Install with `npm i @gcmdev/faxios`. From CommonJS, load it with `await import("@gcmdev/faxios")`;
64
+ there is no `require` build and no UMD/CDN bundle.
65
+ - Check: the call resolves with a `FaxiosResponse` whose `data` is parsed JSON for JSON responses.
66
+
67
+ ## Core patterns
68
+
69
+ ### Choose the right call form
70
+
71
+ - `api(config)`, `api(url, config?)` and `api.request(config)`.
72
+ - `get`, `delete`, `head`, `options` take `(url, config?)`.
73
+ - `post`, `put`, `patch`, `query` take `(url, data?, config?)`. `query` sends the HTTP QUERY method.
74
+ - `postForm`, `putForm`, `patchForm` send `multipart/form-data`.
75
+ - `api.getUri(config)` builds the URL from `baseURL`, `url` and `params` without sending anything. It doesn't substitute `pathParams`, so `{key}` placeholders stay as written.
76
+
77
+ Path and query parameters:
78
+
79
+ ```ts
80
+ import faxios from "@gcmdev/faxios";
81
+
82
+ const res = await faxios.get("https://api.example.com/users/{id}/posts", {
83
+ pathParams: { id: 42 },
84
+ params: { page: 2, tag: "news" },
85
+ });
86
+ // GET https://api.example.com/users/42/posts?page=2&tag=news
87
+ ```
88
+
89
+ `pathParams` values are `encodeURIComponent`-encoded. A missing or `null` value rejects with
90
+ `ERR_BAD_OPTION_VALUE`.
91
+
92
+ Binary downloads need `responseType`, and a type argument because `data` is `unknown`:
93
+
94
+ ```ts
95
+ import faxios from "@gcmdev/faxios";
96
+
97
+ const { data } = await faxios.get<ArrayBuffer>("https://example.com/report.zip", {
98
+ responseType: "arraybuffer",
99
+ maxContentLength: 50 * 1024 * 1024, // the body is buffered; cap it for untrusted servers
100
+ });
101
+ console.log(data.byteLength);
102
+ ```
103
+
104
+ Unset `responseType` reads the body as text, then JSON-parses it if it parses. `"text"` skips the
105
+ JSON parse; `"blob"`, `"formdata"` and `"stream"` (a `ReadableStream`) are also supported.
106
+
107
+ ### Merge defaults the way faxios does
108
+
109
+ `faxios.create(config)` merges `config` over the parent's defaults with `mergeConfig`:
110
+
111
+ - `url`, `method` and `data` never inherit; they come from the request only.
112
+ - `headers` deep-merge case-insensitively. Group headers by method with `common`, `get`, `post`,
113
+ etc. Flat keys apply to every method and win over the same key in a group. Header values must
114
+ be strings, numbers, string arrays, booleans, `null` or `undefined`; convert anything else with
115
+ `String(...)`.
116
+ - Arrays such as `transformRequest` and `transformResponse` are replaced, not concatenated.
117
+ - An explicit `undefined` in the request clears an inherited `baseURL`, `timeout` or schema.
118
+ - `params`, `auth`, `env` and other plain objects deep-merge.
119
+ - Middleware added with `.use()` is not copied into `create()` children. Register it on each
120
+ instance that needs it.
121
+
122
+ To remove an inherited header for one request, set it to `undefined`. To keep a header off the
123
+ wire entirely, including ones faxios adds itself, set it to `null` or `false`.
124
+
125
+ ### Validate and type responses with a schema
126
+
127
+ Any Standard Schema v1 library works (Zod, Valibot, ArkType). Passing `responseSchema` types
128
+ `response.data` as the schema's output:
129
+
130
+ ```ts
131
+ import faxios, { isSchemaValidationError } from "@gcmdev/faxios";
132
+ import { z } from "zod";
133
+
134
+ const User = z.object({ id: z.number(), name: z.string() });
135
+
136
+ try {
137
+ const { data } = await faxios.get("https://api.example.com/users/1", { responseSchema: User });
138
+ console.log(data.name);
139
+ }
140
+ catch (error) {
141
+ if (isSchemaValidationError(error)) console.error(error.code, error.issues);
142
+ else throw error;
143
+ }
144
+ ```
145
+
146
+ - Order: `pathParamsSchema` → `paramsSchema` → `requestSchema` run before `transformRequest`,
147
+ fail-fast, and nothing is sent when one fails. `responseSchema` runs after `transformResponse`,
148
+ only for responses that pass `validateStatus`.
149
+ - Error codes: `ERR_BAD_PATH_PARAMS_SCHEMA`, `ERR_BAD_PARAMS_SCHEMA`, `ERR_BAD_REQUEST_SCHEMA`,
150
+ `ERR_BAD_RESPONSE_SCHEMA`. `error.issues` holds `{ message, path? }` entries. On
151
+ `ERR_BAD_RESPONSE_SCHEMA`, `error.response.data` is the body the schema rejected. Schemas run
152
+ inside dispatch, so middleware sees the unvalidated config before `next(ctx)`.
153
+ - For reusable typed endpoints, use `api.define(method, url, config)` or `api.route(url, config)`
154
+ rather than wrapping calls by hand. They return plain functions with no `.use()`
155
+ (`api.define(...).use(...)` is a TypeError), so put middleware on the instance and call
156
+ `define()`/`route()` on the value `.use()` returned. Middleware added later still runs (the
157
+ endpoint calls `api.request()` each time), but only that value types plugin options.
158
+ `pathParams` is accepted only when `pathParamsSchema` is set.
159
+
160
+ ```ts
161
+ import faxios from "@gcmdev/faxios";
162
+ import { z } from "zod";
163
+
164
+ const api = faxios
165
+ .create({ baseURL: "https://api.example.com" })
166
+ .use(async (ctx, next) => next(ctx));
167
+ const getUser = api.define("get", "/users/{id}", {
168
+ pathParamsSchema: z.object({ id: z.string() }),
169
+ responseSchema: z.object({ name: z.string() }),
170
+ });
171
+ const { data } = await getUser({ pathParams: { id: "123" } });
172
+ console.log(data.name);
173
+ ```
174
+
175
+ - With a plugin such as `retry()`, see "Define endpoints on a plugin instance" in
176
+ [references/plugins.md](references/plugins.md).
177
+
178
+ ### Cancel requests and apply timeouts
179
+
180
+ ```ts
181
+ import faxios, { FaxiosError, isCancel } from "@gcmdev/faxios";
182
+
183
+ const controller = new AbortController();
184
+ const request = faxios.get("https://api.example.com/search", {
185
+ params: { q: "faxios" },
186
+ signal: controller.signal,
187
+ timeout: 3000,
188
+ });
189
+ controller.abort();
190
+
191
+ try {
192
+ await request;
193
+ }
194
+ catch (error) {
195
+ if (isCancel(error)) console.log("canceled"); // code ERR_CANCELED
196
+ else if (error instanceof FaxiosError && error.code === FaxiosError.ETIMEDOUT) console.log("timed out");
197
+ else throw error;
198
+ }
199
+ ```
200
+
201
+ - Cancellation uses `AbortSignal` only. faxios checks the signal before middleware, before each
202
+ schema step and right before `fetch`, so an abort during pre-flight work sends nothing.
203
+ - A timeout always rejects with `ETIMEDOUT`. `ECONNABORTED` is never raised, and
204
+ `transitional.clarifyTimeoutError` has no effect.
205
+
206
+ ### Handle errors by code
207
+
208
+ ```ts
209
+ import faxios, { isFaxiosError } from "@gcmdev/faxios";
210
+
211
+ try {
212
+ await faxios.get("https://api.example.com/users/404");
213
+ }
214
+ catch (error) {
215
+ if (!isFaxiosError(error)) throw error;
216
+ switch (error.code) {
217
+ case "ERR_BAD_REQUEST": console.log("4xx", error.response?.status); break;
218
+ case "ERR_BAD_RESPONSE": console.log("5xx or unparsable JSON"); break;
219
+ case "ERR_NETWORK": console.log("transport failed", error.cause); break;
220
+ default: throw error;
221
+ }
222
+ }
223
+ ```
224
+
225
+ - Non-2xx statuses reject because of the default `validateStatus`. Pass your own `validateStatus`
226
+ to change which statuses resolve.
227
+ - Transport failures (DNS, refused connection, CORS) reject with `ERR_NETWORK`; the runtime's
228
+ original error is on `error.cause`. `ECONNREFUSED` is not raised as the error's own code.
229
+ - `error.toJSON()` never includes the response; list sensitive config keys in `redact` to mask
230
+ them in that output.
231
+
232
+ ### Add behaviour with `.use()` middleware
233
+
234
+ faxios has no `interceptors`. Middleware wraps each request and runs in registration order on the
235
+ way in and in reverse on the way out:
236
+
237
+ ```ts
238
+ import faxios, { FaxiosError } from "@gcmdev/faxios";
239
+
240
+ const api = faxios
241
+ .create({ baseURL: "https://api.example.com" })
242
+ .use(async (ctx, next) => {
243
+ ctx.config.headers.set("X-Request-Id", crypto.randomUUID());
244
+ try {
245
+ return await next(ctx);
246
+ }
247
+ catch (error) {
248
+ if (error instanceof FaxiosError && error.response?.status === 401) console.warn("signed out");
249
+ throw error;
250
+ }
251
+ });
252
+ ```
253
+
254
+ - Keep the value `.use()` returns; plugins that add options or capabilities type only that value.
255
+ - Return without calling `next` to short-circuit, for example from a cache. Each `next(ctx)` call
256
+ dispatches a fresh copy of `ctx.config`, so calling it again retries from the same input.
257
+ - `api.eject(sameMiddleware)` removes middleware by identity; requests in flight keep running it.
258
+ - `ctx.config.headers` is a `FaxiosHeaders`. Mutate it with `.set()`/`.delete()`, or assign
259
+ another `FaxiosHeaders`; never assign a plain object.
260
+ - `ctx.config.method` is always lower-case in middleware: compare with `"post"`, not `"POST"`.
261
+ - Per-request scratch data goes on `ctx.state`.
262
+
263
+ ### Use the built-in plugins from their subpaths
264
+
265
+ Each built-in plugin has its own subpath and is not exported from the root:
266
+ `authBearer` from `@gcmdev/faxios/plugins/auth-bearer`, `retry` from
267
+ `@gcmdev/faxios/plugins/retry`, `timing` from `@gcmdev/faxios/plugins/timing`. Install them with
268
+ `.use()` on the instance and keep the returned value, because it is the only value typed with the
269
+ plugin's request options (such as `retry: false`). Before writing plugin code, read
270
+ [plugins](references/plugins.md) for a complete installation example.
271
+
272
+ - `authBearer(getToken, { scheme, header, origins, overwrite })` sends the token only to the
273
+ `baseURL` origin when `baseURL` is absolute; otherwise only to relative request URLs. Use
274
+ `origins` to allow more. It leaves an explicit `Authorization` header alone unless
275
+ `overwrite: true`. Install `retry` before it if each attempt should call `getToken` again.
276
+ - `retry` defaults: 3 attempts, statuses 408/429/500/502/503/504 plus `ERR_NETWORK` and
277
+ `ETIMEDOUT`, exponential backoff from 100 ms with full jitter. A 429/503 `Retry-After` sets the
278
+ wait unless `respectRetryAfter: false`. Turn that off when something else, such as a queue
279
+ throttle, already honours `Retry-After`.
280
+ Only GET, HEAD, OPTIONS, PUT, DELETE and QUERY retry; list POST or PATCH in `methods` only when
281
+ the API dedupes repeats. Stream bodies are never replayed. Cancellation never retries. A custom
282
+ `retryOn` replaces the whole default predicate (`statuses`, `ERR_NETWORK`, `ETIMEDOUT`), and a
283
+ `Retry-After` longer than `maxRetryAfter` (default 5 min) rejects without retrying.
284
+ - `timing(onTiming)` reports `{ method, url, attempt?, durationMs, status | error }` with no
285
+ headers or body; `url` has no query string and keeps `{param}` placeholders.
286
+ Install it before `retry` for one event per call, after it for one event per attempt.
287
+ - To write your own plugin, use `definePlugin` from `@gcmdev/faxios/plugins`. The same
288
+ [plugins](references/plugins.md) reference covers authoring.
289
+
290
+ ### Customise the transport through fetch, not adapters
291
+
292
+ There is no `adapter` option. Supply `fetch` itself to swap the transport, for example in tests or
293
+ custom runtimes:
294
+
295
+ ```ts
296
+ import faxios from "@gcmdev/faxios";
297
+
298
+ // Tests or custom runtimes: every request on this instance goes through mockFetch.
299
+ const mockFetch: typeof fetch = async () => Response.json({ ok: true });
300
+ const testApi = faxios.create({ env: { fetch: mockFetch } });
301
+ const { data } = await testApi.get("https://api.example.com/feed"); // { ok: true }
302
+
303
+ // Real fetch, with extra RequestInit fields for this request.
304
+ await faxios.get("https://api.example.com/feed", { fetchOptions: { cache: "no-store" } });
305
+ ```
306
+
307
+ - `fetchOptions` is spread into the init object passed to `fetch`. faxios sets `signal`, `method`,
308
+ `headers`, `body`, `duplex` and `credentials` itself, and those override the same keys in
309
+ `fetchOptions`.
310
+ - Plain-object values inside `fetchOptions` are copied when configs merge; class instances are
311
+ passed by reference.
312
+ - Proxies are runtime configuration, not a faxios option. In Node, the project docs route a
313
+ proxy through `fetchOptions: { dispatcher: new ProxyAgent(url) }` with the project's own
314
+ `undici` dependency (`packages/docs/pages/advanced/fetch-adapter.md`, `MIGRATION_GUIDE.md`).
315
+ faxios passes the instance through to `fetch` but does not test proxying. Browsers, Deno and Bun
316
+ use their platform's proxy settings.
317
+
318
+ ## Import boundaries
319
+
320
+ | Import | Status |
321
+ | --- | --- |
322
+ | `@gcmdev/faxios` | Stable: default `faxios`, `Faxios`, `FaxiosError`, `FaxiosHeaders`, `CanceledError`, `isCancel`, `isFaxiosError`, `isSchemaValidationError`, `mergeConfig`, `toFormData`, `formToJSON`, `HttpStatusCode`, `all`, `create`, `VERSION`, and the types |
323
+ | `@gcmdev/faxios/plugins` | Stable: `definePlugin` only |
324
+ | `@gcmdev/faxios/plugins/auth-bearer`, `/retry`, `/timing` | Stable: one plugin each |
325
+ | `@gcmdev/faxios/unsafe/*` | Internal helpers (`buildFullPath`, `buildURL`, `combineURLs`, `isAbsoluteURL`, `utils`). No stability promise; do not use them in application code, and say so if a task seems to need them |
326
+
327
+ Use `faxios.create()` for instances. An instance made with `new Faxios()` has no `use()` or
328
+ `eject()`.
329
+
330
+ Statics such as `isCancel`, `mergeConfig`, `HttpStatusCode` and `spread` exist on the default
331
+ export only. Instances from `create()` do not have them; import them by name instead.
332
+
333
+ ## Common mistakes
334
+
335
+ 1. **HIGH: Using Axios interceptors.** `api.interceptors.request.use(...)` throws because
336
+ `interceptors` is undefined. Use `.use(async (ctx, next) => ...)`. Axios ran request
337
+ interceptors last-registered-first; faxios middleware runs in registration order.
338
+ Source: `packages/tests/unit/api.test.ts`, `src/lib/core/Faxios.ts`.
339
+ 2. **HIGH: Passing Axios transport options.** `adapter`, `proxy`, `httpAgent`, `httpsAgent`,
340
+ `maxRedirects`, `socketPath`, `decompress` and `cancelToken` are not faxios options. Typed object
341
+ literals reject them, but untyped or spread configs pass and are silently ignored at runtime.
342
+ Use `fetchOptions` or `env.fetch`. Source: `src/lib/types.ts`, `MIGRATION_GUIDE.md`.
343
+ 3. **HIGH: Using `CancelToken`.** It does not exist. Use `AbortController` and `signal`.
344
+ 4. **HIGH: Checking for `ECONNABORTED` on timeout.** faxios raises `ETIMEDOUT`. Code that checks
345
+ `ECONNABORTED` never matches. Source: `src/lib/helpers/composeSignals.ts`.
346
+ 5. **HIGH: Sending an absolute URL through an instance with `baseURL`.** When an instance has a
347
+ `baseURL` and `allowAbsoluteUrls` is unset, faxios appends even an absolute request URL to the
348
+ base: `api.get("https://other.example/x")` requests
349
+ `https://api.example.com/v1/https://other.example/x`. Use a separate instance, or set
350
+ `allowAbsoluteUrls: true` when the absolute URL is trusted. Source:
351
+ `src/lib/core/Faxios.ts` (`resolveAllowAbsoluteUrls`), `src/lib/core/buildFullPath.ts`.
352
+ 6. **MEDIUM: Importing plugins from the root.** `import { retry } from "@gcmdev/faxios"` fails and
353
+ `faxios.plugins` is undefined. Import from `@gcmdev/faxios/plugins/<name>`.
354
+ 7. **MEDIUM: Calling statics on an instance.** `api.isCancel(e)` is undefined on a `create()`
355
+ instance. Use the named import.
356
+ 8. **MEDIUM: Expecting `onUploadProgress` everywhere.** It fires only where `fetch` can stream a
357
+ request body (`duplex: "half"`, for example Node). Browsers generally do not report upload
358
+ progress through fetch; do not promise it there.
359
+ 9. **MEDIUM: Retrying POST by accident or by assumption.** The retry plugin skips POST and PATCH
360
+ unless they are listed in `methods`; a custom `retryOn` cannot override that.
361
+ 10. **MEDIUM: Downloading a binary body without `responseType`.** The bytes are decoded as UTF-8
362
+ text and come back corrupted. Set `responseType: "arraybuffer"` and type the call with
363
+ `get<ArrayBuffer>`. Source: `src/lib/adapters/fetch.ts`.
364
+
365
+ ## Completion
366
+
367
+ - Every import resolves to an entry in the table above; nothing imports `unsafe/*` in application
368
+ code.
369
+ - No `interceptors`, `CancelToken`, `adapter`, `proxy`, `httpAgent` or `ECONNABORTED` remains.
370
+ - Type-check the project. A type error on a config key means faxios does not support it; find the
371
+ faxios equivalent above instead of casting it away.
372
+ - Exercise one success path and one failure path (an aborted signal or a non-2xx response) and
373
+ confirm the error code matches the handling code.
374
+
375
+ ## References
376
+
377
+ - When porting an Axios codebase, read [Axios differences](references/axios-differences.md)
378
+ before changing call sites.
379
+ - When installing `authBearer`, `retry` or `timing`, or writing a reusable plugin or typed
380
+ middleware, read [plugins](references/plugins.md).
@@ -0,0 +1,67 @@
1
+ # Axios differences
2
+
3
+ Read this before porting Axios code to faxios or reviewing a port. faxios keeps Axios's call shape
4
+ (`faxios.get(url, config)`, `response.data`, `create()`, `defaults`), but treat every Axios
5
+ behaviour outside this list as unverified until the installed types and a test prove it.
6
+
7
+ ## Mapping
8
+
9
+ | Axios code | faxios replacement | Notes |
10
+ | --- | --- | --- |
11
+ | `import axios from "axios"` | `import faxios from "@gcmdev/faxios"` | ESM only; use `await import()` from CommonJS |
12
+ | `axios.interceptors.request.use(fn)` | `api.use(async (ctx, next) => { ...; return next(ctx); })` | Registration order, not reverse |
13
+ | `axios.interceptors.response.use(ok, fail)` | `try { const res = await next(ctx); ...; return res } catch (e) { ... }` inside `.use()` | Non-2xx arrives as a rejection. Middleware must return a response, so an interceptor that unwraps to `response.data` can't be ported; take `data` at the call site |
14
+ | `interceptors.request.eject(id)` | `api.eject(sameFunctionOrPlugin)` | By identity, not numeric id |
15
+ | `interceptors.request.clear()` | `eject()` each middleware, or a fresh `create()` | No `clear()` |
16
+ | interceptor `synchronous` / `runWhen` options | `if` inside the middleware for `runWhen` | `synchronous` has no equivalent |
17
+ | `transitional.legacyInterceptorReqResOrdering` | remove it | Throws `ERR_BAD_OPTION` ("Unknown option"), like any unknown `transitional` key |
18
+ | `CancelToken.source()` / `cancelToken` | `AbortController` + `signal` | `isCancel(e)` or `e.code === "ERR_CANCELED"` |
19
+ | `axios.isAxiosError(e)` | `isFaxiosError(e)` (named import) | Type guard |
20
+ | `error.code === "ECONNABORTED"` (timeout) | `error.code === "ETIMEDOUT"` | `clarifyTimeoutError` is inert |
21
+ | `error.code === "ECONNREFUSED"` | `error.code === "ERR_NETWORK"`, details on `error.cause` | All transport failures |
22
+ | `adapter: ...` / custom adapter | `env: { fetch }` or `fetchOptions` | No adapter option exists |
23
+ | `proxy: {...}` / `httpAgent` / `httpsAgent` | Runtime-level proxy config. In Node the project docs pass an `undici` `ProxyAgent` as `fetchOptions.dispatcher`, using the app's own `undici` dependency | Not faxios options; faxios passes the dispatcher to `fetch` but does not test proxying |
24
+ | `maxRedirects`, `beforeRedirect` | fetch follows redirects; `fetchOptions: { redirect: "manual" }` to stop | `ERR_FR_TOO_MANY_REDIRECTS` is never raised |
25
+ | `maxRate`, `socketPath`, `decompress`, `insecureHTTPParser`, `httpVersion`, HTTP/2 options, `lookup`, `family` | none | Removed; ignored at runtime when untyped |
26
+ | `onUploadProgress` | same option | Fires only where fetch streams request bodies (Node); not a browser guarantee |
27
+ | `responseType: "document"` | none in practice | Falls back to text |
28
+ | retry via `axios-retry` | `retry()` from `@gcmdev/faxios/plugins/retry` | POST/PATCH excluded by default |
29
+ | auth header interceptor | `authBearer()` from `@gcmdev/faxios/plugins/auth-bearer` | Sends only to the baseURL origin by default |
30
+
31
+ ## Behaviour that changes silently
32
+
33
+ These ports compile and run but behave differently:
34
+
35
+ 1. **Absolute URL on a `baseURL` instance.** Axios sends an absolute request URL as-is. faxios
36
+ appends it to the instance `baseURL` unless `allowAbsoluteUrls: true` is set on the instance or
37
+ request. Search ports for instance calls with `http://` or `https://` URLs.
38
+ 2. **Untyped configs with removed keys.** A config built with spread or `any` keeps `proxy`,
39
+ `adapter` or `httpAgent` and faxios ignores them. The request then goes direct, without the
40
+ proxy or agent the code expected. Delete the keys and move the behaviour to `fetchOptions`.
41
+ 3. **Interceptor order.** Axios ran request interceptors last-registered-first and response
42
+ interceptors first-registered-first. Middleware runs in registration order on the way in and
43
+ in reverse on the way out, so both sides flip; reorder the `.use()` calls.
44
+ 4. **Timeout handling.** Branches that check `ECONNABORTED` never run.
45
+ 5. **Statics on instances.** `instance.isCancel`, `instance.mergeConfig` and similar are undefined
46
+ on `create()` instances.
47
+
48
+ ## Port checklist
49
+
50
+ - [ ] No `axios` import remains, and no `interceptors`, `CancelToken`, `adapter`, `proxy`,
51
+ `httpAgent`, `httpsAgent` or `ECONNABORTED` reference.
52
+ - [ ] Every instance with `baseURL` is checked for absolute-URL calls.
53
+ - [ ] Error handling branches on faxios codes: `ERR_BAD_REQUEST`, `ERR_BAD_RESPONSE`,
54
+ `ERR_NETWORK`, `ETIMEDOUT`, `ERR_CANCELED`, and the `ERR_BAD_*_SCHEMA` codes if schemas are
55
+ used.
56
+ - [ ] The project type-checks without casts on faxios configs.
57
+ - [ ] One success and one failure path run against the ported client.
58
+
59
+ `MIGRATION_GUIDE.md` section "h) Interceptors replaced by `.use()` middleware" and the docs pages
60
+ `advanced/middleware.md` and `advanced/migrating-from-interceptors.md` show interceptor-to-middleware
61
+ conversions; any `interceptors` code there is the "before" side. The guide's Fetch-Only section
62
+ still says Node 18+ and that custom adapters work through `adapter`. Both are wrong: faxios needs
63
+ Node 24+ and has no `adapter` option.
64
+
65
+ Sources: `MIGRATION_GUIDE.md` (Fetch-Only Migration), `src/lib/types.ts`, `src/lib/core/Faxios.ts`,
66
+ `src/lib/core/buildFullPath.ts`, `src/lib/helpers/composeSignals.ts`,
67
+ `src/lib/adapters/fetch-helpers.ts`, `packages/tests/unit/api.test.ts`.
@@ -0,0 +1,127 @@
1
+ # Plugins
2
+
3
+ Read this before installing the built-in plugins (`authBearer`, `retry`, `timing`), writing a
4
+ reusable faxios plugin, typing middleware options, or sharing a value between plugins. Plain
5
+ one-off middleware (`api.use(async (ctx, next) => ...)`) does not need it.
6
+
7
+ ## Install the built-in plugins
8
+
9
+ ```ts
10
+ import faxios from "@gcmdev/faxios";
11
+ import { authBearer } from "@gcmdev/faxios/plugins/auth-bearer";
12
+ import { retry } from "@gcmdev/faxios/plugins/retry";
13
+ import { timing } from "@gcmdev/faxios/plugins/timing";
14
+
15
+ const api = faxios
16
+ .create({ baseURL: "https://api.example.com" })
17
+ .use(timing(event => console.log(event.method, event.url, event.durationMs)))
18
+ .use(retry({ attempts: 3 }))
19
+ .use(authBearer(async () => "token-from-your-store"));
20
+
21
+ await api.get("/reports", { retry: { attempts: 5 } }); // per-request override
22
+ await api.post("/reports", { title: "Q3" }); // POST is not retried by default
23
+ await api.get("/health", { retry: false });
24
+ ```
25
+
26
+ Check: `faxios.get("/health", { retry: false })` on the default export (or any instance without
27
+ `retry()` installed) is a type error. Use the value `.use()` returned. The option defaults and
28
+ ordering rules are in the SKILL.md "Use the built-in plugins from their subpaths" section.
29
+
30
+ ## Define endpoints on a plugin instance
31
+
32
+ `define()` and `route()` return plain functions with no `.use()`. Install plugins first and call
33
+ `define()` on the value `.use()` returned, so the endpoint's per-call config types `retry`:
34
+
35
+ ```ts
36
+ import faxios from "@gcmdev/faxios";
37
+ import { retry } from "@gcmdev/faxios/plugins/retry";
38
+ import { z } from "zod";
39
+
40
+ const api = faxios.create({ baseURL: "https://tags.tiqcdn.com" }).use(retry());
41
+ const getDistro = api.define("get", "/utag/{account}/{profile}/prod/distro.zip", {
42
+ pathParamsSchema: z.object({ account: z.string(), profile: z.string() }),
43
+ });
44
+ await getDistro({ pathParams: { account: "acme", profile: "main" }, retry: { attempts: 2 } });
45
+ ```
46
+
47
+ ## Build a plugin with `definePlugin`
48
+
49
+ `definePlugin` comes from `@gcmdev/faxios/plugins`. It returns the same object and only changes the
50
+ types. faxios infers the plugin's slots:
51
+
52
+ - **options**: request options the plugin reads, from the first type argument of the middleware's
53
+ `ctx: FaxiosContext<Options, Capabilities>` annotation. They become valid keys on every
54
+ config-taking call of the instance `.use()` returns.
55
+ - **requires**: capabilities that must already be installed, from the second type argument.
56
+ - **provides**: capabilities this plugin adds to `ctx.capabilities`, from the `provides` value.
57
+
58
+ ```ts
59
+ import faxios, { type FaxiosContext } from "@gcmdev/faxios";
60
+ import { definePlugin } from "@gcmdev/faxios/plugins";
61
+
62
+ type TraceOptions = { trace?: string | false };
63
+
64
+ export function traceHeader(header = "X-Trace-Id") {
65
+ return definePlugin({
66
+ name: "traceHeader",
67
+ middleware: async (ctx: FaxiosContext<TraceOptions>, next) => {
68
+ const trace = ctx.config.trace;
69
+ if (trace !== false) ctx.config.headers.set(header, trace ?? crypto.randomUUID());
70
+ return next(ctx);
71
+ },
72
+ });
73
+ }
74
+
75
+ const api = faxios.create({ baseURL: "https://api.example.com" }).use(traceHeader());
76
+ await api.get("/orders", { trace: "abc-123" }); // `trace` type-checks only on `api`
77
+ ```
78
+
79
+ Check: `faxios.get("/orders", { trace: "x" })` on an instance without the plugin is a type error.
80
+
81
+ ## Require a capability from another plugin
82
+
83
+ `authBearer` provides `{ auth: { getToken(): Promise<string> } }`, exported as
84
+ `AuthBearerCapability`. A plugin that needs it declares it in its context type, and `.use()` rejects
85
+ installing it before `authBearer`:
86
+
87
+ ```ts
88
+ import faxios, { FaxiosError, type FaxiosContext } from "@gcmdev/faxios";
89
+ import { definePlugin } from "@gcmdev/faxios/plugins";
90
+ import { authBearer, type AuthBearerCapability } from "@gcmdev/faxios/plugins/auth-bearer";
91
+
92
+ function refreshOn401(refresh: () => Promise<void>) {
93
+ return definePlugin({
94
+ name: "refreshOn401",
95
+ middleware: async (ctx: FaxiosContext<unknown, AuthBearerCapability>, next) => {
96
+ try {
97
+ return await next(ctx);
98
+ }
99
+ catch (error) {
100
+ if (!(error instanceof FaxiosError) || error.response?.status !== 401) throw error;
101
+ await refresh();
102
+ ctx.config.headers.set("Authorization", `Bearer ${await ctx.capabilities.auth.getToken()}`);
103
+ return next(ctx);
104
+ }
105
+ },
106
+ });
107
+ }
108
+
109
+ let token = "old";
110
+ const api = faxios
111
+ .create({ baseURL: "https://api.example.com" })
112
+ .use(authBearer(() => token))
113
+ .use(refreshOn401(async () => { token = "new"; }));
114
+ ```
115
+
116
+ ## Rules `.use()` enforces at runtime
117
+
118
+ - `name` must be a non-empty own string, otherwise `ERR_BAD_OPTION_VALUE`.
119
+ - Two plugins on one instance cannot provide the same capability name (`ERR_BAD_OPTION`).
120
+ - Built-in plugin options are validated strictly: unknown or mistyped keys throw
121
+ `ERR_BAD_OPTION` / `ERR_BAD_OPTION_VALUE` when the plugin is created or when a per-request
122
+ override is read.
123
+ - `create()` children do not inherit middleware or plugins.
124
+
125
+ Sources: `src/lib/plugins/definePlugin.ts`, `src/lib/types.ts` (`FaxiosContext`, `FaxiosPlugin`),
126
+ `src/lib/core/Faxios.ts` (`use`), `packages/tests/unit/plugins/authBearer.test.ts`,
127
+ `packages/tests/unit/plugins/definePlugin.test.ts`.
package/src/index.ts ADDED
@@ -0,0 +1,57 @@
1
+ // @ts-self-types="./index.d.ts"
2
+ /* eslint-disable no-barrel-files/no-barrel-files */
3
+ import faxios from "./lib/faxios.ts";
4
+ import type { FaxiosInstance, FaxiosStatic } from "./lib/faxios.ts";
5
+ import type { CreateFaxiosDefaults } from "./lib/types.ts";
6
+
7
+ // Static re-exports so the emitted .d.ts references source modules.
8
+ // zshy rewrites .ts -> .js for static import/export, but NOT for inline
9
+ // import() type expressions (ImportTypeNode). Destructuring these off the
10
+ // runtime instance forced TS to emit the broken inline `import("./x.ts")` form.
11
+ export { default as Faxios } from "./lib/core/Faxios.ts";
12
+ export { default as FaxiosError, isSchemaValidationError } from "./lib/core/FaxiosError.ts";
13
+ export type { SchemaValidationError } from "./lib/core/FaxiosError.ts";
14
+ export { default as CanceledError, default as Cancel } from "./lib/cancel/CanceledError.ts";
15
+ export { default as isCancel } from "./lib/cancel/isCancel.ts";
16
+ export { default as isFaxiosError } from "./lib/helpers/isFaxiosError.ts";
17
+ export { default as toFormData } from "./lib/helpers/toFormData.ts";
18
+ export { default as FaxiosHeaders } from "./lib/core/FaxiosHeaders.ts";
19
+ export { default as HttpStatusCode } from "./lib/helpers/HttpStatusCode.ts";
20
+ export { default as mergeConfig } from "./lib/core/mergeConfig.ts";
21
+ export { VERSION } from "./lib/env/data.ts";
22
+
23
+ export type { FaxiosInstance, FaxiosStatic } from "./lib/faxios.ts";
24
+ export type { StandardSchemaV1 } from "./lib/types/standard-schema.ts";
25
+ export type { BasePerCallConfig, DefineConfig, DefinedEndpoint, FaxiosLike, PerCallConfig } from "./lib/core/define.ts";
26
+ export type { RouteConfig, RouteMethodConfig, RouteBuilder } from "./lib/core/route.ts";
27
+
28
+ export type {
29
+ FaxiosRequestConfig,
30
+ InternalFaxiosRequestConfig,
31
+ FaxiosResponse,
32
+ FaxiosRequestHeaders,
33
+ FaxiosResponseHeadersLike,
34
+ FaxiosHeaderValue,
35
+ Method,
36
+ ResponseType,
37
+ GenericHTMLFormElement,
38
+ RawFaxiosRequestConfig,
39
+ FaxiosPromise,
40
+ CreateFaxiosDefaults,
41
+ FaxiosConfigHeaders,
42
+ RawFaxiosRequestHeaders,
43
+ HeadersDefaults,
44
+ FaxiosContext,
45
+ FaxiosNext,
46
+ FaxiosMiddleware,
47
+ FaxiosPlugin
48
+ } from "./lib/types.ts";
49
+
50
+ // Instance-synthesized members (no 1:1 source module). Types are self-contained
51
+ // (all/formToJSON) or annotated with statically imported types (create), so no
52
+ // inline import() is emitted. Runtime values are the same references as on the instance.
53
+ export const all: FaxiosStatic["all"] = faxios.all;
54
+ export const formToJSON: FaxiosStatic["formToJSON"] = faxios.formToJSON;
55
+ export const create: (instanceConfig?: CreateFaxiosDefaults) => FaxiosInstance = faxios.create;
56
+
57
+ export { faxios as default };