@spooky-sync/core 0.0.1-canary.237 → 0.0.1-canary.238

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { A as Sp00kyQueryResultPromise, B as LocalStore, C as ReconnectConfig, D as RunOptions, E as RegistrationTimings, F as SyncHealthConfig, G as SyncEventSystem, H as DatabaseEventSystem, I as SyncHealthStatus, K as EventDefinition, L as TimingPhase, M as StorageHealthStatus, N as StoreType, O as Sp00kyConfig, P as SyncHealth, R as UpdateOptions, S as QueryUpdateCallback, T as RecordVersionDiff, U as DatabaseEventTypes, V as SealedQuery, W as Logger$1, _ as QueryState, a as MATERIALIZATION_SAMPLE_WINDOW, b as QueryTimeToLive, c as MutationEventType, d as PinoTransmit, f as PreloadOptions, g as QueryHash, h as QueryConfigRecord, i as Level, j as StorageHealth, k as Sp00kyQueryResult, l as PersistenceClient, m as QueryConfig, n as DebounceOptions, o as MutationCallback, p as PreloadRefresh, q as EventSystem, r as EventSubscriptionOptions, s as MutationEvent, t as ConnectionState, u as PhaseStat, v as QueryStatus, w as RecordVersionArray, x as QueryTimings, y as QueryStatusCallback, z as UpEvent } from "./types.js";
1
+ import { A as ServerViewMeta, B as TimingPhase, C as QueryTimings, D as RecordVersionDiff, E as RecordVersionArray, F as StorageHealthStatus, G as DatabaseEventSystem, H as UpEvent, I as StoreType, J as SyncEventSystem, K as DatabaseEventTypes, L as SyncHealth, M as Sp00kyQueryResult, N as Sp00kyQueryResultPromise, O as RegistrationTimings, P as StorageHealth, R as SyncHealthConfig, S as QueryTimeToLive, T as ReconnectConfig, U as LocalStore, V as UpdateOptions, W as SealedQuery, X as EventSystem, Y as EventDefinition, _ as QueryConfigRecord, a as MATERIALIZATION_SAMPLE_WINDOW, b as QueryStatus, c as MutationEvent, d as PhaseStat, f as PinoTransmit, g as QueryConfig, h as QueryAuthorityCallback, i as Level, j as Sp00kyConfig, k as RunOptions, l as MutationEventType, m as PreloadRefresh, n as DebounceOptions, o as MembershipOutcome, p as PreloadOptions, q as Logger$1, r as EventSubscriptionOptions, s as MutationCallback, t as ConnectionState, u as PersistenceClient, v as QueryHash, w as QueryUpdateCallback, x as QueryStatusCallback, y as QueryState, z as SyncHealthStatus } from "./types.js";
2
2
  import * as surrealdb0 from "surrealdb";
3
3
  import { Duration, RecordId, Surreal as Surreal$1, SurrealEvents, SurrealTransaction } from "surrealdb";
4
4
  import { AccessDefinition, BackendNames, BackendRoutes, BucketNames, ColumnSchema, FinalQuery, GetTable, QueryBuilder, QueryOptions, QueryPlan, RoutePayload, SchemaStructure, TableModel, TableNames, TypeNameToTypeMap } from "@spooky-sync/query-builder";
