@lunora/client 1.0.0-alpha.1 → 1.0.0-alpha.11

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 (32) hide show
  1. package/README.md +2 -0
  2. package/__assets__/package-og.svg +1 -1
  3. package/dist/auth/index.d.mts +1 -1
  4. package/dist/auth/index.d.ts +1 -1
  5. package/dist/index.d.mts +136 -5
  6. package/dist/index.d.ts +136 -5
  7. package/dist/index.mjs +8 -7
  8. package/dist/packem_shared/{LunoraClient-B00f7VUM.mjs → LunoraClient-6J-4BGWK.mjs} +744 -187
  9. package/dist/packem_shared/OfflineQueue-BI0FNNvc.mjs +1 -0
  10. package/dist/packem_shared/SubscriptionRegistry-Dn-7k7eo.mjs +1 -0
  11. package/dist/packem_shared/{createIndexedDbPersistence-CW82inU5.mjs → createInMemoryPersistence-DlFjWtOm.mjs} +13 -1
  12. package/dist/packem_shared/{createIndexedDbQueryCache-B1PQ9Twl.mjs → createInMemoryQueryCache-4AkTV38-.mjs} +13 -1
  13. package/dist/packem_shared/createLocalStore-IOur0jHF.mjs +1 -0
  14. package/dist/packem_shared/createMutatorRunner-BETvCd0p.mjs +31 -0
  15. package/dist/packem_shared/{createServerClient-DyFIHnWZ.mjs → createServerClient-CtklXrs2.mjs} +1 -1
  16. package/dist/packem_shared/local-store-BNgN3Dw3.mjs +111 -0
  17. package/dist/packem_shared/{lunora-client.d-DGvyuJ_p.d.mts → lunora-client.d-Dm1BYq19.d.mts} +652 -43
  18. package/dist/packem_shared/{lunora-client.d-DGvyuJ_p.d.ts → lunora-client.d-Dm1BYq19.d.ts} +652 -43
  19. package/dist/packem_shared/{OfflineQueue-D5p_QgF_.mjs → offline-queue-7Wc4onA0.mjs} +42 -5
  20. package/dist/packem_shared/{preload.d-dSaRMuhL.d.mts → preload.d-BfWzGJWV.d.mts} +1 -1
  21. package/dist/packem_shared/{preload.d-BoDmFqSG.d.ts → preload.d-Sp_Ef-_u.d.ts} +1 -1
  22. package/dist/packem_shared/subscription-C1Jy7HiF.mjs +55 -0
  23. package/dist/query/index.d.mts +2 -2
  24. package/dist/query/index.d.ts +2 -2
  25. package/dist/ssr/index.d.mts +3 -3
  26. package/dist/ssr/index.d.ts +3 -3
  27. package/dist/ssr/index.mjs +2 -2
  28. package/package.json +2 -2
  29. package/dist/packem_shared/SubscriptionRegistry-B-Qx_Gux.mjs +0 -26
  30. package/dist/packem_shared/createLocalStore-DSUfoLqY.mjs +0 -36
  31. /package/dist/packem_shared/{createStream-BDkqO5PW.mjs → DEFAULT_MAX_BUFFER-BDkqO5PW.mjs} +0 -0
  32. /package/dist/packem_shared/{serializePreloaded-C0eJTY_W.mjs → deserializePreloaded-C0eJTY_W.mjs} +0 -0
@@ -1,4 +1,4 @@
1
- import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-DGvyuJ_p.mjs";
1
+ import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-Dm1BYq19.mjs";
2
2
  import '@lunora/runtime';
