@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.
Files changed (47) hide show
  1. package/dist/__typechecks__/webmcp-tool-definition.d.ts +2 -0
  2. package/dist/__typechecks__/webmcp-tool-definition.d.ts.map +1 -0
  3. package/dist/ai.d.ts +330 -358
  4. package/dist/ai.d.ts.map +1 -0
  5. package/dist/capability-classification.d.ts +89 -0
  6. package/dist/capability-classification.d.ts.map +1 -0
  7. package/dist/capability.d.ts +191 -0
  8. package/dist/capability.d.ts.map +1 -0
  9. package/dist/data-query.d.ts +121 -0
  10. package/dist/data-query.d.ts.map +1 -0
  11. package/dist/data-surface-actions.d.ts +118 -0
  12. package/dist/data-surface-actions.d.ts.map +1 -0
  13. package/dist/durable-store.d.ts +88 -0
  14. package/dist/durable-store.d.ts.map +1 -0
  15. package/dist/index.d.ts +468 -2245
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/intents.d.ts +273 -300
  18. package/dist/intents.d.ts.map +1 -0
  19. package/dist/internal.d.ts +15 -0
  20. package/dist/internal.d.ts.map +1 -0
  21. package/dist/offline/durable-queue.d.ts +171 -0
  22. package/dist/offline/durable-queue.d.ts.map +1 -0
  23. package/dist/offline/engine.d.ts +359 -0
  24. package/dist/offline/engine.d.ts.map +1 -0
  25. package/dist/offline/leader.d.ts +57 -0
  26. package/dist/offline/leader.d.ts.map +1 -0
  27. package/dist/offline/types.d.ts +232 -0
  28. package/dist/offline/types.d.ts.map +1 -0
  29. package/dist/offline.d.ts +258 -0
  30. package/dist/offline.d.ts.map +1 -0
  31. package/dist/persistence/snapshot-store.d.ts +121 -0
  32. package/dist/persistence/snapshot-store.d.ts.map +1 -0
  33. package/dist/persistence.d.ts +157 -0
  34. package/dist/persistence.d.ts.map +1 -0
  35. package/dist/remote-query.d.ts +61 -0
  36. package/dist/remote-query.d.ts.map +1 -0
  37. package/dist/sse-client.d.ts +182 -0
  38. package/dist/sse-client.d.ts.map +1 -0
  39. package/dist/update-state/meta-store.d.ts +66 -0
  40. package/dist/update-state/meta-store.d.ts.map +1 -0
  41. package/dist/update-state.d.ts +115 -0
  42. package/dist/update-state.d.ts.map +1 -0
  43. package/dist/webmcp-tool-names.d.ts +106 -112
  44. package/dist/webmcp-tool-names.d.ts.map +1 -0
  45. package/dist/webmcp.d.ts +193 -653
  46. package/dist/webmcp.d.ts.map +1 -0
  47. package/package.json +4 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../src/ai.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * The one capability classification rule this package applies, extracted so
