@rocicorp/zero 0.25.0-canary.1 → 0.25.0

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 (166) hide show
  1. package/out/{chunk-AIPM77UE.js → chunk-QZSBDHTA.js} +509 -311
  2. package/out/chunk-QZSBDHTA.js.map +7 -0
  3. package/out/{chunk-55BOUNXO.js → chunk-YTVU4GOY.js} +19 -3
  4. package/out/{chunk-55BOUNXO.js.map → chunk-YTVU4GOY.js.map} +3 -3
  5. package/out/react.js +44 -25
  6. package/out/react.js.map +2 -2
  7. package/out/shared/src/error.d.ts +4 -0
  8. package/out/shared/src/error.d.ts.map +1 -0
  9. package/out/shared/src/error.js +70 -0
  10. package/out/shared/src/error.js.map +1 -0
  11. package/out/solid.js +44 -18
  12. package/out/solid.js.map +2 -2
  13. package/out/zero/package.json +3 -2
  14. package/out/zero/src/zero-out.d.ts +3 -0
  15. package/out/zero/src/zero-out.d.ts.map +1 -0
  16. package/out/zero/src/zero-out.js +13 -0
  17. package/out/zero/src/zero-out.js.map +1 -0
  18. package/out/zero-cache/src/custom/fetch.js +3 -3
  19. package/out/zero-cache/src/custom/fetch.js.map +1 -1
  20. package/out/zero-cache/src/scripts/decommission.d.ts +50 -0
  21. package/out/zero-cache/src/scripts/decommission.d.ts.map +1 -0
  22. package/out/zero-cache/src/scripts/decommission.js +51 -0
  23. package/out/zero-cache/src/scripts/decommission.js.map +1 -0
  24. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  25. package/out/zero-cache/src/server/inspector-delegate.js +2 -1
  26. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  27. package/out/zero-cache/src/services/mutagen/pusher.d.ts +17 -21
  28. package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
  29. package/out/zero-cache/src/services/mutagen/pusher.js +4 -4
  30. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  31. package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts +1 -0
  32. package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts.map +1 -1
  33. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +5 -0
  34. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
  35. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +7 -0
  36. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  37. package/out/zero-cache/src/services/view-syncer/view-syncer.js +24 -1
  38. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  39. package/out/zero-cache/src/types/streams.d.ts +1 -1
  40. package/out/zero-cache/src/types/streams.d.ts.map +1 -1
  41. package/out/zero-cache/src/types/streams.js +19 -9
  42. package/out/zero-cache/src/types/streams.js.map +1 -1
  43. package/out/zero-cache/src/types/subscription.d.ts +16 -1
  44. package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
  45. package/out/zero-cache/src/types/subscription.js +41 -5
  46. package/out/zero-cache/src/types/subscription.js.map +1 -1
  47. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  48. package/out/zero-cache/src/workers/syncer.js +1 -3
  49. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  50. package/out/zero-client/src/client/connection-manager.d.ts +21 -5
  51. package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
  52. package/out/zero-client/src/client/connection-status-enum.d.ts +2 -0
  53. package/out/zero-client/src/client/connection-status-enum.d.ts.map +1 -1
  54. package/out/zero-client/src/client/connection.d.ts +11 -3
  55. package/out/zero-client/src/client/connection.d.ts.map +1 -1
  56. package/out/zero-client/src/client/error.d.ts +33 -161
  57. package/out/zero-client/src/client/error.d.ts.map +1 -1
  58. package/out/zero-client/src/client/mutation-tracker.d.ts.map +1 -1
  59. package/out/zero-client/src/client/options.d.ts +9 -16
  60. package/out/zero-client/src/client/options.d.ts.map +1 -1
  61. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  62. package/out/zero-client/src/client/zero-rep.d.ts +2 -0
  63. package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
  64. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  65. package/out/zero-client/src/mod.d.ts +4 -1
  66. package/out/zero-client/src/mod.d.ts.map +1 -1
  67. package/out/zero-client/src/types/query-result.d.ts +23 -0
  68. package/out/zero-client/src/types/query-result.d.ts.map +1 -0
  69. package/out/zero-protocol/src/application-error.d.ts +33 -0
  70. package/out/zero-protocol/src/application-error.d.ts.map +1 -0
  71. package/out/zero-protocol/src/application-error.js +37 -0
  72. package/out/zero-protocol/src/application-error.js.map +1 -0
  73. package/out/zero-protocol/src/custom-queries.d.ts +27 -95
  74. package/out/zero-protocol/src/custom-queries.d.ts.map +1 -1
  75. package/out/zero-protocol/src/custom-queries.js +9 -24
  76. package/out/zero-protocol/src/custom-queries.js.map +1 -1
  77. package/out/zero-protocol/src/down.d.ts +7 -9
  78. package/out/zero-protocol/src/down.d.ts.map +1 -1
  79. package/out/zero-protocol/src/error.d.ts +42 -0
  80. package/out/zero-protocol/src/error.d.ts.map +1 -1
  81. package/out/zero-protocol/src/error.js +7 -0
  82. package/out/zero-protocol/src/error.js.map +1 -1
  83. package/out/zero-protocol/src/mutations-patch.d.ts +3 -0
  84. package/out/zero-protocol/src/mutations-patch.d.ts.map +1 -1
  85. package/out/zero-protocol/src/poke.d.ts +2 -0
  86. package/out/zero-protocol/src/poke.d.ts.map +1 -1
  87. package/out/zero-protocol/src/protocol-version.d.ts +1 -1
  88. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  89. package/out/zero-protocol/src/protocol-version.js +2 -1
  90. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  91. package/out/zero-protocol/src/push.d.ts +7 -0
  92. package/out/zero-protocol/src/push.d.ts.map +1 -1
  93. package/out/zero-protocol/src/push.js +1 -0
  94. package/out/zero-protocol/src/push.js.map +1 -1
  95. package/out/zero-react/src/mod.d.ts +5 -1
  96. package/out/zero-react/src/mod.d.ts.map +1 -1
  97. package/out/zero-react/src/use-query.d.ts +1 -21
  98. package/out/zero-react/src/use-query.d.ts.map +1 -1
  99. package/out/zero-react/src/zero-provider.d.ts.map +1 -1
  100. package/out/zero-server/src/mod.d.ts +5 -4
  101. package/out/zero-server/src/mod.d.ts.map +1 -1
  102. package/out/zero-server/src/mod.js +5 -4
  103. package/out/zero-server/src/mod.js.map +1 -1
  104. package/out/zero-server/src/process-mutations.d.ts.map +1 -1
  105. package/out/zero-server/src/process-mutations.js +181 -68
  106. package/out/zero-server/src/process-mutations.js.map +1 -1
  107. package/out/zero-server/src/queries/process-queries.d.ts +4 -3
  108. package/out/zero-server/src/queries/process-queries.d.ts.map +1 -1
  109. package/out/zero-server/src/queries/process-queries.js +85 -19
  110. package/out/zero-server/src/queries/process-queries.js.map +1 -1
  111. package/out/zero-solid/src/mod.d.ts +8 -0
  112. package/out/zero-solid/src/mod.d.ts.map +1 -1
  113. package/out/zero-solid/src/solid-view.d.ts +3 -23
  114. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  115. package/out/zero-solid/src/use-query.d.ts +1 -1
  116. package/out/zero-solid/src/use-query.d.ts.map +1 -1
  117. package/out/zero-solid/src/use-zero.d.ts +1 -0
  118. package/out/zero-solid/src/use-zero.d.ts.map +1 -1
  119. package/out/zero.js +4 -2
  120. package/out/zql/src/planner/planner-builder.d.ts +2 -1
  121. package/out/zql/src/planner/planner-builder.d.ts.map +1 -1
  122. package/out/zql/src/planner/planner-builder.js +6 -6
  123. package/out/zql/src/planner/planner-builder.js.map +1 -1
  124. package/out/zql/src/planner/planner-connection.d.ts +9 -3
  125. package/out/zql/src/planner/planner-connection.d.ts.map +1 -1
  126. package/out/zql/src/planner/planner-connection.js +38 -82
  127. package/out/zql/src/planner/planner-connection.js.map +1 -1
  128. package/out/zql/src/planner/planner-debug.d.ts +37 -7
  129. package/out/zql/src/planner/planner-debug.d.ts.map +1 -1
  130. package/out/zql/src/planner/planner-debug.js +131 -80
  131. package/out/zql/src/planner/planner-debug.js.map +1 -1
  132. package/out/zql/src/planner/planner-fan-in.d.ts +5 -3
  133. package/out/zql/src/planner/planner-fan-in.d.ts.map +1 -1
  134. package/out/zql/src/planner/planner-fan-in.js +41 -23
  135. package/out/zql/src/planner/planner-fan-in.js.map +1 -1
  136. package/out/zql/src/planner/planner-fan-out.d.ts +5 -3
  137. package/out/zql/src/planner/planner-fan-out.d.ts.map +1 -1
  138. package/out/zql/src/planner/planner-fan-out.js +22 -5
  139. package/out/zql/src/planner/planner-fan-out.js.map +1 -1
  140. package/out/zql/src/planner/planner-graph.d.ts +2 -2
  141. package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
  142. package/out/zql/src/planner/planner-graph.js +17 -48
  143. package/out/zql/src/planner/planner-graph.js.map +1 -1
  144. package/out/zql/src/planner/planner-join.d.ts +61 -6
  145. package/out/zql/src/planner/planner-join.d.ts.map +1 -1
  146. package/out/zql/src/planner/planner-join.js +148 -65
  147. package/out/zql/src/planner/planner-join.js.map +1 -1
  148. package/out/zql/src/planner/planner-node.d.ts +29 -2
  149. package/out/zql/src/planner/planner-node.d.ts.map +1 -1
  150. package/out/zql/src/planner/planner-source.d.ts +1 -1
  151. package/out/zql/src/planner/planner-source.d.ts.map +1 -1
  152. package/out/zql/src/planner/planner-source.js +2 -2
  153. package/out/zql/src/planner/planner-source.js.map +1 -1
  154. package/out/zql/src/planner/planner-terminus.d.ts +4 -3
  155. package/out/zql/src/planner/planner-terminus.d.ts.map +1 -1
  156. package/out/zql/src/planner/planner-terminus.js +4 -4
  157. package/out/zql/src/planner/planner-terminus.js.map +1 -1
  158. package/out/zql/src/query/error.d.ts +4 -0
  159. package/out/zql/src/query/error.d.ts.map +1 -0
  160. package/out/zql/src/query/error.js +9 -0
  161. package/out/zql/src/query/error.js.map +1 -0
  162. package/out/zql/src/query/named.d.ts.map +1 -1
  163. package/out/zql/src/query/named.js +9 -1
  164. package/out/zql/src/query/named.js.map +1 -1
  165. package/package.json +3 -2
  166. package/out/chunk-AIPM77UE.js.map +0 -7
