@lunora/client 1.0.0-alpha.2 → 1.0.0-alpha.21
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/LICENSE.md +6 -0
- package/README.md +2 -0
- package/__assets__/package-og.svg +1 -1
- package/dist/auth/index.d.mts +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/index.d.mts +144 -24
- package/dist/index.d.ts +144 -24
- package/dist/index.mjs +10 -9
- package/dist/packem_shared/CONFLICT_ERROR_CODE-B8gQ8tyU.mjs +33 -0
- package/dist/packem_shared/{DEFAULT_MAX_BUFFER-BDkqO5PW.mjs → DEFAULT_MAX_BUFFER-7hFnzNk9.mjs} +6 -3
- package/dist/packem_shared/{LunoraClient-UiULzH_1.mjs → LunoraClient-kXpHNyaE.mjs} +1562 -267
- package/dist/packem_shared/OfflineQueue-GGYJRmhF.mjs +1 -0
- package/dist/packem_shared/SubscriptionRegistry-DjGKZsqq.mjs +1 -0
- package/dist/packem_shared/{applyDelta-4jFGTPA3.mjs → applyDelta-CRKZ1PBt.mjs} +21 -1
- package/dist/packem_shared/createInMemoryPersistence-DZ2VHWgm.mjs +79 -0
- package/dist/packem_shared/{createInMemoryQueryCache-B1PQ9Twl.mjs → createInMemoryQueryCache-DiaGZkA2.mjs} +25 -51
- package/dist/packem_shared/createLocalStore-jRoqmazl.mjs +2 -0
- package/dist/packem_shared/createMutatorRunner-BETvCd0p.mjs +31 -0
- package/dist/packem_shared/{createServerClient-BjZc3gD8.mjs → createServerClient-DF-3mLmb.mjs} +1 -1
- package/dist/packem_shared/idb-utility-DrSVX43Q.mjs +48 -0
- package/dist/packem_shared/local-store-BveBeFEo.mjs +106 -0
- package/dist/packem_shared/{lunora-client.d-DGvyuJ_p.d.mts → lunora-client.d-BYkEjCEJ.d.mts} +1001 -58
- package/dist/packem_shared/{lunora-client.d-DGvyuJ_p.d.ts → lunora-client.d-BYkEjCEJ.d.ts} +1001 -58
- package/dist/packem_shared/{OfflineQueue-D5p_QgF_.mjs → offline-queue-B9vfdSqp.mjs} +49 -6
- package/dist/packem_shared/{preload.d-BoDmFqSG.d.ts → preload.d-B-vyHnml.d.ts} +1 -1
- package/dist/packem_shared/{preload.d-dSaRMuhL.d.mts → preload.d-DrfuisCE.d.mts} +1 -1
- package/dist/packem_shared/subscription-BjynOXCU.mjs +68 -0
- package/dist/query/index.d.mts +2 -2
- package/dist/query/index.d.ts +2 -2
- package/dist/ssr/index.d.mts +3 -3
- package/dist/ssr/index.d.ts +3 -3
- package/dist/ssr/index.mjs +1 -1
- package/package.json +5 -2
- package/dist/packem_shared/CONFLICT_ERROR_CODE-aUdVbEDw.mjs +0 -4
- package/dist/packem_shared/SubscriptionRegistry-B-Qx_Gux.mjs +0 -26
- package/dist/packem_shared/createInMemoryPersistence-CW82inU5.mjs +0 -105
- package/dist/packem_shared/createLocalStore-DSUfoLqY.mjs +0 -36
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-BYkEjCEJ.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-BYkEjCEJ.js";
|
|
2
2
|
import '@lunora/runtime';
|
|
3
3
|
interface IdentityStore {
|
|
4
4
|
/** Read the current resolved user, or `null` when signed out / not yet resolved. */
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { c as PersistenceAdapter, B as BookmarkStorage, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, d as ReconnectOptions } from "./packem_shared/lunora-client.d-
|
|
2
|
-
export { type C as CachedQuery, type
|
|
3
|
-
export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-
|
|
4
|
-
export type { AuthCapabilities, AuthImpersonation, AuthPage, AuthSession, AuthUser, CronJobInfo, VectorIndexSummary, VectorQueryMatch } from '@lunora/runtime';
|
|
1
|
+
import { c as PersistenceAdapter, B as BookmarkStorage, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, d as ReconnectOptions } from "./packem_shared/lunora-client.d-BYkEjCEJ.mjs";
|
|
2
|
+
export { type e as BatchSlot, C as CONFLICT_ERROR_CODE, type f as CachedQuery, type g as ClientMessage, type h as ClientShapeSubscribeMessage, type i as ClientShapeUnsubscribeMessage, type j as ConnectionStatus, D as DEFAULT_MAX_BUFFER, type k as FunctionArgumentDescriptor, type l as FunctionDescriptor, type G as GlobalFacetResult, type m as GlobalFacetValue, type n as GlobalFilterClause, type o as GlobalTableInfo, type p as GlobalTablePage, L as LunoraClient, type q as LunoraClientError, type r as LunoraClientOptions, type s as LunoraErrorCode, type t as MutationSettledEvent, type u as OptimisticLocalStore, type v as OptimisticUpdate, type w as OutboxMutation, type x as OutboxSink, type y as PersistedMutation, type P as Preloaded, type z as RowOp, type E as RpcEnvelope, type H as RpcResponseBody, type I as ScheduleRecord, type J as SchedulerPoolStatus, type K as SchedulerStatus, type N as ServerMessage, type T as ServerPokeEndMessage, type V as ServerPokePartMessage, type W as ServerPokeStartMessage, type X as ShardTrafficEntry, type Y as ShardTrafficResult, type Z as StorageListPage, type _ as StorageObject, type $ as StreamHandle, type a0 as StreamIterable, type a1 as SubscriptionCallback, type S as SubscriptionError, type b as SubscriptionErrorCallback, a2 as SubscriptionRegistry, type a3 as SubscriptionState, type a4 as SyncWatermark, type a as Unsubscribe, type U as User, type a5 as WorkflowInstanceAction, type a6 as WorkflowInstanceDetail, type a7 as WorkflowInstancePage, type a8 as WorkflowInstanceStatus, type a9 as WorkflowInstanceSummary, type aa as WorkflowStepDetail, ab as createLocalStore, ac as createStream, ad as getErrorCode, ae as getRetryAfterMs, af as isConflictError, ag as isForbiddenError, ah as isRateLimitedError, ai as isUnauthorizedError } from "./packem_shared/lunora-client.d-BYkEjCEJ.mjs";
|
|
3
|
+
export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-DrfuisCE.mjs";
|
|
4
|
+
export type { AuthCapabilities, AuthConfigInfo, AuthImpersonation, AuthPage, AuthSession, AuthUser, AuthUserFieldSpec, CronJobInfo, KvKeyEntry, KvKeyListResult, KvNamespaceSummary, KvValueResult, VectorIndexSummary, VectorQueryMatch } from '@lunora/runtime';
|
|
5
5
|
/**
|
|
6
6
|
* The slice of React Native's `AsyncStorage` (or any async key/value store —
|
|
7
7
|
* Expo `SecureStore`, a wrapped `localForage`, an in-memory map in tests) this
|
|
@@ -95,17 +95,6 @@ declare const isMutationDelta: (value: unknown) => value is MutationDelta;
|
|
|
95
95
|
* when an `insert`/`update` delta carries no `row` to splice in.
|
|
96
96
|
*/
|
|
97
97
|
declare const applyDelta: (current: unknown, delta: MutationDelta) => undefined | unknown[];
|
|
98
|
-
/** Error code the server uses for optimistic-concurrency conflicts (HTTP 409). */
|
|
99
|
-
declare const CONFLICT_ERROR_CODE = "CONFLICT";
|
|
100
|
-
/**
|
|
101
|
-
* Whether an unknown rejection is an optimistic-concurrency conflict — the
|
|
102
|
-
* server lost a write race and the caller should refetch and retry (or surface
|
|
103
|
-
* the conflict). Structural check on the `code` property the client attaches
|
|
104
|
-
* when decoding the worker's `{ error: { code, message } }` envelope.
|
|
105
|
-
*/
|
|
106
|
-
declare const isConflictError: (error: unknown) => error is Error & {
|
|
107
|
-
code: "CONFLICT";
|
|
108
|
-
};
|
|
109
98
|
/** The single transport method a mutation runner needs — narrowed so adapters can test against a stub. */
|
|
110
99
|
interface MutationCapableClient<F extends FunctionReference> {
|
|
111
100
|
mutation: (function_: F, args: ArgsOf<F>, options?: MutationCallOptions<unknown, unknown, ArgsOf<F>>) => Promise<ReturnOf<F>>;
|
|
@@ -136,6 +125,59 @@ interface MutationRunnerSinks<R> {
|
|
|
136
125
|
* pass straight through to `client.mutation`.
|
|
137
126
|
*/
|
|
138
127
|
declare const createMutationRunner: <F extends FunctionReference>(client: MutationCapableClient<F>, function_: F, sinks: MutationRunnerSinks<ReturnOf<F>>) => ((args: ArgsOf<F>, options?: MutationCallOptions<unknown, unknown, ArgsOf<F>>) => Promise<ReturnOf<F>>);
|
|
128
|
+
/**
|
|
129
|
+
* The structural surface of a TanStack `Transaction` a bound custom mutator
|
|
130
|
+
* returns — its `isPersisted.promise` resolves once the write is persisted and
|
|
131
|
+
* rejects on failure. Typed structurally so the framework adapters need not
|
|
132
|
+
* depend on `@tanstack/db` or `@lunora/db` (the handle is created app-side by
|
|
133
|
+
* `bindMutators`).
|
|
134
|
+
*/
|
|
135
|
+
interface MutatorTransaction {
|
|
136
|
+
isPersisted: {
|
|
137
|
+
promise: Promise<unknown>;
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* A bound custom-mutator handle produced by `bindMutators(client, ctx, mutators)`
|
|
142
|
+
* in `@lunora/db`. Calling it applies the optimistic overlay to the local
|
|
143
|
+
* collections and pushes the authoritative server write; it returns the TanStack
|
|
144
|
+
* transaction whose `isPersisted` promise tracks completion.
|
|
145
|
+
*/
|
|
146
|
+
type MutatorHandle<TArgs> = (args: TArgs) => MutatorTransaction;
|
|
147
|
+
/**
|
|
148
|
+
* Reactive sinks an adapter binds to its own primitive's setters (a React
|
|
149
|
+
* `useState`, a Solid signal, a Vue ref, a Svelte store). The runner pushes into
|
|
150
|
+
* them; how they store the value is the adapter's concern.
|
|
151
|
+
*/
|
|
152
|
+
interface MutatorRunnerSinks {
|
|
153
|
+
/** Receives the normalized {@link Error} when an invocation rejects, or `undefined` on success / reset. */
|
|
154
|
+
setError: (error: Error | undefined) => void;
|
|
155
|
+
/** Receives `true` while at least one invocation is in flight (ref-counted across overlapping calls), else `false`. */
|
|
156
|
+
setPending: (pending: boolean) => void;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Build the framework-neutral `mutate` / `reset` pair of an adapter's
|
|
160
|
+
* custom-mutator hook (`useMutator` / `createMutator` / `mutator`).
|
|
161
|
+
*
|
|
162
|
+
* Owns the orchestration every adapter otherwise copy-pastes: ref-counts
|
|
163
|
+
* overlapping invocations into `setPending` (so it only clears once the last
|
|
164
|
+
* settles), awaits the bound handle's `isPersisted` promise, normalizes a thrown
|
|
165
|
+
* non-`Error`, and routes failure to `setError` (clearing it on success) before
|
|
166
|
+
* re-throwing. Each adapter (`@lunora/react`, `/solid`, `/svelte`, `/vue`) binds
|
|
167
|
+
* the two sinks to its own reactive setters, so this logic lives in exactly one
|
|
168
|
+
* place. The optimistic overlay + server push are owned by the bound handle.
|
|
169
|
+
*
|
|
170
|
+
* `error` tracks the LATEST invocation, not the last to settle: overlapping
|
|
171
|
+
* calls can resolve out of order, so an earlier call that finishes later must
|
|
172
|
+
* not clobber a newer call's outcome. Each invocation takes a monotonic token
|
|
173
|
+
* and only writes `setError` while it is still the most recent one — otherwise
|
|
174
|
+
* `error`/`isError` could surface a stale success or failure (the documented
|
|
175
|
+
* "latest invocation's error" contract every adapter advertises).
|
|
176
|
+
*/
|
|
177
|
+
declare const createMutatorRunner: <TArgs>(handle: MutatorHandle<TArgs>, sinks: MutatorRunnerSinks) => {
|
|
178
|
+
mutate: (args: TArgs) => Promise<void>;
|
|
179
|
+
reset: () => void;
|
|
180
|
+
};
|
|
139
181
|
interface QueuedMutation<T = unknown> {
|
|
140
182
|
readonly args: Record<string, unknown>;
|
|
141
183
|
readonly functionPath: string;
|
|
@@ -146,12 +188,57 @@ interface QueuedMutation<T = unknown> {
|
|
|
146
188
|
* signed out). Absent on hydrated legacy records, which replay ambiently.
|
|
147
189
|
*/
|
|
148
190
|
readonly identity?: string | null;
|
|
191
|
+
/**
|
|
192
|
+
* `true` when a live caller is still awaiting this write's `mutation()`
|
|
193
|
+
* Promise; `false`/absent for a write restored from durable storage after a
|
|
194
|
+
* reload (its original awaiter is gone). Carried so terminal-verdict
|
|
195
|
+
* observers can distinguish "the caller already saw this" from "nothing else
|
|
196
|
+
* will report this". Maps to the public `MutationSettledEvent.hadAwaiter`.
|
|
197
|
+
*/
|
|
198
|
+
liveAwaiter?: boolean;
|
|
199
|
+
/**
|
|
200
|
+
* Invoked on a successful replay with the server's echoed commit CDC cursor,
|
|
201
|
+
* so a live per-call optimistic layer drops gaplessly once a frame reaches it.
|
|
202
|
+
* Absent on hydrated records (the optimistic write lived in a prior session).
|
|
203
|
+
*/
|
|
204
|
+
readonly onCommit?: (commitCursor: number | undefined) => void;
|
|
149
205
|
/** Rejects if the mutation can no longer be replayed. */
|
|
150
206
|
readonly reject: (error: unknown) => void;
|
|
151
207
|
/** Resolves once the mutation has been replayed against the server. */
|
|
152
208
|
readonly resolve: (value: T) => void;
|
|
153
209
|
readonly shardKey?: string;
|
|
154
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Invoked when the queue itself discards an entry on overflow (capacity
|
|
213
|
+
* eviction), so the client can surface the dropped write on its
|
|
214
|
+
* terminal-verdict observer even when the entry has no live awaiter (a hydrated
|
|
215
|
+
* record). The `error` carries the `OFFLINE_QUEUE_OVERFLOW` code.
|
|
216
|
+
*/
|
|
217
|
+
type EvictHandler = (entry: QueuedMutation, error: Error & {
|
|
218
|
+
code?: string;
|
|
219
|
+
}) => void;
|
|
220
|
+
/** Injected dependencies for {@link OfflineQueue} (kept off the user-facing {@link OfflineQueueOptions}). */
|
|
221
|
+
interface OfflineQueueDeps {
|
|
222
|
+
/** Invoked when an entry is discarded on capacity overflow (carries `OFFLINE_QUEUE_OVERFLOW`). */
|
|
223
|
+
onEvict?: EvictHandler;
|
|
224
|
+
/** Invoked with the new depth after any size change (drives the client's pending-sync count). */
|
|
225
|
+
onSizeChange?: (size: number) => void;
|
|
226
|
+
/** Durable store; when present, writes are mirrored and restored across reloads. */
|
|
227
|
+
persistence?: PersistenceAdapter;
|
|
228
|
+
/** App/schema version stamped on persisted writes; mismatched records are purged on hydrate. */
|
|
229
|
+
version?: string;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* A process-unique id, used both per-mutation and as the fallback `clientId`. It
|
|
233
|
+
* MUST be globally unique: the server scopes a custom mutator's replay watermark
|
|
234
|
+
* by `(verifiedIdentity, clientId)`, and an anonymous push has no verified
|
|
235
|
+
* identity — so two anonymous clients that collide on `clientId` would share one
|
|
236
|
+
* watermark namespace, letting one stall/suppress the other's ordered mutations.
|
|
237
|
+
* `crypto.randomUUID` covers every modern runtime; the fallback still mixes
|
|
238
|
+
* crypto-quality (or `Math.random`) entropy with the timestamp + counter so it
|
|
239
|
+
* can't collide across two clients started in the same millisecond.
|
|
240
|
+
*/
|
|
241
|
+
|
|
155
242
|
/**
|
|
156
243
|
* Bounded FIFO queue. Mutations issued while the client is offline are
|
|
157
244
|
* enqueued and replayed in the order they were submitted once the WS
|
|
@@ -170,8 +257,12 @@ declare class OfflineQueue {
|
|
|
170
257
|
private readonly maxItems;
|
|
171
258
|
private readonly onPersistenceError;
|
|
172
259
|
private readonly persistence;
|
|
260
|
+
private readonly onEvict;
|
|
261
|
+
private readonly onSizeChange;
|
|
262
|
+
/** App/schema version stamped on persisted writes; mismatched records are purged on hydrate. */
|
|
263
|
+
private readonly version;
|
|
173
264
|
private readonly items;
|
|
174
|
-
constructor(options?: OfflineQueueOptions,
|
|
265
|
+
constructor(options?: OfflineQueueOptions, deps?: OfflineQueueDeps);
|
|
175
266
|
get size(): number;
|
|
176
267
|
enqueue<T>(entry: QueuedMutation<T>): void;
|
|
177
268
|
/**
|
|
@@ -198,6 +289,8 @@ declare class OfflineQueue {
|
|
|
198
289
|
*/
|
|
199
290
|
requeue(items: QueuedMutation[]): void;
|
|
200
291
|
clear(): void;
|
|
292
|
+
/** Notify the size observer (the client's pending-sync count) after any change. */
|
|
293
|
+
private notifySize;
|
|
201
294
|
}
|
|
202
295
|
/**
|
|
203
296
|
* In-memory {@link PersistenceAdapter}. Doesn't survive a reload — it exists so
|
|
@@ -207,7 +300,7 @@ declare class OfflineQueue {
|
|
|
207
300
|
*/
|
|
208
301
|
declare const createInMemoryPersistence: () => PersistenceAdapter;
|
|
209
302
|
interface IndexedDbPersistenceOptions {
|
|
210
|
-
/** Database name; defaults to `"lunora"
|
|
303
|
+
/** Database name; defaults to `"lunora-outbox"` (its own DB, separate from the read cache). */
|
|
211
304
|
databaseName?: string;
|
|
212
305
|
/** Injectable `IDBFactory` (e.g. `fake-indexeddb` in tests); defaults to the global `indexedDB`. */
|
|
213
306
|
indexedDB?: IDBFactory;
|
|
@@ -225,6 +318,24 @@ interface IndexedDbPersistenceOptions {
|
|
|
225
318
|
*/
|
|
226
319
|
declare const createIndexedDbPersistence: (options?: IndexedDbPersistenceOptions) => PersistenceAdapter;
|
|
227
320
|
/**
|
|
321
|
+
* Resolve the effective offline-queue persistence from the user option,
|
|
322
|
+
* defaulting to a durable IndexedDB store when the environment supports one.
|
|
323
|
+
*
|
|
324
|
+
* An explicit adapter is used as-is; `false` opts out (the caller keeps an
|
|
325
|
+
* in-memory queue, lost on reload); `undefined` (the default) auto-probes
|
|
326
|
+
* IndexedDB when the global is present (browsers) and `autoProbe` is set,
|
|
327
|
+
* otherwise `undefined` — so SSR/Node/React-Native keep today's in-memory
|
|
328
|
+
* behaviour and only environments that can persist do.
|
|
329
|
+
*
|
|
330
|
+
* `autoProbe` is `false` when the `@lunora/db` outbox is wired: that sink is the
|
|
331
|
+
* single durable write path, so the built-in queue must stay in memory rather
|
|
332
|
+
* than persist a second, never-flushed copy. An explicit adapter is still
|
|
333
|
+
* honoured (the caller asked for it); only the implicit default is suppressed.
|
|
334
|
+
*
|
|
335
|
+
* The IndexedDB adapter opens its connection lazily, so constructing it here is
|
|
336
|
+
* cheap and never throws (the `indexedDB` global is verified present first).
|
|
337
|
+
*/
|
|
338
|
+
/**
|
|
228
339
|
* Compose the read-cache key for a subscription. Mirrors how
|
|
229
340
|
* `SubscriptionRegistry` keys live subscriptions so a hydrated value lines up
|
|
230
341
|
* with the subscription that will consume it. `shardKey` defaults to `""` (the
|
|
@@ -242,7 +353,7 @@ declare const createInMemoryQueryCache: (options?: {
|
|
|
242
353
|
maxEntries?: number;
|
|
243
354
|
}) => QueryCacheAdapter;
|
|
244
355
|
interface IndexedDbQueryCacheOptions {
|
|
245
|
-
/** Database name; defaults to `"lunora"` (
|
|
356
|
+
/** Database name; defaults to `"lunora-query-cache"` (its own DB, separate from the offline outbox). */
|
|
246
357
|
databaseName?: string;
|
|
247
358
|
/** Injectable `IDBFactory` (e.g. `fake-indexeddb` in tests); defaults to the global `indexedDB`. */
|
|
248
359
|
indexedDB?: IDBFactory;
|
|
@@ -257,14 +368,23 @@ interface IndexedDbQueryCacheOptions {
|
|
|
257
368
|
* LRU eviction. The store handle is opened lazily and cached, so repeated ops
|
|
258
369
|
* reuse one connection.
|
|
259
370
|
*
|
|
260
|
-
* The store lives in
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
* `IDBFactory` is available — callers in non-browser
|
|
264
|
-
* {@link createInMemoryQueryCache}.
|
|
371
|
+
* The store lives in its own `lunora-query-cache` database — deliberately
|
|
372
|
+
* separate from the offline-mutation outbox's `lunora-outbox` database so the two
|
|
373
|
+
* independently-toggleable adapters never share (and drift on) a schema version.
|
|
374
|
+
* Throws eagerly if no `IDBFactory` is available — callers in non-browser
|
|
375
|
+
* environments should use {@link createInMemoryQueryCache}.
|
|
265
376
|
*/
|
|
266
377
|
declare const createIndexedDbQueryCache: (options?: IndexedDbQueryCacheOptions) => QueryCacheAdapter;
|
|
267
378
|
/**
|
|
379
|
+
* Resolve the effective read-cache from the user option, defaulting to a durable
|
|
380
|
+
* IndexedDB store when the environment supports one. Same tri-state semantics as
|
|
381
|
+
* `resolvePersistenceAdapter` in `./persistence`:
|
|
382
|
+
*
|
|
383
|
+
* - an explicit adapter is used as-is;
|
|
384
|
+
* - `false` opts out — reads stay in memory only;
|
|
385
|
+
* - `undefined` (the default) auto-probes IndexedDB (browsers), else `undefined`.
|
|
386
|
+
*/
|
|
387
|
+
/**
|
|
268
388
|
* Exponential backoff calculator with optional jitter.
|
|
269
389
|
*
|
|
270
390
|
* `next()` doubles the delay each call up to `maxDelayMs`. When `jitter` is
|
|
@@ -278,4 +398,4 @@ interface ReconnectCalculator {
|
|
|
278
398
|
reset: () => void;
|
|
279
399
|
}
|
|
280
400
|
declare const createReconnect: (options?: ReconnectOptions, random?: () => number) => ReconnectCalculator;
|
|
281
|
-
export { type ArgsOf, type AsyncStorageLike, type AsyncStoragePersistenceOptions, type BookmarkStorage,
|
|
401
|
+
export { type ArgsOf, type AsyncStorageLike, type AsyncStoragePersistenceOptions, type BookmarkStorage, type FunctionReference, type IndexedDbPersistenceOptions, type IndexedDbQueryCacheOptions, type MutationCallOptions, type MutationDelta, type MutationRunnerSinks, type MutatorHandle, type MutatorRunnerSinks, type MutatorTransaction, OfflineQueue, type OfflineQueueOptions, type PersistenceAdapter, type QueryCacheAdapter, type QueuedMutation, type ReconnectCalculator, type ReconnectOptions, type ReturnOf, applyDelta, createAsyncStoragePersistence, createInMemoryBookmarkStorage, createInMemoryPersistence, createInMemoryQueryCache, createIndexedDbPersistence, createIndexedDbQueryCache, createMutationRunner, createMutatorRunner, createReconnect, isMutationDelta, queryCacheKey };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { c as PersistenceAdapter, B as BookmarkStorage, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, d as ReconnectOptions } from "./packem_shared/lunora-client.d-
|
|
2
|
-
export { type C as CachedQuery, type
|
|
3
|
-
export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-
|
|
4
|
-
export type { AuthCapabilities, AuthImpersonation, AuthPage, AuthSession, AuthUser, CronJobInfo, VectorIndexSummary, VectorQueryMatch } from '@lunora/runtime';
|
|
1
|
+
import { c as PersistenceAdapter, B as BookmarkStorage, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, d as ReconnectOptions } from "./packem_shared/lunora-client.d-BYkEjCEJ.js";
|
|
2
|
+
export { type e as BatchSlot, C as CONFLICT_ERROR_CODE, type f as CachedQuery, type g as ClientMessage, type h as ClientShapeSubscribeMessage, type i as ClientShapeUnsubscribeMessage, type j as ConnectionStatus, D as DEFAULT_MAX_BUFFER, type k as FunctionArgumentDescriptor, type l as FunctionDescriptor, type G as GlobalFacetResult, type m as GlobalFacetValue, type n as GlobalFilterClause, type o as GlobalTableInfo, type p as GlobalTablePage, L as LunoraClient, type q as LunoraClientError, type r as LunoraClientOptions, type s as LunoraErrorCode, type t as MutationSettledEvent, type u as OptimisticLocalStore, type v as OptimisticUpdate, type w as OutboxMutation, type x as OutboxSink, type y as PersistedMutation, type P as Preloaded, type z as RowOp, type E as RpcEnvelope, type H as RpcResponseBody, type I as ScheduleRecord, type J as SchedulerPoolStatus, type K as SchedulerStatus, type N as ServerMessage, type T as ServerPokeEndMessage, type V as ServerPokePartMessage, type W as ServerPokeStartMessage, type X as ShardTrafficEntry, type Y as ShardTrafficResult, type Z as StorageListPage, type _ as StorageObject, type $ as StreamHandle, type a0 as StreamIterable, type a1 as SubscriptionCallback, type S as SubscriptionError, type b as SubscriptionErrorCallback, a2 as SubscriptionRegistry, type a3 as SubscriptionState, type a4 as SyncWatermark, type a as Unsubscribe, type U as User, type a5 as WorkflowInstanceAction, type a6 as WorkflowInstanceDetail, type a7 as WorkflowInstancePage, type a8 as WorkflowInstanceStatus, type a9 as WorkflowInstanceSummary, type aa as WorkflowStepDetail, ab as createLocalStore, ac as createStream, ad as getErrorCode, ae as getRetryAfterMs, af as isConflictError, ag as isForbiddenError, ah as isRateLimitedError, ai as isUnauthorizedError } from "./packem_shared/lunora-client.d-BYkEjCEJ.js";
|
|
3
|
+
export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-B-vyHnml.js";
|
|
4
|
+
export type { AuthCapabilities, AuthConfigInfo, AuthImpersonation, AuthPage, AuthSession, AuthUser, AuthUserFieldSpec, CronJobInfo, KvKeyEntry, KvKeyListResult, KvNamespaceSummary, KvValueResult, VectorIndexSummary, VectorQueryMatch } from '@lunora/runtime';
|
|
5
5
|
/**
|
|
6
6
|
* The slice of React Native's `AsyncStorage` (or any async key/value store —
|
|
7
7
|
* Expo `SecureStore`, a wrapped `localForage`, an in-memory map in tests) this
|
|
@@ -95,17 +95,6 @@ declare const isMutationDelta: (value: unknown) => value is MutationDelta;
|
|
|
95
95
|
* when an `insert`/`update` delta carries no `row` to splice in.
|
|
96
96
|
*/
|
|
97
97
|
declare const applyDelta: (current: unknown, delta: MutationDelta) => undefined | unknown[];
|
|
98
|
-
/** Error code the server uses for optimistic-concurrency conflicts (HTTP 409). */
|
|
99
|
-
declare const CONFLICT_ERROR_CODE = "CONFLICT";
|
|
100
|
-
/**
|
|
101
|
-
* Whether an unknown rejection is an optimistic-concurrency conflict — the
|
|
102
|
-
* server lost a write race and the caller should refetch and retry (or surface
|
|
103
|
-
* the conflict). Structural check on the `code` property the client attaches
|
|
104
|
-
* when decoding the worker's `{ error: { code, message } }` envelope.
|
|
105
|
-
*/
|
|
106
|
-
declare const isConflictError: (error: unknown) => error is Error & {
|
|
107
|
-
code: "CONFLICT";
|
|
108
|
-
};
|
|
109
98
|
/** The single transport method a mutation runner needs — narrowed so adapters can test against a stub. */
|
|
110
99
|
interface MutationCapableClient<F extends FunctionReference> {
|
|
111
100
|
mutation: (function_: F, args: ArgsOf<F>, options?: MutationCallOptions<unknown, unknown, ArgsOf<F>>) => Promise<ReturnOf<F>>;
|
|
@@ -136,6 +125,59 @@ interface MutationRunnerSinks<R> {
|
|
|
136
125
|
* pass straight through to `client.mutation`.
|
|
137
126
|
*/
|
|
138
127
|
declare const createMutationRunner: <F extends FunctionReference>(client: MutationCapableClient<F>, function_: F, sinks: MutationRunnerSinks<ReturnOf<F>>) => ((args: ArgsOf<F>, options?: MutationCallOptions<unknown, unknown, ArgsOf<F>>) => Promise<ReturnOf<F>>);
|
|
128
|
+
/**
|
|
129
|
+
* The structural surface of a TanStack `Transaction` a bound custom mutator
|
|
130
|
+
* returns — its `isPersisted.promise` resolves once the write is persisted and
|
|
131
|
+
* rejects on failure. Typed structurally so the framework adapters need not
|
|
132
|
+
* depend on `@tanstack/db` or `@lunora/db` (the handle is created app-side by
|
|
133
|
+
* `bindMutators`).
|
|
134
|
+
*/
|
|
135
|
+
interface MutatorTransaction {
|
|
136
|
+
isPersisted: {
|
|
137
|
+
promise: Promise<unknown>;
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* A bound custom-mutator handle produced by `bindMutators(client, ctx, mutators)`
|
|
142
|
+
* in `@lunora/db`. Calling it applies the optimistic overlay to the local
|
|
143
|
+
* collections and pushes the authoritative server write; it returns the TanStack
|
|
144
|
+
* transaction whose `isPersisted` promise tracks completion.
|
|
145
|
+
*/
|
|
146
|
+
type MutatorHandle<TArgs> = (args: TArgs) => MutatorTransaction;
|
|
147
|
+
/**
|
|
148
|
+
* Reactive sinks an adapter binds to its own primitive's setters (a React
|
|
149
|
+
* `useState`, a Solid signal, a Vue ref, a Svelte store). The runner pushes into
|
|
150
|
+
* them; how they store the value is the adapter's concern.
|
|
151
|
+
*/
|
|
152
|
+
interface MutatorRunnerSinks {
|
|
153
|
+
/** Receives the normalized {@link Error} when an invocation rejects, or `undefined` on success / reset. */
|
|
154
|
+
setError: (error: Error | undefined) => void;
|
|
155
|
+
/** Receives `true` while at least one invocation is in flight (ref-counted across overlapping calls), else `false`. */
|
|
156
|
+
setPending: (pending: boolean) => void;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Build the framework-neutral `mutate` / `reset` pair of an adapter's
|
|
160
|
+
* custom-mutator hook (`useMutator` / `createMutator` / `mutator`).
|
|
161
|
+
*
|
|
162
|
+
* Owns the orchestration every adapter otherwise copy-pastes: ref-counts
|
|
163
|
+
* overlapping invocations into `setPending` (so it only clears once the last
|
|
164
|
+
* settles), awaits the bound handle's `isPersisted` promise, normalizes a thrown
|
|
165
|
+
* non-`Error`, and routes failure to `setError` (clearing it on success) before
|
|
166
|
+
* re-throwing. Each adapter (`@lunora/react`, `/solid`, `/svelte`, `/vue`) binds
|
|
167
|
+
* the two sinks to its own reactive setters, so this logic lives in exactly one
|
|
168
|
+
* place. The optimistic overlay + server push are owned by the bound handle.
|
|
169
|
+
*
|
|
170
|
+
* `error` tracks the LATEST invocation, not the last to settle: overlapping
|
|
171
|
+
* calls can resolve out of order, so an earlier call that finishes later must
|
|
172
|
+
* not clobber a newer call's outcome. Each invocation takes a monotonic token
|
|
173
|
+
* and only writes `setError` while it is still the most recent one — otherwise
|
|
174
|
+
* `error`/`isError` could surface a stale success or failure (the documented
|
|
175
|
+
* "latest invocation's error" contract every adapter advertises).
|
|
176
|
+
*/
|
|
177
|
+
declare const createMutatorRunner: <TArgs>(handle: MutatorHandle<TArgs>, sinks: MutatorRunnerSinks) => {
|
|
178
|
+
mutate: (args: TArgs) => Promise<void>;
|
|
179
|
+
reset: () => void;
|
|
180
|
+
};
|
|
139
181
|
interface QueuedMutation<T = unknown> {
|
|
140
182
|
readonly args: Record<string, unknown>;
|
|
141
183
|
readonly functionPath: string;
|
|
@@ -146,12 +188,57 @@ interface QueuedMutation<T = unknown> {
|
|
|
146
188
|
* signed out). Absent on hydrated legacy records, which replay ambiently.
|
|
147
189
|
*/
|
|
148
190
|
readonly identity?: string | null;
|
|
191
|
+
/**
|
|
192
|
+
* `true` when a live caller is still awaiting this write's `mutation()`
|
|
193
|
+
* Promise; `false`/absent for a write restored from durable storage after a
|
|
194
|
+
* reload (its original awaiter is gone). Carried so terminal-verdict
|
|
195
|
+
* observers can distinguish "the caller already saw this" from "nothing else
|
|
196
|
+
* will report this". Maps to the public `MutationSettledEvent.hadAwaiter`.
|
|
197
|
+
*/
|
|
198
|
+
liveAwaiter?: boolean;
|
|
199
|
+
/**
|
|
200
|
+
* Invoked on a successful replay with the server's echoed commit CDC cursor,
|
|
201
|
+
* so a live per-call optimistic layer drops gaplessly once a frame reaches it.
|
|
202
|
+
* Absent on hydrated records (the optimistic write lived in a prior session).
|
|
203
|
+
*/
|
|
204
|
+
readonly onCommit?: (commitCursor: number | undefined) => void;
|
|
149
205
|
/** Rejects if the mutation can no longer be replayed. */
|
|
150
206
|
readonly reject: (error: unknown) => void;
|
|
151
207
|
/** Resolves once the mutation has been replayed against the server. */
|
|
152
208
|
readonly resolve: (value: T) => void;
|
|
153
209
|
readonly shardKey?: string;
|
|
154
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Invoked when the queue itself discards an entry on overflow (capacity
|
|
213
|
+
* eviction), so the client can surface the dropped write on its
|
|
214
|
+
* terminal-verdict observer even when the entry has no live awaiter (a hydrated
|
|
215
|
+
* record). The `error` carries the `OFFLINE_QUEUE_OVERFLOW` code.
|
|
216
|
+
*/
|
|
217
|
+
type EvictHandler = (entry: QueuedMutation, error: Error & {
|
|
218
|
+
code?: string;
|
|
219
|
+
}) => void;
|
|
220
|
+
/** Injected dependencies for {@link OfflineQueue} (kept off the user-facing {@link OfflineQueueOptions}). */
|
|
221
|
+
interface OfflineQueueDeps {
|
|
222
|
+
/** Invoked when an entry is discarded on capacity overflow (carries `OFFLINE_QUEUE_OVERFLOW`). */
|
|
223
|
+
onEvict?: EvictHandler;
|
|
224
|
+
/** Invoked with the new depth after any size change (drives the client's pending-sync count). */
|
|
225
|
+
onSizeChange?: (size: number) => void;
|
|
226
|
+
/** Durable store; when present, writes are mirrored and restored across reloads. */
|
|
227
|
+
persistence?: PersistenceAdapter;
|
|
228
|
+
/** App/schema version stamped on persisted writes; mismatched records are purged on hydrate. */
|
|
229
|
+
version?: string;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* A process-unique id, used both per-mutation and as the fallback `clientId`. It
|
|
233
|
+
* MUST be globally unique: the server scopes a custom mutator's replay watermark
|
|
234
|
+
* by `(verifiedIdentity, clientId)`, and an anonymous push has no verified
|
|
235
|
+
* identity — so two anonymous clients that collide on `clientId` would share one
|
|
236
|
+
* watermark namespace, letting one stall/suppress the other's ordered mutations.
|
|
237
|
+
* `crypto.randomUUID` covers every modern runtime; the fallback still mixes
|
|
238
|
+
* crypto-quality (or `Math.random`) entropy with the timestamp + counter so it
|
|
239
|
+
* can't collide across two clients started in the same millisecond.
|
|
240
|
+
*/
|
|
241
|
+
|
|
155
242
|
/**
|
|
156
243
|
* Bounded FIFO queue. Mutations issued while the client is offline are
|
|
157
244
|
* enqueued and replayed in the order they were submitted once the WS
|
|
@@ -170,8 +257,12 @@ declare class OfflineQueue {
|
|
|
170
257
|
private readonly maxItems;
|
|
171
258
|
private readonly onPersistenceError;
|
|
172
259
|
private readonly persistence;
|
|
260
|
+
private readonly onEvict;
|
|
261
|
+
private readonly onSizeChange;
|
|
262
|
+
/** App/schema version stamped on persisted writes; mismatched records are purged on hydrate. */
|
|
263
|
+
private readonly version;
|
|
173
264
|
private readonly items;
|
|
174
|
-
constructor(options?: OfflineQueueOptions,
|
|
265
|
+
constructor(options?: OfflineQueueOptions, deps?: OfflineQueueDeps);
|
|
175
266
|
get size(): number;
|
|
176
267
|
enqueue<T>(entry: QueuedMutation<T>): void;
|
|
177
268
|
/**
|
|
@@ -198,6 +289,8 @@ declare class OfflineQueue {
|
|
|
198
289
|
*/
|
|
199
290
|
requeue(items: QueuedMutation[]): void;
|
|
200
291
|
clear(): void;
|
|
292
|
+
/** Notify the size observer (the client's pending-sync count) after any change. */
|
|
293
|
+
private notifySize;
|
|
201
294
|
}
|
|
202
295
|
/**
|
|
203
296
|
* In-memory {@link PersistenceAdapter}. Doesn't survive a reload — it exists so
|
|
@@ -207,7 +300,7 @@ declare class OfflineQueue {
|
|
|
207
300
|
*/
|
|
208
301
|
declare const createInMemoryPersistence: () => PersistenceAdapter;
|
|
209
302
|
interface IndexedDbPersistenceOptions {
|
|
210
|
-
/** Database name; defaults to `"lunora"
|
|
303
|
+
/** Database name; defaults to `"lunora-outbox"` (its own DB, separate from the read cache). */
|
|
211
304
|
databaseName?: string;
|
|
212
305
|
/** Injectable `IDBFactory` (e.g. `fake-indexeddb` in tests); defaults to the global `indexedDB`. */
|
|
213
306
|
indexedDB?: IDBFactory;
|
|
@@ -225,6 +318,24 @@ interface IndexedDbPersistenceOptions {
|
|
|
225
318
|
*/
|
|
226
319
|
declare const createIndexedDbPersistence: (options?: IndexedDbPersistenceOptions) => PersistenceAdapter;
|
|
227
320
|
/**
|
|
321
|
+
* Resolve the effective offline-queue persistence from the user option,
|
|
322
|
+
* defaulting to a durable IndexedDB store when the environment supports one.
|
|
323
|
+
*
|
|
324
|
+
* An explicit adapter is used as-is; `false` opts out (the caller keeps an
|
|
325
|
+
* in-memory queue, lost on reload); `undefined` (the default) auto-probes
|
|
326
|
+
* IndexedDB when the global is present (browsers) and `autoProbe` is set,
|
|
327
|
+
* otherwise `undefined` — so SSR/Node/React-Native keep today's in-memory
|
|
328
|
+
* behaviour and only environments that can persist do.
|
|
329
|
+
*
|
|
330
|
+
* `autoProbe` is `false` when the `@lunora/db` outbox is wired: that sink is the
|
|
331
|
+
* single durable write path, so the built-in queue must stay in memory rather
|
|
332
|
+
* than persist a second, never-flushed copy. An explicit adapter is still
|
|
333
|
+
* honoured (the caller asked for it); only the implicit default is suppressed.
|
|
334
|
+
*
|
|
335
|
+
* The IndexedDB adapter opens its connection lazily, so constructing it here is
|
|
336
|
+
* cheap and never throws (the `indexedDB` global is verified present first).
|
|
337
|
+
*/
|
|
338
|
+
/**
|
|
228
339
|
* Compose the read-cache key for a subscription. Mirrors how
|
|
229
340
|
* `SubscriptionRegistry` keys live subscriptions so a hydrated value lines up
|
|
230
341
|
* with the subscription that will consume it. `shardKey` defaults to `""` (the
|
|
@@ -242,7 +353,7 @@ declare const createInMemoryQueryCache: (options?: {
|
|
|
242
353
|
maxEntries?: number;
|
|
243
354
|
}) => QueryCacheAdapter;
|
|
244
355
|
interface IndexedDbQueryCacheOptions {
|
|
245
|
-
/** Database name; defaults to `"lunora"` (
|
|
356
|
+
/** Database name; defaults to `"lunora-query-cache"` (its own DB, separate from the offline outbox). */
|
|
246
357
|
databaseName?: string;
|
|
247
358
|
/** Injectable `IDBFactory` (e.g. `fake-indexeddb` in tests); defaults to the global `indexedDB`. */
|
|
248
359
|
indexedDB?: IDBFactory;
|
|
@@ -257,14 +368,23 @@ interface IndexedDbQueryCacheOptions {
|
|
|
257
368
|
* LRU eviction. The store handle is opened lazily and cached, so repeated ops
|
|
258
369
|
* reuse one connection.
|
|
259
370
|
*
|
|
260
|
-
* The store lives in
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
* `IDBFactory` is available — callers in non-browser
|
|
264
|
-
* {@link createInMemoryQueryCache}.
|
|
371
|
+
* The store lives in its own `lunora-query-cache` database — deliberately
|
|
372
|
+
* separate from the offline-mutation outbox's `lunora-outbox` database so the two
|
|
373
|
+
* independently-toggleable adapters never share (and drift on) a schema version.
|
|
374
|
+
* Throws eagerly if no `IDBFactory` is available — callers in non-browser
|
|
375
|
+
* environments should use {@link createInMemoryQueryCache}.
|
|
265
376
|
*/
|
|
266
377
|
declare const createIndexedDbQueryCache: (options?: IndexedDbQueryCacheOptions) => QueryCacheAdapter;
|
|
267
378
|
/**
|
|
379
|
+
* Resolve the effective read-cache from the user option, defaulting to a durable
|
|
380
|
+
* IndexedDB store when the environment supports one. Same tri-state semantics as
|
|
381
|
+
* `resolvePersistenceAdapter` in `./persistence`:
|
|
382
|
+
*
|
|
383
|
+
* - an explicit adapter is used as-is;
|
|
384
|
+
* - `false` opts out — reads stay in memory only;
|
|
385
|
+
* - `undefined` (the default) auto-probes IndexedDB (browsers), else `undefined`.
|
|
386
|
+
*/
|
|
387
|
+
/**
|
|
268
388
|
* Exponential backoff calculator with optional jitter.
|
|
269
389
|
*
|
|
270
390
|
* `next()` doubles the delay each call up to `maxDelayMs`. When `jitter` is
|
|
@@ -278,4 +398,4 @@ interface ReconnectCalculator {
|
|
|
278
398
|
reset: () => void;
|
|
279
399
|
}
|
|
280
400
|
declare const createReconnect: (options?: ReconnectOptions, random?: () => number) => ReconnectCalculator;
|
|
281
|
-
export { type ArgsOf, type AsyncStorageLike, type AsyncStoragePersistenceOptions, type BookmarkStorage,
|
|
401
|
+
export { type ArgsOf, type AsyncStorageLike, type AsyncStoragePersistenceOptions, type BookmarkStorage, type FunctionReference, type IndexedDbPersistenceOptions, type IndexedDbQueryCacheOptions, type MutationCallOptions, type MutationDelta, type MutationRunnerSinks, type MutatorHandle, type MutatorRunnerSinks, type MutatorTransaction, OfflineQueue, type OfflineQueueOptions, type PersistenceAdapter, type QueryCacheAdapter, type QueuedMutation, type ReconnectCalculator, type ReconnectOptions, type ReturnOf, applyDelta, createAsyncStoragePersistence, createInMemoryBookmarkStorage, createInMemoryPersistence, createInMemoryQueryCache, createIndexedDbPersistence, createIndexedDbQueryCache, createMutationRunner, createMutatorRunner, createReconnect, isMutationDelta, queryCacheKey };
|
package/dist/index.mjs
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
export { createAsyncStoragePersistence } from './packem_shared/createAsyncStoragePersistence-1Z5BZ8RC.mjs';
|
|
2
2
|
export { default as createInMemoryBookmarkStorage } from './packem_shared/createInMemoryBookmarkStorage-BoN7a7TH.mjs';
|
|
3
|
-
export { applyDelta, isMutationDelta } from './packem_shared/applyDelta-
|
|
4
|
-
export { CONFLICT_ERROR_CODE, isConflictError } from './packem_shared/CONFLICT_ERROR_CODE-
|
|
5
|
-
export { createLocalStore } from './packem_shared/
|
|
6
|
-
export { LunoraClient } from './packem_shared/LunoraClient-
|
|
3
|
+
export { applyDelta, isMutationDelta } from './packem_shared/applyDelta-CRKZ1PBt.mjs';
|
|
4
|
+
export { CONFLICT_ERROR_CODE, getErrorCode, getRetryAfterMs, isConflictError, isForbiddenError, isRateLimitedError, isUnauthorizedError } from './packem_shared/CONFLICT_ERROR_CODE-B8gQ8tyU.mjs';
|
|
5
|
+
export { c as createLocalStore } from './packem_shared/local-store-BveBeFEo.mjs';
|
|
6
|
+
export { LunoraClient } from './packem_shared/LunoraClient-kXpHNyaE.mjs';
|
|
7
7
|
export { createMutationRunner } from './packem_shared/createMutationRunner-BqsavzvG.mjs';
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
8
|
+
export { createMutatorRunner } from './packem_shared/createMutatorRunner-BETvCd0p.mjs';
|
|
9
|
+
export { O as OfflineQueue } from './packem_shared/offline-queue-B9vfdSqp.mjs';
|
|
10
|
+
export { createInMemoryPersistence, createIndexedDbPersistence } from './packem_shared/createInMemoryPersistence-DZ2VHWgm.mjs';
|
|
10
11
|
export { preloadQuery, preloadedQueryResult } from './packem_shared/preloadQuery-lobFkD2Z.mjs';
|
|
11
|
-
export { createInMemoryQueryCache, createIndexedDbQueryCache, queryCacheKey } from './packem_shared/createInMemoryQueryCache-
|
|
12
|
+
export { createInMemoryQueryCache, createIndexedDbQueryCache, queryCacheKey } from './packem_shared/createInMemoryQueryCache-DiaGZkA2.mjs';
|
|
12
13
|
export { createReconnect } from './packem_shared/createReconnect-Di_-oHH7.mjs';
|
|
13
|
-
export { DEFAULT_MAX_BUFFER, createStream } from './packem_shared/DEFAULT_MAX_BUFFER-
|
|
14
|
-
export { SubscriptionRegistry } from './packem_shared/
|
|
14
|
+
export { DEFAULT_MAX_BUFFER, createStream } from './packem_shared/DEFAULT_MAX_BUFFER-7hFnzNk9.mjs';
|
|
15
|
+
export { S as SubscriptionRegistry } from './packem_shared/subscription-BjynOXCU.mjs';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const LUNORA_ERROR_CODES = [
|
|
2
|
+
"BAD_REQUEST",
|
|
3
|
+
"CONFLICT",
|
|
4
|
+
"COUNT_RLS_UNSUPPORTED",
|
|
5
|
+
"FORBIDDEN",
|
|
6
|
+
"INTERNAL_SERVER_ERROR",
|
|
7
|
+
"MASK_UNSUPPORTED",
|
|
8
|
+
"NOT_FOUND",
|
|
9
|
+
"NOT_IMPLEMENTED",
|
|
10
|
+
"RELATION_PREDICATE_UNSUPPORTED",
|
|
11
|
+
"TOO_MANY_REQUESTS",
|
|
12
|
+
"UNAUTHORIZED",
|
|
13
|
+
"UNPROCESSABLE"
|
|
14
|
+
];
|
|
15
|
+
const KNOWN_ERROR_CODES = new Set(LUNORA_ERROR_CODES);
|
|
16
|
+
const CONFLICT_ERROR_CODE = "CONFLICT";
|
|
17
|
+
const isConflictError = (error) => error instanceof Error && error.code === CONFLICT_ERROR_CODE;
|
|
18
|
+
const isForbiddenError = (error) => error instanceof Error && error.code === "FORBIDDEN";
|
|
19
|
+
const isUnauthorizedError = (error) => error instanceof Error && error.code === "UNAUTHORIZED";
|
|
20
|
+
const isRateLimitedError = (error) => error instanceof Error && error.code === "TOO_MANY_REQUESTS";
|
|
21
|
+
const getErrorCode = (error) => {
|
|
22
|
+
if (!(error instanceof Error)) {
|
|
23
|
+
return void 0;
|
|
24
|
+
}
|
|
25
|
+
const { code } = error;
|
|
26
|
+
return typeof code === "string" && KNOWN_ERROR_CODES.has(code) ? code : void 0;
|
|
27
|
+
};
|
|
28
|
+
const getRetryAfterMs = (error) => {
|
|
29
|
+
const value = error?.data?.retryAfterMs;
|
|
30
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export { CONFLICT_ERROR_CODE, getErrorCode, getRetryAfterMs, isConflictError, isForbiddenError, isRateLimitedError, isUnauthorizedError };
|
package/dist/packem_shared/{DEFAULT_MAX_BUFFER-BDkqO5PW.mjs → DEFAULT_MAX_BUFFER-7hFnzNk9.mjs}
RENAMED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { LunoraError } from '@lunora/errors';
|
|
2
|
+
|
|
1
3
|
const DEFAULT_MAX_BUFFER = 1024;
|
|
2
4
|
const createStream = (options) => {
|
|
3
5
|
const maxBuffer = options.maxBuffer ?? DEFAULT_MAX_BUFFER;
|
|
@@ -51,9 +53,10 @@ const createStream = (options) => {
|
|
|
51
53
|
}
|
|
52
54
|
if (buffer.length >= maxBuffer) {
|
|
53
55
|
handle.fail(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
new LunoraError(
|
|
57
|
+
"STREAM_BACKPRESSURE",
|
|
58
|
+
`stream buffer overflow (max=${maxBuffer.toString()}); the consumer cannot keep up with the producer`
|
|
59
|
+
)
|
|
57
60
|
);
|
|
58
61
|
return;
|
|
59
62
|
}
|