@@ -733,6 +733,8 @@ declare class DataModule<S extends SchemaStructure> {
733
733
  private pendingQueries;
734
734
  private subscriptions;
735
735
  private statusSubscriptions;
736
+ /** Observers of a query's authority (`membershipKnown`) flips, keyed like `statusSubscriptions`. */
737
+ private authoritySubscriptions;
736
738
  private mutationCallbacks;
737
739
  private debounceTimers;
738
740
  private pendingStreamUpdates;
@@ -754,6 +756,15 @@ declare class DataModule<S extends SchemaStructure> {
754
756
  * DataModule is constructed — mirrors `onQueryStatusChange`.
755
757
  */
756
758
  onHeartbeat?: (hash: QueryHash) => void;
759
+ /**
760
+ * Fired once per episode when the server's `_00_query` row for a query we
761
+ * hold membership for is found missing (see `updateQueryRemoteArray`). Wired
762
+ * by Sp00kyClient to enqueue a `register` down-event so the SSP rebuilds the
763
+ * view; the client keeps rendering what it has meanwhile.
764
+ */
765
+ onViewLost?: (hash: QueryHash) => void;
766
+ /** DevTools observer for authority flips; mirrors `onQueryStatusChange`. */
767
+ onQueryAuthorityChange?: (hash: QueryHash, known: boolean) => void;
757
768
  /**
758
769
  * Optional hook fired by {@link deregisterQuery} when an opt-in query (e.g. a
759
770
  * viewport-windowed list cancelling an off-screen window) loses its last
@@ -806,6 +817,22 @@ declare class DataModule<S extends SchemaStructure> {
806
817
  subscribeStatus(queryHash: string, callback: QueryStatusCallback, options?: {
807
818
  immediate?: boolean;
808
819
  }): () => void;
820
+ /**
821
+ * Subscribe to a query's authority flips: whether server membership is known
822
+ * for it. With `{ immediate: true }` the callback fires synchronously with
823
+ * the current value (`false` for an unknown query).
824
+ */
825
+ subscribeAuthority(queryHash: string, callback: QueryAuthorityCallback, options?: {
826
+ immediate?: boolean;
827
+ }): () => void;
828
+ /** Whether server membership is known for `queryHash` (see `QueryConfig.membershipKnown`). */
829
+ isAuthoritative(queryHash: string): boolean;
830
+ /**
831
+ * The single writer of `config.membershipKnown` for a live query. Fans out
832
+ * to `subscribeAuthority` listeners and DevTools on a change; no-op when
833
+ * unchanged or the query is unknown.
834
+ */
835
+ private setMembershipKnown;
809
836
  /**
810
837
  * Set a query's fetch status and notify status observers (DevTools +
811
838
  * `subscribeStatus` listeners). No-op when the status is unchanged or the
@@ -1117,9 +1144,15 @@ declare class DataModule<S extends SchemaStructure> {
1117
1144
  getActiveQueryHashes(): QueryHash[];
1118
1145
  updateQueryLocalArray(id: string, localArray: RecordVersionArray): Promise<void>;
1119
1146
  updateQueryRemoteArray(hash: string, remoteArray: RecordVersionArray, opts?: {
1120
- /** `_00_query.rowCount` read in the same round trip; `null` = unknown. */
1121
- serverRowCount?: number | null;
1122
- }): Promise<void>;
1147
+ /** The `_00_query` row as read in the same round trip as the edges. */
1148
+ meta?: ServerViewMeta;
1149
+ /**
1150
+ * The caller verified upstream that the ids missing from `remoteArray`
1151
+ * no longer exist (see `Sp00kySync` LIVE removal handling); an empty set
1152
+ * is then a real answer even without a readable row.
1153
+ */
1154
+ verifiedRemoval?: boolean;
1155
+ }): Promise<MembershipOutcome>;
1123
1156
  /**
1124
1157
  * Cancel every armed timer ahead of a local-bucket switch: stream-update
1125
1158
  * debounce timers (their pending updates carry the OLD bucket's id-sets) and
@@ -1205,6 +1238,26 @@ declare class DataModule<S extends SchemaStructure> {
1205
1238
  private calculateMembershipKey;
1206
1239
  private sha256;
1207
1240
  private startTTLHeartbeat;
1241
+ /**
1242
+ * Heartbeat every watched query NOW and re-anchor its timer.
1243
+ *
1244
+ * The TTL timer is the only thing keeping a view alive on the server, and
1245
+ * browsers throttle timers in hidden tabs (Chrome aligns them to one-minute
1246
+ * ticks after five minutes hidden, and suspends them outright on some
1247
+ * mobile platforms). A tab that comes back after a long stretch may have
1248
+ * missed its beat by more than the server's slack, and the sweep will have
1249
+ * taken the row and its edges. The client does not blank on that any more
1250
+ * (`updateQueryRemoteArray` treats a missing row as "view lost"), but the
1251
+ * sooner it finds out, the sooner the view is rebuilt: `heartbeatQuery`
1252
+ * re-registers a query whose row is gone. Called on `visibilitychange` (to
1253
+ * visible) and `online`.
1254
+ *
1255
+ * Queries beaten within the last `minGapMs` are skipped, so a flurry of
1256
+ * wake events costs one beat per query. There is deliberately no local
1257
+ * expiry anywhere in this module: the TTL is the server's, and the client's
1258
+ * only duty is to keep asserting liveness while something is watching.
1259
+ */
1260
+ heartbeatOnWake(minGapMs?: number): number;
1208
1261
  private replaceRecordInQueries;