@@ -1512,6 +1512,103 @@ function rejectIfClosed(tx) {
1512
1512
  return tx.closed ? Promise.reject(new TransactionClosedError()) : void 0;
1513
1513
  }
1514
1514
 
1515
+ // ../shared/src/error.ts
1516
+ function getErrorMessage(error) {
1517
+ return getErrorMessageInternal(error, /* @__PURE__ */ new Set());
1518
+ }
1519
+ function getErrorMessageInternal(error, seen) {
1520
+ if (typeof error === "string") {
1521
+ return error;
1522
+ }
1523
+ if (typeof error === "object" && error !== null) {
1524
+ if (seen.has(error)) {
1525
+ return "Circular error reference detected while extracting the error message.";
1526
+ }
1527
+ seen.add(error);
1528
+ }
1529
+ if (error instanceof Error) {
1530
+ if (error.message) {
1531
+ return error.message;
1532
+ }
1533
+ if ("cause" in error) {
1534
+ const cause = error.cause;
1535
+ if (cause !== void 0) {
1536
+ const causeMessage = getErrorMessageInternal(cause, seen);
1537
+ if (causeMessage) {
1538
+ return causeMessage;
1539
+ }
1540
+ }
1541
+ }
1542
+ }
1543
+ if (typeof error === "object" && error !== null && "message" in error && typeof error.message === "string") {
1544
+ const message = error.message;
1545
+ if (message) {
1546
+ return message;
1547
+ }
1548
+ }
1549
+ try {
1550
+ const json2 = jsonSchema.parse(error);
1551
+ return `Parsed message: ${JSON.stringify(json2)}`;
1552
+ } catch (_e) {
1553
+ }
1554
+ return `Unknown error of type ${typeof error} was thrown and the message could not be determined. See cause for details.`;
1555
+ }
1556
+ function getErrorDetails(error) {
1557
+ if (error instanceof Error) {
1558
+ if ("details" in error) {
1559
+ try {
1560
+ return jsonSchema.parse(error?.details);
1561
+ } catch (_e) {
1562
+ }
1563
+ }
1564
+ if (error.name && error.name !== "Error") {
1565
+ return { name: error.name };
1566
+ }
1567
+ return void 0;
1568
+ }
1569
+ if (typeof error === "object" && error !== null && "details" in error) {
1570
+ try {
1571
+ return jsonSchema.parse(error?.details);
1572
+ } catch (_e) {
1573
+ }
1574
+ }
1575
+ try {
1576
+ return jsonSchema.parse(error);
1577
+ } catch (_e) {
1578
+ }
1579
+ return void 0;
1580
+ }
1581
+
1582
+ // ../zero-protocol/src/application-error.ts
1583
+ var ApplicationError = class extends Error {
1584
+ /**
1585
+ * This maps onto errors for transform and push app-level failures.
1586
+ */
1587
+ #details;
1588
+ constructor(message, options) {
1589
+ super(message, { cause: options?.cause });
1590
+ this.name = "ApplicationError";
1591
+ this.#details = options?.details ?? void 0;
1592
+ }
1593
+ get details() {
1594
+ return this.#details;
1595
+ }
1596
+ };
1597
+ function isApplicationError(error) {
1598
+ return error instanceof ApplicationError;
1599
+ }
1600
+ function wrapWithApplicationError(error) {
1601
+ if (isApplicationError(error)) {
1602
+ return error;
1603
+ }
1604
+ const message = getErrorMessage(error);
1605
+ const details = getErrorDetails(error);
1606
+ return new ApplicationError(message, {
1607
+ cause: error,
1608
+ details
1609
+ });
1610
+ }
1611
+
1515
1612
  // ../zero-protocol/src/error-kind-enum.ts
1516
1613
  var error_kind_enum_exports = {};
