@lunora/db 1.0.0-alpha.230 → 1.0.0-alpha.232

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.
@@ -1,5 +1,5 @@
1
- export { type b as CheckpointRegistry, type L as LunoraCollectionConfig, type f as LunoraCollectionOptions, i as createCheckpointRegistry, m as lunoraCollectionOptions } from "../packem_shared/collection-options.d-BbEYKjp2.mjs";
2
- export { type C as CollectionDef, type I as InsertBinding, type L as LunoraDb, d as defineCollections } from "../packem_shared/index.d-cl7LWrQo.mjs";
1
+ export { type b as CheckpointRegistry, type L as LunoraCollectionConfig, type f as LunoraCollectionOptions, j as createCheckpointRegistry, n as lunoraCollectionOptions } from "../packem_shared/collection-options.d-C2FdJw06.mjs";
2
+ export { type C as CollectionDef, type I as InsertBinding, type L as LunoraDb, d as defineCollections } from "../packem_shared/index.d-B_2dXw1Z.mjs";
3
3
  import '@lunora/client';
4
4
  import '@tanstack/db';
5
5
  import '@tanstack/offline-transactions';
@@ -1,5 +1,5 @@
1
- export { type b as CheckpointRegistry, type L as LunoraCollectionConfig, type f as LunoraCollectionOptions, i as createCheckpointRegistry, m as lunoraCollectionOptions } from "../packem_shared/collection-options.d-BbEYKjp2.js";
2
- export { type C as CollectionDef, type I as InsertBinding, type L as LunoraDb, d as defineCollections } from "../packem_shared/index.d-G0N0-lGJ.js";
1
+ export { type b as CheckpointRegistry, type L as LunoraCollectionConfig, type f as LunoraCollectionOptions, j as createCheckpointRegistry, n as lunoraCollectionOptions } from "../packem_shared/collection-options.d-C2FdJw06.js";
2
+ export { type C as CollectionDef, type I as InsertBinding, type L as LunoraDb, d as defineCollections } from "../packem_shared/index.d-ypscb9Qp.js";
3
3
  import '@lunora/client';
4
4
  import '@tanstack/db';
5
5
  import '@tanstack/offline-transactions';
@@ -1 +1 @@
1
- import{createCheckpointRegistry as t,lunoraCollectionOptions as r}from"../packem_shared/CHECKPOINT_FALLBACK_MS-Do8X5Q7k.mjs";import{defineCollections as n}from"../packem_shared/defineCollections-CuRzO6gd.mjs";export{t as createCheckpointRegistry,n as defineCollections,r as lunoraCollectionOptions};
1
+ import{createCheckpointRegistry as t,lunoraCollectionOptions as r}from"../packem_shared/CHECKPOINT_FALLBACK_MS-Dnkx44kO.mjs";import{defineCollections as n}from"../packem_shared/defineCollections-D4Y0GiBS.mjs";export{t as createCheckpointRegistry,n as defineCollections,r as lunoraCollectionOptions};
package/dist/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Collection } from '@tanstack/db';
2
- import { R as Row } from "./packem_shared/collection-options.d-BbEYKjp2.mjs";
3
- export { C as CHECKPOINT_FALLBACK_MS, type a as CheckpointFallbackEvent, type b as CheckpointRegistry, type c as CheckpointRegistryOptions, type d as CheckpointRegistryStats, type e as CheckpointWatermark, type E as ExecutorOutboxSinkOptions, type L as LunoraCollectionConfig, type f as LunoraCollectionOptions, O as OUTBOX_MUTATION_FN_NAME, type g as OutboxExecutor, type h as OutboxMutationMetadata, type S as SyncWriter, i as createCheckpointRegistry, j as createExecutorOutboxSink, k as createOptimisticOnlineDetector, l as getShardCheckpoints, m as lunoraCollectionOptions, n as makeDiffEmit, r as releaseShardCheckpoints, o as runOutboxMutation, t as toMap } from "./packem_shared/collection-options.d-BbEYKjp2.mjs";
4
- export { type C as CollectionDef, type D as DefineCollectionsOptions, type I as InsertBinding, type L as LunoraDb, type W as WriteRejectedEvent, d as defineCollections } from "./packem_shared/index.d-cl7LWrQo.mjs";
5
- export { type B as BindMutatorsContext, type a as BoundMutatorApi, type b as BoundMutators, type C as ClientMutatorContext, type c as ClientMutatorDef, type d as CollectionMap, D as DIRECT_TRANSACTION_METADATA_KEY, type M as MutatorReference, type e as MutatorRejectedEvent, f as bindMutators, g as defineMutator, i as initMutators } from "./packem_shared/index.d-CCVTzFFn.mjs";
2
+ import { R as Row } from "./packem_shared/collection-options.d-C2FdJw06.mjs";
3
+ export { C as CHECKPOINT_FALLBACK_MS, type a as CheckpointFallbackEvent, type b as CheckpointRegistry, type c as CheckpointRegistryOptions, type d as CheckpointRegistryStats, type e as CheckpointWatermark, type E as ExecutorOutboxSinkOptions, type L as LunoraCollectionConfig, type f as LunoraCollectionOptions, type g as LunoraCollectionUtils, O as OUTBOX_MUTATION_FN_NAME, type h as OutboxExecutor, type i as OutboxMutationMetadata, type S as SyncWriter, j as createCheckpointRegistry, k as createExecutorOutboxSink, l as createOptimisticOnlineDetector, m as getShardCheckpoints, n as lunoraCollectionOptions, o as makeDiffEmit, r as releaseShardCheckpoints, p as runOutboxMutation, t as toMap } from "./packem_shared/collection-options.d-C2FdJw06.mjs";
4
+ export { type C as CollectionDef, type D as DefineCollectionsOptions, type I as InsertBinding, type L as LunoraDb, type W as WriteRejectedEvent, d as defineCollections } from "./packem_shared/index.d-B_2dXw1Z.mjs";
5
+ export { type B as BindMutatorsContext, type a as BoundMutatorApi, type b as BoundMutators, type C as ClientMutatorContext, type c as ClientMutatorDef, type d as CollectionMap, D as DIRECT_TRANSACTION_METADATA_KEY, type M as MutatorReference, type e as MutatorRejectedEvent, f as bindMutators, g as defineMutator, i as initMutators } from "./packem_shared/index.d-9usNsVAH.mjs";
6
6
  import '@lunora/client';
7
7
  import '@tanstack/offline-transactions';