1209
1262
  }
1210
1263
  /**
@@ -1653,6 +1706,25 @@ declare class Sp00kySync<S extends SchemaStructure> {
1653
1706
  * changed.
1654
1707
  */
1655
1708
  private applyListRefSnapshot;
1709
+ /**
1710
+ * Re-read ONE query's server state now (edges + `_00_query` row) and land
1711
+ * it through {@link applyListRefSnapshot}. The targeted form of the poll,
1712
+ * for the moments that cannot wait for the next tick: a registration that
1713
+ * answered `materializing`, and a LIVE removal that has to be checked
1714
+ * against the row before it may empty a painted list.
1715
+ */
1716
+ private refetchListRefForQuery;
1717
+ /** Per-query pending targeted re-reads: one timer and the ladder still to walk. */
1718
+ private listRefRefetches;
1719
+ /**
1720
+ * Schedule a targeted re-read of `queryHash` after `delays[0]` ms. If the
1721
+ * read still says the server is publishing (`materializing`), the next rung
1722
+ * of the ladder is armed; any other outcome ends it. Re-scheduling a hash
1723
+ * that already has a timer replaces it (latest wins), so bursts coalesce.
1724
+ */
1725
+ private scheduleListRefRefetch;
1726
+ private clearListRefRefetch;
1727
+ private clearListRefRefetches;
1656
1728
  /**
1657
1729
  * Resolve the current `_00_list_ref` table name for the active auth
1658
1730
  * context. Public so the `createRemoteQuery` initial-fetch path can
@@ -1708,6 +1780,26 @@ declare class Sp00kySync<S extends SchemaStructure> {
1708
1780
  private refetchAfterReconnect;
1709
1781
  private startRefLiveQueries;
1710
1782
  private handleRemoteListRefChange;
1783
+ /** LIVE removals awaiting verification, per query, with their coalescing timer. */
1784
+ private pendingLiveRemovals;
1785
+ /**
1786
+ * Hold a LIVE `_00_list_ref` DELETE for {@link LIVE_REMOVAL_COALESCE_MS},
1787
+ * then verify the batch (see {@link flushLiveRemovals}). A sweep or a
1788
+ * republish delivers a view's whole set as one burst, so one verification
1789
+ * round covers it.
1790
+ */
1791
+ private queueLiveRemoval;
1792
+ /**
1793
+ * Verify a coalesced batch of LIVE removals against the upstream records.
1794
+ * Ids that no longer exist upstream are dropped from membership (the body
1795
+ * delete already happened inside `syncRecords`) and the query re-renders.
1796
+ * Anything still present upstream - or a verification that could not run -
1797
+ * is settled by a targeted re-read of the server's set for this query,
1798
+ * where the `_00_query` row decides: gone = view lost (keep rows,
1799
+ * re-register), `materializing` = wait, `ready` = adopt the smaller set.
1800
+ */
1801
+ private flushLiveRemovals;
1802
+ private clearLiveRemovals;
1711
1803
  /**
1712
1804
  * Handle a LIVE change to a SUBQUERY child edge (a `_00_list_ref` row with
1713
1805
  * `parent` set) for a `.related()` query. Unlike primary rows, child rows
@@ -2821,6 +2913,16 @@ declare class Sp00kyClient<S extends SchemaStructure> {
2821
2913
  subscribeQueryStatus(queryHash: string, callback: QueryStatusCallback, options?: {
2822
2914
  immediate?: boolean;
2823
2915
  }): () => void;
2916
+ /**
2917
+ * Subscribe to a query's authority flips: `true` once server membership is
2918
+ * known for it (a registration or poll landed, or a durable `_00_window`
2919
+ * seed was read on boot), `false` when it is reset (bucket switch). With
2920
+ * `{ immediate: true }` the callback fires synchronously with the current
2921
+ * value. Powers the bindings' `isAuthoritative()` / cold-only `isLoading()`.
2922
+ */
2923
+ subscribeQueryAuthority(queryHash: string, callback: QueryAuthorityCallback, options?: {
2924
+ immediate?: boolean;
2925
+ }): () => void;
2824
2926
  /**
2825
2927
  * Report the frontend processing time (ms) a client framework spent applying
2826
2928
  * an update for a query (e.g. `useQuery`'s `reconcile()`), so DevTools/MCP can
@@ -2936,4 +3038,4 @@ declare function textToHtml(text: string): string;
2936
3038
  */
