@lunora/client 1.0.0-alpha.245 → 1.0.0-alpha.247
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/index.d.mts +10 -6
- package/dist/index.d.ts +10 -6
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/LunoraClient-C-auNTDs.mjs +1 -0
- package/dist/packem_shared/OfflineQueue-Ba2qgZK1.mjs +1 -0
- package/dist/packem_shared/SubscriptionRegistry-BKgQtuh9.mjs +1 -0
- package/dist/packem_shared/createLocalStore-CsKA0HPB.mjs +1 -0
- package/dist/packem_shared/{createServerClient-T1RiYjZx.mjs → createServerClient-kd9cUs8g.mjs} +1 -1
- package/dist/packem_shared/createSnapshotPrecondition-BXP1NPBW.mjs +1 -0
- package/dist/packem_shared/{local-store-fqWV2n_Z.mjs → local-store-C3bw2MPY.mjs} +1 -1
- package/dist/packem_shared/{lunora-client.d-BGbRstqH.d.ts → lunora-client.d-7WaMRZUK.d.ts} +151 -6
- package/dist/packem_shared/{lunora-client.d-B_eWE1gD.d.mts → lunora-client.d-DtTKDhtw.d.mts} +151 -6
- package/dist/packem_shared/offline-queue-BEqCPDmw.mjs +1 -0
- package/dist/packem_shared/{preload.d-BSeSh11b.d.ts → preload.d-B26QlpOB.d.ts} +1 -1
- package/dist/packem_shared/{preload.d-6WDEiJO5.d.mts → preload.d-CT_9YaL9.d.mts} +1 -1
- package/dist/packem_shared/snapshot-precondition-BEtcSbWr.mjs +1 -0
- package/dist/packem_shared/wire-errors-BgFi7ONA.mjs +1 -0
- package/dist/query/index.d.mts +2 -2
- package/dist/query/index.d.ts +2 -2
- package/dist/service.mjs +1 -1
- package/dist/ssr/index.d.mts +2 -2
- package/dist/ssr/index.d.ts +2 -2
- package/dist/ssr/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/packem_shared/LunoraClient-CUXLD5xx.mjs +0 -1
- package/dist/packem_shared/OfflineQueue-BLRESpAe.mjs +0 -1
- package/dist/packem_shared/SubscriptionRegistry-DKIXE7M7.mjs +0 -1
- package/dist/packem_shared/createLocalStore-BT0QPKdf.mjs +0 -1
- package/dist/packem_shared/createSnapshotPrecondition-CLkxVeN1.mjs +0 -1
- package/dist/packem_shared/offline-queue-Dt_um8sR.mjs +0 -1
- package/dist/packem_shared/wire-errors-u1qRPmDJ.mjs +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LunoraErrorCodeInput, LunoraErrorCode } from '@lunora/errors';
|
|
1
|
+
import { LunoraErrorCodeInput, LunoraErrorCode, LunoraError } from '@lunora/errors';
|
|
2
2
|
import { F as FunctionReference, A as ArgsOf, R as ReturnOf } from "./function-reference.d-Br_hsKje.js";
|
|
3
3
|
import { CronJobInfo, VectorIndexSummary, VectorQueryMatch, PipelineLogQuery, PipelineLogPage, KvNamespaceSummary, KvKeyListResult, KvValueResult, AuthUser, AuthPage, AuthImpersonation, AuthCapabilities, AuthConfigInfo, AuthSession } from '@lunora/runtime';
|
|
4
4
|
/**
|
|
@@ -382,6 +382,14 @@ interface LunoraClientOptions {
|
|
|
382
382
|
* `/api/auth` (matching `@lunora/auth`'s `DEFAULT_AUTH_BASE_PATH`).
|
|
383
383
|
*/
|
|
384
384
|
authBasePath?: string;
|
|
385
|
+
/**
|
|
386
|
+
* Whether the `WebSocket` transport sends the `setAuthToken` bearer on the
|
|
387
|
+
* upgrade, as `@lunora/react-native` does on native. Then a
|
|
388
|
+
* sign-in from signed-out reconnects the shard sockets so the server sees the
|
|
389
|
+
* bearer. A browser socket cannot carry it, so the default `false` leaves its
|
|
390
|
+
* sockets (and their live values) alone.
|
|
391
|
+
*/
|
|
392
|
+
authTokenOnUpgrade?: boolean;
|
|
385
393
|
bookmarkStorage?: BookmarkStorage;
|
|
386
394
|
/**
|
|
387
395
|
* Stable per-client id backing the custom-mutator watermark. Sent on the
|
|
@@ -1320,8 +1328,13 @@ interface OptimisticLayer {
|
|
|
1320
1328
|
readonly transform: (current: unknown) => unknown;
|
|
1321
1329
|
}
|
|
1322
1330
|
interface SubscriptionState {
|
|
1323
|
-
/**
|
|
1324
|
-
|
|
1331
|
+
/**
|
|
1332
|
+
* Where this subscription's `subscribe` frame stands on the current socket:
|
|
1333
|
+
* none outstanding (`"idle"`), sent and not yet answered (`"inflight"`, so a
|
|
1334
|
+
* second subscriber joins it instead of sending another), or acknowledged by
|
|
1335
|
+
* the server (`"acked"`). Written only through {@link setSubscriptionAck}.
|
|
1336
|
+
*/
|
|
1337
|
+
ack: "acked" | "idle" | "inflight";
|
|
1325
1338
|
readonly args: Record<string, unknown>;
|
|
1326
1339
|
/**
|
|
1327
1340
|
* Stable wire-key of `args` (`stableWireKey`), computed once at subscribe
|
|
@@ -1470,12 +1483,17 @@ type LunoraClientError = Error & {
|
|
|
1470
1483
|
code?: LunoraErrorCode | (string & {});
|
|
1471
1484
|
data?: unknown;
|
|
1472
1485
|
docsUrl?: string;
|
|
1486
|
+
/**
|
|
1487
|
+
* The headers of the reply this error came from. Set by the RPC, batch and replay paths; absent on
|
|
1488
|
+
* a failure with no reply (a `fetch` that rejected, a timeout) and on the admin and stream paths.
|
|
1489
|
+
*/
|
|
1490
|
+
headers?: Readonly<Record<string, string>>;
|
|
1473
1491
|
hint?: string | string[];
|
|
1474
1492
|
why?: string;
|
|
1475
1493
|
};
|
|
1476
1494
|
/** One demuxed result slot of a `LunoraClient.batch` call. */
|
|
1477
1495
|
type BatchSlot = {
|
|
1478
|
-
error: LunoraClientError;
|
|
1496
|
+
error: LunoraClientError | LunoraError;
|
|
1479
1497
|
ok: false;
|
|
1480
1498
|
} | {
|
|
1481
1499
|
ok: true;
|
|
@@ -1924,6 +1942,8 @@ declare class LunoraClient {
|
|
|
1924
1942
|
private readonly pollingFallbackAfterFailedAttempts;
|
|
1925
1943
|
/** Polling-fallback cadence (ms); `0` disables it. See {@link LunoraClientOptions.pollingFallback}. */
|
|
1926
1944
|
private readonly pollingFallbackIntervalMs;
|
|
1945
|
+
/** See {@link LunoraClientOptions.authTokenOnUpgrade}. */
|
|
1946
|
+
private readonly authTokenOnUpgrade;
|
|
1927
1947
|
private readonly offlineQueue;
|
|
1928
1948
|
/**
|
|
1929
1949
|
* Durable outbox seam (the `@lunora/db` `createExecutorOutboxSink`). When
|
|
@@ -2075,6 +2095,8 @@ declare class LunoraClient {
|
|
|
2075
2095
|
*/
|
|
2076
2096
|
private readonly connectionContextHolders;
|
|
2077
2097
|
private authToken;
|
|
2098
|
+
/** Hash of the current bearer, keyed on the token so a new token misses once. `setAuthToken` drops it on every change, so a replaced or signed-out bearer is not retained. */
|
|
2099
|
+
private tokenFingerprint;
|
|
2078
2100
|
/**
|
|
2079
2101
|
* Optional STABLE identity subject (a user id), the basis of the offline-queue
|
|
2080
2102
|
* identity stamp when supplied. Keeps a same-user token *refresh* from looking
|
|
@@ -2268,6 +2290,27 @@ declare class LunoraClient {
|
|
|
2268
2290
|
* racing write was never in the queue.
|
|
2269
2291
|
*/
|
|
2270
2292
|
private readonly offlineFlushes;
|
|
2293
|
+
/**
|
|
2294
|
+
* Subscriptions a socket `open` un-answered that no value-bearing frame has
|
|
2295
|
+
* answered since. What they hold is the previous socket's value, or a blank
|
|
2296
|
+
* after a cold reconnect, and the server acks a `subscribe` before it seeds
|
|
2297
|
+
* it, so neither `lastValue` nor `ack` says the value is current. A queued
|
|
2298
|
+
* write whose snapshot precondition reads one of them is not evaluated yet:
|
|
2299
|
+
* see {@link LunoraClient.snapshotAnswer}. On a follower the open is the
|
|
2300
|
+
* leader's, see {@link LunoraClient.awaitLeaderAnswers}.
|
|
2301
|
+
*/
|
|
2302
|
+
private readonly awaitingAnswer;
|
|
2303
|
+
/**
|
|
2304
|
+
* Subscriptions whose wait ended without a value to read: the seed was
|
|
2305
|
+
* refused or undecodable, or the resubscribe was given up on. Still acked and
|
|
2306
|
+
* blank after a cold reconnect, so a snapshot comparison would read the blank
|
|
2307
|
+
* as a change; a guard over one of them is no evidence either way.
|
|
2308
|
+
*/
|
|
2309
|
+
private readonly answeredUnreadable;
|
|
2310
|
+
/** Connection keys whose last flush left a write waiting on {@link LunoraClient.awaitingAnswer}; an answer there flushes again. */
|
|
2311
|
+
private readonly answerHeldShards;
|
|
2312
|
+
/** Gives up on the leader relaying an answer, one per subscription, see {@link LunoraClient.awaitLeaderAnswer}. */
|
|
2313
|
+
private readonly leaderAnswerTimers;
|
|
2271
2314
|
/**
|
|
2272
2315
|
* Per-shard replay backoff, keyed by {@link connectionKey} exactly as the
|
|
2273
2316
|
* flushes and their timers are: `delayMs` is the longest hint the CURRENT
|
|
@@ -2323,7 +2366,10 @@ declare class LunoraClient {
|
|
|
2323
2366
|
* Does NOT update the WebSocket auth — a socket keeps the session credential
|
|
2324
2367
|
* it connected with for its life. To refresh live WS auth, call
|
|
2325
2368
|
* {@link setWsToken} explicitly, which closes existing shard sockets to
|
|
2326
|
-
* force a reconnect with the new credential.
|
|
2369
|
+
* force a reconnect with the new credential. With
|
|
2370
|
+
* {@link LunoraClientOptions.authTokenOnUpgrade} (React Native's
|
|
2371
|
+
* `Authorization` header), a sign-in from signed-out (a token where there was
|
|
2372
|
+
* none) reconnects the sockets, cold, so the upgrade presents it.
|
|
2327
2373
|
*/
|
|
2328
2374
|
setAuthToken(token: string | null, subject?: string | null): void;
|
|
2329
2375
|
getAuthToken(): string | null;
|
|
@@ -2844,6 +2890,25 @@ declare class LunoraClient {
|
|
|
2844
2890
|
* `new globalThis.WebSocket(url)` would silently bypass.
|
|
2845
2891
|
*/
|
|
2846
2892
|
getWebSocketImpl(): typeof WebSocket | undefined;
|
|
2893
|
+
/**
|
|
2894
|
+
* `true` while {@link LunoraClientOptions.crossTabSync} is on and this tab
|
|
2895
|
+
* is not the elected leader, including the election window before it knows
|
|
2896
|
+
* whether another tab leads. Such a tab holds no socket: its subscriptions
|
|
2897
|
+
* see only the frames the leader relays for queries the leader holds too,
|
|
2898
|
+
* so a read that must resolve goes over HTTP instead of waiting on a push.
|
|
2899
|
+
*/
|
|
2900
|
+
isCrossTabFollower(): boolean;
|
|
2901
|
+
/**
|
|
2902
|
+
* Whether a live query on `shardKey` can expect its value to be pushed: by a
|
|
2903
|
+
* socket that is open or still on its first connect attempt, or by the
|
|
2904
|
+
* polling fallback. `false` once a connect attempt has failed to reach `open`
|
|
2905
|
+
* since the socket last did and polling is not delivering instead, where a
|
|
2906
|
+
* read that must resolve should go over HTTP rather than wait on a push. A
|
|
2907
|
+
* shard with no connection yet expects one: subscribing opens it.
|
|
2908
|
+
*/
|
|
2909
|
+
expectsPush(options?: {
|
|
2910
|
+
shardKey?: string;
|
|
2911
|
+
}): boolean;
|
|
2847
2912
|
/**
|
|
2848
2913
|
* Read the current value for a {@link ClientQueryRef}. Returns
|
|
2849
2914
|
* `ref.defaultValue` when no value has been explicitly set.
|
|
@@ -2926,7 +2991,9 @@ declare class LunoraClient {
|
|
|
2926
2991
|
* whether one exists at all rather than just its value. `present` is `false`
|
|
2927
2992
|
* when no subscription is open for the given `(functionPath, args, shardKey)`;
|
|
2928
2993
|
* `value` is the subscription's `lastValue`, which includes any optimistic
|
|
2929
|
-
* overlay.
|
|
2994
|
+
* overlay. `answered` is `false` while an open subscription holds no answer
|
|
2995
|
+
* (never answered, or blanked by a cold reconnect), when `value` is absence
|
|
2996
|
+
* rather than evidence.
|
|
2930
2997
|
*
|
|
2931
2998
|
* The two are separate because a caller like the snapshot precondition has to
|
|
2932
2999
|
* tell "no subscription is active, so this read knows nothing" apart from
|
|
@@ -2939,6 +3006,7 @@ declare class LunoraClient {
|
|
|
2939
3006
|
* in-memory state of an already-opened subscription.
|
|
2940
3007
|
*/
|
|
2941
3008
|
peekActiveQuerySnapshot(functionPath: string, args: Record<string, unknown>, shardKey?: string): {
|
|
3009
|
+
answered: boolean;
|
|
2942
3010
|
present: boolean;
|
|
2943
3011
|
value: unknown;
|
|
2944
3012
|
};
|
|
@@ -3785,6 +3853,29 @@ declare class LunoraClient {
|
|
|
3785
3853
|
signal?: AbortSignal;
|
|
3786
3854
|
}): StreamIterable<HttpStreamChunkOf<Ref>>;
|
|
3787
3855
|
close(): void;
|
|
3856
|
+
/**
|
|
3857
|
+
* A genuine credential change: reject the queued writes that can no longer
|
|
3858
|
+
* replay as the incoming identity, and evict the session the previous one
|
|
3859
|
+
* left live. `true` when it evicted, which reconnects every socket cold.
|
|
3860
|
+
*/
|
|
3861
|
+
private retirePreviousIdentity;
|
|
3862
|
+
/**
|
|
3863
|
+
* How the open sockets must follow a bearer change when the transport
|
|
3864
|
+
* presents the bearer on the upgrade (React Native's `Authorization`
|
|
3865
|
+
* header). An open upgrade keeps the token it was made with for its whole
|
|
3866
|
+
* life, and a browser socket never carries it, so without
|
|
3867
|
+
* `authTokenOnUpgrade` nothing reconnects.
|
|
3868
|
+
*
|
|
3869
|
+
* A sign-in from signed-out is `"cold"`: the sockets upgraded anonymously,
|
|
3870
|
+
* and no view may resume from an anonymous cursor. A refreshed bearer under
|
|
3871
|
+
* an unchanged identity is `"warm"`: the subscriptions resume from their
|
|
3872
|
+
* cursors.
|
|
3873
|
+
*
|
|
3874
|
+
* A sign-out or an account switch leaves a previous identity behind and is
|
|
3875
|
+
* evicted by `setAuthToken` before this is asked.
|
|
3876
|
+
*/
|
|
3877
|
+
private reconcileUpgradeBearer;
|
|
3878
|
+
private applyUpgradeBearer;
|
|
3788
3879
|
/** Guard shared by every public entry point: a closed client accepts no further calls. */
|
|
3789
3880
|
private assertOpen;
|
|
3790
3881
|
/**
|
|
@@ -4374,6 +4465,11 @@ declare class LunoraClient {
|
|
|
4374
4465
|
* shard still waking, a swallowed message) would otherwise leave the
|
|
4375
4466
|
* subscription un-acked on a perfectly live socket until the next reconnect.
|
|
4376
4467
|
* One retry, not a loop: a query that is merely slow must not be re-run repeatedly.
|
|
4468
|
+
*
|
|
4469
|
+
* The retry gets one ack window of its own (`final`), after which the frame is
|
|
4470
|
+
* stood down so a later `subscribe()` can send again; otherwise a lost retry
|
|
4471
|
+
* refuses every send until the next reconnect. Kept in `unackedWatchdogs`, so
|
|
4472
|
+
* an ack or a teardown cancels either phase.
|
|
4377
4473
|
*/
|
|
4378
4474
|
private armUnackedWatchdog;
|
|
4379
4475
|
private sendShapeSubscribeIfOpen;
|
|
@@ -4859,6 +4955,14 @@ declare class LunoraClient {
|
|
|
4859
4955
|
private restartTabCoordinatorForIdentity;
|
|
4860
4956
|
/** Drop every room send held before the socket opened: they were made under the identity that is now going away. */
|
|
4861
4957
|
private resetRoomSends;
|
|
4958
|
+
/**
|
|
4959
|
+
* Blank every live subscription and shape, forget their resume cursors, and
|
|
4960
|
+
* reconnect every socket, so each resubscribe is a cold one the server
|
|
4961
|
+
* re-seeds for the identity the new socket carries. Used when the socket's
|
|
4962
|
+
* credential changes: resuming from a cursor taken under the previous one
|
|
4963
|
+
* would splice a diff onto rows that identity was never shown.
|
|
4964
|
+
*/
|
|
4965
|
+
private reconnectCold;
|
|
4862
4966
|
/**
|
|
4863
4967
|
* Close every open shard socket so each reconnects carrying the credential
|
|
4864
4968
|
* in effect now.
|
|
@@ -4889,6 +4993,47 @@ declare class LunoraClient {
|
|
|
4889
4993
|
* flush AND every write waiting on the barrier.
|
|
4890
4994
|
*/
|
|
4891
4995
|
private flushOfflineQueue;
|
|
4996
|
+
/**
|
|
4997
|
+
* Where a snapshot precondition's subscription stands on its socket, when
|
|
4998
|
+
* comparing would mislead: `"awaiting"` while a reconnect has un-answered it
|
|
4999
|
+
* and no value has answered since (the comparison would judge the previous
|
|
5000
|
+
* socket's value, or a blank), `"unreadable"` once that wait ended with no
|
|
5001
|
+
* value to read. `undefined` for any other precondition or subscription.
|
|
5002
|
+
*/
|
|
5003
|
+
private snapshotAnswer;
|
|
5004
|
+
/**
|
|
5005
|
+
* The precondition a queued write carries. A snapshot precondition reads as
|
|
5006
|
+
* holding while its subscription is awaited, so `drainConflict` keeps the
|
|
5007
|
+
* write rather than drop it on a blank the server acked but has not seeded
|
|
5008
|
+
* yet (the drain then holds it back, {@link drainOfflineQueue}), and once the
|
|
5009
|
+
* wait ended unreadable, which is no evidence the value changed.
|
|
5010
|
+
*/
|
|
5011
|
+
private holdWhileUnanswered;
|
|
5012
|
+
/**
|
|
5013
|
+
* A follower's counterpart of a socket open in {@link markShardPendingAck}: every
|
|
5014
|
+
* subscription awaits the leader's next relay. A follower cannot ask the leader for
|
|
5015
|
+
* one, and the leader relays only the queries it holds itself, so the wait is bounded
|
|
5016
|
+
* by the leader's own (an ack window and one retry) and ends unreadable, as the
|
|
5017
|
+
* leader's does when it gives up.
|
|
5018
|
+
*/
|
|
5019
|
+
private awaitLeaderAnswers;
|
|
5020
|
+
/**
|
|
5021
|
+
* Holds `state` for the leader's next relay. Its timer is its own, so settling
|
|
5022
|
+
* one subscription early never releases another.
|
|
5023
|
+
*/
|
|
5024
|
+
private awaitLeaderAnswer;
|
|
5025
|
+
/**
|
|
5026
|
+
* `state` has been answered on its socket (`readable`), or will not be: release
|
|
5027
|
+
* any write held for it. Not called for an `ack`, which the server sends
|
|
5028
|
+
* before the seed.
|
|
5029
|
+
*/
|
|
5030
|
+
private settleAwaitedAnswer;
|
|
5031
|
+
/**
|
|
5032
|
+
* Put back a drained write whose snapshot cannot be compared yet, and every
|
|
5033
|
+
* write behind it (replaying those first would reorder the shard), recording
|
|
5034
|
+
* the hold so the answer flushes again. Returns the writes that may go on.
|
|
5035
|
+
*/
|
|
5036
|
+
private holdUndecidedWrites;
|
|
4892
5037
|
private drainOfflineQueue;
|
|
4893
5038
|
/**
|
|
4894
5039
|
* Ask for another flush of this shard after a backoff, because every entry it
|
package/dist/packem_shared/{lunora-client.d-B_eWE1gD.d.mts → lunora-client.d-DtTKDhtw.d.mts}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LunoraErrorCodeInput, LunoraErrorCode } from '@lunora/errors';
|
|
1
|
+
import { LunoraErrorCodeInput, LunoraErrorCode, LunoraError } from '@lunora/errors';
|
|
2
2
|
import { F as FunctionReference, A as ArgsOf, R as ReturnOf } from "./function-reference.d-Br_hsKje.mjs";
|
|
3
3
|
import { CronJobInfo, VectorIndexSummary, VectorQueryMatch, PipelineLogQuery, PipelineLogPage, KvNamespaceSummary, KvKeyListResult, KvValueResult, AuthUser, AuthPage, AuthImpersonation, AuthCapabilities, AuthConfigInfo, AuthSession } from '@lunora/runtime';
|
|
4
4
|
/**
|
|
@@ -382,6 +382,14 @@ interface LunoraClientOptions {
|
|
|
382
382
|
* `/api/auth` (matching `@lunora/auth`'s `DEFAULT_AUTH_BASE_PATH`).
|
|
383
383
|
*/
|
|
384
384
|
authBasePath?: string;
|
|
385
|
+
/**
|
|
386
|
+
* Whether the `WebSocket` transport sends the `setAuthToken` bearer on the
|
|
387
|
+
* upgrade, as `@lunora/react-native` does on native. Then a
|
|
388
|
+
* sign-in from signed-out reconnects the shard sockets so the server sees the
|
|
389
|
+
* bearer. A browser socket cannot carry it, so the default `false` leaves its
|
|
390
|
+
* sockets (and their live values) alone.
|
|
391
|
+
*/
|
|
392
|
+
authTokenOnUpgrade?: boolean;
|
|
385
393
|
bookmarkStorage?: BookmarkStorage;
|
|
386
394
|
/**
|
|
387
395
|
* Stable per-client id backing the custom-mutator watermark. Sent on the
|
|
@@ -1320,8 +1328,13 @@ interface OptimisticLayer {
|
|
|
1320
1328
|
readonly transform: (current: unknown) => unknown;
|
|
1321
1329
|
}
|
|
1322
1330
|
interface SubscriptionState {
|
|
1323
|
-
/**
|
|
1324
|
-
|
|
1331
|
+
/**
|
|
1332
|
+
* Where this subscription's `subscribe` frame stands on the current socket:
|
|
1333
|
+
* none outstanding (`"idle"`), sent and not yet answered (`"inflight"`, so a
|
|
1334
|
+
* second subscriber joins it instead of sending another), or acknowledged by
|
|
1335
|
+
* the server (`"acked"`). Written only through {@link setSubscriptionAck}.
|
|
1336
|
+
*/
|
|
1337
|
+
ack: "acked" | "idle" | "inflight";
|
|
1325
1338
|
readonly args: Record<string, unknown>;
|
|
1326
1339
|
/**
|
|
1327
1340
|
* Stable wire-key of `args` (`stableWireKey`), computed once at subscribe
|
|
@@ -1470,12 +1483,17 @@ type LunoraClientError = Error & {
|
|
|
1470
1483
|
code?: LunoraErrorCode | (string & {});
|
|
1471
1484
|
data?: unknown;
|
|
1472
1485
|
docsUrl?: string;
|
|
1486
|
+
/**
|
|
1487
|
+
* The headers of the reply this error came from. Set by the RPC, batch and replay paths; absent on
|
|
1488
|
+
* a failure with no reply (a `fetch` that rejected, a timeout) and on the admin and stream paths.
|
|
1489
|
+
*/
|
|
1490
|
+
headers?: Readonly<Record<string, string>>;
|
|
1473
1491
|
hint?: string | string[];
|
|
1474
1492
|
why?: string;
|
|
1475
1493
|
};
|
|
1476
1494
|
/** One demuxed result slot of a `LunoraClient.batch` call. */
|
|
1477
1495
|
type BatchSlot = {
|
|
1478
|
-
error: LunoraClientError;
|
|
1496
|
+
error: LunoraClientError | LunoraError;
|
|
1479
1497
|
ok: false;
|
|
1480
1498
|
} | {
|
|
1481
1499
|
ok: true;
|
|
@@ -1924,6 +1942,8 @@ declare class LunoraClient {
|
|
|
1924
1942
|
private readonly pollingFallbackAfterFailedAttempts;
|
|
1925
1943
|
/** Polling-fallback cadence (ms); `0` disables it. See {@link LunoraClientOptions.pollingFallback}. */
|
|
1926
1944
|
private readonly pollingFallbackIntervalMs;
|
|
1945
|
+
/** See {@link LunoraClientOptions.authTokenOnUpgrade}. */
|
|
1946
|
+
private readonly authTokenOnUpgrade;
|
|
1927
1947
|
private readonly offlineQueue;
|
|
1928
1948
|
/**
|
|
1929
1949
|
* Durable outbox seam (the `@lunora/db` `createExecutorOutboxSink`). When
|
|
@@ -2075,6 +2095,8 @@ declare class LunoraClient {
|
|
|
2075
2095
|
*/
|
|
2076
2096
|
private readonly connectionContextHolders;
|
|
2077
2097
|
private authToken;
|
|
2098
|
+
/** Hash of the current bearer, keyed on the token so a new token misses once. `setAuthToken` drops it on every change, so a replaced or signed-out bearer is not retained. */
|
|
2099
|
+
private tokenFingerprint;
|
|
2078
2100
|
/**
|
|
2079
2101
|
* Optional STABLE identity subject (a user id), the basis of the offline-queue
|
|
2080
2102
|
* identity stamp when supplied. Keeps a same-user token *refresh* from looking
|
|
@@ -2268,6 +2290,27 @@ declare class LunoraClient {
|
|
|
2268
2290
|
* racing write was never in the queue.
|
|
2269
2291
|
*/
|
|
2270
2292
|
private readonly offlineFlushes;
|
|
2293
|
+
/**
|
|
2294
|
+
* Subscriptions a socket `open` un-answered that no value-bearing frame has
|
|
2295
|
+
* answered since. What they hold is the previous socket's value, or a blank
|
|
2296
|
+
* after a cold reconnect, and the server acks a `subscribe` before it seeds
|
|
2297
|
+
* it, so neither `lastValue` nor `ack` says the value is current. A queued
|
|
2298
|
+
* write whose snapshot precondition reads one of them is not evaluated yet:
|
|
2299
|
+
* see {@link LunoraClient.snapshotAnswer}. On a follower the open is the
|
|
2300
|
+
* leader's, see {@link LunoraClient.awaitLeaderAnswers}.
|
|
2301
|
+
*/
|
|
2302
|
+
private readonly awaitingAnswer;
|
|
2303
|
+
/**
|
|
2304
|
+
* Subscriptions whose wait ended without a value to read: the seed was
|
|
2305
|
+
* refused or undecodable, or the resubscribe was given up on. Still acked and
|
|
2306
|
+
* blank after a cold reconnect, so a snapshot comparison would read the blank
|
|
2307
|
+
* as a change; a guard over one of them is no evidence either way.
|
|
2308
|
+
*/
|
|
2309
|
+
private readonly answeredUnreadable;
|
|
2310
|
+
/** Connection keys whose last flush left a write waiting on {@link LunoraClient.awaitingAnswer}; an answer there flushes again. */
|
|
2311
|
+
private readonly answerHeldShards;
|
|
2312
|
+
/** Gives up on the leader relaying an answer, one per subscription, see {@link LunoraClient.awaitLeaderAnswer}. */
|
|
2313
|
+
private readonly leaderAnswerTimers;
|
|
2271
2314
|
/**
|
|
2272
2315
|
* Per-shard replay backoff, keyed by {@link connectionKey} exactly as the
|
|
2273
2316
|
* flushes and their timers are: `delayMs` is the longest hint the CURRENT
|
|
@@ -2323,7 +2366,10 @@ declare class LunoraClient {
|
|
|
2323
2366
|
* Does NOT update the WebSocket auth — a socket keeps the session credential
|
|
2324
2367
|
* it connected with for its life. To refresh live WS auth, call
|
|
2325
2368
|
* {@link setWsToken} explicitly, which closes existing shard sockets to
|
|
2326
|
-
* force a reconnect with the new credential.
|
|
2369
|
+
* force a reconnect with the new credential. With
|
|
2370
|
+
* {@link LunoraClientOptions.authTokenOnUpgrade} (React Native's
|
|
2371
|
+
* `Authorization` header), a sign-in from signed-out (a token where there was
|
|
2372
|
+
* none) reconnects the sockets, cold, so the upgrade presents it.
|
|
2327
2373
|
*/
|
|
2328
2374
|
setAuthToken(token: string | null, subject?: string | null): void;
|
|
2329
2375
|
getAuthToken(): string | null;
|
|
@@ -2844,6 +2890,25 @@ declare class LunoraClient {
|
|
|
2844
2890
|
* `new globalThis.WebSocket(url)` would silently bypass.
|
|
2845
2891
|
*/
|
|
2846
2892
|
getWebSocketImpl(): typeof WebSocket | undefined;
|
|
2893
|
+
/**
|
|
2894
|
+
* `true` while {@link LunoraClientOptions.crossTabSync} is on and this tab
|
|
2895
|
+
* is not the elected leader, including the election window before it knows
|
|
2896
|
+
* whether another tab leads. Such a tab holds no socket: its subscriptions
|
|
2897
|
+
* see only the frames the leader relays for queries the leader holds too,
|
|
2898
|
+
* so a read that must resolve goes over HTTP instead of waiting on a push.
|
|
2899
|
+
*/
|
|
2900
|
+
isCrossTabFollower(): boolean;
|
|
2901
|
+
/**
|
|
2902
|
+
* Whether a live query on `shardKey` can expect its value to be pushed: by a
|
|
2903
|
+
* socket that is open or still on its first connect attempt, or by the
|
|
2904
|
+
* polling fallback. `false` once a connect attempt has failed to reach `open`
|
|
2905
|
+
* since the socket last did and polling is not delivering instead, where a
|
|
2906
|
+
* read that must resolve should go over HTTP rather than wait on a push. A
|
|
2907
|
+
* shard with no connection yet expects one: subscribing opens it.
|
|
2908
|
+
*/
|
|
2909
|
+
expectsPush(options?: {
|
|
2910
|
+
shardKey?: string;
|
|
2911
|
+
}): boolean;
|
|
2847
2912
|
/**
|
|
2848
2913
|
* Read the current value for a {@link ClientQueryRef}. Returns
|
|
2849
2914
|
* `ref.defaultValue` when no value has been explicitly set.
|
|
@@ -2926,7 +2991,9 @@ declare class LunoraClient {
|
|
|
2926
2991
|
* whether one exists at all rather than just its value. `present` is `false`
|
|
2927
2992
|
* when no subscription is open for the given `(functionPath, args, shardKey)`;
|
|
2928
2993
|
* `value` is the subscription's `lastValue`, which includes any optimistic
|
|
2929
|
-
* overlay.
|
|
2994
|
+
* overlay. `answered` is `false` while an open subscription holds no answer
|
|
2995
|
+
* (never answered, or blanked by a cold reconnect), when `value` is absence
|
|
2996
|
+
* rather than evidence.
|
|
2930
2997
|
*
|
|
2931
2998
|
* The two are separate because a caller like the snapshot precondition has to
|
|
2932
2999
|
* tell "no subscription is active, so this read knows nothing" apart from
|
|
@@ -2939,6 +3006,7 @@ declare class LunoraClient {
|
|
|
2939
3006
|
* in-memory state of an already-opened subscription.
|
|
2940
3007
|
*/
|
|
2941
3008
|
peekActiveQuerySnapshot(functionPath: string, args: Record<string, unknown>, shardKey?: string): {
|
|
3009
|
+
answered: boolean;
|
|
2942
3010
|
present: boolean;
|
|
2943
3011
|
value: unknown;
|
|
2944
3012
|
};
|
|
@@ -3785,6 +3853,29 @@ declare class LunoraClient {
|
|
|
3785
3853
|
signal?: AbortSignal;
|
|
3786
3854
|
}): StreamIterable<HttpStreamChunkOf<Ref>>;
|
|
3787
3855
|
close(): void;
|
|
3856
|
+
/**
|
|
3857
|
+
* A genuine credential change: reject the queued writes that can no longer
|
|
3858
|
+
* replay as the incoming identity, and evict the session the previous one
|
|
3859
|
+
* left live. `true` when it evicted, which reconnects every socket cold.
|
|
3860
|
+
*/
|
|
3861
|
+
private retirePreviousIdentity;
|
|
3862
|
+
/**
|
|
3863
|
+
* How the open sockets must follow a bearer change when the transport
|
|
3864
|
+
* presents the bearer on the upgrade (React Native's `Authorization`
|
|
3865
|
+
* header). An open upgrade keeps the token it was made with for its whole
|
|
3866
|
+
* life, and a browser socket never carries it, so without
|
|
3867
|
+
* `authTokenOnUpgrade` nothing reconnects.
|
|
3868
|
+
*
|
|
3869
|
+
* A sign-in from signed-out is `"cold"`: the sockets upgraded anonymously,
|
|
3870
|
+
* and no view may resume from an anonymous cursor. A refreshed bearer under
|
|
3871
|
+
* an unchanged identity is `"warm"`: the subscriptions resume from their
|
|
3872
|
+
* cursors.
|
|
3873
|
+
*
|
|
3874
|
+
* A sign-out or an account switch leaves a previous identity behind and is
|
|
3875
|
+
* evicted by `setAuthToken` before this is asked.
|
|
3876
|
+
*/
|
|
3877
|
+
private reconcileUpgradeBearer;
|
|
3878
|
+
private applyUpgradeBearer;
|
|
3788
3879
|
/** Guard shared by every public entry point: a closed client accepts no further calls. */
|
|
3789
3880
|
private assertOpen;
|
|
3790
3881
|
/**
|
|
@@ -4374,6 +4465,11 @@ declare class LunoraClient {
|
|
|
4374
4465
|
* shard still waking, a swallowed message) would otherwise leave the
|
|
4375
4466
|
* subscription un-acked on a perfectly live socket until the next reconnect.
|
|
4376
4467
|
* One retry, not a loop: a query that is merely slow must not be re-run repeatedly.
|
|
4468
|
+
*
|
|
4469
|
+
* The retry gets one ack window of its own (`final`), after which the frame is
|
|
4470
|
+
* stood down so a later `subscribe()` can send again; otherwise a lost retry
|
|
4471
|
+
* refuses every send until the next reconnect. Kept in `unackedWatchdogs`, so
|
|
4472
|
+
* an ack or a teardown cancels either phase.
|
|
4377
4473
|
*/
|
|
4378
4474
|
private armUnackedWatchdog;
|
|
4379
4475
|
private sendShapeSubscribeIfOpen;
|
|
@@ -4859,6 +4955,14 @@ declare class LunoraClient {
|
|
|
4859
4955
|
private restartTabCoordinatorForIdentity;
|
|
4860
4956
|
/** Drop every room send held before the socket opened: they were made under the identity that is now going away. */
|
|
4861
4957
|
private resetRoomSends;
|
|
4958
|
+
/**
|
|
4959
|
+
* Blank every live subscription and shape, forget their resume cursors, and
|
|
4960
|
+
* reconnect every socket, so each resubscribe is a cold one the server
|
|
4961
|
+
* re-seeds for the identity the new socket carries. Used when the socket's
|
|
4962
|
+
* credential changes: resuming from a cursor taken under the previous one
|
|
4963
|
+
* would splice a diff onto rows that identity was never shown.
|
|
4964
|
+
*/
|
|
4965
|
+
private reconnectCold;
|
|
4862
4966
|
/**
|
|
4863
4967
|
* Close every open shard socket so each reconnects carrying the credential
|
|
4864
4968
|
* in effect now.
|
|
@@ -4889,6 +4993,47 @@ declare class LunoraClient {
|
|
|
4889
4993
|
* flush AND every write waiting on the barrier.
|
|
4890
4994
|
*/
|
|
4891
4995
|
private flushOfflineQueue;
|
|
4996
|
+
/**
|
|
4997
|
+
* Where a snapshot precondition's subscription stands on its socket, when
|
|
4998
|
+
* comparing would mislead: `"awaiting"` while a reconnect has un-answered it
|
|
4999
|
+
* and no value has answered since (the comparison would judge the previous
|
|
5000
|
+
* socket's value, or a blank), `"unreadable"` once that wait ended with no
|
|
5001
|
+
* value to read. `undefined` for any other precondition or subscription.
|
|
5002
|
+
*/
|
|
5003
|
+
private snapshotAnswer;
|
|
5004
|
+
/**
|
|
5005
|
+
* The precondition a queued write carries. A snapshot precondition reads as
|
|
5006
|
+
* holding while its subscription is awaited, so `drainConflict` keeps the
|
|
5007
|
+
* write rather than drop it on a blank the server acked but has not seeded
|
|
5008
|
+
* yet (the drain then holds it back, {@link drainOfflineQueue}), and once the
|
|
5009
|
+
* wait ended unreadable, which is no evidence the value changed.
|
|
5010
|
+
*/
|
|
5011
|
+
private holdWhileUnanswered;
|
|
5012
|
+
/**
|
|
5013
|
+
* A follower's counterpart of a socket open in {@link markShardPendingAck}: every
|
|
5014
|
+
* subscription awaits the leader's next relay. A follower cannot ask the leader for
|
|
5015
|
+
* one, and the leader relays only the queries it holds itself, so the wait is bounded
|
|
5016
|
+
* by the leader's own (an ack window and one retry) and ends unreadable, as the
|
|
5017
|
+
* leader's does when it gives up.
|
|
5018
|
+
*/
|
|
5019
|
+
private awaitLeaderAnswers;
|
|
5020
|
+
/**
|
|
5021
|
+
* Holds `state` for the leader's next relay. Its timer is its own, so settling
|
|
5022
|
+
* one subscription early never releases another.
|
|
5023
|
+
*/
|
|
5024
|
+
private awaitLeaderAnswer;
|
|
5025
|
+
/**
|
|
5026
|
+
* `state` has been answered on its socket (`readable`), or will not be: release
|
|
5027
|
+
* any write held for it. Not called for an `ack`, which the server sends
|
|
5028
|
+
* before the seed.
|
|
5029
|
+
*/
|
|
5030
|
+
private settleAwaitedAnswer;
|
|
5031
|
+
/**
|
|
5032
|
+
* Put back a drained write whose snapshot cannot be compared yet, and every
|
|
5033
|
+
* write behind it (replaying those first would reorder the shard), recording
|
|
5034
|
+
* the hold so the answer flushes again. Returns the writes that may go on.
|
|
5035
|
+
*/
|
|
5036
|
+
private holdUndecidedWrites;
|
|
4892
5037
|
private drainOfflineQueue;
|
|
4893
5038
|
/**
|
|
4894
5039
|
* Ask for another flush of this shard after a backoff, because every entry it
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let a=0;const d=()=>{if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID();a+=1;const o=typeof crypto<"u"&&typeof crypto.getRandomValues=="function"?Array.from(crypto.getRandomValues(new Uint8Array(8)),e=>e.toString(16).padStart(2,"0")).join(""):Math.random().toString(16).slice(2,12);return`id_${Date.now().toString(36)}_${a.toString(36)}_${o}`},l=(o,e)=>o!==void 0&&e!==o,f=d,h=(o,e,t,i)=>{if(o)try{o({error:t,mutationId:i,operation:e});return}catch{}console.warn(`[lunora] offline-queue persistence ${e} failed`,t)};class p{queueBeforeFirstConnect;maxItems;onPersistenceError;persistence;onEvict;onSizeChange;onReplayingChange;version;items=[];replayingIds=new Set;appending=new Map;unsettled=new Map;unpersisted=new Set;constructor(e={},t={}){this.maxItems=e.maxItems??1e3,this.queueBeforeFirstConnect=e.queueBeforeFirstConnect??!1,this.onPersistenceError=e.onPersistenceError,this.persistence=t.persistence,this.onEvict=t.onEvict,this.onSizeChange=t.onSizeChange,this.onReplayingChange=t.onReplayingChange,this.version=t.version}get size(){return this.items.length}get replaying(){return this.replayingIds.size}enqueue(e){const t=e;t.id??=f();let i=this.items.length;for(;t.issueSeq!==void 0&&i>0&&(this.items[i-1]?.issueSeq??-1)>t.issueSeq;)i-=1;this.items.splice(i,0,t),this.unsettled.set(t.id,t),this.persist(this.recordOf(t,t.id)),this.evictOverflow(),this.notifySize()}discard(e){this.unsettled.delete(e),this.unpersisted.delete(e),this.replayingIds.delete(e)&&this.onReplayingChange?.();const{persistence:t}=this;t&&(this.appending.get(e)??Promise.resolve()).then(async()=>t.remove(e)).catch(i=>{h(this.onPersistenceError,"remove",i,e)})}flushUnpersisted(){for(const e of this.unpersisted){const t=this.unsettled.get(e);t&&!this.appending.has(e)&&this.persist(this.recordOf(t,e))}}async hydrate(){if(!this.persistence)return[];let e;try{e=await this.persistence.load()}catch(s){throw h(this.onPersistenceError,"load",s),s}const t=[],i=new Set(this.items.map(s=>s.id));for(const s of e)if(!i.has(s.id)){if(l(this.version,s.version)){this.persistence.remove(s.id).catch(c=>{h(this.onPersistenceError,"remove",c,s.id)});continue}i.add(s.id),t.push({args:s.args,baselineSeq:s.baselineSeq,clientId:s.clientId,functionPath:s.functionPath,id:s.id,identity:s.identity,reject:()=>{},resolve:()=>{},shardKey:s.shardKey})}this.items.unshift(...t),this.evictOverflow(),this.notifySize();const n=new Set(this.items),r=new Set;for(const s of t)n.has(s)&&r.add(s.shardKey);return[...r]}restampIdentity(e,t){for(const i of this.items){if(i.identity!==e)continue;i.identity=t;const{id:n}=i;!this.persistence||n===void 0||this.rewriteStamp(n,this.recordOf(i,n)).catch(r=>{h(this.onPersistenceError,"replace",r,n)})}}hasPending(e){return this.items.some(t=>e(t))}drain(e){if(!e){const n=[...this.items];return this.items.length=0,this.markReplaying(n),this.notifySize(),n}const t=[],i=[];for(const n of this.items)(e(n)?t:i).push(n);return this.items.length=0,this.items.push(...i),this.markReplaying(t),this.notifySize(),t}requeue(e){if(e.length!==0){for(const t of e)t.id!==void 0&&this.replayingIds.delete(t.id);this.items.unshift(...e),this.notifySize()}}drainConflict(){const e=[],t=[];for(const i of this.items){let n=!0,r;if(i.precondition!==void 0)try{n=i.precondition()}catch(s){n=!1,r=s}if(n)t.push(i);else{const s=new Error("offline mutation skipped: precondition failed before replay",r===void 0?void 0:{cause:r});s.code="OFFLINE_PRECONDITION_FAILED",i.reject(s),e.push(i)}}return e.length>0&&(this.items.length=0,this.items.push(...t),this.notifySize()),e}clear(){for(const e of new Set([...this.items,...this.unsettled.values()])){const t=new Error("CLIENT_CLOSED"),i=e.id??"",n=s=>{t.code="CLIENT_CLOSED",t.persisted=s,e.reject(t)},r=this.appending.get(i);this.replayingIds.has(i)?n(!1):r===void 0?n(this.persistence!==void 0&&!this.unpersisted.has(i)):r.catch(()=>!1).then(n).catch(()=>{})}this.items.length=0,this.replayingIds.clear(),this.unsettled.clear(),this.unpersisted.clear(),this.notifySize()}recordOf(e,t){return{args:e.args,...e.baselineSeq===void 0?{}:{baselineSeq:e.baselineSeq},clientId:e.clientId,functionPath:e.functionPath,id:t,identity:e.identity,shardKey:e.shardKey,...this.version===void 0?{}:{version:this.version}}}persist(e){const{persistence:t}=this;if(!t)return;const i=(async()=>{try{return await t.append(e),this.unpersisted.delete(e.id),!0}catch(n){return this.unsettled.has(e.id)&&this.unpersisted.add(e.id),h(this.onPersistenceError,"append",n,e.id),!1}})();this.appending.set(e.id,i),i.finally(()=>{this.appending.get(e.id)===i&&this.appending.delete(e.id)}).catch(()=>{})}async rewriteStamp(e,t){const i=this.persistence;if(i)try{await this.appending.get(e),await i.replace(t)}catch(n){h(this.onPersistenceError,"replace",n,e)}}evictOverflow(){for(;this.items.length>this.maxItems;){const e=this.items.shift();if(e){e.id&&this.discard(e.id);const t=new Error("offline queue overflow");t.code="OFFLINE_QUEUE_OVERFLOW",e.reject(t),this.onEvict?.(e,t)}}}markReplaying(e){for(const t of e)t.id!==void 0&&this.replayingIds.add(t.id)}notifySize(){this.onSizeChange?.(this.items.length)}}export{p as O,l as i,f as n,h as r};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { L as LunoraClient, P as Preloaded } from "./lunora-client.d-
|
|
1
|
+
import { L as LunoraClient, P as Preloaded } from "./lunora-client.d-7WaMRZUK.js";
|
|
2
2
|
import { F as FunctionReference, A as ArgsOf, R as ReturnOf } from "./function-reference.d-Br_hsKje.js";
|
|
3
3
|
/**
|
|
4
4
|
* Run a query once on the server (during SSR) and capture its result in a
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { L as LunoraClient, P as Preloaded } from "./lunora-client.d-
|
|
1
|
+
import { L as LunoraClient, P as Preloaded } from "./lunora-client.d-DtTKDhtw.mjs";
|
|
2
2
|
import { F as FunctionReference, A as ArgsOf, R as ReturnOf } from "./function-reference.d-Br_hsKje.mjs";
|
|
3
3
|
/**
|
|
4
4
|
* Run a query once on the server (during SSR) and capture its result in a
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{stableWireKey as p}from"@lunora/wire";const u=new WeakMap,i=(e,t)=>{u.set(e,t)},d=e=>e===void 0?void 0:u.get(e),h=(e,t,s,n)=>{const o=e.peekActiveQuerySnapshot(t.__lunoraRef,s,n),a=o.present&&o.answered?p(o.value):void 0,c=()=>{const r=e.peekActiveQuerySnapshot(t.__lunoraRef,s,n);return!o.present||!o.answered||!r.present||!r.answered?!0:p(r.value)===a};return a!==void 0&&i(c,{args:s,functionPath:t.__lunoraRef,shardKey:n}),c};export{h as c,i as r,d as s};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as n}from"@lunora/errors";import{decodeWire as d}from"@lunora/wire";import{TransportError as u,getRetryAfterMs as f}from"./CONFLICT_ERROR_CODE-B7qNZMMk.mjs";const l=t=>{if(t===null)return;const e=Number(t);if(Number.isFinite(e))return e>0?e*1e3:void 0;const r=Date.parse(t);if(Number.isNaN(r))return;const o=r-Date.now();return o>0?o:void 0},v=(t,e)=>{const r=l(e);if(!(r===void 0||f(t)!==void 0))return t.data===void 0?{retryAfterMs:r}:typeof t.data=="object"&&t.data!==null&&!Array.isArray(t.data)?{...t.data,retryAfterMs:r}:void 0},p=t=>{const e=t?.error;if(typeof e!="object"||e===null||Array.isArray(e))return;const{why:r,...o}=e;return typeof r=="string"?{...o,why:r}:o},E=()=>new u("LunoraClient: batch slot carried no error envelope"),i=(t,e)=>{const r=t.error,o=typeof r?.code=="string"?r.code:void 0,s=typeof r?.message=="string"?r.message:void 0;return{code:o,messageText:(typeof t.message=="string"?t.message:void 0)??s??e}},A=t=>{const{code:e,messageText:r}=i(t,"stream error"),o=t.error?.why,s=e===void 0?new Error(r):new n(e,r);return typeof o=="string"&&(s.why=o),s},R=t=>{const{code:e,messageText:r}=i(t,"subscription error"),o=t.error?.why;return{message:r,...e===void 0?{}:{code:e},...typeof o=="string"?{why:o}:{}}},y=Symbol.for("lunora.serverVerdict"),a=t=>{const e=new Error(t.message??"request failed");if(e.code=t.code,e[y]=!0,t.data!==void 0)try{e.data=d(t.data)}catch{}return t.hint!==void 0&&(e.hint=t.hint),t.docsUrl!==void 0&&(e.docsUrl=t.docsUrl),typeof t.why=="string"&&(e.why=t.why),e},m=t=>Object.freeze(Object.fromEntries([...t].filter(([e])=>e!=="set-cookie"))),b=(t,e)=>Object.defineProperty(t,"headers",{value:m(e)}),S=(t,e)=>{const r=a(t),o=v(r,e.get("retry-after"));return o!==void 0&&(r.data=o),b(r,e)},D=t=>{const e=p(t);return e===void 0?E():a(e)},c=new WeakSet,j=t=>{const e=new n("WIRE_DECODE_FAILED",`LunoraClient: the call succeeded but its result could not be decoded (a mutation has still committed) — ${t instanceof Error?t.message:String(t)}`,{cause:t});return c.add(e),e},M=t=>t instanceof Error&&c.has(t);export{l as a,S as b,A as c,R as d,p as e,E as f,M as i,a as r,D as s,j as u,b as w};
|
package/dist/query/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as SubscriptionError, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { S as SubscriptionError, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-DtTKDhtw.mjs";
|
|
2
2
|
export type {
|
|
3
3
|
/**
|
|
4
4
|
* `@lunora/client/query` — the framework-neutral live-query state machine shared
|
|
@@ -10,7 +10,7 @@ export type {
|
|
|
10
10
|
* framework — each adapter supplies thin sinks that write into its own ref /
|
|
11
11
|
* store / signal / cache.
|
|
12
12
|
*/
|
|
13
|
-
b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-
|
|
13
|
+
b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-DtTKDhtw.mjs";
|
|
14
14
|
import { F as FunctionReference, A as ArgsOf, R as ReturnOf } from "../packem_shared/function-reference.d-Br_hsKje.mjs";
|
|
15
15
|
import '@lunora/errors';
|
|
16
16
|
import '@lunora/runtime';
|
package/dist/query/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as SubscriptionError, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { S as SubscriptionError, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-7WaMRZUK.js";
|
|
2
2
|
export type {
|
|
3
3
|
/**
|
|
4
4
|
* `@lunora/client/query` — the framework-neutral live-query state machine shared
|
|
@@ -10,7 +10,7 @@ export type {
|
|
|
10
10
|
* framework — each adapter supplies thin sinks that write into its own ref /
|
|
11
11
|
* store / signal / cache.
|
|
12
12
|
*/
|
|
13
|
-
b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-
|
|
13
|
+
b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-7WaMRZUK.js";
|
|
14
14
|
import { F as FunctionReference, A as ArgsOf, R as ReturnOf } from "../packem_shared/function-reference.d-Br_hsKje.js";
|
|
15
15
|
import '@lunora/errors';
|
|
16
16
|
import '@lunora/runtime';
|
package/dist/service.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{LunoraError as c}from"@lunora/errors";import{encodeArgsOrThrow as d,decodeWire as y}from"@lunora/wire";import{e as f,r as w}from"./packem_shared/wire-errors-
|
|
1
|
+
import{LunoraError as c}from"@lunora/errors";import{encodeArgsOrThrow as d,decodeWire as y}from"@lunora/wire";import{e as f,r as w}from"./packem_shared/wire-errors-BgFi7ONA.mjs";const v="/_lunora/rpc",N="https://lunora.internal",i=async(n,t,r,o,u)=>{const a=r.__lunoraRef,p=JSON.stringify({args:d("@lunora/client/service",a,o??{}),functionPath:a,...u?.shardKey===void 0?{}:{shardKey:u.shardKey}}),e=await n.fetch(new Request(`${N}${v}`,{body:p,headers:{"content-type":"application/json"},method:"POST"}));let s;try{s=await e.json()}catch{throw new c("INTERNAL",`@lunora/client/service: ${t} "${a}" got a non-JSON response (status ${e.status.toString()}). Check the service binding points at the Lunora Worker that declares this function.`,{status:e.status})}if(s===null||typeof s!="object")throw new c("INTERNAL",`@lunora/client/service: ${t} "${a}" returned a JSON body that is not an object (status ${e.status.toString()}). Check the service binding points at the Lunora Worker that declares this function.`,{status:e.status});const h=s,l=f(h);if(l!==void 0)throw w(l);if(!e.ok)throw new c("INTERNAL",`@lunora/client/service: ${t} "${a}" failed with status ${e.status.toString()} and no error envelope.`,{status:e.status});return y(h.result)},R=n=>({action:async(t,r,o)=>await i(n,"action",t,r,o),mutation:async(t,r,o)=>await i(n,"mutation",t,r,o),query:async(t,r,o)=>await i(n,"query",t,r,o)});export{v as RPC_PATH,R as createServiceClient};
|
package/dist/ssr/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-DtTKDhtw.mjs";
|
|
2
2
|
export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/function-reference.d-Br_hsKje.mjs";
|
|
3
3
|
export {
|
|
4
4
|
/**
|
|
@@ -20,7 +20,7 @@ p as preloadQuery,
|
|
|
20
20
|
* WebSocket or touches a UI framework, so it is safe to import from any SSR
|
|
21
21
|
* loader.
|
|
22
22
|
*/
|
|
23
|
-
a as preloadedQueryResult } from "../packem_shared/preload.d-
|
|
23
|
+
a as preloadedQueryResult } from "../packem_shared/preload.d-CT_9YaL9.mjs";
|
|
24
24
|
import '@lunora/errors';
|
|
25
25
|
import '@lunora/runtime';
|
|
26
26
|
/**
|
package/dist/ssr/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-7WaMRZUK.js";
|
|
2
2
|
export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/function-reference.d-Br_hsKje.js";
|
|
3
3
|
export {
|
|
4
4
|
/**
|
|
@@ -20,7 +20,7 @@ p as preloadQuery,
|
|
|
20
20
|
* WebSocket or touches a UI framework, so it is safe to import from any SSR
|
|
21
21
|
* loader.
|
|
22
22
|
*/
|
|
23
|
-
a as preloadedQueryResult } from "../packem_shared/preload.d-
|
|
23
|
+
a as preloadedQueryResult } from "../packem_shared/preload.d-B26QlpOB.js";
|
|
24
24
|
import '@lunora/errors';
|
|
25
25
|
import '@lunora/runtime';
|
|
26
26
|
/**
|
package/dist/ssr/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getServerSession as o}from"../packem_shared/getServerSession-BaOoo1p6.mjs";import{deserializePreloaded as l,serializePreloaded as t}from"../packem_shared/deserializePreloaded-CyFK_cv6.mjs";import{createServerClient as i}from"../packem_shared/createServerClient-
|
|
1
|
+
import{getServerSession as o}from"../packem_shared/getServerSession-BaOoo1p6.mjs";import{deserializePreloaded as l,serializePreloaded as t}from"../packem_shared/deserializePreloaded-CyFK_cv6.mjs";import{createServerClient as i}from"../packem_shared/createServerClient-kd9cUs8g.mjs";import{preloadQuery as s,preloadedQueryResult as f}from"../packem_shared/preloadQuery-uFy24PCR.mjs";export{i as createServerClient,l as deserializePreloaded,o as getServerSession,s as preloadQuery,f as preloadedQueryResult,t as serializePreloaded};
|