@rocicorp/zero 0.3.2024102502 → 0.3.2024102800
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/out/{chunk-2RUT5EQV.js → chunk-F5QR3K72.js} +2 -7
- package/out/chunk-F5QR3K72.js.map +7 -0
- package/out/chunk-HARIWJ2J.js +8 -0
- package/out/{chunk-2RUT5EQV.js.map → chunk-HARIWJ2J.js.map} +1 -1
- package/out/chunk-NKGIR6IA.js +1 -0
- package/out/chunk-NKGIR6IA.js.map +7 -0
- package/out/chunk-RCVGGCMG.js +288 -0
- package/out/chunk-RCVGGCMG.js.map +7 -0
- package/out/internal.js +9 -0
- package/out/internal.js.map +7 -0
- package/out/react.js +5 -4
- package/out/react.js.map +2 -2
- package/out/replicache/src/version.d.ts.map +1 -1
- package/out/replicache/src/version.js +2 -1
- package/out/replicache/src/version.js.map +1 -1
- package/out/solid.js +84 -0
- package/out/solid.js.map +7 -0
- package/out/zero/src/internal.d.ts +2 -0
- package/out/zero/src/internal.d.ts.map +1 -0
- package/out/zero/src/solid.d.ts +2 -0
- package/out/zero/src/solid.d.ts.map +1 -0
- package/out/zero-cache/src/config/config-query.d.ts +2 -2
- package/out/zero-cache/src/config/config-query.d.ts.map +1 -1
- package/out/zero-cache/src/config/config-query.js +1 -1
- package/out/zero-cache/src/config/config-query.js.map +1 -1
- package/out/zero-cache/src/server/life-cycle.d.ts +2 -0
- package/out/zero-cache/src/server/life-cycle.d.ts.map +1 -1
- package/out/zero-cache/src/server/life-cycle.js +37 -21
- package/out/zero-cache/src/server/life-cycle.js.map +1 -1
- package/out/zero-cache/src/server/main.js +2 -7
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/pg/schema/ddl.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/pg/schema/ddl.js +9 -1
- package/out/zero-cache/src/services/change-streamer/pg/schema/ddl.js.map +1 -1
- package/out/zero-cache/src/services/dispatcher/dispatcher.d.ts +2 -2
- package/out/zero-cache/src/services/dispatcher/dispatcher.d.ts.map +1 -1
- package/out/zero-cache/src/services/dispatcher/dispatcher.js +1 -0
- package/out/zero-cache/src/services/dispatcher/dispatcher.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +10 -4
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/query-manager.js +2 -5
- package/out/zero-client/src/client/query-manager.js.map +1 -1
- package/out/zero-client/src/client/version.d.ts.map +1 -1
- package/out/zero-client/src/client/version.js +2 -1
- package/out/zero-client/src/client/version.js.map +1 -1
- package/out/zero-internal/src/mod.d.ts +8 -0
- package/out/zero-internal/src/mod.d.ts.map +1 -0
- package/out/zero-protocol/src/ast-hash.d.ts +3 -0
- package/out/zero-protocol/src/ast-hash.d.ts.map +1 -0
- package/out/zero-protocol/src/ast-hash.js +14 -0
- package/out/zero-protocol/src/ast-hash.js.map +1 -0
- package/out/zero-protocol/src/ast.d.ts.map +1 -1
- package/out/zero-protocol/src/ast.js +8 -1
- package/out/zero-protocol/src/ast.js.map +1 -1
- package/out/zero-react/src/use-query.d.ts.map +1 -1
- package/out/zero-solid/src/mod.d.ts +2 -0
- package/out/zero-solid/src/mod.d.ts.map +1 -0
- package/out/zero-solid/src/solid-view.d.ts +10 -0
- package/out/zero-solid/src/solid-view.d.ts.map +1 -0
- package/out/zero-solid/src/use-query.d.ts +4 -0
- package/out/zero-solid/src/use-query.d.ts.map +1 -0
- package/out/zero.js +445 -673
- package/out/zero.js.map +4 -4
- package/out/zql/src/zql/ivm/array-view.d.ts +1 -10
- package/out/zql/src/zql/ivm/array-view.d.ts.map +1 -1
- package/out/zql/src/zql/ivm/array-view.js +2 -158
- package/out/zql/src/zql/ivm/array-view.js.map +1 -1
- package/out/zql/src/zql/ivm/view-apply-change.d.ts +5 -0
- package/out/zql/src/zql/ivm/view-apply-change.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/view-apply-change.js +156 -0
- package/out/zql/src/zql/ivm/view-apply-change.js.map +1 -0
- package/out/zql/src/zql/ivm/view.d.ts +15 -0
- package/out/zql/src/zql/ivm/view.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/view.js +2 -0
- package/out/zql/src/zql/ivm/view.js.map +1 -0
- package/out/zql/src/zql/query/query-impl.d.ts +11 -12
- package/out/zql/src/zql/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/zql/query/query-impl.js +51 -37
- package/out/zql/src/zql/query/query-impl.js.map +1 -1
- package/out/zql/src/zql/query/query-internal.d.ts +11 -0
- package/out/zql/src/zql/query/query-internal.d.ts.map +1 -0
- package/out/zql/src/zql/query/query-internal.js +2 -0
- package/out/zql/src/zql/query/query-internal.js.map +1 -0
- package/out/zql/src/zql/query/query.d.ts +0 -2
- package/out/zql/src/zql/query/query.d.ts.map +1 -1
- package/package.json +9 -1
|
@@ -16,13 +16,8 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
};
|
|
17
17
|
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
18
18
|
|
|
19
|
-
// ../shared/src/has-own.ts
|
|
20
|
-
var objectPrototypeHasOwnProperty = Object.prototype.hasOwnProperty;
|
|
21
|
-
var hasOwn = Object.hasOwn || ((object, key) => objectPrototypeHasOwnProperty.call(object, key));
|
|
22
|
-
|
|
23
19
|
export {
|
|
24
20
|
__export,
|
|
25
|
-
__reExport
|
|
26
|
-
hasOwn
|
|
21
|
+
__reExport
|
|
27
22
|
};
|
|
28
|
-
//# sourceMappingURL=chunk-
|
|
23
|
+
//# sourceMappingURL=chunk-F5QR3K72.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// ../shared/src/has-own.ts
|
|
2
|
+
var objectPrototypeHasOwnProperty = Object.prototype.hasOwnProperty;
|
|
3
|
+
var hasOwn = Object.hasOwn || ((object, key) => objectPrototypeHasOwnProperty.call(object, key));
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
hasOwn
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=chunk-HARIWJ2J.js.map
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../shared/src/has-own.ts"],
|
|
4
4
|
"sourcesContent": ["/* eslint-disable @typescript-eslint/no-explicit-any */\nconst objectPrototypeHasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * Object.hasOwn polyfill\n */\nexport const hasOwn: (object: any, key: PropertyKey) => boolean =\n (Object as any).hasOwn ||\n ((object, key) => objectPrototypeHasOwnProperty.call(object, key));\n"],
|
|
5
|
-
"mappings": "
|
|
5
|
+
"mappings": ";AACA,IAAM,gCAAgC,OAAO,UAAU;AAKhD,IAAM,SACV,OAAe,WACf,CAAC,QAAQ,QAAQ,8BAA8B,KAAK,QAAQ,GAAG;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=chunk-NKGIR6IA.js.map
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
// ../shared/src/asserts.ts
|
|
2
|
+
function assert(b, msg = "Assertion failed") {
|
|
3
|
+
if (!b) {
|
|
4
|
+
throw new Error(msg);
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
function assertString(v) {
|
|
8
|
+
assertType(v, "string");
|
|
9
|
+
}
|
|
10
|
+
function assertNumber(v) {
|
|
11
|
+
assertType(v, "number");
|
|
12
|
+
}
|
|
13
|
+
function assertBoolean(v) {
|
|
14
|
+
assertType(v, "boolean");
|
|
15
|
+
}
|
|
16
|
+
function assertType(v, t) {
|
|
17
|
+
if (typeof v !== t) {
|
|
18
|
+
throwInvalidType(v, t);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function assertObject(v) {
|
|
22
|
+
if (v === null) {
|
|
23
|
+
throwInvalidType(v, "object");
|
|
24
|
+
}
|
|
25
|
+
assertType(v, "object");
|
|
26
|
+
}
|
|
27
|
+
function assertArray(v) {
|
|
28
|
+
if (!Array.isArray(v)) {
|
|
29
|
+
throwInvalidType(v, "array");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function invalidType(v, t) {
|
|
33
|
+
let s = "Invalid type: ";
|
|
34
|
+
if (v === null || v === void 0) {
|
|
35
|
+
s += v;
|
|
36
|
+
} else {
|
|
37
|
+
s += `${typeof v} \`${v}\``;
|
|
38
|
+
}
|
|
39
|
+
return s + `, expected ${t}`;
|
|
40
|
+
}
|
|
41
|
+
function throwInvalidType(v, t) {
|
|
42
|
+
throw new Error(invalidType(v, t));
|
|
43
|
+
}
|
|
44
|
+
function assertNotNull(v) {
|
|
45
|
+
if (v === null) {
|
|
46
|
+
throw new Error("Expected non-null value");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function assertUndefined(v, msg = "Expected undefined value") {
|
|
50
|
+
if (v !== void 0) {
|
|
51
|
+
throw new Error(msg);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function assertNotUndefined(v, msg = "Expected non undefined value") {
|
|
55
|
+
if (v === void 0) {
|
|
56
|
+
throw new Error(msg);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function unreachable(_) {
|
|
60
|
+
throw new Error("Unreachable");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ../shared/src/must.ts
|
|
64
|
+
function must(v, msg) {
|
|
65
|
+
if (v == null) {
|
|
66
|
+
throw new Error(msg ?? `Unexpected ${v} value`);
|
|
67
|
+
}
|
|
68
|
+
return v;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ../zql/src/zql/ivm/view-apply-change.ts
|
|
72
|
+
function applyChange(parentEntry, change, schema, relationship, format) {
|
|
73
|
+
if (schema.isHidden) {
|
|
74
|
+
switch (change.type) {
|
|
75
|
+
case "add":
|
|
76
|
+
case "remove":
|
|
77
|
+
for (const [relationship2, children] of Object.entries(
|
|
78
|
+
change.node.relationships
|
|
79
|
+
)) {
|
|
80
|
+
const childSchema = must(schema.relationships[relationship2]);
|
|
81
|
+
for (const node of children) {
|
|
82
|
+
applyChange(
|
|
83
|
+
parentEntry,
|
|
84
|
+
{ type: change.type, node },
|
|
85
|
+
childSchema,
|
|
86
|
+
relationship2,
|
|
87
|
+
format
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return;
|
|
92
|
+
case "edit":
|
|
93
|
+
return;
|
|
94
|
+
case "child": {
|
|
95
|
+
const childSchema = must(
|
|
96
|
+
schema.relationships[change.child.relationshipName]
|
|
97
|
+
);
|
|
98
|
+
applyChange(
|
|
99
|
+
parentEntry,
|
|
100
|
+
change.child.change,
|
|
101
|
+
childSchema,
|
|
102
|
+
relationship,
|
|
103
|
+
format
|
|
104
|
+
);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
default:
|
|
108
|
+
unreachable(change);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const { singular, relationships: childFormats } = format;
|
|
112
|
+
switch (change.type) {
|
|
113
|
+
case "add": {
|
|
114
|
+
const newEntry = {
|
|
115
|
+
...change.node.row
|
|
116
|
+
};
|
|
117
|
+
if (singular) {
|
|
118
|
+
assertUndefined(
|
|
119
|
+
parentEntry[relationship],
|
|
120
|
+
"single output already exists"
|
|
121
|
+
);
|
|
122
|
+
parentEntry[relationship] = newEntry;
|
|
123
|
+
} else {
|
|
124
|
+
const view = parentEntry[relationship];
|
|
125
|
+
assertArray(view);
|
|
126
|
+
const { pos, found } = binarySearch(view, newEntry, schema.compareRows);
|
|
127
|
+
assert(!found, "node already exists");
|
|
128
|
+
view.splice(pos, 0, newEntry);
|
|
129
|
+
}
|
|
130
|
+
for (const [relationship2, children] of Object.entries(
|
|
131
|
+
change.node.relationships
|
|
132
|
+
)) {
|
|
133
|
+
const childSchema = must(schema.relationships[relationship2]);
|
|
134
|
+
const childFormat = must(childFormats[relationship2]);
|
|
135
|
+
const newView = childFormat.singular ? void 0 : [];
|
|
136
|
+
newEntry[relationship2] = newView;
|
|
137
|
+
for (const node of children) {
|
|
138
|
+
applyChange(
|
|
139
|
+
newEntry,
|
|
140
|
+
{ type: "add", node },
|
|
141
|
+
childSchema,
|
|
142
|
+
relationship2,
|
|
143
|
+
childFormat
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
case "remove": {
|
|
150
|
+
if (singular) {
|
|
151
|
+
assertObject(parentEntry[relationship]);
|
|
152
|
+
parentEntry[relationship] = void 0;
|
|
153
|
+
} else {
|
|
154
|
+
assertArray(parentEntry[relationship]);
|
|
155
|
+
const view = parentEntry[relationship];
|
|
156
|
+
const { pos, found } = binarySearch(
|
|
157
|
+
view,
|
|
158
|
+
change.node.row,
|
|
159
|
+
schema.compareRows
|
|
160
|
+
);
|
|
161
|
+
assert(found, "node does not exist");
|
|
162
|
+
view.splice(pos, 1);
|
|
163
|
+
}
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
case "child": {
|
|
167
|
+
let existing;
|
|
168
|
+
if (singular) {
|
|
169
|
+
assertObject(parentEntry[relationship]);
|
|
170
|
+
existing = parentEntry[relationship];
|
|
171
|
+
} else {
|
|
172
|
+
assertArray(parentEntry[relationship]);
|
|
173
|
+
const list = parentEntry[relationship];
|
|
174
|
+
const { pos, found } = binarySearch(list, change.row, schema.compareRows);
|
|
175
|
+
assert(found, "node does not exist");
|
|
176
|
+
existing = list[pos];
|
|
177
|
+
}
|
|
178
|
+
const childSchema = must(
|
|
179
|
+
schema.relationships[change.child.relationshipName]
|
|
180
|
+
);
|
|
181
|
+
const childFormat = must(
|
|
182
|
+
format.relationships[change.child.relationshipName]
|
|
183
|
+
);
|
|
184
|
+
applyChange(
|
|
185
|
+
existing,
|
|
186
|
+
change.child.change,
|
|
187
|
+
childSchema,
|
|
188
|
+
change.child.relationshipName,
|
|
189
|
+
childFormat
|
|
190
|
+
);
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
case "edit": {
|
|
194
|
+
if (singular) {
|
|
195
|
+
assertObject(parentEntry[relationship]);
|
|
196
|
+
parentEntry[relationship] = {
|
|
197
|
+
...parentEntry[relationship],
|
|
198
|
+
...change.row
|
|
199
|
+
};
|
|
200
|
+
} else {
|
|
201
|
+
assertArray(parentEntry[relationship]);
|
|
202
|
+
const view = parentEntry[relationship];
|
|
203
|
+
if (schema.compareRows(change.oldRow, change.row) === 0) {
|
|
204
|
+
const { pos, found } = binarySearch(
|
|
205
|
+
view,
|
|
206
|
+
change.oldRow,
|
|
207
|
+
schema.compareRows
|
|
208
|
+
);
|
|
209
|
+
assert(found, "node does not exists");
|
|
210
|
+
view[pos] = makeEntryPreserveRelationships(
|
|
211
|
+
change.row,
|
|
212
|
+
view[pos],
|
|
213
|
+
schema.relationships
|
|
214
|
+
);
|
|
215
|
+
} else {
|
|
216
|
+
const { pos, found } = binarySearch(
|
|
217
|
+
view,
|
|
218
|
+
change.oldRow,
|
|
219
|
+
schema.compareRows
|
|
220
|
+
);
|
|
221
|
+
assert(found, "node does not exists");
|
|
222
|
+
const oldEntry = view[pos];
|
|
223
|
+
view.splice(pos, 1);
|
|
224
|
+
{
|
|
225
|
+
const { pos: pos2, found: found2 } = binarySearch(
|
|
226
|
+
view,
|
|
227
|
+
change.row,
|
|
228
|
+
schema.compareRows
|
|
229
|
+
);
|
|
230
|
+
assert(!found2, "node already exists");
|
|
231
|
+
view.splice(
|
|
232
|
+
pos2,
|
|
233
|
+
0,
|
|
234
|
+
makeEntryPreserveRelationships(
|
|
235
|
+
change.row,
|
|
236
|
+
oldEntry,
|
|
237
|
+
schema.relationships
|
|
238
|
+
)
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
default:
|
|
246
|
+
unreachable(change);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
function binarySearch(view, target, comparator) {
|
|
250
|
+
let low = 0;
|
|
251
|
+
let high = view.length - 1;
|
|
252
|
+
while (low <= high) {
|
|
253
|
+
const mid = low + high >>> 1;
|
|
254
|
+
const comparison = comparator(view[mid], target);
|
|
255
|
+
if (comparison < 0) {
|
|
256
|
+
low = mid + 1;
|
|
257
|
+
} else if (comparison > 0) {
|
|
258
|
+
high = mid - 1;
|
|
259
|
+
} else {
|
|
260
|
+
return { pos: mid, found: true };
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return { pos: low, found: false };
|
|
264
|
+
}
|
|
265
|
+
function makeEntryPreserveRelationships(row, entry, relationships) {
|
|
266
|
+
const result = { ...row };
|
|
267
|
+
for (const relationship in relationships) {
|
|
268
|
+
assert(!(relationship in row), "Relationship already exists");
|
|
269
|
+
result[relationship] = entry[relationship];
|
|
270
|
+
}
|
|
271
|
+
return result;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export {
|
|
275
|
+
assert,
|
|
276
|
+
assertString,
|
|
277
|
+
assertNumber,
|
|
278
|
+
assertBoolean,
|
|
279
|
+
assertObject,
|
|
280
|
+
assertArray,
|
|
281
|
+
throwInvalidType,
|
|
282
|
+
assertNotNull,
|
|
283
|
+
assertNotUndefined,
|
|
284
|
+
unreachable,
|
|
285
|
+
must,
|
|
286
|
+
applyChange
|
|
287
|
+
};
|
|
288
|
+
//# sourceMappingURL=chunk-RCVGGCMG.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../shared/src/asserts.ts", "../../shared/src/must.ts", "../../zql/src/zql/ivm/view-apply-change.ts"],
|
|
4
|
+
"sourcesContent": ["export function assert(b: unknown, msg = 'Assertion failed'): asserts b {\n if (!b) {\n throw new Error(msg);\n }\n}\n\nexport function assertString(v: unknown): asserts v is string {\n assertType(v, 'string');\n}\n\nexport function assertNumber(v: unknown): asserts v is number {\n assertType(v, 'number');\n}\n\nexport function assertBoolean(v: unknown): asserts v is boolean {\n assertType(v, 'boolean');\n}\n\nfunction assertType(v: unknown, t: string) {\n if (typeof v !== t) {\n throwInvalidType(v, t);\n }\n}\n\nexport function assertObject(v: unknown): asserts v is Record<string, unknown> {\n if (v === null) {\n throwInvalidType(v, 'object');\n }\n assertType(v, 'object');\n}\n\nexport function assertArray(v: unknown): asserts v is unknown[] {\n if (!Array.isArray(v)) {\n throwInvalidType(v, 'array');\n }\n}\n\nexport function invalidType(v: unknown, t: string): string {\n let s = 'Invalid type: ';\n if (v === null || v === undefined) {\n s += v;\n } else {\n s += `${typeof v} \\`${v}\\``;\n }\n return s + `, expected ${t}`;\n}\n\nexport function throwInvalidType(v: unknown, t: string): never {\n throw new Error(invalidType(v, t));\n}\n\nexport function assertNotNull<T>(v: T | null): asserts v is T {\n if (v === null) {\n throw new Error('Expected non-null value');\n }\n}\n\nexport function assertUndefined<T>(\n v: T | undefined,\n msg = 'Expected undefined value',\n): asserts v is T {\n if (v !== undefined) {\n throw new Error(msg);\n }\n}\n\nexport function assertNotUndefined<T>(\n v: T | undefined,\n msg = 'Expected non undefined value',\n): asserts v is T {\n if (v === undefined) {\n throw new Error(msg);\n }\n}\n\nexport function assertInstanceof<T>(\n v: unknown,\n t: new (...args: unknown[]) => T,\n): asserts v is T {\n if (!(v instanceof t)) {\n throw new Error(`Expected instanceof ${t.name}`);\n }\n}\n\nexport function assertUint8Array(v: unknown): asserts v is Uint8Array {\n assertInstanceof(v, Uint8Array);\n}\n\nexport function unreachable(): never;\nexport function unreachable(v: never): never;\nexport function unreachable(_?: never): never {\n throw new Error('Unreachable');\n}\n\nexport function notImplemented(): never {\n throw new Error('Not implemented');\n}\n", "export function must<T>(v: T | undefined | null, msg?: string): T {\n // eslint-disable-next-line eqeqeq\n if (v == null) {\n throw new Error(msg ?? `Unexpected ${v} value`);\n }\n return v;\n}\n", "import {\n assert,\n assertArray,\n assertObject,\n assertUndefined,\n unreachable,\n} from '../../../../shared/src/asserts.js';\nimport {must} from '../../../../shared/src/must.js';\nimport type {Row} from '../../../../zero-protocol/src/data.js';\nimport type {Change} from './change.js';\nimport type {Comparator} from './data.js';\nimport type {TableSchema} from './schema.js';\nimport type {Entry, EntryList, Format} from './view.js';\n\nexport function applyChange(\n parentEntry: Entry,\n change: Change,\n schema: TableSchema,\n relationship: string,\n format: Format,\n) {\n if (schema.isHidden) {\n switch (change.type) {\n case 'add':\n case 'remove':\n for (const [relationship, children] of Object.entries(\n change.node.relationships,\n )) {\n const childSchema = must(schema.relationships[relationship]);\n for (const node of children) {\n applyChange(\n parentEntry,\n {type: change.type, node},\n childSchema,\n relationship,\n format,\n );\n }\n }\n return;\n case 'edit':\n // If hidden at this level it means that the hidden row was changed. If\n // the row was changed in such a way that it would change the\n // relationships then the edit would have been split into remove and\n // add.\n return;\n case 'child': {\n const childSchema = must(\n schema.relationships[change.child.relationshipName],\n );\n applyChange(\n parentEntry,\n change.child.change,\n childSchema,\n relationship,\n format,\n );\n return;\n }\n default:\n unreachable(change);\n }\n }\n\n const {singular, relationships: childFormats} = format;\n switch (change.type) {\n case 'add': {\n // TODO: Only create a new entry if we need to mutate the existing one.\n const newEntry: Entry = {\n ...change.node.row,\n };\n if (singular) {\n assertUndefined(\n parentEntry[relationship],\n 'single output already exists',\n );\n parentEntry[relationship] = newEntry;\n } else {\n const view = parentEntry[relationship];\n assertArray(view);\n const {pos, found} = binarySearch(view, newEntry, schema.compareRows);\n assert(!found, 'node already exists');\n view.splice(pos, 0, newEntry);\n }\n for (const [relationship, children] of Object.entries(\n change.node.relationships,\n )) {\n // TODO: Is there a flag to make TypeScript complain that dictionary access might be undefined?\n const childSchema = must(schema.relationships[relationship]);\n const childFormat = must(childFormats[relationship]);\n const newView = childFormat.singular ? undefined : ([] as EntryList);\n newEntry[relationship] = newView;\n for (const node of children) {\n applyChange(\n newEntry,\n {type: 'add', node},\n childSchema,\n relationship,\n childFormat,\n );\n }\n }\n break;\n }\n case 'remove': {\n if (singular) {\n assertObject(parentEntry[relationship]);\n parentEntry[relationship] = undefined;\n } else {\n assertArray(parentEntry[relationship]);\n const view = parentEntry[relationship];\n const {pos, found} = binarySearch(\n view,\n change.node.row,\n schema.compareRows,\n );\n assert(found, 'node does not exist');\n view.splice(pos, 1);\n }\n break;\n }\n case 'child': {\n let existing: Entry;\n if (singular) {\n assertObject(parentEntry[relationship]);\n existing = parentEntry[relationship];\n } else {\n assertArray(parentEntry[relationship]);\n const list = parentEntry[relationship];\n const {pos, found} = binarySearch(list, change.row, schema.compareRows);\n assert(found, 'node does not exist');\n existing = list[pos];\n }\n\n const childSchema = must(\n schema.relationships[change.child.relationshipName],\n );\n const childFormat = must(\n format.relationships[change.child.relationshipName],\n );\n applyChange(\n existing,\n change.child.change,\n childSchema,\n change.child.relationshipName,\n childFormat,\n );\n break;\n }\n case 'edit': {\n if (singular) {\n assertObject(parentEntry[relationship]);\n parentEntry[relationship] = {\n ...parentEntry[relationship],\n ...change.row,\n };\n } else {\n assertArray(parentEntry[relationship]);\n const view = parentEntry[relationship];\n // If the order changed due to the edit, we need to remove and reinsert.\n if (schema.compareRows(change.oldRow, change.row) === 0) {\n const {pos, found} = binarySearch(\n view,\n change.oldRow,\n schema.compareRows,\n );\n assert(found, 'node does not exists');\n view[pos] = makeEntryPreserveRelationships(\n change.row,\n view[pos],\n schema.relationships,\n );\n } else {\n // Remove\n const {pos, found} = binarySearch(\n view,\n change.oldRow,\n schema.compareRows,\n );\n assert(found, 'node does not exists');\n const oldEntry = view[pos];\n view.splice(pos, 1);\n\n // Insert\n {\n const {pos, found} = binarySearch(\n view,\n change.row,\n schema.compareRows,\n );\n assert(!found, 'node already exists');\n view.splice(\n pos,\n 0,\n makeEntryPreserveRelationships(\n change.row,\n oldEntry,\n schema.relationships,\n ),\n );\n }\n }\n }\n break;\n }\n default:\n unreachable(change);\n }\n}\n\n// TODO: Do not return an object. It puts unnecessary pressure on the GC.\nfunction binarySearch(view: EntryList, target: Entry, comparator: Comparator) {\n let low = 0;\n let high = view.length - 1;\n while (low <= high) {\n const mid = (low + high) >>> 1;\n const comparison = comparator(view[mid] as Row, target as Row);\n if (comparison < 0) {\n low = mid + 1;\n } else if (comparison > 0) {\n high = mid - 1;\n } else {\n return {pos: mid, found: true};\n }\n }\n return {pos: low, found: false};\n}\n\nfunction makeEntryPreserveRelationships(\n row: Row,\n entry: Entry,\n relationships: {[key: string]: TableSchema},\n): Entry {\n const result: Entry = {...row};\n for (const relationship in relationships) {\n assert(!(relationship in row), 'Relationship already exists');\n result[relationship] = entry[relationship];\n }\n return result;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["relationship", "pos", "found"]
|
|
7
|
+
}
|
package/out/internal.js
ADDED
package/out/react.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
hasOwn
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-HARIWJ2J.js";
|
|
4
|
+
import "./chunk-F5QR3K72.js";
|
|
4
5
|
|
|
5
6
|
// ../zero-react/src/use-query.tsx
|
|
6
7
|
import { useSyncExternalStore } from "react";
|
|
@@ -87,11 +88,11 @@ var ViewStore = class {
|
|
|
87
88
|
getView(clientID, query, enabled) {
|
|
88
89
|
if (!enabled) {
|
|
89
90
|
return {
|
|
90
|
-
getSnapshot: () => query.singular ? void 0 : emptyArray,
|
|
91
|
+
getSnapshot: () => query.format.singular ? void 0 : emptyArray,
|
|
91
92
|
subscribeReactInternals: disabledSubscriber
|
|
92
93
|
};
|
|
93
94
|
}
|
|
94
|
-
const hash =
|
|
95
|
+
const hash = query.hash() + clientID;
|
|
95
96
|
let existing = this.#views.get(hash);
|
|
96
97
|
if (!existing) {
|
|
97
98
|
existing = new ViewWrapper(
|
|
@@ -122,7 +123,7 @@ var ViewWrapper = class {
|
|
|
122
123
|
#snapshot;
|
|
123
124
|
#reactInternals;
|
|
124
125
|
constructor(query, onMaterialized, onDematerialized) {
|
|
125
|
-
this.#defaultSnapshot = query.singular ? void 0 : emptyArray;
|
|
126
|
+
this.#defaultSnapshot = query.format.singular ? void 0 : emptyArray;
|
|
126
127
|
this.#snapshot = this.#defaultSnapshot;
|
|
127
128
|
this.#onMaterialized = onMaterialized;
|
|
128
129
|
this.#onDematerialized = onDematerialized;
|
package/out/react.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../zero-react/src/use-query.tsx", "../../shared/src/deep-clone.ts", "../../zero-react/src/use-zero.tsx"],
|
|
4
|
-
"sourcesContent": ["import {useSyncExternalStore} from 'react';\nimport {deepClone} from '../../shared/src/deep-clone.js';\nimport type {Immutable} from '../../shared/src/immutable.js';\nimport type {\n Query,\n
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import {useSyncExternalStore} from 'react';\nimport {deepClone} from '../../shared/src/deep-clone.js';\nimport type {Immutable} from '../../shared/src/immutable.js';\nimport type {\n Query,\n QueryType,\n Smash,\n TableSchema,\n TypedView,\n} from '../../zero-client/src/mod.js';\nimport type {QueryInternal} from '../../zql/src/zql/query/query-internal.js';\nimport {useZero} from './use-zero.js';\n\nexport function useQuery<\n TSchema extends TableSchema,\n TReturn extends QueryType,\n>(q: Query<TSchema, TReturn>, enable: boolean = true): Smash<TReturn> {\n const z = useZero();\n const view = viewStore.getView(\n z.clientID,\n q as QueryInternal<TSchema, TReturn>,\n enable,\n );\n // https://react.dev/reference/react/useSyncExternalStore\n return useSyncExternalStore(view.subscribeReactInternals, view.getSnapshot);\n}\n\nconst emptyArray: unknown[] = [];\nconst disabledSubscriber = () => () => {};\n\n/**\n * A global store of all active views.\n *\n * React subscribes and unsubscribes to these views\n * via `useSyncExternalStore`.\n *\n * Managing views through `useEffect` or `useLayoutEffect` causes\n * inconsistencies because effects run after render.\n *\n * For example, if useQuery used use*Effect in the component below:\n * ```ts\n * function Foo({issueID}) {\n * const issue = useQuery(z.query.issue.where('id', issueID).one());\n * if (issue?.id !== undefined && issue.id !== issueID) {\n * console.log('MISMATCH!', issue.id, issueID);\n * }\n * }\n * ```\n *\n * `MISMATCH` will be printed whenever the `issueID` prop changes.\n *\n * This is because the component will render once with\n * the old state returned from `useQuery`. Then the effect inside\n * `useQuery` will run. The component will render again with the new\n * state. This inconsistent transition can cause unexpected results.\n *\n * Emulating `useEffect` via `useState` and `if` causes resource leaks.\n * That is:\n *\n * ```ts\n * function useQuery(q) {\n * const [oldHash, setOldHash] = useState();\n * if (hash(q) !== oldHash) {\n * // make new view\n * }\n *\n * useEffect(() => {\n * return () => view.destroy();\n * }, []);\n * }\n * ```\n *\n * I'm not sure why but in strict mode the cleanup function\n * fails to be called for the first instance of the view and only\n * cleans up later instances.\n *\n * Swapping `useState` to `useRef` has similar problems.\n */\nclass ViewStore {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #views = new Map<string, ViewWrapper<any, any>>();\n\n getView<TSchema extends TableSchema, TReturn extends QueryType>(\n clientID: string,\n query: QueryInternal<TSchema, TReturn>,\n enabled: boolean,\n ): {\n getSnapshot: () => Smash<TReturn>;\n subscribeReactInternals: (internals: () => void) => () => void;\n } {\n if (!enabled) {\n return {\n getSnapshot: () =>\n (query.format.singular ? undefined : emptyArray) as Smash<TReturn>,\n subscribeReactInternals: disabledSubscriber,\n };\n }\n\n const hash = query.hash() + clientID;\n let existing = this.#views.get(hash);\n if (!existing) {\n existing = new ViewWrapper(\n query,\n view => {\n const lastView = this.#views.get(hash);\n // I don't think this can happen\n // but lets guard against it so we don't\n // leak resources.\n if (lastView && lastView !== view) {\n throw new Error('View already exists');\n }\n this.#views.set(hash, view);\n },\n () => {\n this.#views.delete(hash);\n },\n ) as ViewWrapper<TSchema, TReturn>;\n this.#views.set(hash, existing);\n }\n return existing;\n }\n}\n\nconst viewStore = new ViewStore();\n\n/**\n * This wraps and ref counts a view.\n *\n * The only signal we have from React as to whether or not it is\n * done with a view is when it calls `unsubscribe`.\n *\n * In non-strict-mode we can clean up the view as soon\n * as the listener count goes to 0.\n *\n * In strict-mode, the listener cound will go to 0 then a\n * new listener for the same view is immeidatiely added back.\n *\n * This is why the `onMaterialized` and `onDematerialized` callbacks exist --\n * they allow a view which React is still referencing to be added\n * back into the store when React re-subscribes to it.\n *\n * This wrapper also exists to deal with the various\n * `useSyncExternalStore` caveats that cause excessive\n * re-renders and materializations.\n *\n * See: https://react.dev/reference/react/useSyncExternalStore#caveats\n * Especially:\n * 1. The store snapshot returned by getSnapshot must be immutable. If the underlying store has mutable data, return a new immutable snapshot if the data has changed. Otherwise, return a cached last snapshot.\n * 2. If a different subscribe function is passed during a re-render, React will re-subscribe to the store using the newly passed subscribe function. You can prevent this by declaring subscribe outside the component.\n */\nclass ViewWrapper<TSchema extends TableSchema, TReturn extends QueryType> {\n #view: TypedView<Smash<TReturn>> | undefined;\n readonly #defaultSnapshot: Smash<TReturn>;\n readonly #onDematerialized;\n readonly #onMaterialized;\n readonly #query: QueryInternal<TSchema, TReturn>;\n #snapshot: Smash<TReturn>;\n #reactInternals: Set<() => void>;\n\n constructor(\n query: QueryInternal<TSchema, TReturn>,\n onMaterialized: (view: ViewWrapper<TSchema, TReturn>) => void,\n onDematerialized: () => void,\n ) {\n this.#defaultSnapshot = (query.format.singular\n ? undefined\n : emptyArray) as unknown as Smash<TReturn>;\n this.#snapshot = this.#defaultSnapshot;\n this.#onMaterialized = onMaterialized;\n this.#onDematerialized = onDematerialized;\n this.#reactInternals = new Set();\n this.#query = query;\n }\n\n #onData = (snap: Immutable<Smash<TReturn>>) => {\n this.#snapshot = (\n snap === undefined ? snap : deepClone(snap)\n ) as Smash<TReturn>;\n for (const internals of this.#reactInternals) {\n internals();\n }\n };\n\n #materializeIfNeeded = () => {\n if (this.#view) {\n return;\n }\n\n this.#view = this.#query.materialize();\n this.#view.addListener(this.#onData);\n\n this.#onMaterialized(this);\n };\n\n getSnapshot = () => this.#snapshot;\n\n subscribeReactInternals = (internals: () => void): (() => void) => {\n this.#reactInternals.add(internals);\n this.#materializeIfNeeded();\n return () => {\n this.#reactInternals.delete(internals);\n if (this.#reactInternals.size === 0) {\n this.#view?.destroy();\n this.#view = undefined;\n this.#onDematerialized();\n }\n };\n };\n}\n", "import {hasOwn} from './has-own.js';\nimport type {JSONValue, ReadonlyJSONValue} from './json.js';\n\nexport function deepClone(value: ReadonlyJSONValue): JSONValue {\n const seen: Array<ReadonlyJSONValue> = [];\n return internalDeepClone(value, seen);\n}\n\nexport function internalDeepClone(\n value: ReadonlyJSONValue,\n seen: Array<ReadonlyJSONValue>,\n): JSONValue {\n switch (typeof value) {\n case 'boolean':\n case 'number':\n case 'string':\n case 'undefined':\n return value;\n case 'object': {\n if (value === null) {\n return null;\n }\n if (seen.includes(value)) {\n throw new Error('Cyclic object');\n }\n seen.push(value);\n if (Array.isArray(value)) {\n const rv = value.map(v => internalDeepClone(v, seen));\n seen.pop();\n return rv;\n }\n\n const obj: JSONValue = {};\n\n for (const k in value) {\n if (hasOwn(value, k)) {\n const v = (value as Record<string, ReadonlyJSONValue>)[k];\n if (v !== undefined) {\n obj[k] = internalDeepClone(v, seen);\n }\n }\n }\n seen.pop();\n return obj;\n }\n\n default:\n throw new Error(`Invalid type: ${typeof value}`);\n }\n}\n", "import {createContext, useContext} from 'react';\nimport type {Schema, Zero} from '../../zero-client/src/mod.js';\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst ZeroContext = createContext<Zero<Schema> | undefined>(undefined);\n\nexport function useZero<S extends Schema>(): Zero<S> {\n const zero = useContext(ZeroContext);\n if (zero === undefined) {\n throw new Error('useZero must be used within a ZeroProvider');\n }\n return zero as Zero<S>;\n}\n\nexport function createUseZero<S extends Schema>() {\n return () => useZero<S>();\n}\n\nexport function ZeroProvider<S extends Schema>({\n children,\n zero,\n}: {\n children: React.ReactNode;\n zero: Zero<S>;\n}) {\n return (\n <ZeroContext.Provider value={zero as Zero<Schema>}>\n {children}\n </ZeroContext.Provider>\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../../replicache/src/version.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../../replicache/src/version.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,eAAO,MAAM,OAAO,EAAE,MAAkD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../../replicache/src/version.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../../replicache/src/version.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAQhD;;GAEG;AACH,MAAM,CAAC,MAAM,OAAO,GAAW,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO,CAAC"}
|
package/out/solid.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import "./chunk-NKGIR6IA.js";
|
|
2
|
+
import {
|
|
3
|
+
applyChange
|
|
4
|
+
} from "./chunk-RCVGGCMG.js";
|
|
5
|
+
import "./chunk-F5QR3K72.js";
|
|
6
|
+
|
|
7
|
+
// ../zero-solid/src/use-query.ts
|
|
8
|
+
import { createMemo, onCleanup } from "solid-js";
|
|
9
|
+
|
|
10
|
+
// ../zero-solid/src/solid-view.ts
|
|
11
|
+
import { createStore, produce } from "solid-js/store";
|
|
12
|
+
var SolidView = class {
|
|
13
|
+
#input;
|
|
14
|
+
#format;
|
|
15
|
+
#onDestroy;
|
|
16
|
+
// Synthetic "root" entry that has a single "" relationship, so that we can
|
|
17
|
+
// treat all changes, including the root change, generically.
|
|
18
|
+
#root;
|
|
19
|
+
#setRoot;
|
|
20
|
+
constructor(input, format = { singular: false, relationships: {} }, onDestroy = () => {
|
|
21
|
+
}) {
|
|
22
|
+
this.#input = input;
|
|
23
|
+
this.#format = format;
|
|
24
|
+
this.#onDestroy = onDestroy;
|
|
25
|
+
this.#input.setOutput(this);
|
|
26
|
+
[this.#root, this.#setRoot] = createStore({
|
|
27
|
+
"": format.singular ? void 0 : []
|
|
28
|
+
});
|
|
29
|
+
this.#setRoot(
|
|
30
|
+
produce((draftRoot) => {
|
|
31
|
+
for (const node of this.#input.fetch({})) {
|
|
32
|
+
applyChange(
|
|
33
|
+
draftRoot,
|
|
34
|
+
{ type: "add", node },
|
|
35
|
+
this.#input.getSchema(),
|
|
36
|
+
"",
|
|
37
|
+
this.#format
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
get data() {
|
|
44
|
+
return this.#root[""];
|
|
45
|
+
}
|
|
46
|
+
destroy() {
|
|
47
|
+
this.#onDestroy();
|
|
48
|
+
}
|
|
49
|
+
push(change) {
|
|
50
|
+
this.#setRoot(
|
|
51
|
+
produce((draftRoot) => {
|
|
52
|
+
applyChange(
|
|
53
|
+
draftRoot,
|
|
54
|
+
change,
|
|
55
|
+
this.#input.getSchema(),
|
|
56
|
+
"",
|
|
57
|
+
this.#format
|
|
58
|
+
);
|
|
59
|
+
})
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
function solidViewFactory(_query, input, format, onDestroy) {
|
|
64
|
+
const v = new SolidView(input, format, onDestroy);
|
|
65
|
+
return v;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ../zero-solid/src/use-query.ts
|
|
69
|
+
function useQuery(querySignal) {
|
|
70
|
+
return createMemo(() => {
|
|
71
|
+
const query = querySignal();
|
|
72
|
+
const view = query.materialize(
|
|
73
|
+
solidViewFactory
|
|
74
|
+
);
|
|
75
|
+
onCleanup(() => {
|
|
76
|
+
view.destroy();
|
|
77
|
+
});
|
|
78
|
+
return view.data;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
export {
|
|
82
|
+
useQuery
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=solid.js.map
|
package/out/solid.js.map
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../zero-solid/src/use-query.ts", "../../zero-solid/src/solid-view.ts"],
|
|
4
|
+
"sourcesContent": ["import {type Accessor, createMemo, onCleanup} from 'solid-js';\nimport type {\n Query,\n QueryInternal,\n QueryType,\n Smash,\n TableSchema,\n} from '../../zero-internal/src/mod.js';\nimport {solidViewFactory} from './solid-view.js';\n\nexport function useQuery<\n TSchema extends TableSchema,\n TReturn extends QueryType,\n>(querySignal: () => Query<TSchema, TReturn>): Accessor<Smash<TReturn>> {\n return createMemo(() => {\n const query = querySignal();\n const view = (query as QueryInternal<TSchema, TReturn>).materialize(\n solidViewFactory,\n );\n\n onCleanup(() => {\n view.destroy();\n });\n\n return view.data;\n });\n}\n", "import {createStore, produce, type SetStoreFunction} from 'solid-js/store';\nimport {\n applyChange,\n type Change,\n type Entry,\n type Format,\n type Input,\n type Output,\n type Query,\n type QueryType,\n type Smash,\n type TableSchema,\n type View,\n} from '../../zero-internal/src/mod.js';\n\nexport class SolidView<V extends View> implements Output {\n readonly #input: Input;\n readonly #format: Format;\n readonly #onDestroy: () => void;\n\n // Synthetic \"root\" entry that has a single \"\" relationship, so that we can\n // treat all changes, including the root change, generically.\n readonly #root: Entry;\n readonly #setRoot: SetStoreFunction<Entry>;\n\n constructor(\n input: Input,\n format: Format = {singular: false, relationships: {}},\n onDestroy: () => void = () => {},\n ) {\n this.#input = input;\n this.#format = format;\n this.#onDestroy = onDestroy;\n this.#input.setOutput(this);\n [this.#root, this.#setRoot] = createStore({\n '': format.singular ? undefined : [],\n });\n\n this.#setRoot(\n produce(draftRoot => {\n for (const node of this.#input.fetch({})) {\n applyChange(\n draftRoot,\n {type: 'add', node},\n this.#input.getSchema(),\n '',\n this.#format,\n );\n }\n }),\n );\n }\n\n get data() {\n return this.#root[''] as V;\n }\n\n destroy() {\n this.#onDestroy();\n }\n\n push(change: Change): void {\n this.#setRoot(\n produce(draftRoot => {\n applyChange(\n draftRoot,\n change,\n this.#input.getSchema(),\n '',\n this.#format,\n );\n }),\n );\n }\n}\n\nexport function solidViewFactory<\n TSchema extends TableSchema,\n TReturn extends QueryType,\n>(\n _query: Query<TSchema, TReturn>,\n input: Input,\n format: Format,\n onDestroy: () => void,\n): SolidView<Smash<TReturn>> {\n const v = new SolidView<Smash<TReturn>>(input, format, onDestroy);\n\n return v;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;AAAA,SAAuB,YAAY,iBAAgB;;;ACAnD,SAAQ,aAAa,eAAqC;AAenD,IAAM,YAAN,MAAkD;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA,EAIA;AAAA,EACA;AAAA,EAET,YACE,OACA,SAAiB,EAAC,UAAU,OAAO,eAAe,CAAC,EAAC,GACpD,YAAwB,MAAM;AAAA,EAAC,GAC/B;AACA,SAAK,SAAS;AACd,SAAK,UAAU;AACf,SAAK,aAAa;AAClB,SAAK,OAAO,UAAU,IAAI;AAC1B,KAAC,KAAK,OAAO,KAAK,QAAQ,IAAI,YAAY;AAAA,MACxC,IAAI,OAAO,WAAW,SAAY,CAAC;AAAA,IACrC,CAAC;AAED,SAAK;AAAA,MACH,QAAQ,eAAa;AACnB,mBAAW,QAAQ,KAAK,OAAO,MAAM,CAAC,CAAC,GAAG;AACxC;AAAA,YACE;AAAA,YACA,EAAC,MAAM,OAAO,KAAI;AAAA,YAClB,KAAK,OAAO,UAAU;AAAA,YACtB;AAAA,YACA,KAAK;AAAA,UACP;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,IAAI,OAAO;AACT,WAAO,KAAK,MAAM,EAAE;AAAA,EACtB;AAAA,EAEA,UAAU;AACR,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,KAAK,QAAsB;AACzB,SAAK;AAAA,MACH,QAAQ,eAAa;AACnB;AAAA,UACE;AAAA,UACA;AAAA,UACA,KAAK,OAAO,UAAU;AAAA,UACtB;AAAA,UACA,KAAK;AAAA,QACP;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEO,SAAS,iBAId,QACA,OACA,QACA,WAC2B;AAC3B,QAAM,IAAI,IAAI,UAA0B,OAAO,QAAQ,SAAS;AAEhE,SAAO;AACT;;;AD9EO,SAAS,SAGd,aAAsE;AACtE,SAAO,WAAW,MAAM;AACtB,UAAM,QAAQ,YAAY;AAC1B,UAAM,OAAQ,MAA0C;AAAA,MACtD;AAAA,IACF;AAEA,cAAU,MAAM;AACd,WAAK,QAAQ;AAAA,IACf,CAAC;AAED,WAAO,KAAK;AAAA,EACd,CAAC;AACH;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../../src/internal.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solid.d.ts","sourceRoot":"","sources":["../../../src/solid.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { AST } from '../../../zero-protocol/src/ast.js';
|
|
2
|
-
import type { Format } from '../../../zql/src/zql/ivm/
|
|
2
|
+
import type { Format } from '../../../zql/src/zql/ivm/view.js';
|
|
3
3
|
import type { NormalizedTableSchema } from '../../../zql/src/zql/query/normalize-table-schema.js';
|
|
4
4
|
import { AbstractQuery } from '../../../zql/src/zql/query/query-impl.js';
|
|
5
5
|
import type { DefaultQueryResultRow, Query, QueryType, Smash } from '../../../zql/src/zql/query/query.js';
|
|
6
6
|
import type { TableSchema } from '../../../zql/src/zql/query/schema.js';
|
|
7
7
|
import type { TypedView } from '../../../zql/src/zql/query/typed-view.js';
|
|
8
8
|
export declare class ConfigQuery<TTableSchema extends TableSchema, TReturn extends QueryType = DefaultQueryResultRow<TTableSchema>> extends AbstractQuery<TTableSchema, TReturn> {
|
|
9
|
-
constructor(schema: NormalizedTableSchema, ast?: AST
|
|
9
|
+
constructor(schema: NormalizedTableSchema, ast?: AST, format?: Format | undefined);
|
|
10
10
|
get ast(): AST;
|
|
11
11
|
protected _newQuery<TSchema extends TableSchema, TReturn extends QueryType>(schema: NormalizedTableSchema, ast: AST, format: Format | undefined): Query<TSchema, TReturn>;
|
|
12
12
|
materialize(): TypedView<Smash<TReturn>>;
|