2937
3039
 
2938
3040
  //#endregion
2939
- export { AppReleaseHandle, AppReleaseModule, type AppReleaseOptions, type AppReleaseSnapshot, AuthEventSystem, AuthEventTypeMap, AuthEventTypes, AuthService, BLURHASH_IMAGE_EXTENSIONS, type BlobCacheStats, type BlobEntry, type BlobKey, type BlobReadOptions, type BlobUrlLease, type BlurhashEncodeOptions, type BlurhashSetting, BucketHandle, BucketPutOptions, BucketPutResult, CURSOR_COLORS, ConnectionState, CrdtField, CrdtManager, DEFAULT_LOCAL_OP_TIMEOUT_MS, DebounceOptions, EventSubscriptionOptions, FeatureFlagHandle, FeatureFlagModule, type FeatureFlagOptions, type FeatureFlagOverride, type FeatureFlagSnapshot, Level, LocalOpTimeoutError, MATERIALIZATION_SAMPLE_WINDOW, MutationCallback, MutationEvent, MutationEventType, PersistenceClient, PhaseStat, PinoTransmit, PreloadOptions, PreloadRefresh, QueryConfig, QueryConfigRecord, QueryHash, QueryState, QueryStatus, QueryStatusCallback, QueryTimeToLive, QueryTimings, QueryUpdateCallback, ReconnectConfig, RecordVersionArray, RecordVersionDiff, RegistrationTimings, RunOptions, Sp00kyClient, Sp00kyConfig, Sp00kyQueryResult, Sp00kyQueryResultPromise, StorageHealth, StorageHealthStatus, StoreType, SyncHealth, SyncHealthConfig, SyncHealthStatus, TimingPhase, UpdateOptions, blurhashSidecarPath, bucketContentToBlob, createAuthEventSystem, cursorColorFromName, decode as decodeBlurhash, encode as encodeBlurhash, encodeImageToBlurhash, fileToUint8Array, isBlurhashValid, isImagePath, semverGt, textToHtml };
3041
+ export { AppReleaseHandle, AppReleaseModule, type AppReleaseOptions, type AppReleaseSnapshot, AuthEventSystem, AuthEventTypeMap, AuthEventTypes, AuthService, BLURHASH_IMAGE_EXTENSIONS, type BlobCacheStats, type BlobEntry, type BlobKey, type BlobReadOptions, type BlobUrlLease, type BlurhashEncodeOptions, type BlurhashSetting, BucketHandle, BucketPutOptions, BucketPutResult, CURSOR_COLORS, ConnectionState, CrdtField, CrdtManager, DEFAULT_LOCAL_OP_TIMEOUT_MS, DebounceOptions, EventSubscriptionOptions, FeatureFlagHandle, FeatureFlagModule, type FeatureFlagOptions, type FeatureFlagOverride, type FeatureFlagSnapshot, Level, LocalOpTimeoutError, MATERIALIZATION_SAMPLE_WINDOW, MembershipOutcome, MutationCallback, MutationEvent, MutationEventType, PersistenceClient, PhaseStat, PinoTransmit, PreloadOptions, PreloadRefresh, QueryAuthorityCallback, QueryConfig, QueryConfigRecord, QueryHash, QueryState, QueryStatus, QueryStatusCallback, QueryTimeToLive, QueryTimings, QueryUpdateCallback, ReconnectConfig, RecordVersionArray, RecordVersionDiff, RegistrationTimings, RunOptions, ServerViewMeta, Sp00kyClient, Sp00kyConfig, Sp00kyQueryResult, Sp00kyQueryResultPromise, StorageHealth, StorageHealthStatus, StoreType, SyncHealth, SyncHealthConfig, SyncHealthStatus, TimingPhase, UpdateOptions, blurhashSidecarPath, bucketContentToBlob, createAuthEventSystem, cursorColorFromName, decode as decodeBlurhash, encode as encodeBlurhash, encodeImageToBlurhash, fileToUint8Array, isBlurhashValid, isImagePath, semverGt, textToHtml };