3
3
  interface IdentityStore {
4
4
  /** Read the current resolved user, or `null` when signed out / not yet resolved. */
@@ -1,4 +1,4 @@
1
- import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-DGvyuJ_p.js";
1
+ import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-Dm1BYq19.js";
2
2
  import '@lunora/runtime';
3
3
  interface IdentityStore {
4
4
  /** Read the current resolved user, or `null` when signed out / not yet resolved. */
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- import { c as PersistenceAdapter, B as BookmarkStorage, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, d as ReconnectOptions } from "./packem_shared/lunora-client.d-DGvyuJ_p.mjs";
2
- export { type C as CachedQuery, type e as ClientMessage, type f as ConnectionStatus, D as DEFAULT_MAX_BUFFER, type g as FunctionArgumentDescriptor, type h as FunctionDescriptor, type G as GlobalFacetResult, type i as GlobalFacetValue, type j as GlobalFilterClause, type k as GlobalTableInfo, type l as GlobalTablePage, L as LunoraClient, type m as LunoraClientOptions, type n as OptimisticLocalStore, type o as OptimisticUpdate, type p as PersistedMutation, type P as Preloaded, type q as RpcEnvelope, type r as RpcResponseBody, type s as ScheduleRecord, type t as SchedulerPoolStatus, type u as SchedulerStatus, type v as ServerMessage, type w as ShardTrafficEntry, type x as ShardTrafficResult, type y as StorageListPage, type z as StorageObject, type E as StreamHandle, type H as StreamIterable, type I as SubscriptionCallback, type S as SubscriptionError, type b as SubscriptionErrorCallback, J as SubscriptionRegistry, type K as SubscriptionState, type a as Unsubscribe, type U as User, type W as WorkflowInstanceAction, type N as WorkflowInstanceDetail, type T as WorkflowInstancePage, type V as WorkflowInstanceStatus, type X as WorkflowInstanceSummary, type Y as WorkflowStepDetail, Z as createLocalStore, _ as createStream } from "./packem_shared/lunora-client.d-DGvyuJ_p.mjs";
3
- export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-dSaRMuhL.mjs";
1
+ import { c as PersistenceAdapter, B as BookmarkStorage, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, d as ReconnectOptions } from "./packem_shared/lunora-client.d-Dm1BYq19.mjs";
2
+ export { type C as CachedQuery, type e as ClientMessage, type f as ClientShapeSubscribeMessage, type g as ClientShapeUnsubscribeMessage, type h as ConnectionStatus, D as DEFAULT_MAX_BUFFER, type i as FunctionArgumentDescriptor, type j as FunctionDescriptor, type G as GlobalFacetResult, type k as GlobalFacetValue, type l as GlobalFilterClause, type m as GlobalTableInfo, type n as GlobalTablePage, L as LunoraClient, type o as LunoraClientOptions, type p as MutationSettledEvent, type q as OptimisticLocalStore, type r as OptimisticUpdate, type s as OutboxMutation, type t as OutboxSink, type u as PersistedMutation, type P as Preloaded, type v as RowOp, type w as RpcEnvelope, type x as RpcResponseBody, type y as ScheduleRecord, type z as SchedulerPoolStatus, type E as SchedulerStatus, type H as ServerMessage, type I as ServerPokeEndMessage, type J as ServerPokePartMessage, type K as ServerPokeStartMessage, type N as ShardTrafficEntry, type T as ShardTrafficResult, type V as StorageListPage, type W as StorageObject, type X as StreamHandle, type Y as StreamIterable, type Z as SubscriptionCallback, type S as SubscriptionError, type b as SubscriptionErrorCallback, _ as SubscriptionRegistry, type $ as SubscriptionState, type a0 as SyncWatermark, type a as Unsubscribe, type U as User, type a1 as WorkflowInstanceAction, type a2 as WorkflowInstanceDetail, type a3 as WorkflowInstancePage, type a4 as WorkflowInstanceStatus, type a5 as WorkflowInstanceSummary, type a6 as WorkflowStepDetail, a7 as createLocalStore, a8 as createStream } from "./packem_shared/lunora-client.d-Dm1BYq19.mjs";
3
+ export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-BfWzGJWV.mjs";
4
4
  export type { AuthCapabilities, AuthImpersonation, AuthPage, AuthSession, AuthUser, CronJobInfo, VectorIndexSummary, VectorQueryMatch } from '@lunora/runtime';
5
5
  /**
6
6
  * The slice of React Native's `AsyncStorage` (or any async key/value store —
@@ -136,6 +136,59 @@ interface MutationRunnerSinks<R> {
136
136
  * pass straight through to `client.mutation`.
137
137
  */
138
138
  declare const createMutationRunner: <F extends FunctionReference>(client: MutationCapableClient<F>, function_: F, sinks: MutationRunnerSinks<ReturnOf<F>>) => ((args: ArgsOf<F>, options?: MutationCallOptions<unknown, unknown, ArgsOf<F>>) => Promise<ReturnOf<F>>);
139
+ /**
140
+ * The structural surface of a TanStack `Transaction` a bound custom mutator
141
+ * returns — its `isPersisted.promise` resolves once the write is persisted and
142
+ * rejects on failure. Typed structurally so the framework adapters need not
143
+ * depend on `@tanstack/db` or `@lunora/db` (the handle is created app-side by
144
+ * `bindMutators`).
145
+ */
146
+ interface MutatorTransaction {
147
+ isPersisted: {
148
+ promise: Promise<unknown>;
149
+ };
150
+ }
151
+ /**
152
+ * A bound custom-mutator handle produced by `bindMutators(client, ctx, mutators)`
153
+ * in `@lunora/db`. Calling it applies the optimistic overlay to the local
154
+ * collections and pushes the authoritative server write; it returns the TanStack
155
+ * transaction whose `isPersisted` promise tracks completion.
156
+ */
157
+ type MutatorHandle<TArgs> = (args: TArgs) => MutatorTransaction;
158
+ /**
159
+ * Reactive sinks an adapter binds to its own primitive's setters (a React
160
+ * `useState`, a Solid signal, a Vue ref, a Svelte store). The runner pushes into
161
+ * them; how they store the value is the adapter's concern.
162
+ */
163
+ interface MutatorRunnerSinks {
164
+ /** Receives the normalized {@link Error} when an invocation rejects, or `undefined` on success / reset. */
165
+ setError: (error: Error | undefined) => void;
166
+ /** Receives `true` while at least one invocation is in flight (ref-counted across overlapping calls), else `false`. */
167
+ setPending: (pending: boolean) => void;
168
+ }
169
+ /**
170
+ * Build the framework-neutral `mutate` / `reset` pair of an adapter's
171
+ * custom-mutator hook (`useMutator` / `createMutator` / `mutator`).
172
+ *
173
+ * Owns the orchestration every adapter otherwise copy-pastes: ref-counts
174
+ * overlapping invocations into `setPending` (so it only clears once the last
175
+ * settles), awaits the bound handle's `isPersisted` promise, normalizes a thrown
176
+ * non-`Error`, and routes failure to `setError` (clearing it on success) before
177
+ * re-throwing. Each adapter (`@lunora/react`, `/solid`, `/svelte`, `/vue`) binds
178
+ * the two sinks to its own reactive setters, so this logic lives in exactly one
179
+ * place. The optimistic overlay + server push are owned by the bound handle.
180
+ *
181
+ * `error` tracks the LATEST invocation, not the last to settle: overlapping
182
+ * calls can resolve out of order, so an earlier call that finishes later must
183
+ * not clobber a newer call's outcome. Each invocation takes a monotonic token
184
+ * and only writes `setError` while it is still the most recent one — otherwise
185
+ * `error`/`isError` could surface a stale success or failure (the documented
186
+ * "latest invocation's error" contract every adapter advertises).
187
+ */
188
+ declare const createMutatorRunner: <TArgs>(handle: MutatorHandle<TArgs>, sinks: MutatorRunnerSinks) => {
189
+ mutate: (args: TArgs) => Promise<void>;
190
+ reset: () => void;
191
+ };
139
192
  interface QueuedMutation<T = unknown> {
140
193
  readonly args: Record<string, unknown>;
141
194
  readonly functionPath: string;
@@ -146,12 +199,57 @@ interface QueuedMutation<T = unknown> {
146
199
  * signed out). Absent on hydrated legacy records, which replay ambiently.
147
200
  */
148
201
  readonly identity?: string | null;
202
+ /**
203
+ * `true` when a live caller is still awaiting this write's `mutation()`
204
+ * Promise; `false`/absent for a write restored from durable storage after a
205
+ * reload (its original awaiter is gone). Carried so terminal-verdict
206
+ * observers can distinguish "the caller already saw this" from "nothing else
207
+ * will report this". Maps to the public `MutationSettledEvent.hadAwaiter`.
208
+ */
209
+ liveAwaiter?: boolean;
210
+ /**
211
+ * Invoked on a successful replay with the server's echoed commit CDC cursor,
212
+ * so a live per-call optimistic layer drops gaplessly once a frame reaches it.
213
+ * Absent on hydrated records (the optimistic write lived in a prior session).
214
+ */
215
+ readonly onCommit?: (commitCursor: number | undefined) => void;
149
216
  /** Rejects if the mutation can no longer be replayed. */
150
217
  readonly reject: (error: unknown) => void;
151
218
  /** Resolves once the mutation has been replayed against the server. */
152
219
  readonly resolve: (value: T) => void;
153
220
  readonly shardKey?: string;
154
221
  }
222
+ /**
223
+ * Invoked when the queue itself discards an entry on overflow (capacity
224
+ * eviction), so the client can surface the dropped write on its
225
+ * terminal-verdict observer even when the entry has no live awaiter (a hydrated
226
+ * record). The `error` carries the `OFFLINE_QUEUE_OVERFLOW` code.
227
+ */
228
+ type EvictHandler = (entry: QueuedMutation, error: Error & {
229
+ code?: string;
230
+ }) => void;
231
+ /** Injected dependencies for {@link OfflineQueue} (kept off the user-facing {@link OfflineQueueOptions}). */
232
+ interface OfflineQueueDeps {
233
+ /** Invoked when an entry is discarded on capacity overflow (carries `OFFLINE_QUEUE_OVERFLOW`). */
234
+ onEvict?: EvictHandler;
235
+ /** Invoked with the new depth after any size change (drives the client's pending-sync count). */
236
+ onSizeChange?: (size: number) => void;
237
+ /** Durable store; when present, writes are mirrored and restored across reloads. */
238
+ persistence?: PersistenceAdapter;
239
+ /** App/schema version stamped on persisted writes; mismatched records are purged on hydrate. */
240
+ version?: string;
241
+ }
242
+ /**
243
+ * A process-unique id, used both per-mutation and as the fallback `clientId`. It
244
+ * MUST be globally unique: the server scopes a custom mutator's replay watermark
245
+ * by `(verifiedIdentity, clientId)`, and an anonymous push has no verified
246
+ * identity — so two anonymous clients that collide on `clientId` would share one
247
+ * watermark namespace, letting one stall/suppress the other's ordered mutations.
248
+ * `crypto.randomUUID` covers every modern runtime; the fallback still mixes
249
+ * crypto-quality (or `Math.random`) entropy with the timestamp + counter so it
250
+ * can't collide across two clients started in the same millisecond.
251
+ */
252
+
155
253
  /**
156
254
  * Bounded FIFO queue. Mutations issued while the client is offline are
157
255
  * enqueued and replayed in the order they were submitted once the WS
@@ -170,8 +268,12 @@ declare class OfflineQueue {
170
268
  private readonly maxItems;
171
269
  private readonly onPersistenceError;
172
270
  private readonly persistence;
271
+ private readonly onEvict;
272
+ private readonly onSizeChange;
273
+ /** App/schema version stamped on persisted writes; mismatched records are purged on hydrate. */
274
+ private readonly version;
173
275
  private readonly items;
174
- constructor(options?: OfflineQueueOptions, persistence?: PersistenceAdapter);
276
+ constructor(options?: OfflineQueueOptions, deps?: OfflineQueueDeps);
175
277
  get size(): number;
176
278
  enqueue<T>(entry: QueuedMutation<T>): void;
177
279
  /**
@@ -198,6 +300,8 @@ declare class OfflineQueue {
198
300
  */
199
301
  requeue(items: QueuedMutation[]): void;
200
302
  clear(): void;
303
+ /** Notify the size observer (the client's pending-sync count) after any change. */
304
+ private notifySize;
201
305
  }
202
306
  /**
203
307
  * In-memory {@link PersistenceAdapter}. Doesn't survive a reload — it exists so
@@ -225,6 +329,24 @@ interface IndexedDbPersistenceOptions {
225
329
  */
226
330
  declare const createIndexedDbPersistence: (options?: IndexedDbPersistenceOptions) => PersistenceAdapter;
227
331
  /**
332
+ * Resolve the effective offline-queue persistence from the user option,
333
+ * defaulting to a durable IndexedDB store when the environment supports one.
334
+ *
335
+ * An explicit adapter is used as-is; `false` opts out (the caller keeps an
336
+ * in-memory queue, lost on reload); `undefined` (the default) auto-probes
337
+ * IndexedDB when the global is present (browsers) and `autoProbe` is set,
338
+ * otherwise `undefined` — so SSR/Node/React-Native keep today's in-memory
339
+ * behaviour and only environments that can persist do.
340
+ *
341
+ * `autoProbe` is `false` when the `@lunora/db` outbox is wired: that sink is the
342
+ * single durable write path, so the built-in queue must stay in memory rather
343
+ * than persist a second, never-flushed copy. An explicit adapter is still
344
+ * honoured (the caller asked for it); only the implicit default is suppressed.
345
+ *
346
+ * The IndexedDB adapter opens its connection lazily, so constructing it here is
347
+ * cheap and never throws (the `indexedDB` global is verified present first).
348
+ */
349
+ /**
228
350
  * Compose the read-cache key for a subscription. Mirrors how
229
351
  * `SubscriptionRegistry` keys live subscriptions so a hydrated value lines up
230
352
  * with the subscription that will consume it. `shardKey` defaults to `""` (the
@@ -265,6 +387,15 @@ interface IndexedDbQueryCacheOptions {
265
387
  */
266
388
  declare const createIndexedDbQueryCache: (options?: IndexedDbQueryCacheOptions) => QueryCacheAdapter;
267
389
  /**
390
+ * Resolve the effective read-cache from the user option, defaulting to a durable
391
+ * IndexedDB store when the environment supports one. Same tri-state semantics as
392
+ * `resolvePersistenceAdapter` in `./persistence`:
393
+ *
394
+ * - an explicit adapter is used as-is;
395
+ * - `false` opts out — reads stay in memory only;
396
+ * - `undefined` (the default) auto-probes IndexedDB (browsers), else `undefined`.
397
+ */
398
+ /**
268
399
  * Exponential backoff calculator with optional jitter.
269
400
  *
270
401
  * `next()` doubles the delay each call up to `maxDelayMs`. When `jitter` is
@@ -278,4 +409,4 @@ interface ReconnectCalculator {
278
409
  reset: () => void;
279
410
  }
280
411
  declare const createReconnect: (options?: ReconnectOptions, random?: () => number) => ReconnectCalculator;
281
- export { type ArgsOf, type AsyncStorageLike, type AsyncStoragePersistenceOptions, type BookmarkStorage, CONFLICT_ERROR_CODE, type FunctionReference, type IndexedDbPersistenceOptions, type IndexedDbQueryCacheOptions, type MutationCallOptions, type MutationDelta, type MutationRunnerSinks, OfflineQueue, type OfflineQueueOptions, type PersistenceAdapter, type QueryCacheAdapter, type QueuedMutation, type ReconnectCalculator, type ReconnectOptions, type ReturnOf, applyDelta, createAsyncStoragePersistence, createInMemoryBookmarkStorage, createInMemoryPersistence, createInMemoryQueryCache, createIndexedDbPersistence, createIndexedDbQueryCache, createMutationRunner, createReconnect, isConflictError, isMutationDelta, queryCacheKey };
412
+ export { type ArgsOf, type AsyncStorageLike, type AsyncStoragePersistenceOptions, type BookmarkStorage, CONFLICT_ERROR_CODE, type FunctionReference, type IndexedDbPersistenceOptions, type IndexedDbQueryCacheOptions, type MutationCallOptions, type MutationDelta, type MutationRunnerSinks, type MutatorHandle, type MutatorRunnerSinks, type MutatorTransaction, OfflineQueue, type OfflineQueueOptions, type PersistenceAdapter, type QueryCacheAdapter, type QueuedMutation, type ReconnectCalculator, type ReconnectOptions, type ReturnOf, applyDelta, createAsyncStoragePersistence, createInMemoryBookmarkStorage, createInMemoryPersistence, createInMemoryQueryCache, createIndexedDbPersistence, createIndexedDbQueryCache, createMutationRunner, createMutatorRunner, createReconnect, isConflictError, isMutationDelta, queryCacheKey };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { c as PersistenceAdapter, B as BookmarkStorage, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, d as ReconnectOptions } from "./packem_shared/lunora-client.d-DGvyuJ_p.js";
2
- export { type C as CachedQuery, type e as ClientMessage, type f as ConnectionStatus, D as DEFAULT_MAX_BUFFER, type g as FunctionArgumentDescriptor, type h as FunctionDescriptor, type G as GlobalFacetResult, type i as GlobalFacetValue, type j as GlobalFilterClause, type k as GlobalTableInfo, type l as GlobalTablePage, L as LunoraClient, type m as LunoraClientOptions, type n as OptimisticLocalStore, type o as OptimisticUpdate, type p as PersistedMutation, type P as Preloaded, type q as RpcEnvelope, type r as RpcResponseBody, type s as ScheduleRecord, type t as SchedulerPoolStatus, type u as SchedulerStatus, type v as ServerMessage, type w as ShardTrafficEntry, type x as ShardTrafficResult, type y as StorageListPage, type z as StorageObject, type E as StreamHandle, type H as StreamIterable, type I as SubscriptionCallback, type S as SubscriptionError, type b as SubscriptionErrorCallback, J as SubscriptionRegistry, type K as SubscriptionState, type a as Unsubscribe, type U as User, type W as WorkflowInstanceAction, type N as WorkflowInstanceDetail, type T as WorkflowInstancePage, type V as WorkflowInstanceStatus, type X as WorkflowInstanceSummary, type Y as WorkflowStepDetail, Z as createLocalStore, _ as createStream } from "./packem_shared/lunora-client.d-DGvyuJ_p.js";
3
- export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-BoDmFqSG.js";
1
+ import { c as PersistenceAdapter, B as BookmarkStorage, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, d as ReconnectOptions } from "./packem_shared/lunora-client.d-Dm1BYq19.js";
2
+ export { type C as CachedQuery, type e as ClientMessage, type f as ClientShapeSubscribeMessage, type g as ClientShapeUnsubscribeMessage, type h as ConnectionStatus, D as DEFAULT_MAX_BUFFER, type i as FunctionArgumentDescriptor, type j as FunctionDescriptor, type G as GlobalFacetResult, type k as GlobalFacetValue, type l as GlobalFilterClause, type m as GlobalTableInfo, type n as GlobalTablePage, L as LunoraClient, type o as LunoraClientOptions, type p as MutationSettledEvent, type q as OptimisticLocalStore, type r as OptimisticUpdate, type s as OutboxMutation, type t as OutboxSink, type u as PersistedMutation, type P as Preloaded, type v as RowOp, type w as RpcEnvelope, type x as RpcResponseBody, type y as ScheduleRecord, type z as SchedulerPoolStatus, type E as SchedulerStatus, type H as ServerMessage, type I as ServerPokeEndMessage, type J as ServerPokePartMessage, type K as ServerPokeStartMessage, type N as ShardTrafficEntry, type T as ShardTrafficResult, type V as StorageListPage, type W as StorageObject, type X as StreamHandle, type Y as StreamIterable, type Z as SubscriptionCallback, type S as SubscriptionError, type b as SubscriptionErrorCallback, _ as SubscriptionRegistry, type $ as SubscriptionState, type a0 as SyncWatermark, type a as Unsubscribe, type U as User, type a1 as WorkflowInstanceAction, type a2 as WorkflowInstanceDetail, type a3 as WorkflowInstancePage, type a4 as WorkflowInstanceStatus, type a5 as WorkflowInstanceSummary, type a6 as WorkflowStepDetail, a7 as createLocalStore, a8 as createStream } from "./packem_shared/lunora-client.d-Dm1BYq19.js";
3
+ export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-Sp_Ef-_u.js";
4
4
  export type { AuthCapabilities, AuthImpersonation, AuthPage, AuthSession, AuthUser, CronJobInfo, VectorIndexSummary, VectorQueryMatch } from '@lunora/runtime';
5
5
  /**
6
6
  * The slice of React Native's `AsyncStorage` (or any async key/value store —
@@ -136,6 +136,59 @@ interface MutationRunnerSinks<R> {
136
136
  * pass straight through to `client.mutation`.
137
137
  */
138
138
  declare const createMutationRunner: <F extends FunctionReference>(client: MutationCapableClient<F>, function_: F, sinks: MutationRunnerSinks<ReturnOf<F>>) => ((args: ArgsOf<F>, options?: MutationCallOptions<unknown, unknown, ArgsOf<F>>) => Promise<ReturnOf<F>>);
139
+ /**
140
+ * The structural surface of a TanStack `Transaction` a bound custom mutator
141
+ * returns — its `isPersisted.promise` resolves once the write is persisted and
142
+ * rejects on failure. Typed structurally so the framework adapters need not
143
+ * depend on `@tanstack/db` or `@lunora/db` (the handle is created app-side by
144
+ * `bindMutators`).
145
+ */
146
+ interface MutatorTransaction {
147
+ isPersisted: {
148
+ promise: Promise<unknown>;
149
+ };
150
+ }
151
+ /**
152
+ * A bound custom-mutator handle produced by `bindMutators(client, ctx, mutators)`
153
+ * in `@lunora/db`. Calling it applies the optimistic overlay to the local
154
+ * collections and pushes the authoritative server write; it returns the TanStack
155
+ * transaction whose `isPersisted` promise tracks completion.
156
+ */
157
+ type MutatorHandle<TArgs> = (args: TArgs) => MutatorTransaction;
158
+ /**
159
+ * Reactive sinks an adapter binds to its own primitive's setters (a React
160
+ * `useState`, a Solid signal, a Vue ref, a Svelte store). The runner pushes into
161
+ * them; how they store the value is the adapter's concern.
162
+ */
163
+ interface MutatorRunnerSinks {
164
+ /** Receives the normalized {@link Error} when an invocation rejects, or `undefined` on success / reset. */
165
+ setError: (error: Error | undefined) => void;
166
+ /** Receives `true` while at least one invocation is in flight (ref-counted across overlapping calls), else `false`. */
167
+ setPending: (pending: boolean) => void;
168
+ }
169
+ /**
170
+ * Build the framework-neutral `mutate` / `reset` pair of an adapter's
171
+ * custom-mutator hook (`useMutator` / `createMutator` / `mutator`).
172
+ *
173
+ * Owns the orchestration every adapter otherwise copy-pastes: ref-counts
174
+ * overlapping invocations into `setPending` (so it only clears once the last
175
+ * settles), awaits the bound handle's `isPersisted` promise, normalizes a thrown
176
+ * non-`Error`, and routes failure to `setError` (clearing it on success) before
177
+ * re-throwing. Each adapter (`@lunora/react`, `/solid`, `/svelte`, `/vue`) binds
178
+ * the two sinks to its own reactive setters, so this logic lives in exactly one
179
+ * place. The optimistic overlay + server push are owned by the bound handle.
180
+ *
181
+ * `error` tracks the LATEST invocation, not the last to settle: overlapping
182
+ * calls can resolve out of order, so an earlier call that finishes later must
183
+ * not clobber a newer call's outcome. Each invocation takes a monotonic token
184
+ * and only writes `setError` while it is still the most recent one — otherwise
185
+ * `error`/`isError` could surface a stale success or failure (the documented
186
+ * "latest invocation's error" contract every adapter advertises).
187
+ */
188
+ declare const createMutatorRunner: <TArgs>(handle: MutatorHandle<TArgs>, sinks: MutatorRunnerSinks) => {
189
+ mutate: (args: TArgs) => Promise<void>;
190
+ reset: () => void;
191
+ };
139
192
  interface QueuedMutation<T = unknown> {
140
193
  readonly args: Record<string, unknown>;
141
194
  readonly functionPath: string;
@@ -146,12 +199,57 @@ interface QueuedMutation<T = unknown> {
146
199
  * signed out). Absent on hydrated legacy records, which replay ambiently.
147
200
  */
148
201
  readonly identity?: string | null;
202
+ /**
203
+ * `true` when a live caller is still awaiting this write's `mutation()`
204
+ * Promise; `false`/absent for a write restored from durable storage after a
205
+ * reload (its original awaiter is gone). Carried so terminal-verdict
206
+ * observers can distinguish "the caller already saw this" from "nothing else
207
+ * will report this". Maps to the public `MutationSettledEvent.hadAwaiter`.
208
+ */
209
+ liveAwaiter?: boolean;
210
+ /**
211
+ * Invoked on a successful replay with the server's echoed commit CDC cursor,
212
+ * so a live per-call optimistic layer drops gaplessly once a frame reaches it.
213
+ * Absent on hydrated records (the optimistic write lived in a prior session).
214
+ */
215
+ readonly onCommit?: (commitCursor: number | undefined) => void;
149
216
  /** Rejects if the mutation can no longer be replayed. */
150
217
  readonly reject: (error: unknown) => void;
151
218
  /** Resolves once the mutation has been replayed against the server. */
152
219
  readonly resolve: (value: T) => void;
153
220
  readonly shardKey?: string;
154
221
  }
222
+ /**
223
+ * Invoked when the queue itself discards an entry on overflow (capacity
224
+ * eviction), so the client can surface the dropped write on its
225
+ * terminal-verdict observer even when the entry has no live awaiter (a hydrated
226
+ * record). The `error` carries the `OFFLINE_QUEUE_OVERFLOW` code.
227
+ */
228
+ type EvictHandler = (entry: QueuedMutation, error: Error & {
229
+ code?: string;
230
+ }) => void;
231
+ /** Injected dependencies for {@link OfflineQueue} (kept off the user-facing {@link OfflineQueueOptions}). */
232
+ interface OfflineQueueDeps {
233
+ /** Invoked when an entry is discarded on capacity overflow (carries `OFFLINE_QUEUE_OVERFLOW`). */
234
+ onEvict?: EvictHandler;
235
+ /** Invoked with the new depth after any size change (drives the client's pending-sync count). */
236
+ onSizeChange?: (size: number) => void;
237
+ /** Durable store; when present, writes are mirrored and restored across reloads. */
238
+ persistence?: PersistenceAdapter;
239
+ /** App/schema version stamped on persisted writes; mismatched records are purged on hydrate. */
240
+ version?: string;
241
+ }
242
+ /**
243
+ * A process-unique id, used both per-mutation and as the fallback `clientId`. It
244
+ * MUST be globally unique: the server scopes a custom mutator's replay watermark
245
+ * by `(verifiedIdentity, clientId)`, and an anonymous push has no verified
246
+ * identity — so two anonymous clients that collide on `clientId` would share one
247
+ * watermark namespace, letting one stall/suppress the other's ordered mutations.
248
+ * `crypto.randomUUID` covers every modern runtime; the fallback still mixes
249
+ * crypto-quality (or `Math.random`) entropy with the timestamp + counter so it
250
+ * can't collide across two clients started in the same millisecond.
251
+ */
252
+
155
253
  /**
156
254
  * Bounded FIFO queue. Mutations issued while the client is offline are
157
255
  * enqueued and replayed in the order they were submitted once the WS
@@ -170,8 +268,12 @@ declare class OfflineQueue {
170
268
  private readonly maxItems;
171
269
  private readonly onPersistenceError;
172
270
  private readonly persistence;
271
+ private readonly onEvict;
272
+ private readonly onSizeChange;
273
+ /** App/schema version stamped on persisted writes; mismatched records are purged on hydrate. */
274
+ private readonly version;
173
275
  private readonly items;
174
- constructor(options?: OfflineQueueOptions, persistence?: PersistenceAdapter);
276
+ constructor(options?: OfflineQueueOptions, deps?: OfflineQueueDeps);
175
277
  get size(): number;
176
278
  enqueue<T>(entry: QueuedMutation<T>): void;
177
279
  /**
@@ -198,6 +300,8 @@ declare class OfflineQueue {
198
300
  */
199
301
  requeue(items: QueuedMutation[]): void;
200
302
  clear(): void;
303
+ /** Notify the size observer (the client's pending-sync count) after any change. */
304
+ private notifySize;
201
305
  }
