doxum 0.1.28 → 0.1.30
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 +3 -2
- package/dist/advanced.cjs +1 -1
- package/dist/advanced.js +1 -1
- package/dist/{driver-B5vdPohL.js → driver-B7RR-VfX.js} +31 -12
- package/dist/driver-B7RR-VfX.js.map +1 -0
- package/dist/{driver-BL91gn7_.cjs → driver-CN3dGxQI.cjs} +31 -12
- package/dist/driver-CN3dGxQI.cjs.map +1 -0
- package/dist/index.cjs +206 -133
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +206 -133
- package/dist/index.js.map +1 -1
- package/dist/local-sync.cjs +1 -1
- package/dist/local-sync.js +1 -1
- package/dist/{transform-DUleAsG0.cjs → transform-B6YxfR0R.cjs} +176 -50
- package/dist/transform-B6YxfR0R.cjs.map +1 -0
- package/dist/{transform-B4T3AcJr.js → transform-BQY9I6il.js} +147 -51
- package/dist/transform-BQY9I6il.js.map +1 -0
- package/package.json +3 -2
- package/skills/doxum-runtime/SKILL.md +64 -82
- package/skills/doxum-runtime/agents/openai.yaml +2 -2
- package/skills/doxum-runtime/references/document-runtime.md +370 -0
- package/skills/doxum-runtime/references/integrations.md +215 -0
- package/skills/doxum-runtime/references/{invariants.en.md → invariants.md} +5 -2
- package/skills/doxum-runtime/references/projections.md +467 -0
- package/skills/doxum-runtime/references/public-api.md +623 -0
- package/skills/doxum-runtime/references/recipes.md +493 -0
- package/dist/driver-B5vdPohL.js.map +0 -1
- package/dist/driver-BL91gn7_.cjs.map +0 -1
- package/dist/transform-B4T3AcJr.js.map +0 -1
- package/dist/transform-DUleAsG0.cjs.map +0 -1
- package/skills/doxum-runtime/references/api.en.md +0 -283
- package/skills/doxum-runtime/references/api.zh-CN.md +0 -276
- package/skills/doxum-runtime/references/guide.en.md +0 -138
- package/skills/doxum-runtime/references/guide.zh-CN.md +0 -116
- package/skills/doxum-runtime/references/invariants.zh-CN.md +0 -53
- package/skills/doxum-runtime/references/patterns.en.md +0 -162
- package/skills/doxum-runtime/references/patterns.zh-CN.md +0 -159
- package/skills/doxum-runtime/references/projections.en.md +0 -313
- package/skills/doxum-runtime/references/projections.zh-CN.md +0 -306
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
# Public API Reference
|
|
2
|
-
|
|
3
|
-
Use this as the compact public-contract lookup. For projection lifecycle and examples,
|
|
4
|
-
read [projections](projections.en.md); for modeling choices, read the [guide](guide.en.md).
|
|
5
|
-
|
|
6
|
-
## Package entry points
|
|
7
|
-
|
|
8
|
-
| Package | Purpose |
|
|
9
|
-
| ------------------ | ----------------------------------------------------------------------- |
|
|
10
|
-
| `doxum` | schema, canonical document runtime, reads, history, impact, projections |
|
|
11
|
-
| `doxum/advanced` | retained-state and multi-output projection processors |
|
|
12
|
-
| `doxum/react` | React adapters over Core capabilities |
|
|
13
|
-
| `doxum/local-sync` | IndexedDB persistence and browser leader/follower coordination |
|
|
14
|
-
|
|
15
|
-
## `doxum`
|
|
16
|
-
|
|
17
|
-
### Schema
|
|
18
|
-
|
|
19
|
-
| API | Contract |
|
|
20
|
-
| ------------------------- | ---------------------------------------------------------------------- |
|
|
21
|
-
| `field<T>(validator?)` | Atomic payload. Replace whole; payload interior is readonly. |
|
|
22
|
-
| `optional(schema)` | Optional field/variant/map/list/tree member. |
|
|
23
|
-
| `object(shape)` | Fixed declared members; returns opaque `ObjectSchema<T>`. |
|
|
24
|
-
| `variant(tag, variants)` | Tagged union of object branches. |
|
|
25
|
-
| `map(value, { key }?)` | Dynamic keyed record. |
|
|
26
|
-
| `table(entity, { key }?)` | Ordered keyed object/variant entities stored as `{ ids, byId }`. |
|
|
27
|
-
| `list(field, { keyOf })` | Ordered array with stable string identity. |
|
|
28
|
-
| `tree(field)` | Empty-or-single-root tree; optional field means optional node payload. |
|
|
29
|
-
| `parse(schema, input)` | Validate unknown input and copy schema structure. |
|
|
30
|
-
|
|
31
|
-
Public schema types are `Schema<T>`, `ObjectSchema<T>`, `Infer<S>`, `ReadonlyValue<T>`,
|
|
32
|
-
`Validator<T>`, `SchemaPath<S>`, `PathValueOf<P>`, `DocumentAnchor`,
|
|
33
|
-
`DocumentListConfig<T>`, `DocumentTreeNode<T>` and `DocumentTreeValue<T>`.
|
|
34
|
-
Concrete node representation types are internal.
|
|
35
|
-
`Schema` / `ObjectSchema` are declaration-portable handles; downstream packages can
|
|
36
|
-
export inferred schema constants directly without `ReturnType` wrappers.
|
|
37
|
-
|
|
38
|
-
`Validator<T>` is validation-only. A function validator is a predicate/assertion:
|
|
39
|
-
`true` or `undefined` succeeds, `false` rejects, and an assertion may throw.
|
|
40
|
-
A Standard Schema validator must return the original value by identity on success;
|
|
41
|
-
transformed output is rejected. Validators are synchronous and must not mutate input.
|
|
42
|
-
|
|
43
|
-
Draft collection methods:
|
|
44
|
-
|
|
45
|
-
| Container | Read | Write |
|
|
46
|
-
| --------- | -------------------------------------------- | ---------------------------------------------------------------------------- |
|
|
47
|
-
| map | `get`, `has`, `ids` | `put`, `remove`, `replace(next)` |
|
|
48
|
-
| table | `get`, `has`, `ids` | `create`, `remove`, `move`, `reorder`, `replace(id,value)`, `replace(next)` |
|
|
49
|
-
| list | `get`, `has`, `ids` | `insert`, `remove`, `move`, `reorder`, `replace(key,value)`, `replace(next)` |
|
|
50
|
-
| tree | `rootId`, `get`, `has`, `parent`, `children` | `insert`, `move`, `remove`, `replace(id,value)`, `replace(next)` |
|
|
51
|
-
|
|
52
|
-
`replace(parent, key, value)` replaces one object/variant member with plain `Infer` data.
|
|
53
|
-
`document.replace(value)` is a whole-document reset and remains a separate operation.
|
|
54
|
-
|
|
55
|
-
### Document runtime
|
|
56
|
-
|
|
57
|
-
```ts
|
|
58
|
-
const document = createDocument({ schema, initial, history: { capacity: 100 } });
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
`DocumentRuntime<S>` exposes:
|
|
62
|
-
|
|
63
|
-
- `schema`, `revision()`, `snapshot()` and `readonly()`;
|
|
64
|
-
- `update(run, { source?, history? }?)` for synchronous atomic Draft work;
|
|
65
|
-
- `apply(changes, { expectedRevision, source?: 'local' | 'system', history? })`, or
|
|
66
|
-
`apply(changes, { expectedRevision, source: 'remote' })` for remote replay;
|
|
67
|
-
- `replace(value, { source? }?)` for a whole-document reset;
|
|
68
|
-
- `subscribe(listener)` and `subscribe(path | paths, listener)`;
|
|
69
|
-
- `history.undo()`, `redo()`, `clear()`, `group()`;
|
|
70
|
-
- `dispose()`.
|
|
71
|
-
|
|
72
|
-
`document.readonly()` returns `ReadonlyDocument<S>`, which has only `revision()` and
|
|
73
|
-
document commit/path subscriptions. It is the capability-stripped document boundary.
|
|
74
|
-
|
|
75
|
-
`update` returns `TransactionResult`; `apply`, whole-document `replace`, history travel
|
|
76
|
-
and group cancellation return `OperationResult`. Result status is `committed`,
|
|
77
|
-
`unchanged`, or `rejected`. Throw `TransactionRejected` for expected application
|
|
78
|
-
rejection. Ordinary thrown values roll back and rethrow unchanged.
|
|
79
|
-
|
|
80
|
-
Document errors are `TransactionRejected`, `DocumentReentrancyError` and
|
|
81
|
-
`DocumentDisposedError`. Parsing failures use `ParseError` with `ParseIssue` data.
|
|
82
|
-
|
|
83
|
-
### Reads and subscriptions
|
|
84
|
-
|
|
85
|
-
| API | Contract |
|
|
86
|
-
| --------------------------------------- | --------------------------------------------------------- |
|
|
87
|
-
| `read(document, selector)` | One synchronous borrowed `Read`. |
|
|
88
|
-
| `select(document, selector, equality?)` | Dynamic read-tracked `Readable<TResult>`. |
|
|
89
|
-
| `snapshot(value)` | Export borrowed schema structure as stable readonly data. |
|
|
90
|
-
|
|
91
|
-
`Readable<T>` has `current()`, `revision()` and `subscribe(listener)`.
|
|
92
|
-
`select` rebinds dependencies when selector control flow changes and suppresses
|
|
93
|
-
publication when `equality` reports the selected result unchanged.
|
|
94
|
-
|
|
95
|
-
A commit has `revision`, `source`, `changes`, `impact`. Public change/impact types include
|
|
96
|
-
`ChangeSet`, `Change`, `MemberChange`, `ValueTransition`, `DocumentCommit`,
|
|
97
|
-
`DocumentImpact`, `CollectionImpact`, `MutationIssue` and result/diagnostic types.
|
|
98
|
-
|
|
99
|
-
### Projections
|
|
100
|
-
|
|
101
|
-
```ts
|
|
102
|
-
const mode = input<'all' | 'open'>('all');
|
|
103
|
-
const selection = input.collection<RowId, Selection>();
|
|
104
|
-
const rows = observe(document, path => path.rows);
|
|
105
|
-
const count = derive({ rows }, ({ rows }) => rows.size);
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
| API | Contract |
|
|
109
|
-
| ------------------------------------------------------- | -------------------------------------------------------------------- |
|
|
110
|
-
| `input(initial, equality?)` | Runtime-local writable scalar `Input<T>`. |
|
|
111
|
-
| `input.collection<K,V>(initial?, equality?)` | Runtime-local keyed `CollectionInput<K,V>` with per-entry equality. |
|
|
112
|
-
| `observe(document)` | Whole-document Projection source. |
|
|
113
|
-
| `observe(document, path => ...)` | Schema-path scalar or keyed Projection source. |
|
|
114
|
-
| `observe(readable)` | Adapt a Doxum `Readable`. |
|
|
115
|
-
| `observe(externalSource)` | Adapt exported external value/collection source contracts. |
|
|
116
|
-
| `derive(dependencies, compute, equality?)` | Pure value Projection with named dependencies. |
|
|
117
|
-
| `derive.keyed(driver, select, equality?)` | Preserve driver keys/order and project each entry. |
|
|
118
|
-
| `derive.keyed(driver, deps, select, equality?)` | Keyed projection with named global/dynamic keyed dependencies. |
|
|
119
|
-
| `derive.keyed.keys(source)` | Ordered key array; value-only updates do not publish. |
|
|
120
|
-
| `derive.keyed.values(source)` | Ordered value array following keyed collection order. |
|
|
121
|
-
| `derive.keyed.entries(source)` | Ordered readonly `[key, value]` tuples with stable unchanged tuples. |
|
|
122
|
-
| `derive.keyed.get(source, key, equality?)` | Scalar lookup bound precisely to the selected keyed entry. |
|
|
123
|
-
| `derive.keyed.subset(source, orderedKeys)` | Keyed subset whose membership/order come from ordered keys. |
|
|
124
|
-
| `derive.keyed.filter(source, predicate)` | Keyed subset preserving source values and source-relative order. |
|
|
125
|
-
| `derive.keyed.filter(source, deps, predicate)` | Filter with the standard keyed dependency protocol. |
|
|
126
|
-
| `derive.keyed.compact(source, select, equality?)` | Map entries and omit keys whose selected value is `undefined`. |
|
|
127
|
-
| `derive.keyed.compact(source, deps, select, equality?)` | Compact with standard keyed dependencies. |
|
|
128
|
-
| `derive.keyed.groupBy(source, selector)` | Reverse index from group key to source keys in formal source order. |
|
|
129
|
-
| `derive.keyed.groupBy(source, deps, selector)` | Reverse index with the standard keyed dependency protocol. |
|
|
130
|
-
| `derive.keyed.singleton(source, keyOf, equality?)` | Convert an optional scalar to a zero-or-one keyed projection. |
|
|
131
|
-
|
|
132
|
-
Dynamic keyed dependency syntax is
|
|
133
|
-
`{ source: keyedProjection, key: (driverValue, driverKey) => sourceKey | undefined }`.
|
|
134
|
-
The Runtime owns output-key to source-key bindings and reverse invalidation. This helper
|
|
135
|
-
shape is inferred at the call site; no dedicated public helper type is required.
|
|
136
|
-
Plural lookup uses
|
|
137
|
-
`{ source: keyedProjection, keys: (driverValue, driverKey) => readonly sourceKey[] }`.
|
|
138
|
-
The array must be duplicate-free and ordered. The dependency value is a readonly map of
|
|
139
|
-
currently present selected entries in that order; missing selected keys remain bound.
|
|
140
|
-
Keyed selectors keep stable leading arguments: `(value, key)` without extra dependencies
|
|
141
|
-
and `(value, key, dependencies)` when the named dependency object is present.
|
|
142
|
-
|
|
143
|
-
`ProjectionRuntime` exposes:
|
|
144
|
-
|
|
145
|
-
- `read(projection)`;
|
|
146
|
-
- `select(projection)` and `select(projection, selector, equality?)`;
|
|
147
|
-
- `items(keyedProjection)` for ordered keys plus stable per-membership item Readables;
|
|
148
|
-
- `update(input, nextValue)` for scalar `Input<T>`;
|
|
149
|
-
- `update(collectionInput, draft => ...)` for `CollectionInput<K,V>`;
|
|
150
|
-
- `batch(run, { cause? }?)`;
|
|
151
|
-
- `scope()`;
|
|
152
|
-
- `dispose()`.
|
|
153
|
-
|
|
154
|
-
`input.collection` draft callbacks and per-entry equality run before accepted local
|
|
155
|
-
state is installed. If either throws, the published collection and the next draft both
|
|
156
|
-
remain at the pre-update state.
|
|
157
|
-
|
|
158
|
-
`CollectionInputDraft` exposes `get`, `has`, `set`, `remove`. A throwing edit callback
|
|
159
|
-
applies none of that edit. `ProjectionScope` mirrors `read`, `select`, `items`, `update`,
|
|
160
|
-
`batch`, `dispose` and adds `own(projectionOrTree)` for lifecycle ownership of scalar/keyed inputs,
|
|
161
|
-
derives and advanced output trees. One definition can belong to only one scope; call
|
|
162
|
-
`own` before that definition is first materialized as a root.
|
|
163
|
-
|
|
164
|
-
Public projection types are `Projection<T>`, `KeyedProjection<K,V>`, `Input<T>`,
|
|
165
|
-
`CollectionInput<K,V>`, `CollectionInputDraft<K,V>`, `ProjectionRuntime`,
|
|
166
|
-
`ProjectionScope`, plus the external source/event contracts. All keyed producers return
|
|
167
|
-
`KeyedProjection<K,V>`; `CollectionInput<K,V>` is its writable Runtime-local form.
|
|
168
|
-
`ProjectionError` exposes only `phase` and `cause`;
|
|
169
|
-
`ProjectionDisposedError` represents disposed access.
|
|
170
|
-
|
|
171
|
-
`filter` and `subset` reuse source values and therefore do not take a second equality.
|
|
172
|
-
`compact` owns membership through `undefined` while ordinary `derive.keyed` continues
|
|
173
|
-
to preserve every driver key, including when its selected value is `undefined`.
|
|
174
|
-
|
|
175
|
-
External value sources expose `kind: 'value'`, `current()`, `revision()`, `subscribe()`.
|
|
176
|
-
External collection sources expose `kind: 'collection'` plus `get/has/ids` reads and
|
|
177
|
-
optional `CollectionImpact` invalidation hints; the adapter derives exact
|
|
178
|
-
`CollectionChange` transitions.
|
|
179
|
-
|
|
180
|
-
## `doxum/advanced`
|
|
181
|
-
|
|
182
|
-
Use advanced processors only when `derive` / `derive.keyed` cannot express retained
|
|
183
|
-
state, cross-key indexes, or direct incremental output patching.
|
|
184
|
-
|
|
185
|
-
`collectionChange.keys(change)` iterates the added, updated and removed keys of an
|
|
186
|
-
incremental `CollectionChange` in that order. It does not interpret reset or order
|
|
187
|
-
changes; handle `reset` before calling it.
|
|
188
|
-
|
|
189
|
-
All advanced functions use named dependencies and a closed definition object.
|
|
190
|
-
|
|
191
|
-
```ts
|
|
192
|
-
const total = incremental(
|
|
193
|
-
{ rows },
|
|
194
|
-
{
|
|
195
|
-
state: () => ({ runs: 0 }),
|
|
196
|
-
process: ({ values, changes, previous, reset, cause, state }) => nextValue,
|
|
197
|
-
}
|
|
198
|
-
);
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
`incremental.collection(dependencies, { process, state? })` adds keyed `previous`,
|
|
202
|
-
`next`, and borrowed `output` with `set`, `remove`, `order`. `state()` is declared only
|
|
203
|
-
when retained state is needed; stateless process contexts do not contain `state`.
|
|
204
|
-
|
|
205
|
-
`incremental.keyed(driver, dependencies, { process, state?, equality? })` preserves the
|
|
206
|
-
driver's membership/order and owns independent retained state per current driver key.
|
|
207
|
-
Ordinary dependencies invalidate all driver keys; singular/plural keyed dependencies use
|
|
208
|
-
reverse routing. Order-only driver changes do not run `process`. Removal releases one
|
|
209
|
-
key's state, re-add starts a new membership lifecycle, reset intersections retain state,
|
|
210
|
-
and processor recovery recreates all per-key state. The process context contains `key`,
|
|
211
|
-
`value`, named `dependencies`, `reset`, `cause`, and optional `state`; it returns only the
|
|
212
|
-
value for its own output key and receives no collection draft.
|
|
213
|
-
|
|
214
|
-
`incremental.group(dependencies, { output, process, state? })` declares several leaves:
|
|
215
|
-
|
|
216
|
-
```ts
|
|
217
|
-
const view = incremental.group(
|
|
218
|
-
{ rows },
|
|
219
|
-
{
|
|
220
|
-
output: define => ({
|
|
221
|
-
cards: define.collection<RowId, Card>(),
|
|
222
|
-
count: define.value<number>(),
|
|
223
|
-
}),
|
|
224
|
-
state: () => ({ runs: 0 }),
|
|
225
|
-
process: ({ values, changes, previous, next, output, reset, cause, state }) => {},
|
|
226
|
-
}
|
|
227
|
-
);
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
`define.collection<K,V>(equality?)` and `define.value<T>(equality?)` exist only inside
|
|
231
|
-
`output`. The returned static object tree is mirrored with `KeyedProjection<K,V>`
|
|
232
|
-
collection leaves and `Projection<T>` value leaves. Every declared descriptor must be
|
|
233
|
-
returned exactly once.
|
|
234
|
-
|
|
235
|
-
Normal source resets preserve retained state when declared. If a processor faults, the
|
|
236
|
-
Runtime owns recovery: it recreates declared state and runs a reset evaluation. Stateless
|
|
237
|
-
processors use the same recovery path without a state object. There is no public rebuild
|
|
238
|
-
token or manual recovery protocol.
|
|
239
|
-
|
|
240
|
-
Exported advanced APIs include `collectionChange`, the value/collection/keyed/group context
|
|
241
|
-
and definition types, `CollectionChange`, and the declaration-safe `IncrementalGroupOutput` /
|
|
242
|
-
`IncrementalGroupResult` type boundaries. Normal callers infer the latter two; internal
|
|
243
|
-
scheduler/output plumbing is not part of the public contract.
|
|
244
|
-
|
|
245
|
-
## `doxum/react`
|
|
246
|
-
|
|
247
|
-
| API | Contract |
|
|
248
|
-
| ---------------------------------------------------- | -------------------------------------------------------------- |
|
|
249
|
-
| `ProjectionProvider` | Provide `ProjectionRuntime` or `ProjectionScope`. |
|
|
250
|
-
| `useProjection(projection)` | Read a Projection. |
|
|
251
|
-
| `useProjection(projection, selector, equality?)` | Selected Projection read. |
|
|
252
|
-
| `useInput(input)` | Scalar `[value, setValue]` or collection `[map, updateDraft]`. |
|
|
253
|
-
| `useDocumentSelector(document, selector, equality?)` | React adapter over Core document `select`. |
|
|
254
|
-
| `useReadable(readable)` | Subscribe to any Doxum `Readable`. |
|
|
255
|
-
| `useHistory(history)` | History state plus `undo` / `redo`. |
|
|
256
|
-
|
|
257
|
-
## `doxum/local-sync`
|
|
258
|
-
|
|
259
|
-
```ts
|
|
260
|
-
const sync = await attachLocalSync({
|
|
261
|
-
runtime: document,
|
|
262
|
-
database: 'app',
|
|
263
|
-
documentId: 'doc:1',
|
|
264
|
-
schemaVersion: 1,
|
|
265
|
-
changeLimits,
|
|
266
|
-
onError,
|
|
267
|
-
});
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
`LocalSync` exposes `state: Readable<LocalSyncState>`, `flush()` and async `dispose()`.
|
|
271
|
-
Only the leader may write while attached. Whole-document replace and externally supplied
|
|
272
|
-
remote apply are unsupported while attached.
|
|
273
|
-
|
|
274
|
-
`LocalSyncError` is the single public operational error class. Its `code` is one of
|
|
275
|
-
`unavailable`, `schema-mismatch`, `consistency`, `read-only`, `unsupported-operation`,
|
|
276
|
-
`disposed`, `invalid-data`.
|
|
277
|
-
`LocalSyncState` error states carry `LocalSyncError`, and `onError` receives the same
|
|
278
|
-
operational error contract. Consumer state-listener exceptions are isolated from sync
|
|
279
|
-
fault state and `onError`.
|
|
280
|
-
|
|
281
|
-
`JsonChangeLimits` contains `maxChanges`, `maxBytes`, `maxDepth`, `maxStringLength`.
|
|
282
|
-
`defaultJsonChangeLimits` supplies defaults. Limits admit new local commits only;
|
|
283
|
-
durable replay remains readable under smaller current limits.
|
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
# Public API 参考
|
|
2
|
-
|
|
3
|
-
这里列出稳定的公开契约。Projection 生命周期和示例见 [Projection 参考](projections.zh-CN.md),
|
|
4
|
-
建模选择见 [指南](guide.zh-CN.md)。
|
|
5
|
-
|
|
6
|
-
## Package 入口
|
|
7
|
-
|
|
8
|
-
| Package | 用途 |
|
|
9
|
-
| ------------------ | --------------------------------------------------------------------- |
|
|
10
|
-
| `doxum` | schema、canonical document runtime、读取、history、impact、projection |
|
|
11
|
-
| `doxum/advanced` | retained state 与多输出 incremental processor |
|
|
12
|
-
| `doxum/react` | Core capability 的 React adapter |
|
|
13
|
-
| `doxum/local-sync` | IndexedDB 持久化与浏览器 leader/follower 协调 |
|
|
14
|
-
|
|
15
|
-
## `doxum`
|
|
16
|
-
|
|
17
|
-
### Schema
|
|
18
|
-
|
|
19
|
-
| API | 契约 |
|
|
20
|
-
| ------------------------- | ----------------------------------------------------- |
|
|
21
|
-
| `field<T>(validator?)` | 原子 payload,整体替换;内部只读。 |
|
|
22
|
-
| `optional(schema)` | 让 field/variant/map/list/tree member 可缺省。 |
|
|
23
|
-
| `object(shape)` | 固定声明 member;返回 opaque `ObjectSchema<T>`。 |
|
|
24
|
-
| `variant(tag, variants)` | object branch 组成的 tagged union。 |
|
|
25
|
-
| `map(value, { key }?)` | 动态 keyed record。 |
|
|
26
|
-
| `table(entity, { key }?)` | 有序 object/variant entity,数据为 `{ ids, byId }`。 |
|
|
27
|
-
| `list(field, { keyOf })` | 带稳定 string identity 的有序数组。 |
|
|
28
|
-
| `tree(field)` | 空或单根树;optional field 表示 node payload 可缺省。 |
|
|
29
|
-
| `parse(schema, input)` | 校验 unknown 输入并复制 schema structure。 |
|
|
30
|
-
|
|
31
|
-
公开 schema 类型包括 `Schema<T>`、`ObjectSchema<T>`、`Infer<S>`、
|
|
32
|
-
`ReadonlyValue<T>`、`Validator<T>`、`SchemaPath<S>`、`PathValueOf<P>`、
|
|
33
|
-
`DocumentAnchor`、`DocumentListConfig<T>`、`DocumentTreeNode<T>`、
|
|
34
|
-
`DocumentTreeValue<T>`。具体 node representation 属于内部实现,不是公开契约。
|
|
35
|
-
`Schema` / `ObjectSchema` 是可跨 package 生成声明的 handle;下游 package 可以直接
|
|
36
|
-
export 推导出的 schema 常量,不需要应用层写 `ReturnType` 包装。
|
|
37
|
-
|
|
38
|
-
`Validator<T>` 只负责校验。函数 validator 是 predicate/assertion:返回 `true` 或
|
|
39
|
-
`undefined` 表示成功,返回 `false` 表示拒绝,assertion 也可以 throw。
|
|
40
|
-
Standard Schema 成功时必须按 identity 返回原输入;transform output 会被拒绝。
|
|
41
|
-
validator 必须同步且不能修改输入。
|
|
42
|
-
|
|
43
|
-
Draft collection 方法:
|
|
44
|
-
|
|
45
|
-
| Container | 读 | 写 |
|
|
46
|
-
| --------- | -------------------------------------------- | ---------------------------------------------------------------------------- |
|
|
47
|
-
| map | `get`, `has`, `ids` | `put`, `remove`, `replace(next)` |
|
|
48
|
-
| table | `get`, `has`, `ids` | `create`, `remove`, `move`, `reorder`, `replace(id,value)`, `replace(next)` |
|
|
49
|
-
| list | `get`, `has`, `ids` | `insert`, `remove`, `move`, `reorder`, `replace(key,value)`, `replace(next)` |
|
|
50
|
-
| tree | `rootId`, `get`, `has`, `parent`, `children` | `insert`, `move`, `remove`, `replace(id,value)`, `replace(next)` |
|
|
51
|
-
|
|
52
|
-
`replace(parent, key, value)` 用 plain `Infer` 数据替换一个 object/variant member。
|
|
53
|
-
`document.replace(value)` 是 whole-document reset,是独立操作。
|
|
54
|
-
|
|
55
|
-
### Document runtime
|
|
56
|
-
|
|
57
|
-
```ts
|
|
58
|
-
const document = createDocument({ schema, initial, history: { capacity: 100 } });
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
`DocumentRuntime<S>` 提供:
|
|
62
|
-
|
|
63
|
-
- `schema`、`revision()`、`snapshot()`、`readonly()`;
|
|
64
|
-
- `update(run, { source?, history? }?)`:同步、原子的 Draft mutation;
|
|
65
|
-
- `apply(changes, { expectedRevision, source?: 'local' | 'system', history? })`;remote replay
|
|
66
|
-
使用 `apply(changes, { expectedRevision, source: 'remote' })`;
|
|
67
|
-
- `replace(value, { source? }?)`:whole-document reset;
|
|
68
|
-
- `subscribe(listener)`、`subscribe(path | paths, listener)`;
|
|
69
|
-
- `history.undo()`、`redo()`、`clear()`、`group()`;
|
|
70
|
-
- `dispose()`。
|
|
71
|
-
|
|
72
|
-
`document.readonly()` 返回 `ReadonlyDocument<S>`,只保留 `revision()` 和
|
|
73
|
-
document commit/path subscription,用于显式去掉写 capability 的边界。
|
|
74
|
-
|
|
75
|
-
`update` 返回 `TransactionResult`;`apply`、whole-document `replace`、history travel
|
|
76
|
-
和 group cancel 返回 `OperationResult`。状态为 `committed`、`unchanged`、`rejected`。
|
|
77
|
-
应用层预期拒绝用 `TransactionRejected`;普通 throw 会 rollback 后原样抛出。
|
|
78
|
-
|
|
79
|
-
Document 错误为 `TransactionRejected`、`DocumentReentrancyError`、
|
|
80
|
-
`DocumentDisposedError`。parse 错误为 `ParseError`,并带 `ParseIssue`。
|
|
81
|
-
|
|
82
|
-
### 读取与订阅
|
|
83
|
-
|
|
84
|
-
| API | 契约 |
|
|
85
|
-
| --------------------------------------- | ------------------------------------------------------- |
|
|
86
|
-
| `read(document, selector)` | 一次同步 borrowed `Read`。 |
|
|
87
|
-
| `select(document, selector, equality?)` | 动态 read-tracked `Readable<TResult>`。 |
|
|
88
|
-
| `snapshot(value)` | 把 borrowed schema structure 导出为稳定 readonly data。 |
|
|
89
|
-
|
|
90
|
-
`Readable<T>` 提供 `current()`、`revision()`、`subscribe(listener)`。
|
|
91
|
-
`select` 会随 selector 分支变化重绑依赖;`equality` 判定结果相等时不发布。
|
|
92
|
-
|
|
93
|
-
Commit 包含 `revision`、`source`、`changes`、`impact`。公开 change/impact 类型包括
|
|
94
|
-
`ChangeSet`、`Change`、`MemberChange`、`ValueTransition`、`DocumentCommit`、
|
|
95
|
-
`DocumentImpact`、`CollectionImpact`、`MutationIssue` 和结果/诊断类型。
|
|
96
|
-
|
|
97
|
-
### Projection
|
|
98
|
-
|
|
99
|
-
```ts
|
|
100
|
-
const mode = input<'all' | 'open'>('all');
|
|
101
|
-
const selection = input.collection<RowId, Selection>();
|
|
102
|
-
const rows = observe(document, path => path.rows);
|
|
103
|
-
const count = derive({ rows }, ({ rows }) => rows.size);
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
| API | 契约 |
|
|
107
|
-
| ------------------------------------------------------- | -------------------------------------------------------------------- |
|
|
108
|
-
| `input(initial, equality?)` | Runtime-local writable scalar `Input<T>`。 |
|
|
109
|
-
| `input.collection<K,V>(initial?, equality?)` | Runtime-local keyed `CollectionInput<K,V>`,equality 按 entry 比较。 |
|
|
110
|
-
| `observe(document)` | whole-document Projection source。 |
|
|
111
|
-
| `observe(document, path => ...)` | schema-path scalar 或 keyed Projection source。 |
|
|
112
|
-
| `observe(readable)` | 接入 Doxum `Readable`。 |
|
|
113
|
-
| `observe(externalSource)` | 接入公开 external value/collection source contract。 |
|
|
114
|
-
| `derive(dependencies, compute, equality?)` | named dependencies 的 pure value Projection。 |
|
|
115
|
-
| `derive.keyed(driver, select, equality?)` | 保留 driver key/order,逐 entry projection。 |
|
|
116
|
-
| `derive.keyed(driver, deps, select, equality?)` | 带 named global/dynamic keyed dependencies 的 keyed projection。 |
|
|
117
|
-
| `derive.keyed.keys(source)` | 正式顺序的 key array;value-only update 不发布。 |
|
|
118
|
-
| `derive.keyed.values(source)` | 按 keyed collection 正式顺序排列的 value array。 |
|
|
119
|
-
| `derive.keyed.entries(source)` | 正式顺序的 readonly `[key, value]` tuple,未变化 tuple 保持引用。 |
|
|
120
|
-
| `derive.keyed.get(source, key, equality?)` | 精确绑定当前 selected key 的 scalar lookup。 |
|
|
121
|
-
| `derive.keyed.subset(source, orderedKeys)` | membership/order 由 ordered keys 决定的 keyed subset。 |
|
|
122
|
-
| `derive.keyed.filter(source, predicate)` | 保留 source value 与 source-relative order 的 keyed filter。 |
|
|
123
|
-
| `derive.keyed.filter(source, deps, predicate)` | 使用标准 keyed dependency protocol 的 filter。 |
|
|
124
|
-
| `derive.keyed.compact(source, select, equality?)` | map entry,并省略 selected value 为 `undefined` 的 key。 |
|
|
125
|
-
| `derive.keyed.compact(source, deps, select, equality?)` | 使用标准 keyed dependencies 的 compact。 |
|
|
126
|
-
| `derive.keyed.groupBy(source, selector)` | group key → source keys 的 reverse index,成员遵循 source 正式顺序。 |
|
|
127
|
-
| `derive.keyed.groupBy(source, deps, selector)` | 使用标准 keyed dependency protocol 的 reverse index。 |
|
|
128
|
-
| `derive.keyed.singleton(source, keyOf, equality?)` | optional scalar → 0/1 keyed projection。 |
|
|
129
|
-
|
|
130
|
-
动态 keyed dependency 写法为
|
|
131
|
-
`{ source: keyedProjection, key: (driverValue, driverKey) => sourceKey | undefined }`。
|
|
132
|
-
Runtime 拥有 output-key → source-key binding 和 reverse invalidation。这个 helper shape
|
|
133
|
-
在调用点自动推断,不暴露独立 public helper type。
|
|
134
|
-
plural lookup 使用
|
|
135
|
-
`{ source: keyedProjection, keys: (driverValue, driverKey) => readonly sourceKey[] }`。
|
|
136
|
-
返回数组必须有序且无重复;dependency value 是按该顺序包含当前存在 selected entry 的
|
|
137
|
-
readonly map。缺失 key 仍保留 reverse binding,后续 add 会使 dependent driver key 失效。
|
|
138
|
-
keyed selector 的前置参数固定:无额外 dependency 时为 `(value, key)`;存在 named
|
|
139
|
-
dependency object 时为 `(value, key, dependencies)`。
|
|
140
|
-
|
|
141
|
-
`ProjectionRuntime` 提供:
|
|
142
|
-
|
|
143
|
-
- `read(projection)`;
|
|
144
|
-
- `select(projection)`、`select(projection, selector, equality?)`;
|
|
145
|
-
- `items(keyedProjection)`:有序 keys + membership 生命周期稳定的逐 key Readable;
|
|
146
|
-
- `update(input, nextValue)`:写 scalar `Input<T>`;
|
|
147
|
-
- `update(collectionInput, draft => ...)`:写 `CollectionInput<K,V>`;
|
|
148
|
-
- `batch(run, { cause? }?)`;
|
|
149
|
-
- `scope()`;
|
|
150
|
-
- `dispose()`。
|
|
151
|
-
|
|
152
|
-
`input.collection` 的 draft callback 与逐 entry equality 都在本地状态正式安装前完成;
|
|
153
|
-
任一环节抛错时,已发布 collection 与下一次 draft 都保持更新前状态。
|
|
154
|
-
|
|
155
|
-
`CollectionInputDraft` 提供 `get`、`has`、`set`、`remove`。edit callback throw 时该次 edit
|
|
156
|
-
整体不应用。`ProjectionScope` 镜像 `read`、`select`、`items`、`update`、`batch`、`dispose`,
|
|
157
|
-
并增加 `own(projectionOrTree)`,统一拥有 scalar/keyed input、derive 与 advanced output
|
|
158
|
-
tree 的 lifecycle。同一个 definition 只能属于一个 scope,并且必须在该 definition
|
|
159
|
-
首次作为 root materialize 之前调用 `own`。
|
|
160
|
-
|
|
161
|
-
公开 Projection 类型包括 `Projection<T>`、`KeyedProjection<K,V>`、`Input<T>`、
|
|
162
|
-
`CollectionInput<K,V>`、`CollectionInputDraft<K,V>`、`ProjectionRuntime`、
|
|
163
|
-
`ProjectionScope` 和 external source/event contract。所有 keyed producer 都返回
|
|
164
|
-
`KeyedProjection<K,V>`;`CollectionInput<K,V>` 是它的 Runtime-local writable 形式。
|
|
165
|
-
`ProjectionError` 只公开 `phase` 与 `cause`;
|
|
166
|
-
`ProjectionDisposedError` 表达 disposed access。
|
|
167
|
-
|
|
168
|
-
`filter` / `subset` 直接复用 source value,因此没有第二个 equality 参数。
|
|
169
|
-
`compact` 用 `undefined` 表达 membership 缺失;普通 `derive.keyed` 仍保留所有 driver key,
|
|
170
|
-
即使 selected value 本身为 `undefined`。
|
|
171
|
-
|
|
172
|
-
External value source 提供 `kind: 'value'`、`current()`、`revision()`、`subscribe()`。
|
|
173
|
-
External collection source 提供 `kind: 'collection'` 和 `get/has/ids` read,可给
|
|
174
|
-
`CollectionImpact` invalidation hint;adapter 会导出精确 `CollectionChange`。
|
|
175
|
-
|
|
176
|
-
## `doxum/advanced`
|
|
177
|
-
|
|
178
|
-
只有 retained state、cross-key index 或直接 incremental patch 无法用
|
|
179
|
-
`derive` / `derive.keyed` 清晰表达时才使用 advanced processor。
|
|
180
|
-
|
|
181
|
-
`collectionChange.keys(change)` 按 added → updated → removed 遍历 incremental
|
|
182
|
-
`CollectionChange` 的 entry-transition keys。它不解释 reset,也不会把 order change
|
|
183
|
-
扩展成所有 keys;调用前由业务代码先处理 `reset`。
|
|
184
|
-
|
|
185
|
-
所有 advanced API 都使用 named dependencies + closed definition object。
|
|
186
|
-
|
|
187
|
-
```ts
|
|
188
|
-
const total = incremental(
|
|
189
|
-
{ rows },
|
|
190
|
-
{
|
|
191
|
-
state: () => ({ runs: 0 }),
|
|
192
|
-
process: ({ values, changes, previous, reset, cause, state }) => nextValue,
|
|
193
|
-
}
|
|
194
|
-
);
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
`incremental.collection(dependencies, { process, state? })` 额外提供 keyed
|
|
198
|
-
`previous`、`next` 和 borrowed `output`;output 有 `set`、`remove`、`order`。只有确实
|
|
199
|
-
需要 retained state 时才声明 `state()`;无状态 process context 不包含 `state`。
|
|
200
|
-
|
|
201
|
-
`incremental.keyed(driver, dependencies, { process, state?, equality? })` 保留 driver
|
|
202
|
-
membership/order,并为每个当前 driver key 独立拥有 retained state。普通 dependency
|
|
203
|
-
变化使所有当前 driver key 失效;singular/plural keyed dependency 通过 reverse routing
|
|
204
|
-
只运行真正依赖的 key。driver 仅 order 变化不会执行 `process`。remove 释放该 key state,
|
|
205
|
-
同 key re-add 进入新的 membership lifecycle;reset intersection 保留 state,processor
|
|
206
|
-
fault recovery 会重建全部 per-key state。process context 包含 `key`、`value`、named
|
|
207
|
-
`dependencies`、`reset`、`cause` 和可选 `state`,返回当前 output key 的值,不暴露
|
|
208
|
-
collection draft。
|
|
209
|
-
|
|
210
|
-
`incremental.group(dependencies, { output, process, state? })` 声明多个 leaf:
|
|
211
|
-
|
|
212
|
-
```ts
|
|
213
|
-
const view = incremental.group(
|
|
214
|
-
{ rows },
|
|
215
|
-
{
|
|
216
|
-
output: define => ({
|
|
217
|
-
cards: define.collection<RowId, Card>(),
|
|
218
|
-
count: define.value<number>(),
|
|
219
|
-
}),
|
|
220
|
-
state: () => ({ runs: 0 }),
|
|
221
|
-
process: ({ values, changes, previous, next, output, reset, cause, state }) => {},
|
|
222
|
-
}
|
|
223
|
-
);
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
`define.collection<K,V>(equality?)`、`define.value<T>(equality?)` 只存在于
|
|
227
|
-
`output` callback 内。返回值必须是非空静态 object tree,每个 descriptor 恰好返回一次;
|
|
228
|
-
最终同 shape 的 collection leaf 是 `KeyedProjection<K,V>`,value leaf 是
|
|
229
|
-
`Projection<T>`。
|
|
230
|
-
|
|
231
|
-
普通 source reset 保留已声明的 retained state。processor fault 的 recovery 由 Runtime
|
|
232
|
-
拥有:重新创建已声明的 state,再执行 reset evaluation;stateless processor 走同一恢复
|
|
233
|
-
路径但没有 state object。没有公开 rebuild token 或手工恢复协议。
|
|
234
|
-
|
|
235
|
-
advanced 导出 `collectionChange`、value/collection/keyed/group 的 context/definition 类型、`CollectionChange`,
|
|
236
|
-
以及声明可移植性所需的 `IncrementalGroupOutput` / `IncrementalGroupResult` 类型边界。
|
|
237
|
-
普通调用方通常只依赖推导;scheduler/output runtime plumbing 不属于公开 API。
|
|
238
|
-
|
|
239
|
-
## `doxum/react`
|
|
240
|
-
|
|
241
|
-
| API | 契约 |
|
|
242
|
-
| ---------------------------------------------------- | ------------------------------------------------------------- |
|
|
243
|
-
| `ProjectionProvider` | 提供 `ProjectionRuntime` 或 `ProjectionScope`。 |
|
|
244
|
-
| `useProjection(projection)` | 读取 Projection。 |
|
|
245
|
-
| `useProjection(projection, selector, equality?)` | selector 形式读取 Projection。 |
|
|
246
|
-
| `useInput(input)` | scalar `[value,setValue]` 或 collection `[map,updateDraft]`。 |
|
|
247
|
-
| `useDocumentSelector(document, selector, equality?)` | Core document `select` 的 React adapter。 |
|
|
248
|
-
| `useReadable(readable)` | 订阅任意 Doxum `Readable`。 |
|
|
249
|
-
| `useHistory(history)` | history state + `undo` / `redo`。 |
|
|
250
|
-
|
|
251
|
-
## `doxum/local-sync`
|
|
252
|
-
|
|
253
|
-
```ts
|
|
254
|
-
const sync = await attachLocalSync({
|
|
255
|
-
runtime: document,
|
|
256
|
-
database: 'app',
|
|
257
|
-
documentId: 'doc:1',
|
|
258
|
-
schemaVersion: 1,
|
|
259
|
-
changeLimits,
|
|
260
|
-
onError,
|
|
261
|
-
});
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
`LocalSync` 提供 `state: Readable<LocalSyncState>`、`flush()`、async `dispose()`。
|
|
265
|
-
attached 时只有 leader 可写;whole-document replace 和外部 remote apply 不支持。
|
|
266
|
-
|
|
267
|
-
`LocalSyncError` 是唯一公开 operational error class。`code` 取值:
|
|
268
|
-
`unavailable`、`schema-mismatch`、`consistency`、`read-only`、
|
|
269
|
-
`unsupported-operation`、`disposed`、`invalid-data`。
|
|
270
|
-
`LocalSyncState` 的 error state 持有 `LocalSyncError`,`onError` 也只接收同一
|
|
271
|
-
operational error contract;consumer state-listener exception 不进入 sync fault state
|
|
272
|
-
或 `onError`。
|
|
273
|
-
|
|
274
|
-
`JsonChangeLimits` 包含 `maxChanges`、`maxBytes`、`maxDepth`、`maxStringLength`。
|
|
275
|
-
`defaultJsonChangeLimits` 提供默认值。limits 只限制新 local commit;更小的新 limit
|
|
276
|
-
不会阻止读取已经持久化的 durable replay。
|