@cplieger/actions 2.0.13 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/jsr.json +1 -1
- package/package.json +4 -4
- package/src/api.ts +16 -33
- package/src/index.ts +1 -1
package/README.md
CHANGED
|
@@ -116,10 +116,10 @@ const action = apiAction({
|
|
|
116
116
|
- `retryNetwork` — preset retry classifier for transient failures
|
|
117
117
|
- `classifyFetchError(err)` — classify fetch errors (network vs timeout vs HTTP)
|
|
118
118
|
- `hasErrorString(err)` — type guard for objects with a `.message` string
|
|
119
|
-
- `withTimeout(signal, ms)` — compose an AbortSignal with a timeout
|
|
120
|
-
- `API_TIMEOUT_MS` — default API request timeout (30 000 ms)
|
|
121
119
|
- `RETRY_STANDARD` — standard retry config (2 retries, 300ms)
|
|
122
120
|
|
|
121
|
+
> `withTimeout(signal, ms)` and `API_TIMEOUT_MS` moved to [`@cplieger/fetch`](https://github.com/cplieger/fetch) (the layer that owns timeout composition); import them from there.
|
|
122
|
+
|
|
123
123
|
### Test utilities (`@cplieger/actions/testing`)
|
|
124
124
|
|
|
125
125
|
The `./testing` subpath exports test-only helpers. Import only from test code:
|
package/jsr.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cplieger/actions",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"exports": {
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"test": "vitest --run"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@cplieger/fetch": "
|
|
17
|
-
"@cplieger/reactive": "1.2.
|
|
16
|
+
"@cplieger/fetch": "2.0.0",
|
|
17
|
+
"@cplieger/reactive": "1.2.5"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@eslint/js": "10.0.1",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"happy-dom": "20.10.6",
|
|
30
30
|
"prettier": "3.9.5",
|
|
31
31
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
32
|
-
"typescript-eslint": "8.
|
|
32
|
+
"typescript-eslint": "8.64.0",
|
|
33
33
|
"vitest": "4.1.10"
|
|
34
34
|
},
|
|
35
35
|
"description": "Declarative async UI-action framework for TypeScript",
|
package/src/api.ts
CHANGED
|
@@ -1,36 +1,18 @@
|
|
|
1
1
|
// apiAction: factory for HTTP-backed actions. The run() implementation is just
|
|
2
2
|
// a request descriptor (RequestSpec); the request/response envelope is owned by
|
|
3
|
-
// @cplieger/fetch. actions holds its OWN
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// identical typed errors they always have.
|
|
3
|
+
// @cplieger/fetch. actions holds its OWN fetch instance (createFetch) — fully
|
|
4
|
+
// isolated from any instance a consuming app builds (fetch v2 is
|
|
5
|
+
// instances-only) — and maps fetch's ApiResult envelope onto ActionError so
|
|
6
|
+
// callers see the identical typed errors they always have.
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
8
8
|
|
|
9
|
-
import { createFetch } from "@cplieger/fetch";
|
|
9
|
+
import { API_TIMEOUT_MS, createFetch } from "@cplieger/fetch";
|
|
10
10
|
import type { ApiErr, FetchConfig, FetchInstance, RequestOptions } from "@cplieger/fetch";
|
|
11
11
|
|
|
12
12
|
import { defineAction, IDEMPOTENCY_HEADER } from "./define.js";
|
|
13
13
|
import { ActionError } from "./error.js";
|
|
14
14
|
import type { Action, ActionContext, ActionDefinition, RequestSpec } from "./types.js";
|
|
15
15
|
|
|
16
|
-
/** Default request timeout in milliseconds. */
|
|
17
|
-
export const API_TIMEOUT_MS = 30_000;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Compose an optional caller signal with a fresh timeout signal.
|
|
21
|
-
* If the caller provides an existing signal, the result aborts when
|
|
22
|
-
* either the caller signal or the timeout fires — whichever comes first.
|
|
23
|
-
*
|
|
24
|
-
* @param signal - Existing signal to compose with (may be undefined).
|
|
25
|
-
* @param ms - Timeout in milliseconds.
|
|
26
|
-
* @returns A composed AbortSignal.
|
|
27
|
-
*/
|
|
28
|
-
export function withTimeout(signal: AbortSignal | undefined, ms: number): AbortSignal {
|
|
29
|
-
return signal !== undefined
|
|
30
|
-
? AbortSignal.any([signal, AbortSignal.timeout(ms)])
|
|
31
|
-
: AbortSignal.timeout(ms);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
16
|
const JSON_CT = "application/json";
|
|
35
17
|
|
|
36
18
|
// ---------------------------------------------------------------------------
|
|
@@ -57,14 +39,15 @@ export interface ApiConfig {
|
|
|
57
39
|
readonly fetchFn?: typeof fetch;
|
|
58
40
|
}
|
|
59
41
|
|
|
60
|
-
// actions owns a PRIVATE
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
// projected onto this instance. prepareHeaders stays
|
|
65
|
-
// because actions' hook is spec-aware —
|
|
66
|
-
// `(headers)`-only hook can't express,
|
|
67
|
-
// passes the result as the per-request
|
|
42
|
+
// actions owns a PRIVATE @cplieger/fetch instance. fetch v2 is instances-only
|
|
43
|
+
// with config frozen at construction, so isolation from the consuming app's
|
|
44
|
+
// own fetch instances is inherent — and configureApi's replace semantics are
|
|
45
|
+
// implemented the only way v2 allows: by rebuilding the instance. baseUrl /
|
|
46
|
+
// credentials / fetchFn are projected onto this instance. prepareHeaders stays
|
|
47
|
+
// here (not on the instance) because actions' hook is spec-aware —
|
|
48
|
+
// `(headers, { spec })` — a shape fetch's `(headers)`-only hook can't express,
|
|
49
|
+
// so executeRequest runs it itself and passes the result as the per-request
|
|
50
|
+
// headers.
|
|
68
51
|
let apiFetch: FetchInstance = createFetch();
|
|
69
52
|
let apiPrepareHeaders: ApiConfig["prepareHeaders"];
|
|
70
53
|
|
|
@@ -94,8 +77,8 @@ export function configureApi(config: ApiConfig): void {
|
|
|
94
77
|
if (config.fetchFn !== undefined) {
|
|
95
78
|
fetchConfig.fetchFn = config.fetchFn;
|
|
96
79
|
}
|
|
97
|
-
// Rebuild the instance
|
|
98
|
-
//
|
|
80
|
+
// Rebuild the instance: fetch v2 instances are immutable, and configureApi's
|
|
81
|
+
// contract is replace-not-merge, which a fresh instance implements exactly.
|
|
99
82
|
apiFetch = createFetch(fetchConfig);
|
|
100
83
|
apiPrepareHeaders = config.prepareHeaders;
|
|
101
84
|
}
|
package/src/index.ts
CHANGED
|
@@ -11,7 +11,7 @@ export type { TransportSendResult, TransportCommand, TransportSendFn } from "./t
|
|
|
11
11
|
|
|
12
12
|
// Action factories
|
|
13
13
|
export { defineAction } from "./define.js";
|
|
14
|
-
export { apiAction, configureApi
|
|
14
|
+
export { apiAction, configureApi } from "./api.js";
|
|
15
15
|
export type { ApiConfig, ApiActionDefinition } from "./api.js";
|
|
16
16
|
|
|
17
17
|
// Error class + utilities
|