@auldrant/api 0.1.1 → 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/README.md +123 -32
- package/dist/api.d.ts +9 -50
- package/dist/auldrant-api.js +138 -121
- package/dist/index.d.ts +2 -2
- package/dist/static.d.ts +39 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,10 +8,12 @@ We recommend using [Bun](https://bun.sh) to work with @auldrant/api.
|
|
|
8
8
|
bun install
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Quick start
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
-
import {
|
|
14
|
+
import { createApi } from '@auldrant/api';
|
|
15
|
+
|
|
16
|
+
const api = createApi();
|
|
15
17
|
|
|
16
18
|
const result = await api.get<User[]>('/api/users');
|
|
17
19
|
if (result.ok) {
|
|
@@ -21,56 +23,145 @@ if (result.ok) {
|
|
|
21
23
|
}
|
|
22
24
|
```
|
|
23
25
|
|
|
24
|
-
##
|
|
26
|
+
## Configured instance
|
|
27
|
+
|
|
28
|
+
Pass options to `createApi` to set defaults that apply to every request:
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
const api = createApi({
|
|
32
|
+
baseUrl: 'https://api.example.com',
|
|
33
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
34
|
+
timeout: 5000,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Relative paths are resolved against baseUrl
|
|
38
|
+
const users = await api.get<User[]>('/users');
|
|
39
|
+
```
|
|
25
40
|
|
|
26
|
-
|
|
41
|
+
Per-request options always override instance defaults.
|
|
27
42
|
|
|
28
|
-
|
|
43
|
+
## Method helpers
|
|
44
|
+
|
|
45
|
+
All helpers are methods on the instance returned by `createApi` and return `Promise<ApiResponse<T>>`.
|
|
29
46
|
|
|
30
47
|
| Method | Signature |
|
|
31
48
|
|--------|-----------|
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
49
|
+
| `.get` | `(url, options?)` |
|
|
50
|
+
| `.post` | `(url, body?, options?)` |
|
|
51
|
+
| `.put` | `(url, body?, options?)` |
|
|
52
|
+
| `.patch` | `(url, body?, options?)` |
|
|
53
|
+
| `.delete` | `(url, options?)` |
|
|
54
|
+
| `.head` | `(url, options?)` |
|
|
55
|
+
| `.options` | `(url, options?)` |
|
|
39
56
|
|
|
40
57
|
Plain objects passed as `body` are automatically serialized to JSON.
|
|
41
58
|
|
|
42
|
-
|
|
59
|
+
## ApiResponse
|
|
43
60
|
|
|
44
61
|
```ts
|
|
45
62
|
type ApiResponse<T> =
|
|
46
|
-
| { ok: true; data: T;
|
|
47
|
-
| { ok: false; data: null;
|
|
63
|
+
| { ok: true; data: T | null; status: number }
|
|
64
|
+
| { ok: false; data: null; status: number };
|
|
48
65
|
```
|
|
49
66
|
|
|
50
|
-
Use `ok` to narrow the type. Status `0` means a network error or aborted request.
|
|
67
|
+
Use `ok` to narrow the type. Status `0` means a network error, timeout, or aborted request.
|
|
68
|
+
|
|
69
|
+
## Options reference
|
|
70
|
+
|
|
71
|
+
### `RequestOptions` (GET, DELETE, HEAD, OPTIONS)
|
|
72
|
+
|
|
73
|
+
| Field | Type | Default | Description |
|
|
74
|
+
|-------|------|---------|-------------|
|
|
75
|
+
| `accept` | `MimeType` | `MimeType.JSON` | Expected response MIME type |
|
|
76
|
+
| `headers` | `HeadersInit` | — | Additional headers |
|
|
77
|
+
| `signal` | `AbortSignal` | — | Cancel the request |
|
|
78
|
+
| `timeout` | `number` | — | Abort after N milliseconds |
|
|
79
|
+
| `retry` | `number` | `0` | Max additional attempts on network failure |
|
|
80
|
+
| `retryDelay` | `number` | `0` | Milliseconds to wait between retries |
|
|
51
81
|
|
|
52
|
-
###
|
|
82
|
+
### `RequestBodyOptions` (POST, PUT, PATCH)
|
|
83
|
+
|
|
84
|
+
Extends `RequestOptions` with:
|
|
85
|
+
|
|
86
|
+
| Field | Type | Default | Description |
|
|
87
|
+
|-------|------|---------|-------------|
|
|
88
|
+
| `contentType` | `MimeType` | `MimeType.JSON` | Request body content type |
|
|
89
|
+
| `compression` | `CompressionMethod` | — | Compress the request body |
|
|
90
|
+
|
|
91
|
+
### `ApiConfig` (createApi)
|
|
92
|
+
|
|
93
|
+
| Field | Type | Default | Description |
|
|
94
|
+
|-------|------|---------|-------------|
|
|
95
|
+
| `baseUrl` | `string \| URL` | — | Prepended to all relative request paths |
|
|
96
|
+
| `headers` | `HeadersInit` | — | Default headers for every request |
|
|
97
|
+
| `accept` | `MimeType` | `MimeType.JSON` | Default Accept type for every request |
|
|
98
|
+
| `timeout` | `number` | — | Default timeout for every request |
|
|
99
|
+
|
|
100
|
+
## Timeout
|
|
53
101
|
|
|
54
102
|
```ts
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
headers?: HeadersInit;
|
|
58
|
-
signal?: AbortSignal;
|
|
59
|
-
}
|
|
103
|
+
// Per-request
|
|
104
|
+
const result = await api.get('/data', { timeout: 3000 });
|
|
60
105
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
106
|
+
// Or set a default for all requests
|
|
107
|
+
const api = createApi({ timeout: 5000 });
|
|
108
|
+
const result = await api.get('/data'); // uses 5s timeout
|
|
65
109
|
```
|
|
66
110
|
|
|
67
|
-
|
|
111
|
+
Timed-out requests return `{ ok: false, status: 0 }`.
|
|
112
|
+
|
|
113
|
+
## Retry
|
|
68
114
|
|
|
69
|
-
|
|
115
|
+
Retries apply only to network failures (status 0). Server responses (4xx, 5xx) are never
|
|
116
|
+
retried. The wait between attempts doubles on each retry (exponential backoff).
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
const result = await api.get('/data', {
|
|
120
|
+
retry: 3, // up to 3 additional attempts
|
|
121
|
+
retryDelay: 500, // 500ms → 1000ms → 2000ms
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Abort
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
const controller = new AbortController();
|
|
129
|
+
|
|
130
|
+
const result = await api.get('/slow', { signal: controller.signal });
|
|
131
|
+
|
|
132
|
+
// Cancel from elsewhere
|
|
133
|
+
controller.abort();
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Aborted requests return `{ ok: false, status: 0 }`.
|
|
137
|
+
|
|
138
|
+
## Compression
|
|
139
|
+
|
|
140
|
+
Compress request bodies before sending (useful for large payloads):
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
const data = largeJsonPayload;
|
|
144
|
+
|
|
145
|
+
await api.post('/ingest', data, {
|
|
146
|
+
compression: CompressionMethod.GZIP,
|
|
147
|
+
});
|
|
148
|
+
```
|
|
70
149
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
150
|
+
`FormData` and `URLSearchParams` bodies are always passed through unchanged — the browser manages their encoding. Small payloads (under 1 KB) are skipped automatically.
|
|
151
|
+
|
|
152
|
+
## Exports
|
|
153
|
+
|
|
154
|
+
| Export | Kind | Description |
|
|
155
|
+
|--------|------|-------------|
|
|
156
|
+
| `createApi` | function | Creates a configured API instance |
|
|
157
|
+
| `ApiConfig` | type | Config object for `createApi` |
|
|
158
|
+
| `ApiInstance` | type | Return type of `createApi` |
|
|
159
|
+
| `ApiResponse` | type | Discriminated union response type |
|
|
160
|
+
| `RequestOptions` | type | Options for GET/DELETE/HEAD/OPTIONS |
|
|
161
|
+
| `RequestBodyOptions` | type | Options for POST/PUT/PATCH |
|
|
162
|
+
| `HttpMethod` | enum | GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS |
|
|
163
|
+
| `HttpStatus` | enum | Common HTTP status codes |
|
|
164
|
+
| `MimeType` | enum | Common MIME type strings |
|
|
165
|
+
| `CompressionMethod` | enum | gzip, deflate |
|
|
75
166
|
|
|
76
167
|
[fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
|
package/dist/api.d.ts
CHANGED
|
@@ -1,59 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ApiConfig, ApiInstance } from './static.ts';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Creates a configured API client.
|
|
4
4
|
*
|
|
5
5
|
* @example
|
|
6
6
|
* ```ts
|
|
7
|
-
* const
|
|
7
|
+
* const api = createApi({
|
|
8
|
+
* baseUrl: 'https://api.example.com',
|
|
9
|
+
* headers: { Authorization: `Bearer ${token}` },
|
|
10
|
+
* timeout: 5000,
|
|
11
|
+
* });
|
|
12
|
+
* const result = await api.get<User[]>('/users');
|
|
8
13
|
* if (result.ok) {
|
|
9
14
|
* console.log(result.data); // User[]
|
|
10
15
|
* }
|
|
11
16
|
* ```
|
|
12
17
|
*/
|
|
13
|
-
export declare
|
|
14
|
-
/**
|
|
15
|
-
* Sends a GET request.
|
|
16
|
-
* @param url - Request URL
|
|
17
|
-
* @param options - Request options (accept, headers, signal)
|
|
18
|
-
*/
|
|
19
|
-
get<T>(url: string | URL, options?: RequestOptions): Promise<ApiResponse<T>>;
|
|
20
|
-
/**
|
|
21
|
-
* Sends a POST request.
|
|
22
|
-
* @param url - Request URL
|
|
23
|
-
* @param body - Request body (auto-serialized to JSON if plain object)
|
|
24
|
-
* @param options - Request options (contentType, accept, headers, signal, compression)
|
|
25
|
-
*/
|
|
26
|
-
post<T>(url: string | URL, body?: BodyInit | object, options?: RequestBodyOptions): Promise<ApiResponse<T>>;
|
|
27
|
-
/**
|
|
28
|
-
* Sends a PUT request.
|
|
29
|
-
* @param url - Request URL
|
|
30
|
-
* @param body - Request body (auto-serialized to JSON if plain object)
|
|
31
|
-
* @param options - Request options (contentType, accept, headers, signal, compression)
|
|
32
|
-
*/
|
|
33
|
-
put<T>(url: string | URL, body?: BodyInit | object, options?: RequestBodyOptions): Promise<ApiResponse<T>>;
|
|
34
|
-
/**
|
|
35
|
-
* Sends a PATCH request.
|
|
36
|
-
* @param url - Request URL
|
|
37
|
-
* @param body - Request body (auto-serialized to JSON if plain object)
|
|
38
|
-
* @param options - Request options (contentType, accept, headers, signal, compression)
|
|
39
|
-
*/
|
|
40
|
-
patch<T>(url: string | URL, body?: BodyInit | object, options?: RequestBodyOptions): Promise<ApiResponse<T>>;
|
|
41
|
-
/**
|
|
42
|
-
* Sends a DELETE request.
|
|
43
|
-
* @param url - Request URL
|
|
44
|
-
* @param options - Request options (accept, headers, signal)
|
|
45
|
-
*/
|
|
46
|
-
delete<T>(url: string | URL, options?: RequestOptions): Promise<ApiResponse<T>>;
|
|
47
|
-
/**
|
|
48
|
-
* Sends a HEAD request. Returns status and headers only (no body).
|
|
49
|
-
* @param url - Request URL
|
|
50
|
-
* @param options - Request options (headers, signal)
|
|
51
|
-
*/
|
|
52
|
-
head(url: string | URL, options?: RequestOptions): Promise<ApiResponse<null>>;
|
|
53
|
-
/**
|
|
54
|
-
* Sends an OPTIONS request. Returns allowed methods and CORS info.
|
|
55
|
-
* @param url - Request URL
|
|
56
|
-
* @param options - Request options (accept, headers, signal)
|
|
57
|
-
*/
|
|
58
|
-
options<T>(url: string | URL, options?: RequestOptions): Promise<ApiResponse<T>>;
|
|
59
|
-
};
|
|
18
|
+
export declare function createApi(config?: ApiConfig): ApiInstance;
|
package/dist/auldrant-api.js
CHANGED
|
@@ -1,134 +1,151 @@
|
|
|
1
|
-
var
|
|
2
|
-
const
|
|
3
|
-
function
|
|
4
|
-
return
|
|
1
|
+
var g = /* @__PURE__ */ ((E) => (E[E.OK = 200] = "OK", E[E.CREATED = 201] = "CREATED", E[E.ACCEPTED = 202] = "ACCEPTED", E[E.NO_CONTENT = 204] = "NO_CONTENT", E[E.PARTIAL_CONTENT = 206] = "PARTIAL_CONTENT", E[E.MOVED_PERMANENTLY = 301] = "MOVED_PERMANENTLY", E[E.FOUND = 302] = "FOUND", E[E.SEE_OTHER = 303] = "SEE_OTHER", E[E.NOT_MODIFIED = 304] = "NOT_MODIFIED", E[E.TEMPORARY_REDIRECT = 307] = "TEMPORARY_REDIRECT", E[E.PERMANENT_REDIRECT = 308] = "PERMANENT_REDIRECT", E[E.BAD_REQUEST = 400] = "BAD_REQUEST", E[E.UNAUTHORIZED = 401] = "UNAUTHORIZED", E[E.PAYMENT_REQUIRED = 402] = "PAYMENT_REQUIRED", E[E.FORBIDDEN = 403] = "FORBIDDEN", E[E.NOT_FOUND = 404] = "NOT_FOUND", E[E.METHOD_NOT_ALLOWED = 405] = "METHOD_NOT_ALLOWED", E[E.NOT_ACCEPTABLE = 406] = "NOT_ACCEPTABLE", E[E.PROXY_AUTHENTICATION_REQUIRED = 407] = "PROXY_AUTHENTICATION_REQUIRED", E[E.REQUEST_TIMEOUT = 408] = "REQUEST_TIMEOUT", E[E.CONFLICT = 409] = "CONFLICT", E[E.GONE = 410] = "GONE", E[E.LENGTH_REQUIRED = 411] = "LENGTH_REQUIRED", E[E.PRECONDITION_FAILED = 412] = "PRECONDITION_FAILED", E[E.PAYLOAD_TOO_LARGE = 413] = "PAYLOAD_TOO_LARGE", E[E.URI_TOO_LONG = 414] = "URI_TOO_LONG", E[E.UNSUPPORTED_MEDIA_TYPE = 415] = "UNSUPPORTED_MEDIA_TYPE", E[E.RANGE_NOT_SATISFIABLE = 416] = "RANGE_NOT_SATISFIABLE", E[E.EXPECTATION_FAILED = 417] = "EXPECTATION_FAILED", E[E.IM_A_TEAPOT = 418] = "IM_A_TEAPOT", E[E.MISDIRECTED_REQUEST = 421] = "MISDIRECTED_REQUEST", E[E.UNPROCESSABLE_ENTITY = 422] = "UNPROCESSABLE_ENTITY", E[E.LOCKED = 423] = "LOCKED", E[E.FAILED_DEPENDENCY = 424] = "FAILED_DEPENDENCY", E[E.TOO_EARLY = 425] = "TOO_EARLY", E[E.UPGRADE_REQUIRED = 426] = "UPGRADE_REQUIRED", E[E.PRECONDITION_REQUIRED = 428] = "PRECONDITION_REQUIRED", E[E.TOO_MANY_REQUESTS = 429] = "TOO_MANY_REQUESTS", E[E.REQUEST_HEADER_FIELDS_TOO_LARGE = 431] = "REQUEST_HEADER_FIELDS_TOO_LARGE", E[E.UNAVAILABLE_FOR_LEGAL_REASONS = 451] = "UNAVAILABLE_FOR_LEGAL_REASONS", E[E.INTERNAL_SERVER_ERROR = 500] = "INTERNAL_SERVER_ERROR", E[E.NOT_IMPLEMENTED = 501] = "NOT_IMPLEMENTED", E[E.BAD_GATEWAY = 502] = "BAD_GATEWAY", E[E.SERVICE_UNAVAILABLE = 503] = "SERVICE_UNAVAILABLE", E[E.GATEWAY_TIMEOUT = 504] = "GATEWAY_TIMEOUT", E[E.HTTP_VERSION_NOT_SUPPORTED = 505] = "HTTP_VERSION_NOT_SUPPORTED", E[E.VARIANT_ALSO_NEGOTIATES = 506] = "VARIANT_ALSO_NEGOTIATES", E[E.INSUFFICIENT_STORAGE = 507] = "INSUFFICIENT_STORAGE", E[E.LOOP_DETECTED = 508] = "LOOP_DETECTED", E[E.NOT_EXTENDED = 510] = "NOT_EXTENDED", E[E.NETWORK_AUTHENTICATION_REQUIRED = 511] = "NETWORK_AUTHENTICATION_REQUIRED", E))(g || {}), r = /* @__PURE__ */ ((E) => (E.HTML = "text/html", E.PLAIN = "text/plain", E.CSV = "text/csv", E.CSS = "text/css", E.JAVASCRIPT = "text/javascript", E.JSON = "application/json", E.XML = "application/xml", E.PDF = "application/pdf", E.ZIP = "application/zip", E.GZIP = "application/gzip", E.OCTET_STREAM = "application/octet-stream", E.FORM_DATA = "multipart/form-data", E.URL_ENCODED = "application/x-www-form-urlencoded", E.JPEG = "image/jpeg", E.PNG = "image/png", E.GIF = "image/gif", E.SVG = "image/svg+xml", E.WEBP = "image/webp", E.ICO = "image/x-icon", E.MP4 = "video/mp4", E.WEBM = "video/webm", E.MP3 = "audio/mpeg", E.OGG = "audio/ogg", E.WAV = "audio/wav", E.TAR = "application/x-tar", E))(r || {}), N = /* @__PURE__ */ ((E) => (E.GET = "GET", E.POST = "POST", E.PUT = "PUT", E.DELETE = "DELETE", E.PATCH = "PATCH", E.OPTIONS = "OPTIONS", E.HEAD = "HEAD", E))(N || {}), B = /* @__PURE__ */ ((E) => (E.GZIP = "gzip", E.DEFLATE = "deflate", E))(B || {});
|
|
2
|
+
const Y = 1024;
|
|
3
|
+
function v(E, A) {
|
|
4
|
+
return A == null || E instanceof FormData || E instanceof URLSearchParams ? E : E instanceof ReadableStream ? E.pipeThrough(new CompressionStream(A)) : (typeof E == "string" ? E.length : E instanceof Blob ? E.size : E.byteLength) < Y ? E : new Blob([E]).stream().pipeThrough(new CompressionStream(A));
|
|
5
5
|
}
|
|
6
|
-
function
|
|
7
|
-
const _ = new Headers(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
function w(E, A, O, T, R, I) {
|
|
7
|
+
const _ = new Headers(T);
|
|
8
|
+
R && new Headers(R).forEach((e, P) => {
|
|
9
|
+
_.set(P, e);
|
|
10
|
+
}), _.has("Accept") || _.set("Accept", A);
|
|
11
|
+
const i = I instanceof FormData || I instanceof URLSearchParams;
|
|
12
|
+
return E != null && !i && !_.has("Content-Type") && _.set("Content-Type", E), O != null && !_.has("Content-Encoding") && _.set("Content-Encoding", O), _;
|
|
11
13
|
}
|
|
12
|
-
async function
|
|
13
|
-
switch (
|
|
14
|
-
case
|
|
14
|
+
async function Q(E, A) {
|
|
15
|
+
switch (A) {
|
|
16
|
+
case r.JSON:
|
|
15
17
|
return await E.json();
|
|
16
|
-
case
|
|
17
|
-
case
|
|
18
|
-
case
|
|
19
|
-
case
|
|
20
|
-
case
|
|
21
|
-
case
|
|
18
|
+
case r.PLAIN:
|
|
19
|
+
case r.HTML:
|
|
20
|
+
case r.CSV:
|
|
21
|
+
case r.XML:
|
|
22
|
+
case r.CSS:
|
|
23
|
+
case r.JAVASCRIPT:
|
|
22
24
|
return await E.text();
|
|
23
25
|
default:
|
|
24
26
|
return await E.blob();
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
|
-
|
|
28
|
-
const {
|
|
29
|
-
accept: r = R.JSON,
|
|
30
|
-
contentType: _ = R.JSON,
|
|
31
|
-
compression: D,
|
|
32
|
-
headers: C,
|
|
33
|
-
signal: i
|
|
34
|
-
} = n;
|
|
35
|
-
try {
|
|
36
|
-
const L = O != null && T !== A.GET && T !== A.HEAD ? f(O, D) : null, U = G(
|
|
37
|
-
O != null ? _ : void 0,
|
|
38
|
-
r,
|
|
39
|
-
O != null ? D : void 0,
|
|
40
|
-
C,
|
|
41
|
-
O
|
|
42
|
-
), e = {
|
|
43
|
-
method: T,
|
|
44
|
-
body: L,
|
|
45
|
-
headers: U
|
|
46
|
-
};
|
|
47
|
-
i != null && (e.signal = i);
|
|
48
|
-
const I = await fetch(E, e);
|
|
49
|
-
return I.ok ? T === A.HEAD || I.status === 204 ? { ok: !0, data: null, status: I.status } : { ok: !0, data: await a(I, r), status: I.status } : { ok: !1, data: null, status: I.status };
|
|
50
|
-
} catch {
|
|
51
|
-
return { ok: !1, data: null, status: 0 };
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
function P(E) {
|
|
29
|
+
function U(E) {
|
|
55
30
|
return E instanceof FormData || E instanceof URLSearchParams || E instanceof Blob || E instanceof ArrayBuffer || E instanceof ReadableStream || typeof E == "string" ? E : JSON.stringify(E);
|
|
56
31
|
}
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
* @param body - Request body (auto-serialized to JSON if plain object)
|
|
93
|
-
* @param options - Request options (contentType, accept, headers, signal, compression)
|
|
94
|
-
*/
|
|
95
|
-
patch(E, T, O) {
|
|
96
|
-
return N(
|
|
97
|
-
E,
|
|
98
|
-
A.PATCH,
|
|
99
|
-
T != null ? P(T) : void 0,
|
|
100
|
-
O
|
|
101
|
-
);
|
|
102
|
-
},
|
|
103
|
-
/**
|
|
104
|
-
* Sends a DELETE request.
|
|
105
|
-
* @param url - Request URL
|
|
106
|
-
* @param options - Request options (accept, headers, signal)
|
|
107
|
-
*/
|
|
108
|
-
delete(E, T) {
|
|
109
|
-
return N(E, A.DELETE, void 0, T);
|
|
110
|
-
},
|
|
111
|
-
/**
|
|
112
|
-
* Sends a HEAD request. Returns status and headers only (no body).
|
|
113
|
-
* @param url - Request URL
|
|
114
|
-
* @param options - Request options (headers, signal)
|
|
115
|
-
*/
|
|
116
|
-
head(E, T) {
|
|
117
|
-
return N(E, A.HEAD, void 0, T);
|
|
118
|
-
},
|
|
119
|
-
/**
|
|
120
|
-
* Sends an OPTIONS request. Returns allowed methods and CORS info.
|
|
121
|
-
* @param url - Request URL
|
|
122
|
-
* @param options - Request options (accept, headers, signal)
|
|
123
|
-
*/
|
|
124
|
-
options(E, T) {
|
|
125
|
-
return N(E, A.OPTIONS, void 0, T);
|
|
32
|
+
const V = (E) => new Promise((A) => setTimeout(A, E));
|
|
33
|
+
function x(E = {}) {
|
|
34
|
+
async function A(O, T, R, I = {}) {
|
|
35
|
+
const {
|
|
36
|
+
accept: _ = E.accept ?? r.JSON,
|
|
37
|
+
contentType: i = r.JSON,
|
|
38
|
+
compression: e,
|
|
39
|
+
headers: P,
|
|
40
|
+
signal: l,
|
|
41
|
+
retry: f = 0,
|
|
42
|
+
retryDelay: C = 0
|
|
43
|
+
} = I, G = E.baseUrl != null ? new URL(O, E.baseUrl) : O, D = I.timeout ?? E.timeout, o = l != null && D != null ? AbortSignal.any([l, AbortSignal.timeout(D)]) : D != null ? AbortSignal.timeout(D) : l;
|
|
44
|
+
let L = 0;
|
|
45
|
+
for (; ; )
|
|
46
|
+
try {
|
|
47
|
+
const c = R != null && T !== N.GET && T !== N.HEAD ? v(R, e) : null, F = w(
|
|
48
|
+
R != null ? i : void 0,
|
|
49
|
+
_,
|
|
50
|
+
R != null ? e : void 0,
|
|
51
|
+
E.headers,
|
|
52
|
+
P,
|
|
53
|
+
R
|
|
54
|
+
), a = {
|
|
55
|
+
method: T,
|
|
56
|
+
body: c,
|
|
57
|
+
headers: F
|
|
58
|
+
};
|
|
59
|
+
o != null && (a.signal = o);
|
|
60
|
+
const n = await fetch(G, a);
|
|
61
|
+
return n.ok ? T === N.HEAD || n.status === 204 ? { ok: !0, data: null, status: n.status } : { ok: !0, data: await Q(n, _), status: n.status } : { ok: !1, data: null, status: n.status };
|
|
62
|
+
} catch {
|
|
63
|
+
if (L >= f)
|
|
64
|
+
return { ok: !1, data: null, status: 0 };
|
|
65
|
+
L++, C > 0 && await V(C * 2 ** (L - 1));
|
|
66
|
+
}
|
|
126
67
|
}
|
|
127
|
-
|
|
68
|
+
return {
|
|
69
|
+
/**
|
|
70
|
+
* Sends a GET request.
|
|
71
|
+
* @param url - Request URL
|
|
72
|
+
* @param options - Request options (accept, headers, signal, timeout, retry, retryDelay)
|
|
73
|
+
*/
|
|
74
|
+
get(O, T) {
|
|
75
|
+
return A(O, N.GET, void 0, T);
|
|
76
|
+
},
|
|
77
|
+
/**
|
|
78
|
+
* Sends a POST request.
|
|
79
|
+
* @param url - Request URL
|
|
80
|
+
* @param body - Request body (auto-serialized to JSON if plain object)
|
|
81
|
+
* @param options - Request options (contentType, accept, headers, signal, compression, timeout, retry, retryDelay)
|
|
82
|
+
*/
|
|
83
|
+
post(O, T, R) {
|
|
84
|
+
return A(
|
|
85
|
+
O,
|
|
86
|
+
N.POST,
|
|
87
|
+
T != null ? U(T) : void 0,
|
|
88
|
+
R
|
|
89
|
+
);
|
|
90
|
+
},
|
|
91
|
+
/**
|
|
92
|
+
* Sends a PUT request.
|
|
93
|
+
* @param url - Request URL
|
|
94
|
+
* @param body - Request body (auto-serialized to JSON if plain object)
|
|
95
|
+
* @param options - Request options (contentType, accept, headers, signal, compression, timeout, retry, retryDelay)
|
|
96
|
+
*/
|
|
97
|
+
put(O, T, R) {
|
|
98
|
+
return A(
|
|
99
|
+
O,
|
|
100
|
+
N.PUT,
|
|
101
|
+
T != null ? U(T) : void 0,
|
|
102
|
+
R
|
|
103
|
+
);
|
|
104
|
+
},
|
|
105
|
+
/**
|
|
106
|
+
* Sends a PATCH request.
|
|
107
|
+
* @param url - Request URL
|
|
108
|
+
* @param body - Request body (auto-serialized to JSON if plain object)
|
|
109
|
+
* @param options - Request options (contentType, accept, headers, signal, compression, timeout, retry, retryDelay)
|
|
110
|
+
*/
|
|
111
|
+
patch(O, T, R) {
|
|
112
|
+
return A(
|
|
113
|
+
O,
|
|
114
|
+
N.PATCH,
|
|
115
|
+
T != null ? U(T) : void 0,
|
|
116
|
+
R
|
|
117
|
+
);
|
|
118
|
+
},
|
|
119
|
+
/**
|
|
120
|
+
* Sends a DELETE request.
|
|
121
|
+
* @param url - Request URL
|
|
122
|
+
* @param options - Request options (accept, headers, signal, timeout, retry, retryDelay)
|
|
123
|
+
*/
|
|
124
|
+
delete(O, T) {
|
|
125
|
+
return A(O, N.DELETE, void 0, T);
|
|
126
|
+
},
|
|
127
|
+
/**
|
|
128
|
+
* Sends a HEAD request. Returns status and headers only (no body).
|
|
129
|
+
* @param url - Request URL
|
|
130
|
+
* @param options - Request options (headers, signal, timeout)
|
|
131
|
+
*/
|
|
132
|
+
head(O, T) {
|
|
133
|
+
return A(O, N.HEAD, void 0, T);
|
|
134
|
+
},
|
|
135
|
+
/**
|
|
136
|
+
* Sends an OPTIONS request. Returns allowed methods and CORS info.
|
|
137
|
+
* @param url - Request URL
|
|
138
|
+
* @param options - Request options (accept, headers, signal, timeout)
|
|
139
|
+
*/
|
|
140
|
+
options(O, T) {
|
|
141
|
+
return A(O, N.OPTIONS, void 0, T);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
}
|
|
128
145
|
export {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
146
|
+
B as CompressionMethod,
|
|
147
|
+
N as HttpMethod,
|
|
148
|
+
g as HttpStatus,
|
|
149
|
+
r as MimeType,
|
|
150
|
+
x as createApi
|
|
134
151
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { type ApiResponse, CompressionMethod, HttpMethod, HttpStatus, MimeType, type RequestBodyOptions, type RequestOptions, } from './static.ts';
|
|
1
|
+
export { createApi } from './api.ts';
|
|
2
|
+
export { type ApiConfig, type ApiInstance, type ApiResponse, CompressionMethod, HttpMethod, HttpStatus, MimeType, type RequestBodyOptions, type RequestOptions, } from './static.ts';
|
package/dist/static.d.ts
CHANGED
|
@@ -99,6 +99,20 @@ export interface RequestOptions {
|
|
|
99
99
|
headers?: HeadersInit;
|
|
100
100
|
/** AbortSignal to cancel the request. */
|
|
101
101
|
signal?: AbortSignal;
|
|
102
|
+
/** Abort the request after this many milliseconds (raises a TimeoutError). */
|
|
103
|
+
timeout?: number;
|
|
104
|
+
/**
|
|
105
|
+
* Maximum number of additional attempts on network failure (status 0).
|
|
106
|
+
* Server responses (4xx, 5xx) are never retried — they are intentional responses.
|
|
107
|
+
* Defaults to 0 (no retry).
|
|
108
|
+
*/
|
|
109
|
+
retry?: number;
|
|
110
|
+
/**
|
|
111
|
+
* Base delay in milliseconds for exponential backoff between retry attempts.
|
|
112
|
+
* Attempt 1 waits `retryDelay` ms, attempt 2 waits `retryDelay * 2` ms, etc.
|
|
113
|
+
* Defaults to 0 (no delay).
|
|
114
|
+
*/
|
|
115
|
+
retryDelay?: number;
|
|
102
116
|
}
|
|
103
117
|
/** Options for requests that carry a body (POST, PUT, PATCH). */
|
|
104
118
|
export interface RequestBodyOptions extends RequestOptions {
|
|
@@ -120,3 +134,28 @@ export type ApiResponse<T> = {
|
|
|
120
134
|
data: null;
|
|
121
135
|
status: number;
|
|
122
136
|
};
|
|
137
|
+
/**
|
|
138
|
+
* Configuration for a {@link createApi} instance.
|
|
139
|
+
* All fields are optional. Per-request options always take precedence over these defaults.
|
|
140
|
+
*/
|
|
141
|
+
export interface ApiConfig {
|
|
142
|
+
/** Base URL prepended to all relative request paths. Absolute URLs and URL
|
|
143
|
+
* instances bypass this automatically. */
|
|
144
|
+
baseUrl?: string | URL;
|
|
145
|
+
/** Default headers included in every request. Per-request headers take precedence. */
|
|
146
|
+
headers?: HeadersInit;
|
|
147
|
+
/** Default Accept MIME type for all requests. Defaults to {@link MimeType.JSON}. */
|
|
148
|
+
accept?: MimeType;
|
|
149
|
+
/** Default timeout in milliseconds for all requests. */
|
|
150
|
+
timeout?: number;
|
|
151
|
+
}
|
|
152
|
+
/** A configured API client returned by {@link createApi}. */
|
|
153
|
+
export interface ApiInstance {
|
|
154
|
+
get<T>(url: string | URL, options?: RequestOptions): Promise<ApiResponse<T>>;
|
|
155
|
+
post<T>(url: string | URL, body?: BodyInit | object, options?: RequestBodyOptions): Promise<ApiResponse<T>>;
|
|
156
|
+
put<T>(url: string | URL, body?: BodyInit | object, options?: RequestBodyOptions): Promise<ApiResponse<T>>;
|
|
157
|
+
patch<T>(url: string | URL, body?: BodyInit | object, options?: RequestBodyOptions): Promise<ApiResponse<T>>;
|
|
158
|
+
delete<T>(url: string | URL, options?: RequestOptions): Promise<ApiResponse<T>>;
|
|
159
|
+
head(url: string | URL, options?: RequestOptions): Promise<ApiResponse<null>>;
|
|
160
|
+
options<T>(url: string | URL, options?: RequestOptions): Promise<ApiResponse<T>>;
|
|
161
|
+
}
|