@lunora/client 0.0.0 → 1.0.0-alpha.10

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.
Files changed (45) hide show
  1. package/LICENSE.md +105 -0
  2. package/README.md +113 -9
  3. package/__assets__/package-og.svg +14 -0
  4. package/dist/auth/index.d.mts +20 -0
  5. package/dist/auth/index.d.ts +20 -0
  6. package/dist/auth/index.mjs +60 -0
  7. package/dist/index.d.mts +385 -0
  8. package/dist/index.d.ts +385 -0
  9. package/dist/index.mjs +15 -0
  10. package/dist/packem_shared/CONFLICT_ERROR_CODE-aUdVbEDw.mjs +4 -0
  11. package/dist/packem_shared/DEFAULT_MAX_BUFFER-BDkqO5PW.mjs +107 -0
  12. package/dist/packem_shared/LunoraClient-CgZ6FhKP.mjs +2721 -0
  13. package/dist/packem_shared/OfflineQueue-BI0FNNvc.mjs +1 -0
  14. package/dist/packem_shared/SKIP-vItZChkw.mjs +50 -0
  15. package/dist/packem_shared/SubscriptionRegistry-Dn-7k7eo.mjs +1 -0
  16. package/dist/packem_shared/applyDelta-4jFGTPA3.mjs +61 -0
  17. package/dist/packem_shared/createAsyncStoragePersistence-1Z5BZ8RC.mjs +45 -0
  18. package/dist/packem_shared/createInMemoryBookmarkStorage-BoN7a7TH.mjs +11 -0
  19. package/dist/packem_shared/createInMemoryPersistence-CW82inU5.mjs +105 -0
  20. package/dist/packem_shared/createInMemoryQueryCache-B1PQ9Twl.mjs +138 -0
  21. package/dist/packem_shared/createLocalStore-IOur0jHF.mjs +1 -0
  22. package/dist/packem_shared/createMutationRunner-BqsavzvG.mjs +21 -0
  23. package/dist/packem_shared/createMutatorRunner-BETvCd0p.mjs +31 -0
  24. package/dist/packem_shared/createReconnect-Di_-oHH7.mjs +22 -0
  25. package/dist/packem_shared/createServerClient-BxkNcRlR.mjs +11 -0
  26. package/dist/packem_shared/deserializePreloaded-C0eJTY_W.mjs +4 -0
  27. package/dist/packem_shared/getServerSession-8jXewqxd.mjs +13 -0
  28. package/dist/packem_shared/local-store-BNgN3Dw3.mjs +111 -0
  29. package/dist/packem_shared/lunora-client.d-B5vWSgvD.d.mts +2196 -0
  30. package/dist/packem_shared/lunora-client.d-B5vWSgvD.d.ts +2196 -0
  31. package/dist/packem_shared/offline-queue-7Wc4onA0.mjs +164 -0
  32. package/dist/packem_shared/preload.d-3XJD-2hM.d.mts +20 -0
  33. package/dist/packem_shared/preload.d-CKZR675M.d.ts +20 -0
  34. package/dist/packem_shared/preloadQuery-lobFkD2Z.mjs +13 -0
  35. package/dist/packem_shared/subscription-C1Jy7HiF.mjs +55 -0
  36. package/dist/pagination/index.d.mts +82 -0
  37. package/dist/pagination/index.d.ts +82 -0
  38. package/dist/pagination/index.mjs +61 -0
  39. package/dist/query/index.d.mts +62 -0
  40. package/dist/query/index.d.ts +62 -0
  41. package/dist/query/index.mjs +1 -0
  42. package/dist/ssr/index.d.mts +115 -0
  43. package/dist/ssr/index.d.ts +115 -0
  44. package/dist/ssr/index.mjs +4 -0
  45. package/package.json +53 -17