8
8
  /** One row to insert. `_id` may be pre-minted client-side so the optimistic row keys match the persisted one. */
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Collection } from '@tanstack/db';
2
- import { R as Row } from "./packem_shared/collection-options.d-BbEYKjp2.js";
3
- export { C as CHECKPOINT_FALLBACK_MS, type a as CheckpointFallbackEvent, type b as CheckpointRegistry, type c as CheckpointRegistryOptions, type d as CheckpointRegistryStats, type e as CheckpointWatermark, type E as ExecutorOutboxSinkOptions, type L as LunoraCollectionConfig, type f as LunoraCollectionOptions, O as OUTBOX_MUTATION_FN_NAME, type g as OutboxExecutor, type h as OutboxMutationMetadata, type S as SyncWriter, i as createCheckpointRegistry, j as createExecutorOutboxSink, k as createOptimisticOnlineDetector, l as getShardCheckpoints, m as lunoraCollectionOptions, n as makeDiffEmit, r as releaseShardCheckpoints, o as runOutboxMutation, t as toMap } from "./packem_shared/collection-options.d-BbEYKjp2.js";
4
- export { type C as CollectionDef, type D as DefineCollectionsOptions, type I as InsertBinding, type L as LunoraDb, type W as WriteRejectedEvent, d as defineCollections } from "./packem_shared/index.d-G0N0-lGJ.js";
5
- export { type B as BindMutatorsContext, type a as BoundMutatorApi, type b as BoundMutators, type C as ClientMutatorContext, type c as ClientMutatorDef, type d as CollectionMap, D as DIRECT_TRANSACTION_METADATA_KEY, type M as MutatorReference, type e as MutatorRejectedEvent, f as bindMutators, g as defineMutator, i as initMutators } from "./packem_shared/index.d-DCVj2sHQ.js";
2
+ import { R as Row } from "./packem_shared/collection-options.d-C2FdJw06.js";
3
+ export { C as CHECKPOINT_FALLBACK_MS, type a as CheckpointFallbackEvent, type b as CheckpointRegistry, type c as CheckpointRegistryOptions, type d as CheckpointRegistryStats, type e as CheckpointWatermark, type E as ExecutorOutboxSinkOptions, type L as LunoraCollectionConfig, type f as LunoraCollectionOptions, type g as LunoraCollectionUtils, O as OUTBOX_MUTATION_FN_NAME, type h as OutboxExecutor, type i as OutboxMutationMetadata, type S as SyncWriter, j as createCheckpointRegistry, k as createExecutorOutboxSink, l as createOptimisticOnlineDetector, m as getShardCheckpoints, n as lunoraCollectionOptions, o as makeDiffEmit, r as releaseShardCheckpoints, p as runOutboxMutation, t as toMap } from "./packem_shared/collection-options.d-C2FdJw06.js";
4
+ export { type C as CollectionDef, type D as DefineCollectionsOptions, type I as InsertBinding, type L as LunoraDb, type W as WriteRejectedEvent, d as defineCollections } from "./packem_shared/index.d-ypscb9Qp.js";
5
+ export { type B as BindMutatorsContext, type a as BoundMutatorApi, type b as BoundMutators, type C as ClientMutatorContext, type c as ClientMutatorDef, type d as CollectionMap, D as DIRECT_TRANSACTION_METADATA_KEY, type M as MutatorReference, type e as MutatorRejectedEvent, f as bindMutators, g as defineMutator, i as initMutators } from "./packem_shared/index.d-t0PhXOHV.js";
6
6
  import '@lunora/client';
7
7
  import '@tanstack/offline-transactions';
8
8
  /** One row to insert. `_id` may be pre-minted client-side so the optimistic row keys match the persisted one. */
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{applyPlanToCollections as r,applyPlanToDb as i}from"./packem_shared/applyPlanToCollections-DxxdLRGe.mjs";import{CHECKPOINT_FALLBACK_MS as a,createCheckpointRegistry as p,getShardCheckpoints as c,lunoraCollectionOptions as l,releaseShardCheckpoints as s}from"./packem_shared/CHECKPOINT_FALLBACK_MS-Do8X5Q7k.mjs";import{defineCollections as O}from"./packem_shared/defineCollections-CuRzO6gd.mjs";import{DIRECT_TRANSACTION_METADATA_KEY as f,bindMutators as u,defineMutator as x,initMutators as A}from"./packem_shared/DIRECT_TRANSACTION_METADATA_KEY-CCBmcauu.mjs";import{OUTBOX_MUTATION_FN_NAME as m,createExecutorOutboxSink as E,createOptimisticOnlineDetector as _,makeDiffEmit as N,runOutboxMutation as S,toMap as d}from"./packem_shared/OUTBOX_MUTATION_FN_NAME-rGyegnLw.mjs";const t="0.0.0";export{a as CHECKPOINT_FALLBACK_MS,f as DIRECT_TRANSACTION_METADATA_KEY,m as OUTBOX_MUTATION_FN_NAME,t as VERSION,r as applyPlanToCollections,i as applyPlanToDb,u as bindMutators,p as createCheckpointRegistry,E as createExecutorOutboxSink,_ as createOptimisticOnlineDetector,O as defineCollections,x as defineMutator,c as getShardCheckpoints,A as initMutators,l as lunoraCollectionOptions,N as makeDiffEmit,s as releaseShardCheckpoints,S as runOutboxMutation,d as toMap};
1
+ import{applyPlanToCollections as r,applyPlanToDb as i}from"./packem_shared/applyPlanToCollections-DxxdLRGe.mjs";import{CHECKPOINT_FALLBACK_MS as a,createCheckpointRegistry as p,getShardCheckpoints as c,lunoraCollectionOptions as l,releaseShardCheckpoints as s}from"./packem_shared/CHECKPOINT_FALLBACK_MS-Dnkx44kO.mjs";import{defineCollections as O}from"./packem_shared/defineCollections-D4Y0GiBS.mjs";import{DIRECT_TRANSACTION_METADATA_KEY as f,bindMutators as u,defineMutator as x,initMutators as A}from"./packem_shared/DIRECT_TRANSACTION_METADATA_KEY-BGf7W7d4.mjs";import{OUTBOX_MUTATION_FN_NAME as m,createExecutorOutboxSink as E,createOptimisticOnlineDetector as _,makeDiffEmit as N,runOutboxMutation as S,toMap as d}from"./packem_shared/OUTBOX_MUTATION_FN_NAME-rGyegnLw.mjs";const t="0.0.0";export{a as CHECKPOINT_FALLBACK_MS,f as DIRECT_TRANSACTION_METADATA_KEY,m as OUTBOX_MUTATION_FN_NAME,t as VERSION,r as applyPlanToCollections,i as applyPlanToDb,u as bindMutators,p as createCheckpointRegistry,E as createExecutorOutboxSink,_ as createOptimisticOnlineDetector,O as defineCollections,x as defineMutator,c as getShardCheckpoints,A as initMutators,l as lunoraCollectionOptions,N as makeDiffEmit,s as releaseShardCheckpoints,S as runOutboxMutation,d as toMap};
@@ -1,5 +1,5 @@
1
- export { type B as BindMutatorsContext, type a as BoundMutatorApi, type b as BoundMutators, type C as ClientMutatorContext, type c as ClientMutatorDef, type d as CollectionMap, type e as MutatorRejectedEvent, f as bindMutators, g as defineMutator, i as initMutators } from "../packem_shared/index.d-CCVTzFFn.mjs";
1
+ export { type B as BindMutatorsContext, type a as BoundMutatorApi, type b as BoundMutators, type C as ClientMutatorContext, type c as ClientMutatorDef, type d as CollectionMap, type e as MutatorRejectedEvent, f as bindMutators, g as defineMutator, i as initMutators } from "../packem_shared/index.d-9usNsVAH.mjs";
2
2
  import '@lunora/client';
3
3
  import '@tanstack/db';
4
- import "../packem_shared/collection-options.d-BbEYKjp2.mjs";
4
+ import "../packem_shared/collection-options.d-C2FdJw06.mjs";
5
5
  import '@tanstack/offline-transactions';
