@lunora/svelte 0.0.0 → 1.0.0-alpha.1
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 +105 -0
- package/README.md +147 -9
- package/__assets__/package-og.svg +14 -0
- package/dist/index.d.mts +335 -0
- package/dist/index.d.ts +335 -0
- package/dist/index.mjs +10 -0
- package/dist/packem_shared/auth-D8EV6u02.mjs +28 -0
- package/dist/packem_shared/connectionStatus-CROr6jbn.mjs +14 -0
- package/dist/packem_shared/hydratePreloaded-BUv3k4-s.mjs +21 -0
- package/dist/packem_shared/is-function-reference-ycLAcI79.mjs +3 -0
- package/dist/packem_shared/mutation-CA3qEPCB.mjs +31 -0
- package/dist/packem_shared/paginatedQuery-CfCSITZv.mjs +196 -0
- package/dist/packem_shared/presence-Bf-y7QzR.mjs +66 -0
- package/dist/packem_shared/query-B14VE2Qg.mjs +36 -0
- package/dist/packem_shared/rateLimit-Cdw1kp8t.mjs +66 -0
- package/dist/packem_shared/setLunoraClient--bwSz7F6.mjs +16 -0
- package/dist/packem_shared/subscription-B3HDNcpq.mjs +46 -0
- package/dist/server.d.mts +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.mjs +1 -0
- package/dist/worker.d.mts +1 -0
- package/dist/worker.d.ts +1 -0
- package/dist/worker.mjs +1 -0
- package/package.json +58 -17
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import { LunoraClient, User, ConnectionStatus, Preloaded, FunctionReference, ReturnOf, ArgsOf, MutationCallOptions, SubscriptionErrorCallback } from '@lunora/client';
|
|
2
|
+
export type { ArgsOf, ConnectionStatus, FunctionReference, LunoraClient, MutationCallOptions, Preloaded, ReturnOf } from '@lunora/client';
|
|
3
|
+
import { Readable } from 'svelte/store';
|
|
4
|
+
import { PaginationStatus } from '@lunora/client/pagination';
|
|
5
|
+
import { RateLimitStatus, RateLimitConfig } from '@lunora/ratelimit';
|
|
6
|
+
/**
|
|
7
|
+
* Publish a {@link LunoraClient} on the Svelte component context so that
|
|
8
|
+
* descendant components can read it with {@link getLunoraClient} (or implicitly,
|
|
9
|
+
* via the default-client lookups inside `query`/`mutation`/`hydratePreloaded`).
|
|
10
|
+
*
|
|
11
|
+
* Call this once, high in the tree (typically your root `+layout.svelte` or
|
|
12
|
+
* `App.svelte`), during component initialisation — `setContext` must run while
|
|
13
|
+
* the component is being constructed, exactly like React's provider mounts once.
|
|
14
|
+
* This is the Svelte analogue of mounting `LunoraProvider`.
|
|
15
|
+
*/
|
|
16
|
+
declare const setLunoraClient: (client: LunoraClient) => LunoraClient;
|
|
17
|
+
/**
|
|
18
|
+
* Read the {@link LunoraClient} published by {@link setLunoraClient} from the
|
|
19
|
+
* nearest ancestor. Throws if no provider is mounted, mirroring `useLunora`'s
|
|
20
|
+
* "must be used inside a LunoraProvider" guard so the failure is loud and
|
|
21
|
+
* early rather than a confusing `undefined` deref later.
|
|
22
|
+
*
|
|
23
|
+
* Must be called during component initialisation (Svelte's `getContext`
|
|
24
|
+
* constraint); the live stores returned by `query`/`hydratePreloaded` resolve
|
|
25
|
+
* the client eagerly at call time for exactly this reason.
|
|
26
|
+
*/
|
|
27
|
+
declare const getLunoraClient: () => LunoraClient;
|
|
28
|
+
interface AuthStore {
|
|
29
|
+
/** Set the auth token on the underlying `LunoraClient`. */
|
|
30
|
+
setToken: (token: string | null) => void;
|
|
31
|
+
/** Readable store of the auth token (`null` when signed out). */
|
|
32
|
+
token: Readable<string | null>;
|
|
33
|
+
/** Readable store of the resolved user (`null` when signed out or still loading). */
|
|
34
|
+
user: Readable<User | null>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Create a pair of Svelte readable stores tracking the auth token and the
|
|
38
|
+
* resolved user identity. The stores are lazy: subscriptions open on the first
|
|
39
|
+
* reader and close when the last unsubscribes. Calling `setToken(jwt)` after
|
|
40
|
+
* sign-in refreshes both stores.
|
|
41
|
+
*
|
|
42
|
+
* Pass an explicit client to bypass the ambient context (useful in tests).
|
|
43
|
+
*/
|
|
44
|
+
declare const auth: (explicitClient?: ReturnType<typeof getLunoraClient>) => AuthStore;
|
|
45
|
+
/** The shape held by a {@link connectionStatus} store: the latest aggregate live-socket status. */
|
|
46
|
+
type ConnectionStatusStore = Readable<ConnectionStatus>;
|
|
47
|
+
/**
|
|
48
|
+
* Expose the client's aggregate live-socket status as a Svelte readable store.
|
|
49
|
+
* Read it with the `$store` idiom (`{$status}`) and it stays current: the value
|
|
50
|
+
* transitions through `idle` → `connecting` → `connected` → `offline` as
|
|
51
|
+
* sockets open and drop — the Svelte equivalent of `@lunora/react`'s
|
|
52
|
+
* `useConnectionStatus`. Use it to drive a connection indicator.
|
|
53
|
+
*
|
|
54
|
+
* The status listener attaches inside `readable`'s start callback (on the first
|
|
55
|
+
* `$`-read / `.subscribe()`) and is released by the returned stop function when
|
|
56
|
+
* the last subscriber goes away, so a store that's never read attaches nothing.
|
|
57
|
+
*
|
|
58
|
+
* Pass `client` explicitly, or omit it to resolve the ambient client published
|
|
59
|
+
* by `setLunoraClient` (which must therefore be called during component init,
|
|
60
|
+
* before this runs).
|
|
61
|
+
*/
|
|
62
|
+
declare const connectionStatus: (client?: LunoraClient) => ConnectionStatusStore;
|
|
63
|
+
/**
|
|
64
|
+
* Hydrate a query store from a {@link Preloaded} token produced by
|
|
65
|
+
* `preloadQuery` during SSR, then keep it live — the reactive-loader handoff.
|
|
66
|
+
*
|
|
67
|
+
* The store is seeded **synchronously** with `preloaded.value`, so the very
|
|
68
|
+
* first read (`$store` during hydration) returns the server value with no
|
|
69
|
+
* loading flash and no hydration mismatch — there is no `undefined` window and
|
|
70
|
+
* no refetch. When the store gains its first subscriber on the client, a live
|
|
71
|
+
* WS subscription attaches and every subsequent delta re-emits, exactly like a
|
|
72
|
+
* plain `query` store. This is the Svelte equivalent of React's
|
|
73
|
+
* `usePreloadedQuery`.
|
|
74
|
+
*
|
|
75
|
+
* Pass `client` explicitly, or omit it to resolve the ambient client published
|
|
76
|
+
* by `setLunoraClient`.
|
|
77
|
+
*
|
|
78
|
+
* Note on SSR: `readable`'s start callback only runs when the store is actually
|
|
79
|
+
* subscribed (the browser), so on the server the store simply holds the seeded
|
|
80
|
+
* value and opens no socket. The token's `value` is the single source of truth
|
|
81
|
+
* for the first paint either way.
|
|
82
|
+
*/
|
|
83
|
+
declare const hydratePreloaded: <T>(preloaded: Preloaded<T>, client?: LunoraClient) => Readable<T>;
|
|
84
|
+
/**
|
|
85
|
+
* The reactive handle returned by {@link mutation} — the Svelte counterpart to
|
|
86
|
+
* React's `useMutation`, re-expressed as stores you read with `$`. The surface
|
|
87
|
+
* is identical across the Lunora adapters (`@lunora/solid`, `/vue`):
|
|
88
|
+
* `data`/`error`/`pending` are readable stores and `mutate` is an awaitable.
|
|
89
|
+
*/
|
|
90
|
+
interface MutationHandle<F extends FunctionReference> {
|
|
91
|
+
/** The latest invocation's resolved value, or `undefined` before the first success. */
|
|
92
|
+
data: Readable<ReturnOf<F> | undefined>;
|
|
93
|
+
/** The latest invocation's error, or `undefined`. */
|
|
94
|
+
error: Readable<Error | undefined>;
|
|
95
|
+
/**
|
|
96
|
+
* Run the mutation. Resolves with the server result and rejects on failure
|
|
97
|
+
* (errors propagate — there is no swallowing). Optimistic updates passed in
|
|
98
|
+
* `options` are applied and rolled back by the client against the live query
|
|
99
|
+
* subscriptions, exactly as in the React adapter.
|
|
100
|
+
*/
|
|
101
|
+
mutate: (args: ArgsOf<F>, options?: MutationCallOptions<unknown, unknown, ArgsOf<F>>) => Promise<ReturnOf<F>>;
|
|
102
|
+
/**
|
|
103
|
+
* `true` while any invocation from this handle is in flight. Ref-counted, so
|
|
104
|
+
* overlapping calls compose and it only flips back to `false` once the last
|
|
105
|
+
* one settles. Read it with `$pending` in a component to disable a button.
|
|
106
|
+
*/
|
|
107
|
+
pending: Readable<boolean>;
|
|
108
|
+
/** Clear `data`/`error` back to idle. */
|
|
109
|
+
reset: () => void;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Create an optimistic {@link MutationHandle} for a mutation reference. The
|
|
113
|
+
* Svelte counterpart to React's `useMutation`: returns
|
|
114
|
+
* `{ data, error, pending, mutate, reset }` of readable stores plus an awaitable
|
|
115
|
+
* `mutate`. The ref-counted pending + error-normalize orchestration is the
|
|
116
|
+
* shared `createMutationRunner` from `@lunora/client`; only the stores are
|
|
117
|
+
* adapter-specific.
|
|
118
|
+
*
|
|
119
|
+
* Pass `client` explicitly, or omit it to resolve the ambient client published
|
|
120
|
+
* by `setLunoraClient`.
|
|
121
|
+
*/
|
|
122
|
+
declare function mutation<F extends FunctionReference>(function_: F): MutationHandle<F>;
|
|
123
|
+
declare function mutation<F extends FunctionReference>(client: LunoraClient, function_: F): MutationHandle<F>;
|
|
124
|
+
/** The args a paginated query exposes minus the framework-supplied page cursor. */
|
|
125
|
+
type PaginatedArgs<F extends FunctionReference> = Omit<ArgsOf<F>, "paginationOpts">;
|
|
126
|
+
/** The element type of the `page` array a paginated query returns. */
|
|
127
|
+
type PageItemOf<F extends FunctionReference> = ReturnOf<F> extends {
|
|
128
|
+
page: (infer T)[];
|
|
129
|
+
} ? T : unknown;
|
|
130
|
+
interface PaginatedQueryOptions {
|
|
131
|
+
/** Page size for the first page (and the default for `loadMore`). */
|
|
132
|
+
initialNumItems: number;
|
|
133
|
+
shardKey?: string;
|
|
134
|
+
}
|
|
135
|
+
interface PaginatedQueryHandle<T> {
|
|
136
|
+
/** `true` while the first page or a `loadMore` page is in flight. */
|
|
137
|
+
isLoading: Readable<boolean>;
|
|
138
|
+
/** Request the next page. A no-op unless `status === "CanLoadMore"`. */
|
|
139
|
+
loadMore: (numberItems: number) => void;
|
|
140
|
+
/** Flattened items across every loaded page, in order. */
|
|
141
|
+
results: Readable<T[]>;
|
|
142
|
+
status: Readable<PaginationStatus>;
|
|
143
|
+
}
|
|
144
|
+
interface InfiniteQueryOptions {
|
|
145
|
+
/** Page size for the first page (and the default for `fetchNextPage`). */
|
|
146
|
+
initialNumItems: number;
|
|
147
|
+
shardKey?: string;
|
|
148
|
+
}
|
|
149
|
+
interface InfiniteQueryHandle<T> {
|
|
150
|
+
/** Request the next page. A no-op unless `status === "CanLoadMore"`. */
|
|
151
|
+
fetchNextPage: (numberItems?: number) => void;
|
|
152
|
+
/** `true` when the loaded tail reports it can load another page. */
|
|
153
|
+
hasNextPage: Readable<boolean>;
|
|
154
|
+
/** `true` while a `fetchNextPage` page (beyond the first) is in flight. */
|
|
155
|
+
isFetchingNextPage: Readable<boolean>;
|
|
156
|
+
/** `true` while the first page is in flight. */
|
|
157
|
+
isLoading: Readable<boolean>;
|
|
158
|
+
/** One inner array per loaded page, in order; unresolved pages are omitted. */
|
|
159
|
+
pages: Readable<T[][]>;
|
|
160
|
+
status: Readable<PaginationStatus>;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Open a live paginated query as Svelte stores. The first page opens when
|
|
164
|
+
* called; call `loadMore(n)` to append the next page. Results are flattened
|
|
165
|
+
* across all loaded pages.
|
|
166
|
+
*
|
|
167
|
+
* Pass `client` explicitly, or omit it to resolve the ambient client from the
|
|
168
|
+
* Svelte context.
|
|
169
|
+
*/
|
|
170
|
+
declare function paginatedQuery<F extends FunctionReference>(function_: F, args: "skip" | PaginatedArgs<F>, options: PaginatedQueryOptions): PaginatedQueryHandle<PageItemOf<F>>;
|
|
171
|
+
declare function paginatedQuery<F extends FunctionReference>(client: LunoraClient, function_: F, args: "skip" | PaginatedArgs<F>, options: PaginatedQueryOptions): PaginatedQueryHandle<PageItemOf<F>>;
|
|
172
|
+
/**
|
|
173
|
+
* Open a live paginated query as Svelte stores, keeping each page as its own
|
|
174
|
+
* inner array (TanStack-Query-style `fetchNextPage` / `hasNextPage` shape).
|
|
175
|
+
*
|
|
176
|
+
* Pass `client` explicitly, or omit it to resolve the ambient client from the
|
|
177
|
+
* Svelte context.
|
|
178
|
+
*/
|
|
179
|
+
declare function infiniteQuery<F extends FunctionReference>(function_: F, args: "skip" | PaginatedArgs<F>, options: InfiniteQueryOptions): InfiniteQueryHandle<PageItemOf<F>>;
|
|
180
|
+
declare function infiniteQuery<F extends FunctionReference>(client: LunoraClient, function_: F, args: "skip" | PaginatedArgs<F>, options: InfiniteQueryOptions): InfiniteQueryHandle<PageItemOf<F>>;
|
|
181
|
+
/**
|
|
182
|
+
* `presence` — collaborative-awareness stores, the client half of the
|
|
183
|
+
* `@lunora/server` `definePresence` preset.
|
|
184
|
+
*
|
|
185
|
+
* Drives the heartbeat mutation (on call, interval, and tab re-focus) and
|
|
186
|
+
* subscribes to the live `listPresent` query for the given room.
|
|
187
|
+
*
|
|
188
|
+
* Pass `client` explicitly, or omit it to resolve the ambient client from the
|
|
189
|
+
* Svelte context.
|
|
190
|
+
*/
|
|
191
|
+
/**
|
|
192
|
+
* A heartbeat mutation reference: takes `{ roomId, sessionId, data? }`.
|
|
193
|
+
*/
|
|
194
|
+
type HeartbeatReference = FunctionReference<"mutation", {
|
|
195
|
+
data?: Record<string, unknown>;
|
|
196
|
+
roomId: string;
|
|
197
|
+
sessionId: string;
|
|
198
|
+
}>;
|
|
199
|
+
/**
|
|
200
|
+
* A listPresent query reference: takes `{ roomId }` and returns the array of
|
|
201
|
+
* present members.
|
|
202
|
+
*/
|
|
203
|
+
type ListPresentReference = FunctionReference<"query", {
|
|
204
|
+
roomId: string;
|
|
205
|
+
}>;
|
|
206
|
+
interface PresenceOptions<H extends HeartbeatReference, L extends ListPresentReference> {
|
|
207
|
+
/** Awareness blob for the first heartbeat (selection, cursor, name, color…). */
|
|
208
|
+
data?: Record<string, unknown>;
|
|
209
|
+
/** The `api.*` reference for the presence heartbeat mutation. */
|
|
210
|
+
heartbeat: H;
|
|
211
|
+
/** Heartbeat cadence in ms. Defaults to 10s. */
|
|
212
|
+
intervalMs?: number;
|
|
213
|
+
/** The `api.*` reference for the presence listPresent query. */
|
|
214
|
+
listPresent: L;
|
|
215
|
+
/**
|
|
216
|
+
* Stable id for this presence row. Defaults to a fresh per-mount id.
|
|
217
|
+
* Pass a user/connection id to control deduping across tabs.
|
|
218
|
+
*/
|
|
219
|
+
sessionId?: string;
|
|
220
|
+
/** Forwarded to the heartbeat mutation / listPresent subscription when sharding by room. */
|
|
221
|
+
shardKey?: string;
|
|
222
|
+
}
|
|
223
|
+
interface PresenceHandle<L extends ListPresentReference> {
|
|
224
|
+
/** The present members for the room. `undefined` until the first push. */
|
|
225
|
+
present: Readable<ReturnOf<L> | undefined>;
|
|
226
|
+
/** This handle's session id. */
|
|
227
|
+
sessionId: string;
|
|
228
|
+
/** Replace the awareness `data` sent with subsequent heartbeats, and heartbeat immediately. */
|
|
229
|
+
setData: (data: Record<string, unknown> | undefined) => void;
|
|
230
|
+
/** Stop all heartbeats, remove the visibility listener, and unsubscribe. Call in `onDestroy`. */
|
|
231
|
+
teardown: () => void;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Open a live presence handle.
|
|
235
|
+
*
|
|
236
|
+
* Pass `client` explicitly, or omit it to resolve the ambient client from the
|
|
237
|
+
* Svelte context (requires calling inside a component's `<script>` block or
|
|
238
|
+
* inside a function called during component initialisation).
|
|
239
|
+
*
|
|
240
|
+
* Call `teardown()` when the component is destroyed to stop heartbeats and
|
|
241
|
+
* remove the visibility listener (`onDestroy(handle.teardown)`).
|
|
242
|
+
*/
|
|
243
|
+
declare function presence<H extends HeartbeatReference, L extends ListPresentReference>(roomId: string, options: PresenceOptions<H, L>): PresenceHandle<L>;
|
|
244
|
+
declare function presence<H extends HeartbeatReference, L extends ListPresentReference>(client: LunoraClient, roomId: string, options: PresenceOptions<H, L>): PresenceHandle<L>;
|
|
245
|
+
/** Options accepted by {@link query}. */
|
|
246
|
+
interface QueryStoreOptions {
|
|
247
|
+
/** Called when the underlying subscription reports an error. */
|
|
248
|
+
onError?: SubscriptionErrorCallback;
|
|
249
|
+
/** Route to a specific shard when the target function is `.shardBy(...)`-partitioned. */
|
|
250
|
+
shardKey?: string;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* The shape held by a {@link query} store: the latest server value (`undefined`
|
|
254
|
+
* until the first response lands, mirroring React's `useQuery`).
|
|
255
|
+
*/
|
|
256
|
+
type QueryStore<F extends FunctionReference> = Readable<ReturnOf<F> | undefined>;
|
|
257
|
+
/**
|
|
258
|
+
* Open a live query as a Svelte readable store. Read it with the `$store`
|
|
259
|
+
* idiom in a component (`{$messages}`) and it stays current: a WS subscription
|
|
260
|
+
* attaches the moment the store gains its first subscriber and the value
|
|
261
|
+
* re-emits on every server delta — the Svelte equivalent of React's `useQuery`.
|
|
262
|
+
*
|
|
263
|
+
* The subscription is opened lazily (inside `readable`'s start callback, on the
|
|
264
|
+
* first `$`-read / `.subscribe()`) and torn down by the returned stop function
|
|
265
|
+
* when the last subscriber goes away — so a store that's never read opens no
|
|
266
|
+
* socket, and a component that unmounts releases its subscription. Sharing one
|
|
267
|
+
* store across several components shares a single underlying subscription
|
|
268
|
+
* (the `LunoraClient` de-dupes by `(fn, args, shardKey)`).
|
|
269
|
+
*
|
|
270
|
+
* Pass `client` explicitly, or omit it to resolve the ambient client published
|
|
271
|
+
* by `setLunoraClient` (which must therefore be called during component init,
|
|
272
|
+
* before this runs).
|
|
273
|
+
*/
|
|
274
|
+
declare function query<F extends FunctionReference>(function_: F, args: ArgsOf<F>, options?: QueryStoreOptions): QueryStore<F>;
|
|
275
|
+
declare function query<F extends FunctionReference>(client: LunoraClient, function_: F, args: ArgsOf<F>, options?: QueryStoreOptions): QueryStore<F>;
|
|
276
|
+
interface RateLimitOptions {
|
|
277
|
+
/** Clock injection for tests. Defaults to `Date.now`. */
|
|
278
|
+
now?: () => number;
|
|
279
|
+
/**
|
|
280
|
+
* Re-evaluation cadence in milliseconds while throttled, so `retryAfter`
|
|
281
|
+
* ticks down and `disabled` flips back automatically. Defaults to `1000`.
|
|
282
|
+
*/
|
|
283
|
+
tickMs?: number;
|
|
284
|
+
}
|
|
285
|
+
interface RateLimitHandle {
|
|
286
|
+
/** Would consuming `count` (default 1) succeed right now? Does not consume. */
|
|
287
|
+
check: (count?: number) => boolean;
|
|
288
|
+
/** Optimistically consume `count` (default 1) locally; mirrors the server algorithm. */
|
|
289
|
+
consume: (count?: number) => RateLimitStatus;
|
|
290
|
+
/** Readable store: `true` while a single unit cannot be consumed. */
|
|
291
|
+
disabled: Readable<boolean>;
|
|
292
|
+
/** Readable store: `true` while a single unit can be consumed. */
|
|
293
|
+
ok: Readable<boolean>;
|
|
294
|
+
/** Clear local accounting (e.g. after the server confirms a reset). */
|
|
295
|
+
reset: () => void;
|
|
296
|
+
/** Readable store: milliseconds until the next unit is available. `0` when `ok`. */
|
|
297
|
+
retryAfter: Readable<number>;
|
|
298
|
+
/** Stop the auto-tick interval. Call from `onDestroy` to prevent leaks. */
|
|
299
|
+
teardown: () => void;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Client-side mirror of a rate limit for instant UX — disable a button or show
|
|
303
|
+
* a countdown without a round-trip. It runs the same token-bucket / fixed-window
|
|
304
|
+
* math as `@lunora/ratelimit` on the server, so the prediction agrees with the
|
|
305
|
+
* authoritative check; the server remains the source of truth.
|
|
306
|
+
*
|
|
307
|
+
* `config` is read on every call; pass a stable reference (module constant).
|
|
308
|
+
*
|
|
309
|
+
* Call `teardown()` when the component is destroyed to stop the auto-tick
|
|
310
|
+
* interval (`onDestroy(handle.teardown)`).
|
|
311
|
+
*/
|
|
312
|
+
declare const rateLimit: (config: RateLimitConfig, options?: RateLimitOptions) => RateLimitHandle;
|
|
313
|
+
interface SubscriptionStoreOptions {
|
|
314
|
+
onError?: (error: Error) => void;
|
|
315
|
+
shardKey?: string;
|
|
316
|
+
}
|
|
317
|
+
interface SubscriptionHandle<T> {
|
|
318
|
+
/** Svelte readable store of the latest server-pushed value (`undefined` until the first push). */
|
|
319
|
+
data: Readable<T | undefined>;
|
|
320
|
+
/** Svelte readable store of the latest subscription error (`undefined` when healthy). */
|
|
321
|
+
error: Readable<Error | undefined>;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Create a pair of Svelte readable stores that open a live subscription
|
|
325
|
+
* against the Lunora backend. `data` updates on every server push; `error`
|
|
326
|
+
* captures the last subscription error. Both stores are lazy: the subscription
|
|
327
|
+
* opens on the first subscriber to `data` and tears down when it stops.
|
|
328
|
+
*
|
|
329
|
+
* Passing `"skip"` as `args` keeps the stores connected but the subscription
|
|
330
|
+
* dormant (`data` stays `undefined`). Pass an explicit `client` as the first
|
|
331
|
+
* argument to bypass the ambient context (useful in tests).
|
|
332
|
+
*/
|
|
333
|
+
declare function subscription<F extends FunctionReference>(function_: F, args: ArgsOf<F> | "skip", options?: SubscriptionStoreOptions): SubscriptionHandle<ReturnOf<F>>;
|
|
334
|
+
declare function subscription<F extends FunctionReference>(client: LunoraClient, function_: F, args: ArgsOf<F> | "skip", options?: SubscriptionStoreOptions): SubscriptionHandle<ReturnOf<F>>;
|
|
335
|
+
export { type AuthStore, type ConnectionStatusStore, type HeartbeatReference, type InfiniteQueryHandle, type InfiniteQueryOptions, type ListPresentReference, type MutationHandle, type PageItemOf, type PaginatedArgs, type PaginatedQueryHandle, type PaginatedQueryOptions, type PresenceHandle, type PresenceOptions, type QueryStore, type QueryStoreOptions, type RateLimitHandle, type RateLimitOptions, type SubscriptionHandle, type SubscriptionStoreOptions, auth, connectionStatus, getLunoraClient, hydratePreloaded, infiniteQuery, mutation, paginatedQuery, presence, query, rateLimit, setLunoraClient, subscription };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import { LunoraClient, User, ConnectionStatus, Preloaded, FunctionReference, ReturnOf, ArgsOf, MutationCallOptions, SubscriptionErrorCallback } from '@lunora/client';
|
|
2
|
+
export type { ArgsOf, ConnectionStatus, FunctionReference, LunoraClient, MutationCallOptions, Preloaded, ReturnOf } from '@lunora/client';
|
|
3
|
+
import { Readable } from 'svelte/store';
|
|
4
|
+
import { PaginationStatus } from '@lunora/client/pagination';
|
|
5
|
+
import { RateLimitStatus, RateLimitConfig } from '@lunora/ratelimit';
|
|
6
|
+
/**
|
|
7
|
+
* Publish a {@link LunoraClient} on the Svelte component context so that
|
|
8
|
+
* descendant components can read it with {@link getLunoraClient} (or implicitly,
|
|
9
|
+
* via the default-client lookups inside `query`/`mutation`/`hydratePreloaded`).
|
|
10
|
+
*
|
|
11
|
+
* Call this once, high in the tree (typically your root `+layout.svelte` or
|
|
12
|
+
* `App.svelte`), during component initialisation — `setContext` must run while
|
|
13
|
+
* the component is being constructed, exactly like React's provider mounts once.
|
|
14
|
+
* This is the Svelte analogue of mounting `LunoraProvider`.
|
|
15
|
+
*/
|
|
16
|
+
declare const setLunoraClient: (client: LunoraClient) => LunoraClient;
|
|
17
|
+
/**
|
|
18
|
+
* Read the {@link LunoraClient} published by {@link setLunoraClient} from the
|
|
19
|
+
* nearest ancestor. Throws if no provider is mounted, mirroring `useLunora`'s
|
|
20
|
+
* "must be used inside a LunoraProvider" guard so the failure is loud and
|
|
21
|
+
* early rather than a confusing `undefined` deref later.
|
|
22
|
+
*
|
|
23
|
+
* Must be called during component initialisation (Svelte's `getContext`
|
|
24
|
+
* constraint); the live stores returned by `query`/`hydratePreloaded` resolve
|
|
25
|
+
* the client eagerly at call time for exactly this reason.
|
|
26
|
+
*/
|
|
27
|
+
declare const getLunoraClient: () => LunoraClient;
|
|
28
|
+
interface AuthStore {
|
|
29
|
+
/** Set the auth token on the underlying `LunoraClient`. */
|
|
30
|
+
setToken: (token: string | null) => void;
|
|
31
|
+
/** Readable store of the auth token (`null` when signed out). */
|
|
32
|
+
token: Readable<string | null>;
|
|
33
|
+
/** Readable store of the resolved user (`null` when signed out or still loading). */
|
|
34
|
+
user: Readable<User | null>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Create a pair of Svelte readable stores tracking the auth token and the
|
|
38
|
+
* resolved user identity. The stores are lazy: subscriptions open on the first
|
|
39
|
+
* reader and close when the last unsubscribes. Calling `setToken(jwt)` after
|
|
40
|
+
* sign-in refreshes both stores.
|
|
41
|
+
*
|
|
42
|
+
* Pass an explicit client to bypass the ambient context (useful in tests).
|
|
43
|
+
*/
|
|
44
|
+
declare const auth: (explicitClient?: ReturnType<typeof getLunoraClient>) => AuthStore;
|
|
45
|
+
/** The shape held by a {@link connectionStatus} store: the latest aggregate live-socket status. */
|
|
46
|
+
type ConnectionStatusStore = Readable<ConnectionStatus>;
|
|
47
|
+
/**
|
|
48
|
+
* Expose the client's aggregate live-socket status as a Svelte readable store.
|
|
49
|
+
* Read it with the `$store` idiom (`{$status}`) and it stays current: the value
|
|
50
|
+
* transitions through `idle` → `connecting` → `connected` → `offline` as
|
|
51
|
+
* sockets open and drop — the Svelte equivalent of `@lunora/react`'s
|
|
52
|
+
* `useConnectionStatus`. Use it to drive a connection indicator.
|
|
53
|
+
*
|
|
54
|
+
* The status listener attaches inside `readable`'s start callback (on the first
|
|
55
|
+
* `$`-read / `.subscribe()`) and is released by the returned stop function when
|
|
56
|
+
* the last subscriber goes away, so a store that's never read attaches nothing.
|
|
57
|
+
*
|
|
58
|
+
* Pass `client` explicitly, or omit it to resolve the ambient client published
|
|
59
|
+
* by `setLunoraClient` (which must therefore be called during component init,
|
|
60
|
+
* before this runs).
|
|
61
|
+
*/
|
|
62
|
+
declare const connectionStatus: (client?: LunoraClient) => ConnectionStatusStore;
|
|
63
|
+
/**
|
|
64
|
+
* Hydrate a query store from a {@link Preloaded} token produced by
|
|
65
|
+
* `preloadQuery` during SSR, then keep it live — the reactive-loader handoff.
|
|
66
|
+
*
|
|
67
|
+
* The store is seeded **synchronously** with `preloaded.value`, so the very
|
|
68
|
+
* first read (`$store` during hydration) returns the server value with no
|
|
69
|
+
* loading flash and no hydration mismatch — there is no `undefined` window and
|
|
70
|
+
* no refetch. When the store gains its first subscriber on the client, a live
|
|
71
|
+
* WS subscription attaches and every subsequent delta re-emits, exactly like a
|
|
72
|
+
* plain `query` store. This is the Svelte equivalent of React's
|
|
73
|
+
* `usePreloadedQuery`.
|
|
74
|
+
*
|
|
75
|
+
* Pass `client` explicitly, or omit it to resolve the ambient client published
|
|
76
|
+
* by `setLunoraClient`.
|
|
77
|
+
*
|
|
78
|
+
* Note on SSR: `readable`'s start callback only runs when the store is actually
|
|
79
|
+
* subscribed (the browser), so on the server the store simply holds the seeded
|
|
80
|
+
* value and opens no socket. The token's `value` is the single source of truth
|
|
81
|
+
* for the first paint either way.
|
|
82
|
+
*/
|
|
83
|
+
declare const hydratePreloaded: <T>(preloaded: Preloaded<T>, client?: LunoraClient) => Readable<T>;
|
|
84
|
+
/**
|
|
85
|
+
* The reactive handle returned by {@link mutation} — the Svelte counterpart to
|
|
86
|
+
* React's `useMutation`, re-expressed as stores you read with `$`. The surface
|
|
87
|
+
* is identical across the Lunora adapters (`@lunora/solid`, `/vue`):
|
|
88
|
+
* `data`/`error`/`pending` are readable stores and `mutate` is an awaitable.
|
|
89
|
+
*/
|
|
90
|
+
interface MutationHandle<F extends FunctionReference> {
|
|
91
|
+
/** The latest invocation's resolved value, or `undefined` before the first success. */
|
|
92
|
+
data: Readable<ReturnOf<F> | undefined>;
|
|
93
|
+
/** The latest invocation's error, or `undefined`. */
|
|
94
|
+
error: Readable<Error | undefined>;
|
|
95
|
+
/**
|
|
96
|
+
* Run the mutation. Resolves with the server result and rejects on failure
|
|
97
|
+
* (errors propagate — there is no swallowing). Optimistic updates passed in
|
|
98
|
+
* `options` are applied and rolled back by the client against the live query
|
|
99
|
+
* subscriptions, exactly as in the React adapter.
|
|
100
|
+
*/
|
|
101
|
+
mutate: (args: ArgsOf<F>, options?: MutationCallOptions<unknown, unknown, ArgsOf<F>>) => Promise<ReturnOf<F>>;
|
|
102
|
+
/**
|
|
103
|
+
* `true` while any invocation from this handle is in flight. Ref-counted, so
|
|
104
|
+
* overlapping calls compose and it only flips back to `false` once the last
|
|
105
|
+
* one settles. Read it with `$pending` in a component to disable a button.
|
|
106
|
+
*/
|
|
107
|
+
pending: Readable<boolean>;
|
|
108
|
+
/** Clear `data`/`error` back to idle. */
|
|
109
|
+
reset: () => void;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Create an optimistic {@link MutationHandle} for a mutation reference. The
|
|
113
|
+
* Svelte counterpart to React's `useMutation`: returns
|
|
114
|
+
* `{ data, error, pending, mutate, reset }` of readable stores plus an awaitable
|
|
115
|
+
* `mutate`. The ref-counted pending + error-normalize orchestration is the
|
|
116
|
+
* shared `createMutationRunner` from `@lunora/client`; only the stores are
|
|
117
|
+
* adapter-specific.
|
|
118
|
+
*
|
|
119
|
+
* Pass `client` explicitly, or omit it to resolve the ambient client published
|
|
120
|
+
* by `setLunoraClient`.
|
|
121
|
+
*/
|
|
122
|
+
declare function mutation<F extends FunctionReference>(function_: F): MutationHandle<F>;
|
|
123
|
+
declare function mutation<F extends FunctionReference>(client: LunoraClient, function_: F): MutationHandle<F>;
|
|
124
|
+
/** The args a paginated query exposes minus the framework-supplied page cursor. */
|
|
125
|
+
type PaginatedArgs<F extends FunctionReference> = Omit<ArgsOf<F>, "paginationOpts">;
|
|
126
|
+
/** The element type of the `page` array a paginated query returns. */
|
|
127
|
+
type PageItemOf<F extends FunctionReference> = ReturnOf<F> extends {
|
|
128
|
+
page: (infer T)[];
|
|
129
|
+
} ? T : unknown;
|
|
130
|
+
interface PaginatedQueryOptions {
|
|
131
|
+
/** Page size for the first page (and the default for `loadMore`). */
|
|
132
|
+
initialNumItems: number;
|
|
133
|
+
shardKey?: string;
|
|
134
|
+
}
|
|
135
|
+
interface PaginatedQueryHandle<T> {
|
|
136
|
+
/** `true` while the first page or a `loadMore` page is in flight. */
|
|
137
|
+
isLoading: Readable<boolean>;
|
|
138
|
+
/** Request the next page. A no-op unless `status === "CanLoadMore"`. */
|
|
139
|
+
loadMore: (numberItems: number) => void;
|
|
140
|
+
/** Flattened items across every loaded page, in order. */
|
|
141
|
+
results: Readable<T[]>;
|
|
142
|
+
status: Readable<PaginationStatus>;
|
|
143
|
+
}
|
|
144
|
+
interface InfiniteQueryOptions {
|
|
145
|
+
/** Page size for the first page (and the default for `fetchNextPage`). */
|
|
146
|
+
initialNumItems: number;
|
|
147
|
+
shardKey?: string;
|
|
148
|
+
}
|
|
149
|
+
interface InfiniteQueryHandle<T> {
|
|
150
|
+
/** Request the next page. A no-op unless `status === "CanLoadMore"`. */
|
|
151
|
+
fetchNextPage: (numberItems?: number) => void;
|
|
152
|
+
/** `true` when the loaded tail reports it can load another page. */
|
|
153
|
+
hasNextPage: Readable<boolean>;
|
|
154
|
+
/** `true` while a `fetchNextPage` page (beyond the first) is in flight. */
|
|
155
|
+
isFetchingNextPage: Readable<boolean>;
|
|
156
|
+
/** `true` while the first page is in flight. */
|
|
157
|
+
isLoading: Readable<boolean>;
|
|
158
|
+
/** One inner array per loaded page, in order; unresolved pages are omitted. */
|
|
159
|
+
pages: Readable<T[][]>;
|
|
160
|
+
status: Readable<PaginationStatus>;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Open a live paginated query as Svelte stores. The first page opens when
|
|
164
|
+
* called; call `loadMore(n)` to append the next page. Results are flattened
|
|
165
|
+
* across all loaded pages.
|
|
166
|
+
*
|
|
167
|
+
* Pass `client` explicitly, or omit it to resolve the ambient client from the
|
|
168
|
+
* Svelte context.
|
|
169
|
+
*/
|
|
170
|
+
declare function paginatedQuery<F extends FunctionReference>(function_: F, args: "skip" | PaginatedArgs<F>, options: PaginatedQueryOptions): PaginatedQueryHandle<PageItemOf<F>>;
|
|
171
|
+
declare function paginatedQuery<F extends FunctionReference>(client: LunoraClient, function_: F, args: "skip" | PaginatedArgs<F>, options: PaginatedQueryOptions): PaginatedQueryHandle<PageItemOf<F>>;
|
|
172
|
+
/**
|
|
173
|
+
* Open a live paginated query as Svelte stores, keeping each page as its own
|
|
174
|
+
* inner array (TanStack-Query-style `fetchNextPage` / `hasNextPage` shape).
|
|
175
|
+
*
|
|
176
|
+
* Pass `client` explicitly, or omit it to resolve the ambient client from the
|
|
177
|
+
* Svelte context.
|
|
178
|
+
*/
|
|
179
|
+
declare function infiniteQuery<F extends FunctionReference>(function_: F, args: "skip" | PaginatedArgs<F>, options: InfiniteQueryOptions): InfiniteQueryHandle<PageItemOf<F>>;
|
|
180
|
+
declare function infiniteQuery<F extends FunctionReference>(client: LunoraClient, function_: F, args: "skip" | PaginatedArgs<F>, options: InfiniteQueryOptions): InfiniteQueryHandle<PageItemOf<F>>;
|
|
181
|
+
/**
|
|
182
|
+
* `presence` — collaborative-awareness stores, the client half of the
|
|
183
|
+
* `@lunora/server` `definePresence` preset.
|
|
184
|
+
*
|
|
185
|
+
* Drives the heartbeat mutation (on call, interval, and tab re-focus) and
|
|
186
|
+
* subscribes to the live `listPresent` query for the given room.
|
|
187
|
+
*
|
|
188
|
+
* Pass `client` explicitly, or omit it to resolve the ambient client from the
|
|
189
|
+
* Svelte context.
|
|
190
|
+
*/
|
|
191
|
+
/**
|
|
192
|
+
* A heartbeat mutation reference: takes `{ roomId, sessionId, data? }`.
|
|
193
|
+
*/
|
|
194
|
+
type HeartbeatReference = FunctionReference<"mutation", {
|
|
195
|
+
data?: Record<string, unknown>;
|
|
196
|
+
roomId: string;
|
|
197
|
+
sessionId: string;
|
|
198
|
+
}>;
|
|
199
|
+
/**
|
|
200
|
+
* A listPresent query reference: takes `{ roomId }` and returns the array of
|
|
201
|
+
* present members.
|
|
202
|
+
*/
|
|
203
|
+
type ListPresentReference = FunctionReference<"query", {
|
|
204
|
+
roomId: string;
|
|
205
|
+
}>;
|
|
206
|
+
interface PresenceOptions<H extends HeartbeatReference, L extends ListPresentReference> {
|
|
207
|
+
/** Awareness blob for the first heartbeat (selection, cursor, name, color…). */
|
|
208
|
+
data?: Record<string, unknown>;
|
|
209
|
+
/** The `api.*` reference for the presence heartbeat mutation. */
|
|
210
|
+
heartbeat: H;
|
|
211
|
+
/** Heartbeat cadence in ms. Defaults to 10s. */
|
|
212
|
+
intervalMs?: number;
|
|
213
|
+
/** The `api.*` reference for the presence listPresent query. */
|
|
214
|
+
listPresent: L;
|
|
215
|
+
/**
|
|
216
|
+
* Stable id for this presence row. Defaults to a fresh per-mount id.
|
|
217
|
+
* Pass a user/connection id to control deduping across tabs.
|
|
218
|
+
*/
|
|
219
|
+
sessionId?: string;
|
|
220
|
+
/** Forwarded to the heartbeat mutation / listPresent subscription when sharding by room. */
|
|
221
|
+
shardKey?: string;
|
|
222
|
+
}
|
|
223
|
+
interface PresenceHandle<L extends ListPresentReference> {
|
|
224
|
+
/** The present members for the room. `undefined` until the first push. */
|
|
225
|
+
present: Readable<ReturnOf<L> | undefined>;
|
|
226
|
+
/** This handle's session id. */
|
|
227
|
+
sessionId: string;
|
|
228
|
+
/** Replace the awareness `data` sent with subsequent heartbeats, and heartbeat immediately. */
|
|
229
|
+
setData: (data: Record<string, unknown> | undefined) => void;
|
|
230
|
+
/** Stop all heartbeats, remove the visibility listener, and unsubscribe. Call in `onDestroy`. */
|
|
231
|
+
teardown: () => void;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Open a live presence handle.
|
|
235
|
+
*
|
|
236
|
+
* Pass `client` explicitly, or omit it to resolve the ambient client from the
|
|
237
|
+
* Svelte context (requires calling inside a component's `<script>` block or
|
|
238
|
+
* inside a function called during component initialisation).
|
|
239
|
+
*
|
|
240
|
+
* Call `teardown()` when the component is destroyed to stop heartbeats and
|
|
241
|
+
* remove the visibility listener (`onDestroy(handle.teardown)`).
|
|
242
|
+
*/
|
|
243
|
+
declare function presence<H extends HeartbeatReference, L extends ListPresentReference>(roomId: string, options: PresenceOptions<H, L>): PresenceHandle<L>;
|
|
244
|
+
declare function presence<H extends HeartbeatReference, L extends ListPresentReference>(client: LunoraClient, roomId: string, options: PresenceOptions<H, L>): PresenceHandle<L>;
|
|
245
|
+
/** Options accepted by {@link query}. */
|
|
246
|
+
interface QueryStoreOptions {
|
|
247
|
+
/** Called when the underlying subscription reports an error. */
|
|
248
|
+
onError?: SubscriptionErrorCallback;
|
|
249
|
+
/** Route to a specific shard when the target function is `.shardBy(...)`-partitioned. */
|
|
250
|
+
shardKey?: string;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* The shape held by a {@link query} store: the latest server value (`undefined`
|
|
254
|
+
* until the first response lands, mirroring React's `useQuery`).
|
|
255
|
+
*/
|
|
256
|
+
type QueryStore<F extends FunctionReference> = Readable<ReturnOf<F> | undefined>;
|
|
257
|
+
/**
|
|
258
|
+
* Open a live query as a Svelte readable store. Read it with the `$store`
|
|
259
|
+
* idiom in a component (`{$messages}`) and it stays current: a WS subscription
|
|
260
|
+
* attaches the moment the store gains its first subscriber and the value
|
|
261
|
+
* re-emits on every server delta — the Svelte equivalent of React's `useQuery`.
|
|
262
|
+
*
|
|
263
|
+
* The subscription is opened lazily (inside `readable`'s start callback, on the
|
|
264
|
+
* first `$`-read / `.subscribe()`) and torn down by the returned stop function
|
|
265
|
+
* when the last subscriber goes away — so a store that's never read opens no
|
|
266
|
+
* socket, and a component that unmounts releases its subscription. Sharing one
|
|
267
|
+
* store across several components shares a single underlying subscription
|
|
268
|
+
* (the `LunoraClient` de-dupes by `(fn, args, shardKey)`).
|
|
269
|
+
*
|
|
270
|
+
* Pass `client` explicitly, or omit it to resolve the ambient client published
|
|
271
|
+
* by `setLunoraClient` (which must therefore be called during component init,
|
|
272
|
+
* before this runs).
|
|
273
|
+
*/
|
|
274
|
+
declare function query<F extends FunctionReference>(function_: F, args: ArgsOf<F>, options?: QueryStoreOptions): QueryStore<F>;
|
|
275
|
+
declare function query<F extends FunctionReference>(client: LunoraClient, function_: F, args: ArgsOf<F>, options?: QueryStoreOptions): QueryStore<F>;
|
|
276
|
+
interface RateLimitOptions {
|
|
277
|
+
/** Clock injection for tests. Defaults to `Date.now`. */
|
|
278
|
+
now?: () => number;
|
|
279
|
+
/**
|
|
280
|
+
* Re-evaluation cadence in milliseconds while throttled, so `retryAfter`
|
|
281
|
+
* ticks down and `disabled` flips back automatically. Defaults to `1000`.
|
|
282
|
+
*/
|
|
283
|
+
tickMs?: number;
|
|
284
|
+
}
|
|
285
|
+
interface RateLimitHandle {
|
|
286
|
+
/** Would consuming `count` (default 1) succeed right now? Does not consume. */
|
|
287
|
+
check: (count?: number) => boolean;
|
|
288
|
+
/** Optimistically consume `count` (default 1) locally; mirrors the server algorithm. */
|
|
289
|
+
consume: (count?: number) => RateLimitStatus;
|
|
290
|
+
/** Readable store: `true` while a single unit cannot be consumed. */
|
|
291
|
+
disabled: Readable<boolean>;
|
|
292
|
+
/** Readable store: `true` while a single unit can be consumed. */
|
|
293
|
+
ok: Readable<boolean>;
|
|
294
|
+
/** Clear local accounting (e.g. after the server confirms a reset). */
|
|
295
|
+
reset: () => void;
|
|
296
|
+
/** Readable store: milliseconds until the next unit is available. `0` when `ok`. */
|
|
297
|
+
retryAfter: Readable<number>;
|
|
298
|
+
/** Stop the auto-tick interval. Call from `onDestroy` to prevent leaks. */
|
|
299
|
+
teardown: () => void;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Client-side mirror of a rate limit for instant UX — disable a button or show
|
|
303
|
+
* a countdown without a round-trip. It runs the same token-bucket / fixed-window
|
|
304
|
+
* math as `@lunora/ratelimit` on the server, so the prediction agrees with the
|
|
305
|
+
* authoritative check; the server remains the source of truth.
|
|
306
|
+
*
|
|
307
|
+
* `config` is read on every call; pass a stable reference (module constant).
|
|
308
|
+
*
|
|
309
|
+
* Call `teardown()` when the component is destroyed to stop the auto-tick
|
|
310
|
+
* interval (`onDestroy(handle.teardown)`).
|
|
311
|
+
*/
|
|
312
|
+
declare const rateLimit: (config: RateLimitConfig, options?: RateLimitOptions) => RateLimitHandle;
|
|
313
|
+
interface SubscriptionStoreOptions {
|
|
314
|
+
onError?: (error: Error) => void;
|
|
315
|
+
shardKey?: string;
|
|
316
|
+
}
|
|
317
|
+
interface SubscriptionHandle<T> {
|
|
318
|
+
/** Svelte readable store of the latest server-pushed value (`undefined` until the first push). */
|
|
319
|
+
data: Readable<T | undefined>;
|
|
320
|
+
/** Svelte readable store of the latest subscription error (`undefined` when healthy). */
|
|
321
|
+
error: Readable<Error | undefined>;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Create a pair of Svelte readable stores that open a live subscription
|
|
325
|
+
* against the Lunora backend. `data` updates on every server push; `error`
|
|
326
|
+
* captures the last subscription error. Both stores are lazy: the subscription
|
|
327
|
+
* opens on the first subscriber to `data` and tears down when it stops.
|
|
328
|
+
*
|
|
329
|
+
* Passing `"skip"` as `args` keeps the stores connected but the subscription
|
|
330
|
+
* dormant (`data` stays `undefined`). Pass an explicit `client` as the first
|
|
331
|
+
* argument to bypass the ambient context (useful in tests).
|
|
332
|
+
*/
|
|
333
|
+
declare function subscription<F extends FunctionReference>(function_: F, args: ArgsOf<F> | "skip", options?: SubscriptionStoreOptions): SubscriptionHandle<ReturnOf<F>>;
|
|
334
|
+
declare function subscription<F extends FunctionReference>(client: LunoraClient, function_: F, args: ArgsOf<F> | "skip", options?: SubscriptionStoreOptions): SubscriptionHandle<ReturnOf<F>>;
|
|
335
|
+
export { type AuthStore, type ConnectionStatusStore, type HeartbeatReference, type InfiniteQueryHandle, type InfiniteQueryOptions, type ListPresentReference, type MutationHandle, type PageItemOf, type PaginatedArgs, type PaginatedQueryHandle, type PaginatedQueryOptions, type PresenceHandle, type PresenceOptions, type QueryStore, type QueryStoreOptions, type RateLimitHandle, type RateLimitOptions, type SubscriptionHandle, type SubscriptionStoreOptions, auth, connectionStatus, getLunoraClient, hydratePreloaded, infiniteQuery, mutation, paginatedQuery, presence, query, rateLimit, setLunoraClient, subscription };
|