doxum 0.1.17 → 0.1.19

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 CHANGED
@@ -232,12 +232,39 @@ runtime.batch({ cause: { action: 'refresh' } }, () => {
232
232
  stop();
233
233
  ```
234
234
 
235
- Projection declarations are lazy and reusable. The only Runtime operations are
236
- `get`, `readable`, `set`, `batch` and `dispose`; materialization, incremental
237
- state, publication and recovery stay inside the Runtime. Collection values are
235
+ Root projection declarations are lazy and reusable; scoped declarations are
236
+ lazy but tied to their scope. The Runtime owns `get`,
237
+ `readable`, scalar `set`, keyed `update`, `batch`, `scope` and `dispose`;
238
+ materialization, incremental state, publication and recovery stay inside that
239
+ one Runtime. Collection values are
238
240
  immutable `ReadonlyMap`-like snapshots, while a `Readable` owns selector
239
241
  tracking, equality and subscription lifecycle.
240
242
 
243
+ Local projections live in the same graph as their parent definitions:
244
+
245
+ ```ts
246
+ const scope = runtime.scope();
247
+ const localFilter = scope.input<'all' | 'open'>('all');
248
+ const localVisible = scope.derive([tasks, localFilter], (tasks, filter) =>
249
+ filter === 'all' ? tasks : new Map([...tasks].filter(([, task]) => !task.done))
250
+ );
251
+ scope.get(localVisible);
252
+ scope.dispose(); // Releases local nodes, state and subscriptions; parent tasks remain.
253
+ ```
254
+
255
+ For Runtime-local keyed state, `input.collection` publishes the same exact
256
+ `CollectionChange` as document collections. One `update` edits one or many keys
257
+ atomically; the enclosing Runtime batch coalesces accepted edits into one net
258
+ change:
259
+
260
+ ```ts
261
+ const overrides = input.collection<string, Task>();
262
+ runtime.update(overrides, draft => {
263
+ draft.set(taskId, task);
264
+ draft.remove(oldTaskId);
265
+ });
266
+ ```
267
+
241
268
  `observe` is the single source boundary for documents, Doxum `Readable` values,
242
269
  and eventful external sources. External sources declare `kind: 'value'` or
243
270
  `kind: 'collection'`; collection invalidation remains keyed internally.
@@ -252,6 +279,24 @@ import { incremental } from 'doxum/advanced';
252
279
  const doubled = incremental.collection([tasks], ({ sources, output }) => {
253
280
  for (const [id, task] of sources[0]) output.set(id, task.value * 2);
254
281
  });
282
+
283
+ const render = incremental.group(
284
+ [tasks],
285
+ define => ({
286
+ node: {
287
+ shell: define.collection<string, { readonly title: string }>(),
288
+ content: define.collection<string, string>(),
289
+ },
290
+ labels: define.collection<string, string>(),
291
+ }),
292
+ ({ sources, outputs }) => {
293
+ for (const [id, task] of sources[0]) {
294
+ outputs.node.shell.set(id, { title: task.title });
295
+ outputs.node.content.set(id, task.title);
296
+ outputs.labels.set(id, task.title);
297
+ }
298
+ }
299
+ );
255
300
  ```
256
301
 
257
302
  Incremental processors receive a dependency-aligned `changes` tuple. Collection
@@ -259,6 +304,12 @@ entries carry `added`/`updated`/`removed` transitions with complete
259
304
  `before`/`after` values, so a processor can patch indexes without rescanning the
260
305
  collection; scalar dependencies use `undefined` and the initial collection build
261
306
  reports `{ kind: 'reset' }`.
307
+ `incremental.group` runs one processor for several named keyed collection outputs.
308
+ Its static nested namespace is only API organization: every leaf is an ordinary
309
+ `Projection`, all leaves publish atomically in one causal settle, and downstream
310
+ processors depend directly on those leaves. A group materializes as a whole when
311
+ any leaf is first read; split groups when outputs do not share computation or
312
+ atomicity requirements. There is no output event bus or per-output runtime.
262
313
 
263
314
  In React, `useProjection(projection)` reads a value and
264
315
  `useProjection(projection, selector, equality?)` tracks keyed reads such as