202
306
  /**
203
307
  * In-memory {@link PersistenceAdapter}. Doesn't survive a reload — it exists so
@@ -225,6 +329,24 @@ interface IndexedDbPersistenceOptions {
225
329
  */
226
330
  declare const createIndexedDbPersistence: (options?: IndexedDbPersistenceOptions) => PersistenceAdapter;
227
331
  /**
332
+ * Resolve the effective offline-queue persistence from the user option,
333
+ * defaulting to a durable IndexedDB store when the environment supports one.
334
+ *
335
+ * An explicit adapter is used as-is; `false` opts out (the caller keeps an
336
+ * in-memory queue, lost on reload); `undefined` (the default) auto-probes
337
+ * IndexedDB when the global is present (browsers) and `autoProbe` is set,
338
+ * otherwise `undefined` — so SSR/Node/React-Native keep today's in-memory
339
+ * behaviour and only environments that can persist do.
340
+ *
341
+ * `autoProbe` is `false` when the `@lunora/db` outbox is wired: that sink is the
342
+ * single durable write path, so the built-in queue must stay in memory rather
343
+ * than persist a second, never-flushed copy. An explicit adapter is still
344
+ * honoured (the caller asked for it); only the implicit default is suppressed.
345
+ *
346
+ * The IndexedDB adapter opens its connection lazily, so constructing it here is
347
+ * cheap and never throws (the `indexedDB` global is verified present first).
348
+ */
349
+ /**
228
350
  * Compose the read-cache key for a subscription. Mirrors how
229
351
  * `SubscriptionRegistry` keys live subscriptions so a hydrated value lines up
230
352
  * with the subscription that will consume it. `shardKey` defaults to `""` (the
@@ -265,6 +387,15 @@ interface IndexedDbQueryCacheOptions {
265
387
  */
