doxum 0.1.21 → 0.1.23
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 +35 -7
- package/dist/{advanced-FgdTwu5b.d.ts → advanced-CLJCWkHa.d.cts} +3 -3
- package/dist/{advanced-COFJtWMT.js → advanced-CRNHfJBu.js} +482 -446
- package/dist/advanced-CRNHfJBu.js.map +1 -0
- package/dist/{advanced-BRL5pN0y.cjs → advanced-Cle5g3B4.cjs} +615 -459
- package/dist/advanced-Cle5g3B4.cjs.map +1 -0
- package/dist/{advanced-DfKc7TZR.d.cts → advanced-d6J61er9.d.ts} +3 -3
- 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/context-BcLKGfq8.cjs +149 -0
- package/dist/context-BcLKGfq8.cjs.map +1 -0
- package/dist/context-DFEaDUv5.js +84 -0
- package/dist/context-DFEaDUv5.js.map +1 -0
- package/dist/{contract-CdmDHRUq.d.cts → contract-SYJFP0lM.d.cts} +62 -88
- package/dist/{contract-KG5XnQZt.d.ts → contract-ULPQmiEs.d.ts} +62 -88
- package/dist/driver-BD3DQOW6.cjs +382 -0
- package/dist/driver-BD3DQOW6.cjs.map +1 -0
- package/dist/{driver-CLYJOGDQ.js → driver-yFfvDMX5.js} +155 -26
- package/dist/driver-yFfvDMX5.js.map +1 -0
- package/dist/index.cjs +2370 -406
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -5
- package/dist/index.d.ts +6 -5
- package/dist/index.js +2293 -330
- package/dist/index.js.map +1 -1
- package/dist/local-sync.cjs +5 -5
- package/dist/local-sync.cjs.map +1 -1
- package/dist/local-sync.d.cts +1 -1
- package/dist/local-sync.d.ts +1 -1
- package/dist/local-sync.js +2 -2
- package/dist/local-sync.js.map +1 -1
- package/dist/react.cjs +2 -69
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +0 -1
- package/dist/react.d.ts +1 -2
- package/dist/react.js +3 -70
- package/dist/react.js.map +1 -1
- package/package.json +1 -6
- package/skills/doxum-runtime/SKILL.md +7 -1
- package/skills/doxum-runtime/references/guide.en.md +17 -6
- package/skills/doxum-runtime/references/guide.zh-CN.md +15 -5
- package/skills/doxum-runtime/references/invariants.en.md +5 -3
- package/skills/doxum-runtime/references/invariants.zh-CN.md +4 -3
- package/skills/doxum-runtime/references/projections.en.md +5 -0
- package/skills/doxum-runtime/references/projections.zh-CN.md +5 -0
- package/dist/access-BeSV5ve-.js +0 -816
- package/dist/access-BeSV5ve-.js.map +0 -1
- package/dist/access-Bienf28h.cjs +0 -911
- package/dist/access-Bienf28h.cjs.map +0 -1
- package/dist/advanced-BRL5pN0y.cjs.map +0 -1
- package/dist/advanced-COFJtWMT.js.map +0 -1
- package/dist/driver-CLYJOGDQ.js.map +0 -1
- package/dist/driver-Djr3BVvo.cjs +0 -241
- package/dist/driver-Djr3BVvo.cjs.map +0 -1
- package/dist/integration-C4Isp8lJ.js +0 -26
- package/dist/integration-C4Isp8lJ.js.map +0 -1
- package/dist/integration-Z6MsfFI7.cjs +0 -31
- package/dist/integration-Z6MsfFI7.cjs.map +0 -1
- package/dist/integration.cjs +0 -12
- package/dist/integration.d.cts +0 -17
- package/dist/integration.d.ts +0 -17
- package/dist/integration.js +0 -4
- package/dist/issue-DjK1xp5K.cjs +0 -881
- package/dist/issue-DjK1xp5K.cjs.map +0 -1
- package/dist/issue-W0hT8u8D.js +0 -642
- package/dist/issue-W0hT8u8D.js.map +0 -1
- package/dist/notification-Bkjau6B6.js +0 -232
- package/dist/notification-Bkjau6B6.js.map +0 -1
- package/dist/notification-DJfouMEb.cjs +0 -309
- package/dist/notification-DJfouMEb.cjs.map +0 -1
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
const require_issue = require("./issue-DjK1xp5K.cjs");
|
|
2
|
-
//#region core/src/impact-target.ts
|
|
3
|
-
const address = (target) => "at" in target ? target.at : target.address;
|
|
4
|
-
const id = (target) => target.kind === "collection" && "id" in target ? target.id : void 0;
|
|
5
|
-
const belongs = (target, schema) => !("schema" in target) || target.schema === schema;
|
|
6
|
-
const same = (left, right) => {
|
|
7
|
-
if (left.kind !== right.kind) return false;
|
|
8
|
-
if ("schema" in left && "schema" in right && left.schema !== right.schema) return false;
|
|
9
|
-
const leftAddress = address(left);
|
|
10
|
-
const rightAddress = address(right);
|
|
11
|
-
if (leftAddress.length !== rightAddress.length) return false;
|
|
12
|
-
for (let index = 0; index < leftAddress.length; index += 1) if (leftAddress[index] !== rightAddress[index]) return false;
|
|
13
|
-
return left.kind !== "collection" || id(left) === id(right);
|
|
14
|
-
};
|
|
15
|
-
const indexedAddress = (target) => {
|
|
16
|
-
const key = id(target);
|
|
17
|
-
return key === void 0 ? address(target) : [...address(target), key];
|
|
18
|
-
};
|
|
19
|
-
const affected = (target, values, orders) => {
|
|
20
|
-
const at = indexedAddress(target);
|
|
21
|
-
return id(target) !== void 0 ? values.hasAncestor(at) : values.overlaps(at) || orders.hasDescendant(at);
|
|
22
|
-
};
|
|
23
|
-
/** Targets are classified once; commit matching never builds a reverse impact index. */
|
|
24
|
-
var SubscriptionIndex = class {
|
|
25
|
-
ordinary = new require_issue.AddressIndex();
|
|
26
|
-
membership = new require_issue.AddressIndex();
|
|
27
|
-
constructor(schema) {
|
|
28
|
-
this.schema = schema;
|
|
29
|
-
}
|
|
30
|
-
add(target, value) {
|
|
31
|
-
if (belongs(target, this.schema)) (id(target) === void 0 ? this.ordinary : this.membership).add(indexedAddress(target), value);
|
|
32
|
-
}
|
|
33
|
-
delete(target, value) {
|
|
34
|
-
if (belongs(target, this.schema)) (id(target) === void 0 ? this.ordinary : this.membership).delete(indexedAddress(target), value);
|
|
35
|
-
}
|
|
36
|
-
collect(changes, visit) {
|
|
37
|
-
const values = this.ordinary.query(visit);
|
|
38
|
-
const members = this.membership.query(visit, "descendants");
|
|
39
|
-
const orders = this.ordinary.query(visit, "ancestors");
|
|
40
|
-
for (const change of changes.changes) if (change.kind === "reset") {
|
|
41
|
-
values([]);
|
|
42
|
-
members([]);
|
|
43
|
-
} else if (change.kind === "members") {
|
|
44
|
-
values(change.at, change.members);
|
|
45
|
-
members(change.at, change.members);
|
|
46
|
-
if (change.order) orders(change.at);
|
|
47
|
-
} else {
|
|
48
|
-
values(change.at);
|
|
49
|
-
members(change.at);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
clear() {
|
|
53
|
-
this.ordinary.clear();
|
|
54
|
-
this.membership.clear();
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
//#endregion
|
|
58
|
-
//#region core/src/runtime/notification.ts
|
|
59
|
-
const notifications = /* @__PURE__ */ new WeakMap();
|
|
60
|
-
const readableOwners = /* @__PURE__ */ new WeakMap();
|
|
61
|
-
const bindDocumentReadable = (readable, runtime) => {
|
|
62
|
-
readableOwners.set(readable, runtime);
|
|
63
|
-
};
|
|
64
|
-
const documentReadableOwner = (readable) => readableOwners.get(readable);
|
|
65
|
-
const createNotification = (runtime) => {
|
|
66
|
-
const notification = {
|
|
67
|
-
root: /* @__PURE__ */ new Set(),
|
|
68
|
-
filtered: /* @__PURE__ */ new Set(),
|
|
69
|
-
index: new SubscriptionIndex(runtime.schema),
|
|
70
|
-
cleanups: /* @__PURE__ */ new Set(),
|
|
71
|
-
processors: [],
|
|
72
|
-
candidates: /* @__PURE__ */ new Set(),
|
|
73
|
-
rootSnapshot: [],
|
|
74
|
-
notifying: false
|
|
75
|
-
};
|
|
76
|
-
notifications.set(runtime, notification);
|
|
77
|
-
return notification;
|
|
78
|
-
};
|
|
79
|
-
const notificationOf = (runtime) => {
|
|
80
|
-
const value = notifications.get(runtime);
|
|
81
|
-
if (!value) throw new Error("Unknown Doxum runtime.");
|
|
82
|
-
return value;
|
|
83
|
-
};
|
|
84
|
-
const shareNotification = (source, target) => {
|
|
85
|
-
notifications.set(target, notificationOf(source));
|
|
86
|
-
};
|
|
87
|
-
const attachProjection = (runtime, processor) => {
|
|
88
|
-
const notification = notificationOf(runtime);
|
|
89
|
-
const entry = {
|
|
90
|
-
processor,
|
|
91
|
-
active: true
|
|
92
|
-
};
|
|
93
|
-
notification.processors.push(entry);
|
|
94
|
-
return () => {
|
|
95
|
-
if (!entry.active) return;
|
|
96
|
-
entry.active = false;
|
|
97
|
-
if (!notification.notifying) {
|
|
98
|
-
const index = notification.processors.indexOf(entry);
|
|
99
|
-
if (index >= 0) notification.processors.splice(index, 1);
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
};
|
|
103
|
-
const subscribeRoot = (notification, listener) => {
|
|
104
|
-
const entry = {
|
|
105
|
-
listener,
|
|
106
|
-
active: true
|
|
107
|
-
};
|
|
108
|
-
notification.root.add(entry);
|
|
109
|
-
return () => {
|
|
110
|
-
entry.active = false;
|
|
111
|
-
if (!notification.notifying) notification.root.delete(entry);
|
|
112
|
-
else notification.cleanups.add(() => {
|
|
113
|
-
notification.root.delete(entry);
|
|
114
|
-
});
|
|
115
|
-
};
|
|
116
|
-
};
|
|
117
|
-
const subscribeTargets = (notification, targets, listener) => {
|
|
118
|
-
const entry = {
|
|
119
|
-
targets: Object.freeze(targets.slice()),
|
|
120
|
-
listener,
|
|
121
|
-
active: true
|
|
122
|
-
};
|
|
123
|
-
notification.filtered.add(entry);
|
|
124
|
-
entry.targets.forEach((value) => notification.index.add(value, entry));
|
|
125
|
-
const remove = () => {
|
|
126
|
-
notification.filtered.delete(entry);
|
|
127
|
-
entry.targets.forEach((value) => notification.index.delete(value, entry));
|
|
128
|
-
};
|
|
129
|
-
return () => {
|
|
130
|
-
if (!entry.active) return;
|
|
131
|
-
entry.active = false;
|
|
132
|
-
if (notification.notifying) notification.cleanups.add(remove);
|
|
133
|
-
else remove();
|
|
134
|
-
};
|
|
135
|
-
};
|
|
136
|
-
const notify = (notification, commit, afterSettle) => {
|
|
137
|
-
notification.notifying = true;
|
|
138
|
-
const errors = [];
|
|
139
|
-
const call = (listener) => {
|
|
140
|
-
try {
|
|
141
|
-
listener(commit);
|
|
142
|
-
} catch (error) {
|
|
143
|
-
errors.push(Object.freeze({
|
|
144
|
-
phase: "listener",
|
|
145
|
-
error
|
|
146
|
-
}));
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
try {
|
|
150
|
-
const processorCount = notification.processors.length;
|
|
151
|
-
for (let index = 0; index < processorCount; index += 1) {
|
|
152
|
-
const entry = notification.processors[index];
|
|
153
|
-
if (!entry?.active) continue;
|
|
154
|
-
try {
|
|
155
|
-
entry.processor.capture(commit);
|
|
156
|
-
} catch (error) {
|
|
157
|
-
errors.push(Object.freeze({
|
|
158
|
-
phase: "processor",
|
|
159
|
-
error
|
|
160
|
-
}));
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
for (let index = 0; index < processorCount; index += 1) {
|
|
164
|
-
const entry = notification.processors[index];
|
|
165
|
-
if (!entry?.active) continue;
|
|
166
|
-
try {
|
|
167
|
-
entry.processor.settle();
|
|
168
|
-
} catch (error) {
|
|
169
|
-
errors.push(Object.freeze({
|
|
170
|
-
phase: "processor",
|
|
171
|
-
error
|
|
172
|
-
}));
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
for (let index = 0; index < processorCount; index += 1) {
|
|
176
|
-
const entry = notification.processors[index];
|
|
177
|
-
if (!entry?.active) continue;
|
|
178
|
-
try {
|
|
179
|
-
errors.push(...entry.processor.flush());
|
|
180
|
-
} catch (error) {
|
|
181
|
-
errors.push(Object.freeze({
|
|
182
|
-
phase: "flush",
|
|
183
|
-
error
|
|
184
|
-
}));
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
if (afterSettle) errors.push(...afterSettle());
|
|
188
|
-
const candidates = notification.candidates;
|
|
189
|
-
candidates.clear();
|
|
190
|
-
if (notification.filtered.size) notification.index.collect(commit.changes, (entry) => candidates.add(entry));
|
|
191
|
-
candidates.forEach((entry) => {
|
|
192
|
-
if (entry.active) call(entry.listener);
|
|
193
|
-
});
|
|
194
|
-
const rootSnapshot = notification.rootSnapshot;
|
|
195
|
-
rootSnapshot.length = 0;
|
|
196
|
-
notification.root.forEach((entry) => rootSnapshot.push(entry));
|
|
197
|
-
for (const entry of rootSnapshot) if (entry.active) call(entry.listener);
|
|
198
|
-
} finally {
|
|
199
|
-
notification.notifying = false;
|
|
200
|
-
let writeIndex = 0;
|
|
201
|
-
for (const entry of notification.processors) if (entry.active) notification.processors[writeIndex++] = entry;
|
|
202
|
-
notification.processors.length = writeIndex;
|
|
203
|
-
notification.cleanups.forEach((cleanup) => cleanup());
|
|
204
|
-
notification.cleanups.clear();
|
|
205
|
-
}
|
|
206
|
-
return Object.freeze(errors);
|
|
207
|
-
};
|
|
208
|
-
const subscribeDependencies = (runtime, targets, listener) => subscribeTargets(notificationOf(runtime), targets, listener);
|
|
209
|
-
const disposeNotification = (notification) => {
|
|
210
|
-
const attachments = notification.processors.slice();
|
|
211
|
-
notification.root.clear();
|
|
212
|
-
notification.filtered.clear();
|
|
213
|
-
notification.index.clear();
|
|
214
|
-
notification.cleanups.clear();
|
|
215
|
-
notification.processors.length = 0;
|
|
216
|
-
notification.candidates.clear();
|
|
217
|
-
notification.rootSnapshot.length = 0;
|
|
218
|
-
const errors = [];
|
|
219
|
-
attachments.forEach((entry) => {
|
|
220
|
-
if (!entry.active) return;
|
|
221
|
-
try {
|
|
222
|
-
entry.processor.dispose();
|
|
223
|
-
} catch (error) {
|
|
224
|
-
errors.push(error);
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
if (errors.length) throw new AggregateError(errors, "Projection disposal notification failed.");
|
|
228
|
-
};
|
|
229
|
-
//#endregion
|
|
230
|
-
Object.defineProperty(exports, "affected", {
|
|
231
|
-
enumerable: true,
|
|
232
|
-
get: function() {
|
|
233
|
-
return affected;
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
Object.defineProperty(exports, "attachProjection", {
|
|
237
|
-
enumerable: true,
|
|
238
|
-
get: function() {
|
|
239
|
-
return attachProjection;
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
Object.defineProperty(exports, "belongs", {
|
|
243
|
-
enumerable: true,
|
|
244
|
-
get: function() {
|
|
245
|
-
return belongs;
|
|
246
|
-
}
|
|
247
|
-
});
|
|
248
|
-
Object.defineProperty(exports, "bindDocumentReadable", {
|
|
249
|
-
enumerable: true,
|
|
250
|
-
get: function() {
|
|
251
|
-
return bindDocumentReadable;
|
|
252
|
-
}
|
|
253
|
-
});
|
|
254
|
-
Object.defineProperty(exports, "createNotification", {
|
|
255
|
-
enumerable: true,
|
|
256
|
-
get: function() {
|
|
257
|
-
return createNotification;
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
Object.defineProperty(exports, "disposeNotification", {
|
|
261
|
-
enumerable: true,
|
|
262
|
-
get: function() {
|
|
263
|
-
return disposeNotification;
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
Object.defineProperty(exports, "documentReadableOwner", {
|
|
267
|
-
enumerable: true,
|
|
268
|
-
get: function() {
|
|
269
|
-
return documentReadableOwner;
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
Object.defineProperty(exports, "notify", {
|
|
273
|
-
enumerable: true,
|
|
274
|
-
get: function() {
|
|
275
|
-
return notify;
|
|
276
|
-
}
|
|
277
|
-
});
|
|
278
|
-
Object.defineProperty(exports, "same", {
|
|
279
|
-
enumerable: true,
|
|
280
|
-
get: function() {
|
|
281
|
-
return same;
|
|
282
|
-
}
|
|
283
|
-
});
|
|
284
|
-
Object.defineProperty(exports, "shareNotification", {
|
|
285
|
-
enumerable: true,
|
|
286
|
-
get: function() {
|
|
287
|
-
return shareNotification;
|
|
288
|
-
}
|
|
289
|
-
});
|
|
290
|
-
Object.defineProperty(exports, "subscribeDependencies", {
|
|
291
|
-
enumerable: true,
|
|
292
|
-
get: function() {
|
|
293
|
-
return subscribeDependencies;
|
|
294
|
-
}
|
|
295
|
-
});
|
|
296
|
-
Object.defineProperty(exports, "subscribeRoot", {
|
|
297
|
-
enumerable: true,
|
|
298
|
-
get: function() {
|
|
299
|
-
return subscribeRoot;
|
|
300
|
-
}
|
|
301
|
-
});
|
|
302
|
-
Object.defineProperty(exports, "subscribeTargets", {
|
|
303
|
-
enumerable: true,
|
|
304
|
-
get: function() {
|
|
305
|
-
return subscribeTargets;
|
|
306
|
-
}
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
//# sourceMappingURL=notification-DJfouMEb.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"notification-DJfouMEb.cjs","names":["AddressIndex","target.SubscriptionIndex"],"sources":["../core/src/impact-target.ts","../core/src/runtime/notification.ts"],"sourcesContent":["import type { DocumentAddress, ObjectNode, ImpactTarget } from './schema';\nimport type { ChangeSet } from './changes';\nimport { AddressIndex } from './address';\n\nexport const address = (target: ImpactTarget<unknown>): DocumentAddress =>\n 'at' in target ? target.at : target.address;\n\nexport const id = (target: ImpactTarget<unknown>): string | undefined =>\n target.kind === 'collection' && 'id' in target ? target.id : undefined;\n\nexport const belongs = (target: ImpactTarget<unknown>, schema: ObjectNode): boolean =>\n !('schema' in target) || target.schema === schema;\n\nexport const same = (left: ImpactTarget<unknown>, right: ImpactTarget<unknown>): boolean => {\n if (left.kind !== right.kind) return false;\n if ('schema' in left && 'schema' in right && left.schema !== right.schema) return false;\n const leftAddress = address(left);\n const rightAddress = address(right);\n if (leftAddress.length !== rightAddress.length) return false;\n for (let index = 0; index < leftAddress.length; index += 1)\n if (leftAddress[index] !== rightAddress[index]) return false;\n return left.kind !== 'collection' || id(left) === id(right);\n};\n\nexport const indexedAddress = (target: ImpactTarget<unknown>): DocumentAddress => {\n const key = id(target);\n return key === undefined ? address(target) : [...address(target), key];\n};\n\nexport const affected = (\n target: ImpactTarget,\n values: AddressIndex<true>,\n orders: AddressIndex<true>\n): boolean => {\n const at = indexedAddress(target);\n return id(target) !== undefined\n ? values.hasAncestor(at)\n : values.overlaps(at) || orders.hasDescendant(at);\n};\n\n/** Targets are classified once; commit matching never builds a reverse impact index. */\nexport class SubscriptionIndex<T> {\n private readonly ordinary = new AddressIndex<T>();\n private readonly membership = new AddressIndex<T>();\n constructor(private readonly schema: ObjectNode) {}\n add(target: ImpactTarget, value: T): void {\n if (belongs(target, this.schema))\n (id(target) === undefined ? this.ordinary : this.membership).add(\n indexedAddress(target),\n value\n );\n }\n delete(target: ImpactTarget, value: T): void {\n if (belongs(target, this.schema))\n (id(target) === undefined ? this.ordinary : this.membership).delete(\n indexedAddress(target),\n value\n );\n }\n collect(changes: ChangeSet, visit: (value: T) => void): void {\n const values = this.ordinary.query(visit);\n const members = this.membership.query(visit, 'descendants');\n const orders = this.ordinary.query(visit, 'ancestors');\n for (const change of changes.changes) {\n if (change.kind === 'reset') {\n values([]);\n members([]);\n } else if (change.kind === 'members') {\n values(change.at, change.members);\n members(change.at, change.members);\n if (change.order) orders(change.at);\n } else {\n values(change.at);\n members(change.at);\n }\n }\n }\n clear(): void {\n this.ordinary.clear();\n this.membership.clear();\n }\n}\n","import type { ObjectNode, ImpactTarget } from '../schema';\nimport type {\n CommitListener,\n DocumentCommit,\n DocumentReadable,\n DocumentRuntime,\n Unsubscribe,\n ObserverError,\n} from './contract';\nimport * as target from '../impact-target';\n\nexport type ProjectionAttachment<TSchema extends ObjectNode> = {\n capture(commit: DocumentCommit<TSchema>): void;\n settle(): void;\n flush(): readonly ObserverError[];\n dispose(): void;\n};\ntype ProcessorEntry<TSchema extends ObjectNode> = {\n readonly processor: ProjectionAttachment<TSchema>;\n active: boolean;\n};\ntype RootEntry<TSchema extends ObjectNode> = {\n readonly listener: CommitListener<TSchema>;\n active: boolean;\n};\ntype FilteredEntry<TSchema extends ObjectNode> = {\n readonly targets: readonly ImpactTarget<unknown>[];\n readonly listener: CommitListener<TSchema>;\n active: boolean;\n};\nexport type RuntimeNotification<TSchema extends ObjectNode> = {\n readonly root: Set<RootEntry<TSchema>>;\n readonly filtered: Set<FilteredEntry<TSchema>>;\n readonly index: target.SubscriptionIndex<FilteredEntry<TSchema>>;\n readonly cleanups: Set<() => void>;\n readonly processors: ProcessorEntry<TSchema>[];\n readonly candidates: Set<FilteredEntry<TSchema>>;\n readonly rootSnapshot: RootEntry<TSchema>[];\n notifying: boolean;\n};\n\nconst notifications = new WeakMap<object, RuntimeNotification<ObjectNode>>();\nconst readableOwners = new WeakMap<object, DocumentReadable<ObjectNode>>();\n\nexport const bindDocumentReadable = (\n readable: object,\n runtime: DocumentReadable<ObjectNode>\n): void => {\n readableOwners.set(readable, runtime);\n};\nexport const documentReadableOwner = (readable: object): DocumentReadable<ObjectNode> | undefined =>\n readableOwners.get(readable);\n\nexport const createNotification = <TSchema extends ObjectNode>(\n runtime: DocumentRuntime<TSchema>\n): RuntimeNotification<TSchema> => {\n const notification: RuntimeNotification<TSchema> = {\n root: new Set(),\n filtered: new Set(),\n index: new target.SubscriptionIndex(runtime.schema),\n cleanups: new Set(),\n processors: [],\n candidates: new Set(),\n rootSnapshot: [],\n notifying: false,\n };\n notifications.set(runtime as object, notification as RuntimeNotification<ObjectNode>);\n return notification;\n};\n\nconst notificationOf = <TSchema extends ObjectNode>(\n runtime: DocumentReadable<TSchema>\n): RuntimeNotification<TSchema> => {\n const value = notifications.get(runtime as object);\n if (!value) throw new Error('Unknown Doxum runtime.');\n return value as RuntimeNotification<TSchema>;\n};\n\nexport const shareNotification = <TSchema extends ObjectNode>(\n source: DocumentRuntime<TSchema>,\n target: DocumentReadable<TSchema>\n): void => {\n notifications.set(target as object, notificationOf(source) as RuntimeNotification<ObjectNode>);\n};\n\nexport const attachProjection = <TSchema extends ObjectNode>(\n runtime: DocumentReadable<TSchema>,\n processor: ProjectionAttachment<TSchema>\n): Unsubscribe => {\n const notification = notificationOf(runtime);\n const entry: ProcessorEntry<TSchema> = { processor, active: true };\n notification.processors.push(entry);\n return () => {\n if (!entry.active) return;\n entry.active = false;\n if (!notification.notifying) {\n const index = notification.processors.indexOf(entry);\n if (index >= 0) notification.processors.splice(index, 1);\n }\n };\n};\n\nexport const subscribeRoot = <TSchema extends ObjectNode>(\n notification: RuntimeNotification<TSchema>,\n listener: CommitListener<TSchema>\n): Unsubscribe => {\n const entry: RootEntry<TSchema> = { listener, active: true };\n notification.root.add(entry);\n return () => {\n entry.active = false;\n if (!notification.notifying) notification.root.delete(entry);\n else\n notification.cleanups.add(() => {\n notification.root.delete(entry);\n });\n };\n};\n\nexport const subscribeTargets = <TSchema extends ObjectNode>(\n notification: RuntimeNotification<TSchema>,\n targets: readonly ImpactTarget<unknown>[],\n listener: CommitListener<TSchema>\n): Unsubscribe => {\n const entry: FilteredEntry<TSchema> = {\n targets: Object.freeze(targets.slice()),\n listener,\n active: true,\n };\n notification.filtered.add(entry);\n entry.targets.forEach(value => notification.index.add(value, entry));\n const remove = () => {\n notification.filtered.delete(entry);\n entry.targets.forEach(value => notification.index.delete(value, entry));\n };\n return () => {\n if (!entry.active) return;\n entry.active = false;\n if (notification.notifying) notification.cleanups.add(remove);\n else remove();\n };\n};\n\nexport const notify = <TSchema extends ObjectNode>(\n notification: RuntimeNotification<TSchema>,\n commit: DocumentCommit<TSchema>,\n afterSettle?: () => readonly ObserverError[]\n): readonly ObserverError[] => {\n notification.notifying = true;\n const errors: ObserverError[] = [];\n const call = (listener: CommitListener<TSchema>): void => {\n try {\n listener(commit);\n } catch (error) {\n errors.push(Object.freeze({ phase: 'listener', error }));\n }\n };\n try {\n const processorCount = notification.processors.length;\n for (let index = 0; index < processorCount; index += 1) {\n const entry = notification.processors[index];\n if (!entry?.active) continue;\n try {\n entry.processor.capture(commit);\n } catch (error) {\n errors.push(Object.freeze({ phase: 'processor', error }));\n }\n }\n for (let index = 0; index < processorCount; index += 1) {\n const entry = notification.processors[index];\n if (!entry?.active) continue;\n try {\n entry.processor.settle();\n } catch (error) {\n errors.push(Object.freeze({ phase: 'processor', error }));\n }\n }\n for (let index = 0; index < processorCount; index += 1) {\n const entry = notification.processors[index];\n if (!entry?.active) continue;\n try {\n errors.push(...entry.processor.flush());\n } catch (error) {\n errors.push(Object.freeze({ phase: 'flush', error }));\n }\n }\n\n if (afterSettle) errors.push(...afterSettle());\n const candidates = notification.candidates;\n candidates.clear();\n if (notification.filtered.size)\n notification.index.collect(commit.changes, entry => candidates.add(entry));\n candidates.forEach(entry => {\n if (entry.active) call(entry.listener);\n });\n const rootSnapshot = notification.rootSnapshot;\n rootSnapshot.length = 0;\n notification.root.forEach(entry => rootSnapshot.push(entry));\n for (const entry of rootSnapshot) if (entry.active) call(entry.listener);\n } finally {\n notification.notifying = false;\n let writeIndex = 0;\n for (const entry of notification.processors)\n if (entry.active) notification.processors[writeIndex++] = entry;\n notification.processors.length = writeIndex;\n notification.cleanups.forEach(cleanup => cleanup());\n notification.cleanups.clear();\n }\n return Object.freeze(errors);\n};\n\nexport const subscribeDependencies = <S extends ObjectNode>(\n runtime: DocumentReadable<S>,\n targets: readonly ImpactTarget[],\n listener: CommitListener<S>\n): Unsubscribe => subscribeTargets(notificationOf(runtime), targets, listener);\n\nexport const disposeNotification = <TSchema extends ObjectNode>(\n notification: RuntimeNotification<TSchema>\n): void => {\n const attachments = notification.processors.slice();\n notification.root.clear();\n notification.filtered.clear();\n notification.index.clear();\n notification.cleanups.clear();\n notification.processors.length = 0;\n notification.candidates.clear();\n notification.rootSnapshot.length = 0;\n const errors: unknown[] = [];\n attachments.forEach(entry => {\n if (!entry.active) return;\n try {\n entry.processor.dispose();\n } catch (error) {\n errors.push(error);\n }\n });\n if (errors.length) throw new AggregateError(errors, 'Projection disposal notification failed.');\n};\n"],"mappings":"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"}
|