@rocicorp/zero 0.14.2025021001 → 0.14.2025021101

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.
Files changed (80) hide show
  1. package/out/{chunk-MVLDKRBK.js → chunk-5GWP7BBD.js} +321 -267
  2. package/out/chunk-5GWP7BBD.js.map +7 -0
  3. package/out/replicache/src/deleted-clients.d.ts +12 -6
  4. package/out/replicache/src/deleted-clients.d.ts.map +1 -1
  5. package/out/replicache/src/persist/client-group-gc.d.ts +3 -2
  6. package/out/replicache/src/persist/client-group-gc.d.ts.map +1 -1
  7. package/out/replicache/src/persist/clients.d.ts +1 -1
  8. package/out/replicache/src/persist/clients.d.ts.map +1 -1
  9. package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
  10. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  11. package/out/shared/src/immutable.d.ts +1 -1
  12. package/out/shared/src/immutable.d.ts.map +1 -1
  13. package/out/solid.js +1 -1
  14. package/out/zero/src/deploy-permissions.d.ts +3 -0
  15. package/out/zero/src/deploy-permissions.d.ts.map +1 -0
  16. package/out/zero/src/deploy-permissions.js +3 -0
  17. package/out/zero/src/deploy-permissions.js.map +1 -0
  18. package/out/zero-cache/src/auth/load-schema.d.ts +1 -1
  19. package/out/zero-cache/src/auth/load-schema.d.ts.map +1 -1
  20. package/out/zero-cache/src/auth/load-schema.js.map +1 -1
  21. package/out/zero-cache/src/auth/read-authorizer.js +1 -1
  22. package/out/zero-cache/src/auth/read-authorizer.js.map +1 -1
  23. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  24. package/out/zero-cache/src/auth/write-authorizer.js +6 -2
  25. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  26. package/out/zero-cache/src/config/zero-config.d.ts +0 -205
  27. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  28. package/out/zero-cache/src/config/zero-config.js +0 -22
  29. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  30. package/out/zero-cache/src/scripts/deploy-permissions.d.ts +2 -0
  31. package/out/zero-cache/src/scripts/deploy-permissions.d.ts.map +1 -0
  32. package/out/zero-cache/src/scripts/deploy-permissions.js +122 -0
  33. package/out/zero-cache/src/scripts/deploy-permissions.js.map +1 -0
  34. package/out/zero-cache/src/services/change-source/custom/change-source.js +4 -0
  35. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  36. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  37. package/out/zero-cache/src/services/change-source/pg/schema/init.js +3 -1
  38. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  39. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +2 -1
  40. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  41. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +16 -0
  42. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  43. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  44. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  45. package/out/zero-cache/src/services/view-syncer/view-syncer.js +5 -5
  46. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  47. package/out/zero-cache/src/types/pg.d.ts.map +1 -1
  48. package/out/zero-cache/src/types/pg.js +6 -2
  49. package/out/zero-cache/src/types/pg.js.map +1 -1
  50. package/out/zero-cache/src/workers/connection.js +2 -2
  51. package/out/zero-cache/src/workers/connection.js.map +1 -1
  52. package/out/zero-client/src/client/crud.d.ts.map +1 -1
  53. package/out/zero-client/src/client/delete-clients-manager.d.ts +6 -5
  54. package/out/zero-client/src/client/delete-clients-manager.d.ts.map +1 -1
  55. package/out/zero-client/src/client/zero.d.ts +2 -1
  56. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  57. package/out/zero-protocol/src/connect.d.ts +8 -2
  58. package/out/zero-protocol/src/connect.d.ts.map +1 -1
  59. package/out/zero-protocol/src/connect.js +2 -1
  60. package/out/zero-protocol/src/connect.js.map +1 -1
  61. package/out/zero-protocol/src/delete-clients.d.ts +8 -7
  62. package/out/zero-protocol/src/delete-clients.d.ts.map +1 -1
  63. package/out/zero-protocol/src/delete-clients.js +4 -3
  64. package/out/zero-protocol/src/delete-clients.js.map +1 -1
  65. package/out/zero-protocol/src/down.d.ts +4 -3
  66. package/out/zero-protocol/src/down.d.ts.map +1 -1
  67. package/out/zero-protocol/src/protocol-version.d.ts +10 -2
  68. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  69. package/out/zero-protocol/src/protocol-version.js +12 -3
  70. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  71. package/out/zero-protocol/src/up.d.ts +8 -4
  72. package/out/zero-protocol/src/up.d.ts.map +1 -1
  73. package/out/zero-schema/src/compiled-permissions.d.ts +23 -19
  74. package/out/zero-schema/src/compiled-permissions.d.ts.map +1 -1
  75. package/out/zero-schema/src/compiled-permissions.js +7 -4
  76. package/out/zero-schema/src/compiled-permissions.js.map +1 -1
  77. package/out/zero-schema/src/permissions.d.ts.map +1 -1
  78. package/out/zero.js +1 -1
  79. package/package.json +4 -3
  80. package/out/chunk-MVLDKRBK.js.map +0 -7