@@ -1,5 +1,5 @@
1
- export { type B as BindMutatorsContext, type a as BoundMutatorApi, type b as BoundMutators, type C as ClientMutatorContext, type c as ClientMutatorDef, type d as CollectionMap, type e as MutatorRejectedEvent, f as bindMutators, g as defineMutator, i as initMutators } from "../packem_shared/index.d-DCVj2sHQ.js";
1
+ export { type B as BindMutatorsContext, type a as BoundMutatorApi, type b as BoundMutators, type C as ClientMutatorContext, type c as ClientMutatorDef, type d as CollectionMap, type e as MutatorRejectedEvent, f as bindMutators, g as defineMutator, i as initMutators } from "../packem_shared/index.d-t0PhXOHV.js";
2
2
  import '@lunora/client';
3
3
  import '@tanstack/db';
4
- import "../packem_shared/collection-options.d-BbEYKjp2.js";
4
+ import "../packem_shared/collection-options.d-C2FdJw06.js";
5
5
  import '@tanstack/offline-transactions';
@@ -1 +1 @@
1
- import{bindMutators as r,defineMutator as i,initMutators as a}from"../packem_shared/DIRECT_TRANSACTION_METADATA_KEY-CCBmcauu.mjs";export{r as bindMutators,i as defineMutator,a as initMutators};
1
+ import{bindMutators as r,defineMutator as i,initMutators as a}from"../packem_shared/DIRECT_TRANSACTION_METADATA_KEY-BGf7W7d4.mjs";export{r as bindMutators,i as defineMutator,a as initMutators};
@@ -0,0 +1 @@
1
+ import{LunoraError as K}from"@lunora/errors";import{BTreeIndex as W}from"@tanstack/db";import{toMap as x,makeDiffEmit as O}from"./OUTBOX_MUTATION_FN_NAME-rGyegnLw.mjs";const $=()=>{let e;const o=new Set;return{setError:t=>{if(e!==t){e=t;for(const r of o)r()}},utils:{error:()=>e,isError:()=>e!==void 0,subscribeError:t=>(o.add(t),()=>{o.delete(t)})}}},T=()=>{let e=Number.NEGATIVE_INFINITY;const o=[];return{advance:t=>{if(!(t<=e)){e=t;for(let r=o.length-1;r>=0;r-=1){const i=o[r];i&&i.threshold<=e&&(i.resolve(),o.splice(r,1))}}},await:t=>t<=e?Promise.resolve():new Promise(r=>{o.push({resolve:r,threshold:t})}),passed:t=>t<=e,reset:()=>{for(const t of o.splice(0))t.resolve();e=Number.NEGATIVE_INFINITY},waiting:()=>o.length}};let F=!1;const G=e=>{F||(F=!0,console.warn(`[@lunora/db] released an optimistic overlay via the ${String(e.waitedMs)}ms checkpoint fallback: the server confirmed ${e.kind} ${String(e.watermark)} but no sync frame ever echoed it. A dropped shape poke or \`settled\` frame is the usual cause — inspect the subscription rather than raising \`fallbackMs\`. (Reported once per process.)`))},g=new WeakMap,R=new WeakMap,y=new WeakMap,C=new WeakMap,L=e=>{const o=(y.get(e)??0)-1;if(o>0){y.set(e,o);return}y.delete(e),C.get(e)?.()},A=new WeakSet,P=e=>{const o={acknowledge:t=>{e().acknowledge(t)},awaitCheckpoint:async t=>e().awaitCheckpoint(t),awaitMutationId:async t=>e().awaitMutationId(t),dispose:()=>{e().dispose()},resolve:t=>{e().resolve(t)},stats:()=>e().stats()};return A.add(o),o},V=3e3,Y=(e={})=>{const o=e.fallbackMs??V,t=e.onFallback??G,r=T(),i=T();let l=0;const d=new Set,f=(s,n)=>{for(const c of d)c.kind===s&&c.threshold<=n&&(clearTimeout(c.handle),d.delete(c))},u=(s,n)=>{if(o<=0)return;const c=s==="checkpoint"?r:i;if(c.passed(n))return;for(const p of d)if(p.kind===s&&p.threshold>=n)return;const k={handle:setTimeout(()=>{if(d.delete(k),!c.passed(n)){l+=1,c.advance(n);try{t({kind:s,waitedMs:o,watermark:n})}catch{}}},o),kind:s,threshold:n};d.add(k)},v={acknowledge:({checkpoint:s,mutationId:n})=>{s!==void 0&&u("checkpoint",s),n!==void 0&&u("mutationId",n)},awaitCheckpoint:s=>r.await(s),awaitMutationId:s=>i.await(s),dispose:()=>{for(const s of d)clearTimeout(s.handle);d.clear()},resolve:({checkpoint:s,mutationId:n})=>{s!==void 0&&(r.advance(s),f("checkpoint",s)),n!==void 0&&(i.advance(n),f("mutationId",n))},stats:()=>({fallbacks:l,pendingCheckpointWaiters:r.waiting(),pendingMutationWaiters:i.waiting()})};return C.set(v,()=>{v.dispose(),r.reset(),i.reset()}),v},z=e=>{const o=g.get(e);if(o){for(const t of o.values())t.resolve({checkpoint:Number.POSITIVE_INFINITY,mutationId:Number.POSITIVE_INFINITY}),t.dispose();g.delete(e)}},D=e=>{const o=e.currentIdentity();if(g.has(e)&&R.get(e)!==o)for(const t of g.get(e)?.values()??[])C.get(t)?.();R.set(e,o)},H=(e,o,t)=>{D(e);let r=g.get(e);r||(r=new Map,g.set(e,r));const i=o??"",l=r.get(i);if(l)return l;const d=Y(t);return r.set(i,d),d},U=(e,o,t)=>{const r=o[e];if(typeof r=="string"||typeof r=="number")return String(r);throw new K("BAD_REQUEST",`@lunora/db: ${t} has no "${e}" — a \`scopeBy\` collection routes by that field's value`)},X=e=>A.has(e),J=e=>{y.set(e,(y.get(e)??0)+1)},Z=e=>(y.get(e)??0)>0,ee=e=>{if(e.list===void 0==(e.shape===void 0))throw new K("INTERNAL","lunoraCollectionOptions: pass exactly one of `list` or `shape`");const o=e.getKey??(a=>a._id),t=e.shape?.shardKey??e.shardKey,r=e.scopeBy!==void 0&&t===void 0;let i;const l=()=>t??i,d=()=>e.checkpoints??H(e.client,l());let f;const u=()=>{const a=d();return a!==f&&(f=a,J(a)),a},v=()=>{f!==void 0&&e.checkpoints===void 0&&L(f),f=void 0};r||u();const s=new Map;let n,c,k;const{setError:p,utils:E}=$();let b,I;const S=(a,m)=>{u();const w=h=>{p(void 0),n?.(x(h,o)),m?.(),e.shape===void 0&&(u().resolve({mutationId:I??e.client.confirmedMutationWatermark(l())}),I=void 0)},M=h=>k?.(h),N=h=>{h.rowsFollow===!0&&h.mutationId!==void 0&&(I=h.mutationId),u().resolve(h)};return e.shape!==void 0?e.client.subscribeShape({args:a,name:e.shape.name},w,{onCheckpoint:N,onError:M,shardKey:l()}):e.client.subscribe(e.list,a,w,{onCheckpoint:N,onError:M,shardKey:l()})},_={autoIndex:"eager",defaultIndexType:W,getKey:o,id:e.id??e.list?.__lunoraRef??`shape:${e.shape?.name??""}`,utils:E,...e.load==="eager"?{startSync:!0}:{},sync:{sync:a=>(n=O(s,a),k=w=>{p(w),a.markReady(),e.onError?.(w)},e.scopeBy===void 0?c=S(e.shape?.args??{},()=>{a.markReady()}):(a.markReady(),b!==void 0&&(c=S(b,void 0))),()=>{n=void 0,k=void 0,p(void 0),v(),c?.(),c=void 0,s.clear()})}},B=a=>{if(e.scopeBy===void 0)return;const m=r&&a!==void 0?U(e.scopeBy,a,"scope args"):i;r&&(a===void 0||m!==i)&&v(),b=a,i=m,c?.(),c=void 0,p(void 0),I=void 0,n?.(new Map),a!==void 0&&n!==void 0&&(c=S(a,void 0))};return{checkpoints:r&&e.checkpoints===void 0?P(d):d(),config:_,scope:B,utils:E}};export{V as CHECKPOINT_FALLBACK_MS,Y as createCheckpointRegistry,H as getShardCheckpoints,Z as hasCheckpointsAttached,X as isScopeFollowingCheckpoints,ee as lunoraCollectionOptions,J as markCheckpointsAttached,z as releaseShardCheckpoints,U as scopedShardKey,D as syncShardCheckpointIdentity};
@@ -1 +1 @@
1
- import{isAuthReplayFailure as C}from"@lunora/client";import{LunoraError as d}from"@lunora/errors";import{createTransaction as E}from"@tanstack/db";import{isScopeFollowingCheckpoints as R,scopedShardKey as A,getShardCheckpoints as I,hasCheckpointsAttached as T,syncShardCheckpointIdentity as g}from"./CHECKPOINT_FALLBACK_MS-Do8X5Q7k.mjs";import{assertSecureRandom as b,runOutboxMutation as N,toNonRetriable as B}from"./OUTBOX_MUTATION_FN_NAME-rGyegnLw.mjs";const O="__tanstack_db_direct",F="defineMutator: `serverRef` must be a generated mutator reference (api.mutators.*) or a 'namespace:fn' string",j=r=>{const e=typeof r=="string"?r:r?.__lunoraRef;if(typeof e!="string"||e.length===0)throw new d("INTERNAL",F);return e},q=r=>({__lunoraClientMutator:!0,apply:r.apply,serverRef:j(r.serverRef)}),D=(r,e,k)=>{b("bindMutators");const h=32;if(e.checkpoints&&R(e.checkpoints)&&e.scopeBy===void 0&&e.shardKey===void 0)throw new d("BAD_REQUEST","bindMutators: `checkpoints` from a `scopeBy` collection needs the same `scopeBy` (or a pinned `shardKey`) here, so each push reaches the shard it gates on");const w=t=>e.shardKey??(e.scopeBy===void 0?void 0:A(e.scopeBy,t,"the mutator args")),u=new Map;let m=r.currentIdentity();const f=()=>{g(r);const t=r.currentIdentity();t!==m&&(u.clear(),m=t)},v=t=>{f();const o=Math.max(u.get(t??"")??0,r.confirmedMutationWatermark(t))+1;return u.set(t??"",o),o};let l=Promise.resolve();const M=(t,o,n)=>{const c=l.then(async()=>{for(let i=0;;i+=1){const a=v(n);try{const{applied:s}=await r.callMutator(t,o,{clientSeq:a,shardKey:n});if(s)return a}catch(s){throw f(),u.set(n??"",r.confirmedMutationWatermark(n)),s}if(i>=h)throw new d("INTERNAL",`lunora: custom mutator "${t}" could not claim a fresh client sequence after ${String(h)} attempts`)}});return l=c.then(()=>{},()=>{}),c},_=t=>{if(e.checkpoints===!1)return;if(e.checkpoints&&!R(e.checkpoints))return e.checkpoints;const o=I(r,t);return T(o)?o:void 0},S=(t,o,n,c)=>{const{onWriteRejected:i}=e;i&&t.isPersisted.promise.catch(a=>{const s=a instanceof Error?a:new Error(String(a));try{i({args:c,code:s.code,error:s,mutator:o,serverRef:n})}catch{}})},y={};for(const[t,o]of Object.entries(k))y[t]=n=>{const c=w(n),i=E({autoCommit:!0,metadata:{[O]:!0,serverRef:o.serverRef},mutationFn:async()=>{let a=0;try{await N(async()=>{a=await M(o.serverRef,n,c)})}catch(p){throw C(p)?B(p):p}const s=_(c);s&&(s.acknowledge({mutationId:a}),await s.awaitMutationId(a))}});return i.mutate(()=>{o.apply({collections:e.collections},n)}),S(i,t,o.serverRef,n),i};return y},z=()=>({bindMutators:D,defineMutator:q});export{O as DIRECT_TRANSACTION_METADATA_KEY,D as bindMutators,q as defineMutator,z as initMutators};
1
+ import{isAuthReplayFailure as C}from"@lunora/client";import{LunoraError as d}from"@lunora/errors";import{createTransaction as E}from"@tanstack/db";import{isScopeFollowingCheckpoints as R,scopedShardKey as A,getShardCheckpoints as I,hasCheckpointsAttached as T,syncShardCheckpointIdentity as g}from"./CHECKPOINT_FALLBACK_MS-Dnkx44kO.mjs";import{assertSecureRandom as b,runOutboxMutation as N,toNonRetriable as B}from"./OUTBOX_MUTATION_FN_NAME-rGyegnLw.mjs";const O="__tanstack_db_direct",F="defineMutator: `serverRef` must be a generated mutator reference (api.mutators.*) or a 'namespace:fn' string",j=r=>{const e=typeof r=="string"?r:r?.__lunoraRef;if(typeof e!="string"||e.length===0)throw new d("INTERNAL",F);return e},q=r=>({__lunoraClientMutator:!0,apply:r.apply,serverRef:j(r.serverRef)}),D=(r,e,k)=>{b("bindMutators");const h=32;if(e.checkpoints&&R(e.checkpoints)&&e.scopeBy===void 0&&e.shardKey===void 0)throw new d("BAD_REQUEST","bindMutators: `checkpoints` from a `scopeBy` collection needs the same `scopeBy` (or a pinned `shardKey`) here, so each push reaches the shard it gates on");const w=t=>e.shardKey??(e.scopeBy===void 0?void 0:A(e.scopeBy,t,"the mutator args")),u=new Map;let m=r.currentIdentity();const f=()=>{g(r);const t=r.currentIdentity();t!==m&&(u.clear(),m=t)},v=t=>{f();const o=Math.max(u.get(t??"")??0,r.confirmedMutationWatermark(t))+1;return u.set(t??"",o),o};let l=Promise.resolve();const M=(t,o,n)=>{const c=l.then(async()=>{for(let i=0;;i+=1){const a=v(n);try{const{applied:s}=await r.callMutator(t,o,{clientSeq:a,shardKey:n});if(s)return a}catch(s){throw f(),u.set(n??"",r.confirmedMutationWatermark(n)),s}if(i>=h)throw new d("INTERNAL",`lunora: custom mutator "${t}" could not claim a fresh client sequence after ${String(h)} attempts`)}});return l=c.then(()=>{},()=>{}),c},_=t=>{if(e.checkpoints===!1)return;if(e.checkpoints&&!R(e.checkpoints))return e.checkpoints;const o=I(r,t);return T(o)?o:void 0},S=(t,o,n,c)=>{const{onWriteRejected:i}=e;i&&t.isPersisted.promise.catch(a=>{const s=a instanceof Error?a:new Error(String(a));try{i({args:c,code:s.code,error:s,mutator:o,serverRef:n})}catch{}})},y={};for(const[t,o]of Object.entries(k))y[t]=n=>{const c=w(n),i=E({autoCommit:!0,metadata:{[O]:!0,serverRef:o.serverRef},mutationFn:async()=>{let a=0;try{await N(async()=>{a=await M(o.serverRef,n,c)})}catch(p){throw C(p)?B(p):p}const s=_(c);s&&(s.acknowledge({mutationId:a}),await s.awaitMutationId(a))}});return i.mutate(()=>{o.apply({collections:e.collections},n)}),S(i,t,o.serverRef,n),i};return y},z=()=>({bindMutators:D,defineMutator:q});export{O as DIRECT_TRANSACTION_METADATA_KEY,D as bindMutators,q as defineMutator,z as initMutators};
@@ -1,6 +1,21 @@
1
- import { OutboxSink, LunoraClient, FunctionReference, SubscriptionError } from '@lunora/client';
1
+ import { SubscriptionError, OutboxSink, LunoraClient, FunctionReference } from '@lunora/client';
2
2
  import { CollectionConfig } from '@tanstack/db';
