doxum 0.1.40 → 0.1.42
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 +36 -4
- package/dist/advanced.cjs +1 -1
- package/dist/advanced.d.cts +1 -1
- package/dist/advanced.d.ts +1 -1
- package/dist/advanced.js +1 -1
- package/dist/{contract-CNR6BS75.d.cts → contract-DovG1Yp-.d.cts} +2 -1
- package/dist/{contract-COgxO5sv.d.ts → contract-PqdXNaP8.d.ts} +2 -1
- package/dist/{dependency-DzxXGYe1.d.ts → dependency-BYiwTiBj.d.ts} +1 -1
- package/dist/{dependency-Cbf3C8eJ.d.cts → dependency-D0bo_xe_.d.cts} +1 -1
- package/dist/{driver-B7RR-VfX.js → driver-B7Hu6D0u.js} +15 -1
- package/dist/{driver-CN3dGxQI.cjs → driver-i4G4iVX0.cjs} +20 -0
- package/dist/index.cjs +257 -114
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +257 -114
- package/dist/local-sync.cjs +2 -5
- package/dist/local-sync.d.cts +1 -1
- package/dist/local-sync.d.ts +1 -1
- package/dist/local-sync.js +2 -5
- package/dist/react.cjs +38 -3
- package/dist/react.d.cts +19 -3
- package/dist/react.d.ts +19 -3
- package/dist/react.js +38 -4
- package/dist/{transform-8xXf0OKB.cjs → transform-BPh55GWO.cjs} +82 -48
- package/dist/{transform--WCn6_v0.js → transform-BvDYPUMm.js} +82 -48
- package/package.json +1 -1
- package/skills/doxum-runtime/references/integrations.md +38 -7
- package/skills/doxum-runtime/references/invariants.md +23 -0
- package/skills/doxum-runtime/references/projections.md +22 -0
- package/skills/doxum-runtime/references/public-api.md +27 -8
|
@@ -88,16 +88,47 @@ React consumes Doxum through `doxum/react` only. Do not duplicate Runtime subscr
|
|
|
88
88
|
### Projection provider
|
|
89
89
|
|
|
90
90
|
```tsx
|
|
91
|
-
|
|
91
|
+
// runtime is created and disposed by the application/service outside rendering.
|
|
92
|
+
function ApplicationView({ runtime }: { runtime: ProjectionRuntime }) {
|
|
93
|
+
return (
|
|
94
|
+
<ProjectionProvider runtime={runtime} fallback={null}>
|
|
95
|
+
<App />
|
|
96
|
+
</ProjectionProvider>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`runtime` mode owns a child scope, not the supplied Runtime. Scope acquisition happens
|
|
102
|
+
after commit; first render and SSR show `fallback` (default `null`). Every Effect setup
|
|
103
|
+
uses a fresh scope, including StrictMode replay. A runtime change replaces the scope
|
|
104
|
+
and remounts the child subtree with fresh local definitions/state. Abandoned renders
|
|
105
|
+
acquire no scope. Do not create a disposable scope or Runtime in `useMemo` and rely on
|
|
106
|
+
an Effect to clean up that render-created resource.
|
|
92
107
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
)
|
|
108
|
+
For synchronous SSR or externally owned lifetimes, inject the owner explicitly:
|
|
109
|
+
`<ProjectionProvider value={runtimeOrScope}>`. This mode never disposes the supplied
|
|
110
|
+
owner and takes no fallback. Never combine `runtime` and `value`.
|
|
111
|
+
|
|
112
|
+
`useProjectionScope()` returns an existing context scope. It works inside a managed
|
|
113
|
+
Provider or `value={scope}`, and throws for a missing Provider or `value={runtime}`.
|
|
114
|
+
It does not accept a Runtime argument or allocate another scope. To declare local
|
|
115
|
+
state, memoize a definition owned by the current scope, with the scope as a dependency:
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
const scope = useProjectionScope();
|
|
119
|
+
const mode = useMemo(() => scope.own(input('all')), [scope]);
|
|
120
|
+
const [value, update] = useInput(mode);
|
|
98
121
|
```
|
|
99
122
|
|
|
100
|
-
|
|
123
|
+
A scope does not adopt root projections merely because a component reads them. Use
|
|
124
|
+
`scope.onDispose` for synchronous finalization that needs projection reads; do not rely
|
|
125
|
+
on React parent/child cleanup order. Cleanup may read and unsubscribe, but may not write,
|
|
126
|
+
batch, subscribe or register more resources. Perform domain commands before disposal.
|
|
127
|
+
Registration returns an idempotent cancellation function suitable for Effect cleanup.
|
|
128
|
+
If work must run on scope shutdown, leave its registration active until that shutdown;
|
|
129
|
+
cancelling it in an earlier component cleanup intentionally prevents it from running.
|
|
130
|
+
Parent Runtime disposal ends its scopes; subsequent React cleanup and unsubscribe are
|
|
131
|
+
safe no-ops. Ordinary reads after disposal still throw.
|
|
101
132
|
|
|
102
133
|
### Reading projections
|
|
103
134
|
|
|
@@ -61,6 +61,29 @@ This file is maintainer-only. Application/library consumers should use [Public A
|
|
|
61
61
|
initialization failure releases already-created projection resources and preserves the
|
|
62
62
|
original error. Document dirty/pending state has one write owner; structural
|
|
63
63
|
materialization only reads it.
|
|
64
|
+
Collection storage installs an accepted entry batch through one persistent index
|
|
65
|
+
application. The index owns AVL batch merge/balance; storage owns the current Map
|
|
66
|
+
and formal ids; output sealing owns equality and publication. Share untouched
|
|
67
|
+
subtrees and copy the affected path union once for pure value updates. Batch
|
|
68
|
+
structural changes require height-aware join/concat, not just single-edit repair.
|
|
69
|
+
Preserve lazy index creation, durable old snapshots, zero index work for pure
|
|
70
|
+
reorder, and per-install versions for demanded reads inside a Runtime batch.
|
|
71
|
+
Sorting changed keys is internal lookup work, never formal order. Count node
|
|
72
|
+
allocations and sorting separately from selector calls; this is not an O(delta)
|
|
73
|
+
guarantee for all collection maintenance.
|
|
74
|
+
Scheduler owns Runtime active/closing/disposed state and cleanup/read/command
|
|
75
|
+
admission; scope owns only its status and local resource membership. Cleanup stacks
|
|
76
|
+
are cancellable and LIFO, child callbacks precede parent callbacks, and graph teardown
|
|
77
|
+
starts only after all callbacks. Cleanup permits demanded/lazy reads but no new public
|
|
78
|
+
resources or writes. Restore the caller phase after nested computation and balance
|
|
79
|
+
document locks for connections registered/detached while a lock is held. Release
|
|
80
|
+
dependents before dependencies; close all resources even after failures. Disposed
|
|
81
|
+
reads still throw; only repeated dispose/unsubscribe/cancellation are no-ops.
|
|
82
|
+
Simple listener sets share subscription.ts registration identity/removal semantics;
|
|
83
|
+
notification snapshot order/error policy remains with each notification owner.
|
|
84
|
+
React managed scope acquisition happens after commit, never in render/useMemo;
|
|
85
|
+
borrowed owner injection never takes disposal ownership. Fresh Effect setups own
|
|
86
|
+
fresh scopes/subtrees. Keep the managed first-render/SSR fallback explicit.
|
|
64
87
|
10. Local sync uses Web Lock leadership and contiguous durable sequence. Writes precede
|
|
65
88
|
asynchronous persistence. Version 5 / format 3 rejects old databases without editing
|
|
66
89
|
them. External replace and remote apply are prohibited while attached.
|
|
@@ -459,6 +459,28 @@ Rules:
|
|
|
459
459
|
- the same definition cannot belong to two scopes;
|
|
460
460
|
- `scope.items` has the same membership/readable semantics as `runtime.items` and ends with scope disposal.
|
|
461
461
|
|
|
462
|
+
`scope.onDispose(cleanup)` and `runtime.onDispose(cleanup)` register synchronous LIFO
|
|
463
|
+
callbacks; the returned function cancels that one registration without executing it.
|
|
464
|
+
Runtime shutdown runs scope callbacks in reverse creation order, then root callbacks,
|
|
465
|
+
while the graph remains readable. All callbacks finish before teardown. Scope-only
|
|
466
|
+
disposal leaves root materialization alive. Read/Readable.current retain normal demand,
|
|
467
|
+
lazy initialization, ownership and fault semantics during cleanup; commands, new
|
|
468
|
+
subscriptions/resources and cleanup registrations are rejected. Connected document
|
|
469
|
+
writes are locked. Cleanup does not flush projection notifications. Business writes
|
|
470
|
+
belong before disposal. Existing source unsubscribe/processor release are teardown,
|
|
471
|
+
not read-capable cleanup callbacks.
|
|
472
|
+
|
|
473
|
+
All callbacks/releases are attempted even on failure; errors escape after terminal
|
|
474
|
+
closure. `dispose` can be called repeatedly, after an earlier cleanup failure, or on a
|
|
475
|
+
scope already ended by its parent. Unsubscribe and cleanup-registration cancellation
|
|
476
|
+
are idempotent. Each subscription owns a distinct registration even if callbacks are
|
|
477
|
+
identical; old unsubscribe functions cannot detach a newer registration. Normal reads,
|
|
478
|
+
commands, resource creation and existing Readable access still throw after disposal.
|
|
479
|
+
|
|
480
|
+
For React, use the managed `ProjectionProvider runtime={runtime}`; acquire the current
|
|
481
|
+
scope with `useProjectionScope()`. Read [React ownership and SSR](integrations.md#projection-provider)
|
|
482
|
+
before choosing managed versus externally owned Provider mode.
|
|
483
|
+
|
|
462
484
|
## Batching
|
|
463
485
|
|
|
464
486
|
```ts
|
|
@@ -420,6 +420,7 @@ type ProjectionRuntime = {
|
|
|
420
420
|
update<K,V,R>(input: CollectionInput<K,V>, run: (draft: CollectionInputDraft<K,V>) => Synchronous<R>): void;
|
|
421
421
|
batch<T>(run: () => Synchronous<T>, options?: { cause?: unknown }): T;
|
|
422
422
|
scope(): ProjectionScope;
|
|
423
|
+
onDispose<R>(cleanup: () => Synchronous<R>): Unsubscribe;
|
|
423
424
|
dispose(): void;
|
|
424
425
|
};
|
|
425
426
|
|
|
@@ -600,25 +601,36 @@ incremental.group(
|
|
|
600
601
|
|
|
601
602
|
Every declared output must be returned from the static output tree exactly once.
|
|
602
603
|
|
|
604
|
+
Runtime/scope `onDispose` registers synchronous, cancellable LIFO cleanup. Child scope
|
|
605
|
+
callbacks precede parent Runtime callbacks; projections remain readable until all
|
|
606
|
+
callbacks finish. Cleanup rejects commands/new registrations. Failures do not interrupt
|
|
607
|
+
remaining teardown and are thrown only after closure. `dispose` and unsubscribe are
|
|
608
|
+
idempotent; all normal projection access still throws after disposal. See
|
|
609
|
+
[cleanup and scope ownership](projections.md#projectionscope).
|
|
610
|
+
|
|
603
611
|
## `doxum/react`
|
|
604
612
|
|
|
605
613
|
### Public symbol inventory
|
|
606
614
|
|
|
607
615
|
<!-- exports:doxum/react:start -->
|
|
608
616
|
|
|
609
|
-
| Public export
|
|
610
|
-
|
|
|
611
|
-
| `ProjectionProvider`
|
|
612
|
-
| `
|
|
613
|
-
| `
|
|
614
|
-
| `
|
|
615
|
-
| `
|
|
616
|
-
| `
|
|
617
|
+
| Public export | Role |
|
|
618
|
+
| ------------------------- | --------------------------------------------------------- |
|
|
619
|
+
| `ProjectionProvider` | Manage a scope from a Runtime or borrow an external owner |
|
|
620
|
+
| `ProjectionProviderProps` | Mutually exclusive managed/borrowed Provider props |
|
|
621
|
+
| `useProjectionScope` | Read the current scope from context; never allocate one |
|
|
622
|
+
| `useDocumentSelector` | React adapter for Core document `select` |
|
|
623
|
+
| `useReadable` | Subscribe to any Doxum `Readable` |
|
|
624
|
+
| `useHistory` | Read history state and expose undo/redo callbacks |
|
|
625
|
+
| `useProjection` | Read projection or projection selector |
|
|
626
|
+
| `useInput` | Read/update scalar or collection projection input |
|
|
617
627
|
|
|
618
628
|
<!-- exports:doxum/react:end -->
|
|
619
629
|
|
|
620
630
|
```ts
|
|
631
|
+
<ProjectionProvider runtime={runtime} fallback={null}>...</ProjectionProvider>
|
|
621
632
|
<ProjectionProvider value={runtimeOrScope}>...</ProjectionProvider>
|
|
633
|
+
useProjectionScope(): ProjectionScope
|
|
622
634
|
|
|
623
635
|
useProjection(projection): T
|
|
624
636
|
useProjection(projection, selector, equality?): R
|
|
@@ -629,6 +641,13 @@ useReadable(readable): T
|
|
|
629
641
|
useHistory(history): HistoryState & { undo(): OperationResult<C>; redo(): OperationResult<C> }
|
|
630
642
|
```
|
|
631
643
|
|
|
644
|
+
Managed `runtime` mode owns only a child scope, acquired after commit. Initial render
|
|
645
|
+
and SSR use `fallback` (default `null`); StrictMode setup replay and runtime replacement
|
|
646
|
+
create a fresh scope generation and remount its subtree. Borrowed `value` mode injects
|
|
647
|
+
synchronously and never disposes the supplied owner. Use it for synchronous SSR with
|
|
648
|
+
request-owned resources. `useProjectionScope()` requires a scope in context, including
|
|
649
|
+
an explicitly injected scope; an injected root Runtime does not implicitly create one.
|
|
650
|
+
|
|
632
651
|
## `doxum/local-sync`
|
|
633
652
|
|
|
634
653
|
### Public symbol inventory
|