@laguzjs/client 0.0.0-stage → 0.1.0

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Maxence Leguery
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,31 @@
1
- # Temporary Holding Version
1
+ # @laguzjs/client
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Batch every GraphQL query a React commit needs into one request, and stream the
4
+ answer back field by field.
5
+
6
+ ```sh
7
+ npm install @laguzjs/client
8
+ ```
9
+
10
+ ```tsx
11
+ import { createPool, httpFetcher } from "@laguzjs/client";
12
+ import { useData } from "@laguzjs/client/react";
13
+
14
+ const pool = createPool(httpFetcher("/graphql", { stream: true }));
15
+
16
+ function Header() {
17
+ const { data, loading, error } = useData(pool, "user", { id: 1 }, ["name"]);
18
+ return <h1>{data?.name}</h1>;
19
+ }
20
+ ```
21
+
22
+ Works with any GraphQL server. Pair it with
23
+ [`@laguzjs/server`](https://www.npmjs.com/package/@laguzjs/server) to stream
24
+ fields as they resolve and to resolve dependent queries in one round trip.
25
+
26
+ Documentation: [guide](https://github.com/maxenceleguery/laguz/blob/main/docs/guide.md)
27
+ and [laguz.maxenceleguery.net](https://laguz.maxenceleguery.net).
28
+
29
+ ## License
30
+
31
+ MIT
package/dist/http.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import type { Fetcher } from "./pool.ts";
2
+ export type HttpOptions = {
3
+ /** Ask for one NDJSON line per root field. Falls back to JSON if the server doesn't stream. */
4
+ stream?: boolean;
5
+ headers?: Record<string, string>;
6
+ };
7
+ /** A fetcher that POSTs `{ query }` to `url`. */
8
+ export declare function httpFetcher(url: string, options?: HttpOptions): Fetcher;
9
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAA2B,MAAM,WAAW,CAAC;AAElE,MAAM,MAAM,WAAW,GAAG;IACxB,+FAA+F;IAC/F,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAEF,iDAAiD;AACjD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAa3E"}
package/dist/http.js ADDED
@@ -0,0 +1,36 @@
1
+ /** A fetcher that POSTs `{ query }` to `url`. */
2
+ export function httpFetcher(url, options = {}) {
3
+ return (query) => {
4
+ const res = fetch(url, {
5
+ method: "POST",
6
+ headers: {
7
+ "content-type": "application/json",
8
+ accept: options.stream ? "application/x-ndjson, application/json" : "application/json",
9
+ ...options.headers,
10
+ },
11
+ body: JSON.stringify({ query }),
12
+ });
13
+ return options.stream ? lines(res) : res.then((r) => r.json());
14
+ };
15
+ }
16
+ async function* lines(pending) {
17
+ const res = await pending;
18
+ if (!res.headers.get("content-type")?.includes("ndjson")) {
19
+ yield await res.json();
20
+ return;
21
+ }
22
+ let buffer = "";
23
+ for await (const text of res.body.pipeThrough(new TextDecoderStream())) {
24
+ buffer += text;
25
+ let newline;
26
+ while ((newline = buffer.indexOf("\n")) >= 0) {
27
+ const line = buffer.slice(0, newline);
28
+ buffer = buffer.slice(newline + 1);
29
+ if (line.trim())
30
+ yield JSON.parse(line);
31
+ }
32
+ }
33
+ if (buffer.trim())
34
+ yield JSON.parse(buffer);
35
+ }
36
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAQA,iDAAiD;AACjD,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,OAAO,GAAgB,EAAE;IAChE,OAAO,CAAC,KAAK,EAAE,EAAE;QACf,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,EAAE;YACrB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,wCAAwC,CAAC,CAAC,CAAC,kBAAkB;gBACtF,GAAG,OAAO,CAAC,OAAO;aACnB;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC;SAChC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACjE,CAAC,CAAC;AACJ,CAAC;AAED,KAAK,SAAS,CAAC,CAAC,KAAK,CAAC,OAA0B;IAC9C,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC;IAC1B,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzD,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QACvB,OAAO;IACT,CAAC;IACD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,GAAG,CAAC,IAAK,CAAC,WAAW,CAAC,IAAI,iBAAiB,EAAE,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,IAAI,CAAC;QACf,IAAI,OAAO,CAAC;QACZ,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YACtC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;YACnC,IAAI,IAAI,CAAC,IAAI,EAAE;gBAAE,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { createPool, ready } from "./pool.ts";
2
+ export type { Fetcher, GqlError, Match, Options, Pool, Response, Snapshot } from "./pool.ts";
3
+ export { fieldKey, printField, ref, toTree, view } from "./selection.ts";
4
+ export type { FieldArg, Fields, Ref, Tree } from "./selection.ts";
5
+ export { httpFetcher } from "./http.ts";
6
+ export type { HttpOptions } from "./http.ts";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC7F,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACzE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { createPool, ready } from "./pool.js";
2
+ export { fieldKey, printField, ref, toTree, view } from "./selection.js";
3
+ export { httpFetcher } from "./http.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAE9C,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEzE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
package/dist/pool.d.ts ADDED
@@ -0,0 +1,52 @@
1
+ import { type Fields, type Tree } from "./selection.ts";
2
+ export type GqlError = {
3
+ message: string;
4
+ path?: (string | number)[];
5
+ };
6
+ export type Response = {
7
+ data?: Record<string, unknown> | null;
8
+ errors?: GqlError[];
9
+ extensions?: Record<string, unknown>;
10
+ };
11
+ /** Sends a query. Returns one response, or a stream of partial responses. */
12
+ export type Fetcher = (query: string) => Promise<Response> | AsyncIterable<Response>;
13
+ export type Snapshot = {
14
+ data?: any;
15
+ error?: Error;
16
+ has: Tree;
17
+ };
18
+ /** A root field name, or a predicate on the root field and its printed arguments. */
19
+ export type Match = string | ((root: string, args: string) => boolean);
20
+ export type Options = {
21
+ /** Milliseconds before cached data is refetched when a new consumer mounts. Default 0. */
22
+ staleTime?: number;
23
+ /** Milliseconds an entry without consumers stays cached. Default 5 minutes. */
24
+ gcTime?: number;
25
+ /** Retries before an error is reported. Default 3. */
26
+ retry?: number;
27
+ /** Delay before retry `attempt` (0-based). Default exponential, capped at 30 s. */
28
+ retryDelay?: (attempt: number) => number;
29
+ /** Maximum root fields per request, for servers that limit aliases. Default unlimited. */
30
+ maxBatch?: number;
31
+ /**
32
+ * Whether the server resolves refs itself (see @laguzjs/server), so dependent
33
+ * queries can share a request. `"auto"` (default) starts resolving refs on
34
+ * the client and switches once a response carries `extensions.laguz`.
35
+ */
36
+ serverRefs?: boolean | "auto";
37
+ };
38
+ /** Whether `snap` holds everything `tree` selects. */
39
+ export declare const ready: (snap: Snapshot, tree: Tree) => boolean;
40
+ export declare function createPool(fetcher: Fetcher, options?: Options): {
41
+ watch: (root: string, args: object, fields: Fields | Tree, cb: () => void, minStaleTime?: number) => () => void;
42
+ read: (root: string, args: object) => Snapshot;
43
+ load: (root: string, args: object, fields: Fields | Tree) => Promise<void>;
44
+ invalidate: (match?: Match) => void;
45
+ set: (root: string, args: object, fn: (data: any) => any) => () => void;
46
+ mutate: <T>(run: () => Promise<T>, o?: {
47
+ optimistic?: [root: string, args: object, fn: (data: any) => any][];
48
+ invalidate?: Match[];
49
+ }) => Promise<T>;
50
+ };
51
+ export type Pool = ReturnType<typeof createPool>;
52
+ //# sourceMappingURL=pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAaL,KAAK,MAAM,EAEX,KAAK,IAAI,EACV,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,QAAQ,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;CAAE,CAAC;AACvE,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC,CAAC;AACF,6EAA6E;AAC7E,MAAM,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;AACrF,MAAM,MAAM,QAAQ,GAAG;IAAE,IAAI,CAAC,EAAE,GAAG,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,IAAI,CAAA;CAAE,CAAC;AAChE,qFAAqF;AACrF,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC;AAEvE,MAAM,MAAM,OAAO,GAAG;IACpB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mFAAmF;IACnF,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC/B,CAAC;AA8BF,sDAAsD;AACtD,eAAO,MAAM,KAAK,SAAU,QAAQ,QAAQ,IAAI,KAAG,OACV,CAAC;AAS1C,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,OAAY;kBAkRxD,MAAM,QACN,MAAM,UACJ,MAAM,GAAG,IAAI,MACjB,MAAM,IAAI;iBAsBI,MAAM,QAAQ,MAAM,KAAG,QAAQ;iBAO/B,MAAM,QAAQ,MAAM,UAAU,MAAM,GAAG,IAAI,KAAG,OAAO,CAAC,IAAI,CAAC;yBAlEnD,KAAK;gBAgBd,MAAM,QAAQ,MAAM,MAAM,CAAC,IAAI,EAAE,GAAG,KAAK,GAAG;aA2EzC,CAAC,OAChB,MAAM,OAAO,CAAC,CAAC,CAAC,MAClB;QACD,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC;QACpE,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC;KACtB,KACA,OAAO,CAAC,CAAC,CAAC;EAad;AAED,MAAM,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC"}
package/dist/pool.js ADDED
@@ -0,0 +1,339 @@
1
+ import { collectRefs, diff, getPath, merge, mergeData, name, pathTree, printArgs, printTree, printValue, toTree, touchesList, } from "./selection.js";
2
+ const EMPTY = Object.freeze({ has: {} });
3
+ /** Whether `snap` holds everything `tree` selects. */
4
+ export const ready = (snap, tree) => "data" in snap && !diff(tree, snap.has);
5
+ function unref(timer) {
6
+ timer?.unref?.();
7
+ return timer;
8
+ }
9
+ const toError = (err) => (err instanceof Error ? err : new Error(err.message));
10
+ export function createPool(fetcher, options = {}) {
11
+ const { staleTime = 0, gcTime = 5 * 60_000, retry = 3, retryDelay = (attempt) => Math.min(1000 * 2 ** attempt, 30_000), maxBatch = Infinity, serverRefs = "auto", } = options;
12
+ let forward = serverRefs === true;
13
+ let scheduled = false;
14
+ let retryTimer;
15
+ const entries = new Map();
16
+ const dirty = new Set();
17
+ const retrying = new Set();
18
+ const loads = new Map();
19
+ function entry(root, args) {
20
+ const printed = printArgs(args);
21
+ const key = name(root) + printed;
22
+ let e = entries.get(key);
23
+ if (!e) {
24
+ e = {
25
+ key,
26
+ root,
27
+ args: printed,
28
+ argv: args,
29
+ refs: collectRefs(args),
30
+ snap: EMPTY,
31
+ subs: new Set(),
32
+ inflight: new Set(),
33
+ epoch: 0,
34
+ stale: false,
35
+ at: 0,
36
+ fails: 0,
37
+ };
38
+ entries.set(key, e);
39
+ }
40
+ return e;
41
+ }
42
+ // Everything touched before the current task ends is fetched together.
43
+ function touch(e) {
44
+ dirty.add(e);
45
+ if (scheduled)
46
+ return;
47
+ scheduled = true;
48
+ queueMicrotask(flush);
49
+ }
50
+ function release(e) {
51
+ if (e.subs.size)
52
+ return;
53
+ e.gc = unref(setTimeout(() => e.subs.size || entries.delete(e.key), gcTime));
54
+ }
55
+ function update(e, snap) {
56
+ e.snap = snap;
57
+ for (const sub of e.subs)
58
+ sub.cb();
59
+ }
60
+ /** What `e` still has to fetch, or null. `full` replaces the cached data. */
61
+ function need(e) {
62
+ const want = [...e.subs].reduce((tree, sub) => merge(tree, sub.tree), {});
63
+ // A refetch already in flight will call touch() again when it lands.
64
+ if (e.stale)
65
+ return e.inflight.size ? null : { tree: want, full: true };
66
+ const covered = [...e.inflight].reduce(merge, e.snap.has);
67
+ let tree = diff(want, covered);
68
+ // A scalar root field selects nothing but still needs one fetch.
69
+ if (!tree && !e.at && !e.inflight.size)
70
+ tree = want;
71
+ if (!tree)
72
+ return null;
73
+ return touchesList(tree, e.snap.data) ? { tree: want, full: true } : { tree, full: false };
74
+ }
75
+ /**
76
+ * The printed arguments of `e` with its refs replaced by their values. A ref
77
+ * whose dependency is part of `batch` becomes a placeholder the server fills
78
+ * in. Returns null while a value is unknown.
79
+ */
80
+ function resolve(e, batch) {
81
+ let known = true;
82
+ const printed = printArgs(e.argv, ({ $ref: [root, args, path] }) => {
83
+ const dep = entry(root, args);
84
+ if (ready(dep.snap, pathTree(path)))
85
+ return printValue(getPath(dep.snap.data, path));
86
+ const index = batch?.get(dep);
87
+ if (index !== undefined)
88
+ return `$_ref__q${index}__${path.replaceAll(".", "__")}`;
89
+ known = false;
90
+ return "null";
91
+ });
92
+ return known ? printed : null;
93
+ }
94
+ function dependencyError(e) {
95
+ for (const { $ref: [root, args, path], } of e.refs) {
96
+ const snap = entry(root, args).snap;
97
+ if (snap.error && !ready(snap, pathTree(path)))
98
+ return snap.error;
99
+ }
100
+ }
101
+ function flush() {
102
+ scheduled = false;
103
+ const todo = [...dirty].filter((e) => e.subs.size);
104
+ dirty.clear();
105
+ const reqs = [];
106
+ const batch = new Map();
107
+ // Loop until nothing changes: an entry whose ref points into this batch
108
+ // can only join after its dependency, so dependencies get lower aliases.
109
+ let progress = true;
110
+ while (progress) {
111
+ progress = false;
112
+ todo.forEach((e, i) => {
113
+ if (!e)
114
+ return;
115
+ let args = e.args;
116
+ let forwarded = false;
117
+ if (e.refs.length) {
118
+ const known = resolve(e);
119
+ if (known !== null) {
120
+ if (e.at && known !== e.sent) {
121
+ // A dependency's value changed since the last fetch.
122
+ e.epoch++;
123
+ e.inflight.clear();
124
+ e.stale = true;
125
+ }
126
+ args = known;
127
+ }
128
+ else {
129
+ const err = dependencyError(e);
130
+ if (err) {
131
+ todo[i] = undefined;
132
+ if (e.snap.error !== err)
133
+ update(e, { ...e.snap, error: err });
134
+ return;
135
+ }
136
+ const placeholder = forward ? resolve(e, batch) : null;
137
+ // Otherwise wait: the dependency's watcher touches this entry when it lands.
138
+ if (placeholder === null)
139
+ return;
140
+ args = placeholder;
141
+ forwarded = true;
142
+ }
143
+ }
144
+ todo[i] = undefined;
145
+ progress = true;
146
+ const n = need(e);
147
+ if (!n)
148
+ return;
149
+ e.inflight.add(n.tree);
150
+ batch.set(e, reqs.length);
151
+ reqs.push({ e, ...n, epoch: e.epoch, args, forwarded });
152
+ });
153
+ }
154
+ // Placeholders name aliases across the whole batch, so it can't be split.
155
+ const step = reqs.some((r) => r.forwarded) ? Infinity : maxBatch;
156
+ for (let i = 0; i < reqs.length; i += step)
157
+ send(reqs.slice(i, i + step));
158
+ }
159
+ async function send(reqs) {
160
+ const query = `{ ${reqs.map((r, i) => `q${i}: ${r.e.root}${r.args}${printTree(r.tree)}`).join(" ")} }`;
161
+ const pending = new Map(reqs.map((r, i) => [`q${i}`, r]));
162
+ try {
163
+ const res = fetcher(query);
164
+ for await (const chunk of Symbol.asyncIterator in res ? res : [await res]) {
165
+ if (serverRefs === "auto" && Number(chunk.extensions?.laguz) >= 1)
166
+ forward = true;
167
+ const fatal = !chunk.data && chunk.errors?.find((err) => !err.path);
168
+ if (fatal) {
169
+ if (pending.size === 1) {
170
+ for (const r of pending.values())
171
+ settle(r, undefined, fatal);
172
+ return;
173
+ }
174
+ // A single invalid field fails validation for the whole document.
175
+ // Resend each field alone so only that one reports the error.
176
+ for (const r of pending.values()) {
177
+ if (!r.forwarded) {
178
+ send([r]);
179
+ continue;
180
+ }
181
+ // Alone, a forwarded field has no dependency to read from: it
182
+ // waits and resolves on the client instead.
183
+ r.e.inflight.delete(r.tree);
184
+ touch(r.e);
185
+ }
186
+ return;
187
+ }
188
+ for (const [alias, r] of pending) {
189
+ const err = chunk.errors?.find((e) => e.path?.[0] === alias);
190
+ if (err || (chunk.data && alias in chunk.data)) {
191
+ pending.delete(alias);
192
+ settle(r, chunk.data?.[alias], err);
193
+ }
194
+ }
195
+ }
196
+ for (const r of pending.values())
197
+ settle(r, undefined, { message: "no data in response" });
198
+ }
199
+ catch (err) {
200
+ for (const r of pending.values())
201
+ settle(r, undefined, err);
202
+ }
203
+ }
204
+ function settle(r, data, err) {
205
+ const e = r.e;
206
+ e.inflight.delete(r.tree);
207
+ if (r.epoch !== e.epoch)
208
+ return;
209
+ if (err) {
210
+ if (e.fails++ < retry) {
211
+ // One timer for every entry that failed in this window keeps the
212
+ // retries batched. They all wait for the first entry's delay.
213
+ retrying.add(e);
214
+ retryTimer ??= setTimeout(() => {
215
+ retryTimer = undefined;
216
+ retrying.forEach(touch);
217
+ retrying.clear();
218
+ }, retryDelay(e.fails - 1));
219
+ return;
220
+ }
221
+ update(e, { ...e.snap, error: toError(err) });
222
+ return;
223
+ }
224
+ e.fails = 0;
225
+ e.at = Date.now();
226
+ // For a forwarded request the dependency arrived first, so the value is known now.
227
+ e.sent = r.forwarded ? (resolve(e) ?? r.args) : r.args;
228
+ if (r.full)
229
+ e.stale = false;
230
+ update(e, r.full
231
+ ? { data, has: r.tree }
232
+ : { data: mergeData(e.snap.data, data), has: merge(e.snap.has, r.tree) });
233
+ // Consumers that subscribed while this was in flight may want more.
234
+ if (e.subs.size)
235
+ touch(e);
236
+ }
237
+ /** Mark matching entries stale. Those in use refetch together, in one request. */
238
+ function invalidate(match) {
239
+ for (const e of entries.values()) {
240
+ const hit = !match || (typeof match === "string" ? e.root === match : match(e.root, e.args));
241
+ if (!hit)
242
+ continue;
243
+ e.epoch++;
244
+ e.inflight.clear();
245
+ e.stale = true;
246
+ if (e.subs.size)
247
+ touch(e);
248
+ }
249
+ }
250
+ /**
251
+ * Write to the cache, e.g. an optimistic update. In-flight reads of the entry
252
+ * are dropped so they can't overwrite it. Returns a function that restores
253
+ * the previous value.
254
+ */
255
+ function set(root, args, fn) {
256
+ const e = entry(root, args);
257
+ const prev = e.snap;
258
+ e.epoch++;
259
+ e.inflight.clear();
260
+ e.stale = false;
261
+ update(e, { ...prev, data: fn(prev.data) });
262
+ if (e.subs.size)
263
+ touch(e);
264
+ else
265
+ release(e);
266
+ return () => update(e, prev);
267
+ }
268
+ /**
269
+ * Subscribe to `fields` of `root(args)`. The fetch goes out at the end of the
270
+ * current task, together with everything else registered in it.
271
+ * Returns the unsubscribe function.
272
+ */
273
+ function watch(root, args, fields, cb, minStaleTime = 0) {
274
+ const e = entry(root, args);
275
+ clearTimeout(e.gc);
276
+ if (e.at && Date.now() - e.at > Math.max(staleTime, minStaleTime))
277
+ e.stale = true;
278
+ if (e.snap.error)
279
+ e.fails = 0;
280
+ const sub = { tree: Array.isArray(fields) ? toTree(fields) : fields, cb };
281
+ e.subs.add(sub);
282
+ touch(e);
283
+ // A ref depends on another field: subscribe to it and recheck this entry when it changes.
284
+ const deps = e.refs.map(({ $ref: [depRoot, depArgs, path] }) => watch(depRoot, depArgs, pathTree(path), () => touch(e)));
285
+ return () => {
286
+ e.subs.delete(sub);
287
+ deps.forEach((off) => off());
288
+ release(e);
289
+ };
290
+ }
291
+ /** The current snapshot of `root(args)`. Stable until the entry changes. */
292
+ const read = (root, args) => entries.get(name(root) + printArgs(args))?.snap ?? EMPTY;
293
+ /**
294
+ * Fetch without staying subscribed (Suspense, prefetching). Joins the current
295
+ * batch. Resolves once the data is ready or the fetch failed.
296
+ */
297
+ function load(root, args, fields) {
298
+ const tree = Array.isArray(fields) ? toTree(fields) : fields;
299
+ if (ready(read(root, args), tree))
300
+ return Promise.resolve();
301
+ const key = name(root) + printArgs(args) + JSON.stringify(tree);
302
+ const existing = loads.get(key);
303
+ if (existing)
304
+ return existing;
305
+ const before = read(root, args);
306
+ const promise = new Promise((resolve) => {
307
+ const stop = watch(root, args, tree, () => {
308
+ const snap = read(root, args);
309
+ const failed = snap.error && snap !== before;
310
+ if (!ready(snap, tree) && !failed)
311
+ return;
312
+ stop();
313
+ loads.delete(key);
314
+ resolve();
315
+ });
316
+ });
317
+ loads.set(key, promise);
318
+ return promise;
319
+ }
320
+ /**
321
+ * Run a mutation. Optimistic writes apply at once and are rolled back if it
322
+ * throws; the `invalidate` matches refetch afterwards either way.
323
+ */
324
+ async function mutate(run, o = {}) {
325
+ const undo = (o.optimistic ?? []).map(([root, args, fn]) => set(root, args, fn));
326
+ try {
327
+ return await run();
328
+ }
329
+ catch (err) {
330
+ undo.reverse().forEach((restore) => restore());
331
+ throw err;
332
+ }
333
+ finally {
334
+ o.invalidate?.forEach((m) => invalidate(m));
335
+ }
336
+ }
337
+ return { watch, read, load, invalidate, set, mutate };
338
+ }
339
+ //# sourceMappingURL=pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pool.js","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import { type Pool } from "./pool.ts";
2
+ import { type Fields } from "./selection.ts";
3
+ /**
4
+ * Read `fields` of `root(args)`. Pass `args: null` to skip the query, for
5
+ * example until the value it depends on has loaded.
6
+ */
7
+ export declare function useData<T = any>(pool: Pool, root: string, args: object | null, fields: Fields): {
8
+ data: T | undefined;
9
+ error: Error | undefined;
10
+ loading: boolean;
11
+ };
12
+ /**
13
+ * Like {@link useData}, but suspends until the data is ready and throws errors
14
+ * to the nearest error boundary. Call `pool.invalidate(root)` when the boundary
15
+ * resets to retry.
16
+ *
17
+ * Give each component its own `<Suspense>` boundary. React stops rendering the
18
+ * siblings of a component that suspends, so components sharing a boundary are
19
+ * fetched in two requests instead of one.
20
+ */
21
+ export declare function useSuspenseData<T = any>(pool: Pool, root: string, args: object, fields: Fields): T;
22
+ export type Page = {
23
+ root: string;
24
+ args: object;
25
+ fields: Fields;
26
+ };
27
+ /**
28
+ * An infinite list. `page(prev, index)` describes page `index` from the data of
29
+ * the previous page (its cursor), or returns null after the last page.
30
+ *
31
+ * Every page is a regular cache entry: refreshing refetches all loaded pages in
32
+ * one request, and pages whose cursor moved are fetched right after.
33
+ * `prefetch` keeps that many pages loaded ahead, so `loadMore` shows them at once.
34
+ */
35
+ export declare function useInfiniteData<T = any>(pool: Pool, page: (prev: T | undefined, index: number) => Page | null, { prefetch }?: {
36
+ prefetch?: number | undefined;
37
+ }): {
38
+ pages: T[];
39
+ hasMore: boolean;
40
+ loading: boolean;
41
+ loadingMore: boolean;
42
+ error: Error | undefined;
43
+ loadMore: () => void;
44
+ };
45
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AACA,OAAO,EAAS,KAAK,IAAI,EAAiB,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAqB3D;;;GAGG;AACH,wBAAgB,OAAO,CAAC,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM;IAG1F,IAAI,EAAU,CAAC,GAAG,SAAS;IAC3B,KAAK;IACL,OAAO;EAEV;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,CAAC,GAAG,GAAG,EACrC,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,CAAC,CAMH;AAED,MAAM,MAAM,IAAI,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElE;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,CAAC,GAAG,GAAG,EACrC,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,EACzD,EAAE,QAAY,EAAE;;CAAK;;;;;;;EA+EtB"}