stitchkit 0.72.5 → 0.74.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/application/diagnostic-journal-contract.d.ts +24 -0
- package/dist/application/diagnostic-journal-contract.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-lock.d.ts +20 -1
- package/dist/application/diagnostic-journal-lock.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-storage.d.ts +1 -0
- package/dist/application/diagnostic-journal-storage.d.ts.map +1 -1
- package/dist/application/diagnostic-journal.d.ts.map +1 -1
- package/dist/application.d.ts +1 -1
- package/dist/application.d.ts.map +1 -1
- package/dist/application.js +93 -17
- package/dist/browser/client-multipart.d.ts.map +1 -1
- package/dist/browser/client-url.d.ts.map +1 -1
- package/dist/browser/client.d.ts.map +1 -1
- package/dist/browser/http.d.ts +15 -0
- package/dist/browser/http.d.ts.map +1 -1
- package/dist/{index-6d32zk83.js → index-58jzmnn4.js} +91 -64
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +584 -547
- package/dist/remote.js +1 -1
- package/dist/testing.js +1 -1
- package/llms-full.txt +247 -10
- package/package.json +1 -1
package/dist/remote.js
CHANGED
package/dist/testing.js
CHANGED
package/llms-full.txt
CHANGED
|
@@ -61,7 +61,7 @@ own, recorded as an ADR.
|
|
|
61
61
|
| `stitchkit/testing` | tests on Bun or Node | stable | in-process generated clients over a real Fetch handler, plus the store and managed-resource conformance kits |
|
|
62
62
|
| `stitchkit/declaration` | build and deployment tooling (Bun or Node) | evolving | `ProjectDeclarationSchema` — the one machine-readable statement a repository makes about itself |
|
|
63
63
|
| `stitchkit/react` | browser | stable | `createCursorQuery`, `createCacheBridge` |
|
|
64
|
-
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 10 of the
|
|
64
|
+
| `stitchkit/agent-runtime` | server | evolving<br>_redefined in 10 of the 19 minors since 0.56.2, most recently 0.69.0_ | optional durable conversation/run loop, history, models, prompts, fencing and events |
|
|
65
65
|
| `stitchkit/agent-runtime/harness` | server | evolving | resource-aware process-local facade over the canonical Agent runtime; supervision stays outside |
|
|
66
66
|
| `stitchkit/agent-runtime/coding-tools` | server (Bun or Node) | evolving | bounded host-authorized direct file and shell tools; a root boundary, not an OS sandbox |
|
|
67
67
|
| `stitchkit/agent-runtime/openrouter` | server | evolving | isolated OpenRouter language-model adapter |
|
|
@@ -69,7 +69,7 @@ own, recorded as an ADR.
|
|
|
69
69
|
| `stitchkit/agent-runtime/sqlite/bun` | server (Bun) | evolving | durable built-in SQLite store for the agent runtime |
|
|
70
70
|
| `stitchkit/agent-runtime/sqlite/node` | server (Node ≥ 22.5) | evolving | durable built-in SQLite store for the agent runtime |
|
|
71
71
|
| `stitchkit-tui` | terminal (Bun) | evolving | optional official OpenTUI host over a caller-composed headless runtime |
|
|
72
|
-
| `stitchkit/application` | server | evolving<br>_redefined in 4 of the
|
|
72
|
+
| `stitchkit/application` | server | evolving<br>_redefined in 4 of the 19 minors since 0.56.2, most recently 0.72.0_ | managed resource graph, readiness, admission, schedules and bounded shutdown |
|
|
73
73
|
| `stitchkit/application/grammy` | server | evolving | isolated grammY polling and webhook lifecycle adapters |
|
|
74
74
|
| `stitchkit/application/opentelemetry` | server | evolving | maps application snapshots onto an injected OpenTelemetry `Meter` |
|
|
75
75
|
|
|
@@ -2005,6 +2005,18 @@ proves that the remote operation did not begin; Stitchkit never silently retries
|
|
|
2005
2005
|
an ambiguous write. Response consumption/cancellation belongs to the operation,
|
|
2006
2006
|
and `close()` interrupts active work and destroys owned connections.
|
|
2007
2007
|
|
|
2008
|
+
**A caller's cancellation reaches the server on both lanes.** The transport picks
|
|
2009
|
+
a raw-socket lane under Bun and `node:http` elsewhere, and both propagate
|
|
2010
|
+
`AbortSignal` the same way: aborting the request tears the connection down, and
|
|
2011
|
+
the handler's `ctx.signal` fires — measured at roughly 300 ms for a 200 ms abort
|
|
2012
|
+
over either lane, matching plain TCP. `close()` is a different thing: it ends the
|
|
2013
|
+
*transport*, not one request, and a request-level abort does not close it.
|
|
2014
|
+
|
|
2015
|
+
The one way to see cancellation appear not to work is to pass the signal to the
|
|
2016
|
+
plain callable — `api.thing(args, { signal })` — where options are ignored in
|
|
2017
|
+
silence. See [per-call cancellation](#per-call-cancellation): `withOptions` is the
|
|
2018
|
+
only door.
|
|
2019
|
+
|
|
2008
2020
|
The response total is a unary-body policy, not a stream-buffer measurement. A
|
|
2009
2021
|
long-lived NDJSON/SSE client opts into streaming explicitly instead of choosing
|
|
2010
2022
|
an arbitrarily large integer:
|
|
@@ -2078,6 +2090,62 @@ including an explicitly declared empty `200` or `205`. A missing body for a
|
|
|
2078
2090
|
declared output, or a body for an endpoint with no output, fails loudly instead
|
|
2079
2091
|
of changing the typed result.
|
|
2080
2092
|
|
|
2093
|
+
Validation runs in one direction. The response is checked against the endpoint's
|
|
2094
|
+
`output` schema before it reaches the caller; arguments are **not** checked
|
|
2095
|
+
against `input` or `params` before the request is sent. A value the contract
|
|
2096
|
+
forbids travels to the server and comes back as a `VALIDATION_ERROR` — `400`,
|
|
2097
|
+
naming every offending field in the `message` and again in `details.issues` as
|
|
2098
|
+
`{ path, code, message }`. That holds for a JSON body, a query string and a path
|
|
2099
|
+
parameter alike, so a rejected argument always costs a round trip.
|
|
2100
|
+
|
|
2101
|
+
It is tempting to close that gap locally: the schemas are on the contract object,
|
|
2102
|
+
and `input` is the very Zod object the server validates with, so parsing it before
|
|
2103
|
+
the call looks free. **It is not, and it fails in the direction that breaks
|
|
2104
|
+
working code.** A call's arguments and the server's `input` are not the same
|
|
2105
|
+
value, for two independent reasons.
|
|
2106
|
+
|
|
2107
|
+
An argument object is typed as the intersection of `params`, `input` and any
|
|
2108
|
+
multipart fields, so `input` covers one factor of it. Parsed over the whole
|
|
2109
|
+
object it silently strips the keys it does not own — or, being `.strict()`,
|
|
2110
|
+
refuses them:
|
|
2111
|
+
|
|
2112
|
+
```ts
|
|
2113
|
+
// params: { id }, input: z.object({ text }).strict()
|
|
2114
|
+
contract.endpoints.update.input.safeParse({ id: 'item-1', text: 'hello' })
|
|
2115
|
+
// → refused: unrecognized_keys: ["id"] the server accepts this call
|
|
2116
|
+
```
|
|
2117
|
+
|
|
2118
|
+
And on a query string or a multipart body the wire carries strings while the
|
|
2119
|
+
caller holds live values, so a coercing schema answers differently on each side:
|
|
2120
|
+
|
|
2121
|
+
```ts
|
|
2122
|
+
// input: z.object({ flag: z.coerce.boolean() })
|
|
2123
|
+
api.list({ flag: false })
|
|
2124
|
+
// local safeParse({ flag: false }) → false
|
|
2125
|
+
// server safeParse({ flag: 'false' }) → true z.coerce.boolean()('false') is true
|
|
2126
|
+
```
|
|
2127
|
+
|
|
2128
|
+
And a plain JSON body is not the safe exception it looks like, because it still
|
|
2129
|
+
crosses `JSON.stringify`. A schema holding any type that does not survive that
|
|
2130
|
+
round trip — `z.date()`, `z.map()`, `z.set()`, `z.bigint()`, `z.instanceof(...)`,
|
|
2131
|
+
or `NaN` / `Infinity` inside a `z.number()` — agrees locally and refuses on the
|
|
2132
|
+
server:
|
|
2133
|
+
|
|
2134
|
+
```ts
|
|
2135
|
+
// input: z.object({ when: z.date() }), POST, no path params
|
|
2136
|
+
check({ when: new Date() }) // accepted: a live Date
|
|
2137
|
+
// server // refused: expected date, received string
|
|
2138
|
+
```
|
|
2139
|
+
|
|
2140
|
+
This one fails in the safe direction — nothing valid is blocked — but it means a
|
|
2141
|
+
local check passes traffic the server will reject, which is the opposite of what
|
|
2142
|
+
it was added for.
|
|
2143
|
+
|
|
2144
|
+
One schema, one call, opposite answers — inside a single release, with no version
|
|
2145
|
+
skew involved. Argument validation therefore stays on the server, which is the
|
|
2146
|
+
only side that sees what was actually sent. A rejected argument costs a round
|
|
2147
|
+
trip, and the refusal names every offending field.
|
|
2148
|
+
|
|
2081
2149
|
An explicit contract `HEAD` operation is exposed like any other typed method.
|
|
2082
2150
|
Because HEAD endpoints are `rawResponse`, it resolves to the untouched
|
|
2083
2151
|
`Response`, giving the caller direct access to status and headers without JSON
|
|
@@ -2115,11 +2183,22 @@ mistaking their callback context for Stitchkit transport options.
|
|
|
2115
2183
|
argument is ignored, in silence, and the request runs to completion while the
|
|
2116
2184
|
caller believes it was cancelled or bounded. TypeScript refuses the extra
|
|
2117
2185
|
argument at a typed call site and says nothing at an untyped one, which is where
|
|
2118
|
-
the mistake actually happens. Nothing can catch it at runtime
|
|
2119
|
-
second argument is exactly what the callback safety above
|
|
2120
|
-
a foreign object's `signal` may execute someone else's
|
|
2121
|
-
simply this — **per-call options only ever go through
|
|
2122
|
-
cancellation that appears to do nothing is the first thing
|
|
2186
|
+
the mistake actually happens. Nothing can catch it at runtime **on the bare
|
|
2187
|
+
callable**: probing its second argument is exactly what the callback safety above
|
|
2188
|
+
forbids, since reading a foreign object's `signal` may execute someone else's
|
|
2189
|
+
getter. So the rule is simply this — **per-call options only ever go through
|
|
2190
|
+
`withOptions`**, and a cancellation that appears to do nothing is the first thing
|
|
2191
|
+
to check.
|
|
2192
|
+
|
|
2193
|
+
`withOptions` itself is guarded, because there the count settles it without
|
|
2194
|
+
reading anything. Its arity depends on the endpoint — one argument when there is
|
|
2195
|
+
no contract input, two when there is — and a call carrying more throws a
|
|
2196
|
+
`TypeError` naming the endpoint and the correct shape. That guard exists because
|
|
2197
|
+
the silent version of this mistake is expensive: the options are dropped, the
|
|
2198
|
+
request goes out uncancelled, the caller still receives `REQUEST_ABORTED`
|
|
2199
|
+
(cancellation is decided from the signal it was handed, not from what the
|
|
2200
|
+
transport did), and the server runs the operation to its own deadline. Every
|
|
2201
|
+
symptom then points at the transport, and the investigation goes there.
|
|
2123
2202
|
|
|
2124
2203
|
```ts
|
|
2125
2204
|
const controller = new AbortController()
|
|
@@ -2139,10 +2218,20 @@ the same client-only errors:
|
|
|
2139
2218
|
|
|
2140
2219
|
| Failure | `ApiError.code` | `status` |
|
|
2141
2220
|
|---------|-----------------|----------|
|
|
2221
|
+
| arguments refused before sending | `VALIDATION_ERROR` | `0` |
|
|
2142
2222
|
| caller `AbortSignal` | `REQUEST_ABORTED` | `0` |
|
|
2143
2223
|
| endpoint/client timeout | `REQUEST_TIMEOUT` | `0` |
|
|
2144
2224
|
| other transport failure | `UNKNOWN_ERROR` | `0` |
|
|
2145
2225
|
|
|
2226
|
+
`status: 0` is what separates a refusal made here from one made by the server:
|
|
2227
|
+
the same `VALIDATION_ERROR` arrives with `400` when the server refused, and
|
|
2228
|
+
`details.issues` is the same `{ path, code, message }` array either way, so one
|
|
2229
|
+
rendering serves both. A refusal raised here is always a **rejection** — on both
|
|
2230
|
+
transports, for every call shape — and it never reaches the server. The client
|
|
2231
|
+
refuses this way for a missing path param, a missing scoped prefix key, a
|
|
2232
|
+
non-flat field in a `GET` input, and a missing or invalid multipart file. → ADR
|
|
2233
|
+
0148.
|
|
2234
|
+
|
|
2146
2235
|
Abort and timeout do not emit `network_error` and are not retried. The same
|
|
2147
2236
|
options work for query, JSON, multipart and raw-response calls. Stitchkit does
|
|
2148
2237
|
not expose upload progress: Fetch has no portable upload-progress primitive.
|
|
@@ -2186,9 +2275,16 @@ const work = createClient(requestWorkContract, {
|
|
|
2186
2275
|
|
|
2187
2276
|
The same adapter accepts unrelated contract shapes without learning their DTOs
|
|
2188
2277
|
or operation inventory. `createClient` chooses method/path from the contract,
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2278
|
+
forwards `.withOptions(..., { signal })` and validates the response through the
|
|
2279
|
+
endpoint's output schema. A caller payload cannot replace the configured base URL
|
|
2280
|
+
or reserved operation path.
|
|
2281
|
+
|
|
2282
|
+
It does **not** filter your arguments down to the declared ones. Keys the contract
|
|
2283
|
+
does not declare are consumed for the path where they belong there and otherwise
|
|
2284
|
+
sent as they are — `api.list({ q: 'hello', note: 'internal' })` puts
|
|
2285
|
+
`?q=hello¬e=internal` on the wire, and the server drops `note` only because its
|
|
2286
|
+
schema is not `.strict()`. Nothing was validated away on this side: pass the
|
|
2287
|
+
object the contract declares, not a wider one it happens to contain.
|
|
2192
2288
|
|
|
2193
2289
|
Contract metadata describes an effect; it does not authorize one. Authentication,
|
|
2194
2290
|
scope and destination policy remain in the application/server boundary. A schema
|
|
@@ -9496,6 +9592,143 @@ makes one thing your job rather than the resolver's:
|
|
|
9496
9592
|
The mechanical part is identical either way. Only the *noticing* differs, and an
|
|
9497
9593
|
exact pin moves it onto you.
|
|
9498
9594
|
|
|
9595
|
+
## Released migration: 0.74.0
|
|
9596
|
+
|
|
9597
|
+
One change, and it only reaches you if you catch a refusal the **client** raised — one it made while
|
|
9598
|
+
planning the request, before anything was sent. A server refusal is unchanged.
|
|
9599
|
+
|
|
9600
|
+
### If you match on the text of a client-side refusal
|
|
9601
|
+
|
|
9602
|
+
A missing path param, a missing scoped prefix key, a non-flat field in a `GET` input, a missing or
|
|
9603
|
+
invalid multipart file: each used to arrive as a plain `Error` carrying only a sentence. They now
|
|
9604
|
+
arrive as an `ApiError` in the same shape a server validation failure uses.
|
|
9605
|
+
|
|
9606
|
+
```ts
|
|
9607
|
+
// before
|
|
9608
|
+
catch (e) {
|
|
9609
|
+
if (/Missing path param/.test(e.message)) …
|
|
9610
|
+
}
|
|
9611
|
+
|
|
9612
|
+
// after
|
|
9613
|
+
catch (e) {
|
|
9614
|
+
if (e.code === 'VALIDATION_ERROR' && e.status === 0) … // refused here, nothing was sent
|
|
9615
|
+
}
|
|
9616
|
+
// e.details.issues[0].path === 'id'
|
|
9617
|
+
```
|
|
9618
|
+
|
|
9619
|
+
`status` is what separates the two worlds, and it is not new — `0` has always meant *this never
|
|
9620
|
+
reached the server*, as `REQUEST_ABORTED` and `REQUEST_TIMEOUT` already used it:
|
|
9621
|
+
|
|
9622
|
+
| | `code` | `status` |
|
|
9623
|
+
|---|---|---|
|
|
9624
|
+
| the client refused your arguments | `VALIDATION_ERROR` | `0` |
|
|
9625
|
+
| the server refused your arguments | `VALIDATION_ERROR` | `400` |
|
|
9626
|
+
|
|
9627
|
+
`details.issues` is the same `{ path, code, message }` array on both, so one rendering serves both —
|
|
9628
|
+
and `zodIssues` / `ZodIssueSummary` are now importable from `stitchkit` itself, not only from
|
|
9629
|
+
`stitchkit/server`.
|
|
9630
|
+
|
|
9631
|
+
### If you are on `createHttpClient` and your call site relied on a synchronous throw
|
|
9632
|
+
|
|
9633
|
+
This is the sharp one, because it is invisible in a diff. Those refusals used to be thrown
|
|
9634
|
+
**synchronously** on the Ky-backed client — before the call returned a promise — so
|
|
9635
|
+
`api.upload({}).catch(handler)` never reached the handler, while the same mistake on the bare-fetch
|
|
9636
|
+
client rejected normally. They now reject on both.
|
|
9637
|
+
|
|
9638
|
+
```ts
|
|
9639
|
+
// before, on createHttpClient only
|
|
9640
|
+
try {
|
|
9641
|
+
api.upload({}) // threw here
|
|
9642
|
+
} catch (e) { … }
|
|
9643
|
+
|
|
9644
|
+
// after, on both transports
|
|
9645
|
+
await api.upload({}).catch(handler)
|
|
9646
|
+
```
|
|
9647
|
+
|
|
9648
|
+
A `try/catch` around an `await`ed call keeps working. A `try/catch` around an un-awaited call no
|
|
9649
|
+
longer catches anything — which was already true on the other transport.
|
|
9650
|
+
|
|
9651
|
+
Not a migration, but worth knowing: a missing multipart file used to be reported as
|
|
9652
|
+
`UNKNOWN_ERROR`, the code that means *this client cannot tell you what happened*, on the one refusal
|
|
9653
|
+
where it is certain nothing was sent. → ADR 0148 carries the reasoning, including why argument
|
|
9654
|
+
validation stays on the server.
|
|
9655
|
+
|
|
9656
|
+
## Released migration: 0.73.0
|
|
9657
|
+
|
|
9658
|
+
Two breaking changes. Nothing you send to a server changed, and only one of these
|
|
9659
|
+
can reach a call site the compiler already checks.
|
|
9660
|
+
|
|
9661
|
+
### If you call `withOptions` from a call site that lost its types
|
|
9662
|
+
|
|
9663
|
+
`withOptions` takes one argument on an endpoint with no contract input, two when
|
|
9664
|
+
there is one. Passing two to a no-input endpoint used to succeed and silently
|
|
9665
|
+
drop the options: the request went out **uncancelled**, the caller still received
|
|
9666
|
+
`REQUEST_ABORTED` — cancellation is decided from the signal it was handed, not
|
|
9667
|
+
from what the transport did — and the server ran the operation to its own
|
|
9668
|
+
deadline. Every symptom then points at the transport, and the investigation goes
|
|
9669
|
+
there. It now throws a `TypeError` naming the endpoint and the correct shape.
|
|
9670
|
+
|
|
9671
|
+
```ts
|
|
9672
|
+
// before — the options were dropped and the request was never cancelled
|
|
9673
|
+
api.ping.withOptions({}, { signal })
|
|
9674
|
+
|
|
9675
|
+
// after
|
|
9676
|
+
api.ping.withOptions({ signal })
|
|
9677
|
+
```
|
|
9678
|
+
|
|
9679
|
+
A typed call site already refused the wrong arity, so this reaches only code that
|
|
9680
|
+
does not have the types: a `Record<string, …>` view of the client, a hand-written
|
|
9681
|
+
double, a dynamic dispatch. The guard counts arguments and never reads them, so a
|
|
9682
|
+
method handed to a callback API behaves exactly as before.
|
|
9683
|
+
|
|
9684
|
+
### If you match on `ApiError.message`
|
|
9685
|
+
|
|
9686
|
+
An `ApiError` that nothing explained used to carry `API Error: ${code}` — a
|
|
9687
|
+
string that reads like an explanation while only restating the code, so a caller
|
|
9688
|
+
could not tell an origin that explained a failure from one that said nothing. It
|
|
9689
|
+
now says which it is.
|
|
9690
|
+
|
|
9691
|
+
```ts
|
|
9692
|
+
// before
|
|
9693
|
+
err.message === 'API Error: INVALID_INPUT'
|
|
9694
|
+
|
|
9695
|
+
// after
|
|
9696
|
+
err.message === 'INVALID_INPUT (no message supplied)' // better: match err.code
|
|
9697
|
+
```
|
|
9698
|
+
|
|
9699
|
+
Match `err.code` instead: it is the contract, and it did not change. An error
|
|
9700
|
+
carrying a real message is untouched. An empty message now counts as no message,
|
|
9701
|
+
for the same reason — an empty string is not an explanation either.
|
|
9702
|
+
|
|
9703
|
+
### If a diagnostic journal lock file is already on disk
|
|
9704
|
+
|
|
9705
|
+
One operator step, and only on a host that has been **renamed** since its lock was written.
|
|
9706
|
+
|
|
9707
|
+
A lock written before this version carries no machine identity, so there is nothing to compare and
|
|
9708
|
+
the host name is all that is left. If the name still matches, the lock reclaims exactly as it always
|
|
9709
|
+
did and there is nothing to do. If the name has changed, the lock is `unattributable` and is refused
|
|
9710
|
+
— the same refusal this release exists to end, except that this particular file predates the fix and
|
|
9711
|
+
cannot be repaired from the inside. Delete it once:
|
|
9712
|
+
|
|
9713
|
+
```sh
|
|
9714
|
+
rm <journal path>.lock # only when the host was renamed since the file was written
|
|
9715
|
+
```
|
|
9716
|
+
|
|
9717
|
+
Locks written from this version on carry the machine identity, so the situation cannot recur. To see
|
|
9718
|
+
which case you are in without guessing, read the refusal instead of the file:
|
|
9719
|
+
`readDiagnosticJournalLockDiagnosis(err)` returns `attribution: 'unattributable'` for exactly this
|
|
9720
|
+
one, and `'another-machine'` for a lock that genuinely belongs elsewhere and must **not** be deleted.
|
|
9721
|
+
|
|
9722
|
+
Two related fixes need no migration, but change what you will see. An error the
|
|
9723
|
+
transport raised through `createHttpClient` now carries the transport's own text
|
|
9724
|
+
in `message` and the original error as `cause`, where before it carried neither
|
|
9725
|
+
and filed the text under `details.message` alone; if you followed the retry rule
|
|
9726
|
+
in [the client guide](./client.md) — inspect the adapter's `cause`, retry only
|
|
9727
|
+
when it proves dispatch did not happen — that rule was not executable on this
|
|
9728
|
+
transport and now is. And the client guide now states which direction validation
|
|
9729
|
+
runs: responses are checked against `output`, arguments are **not** checked
|
|
9730
|
+
before being sent.
|
|
9731
|
+
|
|
9499
9732
|
## Released migration: 0.72.0
|
|
9500
9733
|
|
|
9501
9734
|
Nothing you *pass* changed. Both items are about types you read or build, and
|
|
@@ -12236,6 +12469,9 @@ The browser-and-server entrypoint. Re-exports everything from
|
|
|
12236
12469
|
| `PathPrefixArgs` | _type_ | required string-valued keys exposed to a typed dynamic `pathPrefix` callback |
|
|
12237
12470
|
| `createHttpClient` | function | the Ky-based HTTP transport; on Next.js SSR its first attempt stays request-memoizable while every retry is a distinct transport attempt — [guide](../guide/client.md#createhttpclient) |
|
|
12238
12471
|
| `ApiError` | class | a non-2xx or client failure, with `code` / `status` / `details` / `hint`, optional readonly `traceId` from `x-request-id`, and standard `cause` preserving an injected transport failure |
|
|
12472
|
+
| `zodIssues` | function | a `ZodError` → structured `{ path, code, message }[]` — the exact projection a `VALIDATION_ERROR` carries in `ApiError.details.issues`, so a caller renders one shape. Also on `stitchkit/server`; same name, one definition |
|
|
12473
|
+
| `ZodIssueSummary` | _type_ | one structured validation issue (`{ path, code, message }`) — the element type of `details.issues`. Also on `stitchkit/server` |
|
|
12474
|
+
| `formatZodError` | function | a `ZodError` → a readable, field-summarised string. Also on `stitchkit/server` |
|
|
12239
12475
|
| `HttpClient` | _type_ | the transport interface `createClient` builds on |
|
|
12240
12476
|
| `ConfiguredHttpClient` | _type_ | a framework-created `HttpClient` carrying its readonly `baseUrl` for URL builders |
|
|
12241
12477
|
| `HttpClientConfig` | _type_ | config for `createHttpClient`; retry `limit` counts retries after the initial attempt (default 2 = at most 3 GET attempts), with `statusCodes: []` by default; `fetch` installs an explicit transport and is mutually exclusive with the legacy Bun-only `unix` option — [details](../guide/client.md#createhttpclient) |
|
|
@@ -12760,6 +12996,7 @@ cutovers are covered by the executable
|
|
|
12760
12996
|
| `DiagnosticJournalConfig` / `DiagnosticJournal` | _type_ | owner schema/path/limits/failure observer and the synchronous `submit`, bounded-wait `flush`/`close`, status handle |
|
|
12761
12997
|
| `DiagnosticJournalLimitsSchema` / `DiagnosticJournalLimits` | schema / _type_ | positive event, pending-item, pending-byte, file-byte and retained-file limits |
|
|
12762
12998
|
| `DiagnosticJournalLockPolicySchema` / `DiagnosticJournalLockPolicy` | schema / _type_ | `refuse` (default) or `reclaim-stale`, which reclaims only a lock whose recorded owner is provably gone |
|
|
12999
|
+
| `readDiagnosticJournalLockDiagnosis` / `DiagnosticJournalLockDiagnosis` | function / _type_ | why a `reclaim-stale` acquisition refused — owner alive, another machine, or a lock this host cannot attribute — read off the thrown `EEXIST` |
|
|
12763
13000
|
| `DiagnosticJournalSubmitResultSchema` / `DiagnosticJournalSubmitResult` | schema / _type_ | accepted epoch/sequence or explicit invalid, oversized, capacity, closed or failed refusal |
|
|
12764
13001
|
| `DiagnosticJournalStatusSchema` / `DiagnosticJournalStatus` | schema / _type_ | state, limits, exact admission/write/failure counters, pending ownership, rotations, partial tails and last safe sequences |
|
|
12765
13002
|
| `DiagnosticJournalFrameSchema` / `DiagnosticJournalFrame` | schema / _type_ | version-1 JSONL frame carrying process epoch, contiguous accepted sequence and schema-validated JSON event |
|
package/package.json
CHANGED