@rindle/api-server 0.1.0-rc.5

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/index.js ADDED
@@ -0,0 +1,388 @@
1
+ export const DEFAULT_RINDLE_API_ROUTES = {
2
+ query: "/api/rindle/query",
3
+ read: "/api/rindle/read",
4
+ mutate: "/api/rindle/mutate",
5
+ };
6
+ export class RindleApiError extends Error {
7
+ code;
8
+ status;
9
+ constructor(code, message, status) {
10
+ super(message);
11
+ this.name = "RindleApiError";
12
+ this.code = code;
13
+ this.status = status;
14
+ }
15
+ }
16
+ /**
17
+ * A read/write-split `RindleDaemonClient` (READ-ROUTER-DESIGN.md §2.1). Writes
18
+ * (`executeSqlTxn` / `rejectMutation` / `applyRowChangeTxn` / `migrate`) go to the single
19
+ * write-master, UNCHANGED and never through the router; reads (`materialize` / `query` /
20
+ * `dematerialize`) go to the read router. Hand one of these to {@link createRindleApiServer} as
21
+ * `daemon` to point the reads leg at the router while writes stay on the master — no placement
22
+ * logic enters the api-server.
23
+ *
24
+ * ```ts
25
+ * const daemon = new SplitDaemonClient(
26
+ * new HttpRindleDaemonClient({ baseUrl: MASTER_URL, headers: writeAuth }), // writes → master
27
+ * new HttpRindleDaemonClient({ baseUrl: ROUTER_URL, headers: routerAuth }), // reads → router
28
+ * );
29
+ * ```
30
+ */
31
+ export class SplitDaemonClient {
32
+ writes;
33
+ reads;
34
+ constructor(writes, reads) {
35
+ this.writes = writes;
36
+ this.reads = reads;
37
+ }
38
+ // writes → the single master, never through the router
39
+ executeSqlTxn(input) {
40
+ return this.writes.executeSqlTxn(input);
41
+ }
42
+ rejectMutation(input) {
43
+ return this.writes.rejectMutation(input);
44
+ }
45
+ applyRowChangeTxn(input) {
46
+ return this.writes.applyRowChangeTxn(input);
47
+ }
48
+ migrate(input) {
49
+ return this.writes.migrate(input);
50
+ }
51
+ // reads → the router (it stamps `wsEndpoint` onto the outputs)
52
+ materialize(input) {
53
+ return this.reads.materialize(input);
54
+ }
55
+ query(input) {
56
+ return this.reads.query(input);
57
+ }
58
+ dematerialize(input) {
59
+ return this.reads.dematerialize(input);
60
+ }
61
+ }
62
+ export function defineApiQueries(queries) {
63
+ return queries;
64
+ }
65
+ /**
66
+ * Register a list of co-located client {@link NamedQuery `defineQuery`} values as the server's query
67
+ * surface — the bulk, no-boilerplate counterpart to {@link defineApiQueries}. Each query already
68
+ * carries its wire `name` and a `resolve` that re-runs its validator on the UNTRUSTED wire args and
69
+ * builds the authoritative `Query`, so the server just imports every co-located query and hands the
70
+ * list here. The same validated args build a byte-identical AST on both tiers.
71
+ *
72
+ * The query's AUTHORITATIVE {@link ApiContext} is forwarded as `resolve`'s ctx — so a context-scoped
73
+ * `defineQuery` (e.g. "my issues") is built from the server's trusted principal, never the client's.
74
+ * A context-free query simply ignores the extra argument.
75
+ *
76
+ * Use {@link defineApiQueries} instead (or in addition) only when the server must DIVERGE from the
77
+ * client — define a server-specific `defineQuery` with the same name and register that.
78
+ *
79
+ * ```ts
80
+ * queries: registerQueries<User>([issuesPageQuery, issueDetailQuery, recentCommentsQuery, usersQuery]),
81
+ * ```
82
+ */
83
+ export function registerQueries(queries) {
84
+ const out = {};
85
+ for (const query of queries) {
86
+ if (Object.prototype.hasOwnProperty.call(out, query.queryName)) {
87
+ throw new Error(`registerQueries: duplicate query name "${query.queryName}"`);
88
+ }
89
+ out[query.queryName] = (ctx, args) => query.resolve(args, ctx);
90
+ }
91
+ return out;
92
+ }
93
+ export function defineApiMutators(mutators) {
94
+ return mutators;
95
+ }
96
+ export function queryResultToAst(result) {
97
+ if (result && typeof result === "object" && "ast" in result && typeof result.ast === "function") {
98
+ return result.ast();
99
+ }
100
+ return result;
101
+ }
102
+ export function createRindleApiServer(opts) {
103
+ const routes = { ...DEFAULT_RINDLE_API_ROUTES, ...opts.routes };
104
+ const mode = opts.mode ?? "normalized";
105
+ // Names that are ALSO configured pins — a lease for one is forced to a `pinned` policy (the lazy
106
+ // floor, §4.1) so the first viewer to route to a follower warms it for late joiners.
107
+ const pinnedNames = new Set((opts.pinnedQueries ?? []).map((p) => p.name));
108
+ // Resolve a named query (+ args) to its AST under a given context — the shared path for both
109
+ // a per-viewer lease and a system-level pin (which skips per-user authorization).
110
+ const resolveAst = async (name, args, context) => {
111
+ const query = opts.queries?.[name];
112
+ if (!query)
113
+ throw new RindleApiError("not-found", `unknown query: ${name}`, 404);
114
+ const result = opts.runQuery
115
+ ? await opts.runQuery({ user: context.user, name, args, query, context })
116
+ : await query(context, args);
117
+ return queryResultToAst(result);
118
+ };
119
+ const createQueryLease = async (input) => {
120
+ const context = { user: input.user, request: input.request };
121
+ await assertAuthorized(opts.authorizeQuery, {
122
+ user: input.user,
123
+ name: input.name,
124
+ args: input.args,
125
+ context,
126
+ });
127
+ const ast = await resolveAst(input.name, input.args, context);
128
+ // Lazy pin tier (§4.1): a leased query that is ALSO a configured pin is materialized with a
129
+ // `pinned` policy regardless of the configured default, so it survives its first viewer's
130
+ // departure. Otherwise use the configured policy.
131
+ const policy = pinnedNames.has(input.name)
132
+ ? { kind: "pinned", name: input.name }
133
+ : await resolvePolicy(opts.materializationPolicy, input);
134
+ const subject = await resolveSubject(opts.subject, input);
135
+ const routingKey = await resolveRoutingKey(opts.routingKey, input);
136
+ const out = await opts.daemon.materialize({
137
+ ast,
138
+ mode,
139
+ policy,
140
+ subject,
141
+ leaseTtlMs: opts.leaseTtlMs,
142
+ // The anonymous routing key rides `metadata.routingKey`; the router keys on
143
+ // `subject ?? metadata.routingKey` (§2.2). Omitted when there is none.
144
+ metadata: routingKey !== undefined ? { routingKey } : undefined,
145
+ });
146
+ return queryLeaseResponse(out);
147
+ };
148
+ const readQuery = async (input) => {
149
+ const context = { user: input.user, request: input.request };
150
+ // Same per-viewer gate a live lease passes — a one-shot read returns the same rows a subscribe
151
+ // would, so it must clear the same authorization.
152
+ await assertAuthorized(opts.authorizeQuery, {
153
+ user: input.user,
154
+ name: input.name,
155
+ args: input.args,
156
+ context,
157
+ });
158
+ const ast = await resolveAst(input.name, input.args, context);
159
+ // Scope the one-shot's dedup `QueryKey` by the SAME key the lease path routes on — the routing
160
+ // key (`subject ?? cookie ?? clientId`) — so the warm pipeline this read leaves behind is the
161
+ // very one the browser's follow-up `subscribe` reuses, ON THE SAME FOLLOWER HRW will place it
162
+ // (the warm handoff, SSR-DESIGN.md §3.4 / READ-ROUTER-DESIGN.md §2.4) rather than a second,
163
+ // viewer-mismatched materialization.
164
+ const subject = await resolveSubject(opts.subject, input);
165
+ const routingKey = await resolveRoutingKey(opts.routingKey, input);
166
+ const visibilityKey = subject ?? routingKey;
167
+ const out = await opts.daemon.query({ ast, visibilityKey, ttlMs: opts.readIdleTtlMs });
168
+ const res = { rows: out.rows, cvMin: out.cvMin, queryKey: out.queryKey };
169
+ if (out.wsEndpoint !== undefined)
170
+ res.wsEndpoint = out.wsEndpoint;
171
+ return res;
172
+ };
173
+ const pushMutation = async (input) => {
174
+ const context = { user: input.user, request: input.request };
175
+ const mutator = opts.mutators?.[input.envelope.name];
176
+ if (!mutator)
177
+ return reject(opts.daemon, input.envelope, `unknown mutator: ${input.envelope.name}`);
178
+ let sql;
179
+ try {
180
+ await assertAuthorized(opts.authorizeMutation, {
181
+ user: input.user,
182
+ envelope: input.envelope,
183
+ context,
184
+ });
185
+ const tx = new CollectingSqlMutationTx();
186
+ const result = await mutator(tx, input.envelope.args, {
187
+ user: input.user,
188
+ envelope: input.envelope,
189
+ daemon: opts.daemon,
190
+ request: input.request,
191
+ });
192
+ sql = mutationResultToSqlTxn(result, tx);
193
+ }
194
+ catch (err) {
195
+ return reject(opts.daemon, input.envelope, String(err?.message ?? err));
196
+ }
197
+ const output = await opts.daemon.executeSqlTxn({
198
+ ...sql,
199
+ clientID: input.envelope.clientID,
200
+ mid: input.envelope.mid,
201
+ });
202
+ return { accepted: true, rejected: false, output };
203
+ };
204
+ const pushMutations = async (input) => {
205
+ const out = [];
206
+ for (const envelope of input.envelopes) {
207
+ out.push(await pushMutation({ user: input.user, envelope, request: input.request }));
208
+ }
209
+ return out;
210
+ };
211
+ const assertPins = async () => {
212
+ const pins = opts.pinnedQueries;
213
+ if (!pins?.length)
214
+ return;
215
+ const context = { user: opts.pinUser, request: undefined };
216
+ // Resolve every pin's authoritative AST under the system pin user (a transient failure on one
217
+ // shouldn't strand the rest), then drive the warm-up — fleet fan-out via the router if
218
+ // configured, else one materialize per pin on the single daemon.
219
+ const resolved = await Promise.allSettled(pins.map(async (pin) => ({
220
+ pin,
221
+ req: {
222
+ ast: await resolveAst(pin.name, pin.args ?? null, context),
223
+ mode,
224
+ policy: { kind: "pinned", name: pin.name },
225
+ leaseTtlMs: opts.leaseTtlMs,
226
+ },
227
+ })));
228
+ const failures = [];
229
+ const pairs = [];
230
+ resolved.forEach((r, i) => {
231
+ if (r.status === "fulfilled")
232
+ pairs.push(r.value);
233
+ else
234
+ failures.push(`${pins[i].name}: ${errMessage(r.reason)}`);
235
+ });
236
+ const reqs = pairs.map((p) => p.req);
237
+ if (reqs.length) {
238
+ if (opts.pinFanout) {
239
+ // Push tier (§4.2): fan EACH pin across ALL live followers via the router (fire-and-forget,
240
+ // router-stateless). A whole-fan-out failure is surfaced so the caller retries.
241
+ try {
242
+ await opts.pinFanout.assertPins(reqs);
243
+ }
244
+ catch (e) {
245
+ failures.push(errMessage(e));
246
+ }
247
+ }
248
+ else {
249
+ // Single-daemon: materialize each pin once (the daemon dedups by canonical query).
250
+ const results = await Promise.allSettled(reqs.map((req) => opts.daemon.materialize(req)));
251
+ results.forEach((r, i) => {
252
+ if (r.status === "rejected")
253
+ failures.push(`${pairs[i].pin.name}: ${errMessage(r.reason)}`);
254
+ });
255
+ }
256
+ }
257
+ if (failures.length) {
258
+ throw new Error(`assertPins: ${failures.length} failed — ${failures.join("; ")}`);
259
+ }
260
+ };
261
+ return {
262
+ routes,
263
+ createQueryLease,
264
+ readQuery,
265
+ assertPins,
266
+ pushMutation,
267
+ pushMutations,
268
+ handleQueryJson: (body, context) => {
269
+ const msg = parseObject(body, "query request");
270
+ return createQueryLease({
271
+ user: context.user,
272
+ name: parseString(msg.name, "name"),
273
+ args: msg.args ?? null,
274
+ request: context.request,
275
+ clientId: typeof msg.clientId === "string" ? msg.clientId : undefined,
276
+ });
277
+ },
278
+ handleReadJson: (body, context) => {
279
+ const msg = parseObject(body, "read request");
280
+ return readQuery({
281
+ user: context.user,
282
+ name: parseString(msg.name, "name"),
283
+ args: msg.args ?? null,
284
+ request: context.request,
285
+ clientId: typeof msg.clientId === "string" ? msg.clientId : undefined,
286
+ });
287
+ },
288
+ handleMutateJson: (body, context) => {
289
+ const msg = parseObject(body, "mutation request");
290
+ if (Array.isArray(msg.envelopes)) {
291
+ return pushMutations({
292
+ user: context.user,
293
+ envelopes: msg.envelopes.map(parseEnvelope),
294
+ request: context.request,
295
+ });
296
+ }
297
+ const envelope = parseEnvelope(msg.envelope ?? msg);
298
+ return pushMutation({ user: context.user, envelope, request: context.request });
299
+ },
300
+ };
301
+ }
302
+ class CollectingSqlMutationTx {
303
+ stmts = [];
304
+ get statements() {
305
+ return this.stmts;
306
+ }
307
+ exec(sql, params = []) {
308
+ this.stmts.push({ sql, params });
309
+ }
310
+ }
311
+ function mutationResultToSqlTxn(result, tx) {
312
+ if (Array.isArray(result))
313
+ return { statements: result };
314
+ if (result && typeof result === "object" && "statements" in result) {
315
+ return { statements: result.statements, idempotencyKey: result.idempotencyKey };
316
+ }
317
+ return { statements: [...tx.statements] };
318
+ }
319
+ async function assertAuthorized(authorizer, input) {
320
+ if (!authorizer)
321
+ return;
322
+ const result = await authorizer(input);
323
+ if (result === false)
324
+ throw new RindleApiError("forbidden", "rindle request forbidden", 403);
325
+ }
326
+ async function resolvePolicy(policy, input) {
327
+ if (!policy)
328
+ return { kind: "whileSubscribed" };
329
+ return typeof policy === "function" ? await policy(input) : policy;
330
+ }
331
+ async function resolveSubject(subject, input) {
332
+ if (typeof subject === "function")
333
+ return subject(input);
334
+ return subject;
335
+ }
336
+ /** Resolve the anonymous routing key (READ-ROUTER-DESIGN.md §2.2): an explicit value/resolver if
337
+ * configured, otherwise the browser-supplied `clientId`. The router keys on `subject ?? this`. */
338
+ async function resolveRoutingKey(routingKey, input) {
339
+ if (routingKey === undefined)
340
+ return input.clientId;
341
+ return typeof routingKey === "function" ? routingKey(input) : routingKey;
342
+ }
343
+ function queryLeaseResponse(out) {
344
+ const res = {
345
+ leaseToken: out.leaseToken,
346
+ materializationId: out.materializationId,
347
+ queryKey: out.queryKey,
348
+ reused: out.reused,
349
+ };
350
+ // Only present in a routed deploy — absent reproduces today's single-daemon response exactly.
351
+ if (out.wsEndpoint !== undefined)
352
+ res.wsEndpoint = out.wsEndpoint;
353
+ return res;
354
+ }
355
+ function errMessage(reason) {
356
+ return String(reason?.message ?? reason);
357
+ }
358
+ async function reject(daemon, envelope, reason) {
359
+ const output = await daemon.rejectMutation({ clientID: envelope.clientID, mid: envelope.mid, reason });
360
+ return { accepted: false, rejected: true, reason, output };
361
+ }
362
+ function parseObject(value, label) {
363
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
364
+ throw new RindleApiError("bad-request", `invalid ${label}`, 400);
365
+ }
366
+ return value;
367
+ }
368
+ function parseString(value, label) {
369
+ if (typeof value !== "string")
370
+ throw new RindleApiError("bad-request", `invalid ${label}`, 400);
371
+ return value;
372
+ }
373
+ function parseEnvelope(value) {
374
+ const obj = parseObject(value, "mutation envelope");
375
+ return {
376
+ clientID: parseString(obj.clientID, "clientID"),
377
+ mid: parseNumber(obj.mid, "mid"),
378
+ name: parseString(obj.name, "name"),
379
+ args: obj.args ?? null,
380
+ };
381
+ }
382
+ function parseNumber(value, label) {
383
+ if (typeof value !== "number" || !Number.isFinite(value)) {
384
+ throw new RindleApiError("bad-request", `invalid ${label}`, 400);
385
+ }
386
+ return value;
387
+ }
388
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@rindle/api-server",
3
+ "version": "0.1.0-rc.5",
4
+ "license": "Apache-2.0",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/rindle-sh/rindle.git",
8
+ "directory": "packages/api-server"
9
+ },
10
+ "type": "module",
11
+ "description": "Application API-server helpers for Rindle query leases and custom mutator routing.",
12
+ "main": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "sideEffects": false,
15
+ "exports": {
16
+ ".": {
17
+ "@rindle/source": "./src/index.ts",
18
+ "types": "./dist/index.d.ts",
19
+ "default": "./dist/index.js"
20
+ }
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "src",
25
+ "README.md"
26
+ ],
27
+ "dependencies": {
28
+ "@rindle/client": "0.1.0-rc.5",
29
+ "@rindle/daemon-client": "0.1.0-rc.5"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^22.10.0",
33
+ "typescript": "^5.7.0"
34
+ },
35
+ "scripts": {
36
+ "build": "tsc -p tsconfig.build.json",
37
+ "typecheck": "tsc --noEmit",
38
+ "test": "tsc --noEmit && node --conditions=@rindle/source --test test/*.test.ts"
39
+ }
40
+ }