3
3
  import { OnlineDetector } from '@tanstack/offline-transactions';
4
+ /**
5
+ * What a collection exposes about its subscription's health, as `collection.utils`.
6
+ *
7
+ * A rejected subscription still moves the collection out of `loading` (so it never
8
+ * hangs there), which on its own is indistinguishable from a successful load that
9
+ * found no rows. This is the difference: `isError()` stays true until rows arrive.
10
+ */
11
+ interface LunoraCollectionUtils {
12
+ /** The last subscription error, or `undefined` once rows have arrived since (or before any error). */
13
+ error: () => SubscriptionError | undefined;
14
+ /** Whether the subscription is currently failing. */
15
+ isError: () => boolean;
16
+ /** Listen for the error state changing; returns the unsubscribe. Shaped for `useSyncExternalStore`. */
17
+ subscribeError: (listener: () => void) => () => void;
18
+ }
4
19
  /**
5
20
  * Reserved `mutationFns` key the unified outbox routes raw `client.mutation`
6
21
  * offline writes through. `defineCollections` registers a handler under this
@@ -378,6 +393,8 @@ interface LunoraCollectionOptions<TRow extends Row> {
378
393
  config: CollectionConfig<TRow, string>;
379
394
  /** Re-point a `scopeBy` collection's subscription (omit `args` to detach). No-op for unscoped collections. */