@@ -0,0 +1,115 @@
1
+ import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-B5vWSgvD.mjs";
2
+ export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/lunora-client.d-B5vWSgvD.mjs";
3
+ export { p as preloadQuery, a as preloadedQueryResult } from "../packem_shared/preload.d-3XJD-2hM.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 `&lt;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 `&lt;` is escaped to `&lt;` so the payload is safe to inline inside a
66
+ * `&lt;script>` tag without a stray `&lt;/script>` (or `&lt;!--`) 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 `&amp;`
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 `&lt;` 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 &lt;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-B5vWSgvD.js";
2
+ export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/lunora-client.d-B5vWSgvD.js";
3
+ export { p as preloadQuery, a as preloadedQueryResult } from "../packem_shared/preload.d-CKZR675M.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 `&lt;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 `&lt;` is escaped to `&lt;` so the payload is safe to inline inside a
66
+ * `&lt;script>` tag without a stray `&lt;/script>` (or `&lt;!--`) 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 `&amp;`
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 `&lt;` 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 &lt;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-BxkNcRlR.mjs';
4
+ export { preloadQuery, preloadedQueryResult } from '../packem_shared/preloadQuery-lobFkD2Z.mjs';
package/package.json CHANGED
@@ -1,31 +1,67 @@
1
1
  {
2
2
  "name": "@lunora/client",
3
- "version": "0.0.0",
3
+ "version": "1.0.0-alpha.10",
4
4
  "description": "Lunora browser SDK: WebSocket transport, optimistic updates, and an offline mutation queue",
5
- "license": "FSL-1.1-Apache-2.0",
5
+ "keywords": [
6
+ "cloudflare",
7
+ "durable-objects",
8
+ "lunora",
9
+ "offline-queue",
10
+ "optimistic-updates",
11
+ "realtime",
12
+ "websocket",
13
+ "workers"
14
+ ],
6
15
  "homepage": "https://lunora.sh",
16
+ "bugs": "https://github.com/anolilab/lunora/issues",
17
+ "license": "FSL-1.1-Apache-2.0",
18
+ "author": {
19
+ "name": "Daniel Bannert",
20
+ "email": "d.bannert@anolilab.de"
21
+ },
7
22
  "repository": {
8
23
  "type": "git",
9
24
  "url": "git+https://github.com/anolilab/lunora.git",
10
25
  "directory": "packages/client"
11
26
  },
12
- "bugs": {
13
- "url": "https://github.com/anolilab/lunora/issues"
14
- },
15
- "keywords": [
16
- "lunora",
17
- "cloudflare",
18
- "workers",
19
- "durable-objects",
20
- "websocket",
21
- "optimistic-updates",
22
- "offline-queue",
23
- "realtime"
27
+ "files": [
28
+ "./dist",
29
+ "README.md",
30
+ "LICENSE.md",
31
+ "__assets__"
24
32
  ],
33
+ "type": "module",
34
+ "sideEffects": false,
35
+ "main": "./dist/index.mjs",
36
+ "module": "./dist/index.mjs",
37
+ "types": "./dist/index.d.ts",
38
+ "exports": {
39
+ ".": {
40
+ "types": "./dist/index.d.ts",
41
+ "import": "./dist/index.mjs"
42
+ },
43
+ "./query": {
44
+ "types": "./dist/query/index.d.ts",
45
+ "import": "./dist/query/index.mjs"
46
+ },
47
+ "./auth": {
48
+ "types": "./dist/auth/index.d.ts",
49
+ "import": "./dist/auth/index.mjs"
50
+ },
51
+ "./pagination": {
52
+ "types": "./dist/pagination/index.d.ts",
53
+ "import": "./dist/pagination/index.mjs"
54
+ },
55
+ "./ssr": {
56
+ "types": "./dist/ssr/index.d.ts",
57
+ "import": "./dist/ssr/index.mjs"
58
+ },
59
+ "./package.json": "./package.json"
60
+ },
25
61
  "publishConfig": {
26
62
  "access": "public"
27
63
  },
28
- "files": [
29
- "README.md"
30
- ]
64
+ "engines": {
65
+ "node": "^22.15.0 || >=24.11.0"
66
+ }
31
67
  }