@@ -1420,33 +1420,46 @@ var WriteImpl2 = class extends ReadImpl2 {
1420
1420
 
1421
1421
  // ../replicache/src/deleted-clients.ts
1422
1422
  var DELETED_CLIENTS_HEAD_NAME = "deleted-clients";
1423
- async function setDeletedClients(dagWrite, deletedClients) {
1424
- const normalized = normalize(deletedClients);
1425
- const chunkData = deepFreeze(normalized);
1423
+ var deletedClientsSchema = readonlyObject({
1424
+ clientIDs: readonlyArray(valita_exports.string()),
1425
+ clientGroupIDs: readonlyArray(valita_exports.string())
1426
+ });
1427
+ async function setDeletedClients(dagWrite, clientIDs, clientGroupIDs) {
1428
+ const data = {
1429
+ clientIDs: normalize(clientIDs),
1430
+ clientGroupIDs: normalize(clientGroupIDs)
1431
+ };
1432
+ const chunkData = deepFreeze(data);
1426
1433
  const chunk = dagWrite.createChunk(chunkData, []);
1427
1434
  await dagWrite.putChunk(chunk);
1428
1435
  await dagWrite.setHead(DELETED_CLIENTS_HEAD_NAME, chunk.hash);
1429
- return normalized;
1436
+ return data;
1430
1437
  }
1431
- var deletedClientsSchema = valita_exports.array(valita_exports.string());
1432
1438
  async function getDeletedClients(dagRead) {
1433
1439
  const hash2 = await dagRead.getHead(DELETED_CLIENTS_HEAD_NAME);
1434
1440
  if (hash2 === void 0) {
1435
- return [];
1441
+ return { clientIDs: [], clientGroupIDs: [] };
1436
1442
  }
1437
1443
  const chunk = await dagRead.mustGetChunk(hash2);
1438
1444
  return parse(chunk.data, deletedClientsSchema);
1439
1445
  }
1440
- async function addDeletedClients(dagWrite, clientIDs) {
1441
- const deletedClients = await getDeletedClients(dagWrite);
1442
- return setDeletedClients(dagWrite, [...deletedClients, ...clientIDs]);
1446
+ async function addDeletedClients(dagWrite, clientIDs, clientGroupIDs) {
1447
+ const { clientIDs: oldClientIDs, clientGroupIDs: oldClientGroupIDs } = await getDeletedClients(dagWrite);
1448
+ return setDeletedClients(
1449
+ dagWrite,
1450
+ [...oldClientIDs, ...clientIDs],
1451
+ [...oldClientGroupIDs, ...clientGroupIDs]
1452
+ );
1443
1453
  }
1444
- async function removeDeletedClients(dagWrite, clientIDs) {
1445
- const deletedClients = await getDeletedClients(dagWrite);
1446
- const newDeletedClients = deletedClients.filter(
1454
+ async function removeDeletedClients(dagWrite, clientIDs, clientGroupIDs) {
1455
+ const { clientIDs: oldClientIDs, clientGroupIDs: oldClientGroupIDs } = await getDeletedClients(dagWrite);
1456
+ const newDeletedClients = oldClientIDs.filter(
1447
1457
  (clientID) => !clientIDs.includes(clientID)
1448
1458
  );
1449
- return setDeletedClients(dagWrite, newDeletedClients);
1459
+ const newDeletedClientGroups = oldClientGroupIDs.filter(
1460
+ (clientGroupID) => !clientGroupIDs.includes(clientGroupID)
1461
+ );
1462
+ return setDeletedClients(dagWrite, newDeletedClients, newDeletedClientGroups);
1450
1463
  }
1451
1464
  function normalize(arr) {
1452
1465
  return [...new Set(arr)].sort();
@@ -3095,13 +3108,13 @@ var DataNodeImpl = class extends NodeImpl {
3095
3108
  }
3096
3109
  }
3097
3110
  };
3098
- function readonlySplice(array12, start, deleteCount, ...items) {
3099
- const arr = array12.slice(0, start);
3111
+ function readonlySplice(array9, start, deleteCount, ...items) {
3112
+ const arr = array9.slice(0, start);
3100
3113
  for (let i = 0; i < items.length; i++) {
3101
3114
  arr.push(items[i]);
3102
3115
  }
3103
- for (let i = start + deleteCount; i < array12.length; i++) {
3104
- arr.push(array12[i]);
3116
+ for (let i = start + deleteCount; i < array9.length; i++) {
3117
+ arr.push(array9[i]);
3105
3118
  }
3106
3119
  return arr;
3107
3120
  }
@@ -5772,7 +5785,7 @@ async function mustGetClient(id, dagRead) {
5772
5785
  return client;
5773
5786
  }
5774
5787
  function initClientV6(newClientID, lc, perdag, mutatorNames, indexes, formatVersion, enableClientGroupForking) {
5775
- return withWriteNoImplicitCommit(perdag, async (dagWrite) => {
5788
+ return withWrite(perdag, async (dagWrite) => {
5776
5789
  async function setClientsAndClientGroupAndCommit(basisHash, cookieJSON, valueHash2, indexRecords2) {
5777
5790
  const newSnapshotData = newSnapshotCommitDataDD31(
5778
5791
  basisHash,
@@ -5806,7 +5819,6 @@ function initClientV6(newClientID, lc, perdag, mutatorNames, indexes, formatVers
5806
5819
  setClients(newClients, dagWrite),
5807
5820
  setClientGroup(newClientGroupID, clientGroup, dagWrite)
5808
5821
  ]);
5809
- await dagWrite.commit();
5810
5822
  return [newClient, chunk.hash, newClients, true];
5811
5823
  }
5812
5824
  const clients = await getClients(dagWrite);
@@ -5821,7 +5833,6 @@ function initClientV6(newClientID, lc, perdag, mutatorNames, indexes, formatVers
5821
5833
  };
5822
5834
  const newClients = new Map(clients).set(newClientID, newClient);
5823
5835
  await setClients(newClients, dagWrite);
5824
- await dagWrite.commit();
5825
5836
  return [newClient, headHash, newClients, false];
5826
5837
  }
5827
5838
  if (!enableClientGroupForking || res.type === FIND_MATCHING_CLIENT_TYPE_NEW) {
@@ -6009,8 +6020,13 @@ function gcClients(clientID, dagStore, clientMaxInactiveTime, onClientsDeleted)
6009
6020
  return clients;
6010
6021
  }
6011
6022
  await setClients(newClients, dagWrite);
6012
- const normalized = await addDeletedClients(dagWrite, deletedClients);
6013
- onClientsDeleted(normalized);
6023
+ const { clientIDs, clientGroupIDs } = await addDeletedClients(
6024
+ dagWrite,
6025
+ deletedClients,
6026
+ // gcClients does not delete client groups
6027
+ []
6028
+ );
6029
+ onClientsDeleted(clientIDs, clientGroupIDs);
6014
6030
  return newClients;
6015
6031
  });
6016
6032
  }
@@ -6018,11 +6034,15 @@ function gcClients(clientID, dagStore, clientMaxInactiveTime, onClientsDeleted)
6018
6034
  // ../replicache/src/persist/client-group-gc.ts
6019
6035
  var GC_INTERVAL_MS = 5 * 60 * 1e3;
6020
6036
  var latestGCUpdate2;
6021
- function initClientGroupGC(dagStore, enableMutationRecovery, lc, signal) {
6037
+ function initClientGroupGC(dagStore, enableMutationRecovery, onClientsDeleted, lc, signal) {
6022
6038
  initBgIntervalProcess(
6023
6039
  "ClientGroupGC",
6024
6040
  () => {
6025
- latestGCUpdate2 = gcClientGroups(dagStore, enableMutationRecovery);
6041
+ latestGCUpdate2 = gcClientGroups(
6042
+ dagStore,
6043
+ enableMutationRecovery,
6044
+ onClientsDeleted
6045
+ );
6026
6046
  return latestGCUpdate2;
6027
6047
  },
6028
6048
  () => GC_INTERVAL_MS,
@@ -6030,7 +6050,7 @@ function initClientGroupGC(dagStore, enableMutationRecovery, lc, signal) {
6030
6050
  signal
6031
6051
  );
6032
6052
  }
6033
- function gcClientGroups(dagStore, enableMutationRecovery) {
6053
+ function gcClientGroups(dagStore, enableMutationRecovery, onClientsDeleted) {
6034
6054
  return withWrite(dagStore, async (tx) => {
6035
6055
  const clients = await getClients(tx);
6036
6056
  const clientGroupIDs = /* @__PURE__ */ new Set();
@@ -6038,12 +6058,16 @@ function gcClientGroups(dagStore, enableMutationRecovery) {
6038
6058
  clientGroupIDs.add(client.clientGroupID);
6039
6059
  }
6040
6060
  const clientGroups = /* @__PURE__ */ new Map();
6061
+ const removeClientGroups = /* @__PURE__ */ new Set();
6041
6062
  for (const [clientGroupID, clientGroup] of await getClientGroups(tx)) {
6042
6063
  if (clientGroupIDs.has(clientGroupID) || enableMutationRecovery && clientGroupHasPendingMutations(clientGroup)) {
6043
6064
  clientGroups.set(clientGroupID, clientGroup);
6065
+ } else {
6066
+ removeClientGroups.add(clientGroupID);
6044
6067
  }
6045
6068
  }
6046
6069
  await setClientGroups(clientGroups, tx);
6070
+ onClientsDeleted([], [...removeClientGroups].sort());
6047
6071
  return clientGroups;
6048
6072
  });
6049
6073
  }
@@ -7056,14 +7080,14 @@ function diffBinarySearch(diff2, prefix, compareKey) {
7056
7080
  }
7057
7081
 
7058
7082
  // ../shared/src/random-values.ts
7059
- function getNonCryptoRandomValues(array12) {
7060
- if (array12 === null) {
7083
+ function getNonCryptoRandomValues(array9) {
7084
+ if (array9 === null) {
7061
7085
  throw new TypeError("array cannot be null");
7062
7086
  }
7063
- for (let i = 0; i < array12.length; i++) {
7064
- array12[i] = Math.floor(Math.random() * 256);
7087
+ for (let i = 0; i < array9.length; i++) {
7088
+ array9[i] = Math.floor(Math.random() * 256);
7065
7089
  }
7066
- return array12;
7090
+ return array9;
7067
7091
  }
7068
7092
 
7069
7093
  // ../replicache/src/sync/request-id.ts
@@ -7424,7 +7448,13 @@ var ReplicacheImpl = class {
7424
7448
  this.#lc,
7425
7449
  signal
7426
7450
  );
7427
- initClientGroupGC(this.perdag, enableMutationRecovery, this.#lc, signal);
7451
+ initClientGroupGC(
7452
+ this.perdag,
7453
+ enableMutationRecovery,
7454
+ onClientsDeleted,
7455
+ this.#lc,
7456
+ signal
7457
+ );
7428
7458
  initNewClientChannel(
7429
7459
  this.name,
7430
7460
  this.idbName,
@@ -8288,10 +8318,15 @@ async function collectIDBDatabases(idbDatabasesStore, now, maxAge, kvDropStore,
8288
8318
  const dbNamesToRemove = [];
8289
8319
  const dbNamesToKeep = [];
8290
8320
  const clientIDsToRemove = [];
8291
- for (const [dbName, [canCollect, clientIDs]] of collectResults) {
8321
+ const clientGroupIDsToRemove = [];
8322
+ for (const [
8323
+ dbName,
8324
+ [canCollect, clientIDs, clientGroupIDs]
8325
+ ] of collectResults) {
8292
8326
  if (canCollect) {
8293
8327
  dbNamesToRemove.push(dbName);
8294
8328
  clientIDsToRemove.push(...clientIDs);
8329
+ clientGroupIDsToRemove.push(...clientGroupIDs);
8295
8330
  } else {
8296
8331
  dbNamesToKeep.push(dbName);
8297
8332
  }
@@ -8304,16 +8339,24 @@ async function collectIDBDatabases(idbDatabasesStore, now, maxAge, kvDropStore,
8304
8339
  if (errors.length) {
8305
8340
  throw errors[0];
8306
8341
  }
8307
- if (clientIDsToRemove.length) {
8308
- const toRemoveIncludingOld = clientIDsToRemove;
8342
+ if (clientIDsToRemove.length || clientGroupIDsToRemove.length) {
8343
+ const newClientIDsToRemove = clientIDsToRemove;
8344
+ const newClientGroupIDsToRemove = clientGroupIDsToRemove;
8309
8345
  for (const name of dbNamesToKeep) {
8310
8346
  await withWrite(newDagStore(name), async (dagWrite) => {
8311
- toRemoveIncludingOld.push(
8312
- ...await addDeletedClients(dagWrite, clientIDsToRemove)
8347
+ const { clientIDs, clientGroupIDs } = await addDeletedClients(
8348
+ dagWrite,
8349
+ clientIDsToRemove,
8350
+ clientGroupIDsToRemove
8313
8351
  );
8352
+ newClientIDsToRemove.push(...clientIDs);
8353
+ newClientGroupIDsToRemove.push(...clientGroupIDs);
8314
8354
  });
8315
8355
  }
8316
- onClientsDeleted(normalize(toRemoveIncludingOld));
8356
+ onClientsDeleted(
8357
+ normalize(newClientIDsToRemove),
8358
+ normalize(newClientGroupIDsToRemove)
8359
+ );
8317
8360
  }
8318
8361
  }
8319
8362
  async function dropDatabaseInternal(name, idbDatabasesStore, kvDropStore) {
@@ -8391,8 +8434,14 @@ function canDatabaseBeCollectedAndGetDeletedClientIDs(enableMutationRecovery, pe
8391
8434
  }
8392
8435
  }
8393
8436
  const clients = await getClients(read);
8394
- const oldDeletedClients = await getDeletedClients(read);
8395
- return [true, [...clients.keys(), ...oldDeletedClients]];
8437
+ const { clientIDs, clientGroupIDs } = await getDeletedClients(read);
8438
+ const newClientIDs = [...clientIDs];
8439
+ const newClientGroupIDs = [...clientGroupIDs];
8440
+ for (const [clientID, client] of clients) {
8441
+ newClientIDs.push(clientID);
8442
+ newClientGroupIDs.push(client.clientGroupID);
8443
+ }
8444
+ return [true, newClientIDs, newClientGroupIDs];
8396
8445
  });
8397
8446
  }
8398
8447
 
@@ -8937,157 +8986,12 @@ function compareUTF8MaybeNull(a, b) {
8937
8986
  return 0;
8938
8987
  }
8939
8988
 
8940
- // ../zql/src/query/expression.ts
8941
- var ExpressionBuilder = class {
8942
- #exists;
8943
- constructor(exists) {
8944
- this.#exists = exists;
8945
- this.exists = this.exists.bind(this);
8946
- }
8947
- get eb() {
8948
- return this;
8949
- }
8950
- cmp(field, opOrValue, value) {
8951
- return cmp(field, opOrValue, value);
8952
- }
8953
- cmpLit(left, op, right) {
8954
- return {
8955
- type: "simple",
8956
- left: isParameterReference(left) ? left[toStaticParam]() : { type: "literal", value: left },
8957
- right: isParameterReference(right) ? right[toStaticParam]() : { type: "literal", value: right },
8958
- op
8959
- };
8960
- }
8961
- and = and;
8962
- or = or;
8963
- not = not;
8964
- exists(relationship, cb) {
8965
- return this.#exists(relationship, cb);
8966
- }
8967
- };
8968
- function and(...conditions) {
8969
- const expressions = filterTrue(filterUndefined(conditions));
8970
- if (expressions.length === 1) {
8971
- return expressions[0];
8972
- }
8973
- if (expressions.some(isAlwaysFalse)) {
8974
- return FALSE;
8975
- }
8976
- return { type: "and", conditions: expressions };
8977
- }
8978
- function or(...conditions) {
8979
- const expressions = filterFalse(filterUndefined(conditions));
8980
- if (expressions.length === 1) {
8981
- return expressions[0];
8982
- }
8983
- if (expressions.some(isAlwaysTrue)) {
8984
- return TRUE;
8985
- }
8986
- return { type: "or", conditions: expressions };
8987
- }
8988
- function not(expression) {
8989
- switch (expression.type) {
8990
- case "and":
8991
- return {
8992
- type: "or",
8993
- conditions: expression.conditions.map(not)
8994
- };
8995
- case "or":
8996
- return {
8997
- type: "and",
8998
- conditions: expression.conditions.map(not)
8999
- };
9000
- case "correlatedSubquery":
9001
- return {
9002
- type: "correlatedSubquery",
9003
- related: expression.related,
9004
- op: negateOperator(expression.op)
9005
- };
9006
- case "simple":
9007
- return {
9008
- type: "simple",
9009
- op: negateOperator(expression.op),
9010
- left: expression.left,
9011
- right: expression.right
9012
- };
9013
- }
9014
- }
9015
- function cmp(field, opOrValue, value) {
9016
- let op;
9017
- if (value === void 0) {
9018
- value = opOrValue;
9019
- op = "=";
9020
- } else {
9021
- op = opOrValue;
9022
- }
9023
- return {
9024
- type: "simple",
9025
- left: { type: "column", name: field },
9026
- right: isParameterReference(value) ? value[toStaticParam]() : { type: "literal", value },
9027
- op
9028
- };
9029
- }
9030
- function isParameterReference(value) {
9031
- return value !== null && typeof value === "object" && value[toStaticParam];
9032
- }
9033
- var TRUE = {
9034
- type: "and",
9035
- conditions: []
9036
- };
9037
- var FALSE = {
9038
- type: "or",
9039
- conditions: []
9040
- };
9041
- function isAlwaysTrue(condition) {
9042
- return condition.type === "and" && condition.conditions.length === 0;
9043
- }
9044
- function isAlwaysFalse(condition) {
9045
- return condition.type === "or" && condition.conditions.length === 0;
9046
- }
9047
- function flatten(type, conditions) {
9048
- const flattened2 = [];
9049
- for (const c of conditions) {
9050
- if (c.type === type) {
9051
- flattened2.push(...c.conditions);
9052
- } else {
9053
- flattened2.push(c);
9054
- }
9055
- }
9056
- return flattened2;
9057
- }
9058
- var negateSimpleOperatorMap = {
9059
- ["="]: "!=",
9060
- ["!="]: "=",
9061
- ["<"]: ">=",
9062
- [">"]: "<=",
9063
- [">="]: "<",
9064
- ["<="]: ">",
9065
- ["IN"]: "NOT IN",
9066
- ["NOT IN"]: "IN",
9067
- ["LIKE"]: "NOT LIKE",
9068
- ["NOT LIKE"]: "LIKE",
9069
- ["ILIKE"]: "NOT ILIKE",
9070
- ["NOT ILIKE"]: "ILIKE",
9071
- ["IS"]: "IS NOT",
9072
- ["IS NOT"]: "IS"
9073
- };
9074
- var negateOperatorMap = {
9075
- ...negateSimpleOperatorMap,
9076
- ["EXISTS"]: "NOT EXISTS",
9077
- ["NOT EXISTS"]: "EXISTS"
9078
- };
9079
- function negateOperator(op) {
9080
- return must(negateOperatorMap[op]);
9081
- }
9082
- function filterUndefined(array12) {
9083
- return array12.filter((e) => e !== void 0);
9084
- }
9085
- function filterTrue(conditions) {
9086
- return conditions.filter((c) => !isAlwaysTrue(c));
9087
- }
9088
- function filterFalse(conditions) {
9089
- return conditions.filter((c) => !isAlwaysFalse(c));
9090
- }
8989
+ // ../zero-protocol/src/protocol-version.ts
8990
+ var PROTOCOL_VERSION = 5;
8991
+ var MIN_SERVER_SUPPORTED_SYNC_PROTOCOL = 2;
8992
+ assert(MIN_SERVER_SUPPORTED_SYNC_PROTOCOL < PROTOCOL_VERSION);
8993
+ var MIN_SERVER_SUPPORTED_PERMISSIONS_PROTOCOL = 4;
8994
+ assert(MIN_SERVER_SUPPORTED_PERMISSIONS_PROTOCOL < PROTOCOL_VERSION);
9091
8995
 
9092
8996
  // ../zql/src/query/query-impl.ts
9093
8997
  import { resolver as resolver7 } from "@rocicorp/resolver";
@@ -10538,11 +10442,11 @@ function createPredicateImpl(rhs, operator) {
10538
10442
  case "LIKE":
10539
10443
  return getLikePredicate(rhs, "");
10540
10444
  case "NOT LIKE":
10541
- return not2(getLikePredicate(rhs, ""));
10445
+ return not(getLikePredicate(rhs, ""));
10542
10446
  case "ILIKE":
10543
10447
  return getLikePredicate(rhs, "i");
10544
10448
  case "NOT ILIKE":
10545
- return not2(getLikePredicate(rhs, "i"));
10449
+ return not(getLikePredicate(rhs, "i"));
10546
10450
  case "IN": {
10547
10451
  assert(Array.isArray(rhs));
10548
10452
  const set = new Set(rhs);
@@ -10558,7 +10462,7 @@ function createPredicateImpl(rhs, operator) {
10558
10462
  throw new Error(`Unexpected operator: ${operator}`);
10559
10463
  }
10560
10464
  }
10561
- function not2(f) {
10465
+ function not(f) {
10562
10466
  return (lhs) => !f(lhs);
10563
10467
  }
10564
10468
  function transformFilters(filters) {
@@ -10929,6 +10833,158 @@ var ArrayView = class {
10929
10833
  }
10930
10834
  };
10931
10835
 
10836
+ // ../zql/src/query/expression.ts
10837
+ var ExpressionBuilder = class {
10838
+ #exists;
10839
+ constructor(exists) {
10840
+ this.#exists = exists;
10841
+ this.exists = this.exists.bind(this);
10842
+ }
10843
+ get eb() {
10844
+ return this;
10845
+ }
10846
+ cmp(field, opOrValue, value) {
10847
+ return cmp(field, opOrValue, value);
10848
+ }
10849
+ cmpLit(left, op, right) {
10850
+ return {
10851
+ type: "simple",
10852
+ left: isParameterReference(left) ? left[toStaticParam]() : { type: "literal", value: left },
10853
+ right: isParameterReference(right) ? right[toStaticParam]() : { type: "literal", value: right },
10854
+ op
10855
+ };
10856
+ }
10857
+ and = and;
10858
+ or = or;
10859
+ not = not2;
10860
+ exists(relationship, cb) {
10861
+ return this.#exists(relationship, cb);
10862
+ }
10863
+ };
10864
+ function and(...conditions) {
10865
+ const expressions = filterTrue(filterUndefined(conditions));
10866
+ if (expressions.length === 1) {
10867
+ return expressions[0];
10868
+ }
10869
+ if (expressions.some(isAlwaysFalse)) {
10870
+ return FALSE;
10871
+ }
10872
+ return { type: "and", conditions: expressions };
10873
+ }
10874
+ function or(...conditions) {
10875
+ const expressions = filterFalse(filterUndefined(conditions));
10876
+ if (expressions.length === 1) {
10877
+ return expressions[0];
10878
+ }
10879
+ if (expressions.some(isAlwaysTrue)) {
10880
+ return TRUE;
10881
+ }
10882
+ return { type: "or", conditions: expressions };
10883
+ }
10884
+ function not2(expression) {
10885
+ switch (expression.type) {
10886
+ case "and":
10887
+ return {
10888
+ type: "or",
10889
+ conditions: expression.conditions.map(not2)
10890
+ };
10891
+ case "or":
10892
+ return {
10893
+ type: "and",
10894
+ conditions: expression.conditions.map(not2)
10895
+ };
10896
+ case "correlatedSubquery":
10897
+ return {
10898
+ type: "correlatedSubquery",
10899
+ related: expression.related,
10900
+ op: negateOperator(expression.op)
10901
+ };
10902
+ case "simple":
10903
+ return {
10904
+ type: "simple",
10905
+ op: negateOperator(expression.op),
10906
+ left: expression.left,
10907
+ right: expression.right
10908
+ };
10909
+ }
10910
+ }
10911
+ function cmp(field, opOrValue, value) {
10912
+ let op;
10913
+ if (value === void 0) {
10914
+ value = opOrValue;
10915
+ op = "=";
10916
+ } else {
10917
+ op = opOrValue;
10918
+ }
10919
+ return {
10920
+ type: "simple",
10921
+ left: { type: "column", name: field },
10922
+ right: isParameterReference(value) ? value[toStaticParam]() : { type: "literal", value },
10923
+ op
10924
+ };
10925
+ }
10926
+ function isParameterReference(value) {
10927
+ return value !== null && typeof value === "object" && value[toStaticParam];
10928
+ }
10929
+ var TRUE = {
10930
+ type: "and",
10931
+ conditions: []
10932
+ };
10933
+ var FALSE = {
10934
+ type: "or",
10935
+ conditions: []
10936
+ };
10937
+ function isAlwaysTrue(condition) {
10938
+ return condition.type === "and" && condition.conditions.length === 0;
10939
+ }
10940
+ function isAlwaysFalse(condition) {
10941
+ return condition.type === "or" && condition.conditions.length === 0;
10942
+ }
10943
+ function flatten(type, conditions) {
10944
+ const flattened2 = [];
10945
+ for (const c of conditions) {
10946
+ if (c.type === type) {
10947
+ flattened2.push(...c.conditions);
10948
+ } else {
10949
+ flattened2.push(c);
10950
+ }
10951
+ }
10952
+ return flattened2;
10953
+ }
10954
+ var negateSimpleOperatorMap = {
10955
+ ["="]: "!=",
10956
+ ["!="]: "=",
10957
+ ["<"]: ">=",
10958
+ [">"]: "<=",
10959
+ [">="]: "<",
10960
+ ["<="]: ">",
10961
+ ["IN"]: "NOT IN",
10962
+ ["NOT IN"]: "IN",
10963
+ ["LIKE"]: "NOT LIKE",
10964
+ ["NOT LIKE"]: "LIKE",
10965
+ ["ILIKE"]: "NOT ILIKE",
10966
+ ["NOT ILIKE"]: "ILIKE",
10967
+ ["IS"]: "IS NOT",
10968
+ ["IS NOT"]: "IS"
10969
+ };
10970
+ var negateOperatorMap = {
10971
+ ...negateSimpleOperatorMap,
10972
+ ["EXISTS"]: "NOT EXISTS",
10973
+ ["NOT EXISTS"]: "EXISTS"
10974
+ };
10975
+ function negateOperator(op) {
10976
+ return must(negateOperatorMap[op]);
10977
+ }
10978
+ function filterUndefined(array9) {
10979
+ return array9.filter((e) => e !== void 0);
10980
+ }
10981
+ function filterTrue(conditions) {
10982
+ return conditions.filter((c) => !isAlwaysTrue(c));
10983
+ }
10984
+ function filterFalse(conditions) {
10985
+ return conditions.filter((c) => !isAlwaysFalse(c));
10986
+ }
10987
+
10932
10988
  // ../zql/src/query/dnf.ts
10933
10989
  function dnf(condition) {
10934
10990
  return unwrap(dnfInner(condition));
@@ -11596,10 +11652,13 @@ function compilePermissions(schema, authz, expressionBuilders) {
11596
11652
  return void 0;
11597
11653
  }
11598
11654
  const nameMapper = clientToServer(schema.tables);
11599
- const ret = {};
11655
+ const ret = {
11656
+ protocolVersion: PROTOCOL_VERSION,
11657
+ tables: {}
11658
+ };
11600
11659
  for (const [tableName, tableConfig] of Object.entries(authz)) {
11601
11660
  const serverName = schema.tables[tableName].serverName ?? tableName;
11602
- ret[serverName] = {
11661
+ ret.tables[serverName] = {
11603
11662
  row: compileRowConfig(
11604
11663
  nameMapper,
11605
11664
  tableName,
@@ -11750,6 +11809,18 @@ function escapeLike(val) {
11750
11809
  import { LogContext as LogContext4 } from "@rocicorp/logger";
11751
11810
  import { resolver as resolver8 } from "@rocicorp/resolver";
11752
11811
 
11812
+ // ../zero-protocol/src/delete-clients.ts
11813
+ var deleteClientsBodySchema = valita_exports.union(
11814
+ readonlyObject({
11815
+ clientIDs: readonlyArray(valita_exports.string()).optional(),
11816
+ clientGroupIDs: readonlyArray(valita_exports.string()).optional()
11817
+ })
11818
+ );
11819
+ var deleteClientsMessageSchema = valita_exports.tuple([
11820
+ valita_exports.literal("deleteClients"),
11821
+ deleteClientsBodySchema
11822
+ ]);
11823
+
11753
11824
  // ../zero-protocol/src/queries-patch.ts
11754
11825
  var putOpSchema = valita_exports.object({
11755
11826
  op: valita_exports.literal("put"),
@@ -11777,7 +11848,7 @@ var connectedMessageSchema = valita_exports.tuple([
11777
11848
  ]);
11778
11849
  var initConnectionBodySchema = valita_exports.object({
11779
11850
  desiredQueriesPatch: queriesPatchSchema,
11780
- deletedClients: valita_exports.array(valita_exports.string()).optional()
11851
+ deleted: deleteClientsBodySchema.optional()
11781
11852
  });
11782
11853
  var initConnectionMessageSchema = valita_exports.tuple([
11783
11854
  valita_exports.literal("initConnection"),
@@ -11791,15 +11862,6 @@ function encodeSecProtocols(initConnectionMessage, authToken) {
11791
11862
  return encodeURIComponent(btoa(JSON.stringify(protocols)));
11792
11863
  }
11793
11864
 
11794
- // ../zero-protocol/src/delete-clients.ts
11795
- var deleteClientsBodySchema = valita_exports.object({
11796
- clientIDs: valita_exports.array(valita_exports.string())
11797
- });
11798
- var deleteClientsMessageSchema = valita_exports.tuple([
11799
- valita_exports.literal("deleteClients"),
11800
- deleteClientsBodySchema
11801
- ]);
11802
-
11803
11865
  // ../zero-protocol/src/error-kind-enum.ts
11804
11866
  var AuthInvalidated = "AuthInvalidated";
11805
11867
  var ClientNotFound = "ClientNotFound";
@@ -12032,11 +12094,6 @@ var downstreamSchema = valita_exports.union(
12032
12094
  var CRUD = "crud";
12033
12095
  var Custom = "custom";
12034
12096
 
12035
- // ../zero-protocol/src/protocol-version.ts
12036
- var PROTOCOL_VERSION = 5;
12037
- var MIN_SERVER_SUPPORTED_PROTOCOL_VERSION = 2;
12038
- assert(MIN_SERVER_SUPPORTED_PROTOCOL_VERSION < PROTOCOL_VERSION);
12039
-
12040
12097
  // ../zero-protocol/src/push.ts
12041
12098
  var CRUD_MUTATION_NAME = "_zero_crud";
12042
12099
  var insertOpSchema = valita_exports.object({
@@ -13379,48 +13436,28 @@ var ZeroContext = class {
13379
13436
  // ../zero-client/src/client/crud.ts
13380
13437
  function makeCRUDMutate(schema, repMutate) {
13381
13438
  const { [CRUD_MUTATION_NAME]: zeroCRUD } = repMutate;
13382
- let inBatch = false;
13383
13439
  const mutateBatch = async (body) => {
13384
- if (inBatch) {
13385
- throw new Error("Cannot call mutate inside a batch");
13386
- }
13387
- inBatch = true;
13388
- try {
13389
- const ops = [];
13390
- const m = {};
13391
- for (const name of Object.keys(schema.tables)) {
13392
- m[name] = makeBatchCRUDMutate(name, schema, ops);
13393
- }
13394
- const rv = await body(m);
13395
- await zeroCRUD({ ops });
13396
- return rv;
13397
- } finally {
13398
- inBatch = false;
13399
- }
13400
- };
13401
- const assertNotInBatch = (tableName, op) => {
13402
- if (inBatch) {
13403
- throw new Error(`Cannot call mutate.${tableName}.${op} inside a batch`);
13440
+ const ops = [];
13441
+ const m = {};
13442
+ for (const name of Object.keys(schema.tables)) {
13443
+ m[name] = makeBatchCRUDMutate(name, schema, ops);
13404
13444
  }
13445
+ const rv = await body(m);
13446
+ await zeroCRUD({ ops });
13447
+ return rv;
13405
13448
  };
13406
13449
  const mutate = {};
13407
13450
  for (const [name, tableSchema] of Object.entries(schema.tables)) {
13408
- mutate[name] = makeEntityCRUDMutate(
13409
- name,
13410
- tableSchema.primaryKey,
13411
- zeroCRUD,
13412
- assertNotInBatch
13413
- );
13451
+ mutate[name] = makeEntityCRUDMutate(name, tableSchema.primaryKey, zeroCRUD);
13414
13452
  }
13415
13453
  return {
13416
13454
  mutate,
13417
13455
  mutateBatch
13418
13456
  };
13419
13457
  }
13420
- function makeEntityCRUDMutate(tableName, primaryKey, zeroCRUD, assertNotInBatch) {
13458
+ function makeEntityCRUDMutate(tableName, primaryKey, zeroCRUD) {
13421
13459
  return {
13422
13460
  insert: (value) => {
13423
- assertNotInBatch(tableName, "insert");
13424
13461
  const op = {
13425
13462
  op: "insert",
13426
13463
  tableName,
@@ -13430,7 +13467,6 @@ function makeEntityCRUDMutate(tableName, primaryKey, zeroCRUD, assertNotInBatch)
13430
13467
  return zeroCRUD({ ops: [op] });
13431
13468
  },
13432
13469
  upsert: (value) => {
13433
- assertNotInBatch(tableName, "upsert");
13434
13470
  const op = {
13435
13471
  op: "upsert",
13436
13472
  tableName,
@@ -13440,7 +13476,6 @@ function makeEntityCRUDMutate(tableName, primaryKey, zeroCRUD, assertNotInBatch)
13440
13476
  return zeroCRUD({ ops: [op] });
13441
13477
  },
13442
13478
  update: (value) => {
13443
- assertNotInBatch(tableName, "update");
13444
13479
  const op = {
13445
13480
  op: "update",
13446
13481
  tableName,
@@ -13450,7 +13485,6 @@ function makeEntityCRUDMutate(tableName, primaryKey, zeroCRUD, assertNotInBatch)
13450
13485
  return zeroCRUD({ ops: [op] });
13451
13486
  },
13452
13487
  delete: (id) => {
13453
- assertNotInBatch(tableName, "delete");
13454
13488
  const op = {
13455
13489
  op: "delete",
13456
13490
  tableName,
@@ -13715,33 +13749,37 @@ var DeleteClientsManager = class {
13715
13749
  * This gets called by Replicache when it deletes clients from the persistent
13716
13750
  * storage.
13717
13751
  */
13718
- onClientsDeleted(clientIDs) {
13752
+ onClientsDeleted(clientIDs, clientGroupIDs) {
13719
13753
  this.#lc.debug?.("DeletedClientsManager, send:", clientIDs);
13720
- this.#send(["deleteClients", { clientIDs }]);
13754
+ this.#send(["deleteClients", { clientIDs, clientGroupIDs }]);
13721
13755
  }
13722
13756
  /**
13723
13757
  * Zero calls this after it connects to ensure that the server knows about all
13724
13758
  * the clients that might have been deleted locally since the last connection.
13725
13759
  */
13726
13760
  async sendDeletedClientsToServer() {
13727
- const deletedClients = await withRead(
13761
+ const deleted = await withRead(
13728
13762
  this.#dagStore,
13729
13763
  (dagRead) => getDeletedClients(dagRead)
13730
13764
  );
13731
- if (deletedClients.length > 0) {
13732
- this.#send(["deleteClients", { clientIDs: deletedClients }]);
13733
- this.#lc.debug?.("DeletedClientsManager, send:", deletedClients);
13765
+ if (deleted.clientIDs.length > 0 || deleted.clientGroupIDs.length > 0) {
13766
+ this.#send(["deleteClients", deleted]);
13767
+ this.#lc.debug?.("DeletedClientsManager, send:", deleted);
13734
13768
  }
13735
13769
  }
13736
13770
  /**
13737
13771
  * This is called as a response to the server telling us which clients it
13738
13772
  * actually deleted.
13739
13773
  */
13740
- clientsDeletedOnServer(clientIDs) {
13741
- return withWrite(this.#dagStore, async (dagWrite) => {
13742
- this.#lc.debug?.("clientsDeletedOnServer:", clientIDs);
13743
- await removeDeletedClients(dagWrite, clientIDs);
13744
- });
13774
+ clientsDeletedOnServer(deletedClients) {
13775
+ const { clientIDs = [], clientGroupIDs = [] } = deletedClients;
13776
+ if (clientIDs.length > 0 || clientGroupIDs.length > 0) {
13777
+ return withWrite(this.#dagStore, async (dagWrite) => {
13778
+ this.#lc.debug?.("clientsDeletedOnServer:", clientIDs, clientGroupIDs);
13779
+ await removeDeletedClients(dagWrite, clientIDs, clientGroupIDs);
13780
+ });
13781
+ }
13782
+ return promiseVoid;
13745
13783
  }
13746
13784
  getDeletedClients() {
13747
13785
  return withRead(this.#dagStore, getDeletedClients);
@@ -13996,7 +14034,7 @@ function makeMessage(message, context, logLevel) {
13996
14034
  }
13997
14035
 
13998
14036
  // ../zero-client/src/client/version.ts
13999
- var version2 = "0.14.2025021001";
14037
+ var version2 = "0.14.2025021101";
14000
14038
 
14001
14039
  // ../zero-client/src/client/log-options.ts
14002
14040
  var LevelFilterLogSink = class {
@@ -14981,9 +15019,10 @@ var Zero = class {
14981
15019
  */
14982
15020
  #initConnectionQueries;
14983
15021
  /**
14984
- * We try to send the deleted clients as part of the sec-protocol header. If we can't
14985
- * because the header would get to long we keep track of the deleted clients and send
14986
- * them after the connection is established.
15022
+ * We try to send the deleted clients and (client groups) as part of the
15023
+ * sec-protocol header. If we can't because the header would get too large we
15024
+ * keep track of the deleted clients and send them after the connection is
15025
+ * established.
14987
15026
  */
14988
15027
  #deletedClients;
14989
15028
  #lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;
@@ -15122,7 +15161,7 @@ var Zero = class {
15122
15161
  const replicacheImplOptions = {
15123
15162
  enableClientGroupForking: false,
15124
15163
  enableMutationRecovery: false,
15125
- onClientsDeleted: (clientIDs) => this.#deleteClientsManager.onClientsDeleted(clientIDs)
15164
+ onClientsDeleted: (clientIDs, clientGroupIDs) => this.#deleteClientsManager.onClientsDeleted(clientIDs, clientGroupIDs)
15126
15165
  };
15127
15166
  const rep = new ReplicacheImpl(replicacheOptions, replicacheImplOptions);
15128
15167
  this.#rep = rep;
@@ -15387,7 +15426,7 @@ var Zero = class {
15387
15426
  break;
15388
15427
  case "deleteClients":
15389
15428
  return this.#deleteClientsManager.clientsDeletedOnServer(
15390
- downMessage[1].clientIDs
15429
+ downMessage[1]
15391
15430
  );
15392
15431
  default:
15393
15432
  msgType;
@@ -15495,11 +15534,10 @@ var Zero = class {
15495
15534
  const queriesPatch = await this.#rep.query(
15496
15535
  (tx) => this.#queryManager.getQueriesPatch(tx, this.#initConnectionQueries)
15497
15536
  );
15537
+ const hasDeletedClients = () => skipEmptyArray(this.#deletedClients?.clientIDs) || skipEmptyArray(this.#deletedClients?.clientGroupIDs);
15498
15538
  const maybeSendDeletedClients = () => {
15499
- if (this.#deletedClients) {
15500
- if (this.#deletedClients.length > 0) {
15501
- send(socket, ["deleteClients", { clientIDs: this.#deletedClients }]);
15502
- }
15539
+ if (hasDeletedClients()) {
15540
+ send(socket, ["deleteClients", this.#deletedClients]);
15503
15541
  this.#deletedClients = void 0;
15504
15542
  }
15505
15543
  };
@@ -15516,7 +15554,7 @@ var Zero = class {
15516
15554
  "initConnection",
15517
15555
  {
15518
15556
  desiredQueriesPatch: [...queriesPatch.values()],
15519
- deletedClients: this.#deletedClients && this.#deletedClients.length > 0 ? this.#deletedClients : void 0
15557
+ deleted: skipEmptyDeletedClients(this.#deletedClients)
15520
15558
  }
15521
15559
  ]);
15522
15560
  this.#deletedClients = void 0;
@@ -16089,7 +16127,7 @@ async function createSocket(rep, queryManager, deleteClientsManager, socketOrigi
16089
16127
  "initConnection",
16090
16128
  {
16091
16129
  desiredQueriesPatch: [...queriesPatch.values()],
16092
- deletedClients: deletedClients.length > 0 ? deletedClients : void 0
16130
+ deleted: skipEmptyDeletedClients(deletedClients)
16093
16131
  }
16094
16132
  ],
16095
16133
  auth
@@ -16107,9 +16145,25 @@ async function createSocket(rep, queryManager, deleteClientsManager, socketOrigi
16107
16145
  secProtocol
16108
16146
  ),
16109
16147
  queriesPatch,
16110
- deletedClients
16148
+ skipEmptyDeletedClients(deletedClients)
16111
16149
  ];
16112
16150
  }
16151
+ function skipEmptyArray(arr) {
16152
+ return arr && arr.length > 0 ? arr : void 0;
16153
+ }
16154
+ function skipEmptyDeletedClients(deletedClients) {
16155
+ if (!deletedClients) {
16156
+ return void 0;
16157
+ }
16158
+ const { clientIDs, clientGroupIDs } = deletedClients;
16159
+ if ((!clientIDs || clientIDs.length === 0) && (!clientGroupIDs || clientGroupIDs.length === 0)) {
16160
+ return void 0;
16161
+ }
16162
+ const data = {};
16163
+ data.clientIDs = skipEmptyArray(clientIDs);
16164
+ data.clientGroupIDs = skipEmptyArray(clientGroupIDs);
16165
+ return data;
16166
+ }
16113
16167
  function addWebSocketIDFromSocketToLogContext({ url }, lc) {
16114
16168
  const wsid = new URL(url).searchParams.get("wsid") ?? nanoid();
16115
16169
  return addWebSocketIDToLogContext(wsid, lc);
@@ -16152,4 +16206,4 @@ export {
16152
16206
  escapeLike,
16153
16207
  Zero
16154
16208
  };
16155
- //# sourceMappingURL=chunk-MVLDKRBK.js.map
16209
+ //# sourceMappingURL=chunk-5GWP7BBD.js.map