march-hare 0.13.11 → 0.14.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 +6 -4
- package/dist/boundary/components/sharing/index.d.ts +24 -9
- package/dist/coalesce/index.d.ts +3 -43
- package/dist/march-hare.js +7 -7
- package/dist/march-hare.js.map +1 -1
- package/dist/march-hare.umd.cjs +1 -1
- package/dist/march-hare.umd.cjs.map +1 -1
- package/dist/resource/index.d.ts +8 -4
- package/dist/resource/types.d.ts +0 -8
- package/dist/types/index.d.ts +24 -24
- package/package.json +1 -1
package/dist/resource/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { ResourceHandle } from './types.js';
|
|
|
2
2
|
import { Cache } from './utils.js';
|
|
3
3
|
import { AppFetcher } from '../app/types.js';
|
|
4
4
|
import { Env } from '../boundary/components/env/types.js';
|
|
5
|
-
export type {
|
|
5
|
+
export type { Fetcher, Invocation, ResourceHandle } from './types.js';
|
|
6
6
|
/**
|
|
7
7
|
* Evicts cache entries across every Resource constructed in the
|
|
8
8
|
* current process. Resources register themselves on declaration, so
|
|
@@ -44,9 +44,13 @@ export declare function nuke(where?: object): void;
|
|
|
44
44
|
* Standalone `shared.Resource` declarations always use an in-memory
|
|
45
45
|
* cache — reach for `app.Resource` when persistence is required.
|
|
46
46
|
*
|
|
47
|
-
* Concurrent calls
|
|
48
|
-
*
|
|
49
|
-
*
|
|
47
|
+
* Concurrent calls with the same `(Resource, params)` share a single
|
|
48
|
+
* in-flight fetch by default — one network request, every caller
|
|
49
|
+
* resolves with the same payload. The underlying work is refcounted: if
|
|
50
|
+
* every caller aborts, the shared `AbortController` is aborted too.
|
|
51
|
+
* Chain `.isolated()` on the thenable returned from
|
|
52
|
+
* `context.actions.resource(...)` to opt out (own controller, own
|
|
53
|
+
* request) for the rare cases that need it.
|
|
50
54
|
*
|
|
51
55
|
* @template E The Env shape (or union) the fetcher's `context.env` is
|
|
52
56
|
* typed against.
|
package/dist/resource/types.d.ts
CHANGED
|
@@ -40,14 +40,6 @@ export type Args<P extends object = Record<never, never>> = {
|
|
|
40
40
|
* and a broadcast/multicast-only `dispatch`.
|
|
41
41
|
*/
|
|
42
42
|
export type Fetcher<T, P extends object = Record<never, never>> = (context: Args<P>) => Promise<T>;
|
|
43
|
-
/**
|
|
44
|
-
* Per-call coalescing token. Two callers with the same Resource, same
|
|
45
|
-
* structural params, and equal `Coalesce` value share a single in-flight
|
|
46
|
-
* promise; different tokens (or different params) fire independent
|
|
47
|
-
* fetches. Primitives compose naturally via stringification; objects
|
|
48
|
-
* are serialised with `JSON.stringify`.
|
|
49
|
-
*/
|
|
50
|
-
export type Coalesce = string | number | bigint | boolean | symbol | object;
|
|
51
43
|
/**
|
|
52
44
|
* Config form accepted by `Resource`. The fetcher shorthand
|
|
53
45
|
* `Resource(fetcher)` is equivalent to `Resource({ fetch: fetcher })`.
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Operation, Process, Inspect as ImmInspect, Box } from 'immertation';
|
|
|
2
2
|
import { ActionId, Task, Tasks } from '../boundary/components/tasks/types.js';
|
|
3
3
|
import { Fault } from '../error/types.js';
|
|
4
4
|
import { Env } from '../boundary/components/env/types.js';
|
|
5
|
-
import {
|
|
5
|
+
import { Invocation } from '../resource/types.js';
|
|
6
6
|
import { WithHandle } from '../with/types.js';
|
|
7
7
|
import * as React from "react";
|
|
8
8
|
/**
|
|
@@ -26,25 +26,22 @@ type ValueAt<T, K extends PropertyKey> = T extends unknown ? K extends keyof T ?
|
|
|
26
26
|
export type Inspect<T, D extends number = 8> = ImmInspect<T> & ([D] extends [0] ? object : {
|
|
27
27
|
[K in UnionKeys<T> as ValueAt<T, K> extends (...args: unknown[]) => unknown ? never : K]: Inspect<ValueAt<T, K>, DepthLimiter[D]>;
|
|
28
28
|
});
|
|
29
|
-
/**
|
|
30
|
-
* Chainable handle returned from `context.actions.resource(invocation)`.
|
|
31
|
-
*
|
|
32
|
-
* - `.exceeds(duration)` short-circuits the fetch when the per-params
|
|
33
|
-
* cache age is within the supplied freshness window.
|
|
34
|
-
* - `.coalesce(token)` opts the call into in-flight sharing: any other
|
|
35
|
-
* caller with the same Resource, same structural params, and equal
|
|
36
|
-
* `token` joins the same promise.
|
|
37
|
-
*
|
|
38
|
-
* Awaiting the handle (`await context.actions.resource(...)`) triggers
|
|
39
|
-
* the fetch with whichever options have been set on the chain.
|
|
40
|
-
*/
|
|
41
29
|
/**
|
|
42
30
|
* Fetch-configured chain returned from `.exceeds(...)` and
|
|
43
|
-
* `.
|
|
31
|
+
* `.isolated()`. Awaiting the chain runs the fetch with whichever
|
|
44
32
|
* options are set; `.evict()` is intentionally absent because the
|
|
45
33
|
* "configured a fetch then evicted instead" sequence has no coherent
|
|
46
34
|
* meaning — eviction is always available off the bare
|
|
47
35
|
* `context.actions.resource(...)` call.
|
|
36
|
+
*
|
|
37
|
+
* Concurrent callers with the same `(Resource, params)` automatically
|
|
38
|
+
* share a single in-flight fetch — one network request, every
|
|
39
|
+
* caller resolves with the same payload. The shared fetch runs on a
|
|
40
|
+
* detached `AbortController` so one caller's abort never cancels work
|
|
41
|
+
* other callers are still waiting on; when every caller has released
|
|
42
|
+
* (their `context.task.controller` aborted) the shared controller is
|
|
43
|
+
* aborted too. Chain `.isolated()` to opt out for the rare case that
|
|
44
|
+
* needs an independent request.
|
|
48
45
|
*/
|
|
49
46
|
export type ResourceFetch<T> = PromiseLike<T> & {
|
|
50
47
|
/**
|
|
@@ -54,22 +51,25 @@ export type ResourceFetch<T> = PromiseLike<T> & {
|
|
|
54
51
|
*/
|
|
55
52
|
readonly exceeds: (duration: Temporal.DurationLike) => ResourceFetch<T>;
|
|
56
53
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
54
|
+
* Opt this call out of the default `(Resource, params)` coalesce
|
|
55
|
+
* path. The fetch fires as an independent network request against
|
|
56
|
+
* the caller's own `context.task.controller` — no joining of
|
|
57
|
+
* any in-flight fetch, no refcounted detached controller. Aborting
|
|
58
|
+
* the caller's task cancels the network exactly as a regular fetch
|
|
59
|
+
* would.
|
|
62
60
|
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
61
|
+
* Reach for this only when two callers need parallel fetches with
|
|
62
|
+
* byte-identical params and the difference in intent genuinely can't
|
|
63
|
+
* be modelled by differing params. The default is almost always
|
|
64
|
+
* what you want.
|
|
65
65
|
*/
|
|
66
|
-
readonly
|
|
66
|
+
readonly isolated: () => ResourceFetch<T>;
|
|
67
67
|
};
|
|
68
68
|
/**
|
|
69
69
|
* Chainable handle returned from `context.actions.resource(invocation)`.
|
|
70
|
-
* Either resolve to the fetched value (`.exceeds`/`.
|
|
70
|
+
* Either resolve to the fetched value (`.exceeds`/`.isolated` + await)
|
|
71
71
|
* or drop the cache slot (`.evict`) — the two paths are mutually
|
|
72
|
-
* exclusive, so once `.exceeds` or `.
|
|
72
|
+
* exclusive, so once `.exceeds` or `.isolated` runs the chain narrows
|
|
73
73
|
* to {@link ResourceFetch} and `.evict` is no longer available.
|
|
74
74
|
*/
|
|
75
75
|
export type ResourceCall<T> = ResourceFetch<T> & {
|