380
395
  scope: (args?: Record<string, unknown>) => void;
396
+ /** Subscription health; the same object is on the created collection as `collection.utils`. */
397
+ utils: LunoraCollectionUtils;
381
398
  }
382
399
  /**
383
400
  * Build a TanStack DB collection config (+ sync controls) that live-syncs a
@@ -391,4 +408,4 @@ interface LunoraCollectionOptions<TRow extends Row> {
391
408
  * overlays against confirmed server watermarks (see {@link CheckpointRegistry}).
392
409
  */
393
410
  declare const lunoraCollectionOptions: <TRow extends Row>(options: LunoraCollectionConfig<TRow>) => LunoraCollectionOptions<TRow>;
394
- export { CHECKPOINT_FALLBACK_MS as C, ExecutorOutboxSinkOptions as E, LunoraCollectionConfig as L, OUTBOX_MUTATION_FN_NAME as O, Row as R, SyncWriter as S, CheckpointFallbackEvent as a, CheckpointRegistry as b, CheckpointRegistryOptions as c, CheckpointRegistryStats as d, CheckpointWatermark as e, LunoraCollectionOptions as f, OutboxExecutor as g, OutboxMutationMetadata as h, createCheckpointRegistry as i, createExecutorOutboxSink as j, createOptimisticOnlineDetector as k, getShardCheckpoints as l, lunoraCollectionOptions as m, makeDiffEmit as n, runOutboxMutation as o, releaseShardCheckpoints as r, toMap as t };
411
+ export { CHECKPOINT_FALLBACK_MS as C, ExecutorOutboxSinkOptions as E, LunoraCollectionConfig as L, OUTBOX_MUTATION_FN_NAME as O, Row as R, SyncWriter as S, CheckpointFallbackEvent as a, CheckpointRegistry as b, CheckpointRegistryOptions as c, CheckpointRegistryStats as d, CheckpointWatermark as e, LunoraCollectionOptions as f, LunoraCollectionUtils as g, OutboxExecutor as h, OutboxMutationMetadata as i, createCheckpointRegistry as j, createExecutorOutboxSink as k, createOptimisticOnlineDetector as l, getShardCheckpoints as m, lunoraCollectionOptions as n, makeDiffEmit as o, runOutboxMutation as p, releaseShardCheckpoints as r, toMap as t };
@@ -1,6 +1,21 @@
1
- import { OutboxSink, LunoraClient, FunctionReference, SubscriptionError } from '@lunora/client';
1
+ import { SubscriptionError, OutboxSink, LunoraClient, FunctionReference } from '@lunora/client';
2
2
  import { CollectionConfig } from '@tanstack/db';
3
3
  import { OnlineDetector } from '@tanstack/offline-transactions';
4
+ /**
5
+ * What a collection exposes about its subscription's health, as `collection.utils`.
6
+ *
7
+ * A rejected subscription still moves the collection out of `loading` (so it never
8
+ * hangs there), which on its own is indistinguishable from a successful load that
9
+ * found no rows. This is the difference: `isError()` stays true until rows arrive.
10
+ */
11
+ interface LunoraCollectionUtils {
12
+ /** The last subscription error, or `undefined` once rows have arrived since (or before any error). */
13
+ error: () => SubscriptionError | undefined;
14
+ /** Whether the subscription is currently failing. */
15
+ isError: () => boolean;
16
+ /** Listen for the error state changing; returns the unsubscribe. Shaped for `useSyncExternalStore`. */
17
+ subscribeError: (listener: () => void) => () => void;
18
+ }
4
19
  /**
5
20
  * Reserved `mutationFns` key the unified outbox routes raw `client.mutation`
6
21
  * offline writes through. `defineCollections` registers a handler under this
@@ -378,6 +393,8 @@ interface LunoraCollectionOptions<TRow extends Row> {
378
393
  config: CollectionConfig<TRow, string>;
379
394
  /** Re-point a `scopeBy` collection's subscription (omit `args` to detach). No-op for unscoped collections. */
380
395
  scope: (args?: Record<string, unknown>) => void;
396
+ /** Subscription health; the same object is on the created collection as `collection.utils`. */
397
+ utils: LunoraCollectionUtils;
381
398
  }
382
399
  /**
383
400
  * Build a TanStack DB collection config (+ sync controls) that live-syncs a
@@ -391,4 +408,4 @@ interface LunoraCollectionOptions<TRow extends Row> {
391
408
  * overlays against confirmed server watermarks (see {@link CheckpointRegistry}).
392
409
  */
393
410
  declare const lunoraCollectionOptions: <TRow extends Row>(options: LunoraCollectionConfig<TRow>) => LunoraCollectionOptions<TRow>;