3
+ * every declaration site in smrt-web shares a single implementation (#2587,
4
+ * #2588).
5
+ *
6
+ * Two sites consume it today: `webmcp.ts` (canonical definitions trusted
7
+ * through it directly, and its legacy CRUD switch's fail-closed default
8
+ * branch) and `intents.ts` (a declared view intent, which is never a CRUD
9
+ * verb and so resolves through the declaration rule alone). Keeping the rule
10
+ * here rather than private to `webmcp.ts` is what lets the intent path be a
11
+ * dependency-free module that never pulls the client-data engine.
12
+ *
13
+ * This module structurally mirrors `CapabilityEffect` / `CapabilityDeclaration`
14
+ * / `CapabilityClassification` in `@happyvertical/smrt-types` rather than
15
+ * importing them — this package's dependency-DAG guardrails keep it free of
16
+ * every `@happyvertical/*` dependency (see AGENTS.md "No inter-smrt
17
+ * dependencies"), the same reason `data-query.ts` mirrors that package's
18
+ * bounded query envelope structurally instead of importing it.
19
+ */
20
+ /**
21
+ * Browser/agent-visible effect classification for a capability. `'read'`
22
+ * never mutates; `'write'` mutates within the application; `'destructive'`
23
+ * may remove or irreversibly change data.
24
+ */
25
+ export type WebMcpToolEffect = 'read' | 'write' | 'destructive';
26
+ /** Every valid {@link WebMcpToolEffect}, in exposure-breadth order. */
27
+ export declare const WEBMCP_TOOL_EFFECTS: readonly WebMcpToolEffect[];
28
+ /**
29
+ * An author-supplied, partial classification. Any omitted field resolves
30
+ * through the fail-closed rule on {@link resolveDeclaredCapability}, never
31
+ * through a CRUD- or name-based guess.
32
+ */
33
+ export interface WebMcpCapabilityDeclaration {
34
+ effect?: WebMcpToolEffect;
35
+ idempotent?: boolean;
36
+ openWorld?: boolean;
37
+ }
38
+ /** A fully resolved classification. */
39
+ export interface WebMcpCapabilityClassification {
40
+ effect: WebMcpToolEffect;
41
+ /**
42
+ * Derived, never declared: every non-read effect is annotated destructive
43
+ * to the browser, so a `write` capability cannot claim the MCP
44
+ * additive-only guarantee.
45
+ */
46
+ destructive: boolean;
47
+ idempotent: boolean;
48
+ openWorld: boolean;
49
+ }
50
+ /** The MCP-shaped annotation set a resolved classification emits. */
51
+ export interface WebMcpCapabilityAnnotations {
52
+ readOnlyHint: boolean;
53
+ destructiveHint: boolean;
54
+ idempotentHint: boolean;
55
+ openWorldHint: boolean;
56
+ untrustedContentHint: boolean;
57
+ }
58
+ /**
59
+ * Resolve a declared capability with no CRUD/action-based guess — the shared
60
+ * fail-closed default documented on `CapabilityClassification` in
61
+ * `@happyvertical/smrt-types` (#2587): an omitted or invalid `effect`
62
+ * resolves to `'destructive'`, an omitted `idempotent` to `false`, an
63
+ * omitted `openWorld` to `true`. Each field defaults independently: a
64
+ * declared `effect: 'read'` does NOT imply `idempotent: true`.
65
+ */
66
+ export declare function resolveDeclaredCapability(declared: WebMcpCapabilityDeclaration): WebMcpCapabilityClassification;
67
+ /**
68
+ * The browser annotations a resolved classification is finally registered
69
+ * with. `destructiveHint` carries the DERIVED `destructive` flag, so a
70
+ * `write` capability is annotated destructive exactly like a generated
71
+ * custom model action declared `effect: 'write'`.
72
+ */
73
+ export declare function capabilityAnnotations(classification: WebMcpCapabilityClassification): WebMcpCapabilityAnnotations;
74
+ /**
75
+ * Encode a resolved classification as the INPUT hints
76
+ * `registerWebMcpBespokeTool` decodes (`bespokeDeclaredSemantics`), so a
77
+ * capability resolved here survives that registrar's own re-resolution
78
+ * unchanged.
79
+ *
80
+ * This is deliberately NOT {@link capabilityAnnotations}. That function emits
81
+ * the derived `destructive` flag, and `destructiveHint: true` is the first
82
+ * check the registrar makes — round-tripping it would silently upgrade every
83
+ * `write` capability to `destructive`. On the input side `destructiveHint`
84
+ * means "the author declared the destructive EFFECT", and `false` selects the
85
+ * `write` bucket; the registrar re-emits it as `true` on its way to the
86
+ * browser.
87
+ */
88
+ export declare function capabilityDeclarationHints(classification: WebMcpCapabilityClassification): WebMcpCapabilityAnnotations;
89
+ //# sourceMappingURL=capability-classification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-classification.d.ts","sourceRoot":"","sources":["../src/capability-classification.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,OAAO,GAAG,aAAa,CAAC;AAEhE,uEAAuE;AACvE,eAAO,MAAM,mBAAmB,EAAE,SAAS,gBAAgB,EAI1D,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,uCAAuC;AACvC,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,gBAAgB,CAAC;IACzB;;;;OAIG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,qEAAqE;AACrE,MAAM,WAAW,2BAA2B;IAC1C,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;IACvB,oBAAoB,EAAE,OAAO,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,2BAA2B,GACpC,8BAA8B,CAYhC;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,8BAA8B,GAC7C,2BAA2B,CAQ7B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CACxC,cAAc,EAAE,8BAA8B,GAC7C,2BAA2B,CAQ7B"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * @happyvertical/smrt-web — capability extension seam (#1755).
3
+ *
4
+ * A capability is a small plug-in that hooks the {@link createSmrtCollection}
5
+ * lifecycle so a follow-on client slice — the offline outbox (#1762),
6
+ * persistence (#1764), or live SSE invalidation (#1763-client) — can live in
7
+ * its OWN module instead of contending on `index.ts`. The factory runs the six
8
+ * hooks below at fixed points; a collection with no capabilities is
9
+ * byte-for-byte the collection of today (the no-op guarantee).
10
+ *
11
+ * ## The engine boundary is sacred
12
+ *
13
+ * Every type here is expressed ENTIRELY in existing SMRT-owned terms
14
+ * (`SmrtWebCollectionDefinition`, `SmrtCrudFetchers`, `SmrtWebRow`, plain TS).
15
+ * No `@tanstack/*` type — no `QueryClient`, no engine `Collection` — appears on
16
+ * the capability surface, so the build's `.d.ts` boundary check stays green and
17
+ * the engine stays swappable. A capability that genuinely needs deeper engine
18
+ * access reaches it through the existing `getEngineCollection()` unknown-bridge
19
+ * from inside its own module — NEVER by widening these types.
20
+ *
21
+ * These types intentionally import nothing from `./index.ts` beyond the
22
+ * SMRT-owned contracts they name, so the seam is reviewable and unit-testable on
23
+ * its own (see {@link runWrapMutation}).
24
+ */
25
+ import type { SmrtCrudFetchers, SmrtWebCollectionDefinition, SmrtWebRow, SmrtWebSubscription } from './index.js';
26
+ /**
27
+ * The context every capability hook receives — a stable, engine-free view of
28
+ * the collection being built. All fields are the exact values the factory uses
29
+ * internally (the resolved cache key/id, the same fetchers), so a capability
30
+ * keys its own storage or subscriptions off the identical discriminators.
31
+ */
32
+ export interface SmrtWebCapabilityContext<TData extends object = object> {
33
+ /** The generated definition this collection materializes. */
34
+ readonly definition: SmrtWebCollectionDefinition<TData>;
35
+ /** The CRUD fetchers the collection persists through. */
36
+ readonly fetchers: SmrtCrudFetchers;
37
+ /**
38
+ * The `queryKey` segments the collection's reads use — a LIVE view: from
39
+ * `onAttach`/`warmStart` onward it is the final key (including every
40
+ * capability-contributed segment); read during `contributeCacheKey` it omits
41
+ * that capability's own not-yet-applied segment. Treat as read-only.
42
+ */
43
+ readonly cacheKey: readonly string[];
44
+ /** The engine-collection id string (mirrors {@link cacheKey}). */
45
+ readonly cacheId: string;
46
+ /**
47
+ * Enter the SAME relationship-derived invalidation the factory runs after a
48
+ * settled mutation. A capability calls this to refetch this collection and its
49
+ * manifest-related collections in response to an EXTERNAL trigger (e.g. an SSE
50
+ * message) without reaching into the engine.
51
+ */
52
+ invalidate(): void;
53
+ /**
54
+ * A snapshot of the collection's current rows as plain public DTOs — the same
55
+ * projection as {@link SmrtWebCollection.toArray}, so the engine's virtual
56
+ * props never cross the boundary. The persistence slice (#1764) reads this in
57
+ * its write-back to serialize the current cache to disk. Populated by the real
58
+ * factory; a hand-built test context may omit it, so callers guard for its
59
+ * presence.
60
+ *
61
+ * SAFE ONLY FROM `onAttach` ONWARD. The factory's implementation closes over
62
+ * the engine collection, which is constructed AFTER `contributeCacheKey` and
63
+ * `warmStart` run — calling this from those earlier hooks would throw
64
+ * (temporal-dead-zone). Read rows from `onAttach`, `onSettled`, or an external
65
+ * trigger, never during construction.
66
+ */
67
+ snapshot?(): ReadonlyArray<SmrtWebRow<TData>>;
68
+ /**
69
+ * Subscribe to the collection's change notifications — the same stream as
70
+ * {@link SmrtWebCollection.subscribeChanges} (plain-DTO payloads). The
71
+ * persistence slice (#1764) wires its debounced write-back here in `onAttach`
72
+ * and detaches in `teardown`. Engine-free by construction: the payload is
73
+ * `unknown` (the capability only needs the change SIGNAL, then re-reads via
74
+ * {@link snapshot}), so no engine type crosses the seam. Populated by the real
75
+ * factory; a hand-built test context may omit it.
76
+ *
77
+ * SAFE ONLY FROM `onAttach` ONWARD (same reason as {@link snapshot}): it closes
78
+ * over the engine collection built after the pre-construction hooks.
79
+ */
80
+ subscribe?(callback: (changes: unknown) => void): SmrtWebSubscription;
81
+ }
82
+ /**
83
+ * A single mutation described in SMRT-owned terms — handed to
84
+ * {@link SmrtWebCapability.wrapMutation} and {@link SmrtWebCapability.onSettled}
85
+ * so a capability can inspect or intercept a write without touching the engine's
86
+ * transaction type.
87
+ */
88
+ export interface SmrtWebMutationEnvelope {
89
+ /** Which mutation kind this describes. */
90
+ readonly kind: 'insert' | 'update' | 'delete';
91
+ /** The row key: the client-local id on insert, else the target row's id. */
92
+ readonly key: string;
93
+ /**
94
+ * The write payload: the full row on insert, the changed fields on update,
95
+ * and an empty object on delete (the key carries the target).
96
+ */
97
+ readonly data: Record<string, unknown>;
98
+ /**
99
+ * The server `updated_at` / `updatedAt` value the mutation is based on, when
100
+ * known. Update/delete handlers capture this from the original row so offline
101
+ * replay can preserve the sync/apply conflict guard even when the write
102
+ * payload only carries changed fields (or no fields for delete).
103
+ */
104
+ readonly baseUpdatedAt?: string;
105
+ }
106
+ /** The outcome handed to {@link SmrtWebCapability.wrapMutation}. */
107
+ export type WrapMutationOutcome = {
108
+ handled: true;
109
+ result: unknown;
110
+ } | {
111
+ handled: false;
112
+ } | undefined;
113
+ /** The settle outcome handed to {@link SmrtWebCapability.onSettled}. */
114
+ export type MutationSettleOutcome = {
115
+ ok: true;
116
+ result: unknown;
117
+ } | {
118
+ ok: false;
119
+ error: unknown;
120
+ };
121
+ /**
122
+ * A capability plugged into {@link createSmrtCollection}. Every hook is
123
+ * optional; a capability implements only the points its slice needs. Hooks fire
124
+ * in these fixed places, and capabilities run in ARRAY ORDER:
125
+ *
126
+ * - `contributeCacheKey` — ONCE, before the engine collection is constructed.
127
+ * - `warmStart` — ONCE, before the first read (seeds the cache).
128
+ * - `wrapMutation` — per mutation, BEFORE the fetcher, with a chance to handle
129
+ * the write itself (offline).
130
+ * - `onSettled` — per mutation, AFTER it settles (success AND fetcher-throw).
131
+ * - `onAttach` — ONCE, right after the engine collection is constructed; the
132
+ * ONLY place a capability registers an external (non-mutation) trigger such as
133
+ * an SSE subscription.
134
+ * - `teardown` — in `cleanup()`, after the engine's own cleanup.
135
+ */
136
+ export interface SmrtWebCapability<TData extends object = object> {
137
+ /** Diagnostic name (e.g. `'offline-outbox'`). */
138
+ readonly name: string;
139
+ /**
140
+ * Contribute extra cache-key segments so this capability can partition the
141
+ * collection's cache (e.g. an outbox variant). Runs ONCE, before construction;
142
+ * returned segments are appended to the collection's cache key/id. Return
143
+ * `undefined` (or omit) to contribute nothing.
144
+ */
145
+ contributeCacheKey?(ctx: SmrtWebCapabilityContext<TData>): string[] | undefined;
146
+ /**
147
+ * Provide rows to seed the cache before the first read — the persistence
148
+ * slice's rehydrate-from-disk path. Runs ONCE, before construction. NOTE:
149
+ * caller-supplied `initialData` (fresher same-request SSR truth) WINS over any
150
+ * capability `warmStart`. Return `undefined` to contribute no seed.
151
+ */
152
+ warmStart?(ctx: SmrtWebCapabilityContext<TData>): Promise<SmrtWebRow<TData>[] | undefined> | SmrtWebRow<TData>[] | undefined;
153
+ /**
154
+ * Intercept a mutation BEFORE its fetcher runs. Return `{ handled: true,
155
+ * result }` to take over the write (the fetcher is skipped and `result`
156
+ * reconciles the optimistic row — the offline path); return `{ handled: false
157
+ * }` or `undefined` to fall through to the real fetcher. With multiple
158
+ * capabilities the FIRST `{ handled: true }` wins and later capabilities'
159
+ * `wrapMutation` are skipped.
160
+ */
161
+ wrapMutation?(envelope: SmrtWebMutationEnvelope, ctx: SmrtWebCapabilityContext<TData>): Promise<WrapMutationOutcome> | WrapMutationOutcome;
162
+ /**
163
+ * Observe a mutation after it settles — on BOTH a successful persist and a
164
+ * fetcher throw (before the optimistic rollback propagates). Never swallows
165
+ * the error: a thrown fetcher error still rolls the transaction back.
166
+ */
167
+ onSettled?(envelope: SmrtWebMutationEnvelope, outcome: MutationSettleOutcome, ctx: SmrtWebCapabilityContext<TData>): void;
168
+ /**
169
+ * Run ONCE, right after the engine collection is constructed. The ONLY hook
170
+ * where a capability wires an external trigger (SSE subscription, focus
171
+ * listener) — `ctx.invalidate()` is callable here.
172
+ */
173
+ onAttach?(ctx: SmrtWebCapabilityContext<TData>): void;
174
+ /** Run inside `cleanup()`, AFTER the engine's own cleanup. Awaited if async. */
175
+ teardown?(ctx: SmrtWebCapabilityContext<TData>): void | Promise<void>;
176
+ }
177
+ /**
178
+ * Run the `wrapMutation` hook across `capabilities` in array order for one
179
+ * mutation, short-circuiting on the FIRST capability that returns `{ handled:
180
+ * true }` (later capabilities' `wrapMutation` are then skipped). A capability
181
+ * that returns `{ handled: false }`, `undefined`, or omits the hook declines,
182
+ * and the next is tried. When every capability declines, resolves `{ handled:
183
+ * false }` so the factory falls through to the real fetcher.
184
+ */
185
+ export declare function runWrapMutation<TData extends object>(capabilities: readonly SmrtWebCapability<TData>[], envelope: SmrtWebMutationEnvelope, ctx: SmrtWebCapabilityContext<TData>): Promise<{
186
+ handled: true;
187
+ result: unknown;
188
+ } | {
189
+ handled: false;
190
+ }>;
191
+ //# sourceMappingURL=capability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Browser transport for the canonical bounded data-query envelope (#2444).
3
+ *
4
+ * This is a textual structural mirror of `@happyvertical/smrt-types` rather
5
+ * than an import: smrt-web deliberately has no inter-SMRT dependencies. The
6
+ * authenticated server adapter owns allowlist, authorization, fingerprint,
7
+ * and byte-limit enforcement. This module gives browser callers a stable
8
+ * request/result shape and rejects malformed response envelopes before they
9
+ * reach a mounted surface.
10
+ */
11
+ export type SmrtWebDataQueryScalar = string | number | boolean | null;
12
+ export type SmrtWebDataQueryFilterOperator = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'notIn' | 'like';
13
+ export type SmrtWebDataQueryFilter = {
14
+ kind: 'condition';
15
+ field: string;
16
+ operator: SmrtWebDataQueryFilterOperator;
17
+ value: SmrtWebDataQueryScalar | SmrtWebDataQueryScalar[];
18
+ } | {
19
+ kind: 'all' | 'any';
20
+ filters: SmrtWebDataQueryFilter[];
21
+ } | {
22
+ kind: 'not';
23
+ filter: SmrtWebDataQueryFilter;
24
+ };
25
+ export interface SmrtWebDataQueryRequest {
26
+ version: 1;
27
+ requestId: string;
28
+ mode: 'rows' | 'count' | 'facets';
29
+ projection?: string[];
30
+ filter?: SmrtWebDataQueryFilter;
31
+ sort?: Array<{
32
+ field: string;
33
+ direction: 'asc' | 'desc';
34
+ }>;
35
+ page?: {
36
+ kind: 'offset';
37
+ offset: number;
38
+ limit: number;
39
+ } | {
40
+ kind: 'cursor';
41
+ after?: string;
42
+ limit: number;
43
+ };
44
+ consistency?: {
45
+ mode: 'eventual' | 'snapshot';
46
+ asOf?: string;
47
+ };
48
+ facets?: Array<{
49
+ field: string;
50
+ limit: number;
51
+ }>;
52
+ }
53
+ export type SmrtWebDataQueryTotal = {
54
+ kind: 'exact' | 'estimated';
55
+ value: number;
56
+ asOf?: string;
57
+ } | {
58
+ kind: 'unavailable';
59
+ reason?: string;
60
+ };
61
+ export interface SmrtWebDataQueryFacetResult {
62
+ field: string;
63
+ values: Array<{
64
+ value: SmrtWebDataQueryScalar;
65
+ count: number;
66
+ }>;
67
+ truncated: boolean;
68
+ }
69
+ export interface SmrtWebDataQueryResult {
70
+ version: 1;
71
+ requestId: string;
72
+ queryFingerprint: string;
73
+ identityField: string;
74
+ rows: Array<Record<string, unknown>>;
75
+ page?: {
76
+ kind: 'offset';
77
+ limit: number;
78
+ offset: number;
79
+ hasMore: boolean;
80
+ } | {
81
+ kind: 'cursor';
82
+ limit: number;
83
+ nextCursor?: string;
84
+ hasMore: boolean;
85
+ };
86
+ total: SmrtWebDataQueryTotal;
87
+ facets?: SmrtWebDataQueryFacetResult[];
88
+ freshness: {
89
+ state: 'fresh' | 'stale' | 'unknown';
90
+ asOf?: string;
91
+ };
92
+ warnings: string[];
93
+ truncated: boolean;
94
+ }
95
+ /** Browser transport seam; REST, WebMCP, and test transports share it. */
96
+ export interface SmrtWebDataQueryTransport {
97
+ query(request: SmrtWebDataQueryRequest, options?: {
98
+ signal?: AbortSignal;
99
+ }): Promise<unknown>;
100
+ }
101
+ /** Mirrors core's hard output limits without adding an inter-SMRT dependency. */
102
+ export declare const MAX_SMRT_WEB_DATA_QUERY_RESULT_BYTES = 10000000;
103
+ export declare const MAX_SMRT_WEB_DATA_QUERY_ROWS = 1000;
104
+ export declare const MAX_SMRT_WEB_DATA_QUERY_FACETS = 20;
105
+ export declare const MAX_SMRT_WEB_DATA_QUERY_FACET_VALUES = 1000;
106
+ export declare const MAX_SMRT_WEB_DATA_QUERY_WARNINGS = 100;
107
+ export declare const MAX_SMRT_WEB_DATA_QUERY_PAGE_LIMIT = 1000;
108
+ export declare const MAX_SMRT_WEB_DATA_QUERY_OFFSET = 1000000;
109
+ export declare const MAX_SMRT_WEB_DATA_QUERY_CONTAINER_ITEMS = 1000;
110
+ export declare const MAX_SMRT_WEB_DATA_QUERY_STRING_LENGTH = 65536;
111
+ /**
112
+ * Check the server-produced, normalized result envelope before a browser
113
+ * surface consumes it. This validates portable shape only; the server's core
114
+ * normalizer remains the authorization, projection, and query-policy boundary.
115
+ */
116
+ export declare function normalizeSmrtWebDataQueryResult(value: unknown): SmrtWebDataQueryResult;
117
+ /** Run a browser transport and return the defensive normalized envelope. */
118
+ export declare function executeSmrtWebDataQuery(transport: SmrtWebDataQueryTransport, request: SmrtWebDataQueryRequest, options?: {
119
+ signal?: AbortSignal;
120
+ }): Promise<SmrtWebDataQueryResult>;
121
+ //# sourceMappingURL=data-query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-query.d.ts","sourceRoot":"","sources":["../src/data-query.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Browser transport for bounded data-surface action envelopes.
3
+ *
4
+ * This structurally mirrors smrt-types without importing another SMRT package.
5
+ * The server remains responsible for authority, descriptor allowlists, and
6
+ * confirmation-token validation; this boundary only rejects malformed replies.
7
+ */
8
+ import type { OutboxCommand, OutboxCommandResult, OutboxCommandTransport } from './offline/types.js';
9
+ export type SmrtWebDataSurfaceJsonPrimitive = string | number | boolean | null;
10
+ export type SmrtWebDataSurfaceJsonValue = SmrtWebDataSurfaceJsonPrimitive | SmrtWebDataSurfaceJsonValue[] | {
11
+ [key: string]: SmrtWebDataSurfaceJsonValue;
12
+ };
13
+ export interface SmrtWebDataSurfaceIdentity {
14
+ surfaceId: string;
15
+ kind: 'table' | 'list' | 'report' | 'custom';
16
+ subject?: {
17
+ type: string;
18
+ id: string;
19
+ label?: string;
20
+ };
21
+ }
22
+ export type SmrtWebDataSurfaceSelection = {
23
+ scope: 'current-page';
24
+ } | {
25
+ scope: 'explicit-ids';
26
+ rowIds: Array<string | number>;
27
+ } | {
28
+ scope: 'all-matching';
29
+ queryFingerprint: string;
30
+ };
31
+ export interface SmrtWebDataSurfaceActionRequest {
32
+ version: 1;
33
+ requestId: string;
34
+ identity: SmrtWebDataSurfaceIdentity;
35
+ actionId: string;
36
+ phase: 'preview' | 'apply';
37
+ expectedRevision: number;
38
+ /** Required by the server for apply; retries with the same key replay safely. */
39
+ idempotencyKey?: string;
40
+ selection: SmrtWebDataSurfaceSelection;
41
+ payload?: SmrtWebDataSurfaceJsonValue;
42
+ confirmationToken?: string;
43
+ }
44
+ export interface SmrtWebDataSurfaceActionResult {
45
+ version: 1;
46
+ requestId: string;
47
+ identity: SmrtWebDataSurfaceIdentity;
48
+ actionId: string;
49
+ phase: 'preview' | 'apply';
50
+ ok: boolean;
51
+ reason?: string;
52
+ confirmationToken?: string;
53
+ details?: {
54
+ [key: string]: SmrtWebDataSurfaceJsonValue;
55
+ };
56
+ }
57
+ export interface SmrtWebDataSurfaceActionTransport {
58
+ action(request: SmrtWebDataSurfaceActionRequest, options?: {
59
+ signal?: AbortSignal;
60
+ }): Promise<unknown>;
61
+ }
62
+ export declare const MAX_SMRT_WEB_DATA_SURFACE_ACTION_RESULT_BYTES = 1000000;
63
+ export declare const MAX_SMRT_WEB_DATA_SURFACE_ACTION_IDENTIFIER_LENGTH = 256;
64
+ export declare const MAX_SMRT_WEB_DATA_SURFACE_ACTION_JSON_DEPTH = 16;
65
+ export declare const MAX_SMRT_WEB_DATA_SURFACE_ACTION_CONTAINER_ITEMS = 1000;
66
+ /** Fail closed before an action result reaches browser state. */
67
+ export declare function normalizeSmrtWebDataSurfaceActionResult(value: unknown): SmrtWebDataSurfaceActionResult;
68
+ export declare function executeSmrtWebDataSurfaceAction(transport: SmrtWebDataSurfaceActionTransport, request: SmrtWebDataSurfaceActionRequest, options?: {
69
+ signal?: AbortSignal;
70
+ }): Promise<SmrtWebDataSurfaceActionResult>;
71
+ /**
72
+ * The replay-time request for {@link dataSurfaceActionCommandTransport}: every
73
+ * action-request field except those the adapter owns — `version`, `phase`,
74
+ * `requestId`, `idempotencyKey`, and `confirmationToken`.
75
+ */
76
+ export type SmrtWebDataSurfaceActionCommandRequest = Omit<SmrtWebDataSurfaceActionRequest, 'version' | 'phase' | 'requestId' | 'idempotencyKey' | 'confirmationToken'>;
77
+ export interface SmrtWebDataSurfaceActionCommandTransportOptions {
78
+ /** The same action transport the mounted surface uses online. */
79
+ transport: SmrtWebDataSurfaceActionTransport;
80
+ /**
81
+ * Build the action request for a queued write at its FIRST replay attempt,
82
+ * so it carries the surface's `expectedRevision` as of replay rather than
83
+ * capture. The built request is pinned durably to the write and reused on
84
+ * every later attempt (including after a reload): the server fingerprints
85
+ * the request per idempotency key, so a resend after a lost response must be
86
+ * identical to replay the recorded result instead of `idempotency_conflict`.
87
+ */
88
+ request: (command: OutboxCommand) => SmrtWebDataSurfaceActionCommandRequest | Promise<SmrtWebDataSurfaceActionCommandRequest>;
89
+ /**
90
+ * Run `preview` first and apply with its `confirmationToken` — for actions
91
+ * whose server adapter requires confirmation. Default false (apply only).
92
+ * The token is pinned before apply; a retry applies with it directly (the
93
+ * server replays a completed result) and previews again only when the token
94
+ * turns out unusable.
95
+ */
96
+ preview?: boolean;
97
+ /** Map a non-throwing result onto an outbox outcome. Default below. */
98
+ classify?: (result: SmrtWebDataSurfaceActionResult) => OutboxCommandResult;
99
+ }
100
+ /**
101
+ * Default outcome mapping for a data-surface action result. `ok` → applied; a
102
+ * transient server reason → retryable `write_failed`; an authentication reason
103
+ * → pause for re-auth; a stale revision/preview → `conflict` (a RESOLVED
104
+ * outcome the app rebases from); anything else — including `denied` — is a
105
+ * terminal rejection surfaced as `failed`.
106
+ */
107
+ export declare function classifySmrtWebDataSurfaceActionResult(result: SmrtWebDataSurfaceActionResult): OutboxCommandResult;
108
+ /**
109
+ * An {@link OutboxCommandTransport} that replays a queued write as a
110
+ * data-surface action `apply` (optionally preceded by `preview`) through the
111
+ * surface's own server adapter — its authority, allowlist, and principal
112
+ * scoping stay on the server path (#3021). The outbox's durable idempotency
113
+ * key becomes the action's `idempotencyKey`, so a resend after a lost response
114
+ * replays the server's recorded result instead of applying twice. Malformed or
115
+ * mismatched replies throw, which the outbox treats as retryable.
116
+ */
117
+ export declare function dataSurfaceActionCommandTransport(options: SmrtWebDataSurfaceActionCommandTransportOptions): OutboxCommandTransport;
118
+ //# sourceMappingURL=data-surface-actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-surface-actions.d.ts","sourceRoot":"","sources":["../src/data-surface-actions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @happyvertical/smrt-web — shared durable-store foundation (#1755).
3
+ *
4
+ * The ONE SMRT-layer namespacing + wipe registry that the future offline
5
+ * outbox (#1762) and persistence (#1764) slices both build on. Pure bookkeeping
6
+ * — ZERO client-data-engine (`@tanstack/*`) imports — so it stays inside the
7
+ * engine-absorption boundary and ships now, before either consumer exists, so
8
+ * the two slices agree on it from day one.
9
+ *
10
+ * Why a SMRT-layer registry rather than one storage engine: TanStack DB
11
+ * persistence (SQLite-WASM / OPFS) and `@tanstack/offline-transactions`
12
+ * (IndexedDB) are SEPARATE storage engines. There is no single primitive that
13
+ * spans both, so the shared foundation lives one level up — a deterministic
14
+ * namespace both slices key their own storage under, plus a registry so
15
+ * {@link wipeDurableStore} can clear BOTH through one call without the outbox
16
+ * and persistence modules importing each other. A logout / tenant-switch wipes
17
+ * every durable artifact for a namespace in one place.
18
+ *
19
+ * Nothing in this package calls these yet — the seam ships ahead of its
20
+ * consumers by design (see PRD #1755).
21
+ */
22
+ /**
23
+ * The identity a durable namespace is derived from. Combining the API base with
24
+ * the tenant + identity + manifest hash means a logout, a tenant switch, or a
25
+ * schema change each land on a DIFFERENT namespace, so durable artifacts are
26
+ * never reused across those boundaries.
27
+ *
28
+ * `manifestHash` is supplied by the caller (its source is #1764's call — a
29
+ * schema-shape digest); this module is source-agnostic and treats it as an
30
+ * opaque discriminator.
31
+ */
32
+ export interface DurableStoreKey {
33
+ /** API base path the durable data was fetched against (e.g. `/api/v1`). */
34
+ apiBase: string;
35
+ /** Active tenant id, if any — absent means the single-tenant / global scope. */
36
+ tenantId?: string;
37
+ /** Authenticated identity id, if any — absent means anonymous. */
38
+ identityId?: string;
39
+ /** Opaque schema-shape digest; a change forces a fresh namespace. */
40
+ manifestHash: string;
41
+ }
42
+ /**
43
+ * Compute the deterministic storage namespace for a {@link DurableStoreKey}.
44
+ * The same key always yields the same string; **any differing segment yields a
45
+ * different one** (injective) — this is critical because the namespace IS the
46
+ * tenant/identity/api isolation + wipe boundary, so a collision would reuse or
47
+ * wipe durable data ACROSS those boundaries.
48
+ *
49
+ * Injectivity is guaranteed three ways: every segment is `encodeURIComponent`-
50
+ * encoded, so a raw `:` in a value becomes `%3A` and can never be mistaken for a
51
+ * separator; an ABSENT `tenantId` / `identityId` maps to the empty string while
52
+ * a PRESENT value is prefixed with `_` (so undefined→``, ``→`_`, `x`→`_x`) — so
53
+ * an explicitly-EMPTY id no longer collides with "no id", nor does a real id of
54
+ * `-`. Both future slices key their own storage primitive (IndexedDB store name,
55
+ * OPFS path, …) under this string.
56
+ */
57
+ export declare function durableStoreNamespace(key: DurableStoreKey): string;
58
+ /**
59
+ * A durable artifact registered under a namespace — the outbox queue (#1762) or
60
+ * a persisted collection store (#1764). Each owns its storage engine and
61
+ * exposes only a `clear()` so {@link wipeDurableStore} can tear it down without
62
+ * knowing which engine backs it.
63
+ */
64
+ export interface DurableResource {
65
+ /** Which slice owns this artifact — for diagnostics and selective sweeps. */
66
+ readonly kind: 'outbox' | 'persisted-collection';
67
+ /** Drop this artifact's durable storage. Best-effort; may reject. */
68
+ clear(): Promise<void>;
69
+ }
70
+ /**
71
+ * Register a durable artifact under a namespace so {@link wipeDurableStore} can
72
+ * later clear it. Returns an unregister function that removes just this
73
+ * resource — call it when the artifact is disposed on its own (before any
74
+ * namespace-wide wipe) so it is not cleared twice.
75
+ */
76
+ export declare function registerDurableResource(namespace: string, resource: DurableResource): () => void;
77
+ /**
78
+ * Clear every durable artifact registered under `namespace`, then drop the
79
+ * namespace. This is the single teardown point a logout / tenant-switch calls:
80
+ * it fans out across BOTH the outbox and persistence slices via the registry,
81
+ * so neither module needs to import the other.
82
+ *
83
+ * Best-effort: a resource whose `clear()` rejects does not abort the sweep —
84
+ * every registered resource is still cleared (a wipe is a teardown, not a
85
+ * transaction). A safe no-op on an unknown or empty namespace.
86
+ */
87
+ export declare function wipeDurableStore(namespace: string): Promise<void>;
88
+ //# sourceMappingURL=durable-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"durable-store.d.ts","sourceRoot":"","sources":["../src/durable-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;;;GASG;AACH,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAOlE;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,sBAAsB,CAAC;IACjD,qEAAqE;IACrE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AASD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,eAAe,GACxB,MAAM,IAAI,CAcZ;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYvE"}