@lunora/client 1.0.0-alpha.27 → 1.0.0-alpha.29
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/auth/index.d.mts +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.mjs +1 -60
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +1 -21
- package/dist/packem_shared/CONFLICT_ERROR_CODE-B2SU0CaJ.mjs +1 -0
- package/dist/packem_shared/ClientServiceWorker-CRQ5yl7-.mjs +1 -0
- package/dist/packem_shared/DEFAULT_MAX_BUFFER-TBn2s7Rz.mjs +1 -0
- package/dist/packem_shared/LunoraClient-DDEoZdgP.mjs +1 -0
- package/dist/packem_shared/OfflineQueue-B603_q8m.mjs +1 -0
- package/dist/packem_shared/SKIP-CArzT3Vl.mjs +1 -0
- package/dist/packem_shared/SubscriptionRegistry-CdrOD7sZ.mjs +1 -0
- package/dist/packem_shared/TabCoordinator-ijLic02x.mjs +1 -0
- package/dist/packem_shared/applyDelta-DXqQORbM.mjs +1 -0
- package/dist/packem_shared/createAsyncStoragePersistence-BRLqeXsC.mjs +1 -0
- package/dist/packem_shared/createClientQuery-CrdRoicO.mjs +1 -0
- package/dist/packem_shared/createInMemoryBookmarkStorage-DCd5Ej-t.mjs +1 -0
- package/dist/packem_shared/createInMemoryPersistence-CQYXy8UP.mjs +1 -0
- package/dist/packem_shared/createInMemoryQueryCache-DjCKrLjk.mjs +1 -0
- package/dist/packem_shared/createLocalStore-B3Tw_Tw1.mjs +1 -0
- package/dist/packem_shared/createMutationRunner-lQXH8Amk.mjs +1 -0
- package/dist/packem_shared/createMutatorRunner-BVzo0FBZ.mjs +1 -0
- package/dist/packem_shared/createReconnect-CFT7YRSR.mjs +1 -0
- package/dist/packem_shared/createReply-DF0jRsv-.mjs +1 -0
- package/dist/packem_shared/createServerClient-B7KqO8tv.mjs +1 -0
- package/dist/packem_shared/createSnapshotPrecondition-DOKRAJ4b.mjs +1 -0
- package/dist/packem_shared/deserializePreloaded-CHfOFpka.mjs +1 -0
- package/dist/packem_shared/getServerSession-CGjgRBAE.mjs +1 -0
- package/dist/packem_shared/httpStream-Cz4_QyjV.mjs +11 -0
- package/dist/packem_shared/idb-utility-C-DR8nG1.mjs +1 -0
- package/dist/packem_shared/local-store-C53xDvEr.mjs +1 -0
- package/dist/packem_shared/{lunora-client.d-B1iZb2Ph.d.mts → lunora-client.d-Bt65hm_E.d.mts} +135 -1
- package/dist/packem_shared/{lunora-client.d-B1iZb2Ph.d.ts → lunora-client.d-Bt65hm_E.d.ts} +135 -1
- package/dist/packem_shared/offline-queue-D73Dq95V.mjs +1 -0
- package/dist/packem_shared/{preload.d-CLwoXl3R.d.mts → preload.d-BmztUzzG.d.mts} +1 -1
- package/dist/packem_shared/{preload.d-Cqb4Kh2I.d.ts → preload.d-DGGRMWB5.d.ts} +1 -1
- package/dist/packem_shared/preloadQuery-DjwSjFwt.mjs +1 -0
- package/dist/packem_shared/wire-key-D_zOxXK4.mjs +1 -0
- package/dist/pagination/index.mjs +1 -61
- package/dist/query/index.d.mts +2 -2
- package/dist/query/index.d.ts +2 -2
- package/dist/query/index.mjs +1 -1
- package/dist/ssr/index.d.mts +3 -3
- package/dist/ssr/index.d.ts +3 -3
- package/dist/ssr/index.mjs +1 -4
- package/dist/upload.mjs +1 -24
- package/package.json +2 -2
- package/dist/packem_shared/CONFLICT_ERROR_CODE-B8gQ8tyU.mjs +0 -33
- package/dist/packem_shared/ClientServiceWorker-C3PAFwy0.mjs +0 -100
- package/dist/packem_shared/DEFAULT_MAX_BUFFER-7hFnzNk9.mjs +0 -110
- package/dist/packem_shared/LunoraClient-DKATLGHY.mjs +0 -3631
- package/dist/packem_shared/OfflineQueue-BgarnAub.mjs +0 -1
- package/dist/packem_shared/SKIP-vItZChkw.mjs +0 -50
- package/dist/packem_shared/SubscriptionRegistry-CxS_Inha.mjs +0 -31
- package/dist/packem_shared/TabCoordinator-D_5oNTTt.mjs +0 -258
- package/dist/packem_shared/applyDelta-CRKZ1PBt.mjs +0 -81
- package/dist/packem_shared/createAsyncStoragePersistence-1Z5BZ8RC.mjs +0 -45
- package/dist/packem_shared/createClientQuery-dJZg1ohm.mjs +0 -80
- package/dist/packem_shared/createInMemoryBookmarkStorage-BoN7a7TH.mjs +0 -11
- package/dist/packem_shared/createInMemoryPersistence-DZ2VHWgm.mjs +0 -79
- package/dist/packem_shared/createInMemoryQueryCache-DiaGZkA2.mjs +0 -112
- package/dist/packem_shared/createLocalStore-BtqUmOQA.mjs +0 -2
- package/dist/packem_shared/createMutationRunner-BqsavzvG.mjs +0 -21
- package/dist/packem_shared/createMutatorRunner-BETvCd0p.mjs +0 -31
- package/dist/packem_shared/createReconnect-Di_-oHH7.mjs +0 -22
- package/dist/packem_shared/createReply-lI4tVS2w.mjs +0 -36
- package/dist/packem_shared/createServerClient-Bp2r9tcB.mjs +0 -11
- package/dist/packem_shared/createSnapshotPrecondition-CxQ1T4ZP.mjs +0 -18
- package/dist/packem_shared/deserializePreloaded-C0eJTY_W.mjs +0 -4
- package/dist/packem_shared/getServerSession-8jXewqxd.mjs +0 -13
- package/dist/packem_shared/httpStream-DIdL8NEw.mjs +0 -168
- package/dist/packem_shared/idb-utility-DrSVX43Q.mjs +0 -48
- package/dist/packem_shared/local-store-DIq-UWfD.mjs +0 -106
- package/dist/packem_shared/offline-queue-N-1JvYb4.mjs +0 -211
- package/dist/packem_shared/preloadQuery-lobFkD2Z.mjs +0 -13
- package/dist/packem_shared/wire-key-Djie6aaR.mjs +0 -266
package/dist/auth/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-Bt65hm_E.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. */
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-Bt65hm_E.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/auth/index.mjs
CHANGED
|
@@ -1,60 +1 @@
|
|
|
1
|
-
const
|
|
2
|
-
const createIdentityStore = (client) => {
|
|
3
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
4
|
-
let user = null;
|
|
5
|
-
let started = false;
|
|
6
|
-
const notify = () => {
|
|
7
|
-
for (const listener of listeners) {
|
|
8
|
-
listener();
|
|
9
|
-
}
|
|
10
|
-
};
|
|
11
|
-
let generation = 0;
|
|
12
|
-
const setUser = (next) => {
|
|
13
|
-
if (user !== next) {
|
|
14
|
-
user = next;
|
|
15
|
-
notify();
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
const refresh = () => {
|
|
19
|
-
generation += 1;
|
|
20
|
-
const current = generation;
|
|
21
|
-
if (client.getAuthToken() === null) {
|
|
22
|
-
setUser(null);
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
client.getCurrentUser().then((next) => {
|
|
26
|
-
if (current === generation) {
|
|
27
|
-
setUser(next);
|
|
28
|
-
}
|
|
29
|
-
return void 0;
|
|
30
|
-
}).catch(() => {
|
|
31
|
-
if (current === generation) {
|
|
32
|
-
setUser(null);
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
};
|
|
36
|
-
client.onAuthTokenChange(refresh);
|
|
37
|
-
return {
|
|
38
|
-
getUser: () => user,
|
|
39
|
-
subscribe: (onChange) => {
|
|
40
|
-
listeners.add(onChange);
|
|
41
|
-
if (!started) {
|
|
42
|
-
started = true;
|
|
43
|
-
refresh();
|
|
44
|
-
}
|
|
45
|
-
return () => {
|
|
46
|
-
listeners.delete(onChange);
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
};
|
|
51
|
-
const getIdentityStore = (client) => {
|
|
52
|
-
let store = stores.get(client);
|
|
53
|
-
if (!store) {
|
|
54
|
-
store = createIdentityStore(client);
|
|
55
|
-
stores.set(client, store);
|
|
56
|
-
}
|
|
57
|
-
return store;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
export { getIdentityStore };
|
|
1
|
+
const c=new WeakMap,d=n=>{const t=new Set;let o=null,u=!1;const a=()=>{for(const e of t)e()};let l=0;const s=e=>{o!==e&&(o=e,a())},r=()=>{l+=1;const e=l;if(n.getAuthToken()===null){s(null);return}n.getCurrentUser().then(g=>{e===l&&s(g)}).catch(()=>{e===l&&s(null)})};return n.onAuthTokenChange(r),{getUser:()=>o,subscribe:e=>(t.add(e),u||(u=!0,r()),()=>{t.delete(e)})}},f=n=>{let t=c.get(n);return t||(t=d(n),c.set(n,t)),t};export{f as getIdentityStore};
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { c as PersistenceAdapter, B as BookmarkStorage, S as SubscriptionError, H as HttpStreamRef, d as HttpStreamArgsOf, e as HttpStreamChunkOf, f as StreamIterable, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, g as ReconnectOptions, L as LunoraClient } from "./packem_shared/lunora-client.d-
|
|
2
|
-
export { type h as BatchSlot, C as CONFLICT_ERROR_CODE, type i as CachedQuery, type j as
|
|
3
|
-
export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-
|
|
1
|
+
import { c as PersistenceAdapter, B as BookmarkStorage, S as SubscriptionError, H as HttpStreamRef, d as HttpStreamArgsOf, e as HttpStreamChunkOf, f as StreamIterable, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, g as ReconnectOptions, L as LunoraClient } from "./packem_shared/lunora-client.d-Bt65hm_E.mjs";
|
|
2
|
+
export { type h as BatchSlot, C as CONFLICT_ERROR_CODE, type i as CachedQuery, type j as ClientDebugShard, type k as ClientDebugSnapshot, type l as ClientDebugSubscription, type m as ClientMessage, type n as ClientQueryRef, type o as ClientShapeSubscribeMessage, type p as ClientShapeUnsubscribeMessage, type q as ConnectionStatus, D as DEFAULT_MAX_BUFFER, type r as FunctionArgumentDescriptor, type s as FunctionDescriptor, type G as GlobalFacetResult, type t as GlobalFacetValue, type u as GlobalFilterClause, type v as GlobalTableInfo, type w as GlobalTablePage, type x as HttpStreamCallArgs, type y as LunoraClientError, type z as LunoraClientOptions, type E as LunoraErrorCode, type I as MutationSettledEvent, type J as OptimisticLocalStore, type K as OptimisticUpdate, type N as OutboxMutation, type T as OutboxSink, type V as PersistedMutation, type P as Preloaded, type W as RowOp, type X as RpcEnvelope, type Y as RpcResponseBody, type Z as ScheduleRecord, type _ as SchedulerPoolStatus, type $ as SchedulerStatus, type a0 as ServerMessage, type a1 as ServerPokeEndMessage, type a2 as ServerPokePartMessage, type a3 as ServerPokeStartMessage, type a4 as ShardTrafficEntry, type a5 as ShardTrafficResult, type a6 as StorageListPage, type a7 as StorageObject, type a8 as StreamHandle, type a9 as SubscriptionCallback, type b as SubscriptionErrorCallback, aa as SubscriptionRegistry, type ab as SubscriptionState, type ac as SyncWatermark, type a as Unsubscribe, type U as User, type ad as WorkflowInstanceAction, type ae as WorkflowInstanceDetail, type af as WorkflowInstancePage, type ag as WorkflowInstanceStatus, type ah as WorkflowInstanceSummary, type ai as WorkflowStepDetail, type aj as WsTokenProvider, ak as createClientQuery, al as createLocalStore, am as createStream, an as getErrorCode, ao as getRetryAfterMs, ap as isConflictError, aq as isForbiddenError, ar as isRateLimitedError, as as isUnauthorizedError } from "./packem_shared/lunora-client.d-Bt65hm_E.mjs";
|
|
3
|
+
export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-BmztUzzG.mjs";
|
|
4
4
|
export type { AuthCapabilities, AuthConfigInfo, AuthImpersonation, AuthPage, AuthSession, AuthUser, AuthUserFieldSpec, CronJobInfo, KvKeyEntry, KvKeyListResult, KvNamespaceSummary, KvValueResult, PipelineLogColumnMap, PipelineLogCursor, PipelineLogField, PipelineLogPage, PipelineLogQuery, PipelineLogRow, VectorIndexSummary, VectorQueryMatch } from '@lunora/runtime';
|
|
5
5
|
/**
|
|
6
6
|
* The slice of React Native's `AsyncStorage` (or any async key/value store —
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { c as PersistenceAdapter, B as BookmarkStorage, S as SubscriptionError, H as HttpStreamRef, d as HttpStreamArgsOf, e as HttpStreamChunkOf, f as StreamIterable, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, g as ReconnectOptions, L as LunoraClient } from "./packem_shared/lunora-client.d-
|
|
2
|
-
export { type h as BatchSlot, C as CONFLICT_ERROR_CODE, type i as CachedQuery, type j as
|
|
3
|
-
export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-
|
|
1
|
+
import { c as PersistenceAdapter, B as BookmarkStorage, S as SubscriptionError, H as HttpStreamRef, d as HttpStreamArgsOf, e as HttpStreamChunkOf, f as StreamIterable, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, g as ReconnectOptions, L as LunoraClient } from "./packem_shared/lunora-client.d-Bt65hm_E.js";
|
|
2
|
+
export { type h as BatchSlot, C as CONFLICT_ERROR_CODE, type i as CachedQuery, type j as ClientDebugShard, type k as ClientDebugSnapshot, type l as ClientDebugSubscription, type m as ClientMessage, type n as ClientQueryRef, type o as ClientShapeSubscribeMessage, type p as ClientShapeUnsubscribeMessage, type q as ConnectionStatus, D as DEFAULT_MAX_BUFFER, type r as FunctionArgumentDescriptor, type s as FunctionDescriptor, type G as GlobalFacetResult, type t as GlobalFacetValue, type u as GlobalFilterClause, type v as GlobalTableInfo, type w as GlobalTablePage, type x as HttpStreamCallArgs, type y as LunoraClientError, type z as LunoraClientOptions, type E as LunoraErrorCode, type I as MutationSettledEvent, type J as OptimisticLocalStore, type K as OptimisticUpdate, type N as OutboxMutation, type T as OutboxSink, type V as PersistedMutation, type P as Preloaded, type W as RowOp, type X as RpcEnvelope, type Y as RpcResponseBody, type Z as ScheduleRecord, type _ as SchedulerPoolStatus, type $ as SchedulerStatus, type a0 as ServerMessage, type a1 as ServerPokeEndMessage, type a2 as ServerPokePartMessage, type a3 as ServerPokeStartMessage, type a4 as ShardTrafficEntry, type a5 as ShardTrafficResult, type a6 as StorageListPage, type a7 as StorageObject, type a8 as StreamHandle, type a9 as SubscriptionCallback, type b as SubscriptionErrorCallback, aa as SubscriptionRegistry, type ab as SubscriptionState, type ac as SyncWatermark, type a as Unsubscribe, type U as User, type ad as WorkflowInstanceAction, type ae as WorkflowInstanceDetail, type af as WorkflowInstancePage, type ag as WorkflowInstanceStatus, type ah as WorkflowInstanceSummary, type ai as WorkflowStepDetail, type aj as WsTokenProvider, ak as createClientQuery, al as createLocalStore, am as createStream, an as getErrorCode, ao as getRetryAfterMs, ap as isConflictError, aq as isForbiddenError, ar as isRateLimitedError, as as isUnauthorizedError } from "./packem_shared/lunora-client.d-Bt65hm_E.js";
|
|
3
|
+
export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-DGGRMWB5.js";
|
|
4
4
|
export type { AuthCapabilities, AuthConfigInfo, AuthImpersonation, AuthPage, AuthSession, AuthUser, AuthUserFieldSpec, CronJobInfo, KvKeyEntry, KvKeyListResult, KvNamespaceSummary, KvValueResult, PipelineLogColumnMap, PipelineLogCursor, PipelineLogField, PipelineLogPage, PipelineLogQuery, PipelineLogRow, VectorIndexSummary, VectorQueryMatch } from '@lunora/runtime';
|
|
5
5
|
/**
|
|
6
6
|
* The slice of React Native's `AsyncStorage` (or any async key/value store —
|
package/dist/index.mjs
CHANGED
|
@@ -1,21 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { default as createInMemoryBookmarkStorage } from './packem_shared/createInMemoryBookmarkStorage-BoN7a7TH.mjs';
|
|
3
|
-
export { createClientQuery } from './packem_shared/createClientQuery-dJZg1ohm.mjs';
|
|
4
|
-
export { TabCoordinator } from './packem_shared/TabCoordinator-D_5oNTTt.mjs';
|
|
5
|
-
export { applyDelta, isMutationDelta } from './packem_shared/applyDelta-CRKZ1PBt.mjs';
|
|
6
|
-
export { CONFLICT_ERROR_CODE, getErrorCode, getRetryAfterMs, isConflictError, isForbiddenError, isRateLimitedError, isUnauthorizedError } from './packem_shared/CONFLICT_ERROR_CODE-B8gQ8tyU.mjs';
|
|
7
|
-
export { httpStream } from './packem_shared/httpStream-DIdL8NEw.mjs';
|
|
8
|
-
export { c as createLocalStore } from './packem_shared/local-store-DIq-UWfD.mjs';
|
|
9
|
-
export { LunoraClient } from './packem_shared/LunoraClient-DKATLGHY.mjs';
|
|
10
|
-
export { createMutationRunner } from './packem_shared/createMutationRunner-BqsavzvG.mjs';
|
|
11
|
-
export { createMutatorRunner } from './packem_shared/createMutatorRunner-BETvCd0p.mjs';
|
|
12
|
-
export { O as OfflineQueue } from './packem_shared/offline-queue-N-1JvYb4.mjs';
|
|
13
|
-
export { createInMemoryPersistence, createIndexedDbPersistence } from './packem_shared/createInMemoryPersistence-DZ2VHWgm.mjs';
|
|
14
|
-
export { preloadQuery, preloadedQueryResult } from './packem_shared/preloadQuery-lobFkD2Z.mjs';
|
|
15
|
-
export { createInMemoryQueryCache, createIndexedDbQueryCache, queryCacheKey } from './packem_shared/createInMemoryQueryCache-DiaGZkA2.mjs';
|
|
16
|
-
export { createReconnect } from './packem_shared/createReconnect-Di_-oHH7.mjs';
|
|
17
|
-
export { default as createSnapshotPrecondition } from './packem_shared/createSnapshotPrecondition-CxQ1T4ZP.mjs';
|
|
18
|
-
export { DEFAULT_MAX_BUFFER, createStream } from './packem_shared/DEFAULT_MAX_BUFFER-7hFnzNk9.mjs';
|
|
19
|
-
export { SubscriptionRegistry } from './packem_shared/SubscriptionRegistry-CxS_Inha.mjs';
|
|
20
|
-
export { ClientServiceWorker } from './packem_shared/ClientServiceWorker-C3PAFwy0.mjs';
|
|
21
|
-
export { createReply, sendToSw } from './packem_shared/createReply-lI4tVS2w.mjs';
|
|
1
|
+
import{createAsyncStoragePersistence as o}from"./packem_shared/createAsyncStoragePersistence-BRLqeXsC.mjs";import{default as a}from"./packem_shared/createInMemoryBookmarkStorage-DCd5Ej-t.mjs";import{createClientQuery as c}from"./packem_shared/createClientQuery-CrdRoicO.mjs";import{TabCoordinator as m}from"./packem_shared/TabCoordinator-ijLic02x.mjs";import{applyDelta as i,isMutationDelta as x}from"./packem_shared/applyDelta-DXqQORbM.mjs";import{CONFLICT_ERROR_CODE as u,getErrorCode as d,getRetryAfterMs as l,isConflictError as y,isForbiddenError as C,isRateLimitedError as R,isUnauthorizedError as E}from"./packem_shared/CONFLICT_ERROR_CODE-B2SU0CaJ.mjs";import{httpStream as M}from"./packem_shared/httpStream-Cz4_QyjV.mjs";import{c as D}from"./packem_shared/local-store-C53xDvEr.mjs";import{LunoraClient as Q}from"./packem_shared/LunoraClient-DDEoZdgP.mjs";import{createMutationRunner as g}from"./packem_shared/createMutationRunner-lQXH8Amk.mjs";import{createMutatorRunner as L}from"./packem_shared/createMutatorRunner-BVzo0FBZ.mjs";import{c as O}from"./packem_shared/offline-queue-D73Dq95V.mjs";import{createInMemoryPersistence as T,createIndexedDbPersistence as _}from"./packem_shared/createInMemoryPersistence-CQYXy8UP.mjs";import{preloadQuery as U,preloadedQueryResult as B}from"./packem_shared/preloadQuery-DjwSjFwt.mjs";import{createInMemoryQueryCache as v,createIndexedDbQueryCache as w,queryCacheKey as z}from"./packem_shared/createInMemoryQueryCache-DjCKrLjk.mjs";import{createReconnect as N}from"./packem_shared/createReconnect-CFT7YRSR.mjs";import{default as X}from"./packem_shared/createSnapshotPrecondition-DOKRAJ4b.mjs";import{DEFAULT_MAX_BUFFER as G,createStream as H}from"./packem_shared/DEFAULT_MAX_BUFFER-TBn2s7Rz.mjs";import{SubscriptionRegistry as V}from"./packem_shared/SubscriptionRegistry-CdrOD7sZ.mjs";import{ClientServiceWorker as Z}from"./packem_shared/ClientServiceWorker-CRQ5yl7-.mjs";import{createReply as ee,sendToSw as re}from"./packem_shared/createReply-DF0jRsv-.mjs";export{u as CONFLICT_ERROR_CODE,Z as ClientServiceWorker,G as DEFAULT_MAX_BUFFER,Q as LunoraClient,O as OfflineQueue,V as SubscriptionRegistry,m as TabCoordinator,i as applyDelta,o as createAsyncStoragePersistence,c as createClientQuery,a as createInMemoryBookmarkStorage,T as createInMemoryPersistence,v as createInMemoryQueryCache,_ as createIndexedDbPersistence,w as createIndexedDbQueryCache,D as createLocalStore,g as createMutationRunner,L as createMutatorRunner,N as createReconnect,ee as createReply,X as createSnapshotPrecondition,H as createStream,d as getErrorCode,l as getRetryAfterMs,M as httpStream,y as isConflictError,C as isForbiddenError,x as isMutationDelta,R as isRateLimitedError,E as isUnauthorizedError,U as preloadQuery,B as preloadedQueryResult,z as queryCacheKey,re as sendToSw};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=["BAD_REQUEST","CONFLICT","COUNT_RLS_UNSUPPORTED","FORBIDDEN","INTERNAL_SERVER_ERROR","MASK_UNSUPPORTED","NOT_FOUND","NOT_IMPLEMENTED","RELATION_PREDICATE_UNSUPPORTED","TOO_MANY_REQUESTS","UNAUTHORIZED","UNPROCESSABLE"],o=new Set(e),t="CONFLICT",R=r=>r instanceof Error&&r.code===t,n=r=>r instanceof Error&&r.code==="FORBIDDEN",s=r=>r instanceof Error&&r.code==="UNAUTHORIZED",O=r=>r instanceof Error&&r.code==="TOO_MANY_REQUESTS",N=r=>{if(!(r instanceof Error))return;const{code:E}=r;return typeof E=="string"&&o.has(E)?E:void 0},i=r=>{const E=r?.data?.retryAfterMs;return typeof E=="number"&&Number.isFinite(E)?E:void 0};export{t as CONFLICT_ERROR_CODE,N as getErrorCode,i as getRetryAfterMs,R as isConflictError,n as isForbiddenError,O as isRateLimitedError,s as isUnauthorizedError};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class r{swUrl;scope;#t=void 0;#r="unregistered";#i;#s=new Set;constructor(t){this.swUrl=t.swUrl,this.scope=t.scope??"/",this.#i=t.onStatusChange}get status(){return this.#r}get registration(){return this.#t}get active(){return this.#t?.active!==null&&this.#t?.active!==void 0}async register(){if(!("serviceWorker"in navigator))return this.#e("unsupported"),!1;this.#e("registering");try{this.#t=await navigator.serviceWorker.register(this.swUrl,{scope:this.scope}),this.#e("active"),navigator.serviceWorker.addEventListener("message",this.#n)}catch{return this.#e("error"),!1}return!0}async unregister(){if(!this.#t)return!1;navigator.serviceWorker.removeEventListener("message",this.#n);const t=await this.#t.unregister();return this.#t=void 0,this.#e("unregistered"),t}postMessage(t){const e=this.#t?.active;e&&e.postMessage(t)}onMessage(t){return this.#s.add(t),()=>{this.#s.delete(t)}}#e(t){this.#r=t,this.#i?.(t)}#n=t=>{for(const e of this.#s)try{e(t)}catch{}}}export{r as ClientServiceWorker};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as h}from"@lunora/errors";const v=1024,d=f=>{const a=f.maxBuffer??v,r=[],u=[];let o=!1,t,s=!1;const n=()=>{const e=u.shift();if(!e)return!1;if(t)return e.reject(t),!0;if(r.length>0){const l=r.shift();return e.resolve({done:!1,value:l}),!0}return o?(e.resolve({done:!0,value:void 0}),!0):(u.unshift(e),!1)},i={complete(){if(!(o||t))for(o=!0;n(););},fail(e){if(!(o||t))for(t=e,r.length=0;n(););},push(e){if(!(o||t||s)){if(r.length>=a){i.fail(new h("STREAM_BACKPRESSURE",`stream buffer overflow (max=${a.toString()}); the consumer cannot keep up with the producer`));return}r.push(e),n()}}},c=()=>{if(!s){s=!0,o=!0,r.length=0;try{f.onCancel()}catch{}for(;n(););}};return{handle:i,iterable:{cancel:c,[Symbol.asyncIterator](){return{next(){if(t)return Promise.reject(t);if(r.length>0){const e=r.shift();return Promise.resolve({done:!1,value:e})}return o?Promise.resolve({done:!0,value:void 0}):new Promise((e,l)=>{u.push({reject:l,resolve:e})})},return(){return c(),Promise.resolve({done:!0,value:void 0})}}}}}};export{v as DEFAULT_MAX_BUFFER,d as createStream};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as u}from"@lunora/errors";import{t as I,c as g,f as W}from"./wire-key-D_zOxXK4.mjs";import D from"./createInMemoryBookmarkStorage-DCd5Ej-t.mjs";import{ClientQueryStore as H}from"./createClientQuery-CrdRoicO.mjs";import{TabCoordinator as V}from"./TabCoordinator-ijLic02x.mjs";import{isMutationDelta as J,applyDelta as X}from"./applyDelta-DXqQORbM.mjs";import{httpStream as Y}from"./httpStream-Cz4_QyjV.mjs";import{f as A,a as Z,d as F,n as x,c as tt}from"./local-store-C53xDvEr.mjs";import{c as et,u as $,d as st,s as it}from"./offline-queue-D73Dq95V.mjs";import{resolvePersistenceAdapter as nt}from"./createInMemoryPersistence-CQYXy8UP.mjs";import{resolveQueryCacheAdapter as rt,queryCacheKey as R}from"./createInMemoryQueryCache-DjCKrLjk.mjs";import{createReconnect as M}from"./createReconnect-CFT7YRSR.mjs";import{createStream as ot}from"./DEFAULT_MAX_BUFFER-TBn2s7Rz.mjs";import{SubscriptionRegistry as k}from"./SubscriptionRegistry-CdrOD7sZ.mjs";const _=500,at=(h,t)=>{if(h.size<t)return;const e=h.keys().next().value;e!==void 0&&h.delete(e)};class S{listeners=new Set;add(t){return this.listeners.add(t),()=>{this.listeners.delete(t)}}emit(...t){const[e]=t;for(const s of this.listeners)try{s(e)}catch{}}clear(){this.listeners.clear()}}const ct="/_lunora/rpc",K="/_lunora/rpc-batch",ht="/_lunora/ws",N=h=>h===void 0||h===""?"":`&bucket=${encodeURIComponent(h)}`,O=h=>{for(let t=h.length-1;t>=0;t-=1)h[t]?.()},ut=(h,t)=>{for(const e of t)e.op==="delete"?h.delete(e.key):e.value!==void 0&&h.set(e.key,e.value)},dt="lunora-ping",lt=3e4,mt=1e4,pt=250,ft=64,yt="/_lunora/admin/shard-traffic",wt="/_lunora/admin/scheduled",gt="/_lunora/admin/scheduled/status",bt="/_lunora/admin/scheduled/ws",vt="/_lunora/admin/scheduled/cancel",kt="/_lunora/admin/scheduled/dead",St="/_lunora/admin/scheduled/dead/retry",Ct="/_lunora/admin/scheduled/dead/cancel",Tt="/_lunora/admin/workflows/instances",It="/_lunora/admin/workflows/instance",Et="/_lunora/admin/workflows/status",E="/_lunora/admin/storage",Lt="/_lunora/admin/storage/url",At="/_lunora/admin/storage/buckets",Rt="/_lunora/admin/functions",_t="/_lunora/admin/cron-jobs",Nt="/_lunora/admin/cron-jobs/run",Ot="/_lunora/admin/openapi",Pt="/_lunora/admin/openrpc",Ft="/_lunora/admin/global/tables",xt="/_lunora/admin/global/table",$t="/_lunora/admin/global/facet",Mt="/_lunora/admin/vector/indexes",Kt="/_lunora/admin/vector/query",qt="/_lunora/admin/logs/archive",Ut="/_lunora/admin/kv/namespaces",Qt="/_lunora/admin/kv/keys",P="/_lunora/admin/kv/value",Bt="/_lunora/admin/auth/users",q="/_lunora/admin/auth/sessions",Wt="/_lunora/admin/auth/users/create",zt="/_lunora/admin/auth/users/role",Gt="/_lunora/admin/auth/users/ban",jt="/_lunora/admin/auth/users/unban",Dt="/_lunora/admin/auth/users/password",Ht="/_lunora/admin/auth/users/remove",Vt="/_lunora/admin/auth/users/impersonate",Jt="/_lunora/admin/auth/sessions/revoke",Xt="/_lunora/admin/auth/sessions/revoke-all",Yt="/_lunora/admin/auth/capabilities",Zt="/_lunora/admin/auth/users/update",te="/_lunora/admin/auth/accounts",ee="/_lunora/admin/auth/accounts/unlink",se="/_lunora/admin/auth/passkeys",ie="/_lunora/admin/auth/passkeys/delete",ne="/_lunora/admin/auth/two-factor/disable",re="/_lunora/admin/auth/organizations",oe="/_lunora/admin/auth/organizations/members",ae="/_lunora/admin/auth/organizations/invitations",ce="/_lunora/admin/auth/organizations/members/remove",he="/_lunora/admin/auth/organizations/invitations/cancel",ue="/_lunora/admin/auth/config",de="/_lunora/admin/auth/organizations/create",le="/_lunora/admin/auth/organizations/update",me="/_lunora/admin/auth/organizations/remove",pe="/_lunora/admin/auth/organizations/members/add",fe="/_lunora/admin/auth/organizations/members/invite",ye="/_lunora/admin/auth/organizations/members/role",we="/_lunora/admin/auth/organizations/teams",ge="/_lunora/admin/auth/organizations/teams/create",be="/_lunora/admin/auth/organizations/teams/update",ve="/_lunora/admin/auth/organizations/teams/remove",ke="/_lunora/admin/auth/organizations/teams/members",Se="/_lunora/admin/auth/organizations/teams/members/add",Ce="/_lunora/admin/auth/organizations/teams/members/remove",Te="/_lunora/admin/auth/organizations/roles",Ie="/_lunora/admin/auth/organizations/roles/create",Ee="/_lunora/admin/auth/organizations/roles/update",Le="/_lunora/admin/auth/organizations/roles/remove",Ae="/api/auth",Re="/get-session",U=h=>h.startsWith("https://")?`wss://${h.slice(8)}`:h.startsWith("http://")?`ws://${h.slice(7)}`:h,b=(h,t)=>`${h.endsWith("/")?h.slice(0,-1):h}${t}`,w=(h,t)=>{const e=new URLSearchParams;for(const[i,n]of Object.entries(t))n!==void 0&&n!==""&&e.set(i,String(n));const s=e.toString();return s===""?h:`${h}?${s}`},m=h=>h??"",_e=h=>{const t=h.error,e=typeof t?.code=="string"?t.code:void 0,s=typeof t?.message=="string"?t.message:void 0,i=(typeof h.message=="string"?h.message:void 0)??s??"stream error";return e===void 0?new Error(i):new u(e,i)},Q=h=>{const t=h.error,e=typeof t?.code=="string"?t.code:void 0,s=typeof t?.message=="string"?t.message:void 0;return{message:(typeof h.message=="string"?h.message:void 0)??s??"subscription error",...e===void 0?{}:{code:e}}},B=(h,t)=>{for(const e of h)try{e(t)}catch{}},Ne=new TextDecoder,Oe=h=>{if(typeof h=="string")return h;if(h instanceof ArrayBuffer)return Ne.decode(h)},y=(h,t)=>{if(!h.socket||h.wsState!=="open")return!1;try{return h.socket.send(JSON.stringify(t)),!0}catch{return!1}},C=h=>{const t=new Error(h.message??"request failed");return t.code=h.code,h.data!==void 0&&(t.data=g(h.data)),h.hint!==void 0&&(t.hint=h.hint),h.docsUrl!==void 0&&(t.docsUrl=h.docsUrl),t},v=(h,t)=>{try{return W(h)}catch(e){const s=e instanceof Error?e.message:String(e);throw new TypeError(`LunoraClient: cannot encode ${t} — ${s}`,e instanceof Error?{cause:e}:void 0)}},Pe=(h,t)=>{const e=Array.from({length:t});for(const s of h){if(typeof s.id!="number"||s.id<0||s.id>=t)continue;const i=s.body;e[s.id]=i&&"error"in i&&i.error?{error:C(i.error),ok:!1}:{ok:!0,value:g(i?.result)}}return e.map(s=>s??{error:new Error("batch call returned no result"),ok:!1})},Fe=new Set(["SHARD_ERROR","SHARD_UNAVAILABLE"]),xe=Promise.resolve();class z{static MAX_POKE_BUFFERS=256;static createClientQuery(t,e){return{defaultValue:e,key:t}}url;wsUrl;clientQueryStore;wsToken;authBasePath;fetchImpl;WebSocketImpl;bookmark;reconnectOptions;connectTimeoutMs;heartbeatIntervalMs;offlineQueue;outbox;clientId;readyResolved=!1;readyResolve;readyPromise;clientWatermarks=new Map;outboxMutationCounter=0;onPersistenceError;persistence;persistenceVersion;outboxLeaderRelease;queryCache;hydratedQueryCache=new Map;pendingCacheWrites=new Map;cacheFlushTimer;subscriptions=new k;tabCoordinator;connections=new Map;defaultConnectionContext;connectionContexts=new Map;connectionContextHolders=new Map;authToken=null;authSubject=void 0;queuedIdentities=new Map;closed=!1;authTokenListeners=new S;statusListeners=new S;tokenExpiredListeners=new S;mutationSettledListeners=new S;pendingChangeListeners=new S;whisperHandlers=new Map;lastStatus="idle";nextSubId=0;nextStreamId=0;streams=new Map;shapeSubscriptions=new Map;pokeBuffers=new Map;nextShapeId=0;constructor(t){this.url=t.url,this.wsUrl=t.wsUrl??b(U(t.url),ht),this.wsToken=t.wsToken;const e=t.authBasePath??Ae;this.authBasePath=e.endsWith("/")?e.slice(0,-1):e,this.fetchImpl=t.fetch??(typeof fetch=="function"?fetch.bind(globalThis):void 0),this.WebSocketImpl=t.WebSocket??(typeof WebSocket=="function"?WebSocket:void 0),this.bookmark=t.bookmarkStorage??D(),this.reconnectOptions=t.reconnect,this.heartbeatIntervalMs=t.heartbeatIntervalMs??lt,this.connectTimeoutMs=t.connectTimeoutMs??mt,this.defaultConnectionContext=t.connectionContext,this.persistence=nt(t.persistence,t.outbox===void 0),this.persistenceVersion=t.persistenceVersion,this.queryCache=rt(t.queryCache),this.onPersistenceError=t.offlineQueue?.onPersistenceError,this.clientQueryStore=new H,t.crossTabSync?(this.tabCoordinator=new V({onBecomeLeader:()=>{for(const s of this.subscriptions.all())this.ensureSocket(s.shardKey),this.sendSubscribeIfOpen(s)},onStopBeingLeader:()=>{for(const[s,i]of this.connections)i.socket?.close(),this.connections.delete(s)},onSubscriptionData:(s,i)=>{const n=this.subscriptions.get(s);if(n){n.serverBase=i;const r=n.optimisticLayers.length===0?i:A(i,n.optimisticLayers);n.lastValue=r;for(const o of n.callbacks)try{o(r)}catch{}}},onSubscriptionError:(s,i)=>{const n=this.subscriptions.get(s);if(n)for(const r of n.errorCallbacks)try{r(i)}catch{}}}),this.tabCoordinator.start()):this.tabCoordinator=void 0,t.hydrateOnStart&&this.queryCache?this.readyPromise=new Promise(s=>{this.readyResolve=s}):(this.readyResolved=!0,this.readyPromise=xe),this.offlineQueue=new et(t.offlineQueue,{onEvict:(s,i)=>{this.emitItemSettled(s,"rejected",i)},onSizeChange:s=>{this.pendingChangeListeners.emit(s)},persistence:this.persistence,version:t.persistenceVersion}),this.outbox=t.outbox,this.clientId=t.clientId??`client-${$()}`,this.persistence&&queueMicrotask(()=>{this.hydrateAsOutboxLeader()}),this.queryCache&&queueMicrotask(()=>{(async()=>{try{await this.hydrateQueryCache()}catch{}finally{this.readyResolved=!0,this.readyResolve?.()}})().catch(()=>{})})}setAuthToken(t,e){const s=this.authToken!==t,i=this.identityFingerprint();this.authToken=t,e!==void 0&&(this.authSubject=e);const n=this.identityFingerprint();n!==i&&(s?this.rejectQueuedForIdentityChange():this.restampQueuedIdentity(i,n)),s&&this.authTokenListeners.emit(t)}getAuthToken(){return this.authToken}currentIdentity(){return this.identityFingerprint()}clientIdentifier(){return this.clientId}confirmedMutationWatermark(t){return this.clientWatermarks.get(t??"")??0}async callMutator(t,e,s){const i=s?.clientSeq;if(i!==void 0&&(!Number.isInteger(i)||i<=0))throw new u("INTERNAL",`callMutator: clientSeq must be a positive integer, got ${String(i)}`);const n=s?.shardKey??"";let r;const o=await this.rpc(t,e,s?.shardKey,{captureBookmark:!0,clientId:this.clientId,clientSeq:i,onMutationAck:c=>{r=c}});return r!==void 0&&r>(this.clientWatermarks.get(n)??0)&&this.clientWatermarks.set(n,r),{applied:r===void 0||r===i,result:o}}onAuthTokenChange(t){return this.authTokenListeners.add(t)}async getCurrentUser(){if(this.closed||!this.fetchImpl)return null;const t={};this.authToken&&(t.authorization=`Bearer ${this.authToken}`);try{const e=await this.fetchImpl(b(this.url,`${this.authBasePath}${Re}`),{credentials:"include",headers:t,method:"GET"});return e.ok?(await e.json())?.user??null:null}catch{return null}}setWsToken(t){if(this.wsToken!==t){this.wsToken=t;for(const e of this.connections.values())if(e.socket)try{e.socket.close()}catch{}}}setConnectionContext(t,e={}){const s=m(e.shardKey);t===void 0?this.connectionContexts.delete(s):this.connectionContexts.set(s,t),this.refreshConnectionContext(s)}acquireConnectionContext(t,e={}){const s=m(e.shardKey),i={context:t},n=this.connectionContextHolders.get(s);n?n.push(i):this.connectionContextHolders.set(s,[i]),this.refreshConnectionContext(s);let r=!1;return()=>{if(r)return;r=!0;const o=this.connectionContextHolders.get(s);if(!o)return;const c=o.indexOf(i);c!==-1&&o.splice(c,1),o.length===0&&this.connectionContextHolders.delete(s),this.refreshConnectionContext(s)}}whisperSubscribe(t,e,s={}){const i=m(s.shardKey);let n=this.whisperHandlers.get(i);n||(n=new Map,this.whisperHandlers.set(i,n));let r=n.get(t);const o=r===void 0;if(r||(r=new Set,n.set(t,r)),r.add(e),this.ensureSocket(s.shardKey),o){const c=this.getConnection(s.shardKey);c&&y(c,{topic:t,type:"whisper_subscribe"})}return()=>{const c=this.whisperHandlers.get(i),a=c?.get(t);if(!a?.delete(e)||a.size>0)return;c?.delete(t),c?.size===0&&this.whisperHandlers.delete(i);const d=this.getConnection(s.shardKey);d&&y(d,{topic:t,type:"whisper_unsubscribe"})}}whisper(t,e,s={}){this.ensureSocket(s.shardKey);const i=this.getConnection(s.shardKey);i&&y(i,{data:v(e??null,`whisper data for topic '${t}'`),topic:t,type:"whisper"})}onTokenExpired(t){return this.tokenExpiredListeners.add(t)}connectionStatus(){return this.computeStatus()}onConnectionStatus(t){const e=this.statusListeners.add(t);return t(this.computeStatus()),e}pendingCount(){return this.offlineQueue.size}debug(){const t=[],e=new Set([...this.connections.keys(),...this.clientWatermarks.keys()]);for(const i of e){const n=this.connections.get(i);t.push({confirmedMutationWatermark:this.clientWatermarks.get(i)??0,hasSocket:n?.socket!==void 0,shardKey:i===""?void 0:i,wasEverConnected:n?.wasEverConnected??!1,wsState:n?.wsState??"idle"})}const s=this.subscriptions.all().map(i=>({acked:i.acked,functionPath:i.fn.__lunoraRef,id:i.id,kind:"query",lastMutationId:i.lastMutationId,pendingOptimisticLayers:i.optimisticLayers.length,serverCursor:i.serverCursor,shardKey:i.shardKey,subscriberCount:i.callbacks.size}));for(const i of this.shapeSubscriptions.values())s.push({acked:i.serverCursor!==void 0,functionPath:`shape:${i.name}`,id:i.id,kind:"shape",lastMutationId:i.lastMutationId,pendingOptimisticLayers:0,rowCount:i.rows.size,serverCursor:i.serverCursor,shardKey:i.shardKey,subscriberCount:i.callbacks.size});return{clientId:this.clientId,closed:this.closed,connectionStatus:this.computeStatus(),pendingWrites:this.offlineQueue.size,shards:t.toSorted((i,n)=>(i.shardKey??"").localeCompare(n.shardKey??"")),subscriptions:s.toSorted((i,n)=>i.functionPath.localeCompare(n.functionPath))}}onPendingChange(t){const e=this.pendingChangeListeners.add(t);return t(this.offlineQueue.size),e}onMutationSettled(t){return this.mutationSettledListeners.add(t)}getWebSocketImpl(){return this.WebSocketImpl}getClientQuery(t){return this.clientQueryStore.get(t)}setClientQuery(t,e){this.clientQueryStore.set(t,e)}subscribeClientQuery(t,e){return this.clientQueryStore.subscribe(t,e)}resetClientQuery(t){this.clientQueryStore.reset(t)}snapshotPrecondition(t,e,s){const i=this.peekActiveQueryValue(t.__lunoraRef,e,s),n=i===void 0?void 0:I(i);return()=>{const r=this.peekActiveQueryValue(t.__lunoraRef,e,s);return n===void 0&&r===void 0?!0:n===void 0||r===void 0?!1:I(r)===n}}whenReady(){return this.readyPromise}get isReady(){return this.readyResolved}peekHydratedQuery(t,e,s){if(!this.readyResolved)return;const i=I(e),n=R(t,i,s),r=this.hydratedQueryCache.get(n);if(r!==void 0)return r.identity===this.identityFingerprint()?r.value:void 0}peekActiveQueryValue(t,e,s){const i=k.key(t,e,s);return this.subscriptions.get(i)?.lastValue}async query(t,e,s={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return await this.rpc(t.__lunoraRef,e,s.shardKey,{attachBookmark:!0})}async batch(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");if(!this.fetchImpl)throw new u("INTERNAL","LunoraClient: no `fetch` implementation available");if(t.length===0)return[];const e=await this.fetchImpl(b(this.url,K),{body:JSON.stringify({calls:t.map((n,r)=>({args:v(n.args??{},`args for batch call '${n.fn.__lunoraRef}'`),functionPath:n.fn.__lunoraRef,id:r,shardKey:n.shardKey}))}),headers:this.rpcRequestHeaders({attachBookmark:!0}),method:"POST"}),s=e.headers.get("x-d1-bookmark");s&&this.bookmark.set(s);let i;try{i=await e.json()}catch{throw new u("INTERNAL",`LunoraClient: batch response was not JSON (status ${e.status.toString()})`)}if(!e.ok||i.error&&!i.results)throw i.error?C(i.error):new u("INTERNAL",`LunoraClient: batch request failed (status ${e.status.toString()})`);return Pe(i.results??[],t.length)}async mutation(t,e,s={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const i=e,n=s.mutationId??$(),{confirms:r,rollbacks:o}=this.applyOptimisticUpdates(t.__lunoraRef,i,s.shardKey,s.optimistic);s.optimisticUpdate&&this.applyOptimisticUpdate(s.optimisticUpdate,e,s.shardKey,o,r);const c=this.getConnection(s.shardKey),a=c?.wsState??"idle",d=c?.socket!==void 0,l=c?.wasEverConnected??!1,{queueBeforeFirstConnect:p}=this.offlineQueue,f=l||p,G=this.WebSocketImpl!==void 0&&f;if(a!=="open"&&!d&&G||a==="connecting"&&f)return this.enqueueOfflineMutation(t,i,s.shardKey,n,o,r,s.precondition);try{let T;const j=await this.rpc(t.__lunoraRef,i,s.shardKey,{captureBookmark:!0,mutationId:n,onCommitCursor:L=>{T=L}});for(const L of r)L(T);return j}catch(T){throw O(o),T}}async action(t,e,s={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return await this.rpc(t.__lunoraRef,e,s.shardKey)}async importRows(t,e,s={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const i=Math.max(1,Math.trunc(s.chunkSize??500)),n=s.toArgs??(a=>({rows:a})),r=e.length;let o=0,c=0;for(let a=0;a<r;a+=i){const d=e.slice(a,a+i),l=c;await this.mutation(t,n(d),{...s.importId===void 0?{}:{mutationId:`${s.importId}:${String(l)}`},shardKey:s.shardKey}),c+=1,o+=d.length,s.onProgress?.({done:o,total:r})}return{chunks:c,imported:o}}async shardTraffic(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=await this.adminFetch(yt,"POST",{table:t});return{failed:e.failed??0,ok:e.ok??0,shards:e.shards??[]}}async listScheduledJobs(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return(await this.adminFetch(wt,"GET")).records??[]}async schedulerStatus(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const t=await this.adminFetch(gt,"GET");return{backlog:t.backlog??0,inFlight:t.inFlight??0,pools:t.pools??[]}}async cancelScheduledJob(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return{cancelled:(await this.adminFetch(vt,"POST",{id:t})).cancelled===!0}}async listDeadJobs(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return(await this.adminFetch(kt,"GET")).records??[]}async retryDeadJob(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return{retried:(await this.adminFetch(St,"POST",{id:t})).retried===!0}}async removeDeadJob(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return{removed:(await this.adminFetch(Ct,"POST",{id:t})).removed===!0}}async listWorkflowInstances(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=new URLSearchParams({name:t.name});t.status!==void 0&&e.set("status",t.status),t.page!==void 0&&e.set("page",String(t.page)),t.perPage!==void 0&&e.set("perPage",String(t.perPage));const s=await this.adminFetch(`${Tt}?${e.toString()}`,"GET");return{configured:s.configured,instances:s.instances??[],page:s.page??1,perPage:s.perPage??t.perPage??0,totalCount:s.totalCount}}async getWorkflowInstance(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=new URLSearchParams({id:t.id,name:t.name}),s=await this.adminFetch(`${It}?${e.toString()}`,"GET");return{createdOn:s.createdOn,endedOn:s.endedOn,error:s.error,id:s.id??t.id,output:s.output,params:s.params,startedOn:s.startedOn,status:s.status??"unknown",steps:s.steps??[]}}async setWorkflowInstanceStatus(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return{status:(await this.adminFetch(Et,"POST",{action:t.action,id:t.id,name:t.name})).status??"unknown"}}subscribeScheduledJobs(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");if(this.WebSocketImpl===void 0)return()=>{};const e=b(U(this.url),bt),s=M(this.reconnectOptions);let i,n,r=!1;const o=d=>{if(r||this.WebSocketImpl===void 0)return;const l=d===void 0?e:`${e}?token=${encodeURIComponent(d)}`;i=new this.WebSocketImpl(l),i.addEventListener("open",()=>{s.reset()}),i.addEventListener("message",p=>{try{const f=JSON.parse(typeof p.data=="string"?p.data:"");f.type==="jobs"&&Array.isArray(f.records)&&t(f.records)}catch{}}),i.addEventListener("close",()=>{i=void 0,r||(n=setTimeout(a,s.next()))}),i.addEventListener("error",()=>{})},c=async d=>{let l;try{l=await d()}catch{r||(n=setTimeout(a,s.next()));return}o(l)},a=()=>{if(r||this.WebSocketImpl===void 0)return;const{wsToken:d}=this;if(typeof d=="function"){c(d).catch(()=>{});return}o(d)};return a(),()=>{r=!0,n!==void 0&&clearTimeout(n),i?.close()}}async listFunctions(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return(await this.adminFetch(Rt,"GET")).functions??[]}async getCronJobs(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return(await this.adminFetch(_t,"GET")).jobs??[]}async runCronJob(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=await this.adminFetch(Nt,"POST",{name:t});return{name:e.name??t,ran:e.ran===!0}}async fetchOpenApi(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return await this.adminFetch(Ot,"GET")}async fetchOpenRpc(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return await this.adminFetch(Pt,"GET")}async listStorageObjects(t={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=new URLSearchParams;t.prefix!==void 0&&t.prefix!==""&&e.set("prefix",t.prefix),t.cursor!==void 0&&t.cursor!==""&&e.set("cursor",t.cursor),t.limit!==void 0&&e.set("limit",String(t.limit)),t.bucket!==void 0&&t.bucket!==""&&e.set("bucket",t.bucket);const s=e.toString(),i=s===""?E:`${E}?${s}`,n=await this.adminFetch(i,"GET");return{cursor:n.cursor,objects:n.objects??[]}}async deleteStorageObject(t,e){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const s=`${E}?key=${encodeURIComponent(t)}${N(e?.bucket)}`,i=await this.adminFetch(s,"DELETE");return{deleted:i.deleted??!0,key:i.key??t}}async listStorageBuckets(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return(await this.adminFetch(At,"GET")).buckets??[]}async uploadStorageObject(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=`${E}?key=${encodeURIComponent(t.key)}${N(t.bucket)}`,s=await this.adminFetch(e,"PUT",t.body,t.contentType);return{etag:s.etag,key:s.key??t.key}}async signedStorageUrl(t,e){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const s=e?.expiresInSeconds,i=s===void 0?"":`&expiresIn=${encodeURIComponent(s.toString())}`,n=`${Lt}?key=${encodeURIComponent(t)}${i}${N(e?.bucket)}`,r=await this.adminFetch(n,"GET");if(typeof r.url!="string")throw new TypeError("LunoraClient: storage URL endpoint returned no `url`");return r.url}async listGlobalTables(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return await this.adminFetch(Ft,"GET")}async readGlobalTablePage(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=new URLSearchParams({table:t.table});return t.limit!==void 0&&e.set("limit",String(t.limit)),t.offset!==void 0&&e.set("offset",String(t.offset)),t.filters!==void 0&&t.filters.length>0&&e.set("filters",JSON.stringify(t.filters)),await this.adminFetch(`${xt}?${e.toString()}`,"GET")}async facetGlobalColumn(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=new URLSearchParams({column:t.column,table:t.table});return t.limit!==void 0&&e.set("limit",String(t.limit)),t.filters!==void 0&&t.filters.length>0&&e.set("filters",JSON.stringify(t.filters)),await this.adminFetch(`${$t}?${e.toString()}`,"GET")}async listVectorIndexes(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return(await this.adminFetch(Mt,"GET")).indexes??[]}async queryVectorIndex(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return(await this.adminFetch(Kt,"POST",t)).matches??[]}async queryLogArchive(t={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=await this.adminFetch(qt,"POST",t);return{nextCursor:e.nextCursor,rows:e.rows??[]}}async listKvNamespaces(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return(await this.adminFetch(Ut,"GET")).namespaces??[]}async listKvKeys(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=w(Qt,{cursor:t.cursor,limit:t.limit,namespace:t.namespace,prefix:t.prefix});return await this.adminFetch(e,"GET")}async getKvValue(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=w(P,{key:t.key,namespace:t.namespace});return await this.adminFetch(e,"GET")}async putKvValue(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");await this.adminFetch(P,"PUT",t)}async deleteKvKey(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=w(P,{key:t.key,namespace:t.namespace});await this.adminFetch(e,"DELETE")}async listAuthUsers(t={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=w(Bt,{filterField:t.filterField,filterValue:t.filterValue,limit:t.limit,offset:t.offset,search:t.search,searchField:t.searchField,sortBy:t.sortBy,sortDirection:t.sortDirection});return await this.adminFetch(e,"GET")}async createAuthUser(t){return await this.adminFetch(Wt,"POST",t)}async setAuthUserRole(t){return await this.adminFetch(zt,"POST",t)}async banAuthUser(t){return await this.adminFetch(Gt,"POST",t)}async unbanAuthUser(t){return await this.adminFetch(jt,"POST",t)}async setAuthUserPassword(t){await this.adminFetch(Dt,"POST",t)}async removeAuthUser(t){await this.adminFetch(Ht,"POST",t)}async impersonateAuthUser(t){return await this.adminFetch(Vt,"POST",t)}async revokeAuthSession(t){await this.adminFetch(Jt,"POST",t)}async revokeAuthUserSessions(t){await this.adminFetch(Xt,"POST",t)}async getAuthCapabilities(){return await this.adminFetch(Yt,"GET")}async updateAuthUser(t){return await this.adminFetch(Zt,"POST",t)}async listAuthAccounts(t){return await this.adminFetch(w(te,{userId:t.userId}),"GET")}async unlinkAuthAccount(t){await this.adminFetch(ee,"POST",t)}async listAuthPasskeys(t){return await this.adminFetch(w(se,{userId:t.userId}),"GET")}async deleteAuthPasskey(t){await this.adminFetch(ie,"POST",t)}async disableAuthTwoFactor(t){await this.adminFetch(ne,"POST",t)}async listAuthOrganizations(t={}){return await this.adminFetch(w(re,{limit:t.limit,offset:t.offset}),"GET")}async listAuthOrgMembers(t){const e=w(oe,{limit:t.limit,offset:t.offset,organizationId:t.organizationId});return await this.adminFetch(e,"GET")}async listAuthOrgInvitations(t){const e=w(ae,{limit:t.limit,offset:t.offset,organizationId:t.organizationId});return await this.adminFetch(e,"GET")}async removeAuthOrgMember(t){await this.adminFetch(ce,"POST",t)}async cancelAuthOrgInvitation(t){await this.adminFetch(he,"POST",t)}async getAuthConfig(){return await this.adminFetch(ue,"GET")}async createAuthOrganization(t){return await this.adminFetch(de,"POST",t)}async updateAuthOrganization(t){return await this.adminFetch(le,"POST",t)}async deleteAuthOrganization(t){await this.adminFetch(me,"POST",t)}async addAuthOrgMember(t){return await this.adminFetch(pe,"POST",t)}async inviteAuthOrgMember(t){return await this.adminFetch(fe,"POST",t)}async setAuthOrgMemberRole(t){return await this.adminFetch(ye,"POST",t)}async listAuthOrgTeams(t){const e=w(we,{limit:t.limit,offset:t.offset,organizationId:t.organizationId});return await this.adminFetch(e,"GET")}async createAuthOrgTeam(t){return await this.adminFetch(ge,"POST",t)}async updateAuthOrgTeam(t){return await this.adminFetch(be,"POST",t)}async removeAuthOrgTeam(t){await this.adminFetch(ve,"POST",t)}async listAuthOrgTeamMembers(t){const e=w(ke,{limit:t.limit,offset:t.offset,teamId:t.teamId});return await this.adminFetch(e,"GET")}async addAuthOrgTeamMember(t){return await this.adminFetch(Se,"POST",t)}async removeAuthOrgTeamMember(t){await this.adminFetch(Ce,"POST",t)}async listAuthOrgRoles(t){const e=w(Te,{limit:t.limit,offset:t.offset,organizationId:t.organizationId});return await this.adminFetch(e,"GET")}async createAuthOrgRole(t){return await this.adminFetch(Ie,"POST",t)}async updateAuthOrgRole(t){return await this.adminFetch(Ee,"POST",t)}async deleteAuthOrgRole(t){await this.adminFetch(Le,"POST",t)}async listAuthSessions(t={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=new URLSearchParams;t.userId!==void 0&&t.userId!==""&&e.set("userId",t.userId),t.limit!==void 0&&e.set("limit",String(t.limit)),t.offset!==void 0&&e.set("offset",String(t.offset));const s=e.toString();return await this.adminFetch(s===""?q:`${q}?${s}`,"GET")}subscribe(t,e,s,i={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const n=e??{},r=k.key(t.__lunoraRef,n,i.shardKey);let o=this.subscriptions.get(r);const c=s,a=i.onError;if(!o){this.nextSubId+=1;const l=`sub_${this.nextSubId.toString()}`,p=I(n),f=this.takeHydratedCache(t.__lunoraRef,p,i.shardKey);o={acked:!1,args:n,argsKey:p,callbacks:new Set,checkpointCallbacks:new Set,errorCallbacks:new Set,fn:t,id:l,lastValue:f?.value,optimisticLayers:[],serverBase:f?.value,serverCursor:f?.serverCursor,shardKey:i.shardKey,...f?.serverEpoch===void 0?{}:{serverEpoch:f.serverEpoch}},this.subscriptions.add(o)}if(o.callbacks.add(c),a&&o.errorCallbacks.add(a),i.onCheckpoint&&o.checkpointCallbacks.add(i.onCheckpoint),o.lastValue!==void 0)try{c(o.lastValue)}catch{}this.ensureSocket(i.shardKey),this.sendSubscribeIfOpen(o);const d=o;return()=>{if(d.callbacks.delete(c),a&&d.errorCallbacks.delete(a),i.onCheckpoint&&d.checkpointCallbacks.delete(i.onCheckpoint),d.callbacks.size===0){const l=this.getConnection(d.shardKey);!(l&&y(l,{id:d.id,type:"unsubscribe"}))&&l&&l.pendingUnsubscribes.push({id:d.id,type:"unsubscribe"}),this.subscriptions.remove(d)}}}subscribeShape(t,e,s={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");this.nextShapeId+=1;const i=`shape_${this.nextShapeId.toString()}`,n={args:t.args,callbacks:new Set([e]),errorCallbacks:s.onError?new Set([s.onError]):new Set,id:i,name:t.name,onCheckpoint:s.onCheckpoint,rows:new Map,shardKey:s.shardKey,wireArgs:t.args===void 0?void 0:v(t.args,`shape args for '${t.name}'`)};return this.shapeSubscriptions.set(i,n),this.ensureSocket(s.shardKey),this.sendShapeSubscribeIfOpen(n),()=>{this.shapeSubscriptions.delete(i);const r=this.getConnection(n.shardKey);!(r&&y(r,{id:i,type:"shape_unsubscribe"}))&&r&&r.pendingUnsubscribes.push({id:i,type:"shape_unsubscribe"})}}stream(t,e,s={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");if(this.WebSocketImpl===void 0)throw new u("INTERNAL","LunoraClient: streams require a WebSocket implementation");this.nextStreamId+=1;const i=`stream_${this.nextStreamId.toString()}`,{shardKey:n}=s,r=e??{},{handle:o,iterable:c}=ot({maxBuffer:s.maxBuffer,onCancel:()=>{const l=this.getConnection(n);l&&y(l,{id:i,type:"unsubscribe"}),this.streams.delete(i)}});this.streams.set(i,{handle:o,shardKey:n}),this.ensureSocket(n);const a=this.getConnection(n),d={id:i,query:{args:v(r,`stream args for '${t.__lunoraRef}'`),functionPath:t.__lunoraRef,shardKey:n},type:"stream"};if(!(a?.wsState==="open"&&y(a,d))&&a){for(a.pendingStreams=a.pendingStreams??[];a.pendingStreams.length>=ft;){const l=a.pendingStreams.shift()?.id,p=l?this.streams.get(l):void 0;p&&(p.handle.fail(new u("STREAM_QUEUE_OVERFLOW","stream-start frame evicted while socket was unreachable")),this.streams.delete(l))}a.pendingStreams.push(d)}return c}httpStream(t,e,s={}){if(this.closed)throw new u("CLIENT_CLOSED","LunoraClient is closed");if(!this.fetchImpl)throw new u("INTERNAL","LunoraClient: no `fetch` implementation available");const i={...this.authToken?{authorization:`Bearer ${this.authToken}`}:{},...s.headers};return Y(t,e,{baseUrl:this.url,fetch:this.fetchImpl,headers:i,maxBuffer:s.maxBuffer,signal:s.signal})}close(){this.closed=!0,this.outboxLeaderRelease?.(),this.outboxLeaderRelease=void 0;for(const t of this.streams.values())t.handle.fail(new u("CLIENT_CLOSED","LunoraClient closed"));this.streams.clear();for(const t of this.connections.values()){if(t.reconnectTimer!==void 0&&(clearTimeout(t.reconnectTimer),t.reconnectTimer=void 0),t.connectTimer!==void 0&&(clearTimeout(t.connectTimer),t.connectTimer=void 0),this.stopHeartbeat(t),t.socket){try{t.socket.close()}catch{}t.socket=void 0}t.wsState="closed"}this.offlineQueue.clear(),this.queuedIdentities.clear(),this.cacheFlushTimer!==void 0&&(clearTimeout(this.cacheFlushTimer),this.cacheFlushTimer=void 0),this.pendingCacheWrites.size>0&&this.flushQueryCacheWrites().catch(()=>{}),this.authTokenListeners.clear(),this.statusListeners.clear(),this.tokenExpiredListeners.clear(),this.mutationSettledListeners.clear(),this.pendingChangeListeners.clear(),this.whisperHandlers.clear(),this.shapeSubscriptions.clear(),this.pokeBuffers.clear(),this.tabCoordinator?.stop(),this.tabCoordinator=void 0}async enqueueOfflineMutation(t,e,s,i,n,r,o){const c=this.identityFingerprint();if(this.outbox){this.outboxMutationCounter+=1;const a=this.outboxMutationCounter;try{await this.outbox.enqueue({args:e,clientId:this.clientId,functionPath:t.__lunoraRef,idempotencyKey:`${this.clientId}:${String(a)}`,identity:c,mutationId:a,shardKey:s})}catch(d){throw O(n),d instanceof Error?d:new Error(String(d))}for(const d of r)d(void 0);return}return new Promise((a,d)=>{const l={args:e,functionPath:t.__lunoraRef,liveAwaiter:!0,id:i,identity:c,precondition:o,onCommit:p=>{for(const f of r)f(p)},reject:p=>{this.queuedIdentities.delete(i),O(n),d(p instanceof Error?p:new Error(String(p)))},resolve:a,shardKey:s};this.offlineQueue.enqueue(l),l.id!==void 0&&this.queuedIdentities.set(l.id,c)})}async hydratePersistedQueue(){try{const t=await this.offlineQueue.hydrate();for(const e of t)this.ensureSocket(e)}catch{}}hydrateAsOutboxLeader(){const t=()=>{this.hydratePersistedQueue().catch(()=>{})},e=globalThis.navigator?.locks;if(!e){t();return}e.request(`lunora:outbox-leader:${this.url}`,()=>(this.closed||t(),new Promise(s=>{if(this.closed){s();return}this.outboxLeaderRelease=s}))).catch(t)}async hydrateQueryCache(){if(this.queryCache)try{const t=await this.queryCache.load();for(const{key:e,...s}of t){if(st(this.persistenceVersion,s.version)){this.queryCache.remove(e).catch(()=>{});continue}this.hydratedQueryCache.set(e,s)}}catch{}}takeHydratedCache(t,e,s){const i=R(t,e,s),n=this.hydratedQueryCache.get(i);if(n!==void 0)return this.hydratedQueryCache.delete(i),n.identity===this.identityFingerprint()?n:void 0}persistQueryValue(t){const e=t.serverBase;if(!this.queryCache||e===void 0)return;const s=R(t.fn.__lunoraRef,t.argsKey,t.shardKey);this.pendingCacheWrites.set(s,{identity:this.identityFingerprint(),serverCursor:t.serverCursor,ts:Date.now(),value:e,...t.serverEpoch===void 0?{}:{serverEpoch:t.serverEpoch},...this.persistenceVersion===void 0?{}:{version:this.persistenceVersion}}),this.cacheFlushTimer??=setTimeout(()=>{this.flushQueryCacheWrites().catch(()=>{})},pt)}async flushQueryCacheWrites(){this.cacheFlushTimer=void 0;const{queryCache:t}=this;if(!t){this.pendingCacheWrites.clear();return}const e=[...this.pendingCacheWrites.entries()];this.pendingCacheWrites.clear(),await Promise.allSettled(e.map(([s,i])=>t.put(s,i)))}computeStatus(){const t=[...this.connections.values()];return t.length===0?"idle":t.some(e=>e.wsState==="open")?"connected":t.some(e=>e.wsState==="connecting")?"connecting":"offline"}emitConnectionStatus(){const t=this.computeStatus();t!==this.lastStatus&&(this.lastStatus=t,this.statusListeners.emit(t))}emitItemSettled(t,e,s){this.mutationSettledListeners.emit({args:t.args,code:s===void 0?void 0:s.code,error:s,functionPath:t.functionPath,hadAwaiter:t.liveAwaiter??!1,id:t.id??"",shardKey:t.shardKey,status:e})}applyOptimisticUpdates(t,e,s,i){const n=[],r=[];if(!i)return{confirms:n,rollbacks:r};const o=k.key(t,e,s),c=this.subscriptions.get(o);if(c){const a=Z(c,i);a&&(n.push(a.confirm),r.push(a.rollback))}return{confirms:n,rollbacks:r}}applyOptimisticUpdate(t,e,s,i,n){const{confirms:r,rollbacks:o,store:c}=tt(this.subscriptions,s);try{t(c,e)}catch{for(let a=o.length-1;a>=0;a-=1)o[a]?.();return}i.push(...o),n.push(...r)}getConnection(t){return this.connections.get(m(t))}getOrCreateConnection(t){const e=m(t);let s=this.connections.get(e);return s||(s={connectTimer:void 0,heartbeatTimer:void 0,pendingUnsubscribes:[],reconnect:M(this.reconnectOptions),reconnectTimer:void 0,shardKey:t,socket:void 0,wasEverConnected:!1,wsState:"idle"},this.connections.set(e,s)),s}wsUrlFor(t,e){const s=[];if(t!==void 0&&s.push(`shard=${encodeURIComponent(t)}`),e!==void 0&&s.push(`token=${encodeURIComponent(e)}`),s.length===0)return this.wsUrl;const i=this.wsUrl.includes("?")?"&":"?";return`${this.wsUrl}${i}${s.join("&")}`}rpcRequestHeaders(t){const e={"content-type":"application/json"};if(this.authToken&&(e.authorization=`Bearer ${this.authToken}`),t.mutationId&&(e["x-lunora-mutation-id"]=t.mutationId),t.clientId!==void 0&&(e["x-lunora-client-id"]=t.clientId),t.clientSeq!==void 0&&(e["x-lunora-client-seq"]=t.clientSeq.toString()),t.attachBookmark){const s=this.bookmark.get();s&&(e["x-d1-bookmark"]=s)}return e}async rpc(t,e,s,i={}){if(!this.fetchImpl)throw new u("INTERNAL","LunoraClient: no `fetch` implementation available");const n=this.rpcRequestHeaders(i),r=await this.fetchImpl(b(this.url,ct),{body:JSON.stringify({args:v(e,`args for '${t}'`),functionPath:t,shardKey:s}),headers:n,method:"POST"});if(i.captureBookmark){const c=r.headers.get("x-d1-bookmark");c&&this.bookmark.set(c)}let o;try{o=await r.json()}catch{const c=r.statusText?` ${r.statusText}`:"";throw new u("INTERNAL",`LunoraClient: response was not JSON (status ${r.status.toString()}${c})`)}if("error"in o)throw C(o.error);if(!r.ok){const c=r.statusText?` ${r.statusText}`:"";throw new u("INTERNAL",`LunoraClient: request failed (status ${r.status.toString()}${c})`)}return i.onMutationAck?.(o.lastMutationId),i.onCommitCursor?.(o.commitCursor),g(o.result)}async adminFetch(t,e,s,i){if(!this.fetchImpl)throw new u("INTERNAL","LunoraClient: no `fetch` implementation available");const n={};this.authToken&&(n.authorization=`Bearer ${this.authToken}`);const r=s instanceof ArrayBuffer||s instanceof Blob;let o;s===void 0?o=void 0:r?(o=s,i!==void 0&&(n["content-type"]=i)):(o=JSON.stringify(s),n["content-type"]="application/json");const c=await this.fetchImpl(b(this.url,t),{body:o,headers:n,method:e});let a;try{a=await c.json()}catch{const d=c.statusText?` ${c.statusText}`:"";throw new u("INTERNAL",`LunoraClient: response was not JSON (status ${c.status.toString()}${d})`)}if(typeof a=="object"&&a!==null&&"error"in a){const d=a.error,l=new Error(d.message??"admin request failed");throw l.code=d.code,l}if(!c.ok){const d=c.statusText?` ${c.statusText}`:"";throw new u("INTERNAL",`LunoraClient: admin request failed (status ${c.status.toString()}${d})`)}return a}effectiveConnectionContext(t){const e=this.connectionContextHolders.get(t);return e&&e.length>0?e[e.length-1]?.context:this.connectionContexts.get(t)??this.defaultConnectionContext}refreshConnectionContext(t){const e=this.connections.get(t);e?.wsState==="open"&&this.sendConnectEnvelope(e)}sendConnectEnvelope(t){const e=this.effectiveConnectionContext(m(t.shardKey));y(t,{clientId:this.clientId,id:"connect",type:"connect",...e===void 0?{}:{context:e}})}resendShapeSubscriptions(t){for(const e of this.shapeSubscriptions.values())m(e.shardKey)===m(t)&&this.sendShapeSubscribeIfOpen(e)}ensureSocket(t){if(this.closed||this.WebSocketImpl===void 0||this.tabCoordinator&&!this.tabCoordinator.isLeader())return;const e=this.getOrCreateConnection(t);if(!(e.wsState==="open"||e.wsState==="connecting")){if(e.wsState="connecting",this.emitConnectionStatus(),typeof this.wsToken=="function"){this.openSocketWithProvidedToken(e,t,this.wsToken).catch(()=>{});return}this.openSocket(e,t,this.wsToken)}}async openSocketWithProvidedToken(t,e,s){let i;try{i=await s()}catch{this.handleDisconnect(t);return}this.closed||this.WebSocketImpl===void 0||t.wsState!=="connecting"||t.socket!==void 0||this.openSocket(t,e,i)}openSocket(t,e,s){if(this.WebSocketImpl===void 0)return;const i=new this.WebSocketImpl(this.wsUrlFor(e,s));t.socket=i,this.connectTimeoutMs>0&&(t.connectTimer=setTimeout(()=>{if(t.connectTimer=void 0,!(t.socket!==i||t.wsState!=="connecting")){try{i.close()}catch{}this.handleDisconnect(t)}},this.connectTimeoutMs)),i.addEventListener("open",()=>{if(t.socket!==i)return;t.connectTimer!==void 0&&(clearTimeout(t.connectTimer),t.connectTimer=void 0),t.wsState="open",t.wasEverConnected=!0,t.reconnect.reset(),this.emitConnectionStatus(),this.sendConnectEnvelope(t),this.markShardPendingAck(e);for(const r of this.subscriptions.all())m(r.shardKey)===m(e)&&this.sendSubscribeIfOpen(r);if(this.resendShapeSubscriptions(e),t.pendingUnsubscribes.length>0){const r=t.pendingUnsubscribes;t.pendingUnsubscribes=[];for(const{id:o,type:c}of r)y(t,{id:o,type:c})}if(t.pendingStreams&&t.pendingStreams.length>0){const r=t.pendingStreams;t.pendingStreams=[];for(const o of r)y(t,o)}const n=this.whisperHandlers.get(m(e));if(n)for(const r of n.keys())y(t,{topic:r,type:"whisper_subscribe"});this.flushOfflineQueue(e).catch(()=>{}),this.startHeartbeat(t)}),i.addEventListener("message",n=>{this.handleServerMessage(n.data,e)}),i.addEventListener("close",n=>{t.socket===i&&(n?.code===4001&&this.notifyTokenExpired(),this.handleDisconnect(t))}),i.addEventListener("error",()=>{t.socket===i&&(t.wsState==="connecting"||t.wsState==="open")&&this.handleDisconnect(t)})}handleDisconnect(t){if(this.closed||t.wsState==="idle"||t.wsState==="closed")return;this.stopHeartbeat(t),t.connectTimer!==void 0&&(clearTimeout(t.connectTimer),t.connectTimer=void 0),t.socket=void 0,t.wsState="idle",this.emitConnectionStatus(),this.markShardPendingAck(t.shardKey);const e=new Set((t.pendingStreams??[]).map(i=>i.id));for(const[i,n]of this.streams)m(n.shardKey)===m(t.shardKey)&&!e.has(i)&&(n.handle.fail(new u("STREAM_DISCONNECTED","stream terminated: WebSocket disconnected")),this.streams.delete(i));if(this.WebSocketImpl===void 0)return;const s=t.reconnect.next();t.reconnectTimer=setTimeout(()=>{t.reconnectTimer=void 0,this.ensureSocket(t.shardKey)},s)}startHeartbeat(t){this.stopHeartbeat(t),!(this.heartbeatIntervalMs<=0)&&(t.heartbeatTimer=setInterval(()=>{if(!(t.wsState!=="open"||!t.socket))try{t.socket.send(dt)}catch{}},this.heartbeatIntervalMs))}stopHeartbeat(t){t.heartbeatTimer!==void 0&&(clearInterval(t.heartbeatTimer),t.heartbeatTimer=void 0)}markShardPendingAck(t){const e=m(t);for(const s of this.subscriptions.all())m(s.shardKey)===e&&(s.acked=!1)}sendSubscribeIfOpen(t){const e=this.getConnection(t.shardKey);if(e?.wsState!=="open"||t.acked)return;const s=t.fn.__lunoraTable??t.fn.__lunoraRef;y(e,{id:t.id,query:{args:W(t.args),functionPath:t.fn.__lunoraRef,table:s,...t.serverCursor===void 0?{}:{sinceSeq:t.serverCursor},...t.serverEpoch===void 0?{}:{sinceEpoch:t.serverEpoch}},type:"subscribe"})}sendShapeSubscribeIfOpen(t){const e=this.getConnection(t.shardKey);e?.wsState==="open"&&y(e,{id:t.id,shape:{name:t.name,...t.wireArgs===void 0?{}:{args:t.wireArgs}},type:"shape_subscribe",...t.serverCursor===void 0?{}:{sinceCheckpoint:t.serverCursor},...t.serverEpoch===void 0?{}:{sinceEpoch:t.serverEpoch}})}handleServerMessage(t,e){const s=Oe(t);if(s===void 0)return;let i;try{i=JSON.parse(s)}catch{return}switch(i.type){case"ack":{const n=this.subscriptions.getById(i.id);n&&(n.acked=!0);return}case"chunk":{const{data:n,id:r}=i;this.streams.get(r)?.handle.push(g(n));return}case"complete":{this.handleCompleteMessage(i.id);return}case"data":case"delta":{this.handleDataMessage(i);return}case"error":{this.handleErrorMessage(i);break}case"pokeEnd":{this.handlePokeEnd(i);break}case"pokePart":{this.handlePokePart(i);break}case"pokeStart":{this.handlePokeStart(i);break}case"resume":{this.handleResumeMessage(i);break}case"settled":{this.handleSettledMessage(i);break}case"whisper":{this.dispatchWhisper(i,e);break}}}handleErrorMessage(t){if(t.error?.code==="TOKEN_EXPIRED"){this.notifyTokenExpired();return}const{id:e}=t,s=e===void 0?void 0:this.streams.get(e);if(s&&e!==void 0){s.handle.fail(_e(t)),this.streams.delete(e);return}const i=e===void 0?void 0:this.subscriptions.getById(e);if(i){B(i.errorCallbacks,Q(t));return}const n=e===void 0?void 0:this.shapeSubscriptions.get(e);n&&B(n.errorCallbacks,Q(t))}handlePokeStart(t){at(this.pokeBuffers,z.MAX_POKE_BUFFERS),this.pokeBuffers.set(t.pokeId,{baseCheckpoint:t.baseCheckpoint,epoch:t.epoch,lastMutationId:new Map,parts:new Map})}handlePokePart(t){const e=this.pokeBuffers.get(t.pokeId);if(!e)return;const s=e.parts.get(t.shapeId)??[];for(const i of t.rowsPatch)s.push(i.value===void 0?i:{...i,value:g(i.value)});e.parts.set(t.shapeId,s),t.lastMutationId!==void 0&&e.lastMutationId.set(t.shapeId,t.lastMutationId)}handlePokeEnd(t){const e=this.pokeBuffers.get(t.pokeId);if(e){this.pokeBuffers.delete(t.pokeId);for(const[s,i]of e.parts){const n=this.shapeSubscriptions.get(s);if(!n)continue;const r=e.epoch!==void 0&&n.serverEpoch!==void 0&&e.epoch!==n.serverEpoch,o=e.baseCheckpoint!==void 0&&n.serverCursor!==void 0&&n.serverCursor!==e.baseCheckpoint;if(r||o){n.rows.clear(),n.serverCursor=void 0,n.serverEpoch=void 0,this.emitShapeRows(n),this.sendShapeSubscribeIfOpen(n);continue}ut(n.rows,i),t.checkpoint!==void 0&&(n.serverCursor=t.checkpoint),t.epoch!==void 0&&(n.serverEpoch=t.epoch);const c=e.lastMutationId.get(s);c!==void 0&&(n.lastMutationId=c),this.emitShapeRows(n),n.onCheckpoint?.({checkpoint:n.serverCursor,mutationId:n.lastMutationId})}}}emitShapeRows(t){const e=[...t.rows.values()];for(const s of t.callbacks)try{s(e)}catch{}}handleDataMessage(t){const{id:e}=t,s=e?this.subscriptions.getById(e):void 0;if(!s)return;const i=this.resolveDataPayload(t,s);if(s.serverBase=i,t.cursor!==void 0&&(s.serverCursor=t.cursor),t.epoch!==void 0&&(s.serverEpoch=t.epoch),this.persistQueryValue(s),F(s,s.serverCursor),x(s,s.optimisticLayers.length===0?i:A(i,s.optimisticLayers)),this.tabCoordinator?.isLeader()){const n=k.key(s.fn.__lunoraRef,s.args,s.shardKey);this.tabCoordinator.broadcastSubscriptionData(n,i)}}handleResumeMessage(t){const e=this.subscriptions.getById(t.id);e&&this.ackAndAdvanceCursor(e,t.cursor,t.epoch)}handleSettledMessage(t){const e=this.subscriptions.getById(t.id);if(e){this.ackAndAdvanceCursor(e,t.cursor,t.epoch),t.lastMutationId!==void 0&&(e.lastMutationId=t.lastMutationId);for(const s of e.checkpointCallbacks)s({checkpoint:e.serverCursor,mutationId:e.lastMutationId})}}ackAndAdvanceCursor(t,e,s){t.acked=!0,(e!==void 0&&e!==t.serverCursor||s!==void 0&&s!==t.serverEpoch)&&(e!==void 0&&(t.serverCursor=e),s!==void 0&&(t.serverEpoch=s),this.persistQueryValue(t),F(t,t.serverCursor)&&x(t,A(t.serverBase,t.optimisticLayers)))}resolveDataPayload(t,e){if("data"in t&&t.data!==void 0)return g(t.data);const s=g(t.delta);if(J(s)&&e.serverBase!==void 0){const i=X(e.serverBase,s);if(i!==void 0)return i}return s}dispatchWhisper(t,e){const s=this.whisperHandlers.get(m(e))?.get(t.topic);if(!s)return;const i=g(t.data);for(const n of s)try{n(i,t.from)}catch{}}notifyTokenExpired(){this.tokenExpiredListeners.emit()}handleCompleteMessage(t){const e=this.streams.get(t);if(e){e.handle.complete(),this.streams.delete(t);return}const s=this.subscriptions.getById(t);s&&this.subscriptions.remove(s)}unpersist(t){t&&this.persistence?.remove(t).catch(e=>{it(this.onPersistenceError,"remove",e,t)})}identityFingerprint(){if(this.authSubject!==void 0)return this.authSubject===null?null:`subj:${this.authSubject}`;const t=this.authToken;return t===null?null:this.hashToken(t)}hashToken(t){let e=2166136261,s=5381;for(let i=0;i<t.length;i+=1){const n=t.charCodeAt(i);e^=n,e=Math.imul(e,16777619),s=Math.imul(s,33)+n}return`${t.length.toString(36)}:${(e>>>0).toString(36)}:${(s>>>0).toString(36)}`}isSameCredentialUnderTokenHash(t){if(t===null||t.startsWith("subj:"))return!1;const e=this.authToken;return e===null?!1:this.hashToken(e)===t}rejectQueuedForIdentityChange(){const t=this.offlineQueue.drain();for(const e of t){this.queuedIdentities.delete(e.id??""),this.unpersist(e.id);const s=new Error("offline mutation discarded: auth identity changed before replay");s.code="OFFLINE_IDENTITY_CHANGED",e.reject(s),this.emitItemSettled(e,"rejected",s)}this.clearQueryCacheForIdentityChange()}restampQueuedIdentity(t,e){for(const[s,i]of this.queuedIdentities)i===t&&this.queuedIdentities.set(s,e)}clearQueryCacheForIdentityChange(){this.cacheFlushTimer!==void 0&&(clearTimeout(this.cacheFlushTimer),this.cacheFlushTimer=void 0),this.pendingCacheWrites.clear(),this.hydratedQueryCache.clear(),this.queryCache?.clear().catch(()=>{})}async flushOfflineQueue(t){const e=this.offlineQueue.drainConflict();for(const a of e){this.unpersist(a.id),this.queuedIdentities.delete(a.id??"");const d=new Error("offline mutation skipped: precondition failed before replay");d.code="OFFLINE_PRECONDITION_FAILED",this.emitItemSettled(a,"rejected",d)}const s=m(t),i=this.offlineQueue.drain(a=>m(a.shardKey)===s);if(i.length===0)return;const n=this.identityFingerprint(),r=[];for(const a of i)this.passesReplayIdentityGate(a,n)&&r.push(a);if(r.length===0)return;const o=this.encodableOrSettleTerminal(r);if(o.length===0)return;if(o.length===1){await this.replaySequential(o);return}const c=[];for(let a=0;a<o.length;a+=_){const d=o.slice(a,a+_),l=await this.replayBatched(d);if(c.push(...l.requeue),l.stop){c.push(...o.slice(a+_));break}}c.length>0&&this.offlineQueue.requeue(c)}encodableOrSettleTerminal(t){const e=[];for(const s of t)try{v(s.args,`args for '${s.functionPath}'`),e.push(s)}catch(i){this.settleReplayTerminal(s,i instanceof Error?i:new Error(String(i)))}return e}passesReplayIdentityGate(t,e){const s=t.id===void 0?void 0:this.queuedIdentities.get(t.id),i=s===void 0?t.identity:s;if(i!==void 0&&i!==e&&!this.isSameCredentialUnderTokenHash(i)){this.queuedIdentities.delete(t.id??""),this.unpersist(t.id);const n=new Error("offline mutation skipped: auth identity changed before replay");return n.code="OFFLINE_IDENTITY_CHANGED",t.reject(n),this.emitItemSettled(t,"rejected",n),!1}return this.queuedIdentities.delete(t.id??""),!0}settleReplaySuccess(t,e,s){this.unpersist(t.id),t.onCommit?.(s),t.resolve(e),this.emitItemSettled(t,"committed")}settleReplayTerminal(t,e){this.unpersist(t.id),t.reject(e),this.emitItemSettled(t,"rejected",e)}async replaySequential(t){for(let e=0;e<t.length;e+=1){const s=t[e];if(s)try{let i;const n=await this.rpc(s.functionPath,s.args,s.shardKey,{captureBookmark:!0,mutationId:s.id,onCommitCursor:r=>{i=r}});this.settleReplaySuccess(s,n,i)}catch(i){if(i.code!==void 0){this.settleReplayTerminal(s,i);continue}this.offlineQueue.requeue(t.slice(e));return}}}async replayBatched(t){if(!this.fetchImpl)return{requeue:t,stop:!0};let e;try{e=await this.fetchImpl(b(this.url,K),{body:JSON.stringify({calls:t.map((n,r)=>({args:v(n.args,`args for '${n.functionPath}'`),functionPath:n.functionPath,id:r,mutationId:n.id,shardKey:n.shardKey}))}),headers:this.rpcRequestHeaders({attachBookmark:!0}),method:"POST"})}catch{return{requeue:t,stop:!0}}const s=e.headers.get("x-d1-bookmark");s&&this.bookmark.set(s);let i;try{i=await e.json()}catch{return{requeue:t,stop:!0}}if(!i.results){if(i.error){const n=C(i.error);for(const r of t)this.settleReplayTerminal(r,n);return{requeue:[],stop:!1}}return{requeue:t,stop:!0}}return{requeue:this.settleReplayBatchSlots(t,i.results),stop:!1}}settleReplayBatchSlots(t,e){const s=new Map;for(const n of e)typeof n.id=="number"&&n.body!==void 0&&s.set(n.id,n.body);const i=[];for(const[n,r]of t.entries()){const o=s.get(n);o===void 0?i.push(r):"error"in o?Fe.has(o.error.code)?i.push(r):this.settleReplayTerminal(r,C(o.error)):this.settleReplaySuccess(r,g(o.result),o.commitCursor)}return i}}export{z as LunoraClient};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{c as s,u as o,s as t}from"./offline-queue-D73Dq95V.mjs";export{s as OfflineQueue,o as nextId,t as reportPersistenceError};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const E="skip",b=e=>e instanceof Error?{message:e.message}:{message:String(e)},f=(e,n,s,o,c={})=>{if(s===E)return o.onReset?.(),()=>{};let t=!1;const a=r=>{t||o.onError?.(r)},u=o.onError?a:void 0;let i;try{i=e.subscribe(n,s,r=>{t||o.onData(r)},{onError:u,shardKey:c.shardKey})}catch(r){if(!o.onError)throw r;return a(b(r)),()=>{t=!0}}return()=>{t=!0,i()}};export{E as SKIP,f as createQuerySubscription,b as toSubscriptionError};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as a}from"./wire-key-D_zOxXK4.mjs";class y{static key(e,t,s){return`${e}::${a(t)}::${s??""}`}byKey=new Map;byId=new Map;get(e){return this.byKey.get(e)}getById(e){return this.byId.get(e)}add(e){this.byKey.set(y.key(e.fn.__lunoraRef,e.args,e.shardKey),e),this.byId.set(e.id,e)}remove(e){const t=y.key(e.fn.__lunoraRef,e.args,e.shardKey);this.byKey.get(t)===e&&this.byKey.delete(t),this.byId.delete(e.id)}all(){return[...this.byKey.values()]}}export{y as SubscriptionRegistry};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let a=0;const r="lunora-bridge",i=1e3,s=3e3;class h{bc;tabId;heartbeatInterval;leaderTimeout;knownLeader=void 0;leader=!1;running=!1;lastHeartbeat=0;heartbeatTimer=void 0;leaderCheckTimer=void 0;onBecomeLeader;onStopBeingLeader;onSubscriptionData;onSubscriptionError;constructor(e={}){if(a+=1,this.tabId=`tab_${String(a)}_${crypto.randomUUID()}`,this.heartbeatInterval=e.heartbeatInterval??i,this.leaderTimeout=e.leaderTimeout??s,this.onBecomeLeader=e.onBecomeLeader,this.onStopBeingLeader=e.onStopBeingLeader,this.onSubscriptionData=e.onSubscriptionData,this.onSubscriptionError=e.onSubscriptionError,typeof BroadcastChannel>"u"){this.bc=void 0;return}this.bc=new BroadcastChannel(e.channelName??r),this.bc.addEventListener("message",t=>{this.handleMessage(t.data)})}start(){if(!this.running){if(this.running=!0,this.bc===void 0){this.becomeLeader();return}this.broadcast({type:"claim-leadership",tabId:this.tabId,ts:Date.now()}),setTimeout(()=>{this.running&&this.knownLeader===void 0&&this.becomeLeader()},this.leaderTimeout),this.leaderCheckTimer=setInterval(()=>{this.checkLeaderHealth()},this.leaderTimeout),this.heartbeatTimer=setInterval(()=>{this.sendHeartbeat()},this.heartbeatInterval)}}stop(){this.running=!1,this.leader&&(this.broadcast({type:"yield-leadership",tabId:this.tabId}),this.leader=!1,this.knownLeader=void 0,this.onStopBeingLeader?.()),this.heartbeatTimer!==void 0&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=void 0),this.leaderCheckTimer!==void 0&&(clearInterval(this.leaderCheckTimer),this.leaderCheckTimer=void 0),this.bc?.close()}isLeader(){return this.leader}get leaderTabId(){return this.knownLeader}get id(){return this.tabId}get isRunning(){return this.running}broadcastSubscriptionData(e,t){this.leader&&this.broadcast({type:"subscription-data",tabId:this.tabId,key:e,data:t})}broadcastSubscriptionError(e,t){this.leader&&this.broadcast({type:"subscription-error",tabId:this.tabId,key:e,error:t})}broadcast(e){this.bc?.postMessage(e)}handleMessage(e){switch(e.type){case"claim-leadership":{this.handleClaimLeadership(e);break}case"heartbeat":{this.handleHeartbeat(e);break}case"subscription-data":{if(this.leader||e.tabId===this.tabId)break;this.onSubscriptionData?.(e.key,e.data);break}case"subscription-error":{if(this.leader||e.tabId===this.tabId)break;this.onSubscriptionError?.(e.key,e.error);break}case"yield-leadership":{this.knownLeader===e.tabId&&(this.knownLeader=void 0);break}}}handleClaimLeadership(e){if(e.tabId!==this.tabId){if(this.leader){this.broadcast({type:"heartbeat",tabId:this.tabId,ts:Date.now()});return}this.knownLeader===void 0&&e.tabId<this.tabId&&(this.knownLeader=e.tabId,this.lastHeartbeat=e.ts)}}handleHeartbeat(e){if(e.tabId!==this.tabId){if(this.leader){this.resolveLeaderVsLeaderTieBreak(e);return}this.lastHeartbeat=e.ts,this.knownLeader=e.tabId}}resolveLeaderVsLeaderTieBreak(e){e.tabId<this.tabId?(this.leader=!1,this.knownLeader=e.tabId,this.lastHeartbeat=e.ts,this.onStopBeingLeader?.()):this.broadcast({type:"heartbeat",tabId:this.tabId,ts:Date.now()})}becomeLeader(){this.leader||(this.leader=!0,this.knownLeader=this.tabId,this.lastHeartbeat=Date.now(),this.onBecomeLeader?.(),this.broadcast({type:"heartbeat",tabId:this.tabId,ts:Date.now()}))}sendHeartbeat(){this.leader&&this.broadcast({type:"heartbeat",tabId:this.tabId,ts:Date.now()})}checkLeaderHealth(){this.running&&(this.leader||this.knownLeader!==void 0&&Date.now()-this.lastHeartbeat>this.leaderTimeout&&(this.knownLeader=void 0,this.broadcast({type:"claim-leadership",tabId:this.tabId,ts:Date.now()}),setTimeout(()=>{this.running&&this.knownLeader===void 0&&this.becomeLeader()},this.leaderTimeout)))}}export{h as TabCoordinator};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const u="_creationTime",p=t=>{if(typeof t!="object"||t===null)return;const e=t._id;return typeof e=="string"?e:void 0},a=t=>{let e;for(const r of t){const n=r[u];if(typeof n=="number"){if(e!==void 0){if(n<e)return!0;if(n>e)return!1}e=n}}return!1},d=(t,e)=>{const r=e[u];if(typeof r!="number")return t.length;const n=a(t);for(const[s,i]of t.entries()){const f=i[u];if(typeof f=="number"&&(n?f<r:f>r))return s}return t.length},y=t=>{if(typeof t!="object"||t===null)return!1;const e=t;return typeof e.key=="string"&&typeof e.table=="string"&&(e.op==="insert"||e.op==="update"||e.op==="delete")},g=(t,e)=>{if(!Array.isArray(t))return;const r=[];for(const o of t){if(p(o)===void 0)return;r.push(o)}const{key:n,op:s,row:i}=e;if(s==="delete"){const o=r.filter(c=>c._id!==n);return o.length===r.length?[...r]:o}if(i===void 0)return;const f=r.findIndex(o=>o._id===n);if(f===-1){const o=[...r];return o.splice(d(r,i),0,i),o}const l=[...r];return l[f]=i,l};export{g as applyDelta,y as isMutationDelta};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const y="lunora:offline-mutations",m=c=>{const{storage:n}=c,a=c.key??y;let o=Promise.resolve();const r=t=>{const e=o.then(t,t);return o=e.then(()=>{},()=>{}),e},s=async()=>{const t=await n.getItem(a);if(t===null)return[];try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}},i=t=>n.setItem(a,JSON.stringify(t));return{append:t=>r(async()=>{const e=await s();e.push(t),await i(e)}),clear:()=>r(()=>n.removeItem(a)),load:()=>r(s),remove:t=>r(async()=>{const e=await s(),l=e.filter(u=>u.id!==t);l.length!==e.length&&await i(l)})}};export{m as createAsyncStoragePersistence};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class u{values=new Map;subscribers=new Map;get(e){return this.values.has(e.key)?this.values.get(e.key):e.defaultValue}set(e,t){if(t===void 0){this.reset(e);return}this.values.set(e.key,t),this.notify(e.key,t)}reset(e){this.values.delete(e.key),this.notify(e.key,e.defaultValue)}subscribe(e,t){let s=this.subscribers.get(e.key);return s||(s=new Set,this.subscribers.set(e.key,s)),s.add(t),()=>{s.delete(t),s.size===0&&this.subscribers.delete(e.key)}}notify(e,t){const s=this.subscribers.get(e);if(s)for(const i of s)try{i(t)}catch{}}}const a=(r,e)=>({defaultValue:e,key:r});export{u as ClientQueryStore,a as createClientQuery};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const l=()=>{let e=null;return{get:()=>e,set:t=>{e=t}}};export{l as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as u}from"@lunora/errors";import{c as n,b as m,D as y}from"./idb-utility-C-DR8nG1.mjs";const D=()=>{const r=new Map,t=e=>({args:{...e.args},functionPath:e.functionPath,id:e.id,identity:e.identity,shardKey:e.shardKey});return{append:e=>(r.set(e.id,t(e)),Promise.resolve()),clear:()=>(r.clear(),Promise.resolve()),load:()=>Promise.resolve([...r.values()].map(e=>t(e))),remove:e=>(r.delete(e),Promise.resolve())}},f="lunora-outbox",p="offline-mutations",c="by_id",x=(r={})=>{const t=r.indexedDB??(typeof indexedDB>"u"?void 0:indexedDB);if(!t)throw new u("INTERNAL","createIndexedDbPersistence: no IndexedDB available — pass `indexedDB` or use createInMemoryPersistence()");const e=r.databaseName??f,s=r.storeName??p,l=y(t,e,1,a=>{a.objectStoreNames.contains(s)||a.createObjectStore(s,{autoIncrement:!0}).createIndex(c,"id",{unique:!0})}),o=m(l,s);return{append:async a=>{await o("readwrite",i=>n(i.add(a)))},clear:async()=>{await o("readwrite",a=>n(a.clear()))},load:async()=>o("readonly",a=>n(a.getAll())),remove:async a=>{await o("readwrite",async i=>{const d=await n(i.index(c).getKey(a));d!==void 0&&await n(i.delete(d))})}}},P=(r,t=!0)=>{if(r!==!1){if(r)return r;if(!(!t||typeof indexedDB>"u"))return x()}};export{D as createInMemoryPersistence,x as createIndexedDbPersistence,P as resolvePersistenceAdapter};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as p}from"@lunora/errors";import{c as i,b as x,D}from"./idb-utility-C-DR8nG1.mjs";const k=(a,o,t)=>`${a}::${o}::${t??""}`,v=500,P=(a={})=>{const o=a.maxEntries??v,t=new Map,c=e=>({...e,value:structuredClone(e.value)}),l=()=>{if(t.size<=o)return;const e=[...t.values()].toSorted((s,y)=>s.ts-y.ts);for(const s of e){if(t.size<=o)break;t.delete(s.key)}};return{clear:()=>(t.clear(),Promise.resolve()),load:()=>Promise.resolve([...t.values()].map(e=>c(e))),put:(e,s)=>(t.set(e,c({...s,key:e})),l(),Promise.resolve()),remove:e=>(t.delete(e),Promise.resolve())}},b="lunora-query-cache",h="query-cache",f="by_ts",C=1,I=(a={})=>{const o=a.indexedDB??(typeof indexedDB>"u"?void 0:indexedDB);if(!o)throw new p("INTERNAL","createIndexedDbQueryCache: no IndexedDB available — pass `indexedDB` or use createInMemoryQueryCache()");const t=a.databaseName??b,c=a.storeName??h,l=a.maxEntries??v,e=D(o,t,C,r=>{r.objectStoreNames.contains(c)||r.createObjectStore(c,{keyPath:"key"}).createIndex(f,"ts",{unique:!1})}),s=x(e,c),y=async r=>{let n=await i(r.count())-l;n<=0||await new Promise((d,w)=>{const u=r.index(f).openCursor();u.addEventListener("success",()=>{const m=u.result;if(!m||n<=0){d();return}m.delete(),n-=1,m.continue()}),u.addEventListener("error",()=>{w(u.error??new Error("IndexedDB eviction failed"))})})};return{clear:async()=>{await s("readwrite",r=>i(r.clear()))},load:async()=>s("readonly",r=>i(r.getAll())),put:async(r,n)=>{await s("readwrite",async d=>{await i(d.put({...n,key:r})),await y(d)})},remove:async r=>{await s("readwrite",n=>i(n.delete(r)))}}},N=a=>{if(a!==!1){if(a)return a;if(!(typeof indexedDB>"u"))return I()}};export{P as createInMemoryQueryCache,I as createIndexedDbQueryCache,k as queryCacheKey,N as resolveQueryCacheAdapter};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{c as t}from"./local-store-C53xDvEr.mjs";import"./SubscriptionRegistry-CdrOD7sZ.mjs";export{t as createLocalStore};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const i=(o,s,r)=>{let t=0;return async(a,c)=>{t+=1,r.setPending(!0);try{const n=await o.mutation(s,a,c);return r.setResult(n),n}catch(n){const e=n instanceof Error?n:new Error(String(n));throw r.setError(e),e}finally{t-=1,r.setPending(t>0)}}};export{i as createMutationRunner};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const c=(i,t)=>{let e=0,r=0;return{mutate:async a=>{r+=1;const o=r;e+=1,t.setPending(!0);try{await i(a).isPersisted.promise,o===r&&t.setError(void 0)}catch(n){const s=n instanceof Error?n:new Error(String(n));throw o===r&&t.setError(s),s}finally{e-=1,t.setPending(e>0)}},reset:()=>{t.setError(void 0)}}};export{c as createMutatorRunner};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const s=(e={},o=Math.random)=>{const a=e.initialDelayMs??250,c=e.maxDelayMs??3e4,i=e.jitter??!0;let t=0;return{next(){const n=Math.min(c,a*2**t);if(t+=1,!i)return n;const r=n/2;return Math.floor(r+o()*(n-r))},reset(){t=0}}};export{s as createReconnect};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const v=(e,r,d=!1)=>new Promise((a,s)=>{if(!e){s(new Error("No active service worker"));return}const o=r.correlationId??crypto.randomUUID(),i={...r,correlationId:o};if(d){let n;const t=c=>{c.data.correlationId===o&&(clearTimeout(n),navigator.serviceWorker.removeEventListener("message",t),a(c.data.payload))};n=setTimeout(()=>{navigator.serviceWorker.removeEventListener("message",t),s(new Error(`SW message ${o} timed out`))},3e4),navigator.serviceWorker.addEventListener("message",t),e.postMessage(i)}else e.postMessage(i),a(void 0)}),l=(e,r)=>({type:`${e.type}:reply`,payload:r,correlationId:e.correlationId});export{l as createReply,v as sendToSw};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraClient as r}from"./LunoraClient-DDEoZdgP.mjs";const o=t=>{const e=new r({fetch:t.fetch,url:t.url});return t.token!==void 0&&e.setAuthToken(t.token),e};export{o as createServerClient};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as n}from"./wire-key-D_zOxXK4.mjs";const d=(r,t,i,u)=>{const a=r.peekActiveQueryValue(t.__lunoraRef,i,u),e=a===void 0?void 0:n(a);return()=>{const o=r.peekActiveQueryValue(t.__lunoraRef,i,u);return e===void 0&&o===void 0?!0:e===void 0||o===void 0?!1:n(o)===e}};export{d as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const r=e=>JSON.stringify(e).replaceAll("<",String.raw`\u003c`),a=e=>JSON.parse(e);export{a as deserializePreloaded,r as serializePreloaded};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const a=e=>e instanceof Headers?e:e.headers,r=async(e,s)=>{const n=a(e);return await s.api.getSession({headers:n})??null};export{r as getServerSession};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import{LunoraError as f}from"@lunora/errors";import{createStream as h}from"./DEFAULT_MAX_BUFFER-TBn2s7Rz.mjs";const m=/^ /u,u=t=>typeof t=="object"&&t!==null?JSON.stringify(t):String(t),p=t=>{let r="";const e=[];for(const a of t.split(`
|
|
2
|
+
`))a.startsWith("event:")?r=a.slice(6).replace(m,""):a.startsWith("data:")&&e.push(a.slice(5).replace(m,""));return{data:e.join(`
|
|
3
|
+
`),event:r}},S=(t,r,e)=>{const a=r.params??{},s=t.path.split("/").map(l=>{if(!l.startsWith(":"))return l;const i=l.slice(1),d=a[i];if(d===void 0)throw new f("HTTP_STREAM_MISSING_PARAM",`httpStream: missing path param ":${i}" for route ${t.path}`);return encodeURIComponent(u(d))}).join("/"),c=new URLSearchParams;for(const[l,i]of Object.entries(r.searchParams??{}))i!==void 0&&c.set(l,u(i));const n=c.toString();return`${e.endsWith("/")?e.slice(0,-1):e}${s}${n===""?"":`?${n}`}`},T=(t,r)=>{if(t.event==="complete")return r.complete(),!0;if(t.event==="error"){let e={};try{e=JSON.parse(t.data)}catch{}const a=typeof e.message=="string"?e.message:"stream error",s=typeof e.code=="string"?e.code:"HTTP_STREAM_ERROR";return r.fail(new f(s,a)),!0}if((t.event===""||t.event==="message")&&t.data!=="")try{r.push(JSON.parse(t.data))}catch{return r.fail(new f("HTTP_STREAM_BAD_CHUNK","httpStream: malformed SSE chunk (invalid JSON)")),!0}return!1},g=async(t,r)=>{const e=t.getReader(),a=new TextDecoder;let s="";const c=()=>{let n=s.indexOf(`
|
|
4
|
+
|
|
5
|
+
`);for(;n!==-1;){const l=p(s.slice(0,n));if(s=s.slice(n+2),T(l,r))return!0;n=s.indexOf(`
|
|
6
|
+
|
|
7
|
+
`)}return!1};for(;;){const{done:n,value:l}=await e.read();if(n)break;if(s+=a.decode(l,{stream:!0}).replaceAll(`\r
|
|
8
|
+
`,`
|
|
9
|
+
`),c()){await e.cancel().catch(()=>{});return}}s+=a.decode().replaceAll(`\r
|
|
10
|
+
`,`
|
|
11
|
+
`),c()||r.fail(new f("HTTP_STREAM_INTERRUPTED","httpStream: stream ended without a complete frame"))},w=(t,r,e={})=>{const a=e.fetch??(typeof fetch=="function"?fetch.bind(globalThis):void 0);if(!a)throw new f("INTERNAL","httpStream: no `fetch` implementation available");const s=S(t,r??{},e.baseUrl??""),c=new AbortController;let n;e.signal&&(e.signal.aborted?c.abort():(n=()=>{c.abort()},e.signal.addEventListener("abort",n,{once:!0})));const l=()=>{n&&e.signal?.removeEventListener("abort",n)},{handle:i,iterable:d}=h({maxBuffer:e.maxBuffer,onCancel:()=>{c.abort()}});return(async()=>{try{const o=await a(s,{headers:{accept:"text/event-stream",...e.headers},method:t.method,signal:c.signal});if(!o.ok){await o.body?.cancel().catch(()=>{}),i.fail(new f("HTTP_STREAM_STATUS",`httpStream: request failed (status ${o.status.toString()})`,{status:o.status}));return}if(!o.body){i.fail(new f("HTTP_STREAM_NO_BODY","httpStream: response has no body"));return}await g(o.body,i)}finally{l()}})().catch(o=>{if(c.signal.aborted){i.complete();return}if(o instanceof Error&&"code"in o){i.fail(o);return}i.fail(new f("HTTP_STREAM_TRANSPORT",o instanceof Error?o.message:String(o),{cause:o}))}),d};export{w as httpStream};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const i=n=>new Promise((t,d)=>{n.addEventListener("success",()=>{t(n.result)}),n.addEventListener("error",()=>{d(n.error??new Error("IndexedDB request failed"))})}),c=(n,t,d,s)=>{let e;return()=>e||(e=new Promise((o,a)=>{const r=n.open(t,d);r.addEventListener("upgradeneeded",()=>{s(r.result)}),r.addEventListener("success",()=>{o(r.result)}),r.addEventListener("error",()=>{a(r.error??new Error("IndexedDB open failed"))})}),e)},E=(n,t)=>async(d,s)=>{const e=(await n()).transaction(t,d),o=await s(e.objectStore(t));return await new Promise((a,r)=>{e.addEventListener("complete",()=>{a()}),e.addEventListener("error",()=>{r(e.error??new Error("IndexedDB transaction failed"))}),e.addEventListener("abort",()=>{r(e.error??new Error("IndexedDB transaction aborted"))})}),o};export{c as D,E as b,i as c};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{SubscriptionRegistry as f}from"./SubscriptionRegistry-CdrOD7sZ.mjs";const m=(t,s)=>{let e=t;for(const o of s)try{e=o.transform(e)}catch{}return e},u=(t,s)=>{if(s!==t.lastValue){t.lastValue=s;for(const e of t.callbacks)try{e(s)}catch{}}},p=(t,s)=>{let e;try{e=s(t.lastValue)}catch{return}const o={id:Symbol("optimistic"),transform:s};t.optimisticLayers.push(o),u(t,e);const i=()=>{const r=t.optimisticLayers.findIndex(c=>c.id===o.id);return r===-1?!1:(t.optimisticLayers.splice(r,1),!0)},a=()=>{u(t,m(t.serverBase,t.optimisticLayers))};return{confirm:r=>{if(r===void 0){i();return}o.commitCursor=r,t.serverCursor!==void 0&&t.serverCursor>=r&&i()&&a()},rollback:()=>{i()&&a()}}},d=(t,s)=>{if(s===void 0||t.optimisticLayers.length===0)return!1;const e=t.optimisticLayers.length;return t.optimisticLayers=t.optimisticLayers.filter(o=>o.commitCursor===void 0||o.commitCursor>s),t.optimisticLayers.length!==e},L=(t,s)=>{const e=[],o=[],i=(a,r)=>t.get(f.key(a,r,s));return{confirms:e,rollbacks:o,store:{getAllQueries:a=>{const r=[];for(const c of t.all())c.fn.__lunoraRef===a.__lunoraRef&&(c.shardKey??"")===(s??"")&&r.push({args:c.args,value:c.lastValue});return r},getQuery:(a,r)=>i(a.__lunoraRef,r??{})?.lastValue,setQuery:(a,r,c)=>{const l=i(a.__lunoraRef,r??{});if(!l)return;const n=p(l,()=>c);n&&(e.push(n.confirm),o.push(n.rollback))}}}};export{p as a,L as c,d,m as f,u as n};
|
package/dist/packem_shared/{lunora-client.d-B1iZb2Ph.d.mts → lunora-client.d-Bt65hm_E.d.mts}
RENAMED
|
@@ -1234,6 +1234,7 @@ declare const createStream: <T>(options: {
|
|
|
1234
1234
|
handle: StreamHandle<T>;
|
|
1235
1235
|
iterable: StreamIterable<T>;
|
|
1236
1236
|
};
|
|
1237
|
+
type WSState = "idle" | "connecting" | "open" | "closed";
|
|
1237
1238
|
/**
|
|
1238
1239
|
* Aggregate live-socket health across every shard connection, for a UI status
|
|
1239
1240
|
* indicator. `idle` = no socket opened yet; `connecting` = at least one socket
|
|
@@ -1241,6 +1242,56 @@ declare const createStream: <T>(options: {
|
|
|
1241
1242
|
* `offline` = sockets exist but all are down (between reconnect attempts).
|
|
1242
1243
|
*/
|
|
1243
1244
|
type ConnectionStatus = "connected" | "connecting" | "idle" | "offline";
|
|
1245
|
+
/** One shard's socket + watermark state in a {@link LunoraClient.debug} snapshot. */
|
|
1246
|
+
interface ClientDebugShard {
|
|
1247
|
+
/**
|
|
1248
|
+
* Highest custom-mutator watermark the server has echoed for this client on this
|
|
1249
|
+
* shard. A write whose `clientSeq` is above this has been sent but not confirmed
|
|
1250
|
+
* — the first thing to check when an optimistic overlay won't clear.
|
|
1251
|
+
*/
|
|
1252
|
+
confirmedMutationWatermark: number;
|
|
1253
|
+
/** Whether a `WebSocket` object currently exists (distinct from it being open). */
|
|
1254
|
+
hasSocket: boolean;
|
|
1255
|
+
/** `undefined` for the default (unsharded) connection. */
|
|
1256
|
+
shardKey: string | undefined;
|
|
1257
|
+
/** Whether this shard's socket has ever completed a handshake — gates offline queueing. */
|
|
1258
|
+
wasEverConnected: boolean;
|
|
1259
|
+
wsState: WSState;
|
|
1260
|
+
}
|
|
1261
|
+
/** One live query or shape subscription in a {@link LunoraClient.debug} snapshot. */
|
|
1262
|
+
interface ClientDebugSubscription {
|
|
1263
|
+
/** Whether the server has acknowledged the subscription on the current socket. */
|
|
1264
|
+
acked: boolean;
|
|
1265
|
+
/** `namespace:fn` for a query, `shape:<name>` for a replication shape. */
|
|
1266
|
+
functionPath: string;
|
|
1267
|
+
id: string;
|
|
1268
|
+
kind: "query" | "shape";
|
|
1269
|
+
/** Highest custom-mutator watermark echoed on THIS subscription (absent until a `settled`/poke frame arrives). */
|
|
1270
|
+
lastMutationId?: number;
|
|
1271
|
+
/** Per-call optimistic layers still folded onto this subscription's value — a non-zero count with no pending write is a leak. */
|
|
1272
|
+
pendingOptimisticLayers: number;
|
|
1273
|
+
/** Replicated rowset size (shapes only). */
|
|
1274
|
+
rowCount?: number;
|
|
1275
|
+
/** The `__cdc_log` cursor the current value reflects. */
|
|
1276
|
+
serverCursor?: number;
|
|
1277
|
+
shardKey: string | undefined;
|
|
1278
|
+
/** How many callers share this subscription (subscriptions are deduped by `(fn, args, shard)`). */
|
|
1279
|
+
subscriberCount: number;
|
|
1280
|
+
}
|
|
1281
|
+
/**
|
|
1282
|
+
* Everything the sync engine believes at one instant — see
|
|
1283
|
+
* {@link LunoraClient.debug} for why this exists.
|
|
1284
|
+
*/
|
|
1285
|
+
interface ClientDebugSnapshot {
|
|
1286
|
+
/** The watermark key the server's custom-mutator protocol advances per `clientSeq`. */
|
|
1287
|
+
clientId: string;
|
|
1288
|
+
closed: boolean;
|
|
1289
|
+
connectionStatus: ConnectionStatus;
|
|
1290
|
+
/** Writes waiting in the built-in offline queue (not the `@lunora/db` outbox). */
|
|
1291
|
+
pendingWrites: number;
|
|
1292
|
+
shards: ClientDebugShard[];
|
|
1293
|
+
subscriptions: ClientDebugSubscription[];
|
|
1294
|
+
}
|
|
1244
1295
|
/**
|
|
1245
1296
|
* Terminal verdict for a mutation that passed through the offline queue,
|
|
1246
1297
|
* delivered to {@link LunoraClient.onMutationSettled}.
|
|
@@ -1703,6 +1754,28 @@ declare class LunoraClient {
|
|
|
1703
1754
|
* `LunoraDb.pendingCount()` instead (this counts only the built-in queue).
|
|
1704
1755
|
*/
|
|
1705
1756
|
pendingCount(): number;
|
|
1757
|
+
/**
|
|
1758
|
+
* A point-in-time snapshot of everything the sync engine believes right now:
|
|
1759
|
+
* per-shard sockets and watermarks, every live query and shape subscription with
|
|
1760
|
+
* its cursor and ack state, and the offline-queue depth.
|
|
1761
|
+
*
|
|
1762
|
+
* This exists because the alternative is `console.log`. When an optimistic
|
|
1763
|
+
* overlay doesn't clear, the questions are always the same — *is the socket open?
|
|
1764
|
+
* what watermark has the server confirmed for this shard? has this shape been
|
|
1765
|
+
* poked since my write? is anything stuck in the queue?* — and none of them were
|
|
1766
|
+
* answerable from outside the client, so every adopter ends up instrumenting the
|
|
1767
|
+
* library by hand or building a bespoke policy layer around a symptom.
|
|
1768
|
+
*
|
|
1769
|
+
* Read it from a devtools console, log it next to a bug report, or render it in a
|
|
1770
|
+
* debug panel. Pull-only and allocation-cheap; nothing here is reactive, so poll
|
|
1771
|
+
* it or read it on demand.
|
|
1772
|
+
*
|
|
1773
|
+
* ```ts
|
|
1774
|
+
* const { shards, subscriptions } = client.debug();
|
|
1775
|
+
* // shards: [{ shardKey: "user-1", wsState: "open", confirmedMutationWatermark: 42, … }]
|
|
1776
|
+
* ```
|
|
1777
|
+
*/
|
|
1778
|
+
debug(): ClientDebugSnapshot;
|
|
1706
1779
|
/**
|
|
1707
1780
|
* Subscribe to changes in {@link pendingCount}. Invokes `listener` immediately
|
|
1708
1781
|
* with the current count, then whenever the queue depth changes (a write is
|
|
@@ -1856,6 +1929,67 @@ declare class LunoraClient {
|
|
|
1856
1929
|
action<F extends FunctionReference>(function_: F, args: ArgsOf<F>, options?: {
|
|
1857
1930
|
shardKey?: string;
|
|
1858
1931
|
}): Promise<ReturnOf<F>>;
|
|
1932
|
+
/**
|
|
1933
|
+
* Bulk-import `rows` through a mutation that accepts a batch, chunked so a large
|
|
1934
|
+
* dataset lands in a bounded number of round-trips.
|
|
1935
|
+
*
|
|
1936
|
+
* **Offline caveat:** each chunk is sent with {@link LunoraClient.mutation}, which
|
|
1937
|
+
* resolves once the write is durably queued rather than once the server has applied
|
|
1938
|
+
* it. So an import run while offline resolves `{ chunks, imported }` with nothing
|
|
1939
|
+
* committed yet — the counts describe what was *handed over*, and the outbox
|
|
1940
|
+
* replays them on reconnect. Don't report "migration complete" on this alone.
|
|
1941
|
+
*
|
|
1942
|
+
* This is the one-shot migration / seed path: "I have 20k rows client-side and a
|
|
1943
|
+
* server mutation that inserts many at once". Doing it by hand goes wrong in two
|
|
1944
|
+
* predictable ways — a serial per-row loop pays one round-trip *and* one watermark
|
|
1945
|
+
* wait per row (a 200-row import becomes 200 sequential hops), while a single
|
|
1946
|
+
* giant call blows the DO's batch limit. So: chunk, send sequentially, and give
|
|
1947
|
+
* each chunk a stable idempotency key derived from `importId` + its index, so a
|
|
1948
|
+
* resumed or retried import doesn't double-insert the chunks that already landed.
|
|
1949
|
+
*
|
|
1950
|
+
* The server mutation is yours (Lunora can't guess the table or the row shape);
|
|
1951
|
+
* back it with `ctx.db.insertMany(...)`, or `insertManyUnsafe(...)` for data you
|
|
1952
|
+
* vouch for. `chunkSize` defaults to 500, matching the DO's default batch cap.
|
|
1953
|
+
*
|
|
1954
|
+
* ```ts
|
|
1955
|
+
* await client.importRows(api.migrate.importNodes, nodes, {
|
|
1956
|
+
* importId: `migrate-${userId}`,
|
|
1957
|
+
* onProgress: ({ done, total }) => setProgress(done / total),
|
|
1958
|
+
* shardKey: userId,
|
|
1959
|
+
* toArgs: (chunk) => ({ nodes: chunk }),
|
|
1960
|
+
* });
|
|
1961
|
+
* ```
|
|
1962
|
+
*/
|
|
1963
|
+
importRows(function_: FunctionReference, rows: ReadonlyArray<unknown>, options?: {
|
|
1964
|
+
/** Rows per call. Defaults to 500 — the DO's default batch cap. */
|
|
1965
|
+
chunkSize?: number;
|
|
1966
|
+
/**
|
|
1967
|
+
* Stable id for this import run. Each chunk is sent under
|
|
1968
|
+
* `${importId}:${chunkIndex}` as its mutation id, so a retry or a resumed
|
|
1969
|
+
* import is deduped server-side instead of inserting the chunk twice.
|
|
1970
|
+
* Omit only for a throwaway import where double-insertion is acceptable.
|
|
1971
|
+
*/
|
|
1972
|
+
importId?: string;
|
|
1973
|
+
/**
|
|
1974
|
+
* Called after each chunk is accepted — for a progress bar.
|
|
1975
|
+
*
|
|
1976
|
+
* "Accepted" is not always "committed": while offline (or mid-reconnect) a
|
|
1977
|
+
* `mutation` resolves as soon as the write is durably **queued**, so a fully
|
|
1978
|
+
* offline import reports completion with nothing yet applied server-side.
|
|
1979
|
+
* Gate a migration's "done" state on connectivity, not just on this.
|
|
1980
|
+
*/
|
|
1981
|
+
onProgress?: (progress: {
|
|
1982
|
+
done: number;
|
|
1983
|
+
total: number;
|
|
1984
|
+
}) => void;
|
|
1985
|
+
/** Routes every chunk to one shard's DO. */
|
|
1986
|
+
shardKey?: string;
|
|
1987
|
+
/** Build the mutation args for one chunk. Defaults to `{ rows: chunk }`. */
|
|
1988
|
+
toArgs?: (chunk: ReadonlyArray<unknown>) => Record<string, unknown>;
|
|
1989
|
+
}): Promise<{
|
|
1990
|
+
chunks: number;
|
|
1991
|
+
imported: number;
|
|
1992
|
+
}>;
|
|
1859
1993
|
/**
|
|
1860
1994
|
* Read the cross-shard request distribution for a `.shardBy(...)` table —
|
|
1861
1995
|
* the feed the studio's `hot_shard` advisor lint consumes. Hits the
|
|
@@ -2842,4 +2976,4 @@ declare class LunoraClient {
|
|
|
2842
2976
|
*/
|
|
2843
2977
|
private settleReplayBatchSlots;
|
|
2844
2978
|
}
|
|
2845
|
-
export {
|
|
2979
|
+
export { SchedulerStatus as $, ArgsOf as A, BookmarkStorage as B, CONFLICT_ERROR_CODE as C, DEFAULT_MAX_BUFFER as D, LunoraErrorCode as E, FunctionReference as F, GlobalFacetResult as G, HttpStreamRef as H, MutationSettledEvent as I, OptimisticLocalStore as J, OptimisticUpdate as K, LunoraClient as L, MutationCallOptions as M, OutboxMutation as N, OfflineQueueOptions as O, Preloaded as P, QueryCacheAdapter as Q, ReturnOf as R, SubscriptionError as S, OutboxSink as T, User as U, PersistedMutation as V, RowOp as W, RpcEnvelope as X, RpcResponseBody as Y, ScheduleRecord as Z, SchedulerPoolStatus as _, Unsubscribe as a, ServerMessage as a0, ServerPokeEndMessage as a1, ServerPokePartMessage as a2, ServerPokeStartMessage as a3, ShardTrafficEntry as a4, ShardTrafficResult as a5, StorageListPage as a6, StorageObject as a7, StreamHandle as a8, SubscriptionCallback as a9, SubscriptionRegistry as aa, SubscriptionState as ab, SyncWatermark as ac, WorkflowInstanceAction as ad, WorkflowInstanceDetail as ae, WorkflowInstancePage as af, WorkflowInstanceStatus as ag, WorkflowInstanceSummary as ah, WorkflowStepDetail as ai, WsTokenProvider as aj, createClientQuery as ak, createLocalStore as al, createStream as am, getErrorCode as an, getRetryAfterMs as ao, isConflictError as ap, isForbiddenError as aq, isRateLimitedError as ar, isUnauthorizedError as as, SubscriptionErrorCallback as b, PersistenceAdapter as c, HttpStreamArgsOf as d, HttpStreamChunkOf as e, StreamIterable as f, ReconnectOptions as g, BatchSlot as h, CachedQuery as i, ClientDebugShard as j, ClientDebugSnapshot as k, ClientDebugSubscription as l, ClientMessage as m, ClientQueryRef as n, ClientShapeSubscribeMessage as o, ClientShapeUnsubscribeMessage as p, ConnectionStatus as q, FunctionArgumentDescriptor as r, FunctionDescriptor as s, GlobalFacetValue as t, GlobalFilterClause as u, GlobalTableInfo as v, GlobalTablePage as w, HttpStreamCallArgs as x, LunoraClientError as y, LunoraClientOptions as z };
|