394
- export { CHECKPOINT_FALLBACK_MS as C, ExecutorOutboxSinkOptions as E, LunoraCollectionConfig as L, OUTBOX_MUTATION_FN_NAME as O, Row as R, SyncWriter as S, CheckpointFallbackEvent as a, CheckpointRegistry as b, CheckpointRegistryOptions as c, CheckpointRegistryStats as d, CheckpointWatermark as e, LunoraCollectionOptions as f, OutboxExecutor as g, OutboxMutationMetadata as h, createCheckpointRegistry as i, createExecutorOutboxSink as j, createOptimisticOnlineDetector as k, getShardCheckpoints as l, lunoraCollectionOptions as m, makeDiffEmit as n, runOutboxMutation as o, releaseShardCheckpoints as r, toMap as t };
411
+ export { CHECKPOINT_FALLBACK_MS as C, ExecutorOutboxSinkOptions as E, LunoraCollectionConfig as L, OUTBOX_MUTATION_FN_NAME as O, Row as R, SyncWriter as S, CheckpointFallbackEvent as a, CheckpointRegistry as b, CheckpointRegistryOptions as c, CheckpointRegistryStats as d, CheckpointWatermark as e, LunoraCollectionOptions as f, LunoraCollectionUtils as g, OutboxExecutor as h, OutboxMutationMetadata as i, createCheckpointRegistry as j, createExecutorOutboxSink as k, createOptimisticOnlineDetector as l, getShardCheckpoints as m, lunoraCollectionOptions as n, makeDiffEmit as o, runOutboxMutation as p, releaseShardCheckpoints as r, toMap as t };
@@ -1 +1 @@
1
- import{lunoraCollectionOptions as I,scopedShardKey as R}from"./CHECKPOINT_FALLBACK_MS-Do8X5Q7k.mjs";import{isAuthReplayFailure as M}from"@lunora/client";import{createCollection as D,safeRandomUUID as U}from"@tanstack/db";import{startOfflineExecutor as j,NonRetriableError as q}from"@tanstack/offline-transactions";import{assertSecureRandom as L,createOutboxCarrier as k,createOptimisticOnlineDetector as W,OUTBOX_MUTATION_FN_NAME as T,registerOutboxCarrier as $,takeOutboxRejection as S,toNonRetriable as _,runOutboxMutation as H,terminalVerdict as P}from"./OUTBOX_MUTATION_FN_NAME-rGyegnLw.mjs";const A=new WeakMap,V=(o,a)=>{let r=A.get(o);r===void 0&&(r=new Map,A.set(o,r));const c=r.get(a)??0;r.set(a,c+1),c===1&&console.warn(`[@lunora/db] table "${a}" is bound by more than one defineCollections call on this client. Each call creates its own live collection and outbox for the table, so the two can drift and derived indexes built from one can silently read stale rows. Bind every table in a single defineCollections call (see the "One source of truth per table" docs section).`)},K=(o,a)=>{try{o.onWriteRejected?.(a)}catch{}},G=(o,a)=>{const r=o.replayIdentityVerdict(a?.identity);if(r.verdict==="mismatch")throw new q("outbox write dropped: identity changed since it was queued");if(r.verdict==="unknown")throw new Error("outbox write deferred: no identity established yet");return r.credential},X=6e4,z=[2e3,5e3,1e4,2e4,4e4],J=(o,a,r)=>{if(a!==o.refused)return"send";const c=r-o.since;if(c>=X)return"expired";const d=o.refused===null?z[o.resends]:void 0;return d!==void 0&&c>=d?"send":"wait"},oe=(o,a,r={})=>{L("defineCollections");const c={},d=new Map,O=async(t,e,i)=>{const n=d.get(t),f=n===void 0?"send":J(n,o.getAuthToken(),Date.now());if(f==="expired")throw d.delete(t),_(n?.error);if(f==="wait")throw new Error("outbox write deferred: waiting for a fresh credential");const l=o.getAuthToken(),u=G(o,e);try{await H(async()=>i(u))}catch(s){if(!M(s))throw s;const y=n?.refused===null&&l===null;throw n!==void 0&&!y?(d.delete(t),_(s)):(d.set(t,{error:s,refused:l,resends:n===void 0?0:n.resends+1,since:n?.since??Date.now()}),new Error("outbox write deferred: its credential was refused",{cause:s}))}d.delete(t)},x=(t,e)=>{const i=P(e);return i!==void 0&&d.delete(t),i},E={},p={},B=Object.entries(a);for(const[t,e]of B){const i=e.insert;V(o,t);const{config:n,scope:f}=I({client:o,getKey:e.getKey,id:t,list:e.list,...e.load===void 0?{}:{load:e.load},onError:e.onError,scopeBy:e.scopeBy,shardKey:e.shardKey});c[t]=D(n),e.scopeBy!==void 0&&(E[t]=f),i&&(p[t]=async({idempotencyKey:l,transaction:u})=>{const s=u.metadata,y=s!==void 0&&s.shardKey===void 0&&e.shardKey===void 0&&e.scopeBy!==void 0;for(const[w,g]of u.mutations.entries()){const b=g.modified,v=`${l}:${String(w)}`;try{await O(v,s,async m=>o.mutation(i.mutation,i.toArgs(b),{mutationId:v,replayBaseline:y?null:s?.baselineSeq??null,replayCredential:m,shardKey:y?R(e.scopeBy,b,"the queued row"):s?.shardKey}))}catch(C){const m=x(v,C);throw m!==void 0?(K(r,{code:m.code,collection:t,error:m,row:b}),m):C}}})}p[T]=async({transaction:t})=>{const e=t.metadata;if(e)try{const i=async n=>o.mutation({__lunoraRef:e.functionPath},e.args,{mutationId:e.idempotencyKey,replayBaseline:e.baselineSeq??null,replayCredential:n,shardKey:e.shardKey});await O(e.idempotencyKey,e,i),S(e.idempotencyKey)}catch(i){const n=x(e.idempotencyKey,i);throw n!==void 0?(S(e.idempotencyKey)?.(),K(r,{code:n.code,collection:e.functionPath,error:n}),n):i}};const F=k(),h=j({collections:{...c,[T]:F},mutationFns:p,onlineDetector:W(),...r.onLeadershipChange?{onLeadershipChange:r.onLeadershipChange}:{},...r.onStorageFailure?{onStorageFailure:r.onStorageFailure}:{},onUnknownMutationFn:(t,e)=>{K(r,{code:"UNKNOWN_MUTATION_FN",collection:t,error:new Error(`offline write dropped: mutation "${t}" no longer exists (removed or renamed in a deploy?)`),row:e.mutations[0]?.modified})}});$(h,F);const N={};for(const[t,e]of B){const i=e.insert,n=c[t];!i||!n||(N[t]=f=>{const l=U(),u=i.optimistic(f,l),s=e.shardKey??(e.scopeBy===void 0?void 0:R(e.scopeBy,u,"the inserted row")),y={baselineSeq:o.currentBaseline(s),identity:o.currentIdentity(),shardKey:s},w=h.createOfflineTransaction({autoCommit:!1,metadata:y,mutationFnName:t}),g=w.mutate(()=>{n.insert(u)});return w.commit().catch(()=>{}),{id:l,transaction:g}})}return{actions:N,collections:c,executor:h,pendingCount:()=>h.getPendingCount(),scope:E}};export{oe as defineCollections};
1
+ import{lunoraCollectionOptions as I,scopedShardKey as R}from"./CHECKPOINT_FALLBACK_MS-Dnkx44kO.mjs";import{isAuthReplayFailure as M}from"@lunora/client";import{createCollection as D,safeRandomUUID as U}from"@tanstack/db";import{startOfflineExecutor as j,NonRetriableError as q}from"@tanstack/offline-transactions";import{assertSecureRandom as L,createOutboxCarrier as k,createOptimisticOnlineDetector as W,OUTBOX_MUTATION_FN_NAME as T,registerOutboxCarrier as $,takeOutboxRejection as S,toNonRetriable as _,runOutboxMutation as H,terminalVerdict as P}from"./OUTBOX_MUTATION_FN_NAME-rGyegnLw.mjs";const A=new WeakMap,V=(o,a)=>{let r=A.get(o);r===void 0&&(r=new Map,A.set(o,r));const c=r.get(a)??0;r.set(a,c+1),c===1&&console.warn(`[@lunora/db] table "${a}" is bound by more than one defineCollections call on this client. Each call creates its own live collection and outbox for the table, so the two can drift and derived indexes built from one can silently read stale rows. Bind every table in a single defineCollections call (see the "One source of truth per table" docs section).`)},K=(o,a)=>{try{o.onWriteRejected?.(a)}catch{}},G=(o,a)=>{const r=o.replayIdentityVerdict(a?.identity);if(r.verdict==="mismatch")throw new q("outbox write dropped: identity changed since it was queued");if(r.verdict==="unknown")throw new Error("outbox write deferred: no identity established yet");return r.credential},X=6e4,z=[2e3,5e3,1e4,2e4,4e4],J=(o,a,r)=>{if(a!==o.refused)return"send";const c=r-o.since;if(c>=X)return"expired";const d=o.refused===null?z[o.resends]:void 0;return d!==void 0&&c>=d?"send":"wait"},oe=(o,a,r={})=>{L("defineCollections");const c={},d=new Map,O=async(t,e,i)=>{const n=d.get(t),f=n===void 0?"send":J(n,o.getAuthToken(),Date.now());if(f==="expired")throw d.delete(t),_(n?.error);if(f==="wait")throw new Error("outbox write deferred: waiting for a fresh credential");const l=o.getAuthToken(),u=G(o,e);try{await H(async()=>i(u))}catch(s){if(!M(s))throw s;const y=n?.refused===null&&l===null;throw n!==void 0&&!y?(d.delete(t),_(s)):(d.set(t,{error:s,refused:l,resends:n===void 0?0:n.resends+1,since:n?.since??Date.now()}),new Error("outbox write deferred: its credential was refused",{cause:s}))}d.delete(t)},x=(t,e)=>{const i=P(e);return i!==void 0&&d.delete(t),i},E={},p={},B=Object.entries(a);for(const[t,e]of B){const i=e.insert;V(o,t);const{config:n,scope:f}=I({client:o,getKey:e.getKey,id:t,list:e.list,...e.load===void 0?{}:{load:e.load},onError:e.onError,scopeBy:e.scopeBy,shardKey:e.shardKey});c[t]=D(n),e.scopeBy!==void 0&&(E[t]=f),i&&(p[t]=async({idempotencyKey:l,transaction:u})=>{const s=u.metadata,y=s!==void 0&&s.shardKey===void 0&&e.shardKey===void 0&&e.scopeBy!==void 0;for(const[w,g]of u.mutations.entries()){const b=g.modified,v=`${l}:${String(w)}`;try{await O(v,s,async m=>o.mutation(i.mutation,i.toArgs(b),{mutationId:v,replayBaseline:y?null:s?.baselineSeq??null,replayCredential:m,shardKey:y?R(e.scopeBy,b,"the queued row"):s?.shardKey}))}catch(C){const m=x(v,C);throw m!==void 0?(K(r,{code:m.code,collection:t,error:m,row:b}),m):C}}})}p[T]=async({transaction:t})=>{const e=t.metadata;if(e)try{const i=async n=>o.mutation({__lunoraRef:e.functionPath},e.args,{mutationId:e.idempotencyKey,replayBaseline:e.baselineSeq??null,replayCredential:n,shardKey:e.shardKey});await O(e.idempotencyKey,e,i),S(e.idempotencyKey)}catch(i){const n=x(e.idempotencyKey,i);throw n!==void 0?(S(e.idempotencyKey)?.(),K(r,{code:n.code,collection:e.functionPath,error:n}),n):i}};const F=k(),h=j({collections:{...c,[T]:F},mutationFns:p,onlineDetector:W(),...r.onLeadershipChange?{onLeadershipChange:r.onLeadershipChange}:{},...r.onStorageFailure?{onStorageFailure:r.onStorageFailure}:{},onUnknownMutationFn:(t,e)=>{K(r,{code:"UNKNOWN_MUTATION_FN",collection:t,error:new Error(`offline write dropped: mutation "${t}" no longer exists (removed or renamed in a deploy?)`),row:e.mutations[0]?.modified})}});$(h,F);const N={};for(const[t,e]of B){const i=e.insert,n=c[t];!i||!n||(N[t]=f=>{const l=U(),u=i.optimistic(f,l),s=e.shardKey??(e.scopeBy===void 0?void 0:R(e.scopeBy,u,"the inserted row")),y={baselineSeq:o.currentBaseline(s),identity:o.currentIdentity(),shardKey:s},w=h.createOfflineTransaction({autoCommit:!1,metadata:y,mutationFnName:t}),g=w.mutate(()=>{n.insert(u)});return w.commit().catch(()=>{}),{id:l,transaction:g}})}return{actions:N,collections:c,executor:h,pendingCount:()=>h.getPendingCount(),scope:E}};export{oe as defineCollections};
@@ -1,6 +1,6 @@
1
1
  import { LunoraClient } from '@lunora/client';
