@lunora/client 0.0.0 → 1.0.0-alpha.2
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 +111 -9
- package/__assets__/package-og.svg +14 -0
- package/dist/auth/index.d.mts +20 -0
- package/dist/auth/index.d.ts +20 -0
- package/dist/auth/index.mjs +60 -0
- package/dist/index.d.mts +281 -0
- package/dist/index.d.ts +281 -0
- package/dist/index.mjs +14 -0
- package/dist/packem_shared/CONFLICT_ERROR_CODE-aUdVbEDw.mjs +4 -0
- package/dist/packem_shared/DEFAULT_MAX_BUFFER-BDkqO5PW.mjs +107 -0
- package/dist/packem_shared/LunoraClient-UiULzH_1.mjs +2165 -0
- package/dist/packem_shared/OfflineQueue-D5p_QgF_.mjs +127 -0
- package/dist/packem_shared/SKIP-vItZChkw.mjs +50 -0
- package/dist/packem_shared/SubscriptionRegistry-B-Qx_Gux.mjs +26 -0
- package/dist/packem_shared/applyDelta-4jFGTPA3.mjs +61 -0
- package/dist/packem_shared/createAsyncStoragePersistence-1Z5BZ8RC.mjs +45 -0
- package/dist/packem_shared/createInMemoryBookmarkStorage-BoN7a7TH.mjs +11 -0
- package/dist/packem_shared/createInMemoryPersistence-CW82inU5.mjs +105 -0
- package/dist/packem_shared/createInMemoryQueryCache-B1PQ9Twl.mjs +138 -0
- package/dist/packem_shared/createLocalStore-DSUfoLqY.mjs +36 -0
- package/dist/packem_shared/createMutationRunner-BqsavzvG.mjs +21 -0
- package/dist/packem_shared/createReconnect-Di_-oHH7.mjs +22 -0
- package/dist/packem_shared/createServerClient-BjZc3gD8.mjs +11 -0
- package/dist/packem_shared/deserializePreloaded-C0eJTY_W.mjs +4 -0
- package/dist/packem_shared/getServerSession-8jXewqxd.mjs +13 -0
- package/dist/packem_shared/lunora-client.d-DGvyuJ_p.d.mts +1597 -0
- package/dist/packem_shared/lunora-client.d-DGvyuJ_p.d.ts +1597 -0
- package/dist/packem_shared/preload.d-BoDmFqSG.d.ts +20 -0
- package/dist/packem_shared/preload.d-dSaRMuhL.d.mts +20 -0
- package/dist/packem_shared/preloadQuery-lobFkD2Z.mjs +13 -0
- package/dist/pagination/index.d.mts +82 -0
- package/dist/pagination/index.d.ts +82 -0
- package/dist/pagination/index.mjs +61 -0
- package/dist/query/index.d.mts +62 -0
- package/dist/query/index.d.ts +62 -0
- package/dist/query/index.mjs +1 -0
- package/dist/ssr/index.d.mts +115 -0
- package/dist/ssr/index.d.ts +115 -0
- package/dist/ssr/index.mjs +4 -0
- package/package.json +53 -17
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { F as FunctionReference, L as LunoraClient, A as ArgsOf, R as ReturnOf, P as Preloaded } from "./lunora-client.d-DGvyuJ_p.js";
|
|
2
|
+
/**
|
|
3
|
+
* Run a query once on the server (during SSR) and capture its result in a
|
|
4
|
+
* serializable {@link Preloaded} token. Embed the token in the rendered HTML and
|
|
5
|
+
* pass it to `usePreloadedQuery` on the client: the first client render shows
|
|
6
|
+
* the server value with no loading flash, then a live subscription takes over.
|
|
7
|
+
*
|
|
8
|
+
* The query is executed through the supplied {@link LunoraClient} over the same
|
|
9
|
+
* HTTP RPC path the browser uses, so the SSR client only needs a `fetch`
|
|
10
|
+
* implementation that can reach the worker — no in-process Durable Object access.
|
|
11
|
+
*/
|
|
12
|
+
declare const preloadQuery: <F extends FunctionReference>(client: LunoraClient, function_: F, args: ArgsOf<F>, options?: {
|
|
13
|
+
shardKey?: string;
|
|
14
|
+
}) => Promise<Preloaded<ReturnOf<F>>>;
|
|
15
|
+
/**
|
|
16
|
+
* Read the captured value out of a {@link Preloaded} token without subscribing.
|
|
17
|
+
* Useful on the server (or in tests) when you only need the data, not a live feed.
|
|
18
|
+
*/
|
|
19
|
+
declare const preloadedQueryResult: <T>(preloaded: Preloaded<T>) => T;
|
|
20
|
+
export { preloadedQueryResult as a, preloadQuery as p };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { F as FunctionReference, L as LunoraClient, A as ArgsOf, R as ReturnOf, P as Preloaded } from "./lunora-client.d-DGvyuJ_p.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* Run a query once on the server (during SSR) and capture its result in a
|
|
4
|
+
* serializable {@link Preloaded} token. Embed the token in the rendered HTML and
|
|
5
|
+
* pass it to `usePreloadedQuery` on the client: the first client render shows
|
|
6
|
+
* the server value with no loading flash, then a live subscription takes over.
|
|
7
|
+
*
|
|
8
|
+
* The query is executed through the supplied {@link LunoraClient} over the same
|
|
9
|
+
* HTTP RPC path the browser uses, so the SSR client only needs a `fetch`
|
|
10
|
+
* implementation that can reach the worker — no in-process Durable Object access.
|
|
11
|
+
*/
|
|
12
|
+
declare const preloadQuery: <F extends FunctionReference>(client: LunoraClient, function_: F, args: ArgsOf<F>, options?: {
|
|
13
|
+
shardKey?: string;
|
|
14
|
+
}) => Promise<Preloaded<ReturnOf<F>>>;
|
|
15
|
+
/**
|
|
16
|
+
* Read the captured value out of a {@link Preloaded} token without subscribing.
|
|
17
|
+
* Useful on the server (or in tests) when you only need the data, not a live feed.
|
|
18
|
+
*/
|
|
19
|
+
declare const preloadedQueryResult: <T>(preloaded: Preloaded<T>) => T;
|
|
20
|
+
export { preloadedQueryResult as a, preloadQuery as p };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const preloadQuery = async (client, function_, args, options = {}) => {
|
|
2
|
+
const value = await client.query(function_, args, options);
|
|
3
|
+
return {
|
|
4
|
+
__lunoraPreloaded: true,
|
|
5
|
+
args: args ?? {},
|
|
6
|
+
functionPath: function_.__lunoraRef,
|
|
7
|
+
shardKey: options.shardKey,
|
|
8
|
+
value
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
const preloadedQueryResult = (preloaded) => preloaded.value;
|
|
12
|
+
|
|
13
|
+
export { preloadQuery, preloadedQueryResult };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@lunora/client/pagination` — the framework-agnostic pagination state machine
|
|
3
|
+
* shared by every Lunora UI adapter (React, Vue, Svelte, Solid).
|
|
4
|
+
*
|
|
5
|
+
* Owns cursor tracking, page-size rebalancing (split/join), `initialPages`,
|
|
6
|
+
* `rebalance`, and the shared types (`Page`, `PaginationResult`,
|
|
7
|
+
* `PaginationStatus`, `PaginatedCoreResult`). Nothing here imports a UI
|
|
8
|
+
* framework — each adapter wires the pure functions into its own reactive
|
|
9
|
+
* primitives.
|
|
10
|
+
*/
|
|
11
|
+
/** Grow factor: a bounded page is split when it exceeds this multiple of its target size. */
|
|
12
|
+
declare const SPLIT_FACTOR = 2;
|
|
13
|
+
/** Shrink factor: a bounded page with a neighbour is joined when it falls below this multiple of its target size. */
|
|
14
|
+
declare const JOIN_FACTOR = .5;
|
|
15
|
+
/** A loaded page: a fixed `(lower, upper]` range plus the size it targets. */
|
|
16
|
+
interface Page {
|
|
17
|
+
lower: null | string;
|
|
18
|
+
numItems: number;
|
|
19
|
+
upper: null | string;
|
|
20
|
+
}
|
|
21
|
+
/** One page returned by a paginated query — the shape `.paginate()` yields. */
|
|
22
|
+
interface PaginationResult<T = unknown> {
|
|
23
|
+
continueCursor: null | string;
|
|
24
|
+
isDone: boolean;
|
|
25
|
+
page: T[];
|
|
26
|
+
/**
|
|
27
|
+
* Reactive-pagination only: the midpoint cursor of a bounded
|
|
28
|
+
* `(cursor, endCursor]` page, used to split an over-grown page into two
|
|
29
|
+
* adjacent ranges. Absent on legacy (open-ended) pages.
|
|
30
|
+
*/
|
|
31
|
+
splitCursor?: null | string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Lifecycle of a `usePaginatedQuery` feed.
|
|
35
|
+
*
|
|
36
|
+
* - `LoadingFirstPage` — the first page is in flight; `results` is empty.
|
|
37
|
+
* - `CanLoadMore` — the loaded tail has a cursor; calling `loadMore` fetches the next page.
|
|
38
|
+
* - `LoadingMore` — a `loadMore` page is in flight; earlier results stay visible.
|
|
39
|
+
* - `Exhausted` — every page has loaded and the server reported `isDone`.
|
|
40
|
+
*/
|
|
41
|
+
type PaginationStatus = "CanLoadMore" | "Exhausted" | "LoadingFirstPage" | "LoadingMore";
|
|
42
|
+
interface PaginatedCoreResult<T> {
|
|
43
|
+
/** Request another page off the open-ended tail. A no-op unless `status === "CanLoadMore"`. */
|
|
44
|
+
loadMore: (numberItems: number) => void;
|
|
45
|
+
/** Per-page resolved results in order; entries are `undefined` until a page resolves. */
|
|
46
|
+
pageResults: (PaginationResult<T> | undefined)[];
|
|
47
|
+
status: PaginationStatus;
|
|
48
|
+
}
|
|
49
|
+
/** First-page seed: a single open-ended range starting at the feed head. */
|
|
50
|
+
declare const initialPages: (numberItems: number) => Page[];
|
|
51
|
+
/**
|
|
52
|
+
* Run the SPLIT/JOIN maintenance pass over the current page list given freshly
|
|
53
|
+
* resolved results. Returns a new page list when a boundary changed, or
|
|
54
|
+
* `undefined` when the layout is already balanced (so the caller can skip a
|
|
55
|
+
* setState).
|
|
56
|
+
*
|
|
57
|
+
* Only ONE structural edit is applied per pass (the first split or join found),
|
|
58
|
+
* letting the subsequent re-render's resolved results drive the next pass — this
|
|
59
|
+
* keeps each transition observable and avoids reasoning about several
|
|
60
|
+
* simultaneous boundary moves.
|
|
61
|
+
*/
|
|
62
|
+
declare const rebalance: (pages: Page[], results: (PaginationResult | undefined)[]) => Page[] | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Derive the feed `status` and the next-page cursor from the current page list
|
|
65
|
+
* and resolved page results. Framework adapters call this each render/effect to
|
|
66
|
+
* compute what to expose to callers.
|
|
67
|
+
*/
|
|
68
|
+
declare const derivePaginationStatus: <T>(skipped: boolean, pageResults: (PaginationResult<T> | undefined)[]) => {
|
|
69
|
+
nextCursor: null | string | undefined;
|
|
70
|
+
status: PaginationStatus;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Apply a `loadMore` to the current page list. Pins the open-ended tail at
|
|
74
|
+
* `cursor` (making it a fixed bounded range) and appends a fresh open-ended
|
|
75
|
+
* page starting at `cursor`. The shared boundary keeps the feed gap- and
|
|
76
|
+
* dup-free.
|
|
77
|
+
*
|
|
78
|
+
* Returns the new page list, or `undefined` when the given `cursor` is not
|
|
79
|
+
* valid (null or undefined — caller should no-op).
|
|
80
|
+
*/
|
|
81
|
+
declare const applyLoadMore: (pages: Page[], cursor: null | string | undefined, numberItems: number) => Page[] | undefined;
|
|
82
|
+
export { JOIN_FACTOR, type Page, type PaginatedCoreResult, type PaginationResult, type PaginationStatus, SPLIT_FACTOR, applyLoadMore, derivePaginationStatus, initialPages, rebalance };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@lunora/client/pagination` — the framework-agnostic pagination state machine
|
|
3
|
+
* shared by every Lunora UI adapter (React, Vue, Svelte, Solid).
|
|
4
|
+
*
|
|
5
|
+
* Owns cursor tracking, page-size rebalancing (split/join), `initialPages`,
|
|
6
|
+
* `rebalance`, and the shared types (`Page`, `PaginationResult`,
|
|
7
|
+
* `PaginationStatus`, `PaginatedCoreResult`). Nothing here imports a UI
|
|
8
|
+
* framework — each adapter wires the pure functions into its own reactive
|
|
9
|
+
* primitives.
|
|
10
|
+
*/
|
|
11
|
+
/** Grow factor: a bounded page is split when it exceeds this multiple of its target size. */
|
|
12
|
+
declare const SPLIT_FACTOR = 2;
|
|
13
|
+
/** Shrink factor: a bounded page with a neighbour is joined when it falls below this multiple of its target size. */
|
|
14
|
+
declare const JOIN_FACTOR = .5;
|
|
15
|
+
/** A loaded page: a fixed `(lower, upper]` range plus the size it targets. */
|
|
16
|
+
interface Page {
|
|
17
|
+
lower: null | string;
|
|
18
|
+
numItems: number;
|
|
19
|
+
upper: null | string;
|
|
20
|
+
}
|
|
21
|
+
/** One page returned by a paginated query — the shape `.paginate()` yields. */
|
|
22
|
+
interface PaginationResult<T = unknown> {
|
|
23
|
+
continueCursor: null | string;
|
|
24
|
+
isDone: boolean;
|
|
25
|
+
page: T[];
|
|
26
|
+
/**
|
|
27
|
+
* Reactive-pagination only: the midpoint cursor of a bounded
|
|
28
|
+
* `(cursor, endCursor]` page, used to split an over-grown page into two
|
|
29
|
+
* adjacent ranges. Absent on legacy (open-ended) pages.
|
|
30
|
+
*/
|
|
31
|
+
splitCursor?: null | string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Lifecycle of a `usePaginatedQuery` feed.
|
|
35
|
+
*
|
|
36
|
+
* - `LoadingFirstPage` — the first page is in flight; `results` is empty.
|
|
37
|
+
* - `CanLoadMore` — the loaded tail has a cursor; calling `loadMore` fetches the next page.
|
|
38
|
+
* - `LoadingMore` — a `loadMore` page is in flight; earlier results stay visible.
|
|
39
|
+
* - `Exhausted` — every page has loaded and the server reported `isDone`.
|
|
40
|
+
*/
|
|
41
|
+
type PaginationStatus = "CanLoadMore" | "Exhausted" | "LoadingFirstPage" | "LoadingMore";
|
|
42
|
+
interface PaginatedCoreResult<T> {
|
|
43
|
+
/** Request another page off the open-ended tail. A no-op unless `status === "CanLoadMore"`. */
|
|
44
|
+
loadMore: (numberItems: number) => void;
|
|
45
|
+
/** Per-page resolved results in order; entries are `undefined` until a page resolves. */
|
|
46
|
+
pageResults: (PaginationResult<T> | undefined)[];
|
|
47
|
+
status: PaginationStatus;
|
|
48
|
+
}
|
|
49
|
+
/** First-page seed: a single open-ended range starting at the feed head. */
|
|
50
|
+
declare const initialPages: (numberItems: number) => Page[];
|
|
51
|
+
/**
|
|
52
|
+
* Run the SPLIT/JOIN maintenance pass over the current page list given freshly
|
|
53
|
+
* resolved results. Returns a new page list when a boundary changed, or
|
|
54
|
+
* `undefined` when the layout is already balanced (so the caller can skip a
|
|
55
|
+
* setState).
|
|
56
|
+
*
|
|
57
|
+
* Only ONE structural edit is applied per pass (the first split or join found),
|
|
58
|
+
* letting the subsequent re-render's resolved results drive the next pass — this
|
|
59
|
+
* keeps each transition observable and avoids reasoning about several
|
|
60
|
+
* simultaneous boundary moves.
|
|
61
|
+
*/
|
|
62
|
+
declare const rebalance: (pages: Page[], results: (PaginationResult | undefined)[]) => Page[] | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Derive the feed `status` and the next-page cursor from the current page list
|
|
65
|
+
* and resolved page results. Framework adapters call this each render/effect to
|
|
66
|
+
* compute what to expose to callers.
|
|
67
|
+
*/
|
|
68
|
+
declare const derivePaginationStatus: <T>(skipped: boolean, pageResults: (PaginationResult<T> | undefined)[]) => {
|
|
69
|
+
nextCursor: null | string | undefined;
|
|
70
|
+
status: PaginationStatus;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Apply a `loadMore` to the current page list. Pins the open-ended tail at
|
|
74
|
+
* `cursor` (making it a fixed bounded range) and appends a fresh open-ended
|
|
75
|
+
* page starting at `cursor`. The shared boundary keeps the feed gap- and
|
|
76
|
+
* dup-free.
|
|
77
|
+
*
|
|
78
|
+
* Returns the new page list, or `undefined` when the given `cursor` is not
|
|
79
|
+
* valid (null or undefined — caller should no-op).
|
|
80
|
+
*/
|
|
81
|
+
declare const applyLoadMore: (pages: Page[], cursor: null | string | undefined, numberItems: number) => Page[] | undefined;
|
|
82
|
+
export { JOIN_FACTOR, type Page, type PaginatedCoreResult, type PaginationResult, type PaginationStatus, SPLIT_FACTOR, applyLoadMore, derivePaginationStatus, initialPages, rebalance };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const SPLIT_FACTOR = 2;
|
|
2
|
+
const JOIN_FACTOR = 0.5;
|
|
3
|
+
const initialPages = (numberItems) => [
|
|
4
|
+
// eslint-disable-next-line unicorn/no-null -- `lower: null` is the feed head, `upper: null` the open-ended tail — both are wire-shape cursors.
|
|
5
|
+
{ lower: null, numItems: numberItems, upper: null }
|
|
6
|
+
];
|
|
7
|
+
const rebalance = (pages, results) => {
|
|
8
|
+
for (const [index, page] of pages.entries()) {
|
|
9
|
+
if (page.upper === null) {
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
const result = results[index];
|
|
13
|
+
if (!result) {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
const size = result.page.length;
|
|
17
|
+
if (size > SPLIT_FACTOR * page.numItems && result.splitCursor) {
|
|
18
|
+
const split = result.splitCursor;
|
|
19
|
+
const next = [...pages];
|
|
20
|
+
next.splice(index, 1, { lower: page.lower, numItems: page.numItems, upper: split }, { lower: split, numItems: page.numItems, upper: page.upper });
|
|
21
|
+
return next;
|
|
22
|
+
}
|
|
23
|
+
if (size < JOIN_FACTOR * page.numItems && index + 1 < pages.length) {
|
|
24
|
+
const neighbour = pages[index + 1];
|
|
25
|
+
if (!neighbour) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const next = [...pages];
|
|
29
|
+
next.splice(index, 2, { lower: page.lower, numItems: page.numItems, upper: neighbour.upper });
|
|
30
|
+
return next;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return void 0;
|
|
34
|
+
};
|
|
35
|
+
const derivePaginationStatus = (skipped, pageResults) => {
|
|
36
|
+
if (skipped || !pageResults[0]) {
|
|
37
|
+
return { nextCursor: void 0, status: "LoadingFirstPage" };
|
|
38
|
+
}
|
|
39
|
+
const tail = pageResults.at(-1);
|
|
40
|
+
if (!tail) {
|
|
41
|
+
return { nextCursor: void 0, status: "LoadingMore" };
|
|
42
|
+
}
|
|
43
|
+
if (tail.isDone || tail.continueCursor === null) {
|
|
44
|
+
return { nextCursor: void 0, status: "Exhausted" };
|
|
45
|
+
}
|
|
46
|
+
return { nextCursor: tail.continueCursor, status: "CanLoadMore" };
|
|
47
|
+
};
|
|
48
|
+
const applyLoadMore = (pages, cursor, numberItems) => {
|
|
49
|
+
if (cursor === void 0 || cursor === null) {
|
|
50
|
+
return void 0;
|
|
51
|
+
}
|
|
52
|
+
const next = [...pages];
|
|
53
|
+
const tail = next.at(-1);
|
|
54
|
+
if (tail) {
|
|
55
|
+
next[next.length - 1] = { lower: tail.lower, numItems: tail.numItems, upper: cursor };
|
|
56
|
+
}
|
|
57
|
+
next.push({ lower: cursor, numItems: numberItems, upper: null });
|
|
58
|
+
return next;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export { JOIN_FACTOR, SPLIT_FACTOR, applyLoadMore, derivePaginationStatus, initialPages, rebalance };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { S as SubscriptionError, F as FunctionReference, A as ArgsOf, R as ReturnOf, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-DGvyuJ_p.mjs";
|
|
2
|
+
export type { b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-DGvyuJ_p.mjs";
|
|
3
|
+
import '@lunora/runtime';
|
|
4
|
+
/**
|
|
5
|
+
* The sentinel a framework adapter resolves its reactive args to when it wants
|
|
6
|
+
* to short-circuit a query — no network call, no socket.
|
|
7
|
+
*/
|
|
8
|
+
declare const SKIP: "skip";
|
|
9
|
+
/** Args after a framework has resolved its reactivity primitive, or the skip sentinel. */
|
|
10
|
+
type ResolvedArgs<F extends FunctionReference> = ArgsOf<F> | typeof SKIP;
|
|
11
|
+
/**
|
|
12
|
+
* The framework-neutral sinks a {@link createQuerySubscription} call drives. A
|
|
13
|
+
* framework adapter supplies these, wiring each into its own reactivity
|
|
14
|
+
* primitive (a TanStack cache write, a Vue `ref`, a Svelte store `set`, a Solid
|
|
15
|
+
* signal setter).
|
|
16
|
+
*
|
|
17
|
+
* `onData` fires when a fresh server value lands (the initial frame or a delta).
|
|
18
|
+
* `onError` fires when the subscription attach threw, or the server pushed a
|
|
19
|
+
* subscription-scoped error — it is optional, and when omitted an attach throw
|
|
20
|
+
* propagates to the caller (preserving the "no error channel" behaviour of
|
|
21
|
+
* adapters like Solid/Vue that never had one) rather than being swallowed.
|
|
22
|
+
* `onReset` fires when the resolved args are `"skip"`: clear any prior value.
|
|
23
|
+
*/
|
|
24
|
+
interface QuerySubscriptionSinks<T> {
|
|
25
|
+
onData: (value: T) => void;
|
|
26
|
+
onError?: (error: SubscriptionError) => void;
|
|
27
|
+
onReset?: () => void;
|
|
28
|
+
}
|
|
29
|
+
interface QuerySubscriptionOptions {
|
|
30
|
+
/** Route to a specific shard when the target function is `.shardBy(...)`-partitioned. */
|
|
31
|
+
shardKey?: string;
|
|
32
|
+
}
|
|
33
|
+
/** Normalise an unknown thrown value into the client's {@link SubscriptionError} shape. */
|
|
34
|
+
declare const toSubscriptionError: (error: unknown) => SubscriptionError;
|
|
35
|
+
/**
|
|
36
|
+
* The subscribe → snapshot → error/reset → cleanup state machine shared by
|
|
37
|
+
* every Lunora framework adapter's live-query hook.
|
|
38
|
+
*
|
|
39
|
+
* Given a `client`, a function reference, the already-resolved `args` (a
|
|
40
|
+
* framework reads its own reactive source first, then hands the plain value in),
|
|
41
|
+
* and a set of {@link QuerySubscriptionSinks}, this opens one `client.subscribe`
|
|
42
|
+
* registration and returns the {@link Unsubscribe} to tear it down. Each
|
|
43
|
+
* framework owns *when* to call this (a React effect, a Vue `watch`, a Svelte
|
|
44
|
+
* store start callback, a Solid `createEffect(on(...))`) and *where* to stash
|
|
45
|
+
* the value — this owns the lifecycle in between, so the skip-handling, the
|
|
46
|
+
* value/error fan-out, the attach-throw normalisation, and the
|
|
47
|
+
* cancellation-guarded teardown live in exactly one place.
|
|
48
|
+
*
|
|
49
|
+
* Behaviour. When `args === "skip"` it calls `sinks.onReset?.()` and returns a
|
|
50
|
+
* no-op teardown; no `client.subscribe` is issued. Otherwise it opens
|
|
51
|
+
* `client.subscribe(fn, args, …, { shardKey, onError })`: server pushes route to
|
|
52
|
+
* `sinks.onData`, and the client's own `onError` channel (a server-rejected
|
|
53
|
+
* subscription) routes to `sinks.onError` when present. The attach is wrapped —
|
|
54
|
+
* if `client.subscribe` itself throws, the error is normalised to a
|
|
55
|
+
* {@link SubscriptionError} and delivered to `sinks.onError` when present; with
|
|
56
|
+
* no `onError` sink the throw is rethrown so adapters without an error channel
|
|
57
|
+
* behave exactly as before. The returned teardown is idempotent and
|
|
58
|
+
* cancellation-guarded: once it runs, no further `onData`/`onError` from an
|
|
59
|
+
* in-flight push reaches the sinks.
|
|
60
|
+
*/
|
|
61
|
+
declare const createQuerySubscription: <F extends FunctionReference, T = ReturnOf<F>>(client: LunoraClient, function_: F, args: ResolvedArgs<F>, sinks: QuerySubscriptionSinks<T>, options?: QuerySubscriptionOptions) => Unsubscribe;
|
|
62
|
+
export { type ArgsOf, type FunctionReference, type QuerySubscriptionOptions, type QuerySubscriptionSinks, type ResolvedArgs, type ReturnOf, SKIP, type SubscriptionError, type Unsubscribe, createQuerySubscription, toSubscriptionError };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { S as SubscriptionError, F as FunctionReference, A as ArgsOf, R as ReturnOf, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-DGvyuJ_p.js";
|
|
2
|
+
export type { b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-DGvyuJ_p.js";
|
|
3
|
+
import '@lunora/runtime';
|
|
4
|
+
/**
|
|
5
|
+
* The sentinel a framework adapter resolves its reactive args to when it wants
|
|
6
|
+
* to short-circuit a query — no network call, no socket.
|
|
7
|
+
*/
|
|
8
|
+
declare const SKIP: "skip";
|
|
9
|
+
/** Args after a framework has resolved its reactivity primitive, or the skip sentinel. */
|
|
10
|
+
type ResolvedArgs<F extends FunctionReference> = ArgsOf<F> | typeof SKIP;
|
|
11
|
+
/**
|
|
12
|
+
* The framework-neutral sinks a {@link createQuerySubscription} call drives. A
|
|
13
|
+
* framework adapter supplies these, wiring each into its own reactivity
|
|
14
|
+
* primitive (a TanStack cache write, a Vue `ref`, a Svelte store `set`, a Solid
|
|
15
|
+
* signal setter).
|
|
16
|
+
*
|
|
17
|
+
* `onData` fires when a fresh server value lands (the initial frame or a delta).
|
|
18
|
+
* `onError` fires when the subscription attach threw, or the server pushed a
|
|
19
|
+
* subscription-scoped error — it is optional, and when omitted an attach throw
|
|
20
|
+
* propagates to the caller (preserving the "no error channel" behaviour of
|
|
21
|
+
* adapters like Solid/Vue that never had one) rather than being swallowed.
|
|
22
|
+
* `onReset` fires when the resolved args are `"skip"`: clear any prior value.
|
|
23
|
+
*/
|
|
24
|
+
interface QuerySubscriptionSinks<T> {
|
|
25
|
+
onData: (value: T) => void;
|
|
26
|
+
onError?: (error: SubscriptionError) => void;
|
|
27
|
+
onReset?: () => void;
|
|
28
|
+
}
|
|
29
|
+
interface QuerySubscriptionOptions {
|
|
30
|
+
/** Route to a specific shard when the target function is `.shardBy(...)`-partitioned. */
|
|
31
|
+
shardKey?: string;
|
|
32
|
+
}
|
|
33
|
+
/** Normalise an unknown thrown value into the client's {@link SubscriptionError} shape. */
|
|
34
|
+
declare const toSubscriptionError: (error: unknown) => SubscriptionError;
|
|
35
|
+
/**
|
|
36
|
+
* The subscribe → snapshot → error/reset → cleanup state machine shared by
|
|
37
|
+
* every Lunora framework adapter's live-query hook.
|
|
38
|
+
*
|
|
39
|
+
* Given a `client`, a function reference, the already-resolved `args` (a
|
|
40
|
+
* framework reads its own reactive source first, then hands the plain value in),
|
|
41
|
+
* and a set of {@link QuerySubscriptionSinks}, this opens one `client.subscribe`
|
|
42
|
+
* registration and returns the {@link Unsubscribe} to tear it down. Each
|
|
43
|
+
* framework owns *when* to call this (a React effect, a Vue `watch`, a Svelte
|
|
44
|
+
* store start callback, a Solid `createEffect(on(...))`) and *where* to stash
|
|
45
|
+
* the value — this owns the lifecycle in between, so the skip-handling, the
|
|
46
|
+
* value/error fan-out, the attach-throw normalisation, and the
|
|
47
|
+
* cancellation-guarded teardown live in exactly one place.
|
|
48
|
+
*
|
|
49
|
+
* Behaviour. When `args === "skip"` it calls `sinks.onReset?.()` and returns a
|
|
50
|
+
* no-op teardown; no `client.subscribe` is issued. Otherwise it opens
|
|
51
|
+
* `client.subscribe(fn, args, …, { shardKey, onError })`: server pushes route to
|
|
52
|
+
* `sinks.onData`, and the client's own `onError` channel (a server-rejected
|
|
53
|
+
* subscription) routes to `sinks.onError` when present. The attach is wrapped —
|
|
54
|
+
* if `client.subscribe` itself throws, the error is normalised to a
|
|
55
|
+
* {@link SubscriptionError} and delivered to `sinks.onError` when present; with
|
|
56
|
+
* no `onError` sink the throw is rethrown so adapters without an error channel
|
|
57
|
+
* behave exactly as before. The returned teardown is idempotent and
|
|
58
|
+
* cancellation-guarded: once it runs, no further `onData`/`onError` from an
|
|
59
|
+
* in-flight push reaches the sinks.
|
|
60
|
+
*/
|
|
61
|
+
declare const createQuerySubscription: <F extends FunctionReference, T = ReturnOf<F>>(client: LunoraClient, function_: F, args: ResolvedArgs<F>, sinks: QuerySubscriptionSinks<T>, options?: QuerySubscriptionOptions) => Unsubscribe;
|
|
62
|
+
export { type ArgsOf, type FunctionReference, type QuerySubscriptionOptions, type QuerySubscriptionSinks, type ResolvedArgs, type ReturnOf, SKIP, type SubscriptionError, type Unsubscribe, createQuerySubscription, toSubscriptionError };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SKIP, createQuerySubscription, toSubscriptionError } from '../packem_shared/SKIP-vItZChkw.mjs';
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-DGvyuJ_p.mjs";
|
|
2
|
+
export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/lunora-client.d-DGvyuJ_p.mjs";
|
|
3
|
+
export { p as preloadQuery, a as preloadedQueryResult } from "../packem_shared/preload.d-dSaRMuhL.mjs";
|
|
4
|
+
import '@lunora/runtime';
|
|
5
|
+
/**
|
|
6
|
+
* Structural shape of a better-auth `getSession` call's resolved value.
|
|
7
|
+
*
|
|
8
|
+
* better-auth's `auth.api.getSession({ headers })` returns `{ user, session }`
|
|
9
|
+
* when a valid session cookie is present, or `null` otherwise. We keep `user`
|
|
10
|
+
* and `session` as open records so `@lunora/client/ssr` carries no hard dependency on
|
|
11
|
+
* better-auth's concrete `User`/`Session` types — the adapter passing the real
|
|
12
|
+
* `auth` instance keeps full inference, while this package stays decoupled.
|
|
13
|
+
*/
|
|
14
|
+
interface ServerSession<User extends Record<string, unknown> = Record<string, unknown>, Session extends Record<string, unknown> = Record<string, unknown>> {
|
|
15
|
+
readonly session: Session;
|
|
16
|
+
readonly user: User;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Structural subset of a better-auth instance: just the one endpoint
|
|
20
|
+
* `getServerSession` needs. Typing it this way (rather than importing
|
|
21
|
+
* `@lunora/auth`'s `LunoraAuth`) means `@lunora/client/ssr` does not depend on
|
|
22
|
+
* better-auth internals — any object exposing `api.getSession` works, including
|
|
23
|
+
* a test stub. The concrete return type is inferred from the passed instance.
|
|
24
|
+
*/
|
|
25
|
+
interface AuthLike<Result = ServerSession | null> {
|
|
26
|
+
readonly api: {
|
|
27
|
+
getSession: (input: {
|
|
28
|
+
headers: Headers;
|
|
29
|
+
}) => Promise<Result> | Result;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Anything `getServerSession` can read request headers from: a `Request`, a
|
|
34
|
+
* `Headers` object, or a plain object exposing `headers`. SSR loaders across
|
|
35
|
+
* meta-frameworks hand back slightly different request objects, so accept the
|
|
36
|
+
* common shapes rather than forcing the caller to unwrap.
|
|
37
|
+
*/
|
|
38
|
+
type HeadersSource = Headers | Request | {
|
|
39
|
+
readonly headers: Headers;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Resolve the signed-in session from a request inside an SSR loader.
|
|
43
|
+
*
|
|
44
|
+
* Wraps `auth.api.getSession({ headers })` — the helper every meta-framework
|
|
45
|
+
* app otherwise hand-rolls — so a loader can read identity off the inbound
|
|
46
|
+
* cookies in one call. Returns `{ user, session }` when a valid session cookie
|
|
47
|
+
* is present, or `null` for anonymous requests.
|
|
48
|
+
*
|
|
49
|
+
* The `auth` parameter is structurally typed ({@link AuthLike}), so this
|
|
50
|
+
* package does not depend on better-auth internals; pass a real
|
|
51
|
+
* `@lunora/auth` instance to keep full type inference on `user`/`session`.
|
|
52
|
+
* Forward the resolved session's token to `createServerClient` to run the
|
|
53
|
+
* server-side load (and the later WS subscription) as the same identity.
|
|
54
|
+
*/
|
|
55
|
+
declare const getServerSession: <Result>(request: HeadersSource, auth: AuthLike<Result>) => Promise<NonNullable<Result> | null>;
|
|
56
|
+
/**
|
|
57
|
+
* Serialize a {@link Preloaded} token to a JSON string for embedding in the
|
|
58
|
+
* rendered HTML (e.g. a `<script>` payload the client
|
|
59
|
+
* reads on hydration). Every field of `Preloaded` is JSON-serializable by
|
|
60
|
+
* construction — `preloadQuery` only captures the query args, function path,
|
|
61
|
+
* optional shard key, and the resolved value — so this is a thin, explicit
|
|
62
|
+
* `JSON.stringify` that documents the dehydration seam and keeps callers from
|
|
63
|
+
* accidentally stringifying a non-serializable wrapper.
|
|
64
|
+
*
|
|
65
|
+
* The `<` is escaped to `<` so the payload is safe to inline inside a
|
|
66
|
+
* `<script>` tag without a stray `</script>` (or `<!--`) prematurely closing
|
|
67
|
+
* it — the standard XSS-safe script-embedding precaution. This escaping is NOT
|
|
68
|
+
* sufficient for an HTML *attribute* sink (which also needs the quote and `&`
|
|
69
|
+
* characters escaped); embed the output in a raw-text script element, not a
|
|
70
|
+
* data attribute.
|
|
71
|
+
*/
|
|
72
|
+
declare const serializePreloaded: <T>(preloaded: Preloaded<T>) => string;
|
|
73
|
+
/**
|
|
74
|
+
* Inverse of {@link serializePreloaded}: parse a serialized token back into a
|
|
75
|
+
* {@link Preloaded} value on the client. The `<` escape from serialization
|
|
76
|
+
* is transparent to `JSON.parse`, so no un-escaping step is needed.
|
|
77
|
+
*/
|
|
78
|
+
declare const deserializePreloaded: <T = unknown>(serialized: string) => Preloaded<T>;
|
|
79
|
+
/** Options accepted by {@link createServerClient}. */
|
|
80
|
+
interface ServerClientOptions {
|
|
81
|
+
/**
|
|
82
|
+
* `fetch` implementation used for HTTP RPC. Defaults to the ambient global
|
|
83
|
+
* `fetch` (present in Node 18+, Workers, and meta-framework SSR runtimes).
|
|
84
|
+
* Pass one explicitly to forward cookies/headers or to use an instrumented
|
|
85
|
+
* fetch.
|
|
86
|
+
*/
|
|
87
|
+
fetch?: typeof fetch;
|
|
88
|
+
/**
|
|
89
|
+
* Bearer token sent as `Authorization: Bearer <token>` on every RPC. In an
|
|
90
|
+
* SSR loader you typically read this from the request (e.g. the session
|
|
91
|
+
* resolved by `getServerSession`) and pass it here so the server-side
|
|
92
|
+
* load runs as the signed-in user — and so the client subscription that
|
|
93
|
+
* resumes after hydration carries the same identity.
|
|
94
|
+
*/
|
|
95
|
+
token?: string;
|
|
96
|
+
/** Base URL of the deployed Lunora worker, e.g. `https://app.example.workers.dev`. */
|
|
97
|
+
url: string;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Build a request-scoped {@link LunoraClient} for use inside an SSR loader. SSR
|
|
101
|
+
* data loading only ever calls `.query()` (HTTP RPC over `fetch`); a
|
|
102
|
+
* `LunoraClient` opens a socket lazily on `.subscribe()`/`.stream()` and those
|
|
103
|
+
* are never called server-side, so no live connection is established even if the
|
|
104
|
+
* server runtime happens to expose a global `WebSocket`.
|
|
105
|
+
*
|
|
106
|
+
* Create one per request rather than sharing a module-level instance: the bearer
|
|
107
|
+
* token (and any forwarded cookies in `fetch`) are per-user, and a shared client
|
|
108
|
+
* would leak one request's identity into another.
|
|
109
|
+
*
|
|
110
|
+
* This is the framework-neutral home of the helper that previously lived only in
|
|
111
|
+
* `@lunora/react/server`; the React server module re-exports the same surface so
|
|
112
|
+
* existing imports keep working.
|
|
113
|
+
*/
|
|
114
|
+
declare const createServerClient: (options: ServerClientOptions) => LunoraClient;
|
|
115
|
+
export { type AuthLike, type HeadersSource, type Preloaded, type ServerClientOptions, type ServerSession, createServerClient, deserializePreloaded, getServerSession, serializePreloaded };
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-DGvyuJ_p.js";
|
|
2
|
+
export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/lunora-client.d-DGvyuJ_p.js";
|
|
3
|
+
export { p as preloadQuery, a as preloadedQueryResult } from "../packem_shared/preload.d-BoDmFqSG.js";
|
|
4
|
+
import '@lunora/runtime';
|
|
5
|
+
/**
|
|
6
|
+
* Structural shape of a better-auth `getSession` call's resolved value.
|
|
7
|
+
*
|
|
8
|
+
* better-auth's `auth.api.getSession({ headers })` returns `{ user, session }`
|
|
9
|
+
* when a valid session cookie is present, or `null` otherwise. We keep `user`
|
|
10
|
+
* and `session` as open records so `@lunora/client/ssr` carries no hard dependency on
|
|
11
|
+
* better-auth's concrete `User`/`Session` types — the adapter passing the real
|
|
12
|
+
* `auth` instance keeps full inference, while this package stays decoupled.
|
|
13
|
+
*/
|
|
14
|
+
interface ServerSession<User extends Record<string, unknown> = Record<string, unknown>, Session extends Record<string, unknown> = Record<string, unknown>> {
|
|
15
|
+
readonly session: Session;
|
|
16
|
+
readonly user: User;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Structural subset of a better-auth instance: just the one endpoint
|
|
20
|
+
* `getServerSession` needs. Typing it this way (rather than importing
|
|
21
|
+
* `@lunora/auth`'s `LunoraAuth`) means `@lunora/client/ssr` does not depend on
|
|
22
|
+
* better-auth internals — any object exposing `api.getSession` works, including
|
|
23
|
+
* a test stub. The concrete return type is inferred from the passed instance.
|
|
24
|
+
*/
|
|
25
|
+
interface AuthLike<Result = ServerSession | null> {
|
|
26
|
+
readonly api: {
|
|
27
|
+
getSession: (input: {
|
|
28
|
+
headers: Headers;
|
|
29
|
+
}) => Promise<Result> | Result;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Anything `getServerSession` can read request headers from: a `Request`, a
|
|
34
|
+
* `Headers` object, or a plain object exposing `headers`. SSR loaders across
|
|
35
|
+
* meta-frameworks hand back slightly different request objects, so accept the
|
|
36
|
+
* common shapes rather than forcing the caller to unwrap.
|
|
37
|
+
*/
|
|
38
|
+
type HeadersSource = Headers | Request | {
|
|
39
|
+
readonly headers: Headers;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Resolve the signed-in session from a request inside an SSR loader.
|
|
43
|
+
*
|
|
44
|
+
* Wraps `auth.api.getSession({ headers })` — the helper every meta-framework
|
|
45
|
+
* app otherwise hand-rolls — so a loader can read identity off the inbound
|
|
46
|
+
* cookies in one call. Returns `{ user, session }` when a valid session cookie
|
|
47
|
+
* is present, or `null` for anonymous requests.
|
|
48
|
+
*
|
|
49
|
+
* The `auth` parameter is structurally typed ({@link AuthLike}), so this
|
|
50
|
+
* package does not depend on better-auth internals; pass a real
|
|
51
|
+
* `@lunora/auth` instance to keep full type inference on `user`/`session`.
|
|
52
|
+
* Forward the resolved session's token to `createServerClient` to run the
|
|
53
|
+
* server-side load (and the later WS subscription) as the same identity.
|
|
54
|
+
*/
|
|
55
|
+
declare const getServerSession: <Result>(request: HeadersSource, auth: AuthLike<Result>) => Promise<NonNullable<Result> | null>;
|
|
56
|
+
/**
|
|
57
|
+
* Serialize a {@link Preloaded} token to a JSON string for embedding in the
|
|
58
|
+
* rendered HTML (e.g. a `<script>` payload the client
|
|
59
|
+
* reads on hydration). Every field of `Preloaded` is JSON-serializable by
|
|
60
|
+
* construction — `preloadQuery` only captures the query args, function path,
|
|
61
|
+
* optional shard key, and the resolved value — so this is a thin, explicit
|
|
62
|
+
* `JSON.stringify` that documents the dehydration seam and keeps callers from
|
|
63
|
+
* accidentally stringifying a non-serializable wrapper.
|
|
64
|
+
*
|
|
65
|
+
* The `<` is escaped to `<` so the payload is safe to inline inside a
|
|
66
|
+
* `<script>` tag without a stray `</script>` (or `<!--`) prematurely closing
|
|
67
|
+
* it — the standard XSS-safe script-embedding precaution. This escaping is NOT
|
|
68
|
+
* sufficient for an HTML *attribute* sink (which also needs the quote and `&`
|
|
69
|
+
* characters escaped); embed the output in a raw-text script element, not a
|
|
70
|
+
* data attribute.
|
|
71
|
+
*/
|
|
72
|
+
declare const serializePreloaded: <T>(preloaded: Preloaded<T>) => string;
|
|
73
|
+
/**
|
|
74
|
+
* Inverse of {@link serializePreloaded}: parse a serialized token back into a
|
|
75
|
+
* {@link Preloaded} value on the client. The `<` escape from serialization
|
|
76
|
+
* is transparent to `JSON.parse`, so no un-escaping step is needed.
|
|
77
|
+
*/
|
|
78
|
+
declare const deserializePreloaded: <T = unknown>(serialized: string) => Preloaded<T>;
|
|
79
|
+
/** Options accepted by {@link createServerClient}. */
|
|
80
|
+
interface ServerClientOptions {
|
|
81
|
+
/**
|
|
82
|
+
* `fetch` implementation used for HTTP RPC. Defaults to the ambient global
|
|
83
|
+
* `fetch` (present in Node 18+, Workers, and meta-framework SSR runtimes).
|
|
84
|
+
* Pass one explicitly to forward cookies/headers or to use an instrumented
|
|
85
|
+
* fetch.
|
|
86
|
+
*/
|
|
87
|
+
fetch?: typeof fetch;
|
|
88
|
+
/**
|
|
89
|
+
* Bearer token sent as `Authorization: Bearer <token>` on every RPC. In an
|
|
90
|
+
* SSR loader you typically read this from the request (e.g. the session
|
|
91
|
+
* resolved by `getServerSession`) and pass it here so the server-side
|
|
92
|
+
* load runs as the signed-in user — and so the client subscription that
|
|
93
|
+
* resumes after hydration carries the same identity.
|
|
94
|
+
*/
|
|
95
|
+
token?: string;
|
|
96
|
+
/** Base URL of the deployed Lunora worker, e.g. `https://app.example.workers.dev`. */
|
|
97
|
+
url: string;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Build a request-scoped {@link LunoraClient} for use inside an SSR loader. SSR
|
|
101
|
+
* data loading only ever calls `.query()` (HTTP RPC over `fetch`); a
|
|
102
|
+
* `LunoraClient` opens a socket lazily on `.subscribe()`/`.stream()` and those
|
|
103
|
+
* are never called server-side, so no live connection is established even if the
|
|
104
|
+
* server runtime happens to expose a global `WebSocket`.
|
|
105
|
+
*
|
|
106
|
+
* Create one per request rather than sharing a module-level instance: the bearer
|
|
107
|
+
* token (and any forwarded cookies in `fetch`) are per-user, and a shared client
|
|
108
|
+
* would leak one request's identity into another.
|
|
109
|
+
*
|
|
110
|
+
* This is the framework-neutral home of the helper that previously lived only in
|
|
111
|
+
* `@lunora/react/server`; the React server module re-exports the same surface so
|
|
112
|
+
* existing imports keep working.
|
|
113
|
+
*/
|
|
114
|
+
declare const createServerClient: (options: ServerClientOptions) => LunoraClient;
|
|
115
|
+
export { type AuthLike, type HeadersSource, type Preloaded, type ServerClientOptions, type ServerSession, createServerClient, deserializePreloaded, getServerSession, serializePreloaded };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { getServerSession } from '../packem_shared/getServerSession-8jXewqxd.mjs';
|
|
2
|
+
export { deserializePreloaded, serializePreloaded } from '../packem_shared/deserializePreloaded-C0eJTY_W.mjs';
|
|
3
|
+
export { createServerClient } from '../packem_shared/createServerClient-BjZc3gD8.mjs';
|
|
4
|
+
export { preloadQuery, preloadedQueryResult } from '../packem_shared/preloadQuery-lobFkD2Z.mjs';
|