@client-compose/client 0.8.0 → 0.9.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/dist/testing.js CHANGED
@@ -6,6 +6,7 @@
6
6
  // screens: { profile: () => screen("profile", [island("header", ProfileHeaderV1, { name: "Ada" })]) },
7
7
  // actions: { follow: () => actionOk(FollowUserV1, { followers: 8 }) },
8
8
  // islands: { "profile/posts": (r) => islandResponse("profile", island("posts", PostsV1, …, "page:3")) },
9
+ // strings: () => stringsResponse("en", { retry: "Try again" }),
9
10
  // });
10
11
  // // pass gateway.fetch as the client's fetch, then assert on gateway.actionRequests()
11
12
  //
@@ -110,6 +111,13 @@ function asActionRequest(request) {
110
111
  idempotencyKey: typeof body.idempotencyKey === "string" ? body.idempotencyKey : undefined,
111
112
  };
112
113
  }
114
+ function asStringsRequest(request) {
115
+ const path = request.url.split("?")[0] ?? "";
116
+ if (!/\/strings\/?$/.test(path) || !isRecord(request.body)) {
117
+ return undefined;
118
+ }
119
+ return { ...request, client: clientContext(request.body.client) };
120
+ }
113
121
  function respond(response) {
114
122
  if (response.stream) {
115
123
  return new Response(response.stream(), {
@@ -152,6 +160,10 @@ export function createFakeGateway(handlers = {}) {
152
160
  if (actionRequest && actionHandler) {
153
161
  return respond(actionHandler(actionRequest));
154
162
  }
163
+ const stringsRequest = asStringsRequest(request);
164
+ if (stringsRequest && handlers.strings) {
165
+ return respond(handlers.strings(stringsRequest));
166
+ }
155
167
  throw new Error(`fake gateway: no handler for ${request.method} ${request.url} ${JSON.stringify(request.body)}`);
156
168
  }
157
169
  return {
@@ -160,6 +172,7 @@ export function createFakeGateway(handlers = {}) {
160
172
  screenRequests: () => requests.flatMap((r) => asScreenRequest(r) ?? []),
161
173
  islandRequests: () => requests.flatMap((r) => asIslandRequest(r) ?? []),
162
174
  actionRequests: () => requests.flatMap((r) => asActionRequest(r) ?? []),
175
+ stringsRequests: () => requests.flatMap((r) => asStringsRequest(r) ?? []),
163
176
  };
164
177
  }
165
178
  /**
@@ -177,12 +190,12 @@ export function installFakeGateway(handlers = {}) {
177
190
  },
178
191
  };
179
192
  }
180
- // ---- Responses ----
181
193
  /**
182
194
  * An island in a screen or island response, typed by its generated descriptor. Give `next` for an
183
- * island with more pages (spec §4.5).
195
+ * island with more pages (spec §4.5), or `{ next, strings }`.
184
196
  */
185
- export function island(key, descriptor, props, next) {
197
+ export function island(key, descriptor, props, more) {
198
+ const { next, strings } = typeof more === "string" ? { next: more, strings: undefined } : (more ?? {});
186
199
  return {
187
200
  key,
188
201
  type: descriptor.type,
@@ -190,6 +203,7 @@ export function island(key, descriptor, props, next) {
190
203
  status: "ok",
191
204
  props,
192
205
  ...(next !== undefined && { next }),
206
+ ...(strings !== undefined && { strings }),
193
207
  };
194
208
  }
195
209
  /** An island that failed on the composer (spec §3.4). */
@@ -203,13 +217,14 @@ export function islandError(key, descriptor, error) {
203
217
  };
204
218
  }
205
219
  /** A screen, all of it at once: its stream's head with every island, then its end (spec §4.6). */
206
- export function screen(id, islands, meta) {
220
+ export function screen(id, islands, meta, language) {
207
221
  const head = {
208
222
  kind: "head",
209
223
  protocol: PROTOCOL_VERSION,
210
224
  screen: id,
211
225
  islands,
212
226
  ...(meta && { meta }),
227
+ ...language,
213
228
  };
214
229
  return {
215
230
  status: 200,
@@ -234,7 +249,7 @@ export function pending(key, descriptor) {
234
249
  * results.send(island("results", ResultsV1, { items: [] }));
235
250
  * results.end();
236
251
  */
237
- export function streamedScreen(id, islands, meta) {
252
+ export function streamedScreen(id, islands, meta, language) {
238
253
  const encoder = new TextEncoder();
239
254
  const queued = [];
240
255
  let controller;
@@ -258,6 +273,7 @@ export function streamedScreen(id, islands, meta) {
258
273
  screen: id,
259
274
  islands,
260
275
  ...(meta && { meta }),
276
+ ...language,
261
277
  });
262
278
  return {
263
279
  status: 200,
@@ -302,6 +318,18 @@ export function islandResponse(screen, entry) {
302
318
  },
303
319
  };
304
320
  }
321
+ /** The app strings in a language (spec §4.7), with its plural rules if its counted strings need them. */
322
+ export function stringsResponse(locale, strings, plurals = {}) {
323
+ return {
324
+ status: 200,
325
+ body: {
326
+ protocol: PROTOCOL_VERSION,
327
+ locale,
328
+ plurals,
329
+ strings,
330
+ },
331
+ };
332
+ }
305
333
  /** A screen request that fails, e.g. `screenError(404, "not_found")` or `screenError(401, "unauthenticated")`. */
306
334
  export function screenError(status, code) {
307
335
  return { status, body: { protocol: PROTOCOL_VERSION, error: { code } } };
@@ -1 +1 @@
1
- {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
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.8.0",
3
+ "version": "0.9.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.5.0"
47
+ "@client-compose/protocol": "0.6.0"
48
48
  },
49
49
  "devDependencies": {
50
- "@client-compose/conformance": "0.8.0"
50
+ "@client-compose/conformance": "0.9.0"
51
51
  },
52
52
  "publishConfig": {
53
53
  "access": "public"
package/src/index.ts CHANGED
@@ -12,16 +12,40 @@ import {
12
12
  type IslandEntry,
13
13
  type IslandRequest,
14
14
  type IslandResponse,
15
+ type PluralRules,
15
16
  PROTOCOL_VERSION,
16
17
  type ScreenHead,
17
18
  type ScreenRequest,
18
19
  type ScreenResponse,
20
+ type StringParams,
19
21
  } from "@client-compose/protocol";
20
22
 
23
+ import { buildStrings } from "./strings.ts";
24
+
25
+ export {
26
+ appStrings,
27
+ buildStrings,
28
+ fetchStrings,
29
+ formatString,
30
+ pluralCategory,
31
+ StringsFetchError,
32
+ type StringValues,
33
+ } from "./strings.ts";
34
+
21
35
  type OkEntry<P = unknown> = IslandEntry<P> & { status: "ok" };
22
36
  type ErrorEntry = IslandEntry & { status: "error" };
23
37
 
24
- export type IslandRenderer<R, P = unknown> = (props: P, entry: OkEntry<P>) => R;
38
+ /**
39
+ * An island's props as its renderer gets them: with its strings as `t` (spec §4.7), if its
40
+ * descriptor declares any.
41
+ */
42
+ export type WithStrings<P, S> = P & (unknown extends S ? unknown : { t: S });
43
+
44
+ /**
45
+ * Renders an island: its props (with `t`, if it declares strings), its entry as the composer sent
46
+ * it, and the screen's plural rules (spec §4.7).
47
+ */
48
+ export type IslandRenderer<R, P = unknown> = (props: P, entry: OkEntry, plurals?: PluralRules) => R;
25
49
 
26
50
  /** What a client shows for an island still pending in a stream's head (spec §4.6). */
27
51
  export type IslandPlaceholder<R> = () => R;
@@ -29,6 +53,10 @@ export type IslandPlaceholder<R> = () => R;
29
53
  export class IslandRegistry<R> {
30
54
  private renderers = new Map<string, Map<number, IslandRenderer<R>>>();
31
55
  private placeholders = new Map<string, IslandPlaceholder<R>>();
56
+ private declaredStrings = new Map<string, StringParams>();
57
+ // Each entry's props with its `t`, made once: a screen streaming in plans again with each island
58
+ // that arrives, and the islands already shown keep the props they were rendered with.
59
+ private propsMade = new WeakMap<object, { plurals?: PluralRules; props: unknown }>();
32
60
 
33
61
  /**
34
62
  * Register a placeholder for an island version, shown while it's pending in a stream's head
@@ -44,18 +72,30 @@ export class IslandRegistry<R> {
44
72
  return this.placeholders.get(`${type}@${version}`);
45
73
  }
46
74
 
47
- /** Register a renderer for a generated island descriptor: `register(ProfileHeaderV2, (props) => …)`. */
48
- register<P>(island: IslandDescriptor<P>, render: IslandRenderer<R, P>): this;
75
+ /**
76
+ * Register a renderer for a generated island descriptor: `register(ProfileHeaderV2, (props) => …)`.
77
+ * If the island declares strings, its props have them as `t`: `props.t.heading`.
78
+ */
79
+ register<P, S>(
80
+ island: IslandDescriptor<P, S>,
81
+ render: IslandRenderer<R, WithStrings<P, S>>,
82
+ ): this;
49
83
  register<P>(type: string, version: number, render: IslandRenderer<R, P>): this;
50
- register<P>(
51
- islandOrType: IslandDescriptor<P> | string,
52
- versionOrRender: number | IslandRenderer<R, P>,
84
+ register<P, S>(
85
+ islandOrType: IslandDescriptor<P, S> | string,
86
+ versionOrRender: number | IslandRenderer<R, WithStrings<P, S>>,
53
87
  maybeRender?: IslandRenderer<R, P>,
54
88
  ): this {
55
89
  if (typeof islandOrType !== "string") {
56
90
  if (typeof versionOrRender === "number") {
57
91
  throw new Error("register(descriptor, render): pass the renderer, not a version");
58
92
  }
93
+ const id = `${islandOrType.type}@${islandOrType.version}`;
94
+ if (islandOrType.strings) {
95
+ this.declaredStrings.set(id, islandOrType.strings);
96
+ } else {
97
+ this.declaredStrings.delete(id);
98
+ }
59
99
  return this.add(islandOrType.type, islandOrType.version, versionOrRender);
60
100
  }
61
101
  if (typeof versionOrRender !== "number" || !maybeRender) {
@@ -86,6 +126,27 @@ export class IslandRegistry<R> {
86
126
  get(type: string, version: number): IslandRenderer<R> | undefined {
87
127
  return this.renderers.get(type)?.get(version);
88
128
  }
129
+
130
+ /**
131
+ * An island's props as its renderer gets them: with its strings as `t`, built with the screen's
132
+ * plural rules, if its descriptor declares any.
133
+ */
134
+ propsOf(entry: OkEntry, plurals: PluralRules | undefined): unknown {
135
+ const declared = this.declaredStrings.get(`${entry.type}@${entry.version}`);
136
+ if (!declared) {
137
+ return entry.props;
138
+ }
139
+ const made = this.propsMade.get(entry);
140
+ if (made && made.plurals === plurals) {
141
+ return made.props;
142
+ }
143
+ const props = {
144
+ ...(typeof entry.props === "object" ? entry.props : {}),
145
+ t: buildStrings(declared, entry.strings, plurals),
146
+ };
147
+ this.propsMade.set(entry, { plurals, props });
148
+ return props;
149
+ }
89
150
  }
90
151
 
91
152
  export function buildRequest(
@@ -159,7 +220,8 @@ export function plan<R>(
159
220
  options.onSkipped?.(entry, "unknown_island");
160
221
  continue;
161
222
  }
162
- out.push({ key: entry.key, render: () => renderer(entry.props, entry) });
223
+ const props = registry.propsOf(entry, response.plurals);
224
+ out.push({ key: entry.key, render: () => renderer(props, entry, response.plurals) });
163
225
  }
164
226
  return out;
165
227
  }
package/src/proxy.ts CHANGED
@@ -23,6 +23,7 @@ import {
23
23
  PROTOCOL_VERSION,
24
24
  type ScreenRequest,
25
25
  type ScreenResponse,
26
+ type StringsResponse,
26
27
  } from "@client-compose/protocol";
27
28
 
28
29
  import {
@@ -33,6 +34,7 @@ import {
33
34
  IslandFetchError,
34
35
  ScreenFetchError,
35
36
  } from "./index.ts";
37
+ import { fetchStrings, StringsFetchError } from "./strings.ts";
36
38
 
37
39
  /** A screen request from the browser: the server sets the client context. */
38
40
  export type ProxiedScreenRequest = Omit<ScreenRequest, "client">;
@@ -76,6 +78,8 @@ export interface ComposerProxy {
76
78
  * server's context and headers. Resolves with the island's entry.
77
79
  */
78
80
  loadIsland(body: unknown): Promise<ProxyResult<IslandEntry>>;
81
+ /** Loads the app strings (spec §4.7) in the server's client context's language. */
82
+ loadStrings(): Promise<ProxyResult<StringsResponse>>;
79
83
  }
80
84
 
81
85
  const isRecord = (value: unknown): value is Record<string, unknown> =>
@@ -221,9 +225,33 @@ export function createComposerProxy(options: ComposerProxyOptions): ComposerProx
221
225
  }
222
226
  }
223
227
 
228
+ async function loadStrings(): Promise<ProxyResult<StringsResponse>> {
229
+ try {
230
+ return {
231
+ ok: true,
232
+ response: await fetchStrings(
233
+ options.baseUrl,
234
+ await options.client(),
235
+ await init(),
236
+ options.fetch,
237
+ ),
238
+ };
239
+ } catch (error) {
240
+ if (error instanceof StringsFetchError) {
241
+ return {
242
+ ok: false,
243
+ status: error.status,
244
+ body: error.body,
245
+ };
246
+ }
247
+ throw error;
248
+ }
249
+ }
250
+
224
251
  return {
225
252
  performAction,
226
253
  loadScreen,
227
254
  loadIsland,
255
+ loadStrings,
228
256
  };
229
257
  }
package/src/strings.ts ADDED
@@ -0,0 +1,178 @@
1
+ // Strings (spec §4.7): the words a client shows, from the composer. Templates are filled in here,
2
+ // counted strings pick their variant by the language's plural rules, and an island's strings
3
+ // become the typed `t` its renderer receives.
4
+
5
+ import {
6
+ type AppStringsDescriptor,
7
+ type ClientContext,
8
+ type PluralRules,
9
+ PROTOCOL_VERSION,
10
+ type StringParams,
11
+ type Strings,
12
+ type StringsResponse,
13
+ type StringTemplate,
14
+ } from "@client-compose/protocol";
15
+
16
+ // ---- Plural rules ----
17
+
18
+ /** A count's plural category in a language: the first whose condition holds, or "other". */
19
+ export function pluralCategory(rules: PluralRules | undefined, count: number): string {
20
+ for (const [category, condition] of Object.entries(rules ?? {})) {
21
+ if (condition !== undefined && holds(condition, count)) {
22
+ return category;
23
+ }
24
+ }
25
+ return "other";
26
+ }
27
+
28
+ /**
29
+ * Whether a CLDR plural condition holds for a whole number: `or` of `and`s of relations like
30
+ * `i % 10 = 2..4` or `v = 0`. For a whole number, `n` and `i` are the number, and `v`, `w`, `f`,
31
+ * `t`, `c` and `e` are zero.
32
+ */
33
+ function holds(condition: string, count: number): boolean {
34
+ return condition.split(" or ").some((all) => all.split(" and ").every((r) => relates(r, count)));
35
+ }
36
+
37
+ const RELATION = /^\s*([nivwftce])\s*(?:%\s*(\d+))?\s*(!=|=)\s*(.+?)\s*$/;
38
+
39
+ function relates(relation: string, count: number): boolean {
40
+ const match = RELATION.exec(relation);
41
+ if (!match) {
42
+ return false;
43
+ }
44
+ const [, operand = "", modulus, op, ranges = ""] = match;
45
+ const base = operand === "n" || operand === "i" ? Math.abs(Math.trunc(count)) : 0;
46
+ const value = modulus === undefined ? base : base % Number(modulus);
47
+ const inRanges = ranges.split(",").some((range) => {
48
+ const [from = "", to] = range.trim().split("..");
49
+ return to === undefined ? value === Number(from) : value >= Number(from) && value <= Number(to);
50
+ });
51
+ return op === "=" ? inRanges : !inRanges;
52
+ }
53
+
54
+ // ---- Templates ----
55
+
56
+ /** The values a string's params take. A counted string's `count` picks its variant. */
57
+ export type StringValues = Record<string, string | number>;
58
+
59
+ /**
60
+ * A string's words with its params filled in. Variants are chosen by the exact count, then its
61
+ * plural category, then `#*`.
62
+ */
63
+ export function formatString(
64
+ template: StringTemplate | undefined,
65
+ values: StringValues = {},
66
+ plurals?: PluralRules,
67
+ ): string {
68
+ if (template === undefined) {
69
+ return "";
70
+ }
71
+ const text = typeof template === "string" ? template : variant(template, values.count, plurals);
72
+ return text.replace(/\{([A-Za-z0-9]+)\}/g, (slot, name: string) =>
73
+ name in values ? String(values[name]) : slot,
74
+ );
75
+ }
76
+
77
+ function variant(
78
+ variants: Record<string, string>,
79
+ count: string | number | undefined,
80
+ plurals: PluralRules | undefined,
81
+ ): string {
82
+ const n = Number(count);
83
+ if (Number.isFinite(n)) {
84
+ const exact = variants[`#${n}`];
85
+ if (exact !== undefined) {
86
+ return exact;
87
+ }
88
+ const category = variants[`#${pluralCategory(plurals, n)}`];
89
+ if (category !== undefined) {
90
+ return category;
91
+ }
92
+ }
93
+ return variants["#*"] ?? "";
94
+ }
95
+
96
+ /**
97
+ * Strings as a renderer receives them: each declared string with no params as its text, each with
98
+ * params as a function filling them in. A string the composer didn't send is empty.
99
+ */
100
+ export function buildStrings<S>(
101
+ declared: StringParams,
102
+ strings: Strings | undefined,
103
+ plurals: PluralRules | undefined,
104
+ ): S {
105
+ const t: Record<string, string | ((values: StringValues) => string)> = {};
106
+ for (const [key, params] of Object.entries(declared)) {
107
+ const template = strings?.[key];
108
+ t[key] =
109
+ params.length === 0
110
+ ? formatString(template, {}, plurals)
111
+ : (values: StringValues) => formatString(template, values, plurals);
112
+ }
113
+ // The declared keys and params are the ones codegen typed S with.
114
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
115
+ return t as S;
116
+ }
117
+
118
+ // ---- App strings ----
119
+
120
+ /** The app strings, typed by their generated descriptor: `appStrings(AppStrings, response).retry`. */
121
+ export function appStrings<S>(descriptor: AppStringsDescriptor<S>, response: StringsResponse): S {
122
+ return buildStrings<S>(descriptor.strings, response.strings, response.plurals);
123
+ }
124
+
125
+ /** Thrown for a strings request the composer didn't answer with 200 and its strings. */
126
+ export class StringsFetchError extends Error {
127
+ readonly status: number;
128
+ readonly body: string;
129
+
130
+ constructor(status: number, body: string) {
131
+ super(`Strings request failed with status ${status}`);
132
+ this.status = status;
133
+ this.body = body;
134
+ }
135
+ }
136
+
137
+ const isRecord = (value: unknown): value is Record<string, unknown> =>
138
+ typeof value === "object" && value !== null && !Array.isArray(value);
139
+
140
+ function isStringsResponse(value: unknown): value is StringsResponse {
141
+ if (!isRecord(value) || typeof value.locale !== "string") {
142
+ return false;
143
+ }
144
+ return isRecord(value.plurals) && isRecord(value.strings);
145
+ }
146
+
147
+ /** Fetch the app strings in the client's language (spec §4.7). */
148
+ export async function fetchStrings(
149
+ baseUrl: string,
150
+ client: ClientContext,
151
+ init: RequestInit = {},
152
+ fetchImpl: typeof fetch = fetch,
153
+ ): Promise<StringsResponse> {
154
+ const headers = new Headers(init.headers);
155
+ if (!headers.has("content-type")) {
156
+ headers.set("content-type", "application/json");
157
+ }
158
+ const res = await fetchImpl(`${baseUrl}/strings`, {
159
+ ...init,
160
+ method: "POST",
161
+ headers,
162
+ body: JSON.stringify({ protocol: PROTOCOL_VERSION, client }),
163
+ });
164
+ const text = await res.text();
165
+ if (!res.ok) {
166
+ throw new StringsFetchError(res.status, text);
167
+ }
168
+ let parsed: unknown;
169
+ try {
170
+ parsed = JSON.parse(text);
171
+ } catch {
172
+ throw new StringsFetchError(res.status, text);
173
+ }
174
+ if (!isStringsResponse(parsed)) {
175
+ throw new StringsFetchError(res.status, text);
176
+ }
177
+ return parsed;
178
+ }