@playfast/reform-proof 0.0.7 → 0.0.9
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/package.json +2 -2
- package/src/engine.ts +452 -0
- package/src/errors.ts +56 -0
- package/src/index.ts +373 -0
- package/src/runner.ts +42 -0
- package/src/structure-events.test.ts +74 -0
- package/src/structure-locators.test.ts +137 -0
- package/src/typed-seams.test.ts +166 -0
- package/dist/engine.d.ts +0 -18
- package/dist/engine.d.ts.map +0 -1
- package/dist/engine.js +0 -259
- package/dist/engine.js.map +0 -1
- package/dist/errors.d.ts +0 -40
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -23
- package/dist/errors.js.map +0 -1
- package/dist/index.d.ts +0 -176
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -92
- package/dist/index.js.map +0 -1
- package/dist/runner.d.ts +0 -22
- package/dist/runner.d.ts.map +0 -1
- package/dist/runner.js +0 -18
- package/dist/runner.js.map +0 -1
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { Layer, Schema as S } from 'effect'
|
|
2
|
+
import {
|
|
3
|
+
Composition,
|
|
4
|
+
Engine,
|
|
5
|
+
Event,
|
|
6
|
+
mount,
|
|
7
|
+
one,
|
|
8
|
+
provide,
|
|
9
|
+
Reducer,
|
|
10
|
+
scene,
|
|
11
|
+
seedScene,
|
|
12
|
+
slot,
|
|
13
|
+
State,
|
|
14
|
+
StateGroup,
|
|
15
|
+
type Trigger,
|
|
16
|
+
ui,
|
|
17
|
+
} from '@playfast/reform'
|
|
18
|
+
import { describe, expect, test } from 'vitest'
|
|
19
|
+
import { Product, Proof, ProductRequirement, expect as proofExpect } from './index'
|
|
20
|
+
|
|
21
|
+
// Exercises the four type-safety seams closed in this change, each against a
|
|
22
|
+
// self-contained mini Counter (the same fixture shape as the stepper test):
|
|
23
|
+
// #1 typed seeds — seedScene is keyed/valued by the state tuple
|
|
24
|
+
// #2 action results — an action resolves to the settled next props
|
|
25
|
+
// #4 typed assertions — app.expectProps is a contract-typed subset match
|
|
26
|
+
// #5 event coverage — a requirement's declared events must be dispatched
|
|
27
|
+
// Negative cases are compile-time (`@ts-expect-error`) — the whole point is that
|
|
28
|
+
// the bad input never reaches runtime.
|
|
29
|
+
|
|
30
|
+
class CountState extends State.make('count', S.Number) {}
|
|
31
|
+
class MiniStates extends StateGroup.make(CountState) {}
|
|
32
|
+
class Bumped extends Event.make('Bumped', S.Struct({})) {}
|
|
33
|
+
class BumpReducer extends Reducer.make('BumpReducer', { states: [CountState], events: [Bumped] }) {}
|
|
34
|
+
const BumpReducerLive = Reducer.live(BumpReducer, (n) => n + 1)
|
|
35
|
+
|
|
36
|
+
// A trivial slot child: a proof runtime resolves slot-bound compositions, so the
|
|
37
|
+
// app needs at least one slot for the suite's provide layer to type-close.
|
|
38
|
+
class LabelUi extends ui('Label')<{ props: { text: string } }>() {}
|
|
39
|
+
class Label extends Composition.make('Label', { title: 'Label', ui: LabelUi }) {}
|
|
40
|
+
const LabelLive = Composition.live(Label, function* () {
|
|
41
|
+
return mount({ props: { text: 'count' }, slots: {} })
|
|
42
|
+
})
|
|
43
|
+
class LabelSlot extends slot('Label')<typeof Label>() {}
|
|
44
|
+
|
|
45
|
+
class CounterUi extends ui('Counter')<{
|
|
46
|
+
props: { count: number }
|
|
47
|
+
slots: { Label: LabelSlot }
|
|
48
|
+
events: { bump: Trigger<Record<string, never>> }
|
|
49
|
+
}>() {}
|
|
50
|
+
class Counter extends Composition.make('Counter', {
|
|
51
|
+
title: 'Counter',
|
|
52
|
+
states: [MiniStates],
|
|
53
|
+
events: [Bumped],
|
|
54
|
+
slots: { Label: LabelSlot },
|
|
55
|
+
ui: CounterUi,
|
|
56
|
+
}) {}
|
|
57
|
+
const CounterLive = Composition.live(Counter, function* () {
|
|
58
|
+
const count = yield* StateGroup.select(MiniStates, 'count')
|
|
59
|
+
const bump = yield* Event.trigger(Bumped)
|
|
60
|
+
return mount({
|
|
61
|
+
props: { count },
|
|
62
|
+
slots: { Label: one({}) },
|
|
63
|
+
events: { bump },
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
const presentations = provide(LabelSlot, Label)
|
|
68
|
+
const Views = Layer.mergeAll(CounterLive, LabelLive).pipe(Layer.provideMerge(presentations))
|
|
69
|
+
const Logic = Layer.mergeAll(BumpReducerLive).pipe(
|
|
70
|
+
Layer.provideMerge(Layer.mergeAll(Engine, StateGroup.live(MiniStates, { count: 5 }))),
|
|
71
|
+
)
|
|
72
|
+
const MiniApp = Views.pipe(Layer.provideMerge(Logic))
|
|
73
|
+
|
|
74
|
+
const CounterScene = scene(Counter, { provide: [MiniApp] })
|
|
75
|
+
|
|
76
|
+
class Bumps extends ProductRequirement.make(Counter, 'bumps the count') {}
|
|
77
|
+
class CounterProduct extends Product.make(Counter, { requirements: [Bumps] }) {}
|
|
78
|
+
|
|
79
|
+
describe('#1 typed seeds', () => {
|
|
80
|
+
test('seedScene overrides the authored seed, typed by the state tuple', async () => {
|
|
81
|
+
const seeded = seedScene(CounterScene, { count: 9 })
|
|
82
|
+
const boots = Proof.implement(Bumps, seeded, function* (app) {
|
|
83
|
+
const props = yield* app.props
|
|
84
|
+
yield* proofExpect(props.count).toBe(9)
|
|
85
|
+
})
|
|
86
|
+
const result = await Proof.run(Proof.suite(CounterProduct, { proofs: [boots] }))
|
|
87
|
+
expect(result.ok).toBe(true)
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
test('an unknown key or mistyped value is a compile error', () => {
|
|
91
|
+
// @ts-expect-error 'other' is not a state member of Counter
|
|
92
|
+
seedScene(CounterScene, { other: 1 })
|
|
93
|
+
// @ts-expect-error 'count' is a number, not a string
|
|
94
|
+
seedScene(CounterScene, { count: 'nope' })
|
|
95
|
+
expect(true).toBe(true)
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
describe('#2 actions return post-settle props', () => {
|
|
100
|
+
test('dispatching an event resolves to the settled next props', async () => {
|
|
101
|
+
const bumps = Proof.implement(Bumps, CounterScene, function* (app) {
|
|
102
|
+
const props = yield* app.actions.bump({})
|
|
103
|
+
yield* proofExpect(props.count).toBe(6)
|
|
104
|
+
})
|
|
105
|
+
const result = await Proof.run(Proof.suite(CounterProduct, { proofs: [bumps] }))
|
|
106
|
+
expect(result.ok).toBe(true)
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
describe('#4 contract-typed prop assertions', () => {
|
|
111
|
+
test('expectProps matches a typed subset of the computed props', async () => {
|
|
112
|
+
const matches = Proof.implement(Bumps, CounterScene, function* (app) {
|
|
113
|
+
yield* app.expectProps({ count: 5 })
|
|
114
|
+
yield* app.actions.bump({})
|
|
115
|
+
yield* app.expectProps({ count: 6 })
|
|
116
|
+
})
|
|
117
|
+
const result = await Proof.run(Proof.suite(CounterProduct, { proofs: [matches] }))
|
|
118
|
+
expect(result.ok).toBe(true)
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
test('a non-matching expectProps fails the proof', async () => {
|
|
122
|
+
const wrong = Proof.implement(Bumps, CounterScene, function* (app) {
|
|
123
|
+
yield* app.expectProps({ count: 999 })
|
|
124
|
+
})
|
|
125
|
+
const result = await Proof.run(Proof.suite(CounterProduct, { proofs: [wrong] }))
|
|
126
|
+
expect(result.ok).toBe(false)
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
test('a typo’d prop key is a compile error', () => {
|
|
130
|
+
Proof.implement(Bumps, CounterScene, function* (app) {
|
|
131
|
+
// @ts-expect-error 'cuont' is not a prop of Counter
|
|
132
|
+
yield* app.expectProps({ cuont: 5 })
|
|
133
|
+
})
|
|
134
|
+
expect(true).toBe(true)
|
|
135
|
+
})
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
describe('#5 requirement-bound event coverage', () => {
|
|
139
|
+
class CoveredBump extends ProductRequirement.make(Counter, 'bumps via the bump event', {
|
|
140
|
+
events: ['bump'],
|
|
141
|
+
}) {}
|
|
142
|
+
class CoveredProduct extends Product.make(Counter, { requirements: [CoveredBump] }) {}
|
|
143
|
+
|
|
144
|
+
test('passes when the declared event is dispatched', async () => {
|
|
145
|
+
const proof = Proof.implement(CoveredBump, CounterScene, function* (app) {
|
|
146
|
+
yield* app.actions.bump({})
|
|
147
|
+
})
|
|
148
|
+
const result = await Proof.run(Proof.suite(CoveredProduct, { proofs: [proof] }))
|
|
149
|
+
expect(result.ok).toBe(true)
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
test('fails, naming the event, when a declared event is never dispatched', async () => {
|
|
153
|
+
const proof = Proof.implement(CoveredBump, CounterScene, function* (app) {
|
|
154
|
+
yield* app.props
|
|
155
|
+
})
|
|
156
|
+
const result = await Proof.run(Proof.suite(CoveredProduct, { proofs: [proof] }))
|
|
157
|
+
expect(result.ok).toBe(false)
|
|
158
|
+
expect(result.results[0]?.error).toContain('bump')
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
test('an event name outside the contract is a compile error', () => {
|
|
162
|
+
// @ts-expect-error 'nope' is not an event of Counter
|
|
163
|
+
ProductRequirement.make(Counter, 'invalid coverage', { events: ['nope'] })
|
|
164
|
+
expect(true).toBe(true)
|
|
165
|
+
})
|
|
166
|
+
})
|
package/dist/engine.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { DriveResult, Proof, ProofResult } from './index';
|
|
2
|
-
/**
|
|
3
|
-
* Run one proof against a fresh runtime, returning its pass/fail result. Each
|
|
4
|
-
* proof gets its own isolated environment, so nothing leaks between proofs. Boots
|
|
5
|
-
* the scene as the host would, settles, then runs the proof body to completion.
|
|
6
|
-
*/
|
|
7
|
-
export declare const executeProof: (proof: Proof) => Promise<ProofResult>;
|
|
8
|
-
/**
|
|
9
|
-
* Drive one proof a step at a time, recording a `StepFrame` after each yielded
|
|
10
|
-
* effect settles. Reuses the same makeFacade runtime/facade/settle as
|
|
11
|
-
* `executeProof`, but instead of handing the body to `Effect.gen` (which runs it
|
|
12
|
-
* to completion), it pumps the generator by hand — `gen.next(value)` yields the
|
|
13
|
-
* next effect, we run it on the live runtime, snapshot the sink, and feed the
|
|
14
|
-
* result back. So the editor gets the per-step timeline with no change to the
|
|
15
|
-
* proof authoring API.
|
|
16
|
-
*/
|
|
17
|
-
export declare const driveProof: (proof: Proof) => Promise<DriveResult>;
|
|
18
|
-
//# sourceMappingURL=engine.d.ts.map
|
package/dist/engine.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAU,WAAW,EAAU,KAAK,EAAE,WAAW,EAAyB,MAAM,SAAS,CAAA;AA0PrG;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAU,OAAO,KAAK,KAAG,OAAO,CAAC,WAAW,CAqBpE,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,GAAU,OAAO,KAAK,KAAG,OAAO,CAAC,WAAW,CAkClE,CAAA"}
|
package/dist/engine.js
DELETED
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
import { Effect, Layer, ManagedRuntime } from 'effect';
|
|
2
|
-
import { yieldWrapGet } from 'effect/Utils';
|
|
3
|
-
import { isValidElement } from 'react';
|
|
4
|
-
import { UnknownAction, UnknownSlot } from './errors';
|
|
5
|
-
import { Bus, CaptureSink, Composition, isFeatureBinding, publish, } from '@playfast/reform';
|
|
6
|
-
// The drain loop, channels, RPC, and reducers run on forked fibers, so a
|
|
7
|
-
// dispatched event takes an unknown number of ticks to flow through. Each poll
|
|
8
|
-
// first drains COOPERATIVELY — a burst of `yieldNow` lets those forked fibers
|
|
9
|
-
// cascade (event → channel → procedure → in-memory RPC → fact → reducer) with no
|
|
10
|
-
// real time — so a synchronous flow reaches its final state within one poll. A
|
|
11
|
-
// real-time `sleep` is still paid each poll to remain the correctness authority
|
|
12
|
-
// for a genuinely time-delayed client (the cooperative drain alone could read a
|
|
13
|
-
// flow waiting on a real timer as falsely "stable" and settle early). The render
|
|
14
|
-
// then re-runs until the captured tree stops changing, bounded so a stuck flow
|
|
15
|
-
// fails fast instead of hanging.
|
|
16
|
-
const SETTLE_DRAIN = 30;
|
|
17
|
-
const SETTLE_STEP = '1 milli';
|
|
18
|
-
const SETTLE_MAX_RENDERS = 100;
|
|
19
|
-
/** Cooperatively run forked engine fibers to a fixpoint without advancing real time. */
|
|
20
|
-
const settleDrain = Effect.yieldNow().pipe(Effect.repeatN(SETTLE_DRAIN));
|
|
21
|
-
// A keyed view backed by a getter — the only place dynamic keys are needed.
|
|
22
|
-
const keyed = (get) => {
|
|
23
|
-
const target = Object.create(null);
|
|
24
|
-
return new Proxy(target, { get: (_t, key) => get(String(key)) });
|
|
25
|
-
};
|
|
26
|
-
const uiNameOf = (comp) => comp.manifest.ui.manifest.name;
|
|
27
|
-
const makeSink = () => {
|
|
28
|
-
// A const holder whose array we swap on reset (no reassigned binding).
|
|
29
|
-
const state = { captures: [] };
|
|
30
|
-
return {
|
|
31
|
-
api: { record: (capture) => state.captures.push(capture) },
|
|
32
|
-
get captures() {
|
|
33
|
-
return state.captures;
|
|
34
|
-
},
|
|
35
|
-
reset: () => {
|
|
36
|
-
state.captures = [];
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
};
|
|
40
|
-
/**
|
|
41
|
-
* Build a proof's runtime layer: the scene's closed wiring with the capture sink
|
|
42
|
-
* merged in, so `Ui`'s `serviceOption(CaptureSink)` finds it and records each
|
|
43
|
-
* render (absent in production, the same layer renders to React). The scene's
|
|
44
|
-
* `provide` is typed to the host-read subset (`MountedServices`); a proof also
|
|
45
|
-
* resolves slot-binding tags (`CompositionClass`), which the same closed layer
|
|
46
|
-
* supplies at runtime — restate that broader `RuntimeServices` surface here. This
|
|
47
|
-
* is the one erasure boundary, the same seam the react host crosses when it reads
|
|
48
|
-
* a slot tag with the requirement erased.
|
|
49
|
-
*/
|
|
50
|
-
const proofLayer = (scene, sink) => {
|
|
51
|
-
const sceneLayer = scene.provide.reduce((a, b) => Layer.merge(a, b));
|
|
52
|
-
return Layer.provideMerge(sceneLayer, Layer.succeed(CaptureSink, sink.api));
|
|
53
|
-
};
|
|
54
|
-
/**
|
|
55
|
-
* Walk a rendered node tree and invoke any slot components it contains (JSX
|
|
56
|
-
* defers them to the host; headless we drive them ourselves), enqueuing the
|
|
57
|
-
* child each stands for. Slot components are matched by identity, so this never
|
|
58
|
-
* calls — and never needs hooks from — ordinary components.
|
|
59
|
-
*/
|
|
60
|
-
const drive = (node, enqueueBy) => {
|
|
61
|
-
if (Array.isArray(node)) {
|
|
62
|
-
for (const child of node)
|
|
63
|
-
drive(child, enqueueBy);
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
if (!isValidElement(node))
|
|
67
|
-
return;
|
|
68
|
-
if (node.type instanceof Function) {
|
|
69
|
-
const enqueue = enqueueBy.get(node.type);
|
|
70
|
-
if (enqueue !== undefined) {
|
|
71
|
-
enqueue(node.props);
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
drive(node.props.children, enqueueBy);
|
|
76
|
-
};
|
|
77
|
-
const makeFacade = (runtime, root, sink) => {
|
|
78
|
-
// Slot bindings (`provide(slot, composition)`) are static, so resolve the
|
|
79
|
-
// whole child tree once, up front — keeping `renderTree` and slot navigation
|
|
80
|
-
// synchronous (no nested runtime drive).
|
|
81
|
-
const bindings = new Map();
|
|
82
|
-
// A slot's child is a plain composition or a `FeatureBinding`. A proof drives the
|
|
83
|
-
// composition the feature mounts; for a `default` feature that composition's logic
|
|
84
|
-
// is already live (its eager `.live` was merged into the scene by `provide`), so
|
|
85
|
-
// unwrapping is all that's needed. (Driving a `lazy` feature — load gap +
|
|
86
|
-
// placeholders — is the proof host's Part B increment; until then a scene wires
|
|
87
|
-
// features as `default`, the eagerly-resolvable form.)
|
|
88
|
-
const childComposition = (child) => isFeatureBinding(child) ? child.composition : child;
|
|
89
|
-
const collect = (comp) => Effect.gen(function* () {
|
|
90
|
-
for (const slotClass of Object.values(comp.manifest.slots ?? {})) {
|
|
91
|
-
if (bindings.has(slotClass))
|
|
92
|
-
continue;
|
|
93
|
-
const child = childComposition(yield* slotClass.tag);
|
|
94
|
-
bindings.set(slotClass, child);
|
|
95
|
-
yield* collect(child);
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
runtime.runSync(collect(root));
|
|
99
|
-
// One breadth-first render of the whole tree. Each view reports its
|
|
100
|
-
// `(props, events)` to the sink; each slot it renders enqueues a child (built
|
|
101
|
-
// on the next level), so a single sweep renders everything.
|
|
102
|
-
const renderLevel = (frontier) => Effect.gen(function* () {
|
|
103
|
-
if (frontier.length === 0)
|
|
104
|
-
return;
|
|
105
|
-
const next = [];
|
|
106
|
-
for (const { comp, props } of frontier) {
|
|
107
|
-
const service = yield* comp.tag;
|
|
108
|
-
// A slot renders to a deferred component (JSX `<slots.Item/>`); map each
|
|
109
|
-
// back to the child it stands for so the tree walk can enqueue it.
|
|
110
|
-
const enqueueBy = new Map();
|
|
111
|
-
const slots = {
|
|
112
|
-
slot: (name) => {
|
|
113
|
-
const slotClass = comp.manifest.slots?.[name];
|
|
114
|
-
const child = slotClass && bindings.get(slotClass);
|
|
115
|
-
const component = () => null;
|
|
116
|
-
if (child)
|
|
117
|
-
enqueueBy.set(component, (childProps) => next.push({ comp: child, props: childProps }));
|
|
118
|
-
return component;
|
|
119
|
-
},
|
|
120
|
-
};
|
|
121
|
-
const env = { props, tracker: { add: () => { } }, slots };
|
|
122
|
-
const node = yield* Composition.render(service, env);
|
|
123
|
-
drive(node, enqueueBy);
|
|
124
|
-
}
|
|
125
|
-
yield* renderLevel(next);
|
|
126
|
-
});
|
|
127
|
-
const renderTree = Effect.gen(function* () {
|
|
128
|
-
sink.reset();
|
|
129
|
-
yield* renderLevel([{ comp: root, props: {} }]);
|
|
130
|
-
});
|
|
131
|
-
const capturesFor = (name) => sink.captures.filter((capture) => capture.name === name);
|
|
132
|
-
// A cheap fingerprint of the rendered tree; when two successive renders match,
|
|
133
|
-
// the engine has stopped producing new state and the read is safe.
|
|
134
|
-
const fingerprint = () => JSON.stringify(sink.captures.map((capture) => [capture.name, capture.props]));
|
|
135
|
-
// Re-render until the tree is stable for two consecutive renders, or give up.
|
|
136
|
-
const settleFrom = (previous, remaining) => Effect.gen(function* () {
|
|
137
|
-
if (remaining === 0)
|
|
138
|
-
return;
|
|
139
|
-
yield* settleDrain;
|
|
140
|
-
yield* Effect.sleep(SETTLE_STEP);
|
|
141
|
-
yield* renderTree;
|
|
142
|
-
const current = fingerprint();
|
|
143
|
-
if (current === previous)
|
|
144
|
-
return;
|
|
145
|
-
yield* settleFrom(current, remaining - 1);
|
|
146
|
-
});
|
|
147
|
-
const settle = Effect.gen(function* () {
|
|
148
|
-
yield* settleDrain;
|
|
149
|
-
yield* renderTree;
|
|
150
|
-
yield* settleFrom(fingerprint(), SETTLE_MAX_RENDERS);
|
|
151
|
-
});
|
|
152
|
-
const triggerOf = (name, index, event) => {
|
|
153
|
-
const trigger = capturesFor(name)[index]?.events[event];
|
|
154
|
-
if (trigger === undefined) {
|
|
155
|
-
throw new UnknownAction({ composition: name, action: event, rendered: capturesFor(name).length });
|
|
156
|
-
}
|
|
157
|
-
return trigger;
|
|
158
|
-
};
|
|
159
|
-
const nodeFacade = (name, index, comp) => ({
|
|
160
|
-
props: Effect.map(renderTree, () => capturesFor(name)[index]?.props),
|
|
161
|
-
// `keyed` resolves event/slot names at runtime; cast the string-keyed proxy
|
|
162
|
-
// to the contract-typed surface. This is the one reflection boundary, the
|
|
163
|
-
// same seam as `definitionClass` — every name the proxy serves is a real
|
|
164
|
-
// contract member, so the cast is sound.
|
|
165
|
-
actions: keyed((event) => (payload) => renderTree.pipe(Effect.flatMap(() => Effect.sync(() => triggerOf(name, index, event)(payload))), Effect.flatMap(() => settle))),
|
|
166
|
-
slots: keyed((slotName) => slotFacade(comp, slotName)),
|
|
167
|
-
frame: settle,
|
|
168
|
-
});
|
|
169
|
-
const slotFacade = (parent, slotName) => {
|
|
170
|
-
const slotClass = parent.manifest.slots?.[slotName];
|
|
171
|
-
const child = slotClass && bindings.get(slotClass);
|
|
172
|
-
if (child === undefined) {
|
|
173
|
-
throw new UnknownSlot({ parent: uiNameOf(parent), slot: slotName });
|
|
174
|
-
}
|
|
175
|
-
const childName = uiNameOf(child);
|
|
176
|
-
const at = (index) => Effect.as(renderTree, nodeFacade(childName, index, child));
|
|
177
|
-
const first = nodeFacade(childName, 0, child);
|
|
178
|
-
return {
|
|
179
|
-
first: at(0),
|
|
180
|
-
at,
|
|
181
|
-
all: Effect.map(renderTree, () => capturesFor(childName).map((_capture, index) => nodeFacade(childName, index, child))),
|
|
182
|
-
// Used directly, a slot behaves as its first instance.
|
|
183
|
-
props: first.props,
|
|
184
|
-
actions: first.actions,
|
|
185
|
-
slots: first.slots,
|
|
186
|
-
frame: first.frame,
|
|
187
|
-
};
|
|
188
|
-
};
|
|
189
|
-
return { facade: nodeFacade(uiNameOf(root), 0, root), settle };
|
|
190
|
-
};
|
|
191
|
-
/**
|
|
192
|
-
* Run one proof against a fresh runtime, returning its pass/fail result. Each
|
|
193
|
-
* proof gets its own isolated environment, so nothing leaks between proofs. Boots
|
|
194
|
-
* the scene as the host would, settles, then runs the proof body to completion.
|
|
195
|
-
*/
|
|
196
|
-
export const executeProof = async (proof) => {
|
|
197
|
-
const sink = makeSink();
|
|
198
|
-
const runtime = ManagedRuntime.make(proofLayer(proof.scene, sink));
|
|
199
|
-
try {
|
|
200
|
-
const { facade, settle } = makeFacade(runtime, proof.scene.composition, sink);
|
|
201
|
-
await runtime.runPromise(Effect.forEach(proof.scene.boot ?? [], (event) => publish('High', event)).pipe(Effect.flatMap(() => settle)));
|
|
202
|
-
await runtime.runPromise(Effect.gen(() => proof.body(facade)));
|
|
203
|
-
return { requirement: proof.requirement.manifest.statement, ok: true };
|
|
204
|
-
}
|
|
205
|
-
catch (error) {
|
|
206
|
-
return {
|
|
207
|
-
requirement: proof.requirement.manifest.statement,
|
|
208
|
-
ok: false,
|
|
209
|
-
error: error instanceof Error ? error.message : String(error),
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
finally {
|
|
213
|
-
await runtime.dispose();
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
|
-
/**
|
|
217
|
-
* Drive one proof a step at a time, recording a `StepFrame` after each yielded
|
|
218
|
-
* effect settles. Reuses the same makeFacade runtime/facade/settle as
|
|
219
|
-
* `executeProof`, but instead of handing the body to `Effect.gen` (which runs it
|
|
220
|
-
* to completion), it pumps the generator by hand — `gen.next(value)` yields the
|
|
221
|
-
* next effect, we run it on the live runtime, snapshot the sink, and feed the
|
|
222
|
-
* result back. So the editor gets the per-step timeline with no change to the
|
|
223
|
-
* proof authoring API.
|
|
224
|
-
*/
|
|
225
|
-
export const driveProof = async (proof) => {
|
|
226
|
-
const sink = makeSink();
|
|
227
|
-
const runtime = ManagedRuntime.make(proofLayer(proof.scene, sink));
|
|
228
|
-
const frames = [];
|
|
229
|
-
const statement = proof.requirement.manifest.statement;
|
|
230
|
-
try {
|
|
231
|
-
const { facade, settle } = makeFacade(runtime, proof.scene.composition, sink);
|
|
232
|
-
await runtime.runPromise(Effect.forEach(proof.scene.boot ?? [], (event) => publish('High', event)).pipe(Effect.flatMap(() => settle)));
|
|
233
|
-
frames.push({ index: 0, captures: [...sink.captures] });
|
|
234
|
-
const generator = proof.body(facade);
|
|
235
|
-
// Pump the generator: run each yielded effect on the runtime, snapshot, recur.
|
|
236
|
-
const pump = async (input, index) => {
|
|
237
|
-
const step = generator.next(input);
|
|
238
|
-
if (step.done === true)
|
|
239
|
-
return;
|
|
240
|
-
const value = await runtime.runPromise(yieldWrapGet(step.value));
|
|
241
|
-
frames.push({ index, captures: [...sink.captures] });
|
|
242
|
-
await pump(value, index + 1);
|
|
243
|
-
};
|
|
244
|
-
await pump(undefined, 1);
|
|
245
|
-
return { requirement: statement, frames, ok: true };
|
|
246
|
-
}
|
|
247
|
-
catch (error) {
|
|
248
|
-
return {
|
|
249
|
-
requirement: statement,
|
|
250
|
-
frames,
|
|
251
|
-
ok: false,
|
|
252
|
-
error: error instanceof Error ? error.message : String(error),
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
finally {
|
|
256
|
-
await runtime.dispose();
|
|
257
|
-
}
|
|
258
|
-
};
|
|
259
|
-
//# sourceMappingURL=engine.js.map
|
package/dist/engine.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { type Cause } from 'effect';
|
|
2
|
-
/**
|
|
3
|
-
* Tagged errors for the proof harness. A failed assertion or a malformed proof
|
|
4
|
-
* navigation throws one of these — tagged and structured, never a bare `Error` —
|
|
5
|
-
* so a runner can distinguish an assertion failure from a harness misuse.
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* The constructor shape `Data.TaggedError(tag)<A>` produces, named so the
|
|
9
|
-
* generated `.d.ts` can describe the `extends` base under `isolatedDeclarations`
|
|
10
|
-
* (which forbids an inferred expression in an extends clause).
|
|
11
|
-
*/
|
|
12
|
-
type TaggedErrorClass<Tag extends string, A extends Record<string, unknown>> = new (args: A) => Cause.YieldableError & {
|
|
13
|
-
readonly _tag: Tag;
|
|
14
|
-
} & Readonly<A>;
|
|
15
|
-
declare const AssertionFailedBase: TaggedErrorClass<'reform-proof/AssertionFailed', {
|
|
16
|
-
readonly detail: string;
|
|
17
|
-
}>;
|
|
18
|
-
/** An `expect(...)` matcher did not hold. */
|
|
19
|
-
export declare class AssertionFailed extends AssertionFailedBase {
|
|
20
|
-
get message(): string;
|
|
21
|
-
}
|
|
22
|
-
declare const UnknownActionBase: TaggedErrorClass<'reform-proof/UnknownAction', {
|
|
23
|
-
readonly composition: string;
|
|
24
|
-
readonly action: string;
|
|
25
|
-
readonly rendered: number;
|
|
26
|
-
}>;
|
|
27
|
-
/** A proof referenced an action the rendered composition never exposed. */
|
|
28
|
-
export declare class UnknownAction extends UnknownActionBase {
|
|
29
|
-
get message(): string;
|
|
30
|
-
}
|
|
31
|
-
declare const UnknownSlotBase: TaggedErrorClass<'reform-proof/UnknownSlot', {
|
|
32
|
-
readonly parent: string;
|
|
33
|
-
readonly slot: string;
|
|
34
|
-
}>;
|
|
35
|
-
/** A proof navigated into a slot the parent composition does not declare. */
|
|
36
|
-
export declare class UnknownSlot extends UnknownSlotBase {
|
|
37
|
-
get message(): string;
|
|
38
|
-
}
|
|
39
|
-
export {};
|
|
40
|
-
//# sourceMappingURL=errors.d.ts.map
|
package/dist/errors.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAQ,MAAM,QAAQ,CAAA;AAEzC;;;;GAIG;AAEH;;;;GAIG;AACH,KAAK,gBAAgB,CAAC,GAAG,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,KAC7E,IAAI,EAAE,CAAC,KACJ,KAAK,CAAC,cAAc,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAA;CAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;AAEhE,QAAA,MAAM,mBAAmB,EAAE,gBAAgB,CACzC,8BAA8B,EAC9B;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CACoD,CAAA;AAEjF,6CAA6C;AAC7C,qBAAa,eAAgB,SAAQ,mBAAmB;IACtD,IAAa,OAAO,IAAI,MAAM,CAE7B;CACF;AAED,QAAA,MAAM,iBAAiB,EAAE,gBAAgB,CACvC,4BAA4B,EAC5B;IAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAKpF,CAAA;AAEF,2EAA2E;AAC3E,qBAAa,aAAc,SAAQ,iBAAiB;IAClD,IAAa,OAAO,IAAI,MAAM,CAE7B;CACF;AAED,QAAA,MAAM,eAAe,EAAE,gBAAgB,CACrC,0BAA0B,EAC1B;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CACgD,CAAA;AAEpG,6EAA6E;AAC7E,qBAAa,WAAY,SAAQ,eAAe;IAC9C,IAAa,OAAO,IAAI,MAAM,CAE7B;CACF"}
|
package/dist/errors.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { Data } from 'effect';
|
|
2
|
-
const AssertionFailedBase = (Data.TaggedError('reform-proof/AssertionFailed'));
|
|
3
|
-
/** An `expect(...)` matcher did not hold. */
|
|
4
|
-
export class AssertionFailed extends AssertionFailedBase {
|
|
5
|
-
get message() {
|
|
6
|
-
return `reform-proof: assertion failed — ${this.detail}`;
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
const UnknownActionBase = (Data.TaggedError('reform-proof/UnknownAction'));
|
|
10
|
-
/** A proof referenced an action the rendered composition never exposed. */
|
|
11
|
-
export class UnknownAction extends UnknownActionBase {
|
|
12
|
-
get message() {
|
|
13
|
-
return `reform-proof: '${this.composition}' has no action '${this.action}' (rendered ${this.rendered} instance(s))`;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
const UnknownSlotBase = (Data.TaggedError('reform-proof/UnknownSlot'));
|
|
17
|
-
/** A proof navigated into a slot the parent composition does not declare. */
|
|
18
|
-
export class UnknownSlot extends UnknownSlotBase {
|
|
19
|
-
get message() {
|
|
20
|
-
return `reform-proof: '${this.parent}' has no slot '${this.slot}'`;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
//# sourceMappingURL=errors.js.map
|
package/dist/errors.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,IAAI,EAAE,MAAM,QAAQ,CAAA;AAiBzC,MAAM,mBAAmB,GAGrB,CAAA,IAAI,CAAC,WAAW,CAAC,8BAA8B,CAA8B,CAAA,CAAA;AAEjF,6CAA6C;AAC7C,MAAM,OAAO,eAAgB,SAAQ,mBAAmB;IACtD,IAAa,OAAO;QAClB,OAAO,oCAAoC,IAAI,CAAC,MAAM,EAAE,CAAA;IAC1D,CAAC;CACF;AAED,MAAM,iBAAiB,GAGnB,CAAA,IAAI,CAAC,WAAW,CAAC,4BAA4B,CAI/C,CAAA,CAAA;AAEF,2EAA2E;AAC3E,MAAM,OAAO,aAAc,SAAQ,iBAAiB;IAClD,IAAa,OAAO;QAClB,OAAO,kBAAkB,IAAI,CAAC,WAAW,oBAAoB,IAAI,CAAC,MAAM,eAAe,IAAI,CAAC,QAAQ,eAAe,CAAA;IACrH,CAAC;CACF;AAED,MAAM,eAAe,GAGjB,CAAA,IAAI,CAAC,WAAW,CAAC,0BAA0B,CAAqD,CAAA,CAAA;AAEpG,6EAA6E;AAC7E,MAAM,OAAO,WAAY,SAAQ,eAAe;IAC9C,IAAa,OAAO;QAClB,OAAO,kBAAkB,IAAI,CAAC,MAAM,kBAAkB,IAAI,CAAC,IAAI,GAAG,CAAA;IACpE,CAAC;CACF"}
|