@client-compose/client 0.7.0 → 0.8.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/README.md CHANGED
@@ -39,8 +39,34 @@ container.replaceChildren(...islands.map((island) => island.render()));
39
39
  never returns one it can't.
40
40
  - **`plan`** returns renderable islands in order. Errored islands are omitted unless you pass
41
41
  `onError`; islands with an unknown type, version or status are skipped and reported.
42
- - **`fetchScreen`** throws `ScreenFetchError` (with `status` and `body`) for non-2xx responses, and
43
- accepts a custom `fetch` as its fourth argument.
42
+ - **`fetchScreen`** reads the screen's stream to its end, and returns it whole. It throws
43
+ `ScreenFetchError` (with `status` and `body`) for non-2xx responses, and accepts a custom `fetch`
44
+ as its fourth argument.
45
+
46
+ ## Streams
47
+
48
+ A screen arrives as a stream (spec §4.6): its head, with any island not yet ready `pending`, then
49
+ each of those as the composer resolves it. **`openScreen`** resolves once the head is in, so you can
50
+ show the screen and fill it in:
51
+
52
+ ```ts
53
+ const stream = await openScreen(baseUrl, request, init);
54
+ let screen = stream.head;
55
+ show(plan(registry, screen)); // pending islands are their placeholders, or left out
56
+ for await (const island of stream.islands) {
57
+ screen = withIsland(screen, island);
58
+ show(plan(registry, screen));
59
+ }
60
+ ```
61
+
62
+ - Register a placeholder for an island with `registry.registerPlaceholder(Descriptor, () => …)`:
63
+ `plan` shows it while the island is pending. Without one, the island is left out until it arrives.
64
+ - An island the stream never brings (the connection dropped) arrives as an error, `incomplete`,
65
+ retryable.
66
+ - `collectScreen(stream)` reads the rest and returns the whole screen.
67
+ - The body is read as it comes when your `fetch` gives a readable stream (browsers, Node, Deno, Bun,
68
+ and `expo/fetch` in React Native). React Native's built-in `fetch` doesn't, so there the screen
69
+ arrives all at once.
44
70
 
45
71
  ## Actions
46
72
 
@@ -78,7 +104,10 @@ resolves the island again from its first page. The React binding's `usePages` do
78
104
  `@client-compose/client/testing` is a fake composer for tests, with no test framework of its own.
79
105
  `createFakeGateway` answers screen and action requests from handlers and records them; pass its
80
106
  `fetch` to the client. Build responses with `island`, `islandError`, `screen`, `screenError`,
81
- `actionOk`, `actionError` and `actionFailure`, typed by the generated descriptors.
107
+ `actionOk`, `actionError` and `actionFailure`, typed by the generated descriptors. A `screen` is
108
+ sent whole (a head and an end); to control when each island arrives, answer with
109
+ `streamedScreen(id, [island(…), pending(key, Descriptor)])`, then call its `send(entry)`, `end()`,
110
+ or `cut()` for a dropped connection.
82
111
 
