@motujs/runtime 0.0.0-stage → 0.1.1

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/mock.d.ts ADDED
@@ -0,0 +1,286 @@
1
+ import { type Transport } from './index.js';
2
+ /** A response computed from the call's arguments — a client-side STUB (not backend fidelity) that lets
3
+ * the lagoon FILTER/derive per request, so reactive behaviour (e.g. search -> filtered results) works
4
+ * for ANY input, not just pre-recorded ones. Explicitly a stub for verifying the ISLAND's wiring. */
5
+ export type FixtureResponder = (args: unknown[]) => unknown;
6
+ /** What every fixture names, whether it answers with data or with a failure. */
7
+ interface FixtureCall {
8
+ service: string;
9
+ method: string;
10
+ /** Optional role gate: caller must hold one of these for the call to succeed. */
11
+ roles?: string[];
12
+ /**
13
+ * Request-keyed matching: match this call's arguments, so a fixture can return DIFFERENT data for
14
+ * different inputs (e.g. filtered search results per criteria). Each slot is deep-equal to the
15
+ * corresponding arg, with two conveniences: an `undefined` slot is a WILDCARD, and a plain object is
16
+ * matched STRUCTURALLY (a subset) so you pin only the fields you care about — e.g.
17
+ * `[undefined, { login: 'brice' }]` matches any page with that login criterion. Omit `match`
18
+ * entirely for the request-agnostic fallback (the previous behaviour). A request-keyed fixture wins
19
+ * over the fallback when it matches.
20
+ */
21
+ match?: unknown[];
22
+ /**
23
+ * Applies from the Nth call to this `service`/`method` onward (1-indexed) instead of every call.
24
+ *
25
+ * WHY THIS DID NOT EXIST. Matching was by ARGUMENTS only, so "the first read succeeds, a later one
26
+ * fails" had no fixture to write: a refetch after a mutation typically repeats the EXACT SAME
27
+ * arguments as the read that preceded it, so `match` cannot tell them apart — only their ORDER
28
+ * differs. That made a whole class of property untestable: does a component correctly IGNORE a
29
+ * failed refresh and keep what it already had, instead of clobbering good data with nothing? That is
30
+ * not a state a seed can jump to — it is a transition, provable only by actually running the success
31
+ * then the failure, in that order, on the same instance.
32
+ *
33
+ * Two fixtures for the same call — one plain, one `{ status: 500, after: 2 }` — now say exactly
34
+ * that: succeed, then fail from the second call on. `after`-guarded fixtures are eligible once
35
+ * `callIndex >= after` and, among otherwise-equal candidates, the one with the highest SATISFIED
36
+ * `after` wins — the more specific temporal rule beats a call-count-agnostic one once it applies.
37
+ */
38
+ after?: number;
39
+ }
40
+ /** A call that answers with data. */
41
+ export interface FixtureResponse extends FixtureCall {
42
+ /**
43
+ * The response: a fixed VALUE (static replay), or a FUNCTION of the call args (`FixtureResponder`) —
44
+ * a stub that derives/filters a dataset per request so the island's REACTIVE behaviour is verifiable
45
+ * offline (type a filter -> results actually narrow). A function response is an explicit client-side
46
+ * stub, NOT a claim of backend fidelity; use a value (or request-keyed `match`) for recorded truth.
47
+ */
48
+ response: unknown | FixtureResponder;
49
+ status?: never;
50
+ }
51
+ /**
52
+ * A call that FAILS — the state an island spends most of its life one bad afternoon away from, and
53
+ * the one the lagoon could not previously show.
54
+ *
55
+ * WHY THIS DID NOT EXIST, and what it cost. `MockTransport` could only fail for reasons of its own:
56
+ * no fixture (404) and role denied (403). A backend that answers 500 for ONE method while everything
57
+ * else works was not expressible, so "the mission-complete call fails — what does a person see, can
58
+ * they retry?" had no answer in the lagoon. `FailingTransport` fails EVERY call with one status,
59
+ * which is the right tool for `error-resilience` ("does it survive?") and the wrong one for a
60
+ * scenario ("what does it show?").
61
+ *
62
+ * The recorder knew. Capturing a real 500 through `motu fixtures record --transport http`, it wrote
63
+ * the fixture out COMMENTED — it had the truth and nowhere to put it. That comment is gone now.
64
+ *
65
+ * What this buys is not an error test. It is that a failure becomes an ORDINARY SCENARIO: it renders
66
+ * in the lagoon, gets a snapshot baseline, is measured by `responsive` and `a11y`, and can be driven
67
+ * by a region flow. The retry affordance nobody could look at is now a picture someone accepted.
68
+ */
69
+ export interface FixtureFailure extends FixtureCall {
70
+ /** The HTTP status the call answers with. Thrown as a `MotuError`, exactly as a real one would be. */
71
+ status: number;
72
+ /** Optional message. Defaults to something that says the failure was declared, not accidental. */
73
+ message?: string;
74
+ response?: never;
75
+ }
76
+ /**
77
+ * One recorded or hand-written answer to a contract call.
78
+ *
79
+ * A UNION, not an optional `status`, so the two forms cannot be mixed: a fixture that carries both a
80
+ * response and a status is a fixture whose author did not decide, and the compiler says so at the
81
+ * point of writing rather than the mock picking one at runtime.
82
+ */
83
+ export type Fixture = FixtureResponse | FixtureFailure;
84
+ /**
85
+ * A lagoon input case: seed the archipelago store, expect the island to render accordingly. Two
86
+ * scenarios with different seeds that produce DIFFERENT rendered output prove data actually flows
87
+ * across the seam (criteria -> contract -> render), not merely that the wiring type-checks. Consumed
88
+ * by `motu island verify`'s differentiation check (exported alongside `fixtures` from a
89
+ * `fixtures.mock.ts`).
90
+ */
91
+ export interface Scenario {
92
+ /** Human label for the case (shown in verify output). */
93
+ name?: string;
94
+ /**
95
+ * This scenario renders NOTHING, on purpose — and why (a banner silent when nothing is wrong, a
96
+ * palette closed). `data-flow` then counts the empty render as this scenario's answer instead of
97
+ * refusing the comparison, and ASSERTS it: if the island renders something here, the check fails.
98
+ * A sentence, not a flag — an empty reason is no declaration.
99
+ */
100
+ blank?: string;
101
+ /** Store seed for this case, e.g. `{ criteria: { login: 'brice' } }`. */
102
+ seed?: Record<string, unknown>;
103
+ /**
104
+ * Keys provided AFTER the island has mounted and settled — a value that ARRIVES, rather than one the
105
+ * island starts with. Applied on top of `seed`; the render is read once these have landed.
106
+ *
107
+ * FOR A COMPONENT THAT TELLS "ALREADY THERE" FROM "JUST HAPPENED", and nothing else. Peps' sphère
108
+ * sheet treats a request present at mount as dismissed (so « Ma Base » does not reopen the last
109
+ * sphère on every visit) and opens only on one that arrives later — a rule no seed can cross, so
110
+ * the opened sheet had no island scenario at all. `afterMount: { request }` is that arrival.
111
+ *
112
+ * DATA, not a script: one batch of keys, provided through the same seam the page uses, never a
113
+ * click or a wait. The keys are pinned like the seed's, so a region source cannot replace them. If
114
+ * the end state can be written as a seed, write it as a seed.
115
+ */
116
+ afterMount?: Record<string, unknown>;
117
+ /**
118
+ * A scripted interaction, run after the seed settles and before the render is read.
119
+ *
120
+ * NOT the same rule as `RegionStep` — that model bans synthetic clicks because a FLOW tests region
121
+ * coupling GIVEN an island's declared output already fired (`emit` simulates the outcome, on
122
+ * purpose, so a flow never runs real component code). A scenario is the opposite kind of claim: it
123
+ * IS the island's own code running, so there is nothing to simulate around. What a click here proves
124
+ * is exactly what `emit` cannot: whether the component's OWN internal handler — a retry, a catch
125
+ * block, a debounce — behaves correctly when actually invoked, not merely when its outcome is
126
+ * assumed.
127
+ *
128
+ * USE IT FOR A TRANSITION NO SEED CAN DESCRIBE, and nothing else. A state is a seed's job; this is
129
+ * for "succeeded, THEN failed" on one live instance — the shape a seed cannot reach because the
130
+ * second half only exists after the first half ran. If you can write the end state as a seed, do.
131
+ *
132
+ * THE CONSTRAINTS ARE THE POINT, because the objection they answer is real: a harness that accepts
133
+ * arbitrary DOM scripting becomes a second, untyped test suite that no longer derives from the
134
+ * declarations. So this stays deliberately too weak to be one —
135
+ *
136
+ * - CLICK ONLY. No typing, no waits, no conditionals, no navigation. Adding those is how a
137
+ * stimulus turns into a script.
138
+ * - ACCESSIBLE NAME ONLY. Never a CSS selector — the same vocabulary `expectRender` reads FROM,
139
+ * so an interaction can only reach what a person could perceive and act on.
140
+ * - NO ASSERTIONS HERE. A scenario's claim stays its rendered output; interactions are stimulus,
141
+ * never expectation. There is deliberately nowhere in this type to put one.
142
+ * - SHORT. Enough clicks to reach the transition, not to walk a user journey.
143
+ *
144
+ * And it must EARN its place: `interaction-effective` fails an interaction that moved neither the
145
+ * render nor any request — the sibling of `flow-mutation`'s "a step that cannot fail is not a
146
+ * check". Note that it deliberately does NOT require the render to change, because the properties
147
+ * this exists for often assert that it must not.
148
+ */
149
+ interactions?: ScenarioInteraction[];
150
+ }
151
+ export interface ScenarioInteraction {
152
+ /**
153
+ * Click the first visible control (button/checkbox/link/etc.) whose ACCESSIBLE NAME matches
154
+ * (substring, case-sensitive). Roles are tried most-specific first, so a checkbox wins over a
155
+ * button wrapping it. Deliberately the only verb this type has — see `Scenario.interactions`.
156
+ */
157
+ click: string;
158
+ }
159
+ /**
160
+ * A region's declared FLOW: a state, an act, and what the region should hold afterwards.
161
+ *
162
+ * Scenarios describe a state; this describes what happens next. `emit` fires an island's DECLARED
163
+ * output — the same seam the wiring probe uses — so a flow can only ever do what the archipelago says
164
+ * that island can do. NO SELECTORS: the moment a harness accepts arbitrary DOM scripting it is a
165
+ * second, untyped test suite, and it stops being derivable from the declarations.
166
+ *
167
+ * `click` is the one exception, and it exists because the rule above was hiding a FALSE CLAIM. A flow
168
+ * that only ever emits enters the region PAST the component's own handler, so a search box whose
169
+ * `onChange` was dropped is inert on screen while every flow still passes: the coupling is reported as
170
+ * carrying when nothing a user does can make it carry. Measured twice — once as a logic mutation, once
171
+ * as a wiring one — and in both cases the flow was green and the feature was dead.
172
+ *
173
+ * It inherits the constraint that keeps island scenarios from being browser tests: a control is named
174
+ * by its ACCESSIBLE NAME, never a selector, resolved by the same function `Scenario.click` uses. A
175
+ * control with no accessible name cannot be driven, which is a feature. There is deliberately no
176
+ * `fill`, no waits and no scripting — a flow that needs those has become a browser test, and Playwright
177
+ * is better at that than this will ever be.
178
+ *
179
+ * Lives beside the archipelago (`<id>.evidence.ts`), because the mapping it asserts is the region's.
180
+ */
181
+ export interface RegionScenario {
182
+ /**
183
+ * The lagoon WORLD this flow runs in (`defineWorlds` in the override file). Absent = the default
184
+ * lagoon. A world re-answers what the lagoon was handed — a source's port, a seed, a member fact — for
185
+ * the states no flow could otherwise reach.
186
+ */
187
+ world?: string;
188
+ name?: string;
189
+ /** Region keys to establish before the flow runs. */
190
+ seed?: Record<string, unknown>;
191
+ steps?: RegionStep[];
192
+ }
193
+ export interface RegionStep {
194
+ /** The island output to fire, in the region's own vocabulary. */
195
+ emit?: {
196
+ slot: string;
197
+ event: string;
198
+ detail?: unknown;
199
+ };
200
+ /**
201
+ * The HOST feeding region keys — the other way a region moves.
202
+ *
203
+ * Every step used to be an `emit`, which quietly meant only regions whose islands WRITE could have
204
+ * flows at all. Twenty's record page is the counter-example: its two widgets both read
205
+ * `editingWidgetId`, the app owns it, and the coupling is real enough to watch one island change
206
+ * while the other does not. That flow was undeclarable until this existed.
207
+ */
208
+ provide?: Record<string, unknown>;
209
+ /** Region keys and the values they must hold afterwards. Compared structurally. */
210
+ expect?: Record<string, unknown>;
211
+ /**
212
+ * What an island RENDERS afterwards, by slot — the assertion a store read cannot make.
213
+ *
214
+ * `expect` names region keys, so a step whose `expect` names the key its `emit` targets is a
215
+ * tautology: it cannot fail unless the wiring is broken. Ending on another island's rendered text
216
+ * is the thing that fails when the store is right and the screen is wrong.
217
+ *
218
+ * THE SLOT INCLUDES WHAT IT OPENED. A dialog, popover, dropdown or select built on a portal renders
219
+ * as a SIBLING of the slot under `document.body`, so everything a member sees after clicking a
220
+ * control in that slot used to be unassertable — a flow could open an overlay, watch the right text
221
+ * appear, and have nothing it was allowed to name. The slot's surface therefore follows ARIA
222
+ * ownership (`aria-controls` / `aria-owns` / `aria-describedby`, transitively, since overlays nest),
223
+ * which is how a portal declares that content is its own and how a screen reader follows it. Radix —
224
+ * and every shadcn component on it — already wires those, so nothing in the application needs
225
+ * annotating. Content inside another slot is never collected: one island's overlay can never satisfy
226
+ * another island's assertion, which is the coupling this check exists to catch.
227
+ */
228
+ expectRender?: Record<string, string | {
229
+ text?: string;
230
+ notText?: string;
231
+ }>;
232
+ /**
233
+ * The backend calls this step may make — and ONLY these. `[]` says it asks for nothing.
234
+ *
235
+ * `flow-calls` already fails a call nothing ANSWERED; this fails a call nobody EXPECTED, answered or
236
+ * not. Without it a change that made a state ask for more stayed green as long as the extra call was
237
+ * answered — bench/evidence's B9 refetched the remote servers on every load, and the only trace was
238
+ * "1 answered" in the lagoon's calls strip. An entry is `METHOD /path` (query ignored), `/path` (any
239
+ * method) or the declaration's label (`shots.list`). Compared as sets: how often a call repeated is
240
+ * not the claim. Step 1 includes the calls the mount made.
241
+ *
242
+ * Not part of `flow-mutation`: "asks for nothing" rarely depends on the step's input, and a mutant
243
+ * judged on it would report every such step as a constant. It is judged on `expect`/`expectRender`.
244
+ */
245
+ expectCalls?: readonly string[];
246
+ /**
247
+ * A control to click, BY ACCESSIBLE NAME — the user's half of a coupling.
248
+ *
249
+ * `emit` proves the region carries a declared output. This proves something the region cannot say by
250
+ * itself: that acting on what is rendered actually produces that output. The two together are the
251
+ * whole claim; `emit` alone is the half that can pass while the screen is dead.
252
+ *
253
+ * Resolved exactly as an island scenario's `click` is — exact accessible name first, then the
254
+ * narrowest containing match, visible elements only, searching the document so a control inside a
255
+ * portal is reachable.
256
+ */
257
+ click?: string;
258
+ }
259
+ /**
260
+ * Backend-free transport for Storybook / sandbox. Replays fixtures and, when a fixture declares
261
+ * `roles`, throws a 403 MotuError if the sandbox's currently-selected role does not satisfy them —
262
+ * letting you demo the authorization behaviour with no server running. When a fixture declares
263
+ * `match`, calls are resolved by their ARGUMENTS so one service/method can return different data per
264
+ * request (request-keyed fixtures), falling back to a match-less fixture for the same method.
265
+ */
266
+ export declare class MockTransport implements Transport {
267
+ private readonly fixtures;
268
+ private currentRoles;
269
+ /** How many times each `service/method` has been called — what `after` counts against. */
270
+ private readonly callCounts;
271
+ constructor(fixtures: Fixture[], currentRoles?: string[]);
272
+ setRoles(roles: string[]): void;
273
+ call<T>(service: string, method: string, args: unknown[]): Promise<T>;
274
+ }
275
+ /**
276
+ * A transport that fails every call with a fixed status. Used by `motu island verify` to mount an
277
+ * island against a broken backend and check it renders an error state instead of white-screening or
278
+ * leaking an unhandled rejection.
279
+ */
280
+ export declare class FailingTransport implements Transport {
281
+ private readonly status;
282
+ constructor(status?: number);
283
+ call<T>(service: string, method: string): Promise<T>;
284
+ }
285
+ export {};
286
+ //# sourceMappingURL=mock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"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"}
package/dist/mock.js ADDED
@@ -0,0 +1,83 @@
1
+ import { MotuError } from './index.js';
2
+ /** Narrow to the failing form. */
3
+ function isFailure(f) {
4
+ return typeof f.status === 'number';
5
+ }
6
+ /** Structural arg matching: `undefined` pattern slot = wildcard; plain objects match as a subset. */
7
+ function matchValue(pattern, actual) {
8
+ if (pattern === undefined)
9
+ return true;
10
+ if (pattern === null || typeof pattern !== 'object')
11
+ return pattern === actual;
12
+ if (Array.isArray(pattern)) {
13
+ return Array.isArray(actual) && pattern.every((p, i) => matchValue(p, actual[i]));
14
+ }
15
+ if (actual === null || typeof actual !== 'object')
16
+ return false;
17
+ return Object.entries(pattern).every(([k, v]) => matchValue(v, actual[k]));
18
+ }
19
+ function argsMatch(pattern, args) {
20
+ return pattern.every((p, i) => matchValue(p, args[i]));
21
+ }
22
+ /**
23
+ * Backend-free transport for Storybook / sandbox. Replays fixtures and, when a fixture declares
24
+ * `roles`, throws a 403 MotuError if the sandbox's currently-selected role does not satisfy them —
25
+ * letting you demo the authorization behaviour with no server running. When a fixture declares
26
+ * `match`, calls are resolved by their ARGUMENTS so one service/method can return different data per
27
+ * request (request-keyed fixtures), falling back to a match-less fixture for the same method.
28
+ */
29
+ export class MockTransport {
30
+ constructor(fixtures, currentRoles = []) {
31
+ this.fixtures = fixtures;
32
+ this.currentRoles = currentRoles;
33
+ /** How many times each `service/method` has been called — what `after` counts against. */
34
+ this.callCounts = new Map();
35
+ }
36
+ setRoles(roles) {
37
+ this.currentRoles = roles;
38
+ }
39
+ async call(service, method, args) {
40
+ const key = `${service}/${method}`;
41
+ const callIndex = (this.callCounts.get(key) ?? 0) + 1;
42
+ this.callCounts.set(key, callIndex);
43
+ const candidates = this.fixtures.filter((f) => f.service === service && f.method === method && (f.after === undefined || callIndex >= f.after));
44
+ if (!candidates.length) {
45
+ throw new MotuError(404, `mock: no fixture for ${service}/${method}`);
46
+ }
47
+ // Prefer a request-keyed fixture whose `match` fits these args; else the request-agnostic fallback.
48
+ // Within either tier, break ties toward the highest SATISFIED `after` — the fixture guarding "from
49
+ // call N on" is the more specific rule once it applies, and should win over one that fires always.
50
+ const mostRelevant = (fs) => [...fs].sort((a, b) => (b.after ?? -1) - (a.after ?? -1))[0];
51
+ const fixture = mostRelevant(candidates.filter((f) => f.match && argsMatch(f.match, args))) ??
52
+ mostRelevant(candidates.filter((f) => !f.match));
53
+ if (!fixture) {
54
+ throw new MotuError(404, `mock: no fixture for ${service}/${method} matching these arguments`);
55
+ }
56
+ if (fixture.roles && !fixture.roles.some((r) => this.currentRoles.includes(r))) {
57
+ throw new MotuError(403, `mock: role denied for ${service}/${method}`);
58
+ }
59
+ // A DECLARED failure. Thrown the way the real transport throws, so the island takes the same code
60
+ // path it will take in the ocean — not a special "mock is sad" path it would never otherwise run.
61
+ if (isFailure(fixture)) {
62
+ throw new MotuError(fixture.status, fixture.message ?? `mock: declared ${fixture.status} for ${service}/${method}`, true);
63
+ }
64
+ // A function response derives the result from the args (a stub filter) so reactive behaviour works
65
+ // for any input; a value response is a static replay.
66
+ const { response } = fixture;
67
+ return (typeof response === 'function' ? response(args) : response);
68
+ }
69
+ }
70
+ /**
71
+ * A transport that fails every call with a fixed status. Used by `motu island verify` to mount an
72
+ * island against a broken backend and check it renders an error state instead of white-screening or
73
+ * leaking an unhandled rejection.
74
+ */
75
+ export class FailingTransport {
76
+ constructor(status = 500) {
77
+ this.status = status;
78
+ }
79
+ async call(service, method) {
80
+ throw new MotuError(this.status, `forced ${this.status} for ${service}/${method}`);
81
+ }
82
+ }
83
+ //# sourceMappingURL=mock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.js","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,231 @@
1
+ import { type Fixture } from './mock.js';
2
+ /**
3
+ * A fake `fetch`, PostgREST-shaped, for injecting into `createClient(url, key, { global: { fetch } })`
4
+ * (or `createBrowserClient`, which forwards the same option) — one layer BELOW where today's lagoon
5
+ * stubs sit.
6
+ *
7
+ * WHY THIS EXISTS. A lagoon stub today replaces a whole service module by hand, which means the
8
+ * module's OWN logic — orchestration, derived visibility rules, period math, whatever a real function
9
+ * does beyond "read a table" — never runs in the lagoon at all. Nobody notices, because there is
10
+ * nothing to notice: the swap is silent by construction. Swapping one layer down, at the wire, lets
11
+ * every repository and service function run FOR REAL, everywhere — the lagoon, a runtime check, a
12
+ * Playwright test — answered by synthetic data instead of synthetic logic.
13
+ *
14
+ * WHAT IT DOES NOT DO. This is not a PostgREST clone. It supports exactly the operators a real
15
+ * project's client-side code was found to use (`eq`, `is`, `gte`, `lt`, `in`, `not.is.null`, a
16
+ * two-clause `or=`, `order`, `limit`/`offset`, `select` as flat columns/`*`/one embed shape passed
17
+ * through verbatim, `.single()`/`.maybeSingle()` via `Accept: vnd.pgrst.object+json`, `count=exact`,
18
+ * writes with `Prefer: return=representation|minimal`, and `rpc`). A query shape outside that set is
19
+ * an UNSCOPED REQUEST (see below), not a silent wrong answer — the fixture author is meant to notice
20
+ * and extend the fake, not have it guess.
21
+ */
22
+ export interface PostgrestTable {
23
+ /**
24
+ * Row data, filtered/sorted/paginated generically per request — this table's whole content.
25
+ *
26
+ * A plain array for a static fixture; a FUNCTION when the initial content needs to react to a
27
+ * scenario's seed (`seededValue`, as `services-club-feed.ts` already does for the module-swap
28
+ * stubs). A remount re-runs the READ, not the module — a table computed once at import time would
29
+ * answer every later scenario with the first one's seed, same failure club-feed's own comment
30
+ * documents. Called fresh on every GET, same as `FixtureResponse.response` already is.
31
+ */
32
+ rows: Record<string, unknown>[] | (() => Record<string, unknown>[]);
33
+ }
34
+ export interface PostgrestFetchOptions {
35
+ /** Origin the fake answers for; requests to any other origin are UNSCOPED (see `recordUnscoped`). */
36
+ baseUrl?: string;
37
+ /** One entry per table the fake can read/write. Absent table = every read/write on it is unscoped. */
38
+ tables?: Record<string, PostgrestTable>;
39
+ /**
40
+ * RPC results/failures and WRITE results/failures, and — the reason `after` exists — read failures
41
+ * you want injected on top of the generic table engine (`{ service: table, method: 'select',
42
+ * status, after }`) without hand-writing the whole read path. Resolved through `MockTransport`, so
43
+ * `after`/`match`/`roles` all apply exactly as documented there.
44
+ */
45
+ fixtures?: Fixture[];
46
+ /** `auth.getUser()` / `auth.getSession()` stand-ins — most apps route auth through their own client
47
+ * and never reach here, but two direct callers are common enough to be worth a first-class slot. */
48
+ auth?: {
49
+ user?: unknown;
50
+ session?: unknown;
51
+ };
52
+ /**
53
+ * Same-origin application routes this fake answers — a Next.js `app/api/**` handler, a Rails
54
+ * controller, anything the app calls with a RELATIVE url.
55
+ *
56
+ * These do not arrive through the database client, so they only reach here via `installFakeFetch`.
57
+ * Declared as prefixes rather than assumed, because intercepting every same-origin request would
58
+ * swallow the dev server's own traffic — HMR, assets, source maps — and a lagoon that cannot load
59
+ * its own modules is a worse failure than an unanswered route.
60
+ *
61
+ * Answered from `fixtures` keyed by PATH: `{ service: '/api/admin/announcement', method: 'GET' }`.
62
+ */
63
+ appRoutes?: string[];
64
+ }
65
+ /** One request the fake could not answer from a declared table/fixture — the thing a check reports. */
66
+ export interface UnscopedRequest {
67
+ method: string;
68
+ path: string;
69
+ /** `table:<name>` / `rpc:<name>` / `auth:<name>` / `unparsed` — what the fake tried to resolve. */
70
+ target: string;
71
+ reason: string;
72
+ }
73
+ /** Read back (and optionally clear) everything recorded since the page loaded or the last read. */
74
+ export declare function readUnscopedRequests(clear?: boolean): UnscopedRequest[];
75
+ /**
76
+ * Requests the fake DELEGATED that then failed — an app route nobody stubbed, most often.
77
+ *
78
+ * Read alongside the unscoped list: unscoped means "the fake saw it and had nothing for it", this
79
+ * means "the fake never claimed it and the real answer was an error". Both say the island is standing
80
+ * on something that is not there; they differ only in whether `appRoutes`/`baseUrl` reached it.
81
+ */
82
+ export declare function readUnansweredRequests(clear?: boolean): {
83
+ method: string;
84
+ url: string;
85
+ status: number;
86
+ why: string;
87
+ }[];
88
+ export declare function readFakeFetchRequestCount(clear?: boolean): number;
89
+ /** Which tables (and how they were used) and which RPCs an island actually reached. */
90
+ export interface DataReach {
91
+ tables: Record<string, string[]>;
92
+ rpcs: string[];
93
+ /** Edge / serverless functions invoked (`functions.invoke`). */
94
+ functions: string[];
95
+ /** Same-origin application routes called, as `GET /api/…`. */
96
+ routes: string[];
97
+ /**
98
+ * The same reach, split by WHO asked, in the vocabulary a declaration uses.
99
+ *
100
+ * Keys are `island:<tag>`, `source:<id>`, or `unattributed`; values are entries like
101
+ * `table:shots(select)`, `rpc:accept_shots`, `fn:notify`, `route:GET /api/x`. The aggregate above
102
+ * answers "what did this screen touch"; this answers "who has to have declared it", which is the
103
+ * only form a check can compare — an island's reach is its own `contract.ambient`, a source's is
104
+ * `reaches` on its `sources` entry, and charging one to the other would report a correct
105
+ * declaration as a violation.
106
+ */
107
+ by: Record<string, string[]>;
108
+ }
109
+ /**
110
+ * THE CALLS THEMSELVES — what was asked, with what, and what came back.
111
+ *
112
+ * `DataReach` above is a SET of names: it answers "did this screen touch `team_schedules`", which is
113
+ * the question a DECLARATION asks. It cannot answer "did my save actually send the new hour", and
114
+ * that is the question a person asks when a screen appears to do nothing.
115
+ *
116
+ * WHY THIS HAS TO EXIST HERE. Intercepting `fetch` is the point of the lagoon, and the side effect is
117
+ * that the browser's own Network panel shows NOTHING: no request is made, so no tool that watches the
118
+ * network can see the app's traffic. motu removed the standard instrument, so motu owes the
119
+ * replacement — the same argument `traced()`/`provenance` already makes one layer up, for host
120
+ * modules ("the lagoon shows the result and never the question").
121
+ *
122
+ * IT PROVES THE CLIENT HALF ONLY, and the panel that renders it should say so. A request leaving with
123
+ * the right payload cannot tell you the refetch happened, that the response was merged, or that the
124
+ * screen re-rendered. It is the diagnosis for "nothing happened" — the write fired and the read did
125
+ * not change — not evidence that a feature works.
126
+ */
127
+ export interface WireCall {
128
+ /** Monotonic, so a UI can order and de-duplicate without trusting the clock. */
129
+ seq: number;
130
+ at: number;
131
+ /** The declaration's own spelling: `rpc:set_session_agenda`, `table:teams(select)`, `fn:x`. */
132
+ target: string;
133
+ /** The HTTP verb, for the table calls where it is the difference between a read and a write. */
134
+ method: string;
135
+ /**
136
+ * THE ADDRESS, as it was actually written — `/rest/v1/shots?select=*&club_id=eq.11`.
137
+ *
138
+ * `target` is the DECLARATION's spelling of the same call, which is what a check compares against
139
+ * an `ambient` entry; it is deliberately lossy (`table:shots(select)`) and cannot answer the
140
+ * question a person asks when a screen is wrong, which is "what did it actually ask for". Origin
141
+ * stripped: every row here shares it, so it would be 40 characters of noise per line.
142
+ */
143
+ url?: string;
144
+ /** `island:<tag>`, `source:<id>` or `unattributed` — the same attribution `data-reach` uses. */
145
+ by: string;
146
+ /**
147
+ * WHAT THE PERSON DID, when a call can be traced to it — the accessible name of the control they
148
+ * pressed, and how many milliseconds earlier.
149
+ *
150
+ * `by` answers "which declaration should account for this", which is what a CHECK needs. It is
151
+ * also `unattributed` for most real calls, because a source fetches outside any island's window —
152
+ * so on the screen where you just pressed Enregistrer, every row says `unattributed` and none of
153
+ * them says WHY it happened. This is the other axis, and it is the one a person reads: the nine
154
+ * rows a save produced, grouped under the button that produced them.
155
+ */
156
+ gesture?: string;
157
+ /**
158
+ * WHICH PRESS, not which label. Every button on this screen is called "Enregistrer" — the séance's
159
+ * agenda, the commitment banner, the settings dialog — so grouping by the label merged two separate
160
+ * actions into one run and reported the second as part of the first. An id per press cannot.
161
+ */
162
+ gestureId?: number;
163
+ /** What was sent: an RPC's arguments, a write's row, a read's query string. Truncated. */
164
+ request?: unknown;
165
+ status?: number;
166
+ /** A SUMMARY, never the body: a row count, or the error. Bodies are unbounded and mostly noise. */
167
+ response?: string;
168
+ }
169
+ /** Notified whenever an intercepted call is recorded. Returns an unsubscribe. */
170
+ export declare function subscribeWireCalls(cb: () => void): () => void;
171
+ /**
172
+ * Say what the person just did, so the calls that follow can be grouped under it.
173
+ *
174
+ * Written through a global rather than an import because the DOCK sets it and the dock is a separate
175
+ * package that this one must not depend on — the same shape `reachOwner` and the request counter
176
+ * already use. Dev-only by construction: nothing sets it unless the overlay is mounted.
177
+ */
178
+ export declare function noteGesture(label: string): void;
179
+ /** Every intercepted call, oldest first. Does NOT clear: a panel polls it, and a flow may read it twice. */
180
+ export declare function readWireCalls(): WireCall[];
181
+ export declare function clearWireCalls(): void;
182
+ export declare function readDataReach(clear?: boolean): DataReach;
183
+ export declare function createPostgrestFetch(options?: PostgrestFetchOptions): typeof fetch;
184
+ /** What a fake answers for: the same-origin route prefixes, and the backend origin. */
185
+ export interface WireClaims {
186
+ appRoutes?: string[];
187
+ baseUrl?: string;
188
+ }
189
+ /** What `createPostgrestFetch` stamped on a fake — its own claim, not a second copy of it. */
190
+ export declare function fakeFetchClaims(fake: typeof fetch): WireClaims | undefined;
191
+ /**
192
+ * Patch `globalThis.fetch` so requests the app makes DIRECTLY — not through the database client —
193
+ * reach the fake too.
194
+ *
195
+ * Injecting `global: { fetch }` into `createClient` covers everything that client issues, which is
196
+ * most of an app's backend traffic and all of its PostgREST and edge-function traffic. It does not
197
+ * cover a service that calls `fetch('/api/…')` itself, because that is `window.fetch` and the client
198
+ * was never involved. Those requests are same-origin, so they are invisible to `network-sealed` as
199
+ * well: they 404 against the dev server, the caller catches it, an empty state renders, and every
200
+ * check stays green.
201
+ *
202
+ * DELEGATES BY DEFAULT. Only paths the fake actually claims are intercepted; everything else — the
203
+ * dev server's modules, HMR, assets, source maps — goes to the original `fetch` untouched. A lagoon
204
+ * that cannot load its own bundle would be a far worse failure than an unanswered route, so the
205
+ * narrow rule is the safe one.
206
+ *
207
+ * ONE PATCH, MANY FAKES. This used to guard on a global boolean, so the FIRST caller won and every
208
+ * later one was a silent no-op — fine while a project had one region with a wire, and wrong the moment
209
+ * it had two: the second region's routes went to the dev server, 404'd, its islands rendered empty and
210
+ * nothing said why. Fakes now REGISTER, and the single patch asks each in turn what it claims.
211
+ *
212
+ * Idempotent per fake: installing the same one twice leaves one entry, so a hot reload does not build
213
+ * a chain of patches or a chain of registrations.
214
+ */
215
+ export declare function installFakeFetch(fake: typeof fetch, options?: WireClaims): void;
216
+ /** Every fake currently installed, in registration order — what a check reads to say who claimed what. */
217
+ export declare function installedFakeFetches(): readonly WireClaims[];
218
+ /** Forget every installed fake and leave the patch in place. For a test, or a lagoon remount. */
219
+ export declare function resetFakeFetches(): void;
220
+ /**
221
+ * Patch `globalThis.fetch` NOW, with whatever is registered — and whatever registers later.
222
+ *
223
+ * Worth being separate from `installFakeFetch` for one reason: a client that captures `globalThis.fetch`
224
+ * at IMPORT time (`createClient(url, key, { global: { fetch } })` evaluated at module scope) keeps
225
+ * whatever `fetch` was when its module ran. If the fakes are declared rather than installed by a
226
+ * top-level side effect, that capture can happen first and the client talks past every fake, silently.
227
+ * Calling this at the top of the lagoon entry — before any application module is imported — closes it:
228
+ * the patch is in place from the start and the registry fills in behind it.
229
+ */
230
+ export declare function armFakeFetch(): void;
231
+ //# sourceMappingURL=postgrest-fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgrest-fetch.d.ts","sourceRoot":"","sources":["../src/postgrest-fetch.ts"],"names":[],"mappings":"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"}