1517
1614
  __export(error_kind_enum_exports, {
@@ -1645,6 +1742,10 @@ var errorKindSchema = valita_exports.union(
1645
1742
  var pushFailedBaseSchema = valita_exports.object({
1646
1743
  kind: pushFailedErrorKindSchema,
1647
1744
  details: jsonSchema.optional(),
1745
+ /**
1746
+ * The mutationIDs of the mutations that failed to process.
1747
+ * This can be a subset of the mutationIDs in the request.
1748
+ */
1648
1749
  mutationIDs: valita_exports.array(mutationIDSchema),
1649
1750
  message: valita_exports.string()
1650
1751
  });
@@ -1677,6 +1778,9 @@ var pushFailedBodySchema = valita_exports.union(
1677
1778
  var transformFailedBaseSchema = valita_exports.object({
1678
1779
  kind: transformFailedErrorKindSchema,
1679
1780
  details: jsonSchema.optional(),
1781
+ /**
1782
+ * The queryIDs of the queries that failed to transform.
1783
+ */
1680
1784
  queryIDs: valita_exports.array(valita_exports.string()),
1681
1785
  message: valita_exports.string()
1682
1786
  });
@@ -1742,38 +1846,24 @@ var transformedQuerySchema = valita_exports.object({
1742
1846
  name: valita_exports.string(),
1743
1847
  ast: astSchema
1744
1848
  });
1745
- var appQueryErrorSchema = valita_exports.object({
1849
+ var appErroredQuerySchema = valita_exports.object({
1746
1850
  error: valita_exports.literal("app"),
1747
1851
  id: valita_exports.string(),
1748
1852
  name: valita_exports.string(),
1749
- details: jsonSchema
1750
- });
1751
- var zeroErrorSchema = valita_exports.object({
1752
- /** @deprecated */
1753
- error: valita_exports.literal("zero"),
1754
- /** @deprecated */
1755
- id: valita_exports.string(),
1756
- /** @deprecated */
1757
- name: valita_exports.string(),
1758
- /** @deprecated */
1759
- details: jsonSchema
1853
+ // optional for backwards compatibility
1854
+ message: valita_exports.string().optional(),
1855
+ details: jsonSchema.optional()
1760
1856
  });
1761
- var httpQueryErrorSchema = valita_exports.object({
1762
- /** @deprecated */
1763
- error: valita_exports.literal("http"),
1764
- /** @deprecated */
1857
+ var parseErroredQuerySchema = valita_exports.object({
1858
+ error: valita_exports.literal("parse"),
1765
1859
  id: valita_exports.string(),
1766
- /** @deprecated */
1767
1860
  name: valita_exports.string(),
1768
- /** @deprecated */
1769
- status: valita_exports.number(),
1770
- /** @deprecated */
1771
- details: jsonSchema
1861
+ message: valita_exports.string(),
1862
+ details: jsonSchema.optional()
1772
1863
  });
1773
1864
  var erroredQuerySchema = valita_exports.union(
1774
- appQueryErrorSchema,
1775
- httpQueryErrorSchema,
1776
- zeroErrorSchema
1865
+ appErroredQuerySchema,
1866
+ parseErroredQuerySchema
1777
1867
  );
1778
1868
  var transformResponseBodySchema = valita_exports.array(
1779
1869
  valita_exports.union(transformedQuerySchema, erroredQuerySchema)
@@ -1814,7 +1904,7 @@ function string4() {
1814
1904
  customType: null
1815
1905
  });
1816
1906
  }
1817
- function number4() {
1907
+ function number3() {
1818
1908
  return new ColumnBuilder({
1819
1909
  type: "number",
1820
1910
  optional: false,
@@ -2406,11 +2496,13 @@ __export(connection_status_enum_exports, {
2406
2496
  Connected: () => Connected,
2407
2497
  Connecting: () => Connecting,
2408
2498
  Disconnected: () => Disconnected,
2409
- Error: () => Error2
2499
+ Error: () => Error2,
2500
+ NeedsAuth: () => NeedsAuth
2410
2501
  });
2411
2502
  var Disconnected = "disconnected";
2412
2503
  var Connecting = "connecting";
2413
2504
  var Connected = "connected";
2505
+ var NeedsAuth = "needs-auth";
2414
2506
  var Error2 = "error";
2415
2507
  var Closed = "closed";
2416
2508
 
@@ -2431,7 +2523,7 @@ function isServerError(ex) {
2431
2523
  }
2432
2524
  function isAuthError(ex) {
2433
2525
  if (isServerError(ex)) {
2434
- if (isAuthErrorKind(ex.errorBody.kind)) {
2526
+ if (ex.kind === error_kind_enum_exports.AuthInvalidated || ex.kind === error_kind_enum_exports.Unauthorized) {
2435
2527
  return true;
2436
2528
  }
2437
2529
  if ((ex.errorBody.kind === error_kind_enum_exports.PushFailed || ex.errorBody.kind === error_kind_enum_exports.TransformFailed) && ex.errorBody.reason === error_reason_enum_exports.HTTP && (ex.errorBody.status === 401 || ex.errorBody.status === 403)) {
@@ -2440,9 +2532,6 @@ function isAuthError(ex) {
2440
2532
  }
2441
2533
  return false;
2442
2534
  }
2443
- function isAuthErrorKind(kind) {
2444
- return kind === error_kind_enum_exports.AuthInvalidated || kind === error_kind_enum_exports.Unauthorized;
2445
- }
2446
2535
  function getBackoffParams(error) {
2447
2536
  if (isServerError(error)) {
2448
2537
  switch (error.errorBody.kind) {
@@ -2459,6 +2548,12 @@ function isClientError(ex) {
2459
2548
  }
2460
2549
  var NO_STATUS_TRANSITION = "NO_STATUS_TRANSITION";
2461
2550
  function getErrorConnectionTransition(ex) {
2551
+ if (isAuthError(ex)) {
2552
+ return {
2553
+ status: connection_status_enum_exports.NeedsAuth,
2554
+ reason: ex
2555
+ };
2556
+ }
2462
2557
  if (isClientError(ex)) {
2463
2558
  switch (ex.kind) {
2464
2559
  // Connecting errors that should continue in the current state
@@ -2486,9 +2581,6 @@ function getErrorConnectionTransition(ex) {
2486
2581
  unreachable(ex.kind);
2487
2582
  }
2488
2583
  }
2489
- if (isAuthError(ex)) {
2490
- return { status: NO_STATUS_TRANSITION, reason: ex };
2491
- }
2492
2584
  if (isServerError(ex)) {
2493
2585
  switch (ex.kind) {
2494
2586
  // Errors that should transition to error state
@@ -2502,6 +2594,8 @@ function getErrorConnectionTransition(ex) {
2502
2594
  case error_kind_enum_exports.VersionNotSupported:
2503
2595
  case error_kind_enum_exports.SchemaVersionNotSupported:
2504
2596
  case error_kind_enum_exports.Internal:
2597
+ // PushFailed and TransformFailed can be auth errors (401/403)
2598
+ // or other errors - handle non-auth cases here
2505
2599
  case error_kind_enum_exports.PushFailed:
2506
2600
  case error_kind_enum_exports.TransformFailed:
2507
2601
  return { status: connection_status_enum_exports.Error, reason: ex };
@@ -2510,11 +2604,13 @@ function getErrorConnectionTransition(ex) {
2510
2604
  case error_kind_enum_exports.Rehome:
2511
2605
  case error_kind_enum_exports.ServerOverloaded:
2512
2606
  return { status: NO_STATUS_TRANSITION, reason: ex };
2513
- // Auth errors will eventually transition to needs-auth state
2514
- // For now, treat them as non-fatal so we can retry
2607
+ // Auth errors are handled above by isAuthError check
2515
2608
  case error_kind_enum_exports.AuthInvalidated:
2516
2609
  case error_kind_enum_exports.Unauthorized:
2517
- return { status: NO_STATUS_TRANSITION, reason: ex };
2610
+ return {
2611
+ status: connection_status_enum_exports.NeedsAuth,
2612
+ reason: ex
2613
+ };
2518
2614
  // Mutation-specific errors don't affect connection state
2519
2615
  case error_kind_enum_exports.MutationRateLimited:
2520
2616
  case error_kind_enum_exports.MutationFailed:
@@ -6821,9 +6917,10 @@ var pushMessageSchema = valita_exports.tuple([valita_exports.literal("push"), pu
6821
6917
  var appErrorSchema = valita_exports.object({
6822
6918
  error: valita_exports.literal("app"),
6823
6919
  // The user can return any additional data here
6920
+ message: valita_exports.string().optional(),
6824
6921
  details: jsonSchema.optional()
6825
6922
  });
6826
- var zeroErrorSchema2 = valita_exports.object({
6923
+ var zeroErrorSchema = valita_exports.object({
6827
6924
  error: valita_exports.union(
6828
6925
  /** @deprecated push oooMutation errors are now represented as ['error', { ... }] messages */
6829
6926
  valita_exports.literal("oooMutation"),
@@ -6835,7 +6932,7 @@ var mutationOkSchema = valita_exports.object({
6835
6932
  // The user can return any additional data here
6836
6933
  data: jsonSchema.optional()
6837
6934
  });
6838
- var mutationErrorSchema = valita_exports.union(appErrorSchema, zeroErrorSchema2);
6935
+ var mutationErrorSchema = valita_exports.union(appErrorSchema, zeroErrorSchema);
6839
6936
  var mutationResultSchema = valita_exports.union(
6840
6937
  mutationOkSchema,
6841
6938
  mutationErrorSchema
@@ -7055,7 +7152,7 @@ var downstreamSchema = valita_exports.union(
7055
7152
  );
7056
7153
 
7057
7154
  // ../zero-protocol/src/protocol-version.ts
7058
- var PROTOCOL_VERSION = 38;
7155
+ var PROTOCOL_VERSION = 39;
7059
7156
  var MIN_SERVER_SUPPORTED_SYNC_PROTOCOL = 18;
7060
7157
  assert(MIN_SERVER_SUPPORTED_SYNC_PROTOCOL < PROTOCOL_VERSION);
7061
7158
 
@@ -9647,32 +9744,40 @@ var PlannerFanIn = class {
9647
9744
  }
9648
9745
  }
9649
9746
  }
9650
- estimateCost(branchPattern) {
9747
+ estimateCost(downstreamChildSelectivity, branchPattern, planDebugger) {
9651
9748
  let totalCost = {
9652
- rows: 0,
9653
- runningCost: 0,
9749
+ returnedRows: 0,
9750
+ cost: 0,
9751
+ scanEst: 0,
9654
9752
  startupCost: 0,
9655
9753
  selectivity: 0,
9656
9754
  limit: void 0
9657
9755
  };
9658
- branchPattern = branchPattern ?? [];
9659
9756
  if (this.#type === "FI") {
9660
9757
  const updatedPattern = [0, ...branchPattern];
9661
9758
  let maxrows = 0;
9662
9759
  let maxRunningCost = 0;
9663
9760
  let maxStartupCost = 0;
9761
+ let maxScanEst = 0;
9664
9762
  let noMatchProb = 1;
9665
9763
  for (const input of this.#inputs) {
9666
- const cost = input.estimateCost(updatedPattern);
9667
- if (cost.rows > maxrows) {
9668
- maxrows = cost.rows;
9764
+ const cost = input.estimateCost(
9765
+ downstreamChildSelectivity,
9766
+ updatedPattern,
9767
+ planDebugger
9768
+ );
9769
+ if (cost.returnedRows > maxrows) {
9770
+ maxrows = cost.returnedRows;
9669
9771
  }
9670
- if (cost.runningCost > maxRunningCost) {
9671
- maxRunningCost = cost.runningCost;
9772
+ if (cost.cost > maxRunningCost) {
9773
+ maxRunningCost = cost.cost;
9672
9774
  }
9673
9775
  if (cost.startupCost > maxStartupCost) {
9674
9776
  maxStartupCost = cost.startupCost;
9675
9777
  }
9778
+ if (cost.scanEst > maxScanEst) {
9779
+ maxScanEst = cost.scanEst;
9780
+ }
9676
9781
  noMatchProb *= 1 - cost.selectivity;
9677
9782
  assert(
9678
9783
  totalCost.limit === void 0 || cost.limit === totalCost.limit,
@@ -9680,19 +9785,25 @@ var PlannerFanIn = class {
9680
9785
  );
9681
9786
  totalCost.limit = cost.limit;
9682
9787
  }
9683
- totalCost.rows = maxrows;
9684
- totalCost.runningCost = maxRunningCost;
9685
- totalCost.startupCost = maxStartupCost;
9788
+ totalCost.returnedRows = maxrows;
9789
+ totalCost.cost = maxRunningCost;
9686
9790
  totalCost.selectivity = 1 - noMatchProb;
9791
+ totalCost.startupCost = maxStartupCost;
9792
+ totalCost.scanEst = maxScanEst;
9687
9793
  } else {
9688
9794
  let i = 0;
9689
9795
  let noMatchProb = 1;
9690
9796
  for (const input of this.#inputs) {
9691
9797
  const updatedPattern = [i, ...branchPattern];
9692
- const cost = input.estimateCost(updatedPattern);
9693
- totalCost.rows += cost.rows;
9694
- totalCost.runningCost += cost.runningCost;
9695
- totalCost.startupCost += cost.startupCost;
9798
+ const cost = input.estimateCost(
9799
+ downstreamChildSelectivity,
9800
+ updatedPattern,
9801
+ planDebugger
9802
+ );
9803
+ totalCost.returnedRows += cost.returnedRows;
9804
+ totalCost.cost += cost.cost;
9805
+ totalCost.scanEst += cost.scanEst;
9806
+ totalCost.startupCost = totalCost.startupCost + cost.startupCost;
9696
9807
  noMatchProb *= 1 - cost.selectivity;
9697
9808
  assert(
9698
9809
  totalCost.limit === void 0 || cost.limit === totalCost.limit,
@@ -9703,19 +9814,45 @@ var PlannerFanIn = class {
9703
9814
  }
9704
9815
  totalCost.selectivity = 1 - noMatchProb;
9705
9816
  }
9817
+ planDebugger?.log({
9818
+ type: "node-cost",
9819
+ nodeType: "fan-in",
9820
+ node: this.#type,
9821
+ branchPattern,
9822
+ downstreamChildSelectivity,
9823
+ costEstimate: totalCost
9824
+ });
9706
9825
  return totalCost;
9707
9826
  }
9708
- propagateConstraints(branchPattern, constraint, from) {
9827
+ propagateConstraints(branchPattern, constraint, from, planDebugger) {
9828
+ planDebugger?.log({
9829
+ type: "node-constraint",
9830
+ nodeType: "fan-in",
9831
+ node: this.#type,
9832
+ branchPattern,
9833
+ constraint,
9834
+ from: from?.kind ?? "unknown"
9835
+ });
9709
9836
  if (this.#type === "FI") {
9710
9837
  const updatedPattern = [0, ...branchPattern];
9711
9838
  for (const input of this.#inputs) {
9712
- input.propagateConstraints(updatedPattern, constraint, from);
9839
+ input.propagateConstraints(
9840
+ updatedPattern,
9841
+ constraint,
9842
+ this,
9843
+ planDebugger
9844
+ );
9713
9845
  }
9714
9846
  return;
9715
9847
  }
9716
9848
  let i = 0;
9717
9849
  for (const input of this.#inputs) {
9718
- input.propagateConstraints([i, ...branchPattern], constraint, from);
9850
+ input.propagateConstraints(
9851
+ [i, ...branchPattern],
9852
+ constraint,
9853
+ this,
9854
+ planDebugger
9855
+ );
9719
9856
  i++;
9720
9857
  }
9721
9858
  }
@@ -9743,11 +9880,37 @@ var PlannerFanOut = class {
9743
9880
  closestJoinOrSource() {
9744
9881
  return this.#input.closestJoinOrSource();
9745
9882
  }
9746
- propagateConstraints(branchPattern, constraint, _from) {
9747
- this.#input.propagateConstraints(branchPattern, constraint, this);
9883
+ propagateConstraints(branchPattern, constraint, from, planDebugger) {
9884
+ planDebugger?.log({
9885
+ type: "node-constraint",
9886
+ nodeType: "fan-out",
9887
+ node: "FO",
9888
+ branchPattern,
9889
+ constraint,
9890
+ from: from?.kind ?? "unknown"
9891
+ });
9892
+ this.#input.propagateConstraints(
9893
+ branchPattern,
9894
+ constraint,
9895
+ this,
9896
+ planDebugger
9897
+ );
9748
9898
  }
9749
- estimateCost(branchPattern) {
9750
- return this.#input.estimateCost(branchPattern);
9899
+ estimateCost(downstreamChildSelectivity, branchPattern, planDebugger) {
9900
+ const ret = this.#input.estimateCost(
9901
+ downstreamChildSelectivity,
9902
+ branchPattern,
9903
+ planDebugger
9904
+ );
9905
+ planDebugger?.log({
9906
+ type: "node-cost",
9907
+ nodeType: "fan-out",
9908
+ node: "FO",
9909
+ branchPattern,
9910
+ downstreamChildSelectivity,
9911
+ costEstimate: ret
9912
+ });
9913
+ return ret;
9751
9914
  }
9752
9915
  convertToUFO() {
9753
9916
  this.#type = "UFO";
@@ -9810,19 +9973,14 @@ var PlannerConnection = class {
9810
9973
  * a single join in the UFO is flipped - other branches report undefined.
9811
9974
  */
9812
9975
  #constraints;
9813
- /**
9814
- * Cached total cost (sum of all branches) to avoid redundant calculations.
9815
- * Invalidated when constraints change.
9816
- */
9817
- #cachedTotalCost = void 0;
9976
+ #isRoot;
9818
9977
  /**
9819
9978
  * Cached per-constraint costs to avoid redundant cost model calls.
9820
9979
  * Maps constraint key (branch pattern string) to computed cost.
9821
9980
  * Invalidated when constraints change.
9822
9981
  */
9823
9982
  #cachedConstraintCosts = /* @__PURE__ */ new Map();
9824
- #costDirty = true;
9825
- constructor(table2, model, sort, filters, baseConstraints, limit, name) {
9983
+ constructor(table2, model, sort, filters, isRoot, baseConstraints, limit, name) {
9826
9984
  this.table = table2;
9827
9985
  this.name = name ?? table2;
9828
9986
  this.#sort = sort;
@@ -9832,6 +9990,7 @@ var PlannerConnection = class {
9832
9990
  this.#baseLimit = limit;
9833
9991
  this.limit = limit;
9834
9992
  this.#constraints = /* @__PURE__ */ new Map();
9993
+ this.#isRoot = isRoot;
9835
9994
  if (limit !== void 0 && filters) {
9836
9995
  const costWithFilters = model(table2, sort, filters, void 0);
9837
9996
  const costWithoutFilters = model(table2, sort, void 0, void 0);
@@ -9864,79 +10023,20 @@ var PlannerConnection = class {
9864
10023
  * The max of the last element of the paths is the number of
9865
10024
  * root branches.
9866
10025
  */
9867
- propagateConstraints(path, c) {
10026
+ propagateConstraints(path, c, from, planDebugger) {
9868
10027
  const key = path.join(",");
9869
10028
  this.#constraints.set(key, c);
9870
- this.#cachedTotalCost = void 0;
9871
10029
  this.#cachedConstraintCosts.clear();
9872
- this.#costDirty = true;
10030
+ planDebugger?.log({
10031
+ type: "node-constraint",
10032
+ nodeType: "connection",
10033
+ node: this.name,
10034
+ branchPattern: path,
10035
+ constraint: c,
10036
+ from: from?.kind ?? "unknown"
10037
+ });
9873
10038
  }
9874
- estimateCost(branchPattern) {
9875
- if (branchPattern === void 0) {
9876
- if (!this.#costDirty && this.#cachedTotalCost !== void 0) {
9877
- return this.#cachedTotalCost;
9878
- }
9879
- let totalRows = 0;
9880
- let maxStartupCost = 0;
9881
- if (this.#constraints.size === 0) {
9882
- const key2 = "";
9883
- let cost2 = this.#cachedConstraintCosts.get(key2);
9884
- if (cost2 === void 0) {
9885
- const { startupCost: startupCost2, rows: rows2 } = this.#model(
9886
- this.table,
9887
- this.#sort,
9888
- this.#filters,
9889
- this.#baseConstraints
9890
- );
9891
- cost2 = {
9892
- rows: rows2,
9893
- runningCost: rows2,
9894
- startupCost: startupCost2,
9895
- selectivity: this.selectivity,
9896
- limit: this.limit
9897
- };
9898
- this.#cachedConstraintCosts.set(key2, cost2);
9899
- }
9900
- totalRows = cost2.rows;
9901
- maxStartupCost = cost2.startupCost;
9902
- } else {
9903
- for (const [key2, constraint2] of this.#constraints.entries()) {
9904
- let cost2 = this.#cachedConstraintCosts.get(key2);
9905
- if (cost2 === void 0) {
9906
- const mergedConstraint2 = mergeConstraints(
9907
- this.#baseConstraints,
9908
- constraint2
9909
- );
9910
- const { startupCost: startupCost2, rows: rows2 } = this.#model(
9911
- this.table,
9912
- this.#sort,
9913
- this.#filters,
9914
- mergedConstraint2
9915
- );
9916
- cost2 = {
9917
- rows: rows2,
9918
- runningCost: rows2,
9919
- startupCost: startupCost2,
9920
- selectivity: this.selectivity,
9921
- limit: this.limit
9922
- };
9923
- this.#cachedConstraintCosts.set(key2, cost2);
9924
- }
9925
- totalRows += cost2.rows;
9926
- maxStartupCost = Math.max(maxStartupCost, cost2.startupCost);
9927
- }
9928
- }
9929
- const ret = {
9930
- rows: totalRows,
9931
- runningCost: totalRows,
9932
- startupCost: maxStartupCost,
9933
- selectivity: this.selectivity,
9934
- limit: this.limit
9935
- };
9936
- this.#cachedTotalCost = ret;
9937
- this.#costDirty = false;
9938
- return ret;
9939
- }
10039
+ estimateCost(downstreamChildSelectivity, branchPattern, planDebugger) {
9940
10040
  const key = branchPattern.join(",");
9941
10041
  let cost = this.#cachedConstraintCosts.get(key);
9942
10042
  if (cost !== void 0) {
@@ -9954,13 +10054,23 @@ var PlannerConnection = class {
9954
10054
  mergedConstraint
9955
10055
  );
9956
10056
  cost = {
9957
- rows,
9958
- runningCost: rows,
9959
10057
  startupCost,
10058
+ scanEst: this.limit === void 0 ? rows : Math.min(rows, this.limit / downstreamChildSelectivity),
10059
+ cost: 0,
10060
+ returnedRows: rows,
9960
10061
  selectivity: this.selectivity,
9961
10062
  limit: this.limit
9962
10063
  };
9963
10064
  this.#cachedConstraintCosts.set(key, cost);
10065
+ planDebugger?.log({
10066
+ type: "node-cost",
10067
+ nodeType: "connection",
10068
+ node: this.name,
10069
+ branchPattern,
10070
+ downstreamChildSelectivity,
10071
+ costEstimate: cost,
10072
+ filters: this.#filters
10073
+ });
9964
10074
  return cost;
9965
10075
  }
9966
10076
  /**
@@ -9969,6 +10079,9 @@ var PlannerConnection = class {
9969
10079
  * outer loop that should produce all rows rather than stopping at the limit.
9970
10080
  */
9971
10081
  unlimit() {
10082
+ if (this.#isRoot) {
10083
+ return;
10084
+ }
9972
10085
  if (this.limit !== void 0) {
9973
10086
  this.limit = void 0;
9974
10087
  }
@@ -9983,9 +10096,7 @@ var PlannerConnection = class {
9983
10096
  reset() {
9984
10097
  this.#constraints.clear();
9985
10098
  this.limit = this.#baseLimit;
9986
- this.#cachedTotalCost = void 0;
9987
10099
  this.#cachedConstraintCosts.clear();
9988
- this.#costDirty = true;
9989
10100
  }
9990
10101
  /**
9991
10102
  * Capture constraint state for snapshotting.
@@ -10003,9 +10114,7 @@ var PlannerConnection = class {
10003
10114
  for (const [key, value] of constraints) {
10004
10115
  this.#constraints.set(key, value);
10005
10116
  }
10006
- this.#cachedTotalCost = void 0;
10007
10117
  this.#cachedConstraintCosts.clear();
10008
- this.#costDirty = true;
10009
10118
  }
10010
10119
  /**
10011
10120
  * Get current constraints for debugging.
@@ -10014,13 +10123,19 @@ var PlannerConnection = class {
10014
10123
  getConstraintsForDebug() {
10015
10124
  return new Map(this.#constraints);
10016
10125
  }
10126
+ /**
10127
+ * Get filters for debugging.
10128
+ * Returns the filters applied to this connection.
10129
+ */
10130
+ getFiltersForDebug() {
10131
+ return this.#filters;
10132
+ }
10017
10133
  /**
10018
10134
  * Get estimated cost for each constraint branch.
10019
10135
  * Returns a map of constraint key to cost estimate.
10020
10136
  * Forces cost calculation if not already cached.
10021
10137
  */
10022
10138
  getConstraintCostsForDebug() {
10023
- this.estimateCost(void 0);
10024
10139
  return new Map(this.#cachedConstraintCosts);
10025
10140
  }
10026
10141
  };
@@ -10033,12 +10148,13 @@ var PlannerSource = class {
10033
10148
  this.name = name;
10034
10149
  this.#model = model;
10035
10150
  }
10036
- connect(sort, filters, baseConstraints, limit) {
10151
+ connect(sort, filters, isRoot, baseConstraints, limit) {
10037
10152
  return new PlannerConnection(
10038
10153
  this.name,
10039
10154
  this.#model,
10040
10155
  sort,
10041
10156
  filters,
10157
+ isRoot,
10042
10158
  baseConstraints,
10043
10159
  limit
10044
10160
  );
@@ -10107,20 +10223,20 @@ var PlannerGraph = class {
10107
10223
  * This sends constraints up through the graph to update
10108
10224
  * connection cost estimates.
10109
10225
  */
10110
- propagateConstraints() {
10226
+ propagateConstraints(planDebugger) {
10111
10227
  assert(
10112
10228
  this.#terminus !== void 0,
10113
10229
  "Cannot propagate constraints without a terminus node"
10114
10230
  );
10115
- this.#terminus.propagateConstraints();
10231
+ this.#terminus.propagateConstraints(planDebugger);
10116
10232
  }
10117
10233
  /**
10118
10234
  * Calculate total cost of the current plan.
10119
10235
  * Total cost includes both startup cost (one-time, e.g., sorting) and running cost.
10120
10236
  */
10121
- getTotalCost() {
10122
- const estimate = must(this.#terminus).estimateCost();
10123
- return estimate.startupCost + estimate.runningCost;
10237
+ getTotalCost(planDebugger) {
10238
+ const estimate = must(this.#terminus).estimateCost(planDebugger);
10239
+ return estimate.cost + estimate.startupCost;
10124
10240
  }
10125
10241
  /**
10126
10242
  * Capture a lightweight snapshot of the current planning state.
@@ -10157,41 +10273,6 @@ var PlannerGraph = class {
10157
10273
  this.#restoreJoins(state);
10158
10274
  this.#restoreFanNodes(state);
10159
10275
  }
10160
- /**
10161
- * Collect cost estimates from all nodes in the graph for debugging.
10162
- */
10163
- #collectNodeCosts() {
10164
- const costs = [];
10165
- for (const c of this.connections) {
10166
- costs.push({
10167
- node: c.name,
10168
- nodeType: "connection",
10169
- costEstimate: c.estimateCost(void 0)
10170
- });
10171
- }
10172
- for (const j of this.joins) {
10173
- costs.push({
10174
- node: j.getName(),
10175
- nodeType: "join",
10176
- costEstimate: j.estimateCost(void 0)
10177
- });
10178
- }
10179
- for (const fo of this.fanOuts) {
10180
- costs.push({
10181
- node: "FO",
10182
- nodeType: "fan-out",
10183
- costEstimate: fo.estimateCost(void 0)
10184
- });
10185
- }
10186
- for (const fi of this.fanIns) {
10187
- costs.push({
10188
- node: "FI",
10189
- nodeType: "fan-in",
10190
- costEstimate: fi.estimateCost(void 0)
10191
- });
10192
- }
10193
- return costs;
10194
- }
10195
10276
  /**
10196
10277
  * Validate that snapshot shape matches current graph structure.
10197
10278
  */
@@ -10282,7 +10363,11 @@ var PlannerGraph = class {
10282
10363
  let bestCost = Infinity;
10283
10364
  let bestPlan = void 0;
10284
10365
  let bestAttemptNumber = -1;
10366
+ const forcePattern = void 0;
10285
10367
  for (let pattern = 0; pattern < numPatterns; pattern++) {
10368
+ if (forcePattern !== void 0 && pattern !== forcePattern) {
10369
+ continue;
10370
+ }
10286
10371
  this.resetPlanningState();
10287
10372
  if (planDebugger) {
10288
10373
  planDebugger.log({
@@ -10299,7 +10384,7 @@ var PlannerGraph = class {
10299
10384
  }
10300
10385
  checkAndConvertFOFI(fofiCache);
10301
10386
  propagateUnlimitForFlippedJoins(this);
10302
- this.propagateConstraints();
10387
+ this.propagateConstraints(planDebugger);
10303
10388
  if (planDebugger) {
10304
10389
  planDebugger.log({
10305
10390
  type: "constraints-propagated",
@@ -10311,13 +10396,16 @@ var PlannerGraph = class {
10311
10396
  }))
10312
10397
  });
10313
10398
  }
10314
- const totalCost = this.getTotalCost();
10399
+ const totalCost = this.getTotalCost(planDebugger);
10315
10400
  if (planDebugger) {
10316
10401
  planDebugger.log({
10317
10402
  type: "plan-complete",
10318
10403
  attemptNumber: pattern,
10319
10404
  totalCost,
10320
- nodeCosts: this.#collectNodeCosts(),
10405
+ flipPattern: pattern,
10406
+ // Bitmask of which joins are flipped
10407
+ // TODO: we'll need a different way to collect these
10408
+ // nodeCosts: this.#collectNodeCosts(),
10321
10409
  joinStates: this.joins.map((j) => {
10322
10410
  const info = j.getDebugInfo();
10323
10411
  return {
@@ -10345,12 +10433,14 @@ var PlannerGraph = class {
10345
10433
  }
10346
10434
  if (bestPlan) {
10347
10435
  this.restorePlanningSnapshot(bestPlan);
10348
- this.propagateConstraints();
10436
+ this.propagateConstraints(planDebugger);
10349
10437
  if (planDebugger) {
10350
10438
  planDebugger.log({
10351
10439
  type: "best-plan-selected",
10352
10440
  bestAttemptNumber,
10353
10441
  totalCost: bestCost,
10442
+ flipPattern: bestAttemptNumber,
10443
+ // The best attempt number is also the flip pattern
10354
10444
  joinStates: this.joins.map((j) => ({
10355
10445
  join: j.getName(),
10356
10446
  type: j.type
@@ -10418,7 +10508,19 @@ function propagateUnlimitForFlippedJoins(graph) {
10418
10508
  }
10419
10509
 
10420
10510
  // ../zql/src/planner/planner-join.ts
10421
- var SEMI_JOIN_OVERHEAD_MULTIPLIER = 1.5;
10511
+ function translateConstraintsForFlippedJoin(incomingConstraint, parentConstraint, childConstraint) {
10512
+ if (!incomingConstraint) return void 0;
10513
+ const parentKeys = Object.keys(parentConstraint);
10514
+ const childKeys = Object.keys(childConstraint);
10515
+ const translated = {};
10516
+ for (const [key, value] of Object.entries(incomingConstraint)) {
10517
+ const index = parentKeys.indexOf(key);
10518
+ if (index !== -1) {
10519
+ translated[childKeys[index]] = value;
10520
+ }
10521
+ }
10522
+ return Object.keys(translated).length > 0 ? translated : void 0;
10523
+ }
10422
10524
  var PlannerJoin = class {
10423
10525
  kind = "join";
10424
10526
  #parent;
@@ -10476,9 +10578,13 @@ var PlannerJoin = class {
10476
10578
  return this.#flippable;
10477
10579
  }
10478
10580
  /**
10479
- * Propagate unlimiting through the child subgraph when this join is flipped.
10480
- * When a join is flipped, the child becomes the outer loop and should produce
10481
- * all rows rather than stopping at an EXISTS limit.
10581
+ * Propagate unlimiting when this join is flipped.
10582
+ * When a join is flipped:
10583
+ * 1. Child becomes outer loop produces all rows (unlimited)
10584
+ * 2. Parent is fetched once per child row → effectively unlimited
10585
+ *
10586
+ * Example: If child produces 896 rows, parent is fetched 896 times.
10587
+ * Even if each fetch returns 1 row, parent produces 896 total rows.
10482
10588
  *
10483
10589
  * Propagation rules:
10484
10590
  * - Connection: call unlimit()
@@ -10488,7 +10594,8 @@ var PlannerJoin = class {
10488
10594
  */
10489
10595
  propagateUnlimit() {
10490
10596
  assert(this.#type === "flipped", "Can only unlimit a flipped join");
10491
- propagateUnlimitToNode(this.#child);
10597
+ this.#parent.propagateUnlimitFromFlippedJoin();
10598
+ this.#child.propagateUnlimitFromFlippedJoin();
10492
10599
  }
10493
10600
  /**
10494
10601
  * Called when a parent join is flipped and this join is part of its child subgraph.
@@ -10497,56 +10604,99 @@ var PlannerJoin = class {
10497
10604
  */
10498
10605
  propagateUnlimitFromFlippedJoin() {
10499
10606
  if (this.#type === "semi") {
10500
- propagateUnlimitToNode(this.#parent);
10607
+ this.#parent.propagateUnlimitFromFlippedJoin();
10501
10608
  }
10502
10609
  }
10503
- propagateConstraints(branchPattern, constraint) {
10610
+ propagateConstraints(branchPattern, constraint, from, planDebugger) {
10611
+ planDebugger?.log({
10612
+ type: "node-constraint",
10613
+ nodeType: "join",
10614
+ node: this.getName(),
10615
+ branchPattern,
10616
+ constraint,
10617
+ from: from ? getNodeName(from) : "unknown"
10618
+ });
10504
10619
  if (this.#type === "semi") {
10505
10620
  this.#child.propagateConstraints(
10506
10621
  branchPattern,
10507
10622
  this.#childConstraint,
10508
- this
10623
+ this,
10624
+ planDebugger
10625
+ );
10626
+ this.#parent.propagateConstraints(
10627
+ branchPattern,
10628
+ constraint,
10629
+ this,
10630
+ planDebugger
10509
10631
  );
10510
- this.#parent.propagateConstraints(branchPattern, constraint, this);
10511
10632
  } else if (this.#type === "flipped") {
10512
- this.#child.propagateConstraints(branchPattern, void 0, this);
10633
+ const translatedConstraint = translateConstraintsForFlippedJoin(
10634
+ constraint,
10635
+ this.#parentConstraint,
10636
+ this.#childConstraint
10637
+ );
10638
+ this.#child.propagateConstraints(
10639
+ branchPattern,
10640
+ translatedConstraint,
10641
+ this,
10642
+ planDebugger
10643
+ );
10513
10644
  this.#parent.propagateConstraints(
10514
10645
  branchPattern,
10515
10646
  mergeConstraints(constraint, this.#parentConstraint),
10516
- this
10647
+ this,
10648
+ planDebugger
10517
10649
  );
10518
10650
  }
10519
10651
  }
10520
10652
  reset() {
10521
10653
  this.#type = "semi";
10522
10654
  }
10523
- estimateCost(branchPattern) {
10524
- const parentCost = this.#parent.estimateCost(branchPattern);
10525
- const childCost = this.#child.estimateCost(branchPattern);
10526
- let scanEst = parentCost.rows;
10527
- if (this.#type === "semi" && parentCost.limit !== void 0) {
10528
- if (childCost.selectivity !== 0) {
10529
- scanEst = Math.min(scanEst, parentCost.limit / childCost.selectivity);
10530
- }
10531
- }
10532
- if (this.#parent.closestJoinOrSource() === "join") {
10533
- const pipelineCost = this.#type === "flipped" ? childCost.startupCost + childCost.runningCost * (parentCost.startupCost + parentCost.runningCost) : parentCost.runningCost + SEMI_JOIN_OVERHEAD_MULTIPLIER * scanEst * (childCost.startupCost + childCost.runningCost);
10534
- return {
10535
- rows: parentCost.rows,
10536
- runningCost: pipelineCost,
10537
- startupCost: parentCost.startupCost,
10538
- selectivity: parentCost.selectivity,
10539
- limit: parentCost.limit
10655
+ estimateCost(downstreamChildSelectivity, branchPattern, planDebugger) {
10656
+ const child = this.#child.estimateCost(1, branchPattern, planDebugger);
10657
+ const parent = this.#parent.estimateCost(
10658
+ // Selectivity flows up the graph from child to parent
10659
+ // so we can determine the total selectivity of all ANDed exists checks.
10660
+ child.selectivity * downstreamChildSelectivity,
10661
+ branchPattern,
10662
+ planDebugger
10663
+ );
10664
+ let costEstimate;
10665
+ if (this.type === "semi") {
10666
+ costEstimate = {
10667
+ startupCost: parent.startupCost,
10668
+ scanEst: parent.limit === void 0 ? parent.returnedRows : Math.min(
10669
+ parent.returnedRows,
10670
+ parent.limit / downstreamChildSelectivity
10671
+ ),
10672
+ cost: parent.cost + parent.scanEst * (child.startupCost + child.scanEst),
10673
+ returnedRows: parent.returnedRows * child.selectivity,
10674
+ selectivity: child.selectivity * parent.selectivity,
10675
+ limit: parent.limit
10676
+ };
10677
+ } else {
10678
+ costEstimate = {
10679
+ startupCost: child.startupCost,
10680
+ scanEst: parent.limit === void 0 ? parent.returnedRows : Math.min(
10681
+ parent.returnedRows * child.returnedRows,
10682
+ parent.limit / downstreamChildSelectivity
10683
+ ),
10684
+ cost: child.cost + child.scanEst * (parent.startupCost + parent.scanEst),
10685
+ returnedRows: parent.returnedRows * child.returnedRows * child.selectivity,
10686
+ selectivity: parent.selectivity * child.selectivity,
10687
+ limit: parent.limit
10540
10688
  };
10541
10689
  }
10542
- const nestedLoopCost = this.#type === "flipped" ? childCost.runningCost * (parentCost.startupCost + parentCost.runningCost) : SEMI_JOIN_OVERHEAD_MULTIPLIER * scanEst * (childCost.startupCost + childCost.runningCost);
10543
- return {
10544
- rows: parentCost.rows,
10545
- runningCost: nestedLoopCost,
10546
- startupCost: parentCost.startupCost,
10547
- selectivity: parentCost.selectivity,
10548
- limit: parentCost.limit
10549
- };
10690
+ planDebugger?.log({
10691
+ type: "node-cost",
10692
+ nodeType: "join",
10693
+ node: this.getName(),
10694
+ branchPattern,
10695
+ downstreamChildSelectivity,
10696
+ costEstimate,
10697
+ joinType: this.#type
10698
+ });
10699
+ return costEstimate;
10550
10700
  }
10551
10701
  /**
10552
10702
  * Get a human-readable name for this join for debugging.
@@ -10588,11 +10738,6 @@ function getNodeName(node) {
10588
10738
  return "terminus";
10589
10739
  }
10590
10740
  }
10591
- function propagateUnlimitToNode(node) {
10592
- if ("propagateUnlimitFromFlippedJoin" in node && typeof node.propagateUnlimitFromFlippedJoin === "function") {
10593
- node.propagateUnlimitFromFlippedJoin();
10594
- }
10595
- }
10596
10741
 
10597
10742
  // ../zql/src/planner/planner-terminus.ts
10598
10743
  var PlannerTerminus = class {
@@ -10607,11 +10752,11 @@ var PlannerTerminus = class {
10607
10752
  closestJoinOrSource() {
10608
10753
  return this.#input.closestJoinOrSource();
10609
10754
  }
10610
- propagateConstraints() {
10611
- this.#input.propagateConstraints([], void 0, this);
10755
+ propagateConstraints(planDebugger) {
10756
+ this.#input.propagateConstraints([], void 0, this, planDebugger);
10612
10757
  }
10613
- estimateCost() {
10614
- return this.#input.estimateCost([]);
10758
+ estimateCost(planDebugger) {
10759
+ return this.#input.estimateCost(1, [], planDebugger);
10615
10760
  }
10616
10761
  /**
10617
10762
  * Propagate unlimiting when a parent join is flipped.
@@ -10636,13 +10781,14 @@ function wireOutput(from, to) {
10636
10781
  assert(false, "Terminus nodes cannot have outputs");
10637
10782
  }
10638
10783
  }
10639
- function buildPlanGraph(ast, model, baseConstraints) {
10784
+ function buildPlanGraph(ast, model, isRoot, baseConstraints) {
10640
10785
  const graph = new PlannerGraph();
10641
10786
  let nextPlanId = 0;
10642
10787
  const source = graph.addSource(ast.table, model);
10643
10788
  const connection = source.connect(
10644
10789
  ast.orderBy ?? [],
10645
10790
  ast.where,
10791
+ isRoot,
10646
10792
  baseConstraints,
10647
10793
  ast.limit
10648
10794
  );
@@ -10672,7 +10818,12 @@ function buildPlanGraph(ast, model, baseConstraints) {
10672
10818
  csq.correlation.childField,
10673
10819
  csq.subquery.table
10674
10820
  );
10675
- subPlans[alias] = buildPlanGraph(csq.subquery, model, childConstraints);
10821
+ subPlans[alias] = buildPlanGraph(
10822
+ csq.subquery,
10823
+ model,
10824
+ true,
10825
+ childConstraints
10826
+ );
10676
10827
  }
10677
10828
  }
10678
10829
  return { plan: graph, subPlans };
@@ -10747,6 +10898,7 @@ function processCorrelatedSubquery(condition, input, graph, model, parentTable,
10747
10898
  const childConnection = childSource.connect(
10748
10899
  related.subquery.orderBy ?? [],
10749
10900
  related.subquery.where,
10901
+ false,
10750
10902
  void 0,
10751
10903
  // no base constraints for EXISTS/NOT EXISTS
10752
10904
  condition.op === "EXISTS" ? 1 : void 0
@@ -10805,7 +10957,7 @@ function planRecursively(plans, planDebugger) {
10805
10957
  plans.plan.plan(planDebugger);
10806
10958
  }
10807
10959
  function planQuery(ast, model, planDebugger) {
10808
- const plans = buildPlanGraph(ast, model);
10960
+ const plans = buildPlanGraph(ast, model, true);
10809
10961
  planRecursively(plans, planDebugger);
10810
10962
  return applyPlansToAST(ast, plans);
10811
10963
  }
@@ -12690,6 +12842,7 @@ var Subscribable = class {
12690
12842
  // ../zero-client/src/client/connection-manager.ts
12691
12843
  var DEFAULT_TIMEOUT_CHECK_INTERVAL_MS = 1e3;
12692
12844
  var TERMINAL_STATES = [
12845
+ connection_status_enum_exports.NeedsAuth,
12693
12846
  connection_status_enum_exports.Error
12694
12847
  ];
12695
12848
  var ConnectionManager = class _ConnectionManager extends Subscribable {
@@ -12758,8 +12911,8 @@ var ConnectionManager = class _ConnectionManager extends Subscribable {
12758
12911
  }
12759
12912
  /**
12760
12913
  * Returns true if the run loop should continue.
12761
- * The run loop continues in disconnected, connecting, connected, and error states.
12762
- * It stops in closed state.
12914
+ * The run loop continues in all states except closed.
12915
+ * In needs-auth and error states, the run loop pauses and waits for connect() to be called.
12763
12916
  */
12764
12917
  shouldContinueRunLoop() {
12765
12918
  return this.#state.name !== connection_status_enum_exports.Closed;
@@ -12858,10 +13011,33 @@ var ConnectionManager = class _ConnectionManager extends Subscribable {
12858
13011
  const nextStatePromise = this.#publishStateAndGetPromise();
12859
13012
  return { nextStatePromise };
12860
13013
  }
13014
+ /**
13015
+ * Transition to needs-auth state.
13016
+ * This pauses the run loop until connect() is called with new credentials.
13017
+ * Resets the retry window and attempt counter.
13018
+ *
13019
+ * @returns An object containing a promise that resolves on the next state change.
13020
+ */
13021
+ needsAuth(reason) {
13022
+ if (this.#state.name === connection_status_enum_exports.Closed) {
13023
+ return { nextStatePromise: this.#nextStatePromise() };
13024
+ }
13025
+ if (this.#state.name === connection_status_enum_exports.NeedsAuth) {
13026
+ return { nextStatePromise: this.#nextStatePromise() };
13027
+ }
13028
+ this.#connectingStartedAt = void 0;
13029
+ this.#maybeStopTimeoutInterval();
13030
+ this.#state = {
13031
+ name: connection_status_enum_exports.NeedsAuth,
13032
+ reason
13033
+ };
13034
+ const nextStatePromise = this.#publishStateAndGetPromise();
13035
+ return { nextStatePromise };
13036
+ }
12861
13037
  /**
12862
13038
  * Transition to error state.
12863
13039
  * This pauses the run loop until connect() is called.
12864
- * Resets the 5-minute retry window and attempt counter.
13040
+ * Resets the retry window and attempt counter.
12865
13041
  *
12866
13042
  * @returns An object containing a promise that resolves on the next state change.
12867
13043
  */
@@ -12971,16 +13147,22 @@ var ConnectionImpl = class {
12971
13147
  #connectionManager;
12972
13148
  #lc;
12973
13149
  #source;
12974
- constructor(connectionManager, lc) {
13150
+ #setAuth;
13151
+ constructor(connectionManager, lc, setAuth) {
12975
13152
  this.#connectionManager = connectionManager;
12976
13153
  this.#lc = lc;
12977
13154
  this.#source = new ConnectionSource(connectionManager);
13155
+ this.#setAuth = setAuth;
12978
13156
  }
12979
13157
  get state() {
12980
13158
  return this.#source;
12981
13159
  }
12982
- async connect() {
13160
+ async connect(opts) {
12983
13161
  const lc = this.#lc.withContext("connect");
13162
+ if (opts && "auth" in opts) {
13163
+ lc.debug?.("Updating auth credential from connect()");
13164
+ this.#setAuth(opts.auth);
13165
+ }
12984
13166
  if (!this.#connectionManager.isInTerminalState()) {
12985
13167
  lc.debug?.(
12986
13168
  "connect() called but not in a terminal state. Current state:",
@@ -14948,7 +15130,7 @@ function makeMessage(message, context, logLevel) {
14948
15130
  }
14949
15131
 
14950
15132
  // ../zero-client/src/client/version.ts
14951
- var version2 = "0.25.0-canary.1";
15133
+ var version2 = "0.25.0";
14952
15134
 
14953
15135
  // ../zero-client/src/client/log-options.ts
14954
15136
  var LevelFilterLogSink = class {
@@ -15328,7 +15510,7 @@ var MutationTracker = class {
15328
15510
  rejectMutation(id, e) {
15329
15511
  const entry = this.#outstandingMutations.get(id);
15330
15512
  if (entry) {
15331
- this.#settleMutation(id, entry, "reject", e);
15513
+ this.#settleMutation(id, entry, "reject", wrapWithApplicationError(e));
15332
15514
  }
15333
15515
  }
15334
15516
  /**
@@ -15514,7 +15696,17 @@ var MutationTracker = class {
15514
15696
  );
15515
15697
  const entry = this.#outstandingMutations.get(ephemeralID);
15516
15698
  assert(entry && entry.mutationID === mid);
15517
- this.#settleMutation(ephemeralID, entry, "reject", error);
15699
+ this.#settleMutation(
15700
+ ephemeralID,
15701
+ entry,
15702
+ "reject",
15703
+ error.error === "app" ? new ApplicationError(
15704
+ error.message ?? `Unknown application error: ${error.error}`,
15705
+ error.details ? { details: error.details } : void 0
15706
+ ) : new Error(
15707
+ error.error === "alreadyProcessed" ? "Mutation already processed" : error.error === "oooMutation" ? "Server reported an out-of-order mutation" : `Unknown fallback error with mutation ID ${mid}: ${error.error}`
15708
+ )
15709
+ );
15518
15710
  if (error.error === "oooMutation") {
15519
15711
  this.#onFatalError(
15520
15712
  new ProtocolError({
@@ -15709,27 +15901,20 @@ var QueryManager = class {
15709
15901
  for (const error of errors) {
15710
15902
  const queryId = error.id;
15711
15903
  const entry = this.#queries.get(queryId);
15712
- if (entry) {
15713
- entry.gotCallbacks.forEach((callback) => callback(false, error));
15904
+ if (!entry) {
15905
+ continue;
15714
15906
  }
15715
- if (error.error !== "app") {
15907
+ if (error.error === "app" || error.error === "parse") {
15908
+ entry.gotCallbacks.forEach((callback) => callback(false, error));
15909
+ } else {
15716
15910
  this.#onFatalError(
15717
- new ProtocolError(
15718
- error.error === "http" ? {
15719
- kind: error_kind_enum_exports.TransformFailed,
15720
- origin: error_origin_enum_exports.ZeroCache,
15721
- reason: error_reason_enum_exports.HTTP,
15722
- message: `HTTP ${error.status} transforming queries`,
15723
- status: error.status,
15724
- queryIDs: []
15725
- } : {
15726
- kind: error_kind_enum_exports.TransformFailed,
15727
- origin: error_origin_enum_exports.ZeroCache,
15728
- reason: error_reason_enum_exports.Internal,
15729
- message: `Unknown error transforming queries`,
15730
- queryIDs: []
15731
- }
15732
- )
15911
+ new ProtocolError({
15912
+ kind: error_kind_enum_exports.TransformFailed,
15913
+ origin: error_origin_enum_exports.ZeroCache,
15914
+ reason: error_reason_enum_exports.Internal,
15915
+ message: `Unknown error transforming queries: ${JSON.stringify(error)}`,
15916
+ queryIDs: []
15917
+ })
15733
15918
  );
15734
15919
  }
15735
15920
  }
@@ -16391,13 +16576,17 @@ function rafFallback(callback) {
16391
16576
  }
16392
16577
 
16393
16578
  // ../zero-client/src/client/zero-rep.ts
16579
+ var REPLICACHE_NO_AUTH_TOKEN = "";
16580
+ var toReplicacheAuthToken = (auth) => auth ?? REPLICACHE_NO_AUTH_TOKEN;
16581
+ var fromReplicacheAuthToken = (auth) => !auth ? void 0 : auth;
16394
16582
  var ZeroRep = class {
16395
16583
  #context;
16396
16584
  #ivmMain;
16397
16585
  #customMutatorsEnabled;
16398
16586
  #mutationTracker;
16399
16587
  #store;
16400
- #auth;
16588
+ // matches replicache's auth token type
16589
+ #auth = REPLICACHE_NO_AUTH_TOKEN;
16401
16590
  constructor(context, ivmMain, customMutatorsEnabled, mutationTracker) {
16402
16591
  this.#context = context;
16403
16592
  this.#ivmMain = ivmMain;
@@ -16405,11 +16594,7 @@ var ZeroRep = class {
16405
16594
  this.#mutationTracker = mutationTracker;
16406
16595
  }
16407
16596
  set auth(auth) {
16408
- if (auth === "") {
16409
- this.#auth = void 0;
16410
- } else {
16411
- this.#auth = auth;
16412
- }
16597
+ this.#auth = auth;
16413
16598
  }
16414
16599
  async init(hash, store) {
16415
16600
  const diffs = [];
@@ -16435,7 +16620,7 @@ var ZeroRep = class {
16435
16620
  }
16436
16621
  return this.#ivmMain.forkToHead(must(this.#store), desiredHead, readOptions).then((branch) => ({
16437
16622
  ivmSources: branch,
16438
- token: this.#auth
16623
+ token: fromReplicacheAuthToken(this.#auth)
16439
16624
  }));
16440
16625
  };
16441
16626
  advance = (expectedHash, newHash, diffs) => {
@@ -16561,6 +16746,7 @@ var Zero = class _Zero {
16561
16746
  #visibilityWatcher;
16562
16747
  #connectionManager;
16563
16748
  #connection;
16749
+ #unsubscribeConnectionState = void 0;
16564
16750
  #activeClientsManager;
16565
16751
  #inspector;
16566
16752
  #connectStart = void 0;
@@ -16637,6 +16823,11 @@ var Zero = class _Zero {
16637
16823
  this.#connectionManager = new ConnectionManager({
16638
16824
  disconnectTimeoutMs: DEFAULT_DISCONNECT_TIMEOUT_MS
16639
16825
  });
16826
+ const syncOnlineState = (state) => {
16827
+ this.#onlineManager.setOnline(state.name === connection_status_enum_exports.Connected);
16828
+ };
16829
+ syncOnlineState(this.#connectionManager.state);
16830
+ this.#unsubscribeConnectionState = this.#connectionManager.subscribe(syncOnlineState);
16640
16831
  const { enableLegacyMutators = true, enableLegacyQueries = true } = schema;
16641
16832
  const replicacheMutators = {
16642
16833
  [CRUD_MUTATION_NAME]: enableLegacyMutators ? makeCRUDMutator(schema) : () => Promise.reject(
@@ -16779,7 +16970,11 @@ var Zero = class _Zero {
16779
16970
  this.#server = server;
16780
16971
  this.userID = userID;
16781
16972
  this.#lc = lc.withContext("clientID", rep.clientID);
16782
- this.#connection = new ConnectionImpl(this.#connectionManager, this.#lc);
16973
+ this.#connection = new ConnectionImpl(
16974
+ this.#connectionManager,
16975
+ this.#lc,
16976
+ (auth) => this.#setAuth(auth)
16977
+ );
16783
16978
  this.#mutationTracker.setClientIDAndWatch(
16784
16979
  rep.clientID,
16785
16980
  rep.experimentalWatch.bind(rep)
@@ -17086,6 +17281,8 @@ var Zero = class _Zero {
17086
17281
  return;
17087
17282
  }
17088
17283
  lc.debug?.("Closing Zero instance. Stack:", new Error().stack);
17284
+ this.#unsubscribeConnectionState?.();
17285
+ this.#unsubscribeConnectionState = void 0;
17089
17286
  this.#onlineManager.cleanup();
17090
17287
  if (!this.#connectionManager.is(connection_status_enum_exports.Disconnected)) {
17091
17288
  this.#disconnect(
@@ -17346,15 +17543,19 @@ ${error.errorBody.message}`, error);
17346
17543
  * attempt times out.
17347
17544
  */
17348
17545
  async #connect(lc, additionalConnectParams) {
17349
- assert(this.#server);
17546
+ if (this.closed) {
17547
+ return;
17548
+ }
17549
+ assert(this.#server, "No server provided");
17350
17550
  assert(
17351
- this.#connectionManager.is(connection_status_enum_exports.Disconnected) || this.#connectionManager.is(connection_status_enum_exports.Connecting)
17551
+ this.#connectionManager.is(connection_status_enum_exports.Disconnected) || this.#connectionManager.is(connection_status_enum_exports.Connecting),
17552
+ "connect() called from invalid state: " + this.#connectionManager.state.name
17352
17553
  );
17353
17554
  const wsid = nanoid();
17354
17555
  lc = addWebSocketIDToLogContext(wsid, lc);
17355
17556
  lc.info?.("Connecting...", { navigatorOnline: localNavigator?.onLine });
17356
17557
  this.#connectionManager.connecting();
17357
- assert(this.#connectStart === void 0);
17558
+ assert(this.#connectStart === void 0, "connect start time is defined");
17358
17559
  const now = Date.now();
17359
17560
  this.#connectStart = now;
17360
17561
  if (this.#totalToConnectStart === void 0) {
@@ -17394,7 +17595,7 @@ ${error.errorBody.message}`, error);
17394
17595
  await this.clientGroupID,
17395
17596
  this.#clientSchema,
17396
17597
  this.userID,
17397
- this.#rep.auth,
17598
+ fromReplicacheAuthToken(this.#rep.auth),
17398
17599
  this.#lastMutationIDReceived,
17399
17600
  wsid,
17400
17601
  this.#options.logLevel === "debug",
@@ -17465,6 +17666,7 @@ ${error.errorBody.message}`, error);
17465
17666
  return;
17466
17667
  case connection_status_enum_exports.Disconnected:
17467
17668
  case connection_status_enum_exports.Connecting:
17669
+ case connection_status_enum_exports.NeedsAuth:
17468
17670
  case connection_status_enum_exports.Error:
17469
17671
  break;
17470
17672
  default:
@@ -17485,6 +17687,9 @@ ${error.errorBody.message}`, error);
17485
17687
  this.#pokeHandler.handleDisconnect();
17486
17688
  const transition = getErrorConnectionTransition(reason);
17487
17689
  switch (transition.status) {
17690
+ case connection_status_enum_exports.NeedsAuth:
17691
+ this.#connectionManager.needsAuth(transition.reason);
17692
+ break;
17488
17693
  case connection_status_enum_exports.Error:
17489
17694
  this.#connectionManager.error(transition.reason);
17490
17695
  break;
@@ -17605,14 +17810,6 @@ ${error.errorBody.message}`, error);
17605
17810
  }
17606
17811
  };
17607
17812
  }
17608
- async #updateAuthToken(lc, error) {
17609
- const { auth: authOption } = this.#options;
17610
- const auth = await (typeof authOption === "function" ? authOption(error) : authOption);
17611
- if (auth) {
17612
- lc.debug?.("Got auth token");
17613
- this.#rep.auth = auth;
17614
- }
17615
- }
17616
17813
  async #runLoop() {
17617
17814
  this.#lc.info?.(`Starting Zero version: ${this.version}`);
17618
17815
  if (this.#server === null) {
@@ -17634,9 +17831,8 @@ ${error.errorBody.message}`, error);
17634
17831
  }
17635
17832
  return lc.withContext("runLoopCounter", runLoopCounter);
17636
17833
  };
17637
- await this.#updateAuthToken(bareLogContext);
17638
- let needsReauth = false;
17639
- let lastReauthAttemptAt;
17834
+ const { auth } = this.#options;
17835
+ this.#setAuth(auth);
17640
17836
  let backoffMs;
17641
17837
  let additionalConnectParams;
17642
17838
  while (this.#connectionManager.shouldContinueRunLoop()) {
@@ -17660,10 +17856,6 @@ ${error.errorBody.message}`, error);
17660
17856
  throwIfConnectionError(visibilityResult.result);
17661
17857
  break;
17662
17858
  }
17663
- if (needsReauth) {
17664
- lastReauthAttemptAt = Date.now();
17665
- await this.#updateAuthToken(lc, "invalid-token");
17666
- }
17667
17859
  if (reloadScheduled()) {
17668
17860
  break;
17669
17861
  }
@@ -17673,8 +17865,6 @@ ${error.errorBody.message}`, error);
17673
17865
  assert(this.#socket);
17674
17866
  lc = getLogContext();
17675
17867
  lc.debug?.("Connected successfully");
17676
- needsReauth = false;
17677
- this.#setOnline(true);
17678
17868
  break;
17679
17869
  }
17680
17870
  case connection_status_enum_exports.Connected: {
@@ -17703,7 +17893,6 @@ ${error.errorBody.message}`, error);
17703
17893
  message: "Connection closed because tab was hidden"
17704
17894
  });
17705
17895
  this.#disconnect(lc, hiddenError);
17706
- this.#setOnline(false);
17707
17896
  break;
17708
17897
  }
17709
17898
  case "stateChange":
@@ -17714,6 +17903,14 @@ ${error.errorBody.message}`, error);
17714
17903
  }
17715
17904
  break;
17716
17905
  }
17906
+ case connection_status_enum_exports.NeedsAuth: {
17907
+ lc.info?.(
17908
+ `Run loop paused in needs-auth state. Call zero.connection.connect({auth}) to resume.`,
17909
+ currentState.reason
17910
+ );
17911
+ await this.#connectionManager.waitForStateChange();
17912
+ break;
17913
+ }
17717
17914
  case connection_status_enum_exports.Error: {
17718
17915
  lc.info?.(
17719
17916
  `Run loop paused in error state. Call zero.connection.connect() to resume.`,
@@ -17757,15 +17954,6 @@ ${error.errorBody.message}`, error);
17757
17954
  }
17758
17955
  additionalConnectParams = backoffParams.reconnectParams;
17759
17956
  }
17760
- if (isAuthError(transition.reason)) {
17761
- const now = Date.now();
17762
- const msSinceLastReauthAttempt = lastReauthAttemptAt === void 0 ? Number.POSITIVE_INFINITY : now - lastReauthAttemptAt;
17763
- needsReauth = true;
17764
- if (msSinceLastReauthAttempt > RUN_LOOP_INTERVAL_MS) {
17765
- continue;
17766
- }
17767
- }
17768
- this.#setOnline(false);
17769
17957
  lc.debug?.(
17770
17958
  "Sleeping",
17771
17959
  backoffMs,
@@ -17775,19 +17963,23 @@ ${error.errorBody.message}`, error);
17775
17963
  await sleep(backoffMs);
17776
17964
  break;
17777
17965
  }
17966
+ case connection_status_enum_exports.NeedsAuth: {
17967
+ lc.debug?.(
17968
+ "Auth error encountered, transitioning to needs-auth state"
17969
+ );
17970
+ this.#connectionManager.needsAuth(transition.reason);
17971
+ break;
17972
+ }
17778
17973
  case connection_status_enum_exports.Error: {
17779
17974
  lc.debug?.("Fatal error encountered, transitioning to error state");
17780
- this.#setOnline(false);
17781
17975
  this.#connectionManager.error(transition.reason);
17782
17976
  break;
17783
17977
  }
17784
17978
  case connection_status_enum_exports.Disconnected: {
17785
- this.#setOnline(false);
17786
17979
  this.#connectionManager.disconnected(transition.reason);
17787
17980
  break;
17788
17981
  }
17789
17982
  case connection_status_enum_exports.Closed: {
17790
- this.#setOnline(false);
17791
17983
  break;
17792
17984
  }
17793
17985
  default:
@@ -17868,8 +18060,13 @@ ${error.errorBody.message}`, error);
17868
18060
  this.#pendingPullsByRequestID.delete(requestID);
17869
18061
  }
17870
18062
  }
17871
- #setOnline(online) {
17872
- this.#onlineManager.setOnline(online);
18063
+ /**
18064
+ * Sets the authentication token on the replicache instance.
18065
+ *
18066
+ * @param auth - The authentication token to set.
18067
+ */
18068
+ #setAuth(auth) {
18069
+ this.#rep.auth = toReplicacheAuthToken(auth);
17873
18070
  }
17874
18071
  /**
17875
18072
  * A rough heuristic for whether the client is currently online and
@@ -18110,6 +18307,7 @@ export {
18110
18307
  dropDatabase,
18111
18308
  dropAllDatabases,
18112
18309
  TransactionClosedError,
18310
+ ApplicationError,
18113
18311
  error_kind_enum_exports,
18114
18312
  error_origin_enum_exports,
18115
18313
  error_reason_enum_exports,
@@ -18117,7 +18315,7 @@ export {
18117
18315
  transformResponseMessageSchema,
18118
18316
  table,
18119
18317
  string4 as string,
18120
- number4 as number,
18318
+ number3 as number,
18121
18319
  boolean,
18122
18320
  json,
18123
18321
  enumeration,
@@ -18136,4 +18334,4 @@ export {
18136
18334
  update_needed_reason_type_enum_exports,
18137
18335
  Zero
18138
18336
  };
18139
- //# sourceMappingURL=chunk-AIPM77UE.js.map
18337
+ //# sourceMappingURL=chunk-QZSBDHTA.js.map