@playfast/reform 0.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 +64 -0
- package/dist/cjs/boundary/boundary.js +86 -0
- package/dist/cjs/calc/asyncCalc.js +128 -0
- package/dist/cjs/calc/asyncData.js +37 -0
- package/dist/cjs/calc/calc.js +58 -0
- package/dist/cjs/calc/calcFamily.js +127 -0
- package/dist/cjs/channel/channel.js +142 -0
- package/dist/cjs/compose/composition.js +50 -0
- package/dist/cjs/compose/host.js +8 -0
- package/dist/cjs/compose/props.js +14 -0
- package/dist/cjs/compose/provide.js +30 -0
- package/dist/cjs/compose/slot.js +27 -0
- package/dist/cjs/compose/ui.js +61 -0
- package/dist/cjs/definition/definition.js +46 -0
- package/dist/cjs/event/event.js +36 -0
- package/dist/cjs/event/eventGroup.js +7 -0
- package/dist/cjs/feature/feature.js +102 -0
- package/dist/cjs/index.js +116 -0
- package/dist/cjs/internal/capture.js +14 -0
- package/dist/cjs/internal/ctx.js +2 -0
- package/dist/cjs/internal/errors.js +62 -0
- package/dist/cjs/internal/inspect.js +36 -0
- package/dist/cjs/internal/queryDriver.js +138 -0
- package/dist/cjs/internal/reuse.js +71 -0
- package/dist/cjs/internal/scheduler.js +73 -0
- package/dist/cjs/internal/seeds.js +19 -0
- package/dist/cjs/internal/sources.js +61 -0
- package/dist/cjs/internal/store.js +77 -0
- package/dist/cjs/internal/track.js +22 -0
- package/dist/cjs/package.json +4 -0
- package/dist/cjs/procedure/procedure.js +52 -0
- package/dist/cjs/reducer/reducer.js +64 -0
- package/dist/cjs/remote/remoteState.js +307 -0
- package/dist/cjs/runtime/bus.js +25 -0
- package/dist/cjs/runtime/loop.js +119 -0
- package/dist/cjs/scene/scene.js +36 -0
- package/dist/cjs/state/state.js +47 -0
- package/dist/cjs/state/stateFamily.js +101 -0
- package/dist/cjs/state/stateGroup.js +47 -0
- package/dist/cjs/state/token.js +23 -0
- package/dist/cjs/ui/node.js +2 -0
- package/dist/cjs/ui/trigger.js +2 -0
- package/dist/dts/boundary/boundary.d.ts +72 -0
- package/dist/dts/boundary/boundary.d.ts.map +1 -0
- package/dist/dts/calc/asyncCalc.d.ts +91 -0
- package/dist/dts/calc/asyncCalc.d.ts.map +1 -0
- package/dist/dts/calc/asyncData.d.ts +55 -0
- package/dist/dts/calc/asyncData.d.ts.map +1 -0
- package/dist/dts/calc/calc.d.ts +57 -0
- package/dist/dts/calc/calc.d.ts.map +1 -0
- package/dist/dts/calc/calcFamily.d.ts +57 -0
- package/dist/dts/calc/calcFamily.d.ts.map +1 -0
- package/dist/dts/channel/channel.d.ts +115 -0
- package/dist/dts/channel/channel.d.ts.map +1 -0
- package/dist/dts/compose/composition.d.ts +72 -0
- package/dist/dts/compose/composition.d.ts.map +1 -0
- package/dist/dts/compose/host.d.ts +17 -0
- package/dist/dts/compose/host.d.ts.map +1 -0
- package/dist/dts/compose/props.d.ts +13 -0
- package/dist/dts/compose/props.d.ts.map +1 -0
- package/dist/dts/compose/provide.d.ts +22 -0
- package/dist/dts/compose/provide.d.ts.map +1 -0
- package/dist/dts/compose/slot.d.ts +49 -0
- package/dist/dts/compose/slot.d.ts.map +1 -0
- package/dist/dts/compose/ui.d.ts +50 -0
- package/dist/dts/compose/ui.d.ts.map +1 -0
- package/dist/dts/definition/definition.d.ts +33 -0
- package/dist/dts/definition/definition.d.ts.map +1 -0
- package/dist/dts/event/event.d.ts +33 -0
- package/dist/dts/event/event.d.ts.map +1 -0
- package/dist/dts/event/eventGroup.d.ts +9 -0
- package/dist/dts/event/eventGroup.d.ts.map +1 -0
- package/dist/dts/feature/feature.d.ts +220 -0
- package/dist/dts/feature/feature.d.ts.map +1 -0
- package/dist/dts/index.d.ts +43 -0
- package/dist/dts/index.d.ts.map +1 -0
- package/dist/dts/internal/capture.d.ts +28 -0
- package/dist/dts/internal/capture.d.ts.map +1 -0
- package/dist/dts/internal/ctx.d.ts +12 -0
- package/dist/dts/internal/ctx.d.ts.map +1 -0
- package/dist/dts/internal/errors.d.ts +69 -0
- package/dist/dts/internal/errors.d.ts.map +1 -0
- package/dist/dts/internal/inspect.d.ts +17 -0
- package/dist/dts/internal/inspect.d.ts.map +1 -0
- package/dist/dts/internal/queryDriver.d.ts +65 -0
- package/dist/dts/internal/queryDriver.d.ts.map +1 -0
- package/dist/dts/internal/reuse.d.ts +10 -0
- package/dist/dts/internal/reuse.d.ts.map +1 -0
- package/dist/dts/internal/scheduler.d.ts +47 -0
- package/dist/dts/internal/scheduler.d.ts.map +1 -0
- package/dist/dts/internal/seeds.d.ts +17 -0
- package/dist/dts/internal/seeds.d.ts.map +1 -0
- package/dist/dts/internal/sources.d.ts +39 -0
- package/dist/dts/internal/sources.d.ts.map +1 -0
- package/dist/dts/internal/store.d.ts +47 -0
- package/dist/dts/internal/store.d.ts.map +1 -0
- package/dist/dts/internal/track.d.ts +33 -0
- package/dist/dts/internal/track.d.ts.map +1 -0
- package/dist/dts/procedure/procedure.d.ts +40 -0
- package/dist/dts/procedure/procedure.d.ts.map +1 -0
- package/dist/dts/reducer/reducer.d.ts +44 -0
- package/dist/dts/reducer/reducer.d.ts.map +1 -0
- package/dist/dts/remote/remoteState.d.ts +119 -0
- package/dist/dts/remote/remoteState.d.ts.map +1 -0
- package/dist/dts/runtime/bus.d.ts +27 -0
- package/dist/dts/runtime/bus.d.ts.map +1 -0
- package/dist/dts/runtime/loop.d.ts +45 -0
- package/dist/dts/runtime/loop.d.ts.map +1 -0
- package/dist/dts/scene/scene.d.ts +44 -0
- package/dist/dts/scene/scene.d.ts.map +1 -0
- package/dist/dts/state/state.d.ts +37 -0
- package/dist/dts/state/state.d.ts.map +1 -0
- package/dist/dts/state/stateFamily.d.ts +79 -0
- package/dist/dts/state/stateFamily.d.ts.map +1 -0
- package/dist/dts/state/stateGroup.d.ts +36 -0
- package/dist/dts/state/stateGroup.d.ts.map +1 -0
- package/dist/dts/state/token.d.ts +30 -0
- package/dist/dts/state/token.d.ts.map +1 -0
- package/dist/dts/ui/node.d.ts +9 -0
- package/dist/dts/ui/node.d.ts.map +1 -0
- package/dist/dts/ui/trigger.d.ts +7 -0
- package/dist/dts/ui/trigger.d.ts.map +1 -0
- package/dist/esm/boundary/boundary.js +83 -0
- package/dist/esm/boundary/boundary.js.map +1 -0
- package/dist/esm/calc/asyncCalc.js +95 -0
- package/dist/esm/calc/asyncCalc.js.map +1 -0
- package/dist/esm/calc/asyncData.js +34 -0
- package/dist/esm/calc/asyncData.js.map +1 -0
- package/dist/esm/calc/calc.js +58 -0
- package/dist/esm/calc/calc.js.map +1 -0
- package/dist/esm/calc/calcFamily.js +124 -0
- package/dist/esm/calc/calcFamily.js.map +1 -0
- package/dist/esm/channel/channel.js +136 -0
- package/dist/esm/channel/channel.js.map +1 -0
- package/dist/esm/compose/composition.js +46 -0
- package/dist/esm/compose/composition.js.map +1 -0
- package/dist/esm/compose/host.js +5 -0
- package/dist/esm/compose/host.js.map +1 -0
- package/dist/esm/compose/props.js +11 -0
- package/dist/esm/compose/props.js.map +1 -0
- package/dist/esm/compose/provide.js +28 -0
- package/dist/esm/compose/provide.js.map +1 -0
- package/dist/esm/compose/slot.js +23 -0
- package/dist/esm/compose/slot.js.map +1 -0
- package/dist/esm/compose/ui.js +57 -0
- package/dist/esm/compose/ui.js.map +1 -0
- package/dist/esm/definition/definition.js +42 -0
- package/dist/esm/definition/definition.js.map +1 -0
- package/dist/esm/event/event.js +30 -0
- package/dist/esm/event/event.js.map +1 -0
- package/dist/esm/event/eventGroup.js +4 -0
- package/dist/esm/event/eventGroup.js.map +1 -0
- package/dist/esm/feature/feature.js +98 -0
- package/dist/esm/feature/feature.js.map +1 -0
- package/dist/esm/index.js +45 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/capture.js +11 -0
- package/dist/esm/internal/capture.js.map +1 -0
- package/dist/esm/internal/ctx.js +2 -0
- package/dist/esm/internal/ctx.js.map +1 -0
- package/dist/esm/internal/errors.js +54 -0
- package/dist/esm/internal/errors.js.map +1 -0
- package/dist/esm/internal/inspect.js +32 -0
- package/dist/esm/internal/inspect.js.map +1 -0
- package/dist/esm/internal/queryDriver.js +134 -0
- package/dist/esm/internal/queryDriver.js.map +1 -0
- package/dist/esm/internal/reuse.js +68 -0
- package/dist/esm/internal/reuse.js.map +1 -0
- package/dist/esm/internal/scheduler.js +69 -0
- package/dist/esm/internal/scheduler.js.map +1 -0
- package/dist/esm/internal/seeds.js +17 -0
- package/dist/esm/internal/seeds.js.map +1 -0
- package/dist/esm/internal/sources.js +59 -0
- package/dist/esm/internal/sources.js.map +1 -0
- package/dist/esm/internal/store.js +73 -0
- package/dist/esm/internal/store.js.map +1 -0
- package/dist/esm/internal/track.js +18 -0
- package/dist/esm/internal/track.js.map +1 -0
- package/dist/esm/package.json +4 -0
- package/dist/esm/procedure/procedure.js +50 -0
- package/dist/esm/procedure/procedure.js.map +1 -0
- package/dist/esm/reducer/reducer.js +63 -0
- package/dist/esm/reducer/reducer.js.map +1 -0
- package/dist/esm/remote/remoteState.js +270 -0
- package/dist/esm/remote/remoteState.js.map +1 -0
- package/dist/esm/runtime/bus.js +20 -0
- package/dist/esm/runtime/bus.js.map +1 -0
- package/dist/esm/runtime/loop.js +116 -0
- package/dist/esm/runtime/loop.js.map +1 -0
- package/dist/esm/scene/scene.js +31 -0
- package/dist/esm/scene/scene.js.map +1 -0
- package/dist/esm/state/state.js +43 -0
- package/dist/esm/state/state.js.map +1 -0
- package/dist/esm/state/stateFamily.js +96 -0
- package/dist/esm/state/stateFamily.js.map +1 -0
- package/dist/esm/state/stateGroup.js +46 -0
- package/dist/esm/state/stateGroup.js.map +1 -0
- package/dist/esm/state/token.js +20 -0
- package/dist/esm/state/token.js.map +1 -0
- package/dist/esm/ui/node.js +2 -0
- package/dist/esm/ui/node.js.map +1 -0
- package/dist/esm/ui/trigger.js +2 -0
- package/dist/esm/ui/trigger.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.live = exports.select = exports.make = void 0;
|
|
4
|
+
const effect_1 = require("effect");
|
|
5
|
+
const definition_js_1 = require("../definition/definition.js");
|
|
6
|
+
const errors_js_1 = require("../internal/errors.js");
|
|
7
|
+
const state_js_1 = require("./state.js");
|
|
8
|
+
const token_js_1 = require("./token.js");
|
|
9
|
+
/** Compose atomic States into a group provided (and addressed) as a unit. */
|
|
10
|
+
const make = (...members) => (0, definition_js_1.definitionClass)({
|
|
11
|
+
kind: 'StateGroup',
|
|
12
|
+
members,
|
|
13
|
+
byName: new Map(members.map((m) => [m.manifest.name, m])),
|
|
14
|
+
});
|
|
15
|
+
exports.make = make;
|
|
16
|
+
/**
|
|
17
|
+
* Address a member by its tag — `StateGroup.select(TodosStates, 'feed')` —
|
|
18
|
+
* yielding a `StateToken` for reads and calc inputs (still `yield*`-able).
|
|
19
|
+
*
|
|
20
|
+
* Data-first only (not `dual`): the member name's type depends on the group, and
|
|
21
|
+
* a group is not `Pipeable`, so a data-last form would be both more verbose and
|
|
22
|
+
* harder to type than the direct call. Effect reserves `dual` for operators on a
|
|
23
|
+
* `Pipeable` self with an independent value arg (e.g. `ref.pipe(Ref.set(v))`);
|
|
24
|
+
* this is not that shape.
|
|
25
|
+
*/
|
|
26
|
+
const select = (group, name) => {
|
|
27
|
+
const member = group.byName.get(name);
|
|
28
|
+
if (member === undefined)
|
|
29
|
+
throw new errors_js_1.UnknownGroupState({ name });
|
|
30
|
+
return new token_js_1.StateToken(name, member.store);
|
|
31
|
+
};
|
|
32
|
+
exports.select = select;
|
|
33
|
+
/**
|
|
34
|
+
* Allocate every member's store as one merged layer, each seeded from `seeds`
|
|
35
|
+
* keyed by member name — `StateGroup.live(BoardStates, { board: { _tag: 'Idle' } })`.
|
|
36
|
+
*/
|
|
37
|
+
const live = (group, seeds) => {
|
|
38
|
+
// Index the typed seed record by the member's runtime name — a genuine
|
|
39
|
+
// reflection boundary (string key into a mapped type). Each member's store
|
|
40
|
+
// layer is then merged; the union of stores is exactly `StoresOf<Members>`,
|
|
41
|
+
// which `reduce`'s single-layer accumulator can't express, so restate it.
|
|
42
|
+
const seedRecord = seeds;
|
|
43
|
+
return group.members
|
|
44
|
+
.map((m) => (0, state_js_1.live)(m, seedRecord[m.manifest.name]))
|
|
45
|
+
.reduce((a, b) => effect_1.Layer.merge(a, b));
|
|
46
|
+
};
|
|
47
|
+
exports.live = live;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StateToken = void 0;
|
|
4
|
+
const effect_1 = require("effect");
|
|
5
|
+
const track_js_1 = require("../internal/track.js");
|
|
6
|
+
/**
|
|
7
|
+
* A reference to one slice of state: yieldable to its current value (`yield*`
|
|
8
|
+
* reads + — under React — subscribes) and carrying the metadata calcs need
|
|
9
|
+
* (its `name` and backing store tag). Returned by `StateGroup.select(group, name)`.
|
|
10
|
+
*/
|
|
11
|
+
class StateToken extends effect_1.Effectable.Class {
|
|
12
|
+
name;
|
|
13
|
+
store;
|
|
14
|
+
constructor(name, store) {
|
|
15
|
+
super();
|
|
16
|
+
this.name = name;
|
|
17
|
+
this.store = store;
|
|
18
|
+
}
|
|
19
|
+
commit() {
|
|
20
|
+
return effect_1.Effect.flatMap(this.store, track_js_1.readTracked);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.StateToken = StateToken;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from 'effect';
|
|
2
|
+
import { type Manifest } from '../definition/definition.js';
|
|
3
|
+
import { type InputStores } from '../internal/sources.js';
|
|
4
|
+
import { type Store } from '../internal/store.js';
|
|
5
|
+
import { type Source } from '../state/token.js';
|
|
6
|
+
/** Some covered source is still on its FIRST load — show the fallback. */
|
|
7
|
+
export interface BoundaryPending {
|
|
8
|
+
readonly _tag: 'Pending';
|
|
9
|
+
}
|
|
10
|
+
/** Some covered source failed before its first value. */
|
|
11
|
+
export interface BoundaryErrored {
|
|
12
|
+
readonly _tag: 'Errored';
|
|
13
|
+
/** The failures, in `over` order (heterogeneous — display via `String`). */
|
|
14
|
+
readonly errors: ReadonlyArray<unknown>;
|
|
15
|
+
}
|
|
16
|
+
/** Every covered source has settled (or is deliberately gated off). */
|
|
17
|
+
export interface BoundaryReady {
|
|
18
|
+
readonly _tag: 'Ready';
|
|
19
|
+
}
|
|
20
|
+
export type BoundaryState = BoundaryPending | BoundaryErrored | BoundaryReady;
|
|
21
|
+
/**
|
|
22
|
+
* Anything a boundary can cover: a `Source` whose value is an async lifecycle —
|
|
23
|
+
* an `AsyncCalc`, or anything lifecycle-valued built over one (e.g. a
|
|
24
|
+
* `RemoteState` overlay). The constraint is the same erased `Source` every calc
|
|
25
|
+
* input uses (store invariance rules out a fixed lifecycle value type — each
|
|
26
|
+
* definition's union carries its own `Gated`/`E` arms); the captured `const`
|
|
27
|
+
* tuple keeps each member's precise store requirement, and the runtime merge
|
|
28
|
+
* reads arms through structural guards, so a non-lifecycle source simply
|
|
29
|
+
* counts as settled.
|
|
30
|
+
*/
|
|
31
|
+
export type AnyLifecycleSource = Source<string, any>;
|
|
32
|
+
export interface BoundaryManifest<N extends string> extends Manifest {
|
|
33
|
+
readonly kind: 'Boundary';
|
|
34
|
+
readonly name: N;
|
|
35
|
+
}
|
|
36
|
+
export interface BoundaryClass<out N extends string, out Over extends ReadonlyArray<AnyLifecycleSource>> extends Effect.Effect<BoundaryState, never, Store<BoundaryState>> {
|
|
37
|
+
new (): {};
|
|
38
|
+
readonly manifest: BoundaryManifest<N>;
|
|
39
|
+
readonly store: Context.Tag<Store<BoundaryState>, Store<BoundaryState>>;
|
|
40
|
+
/** The boundary's name, so it doubles as a `Source` input to a calc. */
|
|
41
|
+
readonly name: N;
|
|
42
|
+
/** The covered lifecycle sources — read by `live` and the editor's graph. */
|
|
43
|
+
readonly over: Over;
|
|
44
|
+
}
|
|
45
|
+
export interface BoundaryConfig<Over extends ReadonlyArray<AnyLifecycleSource>> {
|
|
46
|
+
readonly over: Over;
|
|
47
|
+
}
|
|
48
|
+
export interface BoundaryOptions {
|
|
49
|
+
/**
|
|
50
|
+
* Latch: once Ready, stay Ready. A BOOT boundary wants this — a covered
|
|
51
|
+
* route-gated query that first enables on a later navigation (Idle →
|
|
52
|
+
* Loading) must not re-splash the whole shell; its own screen owns that
|
|
53
|
+
* loading state. Without the latch the boundary re-pends on any covered
|
|
54
|
+
* first load, which is what a per-screen boundary wants.
|
|
55
|
+
*/
|
|
56
|
+
readonly once?: boolean;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Define a boundary over async sources. `yield* MyBoundary` reads the merged
|
|
60
|
+
* `Pending | Errored | Ready` lifecycle; the consuming view renders ONE
|
|
61
|
+
* fallback on Pending and its content slot on Ready — content reveals
|
|
62
|
+
* together, with data already present (fetching never waited on rendering).
|
|
63
|
+
*/
|
|
64
|
+
export declare const make: <const N extends string, const Over extends ReadonlyArray<AnyLifecycleSource>>(name: N, config: BoundaryConfig<Over>) => BoundaryClass<N, Over>;
|
|
65
|
+
/**
|
|
66
|
+
* Wire the merge. A derived store over the covered stores (sensed through the
|
|
67
|
+
* same `wireSources` plumbing every calc uses): recomputes are memoized on the
|
|
68
|
+
* input snapshots and the arms are stable references, so input churn that does
|
|
69
|
+
* not move the merged arm wakes nobody.
|
|
70
|
+
*/
|
|
71
|
+
export declare const live: <N extends string, Over extends ReadonlyArray<AnyLifecycleSource>>(boundary: BoundaryClass<N, Over>, options?: BoundaryOptions) => Layer.Layer<Store<BoundaryState>, never, InputStores<Over>>;
|
|
72
|
+
//# sourceMappingURL=boundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../../../src/boundary/boundary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,EAAE,KAAK,EAAyB,MAAM,QAAQ,CAAA;AAC5E,OAAO,EAAE,KAAK,QAAQ,EAAkB,MAAM,0BAA0B,CAAA;AAExE,OAAO,EAAE,KAAK,WAAW,EAAwB,MAAM,qBAAqB,CAAA;AAC5E,OAAO,EAAoB,KAAK,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAEhE,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAA;AA8B5C,0EAA0E;AAC1E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CACzB;AAED,yDAAyD;AACzD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,CAAA;CACxC;AAED,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CACvB;AAED,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG,eAAe,GAAG,aAAa,CAAA;AAW7E;;;;;;;;;GASG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;AAEpD,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,QAAQ;IAClE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;CACjB;AAED,MAAM,WAAW,aAAa,CAAC,GAAG,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,CAAC,IAAI,SAAS,aAAa,CAAC,kBAAkB,CAAC,CACrG,SAAQ,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IACjE,QAAQ,EAAE,CAAA;IACV,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;IACtC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAA;IACvE,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;IAChB,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;CACpB;AAED,MAAM,WAAW,cAAc,CAAC,IAAI,SAAS,aAAa,CAAC,kBAAkB,CAAC;IAC5E,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CACxB;AAED;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,CAAC,IAAI,SAAS,aAAa,CAAC,kBAAkB,CAAC,EAC/F,MAAM,CAAC,EACP,QAAQ,cAAc,CAAC,IAAI,CAAC,KAC3B,aAAa,CAAC,CAAC,EAAE,IAAI,CAOvB,CAAA;AAUD;;;;;GAKG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,SAAS,MAAM,EAAE,IAAI,SAAS,aAAa,CAAC,kBAAkB,CAAC,EACnF,UAAU,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,EAChC,UAAS,eAAoB,KAC5B,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,CAiD1D,CAAA"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Context, Effect, Layer, Schema } from 'effect';
|
|
2
|
+
import { type Manifest } from '../definition/definition.js';
|
|
3
|
+
import { type AnyEvent } from '../event/event.js';
|
|
4
|
+
import { type InputsObject, type InputStores, type InvalidateBy } from '../internal/sources.js';
|
|
5
|
+
import { type GatedOf } from '../internal/queryDriver.js';
|
|
6
|
+
import { type Store } from '../internal/store.js';
|
|
7
|
+
import { Reducers } from '../runtime/loop.js';
|
|
8
|
+
import { type AnySource } from '../state/token.js';
|
|
9
|
+
import { type AsyncData } from './asyncData.js';
|
|
10
|
+
export interface AsyncCalcManifest<N extends string, A, E> extends Manifest {
|
|
11
|
+
readonly kind: 'AsyncCalc';
|
|
12
|
+
readonly name: N;
|
|
13
|
+
readonly output: Schema.Schema<A, any>;
|
|
14
|
+
readonly error?: Schema.Schema<E, any>;
|
|
15
|
+
/** Whether the query can be disabled (drives the `Idle` arm). */
|
|
16
|
+
readonly gated: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface AsyncCalcClass<out N extends string, out Inputs extends ReadonlyArray<AnySource>, in out A, in out E, in out Gated extends boolean> extends Effect.Effect<AsyncData<A, E, Gated>, never, Store<AsyncData<A, E, Gated>>> {
|
|
19
|
+
new (): {};
|
|
20
|
+
readonly manifest: AsyncCalcManifest<N, A, E>;
|
|
21
|
+
readonly store: Context.Tag<Store<AsyncData<A, E, Gated>>, Store<AsyncData<A, E, Gated>>>;
|
|
22
|
+
/** The calc's name, so it doubles as a `Source` input to another (async) calc. */
|
|
23
|
+
readonly name: N;
|
|
24
|
+
/** Marker data read by `AsyncCalc.live`. */
|
|
25
|
+
readonly inputs: Inputs;
|
|
26
|
+
/** Runtime mirror of `Gated`: whether `disabled` is honored / `Idle` can occur. */
|
|
27
|
+
readonly gated: Gated;
|
|
28
|
+
}
|
|
29
|
+
export interface AsyncCalcConfig<Inputs extends ReadonlyArray<AnySource>, A, E, AlwaysOn extends boolean> {
|
|
30
|
+
readonly inputs: Inputs;
|
|
31
|
+
/** Schema of the `Success` value. */
|
|
32
|
+
readonly output: Schema.Schema<A, any>;
|
|
33
|
+
/** Schema of the failure. Omitted ⇒ the query is infallible and there is no `Error` arm. */
|
|
34
|
+
readonly error?: Schema.Schema<E, any>;
|
|
35
|
+
/** `true` ⇒ the query is always on: no `Idle` arm and `disabled` is rejected on `.live`. */
|
|
36
|
+
readonly alwaysOn?: AlwaysOn;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The `.live` config: the effect plus the reactive logic. `disabled` is only
|
|
40
|
+
* accepted for a gateable query (no `alwaysOn`); `invalidateBy` is the same
|
|
41
|
+
* `queryKey` projection `Calc` uses.
|
|
42
|
+
*/
|
|
43
|
+
export type AsyncCalcLive<Inputs extends ReadonlyArray<AnySource>, A, E, Gated extends boolean, R> = {
|
|
44
|
+
readonly query: (inputs: InputsObject<Inputs>) => Effect.Effect<A, E, R>;
|
|
45
|
+
readonly invalidateBy?: InvalidateBy<Inputs>;
|
|
46
|
+
/**
|
|
47
|
+
* Refetch conciliation. `'switch'` (default): a new key cancels the in-flight
|
|
48
|
+
* run (latest-wins). `'trailing'`: the in-flight run completes; key changes
|
|
49
|
+
* that arrive meanwhile conflate to the latest, and exactly ONE trailing
|
|
50
|
+
* refetch runs after it settles — a burst of N invalidations during one
|
|
51
|
+
* flight costs 2 fetches, not N cancel-restarts.
|
|
52
|
+
*/
|
|
53
|
+
readonly coalesce?: 'switch' | 'trailing';
|
|
54
|
+
/**
|
|
55
|
+
* Structural sharing for `Success` values: reconcile each refetch result
|
|
56
|
+
* against the previous one, substituting previous nodes wherever value
|
|
57
|
+
* equality holds — refetches returning mostly-identical data keep unchanged
|
|
58
|
+
* subtree identities, so downstream memo boundaries skip them. Same pass as
|
|
59
|
+
* `Calc`'s `reuse`; opt-in (one O(result) walk per settle).
|
|
60
|
+
*/
|
|
61
|
+
readonly reuse?: boolean;
|
|
62
|
+
} & (Gated extends true ? {
|
|
63
|
+
readonly disabled?: (inputs: InputsObject<Inputs>) => boolean;
|
|
64
|
+
} : {
|
|
65
|
+
readonly disabled?: never;
|
|
66
|
+
});
|
|
67
|
+
/**
|
|
68
|
+
* Define an async derived value. `output`/`error` schemas and `alwaysOn` shape
|
|
69
|
+
* the value type, so `yield* MyQuery` is typed to exactly the arms that can
|
|
70
|
+
* occur. The query effect itself is supplied by `AsyncCalc.live`.
|
|
71
|
+
*/
|
|
72
|
+
export declare const make: <const N extends string, const Inputs extends ReadonlyArray<AnySource>, A, E = never, const AlwaysOn extends boolean = false>(name: N, config: AsyncCalcConfig<Inputs, A, E, AlwaysOn>) => AsyncCalcClass<N, Inputs, A, E, GatedOf<AlwaysOn>>;
|
|
73
|
+
/**
|
|
74
|
+
* Wire the query and its reactive logic. The query runs on the runtime (its `R`
|
|
75
|
+
* — RPC clients, etc. — is captured from the layer context). A change to an
|
|
76
|
+
* input re-runs it latest-wins (a new run cancels the in-flight one; or, with
|
|
77
|
+
* `coalesce: 'trailing'`, lets it finish and runs one trailing refetch); while a
|
|
78
|
+
* re-run is in flight the last `Success`/`Error` is kept with `refetching: true`.
|
|
79
|
+
* Re-runs are driven by inputs / `invalidateBy` / `disabled` — and, with
|
|
80
|
+
* `invalidateOn`, by listed events: pure sugar that generates a hidden revision
|
|
81
|
+
* state + reducer (the sole writer) and appends the revision to the calc's key,
|
|
82
|
+
* so an event-driven refetch is still just key movement under `Equal.equals`.
|
|
83
|
+
* The hidden pair stays internal — the user's `query`/`invalidateBy` see exactly
|
|
84
|
+
* the declared inputs — and costs the layer one extra requirement: the
|
|
85
|
+
* `Reducers` registry (the `Engine`).
|
|
86
|
+
*/
|
|
87
|
+
export declare function live<N extends string, Inputs extends ReadonlyArray<AnySource>, A, E, Gated extends boolean, R>(calc: AsyncCalcClass<N, Inputs, A, E, Gated>, config: AsyncCalcLive<Inputs, A, E, Gated, R> & {
|
|
88
|
+
readonly invalidateOn: ReadonlyArray<AnyEvent>;
|
|
89
|
+
}): Layer.Layer<Store<AsyncData<A, E, Gated>>, never, InputStores<Inputs> | R | Reducers>;
|
|
90
|
+
export declare function live<N extends string, Inputs extends ReadonlyArray<AnySource>, A, E, Gated extends boolean, R>(calc: AsyncCalcClass<N, Inputs, A, E, Gated>, config: AsyncCalcLive<Inputs, A, E, Gated, R>): Layer.Layer<Store<AsyncData<A, E, Gated>>, never, InputStores<Inputs> | R>;
|
|
91
|
+
//# sourceMappingURL=asyncCalc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asyncCalc.d.ts","sourceRoot":"","sources":["../../../src/calc/asyncCalc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type Store } from '../internal/store.js';
|
|
2
|
+
/** A gated query that is currently switched off (only when not `alwaysOn`). */
|
|
3
|
+
export interface AsyncIdle {
|
|
4
|
+
readonly _tag: 'Idle';
|
|
5
|
+
}
|
|
6
|
+
/** The first fetch, before any value exists. */
|
|
7
|
+
export interface AsyncLoading {
|
|
8
|
+
readonly _tag: 'Loading';
|
|
9
|
+
}
|
|
10
|
+
/** A resolved value; `refetching` is true while a background re-fetch runs. */
|
|
11
|
+
export interface AsyncSuccess<A> {
|
|
12
|
+
readonly _tag: 'Success';
|
|
13
|
+
readonly value: A;
|
|
14
|
+
readonly refetching: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** A failed query; `refetching` is true while a background re-fetch runs. */
|
|
17
|
+
export interface AsyncError<E> {
|
|
18
|
+
readonly _tag: 'Error';
|
|
19
|
+
readonly error: E;
|
|
20
|
+
readonly refetching: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The query lifecycle. `Gated` adds the `Idle` arm (a disable-able query); a
|
|
24
|
+
* non-`never` `E` adds the `Error` arm. Both are decided at `AsyncCalc.make`, so
|
|
25
|
+
* `yield* MyQuery` is typed to exactly the arms that can occur.
|
|
26
|
+
*/
|
|
27
|
+
export type AsyncData<A, E = never, Gated extends boolean = false> = (Gated extends true ? AsyncIdle : never) | AsyncLoading | AsyncSuccess<A> | ([E] extends [never] ? never : AsyncError<E>);
|
|
28
|
+
/** The full (un-narrowed) union — used internally by the live store. */
|
|
29
|
+
export type AnyAsyncData<A, E> = AsyncIdle | AsyncLoading | AsyncSuccess<A> | AsyncError<E>;
|
|
30
|
+
/**
|
|
31
|
+
* Constructors for the arms, namespaced under the same name as the type so call
|
|
32
|
+
* sites read `AsyncData.success(v)` / `AsyncData.error(e)` — no `error` import
|
|
33
|
+
* shadowing the keyword and one obvious home for every arm.
|
|
34
|
+
*/
|
|
35
|
+
export declare const AsyncData: {
|
|
36
|
+
readonly idle: AsyncIdle;
|
|
37
|
+
readonly loading: AsyncLoading;
|
|
38
|
+
readonly success: <A>(value: A, refetching?: boolean) => AsyncSuccess<A>;
|
|
39
|
+
readonly error: <E>(err: E, refetching?: boolean) => AsyncError<E>;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Narrow the live store (which holds the full `AnyAsyncData` union) to the arms
|
|
43
|
+
* the definition actually permits (`Gated`/`E`). The single documented home for
|
|
44
|
+
* that narrowing, so `AsyncCalc.live` returns it without an inline cast.
|
|
45
|
+
*/
|
|
46
|
+
export declare const narrowStore: <A, E, Gated extends boolean>(store: Store<AnyAsyncData<A, E>>) => Store<AsyncData<A, E, Gated>>;
|
|
47
|
+
/**
|
|
48
|
+
* The read-only inverse of `narrowStore`: widen a definition-narrowed store back
|
|
49
|
+
* to the full union, so a consumer (the `RemoteState` overlay) can dispatch on the
|
|
50
|
+
* lifecycle arms without carrying the definition's `Gated`/`E` conditionals.
|
|
51
|
+
* Sound for reads only — every narrowed value IS an `AnyAsyncData` — so callers
|
|
52
|
+
* must never `set` through the widened view (derived stores ignore `set` anyway).
|
|
53
|
+
*/
|
|
54
|
+
export declare const widenStore: <A, E, Gated extends boolean>(store: Store<AsyncData<A, E, Gated>>) => Store<AnyAsyncData<A, E>>;
|
|
55
|
+
//# sourceMappingURL=asyncData.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asyncData.d.ts","sourceRoot":"","sources":["../../../src/calc/asyncData.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAW9C,+EAA+E;AAC/E,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,gDAAgD;AAChD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CACzB;AAED,+EAA+E;AAC/E,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;IACjB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;CAC7B;AAED,6EAA6E;AAC7E,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;IACjB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;CAC7B;AAED;;;;GAIG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,KAAK,SAAS,OAAO,GAAG,KAAK,IAC7D,CAAC,KAAK,SAAS,IAAI,GAAG,SAAS,GAAG,KAAK,CAAC,GACxC,YAAY,GACZ,YAAY,CAAC,CAAC,CAAC,GACf,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;AAEjD,wEAAwE;AACxE,MAAM,MAAM,YAAY,CAAC,CAAC,EAAE,CAAC,IAAI,SAAS,GAAG,YAAY,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAA;AAe3F;;;;GAIG;AACH,eAAO,MAAM,SAAS;;;uBAhBL,CAAC,SAAS,CAAC,2BAAuB,YAAY,CAAC,CAAC,CAAC;qBAKnD,CAAC,OAAO,CAAC,2BAAuB,UAAU,CAAC,CAAC,CAAC;CAWO,CAAA;AAEnE;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,EAAE,CAAC,EAAE,KAAK,SAAS,OAAO,EACrD,OAAO,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAC/B,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAsD,CAAA;AAErF;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,CAAC,EAAE,KAAK,SAAS,OAAO,EACpD,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,KACnC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAkD,CAAA"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Context, Effect, Layer, type Schema } from 'effect';
|
|
2
|
+
import { type Manifest } from '../definition/definition.js';
|
|
3
|
+
import { type InputsObject, type InputStores, type InvalidateBy } from '../internal/sources.js';
|
|
4
|
+
import { type Store } from '../internal/store.js';
|
|
5
|
+
import { type AnySource } from '../state/token.js';
|
|
6
|
+
export { type InputsObject, type InputStores, type InvalidateBy } from '../internal/sources.js';
|
|
7
|
+
export interface CalcOptions<Inputs extends ReadonlyArray<AnySource>> {
|
|
8
|
+
/**
|
|
9
|
+
* Custom invalidation: recompute only when the projected key changes by value
|
|
10
|
+
* equality (React-Query's `queryKey`). Omitted ⇒ recompute when any input
|
|
11
|
+
* value changes. Shared with `AsyncCalc`.
|
|
12
|
+
*/
|
|
13
|
+
readonly invalidateBy?: InvalidateBy<Inputs>;
|
|
14
|
+
/**
|
|
15
|
+
* Structural sharing: reconcile each recomputed output against the previous
|
|
16
|
+
* one, substituting previous nodes wherever value equality holds — so
|
|
17
|
+
* identities only move where values moved and downstream memo boundaries
|
|
18
|
+
* (React subtrees) skip unchanged regions. Referentially transparent (the
|
|
19
|
+
* result is value-equal to the fresh output); costs one O(output) walk per
|
|
20
|
+
* recompute, so opt in for large projections.
|
|
21
|
+
*/
|
|
22
|
+
readonly reuse?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface CalcManifest<N extends string, Out> extends Manifest {
|
|
25
|
+
readonly kind: 'Calc';
|
|
26
|
+
readonly name: N;
|
|
27
|
+
readonly output: Schema.Schema<Out, any>;
|
|
28
|
+
}
|
|
29
|
+
export interface CalcClass<out N extends string, out Inputs extends ReadonlyArray<AnySource>, in out Out> extends Effect.Effect<Out, never, Store<Out>> {
|
|
30
|
+
new (): {};
|
|
31
|
+
readonly manifest: CalcManifest<N, Out>;
|
|
32
|
+
readonly store: Context.Tag<Store<Out>, Store<Out>>;
|
|
33
|
+
/** The calc's name, so it doubles as a `Source` input to another calc. */
|
|
34
|
+
readonly name: N;
|
|
35
|
+
/** Marker data read by `Calc.live`. */
|
|
36
|
+
readonly inputs: Inputs;
|
|
37
|
+
}
|
|
38
|
+
export interface CalcConfig<Inputs extends ReadonlyArray<AnySource>, Out> {
|
|
39
|
+
readonly inputs: Inputs;
|
|
40
|
+
readonly output: Schema.Schema<Out, any>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A derived, memoized value over explicit inputs (state members, other calcs, or
|
|
44
|
+
* async calcs). The *definition* fixes the inputs and the output schema; the
|
|
45
|
+
* *implementation* is the pure projection. Recomputes only when an input changes;
|
|
46
|
+
* `yield* Calc` reads the memoized value.
|
|
47
|
+
*/
|
|
48
|
+
export declare const make: <const N extends string, const Inputs extends ReadonlyArray<AnySource>, Out>(name: N, config: CalcConfig<Inputs, Out>) => CalcClass<N, Inputs, Out>;
|
|
49
|
+
/**
|
|
50
|
+
* Wire the pure projection for a calc. Recomputes only when its invalidation key
|
|
51
|
+
* changes (by default every input value; override with `invalidateBy`), memoized
|
|
52
|
+
* on that key; `yield* Calc` reads the memoized value. The derived store reuses
|
|
53
|
+
* the shared coalescing scheduler, so a recompute that yields an equal value
|
|
54
|
+
* wakes no subscriber.
|
|
55
|
+
*/
|
|
56
|
+
export declare const live: <N extends string, Inputs extends ReadonlyArray<AnySource>, Out>(calc: CalcClass<N, Inputs, Out>, compute: (inputs: InputsObject<Inputs>) => Out, options?: CalcOptions<Inputs>) => Layer.Layer<Store<Out>, never, InputStores<Inputs>>;
|
|
57
|
+
//# sourceMappingURL=calc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calc.d.ts","sourceRoot":"","sources":["../../../src/calc/calc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Context, Effect, Layer, type Schema } from 'effect';
|
|
2
|
+
import { type Manifest } from '../definition/definition.js';
|
|
3
|
+
import { type InputsObject, type InputStores, type InvalidateBy } from '../internal/sources.js';
|
|
4
|
+
import { type FamilyOptions, type FamilyStore } from '../state/stateFamily.js';
|
|
5
|
+
import { type AnySource } from '../state/token.js';
|
|
6
|
+
export interface CalcFamilyManifest<N extends string, K, Out> extends Manifest {
|
|
7
|
+
readonly kind: 'CalcFamily';
|
|
8
|
+
readonly name: N;
|
|
9
|
+
readonly key: Schema.Schema<K, any>;
|
|
10
|
+
readonly output: Schema.Schema<Out, any>;
|
|
11
|
+
}
|
|
12
|
+
export interface CalcFamilyClass<out N extends string, out Inputs extends ReadonlyArray<AnySource>, in out K, in out Out> {
|
|
13
|
+
/** Instance carries the key phantom so `Family['Key']` resolves in key types. */
|
|
14
|
+
new (): {
|
|
15
|
+
readonly Key: K;
|
|
16
|
+
};
|
|
17
|
+
readonly manifest: CalcFamilyManifest<N, K, Out>;
|
|
18
|
+
readonly store: Context.Tag<FamilyStore<K, Out>, FamilyStore<K, Out>>;
|
|
19
|
+
/** Marker data read by `CalcFamily.live` and the editor's graph builder. */
|
|
20
|
+
readonly inputs: Inputs;
|
|
21
|
+
}
|
|
22
|
+
export interface CalcFamilyConfig<Inputs extends ReadonlyArray<AnySource>, K, Out> {
|
|
23
|
+
readonly key: Schema.Schema<K, any>;
|
|
24
|
+
readonly inputs: Inputs;
|
|
25
|
+
readonly output: Schema.Schema<Out, any>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Define a keyed derived value: per-key memoized projections over shared
|
|
29
|
+
* inputs. The *definition* fixes the key/output schemas and the inputs; the
|
|
30
|
+
* *implementation* (the per-key projection) is supplied by `CalcFamily.live`.
|
|
31
|
+
*/
|
|
32
|
+
export declare const make: <const N extends string, const Inputs extends ReadonlyArray<AnySource>, K, Out>(name: N, config: CalcFamilyConfig<Inputs, K, Out>) => CalcFamilyClass<N, Inputs, K, Out>;
|
|
33
|
+
/**
|
|
34
|
+
* Read one member by key — `CalcFamily.read(GroupProjection, id)`. Inside a
|
|
35
|
+
* render it subscribes exactly that member's store (unrelated members never
|
|
36
|
+
* wake the subtree); elsewhere it just snapshots — the same one-read-API
|
|
37
|
+
* contract as `StateFamily.read`.
|
|
38
|
+
*/
|
|
39
|
+
export declare const read: <N extends string, Inputs extends ReadonlyArray<AnySource>, K, Out>(family: CalcFamilyClass<N, Inputs, K, Out>, key: K) => Effect.Effect<Out, never, FamilyStore<K, Out>>;
|
|
40
|
+
export interface CalcFamilyLiveOptions<Inputs extends ReadonlyArray<AnySource>> extends FamilyOptions {
|
|
41
|
+
/**
|
|
42
|
+
* Family-wide invalidation key over the SHARED inputs (the member key plays
|
|
43
|
+
* no part — it is fixed per member). Same contract as `Calc`'s.
|
|
44
|
+
*/
|
|
45
|
+
readonly invalidateBy?: InvalidateBy<Inputs>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Wire the per-key projection. `compute` is curried — `(key) => (inputs) =>
|
|
49
|
+
* Out` — so per-key construction (closing over key-derived constants) runs once
|
|
50
|
+
* per member while the inner projection runs per recompute. Each member is a
|
|
51
|
+
* lazy derived store over the shared wired sources: memoized on the family's
|
|
52
|
+
* invalidation key, notifying only when its own output moves. Unlike a
|
|
53
|
+
* `StateFamily` entry, a member holds an upstream subscription, so every
|
|
54
|
+
* removal path (forget / clear / eviction / the layer finalizer) releases it.
|
|
55
|
+
*/
|
|
56
|
+
export declare const live: <N extends string, Inputs extends ReadonlyArray<AnySource>, K, Out>(family: CalcFamilyClass<N, Inputs, K, Out>, compute: (key: K) => (inputs: InputsObject<Inputs>) => Out, options?: CalcFamilyLiveOptions<Inputs>) => Layer.Layer<FamilyStore<K, Out>, never, InputStores<Inputs>>;
|
|
57
|
+
//# sourceMappingURL=calcFamily.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calcFamily.d.ts","sourceRoot":"","sources":["../../../src/calc/calcFamily.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Context, type Duration, Effect, Layer } from 'effect';
|
|
2
|
+
import { type Manifest } from '../definition/definition.js';
|
|
3
|
+
import type { Tagged } from '../runtime/bus.js';
|
|
4
|
+
/**
|
|
5
|
+
* How a channel schedules the procedure work routed to it. Channels generalize
|
|
6
|
+
* the old per-procedure `concurrency`: a named lane with one policy, shared by
|
|
7
|
+
* every procedure that declares it.
|
|
8
|
+
*
|
|
9
|
+
* - `merge` run every routed event concurrently (the default).
|
|
10
|
+
* - `latest` a new event cancels the in-flight run (switch).
|
|
11
|
+
* - `debounce` collapse a burst, run only after `duration` of quiet.
|
|
12
|
+
* - `throttle` rate-limit to `units` per `duration` (shape or enforce).
|
|
13
|
+
* - `exclusive` one run at a time across the whole channel (mutual exclusion).
|
|
14
|
+
*/
|
|
15
|
+
export type ChannelPolicy = {
|
|
16
|
+
readonly _tag: 'merge';
|
|
17
|
+
} | {
|
|
18
|
+
readonly _tag: 'latest';
|
|
19
|
+
} | {
|
|
20
|
+
readonly _tag: 'debounce';
|
|
21
|
+
readonly duration: Duration.DurationInput;
|
|
22
|
+
} | {
|
|
23
|
+
readonly _tag: 'throttle';
|
|
24
|
+
readonly units: number;
|
|
25
|
+
readonly duration: Duration.DurationInput;
|
|
26
|
+
readonly cost?: number;
|
|
27
|
+
readonly burst?: number;
|
|
28
|
+
readonly strategy?: 'enforce' | 'shape';
|
|
29
|
+
} | {
|
|
30
|
+
readonly _tag: 'exclusive';
|
|
31
|
+
};
|
|
32
|
+
/** The reflectable descriptor a channel carries. */
|
|
33
|
+
export interface ChannelManifest extends Manifest {
|
|
34
|
+
readonly kind: 'Channel';
|
|
35
|
+
}
|
|
36
|
+
export interface ChannelClass {
|
|
37
|
+
new (): {};
|
|
38
|
+
readonly manifest: ChannelManifest;
|
|
39
|
+
readonly policy: ChannelPolicy;
|
|
40
|
+
}
|
|
41
|
+
export interface ChannelConfig {
|
|
42
|
+
readonly policy: ChannelPolicy;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A registered procedure body, with its trigger events and the channel it runs
|
|
46
|
+
* on. `run`'s context (RPC clients, etc.) is already provided at registration
|
|
47
|
+
* (see `Procedure.live`), so the channel fiber can run it with no R.
|
|
48
|
+
*/
|
|
49
|
+
export interface ProcedureEntry {
|
|
50
|
+
/** The procedure's name — used only to warn on duplicate registration. */
|
|
51
|
+
readonly name: string;
|
|
52
|
+
readonly channelName: string;
|
|
53
|
+
readonly handles: ReadonlySet<string>;
|
|
54
|
+
readonly run: (event: Tagged) => Effect.Effect<unknown, unknown, never>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Mutable collector procedures register into; channels read it to find their
|
|
58
|
+
* bodies. `byTag` indexes entries by trigger tag, so a channel routes an event
|
|
59
|
+
* to O(procedures handling it) rather than scanning every registered procedure.
|
|
60
|
+
*/
|
|
61
|
+
export interface ProcedureRegistry {
|
|
62
|
+
readonly entries: Array<ProcedureEntry>;
|
|
63
|
+
readonly byTag: Map<string, Array<ProcedureEntry>>;
|
|
64
|
+
/**
|
|
65
|
+
* Distinct channel names per event tag. The drain loop routes through this so
|
|
66
|
+
* it offers each event to each channel exactly once — not once per matching
|
|
67
|
+
* procedure, which would re-run every procedure on a shared channel per offer.
|
|
68
|
+
*/
|
|
69
|
+
readonly channelsByTag: Map<string, Array<string>>;
|
|
70
|
+
/**
|
|
71
|
+
* Procedures keyed by (channel, tag), so a channel's `runMatching` is a direct
|
|
72
|
+
* lookup instead of scanning `byTag` and re-filtering by channel per event.
|
|
73
|
+
*/
|
|
74
|
+
readonly byChannelTag: Map<string, Map<string, Array<ProcedureEntry>>>;
|
|
75
|
+
readonly register: (entry: ProcedureEntry) => void;
|
|
76
|
+
/**
|
|
77
|
+
* Remove a previously-registered entry — the inverse of `register`, used when a
|
|
78
|
+
* lazy feature unmounts (scope close) so its procedures stop running and their
|
|
79
|
+
* index entries are reclaimed. Eager procedures (root scope) never call it.
|
|
80
|
+
*/
|
|
81
|
+
readonly unregister: (entry: ProcedureEntry) => void;
|
|
82
|
+
}
|
|
83
|
+
declare const Procedures_base: Context.TagClass<Procedures, "reform/Procedures", ProcedureRegistry>;
|
|
84
|
+
export declare class Procedures extends Procedures_base {
|
|
85
|
+
}
|
|
86
|
+
export declare const proceduresLayer: Layer.Layer<Procedures, never, never>;
|
|
87
|
+
/** A live channel: the single loop offers events here; the channel drives them. */
|
|
88
|
+
export interface ChannelRuntime {
|
|
89
|
+
readonly name: string;
|
|
90
|
+
/** The policy this channel was built with — used to reject a name clash. */
|
|
91
|
+
readonly policy: ChannelPolicy;
|
|
92
|
+
readonly offer: (event: Tagged) => void;
|
|
93
|
+
}
|
|
94
|
+
declare const Channels_base: Context.TagClass<Channels, "reform/Channels", {
|
|
95
|
+
readonly byName: Map<string, ChannelRuntime>;
|
|
96
|
+
}>;
|
|
97
|
+
/** Registry of live channels, keyed by name. The single loop routes through it. */
|
|
98
|
+
export declare class Channels extends Channels_base {
|
|
99
|
+
}
|
|
100
|
+
export declare const channelsLayer: Layer.Layer<Channels, never, never>;
|
|
101
|
+
/**
|
|
102
|
+
* A scheduling lane for procedures. The *definition* (`Channel.make`) is a
|
|
103
|
+
* reflectable name + policy; the *implementation* (`Channel.live`) builds the
|
|
104
|
+
* queue + fiber that applies the policy. Procedures reference a channel by value
|
|
105
|
+
* and register into it; `Channel.live` is merged into the app once per channel.
|
|
106
|
+
*/
|
|
107
|
+
export declare const make: (name: string, config: ChannelConfig) => ChannelClass;
|
|
108
|
+
/**
|
|
109
|
+
* Build and register the live machinery for a channel. Idempotent by name, so
|
|
110
|
+
* procedures sharing an `exclusive`/`latest` channel share one queue + fiber +
|
|
111
|
+
* semaphore (and therefore truly serialize / cancel across each other).
|
|
112
|
+
*/
|
|
113
|
+
export declare const live: (channel: ChannelClass) => Layer.Layer<never, never, Channels | Procedures>;
|
|
114
|
+
export {};
|
|
115
|
+
//# sourceMappingURL=channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../../src/channel/channel.ts"],"names":[],"mappings":"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"}
|