2
2
  import { Collection, Transaction } from '@tanstack/db';
3
- import { b as CheckpointRegistry } from "./collection-options.d-BbEYKjp2.mjs";
3
+ import { b as CheckpointRegistry } from "./collection-options.d-C2FdJw06.mjs";
4
4
  /**
5
5
  * TanStack DB's "direct transaction" marker.
6
6
  *
@@ -1,4 +1,4 @@
1
- import { R as Row } from "./collection-options.d-BbEYKjp2.mjs";
1
+ import { R as Row } from "./collection-options.d-C2FdJw06.mjs";
2
2
  import { FunctionReference, SubscriptionError, LunoraClient } from '@lunora/client';
3
3
  import { Transaction, Collection } from '@tanstack/db';
4
4
  import { OfflineExecutor, StorageDiagnostic } from '@tanstack/offline-transactions';
@@ -1,6 +1,6 @@
1
1
  import { LunoraClient } from '@lunora/client';
2
2
  import { Collection, Transaction } from '@tanstack/db';
3
- import { b as CheckpointRegistry } from "./collection-options.d-BbEYKjp2.js";
3
+ import { b as CheckpointRegistry } from "./collection-options.d-C2FdJw06.js";
4
4
  /**
5
5
  * TanStack DB's "direct transaction" marker.
6
6
  *
@@ -1,4 +1,4 @@
1
- import { R as Row } from "./collection-options.d-BbEYKjp2.js";
1
+ import { R as Row } from "./collection-options.d-C2FdJw06.js";
2
2
  import { FunctionReference, SubscriptionError, LunoraClient } from '@lunora/client';
3
3
  import { Transaction, Collection } from '@tanstack/db';
4
4
  import { OfflineExecutor, StorageDiagnostic } from '@tanstack/offline-transactions';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/db",
3
- "version": "1.0.0-alpha.230",
3
+ "version": "1.0.0-alpha.232",
4
4
  "description": "TanStack DB binding: typed, live-synced collections and a durable offline outbox over the Lunora client",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -54,7 +54,7 @@
54
54
  "access": "public"
55
55
  },
56
56
  "dependencies": {
57
- "@lunora/client": "1.0.0-alpha.229",
57
+ "@lunora/client": "1.0.0-alpha.231",
58
58
  "@lunora/errors": ">=1.0.0-alpha.51 <2.0.0-0"
59
59
  },
60
60
  "peerDependencies": {
@@ -1 +0,0 @@
1
- import{LunoraError as F}from"@lunora/errors";import{BTreeIndex as _}from"@tanstack/db";import{toMap as x,makeDiffEmit as B}from"./OUTBOX_MUTATION_FN_NAME-rGyegnLw.mjs";const E=()=>{let e=Number.NEGATIVE_INFINITY;const o=[];return{advance:t=>{if(!(t<=e)){e=t;for(let n=o.length-1;n>=0;n-=1){const i=o[n];i&&i.threshold<=e&&(i.resolve(),o.splice(n,1))}}},await:t=>t<=e?Promise.resolve():new Promise(n=>{o.push({resolve:n,threshold:t})}),passed:t=>t<=e,reset:()=>{for(const t of o.splice(0))t.resolve();e=Number.NEGATIVE_INFINITY},waiting:()=>o.length}};let N=!1;const W=e=>{N||(N=!0,console.warn(`[@lunora/db] released an optimistic overlay via the ${String(e.waitedMs)}ms checkpoint fallback: the server confirmed ${e.kind} ${String(e.watermark)} but no sync frame ever echoed it. A dropped shape poke or \`settled\` frame is the usual cause — inspect the subscription rather than raising \`fallbackMs\`. (Reported once per process.)`))},g=new WeakMap,T=new WeakMap,y=new WeakMap,S=new WeakMap,O=e=>{const o=(y.get(e)??0)-1;if(o>0){y.set(e,o);return}y.delete(e),S.get(e)?.()},R=new WeakSet,$=e=>{const o={acknowledge:t=>{e().acknowledge(t)},awaitCheckpoint:async t=>e().awaitCheckpoint(t),awaitMutationId:async t=>e().awaitMutationId(t),dispose:()=>{e().dispose()},resolve:t=>{e().resolve(t)},stats:()=>e().stats()};return R.add(o),o},G=3e3,P=(e={})=>{const o=e.fallbackMs??G,t=e.onFallback??W,n=E(),i=E();let l=0;const d=new Set,h=(s,a)=>{for(const c of d)c.kind===s&&c.threshold<=a&&(clearTimeout(c.handle),d.delete(c))},p=(s,a)=>{if(o<=0)return;const c=s==="checkpoint"?n:i;if(c.passed(a))return;for(const v of d)if(v.kind===s&&v.threshold>=a)return;const k={handle:setTimeout(()=>{if(d.delete(k),!c.passed(a)){l+=1,c.advance(a);try{t({kind:s,waitedMs:o,watermark:a})}catch{}}},o),kind:s,threshold:a};d.add(k)},u={acknowledge:({checkpoint:s,mutationId:a})=>{s!==void 0&&p("checkpoint",s),a!==void 0&&p("mutationId",a)},awaitCheckpoint:s=>n.await(s),awaitMutationId:s=>i.await(s),dispose:()=>{for(const s of d)clearTimeout(s.handle);d.clear()},resolve:({checkpoint:s,mutationId:a})=>{s!==void 0&&(n.advance(s),h("checkpoint",s)),a!==void 0&&(i.advance(a),h("mutationId",a))},stats:()=>({fallbacks:l,pendingCheckpointWaiters:n.waiting(),pendingMutationWaiters:i.waiting()})};return S.set(u,()=>{u.dispose(),n.reset(),i.reset()}),u},Q=e=>{const o=g.get(e);if(o){for(const t of o.values())t.resolve({checkpoint:Number.POSITIVE_INFINITY,mutationId:Number.POSITIVE_INFINITY}),t.dispose();g.delete(e)}},L=e=>{const o=e.currentIdentity();if(g.has(e)&&T.get(e)!==o)for(const t of g.get(e)?.values()??[])S.get(t)?.();T.set(e,o)},V=(e,o,t)=>{L(e);let n=g.get(e);n||(n=new Map,g.set(e,n));const i=o??"",l=n.get(i);if(l)return l;const d=P(t);return n.set(i,d),d},Y=(e,o,t)=>{const n=o[e];if(typeof n=="string"||typeof n=="number")return String(n);throw new F("BAD_REQUEST",`@lunora/db: ${t} has no "${e}" — a \`scopeBy\` collection routes by that field's value`)},j=e=>R.has(e),D=e=>{y.set(e,(y.get(e)??0)+1)},q=e=>(y.get(e)??0)>0,z=e=>{if(e.list===void 0==(e.shape===void 0))throw new F("INTERNAL","lunoraCollectionOptions: pass exactly one of `list` or `shape`");const o=e.getKey??(r=>r._id),t=e.shape?.shardKey??e.shardKey,n=e.scopeBy!==void 0&&t===void 0;let i;const l=()=>t??i,d=()=>e.checkpoints??V(e.client,l());let h;const p=()=>{const r=d();return r!==h&&(h=r,D(r)),r},u=()=>{h!==void 0&&e.checkpoints===void 0&&O(h),h=void 0};n||p();const s=new Map;let a,c,k,v,w;const b=(r,m)=>{p();const I=f=>{a?.(x(f,o)),m?.(),e.shape===void 0&&(p().resolve({mutationId:w??e.client.confirmedMutationWatermark(l())}),w=void 0)},C=f=>k?.(f),M=f=>{f.rowsFollow===!0&&f.mutationId!==void 0&&(w=f.mutationId),p().resolve(f)};return e.shape!==void 0?e.client.subscribeShape({args:r,name:e.shape.name},I,{onCheckpoint:M,onError:C,shardKey:l()}):e.client.subscribe(e.list,r,I,{onCheckpoint:M,onError:C,shardKey:l()})},K={autoIndex:"eager",defaultIndexType:_,getKey:o,id:e.id??e.list?.__lunoraRef??`shape:${e.shape?.name??""}`,...e.load==="eager"?{startSync:!0}:{},sync:{sync:r=>(a=B(s,r),k=I=>{r.markReady(),e.onError?.(I)},e.scopeBy===void 0?c=b(e.shape?.args??{},()=>{r.markReady()}):(r.markReady(),v!==void 0&&(c=b(v,void 0))),()=>{a=void 0,k=void 0,u(),c?.(),c=void 0,s.clear()})}},A=r=>{if(e.scopeBy===void 0)return;const m=n&&r!==void 0?Y(e.scopeBy,r,"scope args"):i;n&&(r===void 0||m!==i)&&u(),v=r,i=m,c?.(),c=void 0,w=void 0,a?.(new Map),r!==void 0&&a!==void 0&&(c=b(r,void 0))};return{checkpoints:n&&e.checkpoints===void 0?$(d):d(),config:K,scope:A}};export{G as CHECKPOINT_FALLBACK_MS,P as createCheckpointRegistry,V as getShardCheckpoints,q as hasCheckpointsAttached,j as isScopeFollowingCheckpoints,z as lunoraCollectionOptions,D as markCheckpointsAttached,Q as releaseShardCheckpoints,Y as scopedShardKey,L as syncShardCheckpointIdentity};