@happyvertical/smrt-web 0.51.31 → 0.51.33
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/__typechecks__/webmcp-tool-definition.d.ts +2 -0
- package/dist/__typechecks__/webmcp-tool-definition.d.ts.map +1 -0
- package/dist/ai.d.ts +330 -358
- package/dist/ai.d.ts.map +1 -0
- package/dist/capability-classification.d.ts +89 -0
- package/dist/capability-classification.d.ts.map +1 -0
- package/dist/capability.d.ts +191 -0
- package/dist/capability.d.ts.map +1 -0
- package/dist/data-query.d.ts +121 -0
- package/dist/data-query.d.ts.map +1 -0
- package/dist/data-surface-actions.d.ts +118 -0
- package/dist/data-surface-actions.d.ts.map +1 -0
- package/dist/durable-store.d.ts +88 -0
- package/dist/durable-store.d.ts.map +1 -0
- package/dist/index.d.ts +468 -2245
- package/dist/index.d.ts.map +1 -0
- package/dist/intents.d.ts +273 -300
- package/dist/intents.d.ts.map +1 -0
- package/dist/internal.d.ts +15 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/offline/durable-queue.d.ts +171 -0
- package/dist/offline/durable-queue.d.ts.map +1 -0
- package/dist/offline/engine.d.ts +359 -0
- package/dist/offline/engine.d.ts.map +1 -0
- package/dist/offline/leader.d.ts +57 -0
- package/dist/offline/leader.d.ts.map +1 -0
- package/dist/offline/types.d.ts +232 -0
- package/dist/offline/types.d.ts.map +1 -0
- package/dist/offline.d.ts +258 -0
- package/dist/offline.d.ts.map +1 -0
- package/dist/persistence/snapshot-store.d.ts +121 -0
- package/dist/persistence/snapshot-store.d.ts.map +1 -0
- package/dist/persistence.d.ts +157 -0
- package/dist/persistence.d.ts.map +1 -0
- package/dist/remote-query.d.ts +61 -0
- package/dist/remote-query.d.ts.map +1 -0
- package/dist/sse-client.d.ts +182 -0
- package/dist/sse-client.d.ts.map +1 -0
- package/dist/update-state/meta-store.d.ts +66 -0
- package/dist/update-state/meta-store.d.ts.map +1 -0
- package/dist/update-state.d.ts +115 -0
- package/dist/update-state.d.ts.map +1 -0
- package/dist/webmcp-tool-names.d.ts +106 -112
- package/dist/webmcp-tool-names.d.ts.map +1 -0
- package/dist/webmcp.d.ts +193 -653
- package/dist/webmcp.d.ts.map +1 -0
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,2245 +1,468 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
export
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*/
|
|
66
|
-
export
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
*/
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
*/
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
*/
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*/
|
|
256
|
-
export declare function
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
* `
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
*/
|
|
275
|
-
export declare function
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
*
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
/**
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
/**
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
* the
|
|
397
|
-
*/
|
|
398
|
-
|
|
399
|
-
/**
|
|
400
|
-
|
|
401
|
-
/**
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
*
|
|
449
|
-
*
|
|
450
|
-
*
|
|
451
|
-
*
|
|
452
|
-
*
|
|
453
|
-
*
|
|
454
|
-
*
|
|
455
|
-
*
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
*
|
|
461
|
-
*
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
*/
|
|
470
|
-
object: {
|
|
471
|
-
name: string;
|
|
472
|
-
_row?: TData;
|
|
473
|
-
};
|
|
474
|
-
/**
|
|
475
|
-
* The durable-store identity this outbox's queue is namespaced under — folds
|
|
476
|
-
* api base / tenant / identity / manifest hash, so a logout or tenant switch
|
|
477
|
-
* lands on a different IndexedDB database (never cross-identity reuse). Shared
|
|
478
|
-
* with #1764's persistence slice via the same {@link durableStoreNamespace}.
|
|
479
|
-
* `manifestHash` is opaque caller-supplied config for #1762; its canonical
|
|
480
|
-
* source is #1764's call (a schema-shape digest) — comment your call site.
|
|
481
|
-
*/
|
|
482
|
-
namespace: DurableStoreKey;
|
|
483
|
-
/**
|
|
484
|
-
* API base path the sync-apply endpoint lives under (`POST
|
|
485
|
-
* {syncApplyBasePath}/sync/apply`). Defaults to `/api/v1`, matching the REST
|
|
486
|
-
* generator's default. Set to the SvelteKit route base (`/api`) when replaying
|
|
487
|
-
* against the generated SvelteKit `sync/apply/+server.ts`. Ignored when
|
|
488
|
-
* {@link transport} is set.
|
|
489
|
-
*/
|
|
490
|
-
syncApplyBasePath?: string;
|
|
491
|
-
/**
|
|
492
|
-
* Replay this collection's queued writes through a consumer-declared server
|
|
493
|
-
* operation instead of the generated `sync/apply` (#3021) — for a model whose
|
|
494
|
-
* generated write verbs are closed because a hand-written, permission-gated
|
|
495
|
-
* service owns its write rules. Rows are queued under `object.name` and replay
|
|
496
|
-
* ONLY through this transport (never `sync/apply`), each carrying its durable
|
|
497
|
-
* `idempotencyKey`, with the same four-state machine, per-route FIFO, and
|
|
498
|
-
* backoff.
|
|
499
|
-
* See {@link offlineCommandQueue} for writes with no collection at all.
|
|
500
|
-
*/
|
|
501
|
-
transport?: OutboxCommandTransport;
|
|
502
|
-
/** Fetch implementation override (tests, SSR). Defaults to global fetch. */
|
|
503
|
-
fetchFn?: typeof fetch;
|
|
504
|
-
/** Exponential-backoff tuning for retryable replay failures. */
|
|
505
|
-
backoff?: OutboxBackoff;
|
|
506
|
-
/**
|
|
507
|
-
* Called on every observable sync-state transition of a captured mutation
|
|
508
|
-
* (`pending → uploading → synced`, `→ failed`, and the `pending` re-arm after
|
|
509
|
-
* a retryable failure). A push callback; smrt-svelte turns it into a reactive
|
|
510
|
-
* binding later.
|
|
511
|
-
*/
|
|
512
|
-
onSyncStateChange?: (event: SyncStateEvent) => void;
|
|
513
|
-
/**
|
|
514
|
-
* Called when a replayed mutation comes back `conflict` — a RESOLVED outcome
|
|
515
|
-
* (server state won; the item leaves the queue with terminal state `synced`).
|
|
516
|
-
* Persist `serverUpdatedAt` as the new `baseUpdatedAt`, refetch the row, and
|
|
517
|
-
* surface the conflict to the user as appropriate.
|
|
518
|
-
*/
|
|
519
|
-
onConflict?: (conflict: OutboxConflict) => void;
|
|
520
|
-
/** Test-only: inject a deterministic RNG for backoff jitter. */
|
|
521
|
-
random?: () => number;
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
/** Exponential-backoff tuning for retryable replay failures. */
|
|
525
|
-
export declare interface OutboxBackoff {
|
|
526
|
-
/** Delay before the first retry, ms (default 1000). */
|
|
527
|
-
initialDelayMs?: number;
|
|
528
|
-
/** Multiplier applied per attempt (default 2). */
|
|
529
|
-
multiplier?: number;
|
|
530
|
-
/** Ceiling on the computed delay, ms (default 60000). */
|
|
531
|
-
maxDelayMs?: number;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
/**
|
|
535
|
-
* One queued write handed to a consumer-declared {@link OutboxCommandTransport}
|
|
536
|
-
* at replay time (#3021). The transport replays it through a server operation
|
|
537
|
-
* the consumer owns — a data-surface action, a named remote command, a
|
|
538
|
-
* hand-written permission-gated service — instead of the generated
|
|
539
|
-
* `sync/apply`, which calls `collection.create()` directly.
|
|
540
|
-
*/
|
|
541
|
-
export declare interface OutboxCommand {
|
|
542
|
-
/**
|
|
543
|
-
* The durable, client-minted idempotency key (the queue row's `itemId`). It
|
|
544
|
-
* is IDENTICAL on every attempt of this write — including a blind resend
|
|
545
|
-
* after a lost response — so the server operation MUST dedupe on it; that is
|
|
546
|
-
* what makes the outbox's ambiguous-failure retries safe on this path.
|
|
547
|
-
*/
|
|
548
|
-
idempotencyKey: string;
|
|
549
|
-
/** The transport name the write was queued under. */
|
|
550
|
-
name: string;
|
|
551
|
-
/** The mutation kind in sync-apply terms. */
|
|
552
|
-
op: SyncApplyOp;
|
|
553
|
-
/** The client-generated row id the write targets. */
|
|
554
|
-
rowId: string;
|
|
555
|
-
/** Row / changed fields (create, update); absent for delete. */
|
|
556
|
-
payload?: Record<string, unknown>;
|
|
557
|
-
/** The server `updated_at` the client last saw, when the caller supplied one. */
|
|
558
|
-
baseUpdatedAt?: string;
|
|
559
|
-
/** 1-based number of this attempt (`1` on the first send). */
|
|
560
|
-
attempt: number;
|
|
561
|
-
/** The value this write's transport pinned on an earlier attempt, if any. */
|
|
562
|
-
pinned?: unknown;
|
|
563
|
-
/**
|
|
564
|
-
* Durably pin a structured-clone-safe value to this write before sending,
|
|
565
|
-
* so a later attempt (including after a reload) sees it as `pinned`. A
|
|
566
|
-
* transport whose server fingerprints the request per idempotency key pins
|
|
567
|
-
* the request it built, so a resend after a lost response is identical.
|
|
568
|
-
*/
|
|
569
|
-
pin(value: unknown): Promise<void>;
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
/**
|
|
573
|
-
* The server's outcome for one {@link OutboxCommand}, in the SAME vocabulary
|
|
574
|
-
* the sync-apply replay maps — so the four-state machine and backoff are
|
|
575
|
-
* shared, not re-derived:
|
|
576
|
-
*
|
|
577
|
-
* - `applied` → removed, `synced`.
|
|
578
|
-
* - `conflict` → removed, `onConflict` fired, `synced` (a RESOLVED outcome).
|
|
579
|
-
* - `rejected` with `write_failed` → kept, backoff, `pending` (retryable).
|
|
580
|
-
* - `rejected` with `auth_required` / `forbidden` → the whole loop pauses until
|
|
581
|
-
* re-auth (a later enqueue or `retry()`), kept `pending`.
|
|
582
|
-
* - `rejected` with any other reason → removed, `failed` (terminal).
|
|
583
|
-
*
|
|
584
|
-
* A transport that THROWS (network error, lost response, 5xx) is the ambiguous
|
|
585
|
-
* path: the write stays `pending` with backoff and is blindly resent later
|
|
586
|
-
* under the same {@link OutboxCommand.idempotencyKey}.
|
|
587
|
-
*/
|
|
588
|
-
export declare type OutboxCommandResult = {
|
|
589
|
-
status: 'applied';
|
|
590
|
-
updatedAt?: string;
|
|
591
|
-
} | {
|
|
592
|
-
status: 'conflict';
|
|
593
|
-
reason?: 'stale_write' | 'create_conflict';
|
|
594
|
-
updatedAt?: string;
|
|
595
|
-
} | {
|
|
596
|
-
status: 'rejected';
|
|
597
|
-
reason: SyncApplyReason | (string & {});
|
|
598
|
-
};
|
|
599
|
-
|
|
600
|
-
/** Replays one queued write through a consumer-declared server operation. */
|
|
601
|
-
export declare type OutboxCommandTransport = (command: OutboxCommand) => Promise<OutboxCommandResult>;
|
|
602
|
-
|
|
603
|
-
/**
|
|
604
|
-
* A conflict surfaced to {@link OfflineOutboxConfig.onConflict} when a replayed
|
|
605
|
-
* item comes back `conflict`. Per the contract this is a RESOLVED outcome — the
|
|
606
|
-
* server state won, the item is removed, and its terminal observable state is
|
|
607
|
-
* `synced` — so an app treats it as "your write was superseded; here is the
|
|
608
|
-
* server's `updatedAt` to rebase from", NOT as a failure to retry.
|
|
609
|
-
*/
|
|
610
|
-
export declare interface OutboxConflict {
|
|
611
|
-
/** The queue row's `itemId`. */
|
|
612
|
-
itemId: string;
|
|
613
|
-
/** The collection route segment. */
|
|
614
|
-
object: string;
|
|
615
|
-
/** The client-generated row UUID that conflicted. */
|
|
616
|
-
rowId: string;
|
|
617
|
-
/**
|
|
618
|
-
* Why the item conflicted: `stale_write` (an update/delete whose
|
|
619
|
-
* `baseUpdatedAt` was older than the server row) or `create_conflict` (a
|
|
620
|
-
* create landing on an existing, diverged row).
|
|
621
|
-
*/
|
|
622
|
-
reason: 'stale_write' | 'create_conflict';
|
|
623
|
-
/**
|
|
624
|
-
* The server row's `updated_at` after processing — the value to persist as
|
|
625
|
-
* the new `baseUpdatedAt` before re-editing. Present when the endpoint
|
|
626
|
-
* returned it.
|
|
627
|
-
*/
|
|
628
|
-
serverUpdatedAt?: string;
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
/**
|
|
632
|
-
* A programmatic handle to one namespace's outbox — the bridge pattern (like
|
|
633
|
-
* `getEngineCollection`) for trusted callers (an app's outbox panel, a
|
|
634
|
-
* smrt-svelte binding, tests). Fetched via {@link getOutboxHandle}.
|
|
635
|
-
*/
|
|
636
|
-
export declare interface OutboxHandle {
|
|
637
|
-
/**
|
|
638
|
-
* A read-only snapshot of the durable queue (every state). The way to prove
|
|
639
|
-
* durability after a reload, since this slice does not rehydrate the read
|
|
640
|
-
* cache (that's #1764).
|
|
641
|
-
*/
|
|
642
|
-
snapshot(): Promise<OutboxSnapshotItem[]>;
|
|
643
|
-
/**
|
|
644
|
-
* Force a retry of a specific queued item now (clears its backoff gate, wakes
|
|
645
|
-
* the loop, and clears an auth pause). A no-op for an item no longer queued.
|
|
646
|
-
*/
|
|
647
|
-
retry(itemId: string): Promise<void>;
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
/** One item in an {@link OutboxHandle.snapshot} result. */
|
|
651
|
-
export declare interface OutboxSnapshotItem {
|
|
652
|
-
/** The transport name, when the item replays through one (#3021). */
|
|
653
|
-
transport?: string;
|
|
654
|
-
/** The queue row's idempotency handle. */
|
|
655
|
-
itemId: string;
|
|
656
|
-
/** The collection route segment. */
|
|
657
|
-
object: string;
|
|
658
|
-
/** The mutation kind, in sync-apply terms. */
|
|
659
|
-
op: 'create' | 'update' | 'delete';
|
|
660
|
-
/** The client-generated row UUID. */
|
|
661
|
-
rowId: string;
|
|
662
|
-
/** The on-disk lifecycle state. */
|
|
663
|
-
state: 'pending' | 'synced' | 'failed';
|
|
664
|
-
/** Replay attempts so far. */
|
|
665
|
-
attempts: number;
|
|
666
|
-
/** Epoch ms before which this row won't be retried (backoff). */
|
|
667
|
-
nextAttemptAt: number;
|
|
668
|
-
/** Last replay error, if any. */
|
|
669
|
-
lastError?: string;
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
/**
|
|
673
|
-
* The app-observable sync state of a queued mutation — the SAME four-state
|
|
674
|
-
* machine the KMP mobile foundation exposes (ADR 0001), so web and mobile
|
|
675
|
-
* outbox indicators render identically:
|
|
676
|
-
*
|
|
677
|
-
* - `pending` — enqueued, awaiting (re)send.
|
|
678
|
-
* - `uploading` — currently in a sync-apply POST.
|
|
679
|
-
* - `synced` — the mutation's effect is confirmed on the server (a terminal
|
|
680
|
-
* success — INCLUDING a surfaced conflict, which is a RESOLVED outcome: the
|
|
681
|
-
* server state won and the item left the queue).
|
|
682
|
-
* - `failed` — a terminal rejection the client cannot resolve by retrying
|
|
683
|
-
* (`invalid_*`, `not_found`, `id_conflict`, `op_not_allowed`, …) — surfaced
|
|
684
|
-
* for app-level handling.
|
|
685
|
-
*/
|
|
686
|
-
export declare type OutboxSyncState = 'pending' | 'uploading' | 'synced' | 'failed';
|
|
687
|
-
|
|
688
|
-
/**
|
|
689
|
-
* Build a durable persistence capability for a collection. Add the returned
|
|
690
|
-
* capability to the collection's `capabilities` array; a collection without it
|
|
691
|
-
* is unaffected (the seam's no-op guarantee — the "opt-in per model" AC).
|
|
692
|
-
*
|
|
693
|
-
* The same `namespace` across multiple collections shares ONE snapshot database
|
|
694
|
-
* (one open, one durable resource, one wipe), and each collection is keyed by
|
|
695
|
-
* its own `collection` name within it.
|
|
696
|
-
*/
|
|
697
|
-
export declare function persistCollection<TData extends object = object>(config: PersistCollectionConfig<TData>): SmrtWebCapability<TData>;
|
|
698
|
-
|
|
699
|
-
/**
|
|
700
|
-
* Configuration for {@link persistCollection}. Generic in the collection's row
|
|
701
|
-
* type `TData` so the capability matches the collection it plugs into.
|
|
702
|
-
*/
|
|
703
|
-
export declare interface PersistCollectionConfig<TData extends object = object> {
|
|
704
|
-
/**
|
|
705
|
-
* The REST collection name this snapshot is keyed by — MUST be the SAME
|
|
706
|
-
* `definition.name` passed to {@link createSmrtCollection} (it is the store
|
|
707
|
-
* key under the namespace). Provided explicitly (not read off the ctx) so the
|
|
708
|
-
* config is self-describing and testable.
|
|
709
|
-
*/
|
|
710
|
-
collection: string;
|
|
711
|
-
/**
|
|
712
|
-
* The durable-store identity this snapshot is namespaced under — folds api
|
|
713
|
-
* base / tenant / identity / manifest hash, so a logout, tenant switch, or a
|
|
714
|
-
* contract-changing deploy lands on a different IndexedDB database (never
|
|
715
|
-
* cross-identity reuse, and a shape change drops old snapshots). Shared with
|
|
716
|
-
* the outbox (#1762) via the same {@link durableStoreNamespace}, so one
|
|
717
|
-
* {@link wipeDurableStore} clears both.
|
|
718
|
-
*
|
|
719
|
-
* The canonical `manifestHash` source is the build-time inject — the
|
|
720
|
-
* `manifestHash` constant the generated `@happyvertical/smrt-virt-web` module
|
|
721
|
-
* exports (#1764). Thread it here at the call site.
|
|
722
|
-
*/
|
|
723
|
-
namespace: DurableStoreKey;
|
|
724
|
-
/**
|
|
725
|
-
* Trailing-debounce window (ms) for the write-back snapshot. A burst of
|
|
726
|
-
* mutations within the window collapses to ONE IndexedDB write of the final
|
|
727
|
-
* row set. Default {@link DEFAULT_PERSIST_DEBOUNCE_MS}. Set 0 to write on
|
|
728
|
-
* every change (tests).
|
|
729
|
-
*/
|
|
730
|
-
debounceMs?: number;
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
/**
|
|
734
|
-
* Persist and rehydrate a mounted data surface's rows (#3021) — the
|
|
735
|
-
* `persistCollection` twin for a surface (e.g. one registered with
|
|
736
|
-
* `mountListDataSurface`) whose rows come from a server-scoped data-surface
|
|
737
|
-
* query rather than a generated `list` route. The page owns its rows, so it
|
|
738
|
-
* owns the calls: `load()` before the first fetch to paint stale rows, then
|
|
739
|
-
* `save(rows)` whenever it refreshes them.
|
|
740
|
-
*
|
|
741
|
-
* Shares the namespace's snapshot database, durable-resource registration,
|
|
742
|
-
* and IndexedDB-unavailable degrade with {@link persistCollection}: a
|
|
743
|
-
* manifest-hash, tenant, or identity change lands on a different database, and
|
|
744
|
-
* `wipeDurableStore(namespace)` clears the surface's rows with the rest.
|
|
745
|
-
*/
|
|
746
|
-
export declare function persistDataSurface<TRow extends object = object>(config: PersistDataSurfaceConfig): PersistedDataSurface<TRow>;
|
|
747
|
-
|
|
748
|
-
/** Configuration for {@link persistDataSurface}. */
|
|
749
|
-
export declare interface PersistDataSurfaceConfig {
|
|
750
|
-
/**
|
|
751
|
-
* The durable-store identity — the SAME key the app's collections and
|
|
752
|
-
* outbox use. It folds the principal (`identityId`) and tenant, so a surface
|
|
753
|
-
* whose rows the server scopes per principal lands on a per-principal
|
|
754
|
-
* database: another user on the device never reads them, and one
|
|
755
|
-
* `wipeDurableStore(namespace)` on logout clears them with everything else.
|
|
756
|
-
*/
|
|
757
|
-
namespace: DurableStoreKey;
|
|
758
|
-
/** The mounted surface's identity (`descriptor.identity`) — the store key. */
|
|
759
|
-
identity: SmrtWebDataSurfaceIdentity;
|
|
760
|
-
/** Trailing-debounce window for `save` (ms). Default {@link DEFAULT_PERSIST_DEBOUNCE_MS}. */
|
|
761
|
-
debounceMs?: number;
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
/** A durable row snapshot for one mounted data surface (#3021). */
|
|
765
|
-
export declare interface PersistedDataSurface<TRow extends object = object> {
|
|
766
|
-
/**
|
|
767
|
-
* The rows last saved for this surface under this namespace, or `undefined`
|
|
768
|
-
* when none exist (first load, a different principal/tenant/manifest, a
|
|
769
|
-
* wipe, or no IndexedDB). Render them as stale, then revalidate. After a
|
|
770
|
-
* `wipeDurableStore` of its namespace a handle is inert (`load` finds
|
|
771
|
-
* nothing, `save` is ignored); create a new one for the next scope.
|
|
772
|
-
*/
|
|
773
|
-
load(): Promise<TRow[] | undefined>;
|
|
774
|
-
/**
|
|
775
|
-
* Replace the persisted rows (debounced, trailing; last call wins). Pass the
|
|
776
|
-
* surface's CURRENT rows whenever the page refreshes them. Rows must be
|
|
777
|
-
* structured-clone-safe plain objects.
|
|
778
|
-
*/
|
|
779
|
-
save(rows: readonly TRow[]): void;
|
|
780
|
-
/** Write any pending `save` now. */
|
|
781
|
-
flush(): Promise<void>;
|
|
782
|
-
/** Flush a pending `save`, then release the shared store. */
|
|
783
|
-
dispose(): Promise<void>;
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
/**
|
|
787
|
-
* Register a durable artifact under a namespace so {@link wipeDurableStore} can
|
|
788
|
-
* later clear it. Returns an unregister function that removes just this
|
|
789
|
-
* resource — call it when the artifact is disposed on its own (before any
|
|
790
|
-
* namespace-wide wipe) so it is not cleared twice.
|
|
791
|
-
*/
|
|
792
|
-
export declare function registerDurableResource(namespace: string, resource: DurableResource): () => void;
|
|
793
|
-
|
|
794
|
-
/**
|
|
795
|
-
* Register one declared view intent (#2588) against a mounted registry
|
|
796
|
-
* binding, for as long as the returned disposer is not called.
|
|
797
|
-
*
|
|
798
|
-
* This is the ONLY way an intent reaches the browser, and it goes through
|
|
799
|
-
* {@link registerWebMcpBespokeTool}, so an intent inherits the same
|
|
800
|
-
* fail-closed `effects` exposure policy as a generated model tool. The
|
|
801
|
-
* intent's classification was resolved at declaration time by the shared
|
|
802
|
-
* rule, and the hints `compileViewIntentToolSpec` emits round-trip through
|
|
803
|
-
* the bespoke registrar's own re-resolution unchanged.
|
|
804
|
-
*
|
|
805
|
-
* The `execute` registered here is constructed by
|
|
806
|
-
* `compileViewIntentToolSpec` from `intent.target`. No author-supplied code
|
|
807
|
-
* runs, and the only thing it can do is dispatch one browser registry
|
|
808
|
-
* command — the runtime half of the no-REST invariant.
|
|
809
|
-
*
|
|
810
|
-
* The intent's derived tool name is claimed against the document-global
|
|
811
|
-
* tool-name lock (#2613), so an id whose flattened name collides with a
|
|
812
|
-
* generated model tool or a fixed UI tool throws
|
|
813
|
-
* {@link WebMcpToolNameCollisionError} here rather than silently losing the
|
|
814
|
-
* tool at the host. `defineIntent`'s own intent-vs-intent check cannot see
|
|
815
|
-
* either, because both depend on a runtime `namespace` / `prefix` the
|
|
816
|
-
* declaration never sees.
|
|
817
|
-
*
|
|
818
|
-
* @throws {WebMcpToolNameCollisionError} when the derived name is already held.
|
|
819
|
-
*/
|
|
820
|
-
export declare function registerViewIntent(intent: ViewIntent, binding: ViewIntentBinding, options?: RegisterWebMcpBespokeToolOptions): WebMcpRegistrationDisposer;
|
|
821
|
-
|
|
822
|
-
/**
|
|
823
|
-
* Register one hand-written browser tool through the same fail-closed effect
|
|
824
|
-
* classification and `effects` exposure policy as {@link registerWebMcpTools}
|
|
825
|
-
* (#2586). A tool with no `annotations`, or with annotations that leave its
|
|
826
|
-
* effect undeclared, classifies destructive/non-idempotent/open-world — the
|
|
827
|
-
* same default `actionSemantics` gives an undeclared custom model action —
|
|
828
|
-
* and is excluded unless the policy allows `destructive`. `namespace` and
|
|
829
|
-
* `maxTools` are out of scope for a bespoke tool; see
|
|
830
|
-
* {@link RegisterWebMcpBespokeToolOptions}.
|
|
831
|
-
*
|
|
832
|
-
* The tool's name is also claimed against the
|
|
833
|
-
* document-global tool-name lock before the browser sees it. A name a
|
|
834
|
-
* generated model tool, a fixed UI tool, or another live bespoke tool /
|
|
835
|
-
* intent already holds throws {@link WebMcpToolNameCollisionError}
|
|
836
|
-
* SYNCHRONOUSLY, naming the colliding name and the owner that holds it.
|
|
837
|
-
* Previously the host accepted the call and silently dropped the losing
|
|
838
|
-
* registration. Disposing releases the name, so register/dispose/re-register
|
|
839
|
-
* under one name still succeeds.
|
|
840
|
-
*
|
|
841
|
-
* @returns a disposer that deregisters the tool this call registered (a
|
|
842
|
-
* no-op double-call). On a browser without WebMCP, or when policy excludes
|
|
843
|
-
* the tool's effect, the call is a no-op and the disposer is inert.
|
|
844
|
-
* @throws {WebMcpToolNameCollisionError} when the name is already held.
|
|
845
|
-
*/
|
|
846
|
-
export declare function registerWebMcpBespokeTool(spec: WebMcpBespokeToolSpec, options?: RegisterWebMcpBespokeToolOptions): WebMcpRegistrationDisposer;
|
|
847
|
-
|
|
848
|
-
export declare interface RegisterWebMcpBespokeToolOptions {
|
|
849
|
-
/**
|
|
850
|
-
* Allowed effects. Omitted means read-only exposure — the same default as
|
|
851
|
-
* {@link registerWebMcpTools}. `namespace` and `maxTools` deliberately do
|
|
852
|
-
* not apply to a bespoke tool (#2586): a component author already chose a
|
|
853
|
-
* stable name, and counting one intent against a shared budget could make
|
|
854
|
-
* an unrelated generated tool set fail to register.
|
|
855
|
-
*/
|
|
856
|
-
effects?: readonly WebMcpToolEffect[];
|
|
857
|
-
/**
|
|
858
|
-
* Which path this registration belongs to, used ONLY to label its
|
|
859
|
-
* tool-name reservation (#2613) so a later collision names the right
|
|
860
|
-
* source. Defaults to `bespoke`.
|
|
861
|
-
*
|
|
862
|
-
* A UI-framework binding that compiles a declared view intent itself and
|
|
863
|
-
* registers it here — rather than through {@link registerViewIntent} —
|
|
864
|
-
* must pass `'intent'`. `useViewIntent` in `@happyvertical/smrt-svelte`
|
|
865
|
-
* does exactly that, because reusing `useWebMcpTool`'s single WebMCP
|
|
866
|
-
* lifecycle is a documented invariant of that package; without this it
|
|
867
|
-
* would be the only shipped intent path and every intent collision would
|
|
868
|
-
* blame a `useWebMcpTool` call that does not exist.
|
|
869
|
-
*
|
|
870
|
-
* Purely a diagnostic label: it grants no capability, narrows no policy,
|
|
871
|
-
* and changes nothing about how the tool registers or executes.
|
|
872
|
-
*/
|
|
873
|
-
owner?: Extract<WebMcpToolNameOwner, 'intent' | 'bespoke'>;
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
/**
|
|
877
|
-
* Register every collection's generated tool descriptors with WebMCP.
|
|
878
|
-
*
|
|
879
|
-
* Every selected tool name is claimed against the document-global tool-name
|
|
880
|
-
* lock (#2613) before the first browser registration, so a collision with a
|
|
881
|
-
* UI-layer or bespoke tool throws {@link WebMcpToolNameCollisionError} with
|
|
882
|
-
* the offending name and its current owner instead of reaching the host.
|
|
883
|
-
*
|
|
884
|
-
* @returns a disposer that deregisters all tools this call registered. On a
|
|
885
|
-
* browser without WebMCP the call is a no-op and the disposer is inert.
|
|
886
|
-
* @throws {WebMcpToolNameCollisionError} when a selected name is already held.
|
|
887
|
-
*/
|
|
888
|
-
export declare function registerWebMcpTools(definitions: readonly WebMcpRegistrationDefinition[], options?: RegisterWebMcpToolsOptions): WebMcpRegistrationDisposer;
|
|
889
|
-
|
|
890
|
-
export declare interface RegisterWebMcpToolsOptions extends WebMcpExposurePolicy {
|
|
891
|
-
/** REST base path for the fetchers (default `/api/v1`). */
|
|
892
|
-
basePath?: string;
|
|
893
|
-
/** Injectable fetch (tests / SSR-safe wrappers). */
|
|
894
|
-
fetchFn?: typeof fetch;
|
|
895
|
-
/** Shared smrt-web cache handle used by page collections. */
|
|
896
|
-
client?: SmrtWebClient;
|
|
897
|
-
/** Optional cache scope matching the page collection's scope. */
|
|
898
|
-
scope?: string;
|
|
899
|
-
/**
|
|
900
|
-
* Override how a definition's CRUD fetchers are built. Defaults to
|
|
901
|
-
* {@link createDefinitionFetchers}; the primary seam for testing `execute`
|
|
902
|
-
* without a live server.
|
|
903
|
-
*/
|
|
904
|
-
resolveFetchers?: (definition: SmrtWebCollectionDefinition) => SmrtCrudFetchers;
|
|
905
|
-
/**
|
|
906
|
-
* Override direct REST fetchers for a canonical tool-only definition.
|
|
907
|
-
* Fetchers are optional because a get-only or custom-action-only model does
|
|
908
|
-
* not have a list or create route.
|
|
909
|
-
*/
|
|
910
|
-
resolveToolFetchers?: (definition: WebMcpToolDefinition) => Partial<SmrtCrudFetchers>;
|
|
911
|
-
/** Predicate to include/exclude individual tools (e.g. reads-only surfaces). */
|
|
912
|
-
filter?: (definition: SmrtWebCollectionDefinition, descriptor: NonNullable<SmrtWebCollectionDefinition['toolDescriptors']>[number]) => boolean;
|
|
913
|
-
/** Predicate for canonical per-tool definitions. */
|
|
914
|
-
filterTool?: (definition: WebMcpToolDefinition) => boolean;
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
/**
|
|
918
|
-
* Reserve `names` for `owner` against the document's WebMCP registry.
|
|
919
|
-
*
|
|
920
|
-
* Reservation is ALL-OR-NOTHING: if any name is already held — by this path
|
|
921
|
-
* or another — nothing is reserved and a {@link WebMcpToolNameCollisionError}
|
|
922
|
-
* naming the colliding name and its current owner is thrown synchronously,
|
|
923
|
-
* before any tool reaches `document.modelContext`. Duplicates within `names`
|
|
924
|
-
* itself collide the same way.
|
|
925
|
-
*
|
|
926
|
-
* Off-WebMCP (no document) the call is a no-op returning an inert
|
|
927
|
-
* reservation, matching every registrar's own no-op guarantee.
|
|
928
|
-
*
|
|
929
|
-
* A reservation releases only the names it took: `release()` never drops a
|
|
930
|
-
* name a later reservation has since acquired, so a dispose that lands after
|
|
931
|
-
* a same-name re-registration cannot revoke the new holder's claim.
|
|
932
|
-
*/
|
|
933
|
-
export declare function reserveWebMcpToolNames(names: readonly string[], owner: WebMcpToolNameOwner, options?: ReserveWebMcpToolNamesOptions): WebMcpToolNameReservation;
|
|
934
|
-
|
|
935
|
-
declare interface ReserveWebMcpToolNamesOptions {
|
|
936
|
-
/**
|
|
937
|
-
* The document whose `modelContext` the names are registered against.
|
|
938
|
-
* Defaults to `globalThis.document`. Registrars that accept an injectable
|
|
939
|
-
* document (tests, non-window hosts) must pass the SAME object they read
|
|
940
|
-
* `modelContext` from, or their reservations land in a different table.
|
|
941
|
-
*/
|
|
942
|
-
document?: unknown;
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
/**
|
|
946
|
-
* Run the `wrapMutation` hook across `capabilities` in array order for one
|
|
947
|
-
* mutation, short-circuiting on the FIRST capability that returns `{ handled:
|
|
948
|
-
* true }` (later capabilities' `wrapMutation` are then skipped). A capability
|
|
949
|
-
* that returns `{ handled: false }`, `undefined`, or omits the hook declines,
|
|
950
|
-
* and the next is tried. When every capability declines, resolves `{ handled:
|
|
951
|
-
* false }` so the factory falls through to the real fetcher.
|
|
952
|
-
*/
|
|
953
|
-
export declare function runWrapMutation<TData extends object>(capabilities: readonly SmrtWebCapability<TData>[], envelope: SmrtWebMutationEnvelope, ctx: SmrtWebCapabilityContext<TData>): Promise<{
|
|
954
|
-
handled: true;
|
|
955
|
-
result: unknown;
|
|
956
|
-
} | {
|
|
957
|
-
handled: false;
|
|
958
|
-
}>;
|
|
959
|
-
|
|
960
|
-
/**
|
|
961
|
-
* The per-collection CRUD surface of the generated REST client
|
|
962
|
-
* (`createClient(basePath).<collection>` from `@happyvertical/smrt-virt-client`).
|
|
963
|
-
*
|
|
964
|
-
* Return types are `unknown` on purpose: generated fetchers resolve with
|
|
965
|
-
* whatever the server sent, so this package normalizes and validates payloads
|
|
966
|
-
* centrally — see {@link unwrapListResult} / {@link unwrapItemResult}.
|
|
967
|
-
*/
|
|
968
|
-
export declare interface SmrtCrudFetchers {
|
|
969
|
-
list(params?: Record<string, unknown>): Promise<unknown>;
|
|
970
|
-
get?(id: string): Promise<unknown>;
|
|
971
|
-
create(data: Record<string, unknown>): Promise<unknown>;
|
|
972
|
-
update?(id: string, data: Record<string, unknown>): Promise<unknown>;
|
|
973
|
-
delete?(id: string): Promise<unknown>;
|
|
974
|
-
/** Invoke a generated custom action route. */
|
|
975
|
-
custom?(action: string, args: Record<string, unknown>, route?: SmrtWebToolRouteDescriptor): Promise<unknown>;
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
/**
|
|
979
|
-
* A capability plugged into {@link createSmrtCollection}. Every hook is
|
|
980
|
-
* optional; a capability implements only the points its slice needs. Hooks fire
|
|
981
|
-
* in these fixed places, and capabilities run in ARRAY ORDER:
|
|
982
|
-
*
|
|
983
|
-
* - `contributeCacheKey` — ONCE, before the engine collection is constructed.
|
|
984
|
-
* - `warmStart` — ONCE, before the first read (seeds the cache).
|
|
985
|
-
* - `wrapMutation` — per mutation, BEFORE the fetcher, with a chance to handle
|
|
986
|
-
* the write itself (offline).
|
|
987
|
-
* - `onSettled` — per mutation, AFTER it settles (success AND fetcher-throw).
|
|
988
|
-
* - `onAttach` — ONCE, right after the engine collection is constructed; the
|
|
989
|
-
* ONLY place a capability registers an external (non-mutation) trigger such as
|
|
990
|
-
* an SSE subscription.
|
|
991
|
-
* - `teardown` — in `cleanup()`, after the engine's own cleanup.
|
|
992
|
-
*/
|
|
993
|
-
export declare interface SmrtWebCapability<TData extends object = object> {
|
|
994
|
-
/** Diagnostic name (e.g. `'offline-outbox'`). */
|
|
995
|
-
readonly name: string;
|
|
996
|
-
/**
|
|
997
|
-
* Contribute extra cache-key segments so this capability can partition the
|
|
998
|
-
* collection's cache (e.g. an outbox variant). Runs ONCE, before construction;
|
|
999
|
-
* returned segments are appended to the collection's cache key/id. Return
|
|
1000
|
-
* `undefined` (or omit) to contribute nothing.
|
|
1001
|
-
*/
|
|
1002
|
-
contributeCacheKey?(ctx: SmrtWebCapabilityContext<TData>): string[] | undefined;
|
|
1003
|
-
/**
|
|
1004
|
-
* Provide rows to seed the cache before the first read — the persistence
|
|
1005
|
-
* slice's rehydrate-from-disk path. Runs ONCE, before construction. NOTE:
|
|
1006
|
-
* caller-supplied `initialData` (fresher same-request SSR truth) WINS over any
|
|
1007
|
-
* capability `warmStart`. Return `undefined` to contribute no seed.
|
|
1008
|
-
*/
|
|
1009
|
-
warmStart?(ctx: SmrtWebCapabilityContext<TData>): Promise<SmrtWebRow<TData>[] | undefined> | SmrtWebRow<TData>[] | undefined;
|
|
1010
|
-
/**
|
|
1011
|
-
* Intercept a mutation BEFORE its fetcher runs. Return `{ handled: true,
|
|
1012
|
-
* result }` to take over the write (the fetcher is skipped and `result`
|
|
1013
|
-
* reconciles the optimistic row — the offline path); return `{ handled: false
|
|
1014
|
-
* }` or `undefined` to fall through to the real fetcher. With multiple
|
|
1015
|
-
* capabilities the FIRST `{ handled: true }` wins and later capabilities'
|
|
1016
|
-
* `wrapMutation` are skipped.
|
|
1017
|
-
*/
|
|
1018
|
-
wrapMutation?(envelope: SmrtWebMutationEnvelope, ctx: SmrtWebCapabilityContext<TData>): Promise<WrapMutationOutcome> | WrapMutationOutcome;
|
|
1019
|
-
/**
|
|
1020
|
-
* Observe a mutation after it settles — on BOTH a successful persist and a
|
|
1021
|
-
* fetcher throw (before the optimistic rollback propagates). Never swallows
|
|
1022
|
-
* the error: a thrown fetcher error still rolls the transaction back.
|
|
1023
|
-
*/
|
|
1024
|
-
onSettled?(envelope: SmrtWebMutationEnvelope, outcome: MutationSettleOutcome, ctx: SmrtWebCapabilityContext<TData>): void;
|
|
1025
|
-
/**
|
|
1026
|
-
* Run ONCE, right after the engine collection is constructed. The ONLY hook
|
|
1027
|
-
* where a capability wires an external trigger (SSE subscription, focus
|
|
1028
|
-
* listener) — `ctx.invalidate()` is callable here.
|
|
1029
|
-
*/
|
|
1030
|
-
onAttach?(ctx: SmrtWebCapabilityContext<TData>): void;
|
|
1031
|
-
/** Run inside `cleanup()`, AFTER the engine's own cleanup. Awaited if async. */
|
|
1032
|
-
teardown?(ctx: SmrtWebCapabilityContext<TData>): void | Promise<void>;
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
|
-
/**
|
|
1036
|
-
* The context every capability hook receives — a stable, engine-free view of
|
|
1037
|
-
* the collection being built. All fields are the exact values the factory uses
|
|
1038
|
-
* internally (the resolved cache key/id, the same fetchers), so a capability
|
|
1039
|
-
* keys its own storage or subscriptions off the identical discriminators.
|
|
1040
|
-
*/
|
|
1041
|
-
export declare interface SmrtWebCapabilityContext<TData extends object = object> {
|
|
1042
|
-
/** The generated definition this collection materializes. */
|
|
1043
|
-
readonly definition: SmrtWebCollectionDefinition<TData>;
|
|
1044
|
-
/** The CRUD fetchers the collection persists through. */
|
|
1045
|
-
readonly fetchers: SmrtCrudFetchers;
|
|
1046
|
-
/**
|
|
1047
|
-
* The `queryKey` segments the collection's reads use — a LIVE view: from
|
|
1048
|
-
* `onAttach`/`warmStart` onward it is the final key (including every
|
|
1049
|
-
* capability-contributed segment); read during `contributeCacheKey` it omits
|
|
1050
|
-
* that capability's own not-yet-applied segment. Treat as read-only.
|
|
1051
|
-
*/
|
|
1052
|
-
readonly cacheKey: readonly string[];
|
|
1053
|
-
/** The engine-collection id string (mirrors {@link cacheKey}). */
|
|
1054
|
-
readonly cacheId: string;
|
|
1055
|
-
/**
|
|
1056
|
-
* Enter the SAME relationship-derived invalidation the factory runs after a
|
|
1057
|
-
* settled mutation. A capability calls this to refetch this collection and its
|
|
1058
|
-
* manifest-related collections in response to an EXTERNAL trigger (e.g. an SSE
|
|
1059
|
-
* message) without reaching into the engine.
|
|
1060
|
-
*/
|
|
1061
|
-
invalidate(): void;
|
|
1062
|
-
/**
|
|
1063
|
-
* A snapshot of the collection's current rows as plain public DTOs — the same
|
|
1064
|
-
* projection as {@link SmrtWebCollection.toArray}, so the engine's virtual
|
|
1065
|
-
* props never cross the boundary. The persistence slice (#1764) reads this in
|
|
1066
|
-
* its write-back to serialize the current cache to disk. Populated by the real
|
|
1067
|
-
* factory; a hand-built test context may omit it, so callers guard for its
|
|
1068
|
-
* presence.
|
|
1069
|
-
*
|
|
1070
|
-
* SAFE ONLY FROM `onAttach` ONWARD. The factory's implementation closes over
|
|
1071
|
-
* the engine collection, which is constructed AFTER `contributeCacheKey` and
|
|
1072
|
-
* `warmStart` run — calling this from those earlier hooks would throw
|
|
1073
|
-
* (temporal-dead-zone). Read rows from `onAttach`, `onSettled`, or an external
|
|
1074
|
-
* trigger, never during construction.
|
|
1075
|
-
*/
|
|
1076
|
-
snapshot?(): ReadonlyArray<SmrtWebRow<TData>>;
|
|
1077
|
-
/**
|
|
1078
|
-
* Subscribe to the collection's change notifications — the same stream as
|
|
1079
|
-
* {@link SmrtWebCollection.subscribeChanges} (plain-DTO payloads). The
|
|
1080
|
-
* persistence slice (#1764) wires its debounced write-back here in `onAttach`
|
|
1081
|
-
* and detaches in `teardown`. Engine-free by construction: the payload is
|
|
1082
|
-
* `unknown` (the capability only needs the change SIGNAL, then re-reads via
|
|
1083
|
-
* {@link snapshot}), so no engine type crosses the seam. Populated by the real
|
|
1084
|
-
* factory; a hand-built test context may omit it.
|
|
1085
|
-
*
|
|
1086
|
-
* SAFE ONLY FROM `onAttach` ONWARD (same reason as {@link snapshot}): it closes
|
|
1087
|
-
* over the engine collection built after the pre-construction hooks.
|
|
1088
|
-
*/
|
|
1089
|
-
subscribe?(callback: (changes: unknown) => void): SmrtWebSubscription;
|
|
1090
|
-
}
|
|
1091
|
-
|
|
1092
|
-
/**
|
|
1093
|
-
* Opaque handle to the shared client cache / request-dedup layer. Create one
|
|
1094
|
-
* with {@link createSmrtWebClient} and pass the SAME instance to every
|
|
1095
|
-
* collection that should share a cache and deduplicate in-flight requests.
|
|
1096
|
-
*
|
|
1097
|
-
* The engine (currently a TanStack Query client) is intentionally hidden behind
|
|
1098
|
-
* this brand so it stays swappable — do not depend on its concrete shape.
|
|
1099
|
-
*/
|
|
1100
|
-
export declare interface SmrtWebClient {
|
|
1101
|
-
/** Phantom brand — this handle wraps the hidden client-cache engine. */
|
|
1102
|
-
readonly __smrtWebClient: 'SmrtWebClient';
|
|
1103
|
-
}
|
|
1104
|
-
|
|
1105
|
-
/**
|
|
1106
|
-
* A live, cached collection of plain-DTO rows — the SMRT-owned public contract
|
|
1107
|
-
* over the client-data engine. Exposes only the committed surface; the engine's
|
|
1108
|
-
* own type is never named here so it stays swappable.
|
|
1109
|
-
*/
|
|
1110
|
-
export declare interface SmrtWebCollection<TData extends object> {
|
|
1111
|
-
/** All rows currently in the collection (plain DTOs, insertion order). */
|
|
1112
|
-
readonly toArray: ReadonlyArray<SmrtWebRow<TData>>;
|
|
1113
|
-
/** Number of rows currently in the collection. */
|
|
1114
|
-
readonly size: number;
|
|
1115
|
-
/** True when a row with `key` is present. */
|
|
1116
|
-
has(key: string): boolean;
|
|
1117
|
-
/** The row with `key`, or `undefined`. */
|
|
1118
|
-
get(key: string): SmrtWebRow<TData> | undefined;
|
|
1119
|
-
/** Resolve once the first load has completed. */
|
|
1120
|
-
preload(): Promise<void>;
|
|
1121
|
-
/** Tear down subscriptions and cached state. */
|
|
1122
|
-
cleanup(): Promise<void>;
|
|
1123
|
-
/** Subscribe to change notifications; returns a detach handle. */
|
|
1124
|
-
subscribeChanges(callback: (changes: unknown) => void): SmrtWebSubscription;
|
|
1125
|
-
/**
|
|
1126
|
-
* Optimistically insert a row and persist it through the create fetcher. The
|
|
1127
|
-
* row is visible synchronously; the returned transaction settles on the
|
|
1128
|
-
* server outcome (see {@link SmrtWebTransaction}).
|
|
1129
|
-
*/
|
|
1130
|
-
insert(row: SmrtWebRow<TData>): SmrtWebTransaction;
|
|
1131
|
-
/** Optimistically update a row and persist it through the REST surface. */
|
|
1132
|
-
update(key: string, changes: Omit<Partial<SmrtWebRow<TData>>, 'id'>): SmrtWebTransaction;
|
|
1133
|
-
/** Optimistically delete a row and persist it through the REST surface. */
|
|
1134
|
-
delete(key: string): SmrtWebTransaction;
|
|
1135
|
-
/** Execute a custom action and invalidate this collection's related caches. */
|
|
1136
|
-
action(action: string, args: Record<string, unknown>, route?: SmrtWebToolRouteDescriptor): Promise<unknown>;
|
|
1137
|
-
}
|
|
1138
|
-
|
|
1139
|
-
export declare interface SmrtWebCollectionDefinition<TData extends object = object> {
|
|
1140
|
-
/** REST collection name (e.g. `products`). */
|
|
1141
|
-
name: string;
|
|
1142
|
-
/**
|
|
1143
|
-
* Canonical qualified model identity (e.g.
|
|
1144
|
-
* `@happyvertical/smrt-products:Product`). Generated definitions always
|
|
1145
|
-
* provide it; optional here for source compatibility with manual literals
|
|
1146
|
-
* authored before policy-aware web collections.
|
|
1147
|
-
*/
|
|
1148
|
-
objectRef?: string;
|
|
1149
|
-
/** Source class name (e.g. `Product`). */
|
|
1150
|
-
className: string;
|
|
1151
|
-
/** Path under the API base path (e.g. `/products`). */
|
|
1152
|
-
endpoint: string;
|
|
1153
|
-
/** Primary key field name (`id` for SmrtObject). */
|
|
1154
|
-
idField: string;
|
|
1155
|
-
/** CRUD + custom actions exposed by the api decorator config. */
|
|
1156
|
-
actions: string[];
|
|
1157
|
-
/**
|
|
1158
|
-
* WebMCP/MCP tool descriptors for the exposed actions (#1812). Optional so
|
|
1159
|
-
* hand-built definitions (older codegen, tests) still satisfy the type; a
|
|
1160
|
-
* missing value means "no WebMCP tools to register".
|
|
1161
|
-
*/
|
|
1162
|
-
toolDescriptors?: WebToolDescriptor[];
|
|
1163
|
-
/** Persisted field metadata keyed by field name. */
|
|
1164
|
-
fields: Record<string, SmrtWebFieldDefinition>;
|
|
1165
|
-
/**
|
|
1166
|
-
* Manifest-derived relationship edges to sibling REST collections. Drives
|
|
1167
|
-
* relationship-derived cache invalidation: a settled mutation on this
|
|
1168
|
-
* collection invalidates the caches of the collections these edges name.
|
|
1169
|
-
* Optional so hand-built definitions (older codegen, tests) still satisfy the
|
|
1170
|
-
* type; a missing value means "no derived edges".
|
|
1171
|
-
*/
|
|
1172
|
-
relationships?: SmrtWebRelationship[];
|
|
1173
|
-
/** Phantom row-type carrier — never present at runtime. */
|
|
1174
|
-
_row?: TData;
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
|
-
export declare interface SmrtWebDataQueryFacetResult {
|
|
1178
|
-
field: string;
|
|
1179
|
-
values: Array<{
|
|
1180
|
-
value: SmrtWebDataQueryScalar;
|
|
1181
|
-
count: number;
|
|
1182
|
-
}>;
|
|
1183
|
-
truncated: boolean;
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
|
-
export declare type SmrtWebDataQueryFilter = {
|
|
1187
|
-
kind: 'condition';
|
|
1188
|
-
field: string;
|
|
1189
|
-
operator: SmrtWebDataQueryFilterOperator;
|
|
1190
|
-
value: SmrtWebDataQueryScalar | SmrtWebDataQueryScalar[];
|
|
1191
|
-
} | {
|
|
1192
|
-
kind: 'all' | 'any';
|
|
1193
|
-
filters: SmrtWebDataQueryFilter[];
|
|
1194
|
-
} | {
|
|
1195
|
-
kind: 'not';
|
|
1196
|
-
filter: SmrtWebDataQueryFilter;
|
|
1197
|
-
};
|
|
1198
|
-
|
|
1199
|
-
export declare type SmrtWebDataQueryFilterOperator = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'notIn' | 'like';
|
|
1200
|
-
|
|
1201
|
-
export declare interface SmrtWebDataQueryRequest {
|
|
1202
|
-
version: 1;
|
|
1203
|
-
requestId: string;
|
|
1204
|
-
mode: 'rows' | 'count' | 'facets';
|
|
1205
|
-
projection?: string[];
|
|
1206
|
-
filter?: SmrtWebDataQueryFilter;
|
|
1207
|
-
sort?: Array<{
|
|
1208
|
-
field: string;
|
|
1209
|
-
direction: 'asc' | 'desc';
|
|
1210
|
-
}>;
|
|
1211
|
-
page?: {
|
|
1212
|
-
kind: 'offset';
|
|
1213
|
-
offset: number;
|
|
1214
|
-
limit: number;
|
|
1215
|
-
} | {
|
|
1216
|
-
kind: 'cursor';
|
|
1217
|
-
after?: string;
|
|
1218
|
-
limit: number;
|
|
1219
|
-
};
|
|
1220
|
-
consistency?: {
|
|
1221
|
-
mode: 'eventual' | 'snapshot';
|
|
1222
|
-
asOf?: string;
|
|
1223
|
-
};
|
|
1224
|
-
facets?: Array<{
|
|
1225
|
-
field: string;
|
|
1226
|
-
limit: number;
|
|
1227
|
-
}>;
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
export declare interface SmrtWebDataQueryResult {
|
|
1231
|
-
version: 1;
|
|
1232
|
-
requestId: string;
|
|
1233
|
-
queryFingerprint: string;
|
|
1234
|
-
identityField: string;
|
|
1235
|
-
rows: Array<Record<string, unknown>>;
|
|
1236
|
-
page?: {
|
|
1237
|
-
kind: 'offset';
|
|
1238
|
-
limit: number;
|
|
1239
|
-
offset: number;
|
|
1240
|
-
hasMore: boolean;
|
|
1241
|
-
} | {
|
|
1242
|
-
kind: 'cursor';
|
|
1243
|
-
limit: number;
|
|
1244
|
-
nextCursor?: string;
|
|
1245
|
-
hasMore: boolean;
|
|
1246
|
-
};
|
|
1247
|
-
total: SmrtWebDataQueryTotal;
|
|
1248
|
-
facets?: SmrtWebDataQueryFacetResult[];
|
|
1249
|
-
freshness: {
|
|
1250
|
-
state: 'fresh' | 'stale' | 'unknown';
|
|
1251
|
-
asOf?: string;
|
|
1252
|
-
};
|
|
1253
|
-
warnings: string[];
|
|
1254
|
-
truncated: boolean;
|
|
1255
|
-
}
|
|
1256
|
-
|
|
1257
|
-
/**
|
|
1258
|
-
* Browser transport for the canonical bounded data-query envelope (#2444).
|
|
1259
|
-
*
|
|
1260
|
-
* This is a textual structural mirror of `@happyvertical/smrt-types` rather
|
|
1261
|
-
* than an import: smrt-web deliberately has no inter-SMRT dependencies. The
|
|
1262
|
-
* authenticated server adapter owns allowlist, authorization, fingerprint,
|
|
1263
|
-
* and byte-limit enforcement. This module gives browser callers a stable
|
|
1264
|
-
* request/result shape and rejects malformed response envelopes before they
|
|
1265
|
-
* reach a mounted surface.
|
|
1266
|
-
*/
|
|
1267
|
-
export declare type SmrtWebDataQueryScalar = string | number | boolean | null;
|
|
1268
|
-
|
|
1269
|
-
export declare type SmrtWebDataQueryTotal = {
|
|
1270
|
-
kind: 'exact' | 'estimated';
|
|
1271
|
-
value: number;
|
|
1272
|
-
asOf?: string;
|
|
1273
|
-
} | {
|
|
1274
|
-
kind: 'unavailable';
|
|
1275
|
-
reason?: string;
|
|
1276
|
-
};
|
|
1277
|
-
|
|
1278
|
-
/** Browser transport seam; REST, WebMCP, and test transports share it. */
|
|
1279
|
-
export declare interface SmrtWebDataQueryTransport {
|
|
1280
|
-
query(request: SmrtWebDataQueryRequest, options?: {
|
|
1281
|
-
signal?: AbortSignal;
|
|
1282
|
-
}): Promise<unknown>;
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
/**
|
|
1286
|
-
* The replay-time request for {@link dataSurfaceActionCommandTransport}: every
|
|
1287
|
-
* action-request field except those the adapter owns — `version`, `phase`,
|
|
1288
|
-
* `requestId`, `idempotencyKey`, and `confirmationToken`.
|
|
1289
|
-
*/
|
|
1290
|
-
export declare type SmrtWebDataSurfaceActionCommandRequest = Omit<SmrtWebDataSurfaceActionRequest, 'version' | 'phase' | 'requestId' | 'idempotencyKey' | 'confirmationToken'>;
|
|
1291
|
-
|
|
1292
|
-
export declare interface SmrtWebDataSurfaceActionCommandTransportOptions {
|
|
1293
|
-
/** The same action transport the mounted surface uses online. */
|
|
1294
|
-
transport: SmrtWebDataSurfaceActionTransport;
|
|
1295
|
-
/**
|
|
1296
|
-
* Build the action request for a queued write at its FIRST replay attempt,
|
|
1297
|
-
* so it carries the surface's `expectedRevision` as of replay rather than
|
|
1298
|
-
* capture. The built request is pinned durably to the write and reused on
|
|
1299
|
-
* every later attempt (including after a reload): the server fingerprints
|
|
1300
|
-
* the request per idempotency key, so a resend after a lost response must be
|
|
1301
|
-
* identical to replay the recorded result instead of `idempotency_conflict`.
|
|
1302
|
-
*/
|
|
1303
|
-
request: (command: OutboxCommand) => SmrtWebDataSurfaceActionCommandRequest | Promise<SmrtWebDataSurfaceActionCommandRequest>;
|
|
1304
|
-
/**
|
|
1305
|
-
* Run `preview` first and apply with its `confirmationToken` — for actions
|
|
1306
|
-
* whose server adapter requires confirmation. Default false (apply only).
|
|
1307
|
-
* The token is pinned before apply; a retry applies with it directly (the
|
|
1308
|
-
* server replays a completed result) and previews again only when the token
|
|
1309
|
-
* turns out unusable.
|
|
1310
|
-
*/
|
|
1311
|
-
preview?: boolean;
|
|
1312
|
-
/** Map a non-throwing result onto an outbox outcome. Default below. */
|
|
1313
|
-
classify?: (result: SmrtWebDataSurfaceActionResult) => OutboxCommandResult;
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1316
|
-
export declare interface SmrtWebDataSurfaceActionRequest {
|
|
1317
|
-
version: 1;
|
|
1318
|
-
requestId: string;
|
|
1319
|
-
identity: SmrtWebDataSurfaceIdentity;
|
|
1320
|
-
actionId: string;
|
|
1321
|
-
phase: 'preview' | 'apply';
|
|
1322
|
-
expectedRevision: number;
|
|
1323
|
-
/** Required by the server for apply; retries with the same key replay safely. */
|
|
1324
|
-
idempotencyKey?: string;
|
|
1325
|
-
selection: SmrtWebDataSurfaceSelection;
|
|
1326
|
-
payload?: SmrtWebDataSurfaceJsonValue;
|
|
1327
|
-
confirmationToken?: string;
|
|
1328
|
-
}
|
|
1329
|
-
|
|
1330
|
-
export declare interface SmrtWebDataSurfaceActionResult {
|
|
1331
|
-
version: 1;
|
|
1332
|
-
requestId: string;
|
|
1333
|
-
identity: SmrtWebDataSurfaceIdentity;
|
|
1334
|
-
actionId: string;
|
|
1335
|
-
phase: 'preview' | 'apply';
|
|
1336
|
-
ok: boolean;
|
|
1337
|
-
reason?: string;
|
|
1338
|
-
confirmationToken?: string;
|
|
1339
|
-
details?: {
|
|
1340
|
-
[key: string]: SmrtWebDataSurfaceJsonValue;
|
|
1341
|
-
};
|
|
1342
|
-
}
|
|
1343
|
-
|
|
1344
|
-
export declare interface SmrtWebDataSurfaceActionTransport {
|
|
1345
|
-
action(request: SmrtWebDataSurfaceActionRequest, options?: {
|
|
1346
|
-
signal?: AbortSignal;
|
|
1347
|
-
}): Promise<unknown>;
|
|
1348
|
-
}
|
|
1349
|
-
|
|
1350
|
-
export declare interface SmrtWebDataSurfaceIdentity {
|
|
1351
|
-
surfaceId: string;
|
|
1352
|
-
kind: 'table' | 'list' | 'report' | 'custom';
|
|
1353
|
-
subject?: {
|
|
1354
|
-
type: string;
|
|
1355
|
-
id: string;
|
|
1356
|
-
label?: string;
|
|
1357
|
-
};
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
export declare type SmrtWebDataSurfaceJsonPrimitive = string | number | boolean | null;
|
|
1361
|
-
|
|
1362
|
-
export declare type SmrtWebDataSurfaceJsonValue = SmrtWebDataSurfaceJsonPrimitive | SmrtWebDataSurfaceJsonValue[] | {
|
|
1363
|
-
[key: string]: SmrtWebDataSurfaceJsonValue;
|
|
1364
|
-
};
|
|
1365
|
-
|
|
1366
|
-
export declare type SmrtWebDataSurfaceSelection = {
|
|
1367
|
-
scope: 'current-page';
|
|
1368
|
-
} | {
|
|
1369
|
-
scope: 'explicit-ids';
|
|
1370
|
-
rowIds: Array<string | number>;
|
|
1371
|
-
} | {
|
|
1372
|
-
scope: 'all-matching';
|
|
1373
|
-
queryFingerprint: string;
|
|
1374
|
-
};
|
|
1375
|
-
|
|
1376
|
-
/**
|
|
1377
|
-
* The minimal `EventSource` surface the subscriber uses — declared here so a
|
|
1378
|
-
* test injects a fake without a real DOM, and so this module compiles without
|
|
1379
|
-
* DOM `lib` beyond the ambient global. A real `EventSource` satisfies it
|
|
1380
|
-
* structurally.
|
|
1381
|
-
*/
|
|
1382
|
-
export declare interface SmrtWebEventSource {
|
|
1383
|
-
/** Native reconnect fires this after (re)connect. */
|
|
1384
|
-
onopen: ((this: unknown, ev: unknown) => unknown) | null;
|
|
1385
|
-
/**
|
|
1386
|
-
* Fires on a stream error. A transient drop leaves `readyState` at OPEN
|
|
1387
|
-
* (0→…) and the browser auto-reconnects with `Last-Event-ID`; a fatal error
|
|
1388
|
-
* (server 401 / route disabled) leaves it CLOSED.
|
|
1389
|
-
*/
|
|
1390
|
-
onerror: ((this: unknown, ev: unknown) => unknown) | null;
|
|
1391
|
-
/**
|
|
1392
|
-
* Fires only for UNNAMED (`message`) events. The `_events` frames are NAMED
|
|
1393
|
-
* (`change` / `resync`), so this never fires for them — the subscriber uses
|
|
1394
|
-
* {@link addEventListener} instead. Present only to satisfy the structural
|
|
1395
|
-
* type of a real EventSource.
|
|
1396
|
-
*/
|
|
1397
|
-
onmessage: ((this: unknown, ev: unknown) => unknown) | null;
|
|
1398
|
-
/** Register a listener for a NAMED event (`change`, `resync`). */
|
|
1399
|
-
addEventListener(type: string, listener: (ev: {
|
|
1400
|
-
data: string;
|
|
1401
|
-
lastEventId: string;
|
|
1402
|
-
}) => void): void;
|
|
1403
|
-
/** Close the stream (stops reconnection). */
|
|
1404
|
-
close(): void;
|
|
1405
|
-
/** `CONNECTING` (0), `OPEN` (1), or `CLOSED` (2). */
|
|
1406
|
-
readonly readyState: number;
|
|
1407
|
-
}
|
|
1408
|
-
|
|
1409
|
-
/** Factory that constructs an {@link SmrtWebEventSource} for a URL. */
|
|
1410
|
-
export declare type SmrtWebEventSourceFactory = (url: string, init: {
|
|
1411
|
-
withCredentials: boolean;
|
|
1412
|
-
}) => SmrtWebEventSource | null | undefined;
|
|
1413
|
-
|
|
1414
|
-
/**
|
|
1415
|
-
* The ONE app-wide live-updates subscriber. Construct once (see
|
|
1416
|
-
* {@link createSmrtWebEventSubscriber}) and pass it to every
|
|
1417
|
-
* {@link liveInvalidation} capability.
|
|
1418
|
-
*/
|
|
1419
|
-
export declare interface SmrtWebEventSubscriber {
|
|
1420
|
-
/**
|
|
1421
|
-
* The live transport: `'sse'` while the EventSource is the source of truth,
|
|
1422
|
-
* `'polling'` when running (or downgraded to) the `_changes` fallback,
|
|
1423
|
-
* `'idle'` before any transport starts.
|
|
1424
|
-
*/
|
|
1425
|
-
readonly transport: SmrtWebSubscriberTransport;
|
|
1426
|
-
/**
|
|
1427
|
-
* Register an invalidator for a physical table. Returns an unregister
|
|
1428
|
-
* function. Multiple invalidators may share a table (two live collections);
|
|
1429
|
-
* a `change` for that table fires them all.
|
|
1430
|
-
*/
|
|
1431
|
-
registerTable(table: string, invalidate: () => void): () => void;
|
|
1432
|
-
/** Invalidate every registered table (a `resync` / `resyncRequired`). */
|
|
1433
|
-
invalidateAll(): void;
|
|
1434
|
-
/** Tear down the live transport and drop all registrations. */
|
|
1435
|
-
close(): void;
|
|
1436
|
-
}
|
|
1437
|
-
|
|
1438
|
-
/** Configuration for {@link createSmrtWebEventSubscriber}. */
|
|
1439
|
-
export declare interface SmrtWebEventSubscriberConfig {
|
|
1440
|
-
/** Absolute or same-origin URL of the generated `_events` SSE route. */
|
|
1441
|
-
eventsUrl: string;
|
|
1442
|
-
/** Absolute or same-origin URL of the generated `_changes` route (fallback). */
|
|
1443
|
-
changesUrl: string;
|
|
1444
|
-
/** `fetch` implementation for the polling fallback. Defaults to global fetch. */
|
|
1445
|
-
fetchFn?: typeof fetch;
|
|
1446
|
-
/**
|
|
1447
|
-
* Factory for the EventSource. Defaults to `new globalThis.EventSource(url,
|
|
1448
|
-
* { withCredentials })`, guarded by a `typeof` check — when EventSource is
|
|
1449
|
-
* absent (or the factory yields nothing) the subscriber starts on the polling
|
|
1450
|
-
* fallback instead.
|
|
1451
|
-
*/
|
|
1452
|
-
eventSourceFactory?: SmrtWebEventSourceFactory;
|
|
1453
|
-
/** Poll interval for the `_changes` fallback (ms). Default 5000. */
|
|
1454
|
-
pollIntervalMs?: number;
|
|
1455
|
-
/** `withCredentials` for the EventSource (cookie auth). Default true. */
|
|
1456
|
-
withCredentials?: boolean;
|
|
1457
|
-
/**
|
|
1458
|
-
* The RUNNING build's web-collection shape digest. When paired with
|
|
1459
|
-
* `updateState`, a differing server hash from the `_events` manifest frame
|
|
1460
|
-
* latches the contract update signal (#1859).
|
|
1461
|
-
*/
|
|
1462
|
-
manifestHash?: string;
|
|
1463
|
-
/**
|
|
1464
|
-
* Optional update-state primitive from `createUpdateState()`. Only its
|
|
1465
|
-
* contract signal is used here; bundle polling remains the caller's job.
|
|
1466
|
-
*/
|
|
1467
|
-
updateState?: Pick<UpdateState, 'notifyContractUpdated'>;
|
|
1468
|
-
}
|
|
1469
|
-
|
|
1470
|
-
/**
|
|
1471
|
-
* Field metadata emitted per column by the `@happyvertical/smrt-virt-web`
|
|
1472
|
-
* virtual module (generated from the package manifest).
|
|
1473
|
-
*/
|
|
1474
|
-
export declare interface SmrtWebFieldDefinition {
|
|
1475
|
-
type: SmrtWebFieldType;
|
|
1476
|
-
required?: boolean;
|
|
1477
|
-
/** Whether the public field contract explicitly permits `null`. */
|
|
1478
|
-
nullable?: boolean;
|
|
1479
|
-
default?: unknown;
|
|
1480
|
-
/** Developer-authored `@field({ description })` (#2046) — end-user help seed. */
|
|
1481
|
-
description?: string;
|
|
1482
|
-
/** Static `@field({ ui })` hints (#2046). */
|
|
1483
|
-
ui?: SmrtWebFieldUIHints;
|
|
1484
|
-
}
|
|
1485
|
-
|
|
1486
|
-
/**
|
|
1487
|
-
* The field types core's web-collection emission actually produces —
|
|
1488
|
-
* relationship pseudo-columns (`oneToMany`/`manyToMany`) and STI `meta`
|
|
1489
|
-
* internals never reach an emitted definition. Textual mirror of core's
|
|
1490
|
-
* `WebFieldType` (this package is deliberately smrt-dependency-free, so it
|
|
1491
|
-
* cannot import the source type); the four co-managed sites are core's
|
|
1492
|
-
* runtime type, the ambient virt-web d.ts, the physical `@smrt/web` d.ts,
|
|
1493
|
-
* and this mirror.
|
|
1494
|
-
*/
|
|
1495
|
-
export declare type SmrtWebFieldType = 'text' | 'decimal' | 'boolean' | 'integer' | 'datetime' | 'json' | 'foreignKey' | 'crossPackageRef';
|
|
1496
|
-
|
|
1497
|
-
/** Static `@field({ ui })` hints (#2046) — the field-policy rail seed. */
|
|
1498
|
-
export declare interface SmrtWebFieldUIHints {
|
|
1499
|
-
basic?: boolean;
|
|
1500
|
-
group?: string;
|
|
1501
|
-
order?: number;
|
|
1502
|
-
locked?: boolean;
|
|
1503
|
-
}
|
|
1504
|
-
|
|
1505
|
-
/**
|
|
1506
|
-
* A single mutation described in SMRT-owned terms — handed to
|
|
1507
|
-
* {@link SmrtWebCapability.wrapMutation} and {@link SmrtWebCapability.onSettled}
|
|
1508
|
-
* so a capability can inspect or intercept a write without touching the engine's
|
|
1509
|
-
* transaction type.
|
|
1510
|
-
*/
|
|
1511
|
-
export declare interface SmrtWebMutationEnvelope {
|
|
1512
|
-
/** Which mutation kind this describes. */
|
|
1513
|
-
readonly kind: 'insert' | 'update' | 'delete';
|
|
1514
|
-
/** The row key: the client-local id on insert, else the target row's id. */
|
|
1515
|
-
readonly key: string;
|
|
1516
|
-
/**
|
|
1517
|
-
* The write payload: the full row on insert, the changed fields on update,
|
|
1518
|
-
* and an empty object on delete (the key carries the target).
|
|
1519
|
-
*/
|
|
1520
|
-
readonly data: Record<string, unknown>;
|
|
1521
|
-
/**
|
|
1522
|
-
* The server `updated_at` / `updatedAt` value the mutation is based on, when
|
|
1523
|
-
* known. Update/delete handlers capture this from the original row so offline
|
|
1524
|
-
* replay can preserve the sync/apply conflict guard even when the write
|
|
1525
|
-
* payload only carries changed fields (or no fields for delete).
|
|
1526
|
-
*/
|
|
1527
|
-
readonly baseUpdatedAt?: string;
|
|
1528
|
-
}
|
|
1529
|
-
|
|
1530
|
-
export declare interface SmrtWebQuery<TData extends object = object> {
|
|
1531
|
-
readonly state: SmrtWebQueryState<TData>;
|
|
1532
|
-
readonly request: SmrtWebDataQueryRequest | undefined;
|
|
1533
|
-
execute(request: SmrtWebDataQueryRequest, options?: SmrtWebQueryRunOptions): Promise<SmrtWebDataQueryResult>;
|
|
1534
|
-
refresh(options?: Omit<SmrtWebQueryRunOptions, 'mode' | 'force'>): Promise<SmrtWebDataQueryResult | undefined>;
|
|
1535
|
-
retry(): Promise<SmrtWebDataQueryResult | undefined>;
|
|
1536
|
-
subscribe(listener: (state: SmrtWebQueryState<TData>) => void): () => void;
|
|
1537
|
-
subscribeLive(): SmrtWebQueryLiveSubscription | undefined;
|
|
1538
|
-
invalidate(): void;
|
|
1539
|
-
dispose(): void;
|
|
1540
|
-
}
|
|
1541
|
-
|
|
1542
|
-
export declare interface SmrtWebQueryLiveSubscription {
|
|
1543
|
-
unsubscribe(): void;
|
|
1544
|
-
reconnect(): void;
|
|
1545
|
-
}
|
|
1546
|
-
|
|
1547
|
-
/** How a query run is allowed to affect the visible query state. */
|
|
1548
|
-
export declare type SmrtWebQueryMode = 'visible' | 'background' | 'prefetch' | 'silent';
|
|
1549
|
-
|
|
1550
|
-
export declare interface SmrtWebQueryPage {
|
|
1551
|
-
kind: 'offset' | 'cursor';
|
|
1552
|
-
limit: number;
|
|
1553
|
-
offset?: number;
|
|
1554
|
-
nextCursor?: string;
|
|
1555
|
-
hasMore: boolean;
|
|
1556
|
-
}
|
|
1557
|
-
|
|
1558
|
-
export declare interface SmrtWebQueryRunOptions {
|
|
1559
|
-
mode?: SmrtWebQueryMode;
|
|
1560
|
-
signal?: AbortSignal;
|
|
1561
|
-
/** Cancel this run after the given number of milliseconds. */
|
|
1562
|
-
deadlineMs?: number;
|
|
1563
|
-
/** Bypass the keyed cache and execute a fresh request (used by refresh). */
|
|
1564
|
-
force?: boolean;
|
|
1565
|
-
}
|
|
1566
|
-
|
|
1567
|
-
export declare interface SmrtWebQueryState<TData extends object = object> {
|
|
1568
|
-
readonly rows: ReadonlyArray<TData>;
|
|
1569
|
-
readonly page: SmrtWebQueryPage | undefined;
|
|
1570
|
-
readonly total: SmrtWebDataQueryResult['total'] | undefined;
|
|
1571
|
-
readonly loading: boolean;
|
|
1572
|
-
readonly refreshing: boolean;
|
|
1573
|
-
readonly stale: boolean;
|
|
1574
|
-
readonly error: unknown;
|
|
1575
|
-
readonly lastUpdated: number | undefined;
|
|
1576
|
-
readonly result: SmrtWebDataQueryResult | undefined;
|
|
1577
|
-
}
|
|
1578
|
-
|
|
1579
|
-
export declare interface SmrtWebQueryTransport extends SmrtWebDataQueryTransport {
|
|
1580
|
-
/** Subscribe to changes for this exact query, not the entire collection. */
|
|
1581
|
-
subscribe?(request: SmrtWebDataQueryRequest, onResult: (result: unknown) => void, options?: {
|
|
1582
|
-
signal?: AbortSignal;
|
|
1583
|
-
}): SmrtWebQueryLiveSubscription | {
|
|
1584
|
-
unsubscribe(): void;
|
|
1585
|
-
};
|
|
1586
|
-
}
|
|
1587
|
-
|
|
1588
|
-
/**
|
|
1589
|
-
* A manifest-derived edge from this collection to a sibling REST collection,
|
|
1590
|
-
* emitted by the `@happyvertical/smrt-virt-web` virtual module. When a mutation
|
|
1591
|
-
* on this collection settles, the caches of the collections named by these
|
|
1592
|
-
* edges are invalidated (relationship-derived invalidation, #1761), so a
|
|
1593
|
-
* dependent view refetches without any hand-wired cache key.
|
|
1594
|
-
*
|
|
1595
|
-
* SMRT-owned data — no client-engine (`@tanstack/*`) type appears here, so it
|
|
1596
|
-
* stays inside the engine-absorption boundary.
|
|
1597
|
-
*/
|
|
1598
|
-
export declare interface SmrtWebRelationship {
|
|
1599
|
-
/** The declaring field carrying the relationship (e.g. `groupId`, `items`). */
|
|
1600
|
-
field: string;
|
|
1601
|
-
/** The relationship kind, mirroring the manifest field type. */
|
|
1602
|
-
kind: SmrtWebRelationshipKind;
|
|
1603
|
-
/** REST collection name the edge resolves to (e.g. `ad_groups`). */
|
|
1604
|
-
relatedCollection: string;
|
|
1605
|
-
}
|
|
1606
|
-
|
|
1607
|
-
/** The relationship kinds a generated web collection edge can describe. */
|
|
1608
|
-
export declare type SmrtWebRelationshipKind = 'foreignKey' | 'crossPackageRef' | 'oneToMany' | 'manyToMany';
|
|
1609
|
-
|
|
1610
|
-
/**
|
|
1611
|
-
* Raised when a generated-client call resolved with an error payload
|
|
1612
|
-
* (`{ error: string }` from the generated REST routes) or an unexpected shape.
|
|
1613
|
-
* Thrown inside a mutation handler, this triggers the automatic rollback of
|
|
1614
|
-
* optimistic state. HTTP 5xx failures are always opaque: their server payload
|
|
1615
|
-
* is neither parsed nor retained because it may contain internal detail.
|
|
1616
|
-
*/
|
|
1617
|
-
export declare class SmrtWebRequestError extends Error {
|
|
1618
|
-
readonly payload: unknown;
|
|
1619
|
-
readonly status?: number;
|
|
1620
|
-
readonly code?: string;
|
|
1621
|
-
constructor(message: string, payload?: unknown, status?: number, code?: string);
|
|
1622
|
-
}
|
|
1623
|
-
|
|
1624
|
-
/** A row as stored in the client collection: the DTO plus a required key. */
|
|
1625
|
-
export declare type SmrtWebRow<TData extends object> = TData & {
|
|
1626
|
-
id: string;
|
|
1627
|
-
};
|
|
1628
|
-
|
|
1629
|
-
/** Which transport a subscriber is currently using. */
|
|
1630
|
-
export declare type SmrtWebSubscriberTransport = 'sse' | 'polling' | 'idle';
|
|
1631
|
-
|
|
1632
|
-
/** A change-subscription handle. Call {@link unsubscribe} to detach. */
|
|
1633
|
-
export declare interface SmrtWebSubscription {
|
|
1634
|
-
unsubscribe(): void;
|
|
1635
|
-
}
|
|
1636
|
-
|
|
1637
|
-
export declare interface SmrtWebToolRouteDescriptor {
|
|
1638
|
-
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
1639
|
-
scope: 'item' | 'collection';
|
|
1640
|
-
/** Route segments below the collection endpoint; dynamic segments use `[x]`. */
|
|
1641
|
-
path: string[];
|
|
1642
|
-
/** Transport names rewritten by the tool schema (e.g. `actionId` → `id`). */
|
|
1643
|
-
parameterAliases?: Record<string, string>;
|
|
1644
|
-
/** The generated method accepts one `options` bag as its sole argument. */
|
|
1645
|
-
optionsBag?: boolean;
|
|
1646
|
-
}
|
|
1647
|
-
|
|
1648
|
-
/**
|
|
1649
|
-
* A pending optimistic mutation. Await {@link isPersisted} to observe the
|
|
1650
|
-
* server outcome: it resolves once the write has been persisted through the
|
|
1651
|
-
* REST surface, and rejects (rolling the optimistic state back) on error.
|
|
1652
|
-
*/
|
|
1653
|
-
export declare interface SmrtWebTransaction {
|
|
1654
|
-
readonly isPersisted: {
|
|
1655
|
-
readonly promise: Promise<unknown>;
|
|
1656
|
-
};
|
|
1657
|
-
}
|
|
1658
|
-
|
|
1659
|
-
/**
|
|
1660
|
-
* @happyvertical/smrt-web — offline outbox shared types (#1762).
|
|
1661
|
-
*
|
|
1662
|
-
* The SMRT-owned vocabulary the outbox modules (`durable-queue`, `leader`,
|
|
1663
|
-
* `engine`) and the public surface (`offline.ts`) share. Kept in its own leaf
|
|
1664
|
-
* module — imported by everything, importing nothing from the package — so there
|
|
1665
|
-
* is no cycle back through `index.ts` and the whole outbox stays inside the
|
|
1666
|
-
* engine-absorption boundary (#1761): NOT ONE `@tanstack/*` type appears here.
|
|
1667
|
-
*
|
|
1668
|
-
* The sync-apply op/status/reason names mirror
|
|
1669
|
-
* `packages/core/src/sync/apply.ts` (the replay target) verbatim, so a queue row
|
|
1670
|
-
* maps to a batch item and a batch result maps to a state transition with no
|
|
1671
|
-
* translation layer. smrt-web has no inter-smrt dependency (dependency-DAG
|
|
1672
|
-
* guardrails), so these are re-declared here rather than imported from core.
|
|
1673
|
-
*/
|
|
1674
|
-
/**
|
|
1675
|
-
* Mutation kinds the sync-apply batch endpoint accepts. Mirrors core's
|
|
1676
|
-
* `SyncApplyOp`. The outbox maps the capability seam's insert/update/delete
|
|
1677
|
-
* envelope kinds onto these (`insert → create`).
|
|
1678
|
-
*/
|
|
1679
|
-
declare type SyncApplyOp = 'create' | 'update' | 'delete';
|
|
1680
|
-
|
|
1681
|
-
/**
|
|
1682
|
-
* Machine-readable reasons a sync-apply item was `conflict` or `rejected`.
|
|
1683
|
-
* Mirrors core's `SyncApplyReason` union. Drives the engine's result mapping:
|
|
1684
|
-
* `auth_required`/`forbidden` pause the loop; `write_failed` retries; the rest
|
|
1685
|
-
* are terminal.
|
|
1686
|
-
*/
|
|
1687
|
-
declare type SyncApplyReason = 'invalid_item' | 'invalid_id' | 'invalid_payload' | 'unknown_object' | 'op_not_allowed' | 'auth_required' | 'forbidden' | 'not_found' | 'id_conflict' | 'write_failed' | 'stale_write' | 'create_conflict';
|
|
1688
|
-
|
|
1689
|
-
/**
|
|
1690
|
-
* A sync-state transition delivered to {@link OfflineOutboxConfig.onSyncStateChange}.
|
|
1691
|
-
* A PUSH callback (not a subscribable store): smrt-svelte wraps it into a
|
|
1692
|
-
* reactive binding later (#1762 follow-on). Carries enough for an app to render
|
|
1693
|
-
* a per-row indicator and a retry affordance.
|
|
1694
|
-
*/
|
|
1695
|
-
export declare interface SyncStateEvent {
|
|
1696
|
-
/** The queue row's `itemId` (its idempotency handle) this state is for. */
|
|
1697
|
-
itemId: string;
|
|
1698
|
-
/** The client-generated row UUID the mutation targets. */
|
|
1699
|
-
rowId: string;
|
|
1700
|
-
/** The collection route segment (e.g. `products`). */
|
|
1701
|
-
object: string;
|
|
1702
|
-
/** The new observable state. */
|
|
1703
|
-
state: OutboxSyncState;
|
|
1704
|
-
/** How many replay attempts have run (0 until the first send). */
|
|
1705
|
-
attempts: number;
|
|
1706
|
-
/** The last replay error message, when `state` is `pending` after a retry. */
|
|
1707
|
-
error?: string;
|
|
1708
|
-
}
|
|
1709
|
-
|
|
1710
|
-
/** Reject generated REST error envelopes while preserving opaque successes. */
|
|
1711
|
-
export declare function throwIfSmrtWebError(result: unknown, context: string): unknown;
|
|
1712
|
-
|
|
1713
|
-
/**
|
|
1714
|
-
* Normalize a generated-client item result (create/update) to a row.
|
|
1715
|
-
* `{ error }` payloads become failures — inside mutation handlers this is what
|
|
1716
|
-
* makes optimistic state roll back.
|
|
1717
|
-
*/
|
|
1718
|
-
export declare function unwrapItemResult(result: unknown, context: string): Record<string, unknown>;
|
|
1719
|
-
|
|
1720
|
-
/**
|
|
1721
|
-
* Normalize a generated-client list result to an array of rows.
|
|
1722
|
-
*
|
|
1723
|
-
* The generated REST routes return a bare JSON array; `{ error }` payloads are
|
|
1724
|
-
* surfaced as failures. The `{ data: [...] }` envelope is tolerated for
|
|
1725
|
-
* ApiResponse-shaped clients (e.g. a mock client).
|
|
1726
|
-
*/
|
|
1727
|
-
export declare function unwrapListResult(result: unknown, collectionName: string): Array<Record<string, unknown>>;
|
|
1728
|
-
|
|
1729
|
-
/** The two independent update signals plus their derived union. */
|
|
1730
|
-
export declare interface UpdateAvailableState {
|
|
1731
|
-
/** The client bundle changed on the server (SvelteKit `updated`). */
|
|
1732
|
-
readonly bundle: boolean;
|
|
1733
|
-
/** The API contract (manifest hash) changed across this load. */
|
|
1734
|
-
readonly contract: boolean;
|
|
1735
|
-
/** `bundle || contract` — either means an update is available. */
|
|
1736
|
-
readonly updateAvailable: boolean;
|
|
1737
|
-
}
|
|
1738
|
-
|
|
1739
|
-
/** The framework-free update-available primitive. */
|
|
1740
|
-
export declare interface UpdateState {
|
|
1741
|
-
/** The current signal state (a fresh immutable snapshot). */
|
|
1742
|
-
get(): UpdateAvailableState;
|
|
1743
|
-
/**
|
|
1744
|
-
* Subscribe to state changes; the callback fires immediately with the current
|
|
1745
|
-
* state and again on every transition. Returns an unsubscribe function.
|
|
1746
|
-
*/
|
|
1747
|
-
subscribe(callback: (state: UpdateAvailableState) => void): () => void;
|
|
1748
|
-
/**
|
|
1749
|
-
* Push the BUNDLE signal — call from the consumer/smrt-svelte binding when
|
|
1750
|
-
* SvelteKit's `updated` store flips true. Idempotent: once set it stays set
|
|
1751
|
-
* (a bundle update does not un-happen).
|
|
1752
|
-
*/
|
|
1753
|
-
notifyBundleUpdated(): void;
|
|
1754
|
-
/**
|
|
1755
|
-
* Push the API CONTRACT signal — call when a live transport observes a server
|
|
1756
|
-
* `manifestHash` that differs from this running build (#1859). Idempotent:
|
|
1757
|
-
* once set it stays set (a contract mismatch does not un-happen).
|
|
1758
|
-
*/
|
|
1759
|
-
notifyContractUpdated(): void;
|
|
1760
|
-
/**
|
|
1761
|
-
* Resolves once the async contract detection has settled (compared the running
|
|
1762
|
-
* hash against the persisted last-seen value and fired the signal if needed).
|
|
1763
|
-
* Primarily for tests/SSR; UI code just subscribes.
|
|
1764
|
-
*/
|
|
1765
|
-
readonly ready: Promise<void>;
|
|
1766
|
-
/** Detach the durable resource (does NOT wipe — that's wipeDurableStore). */
|
|
1767
|
-
dispose(): void;
|
|
1768
|
-
}
|
|
1769
|
-
|
|
1770
|
-
/** Configuration for {@link createUpdateState}. */
|
|
1771
|
-
export declare interface UpdateStateConfig {
|
|
1772
|
-
/**
|
|
1773
|
-
* The RUNNING build's web-collection shape digest — the `manifestHash`
|
|
1774
|
-
* constant the generated `@happyvertical/smrt-virt-web` module exports
|
|
1775
|
-
* (#1764). Compared against the persisted last-seen value to detect a contract
|
|
1776
|
-
* change across loads. Omit to disable contract detection (bundle-only).
|
|
1777
|
-
*/
|
|
1778
|
-
manifestHash?: string;
|
|
1779
|
-
/**
|
|
1780
|
-
* The durable-store identity the last-seen manifest hash is namespaced under —
|
|
1781
|
-
* folds api base / tenant / identity (and, yes, the manifest hash itself, but
|
|
1782
|
-
* see below). Shared with persistence/outbox so one {@link wipeDurableStore}
|
|
1783
|
-
* clears the last-seen record too.
|
|
1784
|
-
*
|
|
1785
|
-
* NOTE the namespace's OWN `manifestHash` segment should be a STABLE value
|
|
1786
|
-
* (e.g. the app's api-version or a constant), NOT the running build hash —
|
|
1787
|
-
* otherwise a contract change would move the namespace and the compare would
|
|
1788
|
-
* never find the prior value (always "first run"). Contract change is detected
|
|
1789
|
-
* by the STORED VALUE under a stable namespace, not by the namespace moving.
|
|
1790
|
-
*/
|
|
1791
|
-
namespace: DurableStoreKey;
|
|
1792
|
-
}
|
|
1793
|
-
|
|
1794
|
-
/** Validate that an opaque cache handle came from {@link createSmrtWebClient}. */
|
|
1795
|
-
export declare function validateSmrtWebClient(client: SmrtWebClient): void;
|
|
1796
|
-
|
|
1797
|
-
/**
|
|
1798
|
-
* A validated, frozen intent.
|
|
1799
|
-
*
|
|
1800
|
-
* `kind: 'intent'` and `id` are the exported identity a `smrt-playbooks`
|
|
1801
|
-
* step reference (`{ kind: 'intent', id }`) names, and this object is
|
|
1802
|
-
* directly assignable to that package's `PlaybookIntentRecord` seam —
|
|
1803
|
-
* `{ id, classification, planes }` — so {@link resolveViewIntent} can be
|
|
1804
|
-
* passed as its `intents` resolver unchanged.
|
|
1805
|
-
*/
|
|
1806
|
-
export declare interface ViewIntent {
|
|
1807
|
-
readonly kind: 'intent';
|
|
1808
|
-
readonly id: string;
|
|
1809
|
-
readonly description: string;
|
|
1810
|
-
readonly inputSchema: Record<string, unknown>;
|
|
1811
|
-
/** Resolved through the shared fail-closed rule at declaration time. */
|
|
1812
|
-
readonly classification: WebMcpCapabilityClassification;
|
|
1813
|
-
readonly target: ViewIntentTarget;
|
|
1814
|
-
/**
|
|
1815
|
-
* An intent moves mounted browser state, so it is browser-valid only. A
|
|
1816
|
-
* server-side agent reaches one through the #2446 command/ack bridge, which
|
|
1817
|
-
* a playbook must declare explicitly.
|
|
1818
|
-
*/
|
|
1819
|
-
readonly planes: readonly ['browser'];
|
|
1820
|
-
}
|
|
1821
|
-
|
|
1822
|
-
/** The mounted identity a binding supplies for an intent's lifetime. */
|
|
1823
|
-
export declare type ViewIntentBinding = {
|
|
1824
|
-
registry: 'control';
|
|
1825
|
-
registryPort: ViewIntentControlRegistryPort;
|
|
1826
|
-
identity: ViewIntentControlIdentity;
|
|
1827
|
-
} | {
|
|
1828
|
-
registry: 'dataSurface';
|
|
1829
|
-
registryPort: ViewIntentDataSurfaceRegistryPort;
|
|
1830
|
-
identity: ViewIntentDataSurfaceIdentity;
|
|
1831
|
-
};
|
|
1832
|
-
|
|
1833
|
-
/**
|
|
1834
|
-
* Control commands a view intent may dispatch. Structurally mirrors
|
|
1835
|
-
* `ControlCommandAction` in `@happyvertical/smrt-ui/forms`; this package
|
|
1836
|
-
* cannot import that one (see AGENTS.md "No inter-smrt dependencies").
|
|
1837
|
-
*/
|
|
1838
|
-
export declare type ViewIntentControlAction = 'focus' | 'reveal' | 'highlight' | 'explain' | 'validate' | 'stage' | 'apply' | 'discard' | 'clear' | 'undo';
|
|
1839
|
-
|
|
1840
|
-
/** A mounted control's full registry key, subject included. */
|
|
1841
|
-
export declare interface ViewIntentControlIdentity {
|
|
1842
|
-
formId: string;
|
|
1843
|
-
controlId: string;
|
|
1844
|
-
subject?: ViewIntentSubject;
|
|
1845
|
-
}
|
|
1846
|
-
|
|
1847
|
-
/**
|
|
1848
|
-
* The `ControlInteractionRegistry` surface an intent uses. Declared
|
|
1849
|
-
* structurally so this package takes no dependency on
|
|
1850
|
-
* `@happyvertical/smrt-ui`; the real registry satisfies it.
|
|
1851
|
-
*/
|
|
1852
|
-
export declare interface ViewIntentControlRegistryPort {
|
|
1853
|
-
execute(command: {
|
|
1854
|
-
action: ViewIntentControlAction;
|
|
1855
|
-
identity: ViewIntentControlIdentity;
|
|
1856
|
-
value?: unknown;
|
|
1857
|
-
durationMs?: number;
|
|
1858
|
-
revision?: number;
|
|
1859
|
-
}, context?: {
|
|
1860
|
-
source: 'agent';
|
|
1861
|
-
}): Promise<{
|
|
1862
|
-
ok: boolean;
|
|
1863
|
-
reason?: string;
|
|
1864
|
-
}>;
|
|
1865
|
-
}
|
|
1866
|
-
|
|
1867
|
-
/**
|
|
1868
|
-
* A control-registry target: the intent dispatches exactly one
|
|
1869
|
-
* `ControlInteractionRegistry` command against a mounted control.
|
|
1870
|
-
*
|
|
1871
|
-
* `formId`/`controlId` are the statically declared half of the identity. A
|
|
1872
|
-
* binding supplies the mounted identity and must MATCH anything declared
|
|
1873
|
-
* here — a declaration is authority over a binding, never the other way
|
|
1874
|
-
* round.
|
|
1875
|
-
*/
|
|
1876
|
-
export declare interface ViewIntentControlTarget {
|
|
1877
|
-
registry: 'control';
|
|
1878
|
-
action: ViewIntentControlAction;
|
|
1879
|
-
formId?: string;
|
|
1880
|
-
controlId?: string;
|
|
1881
|
-
}
|
|
1882
|
-
|
|
1883
|
-
/** A mounted data surface's full registry key, subject included. */
|
|
1884
|
-
export declare interface ViewIntentDataSurfaceIdentity {
|
|
1885
|
-
surfaceId: string;
|
|
1886
|
-
kind: ViewIntentDataSurfaceKind;
|
|
1887
|
-
subject?: ViewIntentSubject;
|
|
1888
|
-
}
|
|
1889
|
-
|
|
1890
|
-
/** Mirrors `DataSurfaceIdentity['kind']` in `@happyvertical/smrt-ui/data`. */
|
|
1891
|
-
export declare type ViewIntentDataSurfaceKind = 'table' | 'list' | 'report' | 'custom';
|
|
1892
|
-
|
|
1893
|
-
/** The `DataSurfaceRegistry` surface an intent uses. */
|
|
1894
|
-
export declare interface ViewIntentDataSurfaceRegistryPort {
|
|
1895
|
-
inspect(identity: ViewIntentDataSurfaceIdentity): {
|
|
1896
|
-
revision: number;
|
|
1897
|
-
} | undefined;
|
|
1898
|
-
execute(command: {
|
|
1899
|
-
version: 1;
|
|
1900
|
-
commandId: string;
|
|
1901
|
-
identity: ViewIntentDataSurfaceIdentity;
|
|
1902
|
-
expectedRevision: number;
|
|
1903
|
-
controlId: string;
|
|
1904
|
-
payload?: unknown;
|
|
1905
|
-
}): Promise<{
|
|
1906
|
-
ok: boolean;
|
|
1907
|
-
revision?: number;
|
|
1908
|
-
reason?: string;
|
|
1909
|
-
}>;
|
|
1910
|
-
}
|
|
1911
|
-
|
|
1912
|
-
/**
|
|
1913
|
-
* A data-surface target: the intent dispatches one
|
|
1914
|
-
* `DataSurfaceVisibleCommand` — a browser-visible state transition, never a
|
|
1915
|
-
* server-side query or mutation.
|
|
1916
|
-
*/
|
|
1917
|
-
export declare interface ViewIntentDataSurfaceTarget {
|
|
1918
|
-
registry: 'dataSurface';
|
|
1919
|
-
/** The visible-command `controlId` the mounted surface implements. */
|
|
1920
|
-
controlId: string;
|
|
1921
|
-
surfaceId?: string;
|
|
1922
|
-
kind?: ViewIntentDataSurfaceKind;
|
|
1923
|
-
}
|
|
1924
|
-
|
|
1925
|
-
/**
|
|
1926
|
-
* The literal object passed to {@link defineIntent}. Every field is data;
|
|
1927
|
-
* none is a function, a URL, or a route.
|
|
1928
|
-
*/
|
|
1929
|
-
export declare interface ViewIntentDeclaration {
|
|
1930
|
-
/**
|
|
1931
|
-
* Stable, namespaced identity — at least one dot, lowercase, e.g.
|
|
1932
|
-
* `orders.filter_by_status`. It is the intent's name in the manifest
|
|
1933
|
-
* (#2591) and in a playbook step (`{ kind: 'intent', id }`, #2589), so it
|
|
1934
|
-
* must not be derived from anything that can change (a namespace, a
|
|
1935
|
-
* generated tool name, a route).
|
|
1936
|
-
*/
|
|
1937
|
-
id: string;
|
|
1938
|
-
/** Human/agent-readable description. Becomes the tool description. */
|
|
1939
|
-
description: string;
|
|
1940
|
-
/** JSON Schema for the tool's arguments. Must be plain JSON. */
|
|
1941
|
-
inputSchema?: Record<string, unknown>;
|
|
1942
|
-
/**
|
|
1943
|
-
* Partial capability declaration resolved by the shared fail-closed rule
|
|
1944
|
-
* (#2587). Omitted entirely, an intent classifies destructive,
|
|
1945
|
-
* non-idempotent, open-world.
|
|
1946
|
-
*/
|
|
1947
|
-
capability?: WebMcpCapabilityDeclaration;
|
|
1948
|
-
/** Which registry this compiles into, and what it addresses there. */
|
|
1949
|
-
target: ViewIntentTarget;
|
|
1950
|
-
}
|
|
1951
|
-
|
|
1952
|
-
/**
|
|
1953
|
-
* The optional record a registry identity is qualified by. Rich forms use it
|
|
1954
|
-
* to tell apart controls that share a `formId`/`controlId` across records.
|
|
1955
|
-
* Structurally mirrors `ControlIdentity['subject']` /
|
|
1956
|
-
* `DataSurfaceIdentity['subject']` in `@happyvertical/smrt-ui`.
|
|
1957
|
-
*/
|
|
1958
|
-
export declare interface ViewIntentSubject {
|
|
1959
|
-
type: string;
|
|
1960
|
-
id: string;
|
|
1961
|
-
label?: string;
|
|
1962
|
-
}
|
|
1963
|
-
|
|
1964
|
-
export declare type ViewIntentTarget = ViewIntentControlTarget | ViewIntentDataSurfaceTarget;
|
|
1965
|
-
|
|
1966
|
-
/** Derive the WebMCP tool name for an intent id. */
|
|
1967
|
-
export declare function viewIntentToolName(id: string): string;
|
|
1968
|
-
|
|
1969
|
-
/**
|
|
1970
|
-
* A bespoke tool spec, structurally identical to
|
|
1971
|
-
* `WebMcpBespokeToolSpec` in `./webmcp.js`. Declared here rather than
|
|
1972
|
-
* imported so this module stays free of even a type edge to the registrar
|
|
1973
|
-
* entry.
|
|
1974
|
-
*/
|
|
1975
|
-
export declare interface ViewIntentToolSpec {
|
|
1976
|
-
name: string;
|
|
1977
|
-
description: string;
|
|
1978
|
-
inputSchema: Record<string, unknown>;
|
|
1979
|
-
annotations: WebMcpCapabilityAnnotations;
|
|
1980
|
-
execute: (args: Record<string, unknown>) => Promise<string>;
|
|
1981
|
-
}
|
|
1982
|
-
|
|
1983
|
-
/**
|
|
1984
|
-
* A hand-written browser tool from application code — not generated from a
|
|
1985
|
-
* `@smrt()` model. Structurally identical to the WebMCP `registerTool` input;
|
|
1986
|
-
* kept as a separate type so this framework-agnostic module never depends on
|
|
1987
|
-
* a UI layer's tool-spec type.
|
|
1988
|
-
*/
|
|
1989
|
-
export declare interface WebMcpBespokeToolSpec {
|
|
1990
|
-
name: string;
|
|
1991
|
-
description: string;
|
|
1992
|
-
inputSchema: Record<string, unknown>;
|
|
1993
|
-
annotations?: {
|
|
1994
|
-
readOnlyHint?: boolean;
|
|
1995
|
-
destructiveHint?: boolean;
|
|
1996
|
-
idempotentHint?: boolean;
|
|
1997
|
-
openWorldHint?: boolean;
|
|
1998
|
-
untrustedContentHint?: boolean;
|
|
1999
|
-
};
|
|
2000
|
-
execute: (args: Record<string, unknown>, options?: WebMcpToolExecutionOptions) => string | Promise<string>;
|
|
2001
|
-
}
|
|
2002
|
-
|
|
2003
|
-
/** The MCP-shaped annotation set a resolved classification emits. */
|
|
2004
|
-
declare interface WebMcpCapabilityAnnotations {
|
|
2005
|
-
readOnlyHint: boolean;
|
|
2006
|
-
destructiveHint: boolean;
|
|
2007
|
-
idempotentHint: boolean;
|
|
2008
|
-
openWorldHint: boolean;
|
|
2009
|
-
untrustedContentHint: boolean;
|
|
2010
|
-
}
|
|
2011
|
-
|
|
2012
|
-
/** A fully resolved classification. */
|
|
2013
|
-
declare interface WebMcpCapabilityClassification {
|
|
2014
|
-
effect: WebMcpToolEffect;
|
|
2015
|
-
/**
|
|
2016
|
-
* Derived, never declared: every non-read effect is annotated destructive
|
|
2017
|
-
* to the browser, so a `write` capability cannot claim the MCP
|
|
2018
|
-
* additive-only guarantee.
|
|
2019
|
-
*/
|
|
2020
|
-
destructive: boolean;
|
|
2021
|
-
idempotent: boolean;
|
|
2022
|
-
openWorld: boolean;
|
|
2023
|
-
}
|
|
2024
|
-
|
|
2025
|
-
/**
|
|
2026
|
-
* An author-supplied, partial classification. Any omitted field resolves
|
|
2027
|
-
* through the fail-closed rule on {@link resolveDeclaredCapability}, never
|
|
2028
|
-
* through a CRUD- or name-based guess.
|
|
2029
|
-
*/
|
|
2030
|
-
declare interface WebMcpCapabilityDeclaration {
|
|
2031
|
-
effect?: WebMcpToolEffect;
|
|
2032
|
-
idempotent?: boolean;
|
|
2033
|
-
openWorld?: boolean;
|
|
2034
|
-
}
|
|
2035
|
-
|
|
2036
|
-
export declare interface WebMcpExposurePolicy {
|
|
2037
|
-
/** Allowed effects. Omitted means read-only exposure. */
|
|
2038
|
-
effects?: readonly WebMcpToolEffect[];
|
|
2039
|
-
/** Prefix every registered tool name with `<namespace>_`. */
|
|
2040
|
-
namespace?: string;
|
|
2041
|
-
/** Optional maximum tools registered by one call. */
|
|
2042
|
-
maxTools?: number;
|
|
2043
|
-
}
|
|
2044
|
-
|
|
2045
|
-
/** Accepted legacy collection definitions and canonical per-tool definitions. */
|
|
2046
|
-
export declare type WebMcpRegistrationDefinition = SmrtWebCollectionDefinition | WebMcpToolDefinition;
|
|
2047
|
-
|
|
2048
|
-
/** Disposes a registration and exposes completion of browser registration. */
|
|
2049
|
-
export declare interface WebMcpRegistrationDisposer {
|
|
2050
|
-
(): void;
|
|
2051
|
-
/** Rejects if the browser rejects any tool; all sibling tools are aborted. */
|
|
2052
|
-
readonly ready: Promise<void>;
|
|
2053
|
-
}
|
|
2054
|
-
|
|
2055
|
-
/**
|
|
2056
|
-
* Canonical data-only definition for one API-backed browser tool. Unlike a
|
|
2057
|
-
* collection definition, this does not imply that a list route or client cache
|
|
2058
|
-
* exists. Generated definitions carry explicit semantics; manual legacy
|
|
2059
|
-
* literals may omit them and register with fail-closed defaults.
|
|
2060
|
-
*/
|
|
2061
|
-
export declare interface WebMcpToolDefinition extends WebToolDescriptor {
|
|
2062
|
-
/** Stable definition identity is `(collection, action)`. */
|
|
2063
|
-
collection: string;
|
|
2064
|
-
/** Canonical qualified row-model identity. */
|
|
2065
|
-
objectRef: string;
|
|
2066
|
-
/** Row-model class used by the shared MCP tool vocabulary. */
|
|
2067
|
-
className: string;
|
|
2068
|
-
endpoint: string;
|
|
2069
|
-
idField: string;
|
|
2070
|
-
idType: 'uuid' | 'text';
|
|
2071
|
-
/** Complete generated route metadata, including CRUD actions. */
|
|
2072
|
-
route: SmrtWebToolRouteDescriptor;
|
|
2073
|
-
/** Cache-invalidation edges for materialized sibling collections. */
|
|
2074
|
-
relationships: SmrtWebRelationship[];
|
|
2075
|
-
}
|
|
2076
|
-
|
|
2077
|
-
/**
|
|
2078
|
-
* The one capability classification rule this package applies, extracted so
|
|
2079
|
-
* every declaration site in smrt-web shares a single implementation (#2587,
|
|
2080
|
-
* #2588).
|
|
2081
|
-
*
|
|
2082
|
-
* Two sites consume it today: `webmcp.ts` (canonical definitions trusted
|
|
2083
|
-
* through it directly, and its legacy CRUD switch's fail-closed default
|
|
2084
|
-
* branch) and `intents.ts` (a declared view intent, which is never a CRUD
|
|
2085
|
-
* verb and so resolves through the declaration rule alone). Keeping the rule
|
|
2086
|
-
* here rather than private to `webmcp.ts` is what lets the intent path be a
|
|
2087
|
-
* dependency-free module that never pulls the client-data engine.
|
|
2088
|
-
*
|
|
2089
|
-
* This module structurally mirrors `CapabilityEffect` / `CapabilityDeclaration`
|
|
2090
|
-
* / `CapabilityClassification` in `@happyvertical/smrt-types` rather than
|
|
2091
|
-
* importing them — this package's dependency-DAG guardrails keep it free of
|
|
2092
|
-
* every `@happyvertical/*` dependency (see AGENTS.md "No inter-smrt
|
|
2093
|
-
* dependencies"), the same reason `data-query.ts` mirrors that package's
|
|
2094
|
-
* bounded query envelope structurally instead of importing it.
|
|
2095
|
-
*/
|
|
2096
|
-
/**
|
|
2097
|
-
* Browser/agent-visible effect classification for a capability. `'read'`
|
|
2098
|
-
* never mutates; `'write'` mutates within the application; `'destructive'`
|
|
2099
|
-
* may remove or irreversibly change data.
|
|
2100
|
-
*/
|
|
2101
|
-
export declare type WebMcpToolEffect = 'read' | 'write' | 'destructive';
|
|
2102
|
-
|
|
2103
|
-
/** Host-supplied per-invocation options, distinct from registration lifetime. */
|
|
2104
|
-
export declare interface WebMcpToolExecutionOptions {
|
|
2105
|
-
/** Caller cancellation. Older hosts may omit execution options entirely. */
|
|
2106
|
-
signal?: AbortSignal;
|
|
2107
|
-
}
|
|
2108
|
-
|
|
2109
|
-
/**
|
|
2110
|
-
* Thrown synchronously when a name is already held. Carries the colliding
|
|
2111
|
-
* name and the owner that holds it so a host can report both without parsing
|
|
2112
|
-
* the message.
|
|
2113
|
-
*/
|
|
2114
|
-
export declare class WebMcpToolNameCollisionError extends Error {
|
|
2115
|
-
readonly toolName: string;
|
|
2116
|
-
/** The path that already holds {@link toolName}. */
|
|
2117
|
-
readonly owner: WebMcpToolNameOwner;
|
|
2118
|
-
/** The path that tried to take it. */
|
|
2119
|
-
readonly requestedBy: WebMcpToolNameOwner;
|
|
2120
|
-
constructor(toolName: string,
|
|
2121
|
-
/** The path that already holds {@link toolName}. */
|
|
2122
|
-
owner: WebMcpToolNameOwner,
|
|
2123
|
-
/** The path that tried to take it. */
|
|
2124
|
-
requestedBy: WebMcpToolNameOwner);
|
|
2125
|
-
}
|
|
2126
|
-
|
|
2127
|
-
/**
|
|
2128
|
-
* Document-global WebMCP tool-name lock (#2613).
|
|
2129
|
-
*
|
|
2130
|
-
* A browser tool name is derived independently on three paths that all end at
|
|
2131
|
-
* the same `document.modelContext`:
|
|
2132
|
-
*
|
|
2133
|
-
* 1. **generated** model tools — `<namespace>_<model>_<action>`, built by
|
|
2134
|
-
* `registerWebMcpTools` from the exposure policy;
|
|
2135
|
-
* 2. **ui** — the six fixed `smrt_ui_*` tools a UI layer registers under a
|
|
2136
|
-
* configurable prefix (`registerWebMcpUiTools` in `@happyvertical/smrt-svelte`);
|
|
2137
|
-
* 3. **intent** / **bespoke** — declared view intents (#2588) and hand-written
|
|
2138
|
-
* `useWebMcpTool` tools, whose names come from the declaration `id` or the
|
|
2139
|
-
* spec `name`.
|
|
2140
|
-
*
|
|
2141
|
-
* None of the three can see the others at declaration time: a namespace and a
|
|
2142
|
-
* UI prefix are runtime values a declaration never sees. `registerWebMcpTools`
|
|
2143
|
-
* rejects duplicates WITHIN its own prospective set, but nothing checked
|
|
2144
|
-
* ACROSS the paths, so a collision reached the host — which rejects the later
|
|
2145
|
-
* registration and leaves the tool silently absent.
|
|
2146
|
-
*
|
|
2147
|
-
* This module is the shared reservation table those paths coordinate through.
|
|
2148
|
-
* It is an AVAILABILITY guard, not a trust boundary: every path stays
|
|
2149
|
-
* fail-closed and browser-only regardless, and a collision loses a tool rather
|
|
2150
|
-
* than granting one. The authenticated REST surface remains the auth, tenant,
|
|
2151
|
-
* and field-write boundary.
|
|
2152
|
-
*
|
|
2153
|
-
* ## Why the table lives on the document, not in this module
|
|
2154
|
-
*
|
|
2155
|
-
* The lock must be shared by every registrar reachable from one page, which
|
|
2156
|
-
* spans package boundaries (`smrt-web` and a UI layer) and therefore possibly
|
|
2157
|
-
* more than one copy of this module — a second bundle chunk, a duplicated
|
|
2158
|
-
* dependency, or an HMR reload that replaces module state while the host
|
|
2159
|
-
* registry keeps every tool it already accepted. Module-level state loses the
|
|
2160
|
-
* reservations in all of those cases, and a lost reservation is worse than no
|
|
2161
|
-
* lock: it lets a duplicate through, or (on the release side) strands a name
|
|
2162
|
-
* forever. The table is therefore stored on the `document` object itself under
|
|
2163
|
-
* a cross-realm `Symbol.for` key, which every copy of this module resolves to
|
|
2164
|
-
* the same slot.
|
|
2165
|
-
*
|
|
2166
|
-
* The table is additionally stamped with the `modelContext` it was built for.
|
|
2167
|
-
* When a host installs a NEW model context on the same document — a fresh
|
|
2168
|
-
* origin-trial registry, or a test harness swapping the double — every tool
|
|
2169
|
-
* the old registry held is gone, so the table resets rather than stranding
|
|
2170
|
-
* those names.
|
|
2171
|
-
*
|
|
2172
|
-
* This module is dependency-free by design (see the package's dependency-DAG
|
|
2173
|
-
* guardrails) and ships as the `@happyvertical/smrt-web/webmcp-tool-names`
|
|
2174
|
-
* entry so a UI layer can reserve its fixed tool names without pulling in the
|
|
2175
|
-
* client-data engine.
|
|
2176
|
-
*/
|
|
2177
|
-
/** Which registration path holds a reserved WebMCP tool name. */
|
|
2178
|
-
export declare type WebMcpToolNameOwner = 'generated' | 'ui' | 'intent' | 'bespoke';
|
|
2179
|
-
|
|
2180
|
-
/**
|
|
2181
|
-
* The owner currently holding `name` on this document, or undefined. For
|
|
2182
|
-
* diagnostics and tests; registration paths use
|
|
2183
|
-
* {@link reserveWebMcpToolNames}, which is atomic.
|
|
2184
|
-
*/
|
|
2185
|
-
export declare function webMcpToolNameOwner(name: string, options?: ReserveWebMcpToolNamesOptions): WebMcpToolNameOwner | undefined;
|
|
2186
|
-
|
|
2187
|
-
/** Releases every name one reservation holds. Idempotent. */
|
|
2188
|
-
export declare interface WebMcpToolNameReservation {
|
|
2189
|
-
release(): void;
|
|
2190
|
-
}
|
|
2191
|
-
|
|
2192
|
-
/**
|
|
2193
|
-
* One generated collection definition: everything needed to construct a client
|
|
2194
|
-
* collection over the generated REST surface. The `_row` property is a phantom
|
|
2195
|
-
* type carrier threaded through codegen — it never exists at runtime, it only
|
|
2196
|
-
* lets factories infer the row type from a definition.
|
|
2197
|
-
*/
|
|
2198
|
-
/**
|
|
2199
|
-
* One WebMCP / MCP tool descriptor for a collection action (#1812). Emitted by
|
|
2200
|
-
* the core web-collections codegen as PLAIN DATA (this package has no smrt
|
|
2201
|
-
* dependency), shaped to match Chrome's `document.modelContext.registerTool`
|
|
2202
|
-
* input — see https://developer.chrome.com/docs/ai/webmcp. Consumed by
|
|
2203
|
-
* {@link registerWebMcpTools} in `./webmcp`.
|
|
2204
|
-
*/
|
|
2205
|
-
export declare interface WebToolDescriptor {
|
|
2206
|
-
/** The action this tool performs (`list` | `get` | … | a custom method name). */
|
|
2207
|
-
action: string;
|
|
2208
|
-
/** Tool id, `${className.toLowerCase()}_${action}` (e.g. `product_list`). */
|
|
2209
|
-
name: string;
|
|
2210
|
-
description: string;
|
|
2211
|
-
/** JSON Schema for the tool's arguments. */
|
|
2212
|
-
inputSchema: Record<string, unknown>;
|
|
2213
|
-
/** True for non-mutating reads → WebMCP `annotations.readOnlyHint`. */
|
|
2214
|
-
readOnly: boolean;
|
|
2215
|
-
/** Capability effect used by WebMCP exposure policy. */
|
|
2216
|
-
effect?: 'read' | 'write' | 'destructive';
|
|
2217
|
-
/** Whether repeating the tool with the same arguments is safe. */
|
|
2218
|
-
idempotent?: boolean;
|
|
2219
|
-
/** Whether the tool may interact outside the SMRT application. */
|
|
2220
|
-
openWorld?: boolean;
|
|
2221
|
-
/** Generated custom-route transport metadata. */
|
|
2222
|
-
route?: SmrtWebToolRouteDescriptor;
|
|
2223
|
-
}
|
|
2224
|
-
|
|
2225
|
-
/**
|
|
2226
|
-
* Clear every durable artifact registered under `namespace`, then drop the
|
|
2227
|
-
* namespace. This is the single teardown point a logout / tenant-switch calls:
|
|
2228
|
-
* it fans out across BOTH the outbox and persistence slices via the registry,
|
|
2229
|
-
* so neither module needs to import the other.
|
|
2230
|
-
*
|
|
2231
|
-
* Best-effort: a resource whose `clear()` rejects does not abort the sweep —
|
|
2232
|
-
* every registered resource is still cleared (a wipe is a teardown, not a
|
|
2233
|
-
* transaction). A safe no-op on an unknown or empty namespace.
|
|
2234
|
-
*/
|
|
2235
|
-
export declare function wipeDurableStore(namespace: string): Promise<void>;
|
|
2236
|
-
|
|
2237
|
-
/** The outcome handed to {@link SmrtWebCapability.wrapMutation}. */
|
|
2238
|
-
export declare type WrapMutationOutcome = {
|
|
2239
|
-
handled: true;
|
|
2240
|
-
result: unknown;
|
|
2241
|
-
} | {
|
|
2242
|
-
handled: false;
|
|
2243
|
-
} | undefined;
|
|
2244
|
-
|
|
2245
|
-
export { }
|
|
1
|
+
/**
|
|
2
|
+
* @happyvertical/smrt-web — browser client data runtime (#1761).
|
|
3
|
+
*
|
|
4
|
+
* A typed collection factory that materializes the manifest-generated web
|
|
5
|
+
* collection definitions (`@happyvertical/smrt-virt-web`) as cached, reactive
|
|
6
|
+
* collections over the generated SMRT REST surface.
|
|
7
|
+
*
|
|
8
|
+
* This package is the **engine-absorption boundary**: the client-data engine
|
|
9
|
+
* (currently TanStack DB) is an implementation detail held entirely inside
|
|
10
|
+
* this module. Its types never appear on the public API — collections are
|
|
11
|
+
* handed back as the SMRT-owned {@link SmrtWebCollection}, and the shared cache
|
|
12
|
+
* as the opaque {@link SmrtWebClient} — so the engine stays swappable without a
|
|
13
|
+
* consumer-visible break. Consumers never import `@tanstack/*` directly.
|
|
14
|
+
*
|
|
15
|
+
* Framework-agnostic by construction: this entry imports no UI framework.
|
|
16
|
+
* Svelte live-query bindings ship separately (see PRD #1755) so this core never
|
|
17
|
+
* pulls the Svelte-only `@tanstack/svelte-db` export condition.
|
|
18
|
+
*
|
|
19
|
+
* Scope of this slice:
|
|
20
|
+
* - stale-while-revalidate reads (a `staleTimeMs` window, background revalidation)
|
|
21
|
+
* - concurrent-read dedup (one network request per in-flight collection load)
|
|
22
|
+
* - optimistic create that persists through the generated REST surface and
|
|
23
|
+
* rolls back automatically when the server errors
|
|
24
|
+
* - relationship-derived invalidation (#1761): a settled mutation invalidates
|
|
25
|
+
* the caches of the collections related to the mutated one, with the edges
|
|
26
|
+
* derived from the manifest (`definition.relationships`) — no hand-wired
|
|
27
|
+
* cache keys. Cross-collection reach requires a shared client from
|
|
28
|
+
* {@link createSmrtWebClient}; with a private client only the mutated
|
|
29
|
+
* collection refetches.
|
|
30
|
+
* - hydration seeding (#1761): rows fetched server-side (a SvelteKit
|
|
31
|
+
* `+page.server.ts` load) seed the shared cache via
|
|
32
|
+
* {@link CreateSmrtCollectionOptions.initialData}, so the first client read
|
|
33
|
+
* serves them WITHOUT a duplicate first-render fetch.
|
|
34
|
+
*
|
|
35
|
+
* Deliberately NOT here yet (see PRD #1755): offline outbox, SSE invalidation,
|
|
36
|
+
* persistence, version awareness.
|
|
37
|
+
*/
|
|
38
|
+
import type { SmrtWebCapability } from './capability.js';
|
|
39
|
+
export type { MutationSettleOutcome, SmrtWebCapability, SmrtWebCapabilityContext, SmrtWebMutationEnvelope, WrapMutationOutcome, } from './capability.js';
|
|
40
|
+
export { runWrapMutation } from './capability.js';
|
|
41
|
+
export type { SmrtWebDataQueryFacetResult, SmrtWebDataQueryFilter, SmrtWebDataQueryFilterOperator, SmrtWebDataQueryRequest, SmrtWebDataQueryResult, SmrtWebDataQueryScalar, SmrtWebDataQueryTotal, SmrtWebDataQueryTransport, } from './data-query.js';
|
|
42
|
+
export { executeSmrtWebDataQuery, MAX_SMRT_WEB_DATA_QUERY_CONTAINER_ITEMS, MAX_SMRT_WEB_DATA_QUERY_FACET_VALUES, MAX_SMRT_WEB_DATA_QUERY_FACETS, MAX_SMRT_WEB_DATA_QUERY_OFFSET, MAX_SMRT_WEB_DATA_QUERY_PAGE_LIMIT, MAX_SMRT_WEB_DATA_QUERY_RESULT_BYTES, MAX_SMRT_WEB_DATA_QUERY_ROWS, MAX_SMRT_WEB_DATA_QUERY_STRING_LENGTH, MAX_SMRT_WEB_DATA_QUERY_WARNINGS, normalizeSmrtWebDataQueryResult, } from './data-query.js';
|
|
43
|
+
export type { SmrtWebDataSurfaceActionCommandRequest, SmrtWebDataSurfaceActionCommandTransportOptions, SmrtWebDataSurfaceActionRequest, SmrtWebDataSurfaceActionResult, SmrtWebDataSurfaceActionTransport, SmrtWebDataSurfaceIdentity, SmrtWebDataSurfaceJsonPrimitive, SmrtWebDataSurfaceJsonValue, SmrtWebDataSurfaceSelection, } from './data-surface-actions.js';
|
|
44
|
+
export { classifySmrtWebDataSurfaceActionResult, dataSurfaceActionCommandTransport, executeSmrtWebDataSurfaceAction, MAX_SMRT_WEB_DATA_SURFACE_ACTION_CONTAINER_ITEMS, MAX_SMRT_WEB_DATA_SURFACE_ACTION_IDENTIFIER_LENGTH, MAX_SMRT_WEB_DATA_SURFACE_ACTION_JSON_DEPTH, MAX_SMRT_WEB_DATA_SURFACE_ACTION_RESULT_BYTES, normalizeSmrtWebDataSurfaceActionResult, } from './data-surface-actions.js';
|
|
45
|
+
export type { DurableResource, DurableStoreKey } from './durable-store.js';
|
|
46
|
+
export { durableStoreNamespace, registerDurableResource, wipeDurableStore, } from './durable-store.js';
|
|
47
|
+
export type { OfflineCommandInput, OfflineCommandQueue, OfflineCommandQueueConfig, OfflineOutboxConfig, OutboxBackoff, OutboxCommand, OutboxCommandResult, OutboxCommandTransport, OutboxConflict, OutboxHandle, OutboxSnapshotItem, OutboxSyncState, SyncStateEvent, } from './offline.js';
|
|
48
|
+
export { getOutboxHandle, offlineCommandQueue, offlineOutbox, } from './offline.js';
|
|
49
|
+
export type { PersistCollectionConfig, PersistDataSurfaceConfig, PersistedDataSurface, } from './persistence.js';
|
|
50
|
+
export { DEFAULT_PERSIST_DEBOUNCE_MS, persistCollection, persistDataSurface, } from './persistence.js';
|
|
51
|
+
export type { SmrtWebQuery, SmrtWebQueryLiveSubscription, SmrtWebQueryMode, SmrtWebQueryPage, SmrtWebQueryRunOptions, SmrtWebQueryState, SmrtWebQueryTransport, } from './remote-query.js';
|
|
52
|
+
export { createSmrtWebQuery } from './remote-query.js';
|
|
53
|
+
export type { LiveInvalidationConfig, SmrtWebEventSource, SmrtWebEventSourceFactory, SmrtWebEventSubscriber, SmrtWebEventSubscriberConfig, SmrtWebSubscriberTransport, } from './sse-client.js';
|
|
54
|
+
export { createSmrtWebEventSubscriber, liveInvalidation, } from './sse-client.js';
|
|
55
|
+
export type { UpdateAvailableState, UpdateState, UpdateStateConfig, } from './update-state.js';
|
|
56
|
+
export { createUpdateState } from './update-state.js';
|
|
57
|
+
/**
|
|
58
|
+
* The field types core's web-collection emission actually produces —
|
|
59
|
+
* relationship pseudo-columns (`oneToMany`/`manyToMany`) and STI `meta`
|
|
60
|
+
* internals never reach an emitted definition. Textual mirror of core's
|
|
61
|
+
* `WebFieldType` (this package is deliberately smrt-dependency-free, so it
|
|
62
|
+
* cannot import the source type); the four co-managed sites are core's
|
|
63
|
+
* runtime type, the ambient virt-web d.ts, the physical `@smrt/web` d.ts,
|
|
64
|
+
* and this mirror.
|
|
65
|
+
*/
|
|
66
|
+
export type SmrtWebFieldType = 'text' | 'decimal' | 'boolean' | 'integer' | 'datetime' | 'json' | 'foreignKey' | 'crossPackageRef';
|
|
67
|
+
/** Static `@field({ ui })` hints (#2046) — the field-policy rail seed. */
|
|
68
|
+
export interface SmrtWebFieldUIHints {
|
|
69
|
+
basic?: boolean;
|
|
70
|
+
group?: string;
|
|
71
|
+
order?: number;
|
|
72
|
+
locked?: boolean;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Field metadata emitted per column by the `@happyvertical/smrt-virt-web`
|
|
76
|
+
* virtual module (generated from the package manifest).
|
|
77
|
+
*/
|
|
78
|
+
export interface SmrtWebFieldDefinition {
|
|
79
|
+
type: SmrtWebFieldType;
|
|
80
|
+
required?: boolean;
|
|
81
|
+
/** Whether the public field contract explicitly permits `null`. */
|
|
82
|
+
nullable?: boolean;
|
|
83
|
+
default?: unknown;
|
|
84
|
+
/** Developer-authored `@field({ description })` (#2046) — end-user help seed. */
|
|
85
|
+
description?: string;
|
|
86
|
+
/** Static `@field({ ui })` hints (#2046). */
|
|
87
|
+
ui?: SmrtWebFieldUIHints;
|
|
88
|
+
}
|
|
89
|
+
/** The relationship kinds a generated web collection edge can describe. */
|
|
90
|
+
export type SmrtWebRelationshipKind = 'foreignKey' | 'crossPackageRef' | 'oneToMany' | 'manyToMany';
|
|
91
|
+
/**
|
|
92
|
+
* A manifest-derived edge from this collection to a sibling REST collection,
|
|
93
|
+
* emitted by the `@happyvertical/smrt-virt-web` virtual module. When a mutation
|
|
94
|
+
* on this collection settles, the caches of the collections named by these
|
|
95
|
+
* edges are invalidated (relationship-derived invalidation, #1761), so a
|
|
96
|
+
* dependent view refetches without any hand-wired cache key.
|
|
97
|
+
*
|
|
98
|
+
* SMRT-owned data — no client-engine (`@tanstack/*`) type appears here, so it
|
|
99
|
+
* stays inside the engine-absorption boundary.
|
|
100
|
+
*/
|
|
101
|
+
export interface SmrtWebRelationship {
|
|
102
|
+
/** The declaring field carrying the relationship (e.g. `groupId`, `items`). */
|
|
103
|
+
field: string;
|
|
104
|
+
/** The relationship kind, mirroring the manifest field type. */
|
|
105
|
+
kind: SmrtWebRelationshipKind;
|
|
106
|
+
/** REST collection name the edge resolves to (e.g. `ad_groups`). */
|
|
107
|
+
relatedCollection: string;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* One generated collection definition: everything needed to construct a client
|
|
111
|
+
* collection over the generated REST surface. The `_row` property is a phantom
|
|
112
|
+
* type carrier threaded through codegen — it never exists at runtime, it only
|
|
113
|
+
* lets factories infer the row type from a definition.
|
|
114
|
+
*/
|
|
115
|
+
/**
|
|
116
|
+
* One WebMCP / MCP tool descriptor for a collection action (#1812). Emitted by
|
|
117
|
+
* the core web-collections codegen as PLAIN DATA (this package has no smrt
|
|
118
|
+
* dependency), shaped to match Chrome's `document.modelContext.registerTool`
|
|
119
|
+
* input — see https://developer.chrome.com/docs/ai/webmcp. Consumed by
|
|
120
|
+
* {@link registerWebMcpTools} in `./webmcp`.
|
|
121
|
+
*/
|
|
122
|
+
export interface WebToolDescriptor {
|
|
123
|
+
/** The action this tool performs (`list` | `get` | … | a custom method name). */
|
|
124
|
+
action: string;
|
|
125
|
+
/** Tool id, `${className.toLowerCase()}_${action}` (e.g. `product_list`). */
|
|
126
|
+
name: string;
|
|
127
|
+
description: string;
|
|
128
|
+
/** JSON Schema for the tool's arguments. */
|
|
129
|
+
inputSchema: Record<string, unknown>;
|
|
130
|
+
/** True for non-mutating reads → WebMCP `annotations.readOnlyHint`. */
|
|
131
|
+
readOnly: boolean;
|
|
132
|
+
/** Capability effect used by WebMCP exposure policy. */
|
|
133
|
+
effect?: 'read' | 'write' | 'destructive';
|
|
134
|
+
/** Whether repeating the tool with the same arguments is safe. */
|
|
135
|
+
idempotent?: boolean;
|
|
136
|
+
/** Whether the tool may interact outside the SMRT application. */
|
|
137
|
+
openWorld?: boolean;
|
|
138
|
+
/** Generated custom-route transport metadata. */
|
|
139
|
+
route?: SmrtWebToolRouteDescriptor;
|
|
140
|
+
}
|
|
141
|
+
export interface SmrtWebToolRouteDescriptor {
|
|
142
|
+
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
143
|
+
scope: 'item' | 'collection';
|
|
144
|
+
/** Route segments below the collection endpoint; dynamic segments use `[x]`. */
|
|
145
|
+
path: string[];
|
|
146
|
+
/** Transport names rewritten by the tool schema (e.g. `actionId` → `id`). */
|
|
147
|
+
parameterAliases?: Record<string, string>;
|
|
148
|
+
/** The generated method accepts one `options` bag as its sole argument. */
|
|
149
|
+
optionsBag?: boolean;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Canonical data-only definition for one API-backed browser tool. Unlike a
|
|
153
|
+
* collection definition, this does not imply that a list route or client cache
|
|
154
|
+
* exists. Generated definitions carry explicit semantics; manual legacy
|
|
155
|
+
* literals may omit them and register with fail-closed defaults.
|
|
156
|
+
*/
|
|
157
|
+
export interface WebMcpToolDefinition extends WebToolDescriptor {
|
|
158
|
+
/** Stable definition identity is `(collection, action)`. */
|
|
159
|
+
collection: string;
|
|
160
|
+
/** Canonical qualified row-model identity. */
|
|
161
|
+
objectRef: string;
|
|
162
|
+
/** Row-model class used by the shared MCP tool vocabulary. */
|
|
163
|
+
className: string;
|
|
164
|
+
endpoint: string;
|
|
165
|
+
idField: string;
|
|
166
|
+
idType: 'uuid' | 'text';
|
|
167
|
+
/** Complete generated route metadata, including CRUD actions. */
|
|
168
|
+
route: SmrtWebToolRouteDescriptor;
|
|
169
|
+
/** Cache-invalidation edges for materialized sibling collections. */
|
|
170
|
+
relationships: SmrtWebRelationship[];
|
|
171
|
+
}
|
|
172
|
+
export interface SmrtWebCollectionDefinition<TData extends object = object> {
|
|
173
|
+
/** REST collection name (e.g. `products`). */
|
|
174
|
+
name: string;
|
|
175
|
+
/**
|
|
176
|
+
* Canonical qualified model identity (e.g.
|
|
177
|
+
* `@happyvertical/smrt-products:Product`). Generated definitions always
|
|
178
|
+
* provide it; optional here for source compatibility with manual literals
|
|
179
|
+
* authored before policy-aware web collections.
|
|
180
|
+
*/
|
|
181
|
+
objectRef?: string;
|
|
182
|
+
/** Source class name (e.g. `Product`). */
|
|
183
|
+
className: string;
|
|
184
|
+
/** Path under the API base path (e.g. `/products`). */
|
|
185
|
+
endpoint: string;
|
|
186
|
+
/** Primary key field name (`id` for SmrtObject). */
|
|
187
|
+
idField: string;
|
|
188
|
+
/** CRUD + custom actions exposed by the api decorator config. */
|
|
189
|
+
actions: string[];
|
|
190
|
+
/**
|
|
191
|
+
* WebMCP/MCP tool descriptors for the exposed actions (#1812). Optional so
|
|
192
|
+
* hand-built definitions (older codegen, tests) still satisfy the type; a
|
|
193
|
+
* missing value means "no WebMCP tools to register".
|
|
194
|
+
*/
|
|
195
|
+
toolDescriptors?: WebToolDescriptor[];
|
|
196
|
+
/** Persisted field metadata keyed by field name. */
|
|
197
|
+
fields: Record<string, SmrtWebFieldDefinition>;
|
|
198
|
+
/**
|
|
199
|
+
* Manifest-derived relationship edges to sibling REST collections. Drives
|
|
200
|
+
* relationship-derived cache invalidation: a settled mutation on this
|
|
201
|
+
* collection invalidates the caches of the collections these edges name.
|
|
202
|
+
* Optional so hand-built definitions (older codegen, tests) still satisfy the
|
|
203
|
+
* type; a missing value means "no derived edges".
|
|
204
|
+
*/
|
|
205
|
+
relationships?: SmrtWebRelationship[];
|
|
206
|
+
/** Phantom row-type carrier — never present at runtime. */
|
|
207
|
+
_row?: TData;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* The per-collection CRUD surface of the generated REST client
|
|
211
|
+
* (`createClient(basePath).<collection>` from `@happyvertical/smrt-virt-client`).
|
|
212
|
+
*
|
|
213
|
+
* Return types are `unknown` on purpose: generated fetchers resolve with
|
|
214
|
+
* whatever the server sent, so this package normalizes and validates payloads
|
|
215
|
+
* centrally — see {@link unwrapListResult} / {@link unwrapItemResult}.
|
|
216
|
+
*/
|
|
217
|
+
export interface SmrtCrudFetchers {
|
|
218
|
+
list(params?: Record<string, unknown>): Promise<unknown>;
|
|
219
|
+
get?(id: string): Promise<unknown>;
|
|
220
|
+
create(data: Record<string, unknown>): Promise<unknown>;
|
|
221
|
+
update?(id: string, data: Record<string, unknown>): Promise<unknown>;
|
|
222
|
+
delete?(id: string): Promise<unknown>;
|
|
223
|
+
/** Invoke a generated custom action route. */
|
|
224
|
+
custom?(action: string, args: Record<string, unknown>, route?: SmrtWebToolRouteDescriptor): Promise<unknown>;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Raised when a generated-client call resolved with an error payload
|
|
228
|
+
* (`{ error: string }` from the generated REST routes) or an unexpected shape.
|
|
229
|
+
* Thrown inside a mutation handler, this triggers the automatic rollback of
|
|
230
|
+
* optimistic state. HTTP 5xx failures are always opaque: their server payload
|
|
231
|
+
* is neither parsed nor retained because it may contain internal detail.
|
|
232
|
+
*/
|
|
233
|
+
export declare class SmrtWebRequestError extends Error {
|
|
234
|
+
readonly payload: unknown;
|
|
235
|
+
readonly status?: number;
|
|
236
|
+
readonly code?: string;
|
|
237
|
+
constructor(message: string, payload?: unknown, status?: number, code?: string);
|
|
238
|
+
}
|
|
239
|
+
/** A row as stored in the client collection: the DTO plus a required key. */
|
|
240
|
+
export type SmrtWebRow<TData extends object> = TData & {
|
|
241
|
+
id: string;
|
|
242
|
+
};
|
|
243
|
+
/**
|
|
244
|
+
* Normalize a generated-client list result to an array of rows.
|
|
245
|
+
*
|
|
246
|
+
* The generated REST routes return a bare JSON array; `{ error }` payloads are
|
|
247
|
+
* surfaced as failures. The `{ data: [...] }` envelope is tolerated for
|
|
248
|
+
* ApiResponse-shaped clients (e.g. a mock client).
|
|
249
|
+
*/
|
|
250
|
+
export declare function unwrapListResult(result: unknown, collectionName: string): Array<Record<string, unknown>>;
|
|
251
|
+
/**
|
|
252
|
+
* Normalize a generated-client item result (create/update) to a row.
|
|
253
|
+
* `{ error }` payloads become failures — inside mutation handlers this is what
|
|
254
|
+
* makes optimistic state roll back.
|
|
255
|
+
*/
|
|
256
|
+
export declare function unwrapItemResult(result: unknown, context: string): Record<string, unknown>;
|
|
257
|
+
/** Reject generated REST error envelopes while preserving opaque successes. */
|
|
258
|
+
export declare function throwIfSmrtWebError(result: unknown, context: string): unknown;
|
|
259
|
+
/**
|
|
260
|
+
* Serialize `list` query params into the query string the generated REST list
|
|
261
|
+
* route parses (`handleList` in `core/src/generators/rest.ts`): `limit`,
|
|
262
|
+
* `offset`, `orderBy` as scalars, and `where` entries as `field=value`
|
|
263
|
+
* (equality) or `field[op]=value` for a `{ op, value }` condition (`in` joins an
|
|
264
|
+
* array with commas). Called with no params (the collection runtime's argument-
|
|
265
|
+
* free `list()`) it returns `''`, so the bare-URL behavior is unchanged.
|
|
266
|
+
*/
|
|
267
|
+
export declare function buildListQuery(params?: Record<string, unknown>): string;
|
|
268
|
+
/**
|
|
269
|
+
* Build CRUD fetchers from a generated collection definition — the same URL
|
|
270
|
+
* scheme and payload handling as the generated REST client
|
|
271
|
+
* (`basePath + endpoint`), with one improvement: HTTP error statuses reject
|
|
272
|
+
* instead of resolving with them. Typed/legacy 4xx detail is retained; 5xx
|
|
273
|
+
* failures stay opaque and payload-free.
|
|
274
|
+
*/
|
|
275
|
+
export declare function createDefinitionFetchers(definition: Pick<SmrtWebCollectionDefinition<object>, 'name' | 'endpoint'>, basePath?: string, fetchFn?: typeof fetch): SmrtCrudFetchers;
|
|
276
|
+
/**
|
|
277
|
+
* Generate a client-local id for optimistic inserts. The generated REST layer
|
|
278
|
+
* strips client-supplied ids on create (mass-assignment guard #1540), so this
|
|
279
|
+
* id only identifies the optimistic row until the post-persist refetch swaps in
|
|
280
|
+
* the server-assigned row.
|
|
281
|
+
*/
|
|
282
|
+
export declare function newLocalId(): string;
|
|
283
|
+
/**
|
|
284
|
+
* Opaque handle to the shared client cache / request-dedup layer. Create one
|
|
285
|
+
* with {@link createSmrtWebClient} and pass the SAME instance to every
|
|
286
|
+
* collection that should share a cache and deduplicate in-flight requests.
|
|
287
|
+
*
|
|
288
|
+
* The engine (currently a TanStack Query client) is intentionally hidden behind
|
|
289
|
+
* this brand so it stays swappable — do not depend on its concrete shape.
|
|
290
|
+
*/
|
|
291
|
+
export interface SmrtWebClient {
|
|
292
|
+
/** Phantom brand — this handle wraps the hidden client-cache engine. */
|
|
293
|
+
readonly __smrtWebClient: 'SmrtWebClient';
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Create a shared client-cache handle. Pass the returned handle as
|
|
297
|
+
* {@link CreateSmrtCollectionOptions.client} to every collection that should
|
|
298
|
+
* share a cache and deduplicate requests app-wide.
|
|
299
|
+
*/
|
|
300
|
+
export declare function createSmrtWebClient(): SmrtWebClient;
|
|
301
|
+
/** Validate that an opaque cache handle came from {@link createSmrtWebClient}. */
|
|
302
|
+
export declare function validateSmrtWebClient(client: SmrtWebClient): void;
|
|
303
|
+
/**
|
|
304
|
+
* Invalidate materialized collection caches through the opaque SMRT client.
|
|
305
|
+
*
|
|
306
|
+
* This is the public cache-coherence seam for transports that execute a write
|
|
307
|
+
* without constructing a {@link SmrtWebCollection} (for example, a tool-only
|
|
308
|
+
* WebMCP definition). Matching is by collection name across every scope on the
|
|
309
|
+
* shared client, mirroring settled collection mutations: over-invalidation is
|
|
310
|
+
* safe, while leaving a related page cache stale is not.
|
|
311
|
+
*/
|
|
312
|
+
export declare function invalidateSmrtWebCollections(client: SmrtWebClient, collectionNames: readonly string[]): void;
|
|
313
|
+
/**
|
|
314
|
+
* A pending optimistic mutation. Await {@link isPersisted} to observe the
|
|
315
|
+
* server outcome: it resolves once the write has been persisted through the
|
|
316
|
+
* REST surface, and rejects (rolling the optimistic state back) on error.
|
|
317
|
+
*/
|
|
318
|
+
export interface SmrtWebTransaction {
|
|
319
|
+
readonly isPersisted: {
|
|
320
|
+
readonly promise: Promise<unknown>;
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
/** A change-subscription handle. Call {@link unsubscribe} to detach. */
|
|
324
|
+
export interface SmrtWebSubscription {
|
|
325
|
+
unsubscribe(): void;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* A live, cached collection of plain-DTO rows — the SMRT-owned public contract
|
|
329
|
+
* over the client-data engine. Exposes only the committed surface; the engine's
|
|
330
|
+
* own type is never named here so it stays swappable.
|
|
331
|
+
*/
|
|
332
|
+
export interface SmrtWebCollection<TData extends object> {
|
|
333
|
+
/** All rows currently in the collection (plain DTOs, insertion order). */
|
|
334
|
+
readonly toArray: ReadonlyArray<SmrtWebRow<TData>>;
|
|
335
|
+
/** Number of rows currently in the collection. */
|
|
336
|
+
readonly size: number;
|
|
337
|
+
/** True when a row with `key` is present. */
|
|
338
|
+
has(key: string): boolean;
|
|
339
|
+
/** The row with `key`, or `undefined`. */
|
|
340
|
+
get(key: string): SmrtWebRow<TData> | undefined;
|
|
341
|
+
/** Resolve once the first load has completed. */
|
|
342
|
+
preload(): Promise<void>;
|
|
343
|
+
/** Tear down subscriptions and cached state. */
|
|
344
|
+
cleanup(): Promise<void>;
|
|
345
|
+
/** Subscribe to change notifications; returns a detach handle. */
|
|
346
|
+
subscribeChanges(callback: (changes: unknown) => void): SmrtWebSubscription;
|
|
347
|
+
/**
|
|
348
|
+
* Optimistically insert a row and persist it through the create fetcher. The
|
|
349
|
+
* row is visible synchronously; the returned transaction settles on the
|
|
350
|
+
* server outcome (see {@link SmrtWebTransaction}).
|
|
351
|
+
*/
|
|
352
|
+
insert(row: SmrtWebRow<TData>): SmrtWebTransaction;
|
|
353
|
+
/** Optimistically update a row and persist it through the REST surface. */
|
|
354
|
+
update(key: string, changes: Omit<Partial<SmrtWebRow<TData>>, 'id'>): SmrtWebTransaction;
|
|
355
|
+
/** Optimistically delete a row and persist it through the REST surface. */
|
|
356
|
+
delete(key: string): SmrtWebTransaction;
|
|
357
|
+
/** Execute a custom action and invalidate this collection's related caches. */
|
|
358
|
+
action(action: string, args: Record<string, unknown>, route?: SmrtWebToolRouteDescriptor): Promise<unknown>;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Options for {@link createSmrtCollection}. Generic in the collection's row
|
|
362
|
+
* type `TData` so {@link initialData} is checked against the same DTO the
|
|
363
|
+
* collection stores; every other option is row-type-agnostic, so the parameter
|
|
364
|
+
* defaults to `object` and can be omitted at call sites that pass no seed.
|
|
365
|
+
*/
|
|
366
|
+
export interface CreateSmrtCollectionOptions<TData extends object = object> {
|
|
367
|
+
/**
|
|
368
|
+
* Generated REST client surface for this collection, e.g.
|
|
369
|
+
* `createClient('/api/v1').products` from the virt-client module. When
|
|
370
|
+
* omitted, fetchers are derived from the definition's endpoint and `basePath`
|
|
371
|
+
* with the same URL scheme and payload shapes the generated client uses.
|
|
372
|
+
*/
|
|
373
|
+
fetchers?: SmrtCrudFetchers;
|
|
374
|
+
/** API base path for definition-derived fetchers (default `/api/v1`). */
|
|
375
|
+
basePath?: string;
|
|
376
|
+
/** Fetch implementation override (tests, SSR). Defaults to global fetch. */
|
|
377
|
+
fetchFn?: typeof fetch;
|
|
378
|
+
/**
|
|
379
|
+
* Shared cache handle from {@link createSmrtWebClient}. Pass one app-wide
|
|
380
|
+
* instance so collections share a cache and deduplicate requests; a private
|
|
381
|
+
* cache is created when omitted.
|
|
382
|
+
*/
|
|
383
|
+
client?: SmrtWebClient;
|
|
384
|
+
/**
|
|
385
|
+
* Cache namespace for this collection's reads. Fold a backend / tenant /
|
|
386
|
+
* preview discriminator in here when the SAME generated collection is
|
|
387
|
+
* materialized against DIFFERENT backends while sharing one {@link client} —
|
|
388
|
+
* without it those reads share a cache key and could serve one backend's rows
|
|
389
|
+
* for the other for the whole `staleTimeMs` window. Omit for the common
|
|
390
|
+
* single-backend case.
|
|
391
|
+
*/
|
|
392
|
+
scope?: string;
|
|
393
|
+
/**
|
|
394
|
+
* Stale-while-revalidate window in milliseconds (default 30s): reads within
|
|
395
|
+
* the window are served from the local collection without a network request;
|
|
396
|
+
* the first read after it revalidates in the background.
|
|
397
|
+
*/
|
|
398
|
+
staleTimeMs?: number;
|
|
399
|
+
/** Retry failed loads (default false: fail fast, surface errors). */
|
|
400
|
+
retry?: boolean;
|
|
401
|
+
/**
|
|
402
|
+
* Rows to seed this collection's cache with, before its first read — the
|
|
403
|
+
* hydration path for server-rendered data (#1761). Fetch rows in a SvelteKit
|
|
404
|
+
* `+page.server.ts` load, pass them here on the client, and the first read
|
|
405
|
+
* serves them from cache WITHOUT a duplicate first-render network request
|
|
406
|
+
* (SMRT-owned type, so no engine type appears on the option).
|
|
407
|
+
*
|
|
408
|
+
* The seed is written to the cache with a fresh timestamp, so it counts as
|
|
409
|
+
* fresh for `staleTimeMs`: with the default window the first read does not
|
|
410
|
+
* fetch, and the collection revalidates in the background only once the window
|
|
411
|
+
* elapses (or immediately if `staleTimeMs` is 0). Seed the SAME rows the
|
|
412
|
+
* server serialized so the pre- and post-hydration renders match.
|
|
413
|
+
*
|
|
414
|
+
* Seeds the SAME cache key the reads use — so with a shared {@link client},
|
|
415
|
+
* fold the backend / tenant discriminator into {@link scope} to match, exactly
|
|
416
|
+
* as reads do; otherwise one backend's seed would serve the other for the
|
|
417
|
+
* `staleTimeMs` window.
|
|
418
|
+
*/
|
|
419
|
+
initialData?: SmrtWebRow<TData>[];
|
|
420
|
+
/**
|
|
421
|
+
* Capability plug-ins hooking the collection lifecycle (#1755) — the seam
|
|
422
|
+
* that lets the offline outbox (#1762), persistence (#1764), and live SSE
|
|
423
|
+
* invalidation (#1763-client) slices each live in their own module instead of
|
|
424
|
+
* contending on this factory. Capabilities run in array order at six fixed
|
|
425
|
+
* points (see {@link SmrtWebCapability}). Additive and defaulting to none: an
|
|
426
|
+
* undefined or empty array is byte-for-byte the collection of today (the
|
|
427
|
+
* no-op guarantee), so this ships zero concrete capabilities by design.
|
|
428
|
+
*/
|
|
429
|
+
capabilities?: SmrtWebCapability<TData>[];
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Retrieve the underlying engine collection backing a handle — an advanced
|
|
433
|
+
* bridge for trusted framework bindings (e.g. the smrt-svelte live-query
|
|
434
|
+
* binding), which must feed the engine collection to the query builder. Returns
|
|
435
|
+
* `unknown` so no engine type crosses the boundary; callers cast. Throws for a
|
|
436
|
+
* handle not produced by {@link createSmrtCollection}. Not needed for normal
|
|
437
|
+
* use.
|
|
438
|
+
*/
|
|
439
|
+
export declare function getEngineCollection<TData extends object>(handle: SmrtWebCollection<TData>): unknown;
|
|
440
|
+
/**
|
|
441
|
+
* Create a typed client collection over a generated SMRT collection definition
|
|
442
|
+
* and the matching generated REST client fetchers.
|
|
443
|
+
*
|
|
444
|
+
* Reads: stale-while-revalidate. The first subscriber triggers a fetch;
|
|
445
|
+
* re-subscribing within `staleTimeMs` serves local data with no request. N
|
|
446
|
+
* concurrent identical reads coalesce into one network request.
|
|
447
|
+
*
|
|
448
|
+
* Writes: `collection.insert({ ...data, id: newLocalId() })` applies instantly,
|
|
449
|
+
* persists through `fetchers.create()` (the temp id is stripped — the server
|
|
450
|
+
* assigns the real one), then refetches to reconcile. A failed create rejects
|
|
451
|
+
* the transaction and the optimistic row rolls back automatically.
|
|
452
|
+
*
|
|
453
|
+
* Relationship-derived invalidation: once a create/update/delete has persisted,
|
|
454
|
+
* the query caches of this collection AND the collections named by
|
|
455
|
+
* `definition.relationships` (manifest-derived edges) are invalidated, so
|
|
456
|
+
* dependent views refetch. Reaching OTHER collections requires them to share
|
|
457
|
+
* this collection's `client` (see {@link createSmrtWebClient}); with a private
|
|
458
|
+
* client only this collection refetches.
|
|
459
|
+
*
|
|
460
|
+
* Hydration seeding: pass rows fetched server-side as
|
|
461
|
+
* {@link CreateSmrtCollectionOptions.initialData} and the collection's first
|
|
462
|
+
* read is served from them with NO network request (until `staleTimeMs`
|
|
463
|
+
* elapses) — the SvelteKit `+page.server.ts` → hydrate path.
|
|
464
|
+
*/
|
|
465
|
+
export declare function createSmrtCollection<TData extends object>(definition: SmrtWebCollectionDefinition<TData>, options: CreateSmrtCollectionOptions<TData>): SmrtWebCollection<TData>;
|
|
466
|
+
export { type RegisterWebMcpBespokeToolOptions, type RegisterWebMcpToolsOptions, registerViewIntent, registerWebMcpBespokeTool, registerWebMcpTools, reserveWebMcpToolNames, type WebMcpBespokeToolSpec, type WebMcpExposurePolicy, type WebMcpRegistrationDefinition, type WebMcpRegistrationDisposer, type WebMcpToolEffect, type WebMcpToolExecutionOptions, WebMcpToolNameCollisionError, type WebMcpToolNameOwner, type WebMcpToolNameReservation, webMcpToolNameOwner, } from './webmcp.js';
|
|
467
|
+
export { compileViewIntentToolSpec, type ViewIntent, type ViewIntentBinding, type ViewIntentControlAction, type ViewIntentControlIdentity, type ViewIntentControlRegistryPort, type ViewIntentControlTarget, type ViewIntentDataSurfaceIdentity, type ViewIntentDataSurfaceKind, type ViewIntentDataSurfaceRegistryPort, type ViewIntentDataSurfaceTarget, type ViewIntentDeclaration, type ViewIntentSubject, type ViewIntentTarget, type ViewIntentToolSpec, viewIntentToolName, } from './intents.js';
|
|
468
|
+
//# sourceMappingURL=index.d.ts.map
|