doxum 0.1.2 → 0.1.4
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 +59 -27
- package/dist/{contract-DGkZcTiP.d.cts → contract-BsY1XLiG.d.ts} +2 -1
- package/dist/{contract-Dh3az8aN.d.ts → contract-D8kjdfqT.d.cts} +2 -1
- package/dist/{access-5D4KKFm7.js → dependency-C5_R1tvQ.js} +40 -262
- package/dist/dependency-C5_R1tvQ.js.map +1 -0
- package/dist/{access-z56fVqZ2.cjs → dependency-Dfzs3khk.cjs} +62 -344
- package/dist/dependency-Dfzs3khk.cjs.map +1 -0
- package/dist/driver-CNxqMVFH.cjs +69 -0
- package/dist/driver-CNxqMVFH.cjs.map +1 -0
- package/dist/driver-CbzfW5MR.js +46 -0
- package/dist/driver-CbzfW5MR.js.map +1 -0
- package/dist/index.cjs +2636 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2594 -4
- package/dist/index.js.map +1 -1
- package/dist/integration.cjs +2 -3
- package/dist/integration.cjs.map +1 -1
- package/dist/integration.d.cts +1 -1
- package/dist/integration.d.ts +1 -1
- package/dist/integration.js +1 -2
- package/dist/integration.js.map +1 -1
- package/dist/local-sync.cjs +154 -329
- package/dist/local-sync.cjs.map +1 -1
- package/dist/local-sync.d.cts +17 -22
- package/dist/local-sync.d.ts +17 -22
- package/dist/local-sync.js +149 -326
- package/dist/local-sync.js.map +1 -1
- package/dist/ownership-B-VAPcce.js +242 -0
- package/dist/ownership-B-VAPcce.js.map +1 -0
- package/dist/ownership-CU-9DKJQ.cjs +301 -0
- package/dist/ownership-CU-9DKJQ.cjs.map +1 -0
- package/package.json +1 -1
- package/skills/doxum-runtime/references/guide.en.md +52 -1
- package/skills/doxum-runtime/references/guide.zh-CN.md +46 -1
- package/skills/doxum-runtime/references/invariants.en.md +14 -4
- package/skills/doxum-runtime/references/invariants.zh-CN.md +1 -1
- package/dist/access-5D4KKFm7.js.map +0 -1
- package/dist/access-z56fVqZ2.cjs.map +0 -1
- package/dist/dependency-BRn1TRDi.js +0 -20
- package/dist/dependency-BRn1TRDi.js.map +0 -1
- package/dist/dependency-DmQXyj7q.cjs +0 -25
- package/dist/dependency-DmQXyj7q.cjs.map +0 -1
- package/dist/readable-B8E3FMq6.cjs +0 -2614
- package/dist/readable-B8E3FMq6.cjs.map +0 -1
- package/dist/readable-CIj02gIj.js +0 -2579
- package/dist/readable-CIj02gIj.js.map +0 -1
package/README.md
CHANGED
|
@@ -7,16 +7,17 @@ undo/redo, precise change notifications, and incremental derived data.
|
|
|
7
7
|
Licensed under the [MIT License](LICENSE).
|
|
8
8
|
|
|
9
9
|
The `doxum` core entry is a local in-memory runtime. The optional
|
|
10
|
-
`doxum/local-sync` browser
|
|
11
|
-
cross-tab synchronization
|
|
12
|
-
resolution remain separate
|
|
10
|
+
`doxum/local-sync` browser attachment adds IndexedDB persistence and
|
|
11
|
+
same-origin cross-tab synchronization with one writable tab at a time; network
|
|
12
|
+
collaboration, authorization, and conflict resolution remain separate
|
|
13
|
+
application concerns.
|
|
13
14
|
|
|
14
15
|
## Packages
|
|
15
16
|
|
|
16
17
|
- `doxum` defines schemas, mutations, history, subscriptions, and views.
|
|
17
|
-
- `doxum/local-sync`
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
- `doxum/local-sync` lets one Web-Lock leader write a runtime synchronously,
|
|
19
|
+
persists its commands asynchronously to IndexedDB, and makes other tabs
|
|
20
|
+
ordered read-only mirrors.
|
|
20
21
|
- `doxum/react` binds Doxum read models to React 18+ with fine-grained external
|
|
21
22
|
store subscriptions.
|
|
22
23
|
|
|
@@ -152,19 +153,37 @@ already settled.
|
|
|
152
153
|
|
|
153
154
|
## Local Persistence And Cross-Tab Sync
|
|
154
155
|
|
|
155
|
-
`doxum/local-sync` is an optional browser
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
156
|
+
`doxum/local-sync` is an optional browser attachment for a document that needs
|
|
157
|
+
offline persistence and same-origin, cross-tab convergence. It uses IndexedDB
|
|
158
|
+
as the ordered checkpoint and commit log, Web Locks to serialize background
|
|
159
|
+
confirmation, and BroadcastChannel only to notify other tabs to catch up from
|
|
160
|
+
IndexedDB. It does not need a server or Yjs.
|
|
161
|
+
|
|
162
|
+
The attachment deliberately uses a simple single-writer model. It hydrates the
|
|
163
|
+
runtime from the IndexedDB checkpoint and ordered command log, then attempts to
|
|
164
|
+
hold a Web Lock for that document. The lock holder is the `leader` and may use
|
|
165
|
+
the normal synchronous runtime APIs. All other attached tabs are `follower`
|
|
166
|
+
mirrors: they read the durable tail in order after a BroadcastChannel hint, and
|
|
167
|
+
their direct writes throw `LocalSyncReadOnlyError`. When the leader disposes,
|
|
168
|
+
a follower catches up and becomes the next leader.
|
|
169
|
+
|
|
170
|
+
The leader's `runtime.update`, normal `runtime.apply`, and
|
|
171
|
+
`runtime.history.undo()` / `redo()` stay synchronous and immediately visible.
|
|
172
|
+
Local-sync observes the resulting local, system, and history commits and writes
|
|
173
|
+
their JSON operation batches to IndexedDB in the background. It deliberately
|
|
174
|
+
rejects `runtime.replace()` and an externally supplied `apply(..., {
|
|
175
|
+
source: 'remote' })` while attached: neither is a local operation command that
|
|
176
|
+
the log can faithfully append. `flush()` is the explicit point that waits for
|
|
177
|
+
commits observed before the call to persist (or, in a follower, waits to catch
|
|
178
|
+
up to the durable head). A browser crash, quota failure, or malformed JSON
|
|
179
|
+
payload can therefore leave an already visible leader commit unpersisted;
|
|
180
|
+
inspect `state()` or use `onError` to surface that condition.
|
|
160
181
|
|
|
161
182
|
```ts
|
|
162
|
-
import { select } from 'doxum';
|
|
163
|
-
import {
|
|
183
|
+
import { createDocument, select } from 'doxum';
|
|
184
|
+
import { attachLocalSync } from 'doxum/local-sync';
|
|
164
185
|
|
|
165
|
-
const
|
|
166
|
-
database: 'my-app',
|
|
167
|
-
documentId: 'project-1',
|
|
186
|
+
const runtime = createDocument({
|
|
168
187
|
schema: taskSchema,
|
|
169
188
|
initial: {
|
|
170
189
|
title: 'Launch',
|
|
@@ -172,21 +191,34 @@ const local = await openLocalDocument({
|
|
|
172
191
|
},
|
|
173
192
|
});
|
|
174
193
|
|
|
175
|
-
await
|
|
176
|
-
|
|
194
|
+
const localSync = await attachLocalSync({
|
|
195
|
+
runtime,
|
|
196
|
+
database: 'my-app',
|
|
197
|
+
documentId: 'project-1',
|
|
177
198
|
});
|
|
178
199
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
200
|
+
if (localSync.state().status === 'leader') {
|
|
201
|
+
runtime.update(tx => {
|
|
202
|
+
tx.write.title.set('Ship Doxum');
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
runtime.history.undo();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
select(runtime, read => read.title.get()); // leader write or follower replay
|
|
209
|
+
await localSync.flush(); // persist observed leader commands / catch up a follower
|
|
210
|
+
|
|
211
|
+
await localSync.dispose();
|
|
182
212
|
```
|
|
183
213
|
|
|
184
|
-
`
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
214
|
+
`attachLocalSync` first hydrates the passed runtime from IndexedDB; await it
|
|
215
|
+
before allowing reads or edits. It does not make runtime mutation asynchronous,
|
|
216
|
+
does not own `runtime.dispose()`, and does not expose a second undo API. Runtime
|
|
217
|
+
history is in-memory only: hydration and remote tail application invalidate it,
|
|
218
|
+
so an undo stack never transfers to a new leader or survives reopening a tab.
|
|
219
|
+
Local-sync data must be JSON. Because command validation happens after the
|
|
220
|
+
runtime commit, a non-JSON payload is reported as a post-commit attachment error
|
|
221
|
+
rather than rolling back an already observed document change.
|
|
190
222
|
|
|
191
223
|
## React
|
|
192
224
|
|
|
@@ -517,6 +517,7 @@ type DocumentReadable<TSchema extends DocumentSchema> = {
|
|
|
517
517
|
subscribe(target: ImpactTarget<unknown> | readonly [ImpactTarget<unknown>, ...ImpactTarget<unknown>[]], listener: CommitListener<TSchema>): Unsubscribe;
|
|
518
518
|
};
|
|
519
519
|
type DocumentRuntime<TSchema extends DocumentSchema> = DocumentReadable<TSchema> & {
|
|
520
|
+
/** Schema configuration captured when this runtime was created. */readonly schema: TSchema;
|
|
520
521
|
update<TResult>(run: (transaction: DocumentTransaction<TSchema>) => TResult, options?: {
|
|
521
522
|
readonly source?: Extract<CommitSource, 'local' | 'system'>;
|
|
522
523
|
readonly history?: boolean;
|
|
@@ -535,4 +536,4 @@ type DocumentRuntime<TSchema extends DocumentSchema> = DocumentReadable<TSchema>
|
|
|
535
536
|
};
|
|
536
537
|
//#endregion
|
|
537
538
|
export { DocumentOperationUnion as $, variant as $t, MutationIssue as A, ObjectNode as At, WriterOfNode as B, VariantNode as Bt, contains as C, DocumentTreeValue as Ct, resolveAddress as D, ImpactTarget as Dt, read as E, FieldNode as Et, EntityWriter as F, SchemaPath as Ft, ListReader as G, map as Gt, DocumentReader as H, dict as Ht, FieldWriter as I, SingleNode as It, DictDeleteOperation as J, record as Jt, ReaderOfNode as K, object as Kt, ListWriter as L, TableNode as Lt, CollectionWriter as M, OptionalNode as Mt, DictionaryWriter as N, ReadonlyDocument as Nt, CollectionImpact as O, ListNode as Ot, DocumentWriter as P, RecordNode as Pt, DocumentOperation as Q, tree as Qt, MapWriter as R, TreeNode as Rt, AddressRef as S, DocumentTreeNode as St, overlaps as T, DocumentValueOfShape as Tt, EntityReader as U, field as Ut, CollectionReader as V, VariantShape as Vt, FieldReader as W, list as Wt, DictSetOperation as X, single as Xt, DictReplaceOperation as Y, schema as Yt, DocumentAnchor as Z, table as Zt, CommandFootprint as _, DictNode as _t, DocumentProblem as a, FieldSetOperation as at, decodeCommandFootprint as b, DocumentNode as bt, DocumentRuntime as c, ListRemoveOperation as ct, LocalHistory as d, TreeMoveOperation as dt, EntityCreateOperation as et, ObserverError as f, TreeRemoveOperation as ft, Unsubscribe as g, CollectionSelector as gt, TransactionResult as h, VariantReplaceOperation as ht, DocumentDisposedError as i, FieldClearOperation as it, MutationIssueCode as j, ObjectShape as jt, DocumentImpact as k, MapNode as kt, DocumentTransaction as l, ListReplaceOperation as lt, PreparedUpdateResult as m, TreeSetOperation as mt, DocumentCommit as n, EntityMoveOperation as nt, DocumentReadable as o, ListInsertOperation as ot, OperationResult as p, TreeReplaceOperation as pt, TreeReader as q, optional as qt, DocumentDiagnostic as r, EntityRemoveOperation as rt, DocumentReentrancyError as s, ListMoveOperation as st, CommitSource as t, EntityEntry as tt, HistoryState as u, TreeInsertOperation as ut, CommandFootprintTarget as v, DocumentAddress as vt, debugKey as w, DocumentValueOfNode as wt, footprintsOverlap as x, DocumentSchema as xt, commandFootprint as y, DocumentListConfig as yt, TreeWriter as z, ValueSelector as zt };
|
|
538
|
-
//# sourceMappingURL=contract-
|
|
539
|
+
//# sourceMappingURL=contract-BsY1XLiG.d.ts.map
|
|
@@ -517,6 +517,7 @@ type DocumentReadable<TSchema extends DocumentSchema> = {
|
|
|
517
517
|
subscribe(target: ImpactTarget<unknown> | readonly [ImpactTarget<unknown>, ...ImpactTarget<unknown>[]], listener: CommitListener<TSchema>): Unsubscribe;
|
|
518
518
|
};
|
|
519
519
|
type DocumentRuntime<TSchema extends DocumentSchema> = DocumentReadable<TSchema> & {
|
|
520
|
+
/** Schema configuration captured when this runtime was created. */readonly schema: TSchema;
|
|
520
521
|
update<TResult>(run: (transaction: DocumentTransaction<TSchema>) => TResult, options?: {
|
|
521
522
|
readonly source?: Extract<CommitSource, 'local' | 'system'>;
|
|
522
523
|
readonly history?: boolean;
|
|
@@ -535,4 +536,4 @@ type DocumentRuntime<TSchema extends DocumentSchema> = DocumentReadable<TSchema>
|
|
|
535
536
|
};
|
|
536
537
|
//#endregion
|
|
537
538
|
export { DocumentOperationUnion as $, variant as $t, MutationIssue as A, ObjectNode as At, WriterOfNode as B, VariantNode as Bt, contains as C, DocumentTreeValue as Ct, resolveAddress as D, ImpactTarget as Dt, read as E, FieldNode as Et, EntityWriter as F, SchemaPath as Ft, ListReader as G, map as Gt, DocumentReader as H, dict as Ht, FieldWriter as I, SingleNode as It, DictDeleteOperation as J, record as Jt, ReaderOfNode as K, object as Kt, ListWriter as L, TableNode as Lt, CollectionWriter as M, OptionalNode as Mt, DictionaryWriter as N, ReadonlyDocument as Nt, CollectionImpact as O, ListNode as Ot, DocumentWriter as P, RecordNode as Pt, DocumentOperation as Q, tree as Qt, MapWriter as R, TreeNode as Rt, AddressRef as S, DocumentTreeNode as St, overlaps as T, DocumentValueOfShape as Tt, EntityReader as U, field as Ut, CollectionReader as V, VariantShape as Vt, FieldReader as W, list as Wt, DictSetOperation as X, single as Xt, DictReplaceOperation as Y, schema as Yt, DocumentAnchor as Z, table as Zt, CommandFootprint as _, DictNode as _t, DocumentProblem as a, FieldSetOperation as at, decodeCommandFootprint as b, DocumentNode as bt, DocumentRuntime as c, ListRemoveOperation as ct, LocalHistory as d, TreeMoveOperation as dt, EntityCreateOperation as et, ObserverError as f, TreeRemoveOperation as ft, Unsubscribe as g, CollectionSelector as gt, TransactionResult as h, VariantReplaceOperation as ht, DocumentDisposedError as i, FieldClearOperation as it, MutationIssueCode as j, ObjectShape as jt, DocumentImpact as k, MapNode as kt, DocumentTransaction as l, ListReplaceOperation as lt, PreparedUpdateResult as m, TreeSetOperation as mt, DocumentCommit as n, EntityMoveOperation as nt, DocumentReadable as o, ListInsertOperation as ot, OperationResult as p, TreeReplaceOperation as pt, TreeReader as q, optional as qt, DocumentDiagnostic as r, EntityRemoveOperation as rt, DocumentReentrancyError as s, ListMoveOperation as st, CommitSource as t, EntityEntry as tt, HistoryState as u, TreeInsertOperation as ut, CommandFootprintTarget as v, DocumentAddress as vt, debugKey as w, DocumentValueOfNode as wt, footprintsOverlap as x, DocumentSchema as xt, commandFootprint as y, DocumentListConfig as yt, TreeWriter as z, ValueSelector as zt };
|
|
538
|
-
//# sourceMappingURL=contract-
|
|
539
|
+
//# sourceMappingURL=contract-D8kjdfqT.d.cts.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-pbuEa-1d.js";
|
|
2
|
+
import { i as isRecord$1, t as cloneValue, u as profile } from "./ownership-B-VAPcce.js";
|
|
2
3
|
//#region core/src/schema.ts
|
|
3
4
|
const node = (value) => Object.freeze(value);
|
|
4
5
|
const field = () => node({ kind: "field" });
|
|
@@ -58,186 +59,6 @@ const schema = (shape) => {
|
|
|
58
59
|
return Object.freeze(result);
|
|
59
60
|
};
|
|
60
61
|
//#endregion
|
|
61
|
-
//#region core/src/profile.ts
|
|
62
|
-
const active = { current: void 0 };
|
|
63
|
-
const profile = {
|
|
64
|
-
clone: {
|
|
65
|
-
call: () => {
|
|
66
|
-
const value = active.current;
|
|
67
|
-
if (value) value.clone.calls += 1;
|
|
68
|
-
},
|
|
69
|
-
node: (reason) => {
|
|
70
|
-
const value = active.current;
|
|
71
|
-
if (!value) return;
|
|
72
|
-
value.clone.nodes[reason] += 1;
|
|
73
|
-
},
|
|
74
|
-
container: () => {
|
|
75
|
-
const value = active.current;
|
|
76
|
-
if (value) value.clone.containers += 1;
|
|
77
|
-
},
|
|
78
|
-
deepEqual: () => {
|
|
79
|
-
const value = active.current;
|
|
80
|
-
if (value) value.clone.deepEqual.calls += 1;
|
|
81
|
-
},
|
|
82
|
-
deepEqualContainer: () => {
|
|
83
|
-
const value = active.current;
|
|
84
|
-
if (value) value.clone.deepEqual.containers += 1;
|
|
85
|
-
},
|
|
86
|
-
initialDocument: () => {
|
|
87
|
-
const value = active.current;
|
|
88
|
-
if (value) value.clone.documents.initial += 1;
|
|
89
|
-
}
|
|
90
|
-
},
|
|
91
|
-
mutation: {
|
|
92
|
-
normalized: () => {
|
|
93
|
-
const value = active.current;
|
|
94
|
-
if (value) value.mutation.normalized += 1;
|
|
95
|
-
},
|
|
96
|
-
executed: () => {
|
|
97
|
-
const value = active.current;
|
|
98
|
-
if (value) value.mutation.executed += 1;
|
|
99
|
-
},
|
|
100
|
-
inverse: () => {
|
|
101
|
-
const value = active.current;
|
|
102
|
-
if (value) value.mutation.inverseCreated += 1;
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
batch: {
|
|
106
|
-
operation: () => {
|
|
107
|
-
const value = active.current;
|
|
108
|
-
if (value) value.batch.operations += 1;
|
|
109
|
-
},
|
|
110
|
-
entry: (amount = 1) => {
|
|
111
|
-
const value = active.current;
|
|
112
|
-
if (value) value.batch.entries += amount;
|
|
113
|
-
},
|
|
114
|
-
collectionResolved: () => {
|
|
115
|
-
const value = active.current;
|
|
116
|
-
if (value) value.batch.collectionsResolved += 1;
|
|
117
|
-
},
|
|
118
|
-
journalRecord: () => {
|
|
119
|
-
const value = active.current;
|
|
120
|
-
if (value) value.batch.journalRecords += 1;
|
|
121
|
-
},
|
|
122
|
-
rejected: () => {
|
|
123
|
-
const value = active.current;
|
|
124
|
-
if (value) value.batch.rejected += 1;
|
|
125
|
-
},
|
|
126
|
-
inverse: () => {
|
|
127
|
-
const value = active.current;
|
|
128
|
-
if (value) value.batch.inverseOperations += 1;
|
|
129
|
-
},
|
|
130
|
-
payloadTransferred: () => {
|
|
131
|
-
const value = active.current;
|
|
132
|
-
if (value) value.batch.payloadTransferred += 1;
|
|
133
|
-
},
|
|
134
|
-
payloadSnapshot: () => {
|
|
135
|
-
const value = active.current;
|
|
136
|
-
if (value) value.batch.payloadSnapshots += 1;
|
|
137
|
-
}
|
|
138
|
-
},
|
|
139
|
-
journal: {
|
|
140
|
-
subject: () => {
|
|
141
|
-
const value = active.current;
|
|
142
|
-
if (value) value.journal.subjects += 1;
|
|
143
|
-
},
|
|
144
|
-
comparison: () => {
|
|
145
|
-
const value = active.current;
|
|
146
|
-
if (value) value.journal.comparisons += 1;
|
|
147
|
-
},
|
|
148
|
-
absorbed: () => {
|
|
149
|
-
const value = active.current;
|
|
150
|
-
if (value) value.journal.absorbed += 1;
|
|
151
|
-
},
|
|
152
|
-
orderSnapshot: (items) => {
|
|
153
|
-
const value = active.current;
|
|
154
|
-
if (!value) return;
|
|
155
|
-
value.journal.orderSnapshots += 1;
|
|
156
|
-
value.journal.orderItems += items;
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
address: {
|
|
160
|
-
schemaStep: () => {
|
|
161
|
-
const value = active.current;
|
|
162
|
-
if (value) value.address.schemaSteps += 1;
|
|
163
|
-
},
|
|
164
|
-
documentStep: () => {
|
|
165
|
-
const value = active.current;
|
|
166
|
-
if (value) value.address.documentSteps += 1;
|
|
167
|
-
},
|
|
168
|
-
arrayCopied: () => {
|
|
169
|
-
const value = active.current;
|
|
170
|
-
if (value) value.address.arraysCopied += 1;
|
|
171
|
-
},
|
|
172
|
-
prefixComparison: () => {
|
|
173
|
-
const value = active.current;
|
|
174
|
-
if (value) value.address.prefixComparisons += 1;
|
|
175
|
-
},
|
|
176
|
-
segmentCompared: () => {
|
|
177
|
-
const value = active.current;
|
|
178
|
-
if (value) value.address.segmentsCompared += 1;
|
|
179
|
-
}
|
|
180
|
-
},
|
|
181
|
-
impact: { affects: () => {
|
|
182
|
-
const value = active.current;
|
|
183
|
-
if (value) value.impact.affectsChecks += 1;
|
|
184
|
-
} },
|
|
185
|
-
reader: {
|
|
186
|
-
session: () => {
|
|
187
|
-
const value = active.current;
|
|
188
|
-
if (value) value.reader.sessions += 1;
|
|
189
|
-
},
|
|
190
|
-
lookup: () => {
|
|
191
|
-
const value = active.current;
|
|
192
|
-
if (value) value.reader.nodeLookups += 1;
|
|
193
|
-
},
|
|
194
|
-
collectionIds: (amount = 1) => {
|
|
195
|
-
const value = active.current;
|
|
196
|
-
if (value) value.reader.collectionIds += amount;
|
|
197
|
-
},
|
|
198
|
-
structuralSnapshot: () => {
|
|
199
|
-
const value = active.current;
|
|
200
|
-
if (value) value.reader.structuralSnapshots += 1;
|
|
201
|
-
}
|
|
202
|
-
},
|
|
203
|
-
collectionView: {
|
|
204
|
-
mapped: () => {
|
|
205
|
-
const value = active.current;
|
|
206
|
-
if (value) value.collectionView.mappedItems += 1;
|
|
207
|
-
},
|
|
208
|
-
idsScanned: (amount = 1) => {
|
|
209
|
-
const value = active.current;
|
|
210
|
-
if (value) value.collectionView.idsScanned += amount;
|
|
211
|
-
},
|
|
212
|
-
arrayCopied: () => {
|
|
213
|
-
const value = active.current;
|
|
214
|
-
if (value) value.collectionView.arraysCopied += 1;
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
materialized: {
|
|
218
|
-
updated: () => {
|
|
219
|
-
const value = active.current;
|
|
220
|
-
if (value) value.materialized.updated += 1;
|
|
221
|
-
},
|
|
222
|
-
skipped: () => {
|
|
223
|
-
const value = active.current;
|
|
224
|
-
if (value) value.materialized.skipped += 1;
|
|
225
|
-
},
|
|
226
|
-
rebuilt: () => {
|
|
227
|
-
const value = active.current;
|
|
228
|
-
if (value) value.materialized.rebuilt += 1;
|
|
229
|
-
},
|
|
230
|
-
sourceChanged: () => {
|
|
231
|
-
const value = active.current;
|
|
232
|
-
if (value) value.materialized.sourceChanges += 1;
|
|
233
|
-
},
|
|
234
|
-
notification: () => {
|
|
235
|
-
const value = active.current;
|
|
236
|
-
if (value) value.materialized.notifications += 1;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
};
|
|
240
|
-
//#endregion
|
|
241
62
|
//#region core/src/address.ts
|
|
242
63
|
const registries = /* @__PURE__ */ new WeakMap();
|
|
243
64
|
const registryNode = () => ({ static: /* @__PURE__ */ new Map() });
|
|
@@ -257,14 +78,14 @@ const hashText = (value, seed) => {
|
|
|
257
78
|
return hash >>> 0;
|
|
258
79
|
};
|
|
259
80
|
const appendAddressHash = (hash, segment) => hashText(segment, hashText("/", hash));
|
|
260
|
-
const isRecord
|
|
81
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
261
82
|
const unwrap = (node) => {
|
|
262
83
|
let current = node;
|
|
263
84
|
while (current?.kind === "single") current = current.value;
|
|
264
85
|
return current;
|
|
265
86
|
};
|
|
266
87
|
const variantNode = (node, value) => {
|
|
267
|
-
const tag = isRecord
|
|
88
|
+
const tag = isRecord(value) && typeof value[node.tag] === "string" ? value[node.tag] : void 0;
|
|
268
89
|
return node.variants[String(tag ?? Object.keys(node.variants)[0] ?? "")];
|
|
269
90
|
};
|
|
270
91
|
const schemaRoot$1 = (schema) => ({
|
|
@@ -344,8 +165,8 @@ const nodeAt = (schema, address, document) => {
|
|
|
344
165
|
return unwrap(node);
|
|
345
166
|
};
|
|
346
167
|
const readSegment = (value, segment) => {
|
|
347
|
-
if (!isRecord
|
|
348
|
-
if (isRecord
|
|
168
|
+
if (!isRecord(value) && !Array.isArray(value)) return void 0;
|
|
169
|
+
if (isRecord(value) && "byId" in value && isRecord(value.byId)) {
|
|
349
170
|
const entity = value.byId[segment];
|
|
350
171
|
if (entity !== void 0 || Object.prototype.hasOwnProperty.call(value.byId, segment)) return entity;
|
|
351
172
|
}
|
|
@@ -386,7 +207,7 @@ const resolveLocated = (schema, root, address) => {
|
|
|
386
207
|
profile.address.documentStep();
|
|
387
208
|
const last = address[address.length - 1];
|
|
388
209
|
const resolved = step(node, current, last);
|
|
389
|
-
if (!resolved.node || !isRecord
|
|
210
|
+
if (!resolved.node || !isRecord(current) && !Array.isArray(current)) return void 0;
|
|
390
211
|
if (node?.kind === "table" || node?.kind === "map") collection = {
|
|
391
212
|
address: address.slice(0, -1),
|
|
392
213
|
addressHash,
|
|
@@ -394,7 +215,7 @@ const resolveLocated = (schema, root, address) => {
|
|
|
394
215
|
...collection ? { parent: collection } : {}
|
|
395
216
|
};
|
|
396
217
|
addressHash = appendAddressHash(addressHash, last);
|
|
397
|
-
if (isRecord
|
|
218
|
+
if (isRecord(current) && "byId" in current && isRecord(current.byId) && last in current.byId) return {
|
|
398
219
|
addressHash,
|
|
399
220
|
node: resolved.node,
|
|
400
221
|
parent: current.byId,
|
|
@@ -415,9 +236,9 @@ const locate = (root, address) => {
|
|
|
415
236
|
if (address.length === 0) return void 0;
|
|
416
237
|
let current = root;
|
|
417
238
|
for (let index = 0; index < address.length - 1; index += 1) current = readSegment(current, address[index]);
|
|
418
|
-
if (!isRecord
|
|
239
|
+
if (!isRecord(current) && !Array.isArray(current)) return void 0;
|
|
419
240
|
const last = address[address.length - 1];
|
|
420
|
-
if (isRecord
|
|
241
|
+
if (isRecord(current) && "byId" in current && isRecord(current.byId) && last in current.byId) return {
|
|
421
242
|
parent: current.byId,
|
|
422
243
|
key: last,
|
|
423
244
|
value: current.byId[last]
|
|
@@ -475,65 +296,6 @@ const same = (left, right) => {
|
|
|
475
296
|
};
|
|
476
297
|
const bucket = (target) => address(target)[0];
|
|
477
298
|
//#endregion
|
|
478
|
-
//#region core/src/value/ownership.ts
|
|
479
|
-
const stablePayloads = /* @__PURE__ */ new WeakSet();
|
|
480
|
-
const markStablePayload = (value) => {
|
|
481
|
-
if (Array.isArray(value) || isPlainObject(value)) stablePayloads.add(value);
|
|
482
|
-
return value;
|
|
483
|
-
};
|
|
484
|
-
const isStablePayload = (value) => (Array.isArray(value) || isPlainObject(value)) && stablePayloads.has(value);
|
|
485
|
-
const isPlainObject = (value) => {
|
|
486
|
-
if (value === null || typeof value !== "object") return false;
|
|
487
|
-
const prototype = Object.getPrototypeOf(value);
|
|
488
|
-
return prototype === Object.prototype || prototype === null;
|
|
489
|
-
};
|
|
490
|
-
const countCloneReason = (reason) => {
|
|
491
|
-
if (reason) profile.clone.node(reason);
|
|
492
|
-
};
|
|
493
|
-
const cloneValue = (value, reason) => {
|
|
494
|
-
profile.clone.call();
|
|
495
|
-
countCloneReason(reason);
|
|
496
|
-
if (Array.isArray(value)) {
|
|
497
|
-
profile.clone.container();
|
|
498
|
-
const result = new Array(value.length);
|
|
499
|
-
for (let index = 0; index < value.length; index += 1) result[index] = cloneValue(value[index], reason);
|
|
500
|
-
return reason === "commit" || reason === "inverse" || reason === "snapshot" ? markStablePayload(Object.freeze(result)) : result;
|
|
501
|
-
}
|
|
502
|
-
if (isPlainObject(value)) {
|
|
503
|
-
profile.clone.container();
|
|
504
|
-
const result = Object.create(Object.getPrototypeOf(value));
|
|
505
|
-
for (const key in value) if (Object.prototype.hasOwnProperty.call(value, key)) result[key] = cloneValue(value[key], reason);
|
|
506
|
-
return reason === "commit" || reason === "inverse" || reason === "snapshot" ? markStablePayload(Object.freeze(result)) : result;
|
|
507
|
-
}
|
|
508
|
-
return value;
|
|
509
|
-
};
|
|
510
|
-
const ownPayload = (value, reason = "canonical") => Array.isArray(value) || isPlainObject(value) ? cloneValue(value, reason) : value;
|
|
511
|
-
const transferPayload = (value) => {
|
|
512
|
-
profile.batch.payloadTransferred();
|
|
513
|
-
return value;
|
|
514
|
-
};
|
|
515
|
-
const snapshotPayload = (value, reason = "commit") => (profile.batch.payloadSnapshot(), ownPayload(value, reason));
|
|
516
|
-
const deepEqual = (left, right) => {
|
|
517
|
-
profile.clone.deepEqual();
|
|
518
|
-
if (Object.is(left, right)) return true;
|
|
519
|
-
if (Array.isArray(left) && Array.isArray(right)) {
|
|
520
|
-
profile.clone.deepEqualContainer();
|
|
521
|
-
if (left.length !== right.length) return false;
|
|
522
|
-
for (let index = 0; index < left.length; index += 1) if (!deepEqual(left[index], right[index])) return false;
|
|
523
|
-
return true;
|
|
524
|
-
}
|
|
525
|
-
if (isPlainObject(left) && isPlainObject(right)) {
|
|
526
|
-
profile.clone.deepEqualContainer();
|
|
527
|
-
const leftKeys = Object.keys(left);
|
|
528
|
-
if (leftKeys.length !== Object.keys(right).length) return false;
|
|
529
|
-
for (const key of leftKeys) if (!Object.prototype.hasOwnProperty.call(right, key) || !deepEqual(left[key], right[key])) return false;
|
|
530
|
-
return true;
|
|
531
|
-
}
|
|
532
|
-
return false;
|
|
533
|
-
};
|
|
534
|
-
const sameStructuralValue = (left, right) => Object.is(left, right) || (Array.isArray(left) || isPlainObject(left)) && deepEqual(left, right);
|
|
535
|
-
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
536
|
-
//#endregion
|
|
537
299
|
//#region core/src/access/reader.ts
|
|
538
300
|
const schemaRoot = (schema) => object(schema.shape);
|
|
539
301
|
const assertActive = (context) => {
|
|
@@ -591,30 +353,30 @@ const readerFor = (node, context, address = []) => {
|
|
|
591
353
|
rootId: () => {
|
|
592
354
|
collectValue(context, address);
|
|
593
355
|
const value = readAt(context, address);
|
|
594
|
-
return isRecord(value) && typeof value.rootId === "string" ? value.rootId : void 0;
|
|
356
|
+
return isRecord$1(value) && typeof value.rootId === "string" ? value.rootId : void 0;
|
|
595
357
|
},
|
|
596
358
|
has: (id) => {
|
|
597
359
|
collectValue(context, address);
|
|
598
360
|
const value = readAt(context, address);
|
|
599
|
-
return isRecord(value) && isRecord(value.nodes) && Object.prototype.hasOwnProperty.call(value.nodes, id);
|
|
361
|
+
return isRecord$1(value) && isRecord$1(value.nodes) && Object.prototype.hasOwnProperty.call(value.nodes, id);
|
|
600
362
|
},
|
|
601
363
|
value: (id) => {
|
|
602
364
|
collectValue(context, address);
|
|
603
365
|
const value = readAt(context, address);
|
|
604
366
|
profile.reader.structuralSnapshot();
|
|
605
|
-
return cloneValue(isRecord(value) && isRecord(value.nodes) && isRecord(value.nodes[id]) ? value.nodes[id].value : void 0, "reader");
|
|
367
|
+
return cloneValue(isRecord$1(value) && isRecord$1(value.nodes) && isRecord$1(value.nodes[id]) ? value.nodes[id].value : void 0, "reader");
|
|
606
368
|
},
|
|
607
369
|
parent: (id) => {
|
|
608
370
|
collectValue(context, address);
|
|
609
371
|
const value = readAt(context, address);
|
|
610
|
-
const entry = isRecord(value) && isRecord(value.nodes) ? value.nodes[id] : void 0;
|
|
611
|
-
return isRecord(entry) && typeof entry.parentId === "string" ? entry.parentId : void 0;
|
|
372
|
+
const entry = isRecord$1(value) && isRecord$1(value.nodes) ? value.nodes[id] : void 0;
|
|
373
|
+
return isRecord$1(entry) && typeof entry.parentId === "string" ? entry.parentId : void 0;
|
|
612
374
|
},
|
|
613
375
|
children: (id) => {
|
|
614
376
|
collectValue(context, address);
|
|
615
377
|
const value = readAt(context, address);
|
|
616
|
-
const entry = isRecord(value) && isRecord(value.nodes) ? value.nodes[id] : void 0;
|
|
617
|
-
return isRecord(entry) && Array.isArray(entry.children) ? [...entry.children] : [];
|
|
378
|
+
const entry = isRecord$1(value) && isRecord$1(value.nodes) ? value.nodes[id] : void 0;
|
|
379
|
+
return isRecord$1(entry) && Array.isArray(entry.children) ? [...entry.children] : [];
|
|
618
380
|
}
|
|
619
381
|
};
|
|
620
382
|
if (node.kind === "table" || node.kind === "map") {
|
|
@@ -623,21 +385,21 @@ const readerFor = (node, context, address = []) => {
|
|
|
623
385
|
ids: () => {
|
|
624
386
|
collectCollection(context, address);
|
|
625
387
|
const value = readAt(context, address);
|
|
626
|
-
const ids = node.kind === "table" && isRecord(value) && Array.isArray(value.ids) ? [...value.ids] : isRecord(value) ? Object.keys(value) : [];
|
|
388
|
+
const ids = node.kind === "table" && isRecord$1(value) && Array.isArray(value.ids) ? [...value.ids] : isRecord$1(value) ? Object.keys(value) : [];
|
|
627
389
|
profile.reader.collectionIds(ids.length);
|
|
628
390
|
return ids;
|
|
629
391
|
},
|
|
630
392
|
has: (id) => {
|
|
631
393
|
collectCollection(context, address, id);
|
|
632
394
|
const value = readAt(context, address);
|
|
633
|
-
const byId = node.kind === "table" && isRecord(value) && isRecord(value.byId) ? value.byId : value;
|
|
634
|
-
return isRecord(byId) && Object.prototype.hasOwnProperty.call(byId, id);
|
|
395
|
+
const byId = node.kind === "table" && isRecord$1(value) && isRecord$1(value.byId) ? value.byId : value;
|
|
396
|
+
return isRecord$1(byId) && Object.prototype.hasOwnProperty.call(byId, id);
|
|
635
397
|
},
|
|
636
398
|
get: (id) => {
|
|
637
399
|
collectCollection(context, address, id);
|
|
638
400
|
const value = readAt(context, address);
|
|
639
|
-
const byId = node.kind === "table" && isRecord(value) && isRecord(value.byId) ? value.byId : value;
|
|
640
|
-
if (!isRecord(byId) || !Object.prototype.hasOwnProperty.call(byId, id)) return void 0;
|
|
401
|
+
const byId = node.kind === "table" && isRecord$1(value) && isRecord$1(value.byId) ? value.byId : value;
|
|
402
|
+
if (!isRecord$1(byId) || !Object.prototype.hasOwnProperty.call(byId, id)) return void 0;
|
|
641
403
|
const cached = items?.get(id);
|
|
642
404
|
if (cached) return cached;
|
|
643
405
|
const reader = readerFor(node.value, context, [...address, id]);
|
|
@@ -650,7 +412,7 @@ const readerFor = (node, context, address = []) => {
|
|
|
650
412
|
if (node.kind === "variant") return new Proxy({}, { get: (_target, property) => {
|
|
651
413
|
if (typeof property === "symbol") return void 0;
|
|
652
414
|
const value = readAt(context, address);
|
|
653
|
-
const tag = isRecord(value) && typeof value[node.tag] === "string" ? String(value[node.tag]) : void 0;
|
|
415
|
+
const tag = isRecord$1(value) && typeof value[node.tag] === "string" ? String(value[node.tag]) : void 0;
|
|
654
416
|
const child = (tag ? node.variants[tag] : void 0)?.shape[property];
|
|
655
417
|
return child ? readerFor(child, context, [...address, property]) : void 0;
|
|
656
418
|
} });
|
|
@@ -713,6 +475,22 @@ const readWith = (runtime, run, dependencies) => {
|
|
|
713
475
|
}
|
|
714
476
|
};
|
|
715
477
|
//#endregion
|
|
716
|
-
|
|
478
|
+
//#region core/src/access/dependency.ts
|
|
479
|
+
const createDependencyTracker = () => {
|
|
480
|
+
const targets = [];
|
|
481
|
+
return {
|
|
482
|
+
record: (value) => {
|
|
483
|
+
if (!targets.some((entry) => same(entry, value))) targets.push(value);
|
|
484
|
+
},
|
|
485
|
+
clear: () => {
|
|
486
|
+
targets.length = 0;
|
|
487
|
+
},
|
|
488
|
+
size: () => targets.length,
|
|
489
|
+
some: (test) => targets.some(test),
|
|
490
|
+
snapshot: () => Object.freeze(targets.slice())
|
|
491
|
+
};
|
|
492
|
+
};
|
|
493
|
+
//#endregion
|
|
494
|
+
export { optional as A, resolveLocated as C, list as D, field as E, tree as F, variant as I, schema as M, single as N, map as O, table as P, resolveAddress as S, dict as T, debugKey as _, readWith as a, overlaps as b, DocumentReentrancyError as c, address as d, belongs as f, contains as g, impact_target_exports as h, documentOf as i, record as j, object as k, documentReader as l, id as m, accessOf as n, schemaOf as o, bucket as p, bindRuntimeAccess as r, DocumentDisposedError as s, createDependencyTracker as t, readerFor as u, locate as v, set as w, read as x, nodeAt as y };
|
|
717
495
|
|
|
718
|
-
//# sourceMappingURL=
|
|
496
|
+
//# sourceMappingURL=dependency-C5_R1tvQ.js.map
|