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
package/README.md
CHANGED
|
@@ -276,8 +276,8 @@ runtime.dispose();
|
|
|
276
276
|
|
|
277
277
|
The stable vocabulary is `read` for a synchronous current value, `select` for a
|
|
278
278
|
`Readable`, and `observe` for declaring a lazy source boundary. `ProjectionRuntime`
|
|
279
|
-
exposes `read`, `select`, `items`, `update`, `batch`, `scope` and `dispose`.
|
|
280
|
-
`ProjectionScope` mirrors `read`, `select`, `items`, `update`, `batch` and `dispose`, plus
|
|
279
|
+
exposes `read`, `select`, `items`, `update`, `batch`, `scope`, `onDispose` and `dispose`.
|
|
280
|
+
`ProjectionScope` mirrors `read`, `select`, `items`, `update`, `batch`, `onDispose` and `dispose`, plus
|
|
281
281
|
`own(definitionOrTree)` for lifecycle ownership of lazy projection definitions.
|
|
282
282
|
|
|
283
283
|
### Commands inside a batch
|
|
@@ -638,8 +638,40 @@ values. Ordinary source resets preserve retained state when one exists. If a pro
|
|
|
638
638
|
faults, the Runtime owns recovery, recreates declared state, and performs a reset
|
|
639
639
|
evaluation. Stateless processors use the same recovery path without a state object.
|
|
640
640
|
|
|
641
|
+
### Projection disposal
|
|
642
|
+
|
|
643
|
+
`runtime.dispose()`, `scope.dispose()` and Doxum unsubscribe functions are idempotent.
|
|
644
|
+
A parent Runtime ends its scopes, so later component cleanup can safely dispose them
|
|
645
|
+
again. Every subscription registration is independent, including registrations with
|
|
646
|
+
the same callback; an old unsubscribe cannot cancel a later subscription.
|
|
647
|
+
|
|
648
|
+
`runtime.onDispose(cleanup)` / `scope.onDispose(cleanup)` register synchronous,
|
|
649
|
+
cancellable callbacks. The returned function unregisters that callback without
|
|
650
|
+
executing it. Owner callbacks run in LIFO order; Runtime shutdown runs child scope
|
|
651
|
+
callbacks before its own while all projections remain readable. Cleanup may read
|
|
652
|
+
current values and unsubscribe, but cannot update, batch, subscribe or register new
|
|
653
|
+
resources. Perform domain writes before disposal. After callbacks, consumers and
|
|
654
|
+
producers are released, then source connections; failures do not prevent remaining
|
|
655
|
+
cleanup, and are thrown after disposal completes. Repeated disposal does not retry
|
|
656
|
+
failed callbacks. Reads, commands and new subscriptions still throw after disposal.
|
|
657
|
+
|
|
641
658
|
### React
|
|
642
659
|
|
|
660
|
+
```tsx
|
|
661
|
+
// runtime is owned by the application/service; this Provider owns only its scope.
|
|
662
|
+
<ProjectionProvider runtime={runtime} fallback={<span>Loading…</span>}>
|
|
663
|
+
<TaskList />
|
|
664
|
+
</ProjectionProvider>
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
Managed Providers acquire a scope after commit and release it on cleanup. StrictMode
|
|
668
|
+
setup replay creates a fresh scope; runtime replacement also remounts the scoped subtree.
|
|
669
|
+
`useProjectionScope()` returns that scope for `scope.own(...)` and `scope.onDispose(...)`.
|
|
670
|
+
The initial render and SSR render `fallback` (default `null`). For synchronous SSR or
|
|
671
|
+
an externally managed lifetime, use `<ProjectionProvider value={runtimeOrScope}>`;
|
|
672
|
+
this mode only injects the owner and never disposes it. The two modes are mutually
|
|
673
|
+
exclusive. Do not create disposable scopes in `useMemo` or revive a disposed scope.
|
|
674
|
+
|
|
643
675
|
```ts
|
|
644
676
|
const task = useProjection(tasks, tasks => tasks.get(taskId), equality);
|
|
645
677
|
const [mode, setMode] = useInput(filter);
|
|
@@ -648,8 +680,8 @@ const [selectedRows, updateSelectedRows] = useInput(selection);
|
|
|
648
680
|
|
|
649
681
|
`useProjection(projection, selector, equality?)` uses the same keyed selector semantics
|
|
650
682
|
as Core. `useInput` handles both scalar `Input<T>` and `CollectionInput<K,V>`; collection
|
|
651
|
-
updates receive a keyed draft callback.
|
|
652
|
-
`
|
|
683
|
+
updates receive a keyed draft callback. Reading a root projection through a managed
|
|
684
|
+
scope does not transfer its ownership; use `scope.own(...)` for local definitions.
|
|
653
685
|
|
|
654
686
|
See [projection contracts](docs/projections.md).
|
|
655
687
|
|
package/dist/advanced.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_transform = require("./transform-
|
|
2
|
+
const require_transform = require("./transform-BPh55GWO.cjs");
|
|
3
3
|
const require_record = require("./record-ChYUi8PP.cjs");
|
|
4
4
|
//#region core/src/projection/advanced.ts
|
|
5
5
|
const resetCollectionChange = Object.freeze({ kind: "reset" });
|
package/dist/advanced.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as ProjectionChange, d as CollectionRead, l as CollectionChange, n as KeyedDependencyValues, o as KeyedProjection, s as Projection, t as KeyedDependencies, u as CollectionDraft } from "./dependency-
|
|
1
|
+
import { c as ProjectionChange, d as CollectionRead, l as CollectionChange, n as KeyedDependencyValues, o as KeyedProjection, s as Projection, t as KeyedDependencies, u as CollectionDraft } from "./dependency-D0bo_xe_.cjs";
|
|
2
2
|
|
|
3
3
|
//#region core/src/projection/collection/change.d.ts
|
|
4
4
|
declare const collectionChange: {
|
package/dist/advanced.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as ProjectionChange, d as CollectionRead, l as CollectionChange, n as KeyedDependencyValues, o as KeyedProjection, s as Projection, t as KeyedDependencies, u as CollectionDraft } from "./dependency-
|
|
1
|
+
import { c as ProjectionChange, d as CollectionRead, l as CollectionChange, n as KeyedDependencyValues, o as KeyedProjection, s as Projection, t as KeyedDependencies, u as CollectionDraft } from "./dependency-BYiwTiBj.js";
|
|
2
2
|
|
|
3
3
|
//#region core/src/projection/collection/change.d.ts
|
|
4
4
|
declare const collectionChange: {
|
package/dist/advanced.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as defineProcessor, S as compileProjectionDependencies, _ as assertSynchronous, r as collectionChange, t as createKeyedTransform, w as collectionView } from "./transform
|
|
1
|
+
import { D as defineProcessor, S as compileProjectionDependencies, _ as assertSynchronous, r as collectionChange, t as createKeyedTransform, w as collectionView } from "./transform-BvDYPUMm.js";
|
|
2
2
|
import { n as isPlainObject } from "./record-B2yRhYsc.js";
|
|
3
3
|
//#region core/src/projection/advanced.ts
|
|
4
4
|
const resetCollectionChange = Object.freeze({ kind: "reset" });
|
|
@@ -509,10 +509,11 @@ type MutationIssue = {
|
|
|
509
509
|
};
|
|
510
510
|
//#endregion
|
|
511
511
|
//#region core/src/readable.d.ts
|
|
512
|
+
/** Ends one registration at most once; safe after owner disposal. */
|
|
512
513
|
type Unsubscribe = () => void;
|
|
513
514
|
type Readable<TValue> = {
|
|
514
515
|
current(): TValue;
|
|
515
|
-
revision(): number;
|
|
516
|
+
revision(): number; /** Each call registers independently, even when the listener function is reused. */
|
|
516
517
|
subscribe(listener: () => void): Unsubscribe;
|
|
517
518
|
};
|
|
518
519
|
//#endregion
|
|
@@ -509,10 +509,11 @@ type MutationIssue = {
|
|
|
509
509
|
};
|
|
510
510
|
//#endregion
|
|
511
511
|
//#region core/src/readable.d.ts
|
|
512
|
+
/** Ends one registration at most once; safe after owner disposal. */
|
|
512
513
|
type Unsubscribe = () => void;
|
|
513
514
|
type Readable<TValue> = {
|
|
514
515
|
current(): TValue;
|
|
515
|
-
revision(): number;
|
|
516
|
+
revision(): number; /** Each call registers independently, even when the listener function is reused. */
|
|
516
517
|
subscribe(listener: () => void): Unsubscribe;
|
|
517
518
|
};
|
|
518
519
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as Unsubscribe, b as CollectionImpact, p as Synchronous } from "./contract-
|
|
1
|
+
import { _ as Unsubscribe, b as CollectionImpact, p as Synchronous } from "./contract-PqdXNaP8.js";
|
|
2
2
|
|
|
3
3
|
//#region core/src/projection/contract.d.ts
|
|
4
4
|
/** The one processor-facing collection transition protocol. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as Unsubscribe, b as CollectionImpact, p as Synchronous } from "./contract-
|
|
1
|
+
import { _ as Unsubscribe, b as CollectionImpact, p as Synchronous } from "./contract-DovG1Yp-.cjs";
|
|
2
2
|
|
|
3
3
|
//#region core/src/projection/contract.d.ts
|
|
4
4
|
/** The one processor-facing collection transition protocol. */
|
|
@@ -208,6 +208,20 @@ var AddressIndex = class {
|
|
|
208
208
|
}
|
|
209
209
|
};
|
|
210
210
|
//#endregion
|
|
211
|
+
//#region core/src/subscription.ts
|
|
212
|
+
/** Each registration owns its identity, independently of callback reuse. */
|
|
213
|
+
const addListener = (listeners, listener, removed) => {
|
|
214
|
+
const entry = (...args) => listener(...args);
|
|
215
|
+
listeners.add(entry);
|
|
216
|
+
let active = true;
|
|
217
|
+
return () => {
|
|
218
|
+
if (!active) return;
|
|
219
|
+
active = false;
|
|
220
|
+
listeners.delete(entry);
|
|
221
|
+
removed?.();
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
//#endregion
|
|
211
225
|
//#region core/src/mutation/changes.ts
|
|
212
226
|
const validated = /* @__PURE__ */ new WeakSet();
|
|
213
227
|
const compareChanges = (a, b) => {
|
|
@@ -399,4 +413,4 @@ const installRuntimeWriteDriver = (runtime, driver) => {
|
|
|
399
413
|
});
|
|
400
414
|
};
|
|
401
415
|
//#endregion
|
|
402
|
-
export { changeCount as a,
|
|
416
|
+
export { validate as _, changeCount as a, addListener as c, fail as d, invalidValue as f, parent as g, is as h, contextOf as i, AddressIndex as l, contains as m, installRuntimeWriteDriver as n, decodeChanges as o, children as p, bindContext as r, sealChanges as s, assertRuntimeWritable as t, MutationRejected as u };
|
|
@@ -208,6 +208,20 @@ var AddressIndex = class {
|
|
|
208
208
|
}
|
|
209
209
|
};
|
|
210
210
|
//#endregion
|
|
211
|
+
//#region core/src/subscription.ts
|
|
212
|
+
/** Each registration owns its identity, independently of callback reuse. */
|
|
213
|
+
const addListener = (listeners, listener, removed) => {
|
|
214
|
+
const entry = (...args) => listener(...args);
|
|
215
|
+
listeners.add(entry);
|
|
216
|
+
let active = true;
|
|
217
|
+
return () => {
|
|
218
|
+
if (!active) return;
|
|
219
|
+
active = false;
|
|
220
|
+
listeners.delete(entry);
|
|
221
|
+
removed?.();
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
//#endregion
|
|
211
225
|
//#region core/src/mutation/changes.ts
|
|
212
226
|
const validated = /* @__PURE__ */ new WeakSet();
|
|
213
227
|
const compareChanges = (a, b) => {
|
|
@@ -411,6 +425,12 @@ Object.defineProperty(exports, "MutationRejected", {
|
|
|
411
425
|
return MutationRejected;
|
|
412
426
|
}
|
|
413
427
|
});
|
|
428
|
+
Object.defineProperty(exports, "addListener", {
|
|
429
|
+
enumerable: true,
|
|
430
|
+
get: function() {
|
|
431
|
+
return addListener;
|
|
432
|
+
}
|
|
433
|
+
});
|
|
414
434
|
Object.defineProperty(exports, "assertRuntimeWritable", {
|
|
415
435
|
enumerable: true,
|
|
416
436
|
get: function() {
|