dexix-request 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/LICENSE +21 -0
- package/README.md +328 -0
- package/dist/index.cjs +3 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +184 -0
- package/dist/index.d.ts +184 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2026-07-12
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial public release of DexiX Request.
|
|
13
|
+
- Callable instance API: `dx(url)`, `dx.get`, `dx.post`, `dx.put`, `dx.patch`, `dx.delete`, `dx.head`, `dx.options`.
|
|
14
|
+
- `dx.create()` for scoped instances with `baseURL`, default `headers`, and other defaults.
|
|
15
|
+
- Automatic JSON parsing of response bodies — no more `response.json()`.
|
|
16
|
+
- Automatic JSON serialization of plain object and array request bodies.
|
|
17
|
+
- Native support for `FormData`, `Blob`, `URLSearchParams`, `ArrayBuffer`, typed arrays, and `ReadableStream` bodies.
|
|
18
|
+
- Built-in request `timeout`, composable with a user-supplied `AbortSignal`.
|
|
19
|
+
- Custom error classes: `NetworkError`, `TimeoutError`, `HTTPError`, `ParseError`, all extending a shared `DexiXError` base with `status`, `headers`, `url`, `request`, and `response`.
|
|
20
|
+
- Full TypeScript generics: `dx.get<T>()`, `dx.post<T>()`, etc., with zero use of `any` in the public API.
|
|
21
|
+
- Zero runtime dependencies. ESM and CommonJS builds, tree-shakeable, under 5KB gzipped.
|
|
22
|
+
- `onRequest` / `onResponse` hooks for logging, auth injection, and observability.
|
|
23
|
+
- Full test suite covering GET, POST, PUT, DELETE, error handling, timeouts, and JSON parsing.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DexiX Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="https://raw.githubusercontent.com/dexix-dev/dexix-request/main/.github/logo-placeholder.svg" width="88" height="88" alt="DexiX Request logo" />
|
|
4
|
+
|
|
5
|
+
# DexiX Request
|
|
6
|
+
|
|
7
|
+
**If Axios were redesigned from scratch in 2026.**
|
|
8
|
+
|
|
9
|
+
A tiny, modern, zero-dependency HTTP client for JavaScript and TypeScript — for the browser, Node.js, and React.
|
|
10
|
+
|
|
11
|
+
[](https://www.npmjs.com/package/dexix-request)
|
|
12
|
+
[](https://www.npmjs.com/package/dexix-request)
|
|
13
|
+
[](https://bundlephobia.com/package/dexix-request)
|
|
14
|
+
[](https://github.com/dexix-dev/dexix-request/actions/workflows/ci.yml)
|
|
15
|
+
[](https://www.npmjs.com/package/dexix-request)
|
|
16
|
+
[](./LICENSE)
|
|
17
|
+
[](./package.json)
|
|
18
|
+
|
|
19
|
+
[Quick Start](#quick-start) · [Features](#features) · [API Reference](#api-reference) · [Why DexiX](#why-dexix-request) · [Comparison](#comparison-with-axios) · [FAQ](#faq)
|
|
20
|
+
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install dexix-request
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pnpm add dexix-request
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
yarn add dexix-request
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
No peer dependencies. No polyfills required in any environment that has `fetch` (all evergreen browsers, and Node.js 20+).
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import dx from "dexix-request";
|
|
45
|
+
|
|
46
|
+
// Calling the instance directly performs a GET request.
|
|
47
|
+
const users = await dx("/users");
|
|
48
|
+
|
|
49
|
+
// Method helpers for everything else.
|
|
50
|
+
const user = await dx.get<User>("/users/1");
|
|
51
|
+
|
|
52
|
+
await dx.post("/posts", {
|
|
53
|
+
title: "Hello DexiX",
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Scoped instances for talking to a specific API.
|
|
57
|
+
const api = dx.create({
|
|
58
|
+
baseURL: "https://api.example.com",
|
|
59
|
+
headers: { Authorization: "Bearer token" },
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const profile = await api("/me");
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
That's it. No `response.json()`. No `axios.create()` boilerplate. No config objects three levels deep.
|
|
66
|
+
|
|
67
|
+
## Features
|
|
68
|
+
|
|
69
|
+
- ✅ **Extremely simple API** — call the instance directly, or use `.get` / `.post` / `.put` / `.patch` / `.delete` / `.head` / `.options`
|
|
70
|
+
- ✅ **Automatic JSON** — request bodies are serialized and response bodies are parsed for you
|
|
71
|
+
- ✅ **Zero dependencies** — nothing to audit, nothing to update, nothing to break
|
|
72
|
+
- ✅ **Tiny** — ~2KB gzipped, tree-shakeable, side-effect free
|
|
73
|
+
- ✅ **Modern TypeScript** — full generics, strict types, no `any` in the public API
|
|
74
|
+
- ✅ **Built on the platform** — `fetch`, `AbortController`, `URLSearchParams`, `ReadableStream`, `FormData` — nothing reinvented
|
|
75
|
+
- ✅ **Composable timeouts** — `timeout` and a caller-supplied `AbortSignal` work together, not against each other
|
|
76
|
+
- ✅ **Rich errors** — `NetworkError`, `TimeoutError`, `HTTPError`, and `ParseError`, each carrying the request and response
|
|
77
|
+
- ✅ **Works everywhere** — browser, Node.js 20+, React, Next.js, Vite, ESM, and CommonJS
|
|
78
|
+
|
|
79
|
+
## Examples
|
|
80
|
+
|
|
81
|
+
### JavaScript
|
|
82
|
+
|
|
83
|
+
```js
|
|
84
|
+
import dx from "dexix-request";
|
|
85
|
+
|
|
86
|
+
const todos = await dx.get("https://api.example.com/todos", {
|
|
87
|
+
query: { userId: 1 },
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const created = await dx.post("https://api.example.com/todos", {
|
|
91
|
+
title: "Ship DexiX Request",
|
|
92
|
+
completed: false,
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### TypeScript
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
import dx from "dexix-request";
|
|
100
|
+
|
|
101
|
+
interface Todo {
|
|
102
|
+
id: number;
|
|
103
|
+
title: string;
|
|
104
|
+
completed: boolean;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const todos = await dx.get<Todo[]>("https://api.example.com/todos");
|
|
108
|
+
const todo = await dx.post<Todo>("https://api.example.com/todos", {
|
|
109
|
+
title: "Ship DexiX Request",
|
|
110
|
+
completed: false,
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### React
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
import { useEffect, useState } from "react";
|
|
118
|
+
import dx, { HTTPError } from "dexix-request";
|
|
119
|
+
|
|
120
|
+
function useUser(id: number) {
|
|
121
|
+
const [user, setUser] = useState<User | null>(null);
|
|
122
|
+
const [error, setError] = useState<string | null>(null);
|
|
123
|
+
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
const controller = new AbortController();
|
|
126
|
+
|
|
127
|
+
dx.get<User>(`/users/${id}`, { signal: controller.signal })
|
|
128
|
+
.then(setUser)
|
|
129
|
+
.catch((err) => {
|
|
130
|
+
if (err instanceof HTTPError && err.status === 404) {
|
|
131
|
+
setError("User not found");
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
return () => controller.abort();
|
|
136
|
+
}, [id]);
|
|
137
|
+
|
|
138
|
+
return { user, error };
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
More complete examples live in [`examples/`](./examples): [Node.js](./examples/node.mjs), [browser](./examples/browser.js), [React](./examples/react-example.tsx), and [TypeScript](./examples/typescript-example.ts).
|
|
143
|
+
|
|
144
|
+
## API Reference
|
|
145
|
+
|
|
146
|
+
### `dx(url, config?)`
|
|
147
|
+
|
|
148
|
+
Performs a `GET` request and resolves with the parsed response body. Equivalent to `dx.get(url, config)`.
|
|
149
|
+
|
|
150
|
+
### `dx.get<T>(url, config?)`
|
|
151
|
+
|
|
152
|
+
### `dx.post<T>(url, body?, config?)`
|
|
153
|
+
|
|
154
|
+
### `dx.put<T>(url, body?, config?)`
|
|
155
|
+
|
|
156
|
+
### `dx.patch<T>(url, body?, config?)`
|
|
157
|
+
|
|
158
|
+
### `dx.delete<T>(url, config?)`
|
|
159
|
+
|
|
160
|
+
### `dx.head(url, config?)`
|
|
161
|
+
|
|
162
|
+
### `dx.options<T>(url, config?)`
|
|
163
|
+
|
|
164
|
+
Every method returns a `Promise<T>` that resolves with the already-parsed response body, or rejects with a [DexiX error](#error-handling).
|
|
165
|
+
|
|
166
|
+
### `dx.create(config?)`
|
|
167
|
+
|
|
168
|
+
Creates a new, independent instance with its own defaults. Config passed to individual requests is merged on top of (and overrides) the instance's defaults.
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
const api = dx.create({
|
|
172
|
+
baseURL: "https://api.example.com",
|
|
173
|
+
headers: { "X-App": "my-app" },
|
|
174
|
+
timeout: 10_000,
|
|
175
|
+
});
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### `RequestConfig`
|
|
179
|
+
|
|
180
|
+
| Option | Type | Description |
|
|
181
|
+
| --------------- | ---------------------------------------- | ----------------------------------------------------------------|
|
|
182
|
+
| `baseURL` | `string` | Prepended to relative URLs. |
|
|
183
|
+
| `headers` | `HeadersInit \| Record<string, string>` | Merged with instance defaults; per-request wins. |
|
|
184
|
+
| `query` | `Record<string, ...>` | Serialized into the URL's query string. Arrays become repeated keys. |
|
|
185
|
+
| `body` | `BodyInit \| object \| unknown[]` | Plain objects/arrays are JSON-serialized automatically. |
|
|
186
|
+
| `timeout` | `number` | Milliseconds before the request is aborted with `TimeoutError`. |
|
|
187
|
+
| `signal` | `AbortSignal` | Composed with the internal timeout signal. |
|
|
188
|
+
| `responseType` | `"json" \| "text" \| "blob" \| "arrayBuffer" \| "stream"` | Overrides automatic response parsing. |
|
|
189
|
+
| `credentials`, `cache`, `redirect`, `referrerPolicy`, `mode` | — | Forwarded straight to `fetch`. |
|
|
190
|
+
| `onRequest` | `(request: Request) => void` | Called with the final `Request` before it's sent. |
|
|
191
|
+
| `onResponse` | `(response: Response) => void` | Called with the raw `Response` before the body is parsed. |
|
|
192
|
+
|
|
193
|
+
## Error Handling
|
|
194
|
+
|
|
195
|
+
DexiX Request never throws a bare `Error`. Every failure is one of four typed classes, all extending `DexiXError`:
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
import dx, { NetworkError, TimeoutError, HTTPError, ParseError } from "dexix-request";
|
|
199
|
+
|
|
200
|
+
try {
|
|
201
|
+
await dx.get("/users/1");
|
|
202
|
+
} catch (error) {
|
|
203
|
+
if (error instanceof HTTPError) {
|
|
204
|
+
// Server responded with a non-2xx status.
|
|
205
|
+
console.error(error.status, error.response?.data);
|
|
206
|
+
} else if (error instanceof TimeoutError) {
|
|
207
|
+
// Request exceeded `timeout`.
|
|
208
|
+
console.error(`Timed out after ${error.timeout}ms`);
|
|
209
|
+
} else if (error instanceof NetworkError) {
|
|
210
|
+
// The request never reached a server (offline, DNS, CORS, etc).
|
|
211
|
+
console.error(error.message);
|
|
212
|
+
} else if (error instanceof ParseError) {
|
|
213
|
+
// A response body couldn't be parsed as JSON/text/etc.
|
|
214
|
+
console.error(error.message);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Every DexiX error carries:
|
|
220
|
+
|
|
221
|
+
- `message` — human-readable description
|
|
222
|
+
- `status` — HTTP status code, when a response was received
|
|
223
|
+
- `headers` — response `Headers`, when a response was received
|
|
224
|
+
- `url` — the fully-resolved request URL
|
|
225
|
+
- `request` — `{ url, method, headers, body }` describing what was sent
|
|
226
|
+
- `response` — `{ data, status, statusText, headers, url }`, when available
|
|
227
|
+
|
|
228
|
+
## Why DexiX Request
|
|
229
|
+
|
|
230
|
+
Most HTTP clients fall into one of two camps: a thin `fetch` wrapper that still makes you write `response.json()` everywhere, or a heavyweight library carrying years of legacy API surface and a dependency tree of its own.
|
|
231
|
+
|
|
232
|
+
DexiX Request is neither. It's built directly on the platform primitives that already ship in every modern runtime — `fetch`, `AbortController`, `Headers`, `URLSearchParams`, `FormData`, `ReadableStream` — and adds exactly one thing on top: an API that gets out of your way.
|
|
233
|
+
|
|
234
|
+
- No dependencies to audit or update.
|
|
235
|
+
- No custom body-parsing logic to trust — you get real `Headers`, real `Request`, real `Response` under the hood.
|
|
236
|
+
- No configuration required to get sensible behavior; every option is there for when you need to override it, not because you have to set it.
|
|
237
|
+
|
|
238
|
+
## Comparison with Axios
|
|
239
|
+
|
|
240
|
+
| | DexiX Request | Axios |
|
|
241
|
+
| --- | --- | --- |
|
|
242
|
+
| Dependencies | 0 | 0 (as of v1, but larger internal surface) |
|
|
243
|
+
| Bundle size (gzip) | ~2KB | ~13KB |
|
|
244
|
+
| Transport | `fetch` | `XMLHttpRequest` (browser) / `http` (Node) |
|
|
245
|
+
| TypeScript | Written in TS, strict, no `any` | Typed via bundled `.d.ts`, some `any` |
|
|
246
|
+
| Interceptors | `onRequest` / `onResponse` hooks | Interceptor chain |
|
|
247
|
+
| Cancellation | Native `AbortSignal`, composable with `timeout` | Native `AbortSignal` (v1+) or legacy `CancelToken` |
|
|
248
|
+
| Default body parsing | Automatic JSON | Automatic JSON |
|
|
249
|
+
| Node.js support | 20+ (uses global `fetch`) | Broad, including legacy Node |
|
|
250
|
+
| Instance creation | `dx.create(config)` | `axios.create(config)` |
|
|
251
|
+
|
|
252
|
+
DexiX Request intentionally supports fewer legacy environments in exchange for a smaller, simpler, more predictable core. If you need to support Node.js < 18 or Internet Explorer, Axios remains the better fit.
|
|
253
|
+
|
|
254
|
+
## Roadmap
|
|
255
|
+
|
|
256
|
+
- [ ] Request/response interceptor chains (beyond `onRequest`/`onResponse`)
|
|
257
|
+
- [ ] Built-in retry with configurable backoff
|
|
258
|
+
- [ ] Upload/download progress events
|
|
259
|
+
- [ ] Automatic request deduplication
|
|
260
|
+
- [ ] Optional plugin for schema validation (Zod/Valibot) on responses
|
|
261
|
+
|
|
262
|
+
Have an idea? [Open an issue](https://github.com/dexix-dev/dexix-request/issues).
|
|
263
|
+
|
|
264
|
+
## Browser Support
|
|
265
|
+
|
|
266
|
+
All browsers with `fetch`, `AbortController`, and `URLSearchParams` support — effectively every browser released since 2017 (Chrome 66+, Firefox 60+, Safari 12+, Edge 79+). DexiX Request does not include or require any polyfills.
|
|
267
|
+
|
|
268
|
+
## Performance
|
|
269
|
+
|
|
270
|
+
- **Bundle size:** ~2KB gzipped, well under the 5KB target
|
|
271
|
+
- **Zero dependencies:** nothing extra ships in your `node_modules` or your bundle
|
|
272
|
+
- **Tree-shakeable:** unused exports (individual error classes, `createInstance`) are dropped by any modern bundler
|
|
273
|
+
- **Minimal allocations:** a single `Headers` merge and a single `Request` construction per call — no intermediate wrapper objects
|
|
274
|
+
|
|
275
|
+
## Developer Experience
|
|
276
|
+
|
|
277
|
+
- Every public function is documented with JSDoc, so your editor shows real descriptions, not just type signatures.
|
|
278
|
+
- Errors are specific and typed, so `catch` blocks can branch with `instanceof` instead of parsing error strings.
|
|
279
|
+
- `dx.create()` returns a fully independent instance — no shared mutable state, no surprises across modules.
|
|
280
|
+
|
|
281
|
+
## Contributing
|
|
282
|
+
|
|
283
|
+
Contributions are welcome. To get started:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
git clone https://github.com/dexix-dev/dexix-request.git
|
|
287
|
+
cd dexix-request/packages/request
|
|
288
|
+
npm install
|
|
289
|
+
npm run test
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
Please open an issue before starting work on a large change, and make sure `npm run typecheck` and `npm run test` both pass before opening a pull request.
|
|
293
|
+
|
|
294
|
+
## FAQ
|
|
295
|
+
|
|
296
|
+
**Does DexiX Request work in Node.js?**
|
|
297
|
+
Yes — Node.js 20+ ships a global `fetch` implementation, so DexiX Request works with no extra setup.
|
|
298
|
+
|
|
299
|
+
**Does it support CommonJS?**
|
|
300
|
+
Yes. The published package includes both ESM (`dist/index.js`) and CommonJS (`dist/index.cjs`) builds, selected automatically via `package.json#exports`.
|
|
301
|
+
|
|
302
|
+
**Can I use it with Next.js Server Components / Route Handlers?**
|
|
303
|
+
Yes — DexiX Request is just `fetch` under the hood, so it works anywhere `fetch` is available, including the Edge Runtime.
|
|
304
|
+
|
|
305
|
+
**How do I send `multipart/form-data`?**
|
|
306
|
+
Pass a `FormData` instance as the body — DexiX Request passes it through untouched so the platform can set the correct multipart boundary.
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
const form = new FormData();
|
|
310
|
+
form.append("file", file);
|
|
311
|
+
await dx.post("/upload", form);
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**How do I cancel a request?**
|
|
315
|
+
Pass an `AbortSignal` via `signal`, or set a `timeout` — both work together.
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
const controller = new AbortController();
|
|
319
|
+
dx.get("/slow", { signal: controller.signal });
|
|
320
|
+
controller.abort();
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**Does DexiX Request retry failed requests automatically?**
|
|
324
|
+
Not yet — automatic retry with backoff is on the [roadmap](#roadmap). Today, wrap a call in your own retry logic if needed.
|
|
325
|
+
|
|
326
|
+
## License
|
|
327
|
+
|
|
328
|
+
[MIT](./LICENSE) © DexiX Contributors
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var i=class extends Error{request;response;status;headers;url;constructor(t,r,n){super(t),this.name="DexiXError",this.request=r,this.response=n,this.status=n?.status,this.headers=n?.headers,this.url=r.url,Object.setPrototypeOf(this,new.target.prototype);}};var c=class extends i{constructor(t,r){super(`Request failed with status ${r.status} (${r.statusText}) for ${t.url}`,t,r),this.name="HTTPError";}};var d=class extends i{constructor(t,r,n){super(t||"Network request failed",r),this.name="NetworkError",n!==void 0&&(this.cause=n);}};var m=class extends i{timeout;constructor(t,r){super(`Request to ${t.url} timed out after ${r}ms`,t),this.name="TimeoutError",this.timeout=r;}};function C(e){return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(e)}function k(e,t){if(!e||C(t))return t;let r=e.endsWith("/")?e.slice(0,-1):e,n=t.startsWith("/")?t:`/${t}`;return `${r}${n}`}function H(e,t){if(!t||Object.keys(t).length===0)return e;let[r,n=""]=e.split("?"),o=new URLSearchParams(n);for(let[f,u]of Object.entries(t))if(u!=null)if(Array.isArray(u))for(let b of u)o.append(f,String(b));else o.append(f,String(u));let s=o.toString();return s?`${r}?${s}`:r}function q(e,t,r){let n=k(e??"",t);return H(n,r)}function l(...e){let t=new Headers;for(let r of e)if(r){if(r instanceof Headers){r.forEach((n,o)=>{t.set(o,n);});continue}if(Array.isArray(r)){for(let[n,o]of r)t.set(n,o);continue}for(let[n,o]of Object.entries(r))o===void 0?t.delete(n):t.set(n,o);}return t}function R(e,t){return {...e,...t,headers:l(e.headers,t.headers),query:{...e.query,...t.query}}}function E(e){if(typeof e!="object"||e===null)return false;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function S(e){return typeof e=="string"||e instanceof FormData||e instanceof Blob||e instanceof URLSearchParams||e instanceof ArrayBuffer||ArrayBuffer.isView(e)||e instanceof ReadableStream}function w(e){return e==null?{body:void 0}:S(e)?e instanceof FormData?{body:e}:e instanceof URLSearchParams?{body:e,contentType:"application/x-www-form-urlencoded;charset=UTF-8"}:typeof e=="string"?{body:e,contentType:"text/plain;charset=UTF-8"}:{body:e}:E(e)||Array.isArray(e)?{body:JSON.stringify(e),contentType:"application/json;charset=UTF-8"}:{body:JSON.stringify(e),contentType:"application/json;charset=UTF-8"}}var x=class extends i{constructor(t,r,n){super(`Failed to parse response body from ${t.url}`,t,r),this.name="ParseError",n!==void 0&&(this.cause=n);}};var O=new Set([204,205,304]);function A(e){let t=e.headers.get("content-type")??"";return t.includes("application/json")||t.includes("+json")?"json":t.startsWith("text/")?"text":"json"}async function h(e,t,r){if(t.method==="HEAD"||O.has(e.status))return;let n=r??A(e);try{switch(n){case "json":{let o=await e.text();return o.length===0?void 0:JSON.parse(o)}case "text":return await e.text();case "blob":return await e.blob();case "arrayBuffer":return await e.arrayBuffer();case "stream":return e.body;default:return await e.text()}}catch(o){let s={data:void 0,status:e.status,statusText:e.statusText,headers:e.headers,url:e.url||t.url};throw new x(t,s,o)}}function D(e,t){if(!t||t<=0)return {signal:e,cancel:()=>{},didTimeout:()=>false};let r=new AbortController,n=false,o=setTimeout(()=>{n=true,r.abort();},t),s=()=>r.abort();e?.addEventListener("abort",s,{once:true});let f=()=>{clearTimeout(o),e?.removeEventListener("abort",s);};return {signal:r.signal,cancel:f,didTimeout:()=>n}}async function j(e){let{body:t,contentType:r}=w(e.body),n=l(r?{"content-type":r}:void 0,e.headers),o=q(e.baseURL,e.url,e.query),s={url:o,method:e.method,headers:n,body:e.body},{signal:f,cancel:u,didTimeout:b}=D(e.signal,e.timeout),I={method:e.method,headers:n,body:e.method==="GET"||e.method==="HEAD"?void 0:t,signal:f,credentials:e.credentials,cache:e.cache,redirect:e.redirect,referrerPolicy:e.referrerPolicy,mode:e.mode},X=new Request(o,I);e.onRequest&&await e.onRequest(X);let a;try{a=await fetch(X);}catch(p){throw u(),p instanceof DOMException&&p.name==="AbortError"?b()?new m(s,e.timeout??0):p:new d(p instanceof Error?p.message:"Network request failed",s,p)}if(u(),e.onResponse&&await e.onResponse(a),!a.ok){let P={data:await h(a,s,e.responseType).catch(()=>{}),status:a.status,statusText:a.statusText,headers:a.headers,url:a.url||o};throw new c(s,P)}return h(a,s,e.responseType)}function y(e,t,r,n){let o={...R(e,n??{}),method:t,url:r};return j(o)}function g(e,t,r,n,o){return y(e,t,r,{...o,body:n??o?.body})}function T(e={}){let t=((r,n)=>y(e,"GET",r,n));return t.get=(r,n)=>y(e,"GET",r,n),t.post=(r,n,o)=>g(e,"POST",r,n,o),t.put=(r,n,o)=>g(e,"PUT",r,n,o),t.patch=(r,n,o)=>g(e,"PATCH",r,n,o),t.delete=(r,n)=>y(e,"DELETE",r,n),t.head=(r,n)=>y(e,"HEAD",r,n),t.options=(r,n)=>y(e,"OPTIONS",r,n),Object.defineProperty(t,"defaults",{value:e,writable:false,enumerable:true}),t.create=r=>T(R(e,r??{})),t}var B=T();var Ee=B;
|
|
2
|
+
exports.DexiXError=i;exports.HTTPError=c;exports.NetworkError=d;exports.ParseError=x;exports.TimeoutError=m;exports.createInstance=T;exports.default=Ee;//# sourceMappingURL=index.cjs.map
|
|
3
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors/DexiXError.ts","../src/errors/HTTPError.ts","../src/errors/NetworkError.ts","../src/errors/TimeoutError.ts","../src/utils/buildURL.ts","../src/utils/mergeHeaders.ts","../src/utils/mergeConfig.ts","../src/utils/isPlainObject.ts","../src/utils/serializeBody.ts","../src/errors/ParseError.ts","../src/utils/parseResponse.ts","../src/utils/combineSignals.ts","../src/core/dispatch.ts","../src/core/instance.ts","../src/index.ts"],"names":["DexiXError","message","request","response","HTTPError","NetworkError","cause","TimeoutError","timeout","isAbsoluteURL","url","joinURL","baseURL","trimmedBase","trimmedPath","appendQuery","query","path","existingSearch","params","key","value","item","search","buildURL","joined","mergeHeaders","sources","result","source","mergeConfig","parent","child","isPlainObject","prototype","isNativeBodyType","serializeBody","body","ParseError","EMPTY_STATUS_CODES","inferResponseType","contentType","parseResponse","responseType","type","text","failedResponse","combineSignals","userSignal","controller","timedOut","timer","onUserAbort","cancel","dispatch","config","headers","requestInfo","signal","didTimeout","init","errorResponse","defaults","method","resolved","requestWithBody","createInstance","instance","dx","index_default"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { DexiXRequestInfo, DexiXResponse } from \"../types/index.js\";\n\n/**\n * Base class for every error thrown by DexiX Request.\n * All DexiX errors carry the originating request and, when available,\n * the response that was received.\n */\nexport class DexiXError extends Error {\n /** The request that caused this error. */\n public readonly request: DexiXRequestInfo;\n /** The response received, if any (absent for network/timeout errors). */\n public readonly response?: DexiXResponse;\n /** HTTP status code, if a response was received. */\n public readonly status?: number;\n /** Response headers, if a response was received. */\n public readonly headers?: Headers;\n /** The request URL. */\n public readonly url: string;\n\n public constructor(\n message: string,\n request: DexiXRequestInfo,\n response?: DexiXResponse,\n ) {\n super(message);\n this.name = \"DexiXError\";\n this.request = request;\n this.response = response;\n this.status = response?.status;\n this.headers = response?.headers;\n this.url = request.url;\n\n // Restore the correct prototype chain when compiled down to ES5-style\n // targets (not an issue at ES2022, but harmless and defensive).\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","import { DexiXError } from \"./DexiXError.js\";\nimport type { DexiXRequestInfo, DexiXResponse } from \"../types/index.js\";\n\n/**\n * Thrown when the server responds with a non-2xx status code.\n * Always carries the full `response`, including any parsed body DexiX\n * Request was able to extract before raising the error.\n */\nexport class HTTPError extends DexiXError {\n public constructor(request: DexiXRequestInfo, response: DexiXResponse) {\n super(\n `Request failed with status ${response.status} (${response.statusText}) for ${request.url}`,\n request,\n response,\n );\n this.name = \"HTTPError\";\n }\n}\n","import { DexiXError } from \"./DexiXError.js\";\nimport type { DexiXRequestInfo } from \"../types/index.js\";\n\n/**\n * Thrown when the request could not be completed because of a network\n * failure (DNS resolution failure, connection refused, offline, CORS\n * rejection, etc). No response was ever received.\n */\nexport class NetworkError extends DexiXError {\n public constructor(message: string, request: DexiXRequestInfo, cause?: unknown) {\n super(message || \"Network request failed\", request);\n this.name = \"NetworkError\";\n if (cause !== undefined) {\n this.cause = cause;\n }\n }\n}\n","import { DexiXError } from \"./DexiXError.js\";\nimport type { DexiXRequestInfo } from \"../types/index.js\";\n\n/**\n * Thrown when a request exceeds its configured `timeout` before a\n * response is received.\n */\nexport class TimeoutError extends DexiXError {\n /** The timeout duration, in milliseconds, that was exceeded. */\n public readonly timeout: number;\n\n public constructor(request: DexiXRequestInfo, timeout: number) {\n super(`Request to ${request.url} timed out after ${timeout}ms`, request);\n this.name = \"TimeoutError\";\n this.timeout = timeout;\n }\n}\n","import type { QueryParams } from \"../types/index.js\";\n\n/**\n * Detects absolute URLs (has a scheme like `https://`, `http://`, or is\n * protocol-relative `//host`).\n */\nfunction isAbsoluteURL(url: string): boolean {\n return /^([a-z][a-z\\d+\\-.]*:)?\\/\\//i.test(url);\n}\n\n/**\n * Joins a base URL and a relative path without producing double slashes\n * or dropping a needed one.\n */\nfunction joinURL(baseURL: string, url: string): string {\n if (!baseURL) return url;\n if (isAbsoluteURL(url)) return url;\n\n const trimmedBase = baseURL.endsWith(\"/\") ? baseURL.slice(0, -1) : baseURL;\n const trimmedPath = url.startsWith(\"/\") ? url : `/${url}`;\n return `${trimmedBase}${trimmedPath}`;\n}\n\n/**\n * Appends query parameters to a URL, preserving any existing search\n * string already present on the URL. Array values become repeated keys.\n * `null`/`undefined` values are omitted entirely.\n */\nfunction appendQuery(url: string, query?: QueryParams): string {\n if (!query || Object.keys(query).length === 0) {\n return url;\n }\n\n const [path, existingSearch = \"\"] = url.split(\"?\");\n const params = new URLSearchParams(existingSearch);\n\n for (const [key, value] of Object.entries(query)) {\n if (value === null || value === undefined) continue;\n\n if (Array.isArray(value)) {\n for (const item of value) {\n params.append(key, String(item));\n }\n } else {\n params.append(key, String(value));\n }\n }\n\n const search = params.toString();\n return search ? `${path}?${search}` : (path as string);\n}\n\n/**\n * Builds the final request URL from a base URL, a relative or absolute\n * URL, and an optional set of query parameters.\n */\nexport function buildURL(baseURL: string | undefined, url: string, query?: QueryParams): string {\n const joined = joinURL(baseURL ?? \"\", url);\n return appendQuery(joined, query);\n}\n","import type { HeadersInput } from \"../types/index.js\";\n\n/**\n * Merges any number of header sources into a single `Headers` instance.\n * Later sources override earlier ones for the same (case-insensitive) key.\n * A value of `undefined` in a plain-object source removes that header.\n */\nexport function mergeHeaders(...sources: Array<HeadersInput | undefined>): Headers {\n const result = new Headers();\n\n for (const source of sources) {\n if (!source) continue;\n\n if (source instanceof Headers) {\n source.forEach((value, key) => {\n result.set(key, value);\n });\n continue;\n }\n\n if (Array.isArray(source)) {\n for (const [key, value] of source) {\n result.set(key, value);\n }\n continue;\n }\n\n for (const [key, value] of Object.entries(source)) {\n if (value === undefined) {\n result.delete(key);\n } else {\n result.set(key, value);\n }\n }\n }\n\n return result;\n}\n","import { mergeHeaders } from \"./mergeHeaders.js\";\nimport type { RequestConfig } from \"../types/index.js\";\n\n/**\n * Merges a child `RequestConfig` on top of a parent one. Headers and\n * query params are merged (child wins per-key); every other field is\n * simply overridden by the child when present.\n */\nexport function mergeConfig(parent: RequestConfig, child: RequestConfig): RequestConfig {\n return {\n ...parent,\n ...child,\n headers: mergeHeaders(parent.headers, child.headers),\n query: { ...parent.query, ...child.query },\n };\n}\n","/**\n * Returns `true` for plain JavaScript objects (object literals, or objects\n * with `Object.prototype` / `null` as their prototype). Returns `false`\n * for arrays, class instances, `FormData`, `Blob`, `File`, `URLSearchParams`,\n * `ReadableStream`, `Date`, `Map`, `Set`, and primitives.\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const prototype = Object.getPrototypeOf(value) as unknown;\n return prototype === Object.prototype || prototype === null;\n}\n","import { isPlainObject } from \"./isPlainObject.js\";\nimport type { RequestBody } from \"../types/index.js\";\n\n/**\n * Result of serializing a request body: the value ready to hand to\n * `fetch`, and an optional `Content-Type` to apply when one wasn't\n * already set by the caller.\n */\nexport interface SerializedBody {\n body: BodyInit | null | undefined;\n contentType?: string;\n}\n\n/**\n * Determines whether a value is already a \"native\" body type that\n * `fetch` understands natively and should be passed through untouched.\n */\nfunction isNativeBodyType(value: unknown): value is BodyInit {\n return (\n typeof value === \"string\" ||\n value instanceof FormData ||\n value instanceof Blob ||\n value instanceof URLSearchParams ||\n value instanceof ArrayBuffer ||\n ArrayBuffer.isView(value) ||\n value instanceof ReadableStream\n );\n}\n\n/**\n * Serializes a DexiX request body. Plain objects and arrays are\n * JSON-serialized automatically; every other supported `BodyInit` type is\n * passed through untouched so the caller retains full control when\n * needed (e.g. uploading a `FormData` or streaming a `ReadableStream`).\n */\nexport function serializeBody(body: RequestBody): SerializedBody {\n if (body === null || body === undefined) {\n return { body: undefined };\n }\n\n if (isNativeBodyType(body)) {\n // FormData sets its own multipart boundary; let the platform handle it.\n if (body instanceof FormData) {\n return { body };\n }\n if (body instanceof URLSearchParams) {\n return { body, contentType: \"application/x-www-form-urlencoded;charset=UTF-8\" };\n }\n if (typeof body === \"string\") {\n return { body, contentType: \"text/plain;charset=UTF-8\" };\n }\n return { body };\n }\n\n if (isPlainObject(body) || Array.isArray(body)) {\n return {\n body: JSON.stringify(body),\n contentType: \"application/json;charset=UTF-8\",\n };\n }\n\n // Fallback: best-effort JSON serialization for other serializable values.\n return {\n body: JSON.stringify(body),\n contentType: \"application/json;charset=UTF-8\",\n };\n}\n","import { DexiXError } from \"./DexiXError.js\";\nimport type { DexiXRequestInfo, DexiXResponse } from \"../types/index.js\";\n\n/**\n * Thrown when a response body could not be parsed according to the\n * requested (or inferred) `responseType`, e.g. invalid JSON.\n */\nexport class ParseError extends DexiXError {\n public constructor(request: DexiXRequestInfo, response: DexiXResponse, cause?: unknown) {\n super(`Failed to parse response body from ${request.url}`, request, response);\n this.name = \"ParseError\";\n if (cause !== undefined) {\n this.cause = cause;\n }\n }\n}\n","import { ParseError } from \"../errors/ParseError.js\";\nimport type { DexiXRequestInfo, DexiXResponse, ResponseType } from \"../types/index.js\";\n\nconst EMPTY_STATUS_CODES = new Set([204, 205, 304]);\n\n/**\n * Infers the best response type from the `Content-Type` header when the\n * caller didn't explicitly request one.\n */\nfunction inferResponseType(response: Response): ResponseType {\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n\n if (contentType.includes(\"application/json\") || contentType.includes(\"+json\")) {\n return \"json\";\n }\n if (contentType.startsWith(\"text/\")) {\n return \"text\";\n }\n return \"json\";\n}\n\n/**\n * Parses a `Response` body according to `responseType` (or an inferred\n * type based on `Content-Type`), returning the parsed value. Throws\n * `ParseError` if parsing fails.\n */\nexport async function parseResponse<T>(\n response: Response,\n request: DexiXRequestInfo,\n responseType?: ResponseType,\n): Promise<T> {\n if (request.method === \"HEAD\" || EMPTY_STATUS_CODES.has(response.status)) {\n return undefined as T;\n }\n\n const type = responseType ?? inferResponseType(response);\n\n try {\n switch (type) {\n case \"json\": {\n const text = await response.text();\n if (text.length === 0) {\n return undefined as T;\n }\n return JSON.parse(text) as T;\n }\n case \"text\":\n return (await response.text()) as unknown as T;\n case \"blob\":\n return (await response.blob()) as unknown as T;\n case \"arrayBuffer\":\n return (await response.arrayBuffer()) as unknown as T;\n case \"stream\":\n return response.body as unknown as T;\n default:\n return (await response.text()) as unknown as T;\n }\n } catch (cause) {\n const failedResponse: DexiXResponse = {\n data: undefined,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n url: response.url || request.url,\n };\n throw new ParseError(request, failedResponse, cause);\n }\n}\n","/**\n * Combines an optional user-provided `AbortSignal` with an internal\n * timeout, producing a single signal that aborts when either source\n * aborts. Returns the combined signal along with a `cancel()` function\n * that must be called once the request settles to clear the timer, and\n * a `didTimeout()` predicate to distinguish a timeout abort from a\n * user-initiated abort.\n */\nexport function combineSignals(\n userSignal: AbortSignal | undefined,\n timeout: number | undefined,\n): {\n signal: AbortSignal | undefined;\n cancel: () => void;\n didTimeout: () => boolean;\n} {\n if (!timeout || timeout <= 0) {\n return {\n signal: userSignal,\n cancel: () => {},\n didTimeout: () => false,\n };\n }\n\n const controller = new AbortController();\n let timedOut = false;\n\n const timer = setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, timeout);\n\n const onUserAbort = () => controller.abort();\n userSignal?.addEventListener(\"abort\", onUserAbort, { once: true });\n\n const cancel = () => {\n clearTimeout(timer);\n userSignal?.removeEventListener(\"abort\", onUserAbort);\n };\n\n return {\n signal: controller.signal,\n cancel,\n didTimeout: () => timedOut,\n };\n}\n","import { HTTPError } from \"../errors/HTTPError.js\";\nimport { NetworkError } from \"../errors/NetworkError.js\";\nimport { TimeoutError } from \"../errors/TimeoutError.js\";\nimport { buildURL, combineSignals, mergeHeaders, parseResponse, serializeBody } from \"../utils/index.js\";\nimport type { DexiXRequestInfo, DexiXResponse, ResolvedRequestConfig } from \"../types/index.js\";\n\n/**\n * Executes a single HTTP request described by a fully-resolved config.\n * This is the single point in the library that calls `fetch`.\n *\n * @internal\n */\nexport async function dispatch<T>(config: ResolvedRequestConfig): Promise<T> {\n const { body, contentType } = serializeBody(config.body);\n\n const headers = mergeHeaders(\n contentType ? { \"content-type\": contentType } : undefined,\n config.headers,\n );\n\n const url = buildURL(config.baseURL, config.url, config.query);\n\n const requestInfo: DexiXRequestInfo = {\n url,\n method: config.method,\n headers,\n body: config.body,\n };\n\n const { signal, cancel, didTimeout } = combineSignals(config.signal, config.timeout);\n\n const init: RequestInit = {\n method: config.method,\n headers,\n body: config.method === \"GET\" || config.method === \"HEAD\" ? undefined : body,\n signal,\n credentials: config.credentials,\n cache: config.cache,\n redirect: config.redirect,\n referrerPolicy: config.referrerPolicy,\n mode: config.mode,\n };\n\n const request = new Request(url, init);\n\n if (config.onRequest) {\n await config.onRequest(request);\n }\n\n let response: Response;\n\n try {\n response = await fetch(request);\n } catch (cause) {\n cancel();\n\n if (cause instanceof DOMException && cause.name === \"AbortError\") {\n if (didTimeout()) {\n throw new TimeoutError(requestInfo, config.timeout ?? 0);\n }\n throw cause;\n }\n\n throw new NetworkError(\n cause instanceof Error ? cause.message : \"Network request failed\",\n requestInfo,\n cause,\n );\n }\n\n cancel();\n\n if (config.onResponse) {\n await config.onResponse(response);\n }\n\n if (!response.ok) {\n const data = await parseResponse<unknown>(response, requestInfo, config.responseType).catch(\n () => undefined,\n );\n\n const errorResponse: DexiXResponse = {\n data,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n url: response.url || url,\n };\n\n throw new HTTPError(requestInfo, errorResponse);\n }\n\n return parseResponse<T>(response, requestInfo, config.responseType);\n}\n","import { dispatch } from \"./dispatch.js\";\nimport { mergeConfig } from \"../utils/index.js\";\nimport type {\n DexiXInstance,\n HttpMethod,\n RequestBody,\n RequestConfig,\n ResolvedRequestConfig,\n} from \"../types/index.js\";\n\nfunction request<T>(\n defaults: RequestConfig,\n method: HttpMethod,\n url: string,\n config?: RequestConfig,\n): Promise<T> {\n const resolved: ResolvedRequestConfig = {\n ...mergeConfig(defaults, config ?? {}),\n method,\n url,\n };\n\n return dispatch<T>(resolved);\n}\n\nfunction requestWithBody<T>(\n defaults: RequestConfig,\n method: HttpMethod,\n url: string,\n body?: RequestBody,\n config?: RequestConfig,\n): Promise<T> {\n return request<T>(defaults, method, url, { ...config, body: body ?? config?.body });\n}\n\n/**\n * Creates a new DexiX Request instance. Calling the instance directly\n * performs a GET request; method-specific helpers (`get`, `post`, `put`,\n * `patch`, `delete`, `head`, `options`) are attached for convenience.\n */\nexport function createInstance(defaults: RequestConfig = {}): DexiXInstance {\n const instance = (<T>(url: string, config?: RequestConfig): Promise<T> =>\n request<T>(defaults, \"GET\", url, config)) as DexiXInstance;\n\n instance.get = (url, config) => request(defaults, \"GET\", url, config);\n instance.post = (url, body, config) => requestWithBody(defaults, \"POST\", url, body, config);\n instance.put = (url, body, config) => requestWithBody(defaults, \"PUT\", url, body, config);\n instance.patch = (url, body, config) => requestWithBody(defaults, \"PATCH\", url, body, config);\n instance.delete = (url, config) => request(defaults, \"DELETE\", url, config);\n instance.head = (url, config) => request(defaults, \"HEAD\", url, config);\n instance.options = (url, config) => request(defaults, \"OPTIONS\", url, config);\n\n Object.defineProperty(instance, \"defaults\", {\n value: defaults,\n writable: false,\n enumerable: true,\n });\n\n instance.create = (config?: RequestConfig) => createInstance(mergeConfig(defaults, config ?? {}));\n\n return instance;\n}\n","import { createInstance } from \"./core/index.js\";\nimport type { DexiXInstance } from \"./types/index.js\";\n\nexport type {\n DexiXInstance,\n RequestConfig,\n HttpMethod,\n QueryParams,\n RequestBody,\n HeadersInput,\n ResponseType,\n DexiXResponse,\n DexiXRequestInfo,\n} from \"./types/index.js\";\n\nexport { DexiXError, NetworkError, TimeoutError, HTTPError, ParseError } from \"./errors/index.js\";\n\n/**\n * The default DexiX Request instance.\n *\n * @example\n * ```ts\n * import dx from \"dexix-request\";\n *\n * const users = await dx(\"/users\");\n * const user = await dx.get<User>(\"/users/1\");\n * await dx.post(\"/posts\", { title: \"Hello\" });\n * ```\n */\nconst dx: DexiXInstance = createInstance();\n\nexport { createInstance };\nexport default dx;\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP methods supported by DexiX Request.
|
|
3
|
+
*/
|
|
4
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
|
|
5
|
+
/**
|
|
6
|
+
* Plain object of query parameters. Array values are serialized as
|
|
7
|
+
* repeated keys (e.g. `{ tag: ["a", "b"] }` -> `?tag=a&tag=b`).
|
|
8
|
+
*/
|
|
9
|
+
type QueryParams = Record<string, string | number | boolean | null | undefined | Array<string | number | boolean>>;
|
|
10
|
+
/**
|
|
11
|
+
* Anything that can be sent as a request body.
|
|
12
|
+
* Plain objects and arrays are automatically JSON-serialized.
|
|
13
|
+
*/
|
|
14
|
+
type RequestBody = BodyInit | Record<string, unknown> | unknown[] | null | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Headers accepted by DexiX Request. Accepts a plain object, a `Headers`
|
|
17
|
+
* instance, or an array of key/value pairs (same as the `HeadersInit` type).
|
|
18
|
+
*/
|
|
19
|
+
type HeadersInput = HeadersInit | Record<string, string | undefined>;
|
|
20
|
+
/**
|
|
21
|
+
* Response type hint. DexiX Request defaults to `"json"` and falls back
|
|
22
|
+
* gracefully when the response has no JSON body.
|
|
23
|
+
*/
|
|
24
|
+
type ResponseType = "json" | "text" | "blob" | "arrayBuffer" | "stream";
|
|
25
|
+
/**
|
|
26
|
+
* Configuration accepted by every request call, and by `dx.create()`.
|
|
27
|
+
*/
|
|
28
|
+
interface RequestConfig {
|
|
29
|
+
/** Base URL prepended to every relative request URL. */
|
|
30
|
+
baseURL?: string;
|
|
31
|
+
/** Headers merged into every request. */
|
|
32
|
+
headers?: HeadersInput;
|
|
33
|
+
/** Query parameters appended to the URL's search string. */
|
|
34
|
+
query?: QueryParams;
|
|
35
|
+
/** Request body. Objects/arrays are JSON-serialized automatically. */
|
|
36
|
+
body?: RequestBody;
|
|
37
|
+
/** Timeout in milliseconds. `0` or `undefined` disables the timeout. */
|
|
38
|
+
timeout?: number;
|
|
39
|
+
/** An `AbortSignal` to cancel the request. Composable with `timeout`. */
|
|
40
|
+
signal?: AbortSignal;
|
|
41
|
+
/** How to parse the response body. Defaults to `"json"`. */
|
|
42
|
+
responseType?: ResponseType;
|
|
43
|
+
/** Credentials mode, forwarded to `fetch`. */
|
|
44
|
+
credentials?: RequestCredentials;
|
|
45
|
+
/** Cache mode, forwarded to `fetch`. */
|
|
46
|
+
cache?: RequestCache;
|
|
47
|
+
/** Redirect mode, forwarded to `fetch`. */
|
|
48
|
+
redirect?: RequestRedirect;
|
|
49
|
+
/** Referrer policy, forwarded to `fetch`. */
|
|
50
|
+
referrerPolicy?: ReferrerPolicy;
|
|
51
|
+
/** Mode, forwarded to `fetch`. */
|
|
52
|
+
mode?: RequestMode;
|
|
53
|
+
/**
|
|
54
|
+
* Called once per request with the fully-resolved `Request` before it is
|
|
55
|
+
* sent. Useful for logging or attaching auth tokens dynamically.
|
|
56
|
+
*/
|
|
57
|
+
onRequest?: (request: Request) => void | Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Called once per request with the raw `Response`, before the body is
|
|
60
|
+
* parsed.
|
|
61
|
+
*/
|
|
62
|
+
onResponse?: (response: Response) => void | Promise<void>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Metadata attached to every DexiX error, describing the request that
|
|
66
|
+
* produced it.
|
|
67
|
+
*/
|
|
68
|
+
interface DexiXRequestInfo {
|
|
69
|
+
url: string;
|
|
70
|
+
method: HttpMethod;
|
|
71
|
+
headers: Headers;
|
|
72
|
+
body?: RequestBody;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The shape of a successful DexiX Request response before unwrapping.
|
|
76
|
+
* Consumers normally never see this directly, since `dx()` resolves to
|
|
77
|
+
* the parsed body, but it's available via `HTTPError.response`.
|
|
78
|
+
*/
|
|
79
|
+
interface DexiXResponse<T = unknown> {
|
|
80
|
+
data: T;
|
|
81
|
+
status: number;
|
|
82
|
+
statusText: string;
|
|
83
|
+
headers: Headers;
|
|
84
|
+
url: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* A callable DexiX Request instance. Calling it directly performs a GET
|
|
88
|
+
* request. Method-specific helpers are attached for convenience.
|
|
89
|
+
*/
|
|
90
|
+
interface DexiXInstance {
|
|
91
|
+
<T = unknown>(url: string, config?: RequestConfig): Promise<T>;
|
|
92
|
+
get<T = unknown>(url: string, config?: RequestConfig): Promise<T>;
|
|
93
|
+
post<T = unknown>(url: string, body?: RequestBody, config?: RequestConfig): Promise<T>;
|
|
94
|
+
put<T = unknown>(url: string, body?: RequestBody, config?: RequestConfig): Promise<T>;
|
|
95
|
+
patch<T = unknown>(url: string, body?: RequestBody, config?: RequestConfig): Promise<T>;
|
|
96
|
+
delete<T = unknown>(url: string, config?: RequestConfig): Promise<T>;
|
|
97
|
+
head(url: string, config?: RequestConfig): Promise<void>;
|
|
98
|
+
options<T = unknown>(url: string, config?: RequestConfig): Promise<T>;
|
|
99
|
+
/** The base configuration this instance was created with. */
|
|
100
|
+
readonly defaults: RequestConfig;
|
|
101
|
+
/**
|
|
102
|
+
* Create a new, independent DexiX Request instance. Config is merged
|
|
103
|
+
* with the parent instance's defaults (child config wins).
|
|
104
|
+
*/
|
|
105
|
+
create(config?: RequestConfig): DexiXInstance;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Creates a new DexiX Request instance. Calling the instance directly
|
|
110
|
+
* performs a GET request; method-specific helpers (`get`, `post`, `put`,
|
|
111
|
+
* `patch`, `delete`, `head`, `options`) are attached for convenience.
|
|
112
|
+
*/
|
|
113
|
+
declare function createInstance(defaults?: RequestConfig): DexiXInstance;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Base class for every error thrown by DexiX Request.
|
|
117
|
+
* All DexiX errors carry the originating request and, when available,
|
|
118
|
+
* the response that was received.
|
|
119
|
+
*/
|
|
120
|
+
declare class DexiXError extends Error {
|
|
121
|
+
/** The request that caused this error. */
|
|
122
|
+
readonly request: DexiXRequestInfo;
|
|
123
|
+
/** The response received, if any (absent for network/timeout errors). */
|
|
124
|
+
readonly response?: DexiXResponse;
|
|
125
|
+
/** HTTP status code, if a response was received. */
|
|
126
|
+
readonly status?: number;
|
|
127
|
+
/** Response headers, if a response was received. */
|
|
128
|
+
readonly headers?: Headers;
|
|
129
|
+
/** The request URL. */
|
|
130
|
+
readonly url: string;
|
|
131
|
+
constructor(message: string, request: DexiXRequestInfo, response?: DexiXResponse);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Thrown when the request could not be completed because of a network
|
|
136
|
+
* failure (DNS resolution failure, connection refused, offline, CORS
|
|
137
|
+
* rejection, etc). No response was ever received.
|
|
138
|
+
*/
|
|
139
|
+
declare class NetworkError extends DexiXError {
|
|
140
|
+
constructor(message: string, request: DexiXRequestInfo, cause?: unknown);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Thrown when a request exceeds its configured `timeout` before a
|
|
145
|
+
* response is received.
|
|
146
|
+
*/
|
|
147
|
+
declare class TimeoutError extends DexiXError {
|
|
148
|
+
/** The timeout duration, in milliseconds, that was exceeded. */
|
|
149
|
+
readonly timeout: number;
|
|
150
|
+
constructor(request: DexiXRequestInfo, timeout: number);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Thrown when the server responds with a non-2xx status code.
|
|
155
|
+
* Always carries the full `response`, including any parsed body DexiX
|
|
156
|
+
* Request was able to extract before raising the error.
|
|
157
|
+
*/
|
|
158
|
+
declare class HTTPError extends DexiXError {
|
|
159
|
+
constructor(request: DexiXRequestInfo, response: DexiXResponse);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Thrown when a response body could not be parsed according to the
|
|
164
|
+
* requested (or inferred) `responseType`, e.g. invalid JSON.
|
|
165
|
+
*/
|
|
166
|
+
declare class ParseError extends DexiXError {
|
|
167
|
+
constructor(request: DexiXRequestInfo, response: DexiXResponse, cause?: unknown);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* The default DexiX Request instance.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```ts
|
|
175
|
+
* import dx from "dexix-request";
|
|
176
|
+
*
|
|
177
|
+
* const users = await dx("/users");
|
|
178
|
+
* const user = await dx.get<User>("/users/1");
|
|
179
|
+
* await dx.post("/posts", { title: "Hello" });
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
declare const dx: DexiXInstance;
|
|
183
|
+
|
|
184
|
+
export { DexiXError, type DexiXInstance, type DexiXRequestInfo, type DexiXResponse, HTTPError, type HeadersInput, type HttpMethod, NetworkError, ParseError, type QueryParams, type RequestBody, type RequestConfig, type ResponseType, TimeoutError, createInstance, dx as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP methods supported by DexiX Request.
|
|
3
|
+
*/
|
|
4
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
|
|
5
|
+
/**
|
|
6
|
+
* Plain object of query parameters. Array values are serialized as
|
|
7
|
+
* repeated keys (e.g. `{ tag: ["a", "b"] }` -> `?tag=a&tag=b`).
|
|
8
|
+
*/
|
|
9
|
+
type QueryParams = Record<string, string | number | boolean | null | undefined | Array<string | number | boolean>>;
|
|
10
|
+
/**
|
|
11
|
+
* Anything that can be sent as a request body.
|
|
12
|
+
* Plain objects and arrays are automatically JSON-serialized.
|
|
13
|
+
*/
|
|
14
|
+
type RequestBody = BodyInit | Record<string, unknown> | unknown[] | null | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Headers accepted by DexiX Request. Accepts a plain object, a `Headers`
|
|
17
|
+
* instance, or an array of key/value pairs (same as the `HeadersInit` type).
|
|
18
|
+
*/
|
|
19
|
+
type HeadersInput = HeadersInit | Record<string, string | undefined>;
|
|
20
|
+
/**
|
|
21
|
+
* Response type hint. DexiX Request defaults to `"json"` and falls back
|
|
22
|
+
* gracefully when the response has no JSON body.
|
|
23
|
+
*/
|
|
24
|
+
type ResponseType = "json" | "text" | "blob" | "arrayBuffer" | "stream";
|
|
25
|
+
/**
|
|
26
|
+
* Configuration accepted by every request call, and by `dx.create()`.
|
|
27
|
+
*/
|
|
28
|
+
interface RequestConfig {
|
|
29
|
+
/** Base URL prepended to every relative request URL. */
|
|
30
|
+
baseURL?: string;
|
|
31
|
+
/** Headers merged into every request. */
|
|
32
|
+
headers?: HeadersInput;
|
|
33
|
+
/** Query parameters appended to the URL's search string. */
|
|
34
|
+
query?: QueryParams;
|
|
35
|
+
/** Request body. Objects/arrays are JSON-serialized automatically. */
|
|
36
|
+
body?: RequestBody;
|
|
37
|
+
/** Timeout in milliseconds. `0` or `undefined` disables the timeout. */
|
|
38
|
+
timeout?: number;
|
|
39
|
+
/** An `AbortSignal` to cancel the request. Composable with `timeout`. */
|
|
40
|
+
signal?: AbortSignal;
|
|
41
|
+
/** How to parse the response body. Defaults to `"json"`. */
|
|
42
|
+
responseType?: ResponseType;
|
|
43
|
+
/** Credentials mode, forwarded to `fetch`. */
|
|
44
|
+
credentials?: RequestCredentials;
|
|
45
|
+
/** Cache mode, forwarded to `fetch`. */
|
|
46
|
+
cache?: RequestCache;
|
|
47
|
+
/** Redirect mode, forwarded to `fetch`. */
|
|
48
|
+
redirect?: RequestRedirect;
|
|
49
|
+
/** Referrer policy, forwarded to `fetch`. */
|
|
50
|
+
referrerPolicy?: ReferrerPolicy;
|
|
51
|
+
/** Mode, forwarded to `fetch`. */
|
|
52
|
+
mode?: RequestMode;
|
|
53
|
+
/**
|
|
54
|
+
* Called once per request with the fully-resolved `Request` before it is
|
|
55
|
+
* sent. Useful for logging or attaching auth tokens dynamically.
|
|
56
|
+
*/
|
|
57
|
+
onRequest?: (request: Request) => void | Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Called once per request with the raw `Response`, before the body is
|
|
60
|
+
* parsed.
|
|
61
|
+
*/
|
|
62
|
+
onResponse?: (response: Response) => void | Promise<void>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Metadata attached to every DexiX error, describing the request that
|
|
66
|
+
* produced it.
|
|
67
|
+
*/
|
|
68
|
+
interface DexiXRequestInfo {
|
|
69
|
+
url: string;
|
|
70
|
+
method: HttpMethod;
|
|
71
|
+
headers: Headers;
|
|
72
|
+
body?: RequestBody;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The shape of a successful DexiX Request response before unwrapping.
|
|
76
|
+
* Consumers normally never see this directly, since `dx()` resolves to
|
|
77
|
+
* the parsed body, but it's available via `HTTPError.response`.
|
|
78
|
+
*/
|
|
79
|
+
interface DexiXResponse<T = unknown> {
|
|
80
|
+
data: T;
|
|
81
|
+
status: number;
|
|
82
|
+
statusText: string;
|
|
83
|
+
headers: Headers;
|
|
84
|
+
url: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* A callable DexiX Request instance. Calling it directly performs a GET
|
|
88
|
+
* request. Method-specific helpers are attached for convenience.
|
|
89
|
+
*/
|
|
90
|
+
interface DexiXInstance {
|
|
91
|
+
<T = unknown>(url: string, config?: RequestConfig): Promise<T>;
|
|
92
|
+
get<T = unknown>(url: string, config?: RequestConfig): Promise<T>;
|
|
93
|
+
post<T = unknown>(url: string, body?: RequestBody, config?: RequestConfig): Promise<T>;
|
|
94
|
+
put<T = unknown>(url: string, body?: RequestBody, config?: RequestConfig): Promise<T>;
|
|
95
|
+
patch<T = unknown>(url: string, body?: RequestBody, config?: RequestConfig): Promise<T>;
|
|
96
|
+
delete<T = unknown>(url: string, config?: RequestConfig): Promise<T>;
|
|
97
|
+
head(url: string, config?: RequestConfig): Promise<void>;
|
|
98
|
+
options<T = unknown>(url: string, config?: RequestConfig): Promise<T>;
|
|
99
|
+
/** The base configuration this instance was created with. */
|
|
100
|
+
readonly defaults: RequestConfig;
|
|
101
|
+
/**
|
|
102
|
+
* Create a new, independent DexiX Request instance. Config is merged
|
|
103
|
+
* with the parent instance's defaults (child config wins).
|
|
104
|
+
*/
|
|
105
|
+
create(config?: RequestConfig): DexiXInstance;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Creates a new DexiX Request instance. Calling the instance directly
|
|
110
|
+
* performs a GET request; method-specific helpers (`get`, `post`, `put`,
|
|
111
|
+
* `patch`, `delete`, `head`, `options`) are attached for convenience.
|
|
112
|
+
*/
|
|
113
|
+
declare function createInstance(defaults?: RequestConfig): DexiXInstance;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Base class for every error thrown by DexiX Request.
|
|
117
|
+
* All DexiX errors carry the originating request and, when available,
|
|
118
|
+
* the response that was received.
|
|
119
|
+
*/
|
|
120
|
+
declare class DexiXError extends Error {
|
|
121
|
+
/** The request that caused this error. */
|
|
122
|
+
readonly request: DexiXRequestInfo;
|
|
123
|
+
/** The response received, if any (absent for network/timeout errors). */
|
|
124
|
+
readonly response?: DexiXResponse;
|
|
125
|
+
/** HTTP status code, if a response was received. */
|
|
126
|
+
readonly status?: number;
|
|
127
|
+
/** Response headers, if a response was received. */
|
|
128
|
+
readonly headers?: Headers;
|
|
129
|
+
/** The request URL. */
|
|
130
|
+
readonly url: string;
|
|
131
|
+
constructor(message: string, request: DexiXRequestInfo, response?: DexiXResponse);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Thrown when the request could not be completed because of a network
|
|
136
|
+
* failure (DNS resolution failure, connection refused, offline, CORS
|
|
137
|
+
* rejection, etc). No response was ever received.
|
|
138
|
+
*/
|
|
139
|
+
declare class NetworkError extends DexiXError {
|
|
140
|
+
constructor(message: string, request: DexiXRequestInfo, cause?: unknown);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Thrown when a request exceeds its configured `timeout` before a
|
|
145
|
+
* response is received.
|
|
146
|
+
*/
|
|
147
|
+
declare class TimeoutError extends DexiXError {
|
|
148
|
+
/** The timeout duration, in milliseconds, that was exceeded. */
|
|
149
|
+
readonly timeout: number;
|
|
150
|
+
constructor(request: DexiXRequestInfo, timeout: number);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Thrown when the server responds with a non-2xx status code.
|
|
155
|
+
* Always carries the full `response`, including any parsed body DexiX
|
|
156
|
+
* Request was able to extract before raising the error.
|
|
157
|
+
*/
|
|
158
|
+
declare class HTTPError extends DexiXError {
|
|
159
|
+
constructor(request: DexiXRequestInfo, response: DexiXResponse);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Thrown when a response body could not be parsed according to the
|
|
164
|
+
* requested (or inferred) `responseType`, e.g. invalid JSON.
|
|
165
|
+
*/
|
|
166
|
+
declare class ParseError extends DexiXError {
|
|
167
|
+
constructor(request: DexiXRequestInfo, response: DexiXResponse, cause?: unknown);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* The default DexiX Request instance.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```ts
|
|
175
|
+
* import dx from "dexix-request";
|
|
176
|
+
*
|
|
177
|
+
* const users = await dx("/users");
|
|
178
|
+
* const user = await dx.get<User>("/users/1");
|
|
179
|
+
* await dx.post("/posts", { title: "Hello" });
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
declare const dx: DexiXInstance;
|
|
183
|
+
|
|
184
|
+
export { DexiXError, type DexiXInstance, type DexiXRequestInfo, type DexiXResponse, HTTPError, type HeadersInput, type HttpMethod, NetworkError, ParseError, type QueryParams, type RequestBody, type RequestConfig, type ResponseType, TimeoutError, createInstance, dx as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
var i=class extends Error{request;response;status;headers;url;constructor(t,r,n){super(t),this.name="DexiXError",this.request=r,this.response=n,this.status=n?.status,this.headers=n?.headers,this.url=r.url,Object.setPrototypeOf(this,new.target.prototype);}};var c=class extends i{constructor(t,r){super(`Request failed with status ${r.status} (${r.statusText}) for ${t.url}`,t,r),this.name="HTTPError";}};var d=class extends i{constructor(t,r,n){super(t||"Network request failed",r),this.name="NetworkError",n!==void 0&&(this.cause=n);}};var m=class extends i{timeout;constructor(t,r){super(`Request to ${t.url} timed out after ${r}ms`,t),this.name="TimeoutError",this.timeout=r;}};function C(e){return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(e)}function k(e,t){if(!e||C(t))return t;let r=e.endsWith("/")?e.slice(0,-1):e,n=t.startsWith("/")?t:`/${t}`;return `${r}${n}`}function H(e,t){if(!t||Object.keys(t).length===0)return e;let[r,n=""]=e.split("?"),o=new URLSearchParams(n);for(let[f,u]of Object.entries(t))if(u!=null)if(Array.isArray(u))for(let b of u)o.append(f,String(b));else o.append(f,String(u));let s=o.toString();return s?`${r}?${s}`:r}function q(e,t,r){let n=k(e??"",t);return H(n,r)}function l(...e){let t=new Headers;for(let r of e)if(r){if(r instanceof Headers){r.forEach((n,o)=>{t.set(o,n);});continue}if(Array.isArray(r)){for(let[n,o]of r)t.set(n,o);continue}for(let[n,o]of Object.entries(r))o===void 0?t.delete(n):t.set(n,o);}return t}function R(e,t){return {...e,...t,headers:l(e.headers,t.headers),query:{...e.query,...t.query}}}function E(e){if(typeof e!="object"||e===null)return false;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function S(e){return typeof e=="string"||e instanceof FormData||e instanceof Blob||e instanceof URLSearchParams||e instanceof ArrayBuffer||ArrayBuffer.isView(e)||e instanceof ReadableStream}function w(e){return e==null?{body:void 0}:S(e)?e instanceof FormData?{body:e}:e instanceof URLSearchParams?{body:e,contentType:"application/x-www-form-urlencoded;charset=UTF-8"}:typeof e=="string"?{body:e,contentType:"text/plain;charset=UTF-8"}:{body:e}:E(e)||Array.isArray(e)?{body:JSON.stringify(e),contentType:"application/json;charset=UTF-8"}:{body:JSON.stringify(e),contentType:"application/json;charset=UTF-8"}}var x=class extends i{constructor(t,r,n){super(`Failed to parse response body from ${t.url}`,t,r),this.name="ParseError",n!==void 0&&(this.cause=n);}};var O=new Set([204,205,304]);function A(e){let t=e.headers.get("content-type")??"";return t.includes("application/json")||t.includes("+json")?"json":t.startsWith("text/")?"text":"json"}async function h(e,t,r){if(t.method==="HEAD"||O.has(e.status))return;let n=r??A(e);try{switch(n){case "json":{let o=await e.text();return o.length===0?void 0:JSON.parse(o)}case "text":return await e.text();case "blob":return await e.blob();case "arrayBuffer":return await e.arrayBuffer();case "stream":return e.body;default:return await e.text()}}catch(o){let s={data:void 0,status:e.status,statusText:e.statusText,headers:e.headers,url:e.url||t.url};throw new x(t,s,o)}}function D(e,t){if(!t||t<=0)return {signal:e,cancel:()=>{},didTimeout:()=>false};let r=new AbortController,n=false,o=setTimeout(()=>{n=true,r.abort();},t),s=()=>r.abort();e?.addEventListener("abort",s,{once:true});let f=()=>{clearTimeout(o),e?.removeEventListener("abort",s);};return {signal:r.signal,cancel:f,didTimeout:()=>n}}async function j(e){let{body:t,contentType:r}=w(e.body),n=l(r?{"content-type":r}:void 0,e.headers),o=q(e.baseURL,e.url,e.query),s={url:o,method:e.method,headers:n,body:e.body},{signal:f,cancel:u,didTimeout:b}=D(e.signal,e.timeout),I={method:e.method,headers:n,body:e.method==="GET"||e.method==="HEAD"?void 0:t,signal:f,credentials:e.credentials,cache:e.cache,redirect:e.redirect,referrerPolicy:e.referrerPolicy,mode:e.mode},X=new Request(o,I);e.onRequest&&await e.onRequest(X);let a;try{a=await fetch(X);}catch(p){throw u(),p instanceof DOMException&&p.name==="AbortError"?b()?new m(s,e.timeout??0):p:new d(p instanceof Error?p.message:"Network request failed",s,p)}if(u(),e.onResponse&&await e.onResponse(a),!a.ok){let P={data:await h(a,s,e.responseType).catch(()=>{}),status:a.status,statusText:a.statusText,headers:a.headers,url:a.url||o};throw new c(s,P)}return h(a,s,e.responseType)}function y(e,t,r,n){let o={...R(e,n??{}),method:t,url:r};return j(o)}function g(e,t,r,n,o){return y(e,t,r,{...o,body:n??o?.body})}function T(e={}){let t=((r,n)=>y(e,"GET",r,n));return t.get=(r,n)=>y(e,"GET",r,n),t.post=(r,n,o)=>g(e,"POST",r,n,o),t.put=(r,n,o)=>g(e,"PUT",r,n,o),t.patch=(r,n,o)=>g(e,"PATCH",r,n,o),t.delete=(r,n)=>y(e,"DELETE",r,n),t.head=(r,n)=>y(e,"HEAD",r,n),t.options=(r,n)=>y(e,"OPTIONS",r,n),Object.defineProperty(t,"defaults",{value:e,writable:false,enumerable:true}),t.create=r=>T(R(e,r??{})),t}var B=T();var Ee=B;
|
|
2
|
+
export{i as DexiXError,c as HTTPError,d as NetworkError,x as ParseError,m as TimeoutError,T as createInstance,Ee as default};//# sourceMappingURL=index.js.map
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors/DexiXError.ts","../src/errors/HTTPError.ts","../src/errors/NetworkError.ts","../src/errors/TimeoutError.ts","../src/utils/buildURL.ts","../src/utils/mergeHeaders.ts","../src/utils/mergeConfig.ts","../src/utils/isPlainObject.ts","../src/utils/serializeBody.ts","../src/errors/ParseError.ts","../src/utils/parseResponse.ts","../src/utils/combineSignals.ts","../src/core/dispatch.ts","../src/core/instance.ts","../src/index.ts"],"names":["DexiXError","message","request","response","HTTPError","NetworkError","cause","TimeoutError","timeout","isAbsoluteURL","url","joinURL","baseURL","trimmedBase","trimmedPath","appendQuery","query","path","existingSearch","params","key","value","item","search","buildURL","joined","mergeHeaders","sources","result","source","mergeConfig","parent","child","isPlainObject","prototype","isNativeBodyType","serializeBody","body","ParseError","EMPTY_STATUS_CODES","inferResponseType","contentType","parseResponse","responseType","type","text","failedResponse","combineSignals","userSignal","controller","timedOut","timer","onUserAbort","cancel","dispatch","config","headers","requestInfo","signal","didTimeout","init","errorResponse","defaults","method","resolved","requestWithBody","createInstance","instance","dx","index_default"],"mappings":"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","file":"index.js","sourcesContent":["import type { DexiXRequestInfo, DexiXResponse } from \"../types/index.js\";\n\n/**\n * Base class for every error thrown by DexiX Request.\n * All DexiX errors carry the originating request and, when available,\n * the response that was received.\n */\nexport class DexiXError extends Error {\n /** The request that caused this error. */\n public readonly request: DexiXRequestInfo;\n /** The response received, if any (absent for network/timeout errors). */\n public readonly response?: DexiXResponse;\n /** HTTP status code, if a response was received. */\n public readonly status?: number;\n /** Response headers, if a response was received. */\n public readonly headers?: Headers;\n /** The request URL. */\n public readonly url: string;\n\n public constructor(\n message: string,\n request: DexiXRequestInfo,\n response?: DexiXResponse,\n ) {\n super(message);\n this.name = \"DexiXError\";\n this.request = request;\n this.response = response;\n this.status = response?.status;\n this.headers = response?.headers;\n this.url = request.url;\n\n // Restore the correct prototype chain when compiled down to ES5-style\n // targets (not an issue at ES2022, but harmless and defensive).\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","import { DexiXError } from \"./DexiXError.js\";\nimport type { DexiXRequestInfo, DexiXResponse } from \"../types/index.js\";\n\n/**\n * Thrown when the server responds with a non-2xx status code.\n * Always carries the full `response`, including any parsed body DexiX\n * Request was able to extract before raising the error.\n */\nexport class HTTPError extends DexiXError {\n public constructor(request: DexiXRequestInfo, response: DexiXResponse) {\n super(\n `Request failed with status ${response.status} (${response.statusText}) for ${request.url}`,\n request,\n response,\n );\n this.name = \"HTTPError\";\n }\n}\n","import { DexiXError } from \"./DexiXError.js\";\nimport type { DexiXRequestInfo } from \"../types/index.js\";\n\n/**\n * Thrown when the request could not be completed because of a network\n * failure (DNS resolution failure, connection refused, offline, CORS\n * rejection, etc). No response was ever received.\n */\nexport class NetworkError extends DexiXError {\n public constructor(message: string, request: DexiXRequestInfo, cause?: unknown) {\n super(message || \"Network request failed\", request);\n this.name = \"NetworkError\";\n if (cause !== undefined) {\n this.cause = cause;\n }\n }\n}\n","import { DexiXError } from \"./DexiXError.js\";\nimport type { DexiXRequestInfo } from \"../types/index.js\";\n\n/**\n * Thrown when a request exceeds its configured `timeout` before a\n * response is received.\n */\nexport class TimeoutError extends DexiXError {\n /** The timeout duration, in milliseconds, that was exceeded. */\n public readonly timeout: number;\n\n public constructor(request: DexiXRequestInfo, timeout: number) {\n super(`Request to ${request.url} timed out after ${timeout}ms`, request);\n this.name = \"TimeoutError\";\n this.timeout = timeout;\n }\n}\n","import type { QueryParams } from \"../types/index.js\";\n\n/**\n * Detects absolute URLs (has a scheme like `https://`, `http://`, or is\n * protocol-relative `//host`).\n */\nfunction isAbsoluteURL(url: string): boolean {\n return /^([a-z][a-z\\d+\\-.]*:)?\\/\\//i.test(url);\n}\n\n/**\n * Joins a base URL and a relative path without producing double slashes\n * or dropping a needed one.\n */\nfunction joinURL(baseURL: string, url: string): string {\n if (!baseURL) return url;\n if (isAbsoluteURL(url)) return url;\n\n const trimmedBase = baseURL.endsWith(\"/\") ? baseURL.slice(0, -1) : baseURL;\n const trimmedPath = url.startsWith(\"/\") ? url : `/${url}`;\n return `${trimmedBase}${trimmedPath}`;\n}\n\n/**\n * Appends query parameters to a URL, preserving any existing search\n * string already present on the URL. Array values become repeated keys.\n * `null`/`undefined` values are omitted entirely.\n */\nfunction appendQuery(url: string, query?: QueryParams): string {\n if (!query || Object.keys(query).length === 0) {\n return url;\n }\n\n const [path, existingSearch = \"\"] = url.split(\"?\");\n const params = new URLSearchParams(existingSearch);\n\n for (const [key, value] of Object.entries(query)) {\n if (value === null || value === undefined) continue;\n\n if (Array.isArray(value)) {\n for (const item of value) {\n params.append(key, String(item));\n }\n } else {\n params.append(key, String(value));\n }\n }\n\n const search = params.toString();\n return search ? `${path}?${search}` : (path as string);\n}\n\n/**\n * Builds the final request URL from a base URL, a relative or absolute\n * URL, and an optional set of query parameters.\n */\nexport function buildURL(baseURL: string | undefined, url: string, query?: QueryParams): string {\n const joined = joinURL(baseURL ?? \"\", url);\n return appendQuery(joined, query);\n}\n","import type { HeadersInput } from \"../types/index.js\";\n\n/**\n * Merges any number of header sources into a single `Headers` instance.\n * Later sources override earlier ones for the same (case-insensitive) key.\n * A value of `undefined` in a plain-object source removes that header.\n */\nexport function mergeHeaders(...sources: Array<HeadersInput | undefined>): Headers {\n const result = new Headers();\n\n for (const source of sources) {\n if (!source) continue;\n\n if (source instanceof Headers) {\n source.forEach((value, key) => {\n result.set(key, value);\n });\n continue;\n }\n\n if (Array.isArray(source)) {\n for (const [key, value] of source) {\n result.set(key, value);\n }\n continue;\n }\n\n for (const [key, value] of Object.entries(source)) {\n if (value === undefined) {\n result.delete(key);\n } else {\n result.set(key, value);\n }\n }\n }\n\n return result;\n}\n","import { mergeHeaders } from \"./mergeHeaders.js\";\nimport type { RequestConfig } from \"../types/index.js\";\n\n/**\n * Merges a child `RequestConfig` on top of a parent one. Headers and\n * query params are merged (child wins per-key); every other field is\n * simply overridden by the child when present.\n */\nexport function mergeConfig(parent: RequestConfig, child: RequestConfig): RequestConfig {\n return {\n ...parent,\n ...child,\n headers: mergeHeaders(parent.headers, child.headers),\n query: { ...parent.query, ...child.query },\n };\n}\n","/**\n * Returns `true` for plain JavaScript objects (object literals, or objects\n * with `Object.prototype` / `null` as their prototype). Returns `false`\n * for arrays, class instances, `FormData`, `Blob`, `File`, `URLSearchParams`,\n * `ReadableStream`, `Date`, `Map`, `Set`, and primitives.\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const prototype = Object.getPrototypeOf(value) as unknown;\n return prototype === Object.prototype || prototype === null;\n}\n","import { isPlainObject } from \"./isPlainObject.js\";\nimport type { RequestBody } from \"../types/index.js\";\n\n/**\n * Result of serializing a request body: the value ready to hand to\n * `fetch`, and an optional `Content-Type` to apply when one wasn't\n * already set by the caller.\n */\nexport interface SerializedBody {\n body: BodyInit | null | undefined;\n contentType?: string;\n}\n\n/**\n * Determines whether a value is already a \"native\" body type that\n * `fetch` understands natively and should be passed through untouched.\n */\nfunction isNativeBodyType(value: unknown): value is BodyInit {\n return (\n typeof value === \"string\" ||\n value instanceof FormData ||\n value instanceof Blob ||\n value instanceof URLSearchParams ||\n value instanceof ArrayBuffer ||\n ArrayBuffer.isView(value) ||\n value instanceof ReadableStream\n );\n}\n\n/**\n * Serializes a DexiX request body. Plain objects and arrays are\n * JSON-serialized automatically; every other supported `BodyInit` type is\n * passed through untouched so the caller retains full control when\n * needed (e.g. uploading a `FormData` or streaming a `ReadableStream`).\n */\nexport function serializeBody(body: RequestBody): SerializedBody {\n if (body === null || body === undefined) {\n return { body: undefined };\n }\n\n if (isNativeBodyType(body)) {\n // FormData sets its own multipart boundary; let the platform handle it.\n if (body instanceof FormData) {\n return { body };\n }\n if (body instanceof URLSearchParams) {\n return { body, contentType: \"application/x-www-form-urlencoded;charset=UTF-8\" };\n }\n if (typeof body === \"string\") {\n return { body, contentType: \"text/plain;charset=UTF-8\" };\n }\n return { body };\n }\n\n if (isPlainObject(body) || Array.isArray(body)) {\n return {\n body: JSON.stringify(body),\n contentType: \"application/json;charset=UTF-8\",\n };\n }\n\n // Fallback: best-effort JSON serialization for other serializable values.\n return {\n body: JSON.stringify(body),\n contentType: \"application/json;charset=UTF-8\",\n };\n}\n","import { DexiXError } from \"./DexiXError.js\";\nimport type { DexiXRequestInfo, DexiXResponse } from \"../types/index.js\";\n\n/**\n * Thrown when a response body could not be parsed according to the\n * requested (or inferred) `responseType`, e.g. invalid JSON.\n */\nexport class ParseError extends DexiXError {\n public constructor(request: DexiXRequestInfo, response: DexiXResponse, cause?: unknown) {\n super(`Failed to parse response body from ${request.url}`, request, response);\n this.name = \"ParseError\";\n if (cause !== undefined) {\n this.cause = cause;\n }\n }\n}\n","import { ParseError } from \"../errors/ParseError.js\";\nimport type { DexiXRequestInfo, DexiXResponse, ResponseType } from \"../types/index.js\";\n\nconst EMPTY_STATUS_CODES = new Set([204, 205, 304]);\n\n/**\n * Infers the best response type from the `Content-Type` header when the\n * caller didn't explicitly request one.\n */\nfunction inferResponseType(response: Response): ResponseType {\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n\n if (contentType.includes(\"application/json\") || contentType.includes(\"+json\")) {\n return \"json\";\n }\n if (contentType.startsWith(\"text/\")) {\n return \"text\";\n }\n return \"json\";\n}\n\n/**\n * Parses a `Response` body according to `responseType` (or an inferred\n * type based on `Content-Type`), returning the parsed value. Throws\n * `ParseError` if parsing fails.\n */\nexport async function parseResponse<T>(\n response: Response,\n request: DexiXRequestInfo,\n responseType?: ResponseType,\n): Promise<T> {\n if (request.method === \"HEAD\" || EMPTY_STATUS_CODES.has(response.status)) {\n return undefined as T;\n }\n\n const type = responseType ?? inferResponseType(response);\n\n try {\n switch (type) {\n case \"json\": {\n const text = await response.text();\n if (text.length === 0) {\n return undefined as T;\n }\n return JSON.parse(text) as T;\n }\n case \"text\":\n return (await response.text()) as unknown as T;\n case \"blob\":\n return (await response.blob()) as unknown as T;\n case \"arrayBuffer\":\n return (await response.arrayBuffer()) as unknown as T;\n case \"stream\":\n return response.body as unknown as T;\n default:\n return (await response.text()) as unknown as T;\n }\n } catch (cause) {\n const failedResponse: DexiXResponse = {\n data: undefined,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n url: response.url || request.url,\n };\n throw new ParseError(request, failedResponse, cause);\n }\n}\n","/**\n * Combines an optional user-provided `AbortSignal` with an internal\n * timeout, producing a single signal that aborts when either source\n * aborts. Returns the combined signal along with a `cancel()` function\n * that must be called once the request settles to clear the timer, and\n * a `didTimeout()` predicate to distinguish a timeout abort from a\n * user-initiated abort.\n */\nexport function combineSignals(\n userSignal: AbortSignal | undefined,\n timeout: number | undefined,\n): {\n signal: AbortSignal | undefined;\n cancel: () => void;\n didTimeout: () => boolean;\n} {\n if (!timeout || timeout <= 0) {\n return {\n signal: userSignal,\n cancel: () => {},\n didTimeout: () => false,\n };\n }\n\n const controller = new AbortController();\n let timedOut = false;\n\n const timer = setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, timeout);\n\n const onUserAbort = () => controller.abort();\n userSignal?.addEventListener(\"abort\", onUserAbort, { once: true });\n\n const cancel = () => {\n clearTimeout(timer);\n userSignal?.removeEventListener(\"abort\", onUserAbort);\n };\n\n return {\n signal: controller.signal,\n cancel,\n didTimeout: () => timedOut,\n };\n}\n","import { HTTPError } from \"../errors/HTTPError.js\";\nimport { NetworkError } from \"../errors/NetworkError.js\";\nimport { TimeoutError } from \"../errors/TimeoutError.js\";\nimport { buildURL, combineSignals, mergeHeaders, parseResponse, serializeBody } from \"../utils/index.js\";\nimport type { DexiXRequestInfo, DexiXResponse, ResolvedRequestConfig } from \"../types/index.js\";\n\n/**\n * Executes a single HTTP request described by a fully-resolved config.\n * This is the single point in the library that calls `fetch`.\n *\n * @internal\n */\nexport async function dispatch<T>(config: ResolvedRequestConfig): Promise<T> {\n const { body, contentType } = serializeBody(config.body);\n\n const headers = mergeHeaders(\n contentType ? { \"content-type\": contentType } : undefined,\n config.headers,\n );\n\n const url = buildURL(config.baseURL, config.url, config.query);\n\n const requestInfo: DexiXRequestInfo = {\n url,\n method: config.method,\n headers,\n body: config.body,\n };\n\n const { signal, cancel, didTimeout } = combineSignals(config.signal, config.timeout);\n\n const init: RequestInit = {\n method: config.method,\n headers,\n body: config.method === \"GET\" || config.method === \"HEAD\" ? undefined : body,\n signal,\n credentials: config.credentials,\n cache: config.cache,\n redirect: config.redirect,\n referrerPolicy: config.referrerPolicy,\n mode: config.mode,\n };\n\n const request = new Request(url, init);\n\n if (config.onRequest) {\n await config.onRequest(request);\n }\n\n let response: Response;\n\n try {\n response = await fetch(request);\n } catch (cause) {\n cancel();\n\n if (cause instanceof DOMException && cause.name === \"AbortError\") {\n if (didTimeout()) {\n throw new TimeoutError(requestInfo, config.timeout ?? 0);\n }\n throw cause;\n }\n\n throw new NetworkError(\n cause instanceof Error ? cause.message : \"Network request failed\",\n requestInfo,\n cause,\n );\n }\n\n cancel();\n\n if (config.onResponse) {\n await config.onResponse(response);\n }\n\n if (!response.ok) {\n const data = await parseResponse<unknown>(response, requestInfo, config.responseType).catch(\n () => undefined,\n );\n\n const errorResponse: DexiXResponse = {\n data,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n url: response.url || url,\n };\n\n throw new HTTPError(requestInfo, errorResponse);\n }\n\n return parseResponse<T>(response, requestInfo, config.responseType);\n}\n","import { dispatch } from \"./dispatch.js\";\nimport { mergeConfig } from \"../utils/index.js\";\nimport type {\n DexiXInstance,\n HttpMethod,\n RequestBody,\n RequestConfig,\n ResolvedRequestConfig,\n} from \"../types/index.js\";\n\nfunction request<T>(\n defaults: RequestConfig,\n method: HttpMethod,\n url: string,\n config?: RequestConfig,\n): Promise<T> {\n const resolved: ResolvedRequestConfig = {\n ...mergeConfig(defaults, config ?? {}),\n method,\n url,\n };\n\n return dispatch<T>(resolved);\n}\n\nfunction requestWithBody<T>(\n defaults: RequestConfig,\n method: HttpMethod,\n url: string,\n body?: RequestBody,\n config?: RequestConfig,\n): Promise<T> {\n return request<T>(defaults, method, url, { ...config, body: body ?? config?.body });\n}\n\n/**\n * Creates a new DexiX Request instance. Calling the instance directly\n * performs a GET request; method-specific helpers (`get`, `post`, `put`,\n * `patch`, `delete`, `head`, `options`) are attached for convenience.\n */\nexport function createInstance(defaults: RequestConfig = {}): DexiXInstance {\n const instance = (<T>(url: string, config?: RequestConfig): Promise<T> =>\n request<T>(defaults, \"GET\", url, config)) as DexiXInstance;\n\n instance.get = (url, config) => request(defaults, \"GET\", url, config);\n instance.post = (url, body, config) => requestWithBody(defaults, \"POST\", url, body, config);\n instance.put = (url, body, config) => requestWithBody(defaults, \"PUT\", url, body, config);\n instance.patch = (url, body, config) => requestWithBody(defaults, \"PATCH\", url, body, config);\n instance.delete = (url, config) => request(defaults, \"DELETE\", url, config);\n instance.head = (url, config) => request(defaults, \"HEAD\", url, config);\n instance.options = (url, config) => request(defaults, \"OPTIONS\", url, config);\n\n Object.defineProperty(instance, \"defaults\", {\n value: defaults,\n writable: false,\n enumerable: true,\n });\n\n instance.create = (config?: RequestConfig) => createInstance(mergeConfig(defaults, config ?? {}));\n\n return instance;\n}\n","import { createInstance } from \"./core/index.js\";\nimport type { DexiXInstance } from \"./types/index.js\";\n\nexport type {\n DexiXInstance,\n RequestConfig,\n HttpMethod,\n QueryParams,\n RequestBody,\n HeadersInput,\n ResponseType,\n DexiXResponse,\n DexiXRequestInfo,\n} from \"./types/index.js\";\n\nexport { DexiXError, NetworkError, TimeoutError, HTTPError, ParseError } from \"./errors/index.js\";\n\n/**\n * The default DexiX Request instance.\n *\n * @example\n * ```ts\n * import dx from \"dexix-request\";\n *\n * const users = await dx(\"/users\");\n * const user = await dx.get<User>(\"/users/1\");\n * await dx.post(\"/posts\", { title: \"Hello\" });\n * ```\n */\nconst dx: DexiXInstance = createInstance();\n\nexport { createInstance };\nexport default dx;\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dexix-request",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A tiny, modern, zero-dependency HTTP client for JavaScript and TypeScript. Built for the browser, Node.js, and React.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"http",
|
|
7
|
+
"http-client",
|
|
8
|
+
"fetch",
|
|
9
|
+
"request",
|
|
10
|
+
"api",
|
|
11
|
+
"typescript",
|
|
12
|
+
"axios-alternative",
|
|
13
|
+
"react",
|
|
14
|
+
"node"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://github.com/AkbariCodes/DexiX-Request/#readme",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/AkbariCodes/DexiX-Request/issues"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/AkbariCodes/DexiX-Request.git"
|
|
23
|
+
},
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"author": "DexiX Contributors",
|
|
26
|
+
"type": "module",
|
|
27
|
+
"sideEffects": false,
|
|
28
|
+
"main": "./dist/index.cjs",
|
|
29
|
+
"module": "./dist/index.js",
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"import": "./dist/index.js",
|
|
35
|
+
"require": "./dist/index.cjs"
|
|
36
|
+
},
|
|
37
|
+
"./package.json": "./package.json"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"README.md",
|
|
42
|
+
"LICENSE",
|
|
43
|
+
"CHANGELOG.md"
|
|
44
|
+
],
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=20"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsup",
|
|
50
|
+
"dev": "tsup --watch",
|
|
51
|
+
"test": "vitest run",
|
|
52
|
+
"test:watch": "vitest",
|
|
53
|
+
"test:coverage": "vitest run --coverage",
|
|
54
|
+
"typecheck": "tsc --noEmit",
|
|
55
|
+
"lint": "tsc --noEmit",
|
|
56
|
+
"prepublishOnly": "npm run build"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"tsup": "^8.5.1",
|
|
60
|
+
"typescript": "^5.9.3",
|
|
61
|
+
"vitest": "^2.0.5"
|
|
62
|
+
},
|
|
63
|
+
"publishConfig": {
|
|
64
|
+
"access": "public"
|
|
65
|
+
}
|
|
66
|
+
}
|