83
112
  ```ts
84
113
  import { actionError, createFakeGateway } from "@client-compose/client/testing";
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type ActionDescriptor, type ActionRequest, type ActionResponse, type Capabilities, type ClientContext, type DeclaredError, type IslandDescriptor, type IslandEntry, type IslandRequest, type ScreenRequest, type ScreenResponse } from "@client-compose/protocol";
1
+ import { type ActionDescriptor, type ActionRequest, type ActionResponse, type Capabilities, type ClientContext, type DeclaredError, type IslandDescriptor, type IslandEntry, type IslandRequest, type ScreenHead, type ScreenRequest, type ScreenResponse } from "@client-compose/protocol";
2
2
  type OkEntry<P = unknown> = IslandEntry<P> & {
3
3
  status: "ok";
4
4
  };
@@ -6,8 +6,18 @@ type ErrorEntry = IslandEntry & {
6
6
  status: "error";
7
7
  };
8
8
  export type IslandRenderer<R, P = unknown> = (props: P, entry: OkEntry<P>) => R;
9
+ /** What a client shows for an island still pending in a stream's head (spec §4.6). */
10
+ export type IslandPlaceholder<R> = () => R;
9
11
  export declare class IslandRegistry<R> {
10
12
  private renderers;
13
+ private placeholders;
14
+ /**
15
+ * Register a placeholder for an island version, shown while it's pending in a stream's head
16
+ * (spec §4.6). Each app draws its own: the protocol says nothing about how one looks.
17
+ */
18
+ registerPlaceholder(island: IslandDescriptor<unknown>, placeholder: IslandPlaceholder<R>): this;
19
+ /** The placeholder for an island version, if one was registered. */
20
+ placeholder(type: string, version: number): IslandPlaceholder<R> | undefined;
11
21
  /** Register a renderer for a generated island descriptor: `register(ProfileHeaderV2, (props) => …)`. */
12
22
  register<P>(island: IslandDescriptor<P>, render: IslandRenderer<R, P>): this;
13
23
  register<P>(type: string, version: number, render: IslandRenderer<R, P>): this;
@@ -19,6 +29,8 @@ export declare function buildRequest(registry: IslandRegistry<unknown>, screen:
19
29
  export interface PlannedIsland<R> {
20
30
  key: string;
21
31
  render: () => R;
32
+ /** It's a placeholder, for an island still pending in a stream's head (spec §4.6). */
33
+ pending?: boolean;
22
34
  }
23
35
  export type SkipReason = "unknown_island" | "unknown_status";
24
36
  export interface PlanOptions<R> {
@@ -27,8 +39,11 @@ export interface PlanOptions<R> {
27
39
  /** Called for islands the client can't render (spec §4.4). Useful for telemetry. */
28
40
  onSkipped?: (entry: IslandEntry, reason: SkipReason) => void;
29
41
  }
30
- /** Turn a response into an ordered list of renderable islands. */
31
- export declare function plan<R>(registry: IslandRegistry<R>, response: ScreenResponse, options?: PlanOptions<R>): PlannedIsland<R>[];
42
+ /**
43
+ * Turn a screen, or a stream's head (spec §4.6), into an ordered list of renderable islands. An
44
+ * island still pending is its registered placeholder, or left out until it arrives.
45
+ */
46
+ export declare function plan<R>(registry: IslandRegistry<R>, response: ScreenResponse | ScreenHead, options?: PlanOptions<R>): PlannedIsland<R>[];
32
47
  export declare class ScreenFetchError extends Error {
33
48
  readonly status: number;
34
49
  readonly body: string;
@@ -36,7 +51,33 @@ export declare class ScreenFetchError extends Error {
36
51
  readonly code: string | undefined;
37
52
  constructor(status: number, body: string);
38
53
  }
54
+ /**
55
+ * Fetch a screen, all of it: its stream (spec §4.6) read to the end. Throws ScreenFetchError for a
56
+ * non-2xx response (e.g. `not_found`) or one that isn't a screen. To show its islands as they
57
+ * arrive, use openScreen.
58
+ */
39
59
  export declare function fetchScreen(baseUrl: string, request: ScreenRequest, init?: RequestInit, fetchImpl?: typeof fetch): Promise<ScreenResponse>;
60
+ /** A screen as it arrives: its head, then each pending island as the composer resolves it. */
61
+ export interface ScreenStream {
62
+ /** The screen, its islands resolved or pending. */
63
+ head: ScreenHead;
64
+ /**
65
+ * Each pending island's entry, as it arrives. If the stream ends early, those that never came
66
+ * arrive as errors: `incomplete`, retryable.
67
+ */
68
+ islands: AsyncIterable<IslandEntry>;
69
+ }
70
+ /**
71
+ * Request a screen, and resolve once its head has arrived. Throws ScreenFetchError for a non-2xx
72
+ * response (e.g. `not_found`) or one that isn't a screen's stream.
73
+ */
74
+ export declare function openScreen(baseUrl: string, request: ScreenRequest, init?: RequestInit, fetchImpl?: typeof fetch): Promise<ScreenStream>;
75
+ /** Reads the rest of a stream, and returns the screen with every island in place. */
76
+ export declare function collectScreen(stream: ScreenStream): Promise<ScreenResponse>;
77
+ /** The head with a pending island's entry in its place; unchanged if the key isn't pending. */
78
+ export declare function withIsland(head: ScreenHead, entry: IslandEntry): ScreenHead;
79
+ /** A screen's head and end as a stream, for a screen that's already complete (spec §4.6). */
80
+ export declare function screenLines(screen: ScreenResponse): string;
40
81
  /**
41
82
  * A request for one island of a screen: the page `cursor` asks for (an entry's `next`), or the
42
83
  * island from its first page without one. `params` are the screen's own.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -3,6 +3,19 @@
3
3
  import { PROTOCOL_VERSION, } from "@client-compose/protocol";
4
4
  export class IslandRegistry {
5
5
  renderers = new Map();
6
+ placeholders = new Map();
7
+ /**
8
+ * Register a placeholder for an island version, shown while it's pending in a stream's head
9
+ * (spec §4.6). Each app draws its own: the protocol says nothing about how one looks.
10
+ */
11
+ registerPlaceholder(island, placeholder) {
12
+ this.placeholders.set(`${island.type}@${island.version}`, placeholder);
13
+ return this;
14
+ }
15
+ /** The placeholder for an island version, if one was registered. */
16
+ placeholder(type, version) {
17
+ return this.placeholders.get(`${type}@${version}`);
18
+ }
6
19
  register(islandOrType, versionOrRender, maybeRender) {
7
20
  if (typeof islandOrType !== "string") {
8
21
  if (typeof versionOrRender === "number") {
@@ -43,10 +56,26 @@ export function buildRequest(registry, screen, client, params) {
43
56
  islands: registry.capabilities(),
44
57
  };
45
58
  }
46
- /** Turn a response into an ordered list of renderable islands. */
59
+ /**
60
+ * Turn a screen, or a stream's head (spec §4.6), into an ordered list of renderable islands. An
61
+ * island still pending is its registered placeholder, or left out until it arrives.
62
+ */
47
63
  export function plan(registry, response, options = {}) {
48
64
  const out = [];
49
65
  for (const entry of response.islands) {
66
+ if (entry.status === "pending") {
67
+ const placeholder = registry.get(entry.type, entry.version)
68
+ ? registry.placeholder(entry.type, entry.version)
69
+ : undefined;
70
+ if (placeholder) {
71
+ out.push({
72
+ key: entry.key,
73
+ render: placeholder,
74
+ pending: true,
75
+ });
76
+ }
77
+ continue;
78
+ }
50
79
  if (entry.status === "error") {
51
80
  const fallback = options.onError?.(entry);
52
81
  if (fallback !== undefined) {
@@ -87,12 +116,6 @@ function isIslandEntry(value) {
87
116
  const named = typeof value.key === "string" && typeof value.type === "string";
88
117
  return named && typeof value.version === "number" && typeof value.status === "string";
89
118
  }
90
- function isScreenResponse(value) {
91
- if (!isRecord(value) || typeof value.screen !== "string") {
92
- return false;
93
- }
94
- return Array.isArray(value.islands) && value.islands.every(isIslandEntry);
95
- }
96
119
  /** An action's outcome: what a client needs of one is its status (the client fixtures, spec §8.2). */
97
120
  function isActionResponse(value) {
98
121
  return isRecord(value) && (value.status === "ok" || value.status === "error");
@@ -131,22 +154,126 @@ function jsonHeaders(init) {
131
154
  }
132
155
  return headers;
133
156
  }
157
+ /**
158
+ * Fetch a screen, all of it: its stream (spec §4.6) read to the end. Throws ScreenFetchError for a
159
+ * non-2xx response (e.g. `not_found`) or one that isn't a screen. To show its islands as they
160
+ * arrive, use openScreen.
161
+ */
134
162
  export async function fetchScreen(baseUrl, request, init = {}, fetchImpl = fetch) {
163
+ return collectScreen(await openScreen(baseUrl, request, init, fetchImpl));
164
+ }
165
+ /**
166
+ * Request a screen, and resolve once its head has arrived. Throws ScreenFetchError for a non-2xx
167
+ * response (e.g. `not_found`) or one that isn't a screen's stream.
168
+ */
169
+ export async function openScreen(baseUrl, request, init = {}, fetchImpl = fetch) {
135
170
  const res = await fetchImpl(`${baseUrl}/screens/${encodeURIComponent(request.screen)}`, {
136
171
  ...init,
137
172
  method: "POST",
138
173
  headers: jsonHeaders(init.headers),
139
174
  body: JSON.stringify(request),
140
175
  });
141
- const text = await res.text();
142
176
  if (!res.ok) {
143
- throw new ScreenFetchError(res.status, text);
177
+ throw new ScreenFetchError(res.status, await res.text());
144
178
  }
145
- const response = parseJson(text);
146
- if (!isScreenResponse(response)) {
147
- throw new ScreenFetchError(res.status, text);
179
+ const lines = linesOf(res)[Symbol.asyncIterator]();
180
+ const first = await lines.next();
181
+ const head = first.done ? undefined : parseJson(first.value);
182
+ if (!isRecord(head) || head.kind !== "head" || !isScreenHead(head)) {
183
+ await lines.return?.();
184
+ throw new ScreenFetchError(res.status, first.done ? "" : first.value);
185
+ }
186
+ const { kind: _kind, ...screen } = head;
187
+ return { head: screen, islands: pendingIslands(screen, lines) };
188
+ }
189
+ /** Reads the rest of a stream, and returns the screen with every island in place. */
190
+ export async function collectScreen(stream) {
191
+ let head = stream.head;
192
+ for await (const entry of stream.islands) {
193
+ head = withIsland(head, entry);
194
+ }
195
+ return {
196
+ ...head,
197
+ islands: head.islands.filter((e) => e.status !== "pending"),
198
+ };
199
+ }
200
+ /** The head with a pending island's entry in its place; unchanged if the key isn't pending. */
201
+ export function withIsland(head, entry) {
202
+ return {
203
+ ...head,
204
+ islands: head.islands.map((e) => (e.key === entry.key && e.status === "pending" ? entry : e)),
205
+ };
206
+ }
207
+ /** A screen's head and end as a stream, for a screen that's already complete (spec §4.6). */
208
+ export function screenLines(screen) {
209
+ return `${JSON.stringify({ kind: "head", ...screen })}\n${JSON.stringify({ kind: "end" })}\n`;
210
+ }
211
+ function isScreenHead(value) {
212
+ return (typeof value.screen === "string" &&
213
+ Array.isArray(value.islands) &&
214
+ value.islands.every(isIslandEntry));
215
+ }
216
+ /** The islands pending in `head`, as `lines` bring them, until the end line. */
217
+ async function* pendingIslands(head, lines) {
218
+ const waiting = new Map(head.islands.filter((e) => e.status === "pending").map((e) => [e.key, e]));
219
+ try {
220
+ while (waiting.size > 0) {
221
+ const next = await lines.next();
222
+ if (next.done) {
223
+ break;
224
+ }
225
+ const line = parseJson(next.value);
226
+ if (!isRecord(line) || line.kind === "end") {
227
+ break;
228
+ }
229
+ // Lines of a kind it doesn't know, or for an island that isn't pending, are skipped (spec §4.6).
230
+ const entry = line.kind === "island" && isRecord(line.island) ? line.island : undefined;
231
+ if (entry?.status !== "pending" && isIslandEntry(entry) && waiting.delete(entry.key)) {
232
+ yield entry;
233
+ }
234
+ }
235
+ }
236
+ finally {
237
+ await lines.return?.();
238
+ }
239
+ for (const e of waiting.values()) {
240
+ yield {
241
+ key: e.key,
242
+ type: e.type,
243
+ version: e.version,
244
+ status: "error",
245
+ error: { code: "incomplete", retryable: true },
246
+ };
247
+ }
248
+ }
249
+ /** A body's lines, as they arrive if the body can be read as a stream, or all at once. */
250
+ async function* linesOf(res) {
251
+ if (!res.body) {
252
+ yield* (await res.text()).split("\n").filter((line) => line !== "");
253
+ return;
254
+ }
255
+ const reader = res.body.getReader();
256
+ const decoder = new TextDecoder();
257
+ let buffered = "";
258
+ try {
259
+ for (;;) {
260
+ const { done, value } = await reader.read();
261
+ if (done) {
262
+ break;
263
+ }
264
+ buffered += decoder.decode(value, { stream: true });
265
+ const lines = buffered.split("\n");
266
+ buffered = lines.pop() ?? "";
267
+ yield* lines.filter((line) => line !== "");
268
+ }
269
+ buffered += decoder.decode();
270
+ if (buffered.trim() !== "") {
271
+ yield buffered;
272
+ }
273
+ }
274
+ finally {
275
+ await reader.cancel().catch(() => undefined);
148
276
  }
149
- return response;
150
277
  }
151
278
  // ---- Island requests (spec §4.5) ----
152
279
  /**
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/testing.d.ts CHANGED
@@ -1,8 +1,13 @@
1
- import { type ActionDescriptor, type ActionEffects, type Capabilities, type ClientContext, type DeclaredError, type IslandDescriptor, type IslandEntry, type IslandError, type ScreenMeta } from "@client-compose/protocol";
2
- /** A response for the fake composer to send. */
1
+ import { type ActionDescriptor, type ActionEffects, type Capabilities, type ClientContext, type DeclaredError, type IslandDescriptor, type IslandEntry, type IslandError, type PendingIsland, type ScreenMeta } from "@client-compose/protocol";
2
+ /**
3
+ * A response for the fake composer to send: a JSON body, or a screen's stream (spec §4.6), as
4
+ * lines that come when they're given.
5
+ */
3
6
  export interface FakeResponse {
4
7
  status: number;
5
- body: unknown;
8
+ body?: unknown;
9
+ /** Opens the stream's body, for each request answered with it. */
10
+ stream?: () => ReadableStream<Uint8Array>;
6
11
  }
7
12
  /** A request the fake composer received. */
8
13
  export interface RecordedRequest {
@@ -72,8 +77,29 @@ export declare function installFakeGateway(handlers?: FakeGatewayHandlers): Inst
72
77
  export declare function island<P>(key: string, descriptor: IslandDescriptor<P>, props: P, next?: string): IslandEntry<P>;
73
78
  /** An island that failed on the composer (spec §3.4). */
74
79
  export declare function islandError(key: string, descriptor: IslandDescriptor<unknown>, error: IslandError): IslandEntry;
75
- /** A screen response. */
80
+ /** A screen, all of it at once: its stream's head with every island, then its end (spec §4.6). */
76
81
  export declare function screen(id: string, islands: IslandEntry<unknown>[], meta?: ScreenMeta): FakeResponse;
82
+ /** An island still being resolved, in a streamed screen's head (spec §4.6). */
83
+ export declare function pending(key: string, descriptor: IslandDescriptor<unknown>): PendingIsland;
84
+ /** A streamed screen whose lines a test sends, so it controls when each island arrives. */
85
+ export interface StreamedScreen extends FakeResponse {
86
+ /** Sends a pending island's entry. */
87
+ send(entry: IslandEntry<unknown>): void;
88
+ /** Sends the end line. */
89
+ end(): void;
90
+ /** Ends the stream without its end line, as a dropped connection would. */
91
+ cut(): void;
92
+ }
93
+ /**
94
+ * A screen whose head is sent at once, with its islands resolved or `pending(…)`, and whose other
95
+ * lines are sent when the test says (spec §4.6). Answer one request with it.
96
+ *
97
+ * const results = streamedScreen("search", [island("box", BoxV1, {}), pending("results", ResultsV1)]);
98
+ * // render, check the placeholder, then:
99
+ * results.send(island("results", ResultsV1, { items: [] }));
100
+ * results.end();
101
+ */
102
+ export declare function streamedScreen(id: string, islands: (IslandEntry<unknown> | PendingIsland)[], meta?: ScreenMeta): StreamedScreen;
77
103
  /** An island response (spec §4.5): a page of one island, or the island resolved again. */
78
104
  export declare function islandResponse(screen: string, entry: IslandEntry<unknown>): FakeResponse;
79
105
  /** A screen request that fails, e.g. `screenError(404, "not_found")` or `screenError(401, "unauthenticated")`. */
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
package/dist/testing.js CHANGED
@@ -111,6 +111,12 @@ function asActionRequest(request) {
111
111
  };
112
112
  }
113
113
  function respond(response) {
114
+ if (response.stream) {
115
+ return new Response(response.stream(), {
116
+ status: response.status,
117
+ headers: { "content-type": "application/jsonl" },
118
+ });
119
+ }
114
120
  return new Response(JSON.stringify(response.body), {
115
121
  status: response.status,
116
122
  headers: { "content-type": "application/json" },
@@ -196,18 +202,95 @@ export function islandError(key, descriptor, error) {
196
202
  error,
197
203
  };
198
204
  }
199
- /** A screen response. */
205
+ /** A screen, all of it at once: its stream's head with every island, then its end (spec §4.6). */
200
206
  export function screen(id, islands, meta) {
207
+ const head = {
208
+ kind: "head",
209
+ protocol: PROTOCOL_VERSION,
210
+ screen: id,
211
+ islands,
212
+ ...(meta && { meta }),
213
+ };
201
214
  return {
202
215
  status: 200,
203
- body: {
204
- protocol: PROTOCOL_VERSION,
205
- screen: id,
206
- islands,
207
- ...(meta && { meta }),
216
+ stream: () => linesStream([head, { kind: "end" }]),
217
+ };
218
+ }
219
+ /** An island still being resolved, in a streamed screen's head (spec §4.6). */
220
+ export function pending(key, descriptor) {
221
+ return {
222
+ key,
223
+ type: descriptor.type,
224
+ version: descriptor.version,
225
+ status: "pending",
226
+ };
227
+ }
228
+ /**
229
+ * A screen whose head is sent at once, with its islands resolved or `pending(…)`, and whose other
230
+ * lines are sent when the test says (spec §4.6). Answer one request with it.
231
+ *
232
+ * const results = streamedScreen("search", [island("box", BoxV1, {}), pending("results", ResultsV1)]);
233
+ * // render, check the placeholder, then:
234
+ * results.send(island("results", ResultsV1, { items: [] }));
235
+ * results.end();
236
+ */
237
+ export function streamedScreen(id, islands, meta) {
238
+ const encoder = new TextEncoder();
239
+ const queued = [];
240
+ let controller;
241
+ let closed = false;
242
+ const write = (line) => {
243
+ const text = `${JSON.stringify(line)}\n`;
244
+ if (controller) {
245
+ controller.enqueue(encoder.encode(text));
246
+ }
247
+ else {
248
+ queued.push(text);
249
+ }
250
+ };
251
+ const close = () => {
252
+ closed = true;
253
+ controller?.close();
254
+ };
255
+ write({
256
+ kind: "head",
257
+ protocol: PROTOCOL_VERSION,
258
+ screen: id,
259
+ islands,
260
+ ...(meta && { meta }),
261
+ });
262
+ return {
263
+ status: 200,
264
+ stream: () => new ReadableStream({
265
+ start(c) {
266
+ controller = c;
267
+ for (const text of queued.splice(0)) {
268
+ c.enqueue(encoder.encode(text));
269
+ }
270
+ if (closed) {
271
+ c.close();
272
+ }
273
+ },
274
+ }),
275
+ send: (entry) => write({ kind: "island", island: entry }),
276
+ end: () => {
277
+ write({ kind: "end" });
278
+ close();
208
279
  },
280
+ cut: close,
209
281
  };
210
282
  }
283
+ function linesStream(lines) {
284
+ const encoder = new TextEncoder();
285
+ return new ReadableStream({
286
+ start(controller) {
287
+ for (const line of lines) {
288
+ controller.enqueue(encoder.encode(`${JSON.stringify(line)}\n`));
289
+ }
290
+ controller.close();
291
+ },
292
+ });
293
+ }
211
294
  /** An island response (spec §4.5): a page of one island, or the island resolved again. */
212
295
  export function islandResponse(screen, entry) {
213
296
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,8FAA8F;AAC9F,yFAAyF;AACzF,EAAE;AACF,0CAA0C;AAC1C,6GAA6G;AAC7G,6EAA6E;AAC7E,+GAA+G;AAC/G,UAAU;AACV,2FAA2F;AAC3F,EAAE;AACF,0FAA0F;AAE1F,OAAO,EASL,gBAAgB,GAEjB,MAAM,0BAA0B,CAAC;AAgElC,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CACpE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAEvE,SAAS,OAAO,CAAC,KAAc;IAC7B,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAyB,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CACrF,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC;QAC9C,IAAI;QACJ,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;KAC1F,CAAC,CACH,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IACE,CAAC,QAAQ,CAAC,KAAK,CAAC;QAChB,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ;QAClC,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,EACpC,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO;QACL,GAAG,KAAK;QACR,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,UAAU,EAAE,KAAK,CAAC,UAAU;KACZ,CAAC;AACrB,CAAC;AAED,SAAS,SAAS,CAAC,IAAa;IAC9B,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,KAAK,CAAC,KAAwB;IACrC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,KAAK,YAAY,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;AACvD,CAAC;AAED,SAAS,SAAS,CAAC,IAA6B;IAC9C,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IAChE,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,mCAAmC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,eAAe,CAAC,OAAwB;IAC/C,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACzB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChF,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACpE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO;QACL,GAAG,OAAO;QACV,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;QAC5B,MAAM,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;QAClC,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC;KACpC,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,OAAwB;IAC/C,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACzB,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACjD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO;QACL,GAAG,OAAO;QACV,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,OAAO,EAAE,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC5D,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;QAC5B,MAAM,EAAE,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QACjE,MAAM,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;KACnC,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,OAAwB;IAC/C,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACzB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC7F,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO;QACL,GAAG,OAAO;QACV,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,OAAO,EAAE,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC5D,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,MAAM,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;QAClC,cAAc,EAAE,OAAO,IAAI,CAAC,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS;KAC1F,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,QAAsB;IACrC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;QACjD,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;KAChD,CAAC,CAAC;AACL,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,iBAAiB,CAAC,WAAgC,EAAE;IAClE,MAAM,QAAQ,GAAsB,EAAE,CAAC;IACvC,KAAK,UAAU,SAAS,CAAC,KAAwB,EAAE,IAAkB;QACnE,MAAM,OAAO,GAAoB;YAC/B,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC;YACjB,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,KAAK;YAC7B,OAAO,EAAE,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC;YACjC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC;SAC5B,CAAC;QACF,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEvB,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;QACD,MAAM,aAAa,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,aAAa,GACjB,aAAa,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,aAAa,CAAC,MAAM,IAAI,aAAa,CAAC,GAAG,EAAE,CAAC,CAAC;QACtF,IAAI,aAAa,IAAI,aAAa,EAAE,CAAC;YACnC,OAAO,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC;QAC/C,CAAC;QACD,MAAM,aAAa,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,aAAa,GAAG,aAAa,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAChF,IAAI,aAAa,IAAI,aAAa,EAAE,CAAC;YACnC,OAAO,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC;QAC/C,CAAC;QACD,MAAM,aAAa,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,aAAa,GAAG,aAAa,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAChF,IAAI,aAAa,IAAI,aAAa,EAAE,CAAC;YACnC,OAAO,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC;QAC/C,CAAC;QACD,MAAM,IAAI,KAAK,CACb,gCAAgC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAChG,CAAC;IACJ,CAAC;IACD,OAAO;QACL,KAAK,EAAE,SAAS;QAChB,QAAQ;QACR,cAAc,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACvE,cAAc,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACvE,cAAc,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;KACxE,CAAC;AACJ,CAAC;AAOD;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,WAAgC,EAAE;IACnE,MAAM,OAAO,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC;IAClC,UAAU,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IACjC,OAAO;QACL,GAAG,OAAO;QACV,OAAO,EAAE,GAAG,EAAE;YACZ,UAAU,CAAC,KAAK,GAAG,QAAQ,CAAC;QAC9B,CAAC;KACF,CAAC;AACJ,CAAC;AAED,sBAAsB;AAEtB;;;GAGG;AACH,MAAM,UAAU,MAAM,CACpB,GAAW,EACX,UAA+B,EAC/B,KAAQ,EACR,IAAa;IAEb,OAAO;QACL,GAAG;QACH,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,OAAO,EAAE,UAAU,CAAC,OAAO;QAC3B,MAAM,EAAE,IAAI;QACZ,KAAK;QACL,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC;KACpC,CAAC;AACJ,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,WAAW,CACzB,GAAW,EACX,UAAqC,EACrC,KAAkB;IAElB,OAAO;QACL,GAAG;QACH,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,OAAO,EAAE,UAAU,CAAC,OAAO;QAC3B,MAAM,EAAE,OAAO;QACf,KAAK;KACN,CAAC;AACJ,CAAC;AAED,yBAAyB;AACzB,MAAM,UAAU,MAAM,CACpB,EAAU,EACV,OAA+B,EAC/B,IAAiB;IAEjB,OAAO;QACL,MAAM,EAAE,GAAG;QACX,IAAI,EAAE;YACJ,QAAQ,EAAE,gBAAgB;YAC1B,MAAM,EAAE,EAAE;YACV,OAAO;YACP,GAAG,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,CAAC;SACtB;KACF,CAAC;AACJ,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,KAA2B;IACxE,OAAO;QACL,MAAM,EAAE,GAAG;QACX,IAAI,EAAE;YACJ,QAAQ,EAAE,gBAAgB;YAC1B,MAAM;YACN,MAAM,EAAE,KAAK;SACd;KACF,CAAC;AACJ,CAAC;AAED,kHAAkH;AAClH,MAAM,UAAU,WAAW,CAAC,MAAc,EAAE,IAAY;IACtD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,gBAAgB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AAC3E,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,QAAQ,CACtB,MAAiC,EACjC,MAAS,EACT,OAAuB;IAEvB,MAAM,IAAI,GAAG;QACX,QAAQ,EAAE,gBAAgB;QAC1B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC;IACF,OAAO;QACL,MAAM,EAAE,GAAG;QACX,IAAI,EAAE;YACJ,GAAG,IAAI;YACP,MAAM,EAAE,IAAI;YACZ,MAAM;YACN,GAAG,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,CAAC;SAC5B;KACF,CAAC;AACJ,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,WAAW,CACzB,MAAiC,EACjC,KAAQ;IAER,MAAM,IAAI,GAAG;QACX,QAAQ,EAAE,gBAAgB;QAC1B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC;IACF,OAAO;QACL,MAAM,EAAE,GAAG;QACX,IAAI,EAAE;YACJ,GAAG,IAAI;YACP,MAAM,EAAE,OAAO;YACf,KAAK;SACN;KACF,CAAC;AACJ,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,IAAY;IACxD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,gBAAgB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AAC3E,CAAC"}
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@client-compose/client",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Framework-agnostic Client Compose client: island registry, screen requests and render planning.",
5
5
  "keywords": [
6
6
  "client-compose",
@@ -44,10 +44,10 @@
44
44
  "LICENSE"
45
45
  ],
46
46
  "dependencies": {
47
- "@client-compose/protocol": "0.4.0"
47
+ "@client-compose/protocol": "0.5.0"
48
48
  },
49
49
  "devDependencies": {
50
- "@client-compose/conformance": "0.7.0"
50
+ "@client-compose/conformance": "0.8.0"
51
51
  },
52
52
  "publishConfig": {
53
53
  "access": "public"
package/src/index.ts CHANGED
@@ -13,6 +13,7 @@ import {
13
13
  type IslandRequest,
14
14
  type IslandResponse,
15
15
  PROTOCOL_VERSION,
16
+ type ScreenHead,
16
17
  type ScreenRequest,
17
18
  type ScreenResponse,
18
19
  } from "@client-compose/protocol";
@@ -22,8 +23,26 @@ type ErrorEntry = IslandEntry & { status: "error" };
22
23
 
23
24
  export type IslandRenderer<R, P = unknown> = (props: P, entry: OkEntry<P>) => R;
24
25
 
26
+ /** What a client shows for an island still pending in a stream's head (spec §4.6). */
27
+ export type IslandPlaceholder<R> = () => R;
28
+
25
29
  export class IslandRegistry<R> {
26
30
  private renderers = new Map<string, Map<number, IslandRenderer<R>>>();
31
+ private placeholders = new Map<string, IslandPlaceholder<R>>();
32
+
33
+ /**
34
+ * Register a placeholder for an island version, shown while it's pending in a stream's head
35
+ * (spec §4.6). Each app draws its own: the protocol says nothing about how one looks.
36
+ */
37
+ registerPlaceholder(island: IslandDescriptor<unknown>, placeholder: IslandPlaceholder<R>): this {
38
+ this.placeholders.set(`${island.type}@${island.version}`, placeholder);
39
+ return this;
40
+ }
41
+
42
+ /** The placeholder for an island version, if one was registered. */
43
+ placeholder(type: string, version: number): IslandPlaceholder<R> | undefined {
44
+ return this.placeholders.get(`${type}@${version}`);
45
+ }
27
46
 
28
47
  /** Register a renderer for a generated island descriptor: `register(ProfileHeaderV2, (props) => …)`. */
29
48
  register<P>(island: IslandDescriptor<P>, render: IslandRenderer<R, P>): this;
@@ -87,6 +106,8 @@ export function buildRequest(
87
106
  export interface PlannedIsland<R> {
88
107
  key: string;
89
108
  render: () => R;
109
+ /** It's a placeholder, for an island still pending in a stream's head (spec §4.6). */
110
+ pending?: boolean;
90
111
  }
91
112
 
92
113
  export type SkipReason = "unknown_island" | "unknown_status";
@@ -98,14 +119,30 @@ export interface PlanOptions<R> {
98
119
  onSkipped?: (entry: IslandEntry, reason: SkipReason) => void;
99
120
  }
100
121
 
101
- /** Turn a response into an ordered list of renderable islands. */
122
+ /**
123
+ * Turn a screen, or a stream's head (spec §4.6), into an ordered list of renderable islands. An
124
+ * island still pending is its registered placeholder, or left out until it arrives.
125
+ */
102
126
  export function plan<R>(
103
127
  registry: IslandRegistry<R>,
104
- response: ScreenResponse,
128
+ response: ScreenResponse | ScreenHead,
105
129
  options: PlanOptions<R> = {},
106
130
  ): PlannedIsland<R>[] {
107
131
  const out: PlannedIsland<R>[] = [];
108
132
  for (const entry of response.islands) {
133
+ if (entry.status === "pending") {
134
+ const placeholder = registry.get(entry.type, entry.version)
135
+ ? registry.placeholder(entry.type, entry.version)
136
+ : undefined;
137
+ if (placeholder) {
138
+ out.push({
139
+ key: entry.key,
140
+ render: placeholder,
141
+ pending: true,
142
+ });
143
+ }
144
+ continue;
145
+ }
109
146
  if (entry.status === "error") {
110
147
  const fallback = options.onError?.(entry);
111
148
  if (fallback !== undefined) {
@@ -150,13 +187,6 @@ function isIslandEntry(value: unknown): value is IslandEntry {
150
187
  return named && typeof value.version === "number" && typeof value.status === "string";
151
188
  }
152
189
 
153
- function isScreenResponse(value: unknown): value is ScreenResponse {
154
- if (!isRecord(value) || typeof value.screen !== "string") {
155
- return false;
156
- }
157
- return Array.isArray(value.islands) && value.islands.every(isIslandEntry);
158
- }
159
-
160
190
  /** An action's outcome: what a client needs of one is its status (the client fixtures, spec §8.2). */
161
191
  function isActionResponse(value: unknown): value is ActionResponse {
162
192
  return isRecord(value) && (value.status === "ok" || value.status === "error");
@@ -199,27 +229,163 @@ function jsonHeaders(init: HeadersInit | undefined): Headers {
199
229
  return headers;
200
230
  }
201
231
 
232
+ /**
233
+ * Fetch a screen, all of it: its stream (spec §4.6) read to the end. Throws ScreenFetchError for a
234
+ * non-2xx response (e.g. `not_found`) or one that isn't a screen. To show its islands as they
235
+ * arrive, use openScreen.
236
+ */
202
237
  export async function fetchScreen(
203
238
  baseUrl: string,
204
239
  request: ScreenRequest,
205
240
  init: RequestInit = {},
206
241
  fetchImpl: typeof fetch = fetch,
207
242
  ): Promise<ScreenResponse> {
243
+ return collectScreen(await openScreen(baseUrl, request, init, fetchImpl));
244
+ }
245
+
246
+ // ---- Streams (spec §4.6) ----
247
+
248
+ /** A screen as it arrives: its head, then each pending island as the composer resolves it. */
249
+ export interface ScreenStream {
250
+ /** The screen, its islands resolved or pending. */
251
+ head: ScreenHead;
252
+ /**
253
+ * Each pending island's entry, as it arrives. If the stream ends early, those that never came
254
+ * arrive as errors: `incomplete`, retryable.
255
+ */
256
+ islands: AsyncIterable<IslandEntry>;
257
+ }
258
+
259
+ /**
260
+ * Request a screen, and resolve once its head has arrived. Throws ScreenFetchError for a non-2xx
261
+ * response (e.g. `not_found`) or one that isn't a screen's stream.
262
+ */
263
+ export async function openScreen(
264
+ baseUrl: string,
265
+ request: ScreenRequest,
266
+ init: RequestInit = {},
267
+ fetchImpl: typeof fetch = fetch,
268
+ ): Promise<ScreenStream> {
208
269
  const res = await fetchImpl(`${baseUrl}/screens/${encodeURIComponent(request.screen)}`, {
209
270
  ...init,
210
271
  method: "POST",
211
272
  headers: jsonHeaders(init.headers),
212
273
  body: JSON.stringify(request),
213
274
  });
214
- const text = await res.text();
215
275
  if (!res.ok) {
216
- throw new ScreenFetchError(res.status, text);
276
+ throw new ScreenFetchError(res.status, await res.text());
217
277
  }
218
- const response = parseJson(text);
219
- if (!isScreenResponse(response)) {
220
- throw new ScreenFetchError(res.status, text);
278
+ const lines = linesOf(res)[Symbol.asyncIterator]();
279
+ const first = await lines.next();
280
+ const head = first.done ? undefined : parseJson(first.value);
281
+ if (!isRecord(head) || head.kind !== "head" || !isScreenHead(head)) {
282
+ await lines.return?.();
283
+ throw new ScreenFetchError(res.status, first.done ? "" : first.value);
284
+ }
285
+ const { kind: _kind, ...screen } = head;
286
+ return { head: screen, islands: pendingIslands(screen, lines) };
287
+ }
288
+
289
+ /** Reads the rest of a stream, and returns the screen with every island in place. */
290
+ export async function collectScreen(stream: ScreenStream): Promise<ScreenResponse> {
291
+ let head = stream.head;
292
+ for await (const entry of stream.islands) {
293
+ head = withIsland(head, entry);
294
+ }
295
+ return {
296
+ ...head,
297
+ islands: head.islands.filter((e): e is IslandEntry => e.status !== "pending"),
298
+ };
299
+ }
300
+
301
+ /** The head with a pending island's entry in its place; unchanged if the key isn't pending. */
302
+ export function withIsland(head: ScreenHead, entry: IslandEntry): ScreenHead {
303
+ return {
304
+ ...head,
305
+ islands: head.islands.map((e) => (e.key === entry.key && e.status === "pending" ? entry : e)),
306
+ };
307
+ }
308
+
309
+ /** A screen's head and end as a stream, for a screen that's already complete (spec §4.6). */
310
+ export function screenLines(screen: ScreenResponse): string {
311
+ return `${JSON.stringify({ kind: "head", ...screen })}\n${JSON.stringify({ kind: "end" })}\n`;
312
+ }
313
+
314
+ function isScreenHead(
315
+ value: Record<string, unknown>,
316
+ ): value is Record<string, unknown> & ScreenHead {
317
+ return (
318
+ typeof value.screen === "string" &&
319
+ Array.isArray(value.islands) &&
320
+ value.islands.every(isIslandEntry)
321
+ );
322
+ }
323
+
324
+ /** The islands pending in `head`, as `lines` bring them, until the end line. */
325
+ async function* pendingIslands(
326
+ head: ScreenHead,
327
+ lines: AsyncIterator<string>,
328
+ ): AsyncIterable<IslandEntry> {
329
+ const waiting = new Map(
330
+ head.islands.filter((e) => e.status === "pending").map((e) => [e.key, e]),
331
+ );
332
+ try {
333
+ while (waiting.size > 0) {
334
+ const next = await lines.next();
335
+ if (next.done) {
336
+ break;
337
+ }
338
+ const line = parseJson(next.value);
339
+ if (!isRecord(line) || line.kind === "end") {
340
+ break;
341
+ }
342
+ // Lines of a kind it doesn't know, or for an island that isn't pending, are skipped (spec §4.6).
343
+ const entry = line.kind === "island" && isRecord(line.island) ? line.island : undefined;
344
+ if (entry?.status !== "pending" && isIslandEntry(entry) && waiting.delete(entry.key)) {
345
+ yield entry;
346
+ }
347
+ }
348
+ } finally {
349
+ await lines.return?.();
350
+ }
351
+ for (const e of waiting.values()) {
352
+ yield {
353
+ key: e.key,
354
+ type: e.type,
355
+ version: e.version,
356
+ status: "error",
357
+ error: { code: "incomplete", retryable: true },
358
+ };
359
+ }
360
+ }
361
+
362
+ /** A body's lines, as they arrive if the body can be read as a stream, or all at once. */
363
+ async function* linesOf(res: Response): AsyncIterable<string> {
364
+ if (!res.body) {
365
+ yield* (await res.text()).split("\n").filter((line) => line !== "");
366
+ return;
367
+ }
368
+ const reader = res.body.getReader();
369
+ const decoder = new TextDecoder();
370
+ let buffered = "";
371
+ try {
372
+ for (;;) {
373
+ const { done, value } = await reader.read();
374
+ if (done) {
375
+ break;
376
+ }
377
+ buffered += decoder.decode(value, { stream: true });
378
+ const lines = buffered.split("\n");
379
+ buffered = lines.pop() ?? "";
380
+ yield* lines.filter((line) => line !== "");
381
+ }
382
+ buffered += decoder.decode();
383
+ if (buffered.trim() !== "") {
384
+ yield buffered;
385
+ }
386
+ } finally {
387
+ await reader.cancel().catch(() => undefined);
221
388
  }
222
- return response;
223
389
  }
224
390
 
225
391
  // ---- Island requests (spec §4.5) ----
package/src/testing.ts CHANGED
@@ -20,14 +20,20 @@ import {
20
20
  type IslandDescriptor,
21
21
  type IslandEntry,
22
22
  type IslandError,
23
+ type PendingIsland,
23
24
  PROTOCOL_VERSION,
24
25
  type ScreenMeta,
25
26
  } from "@client-compose/protocol";
26
27
 
27
- /** A response for the fake composer to send. */
28
+ /**
29
+ * A response for the fake composer to send: a JSON body, or a screen's stream (spec §4.6), as
30
+ * lines that come when they're given.
31
+ */
28
32
  export interface FakeResponse {
29
33
  status: number;
30
- body: unknown;
34
+ body?: unknown;
35
+ /** Opens the stream's body, for each request answered with it. */
36
+ stream?: () => ReadableStream<Uint8Array>;
31
37
  }
32
38
 
33
39
  /** A request the fake composer received. */
@@ -203,6 +209,12 @@ function asActionRequest(request: RecordedRequest): RecordedActionRequest | unde
203
209
  }
204
210
 
205
211
  function respond(response: FakeResponse): Response {
212
+ if (response.stream) {
213
+ return new Response(response.stream(), {
214
+ status: response.status,
215
+ headers: { "content-type": "application/jsonl" },
216
+ });
217
+ }
206
218
  return new Response(JSON.stringify(response.body), {
207
219
  status: response.status,
208
220
  headers: { "content-type": "application/json" },
@@ -312,23 +324,117 @@ export function islandError(
312
324
  };
313
325
  }
314
326
 
315
- /** A screen response. */
327
+ /** A screen, all of it at once: its stream's head with every island, then its end (spec §4.6). */
316
328
  export function screen(
317
329
  id: string,
318
330
  islands: IslandEntry<unknown>[],
319
331
  meta?: ScreenMeta,
320
332
  ): FakeResponse {
333
+ const head = {
334
+ kind: "head",
335
+ protocol: PROTOCOL_VERSION,
336
+ screen: id,
337
+ islands,
338
+ ...(meta && { meta }),
339
+ };
321
340
  return {
322
341
  status: 200,
323
- body: {
324
- protocol: PROTOCOL_VERSION,
325
- screen: id,
326
- islands,
327
- ...(meta && { meta }),
342
+ stream: () => linesStream([head, { kind: "end" }]),
343
+ };
344
+ }
345
+
346
+ /** An island still being resolved, in a streamed screen's head (spec §4.6). */
347
+ export function pending(key: string, descriptor: IslandDescriptor<unknown>): PendingIsland {
348
+ return {
349
+ key,
350
+ type: descriptor.type,
351
+ version: descriptor.version,
352
+ status: "pending",
353
+ };
354
+ }
355
+
356
+ /** A streamed screen whose lines a test sends, so it controls when each island arrives. */
357
+ export interface StreamedScreen extends FakeResponse {
358
+ /** Sends a pending island's entry. */
359
+ send(entry: IslandEntry<unknown>): void;
360
+ /** Sends the end line. */
361
+ end(): void;
362
+ /** Ends the stream without its end line, as a dropped connection would. */
363
+ cut(): void;
364
+ }
365
+
366
+ /**
367
+ * A screen whose head is sent at once, with its islands resolved or `pending(…)`, and whose other
368
+ * lines are sent when the test says (spec §4.6). Answer one request with it.
369
+ *
370
+ * const results = streamedScreen("search", [island("box", BoxV1, {}), pending("results", ResultsV1)]);
371
+ * // render, check the placeholder, then:
372
+ * results.send(island("results", ResultsV1, { items: [] }));
373
+ * results.end();
374
+ */
375
+ export function streamedScreen(
376
+ id: string,
377
+ islands: (IslandEntry<unknown> | PendingIsland)[],
378
+ meta?: ScreenMeta,
379
+ ): StreamedScreen {
380
+ const encoder = new TextEncoder();
381
+ const queued: string[] = [];
382
+ let controller: ReadableStreamDefaultController<Uint8Array> | undefined;
383
+ let closed = false;
384
+ const write = (line: unknown) => {
385
+ const text = `${JSON.stringify(line)}\n`;
386
+ if (controller) {
387
+ controller.enqueue(encoder.encode(text));
388
+ } else {
389
+ queued.push(text);
390
+ }
391
+ };
392
+ const close = () => {
393
+ closed = true;
394
+ controller?.close();
395
+ };
396
+ write({
397
+ kind: "head",
398
+ protocol: PROTOCOL_VERSION,
399
+ screen: id,
400
+ islands,
401
+ ...(meta && { meta }),
402
+ });
403
+ return {
404
+ status: 200,
405
+ stream: () =>
406
+ new ReadableStream<Uint8Array>({
407
+ start(c) {
408
+ controller = c;
409
+ for (const text of queued.splice(0)) {
410
+ c.enqueue(encoder.encode(text));
411
+ }
412
+ if (closed) {
413
+ c.close();
414
+ }
415
+ },
416
+ }),
417
+ send: (entry) => write({ kind: "island", island: entry }),
418
+ end: () => {
419
+ write({ kind: "end" });
420
+ close();
328
421
  },
422
+ cut: close,
329
423
  };
330
424
  }
331
425
 
426
+ function linesStream(lines: unknown[]): ReadableStream<Uint8Array> {
427
+ const encoder = new TextEncoder();
428
+ return new ReadableStream({
429
+ start(controller) {
430
+ for (const line of lines) {
431
+ controller.enqueue(encoder.encode(`${JSON.stringify(line)}\n`));
432
+ }
433
+ controller.close();
434
+ },
435
+ });
436
+ }
437
+
332
438
  /** An island response (spec §4.5): a page of one island, or the island resolved again. */
333
439
  export function islandResponse(screen: string, entry: IslandEntry<unknown>): FakeResponse {
334
440
  return {