@rocicorp/zero 0.13.2025020303 → 0.13.2025020402
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/advanced.js +2 -2
- package/out/{chunk-L6HKVJYT.js → chunk-ADFMUREC.js} +1092 -928
- package/out/chunk-ADFMUREC.js.map +7 -0
- package/out/{chunk-ZVLXEWWB.js → chunk-Q6D7EOS6.js} +1 -1
- package/out/{chunk-ZVLXEWWB.js.map → chunk-Q6D7EOS6.js.map} +2 -2
- package/out/chunk-ULOTOBTC.js +1 -0
- package/out/react.js +44 -3
- package/out/react.js.map +3 -3
- package/out/replicache/src/patch-operation.d.ts +1 -1
- package/out/replicache/src/patch-operation.d.ts.map +1 -1
- package/out/solid.js +112 -37
- package/out/solid.js.map +2 -2
- package/out/zero-advanced/src/mod.d.ts +1 -1
- package/out/zero-advanced/src/mod.d.ts.map +1 -1
- package/out/zero-cache/src/auth/load-schema.d.ts +1 -1
- package/out/zero-cache/src/auth/load-schema.d.ts.map +1 -1
- package/out/zero-cache/src/auth/load-schema.js +8 -1
- package/out/zero-cache/src/auth/load-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.js +1 -3
- package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js +2 -2
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/validation.d.ts +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/validation.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/validation.js +1 -7
- package/out/zero-cache/src/services/change-source/pg/schema/validation.js.map +1 -1
- package/out/zero-client/src/client/context.d.ts +2 -2
- package/out/zero-client/src/client/context.d.ts.map +1 -1
- package/out/zero-client/src/client/custom.d.ts +9 -2
- package/out/zero-client/src/client/custom.d.ts.map +1 -1
- package/out/zero-client/src/client/ivm-source-repo.d.ts +34 -0
- package/out/zero-client/src/client/ivm-source-repo.d.ts.map +1 -0
- package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/zero-poke-handler.d.ts +2 -9
- package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-protocol/src/ast.d.ts +3 -4
- package/out/zero-protocol/src/ast.d.ts.map +1 -1
- package/out/zero-protocol/src/ast.js +10 -56
- package/out/zero-protocol/src/ast.js.map +1 -1
- package/out/zero-protocol/src/push.d.ts +2 -0
- package/out/zero-protocol/src/push.d.ts.map +1 -1
- package/out/zero-protocol/src/push.js +24 -0
- package/out/zero-protocol/src/push.js.map +1 -1
- package/out/zero-schema/src/builder/schema-builder.d.ts +1 -0
- package/out/zero-schema/src/builder/schema-builder.d.ts.map +1 -1
- package/out/zero-schema/src/builder/schema-builder.js +49 -0
- package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
- package/out/zero-schema/src/mod.d.ts +5 -0
- package/out/zero-schema/src/mod.d.ts.map +1 -0
- package/out/zero-schema/src/name-mapper.d.ts +23 -0
- package/out/zero-schema/src/name-mapper.d.ts.map +1 -0
- package/out/zero-schema/src/name-mapper.js +77 -0
- package/out/zero-schema/src/name-mapper.js.map +1 -0
- package/out/zero-schema/src/permissions.d.ts.map +1 -1
- package/out/zero-solid/src/solid-view.d.ts +3 -2
- package/out/zero-solid/src/solid-view.d.ts.map +1 -1
- package/out/zero.js +2 -2
- package/out/zql/src/ivm/memory-source.d.ts +3 -1
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +6 -2
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/view-apply-change.d.ts +34 -2
- package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
- package/out/zql/src/ivm/view-apply-change.js.map +1 -1
- package/package.json +1 -1
- package/out/chunk-5JO5DB4D.js +0 -50
- package/out/chunk-5JO5DB4D.js.map +0 -7
- package/out/chunk-ALG35NEG.js +0 -1
- package/out/chunk-L6HKVJYT.js.map +0 -7
- /package/out/{chunk-ALG35NEG.js.map → chunk-ULOTOBTC.js.map} +0 -0
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
throwInvalidType,
|
|
19
19
|
unreachable,
|
|
20
20
|
valuesEqual
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-Q6D7EOS6.js";
|
|
22
22
|
import {
|
|
23
23
|
__export,
|
|
24
24
|
__reExport
|
|
@@ -1957,6 +1957,38 @@ function* joinIterables(...iters) {
|
|
|
1957
1957
|
yield* iter;
|
|
1958
1958
|
}
|
|
1959
1959
|
}
|
|
1960
|
+
function* filterIter(iter, p) {
|
|
1961
|
+
let index = 0;
|
|
1962
|
+
for (const t2 of iter) {
|
|
1963
|
+
if (p(t2, index++)) {
|
|
1964
|
+
yield t2;
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
function* mapIter(iter, f) {
|
|
1969
|
+
let index = 0;
|
|
1970
|
+
for (const t2 of iter) {
|
|
1971
|
+
yield f(t2, index++);
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
var IterWrapper = class _IterWrapper {
|
|
1975
|
+
iter;
|
|
1976
|
+
constructor(iter) {
|
|
1977
|
+
this.iter = iter;
|
|
1978
|
+
}
|
|
1979
|
+
[Symbol.iterator]() {
|
|
1980
|
+
return this.iter[Symbol.iterator]();
|
|
1981
|
+
}
|
|
1982
|
+
map(f) {
|
|
1983
|
+
return new _IterWrapper(mapIter(this.iter, f));
|
|
1984
|
+
}
|
|
1985
|
+
filter(p) {
|
|
1986
|
+
return new _IterWrapper(filterIter(this.iter, p));
|
|
1987
|
+
}
|
|
1988
|
+
};
|
|
1989
|
+
function wrapIterable(iter) {
|
|
1990
|
+
return new IterWrapper(iter);
|
|
1991
|
+
}
|
|
1960
1992
|
function* mergeIterables(iterables, comparator2, distinct = false) {
|
|
1961
1993
|
const iterators = iterables.map((i) => i[Symbol.iterator]());
|
|
1962
1994
|
try {
|
|
@@ -8286,6 +8318,87 @@ function one(...args) {
|
|
|
8286
8318
|
}));
|
|
8287
8319
|
}
|
|
8288
8320
|
|
|
8321
|
+
// ../zero-schema/src/name-mapper.ts
|
|
8322
|
+
function clientToServer(tables) {
|
|
8323
|
+
return createMapperFrom("client", tables);
|
|
8324
|
+
}
|
|
8325
|
+
function serverToClient(tables) {
|
|
8326
|
+
return createMapperFrom("server", tables);
|
|
8327
|
+
}
|
|
8328
|
+
function createMapperFrom(src, tables) {
|
|
8329
|
+
const mapping = new Map(
|
|
8330
|
+
Object.entries(tables).map(
|
|
8331
|
+
([tableName, { serverName: serverTableName, columns }]) => {
|
|
8332
|
+
let allColumnsSame = true;
|
|
8333
|
+
const names = {};
|
|
8334
|
+
for (const [name, { serverName }] of Object.entries(columns)) {
|
|
8335
|
+
if (serverName && serverName !== name) {
|
|
8336
|
+
allColumnsSame = false;
|
|
8337
|
+
}
|
|
8338
|
+
if (src === "client") {
|
|
8339
|
+
names[name] = serverName ?? name;
|
|
8340
|
+
} else {
|
|
8341
|
+
names[serverName ?? name] = name;
|
|
8342
|
+
}
|
|
8343
|
+
}
|
|
8344
|
+
return [
|
|
8345
|
+
src === "client" ? tableName : serverTableName ?? tableName,
|
|
8346
|
+
{
|
|
8347
|
+
tableName: src === "client" ? serverTableName ?? tableName : tableName,
|
|
8348
|
+
columns: names,
|
|
8349
|
+
allColumnsSame
|
|
8350
|
+
}
|
|
8351
|
+
];
|
|
8352
|
+
}
|
|
8353
|
+
)
|
|
8354
|
+
);
|
|
8355
|
+
return new NameMapper(mapping);
|
|
8356
|
+
}
|
|
8357
|
+
var NameMapper = class {
|
|
8358
|
+
#tables = /* @__PURE__ */ new Map();
|
|
8359
|
+
constructor(tables) {
|
|
8360
|
+
this.#tables = tables;
|
|
8361
|
+
}
|
|
8362
|
+
#getTable(src, ctx) {
|
|
8363
|
+
const table2 = this.#tables.get(src);
|
|
8364
|
+
if (!table2) {
|
|
8365
|
+
throw new Error(
|
|
8366
|
+
`unknown table "${src}" ${!ctx ? "" : `in ${JSON.stringify(ctx)}`}`
|
|
8367
|
+
);
|
|
8368
|
+
}
|
|
8369
|
+
return table2;
|
|
8370
|
+
}
|
|
8371
|
+
tableName(src, context) {
|
|
8372
|
+
return this.#getTable(src, context).tableName;
|
|
8373
|
+
}
|
|
8374
|
+
columnName(table2, src, ctx) {
|
|
8375
|
+
const dst = this.#getTable(table2, ctx).columns[src];
|
|
8376
|
+
if (!dst) {
|
|
8377
|
+
throw new Error(
|
|
8378
|
+
`unknown column "${src}" of "${table2}" table ${!ctx ? "" : `in ${JSON.stringify(ctx)}`}`
|
|
8379
|
+
);
|
|
8380
|
+
}
|
|
8381
|
+
return dst;
|
|
8382
|
+
}
|
|
8383
|
+
row(table2, row) {
|
|
8384
|
+
const dest = this.#getTable(table2);
|
|
8385
|
+
const { allColumnsSame, columns } = dest;
|
|
8386
|
+
if (allColumnsSame) {
|
|
8387
|
+
return row;
|
|
8388
|
+
}
|
|
8389
|
+
const clientRow = {};
|
|
8390
|
+
for (const col in row) {
|
|
8391
|
+
clientRow[columns[col] ?? col] = row[col];
|
|
8392
|
+
}
|
|
8393
|
+
return clientRow;
|
|
8394
|
+
}
|
|
8395
|
+
columns(table2, cols) {
|
|
8396
|
+
const dest = this.#getTable(table2);
|
|
8397
|
+
const { allColumnsSame, columns } = dest;
|
|
8398
|
+
return cols === void 0 || allColumnsSame ? cols : cols.map((col) => columns[col] ?? col);
|
|
8399
|
+
}
|
|
8400
|
+
};
|
|
8401
|
+
|
|
8289
8402
|
// ../zero-schema/src/builder/table-builder.ts
|
|
8290
8403
|
function table(name) {
|
|
8291
8404
|
return new TableBuilder({
|
|
@@ -8696,77 +8809,23 @@ function normalizeAST(ast) {
|
|
|
8696
8809
|
}
|
|
8697
8810
|
return normalized;
|
|
8698
8811
|
}
|
|
8699
|
-
function
|
|
8700
|
-
return transformAST(ast,
|
|
8701
|
-
|
|
8702
|
-
|
|
8703
|
-
return transformWhere(cond, table2, clientToServer(tables));
|
|
8704
|
-
}
|
|
8705
|
-
function clientToServer(tables) {
|
|
8706
|
-
const mustTable = (table2) => {
|
|
8707
|
-
const t2 = tables[table2];
|
|
8708
|
-
if (!table2) {
|
|
8709
|
-
throw new Error(`invalid table "${table2}"`);
|
|
8710
|
-
}
|
|
8711
|
-
return t2;
|
|
8712
|
-
};
|
|
8713
|
-
return {
|
|
8714
|
-
tableName: (table2) => mustTable(table2).serverName ?? table2,
|
|
8715
|
-
columnName: (table2, col) => {
|
|
8716
|
-
const c = mustTable(table2).columns[col];
|
|
8717
|
-
if (!c) {
|
|
8718
|
-
throw new Error(`invalid column "${col}" in table "${table2}"`);
|
|
8719
|
-
}
|
|
8720
|
-
return c.serverName ?? col;
|
|
8721
|
-
},
|
|
8812
|
+
function mapAST(ast, mapper) {
|
|
8813
|
+
return transformAST(ast, {
|
|
8814
|
+
tableName: (table2) => mapper.tableName(table2),
|
|
8815
|
+
columnName: (table2, col) => mapper.columnName(table2, col),
|
|
8722
8816
|
related: (r) => r,
|
|
8723
8817
|
where: (w) => w,
|
|
8724
8818
|
conditions: (c) => c
|
|
8725
|
-
};
|
|
8726
|
-
}
|
|
8727
|
-
function toClientAST(ast, tables) {
|
|
8728
|
-
return transformAST(ast, serverToClient(tables));
|
|
8819
|
+
});
|
|
8729
8820
|
}
|
|
8730
|
-
function
|
|
8731
|
-
|
|
8732
|
-
|
|
8733
|
-
|
|
8734
|
-
clientName
|
|
8735
|
-
])
|
|
8736
|
-
);
|
|
8737
|
-
const columnNamesByTable = Object.fromEntries(
|
|
8738
|
-
Object.entries(tables).map(
|
|
8739
|
-
([clientTable, { serverName: serverTable, columns }]) => {
|
|
8740
|
-
const columnNames = Object.fromEntries(
|
|
8741
|
-
Object.entries(columns).map(([clientName, { serverName }]) => [
|
|
8742
|
-
serverName ?? clientName,
|
|
8743
|
-
clientName
|
|
8744
|
-
])
|
|
8745
|
-
);
|
|
8746
|
-
return [serverTable ?? clientTable, columnNames];
|
|
8747
|
-
}
|
|
8748
|
-
)
|
|
8749
|
-
);
|
|
8750
|
-
function mustTable(table2, tables2) {
|
|
8751
|
-
const t2 = tables2[table2];
|
|
8752
|
-
if (!table2) {
|
|
8753
|
-
throw new Error(`invalid table "${table2}"`);
|
|
8754
|
-
}
|
|
8755
|
-
return t2;
|
|
8756
|
-
}
|
|
8757
|
-
return {
|
|
8758
|
-
tableName: (table2) => mustTable(table2, tableNames),
|
|
8759
|
-
columnName: (table2, col) => {
|
|
8760
|
-
const name = mustTable(table2, columnNamesByTable)[col];
|
|
8761
|
-
if (!name) {
|
|
8762
|
-
throw new Error(`invalid column "${col}" in table "${table2}"`);
|
|
8763
|
-
}
|
|
8764
|
-
return name;
|
|
8765
|
-
},
|
|
8821
|
+
function mapCondition(cond, table2, mapper) {
|
|
8822
|
+
return transformWhere(cond, table2, {
|
|
8823
|
+
tableName: (table3) => mapper.tableName(table3),
|
|
8824
|
+
columnName: (table3, col) => mapper.columnName(table3, col),
|
|
8766
8825
|
related: (r) => r,
|
|
8767
8826
|
where: (w) => w,
|
|
8768
8827
|
conditions: (c) => c
|
|
8769
|
-
};
|
|
8828
|
+
});
|
|
8770
8829
|
}
|
|
8771
8830
|
function sortedRelated(related) {
|
|
8772
8831
|
return related.sort(cmpRelated);
|
|
@@ -11424,18 +11483,19 @@ function compilePermissions(schema, authz, expressionBuilders) {
|
|
|
11424
11483
|
if (!authz) {
|
|
11425
11484
|
return void 0;
|
|
11426
11485
|
}
|
|
11486
|
+
const nameMapper = clientToServer(schema.tables);
|
|
11427
11487
|
const ret = {};
|
|
11428
11488
|
for (const [tableName, tableConfig] of Object.entries(authz)) {
|
|
11429
11489
|
const serverName = schema.tables[tableName].serverName ?? tableName;
|
|
11430
11490
|
ret[serverName] = {
|
|
11431
11491
|
row: compileRowConfig(
|
|
11432
|
-
|
|
11492
|
+
nameMapper,
|
|
11433
11493
|
tableName,
|
|
11434
11494
|
tableConfig.row,
|
|
11435
11495
|
expressionBuilders[tableName]
|
|
11436
11496
|
),
|
|
11437
11497
|
cell: compileCellConfig(
|
|
11438
|
-
|
|
11498
|
+
nameMapper,
|
|
11439
11499
|
tableName,
|
|
11440
11500
|
tableConfig.cell,
|
|
11441
11501
|
expressionBuilders[tableName]
|
|
@@ -11444,66 +11504,93 @@ function compilePermissions(schema, authz, expressionBuilders) {
|
|
|
11444
11504
|
}
|
|
11445
11505
|
return ret;
|
|
11446
11506
|
}
|
|
11447
|
-
function compileRowConfig(
|
|
11507
|
+
function compileRowConfig(clientToServer2, tableName, rowRules, expressionBuilder) {
|
|
11448
11508
|
if (!rowRules) {
|
|
11449
11509
|
return void 0;
|
|
11450
11510
|
}
|
|
11451
11511
|
return {
|
|
11452
|
-
select: compileRules(
|
|
11453
|
-
|
|
11512
|
+
select: compileRules(
|
|
11513
|
+
clientToServer2,
|
|
11514
|
+
tableName,
|
|
11515
|
+
rowRules.select,
|
|
11516
|
+
expressionBuilder
|
|
11517
|
+
),
|
|
11518
|
+
insert: compileRules(
|
|
11519
|
+
clientToServer2,
|
|
11520
|
+
tableName,
|
|
11521
|
+
rowRules.insert,
|
|
11522
|
+
expressionBuilder
|
|
11523
|
+
),
|
|
11454
11524
|
update: {
|
|
11455
11525
|
preMutation: compileRules(
|
|
11456
|
-
|
|
11526
|
+
clientToServer2,
|
|
11457
11527
|
tableName,
|
|
11458
11528
|
rowRules.update?.preMutation,
|
|
11459
11529
|
expressionBuilder
|
|
11460
11530
|
),
|
|
11461
11531
|
postMutation: compileRules(
|
|
11462
|
-
|
|
11532
|
+
clientToServer2,
|
|
11463
11533
|
tableName,
|
|
11464
11534
|
rowRules.update?.postMutation,
|
|
11465
11535
|
expressionBuilder
|
|
11466
11536
|
)
|
|
11467
11537
|
},
|
|
11468
|
-
delete: compileRules(
|
|
11538
|
+
delete: compileRules(
|
|
11539
|
+
clientToServer2,
|
|
11540
|
+
tableName,
|
|
11541
|
+
rowRules.delete,
|
|
11542
|
+
expressionBuilder
|
|
11543
|
+
)
|
|
11469
11544
|
};
|
|
11470
11545
|
}
|
|
11471
|
-
function compileRules(
|
|
11546
|
+
function compileRules(clientToServer2, tableName, rules, expressionBuilder) {
|
|
11472
11547
|
if (!rules) {
|
|
11473
11548
|
return void 0;
|
|
11474
11549
|
}
|
|
11475
11550
|
return rules.map((rule) => {
|
|
11476
11551
|
const cond = rule(authDataRef, expressionBuilder);
|
|
11477
|
-
return [
|
|
11478
|
-
"allow",
|
|
11479
|
-
toServerCondition(cond, tableName, schema.tables)
|
|
11480
|
-
];
|
|
11552
|
+
return ["allow", mapCondition(cond, tableName, clientToServer2)];
|
|
11481
11553
|
});
|
|
11482
11554
|
}
|
|
11483
|
-
function compileCellConfig(
|
|
11555
|
+
function compileCellConfig(clientToServer2, tableName, cellRules, expressionBuilder) {
|
|
11484
11556
|
if (!cellRules) {
|
|
11485
11557
|
return void 0;
|
|
11486
11558
|
}
|
|
11487
11559
|
const ret = {};
|
|
11488
11560
|
for (const [columnName, rules] of Object.entries(cellRules)) {
|
|
11489
11561
|
ret[columnName] = {
|
|
11490
|
-
select: compileRules(
|
|
11491
|
-
|
|
11562
|
+
select: compileRules(
|
|
11563
|
+
clientToServer2,
|
|
11564
|
+
tableName,
|
|
11565
|
+
rules.select,
|
|
11566
|
+
expressionBuilder
|
|
11567
|
+
),
|
|
11568
|
+
insert: compileRules(
|
|
11569
|
+
clientToServer2,
|
|
11570
|
+
tableName,
|
|
11571
|
+
rules.insert,
|
|
11572
|
+
expressionBuilder
|
|
11573
|
+
),
|
|
11492
11574
|
update: {
|
|
11493
11575
|
preMutation: compileRules(
|
|
11494
|
-
|
|
11576
|
+
clientToServer2,
|
|
11495
11577
|
tableName,
|
|
11496
11578
|
rules.update?.preMutation,
|
|
11497
11579
|
expressionBuilder
|
|
11498
11580
|
),
|
|
11499
11581
|
postMutation: compileRules(
|
|
11500
|
-
|
|
11582
|
+
clientToServer2,
|
|
11501
11583
|
tableName,
|
|
11502
11584
|
rules.update?.postMutation,
|
|
11503
11585
|
expressionBuilder
|
|
11504
11586
|
)
|
|
11505
11587
|
},
|
|
11506
|
-
delete: compileRules(
|
|
11588
|
+
delete: compileRules(
|
|
11589
|
+
clientToServer2,
|
|
11590
|
+
tableName,
|
|
11591
|
+
rules.delete,
|
|
11592
|
+
expressionBuilder
|
|
11593
|
+
)
|
|
11507
11594
|
};
|
|
11508
11595
|
}
|
|
11509
11596
|
return ret;
|
|
@@ -11887,6 +11974,29 @@ var pushBodySchema = valita_exports.object({
|
|
|
11887
11974
|
requestID: valita_exports.string()
|
|
11888
11975
|
});
|
|
11889
11976
|
var pushMessageSchema = valita_exports.tuple([valita_exports.literal("push"), pushBodySchema]);
|
|
11977
|
+
function mapCRUD(arg, map) {
|
|
11978
|
+
return {
|
|
11979
|
+
ops: arg.ops.map(({ op, tableName, primaryKey, value }) => {
|
|
11980
|
+
switch (op) {
|
|
11981
|
+
case "delete": {
|
|
11982
|
+
return {
|
|
11983
|
+
op,
|
|
11984
|
+
tableName: map.tableName(tableName),
|
|
11985
|
+
primaryKey: map.columns(tableName, primaryKey),
|
|
11986
|
+
value: map.row(tableName, value)
|
|
11987
|
+
};
|
|
11988
|
+
}
|
|
11989
|
+
default:
|
|
11990
|
+
return {
|
|
11991
|
+
op,
|
|
11992
|
+
tableName: map.tableName(tableName),
|
|
11993
|
+
primaryKey: map.columns(tableName, primaryKey),
|
|
11994
|
+
value: map.row(tableName, value)
|
|
11995
|
+
};
|
|
11996
|
+
}
|
|
11997
|
+
})
|
|
11998
|
+
};
|
|
11999
|
+
}
|
|
11890
12000
|
|
|
11891
12001
|
// ../zero-client/src/util/nanoid.ts
|
|
11892
12002
|
function nanoid(size = 21) {
|
|
@@ -11916,6 +12026,9 @@ var Disconnected = 0;
|
|
|
11916
12026
|
var Connecting = 1;
|
|
11917
12027
|
var Connected = 2;
|
|
11918
12028
|
|
|
12029
|
+
// ../zql/src/ivm/memory-storage.ts
|
|
12030
|
+
import { compareUTF8 as compareUTF84 } from "compare-utf8";
|
|
12031
|
+
|
|
11919
12032
|
// ../shared/src/btree-set.ts
|
|
11920
12033
|
var MAX_NODE_SIZE = 32;
|
|
11921
12034
|
var BTreeSet = class _BTreeSet {
|
|
@@ -12403,885 +12516,965 @@ function indexOf(key, keys, failXor, comparator2) {
|
|
|
12403
12516
|
var emptyLeaf = new BNode([]);
|
|
12404
12517
|
emptyLeaf.isShared = true;
|
|
12405
12518
|
|
|
12406
|
-
// ../zql/src/ivm/
|
|
12407
|
-
function
|
|
12408
|
-
|
|
12409
|
-
|
|
12410
|
-
|
|
12519
|
+
// ../zql/src/ivm/memory-storage.ts
|
|
12520
|
+
function comparator(a, b) {
|
|
12521
|
+
return compareUTF84(a[0], b[0]);
|
|
12522
|
+
}
|
|
12523
|
+
var MemoryStorage = class {
|
|
12524
|
+
#data = new BTreeSet(comparator);
|
|
12525
|
+
set(key, value) {
|
|
12526
|
+
this.#data.add([key, value]);
|
|
12527
|
+
}
|
|
12528
|
+
get(key, def) {
|
|
12529
|
+
const r = this.#data.get([key, null]);
|
|
12530
|
+
if (r !== void 0) {
|
|
12531
|
+
return r[1];
|
|
12411
12532
|
}
|
|
12533
|
+
return def;
|
|
12412
12534
|
}
|
|
12413
|
-
|
|
12414
|
-
|
|
12415
|
-
function constraintMatchesPrimaryKey(constraint, primary) {
|
|
12416
|
-
const constraintKeys = Object.keys(constraint);
|
|
12417
|
-
if (constraintKeys.length !== primary.length) {
|
|
12418
|
-
return false;
|
|
12535
|
+
del(key) {
|
|
12536
|
+
this.#data.delete([key, null]);
|
|
12419
12537
|
}
|
|
12420
|
-
|
|
12421
|
-
|
|
12422
|
-
|
|
12423
|
-
|
|
12538
|
+
*scan(options) {
|
|
12539
|
+
for (const entry of this.#data.valuesFrom(
|
|
12540
|
+
options && [options.prefix, null]
|
|
12541
|
+
)) {
|
|
12542
|
+
if (options && !entry[0].startsWith(options.prefix)) {
|
|
12543
|
+
return;
|
|
12544
|
+
}
|
|
12545
|
+
yield entry;
|
|
12424
12546
|
}
|
|
12425
12547
|
}
|
|
12426
|
-
|
|
12548
|
+
cloneData() {
|
|
12549
|
+
return structuredClone(Object.fromEntries(this.#data.values()));
|
|
12550
|
+
}
|
|
12551
|
+
};
|
|
12552
|
+
|
|
12553
|
+
// ../zero-client/src/client/keys.ts
|
|
12554
|
+
var CLIENTS_KEY_PREFIX = "c/";
|
|
12555
|
+
var DESIRED_QUERIES_KEY_PREFIX = "d/";
|
|
12556
|
+
var GOT_QUERIES_KEY_PREFIX = "g/";
|
|
12557
|
+
var ENTITIES_KEY_PREFIX = "e/";
|
|
12558
|
+
function toClientsKey(clientID) {
|
|
12559
|
+
return CLIENTS_KEY_PREFIX + clientID;
|
|
12560
|
+
}
|
|
12561
|
+
function toDesiredQueriesKey(clientID, hash2) {
|
|
12562
|
+
return DESIRED_QUERIES_KEY_PREFIX + clientID + "/" + hash2;
|
|
12563
|
+
}
|
|
12564
|
+
function desiredQueriesPrefixForClient(clientID) {
|
|
12565
|
+
return DESIRED_QUERIES_KEY_PREFIX + clientID + "/";
|
|
12566
|
+
}
|
|
12567
|
+
function toGotQueriesKey(hash2) {
|
|
12568
|
+
return GOT_QUERIES_KEY_PREFIX + hash2;
|
|
12569
|
+
}
|
|
12570
|
+
function toPrimaryKeyString(tableName, primaryKey, value) {
|
|
12571
|
+
if (primaryKey.length === 1) {
|
|
12572
|
+
return ENTITIES_KEY_PREFIX + tableName + "/" + parse(value[primaryKey[0]], primaryKeyValueSchema);
|
|
12573
|
+
}
|
|
12574
|
+
const values = primaryKey.map((k) => parse(value[k], primaryKeyValueSchema));
|
|
12575
|
+
const str = JSON.stringify(values);
|
|
12576
|
+
const idSegment = h128(str);
|
|
12577
|
+
return ENTITIES_KEY_PREFIX + tableName + "/" + idSegment;
|
|
12427
12578
|
}
|
|
12428
12579
|
|
|
12429
|
-
// ../
|
|
12430
|
-
var
|
|
12431
|
-
|
|
12432
|
-
|
|
12433
|
-
|
|
12434
|
-
|
|
12435
|
-
#
|
|
12436
|
-
#
|
|
12437
|
-
#
|
|
12438
|
-
|
|
12439
|
-
|
|
12440
|
-
|
|
12441
|
-
this.#
|
|
12442
|
-
this.#
|
|
12443
|
-
|
|
12444
|
-
this.#indexes.set(JSON.stringify(this.#primaryIndexSort), {
|
|
12445
|
-
comparator: comparator2,
|
|
12446
|
-
data: new BTreeSet(comparator2),
|
|
12447
|
-
usedBy: /* @__PURE__ */ new Set()
|
|
12448
|
-
});
|
|
12449
|
-
assertOrderingIncludesPK(this.#primaryIndexSort, this.#primaryKey);
|
|
12580
|
+
// ../zero-client/src/client/context.ts
|
|
12581
|
+
var ZeroContext = class {
|
|
12582
|
+
// It is a bummer to have to maintain separate MemorySources here and copy the
|
|
12583
|
+
// data in from the Replicache db. But we want the data to be accessible via
|
|
12584
|
+
// pipelines *synchronously* and the core Replicache infra is all async. So
|
|
12585
|
+
// that needs to be fixed.
|
|
12586
|
+
#mainSources;
|
|
12587
|
+
#addQuery;
|
|
12588
|
+
#batchViewUpdates;
|
|
12589
|
+
#commitListeners = /* @__PURE__ */ new Set();
|
|
12590
|
+
staticQueryParameters = void 0;
|
|
12591
|
+
constructor(mainSources, addQuery, batchViewUpdates) {
|
|
12592
|
+
this.#mainSources = mainSources;
|
|
12593
|
+
this.#addQuery = addQuery;
|
|
12594
|
+
this.#batchViewUpdates = batchViewUpdates;
|
|
12450
12595
|
}
|
|
12451
|
-
|
|
12452
|
-
|
|
12453
|
-
return {
|
|
12454
|
-
tableName: this.#tableName,
|
|
12455
|
-
columns: this.#columns,
|
|
12456
|
-
primaryKey: this.#primaryKey
|
|
12457
|
-
};
|
|
12596
|
+
getSource(name) {
|
|
12597
|
+
return this.#mainSources.getSource(name);
|
|
12458
12598
|
}
|
|
12459
|
-
|
|
12460
|
-
return
|
|
12461
|
-
tableName: this.#tableName,
|
|
12462
|
-
columns: this.#columns,
|
|
12463
|
-
primaryKey: this.#primaryKey,
|
|
12464
|
-
sort: connection.sort,
|
|
12465
|
-
system: "client",
|
|
12466
|
-
relationships: {},
|
|
12467
|
-
isHidden: false,
|
|
12468
|
-
compareRows: connection.compareRows
|
|
12469
|
-
};
|
|
12599
|
+
addServerQuery(ast, gotCallback) {
|
|
12600
|
+
return this.#addQuery(ast, gotCallback);
|
|
12470
12601
|
}
|
|
12471
|
-
|
|
12472
|
-
|
|
12473
|
-
|
|
12474
|
-
|
|
12475
|
-
|
|
12476
|
-
|
|
12477
|
-
|
|
12478
|
-
connection.output = output;
|
|
12479
|
-
},
|
|
12480
|
-
destroy: () => {
|
|
12481
|
-
this.#disconnect(input);
|
|
12482
|
-
},
|
|
12483
|
-
fullyAppliedFilters: !transformedFilters.conditionsRemoved
|
|
12602
|
+
createStorage() {
|
|
12603
|
+
return new MemoryStorage();
|
|
12604
|
+
}
|
|
12605
|
+
onTransactionCommit(cb) {
|
|
12606
|
+
this.#commitListeners.add(cb);
|
|
12607
|
+
return () => {
|
|
12608
|
+
this.#commitListeners.delete(cb);
|
|
12484
12609
|
};
|
|
12485
|
-
const connection = {
|
|
12486
|
-
input,
|
|
12487
|
-
output: void 0,
|
|
12488
|
-
sort,
|
|
12489
|
-
compareRows: makeComparator(sort),
|
|
12490
|
-
filters: transformedFilters.filters ? {
|
|
12491
|
-
condition: transformedFilters.filters,
|
|
12492
|
-
predicate: createPredicate(transformedFilters.filters)
|
|
12493
|
-
} : void 0
|
|
12494
|
-
};
|
|
12495
|
-
const schema = this.#getSchema(connection);
|
|
12496
|
-
assertOrderingIncludesPK(sort, this.#primaryKey);
|
|
12497
|
-
this.#connections.push(connection);
|
|
12498
|
-
return input;
|
|
12499
12610
|
}
|
|
12500
|
-
|
|
12501
|
-
|
|
12502
|
-
|
|
12503
|
-
|
|
12504
|
-
|
|
12505
|
-
|
|
12506
|
-
|
|
12507
|
-
|
|
12508
|
-
|
|
12509
|
-
|
|
12510
|
-
|
|
12511
|
-
|
|
12512
|
-
this.#indexes.delete(key);
|
|
12513
|
-
}
|
|
12514
|
-
}
|
|
12611
|
+
batchViewUpdates(applyViewUpdates) {
|
|
12612
|
+
let result;
|
|
12613
|
+
let viewChangesPerformed = false;
|
|
12614
|
+
this.#batchViewUpdates(() => {
|
|
12615
|
+
result = applyViewUpdates();
|
|
12616
|
+
viewChangesPerformed = true;
|
|
12617
|
+
});
|
|
12618
|
+
assert(
|
|
12619
|
+
viewChangesPerformed,
|
|
12620
|
+
"batchViewUpdates must call applyViewUpdates synchronously."
|
|
12621
|
+
);
|
|
12622
|
+
return result;
|
|
12515
12623
|
}
|
|
12516
|
-
|
|
12517
|
-
|
|
12518
|
-
|
|
12519
|
-
|
|
12624
|
+
processChanges(changes) {
|
|
12625
|
+
this.batchViewUpdates(() => {
|
|
12626
|
+
try {
|
|
12627
|
+
for (const diff2 of changes) {
|
|
12628
|
+
const { key } = diff2;
|
|
12629
|
+
assert(key.startsWith(ENTITIES_KEY_PREFIX));
|
|
12630
|
+
const slash = key.indexOf("/", ENTITIES_KEY_PREFIX.length);
|
|
12631
|
+
const name = key.slice(ENTITIES_KEY_PREFIX.length, slash);
|
|
12632
|
+
const source = this.getSource(name);
|
|
12633
|
+
if (!source) {
|
|
12634
|
+
continue;
|
|
12635
|
+
}
|
|
12636
|
+
switch (diff2.op) {
|
|
12637
|
+
case "del":
|
|
12638
|
+
assert(typeof diff2.oldValue === "object");
|
|
12639
|
+
source.push({
|
|
12640
|
+
type: "remove",
|
|
12641
|
+
row: diff2.oldValue
|
|
12642
|
+
});
|
|
12643
|
+
break;
|
|
12644
|
+
case "add":
|
|
12645
|
+
assert(typeof diff2.newValue === "object");
|
|
12646
|
+
source.push({
|
|
12647
|
+
type: "add",
|
|
12648
|
+
row: diff2.newValue
|
|
12649
|
+
});
|
|
12650
|
+
break;
|
|
12651
|
+
case "change":
|
|
12652
|
+
assert(typeof diff2.newValue === "object");
|
|
12653
|
+
assert(typeof diff2.oldValue === "object");
|
|
12654
|
+
source.push({
|
|
12655
|
+
type: "edit",
|
|
12656
|
+
row: diff2.newValue,
|
|
12657
|
+
oldRow: diff2.oldValue
|
|
12658
|
+
});
|
|
12659
|
+
break;
|
|
12660
|
+
default:
|
|
12661
|
+
unreachable(diff2);
|
|
12662
|
+
}
|
|
12663
|
+
}
|
|
12664
|
+
} finally {
|
|
12665
|
+
this.#endTransaction();
|
|
12666
|
+
}
|
|
12667
|
+
});
|
|
12520
12668
|
}
|
|
12521
|
-
#
|
|
12522
|
-
const
|
|
12523
|
-
|
|
12524
|
-
if (index) {
|
|
12525
|
-
index.usedBy.add(usedBy);
|
|
12526
|
-
return index;
|
|
12527
|
-
}
|
|
12528
|
-
const comparator2 = makeBoundComparator(sort);
|
|
12529
|
-
const data = new BTreeSet(comparator2);
|
|
12530
|
-
for (const row of this.#getPrimaryIndex().data) {
|
|
12531
|
-
data.add(row);
|
|
12669
|
+
#endTransaction() {
|
|
12670
|
+
for (const listener of this.#commitListeners) {
|
|
12671
|
+
listener();
|
|
12532
12672
|
}
|
|
12533
|
-
const newIndex = { comparator: comparator2, data, usedBy: /* @__PURE__ */ new Set([usedBy]) };
|
|
12534
|
-
this.#indexes.set(key, newIndex);
|
|
12535
|
-
return newIndex;
|
|
12536
|
-
}
|
|
12537
|
-
// For unit testing that we correctly clean up indexes.
|
|
12538
|
-
getIndexKeys() {
|
|
12539
|
-
return [...this.#indexes.keys()];
|
|
12540
12673
|
}
|
|
12541
|
-
|
|
12542
|
-
|
|
12543
|
-
|
|
12544
|
-
|
|
12545
|
-
|
|
12546
|
-
|
|
12547
|
-
|
|
12548
|
-
if (
|
|
12549
|
-
|
|
12550
|
-
indexSort.push([key, "asc"]);
|
|
12551
|
-
}
|
|
12552
|
-
}
|
|
12553
|
-
if (this.#primaryKey.length > 1 || !req.constraint || !constraintMatchesPrimaryKey(req.constraint, this.#primaryKey)) {
|
|
12554
|
-
indexSort.push(...requestedSort);
|
|
12674
|
+
};
|
|
12675
|
+
|
|
12676
|
+
// ../zero-client/src/client/crud.ts
|
|
12677
|
+
function makeCRUDMutate(schema, repMutate) {
|
|
12678
|
+
const { [CRUD_MUTATION_NAME]: zeroCRUD } = repMutate;
|
|
12679
|
+
let inBatch = false;
|
|
12680
|
+
const mutateBatch = async (body) => {
|
|
12681
|
+
if (inBatch) {
|
|
12682
|
+
throw new Error("Cannot call mutate inside a batch");
|
|
12555
12683
|
}
|
|
12556
|
-
|
|
12557
|
-
|
|
12558
|
-
|
|
12559
|
-
|
|
12560
|
-
|
|
12561
|
-
|
|
12684
|
+
inBatch = true;
|
|
12685
|
+
try {
|
|
12686
|
+
const ops = [];
|
|
12687
|
+
const m = {};
|
|
12688
|
+
for (const name of Object.keys(schema.tables)) {
|
|
12689
|
+
m[name] = makeBatchCRUDMutate(name, schema, ops);
|
|
12562
12690
|
}
|
|
12691
|
+
const rv = await body(m);
|
|
12692
|
+
await zeroCRUD({ ops });
|
|
12693
|
+
return rv;
|
|
12694
|
+
} finally {
|
|
12695
|
+
inBatch = false;
|
|
12563
12696
|
}
|
|
12564
|
-
|
|
12565
|
-
|
|
12566
|
-
if (
|
|
12567
|
-
|
|
12568
|
-
for (const [key, dir] of indexSort) {
|
|
12569
|
-
if (hasOwn(req.constraint, key)) {
|
|
12570
|
-
scanStart[key] = req.constraint[key];
|
|
12571
|
-
} else {
|
|
12572
|
-
if (req.reverse) {
|
|
12573
|
-
scanStart[key] = dir === "asc" ? maxValue : minValue;
|
|
12574
|
-
} else {
|
|
12575
|
-
scanStart[key] = dir === "asc" ? minValue : maxValue;
|
|
12576
|
-
}
|
|
12577
|
-
}
|
|
12578
|
-
}
|
|
12579
|
-
} else {
|
|
12580
|
-
scanStart = startAt;
|
|
12697
|
+
};
|
|
12698
|
+
const assertNotInBatch = (tableName, op) => {
|
|
12699
|
+
if (inBatch) {
|
|
12700
|
+
throw new Error(`Cannot call mutate.${tableName}.${op} inside a batch`);
|
|
12581
12701
|
}
|
|
12582
|
-
|
|
12583
|
-
|
|
12584
|
-
|
|
12585
|
-
|
|
12586
|
-
|
|
12587
|
-
|
|
12588
|
-
|
|
12589
|
-
|
|
12590
|
-
const withConstraint = generateWithConstraint(
|
|
12591
|
-
generateWithStart(withOverlay, req.start, comparator2),
|
|
12592
|
-
req.constraint
|
|
12702
|
+
};
|
|
12703
|
+
const mutate = {};
|
|
12704
|
+
for (const [name, tableSchema] of Object.entries(schema.tables)) {
|
|
12705
|
+
mutate[name] = makeEntityCRUDMutate(
|
|
12706
|
+
name,
|
|
12707
|
+
tableSchema.primaryKey,
|
|
12708
|
+
zeroCRUD,
|
|
12709
|
+
assertNotInBatch
|
|
12593
12710
|
);
|
|
12594
|
-
yield* conn.filters ? generateWithFilter(withConstraint, conn.filters.predicate) : withConstraint;
|
|
12595
12711
|
}
|
|
12596
|
-
|
|
12597
|
-
|
|
12598
|
-
|
|
12599
|
-
|
|
12600
|
-
|
|
12601
|
-
|
|
12602
|
-
|
|
12603
|
-
|
|
12604
|
-
|
|
12605
|
-
|
|
12606
|
-
|
|
12607
|
-
|
|
12608
|
-
|
|
12609
|
-
|
|
12610
|
-
|
|
12611
|
-
|
|
12612
|
-
|
|
12613
|
-
|
|
12614
|
-
|
|
12615
|
-
|
|
12616
|
-
|
|
12617
|
-
|
|
12618
|
-
|
|
12619
|
-
|
|
12620
|
-
|
|
12621
|
-
|
|
12622
|
-
|
|
12623
|
-
|
|
12624
|
-
|
|
12625
|
-
|
|
12626
|
-
|
|
12712
|
+
return {
|
|
12713
|
+
mutate,
|
|
12714
|
+
mutateBatch
|
|
12715
|
+
};
|
|
12716
|
+
}
|
|
12717
|
+
function makeEntityCRUDMutate(tableName, primaryKey, zeroCRUD, assertNotInBatch) {
|
|
12718
|
+
return {
|
|
12719
|
+
insert: (value) => {
|
|
12720
|
+
assertNotInBatch(tableName, "insert");
|
|
12721
|
+
const op = {
|
|
12722
|
+
op: "insert",
|
|
12723
|
+
tableName,
|
|
12724
|
+
primaryKey,
|
|
12725
|
+
value
|
|
12726
|
+
};
|
|
12727
|
+
return zeroCRUD({ ops: [op] });
|
|
12728
|
+
},
|
|
12729
|
+
upsert: (value) => {
|
|
12730
|
+
assertNotInBatch(tableName, "upsert");
|
|
12731
|
+
const op = {
|
|
12732
|
+
op: "upsert",
|
|
12733
|
+
tableName,
|
|
12734
|
+
primaryKey,
|
|
12735
|
+
value
|
|
12736
|
+
};
|
|
12737
|
+
return zeroCRUD({ ops: [op] });
|
|
12738
|
+
},
|
|
12739
|
+
update: (value) => {
|
|
12740
|
+
assertNotInBatch(tableName, "update");
|
|
12741
|
+
const op = {
|
|
12742
|
+
op: "update",
|
|
12743
|
+
tableName,
|
|
12744
|
+
primaryKey,
|
|
12745
|
+
value
|
|
12746
|
+
};
|
|
12747
|
+
return zeroCRUD({ ops: [op] });
|
|
12748
|
+
},
|
|
12749
|
+
delete: (id) => {
|
|
12750
|
+
assertNotInBatch(tableName, "delete");
|
|
12751
|
+
const op = {
|
|
12752
|
+
op: "delete",
|
|
12753
|
+
tableName,
|
|
12754
|
+
primaryKey,
|
|
12755
|
+
value: id
|
|
12756
|
+
};
|
|
12757
|
+
return zeroCRUD({ ops: [op] });
|
|
12627
12758
|
}
|
|
12628
|
-
|
|
12629
|
-
|
|
12630
|
-
|
|
12631
|
-
|
|
12632
|
-
|
|
12633
|
-
|
|
12634
|
-
|
|
12635
|
-
|
|
12636
|
-
|
|
12637
|
-
|
|
12638
|
-
|
|
12639
|
-
|
|
12640
|
-
|
|
12641
|
-
|
|
12642
|
-
|
|
12643
|
-
|
|
12644
|
-
|
|
12645
|
-
|
|
12646
|
-
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
|
|
12652
|
-
|
|
12653
|
-
|
|
12759
|
+
};
|
|
12760
|
+
}
|
|
12761
|
+
function makeBatchCRUDMutate(tableName, schema, ops) {
|
|
12762
|
+
const { primaryKey } = schema.tables[tableName];
|
|
12763
|
+
return {
|
|
12764
|
+
insert: (value) => {
|
|
12765
|
+
const op = {
|
|
12766
|
+
op: "insert",
|
|
12767
|
+
tableName,
|
|
12768
|
+
primaryKey,
|
|
12769
|
+
value
|
|
12770
|
+
};
|
|
12771
|
+
ops.push(op);
|
|
12772
|
+
return promiseVoid;
|
|
12773
|
+
},
|
|
12774
|
+
upsert: (value) => {
|
|
12775
|
+
const op = {
|
|
12776
|
+
op: "upsert",
|
|
12777
|
+
tableName,
|
|
12778
|
+
primaryKey,
|
|
12779
|
+
value
|
|
12780
|
+
};
|
|
12781
|
+
ops.push(op);
|
|
12782
|
+
return promiseVoid;
|
|
12783
|
+
},
|
|
12784
|
+
update: (value) => {
|
|
12785
|
+
const op = {
|
|
12786
|
+
op: "update",
|
|
12787
|
+
tableName,
|
|
12788
|
+
primaryKey,
|
|
12789
|
+
value
|
|
12790
|
+
};
|
|
12791
|
+
ops.push(op);
|
|
12792
|
+
return promiseVoid;
|
|
12793
|
+
},
|
|
12794
|
+
delete: (id) => {
|
|
12795
|
+
const op = {
|
|
12796
|
+
op: "delete",
|
|
12797
|
+
tableName,
|
|
12798
|
+
primaryKey,
|
|
12799
|
+
value: id
|
|
12800
|
+
};
|
|
12801
|
+
ops.push(op);
|
|
12802
|
+
return promiseVoid;
|
|
12654
12803
|
}
|
|
12655
|
-
|
|
12656
|
-
|
|
12657
|
-
|
|
12658
|
-
|
|
12659
|
-
|
|
12660
|
-
|
|
12804
|
+
};
|
|
12805
|
+
}
|
|
12806
|
+
function makeCRUDMutator(schema) {
|
|
12807
|
+
return async function zeroCRUDMutator(tx, crudArg) {
|
|
12808
|
+
for (const op of crudArg.ops) {
|
|
12809
|
+
switch (op.op) {
|
|
12810
|
+
case "insert":
|
|
12811
|
+
await insertImpl(tx, op, schema);
|
|
12661
12812
|
break;
|
|
12662
|
-
|
|
12663
|
-
|
|
12664
|
-
const removed = data2.delete(change.row);
|
|
12665
|
-
assert(removed);
|
|
12813
|
+
case "upsert":
|
|
12814
|
+
await upsertImpl(tx, op, schema);
|
|
12666
12815
|
break;
|
|
12667
|
-
|
|
12668
|
-
|
|
12669
|
-
|
|
12670
|
-
|
|
12671
|
-
|
|
12816
|
+
case "update":
|
|
12817
|
+
await updateImpl(tx, op, schema);
|
|
12818
|
+
break;
|
|
12819
|
+
case "delete":
|
|
12820
|
+
await deleteImpl(tx, op, schema);
|
|
12672
12821
|
break;
|
|
12673
|
-
}
|
|
12674
|
-
default:
|
|
12675
|
-
unreachable(change);
|
|
12676
12822
|
}
|
|
12677
12823
|
}
|
|
12678
|
-
}
|
|
12679
|
-
};
|
|
12680
|
-
function* generateWithConstraint(it, constraint) {
|
|
12681
|
-
for (const node of it) {
|
|
12682
|
-
if (constraint && !constraintMatchesRow(constraint, node.row)) {
|
|
12683
|
-
break;
|
|
12684
|
-
}
|
|
12685
|
-
yield node;
|
|
12686
|
-
}
|
|
12824
|
+
};
|
|
12687
12825
|
}
|
|
12688
|
-
function
|
|
12689
|
-
|
|
12690
|
-
|
|
12691
|
-
|
|
12826
|
+
function defaultOptionalFieldsToNull(schema, value) {
|
|
12827
|
+
let rv = value;
|
|
12828
|
+
for (const name in schema.columns) {
|
|
12829
|
+
if (rv[name] === void 0) {
|
|
12830
|
+
rv = { ...rv, [name]: null };
|
|
12692
12831
|
}
|
|
12693
12832
|
}
|
|
12833
|
+
return rv;
|
|
12694
12834
|
}
|
|
12695
|
-
function
|
|
12696
|
-
|
|
12697
|
-
|
|
12698
|
-
|
|
12835
|
+
async function insertImpl(tx, arg, schema) {
|
|
12836
|
+
const key = toPrimaryKeyString(
|
|
12837
|
+
arg.tableName,
|
|
12838
|
+
schema.tables[arg.tableName].primaryKey,
|
|
12839
|
+
arg.value
|
|
12840
|
+
);
|
|
12841
|
+
if (!await tx.has(key)) {
|
|
12842
|
+
const val = defaultOptionalFieldsToNull(
|
|
12843
|
+
schema.tables[arg.tableName],
|
|
12844
|
+
arg.value
|
|
12845
|
+
);
|
|
12846
|
+
await tx.set(key, val);
|
|
12699
12847
|
}
|
|
12700
|
-
|
|
12701
|
-
|
|
12702
|
-
|
|
12703
|
-
|
|
12704
|
-
|
|
12705
|
-
|
|
12706
|
-
|
|
12707
|
-
|
|
12708
|
-
|
|
12709
|
-
|
|
12710
|
-
|
|
12711
|
-
|
|
12712
|
-
|
|
12713
|
-
|
|
12714
|
-
|
|
12848
|
+
}
|
|
12849
|
+
async function upsertImpl(tx, arg, schema) {
|
|
12850
|
+
const key = toPrimaryKeyString(
|
|
12851
|
+
arg.tableName,
|
|
12852
|
+
schema.tables[arg.tableName].primaryKey,
|
|
12853
|
+
arg.value
|
|
12854
|
+
);
|
|
12855
|
+
const val = defaultOptionalFieldsToNull(
|
|
12856
|
+
schema.tables[arg.tableName],
|
|
12857
|
+
arg.value
|
|
12858
|
+
);
|
|
12859
|
+
await tx.set(key, val);
|
|
12860
|
+
}
|
|
12861
|
+
async function updateImpl(tx, arg, schema) {
|
|
12862
|
+
const key = toPrimaryKeyString(
|
|
12863
|
+
arg.tableName,
|
|
12864
|
+
schema.tables[arg.tableName].primaryKey,
|
|
12865
|
+
arg.value
|
|
12866
|
+
);
|
|
12867
|
+
const prev = await tx.get(key);
|
|
12868
|
+
if (prev === void 0) {
|
|
12869
|
+
return;
|
|
12870
|
+
}
|
|
12871
|
+
const update = arg.value;
|
|
12872
|
+
const next = { ...prev };
|
|
12873
|
+
for (const k in update) {
|
|
12874
|
+
if (update[k] !== void 0) {
|
|
12875
|
+
next[k] = update[k];
|
|
12715
12876
|
}
|
|
12716
12877
|
}
|
|
12878
|
+
await tx.set(key, next);
|
|
12717
12879
|
}
|
|
12718
|
-
function
|
|
12719
|
-
const
|
|
12720
|
-
|
|
12721
|
-
|
|
12722
|
-
|
|
12723
|
-
compare,
|
|
12724
|
-
filterPredicate
|
|
12880
|
+
async function deleteImpl(tx, arg, schema) {
|
|
12881
|
+
const key = toPrimaryKeyString(
|
|
12882
|
+
arg.tableName,
|
|
12883
|
+
schema.tables[arg.tableName].primaryKey,
|
|
12884
|
+
arg.value
|
|
12725
12885
|
);
|
|
12726
|
-
|
|
12886
|
+
await tx.del(key);
|
|
12727
12887
|
}
|
|
12728
|
-
|
|
12729
|
-
|
|
12730
|
-
|
|
12731
|
-
|
|
12732
|
-
|
|
12733
|
-
|
|
12734
|
-
|
|
12735
|
-
|
|
12736
|
-
|
|
12737
|
-
|
|
12738
|
-
|
|
12739
|
-
|
|
12740
|
-
|
|
12741
|
-
|
|
12742
|
-
|
|
12743
|
-
|
|
12744
|
-
|
|
12745
|
-
break;
|
|
12746
|
-
case "edit":
|
|
12747
|
-
overlays = {
|
|
12748
|
-
add: overlay.change.row,
|
|
12749
|
-
remove: overlay.change.oldRow
|
|
12750
|
-
};
|
|
12751
|
-
break;
|
|
12752
|
-
}
|
|
12753
|
-
if (startAt) {
|
|
12754
|
-
overlays = overlaysForStartAt(overlays, startAt, compare);
|
|
12888
|
+
|
|
12889
|
+
// ../zero-client/src/client/custom.ts
|
|
12890
|
+
var TransactionImpl = class {
|
|
12891
|
+
constructor(repTx, schema, ivmSourceRepo) {
|
|
12892
|
+
must(repTx.reason === "initial" || repTx.reason === "rebase");
|
|
12893
|
+
this.clientID = repTx.clientID;
|
|
12894
|
+
this.mutationID = repTx.mutationID;
|
|
12895
|
+
this.reason = repTx.reason === "initial" ? "optimistic" : "rebase";
|
|
12896
|
+
this.mutate = makeSchemaCRUD(schema, repTx);
|
|
12897
|
+
this.query = makeSchemaQuery(
|
|
12898
|
+
schema,
|
|
12899
|
+
this.reason === "optimistic" ? ivmSourceRepo.main : (
|
|
12900
|
+
// TODO: we don't initialize the sync branch yet.
|
|
12901
|
+
// to fix in the next PR.
|
|
12902
|
+
ivmSourceRepo.main
|
|
12903
|
+
)
|
|
12904
|
+
);
|
|
12755
12905
|
}
|
|
12756
|
-
|
|
12757
|
-
|
|
12906
|
+
clientID;
|
|
12907
|
+
mutationID;
|
|
12908
|
+
reason;
|
|
12909
|
+
mutate;
|
|
12910
|
+
query;
|
|
12911
|
+
};
|
|
12912
|
+
function makeReplicacheMutator(mutator, schema, ivmSourceRepo) {
|
|
12913
|
+
return (repTx, args) => {
|
|
12914
|
+
const tx = new TransactionImpl(repTx, schema, ivmSourceRepo);
|
|
12915
|
+
return mutator(tx, args);
|
|
12916
|
+
};
|
|
12917
|
+
}
|
|
12918
|
+
function makeSchemaQuery(schema, ivmBranch) {
|
|
12919
|
+
const rv = {};
|
|
12920
|
+
const context = new ZeroContext(
|
|
12921
|
+
ivmBranch,
|
|
12922
|
+
() => () => {
|
|
12923
|
+
},
|
|
12924
|
+
(applyViewUpdates) => applyViewUpdates()
|
|
12925
|
+
);
|
|
12926
|
+
for (const name of Object.keys(schema.tables)) {
|
|
12927
|
+
rv[name] = newQuery(context, schema, name);
|
|
12758
12928
|
}
|
|
12759
|
-
|
|
12760
|
-
|
|
12929
|
+
return rv;
|
|
12930
|
+
}
|
|
12931
|
+
function makeSchemaCRUD(schema, tx) {
|
|
12932
|
+
const mutate = {};
|
|
12933
|
+
for (const [name] of Object.entries(schema.tables)) {
|
|
12934
|
+
mutate[name] = makeTableCRUD(schema, name, tx);
|
|
12761
12935
|
}
|
|
12762
|
-
return
|
|
12936
|
+
return mutate;
|
|
12763
12937
|
}
|
|
12764
|
-
function
|
|
12765
|
-
const
|
|
12938
|
+
function makeTableCRUD(schema, tableName, tx) {
|
|
12939
|
+
const table2 = must(schema.tables[tableName]);
|
|
12940
|
+
const { primaryKey } = table2;
|
|
12766
12941
|
return {
|
|
12767
|
-
|
|
12768
|
-
|
|
12942
|
+
insert: (value) => insertImpl(tx, { op: "insert", tableName, primaryKey, value }, schema),
|
|
12943
|
+
upsert: (value) => upsertImpl(tx, { op: "upsert", tableName, primaryKey, value }, schema),
|
|
12944
|
+
update: (value) => updateImpl(tx, { op: "update", tableName, primaryKey, value }, schema),
|
|
12945
|
+
delete: (id) => deleteImpl(tx, { op: "delete", tableName, primaryKey, value: id }, schema)
|
|
12769
12946
|
};
|
|
12770
12947
|
}
|
|
12771
|
-
|
|
12772
|
-
|
|
12773
|
-
|
|
12774
|
-
|
|
12775
|
-
|
|
12776
|
-
}
|
|
12948
|
+
|
|
12949
|
+
// ../zero-client/src/client/enable-analytics.ts
|
|
12950
|
+
var IPV4_ADDRESS_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
|
12951
|
+
var IPV6_ADDRESS_HOSTNAME_REGEX = /^\[[a-fA-F0-9:]*:[a-fA-F0-9:]*\]$/;
|
|
12952
|
+
var IP_ADDRESS_HOSTNAME_REGEX = new RegExp(
|
|
12953
|
+
`(${IPV4_ADDRESS_REGEX.source}|${IPV6_ADDRESS_HOSTNAME_REGEX.source})`
|
|
12954
|
+
);
|
|
12955
|
+
function shouldEnableAnalytics(server, enableAnalytics = true) {
|
|
12956
|
+
if (!enableAnalytics) {
|
|
12957
|
+
return false;
|
|
12958
|
+
}
|
|
12959
|
+
const serverURL = server === null ? null : new URL(server);
|
|
12960
|
+
const socketHostname = serverURL?.hostname;
|
|
12961
|
+
return server !== null && socketHostname !== void 0 && socketHostname !== "localhost" && !IP_ADDRESS_HOSTNAME_REGEX.test(socketHostname);
|
|
12777
12962
|
}
|
|
12778
|
-
|
|
12779
|
-
|
|
12780
|
-
|
|
12781
|
-
|
|
12782
|
-
remove: undefinedIfDoesntMatchFilter(remove)
|
|
12783
|
-
};
|
|
12963
|
+
|
|
12964
|
+
// ../zero-client/src/client/http-string.ts
|
|
12965
|
+
function toWSString(url) {
|
|
12966
|
+
return "ws" + url.slice(4);
|
|
12784
12967
|
}
|
|
12785
|
-
function
|
|
12786
|
-
|
|
12787
|
-
|
|
12788
|
-
|
|
12789
|
-
|
|
12790
|
-
|
|
12791
|
-
|
|
12792
|
-
|
|
12793
|
-
|
|
12794
|
-
}
|
|
12968
|
+
function appendPath(url, toAppend) {
|
|
12969
|
+
return url + (url.endsWith("/") ? toAppend.substring(1) : toAppend);
|
|
12970
|
+
}
|
|
12971
|
+
|
|
12972
|
+
// ../zql/src/ivm/constraint.ts
|
|
12973
|
+
function constraintMatchesRow(constraint, row) {
|
|
12974
|
+
for (const key in constraint) {
|
|
12975
|
+
if (!valuesEqual(row[key], constraint[key])) {
|
|
12976
|
+
return false;
|
|
12795
12977
|
}
|
|
12796
|
-
|
|
12797
|
-
|
|
12798
|
-
|
|
12799
|
-
|
|
12978
|
+
}
|
|
12979
|
+
return true;
|
|
12980
|
+
}
|
|
12981
|
+
function constraintMatchesPrimaryKey(constraint, primary) {
|
|
12982
|
+
const constraintKeys = Object.keys(constraint);
|
|
12983
|
+
if (constraintKeys.length !== primary.length) {
|
|
12984
|
+
return false;
|
|
12985
|
+
}
|
|
12986
|
+
constraintKeys.sort(stringCompare);
|
|
12987
|
+
for (let i = 0; i < constraintKeys.length; i++) {
|
|
12988
|
+
if (constraintKeys[i][0] !== primary[i]) {
|
|
12989
|
+
return false;
|
|
12990
|
+
}
|
|
12991
|
+
}
|
|
12992
|
+
return true;
|
|
12993
|
+
}
|
|
12994
|
+
|
|
12995
|
+
// ../zql/src/ivm/memory-source.ts
|
|
12996
|
+
var MemorySource = class _MemorySource {
|
|
12997
|
+
#tableName;
|
|
12998
|
+
#columns;
|
|
12999
|
+
#primaryKey;
|
|
13000
|
+
#primaryIndexSort;
|
|
13001
|
+
#indexes = /* @__PURE__ */ new Map();
|
|
13002
|
+
#connections = [];
|
|
13003
|
+
#overlay;
|
|
13004
|
+
constructor(tableName, columns, primaryKey, primaryIndexData) {
|
|
13005
|
+
this.#tableName = tableName;
|
|
13006
|
+
this.#columns = columns;
|
|
13007
|
+
this.#primaryKey = primaryKey;
|
|
13008
|
+
this.#primaryIndexSort = primaryKey.map((k) => [k, "asc"]);
|
|
13009
|
+
const comparator2 = makeBoundComparator(this.#primaryIndexSort);
|
|
13010
|
+
this.#indexes.set(JSON.stringify(this.#primaryIndexSort), {
|
|
13011
|
+
comparator: comparator2,
|
|
13012
|
+
data: primaryIndexData ?? new BTreeSet(comparator2),
|
|
13013
|
+
usedBy: /* @__PURE__ */ new Set()
|
|
13014
|
+
});
|
|
13015
|
+
assertOrderingIncludesPK(this.#primaryIndexSort, this.#primaryKey);
|
|
13016
|
+
}
|
|
13017
|
+
// Mainly for tests.
|
|
13018
|
+
getSchemaInfo() {
|
|
13019
|
+
return {
|
|
13020
|
+
tableName: this.#tableName,
|
|
13021
|
+
columns: this.#columns,
|
|
13022
|
+
primaryKey: this.#primaryKey
|
|
13023
|
+
};
|
|
13024
|
+
}
|
|
13025
|
+
fork() {
|
|
13026
|
+
const primaryIndex = this.#getPrimaryIndex();
|
|
13027
|
+
return new _MemorySource(
|
|
13028
|
+
this.#tableName,
|
|
13029
|
+
this.#columns,
|
|
13030
|
+
this.#primaryKey,
|
|
13031
|
+
primaryIndex.data.clone()
|
|
13032
|
+
);
|
|
13033
|
+
}
|
|
13034
|
+
#getSchema(connection) {
|
|
13035
|
+
return {
|
|
13036
|
+
tableName: this.#tableName,
|
|
13037
|
+
columns: this.#columns,
|
|
13038
|
+
primaryKey: this.#primaryKey,
|
|
13039
|
+
sort: connection.sort,
|
|
13040
|
+
system: "client",
|
|
13041
|
+
relationships: {},
|
|
13042
|
+
isHidden: false,
|
|
13043
|
+
compareRows: connection.compareRows
|
|
13044
|
+
};
|
|
13045
|
+
}
|
|
13046
|
+
connect(sort, filters) {
|
|
13047
|
+
const transformedFilters = transformFilters(filters);
|
|
13048
|
+
const input = {
|
|
13049
|
+
getSchema: () => schema,
|
|
13050
|
+
fetch: (req) => this.#fetch(req, connection),
|
|
13051
|
+
cleanup: (req) => this.#cleanup(req, connection),
|
|
13052
|
+
setOutput: (output) => {
|
|
13053
|
+
connection.output = output;
|
|
13054
|
+
},
|
|
13055
|
+
destroy: () => {
|
|
13056
|
+
this.#disconnect(input);
|
|
13057
|
+
},
|
|
13058
|
+
fullyAppliedFilters: !transformedFilters.conditionsRemoved
|
|
13059
|
+
};
|
|
13060
|
+
const connection = {
|
|
13061
|
+
input,
|
|
13062
|
+
output: void 0,
|
|
13063
|
+
sort,
|
|
13064
|
+
compareRows: makeComparator(sort),
|
|
13065
|
+
filters: transformedFilters.filters ? {
|
|
13066
|
+
condition: transformedFilters.filters,
|
|
13067
|
+
predicate: createPredicate(transformedFilters.filters)
|
|
13068
|
+
} : void 0
|
|
13069
|
+
};
|
|
13070
|
+
const schema = this.#getSchema(connection);
|
|
13071
|
+
assertOrderingIncludesPK(sort, this.#primaryKey);
|
|
13072
|
+
this.#connections.push(connection);
|
|
13073
|
+
return input;
|
|
13074
|
+
}
|
|
13075
|
+
#disconnect(input) {
|
|
13076
|
+
const idx = this.#connections.findIndex((c) => c.input === input);
|
|
13077
|
+
assert(idx !== -1, "Connection not found");
|
|
13078
|
+
const connection = this.#connections[idx];
|
|
13079
|
+
this.#connections.splice(idx, 1);
|
|
13080
|
+
const primaryIndexKey = JSON.stringify(this.#primaryIndexSort);
|
|
13081
|
+
for (const [key, index] of this.#indexes) {
|
|
13082
|
+
if (key === primaryIndexKey) {
|
|
12800
13083
|
continue;
|
|
12801
13084
|
}
|
|
13085
|
+
index.usedBy.delete(connection);
|
|
13086
|
+
if (index.usedBy.size === 0) {
|
|
13087
|
+
this.#indexes.delete(key);
|
|
13088
|
+
}
|
|
12802
13089
|
}
|
|
12803
|
-
yield { row, relationships: {} };
|
|
12804
13090
|
}
|
|
12805
|
-
|
|
12806
|
-
|
|
13091
|
+
#getPrimaryIndex() {
|
|
13092
|
+
const index = this.#indexes.get(JSON.stringify(this.#primaryIndexSort));
|
|
13093
|
+
assert(index, "Primary index not found");
|
|
13094
|
+
return index;
|
|
12807
13095
|
}
|
|
12808
|
-
|
|
12809
|
-
|
|
12810
|
-
|
|
12811
|
-
|
|
12812
|
-
|
|
12813
|
-
|
|
12814
|
-
const key = entry[0];
|
|
12815
|
-
const cmp2 = compareBounds(a[key], b[key]);
|
|
12816
|
-
if (cmp2 !== 0) {
|
|
12817
|
-
return entry[1] === "asc" ? cmp2 : -cmp2;
|
|
12818
|
-
}
|
|
13096
|
+
#getOrCreateIndex(sort, usedBy) {
|
|
13097
|
+
const key = JSON.stringify(sort);
|
|
13098
|
+
const index = this.#indexes.get(key);
|
|
13099
|
+
if (index) {
|
|
13100
|
+
index.usedBy.add(usedBy);
|
|
13101
|
+
return index;
|
|
12819
13102
|
}
|
|
12820
|
-
|
|
12821
|
-
|
|
12822
|
-
|
|
12823
|
-
|
|
12824
|
-
if (a === b) {
|
|
12825
|
-
return 0;
|
|
12826
|
-
}
|
|
12827
|
-
if (a === minValue) {
|
|
12828
|
-
return -1;
|
|
12829
|
-
}
|
|
12830
|
-
if (b === minValue) {
|
|
12831
|
-
return 1;
|
|
12832
|
-
}
|
|
12833
|
-
if (a === maxValue) {
|
|
12834
|
-
return 1;
|
|
12835
|
-
}
|
|
12836
|
-
if (b === maxValue) {
|
|
12837
|
-
return -1;
|
|
12838
|
-
}
|
|
12839
|
-
return compareValues(a, b);
|
|
12840
|
-
}
|
|
12841
|
-
function* generateRows(data, scanStart, reverse) {
|
|
12842
|
-
yield* data[reverse ? "valuesFromReversed" : "valuesFrom"](
|
|
12843
|
-
scanStart
|
|
12844
|
-
);
|
|
12845
|
-
}
|
|
12846
|
-
|
|
12847
|
-
// ../zql/src/ivm/memory-storage.ts
|
|
12848
|
-
import { compareUTF8 as compareUTF84 } from "compare-utf8";
|
|
12849
|
-
function comparator(a, b) {
|
|
12850
|
-
return compareUTF84(a[0], b[0]);
|
|
12851
|
-
}
|
|
12852
|
-
var MemoryStorage = class {
|
|
12853
|
-
#data = new BTreeSet(comparator);
|
|
12854
|
-
set(key, value) {
|
|
12855
|
-
this.#data.add([key, value]);
|
|
12856
|
-
}
|
|
12857
|
-
get(key, def) {
|
|
12858
|
-
const r = this.#data.get([key, null]);
|
|
12859
|
-
if (r !== void 0) {
|
|
12860
|
-
return r[1];
|
|
13103
|
+
const comparator2 = makeBoundComparator(sort);
|
|
13104
|
+
const data = new BTreeSet(comparator2);
|
|
13105
|
+
for (const row of this.#getPrimaryIndex().data) {
|
|
13106
|
+
data.add(row);
|
|
12861
13107
|
}
|
|
12862
|
-
|
|
13108
|
+
const newIndex = { comparator: comparator2, data, usedBy: /* @__PURE__ */ new Set([usedBy]) };
|
|
13109
|
+
this.#indexes.set(key, newIndex);
|
|
13110
|
+
return newIndex;
|
|
12863
13111
|
}
|
|
12864
|
-
|
|
12865
|
-
|
|
13112
|
+
// For unit testing that we correctly clean up indexes.
|
|
13113
|
+
getIndexKeys() {
|
|
13114
|
+
return [...this.#indexes.keys()];
|
|
12866
13115
|
}
|
|
12867
|
-
|
|
12868
|
-
|
|
12869
|
-
|
|
12870
|
-
)
|
|
12871
|
-
|
|
12872
|
-
|
|
13116
|
+
*#fetch(req, from) {
|
|
13117
|
+
let overlay;
|
|
13118
|
+
const callingConnectionNum = this.#connections.indexOf(from);
|
|
13119
|
+
assert(callingConnectionNum !== -1, "Output not found");
|
|
13120
|
+
const conn = this.#connections[callingConnectionNum];
|
|
13121
|
+
const { sort: requestedSort } = conn;
|
|
13122
|
+
const indexSort = [];
|
|
13123
|
+
if (req.constraint) {
|
|
13124
|
+
for (const key of Object.keys(req.constraint)) {
|
|
13125
|
+
indexSort.push([key, "asc"]);
|
|
12873
13126
|
}
|
|
12874
|
-
yield entry;
|
|
12875
13127
|
}
|
|
12876
|
-
|
|
12877
|
-
|
|
12878
|
-
return structuredClone(Object.fromEntries(this.#data.values()));
|
|
12879
|
-
}
|
|
12880
|
-
};
|
|
12881
|
-
|
|
12882
|
-
// ../zero-client/src/client/keys.ts
|
|
12883
|
-
var CLIENTS_KEY_PREFIX = "c/";
|
|
12884
|
-
var DESIRED_QUERIES_KEY_PREFIX = "d/";
|
|
12885
|
-
var GOT_QUERIES_KEY_PREFIX = "g/";
|
|
12886
|
-
var ENTITIES_KEY_PREFIX = "e/";
|
|
12887
|
-
function toClientsKey(clientID) {
|
|
12888
|
-
return CLIENTS_KEY_PREFIX + clientID;
|
|
12889
|
-
}
|
|
12890
|
-
function toDesiredQueriesKey(clientID, hash2) {
|
|
12891
|
-
return DESIRED_QUERIES_KEY_PREFIX + clientID + "/" + hash2;
|
|
12892
|
-
}
|
|
12893
|
-
function desiredQueriesPrefixForClient(clientID) {
|
|
12894
|
-
return DESIRED_QUERIES_KEY_PREFIX + clientID + "/";
|
|
12895
|
-
}
|
|
12896
|
-
function toGotQueriesKey(hash2) {
|
|
12897
|
-
return GOT_QUERIES_KEY_PREFIX + hash2;
|
|
12898
|
-
}
|
|
12899
|
-
function toPrimaryKeyString(tableName, primaryKey, value) {
|
|
12900
|
-
if (primaryKey.length === 1) {
|
|
12901
|
-
return ENTITIES_KEY_PREFIX + tableName + "/" + parse(value[primaryKey[0]], primaryKeyValueSchema);
|
|
12902
|
-
}
|
|
12903
|
-
const values = primaryKey.map((k) => parse(value[k], primaryKeyValueSchema));
|
|
12904
|
-
const str = JSON.stringify(values);
|
|
12905
|
-
const idSegment = h128(str);
|
|
12906
|
-
return ENTITIES_KEY_PREFIX + tableName + "/" + idSegment;
|
|
12907
|
-
}
|
|
12908
|
-
|
|
12909
|
-
// ../zero-client/src/client/context.ts
|
|
12910
|
-
var ZeroContext = class {
|
|
12911
|
-
// It is a bummer to have to maintain separate MemorySources here and copy the
|
|
12912
|
-
// data in from the Replicache db. But we want the data to be accessible via
|
|
12913
|
-
// pipelines *synchronously* and the core Replicache infra is all async. So
|
|
12914
|
-
// that needs to be fixed.
|
|
12915
|
-
#sources = /* @__PURE__ */ new Map();
|
|
12916
|
-
#tables;
|
|
12917
|
-
#addQuery;
|
|
12918
|
-
#batchViewUpdates;
|
|
12919
|
-
#commitListeners = /* @__PURE__ */ new Set();
|
|
12920
|
-
staticQueryParameters = void 0;
|
|
12921
|
-
constructor(tables, addQuery, batchViewUpdates) {
|
|
12922
|
-
this.#tables = tables;
|
|
12923
|
-
this.#addQuery = addQuery;
|
|
12924
|
-
this.#batchViewUpdates = batchViewUpdates;
|
|
12925
|
-
}
|
|
12926
|
-
getSource(name) {
|
|
12927
|
-
if (this.#sources.has(name)) {
|
|
12928
|
-
return this.#sources.get(name);
|
|
13128
|
+
if (this.#primaryKey.length > 1 || !req.constraint || !constraintMatchesPrimaryKey(req.constraint, this.#primaryKey)) {
|
|
13129
|
+
indexSort.push(...requestedSort);
|
|
12929
13130
|
}
|
|
12930
|
-
const
|
|
12931
|
-
const
|
|
12932
|
-
|
|
12933
|
-
|
|
12934
|
-
|
|
12935
|
-
|
|
12936
|
-
|
|
12937
|
-
|
|
12938
|
-
|
|
12939
|
-
|
|
12940
|
-
|
|
12941
|
-
|
|
12942
|
-
|
|
12943
|
-
|
|
12944
|
-
|
|
12945
|
-
|
|
12946
|
-
|
|
12947
|
-
|
|
12948
|
-
|
|
12949
|
-
|
|
12950
|
-
this.#batchViewUpdates(() => {
|
|
12951
|
-
result = applyViewUpdates();
|
|
12952
|
-
viewChangesPerformed = true;
|
|
12953
|
-
});
|
|
12954
|
-
assert(
|
|
12955
|
-
viewChangesPerformed,
|
|
12956
|
-
"batchViewUpdates must call applyViewUpdates synchronously."
|
|
12957
|
-
);
|
|
12958
|
-
return result;
|
|
12959
|
-
}
|
|
12960
|
-
processChanges(changes) {
|
|
12961
|
-
try {
|
|
12962
|
-
this.batchViewUpdates(() => {
|
|
12963
|
-
for (const diff2 of changes) {
|
|
12964
|
-
const { key } = diff2;
|
|
12965
|
-
assert(key.startsWith(ENTITIES_KEY_PREFIX));
|
|
12966
|
-
const slash = key.indexOf("/", ENTITIES_KEY_PREFIX.length);
|
|
12967
|
-
const name = key.slice(ENTITIES_KEY_PREFIX.length, slash);
|
|
12968
|
-
const source = this.getSource(name);
|
|
12969
|
-
if (!source) {
|
|
12970
|
-
continue;
|
|
12971
|
-
}
|
|
12972
|
-
switch (diff2.op) {
|
|
12973
|
-
case "del":
|
|
12974
|
-
assert(typeof diff2.oldValue === "object");
|
|
12975
|
-
source.push({
|
|
12976
|
-
type: "remove",
|
|
12977
|
-
row: diff2.oldValue
|
|
12978
|
-
});
|
|
12979
|
-
break;
|
|
12980
|
-
case "add":
|
|
12981
|
-
assert(typeof diff2.newValue === "object");
|
|
12982
|
-
source.push({
|
|
12983
|
-
type: "add",
|
|
12984
|
-
row: diff2.newValue
|
|
12985
|
-
});
|
|
12986
|
-
break;
|
|
12987
|
-
case "change":
|
|
12988
|
-
assert(typeof diff2.newValue === "object");
|
|
12989
|
-
assert(typeof diff2.oldValue === "object");
|
|
12990
|
-
source.push({
|
|
12991
|
-
type: "edit",
|
|
12992
|
-
row: diff2.newValue,
|
|
12993
|
-
oldRow: diff2.oldValue
|
|
12994
|
-
});
|
|
12995
|
-
break;
|
|
12996
|
-
default:
|
|
12997
|
-
unreachable(diff2);
|
|
13131
|
+
const index = this.#getOrCreateIndex(indexSort, from);
|
|
13132
|
+
const { data, comparator: compare } = index;
|
|
13133
|
+
const comparator2 = (r1, r2) => compare(r1, r2) * (req.reverse ? -1 : 1);
|
|
13134
|
+
if (this.#overlay) {
|
|
13135
|
+
if (callingConnectionNum <= this.#overlay.outputIndex) {
|
|
13136
|
+
overlay = this.#overlay;
|
|
13137
|
+
}
|
|
13138
|
+
}
|
|
13139
|
+
const startAt = req.start?.row;
|
|
13140
|
+
let scanStart;
|
|
13141
|
+
if (req.constraint) {
|
|
13142
|
+
scanStart = {};
|
|
13143
|
+
for (const [key, dir] of indexSort) {
|
|
13144
|
+
if (hasOwn(req.constraint, key)) {
|
|
13145
|
+
scanStart[key] = req.constraint[key];
|
|
13146
|
+
} else {
|
|
13147
|
+
if (req.reverse) {
|
|
13148
|
+
scanStart[key] = dir === "asc" ? maxValue : minValue;
|
|
13149
|
+
} else {
|
|
13150
|
+
scanStart[key] = dir === "asc" ? minValue : maxValue;
|
|
12998
13151
|
}
|
|
12999
13152
|
}
|
|
13000
|
-
}
|
|
13001
|
-
}
|
|
13002
|
-
|
|
13153
|
+
}
|
|
13154
|
+
} else {
|
|
13155
|
+
scanStart = startAt;
|
|
13156
|
+
}
|
|
13157
|
+
const withOverlay = generateWithOverlay(
|
|
13158
|
+
startAt,
|
|
13159
|
+
generateRows(data, scanStart, req.reverse),
|
|
13160
|
+
req.constraint,
|
|
13161
|
+
overlay,
|
|
13162
|
+
comparator2,
|
|
13163
|
+
conn.filters?.predicate
|
|
13164
|
+
);
|
|
13165
|
+
const withConstraint = generateWithConstraint(
|
|
13166
|
+
generateWithStart(withOverlay, req.start, comparator2),
|
|
13167
|
+
req.constraint
|
|
13168
|
+
);
|
|
13169
|
+
yield* conn.filters ? generateWithFilter(withConstraint, conn.filters.predicate) : withConstraint;
|
|
13170
|
+
}
|
|
13171
|
+
#cleanup(req, connection) {
|
|
13172
|
+
return this.#fetch(req, connection);
|
|
13173
|
+
}
|
|
13174
|
+
push(change) {
|
|
13175
|
+
for (const _ of this.genPush(change)) {
|
|
13003
13176
|
}
|
|
13004
13177
|
}
|
|
13005
|
-
|
|
13006
|
-
|
|
13007
|
-
|
|
13178
|
+
*genPush(change) {
|
|
13179
|
+
const primaryIndex = this.#getPrimaryIndex();
|
|
13180
|
+
const { data } = primaryIndex;
|
|
13181
|
+
switch (change.type) {
|
|
13182
|
+
case "add":
|
|
13183
|
+
assert(
|
|
13184
|
+
!data.has(change.row),
|
|
13185
|
+
() => `Row already exists ${JSON.stringify(change)}`
|
|
13186
|
+
);
|
|
13187
|
+
break;
|
|
13188
|
+
case "remove":
|
|
13189
|
+
assert(
|
|
13190
|
+
data.has(change.row),
|
|
13191
|
+
() => `Row not found ${JSON.stringify(change)}`
|
|
13192
|
+
);
|
|
13193
|
+
break;
|
|
13194
|
+
case "edit":
|
|
13195
|
+
assert(
|
|
13196
|
+
data.has(change.oldRow),
|
|
13197
|
+
() => `Row not found ${JSON.stringify(change)}`
|
|
13198
|
+
);
|
|
13199
|
+
break;
|
|
13200
|
+
default:
|
|
13201
|
+
unreachable(change);
|
|
13202
|
+
}
|
|
13203
|
+
const outputChange = change.type === "edit" ? {
|
|
13204
|
+
type: change.type,
|
|
13205
|
+
oldNode: {
|
|
13206
|
+
row: change.oldRow,
|
|
13207
|
+
relationships: {}
|
|
13208
|
+
},
|
|
13209
|
+
node: {
|
|
13210
|
+
row: change.row,
|
|
13211
|
+
relationships: {}
|
|
13212
|
+
}
|
|
13213
|
+
} : {
|
|
13214
|
+
type: change.type,
|
|
13215
|
+
node: {
|
|
13216
|
+
row: change.row,
|
|
13217
|
+
relationships: {}
|
|
13218
|
+
}
|
|
13219
|
+
};
|
|
13220
|
+
for (const [
|
|
13221
|
+
outputIndex,
|
|
13222
|
+
{ output, filters }
|
|
13223
|
+
] of this.#connections.entries()) {
|
|
13224
|
+
if (output) {
|
|
13225
|
+
this.#overlay = { outputIndex, change };
|
|
13226
|
+
filterPush(outputChange, output, filters?.predicate);
|
|
13227
|
+
yield;
|
|
13228
|
+
}
|
|
13229
|
+
}
|
|
13230
|
+
this.#overlay = void 0;
|
|
13231
|
+
for (const { data: data2 } of this.#indexes.values()) {
|
|
13232
|
+
switch (change.type) {
|
|
13233
|
+
case "add": {
|
|
13234
|
+
const added = data2.add(change.row);
|
|
13235
|
+
assert(added);
|
|
13236
|
+
break;
|
|
13237
|
+
}
|
|
13238
|
+
case "remove": {
|
|
13239
|
+
const removed = data2.delete(change.row);
|
|
13240
|
+
assert(removed);
|
|
13241
|
+
break;
|
|
13242
|
+
}
|
|
13243
|
+
case "edit": {
|
|
13244
|
+
const removed = data2.delete(change.oldRow);
|
|
13245
|
+
assert(removed);
|
|
13246
|
+
data2.add(change.row);
|
|
13247
|
+
break;
|
|
13248
|
+
}
|
|
13249
|
+
default:
|
|
13250
|
+
unreachable(change);
|
|
13251
|
+
}
|
|
13008
13252
|
}
|
|
13009
13253
|
}
|
|
13010
13254
|
};
|
|
13011
|
-
|
|
13012
|
-
|
|
13013
|
-
|
|
13014
|
-
|
|
13015
|
-
let inBatch = false;
|
|
13016
|
-
const mutateBatch = async (body) => {
|
|
13017
|
-
if (inBatch) {
|
|
13018
|
-
throw new Error("Cannot call mutate inside a batch");
|
|
13255
|
+
function* generateWithConstraint(it, constraint) {
|
|
13256
|
+
for (const node of it) {
|
|
13257
|
+
if (constraint && !constraintMatchesRow(constraint, node.row)) {
|
|
13258
|
+
break;
|
|
13019
13259
|
}
|
|
13020
|
-
|
|
13021
|
-
|
|
13022
|
-
|
|
13023
|
-
|
|
13024
|
-
|
|
13025
|
-
|
|
13260
|
+
yield node;
|
|
13261
|
+
}
|
|
13262
|
+
}
|
|
13263
|
+
function* generateWithFilter(it, filter) {
|
|
13264
|
+
for (const node of it) {
|
|
13265
|
+
if (filter(node.row)) {
|
|
13266
|
+
yield node;
|
|
13267
|
+
}
|
|
13268
|
+
}
|
|
13269
|
+
}
|
|
13270
|
+
function* generateWithStart(nodes, start, compare) {
|
|
13271
|
+
if (!start) {
|
|
13272
|
+
yield* nodes;
|
|
13273
|
+
return;
|
|
13274
|
+
}
|
|
13275
|
+
let started = false;
|
|
13276
|
+
for (const node of nodes) {
|
|
13277
|
+
if (!started) {
|
|
13278
|
+
if (start.basis === "at") {
|
|
13279
|
+
if (compare(node.row, start.row) >= 0) {
|
|
13280
|
+
started = true;
|
|
13281
|
+
}
|
|
13282
|
+
} else if (start.basis === "after") {
|
|
13283
|
+
if (compare(node.row, start.row) > 0) {
|
|
13284
|
+
started = true;
|
|
13285
|
+
}
|
|
13026
13286
|
}
|
|
13027
|
-
const rv = await body(m);
|
|
13028
|
-
await zeroCRUD({ ops });
|
|
13029
|
-
return rv;
|
|
13030
|
-
} finally {
|
|
13031
|
-
inBatch = false;
|
|
13032
13287
|
}
|
|
13033
|
-
|
|
13034
|
-
|
|
13035
|
-
if (inBatch) {
|
|
13036
|
-
throw new Error(`Cannot call mutate.${tableName}.${op} inside a batch`);
|
|
13288
|
+
if (started) {
|
|
13289
|
+
yield node;
|
|
13037
13290
|
}
|
|
13038
|
-
};
|
|
13039
|
-
const mutate = {};
|
|
13040
|
-
for (const [name, tableSchema] of Object.entries(schema.tables)) {
|
|
13041
|
-
mutate[name] = makeEntityCRUDMutate(
|
|
13042
|
-
name,
|
|
13043
|
-
tableSchema.primaryKey,
|
|
13044
|
-
zeroCRUD,
|
|
13045
|
-
assertNotInBatch
|
|
13046
|
-
);
|
|
13047
13291
|
}
|
|
13048
|
-
return {
|
|
13049
|
-
mutate,
|
|
13050
|
-
mutateBatch
|
|
13051
|
-
};
|
|
13052
13292
|
}
|
|
13053
|
-
function
|
|
13054
|
-
|
|
13055
|
-
|
|
13056
|
-
|
|
13057
|
-
|
|
13058
|
-
|
|
13059
|
-
|
|
13060
|
-
|
|
13061
|
-
|
|
13062
|
-
};
|
|
13063
|
-
return zeroCRUD({ ops: [op] });
|
|
13064
|
-
},
|
|
13065
|
-
upsert: (value) => {
|
|
13066
|
-
assertNotInBatch(tableName, "upsert");
|
|
13067
|
-
const op = {
|
|
13068
|
-
op: "upsert",
|
|
13069
|
-
tableName,
|
|
13070
|
-
primaryKey,
|
|
13071
|
-
value
|
|
13072
|
-
};
|
|
13073
|
-
return zeroCRUD({ ops: [op] });
|
|
13074
|
-
},
|
|
13075
|
-
update: (value) => {
|
|
13076
|
-
assertNotInBatch(tableName, "update");
|
|
13077
|
-
const op = {
|
|
13078
|
-
op: "update",
|
|
13079
|
-
tableName,
|
|
13080
|
-
primaryKey,
|
|
13081
|
-
value
|
|
13082
|
-
};
|
|
13083
|
-
return zeroCRUD({ ops: [op] });
|
|
13084
|
-
},
|
|
13085
|
-
delete: (id) => {
|
|
13086
|
-
assertNotInBatch(tableName, "delete");
|
|
13087
|
-
const op = {
|
|
13088
|
-
op: "delete",
|
|
13089
|
-
tableName,
|
|
13090
|
-
primaryKey,
|
|
13091
|
-
value: id
|
|
13092
|
-
};
|
|
13093
|
-
return zeroCRUD({ ops: [op] });
|
|
13094
|
-
}
|
|
13095
|
-
};
|
|
13293
|
+
function* generateWithOverlay(startAt, rows, constraint, overlay, compare, filterPredicate) {
|
|
13294
|
+
const overlays = computeOverlays(
|
|
13295
|
+
startAt,
|
|
13296
|
+
constraint,
|
|
13297
|
+
overlay,
|
|
13298
|
+
compare,
|
|
13299
|
+
filterPredicate
|
|
13300
|
+
);
|
|
13301
|
+
yield* generateWithOverlayInner(rows, overlays, compare);
|
|
13096
13302
|
}
|
|
13097
|
-
function
|
|
13098
|
-
|
|
13099
|
-
|
|
13100
|
-
|
|
13101
|
-
|
|
13102
|
-
|
|
13103
|
-
|
|
13104
|
-
|
|
13105
|
-
|
|
13106
|
-
|
|
13107
|
-
ops.push(op);
|
|
13108
|
-
return promiseVoid;
|
|
13109
|
-
},
|
|
13110
|
-
upsert: (value) => {
|
|
13111
|
-
const op = {
|
|
13112
|
-
op: "upsert",
|
|
13113
|
-
tableName,
|
|
13114
|
-
primaryKey,
|
|
13115
|
-
value
|
|
13303
|
+
function computeOverlays(startAt, constraint, overlay, compare, filterPredicate) {
|
|
13304
|
+
let overlays = {
|
|
13305
|
+
add: void 0,
|
|
13306
|
+
remove: void 0
|
|
13307
|
+
};
|
|
13308
|
+
switch (overlay?.change.type) {
|
|
13309
|
+
case "add":
|
|
13310
|
+
overlays = {
|
|
13311
|
+
add: overlay.change.row,
|
|
13312
|
+
remove: void 0
|
|
13116
13313
|
};
|
|
13117
|
-
|
|
13118
|
-
|
|
13119
|
-
|
|
13120
|
-
|
|
13121
|
-
|
|
13122
|
-
op: "update",
|
|
13123
|
-
tableName,
|
|
13124
|
-
primaryKey,
|
|
13125
|
-
value
|
|
13314
|
+
break;
|
|
13315
|
+
case "remove":
|
|
13316
|
+
overlays = {
|
|
13317
|
+
add: void 0,
|
|
13318
|
+
remove: overlay.change.row
|
|
13126
13319
|
};
|
|
13127
|
-
|
|
13128
|
-
|
|
13129
|
-
|
|
13130
|
-
|
|
13131
|
-
|
|
13132
|
-
op: "delete",
|
|
13133
|
-
tableName,
|
|
13134
|
-
primaryKey,
|
|
13135
|
-
value: id
|
|
13320
|
+
break;
|
|
13321
|
+
case "edit":
|
|
13322
|
+
overlays = {
|
|
13323
|
+
add: overlay.change.row,
|
|
13324
|
+
remove: overlay.change.oldRow
|
|
13136
13325
|
};
|
|
13137
|
-
|
|
13138
|
-
|
|
13139
|
-
|
|
13326
|
+
break;
|
|
13327
|
+
}
|
|
13328
|
+
if (startAt) {
|
|
13329
|
+
overlays = overlaysForStartAt(overlays, startAt, compare);
|
|
13330
|
+
}
|
|
13331
|
+
if (constraint) {
|
|
13332
|
+
overlays = overlaysForConstraint(overlays, constraint);
|
|
13333
|
+
}
|
|
13334
|
+
if (filterPredicate) {
|
|
13335
|
+
overlays = overlaysForFilterPredicate(overlays, filterPredicate);
|
|
13336
|
+
}
|
|
13337
|
+
return overlays;
|
|
13338
|
+
}
|
|
13339
|
+
function overlaysForStartAt({ add, remove }, startAt, compare) {
|
|
13340
|
+
const undefinedIfBeforeStartAt = (row) => row === void 0 || compare(row, startAt) < 0 ? void 0 : row;
|
|
13341
|
+
return {
|
|
13342
|
+
add: undefinedIfBeforeStartAt(add),
|
|
13343
|
+
remove: undefinedIfBeforeStartAt(remove)
|
|
13140
13344
|
};
|
|
13141
13345
|
}
|
|
13142
|
-
function
|
|
13143
|
-
|
|
13144
|
-
|
|
13145
|
-
|
|
13146
|
-
|
|
13147
|
-
await insertImpl(tx, op, schema);
|
|
13148
|
-
break;
|
|
13149
|
-
case "upsert":
|
|
13150
|
-
await upsertImpl(tx, op, schema);
|
|
13151
|
-
break;
|
|
13152
|
-
case "update":
|
|
13153
|
-
await updateImpl(tx, op, schema);
|
|
13154
|
-
break;
|
|
13155
|
-
case "delete":
|
|
13156
|
-
await deleteImpl(tx, op, schema);
|
|
13157
|
-
break;
|
|
13158
|
-
}
|
|
13159
|
-
}
|
|
13346
|
+
function overlaysForConstraint({ add, remove }, constraint) {
|
|
13347
|
+
const undefinedIfDoesntMatchConstraint = (row) => row === void 0 || !constraintMatchesRow(constraint, row) ? void 0 : row;
|
|
13348
|
+
return {
|
|
13349
|
+
add: undefinedIfDoesntMatchConstraint(add),
|
|
13350
|
+
remove: undefinedIfDoesntMatchConstraint(remove)
|
|
13160
13351
|
};
|
|
13161
13352
|
}
|
|
13162
|
-
function
|
|
13163
|
-
|
|
13164
|
-
|
|
13165
|
-
|
|
13166
|
-
|
|
13353
|
+
function overlaysForFilterPredicate({ add, remove }, filterPredicate) {
|
|
13354
|
+
const undefinedIfDoesntMatchFilter = (row) => row === void 0 || !filterPredicate(row) ? void 0 : row;
|
|
13355
|
+
return {
|
|
13356
|
+
add: undefinedIfDoesntMatchFilter(add),
|
|
13357
|
+
remove: undefinedIfDoesntMatchFilter(remove)
|
|
13358
|
+
};
|
|
13359
|
+
}
|
|
13360
|
+
function* generateWithOverlayInner(rowIterator, overlays, compare) {
|
|
13361
|
+
let addOverlayYielded = false;
|
|
13362
|
+
let removeOverlaySkipped = false;
|
|
13363
|
+
for (const row of rowIterator) {
|
|
13364
|
+
if (!addOverlayYielded && overlays.add) {
|
|
13365
|
+
const cmp2 = compare(overlays.add, row);
|
|
13366
|
+
if (cmp2 < 0) {
|
|
13367
|
+
addOverlayYielded = true;
|
|
13368
|
+
yield { row: overlays.add, relationships: {} };
|
|
13369
|
+
}
|
|
13370
|
+
}
|
|
13371
|
+
if (!removeOverlaySkipped && overlays.remove) {
|
|
13372
|
+
const cmp2 = compare(overlays.remove, row);
|
|
13373
|
+
if (cmp2 === 0) {
|
|
13374
|
+
removeOverlaySkipped = true;
|
|
13375
|
+
continue;
|
|
13376
|
+
}
|
|
13167
13377
|
}
|
|
13378
|
+
yield { row, relationships: {} };
|
|
13168
13379
|
}
|
|
13169
|
-
|
|
13170
|
-
}
|
|
13171
|
-
async function insertImpl(tx, arg, schema) {
|
|
13172
|
-
const key = toPrimaryKeyString(
|
|
13173
|
-
arg.tableName,
|
|
13174
|
-
schema.tables[arg.tableName].primaryKey,
|
|
13175
|
-
arg.value
|
|
13176
|
-
);
|
|
13177
|
-
if (!await tx.has(key)) {
|
|
13178
|
-
const val = defaultOptionalFieldsToNull(
|
|
13179
|
-
schema.tables[arg.tableName],
|
|
13180
|
-
arg.value
|
|
13181
|
-
);
|
|
13182
|
-
await tx.set(key, val);
|
|
13380
|
+
if (!addOverlayYielded && overlays.add) {
|
|
13381
|
+
yield { row: overlays.add, relationships: {} };
|
|
13183
13382
|
}
|
|
13184
13383
|
}
|
|
13185
|
-
|
|
13186
|
-
|
|
13187
|
-
|
|
13188
|
-
|
|
13189
|
-
|
|
13190
|
-
|
|
13191
|
-
|
|
13192
|
-
|
|
13193
|
-
|
|
13194
|
-
|
|
13195
|
-
|
|
13384
|
+
var minValue = Symbol("min-value");
|
|
13385
|
+
var maxValue = Symbol("max-value");
|
|
13386
|
+
function makeBoundComparator(sort) {
|
|
13387
|
+
return (a, b) => {
|
|
13388
|
+
for (const entry of sort) {
|
|
13389
|
+
const key = entry[0];
|
|
13390
|
+
const cmp2 = compareBounds(a[key], b[key]);
|
|
13391
|
+
if (cmp2 !== 0) {
|
|
13392
|
+
return entry[1] === "asc" ? cmp2 : -cmp2;
|
|
13393
|
+
}
|
|
13394
|
+
}
|
|
13395
|
+
return 0;
|
|
13396
|
+
};
|
|
13196
13397
|
}
|
|
13197
|
-
|
|
13198
|
-
|
|
13199
|
-
|
|
13200
|
-
schema.tables[arg.tableName].primaryKey,
|
|
13201
|
-
arg.value
|
|
13202
|
-
);
|
|
13203
|
-
const prev = await tx.get(key);
|
|
13204
|
-
if (prev === void 0) {
|
|
13205
|
-
return;
|
|
13398
|
+
function compareBounds(a, b) {
|
|
13399
|
+
if (a === b) {
|
|
13400
|
+
return 0;
|
|
13206
13401
|
}
|
|
13207
|
-
|
|
13208
|
-
|
|
13209
|
-
for (const k in update) {
|
|
13210
|
-
if (update[k] !== void 0) {
|
|
13211
|
-
next[k] = update[k];
|
|
13212
|
-
}
|
|
13402
|
+
if (a === minValue) {
|
|
13403
|
+
return -1;
|
|
13213
13404
|
}
|
|
13214
|
-
|
|
13405
|
+
if (b === minValue) {
|
|
13406
|
+
return 1;
|
|
13407
|
+
}
|
|
13408
|
+
if (a === maxValue) {
|
|
13409
|
+
return 1;
|
|
13410
|
+
}
|
|
13411
|
+
if (b === maxValue) {
|
|
13412
|
+
return -1;
|
|
13413
|
+
}
|
|
13414
|
+
return compareValues(a, b);
|
|
13215
13415
|
}
|
|
13216
|
-
|
|
13217
|
-
|
|
13218
|
-
|
|
13219
|
-
schema.tables[arg.tableName].primaryKey,
|
|
13220
|
-
arg.value
|
|
13416
|
+
function* generateRows(data, scanStart, reverse) {
|
|
13417
|
+
yield* data[reverse ? "valuesFromReversed" : "valuesFrom"](
|
|
13418
|
+
scanStart
|
|
13221
13419
|
);
|
|
13222
|
-
await tx.del(key);
|
|
13223
13420
|
}
|
|
13224
13421
|
|
|
13225
|
-
// ../zero-client/src/client/
|
|
13226
|
-
var
|
|
13227
|
-
|
|
13228
|
-
|
|
13229
|
-
|
|
13230
|
-
|
|
13231
|
-
this
|
|
13232
|
-
this
|
|
13422
|
+
// ../zero-client/src/client/ivm-source-repo.ts
|
|
13423
|
+
var IVMSourceRepo = class {
|
|
13424
|
+
#main;
|
|
13425
|
+
#tables;
|
|
13426
|
+
sync;
|
|
13427
|
+
constructor(tables) {
|
|
13428
|
+
this.#main = new IVMSourceBranch(tables);
|
|
13429
|
+
this.#tables = tables;
|
|
13430
|
+
}
|
|
13431
|
+
get main() {
|
|
13432
|
+
return this.#main;
|
|
13433
|
+
}
|
|
13434
|
+
/**
|
|
13435
|
+
* Creates a new empty branch.
|
|
13436
|
+
*/
|
|
13437
|
+
newBranch() {
|
|
13438
|
+
return new IVMSourceBranch(this.#tables);
|
|
13233
13439
|
}
|
|
13234
|
-
clientID;
|
|
13235
|
-
mutationID;
|
|
13236
|
-
reason;
|
|
13237
|
-
mutate;
|
|
13238
13440
|
};
|
|
13239
|
-
|
|
13240
|
-
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
function makeSchemaCRUD(schema, tx) {
|
|
13246
|
-
const mutate = {};
|
|
13247
|
-
for (const [name] of Object.entries(schema.tables)) {
|
|
13248
|
-
mutate[name] = makeTableCRUD(schema, name, tx);
|
|
13441
|
+
var IVMSourceBranch = class _IVMSourceBranch {
|
|
13442
|
+
#sources;
|
|
13443
|
+
#tables;
|
|
13444
|
+
constructor(tables, sources = /* @__PURE__ */ new Map()) {
|
|
13445
|
+
this.#tables = tables;
|
|
13446
|
+
this.#sources = sources;
|
|
13249
13447
|
}
|
|
13250
|
-
|
|
13251
|
-
|
|
13252
|
-
|
|
13253
|
-
|
|
13254
|
-
|
|
13255
|
-
|
|
13256
|
-
|
|
13257
|
-
|
|
13258
|
-
update: (value) => updateImpl(tx, { op: "update", tableName, primaryKey, value }, schema),
|
|
13259
|
-
delete: (id) => deleteImpl(tx, { op: "delete", tableName, primaryKey, value: id }, schema)
|
|
13260
|
-
};
|
|
13261
|
-
}
|
|
13262
|
-
|
|
13263
|
-
// ../zero-client/src/client/enable-analytics.ts
|
|
13264
|
-
var IPV4_ADDRESS_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
|
13265
|
-
var IPV6_ADDRESS_HOSTNAME_REGEX = /^\[[a-fA-F0-9:]*:[a-fA-F0-9:]*\]$/;
|
|
13266
|
-
var IP_ADDRESS_HOSTNAME_REGEX = new RegExp(
|
|
13267
|
-
`(${IPV4_ADDRESS_REGEX.source}|${IPV6_ADDRESS_HOSTNAME_REGEX.source})`
|
|
13268
|
-
);
|
|
13269
|
-
function shouldEnableAnalytics(server, enableAnalytics = true) {
|
|
13270
|
-
if (!enableAnalytics) {
|
|
13271
|
-
return false;
|
|
13448
|
+
getSource(name) {
|
|
13449
|
+
if (this.#sources.has(name)) {
|
|
13450
|
+
return this.#sources.get(name);
|
|
13451
|
+
}
|
|
13452
|
+
const schema = this.#tables[name];
|
|
13453
|
+
const source = schema ? new MemorySource(name, schema.columns, schema.primaryKey) : void 0;
|
|
13454
|
+
this.#sources.set(name, source);
|
|
13455
|
+
return source;
|
|
13272
13456
|
}
|
|
13273
|
-
|
|
13274
|
-
|
|
13275
|
-
|
|
13276
|
-
|
|
13277
|
-
|
|
13278
|
-
|
|
13279
|
-
|
|
13280
|
-
|
|
13281
|
-
|
|
13282
|
-
|
|
13283
|
-
|
|
13284
|
-
|
|
13457
|
+
/**
|
|
13458
|
+
* Creates a new IVMSourceBranch that is a copy of the current one.
|
|
13459
|
+
*
|
|
13460
|
+
* This is used when:
|
|
13461
|
+
* 1. We need to rebase a change. We fork the `sync` branch and run the mutations against the fork.
|
|
13462
|
+
* 2. We need to create `main` at startup.
|
|
13463
|
+
* 3. We need to create a new `sync` head because we got a new server snapshot.
|
|
13464
|
+
* The old `sync` head is forked and the new server snapshot is applied to the fork.
|
|
13465
|
+
*/
|
|
13466
|
+
fork() {
|
|
13467
|
+
return new _IVMSourceBranch(
|
|
13468
|
+
this.#tables,
|
|
13469
|
+
new Map(
|
|
13470
|
+
wrapIterable(this.#sources.entries()).map(([name, source]) => [
|
|
13471
|
+
name,
|
|
13472
|
+
source?.fork()
|
|
13473
|
+
])
|
|
13474
|
+
)
|
|
13475
|
+
);
|
|
13476
|
+
}
|
|
13477
|
+
};
|
|
13285
13478
|
|
|
13286
13479
|
// ../zero-client/src/client/log-options.ts
|
|
13287
13480
|
import {
|
|
@@ -13508,7 +13701,7 @@ function makeMessage(message, context, logLevel) {
|
|
|
13508
13701
|
}
|
|
13509
13702
|
|
|
13510
13703
|
// ../zero-client/src/client/version.ts
|
|
13511
|
-
var version2 = "0.13.
|
|
13704
|
+
var version2 = "0.13.2025020402";
|
|
13512
13705
|
|
|
13513
13706
|
// ../zero-client/src/client/log-options.ts
|
|
13514
13707
|
var LevelFilterLogSink = class {
|
|
@@ -13809,7 +14002,7 @@ var Success = 1;
|
|
|
13809
14002
|
// ../zero-client/src/client/query-manager.ts
|
|
13810
14003
|
var QueryManager = class {
|
|
13811
14004
|
#clientID;
|
|
13812
|
-
#
|
|
14005
|
+
#clientToServer;
|
|
13813
14006
|
#send;
|
|
13814
14007
|
#queries = /* @__PURE__ */ new Map();
|
|
13815
14008
|
#recentQueriesMaxSize;
|
|
@@ -13817,7 +14010,7 @@ var QueryManager = class {
|
|
|
13817
14010
|
#gotQueries = /* @__PURE__ */ new Set();
|
|
13818
14011
|
constructor(clientID, tables, send2, experimentalWatch, recentQueriesMaxSize) {
|
|
13819
14012
|
this.#clientID = clientID;
|
|
13820
|
-
this.#
|
|
14013
|
+
this.#clientToServer = clientToServer(tables);
|
|
13821
14014
|
this.#recentQueriesMaxSize = recentQueriesMaxSize;
|
|
13822
14015
|
this.#send = send2;
|
|
13823
14016
|
experimentalWatch(
|
|
@@ -13901,7 +14094,7 @@ var QueryManager = class {
|
|
|
13901
14094
|
let entry = this.#queries.get(astHash);
|
|
13902
14095
|
this.#recentQueries.delete(astHash);
|
|
13903
14096
|
if (!entry) {
|
|
13904
|
-
const serverAST =
|
|
14097
|
+
const serverAST = mapAST(normalized, this.#clientToServer);
|
|
13905
14098
|
entry = {
|
|
13906
14099
|
normalized: serverAST,
|
|
13907
14100
|
count: 1,
|
|
@@ -14138,26 +14331,6 @@ function getServer(server) {
|
|
|
14138
14331
|
|
|
14139
14332
|
// ../zero-client/src/client/zero-poke-handler.ts
|
|
14140
14333
|
import { Lock as Lock4 } from "@rocicorp/lock";
|
|
14141
|
-
function makeClientNames(schema) {
|
|
14142
|
-
return new Map(
|
|
14143
|
-
Object.entries(schema.tables).map(
|
|
14144
|
-
([tableName, { serverName: serverTableName, columns }]) => {
|
|
14145
|
-
let allSame = true;
|
|
14146
|
-
const names = {};
|
|
14147
|
-
for (const [name, { serverName }] of Object.entries(columns)) {
|
|
14148
|
-
if (serverName && serverName !== name) {
|
|
14149
|
-
allSame = false;
|
|
14150
|
-
}
|
|
14151
|
-
names[serverName ?? name] = name;
|
|
14152
|
-
}
|
|
14153
|
-
return [
|
|
14154
|
-
serverTableName ?? tableName,
|
|
14155
|
-
{ tableName, columns: allSame ? null : names }
|
|
14156
|
-
];
|
|
14157
|
-
}
|
|
14158
|
-
)
|
|
14159
|
-
);
|
|
14160
|
-
}
|
|
14161
14334
|
var PokeHandler = class {
|
|
14162
14335
|
#replicachePoke;
|
|
14163
14336
|
#onPokeError;
|
|
@@ -14171,14 +14344,14 @@ var PokeHandler = class {
|
|
|
14171
14344
|
// order poke errors.
|
|
14172
14345
|
#pokeLock = new Lock4();
|
|
14173
14346
|
#schema;
|
|
14174
|
-
#
|
|
14347
|
+
#serverToClient;
|
|
14175
14348
|
#raf = getBrowserGlobalMethod("requestAnimationFrame") ?? rafFallback;
|
|
14176
14349
|
constructor(replicachePoke, onPokeError, clientID, schema, lc) {
|
|
14177
14350
|
this.#replicachePoke = replicachePoke;
|
|
14178
14351
|
this.#onPokeError = onPokeError;
|
|
14179
14352
|
this.#clientID = clientID;
|
|
14180
14353
|
this.#schema = schema;
|
|
14181
|
-
this.#
|
|
14354
|
+
this.#serverToClient = serverToClient(schema.tables);
|
|
14182
14355
|
this.#lc = lc.withContext("PokeHandler");
|
|
14183
14356
|
}
|
|
14184
14357
|
handlePokeStart(pokeStart) {
|
|
@@ -14259,7 +14432,7 @@ var PokeHandler = class {
|
|
|
14259
14432
|
const merged = mergePokes(
|
|
14260
14433
|
this.#pokeBuffer,
|
|
14261
14434
|
this.#schema,
|
|
14262
|
-
this.#
|
|
14435
|
+
this.#serverToClient
|
|
14263
14436
|
);
|
|
14264
14437
|
this.#pokeBuffer.length = 0;
|
|
14265
14438
|
if (merged === void 0) {
|
|
@@ -14289,7 +14462,7 @@ var PokeHandler = class {
|
|
|
14289
14462
|
this.#pokeBuffer.length = 0;
|
|
14290
14463
|
}
|
|
14291
14464
|
};
|
|
14292
|
-
function mergePokes(pokeBuffer, schema,
|
|
14465
|
+
function mergePokes(pokeBuffer, schema, serverToClient2) {
|
|
14293
14466
|
if (pokeBuffer.length === 0) {
|
|
14294
14467
|
return void 0;
|
|
14295
14468
|
}
|
|
@@ -14329,7 +14502,7 @@ function mergePokes(pokeBuffer, schema, clientNames) {
|
|
|
14329
14502
|
(op) => queryPatchOpToReplicachePatchOp(
|
|
14330
14503
|
op,
|
|
14331
14504
|
(hash2) => toDesiredQueriesKey(clientID, hash2),
|
|
14332
|
-
|
|
14505
|
+
serverToClient2
|
|
14333
14506
|
)
|
|
14334
14507
|
)
|
|
14335
14508
|
);
|
|
@@ -14338,14 +14511,18 @@ function mergePokes(pokeBuffer, schema, clientNames) {
|
|
|
14338
14511
|
if (pokePart.gotQueriesPatch) {
|
|
14339
14512
|
mergedPatch.push(
|
|
14340
14513
|
...pokePart.gotQueriesPatch.map(
|
|
14341
|
-
(op) => queryPatchOpToReplicachePatchOp(
|
|
14514
|
+
(op) => queryPatchOpToReplicachePatchOp(
|
|
14515
|
+
op,
|
|
14516
|
+
toGotQueriesKey,
|
|
14517
|
+
serverToClient2
|
|
14518
|
+
)
|
|
14342
14519
|
)
|
|
14343
14520
|
);
|
|
14344
14521
|
}
|
|
14345
14522
|
if (pokePart.rowsPatch) {
|
|
14346
14523
|
mergedPatch.push(
|
|
14347
14524
|
...pokePart.rowsPatch.map(
|
|
14348
|
-
(p) => rowsPatchOpToReplicachePatchOp(p, schema,
|
|
14525
|
+
(p) => rowsPatchOpToReplicachePatchOp(p, schema, serverToClient2)
|
|
14349
14526
|
)
|
|
14350
14527
|
);
|
|
14351
14528
|
}
|
|
@@ -14378,7 +14555,7 @@ function clientsPatchOpToReplicachePatchOp(op) {
|
|
|
14378
14555
|
};
|
|
14379
14556
|
}
|
|
14380
14557
|
}
|
|
14381
|
-
function queryPatchOpToReplicachePatchOp(op, toKey,
|
|
14558
|
+
function queryPatchOpToReplicachePatchOp(op, toKey, serverToClient2) {
|
|
14382
14559
|
switch (op.op) {
|
|
14383
14560
|
case "clear":
|
|
14384
14561
|
return op;
|
|
@@ -14392,19 +14569,15 @@ function queryPatchOpToReplicachePatchOp(op, toKey, schema) {
|
|
|
14392
14569
|
return {
|
|
14393
14570
|
op: "put",
|
|
14394
14571
|
key: toKey(op.hash),
|
|
14395
|
-
value:
|
|
14572
|
+
value: mapAST(op.ast, serverToClient2)
|
|
14396
14573
|
};
|
|
14397
14574
|
}
|
|
14398
14575
|
}
|
|
14399
|
-
function rowsPatchOpToReplicachePatchOp(op, schema,
|
|
14576
|
+
function rowsPatchOpToReplicachePatchOp(op, schema, serverToClient2) {
|
|
14400
14577
|
if (op.op === "clear") {
|
|
14401
14578
|
return op;
|
|
14402
14579
|
}
|
|
14403
|
-
const
|
|
14404
|
-
if (!names) {
|
|
14405
|
-
throw new Error(`unknown table name in ${JSON.stringify(op)}`);
|
|
14406
|
-
}
|
|
14407
|
-
const { tableName, columns } = names;
|
|
14580
|
+
const tableName = serverToClient2.tableName(op.tableName, op);
|
|
14408
14581
|
switch (op.op) {
|
|
14409
14582
|
case "del":
|
|
14410
14583
|
return {
|
|
@@ -14412,7 +14585,7 @@ function rowsPatchOpToReplicachePatchOp(op, schema, clientNames) {
|
|
|
14412
14585
|
key: toPrimaryKeyString(
|
|
14413
14586
|
tableName,
|
|
14414
14587
|
schema.tables[tableName].primaryKey,
|
|
14415
|
-
|
|
14588
|
+
serverToClient2.row(op.tableName, op.id)
|
|
14416
14589
|
)
|
|
14417
14590
|
};
|
|
14418
14591
|
case "put":
|
|
@@ -14421,9 +14594,9 @@ function rowsPatchOpToReplicachePatchOp(op, schema, clientNames) {
|
|
|
14421
14594
|
key: toPrimaryKeyString(
|
|
14422
14595
|
tableName,
|
|
14423
14596
|
schema.tables[tableName].primaryKey,
|
|
14424
|
-
|
|
14597
|
+
serverToClient2.row(op.tableName, op.value)
|
|
14425
14598
|
),
|
|
14426
|
-
value:
|
|
14599
|
+
value: serverToClient2.row(op.tableName, op.value)
|
|
14427
14600
|
};
|
|
14428
14601
|
case "update":
|
|
14429
14602
|
return {
|
|
@@ -14431,28 +14604,15 @@ function rowsPatchOpToReplicachePatchOp(op, schema, clientNames) {
|
|
|
14431
14604
|
key: toPrimaryKeyString(
|
|
14432
14605
|
tableName,
|
|
14433
14606
|
schema.tables[tableName].primaryKey,
|
|
14434
|
-
|
|
14607
|
+
serverToClient2.row(op.tableName, op.id)
|
|
14435
14608
|
),
|
|
14436
|
-
merge: op.merge ?
|
|
14437
|
-
constrain:
|
|
14609
|
+
merge: op.merge ? serverToClient2.row(op.tableName, op.merge) : void 0,
|
|
14610
|
+
constrain: serverToClient2.columns(op.tableName, op.constrain)
|
|
14438
14611
|
};
|
|
14439
14612
|
default:
|
|
14440
14613
|
throw new Error("to be implemented");
|
|
14441
14614
|
}
|
|
14442
14615
|
}
|
|
14443
|
-
function toClientRow(row, names) {
|
|
14444
|
-
if (names === null) {
|
|
14445
|
-
return row;
|
|
14446
|
-
}
|
|
14447
|
-
const clientRow = {};
|
|
14448
|
-
for (const col in row) {
|
|
14449
|
-
clientRow[names[col] ?? col] = row[col];
|
|
14450
|
-
}
|
|
14451
|
-
return clientRow;
|
|
14452
|
-
}
|
|
14453
|
-
function toClientColumns(columns, names) {
|
|
14454
|
-
return !names || !columns ? columns : columns.map((col) => names[col] ?? col);
|
|
14455
|
-
}
|
|
14456
14616
|
function rafFallback(callback) {
|
|
14457
14617
|
setTimeout(callback, 0);
|
|
14458
14618
|
}
|
|
@@ -14511,6 +14671,8 @@ var Zero = class {
|
|
|
14511
14671
|
#enableAnalytics;
|
|
14512
14672
|
#pokeHandler;
|
|
14513
14673
|
#queryManager;
|
|
14674
|
+
#ivmSources;
|
|
14675
|
+
#clientToServer;
|
|
14514
14676
|
/**
|
|
14515
14677
|
* The queries we sent when inside the sec-protocol header when establishing a connection.
|
|
14516
14678
|
* More queries could be registered while we're waiting for the 'connected' message
|
|
@@ -14625,13 +14787,14 @@ var Zero = class {
|
|
|
14625
14787
|
const replicacheMutators = {
|
|
14626
14788
|
[CRUD_MUTATION_NAME]: makeCRUDMutator(schema)
|
|
14627
14789
|
};
|
|
14790
|
+
this.#ivmSources = new IVMSourceRepo(schema.tables);
|
|
14628
14791
|
for (const [namespace, mutatorsForNamespace] of Object.entries(
|
|
14629
14792
|
options.mutators ?? {}
|
|
14630
14793
|
)) {
|
|
14631
14794
|
for (const [name, mutator] of Object.entries(
|
|
14632
14795
|
mutatorsForNamespace
|
|
14633
14796
|
)) {
|
|
14634
|
-
replicacheMutators[customMutatorKey(namespace, name)] = makeReplicacheMutator(mutator, schema);
|
|
14797
|
+
replicacheMutators[customMutatorKey(namespace, name)] = makeReplicacheMutator(mutator, schema, this.#ivmSources);
|
|
14635
14798
|
}
|
|
14636
14799
|
}
|
|
14637
14800
|
this.storageKey = storageKey ?? "";
|
|
@@ -14713,8 +14876,9 @@ var Zero = class {
|
|
|
14713
14876
|
rep.experimentalWatch.bind(rep),
|
|
14714
14877
|
maxRecentQueries
|
|
14715
14878
|
);
|
|
14879
|
+
this.#clientToServer = clientToServer(schema.tables);
|
|
14716
14880
|
this.#zeroContext = new ZeroContext(
|
|
14717
|
-
|
|
14881
|
+
this.#ivmSources.main,
|
|
14718
14882
|
(ast, gotCallback) => this.#queryManager.add(ast, gotCallback),
|
|
14719
14883
|
batchViewUpdates
|
|
14720
14884
|
);
|
|
@@ -15250,7 +15414,7 @@ var Zero = class {
|
|
|
15250
15414
|
id: m.id,
|
|
15251
15415
|
clientID: m.clientID,
|
|
15252
15416
|
name: m.name,
|
|
15253
|
-
args: [m.args]
|
|
15417
|
+
args: [mapCRUD(m.args, this.#clientToServer)]
|
|
15254
15418
|
} : {
|
|
15255
15419
|
type: Custom,
|
|
15256
15420
|
timestamp,
|
|
@@ -15649,4 +15813,4 @@ export {
|
|
|
15649
15813
|
escapeLike,
|
|
15650
15814
|
Zero
|
|
15651
15815
|
};
|
|
15652
|
-
//# sourceMappingURL=chunk-
|
|
15816
|
+
//# sourceMappingURL=chunk-ADFMUREC.js.map
|