266
388
  declare const createIndexedDbQueryCache: (options?: IndexedDbQueryCacheOptions) => QueryCacheAdapter;
267
389
  /**
390
+ * Resolve the effective read-cache from the user option, defaulting to a durable
391
+ * IndexedDB store when the environment supports one. Same tri-state semantics as
392
+ * `resolvePersistenceAdapter` in `./persistence`:
393
+ *
394
+ * - an explicit adapter is used as-is;
395
+ * - `false` opts out — reads stay in memory only;
396
+ * - `undefined` (the default) auto-probes IndexedDB (browsers), else `undefined`.
397
+ */
398
+ /**
268
399
  * Exponential backoff calculator with optional jitter.
269
400
  *
270
401
  * `next()` doubles the delay each call up to `maxDelayMs`. When `jitter` is
@@ -278,4 +409,4 @@ interface ReconnectCalculator {
278
409
  reset: () => void;
279
410
  }
280
411
  declare const createReconnect: (options?: ReconnectOptions, random?: () => number) => ReconnectCalculator;
281
- export { type ArgsOf, type AsyncStorageLike, type AsyncStoragePersistenceOptions, type BookmarkStorage, CONFLICT_ERROR_CODE, type FunctionReference, type IndexedDbPersistenceOptions, type IndexedDbQueryCacheOptions, type MutationCallOptions, type MutationDelta, type MutationRunnerSinks, OfflineQueue, type OfflineQueueOptions, type PersistenceAdapter, type QueryCacheAdapter, type QueuedMutation, type ReconnectCalculator, type ReconnectOptions, type ReturnOf, applyDelta, createAsyncStoragePersistence, createInMemoryBookmarkStorage, createInMemoryPersistence, createInMemoryQueryCache, createIndexedDbPersistence, createIndexedDbQueryCache, createMutationRunner, createReconnect, isConflictError, isMutationDelta, queryCacheKey };
412
+ export { type ArgsOf, type AsyncStorageLike, type AsyncStoragePersistenceOptions, type BookmarkStorage, CONFLICT_ERROR_CODE, type FunctionReference, type IndexedDbPersistenceOptions, type IndexedDbQueryCacheOptions, type MutationCallOptions, type MutationDelta, type MutationRunnerSinks, type MutatorHandle, type MutatorRunnerSinks, type MutatorTransaction, OfflineQueue, type OfflineQueueOptions, type PersistenceAdapter, type QueryCacheAdapter, type QueuedMutation, type ReconnectCalculator, type ReconnectOptions, type ReturnOf, applyDelta, createAsyncStoragePersistence, createInMemoryBookmarkStorage, createInMemoryPersistence, createInMemoryQueryCache, createIndexedDbPersistence, createIndexedDbQueryCache, createMutationRunner, createMutatorRunner, createReconnect, isConflictError, isMutationDelta, queryCacheKey };
package/dist/index.mjs CHANGED
@@ -2,13 +2,14 @@ export { createAsyncStoragePersistence } from './packem_shared/createAsyncStorag
2
2
  export { default as createInMemoryBookmarkStorage } from './packem_shared/createInMemoryBookmarkStorage-BoN7a7TH.mjs';
3
3
  export { applyDelta, isMutationDelta } from './packem_shared/applyDelta-4jFGTPA3.mjs';
4
4
  export { CONFLICT_ERROR_CODE, isConflictError } from './packem_shared/CONFLICT_ERROR_CODE-aUdVbEDw.mjs';
5
- export { createLocalStore } from './packem_shared/createLocalStore-DSUfoLqY.mjs';
6
- export { LunoraClient } from './packem_shared/LunoraClient-B00f7VUM.mjs';
5
+ export { c as createLocalStore } from './packem_shared/local-store-BNgN3Dw3.mjs';
6
+ export { LunoraClient } from './packem_shared/LunoraClient-6J-4BGWK.mjs';
7
7
  export { createMutationRunner } from './packem_shared/createMutationRunner-BqsavzvG.mjs';
8
- export { OfflineQueue } from './packem_shared/OfflineQueue-D5p_QgF_.mjs';
9
- export { createInMemoryPersistence, createIndexedDbPersistence } from './packem_shared/createIndexedDbPersistence-CW82inU5.mjs';
8
+ export { createMutatorRunner } from './packem_shared/createMutatorRunner-BETvCd0p.mjs';
9
+ export { O as OfflineQueue } from './packem_shared/offline-queue-7Wc4onA0.mjs';
10
+ export { createInMemoryPersistence, createIndexedDbPersistence } from './packem_shared/createInMemoryPersistence-DlFjWtOm.mjs';
10
11
  export { preloadQuery, preloadedQueryResult } from './packem_shared/preloadQuery-lobFkD2Z.mjs';
11
- export { createInMemoryQueryCache, createIndexedDbQueryCache, queryCacheKey } from './packem_shared/createIndexedDbQueryCache-B1PQ9Twl.mjs';
12
+ export { createInMemoryQueryCache, createIndexedDbQueryCache, queryCacheKey } from './packem_shared/createInMemoryQueryCache-4AkTV38-.mjs';
12
13
  export { createReconnect } from './packem_shared/createReconnect-Di_-oHH7.mjs';
13
- export { DEFAULT_MAX_BUFFER, createStream } from './packem_shared/createStream-BDkqO5PW.mjs';
14
- export { SubscriptionRegistry } from './packem_shared/SubscriptionRegistry-B-Qx_Gux.mjs';
14
+ export { DEFAULT_MAX_BUFFER, createStream } from './packem_shared/DEFAULT_MAX_BUFFER-BDkqO5PW.mjs';
15
+ export { S as SubscriptionRegistry } from './packem_shared/subscription-C1Jy7HiF.mjs';