aspi 2.6.0 → 2.8.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 +14 -11
- package/dist/index.cjs +84 -16
- package/dist/index.d.cts +125 -68
- package/dist/index.d.ts +125 -68
- package/dist/index.js +83 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Zero runtime dependencies. Three response modes. Full error-union types.
|
|
|
12
12
|
## Features
|
|
13
13
|
|
|
14
14
|
- **Zero dependencies** — thin wrapper around the platform `fetch` API
|
|
15
|
-
- **Three response modes** — tuple `[data, error]`, `Result` monad, or `throwable` (your choice per call)
|
|
15
|
+
- **Three response modes** — tuple `[data, error]`, `Result` monad, or `throwable` (your choice per call, plus explicit `.withTuple()` to reset)
|
|
16
16
|
- **Typed error unions** — every error variant is tagged and narrowable at compile time
|
|
17
17
|
- **Custom error mapping** — map any HTTP status code to a structured, typed error object
|
|
18
18
|
- **Retry with back-off** — fixed or dynamic delay, status-code filtering, custom predicates
|
|
@@ -65,7 +65,7 @@ if (data) console.log(data.title);
|
|
|
65
65
|
|
|
66
66
|
## Response modes
|
|
67
67
|
|
|
68
|
-
Every request can be consumed in one of three modes. Switch mode by calling `.withResult()
|
|
68
|
+
Every request can be consumed in one of three modes. Switch mode by calling `.withResult()`, `.throwable()`, or `.withTuple()` before the body-parser method.
|
|
69
69
|
|
|
70
70
|
### 1. Tuple mode (default)
|
|
71
71
|
|
|
@@ -106,7 +106,7 @@ try {
|
|
|
106
106
|
}
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
-
> `throwable()` and `
|
|
109
|
+
> `throwable()`, `withResult()`, and `withTuple()` are mutually exclusive — the **last one called wins**. Use `.withTuple()` to explicitly reset back to the default tuple mode after a previous `.withResult()` or `.throwable()`.
|
|
110
110
|
|
|
111
111
|
---
|
|
112
112
|
|
|
@@ -116,12 +116,12 @@ try {
|
|
|
116
116
|
|
|
117
117
|
Every response mode surfaces the same tagged error variants:
|
|
118
118
|
|
|
119
|
-
| Tag
|
|
120
|
-
|
|
|
121
|
-
| `aspiError`
|
|
122
|
-
| `jsonParseError`
|
|
123
|
-
| `
|
|
124
|
-
| _custom_
|
|
119
|
+
| Tag | When |
|
|
120
|
+
| ------------------ | ------------------------------------------------------------------------------------------------- |
|
|
121
|
+
| `aspiError` | Any non-2xx response with no matching custom handler |
|
|
122
|
+
| `jsonParseError` | Response body could not be parsed as JSON |
|
|
123
|
+
| `schemaParseError` | Response (or request body) failed schema validation (when `.schema()` or `.bodySchema()` is used) |
|
|
124
|
+
| _custom_ | Any tag you define via `.error()` or a convenience shortcut |
|
|
125
125
|
|
|
126
126
|
### Custom error mapping
|
|
127
127
|
|
|
@@ -228,7 +228,7 @@ const [data, error] = await api
|
|
|
228
228
|
.bodyJson({ name: 'Alice', email: 'alice@example.com' })
|
|
229
229
|
.json<User>();
|
|
230
230
|
|
|
231
|
-
// If bodyJson fails validation, error.tag === '
|
|
231
|
+
// If bodyJson fails validation, error.tag === 'schemaParseError'
|
|
232
232
|
```
|
|
233
233
|
|
|
234
234
|
### Query parameters
|
|
@@ -309,6 +309,8 @@ Aspi integrates with any library that implements the [StandardSchemaV1](https://
|
|
|
309
309
|
|
|
310
310
|
Attach a schema with `.schema()` before the body-parser. The inferred output type is used automatically — you don't need to pass a generic.
|
|
311
311
|
|
|
312
|
+
Aspi supports both **synchronous and asynchronous** `validate` implementations, so schema libraries that return `Promise<Result>` work out of the box.
|
|
313
|
+
|
|
312
314
|
```ts
|
|
313
315
|
import { z } from 'zod';
|
|
314
316
|
|
|
@@ -323,7 +325,7 @@ const result = await api.get('/todos/1').withResult().schema(TodoSchema).json();
|
|
|
323
325
|
Result.match(result, {
|
|
324
326
|
onOk: ({ data }) => console.log(data.title), // data: { id: number; title: string; completed: boolean }
|
|
325
327
|
onErr: (err) => {
|
|
326
|
-
if (err.tag === '
|
|
328
|
+
if (err.tag === 'schemaParseError') {
|
|
327
329
|
console.error('Validation failed:', err.data); // StandardSchemaV1 issue list
|
|
328
330
|
}
|
|
329
331
|
},
|
|
@@ -530,6 +532,7 @@ These methods are available on the `Aspi` instance and affect all requests creat
|
|
|
530
532
|
| `useCapability(cap)` | Register a capability |
|
|
531
533
|
| `withResult()` | Switch all requests to Result mode |
|
|
532
534
|
| `throwable()` | Switch all requests to throwable mode |
|
|
535
|
+
| `withTuple()` | Switch all requests back to tuple mode |
|
|
533
536
|
| `.error(tag, status, cb)` | Map an HTTP status to a typed error |
|
|
534
537
|
|
|
535
538
|
Per-request methods (`api.get('/…').setQueryParams(…)`, `.schema(…)`, `.bodyJson(…)`, etc.) override the global config for that call only.
|
package/dist/index.cjs
CHANGED
|
@@ -20,7 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
Aspi: () =>
|
|
23
|
+
Aspi: () => Aspi2,
|
|
24
24
|
AspiError: () => AspiError,
|
|
25
25
|
CustomError: () => CustomError,
|
|
26
26
|
Request: () => Request,
|
|
@@ -30,7 +30,7 @@ __export(index_exports, {
|
|
|
30
30
|
isAspiError: () => isAspiError,
|
|
31
31
|
isCustomError: () => isCustomError,
|
|
32
32
|
isJSONParseError: () => isJSONParseError,
|
|
33
|
-
|
|
33
|
+
isSchemaParseError: () => isSchemaParseError
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
36
|
|
|
@@ -110,12 +110,12 @@ var isAspiError = (error) => {
|
|
|
110
110
|
var isCustomError = (error) => {
|
|
111
111
|
return error instanceof CustomError;
|
|
112
112
|
};
|
|
113
|
-
var isParseError = (error) => {
|
|
114
|
-
return error instanceof CustomError && error.tag === "parseError";
|
|
115
|
-
};
|
|
116
113
|
var isJSONParseError = (error) => {
|
|
117
114
|
return error instanceof CustomError && error.tag === "jsonParseError";
|
|
118
115
|
};
|
|
116
|
+
var isSchemaParseError = (error) => {
|
|
117
|
+
return error instanceof CustomError && error.tag === "schemaParseError";
|
|
118
|
+
};
|
|
119
119
|
|
|
120
120
|
// src/result.ts
|
|
121
121
|
var result_exports = {};
|
|
@@ -325,6 +325,8 @@ var Request = class {
|
|
|
325
325
|
#timeoutMs;
|
|
326
326
|
#shouldBeResult = false;
|
|
327
327
|
#bodySchemaIssues = [];
|
|
328
|
+
#bodySchemaAsyncResult = null;
|
|
329
|
+
#bodySchemaAsyncBody = null;
|
|
328
330
|
#throwOnError = false;
|
|
329
331
|
#capabilities = [];
|
|
330
332
|
constructor(method, path, requestOptions, capabilities = []) {
|
|
@@ -478,9 +480,9 @@ var Request = class {
|
|
|
478
480
|
if (this.#bodySchema) {
|
|
479
481
|
const data = this.#bodySchema["~standard"].validate(body);
|
|
480
482
|
if (data instanceof Promise) {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
if (data.issues) {
|
|
483
|
+
this.#bodySchemaAsyncResult = data;
|
|
484
|
+
this.#bodySchemaAsyncBody = body;
|
|
485
|
+
} else if (data.issues) {
|
|
484
486
|
this.#bodySchemaIssues = data.issues;
|
|
485
487
|
} else {
|
|
486
488
|
this.#localRequestInit.body = JSON.stringify(data.value);
|
|
@@ -1158,6 +1160,49 @@ var Request = class {
|
|
|
1158
1160
|
this.#shouldBeResult = true;
|
|
1159
1161
|
return this;
|
|
1160
1162
|
}
|
|
1163
|
+
/**
|
|
1164
|
+
* Switches the request into **tuple** mode (the default).
|
|
1165
|
+
*
|
|
1166
|
+
* In tuple mode the response helpers (`json`, `text`, `blob`, …) resolve to a
|
|
1167
|
+
* tuple `[value, error]` where exactly one element is non‑null. This is useful
|
|
1168
|
+
* when you want an explicit opt‑in method to reset from `withResult()` or
|
|
1169
|
+
* `throwable()` back to the default tuple behaviour.
|
|
1170
|
+
*
|
|
1171
|
+
* Calling `withTuple` disables both Result mode and throwable mode.
|
|
1172
|
+
*
|
|
1173
|
+
* @returns {Request<
|
|
1174
|
+
* Method,
|
|
1175
|
+
* TRequest,
|
|
1176
|
+
* Merge<
|
|
1177
|
+
* Omit<Opts, 'withResult' | 'throwable'>,
|
|
1178
|
+
* {
|
|
1179
|
+
* withResult: false;
|
|
1180
|
+
* throwable: false;
|
|
1181
|
+
* }
|
|
1182
|
+
* >
|
|
1183
|
+
* >} The same {@link Request} instance, now typed with `withResult: false` and
|
|
1184
|
+
* `throwable: false` for fluent chaining.
|
|
1185
|
+
*
|
|
1186
|
+
* @example
|
|
1187
|
+
* ```ts
|
|
1188
|
+
* const request = new Request('/users', config);
|
|
1189
|
+
*
|
|
1190
|
+
* const [user, err] = await request
|
|
1191
|
+
* .withTuple() // explicitly use tuple mode
|
|
1192
|
+
* .json<User>();
|
|
1193
|
+
*
|
|
1194
|
+
* if (err) {
|
|
1195
|
+
* console.error(err);
|
|
1196
|
+
* } else {
|
|
1197
|
+
* console.log(user);
|
|
1198
|
+
* }
|
|
1199
|
+
* ```
|
|
1200
|
+
*/
|
|
1201
|
+
withTuple() {
|
|
1202
|
+
this.#throwOnError = false;
|
|
1203
|
+
this.#shouldBeResult = false;
|
|
1204
|
+
return this;
|
|
1205
|
+
}
|
|
1161
1206
|
#mapResponse(value) {
|
|
1162
1207
|
if (this.#shouldBeResult) {
|
|
1163
1208
|
return value;
|
|
@@ -1175,8 +1220,20 @@ var Request = class {
|
|
|
1175
1220
|
return response.ok || response.status >= 300 && response.status < 400;
|
|
1176
1221
|
}
|
|
1177
1222
|
async #makeRequest(responseParser, isJson = false) {
|
|
1223
|
+
if (this.#bodySchemaAsyncResult) {
|
|
1224
|
+
const data = await this.#bodySchemaAsyncResult;
|
|
1225
|
+
if (data.issues) {
|
|
1226
|
+
this.#bodySchemaIssues = data.issues;
|
|
1227
|
+
} else {
|
|
1228
|
+
this.#localRequestInit.body = JSON.stringify(data.value);
|
|
1229
|
+
}
|
|
1230
|
+
this.#bodySchemaAsyncResult = null;
|
|
1231
|
+
this.#bodySchemaAsyncBody = null;
|
|
1232
|
+
}
|
|
1178
1233
|
if (this.#bodySchemaIssues.length) {
|
|
1179
|
-
return err(
|
|
1234
|
+
return err(
|
|
1235
|
+
new CustomError("schemaParseError", this.#bodySchemaIssues)
|
|
1236
|
+
);
|
|
1180
1237
|
}
|
|
1181
1238
|
const request = this.#request();
|
|
1182
1239
|
const { retries, retryDelay, retryOn, retryWhile, onRetry } = this.#sanitisedRetryConfig();
|
|
@@ -1310,12 +1367,9 @@ var Request = class {
|
|
|
1310
1367
|
);
|
|
1311
1368
|
}
|
|
1312
1369
|
if (isJson && this.#schema) {
|
|
1313
|
-
const data = this.#schema["~standard"].validate(responseData);
|
|
1314
|
-
if (data instanceof Promise) {
|
|
1315
|
-
throw new Error("Schema validation should not return a promise");
|
|
1316
|
-
}
|
|
1370
|
+
const data = await this.#schema["~standard"].validate(responseData);
|
|
1317
1371
|
if (data.issues) {
|
|
1318
|
-
return err(new CustomError("
|
|
1372
|
+
return err(new CustomError("schemaParseError", data.issues));
|
|
1319
1373
|
}
|
|
1320
1374
|
return ok({
|
|
1321
1375
|
data: data.value,
|
|
@@ -1525,7 +1579,7 @@ var Request = class {
|
|
|
1525
1579
|
};
|
|
1526
1580
|
|
|
1527
1581
|
// src/aspi.ts
|
|
1528
|
-
var
|
|
1582
|
+
var Aspi2 = class {
|
|
1529
1583
|
#globalRequestInit;
|
|
1530
1584
|
#middlewares = [];
|
|
1531
1585
|
#retryConfig;
|
|
@@ -1885,6 +1939,20 @@ var Aspi = class {
|
|
|
1885
1939
|
this.#throwOnError = false;
|
|
1886
1940
|
return this;
|
|
1887
1941
|
}
|
|
1942
|
+
/**
|
|
1943
|
+
* Configures all subsequent requests to return the default tuple `[value, error]`.
|
|
1944
|
+
*
|
|
1945
|
+
* This is the default behaviour, but `withTuple()` is provided as an explicit
|
|
1946
|
+
* reset when you have previously called {@link withResult} or {@link throwable}
|
|
1947
|
+
* on the {@link Aspi} instance.
|
|
1948
|
+
*
|
|
1949
|
+
* @returns The Aspi instance with tuple handling enabled.
|
|
1950
|
+
*/
|
|
1951
|
+
withTuple() {
|
|
1952
|
+
this.#shouldBeResult = false;
|
|
1953
|
+
this.#throwOnError = false;
|
|
1954
|
+
return this;
|
|
1955
|
+
}
|
|
1888
1956
|
/**
|
|
1889
1957
|
* Registers a capability on this {@link Aspi} instance.
|
|
1890
1958
|
*
|
|
@@ -1939,5 +2007,5 @@ var Aspi = class {
|
|
|
1939
2007
|
isAspiError,
|
|
1940
2008
|
isCustomError,
|
|
1941
2009
|
isJSONParseError,
|
|
1942
|
-
|
|
2010
|
+
isSchemaParseError
|
|
1943
2011
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standard Schema is a common interface designed to be implemented by JavaScript and TypeScript schema libraries.
|
|
3
|
+
* Will support multiple schema validators including Zod, Valibot, and ArkType
|
|
4
|
+
* https://standardschema.dev/
|
|
5
|
+
*/
|
|
6
|
+
/** The Standard Schema interface. */
|
|
7
|
+
interface StandardSchemaV1<Input = unknown, Output = Input> {
|
|
8
|
+
/** The Standard Schema properties. */
|
|
9
|
+
readonly '~standard': StandardSchemaV1.Props<Input, Output>;
|
|
10
|
+
}
|
|
11
|
+
declare namespace StandardSchemaV1 {
|
|
12
|
+
/** The Standard Schema properties interface. */
|
|
13
|
+
interface Props<Input = unknown, Output = Input> {
|
|
14
|
+
/** The version number of the standard. */
|
|
15
|
+
readonly version: 1;
|
|
16
|
+
/** The vendor name of the schema library. */
|
|
17
|
+
readonly vendor: string;
|
|
18
|
+
/** Validates unknown input values. */
|
|
19
|
+
readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;
|
|
20
|
+
/** Inferred types associated with the schema. */
|
|
21
|
+
readonly types?: Types<Input, Output> | undefined;
|
|
22
|
+
}
|
|
23
|
+
/** The result interface of the validate function. */
|
|
24
|
+
type Result<Output> = SuccessResult<Output> | FailureResult;
|
|
25
|
+
/** The result interface if validation succeeds. */
|
|
26
|
+
interface SuccessResult<Output> {
|
|
27
|
+
/** The typed output value. */
|
|
28
|
+
readonly value: Output;
|
|
29
|
+
/** The non-existent issues. */
|
|
30
|
+
readonly issues?: undefined;
|
|
31
|
+
}
|
|
32
|
+
/** The result interface if validation fails. */
|
|
33
|
+
interface FailureResult {
|
|
34
|
+
/** The issues of failed validation. */
|
|
35
|
+
readonly issues: ReadonlyArray<Issue>;
|
|
36
|
+
}
|
|
37
|
+
/** The issue interface of the failure output. */
|
|
38
|
+
interface Issue {
|
|
39
|
+
/** The error message of the issue. */
|
|
40
|
+
readonly message: string;
|
|
41
|
+
/** The path of the issue, if any. */
|
|
42
|
+
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
|
|
43
|
+
}
|
|
44
|
+
/** The path segment interface of the issue. */
|
|
45
|
+
interface PathSegment {
|
|
46
|
+
/** The key representing a path segment. */
|
|
47
|
+
readonly key: PropertyKey;
|
|
48
|
+
}
|
|
49
|
+
/** The Standard Schema types interface. */
|
|
50
|
+
interface Types<Input = unknown, Output = Input> {
|
|
51
|
+
/** The input type of the schema. */
|
|
52
|
+
readonly input: Input;
|
|
53
|
+
/** The output type of the schema. */
|
|
54
|
+
readonly output: Output;
|
|
55
|
+
}
|
|
56
|
+
/** Infers the input type of a Standard Schema. */
|
|
57
|
+
type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['input'];
|
|
58
|
+
/** Infers the output type of a Standard Schema. */
|
|
59
|
+
type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['output'];
|
|
60
|
+
}
|
|
61
|
+
|
|
1
62
|
/**
|
|
2
63
|
* Standard HTTP /**
|
|
3
64
|
* Common HTTP error status codes with their numeric values.
|
|
@@ -364,14 +425,16 @@ interface JSONParseError extends CustomError<'jsonParseError', {
|
|
|
364
425
|
}> {
|
|
365
426
|
}
|
|
366
427
|
/**
|
|
367
|
-
*
|
|
368
|
-
*
|
|
428
|
+
* Interface representing a schema validation error (body or response).
|
|
429
|
+
* @interface SchemaParseError
|
|
430
|
+
* @extends {CustomError<'schemaParseError', ReadonlyArray<StandardSchemaV1.Issue>>}
|
|
369
431
|
*/
|
|
370
|
-
|
|
432
|
+
interface SchemaParseError extends CustomError<'schemaParseError', ReadonlyArray<StandardSchemaV1.Issue>> {
|
|
433
|
+
}
|
|
371
434
|
declare const isAspiError: <TReq extends AspiRequestInit>(error: unknown) => error is AspiError<TReq>;
|
|
372
435
|
declare const isCustomError: <Tag extends string, A>(error: unknown) => error is CustomError<Tag, A>;
|
|
373
|
-
declare const isParseError: (error: unknown) => error is ParseError;
|
|
374
436
|
declare const isJSONParseError: (error: unknown) => error is JSONParseError;
|
|
437
|
+
declare const isSchemaParseError: (error: unknown) => error is SchemaParseError;
|
|
375
438
|
|
|
376
439
|
/**
|
|
377
440
|
* Arguments passed to a capability factory.
|
|
@@ -756,67 +819,6 @@ declare namespace result {
|
|
|
756
819
|
export { type result_Err as Err, type result_Ok as Ok, type result_Result as Result, result_catchAllErrors as catchAllErrors, result_catchError as catchError, result_catchErrors as catchErrors, result_err as err, result_getErrorOrNull as getErrorOrNull, result_getOrElse as getOrElse, result_getOrNull as getOrNull, result_getOrThrow as getOrThrow, result_getOrThrowWith as getOrThrowWith, result_isErr as isErr, result_isOk as isOk, result_map as map, result_mapErr as mapErr, result_match as match, result_ok as ok, result_pipe as pipe };
|
|
757
820
|
}
|
|
758
821
|
|
|
759
|
-
/**
|
|
760
|
-
* Standard Schema is a common interface designed to be implemented by JavaScript and TypeScript schema libraries.
|
|
761
|
-
* Will support multiple schema validators including Zod, Valibot, and ArkType
|
|
762
|
-
* https://standardschema.dev/
|
|
763
|
-
*/
|
|
764
|
-
/** The Standard Schema interface. */
|
|
765
|
-
interface StandardSchemaV1<Input = unknown, Output = Input> {
|
|
766
|
-
/** The Standard Schema properties. */
|
|
767
|
-
readonly '~standard': StandardSchemaV1.Props<Input, Output>;
|
|
768
|
-
}
|
|
769
|
-
declare namespace StandardSchemaV1 {
|
|
770
|
-
/** The Standard Schema properties interface. */
|
|
771
|
-
interface Props<Input = unknown, Output = Input> {
|
|
772
|
-
/** The version number of the standard. */
|
|
773
|
-
readonly version: 1;
|
|
774
|
-
/** The vendor name of the schema library. */
|
|
775
|
-
readonly vendor: string;
|
|
776
|
-
/** Validates unknown input values. */
|
|
777
|
-
readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;
|
|
778
|
-
/** Inferred types associated with the schema. */
|
|
779
|
-
readonly types?: Types<Input, Output> | undefined;
|
|
780
|
-
}
|
|
781
|
-
/** The result interface of the validate function. */
|
|
782
|
-
type Result<Output> = SuccessResult<Output> | FailureResult;
|
|
783
|
-
/** The result interface if validation succeeds. */
|
|
784
|
-
interface SuccessResult<Output> {
|
|
785
|
-
/** The typed output value. */
|
|
786
|
-
readonly value: Output;
|
|
787
|
-
/** The non-existent issues. */
|
|
788
|
-
readonly issues?: undefined;
|
|
789
|
-
}
|
|
790
|
-
/** The result interface if validation fails. */
|
|
791
|
-
interface FailureResult {
|
|
792
|
-
/** The issues of failed validation. */
|
|
793
|
-
readonly issues: ReadonlyArray<Issue>;
|
|
794
|
-
}
|
|
795
|
-
/** The issue interface of the failure output. */
|
|
796
|
-
interface Issue {
|
|
797
|
-
/** The error message of the issue. */
|
|
798
|
-
readonly message: string;
|
|
799
|
-
/** The path of the issue, if any. */
|
|
800
|
-
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
|
|
801
|
-
}
|
|
802
|
-
/** The path segment interface of the issue. */
|
|
803
|
-
interface PathSegment {
|
|
804
|
-
/** The key representing a path segment. */
|
|
805
|
-
readonly key: PropertyKey;
|
|
806
|
-
}
|
|
807
|
-
/** The Standard Schema types interface. */
|
|
808
|
-
interface Types<Input = unknown, Output = Input> {
|
|
809
|
-
/** The input type of the schema. */
|
|
810
|
-
readonly input: Input;
|
|
811
|
-
/** The output type of the schema. */
|
|
812
|
-
readonly output: Output;
|
|
813
|
-
}
|
|
814
|
-
/** Infers the input type of a Standard Schema. */
|
|
815
|
-
type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['input'];
|
|
816
|
-
/** Infers the output type of a Standard Schema. */
|
|
817
|
-
type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['output'];
|
|
818
|
-
}
|
|
819
|
-
|
|
820
822
|
/**
|
|
821
823
|
* A class for building and executing HTTP requests with customizable options and error handling.
|
|
822
824
|
* @template Method The HTTP method type (GET, POST, etc.)
|
|
@@ -937,7 +939,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
937
939
|
bodySchema<TSchema extends StandardSchemaV1>(schema: TSchema): Request<Method, TRequest, Omit<Opts, "bodySchema"> & {
|
|
938
940
|
bodySchema: TSchema;
|
|
939
941
|
error: Opts["error"] & {
|
|
940
|
-
|
|
942
|
+
schemaParseError: CustomError<"schemaParseError", StandardSchemaV1.FailureResult["issues"]>;
|
|
941
943
|
};
|
|
942
944
|
}>;
|
|
943
945
|
/**
|
|
@@ -1209,7 +1211,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
1209
1211
|
schema<TSchema extends StandardSchemaV1>(schema: TSchema): Request<Method, TRequest, Merge<Omit<Opts, "schema">, {
|
|
1210
1212
|
schema: TSchema;
|
|
1211
1213
|
error: Merge<Opts["error"], {
|
|
1212
|
-
|
|
1214
|
+
schemaParseError: CustomError<"schemaParseError", StandardSchemaV1.FailureResult["issues"]>;
|
|
1213
1215
|
}>;
|
|
1214
1216
|
}>>;
|
|
1215
1217
|
/**
|
|
@@ -1562,6 +1564,48 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
1562
1564
|
withResult: true;
|
|
1563
1565
|
throwable: false;
|
|
1564
1566
|
}>>;
|
|
1567
|
+
/**
|
|
1568
|
+
* Switches the request into **tuple** mode (the default).
|
|
1569
|
+
*
|
|
1570
|
+
* In tuple mode the response helpers (`json`, `text`, `blob`, …) resolve to a
|
|
1571
|
+
* tuple `[value, error]` where exactly one element is non‑null. This is useful
|
|
1572
|
+
* when you want an explicit opt‑in method to reset from `withResult()` or
|
|
1573
|
+
* `throwable()` back to the default tuple behaviour.
|
|
1574
|
+
*
|
|
1575
|
+
* Calling `withTuple` disables both Result mode and throwable mode.
|
|
1576
|
+
*
|
|
1577
|
+
* @returns {Request<
|
|
1578
|
+
* Method,
|
|
1579
|
+
* TRequest,
|
|
1580
|
+
* Merge<
|
|
1581
|
+
* Omit<Opts, 'withResult' | 'throwable'>,
|
|
1582
|
+
* {
|
|
1583
|
+
* withResult: false;
|
|
1584
|
+
* throwable: false;
|
|
1585
|
+
* }
|
|
1586
|
+
* >
|
|
1587
|
+
* >} The same {@link Request} instance, now typed with `withResult: false` and
|
|
1588
|
+
* `throwable: false` for fluent chaining.
|
|
1589
|
+
*
|
|
1590
|
+
* @example
|
|
1591
|
+
* ```ts
|
|
1592
|
+
* const request = new Request('/users', config);
|
|
1593
|
+
*
|
|
1594
|
+
* const [user, err] = await request
|
|
1595
|
+
* .withTuple() // explicitly use tuple mode
|
|
1596
|
+
* .json<User>();
|
|
1597
|
+
*
|
|
1598
|
+
* if (err) {
|
|
1599
|
+
* console.error(err);
|
|
1600
|
+
* } else {
|
|
1601
|
+
* console.log(user);
|
|
1602
|
+
* }
|
|
1603
|
+
* ```
|
|
1604
|
+
*/
|
|
1605
|
+
withTuple(): Request<Method, TRequest, Merge<Omit<Opts, "withResult" | "throwable">, {
|
|
1606
|
+
withResult: false;
|
|
1607
|
+
throwable: false;
|
|
1608
|
+
}>>;
|
|
1565
1609
|
/**
|
|
1566
1610
|
* Returns the underlying {@link AspiRequest} object that will be used for the fetch call.
|
|
1567
1611
|
*
|
|
@@ -1965,6 +2009,19 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
|
|
|
1965
2009
|
withResult: true;
|
|
1966
2010
|
throwable: false;
|
|
1967
2011
|
}>>;
|
|
2012
|
+
/**
|
|
2013
|
+
* Configures all subsequent requests to return the default tuple `[value, error]`.
|
|
2014
|
+
*
|
|
2015
|
+
* This is the default behaviour, but `withTuple()` is provided as an explicit
|
|
2016
|
+
* reset when you have previously called {@link withResult} or {@link throwable}
|
|
2017
|
+
* on the {@link Aspi} instance.
|
|
2018
|
+
*
|
|
2019
|
+
* @returns The Aspi instance with tuple handling enabled.
|
|
2020
|
+
*/
|
|
2021
|
+
withTuple(): Aspi<TRequest, Merge<Omit<Opts, "withResult" | "throwable">, {
|
|
2022
|
+
withResult: false;
|
|
2023
|
+
throwable: false;
|
|
2024
|
+
}>>;
|
|
1968
2025
|
/**
|
|
1969
2026
|
* Registers a capability on this {@link Aspi} instance.
|
|
1970
2027
|
*
|
|
@@ -2005,4 +2062,4 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
|
|
|
2005
2062
|
useCapability(capability: Capability<TRequest>): this;
|
|
2006
2063
|
}
|
|
2007
2064
|
|
|
2008
|
-
export { Aspi, type AspiConfigBase, AspiError, type AspiPlainResponse, type AspiRequest, type AspiRequestInit, type AspiRequestInitWithoutBodyAndMethod, type AspiResponse, type AspiResultOk, type AspiRetryConfig, type BaseURL, type Capability, type CapabilityArgs, CustomError, type CustomErrorCb, type ErrorCallbacks, type HttpErrorCodes, type HttpErrorStatus, type HttpMethods, type JSONParseError, type Merge, type
|
|
2065
|
+
export { Aspi, type AspiConfigBase, AspiError, type AspiPlainResponse, type AspiRequest, type AspiRequestInit, type AspiRequestInitWithoutBodyAndMethod, type AspiResponse, type AspiResultOk, type AspiRetryConfig, type BaseURL, type Capability, type CapabilityArgs, CustomError, type CustomErrorCb, type ErrorCallbacks, type HttpErrorCodes, type HttpErrorStatus, type HttpMethods, type JSONParseError, type Merge, type Prettify, Request, type RequestOptions, type RequestTransformer, result as Result, type SchemaParseError, getHttpErrorStatus, httpErrors, isAspiError, isCustomError, isJSONParseError, isSchemaParseError };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standard Schema is a common interface designed to be implemented by JavaScript and TypeScript schema libraries.
|
|
3
|
+
* Will support multiple schema validators including Zod, Valibot, and ArkType
|
|
4
|
+
* https://standardschema.dev/
|
|
5
|
+
*/
|
|
6
|
+
/** The Standard Schema interface. */
|
|
7
|
+
interface StandardSchemaV1<Input = unknown, Output = Input> {
|
|
8
|
+
/** The Standard Schema properties. */
|
|
9
|
+
readonly '~standard': StandardSchemaV1.Props<Input, Output>;
|
|
10
|
+
}
|
|
11
|
+
declare namespace StandardSchemaV1 {
|
|
12
|
+
/** The Standard Schema properties interface. */
|
|
13
|
+
interface Props<Input = unknown, Output = Input> {
|
|
14
|
+
/** The version number of the standard. */
|
|
15
|
+
readonly version: 1;
|
|
16
|
+
/** The vendor name of the schema library. */
|
|
17
|
+
readonly vendor: string;
|
|
18
|
+
/** Validates unknown input values. */
|
|
19
|
+
readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;
|
|
20
|
+
/** Inferred types associated with the schema. */
|
|
21
|
+
readonly types?: Types<Input, Output> | undefined;
|
|
22
|
+
}
|
|
23
|
+
/** The result interface of the validate function. */
|
|
24
|
+
type Result<Output> = SuccessResult<Output> | FailureResult;
|
|
25
|
+
/** The result interface if validation succeeds. */
|
|
26
|
+
interface SuccessResult<Output> {
|
|
27
|
+
/** The typed output value. */
|
|
28
|
+
readonly value: Output;
|
|
29
|
+
/** The non-existent issues. */
|
|
30
|
+
readonly issues?: undefined;
|
|
31
|
+
}
|
|
32
|
+
/** The result interface if validation fails. */
|
|
33
|
+
interface FailureResult {
|
|
34
|
+
/** The issues of failed validation. */
|
|
35
|
+
readonly issues: ReadonlyArray<Issue>;
|
|
36
|
+
}
|
|
37
|
+
/** The issue interface of the failure output. */
|
|
38
|
+
interface Issue {
|
|
39
|
+
/** The error message of the issue. */
|
|
40
|
+
readonly message: string;
|
|
41
|
+
/** The path of the issue, if any. */
|
|
42
|
+
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
|
|
43
|
+
}
|
|
44
|
+
/** The path segment interface of the issue. */
|
|
45
|
+
interface PathSegment {
|
|
46
|
+
/** The key representing a path segment. */
|
|
47
|
+
readonly key: PropertyKey;
|
|
48
|
+
}
|
|
49
|
+
/** The Standard Schema types interface. */
|
|
50
|
+
interface Types<Input = unknown, Output = Input> {
|
|
51
|
+
/** The input type of the schema. */
|
|
52
|
+
readonly input: Input;
|
|
53
|
+
/** The output type of the schema. */
|
|
54
|
+
readonly output: Output;
|
|
55
|
+
}
|
|
56
|
+
/** Infers the input type of a Standard Schema. */
|
|
57
|
+
type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['input'];
|
|
58
|
+
/** Infers the output type of a Standard Schema. */
|
|
59
|
+
type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['output'];
|
|
60
|
+
}
|
|
61
|
+
|
|
1
62
|
/**
|
|
2
63
|
* Standard HTTP /**
|
|
3
64
|
* Common HTTP error status codes with their numeric values.
|
|
@@ -364,14 +425,16 @@ interface JSONParseError extends CustomError<'jsonParseError', {
|
|
|
364
425
|
}> {
|
|
365
426
|
}
|
|
366
427
|
/**
|
|
367
|
-
*
|
|
368
|
-
*
|
|
428
|
+
* Interface representing a schema validation error (body or response).
|
|
429
|
+
* @interface SchemaParseError
|
|
430
|
+
* @extends {CustomError<'schemaParseError', ReadonlyArray<StandardSchemaV1.Issue>>}
|
|
369
431
|
*/
|
|
370
|
-
|
|
432
|
+
interface SchemaParseError extends CustomError<'schemaParseError', ReadonlyArray<StandardSchemaV1.Issue>> {
|
|
433
|
+
}
|
|
371
434
|
declare const isAspiError: <TReq extends AspiRequestInit>(error: unknown) => error is AspiError<TReq>;
|
|
372
435
|
declare const isCustomError: <Tag extends string, A>(error: unknown) => error is CustomError<Tag, A>;
|
|
373
|
-
declare const isParseError: (error: unknown) => error is ParseError;
|
|
374
436
|
declare const isJSONParseError: (error: unknown) => error is JSONParseError;
|
|
437
|
+
declare const isSchemaParseError: (error: unknown) => error is SchemaParseError;
|
|
375
438
|
|
|
376
439
|
/**
|
|
377
440
|
* Arguments passed to a capability factory.
|
|
@@ -756,67 +819,6 @@ declare namespace result {
|
|
|
756
819
|
export { type result_Err as Err, type result_Ok as Ok, type result_Result as Result, result_catchAllErrors as catchAllErrors, result_catchError as catchError, result_catchErrors as catchErrors, result_err as err, result_getErrorOrNull as getErrorOrNull, result_getOrElse as getOrElse, result_getOrNull as getOrNull, result_getOrThrow as getOrThrow, result_getOrThrowWith as getOrThrowWith, result_isErr as isErr, result_isOk as isOk, result_map as map, result_mapErr as mapErr, result_match as match, result_ok as ok, result_pipe as pipe };
|
|
757
820
|
}
|
|
758
821
|
|
|
759
|
-
/**
|
|
760
|
-
* Standard Schema is a common interface designed to be implemented by JavaScript and TypeScript schema libraries.
|
|
761
|
-
* Will support multiple schema validators including Zod, Valibot, and ArkType
|
|
762
|
-
* https://standardschema.dev/
|
|
763
|
-
*/
|
|
764
|
-
/** The Standard Schema interface. */
|
|
765
|
-
interface StandardSchemaV1<Input = unknown, Output = Input> {
|
|
766
|
-
/** The Standard Schema properties. */
|
|
767
|
-
readonly '~standard': StandardSchemaV1.Props<Input, Output>;
|
|
768
|
-
}
|
|
769
|
-
declare namespace StandardSchemaV1 {
|
|
770
|
-
/** The Standard Schema properties interface. */
|
|
771
|
-
interface Props<Input = unknown, Output = Input> {
|
|
772
|
-
/** The version number of the standard. */
|
|
773
|
-
readonly version: 1;
|
|
774
|
-
/** The vendor name of the schema library. */
|
|
775
|
-
readonly vendor: string;
|
|
776
|
-
/** Validates unknown input values. */
|
|
777
|
-
readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;
|
|
778
|
-
/** Inferred types associated with the schema. */
|
|
779
|
-
readonly types?: Types<Input, Output> | undefined;
|
|
780
|
-
}
|
|
781
|
-
/** The result interface of the validate function. */
|
|
782
|
-
type Result<Output> = SuccessResult<Output> | FailureResult;
|
|
783
|
-
/** The result interface if validation succeeds. */
|
|
784
|
-
interface SuccessResult<Output> {
|
|
785
|
-
/** The typed output value. */
|
|
786
|
-
readonly value: Output;
|
|
787
|
-
/** The non-existent issues. */
|
|
788
|
-
readonly issues?: undefined;
|
|
789
|
-
}
|
|
790
|
-
/** The result interface if validation fails. */
|
|
791
|
-
interface FailureResult {
|
|
792
|
-
/** The issues of failed validation. */
|
|
793
|
-
readonly issues: ReadonlyArray<Issue>;
|
|
794
|
-
}
|
|
795
|
-
/** The issue interface of the failure output. */
|
|
796
|
-
interface Issue {
|
|
797
|
-
/** The error message of the issue. */
|
|
798
|
-
readonly message: string;
|
|
799
|
-
/** The path of the issue, if any. */
|
|
800
|
-
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
|
|
801
|
-
}
|
|
802
|
-
/** The path segment interface of the issue. */
|
|
803
|
-
interface PathSegment {
|
|
804
|
-
/** The key representing a path segment. */
|
|
805
|
-
readonly key: PropertyKey;
|
|
806
|
-
}
|
|
807
|
-
/** The Standard Schema types interface. */
|
|
808
|
-
interface Types<Input = unknown, Output = Input> {
|
|
809
|
-
/** The input type of the schema. */
|
|
810
|
-
readonly input: Input;
|
|
811
|
-
/** The output type of the schema. */
|
|
812
|
-
readonly output: Output;
|
|
813
|
-
}
|
|
814
|
-
/** Infers the input type of a Standard Schema. */
|
|
815
|
-
type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['input'];
|
|
816
|
-
/** Infers the output type of a Standard Schema. */
|
|
817
|
-
type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['output'];
|
|
818
|
-
}
|
|
819
|
-
|
|
820
822
|
/**
|
|
821
823
|
* A class for building and executing HTTP requests with customizable options and error handling.
|
|
822
824
|
* @template Method The HTTP method type (GET, POST, etc.)
|
|
@@ -937,7 +939,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
937
939
|
bodySchema<TSchema extends StandardSchemaV1>(schema: TSchema): Request<Method, TRequest, Omit<Opts, "bodySchema"> & {
|
|
938
940
|
bodySchema: TSchema;
|
|
939
941
|
error: Opts["error"] & {
|
|
940
|
-
|
|
942
|
+
schemaParseError: CustomError<"schemaParseError", StandardSchemaV1.FailureResult["issues"]>;
|
|
941
943
|
};
|
|
942
944
|
}>;
|
|
943
945
|
/**
|
|
@@ -1209,7 +1211,7 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
1209
1211
|
schema<TSchema extends StandardSchemaV1>(schema: TSchema): Request<Method, TRequest, Merge<Omit<Opts, "schema">, {
|
|
1210
1212
|
schema: TSchema;
|
|
1211
1213
|
error: Merge<Opts["error"], {
|
|
1212
|
-
|
|
1214
|
+
schemaParseError: CustomError<"schemaParseError", StandardSchemaV1.FailureResult["issues"]>;
|
|
1213
1215
|
}>;
|
|
1214
1216
|
}>>;
|
|
1215
1217
|
/**
|
|
@@ -1562,6 +1564,48 @@ declare class Request<Method extends HttpMethods, TRequest extends AspiRequestIn
|
|
|
1562
1564
|
withResult: true;
|
|
1563
1565
|
throwable: false;
|
|
1564
1566
|
}>>;
|
|
1567
|
+
/**
|
|
1568
|
+
* Switches the request into **tuple** mode (the default).
|
|
1569
|
+
*
|
|
1570
|
+
* In tuple mode the response helpers (`json`, `text`, `blob`, …) resolve to a
|
|
1571
|
+
* tuple `[value, error]` where exactly one element is non‑null. This is useful
|
|
1572
|
+
* when you want an explicit opt‑in method to reset from `withResult()` or
|
|
1573
|
+
* `throwable()` back to the default tuple behaviour.
|
|
1574
|
+
*
|
|
1575
|
+
* Calling `withTuple` disables both Result mode and throwable mode.
|
|
1576
|
+
*
|
|
1577
|
+
* @returns {Request<
|
|
1578
|
+
* Method,
|
|
1579
|
+
* TRequest,
|
|
1580
|
+
* Merge<
|
|
1581
|
+
* Omit<Opts, 'withResult' | 'throwable'>,
|
|
1582
|
+
* {
|
|
1583
|
+
* withResult: false;
|
|
1584
|
+
* throwable: false;
|
|
1585
|
+
* }
|
|
1586
|
+
* >
|
|
1587
|
+
* >} The same {@link Request} instance, now typed with `withResult: false` and
|
|
1588
|
+
* `throwable: false` for fluent chaining.
|
|
1589
|
+
*
|
|
1590
|
+
* @example
|
|
1591
|
+
* ```ts
|
|
1592
|
+
* const request = new Request('/users', config);
|
|
1593
|
+
*
|
|
1594
|
+
* const [user, err] = await request
|
|
1595
|
+
* .withTuple() // explicitly use tuple mode
|
|
1596
|
+
* .json<User>();
|
|
1597
|
+
*
|
|
1598
|
+
* if (err) {
|
|
1599
|
+
* console.error(err);
|
|
1600
|
+
* } else {
|
|
1601
|
+
* console.log(user);
|
|
1602
|
+
* }
|
|
1603
|
+
* ```
|
|
1604
|
+
*/
|
|
1605
|
+
withTuple(): Request<Method, TRequest, Merge<Omit<Opts, "withResult" | "throwable">, {
|
|
1606
|
+
withResult: false;
|
|
1607
|
+
throwable: false;
|
|
1608
|
+
}>>;
|
|
1565
1609
|
/**
|
|
1566
1610
|
* Returns the underlying {@link AspiRequest} object that will be used for the fetch call.
|
|
1567
1611
|
*
|
|
@@ -1965,6 +2009,19 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
|
|
|
1965
2009
|
withResult: true;
|
|
1966
2010
|
throwable: false;
|
|
1967
2011
|
}>>;
|
|
2012
|
+
/**
|
|
2013
|
+
* Configures all subsequent requests to return the default tuple `[value, error]`.
|
|
2014
|
+
*
|
|
2015
|
+
* This is the default behaviour, but `withTuple()` is provided as an explicit
|
|
2016
|
+
* reset when you have previously called {@link withResult} or {@link throwable}
|
|
2017
|
+
* on the {@link Aspi} instance.
|
|
2018
|
+
*
|
|
2019
|
+
* @returns The Aspi instance with tuple handling enabled.
|
|
2020
|
+
*/
|
|
2021
|
+
withTuple(): Aspi<TRequest, Merge<Omit<Opts, "withResult" | "throwable">, {
|
|
2022
|
+
withResult: false;
|
|
2023
|
+
throwable: false;
|
|
2024
|
+
}>>;
|
|
1968
2025
|
/**
|
|
1969
2026
|
* Registers a capability on this {@link Aspi} instance.
|
|
1970
2027
|
*
|
|
@@ -2005,4 +2062,4 @@ declare class Aspi<TRequest extends AspiRequestInit = AspiRequestInit, Opts exte
|
|
|
2005
2062
|
useCapability(capability: Capability<TRequest>): this;
|
|
2006
2063
|
}
|
|
2007
2064
|
|
|
2008
|
-
export { Aspi, type AspiConfigBase, AspiError, type AspiPlainResponse, type AspiRequest, type AspiRequestInit, type AspiRequestInitWithoutBodyAndMethod, type AspiResponse, type AspiResultOk, type AspiRetryConfig, type BaseURL, type Capability, type CapabilityArgs, CustomError, type CustomErrorCb, type ErrorCallbacks, type HttpErrorCodes, type HttpErrorStatus, type HttpMethods, type JSONParseError, type Merge, type
|
|
2065
|
+
export { Aspi, type AspiConfigBase, AspiError, type AspiPlainResponse, type AspiRequest, type AspiRequestInit, type AspiRequestInitWithoutBodyAndMethod, type AspiResponse, type AspiResultOk, type AspiRetryConfig, type BaseURL, type Capability, type CapabilityArgs, CustomError, type CustomErrorCb, type ErrorCallbacks, type HttpErrorCodes, type HttpErrorStatus, type HttpMethods, type JSONParseError, type Merge, type Prettify, Request, type RequestOptions, type RequestTransformer, result as Result, type SchemaParseError, getHttpErrorStatus, httpErrors, isAspiError, isCustomError, isJSONParseError, isSchemaParseError };
|
package/dist/index.js
CHANGED
|
@@ -80,12 +80,12 @@ var isAspiError = (error) => {
|
|
|
80
80
|
var isCustomError = (error) => {
|
|
81
81
|
return error instanceof CustomError;
|
|
82
82
|
};
|
|
83
|
-
var isParseError = (error) => {
|
|
84
|
-
return error instanceof CustomError && error.tag === "parseError";
|
|
85
|
-
};
|
|
86
83
|
var isJSONParseError = (error) => {
|
|
87
84
|
return error instanceof CustomError && error.tag === "jsonParseError";
|
|
88
85
|
};
|
|
86
|
+
var isSchemaParseError = (error) => {
|
|
87
|
+
return error instanceof CustomError && error.tag === "schemaParseError";
|
|
88
|
+
};
|
|
89
89
|
|
|
90
90
|
// src/result.ts
|
|
91
91
|
var result_exports = {};
|
|
@@ -295,6 +295,8 @@ var Request = class {
|
|
|
295
295
|
#timeoutMs;
|
|
296
296
|
#shouldBeResult = false;
|
|
297
297
|
#bodySchemaIssues = [];
|
|
298
|
+
#bodySchemaAsyncResult = null;
|
|
299
|
+
#bodySchemaAsyncBody = null;
|
|
298
300
|
#throwOnError = false;
|
|
299
301
|
#capabilities = [];
|
|
300
302
|
constructor(method, path, requestOptions, capabilities = []) {
|
|
@@ -448,9 +450,9 @@ var Request = class {
|
|
|
448
450
|
if (this.#bodySchema) {
|
|
449
451
|
const data = this.#bodySchema["~standard"].validate(body);
|
|
450
452
|
if (data instanceof Promise) {
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
if (data.issues) {
|
|
453
|
+
this.#bodySchemaAsyncResult = data;
|
|
454
|
+
this.#bodySchemaAsyncBody = body;
|
|
455
|
+
} else if (data.issues) {
|
|
454
456
|
this.#bodySchemaIssues = data.issues;
|
|
455
457
|
} else {
|
|
456
458
|
this.#localRequestInit.body = JSON.stringify(data.value);
|
|
@@ -1128,6 +1130,49 @@ var Request = class {
|
|
|
1128
1130
|
this.#shouldBeResult = true;
|
|
1129
1131
|
return this;
|
|
1130
1132
|
}
|
|
1133
|
+
/**
|
|
1134
|
+
* Switches the request into **tuple** mode (the default).
|
|
1135
|
+
*
|
|
1136
|
+
* In tuple mode the response helpers (`json`, `text`, `blob`, …) resolve to a
|
|
1137
|
+
* tuple `[value, error]` where exactly one element is non‑null. This is useful
|
|
1138
|
+
* when you want an explicit opt‑in method to reset from `withResult()` or
|
|
1139
|
+
* `throwable()` back to the default tuple behaviour.
|
|
1140
|
+
*
|
|
1141
|
+
* Calling `withTuple` disables both Result mode and throwable mode.
|
|
1142
|
+
*
|
|
1143
|
+
* @returns {Request<
|
|
1144
|
+
* Method,
|
|
1145
|
+
* TRequest,
|
|
1146
|
+
* Merge<
|
|
1147
|
+
* Omit<Opts, 'withResult' | 'throwable'>,
|
|
1148
|
+
* {
|
|
1149
|
+
* withResult: false;
|
|
1150
|
+
* throwable: false;
|
|
1151
|
+
* }
|
|
1152
|
+
* >
|
|
1153
|
+
* >} The same {@link Request} instance, now typed with `withResult: false` and
|
|
1154
|
+
* `throwable: false` for fluent chaining.
|
|
1155
|
+
*
|
|
1156
|
+
* @example
|
|
1157
|
+
* ```ts
|
|
1158
|
+
* const request = new Request('/users', config);
|
|
1159
|
+
*
|
|
1160
|
+
* const [user, err] = await request
|
|
1161
|
+
* .withTuple() // explicitly use tuple mode
|
|
1162
|
+
* .json<User>();
|
|
1163
|
+
*
|
|
1164
|
+
* if (err) {
|
|
1165
|
+
* console.error(err);
|
|
1166
|
+
* } else {
|
|
1167
|
+
* console.log(user);
|
|
1168
|
+
* }
|
|
1169
|
+
* ```
|
|
1170
|
+
*/
|
|
1171
|
+
withTuple() {
|
|
1172
|
+
this.#throwOnError = false;
|
|
1173
|
+
this.#shouldBeResult = false;
|
|
1174
|
+
return this;
|
|
1175
|
+
}
|
|
1131
1176
|
#mapResponse(value) {
|
|
1132
1177
|
if (this.#shouldBeResult) {
|
|
1133
1178
|
return value;
|
|
@@ -1145,8 +1190,20 @@ var Request = class {
|
|
|
1145
1190
|
return response.ok || response.status >= 300 && response.status < 400;
|
|
1146
1191
|
}
|
|
1147
1192
|
async #makeRequest(responseParser, isJson = false) {
|
|
1193
|
+
if (this.#bodySchemaAsyncResult) {
|
|
1194
|
+
const data = await this.#bodySchemaAsyncResult;
|
|
1195
|
+
if (data.issues) {
|
|
1196
|
+
this.#bodySchemaIssues = data.issues;
|
|
1197
|
+
} else {
|
|
1198
|
+
this.#localRequestInit.body = JSON.stringify(data.value);
|
|
1199
|
+
}
|
|
1200
|
+
this.#bodySchemaAsyncResult = null;
|
|
1201
|
+
this.#bodySchemaAsyncBody = null;
|
|
1202
|
+
}
|
|
1148
1203
|
if (this.#bodySchemaIssues.length) {
|
|
1149
|
-
return err(
|
|
1204
|
+
return err(
|
|
1205
|
+
new CustomError("schemaParseError", this.#bodySchemaIssues)
|
|
1206
|
+
);
|
|
1150
1207
|
}
|
|
1151
1208
|
const request = this.#request();
|
|
1152
1209
|
const { retries, retryDelay, retryOn, retryWhile, onRetry } = this.#sanitisedRetryConfig();
|
|
@@ -1280,12 +1337,9 @@ var Request = class {
|
|
|
1280
1337
|
);
|
|
1281
1338
|
}
|
|
1282
1339
|
if (isJson && this.#schema) {
|
|
1283
|
-
const data = this.#schema["~standard"].validate(responseData);
|
|
1284
|
-
if (data instanceof Promise) {
|
|
1285
|
-
throw new Error("Schema validation should not return a promise");
|
|
1286
|
-
}
|
|
1340
|
+
const data = await this.#schema["~standard"].validate(responseData);
|
|
1287
1341
|
if (data.issues) {
|
|
1288
|
-
return err(new CustomError("
|
|
1342
|
+
return err(new CustomError("schemaParseError", data.issues));
|
|
1289
1343
|
}
|
|
1290
1344
|
return ok({
|
|
1291
1345
|
data: data.value,
|
|
@@ -1495,7 +1549,7 @@ var Request = class {
|
|
|
1495
1549
|
};
|
|
1496
1550
|
|
|
1497
1551
|
// src/aspi.ts
|
|
1498
|
-
var
|
|
1552
|
+
var Aspi2 = class {
|
|
1499
1553
|
#globalRequestInit;
|
|
1500
1554
|
#middlewares = [];
|
|
1501
1555
|
#retryConfig;
|
|
@@ -1855,6 +1909,20 @@ var Aspi = class {
|
|
|
1855
1909
|
this.#throwOnError = false;
|
|
1856
1910
|
return this;
|
|
1857
1911
|
}
|
|
1912
|
+
/**
|
|
1913
|
+
* Configures all subsequent requests to return the default tuple `[value, error]`.
|
|
1914
|
+
*
|
|
1915
|
+
* This is the default behaviour, but `withTuple()` is provided as an explicit
|
|
1916
|
+
* reset when you have previously called {@link withResult} or {@link throwable}
|
|
1917
|
+
* on the {@link Aspi} instance.
|
|
1918
|
+
*
|
|
1919
|
+
* @returns The Aspi instance with tuple handling enabled.
|
|
1920
|
+
*/
|
|
1921
|
+
withTuple() {
|
|
1922
|
+
this.#shouldBeResult = false;
|
|
1923
|
+
this.#throwOnError = false;
|
|
1924
|
+
return this;
|
|
1925
|
+
}
|
|
1858
1926
|
/**
|
|
1859
1927
|
* Registers a capability on this {@link Aspi} instance.
|
|
1860
1928
|
*
|
|
@@ -1898,7 +1966,7 @@ var Aspi = class {
|
|
|
1898
1966
|
}
|
|
1899
1967
|
};
|
|
1900
1968
|
export {
|
|
1901
|
-
Aspi,
|
|
1969
|
+
Aspi2 as Aspi,
|
|
1902
1970
|
AspiError,
|
|
1903
1971
|
CustomError,
|
|
1904
1972
|
Request,
|
|
@@ -1908,5 +1976,5 @@ export {
|
|
|
1908
1976
|
isAspiError,
|
|
1909
1977
|
isCustomError,
|
|
1910
1978
|
isJSONParseError,
|
|
1911
|
-
|
|
1979
|
+
isSchemaParseError
|
|
1912
1980
|
};
|
package/package.json
CHANGED