release(v4.0.2): consumer-strict reader-shape fixes
Some checks failed
Test / test (push) Has been cancelled
Docker build and publish / docker (push) Has been cancelled
Publish / publish (push) Has been cancelled

4.0.1's typecheck gate compiled each package internally against
lib: ["ES2022"]. That doesn't catch types that only fail when
*consumer* code (lib: ["DOM"] + exactOptionalPropertyTypes) tries to
assign a native browser type into one of our locally-defined narrower
types. Dispatch hit one such case in @shade/files inline-threshold.ts.

This release adds a tests/consumer-strict/ smoke project to the
pre-publish gate. It compiles a tiny "as if I were a downstream app"
TS file against:

  lib: ["ES2022", "DOM", "DOM.Iterable"]
  types: ["bun-types"]
  exactOptionalPropertyTypes: true
  strict: true
  paths → packages/*/src/index.ts

scripts/typecheck-all.ts now runs the smoke after per-package checks.
Both must pass before publish:dry / publish:all proceeds.

### Fixed
- @shade/files inline-threshold.ts: MinimalReader<T> rewritten as the
  explicit disjoint union { done:false, value:T } | { done:true,
  value?: T | undefined } that's assignable from every native reader
  shape (bun, DOM, node:stream/web). Fixes the
  "ReadableStreamReadResult is not assignable" Dispatch reported.
- @shade/files streams-bridge (client + server): stash setTimeout
  return in a local before .unref?.() via { unref?: () => void } cast.
  Fluent .unref?.() failed under lib: ["DOM"] (setTimeout returns
  number there).
- @shade/sdk background.ts: same setInterval .unref?.() fix.

Wire-compatible. No API shape changed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-03 19:51:46 +02:00
parent 70e319fef8
commit 0bdf9e859c
34 changed files with 317 additions and 32 deletions

View File

@@ -5,6 +5,58 @@ All notable changes to Shade are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [4.0.2] — 2026-05-03 — Consumer-strict reader-shape fixes
`4.0.1` shipped the `tsc --noEmit` gate that compiles each package
internally against `lib: ["ES2022"]`. That gate did not catch types
that only fail when *consumer* code (running with `lib: ["DOM"]` +
`exactOptionalPropertyTypes`) tries to assign a native browser type
into one of our locally-defined narrower types.
This release adds a consumer-strict smoke test to the pre-publish
gate and fixes every collision that smoke uncovered.
### Fixed
#### `@shade/files`
- `inline-threshold.ts`: rewrote the local `MinimalReader<T>` interface
as an explicit disjoint union (`{ done: false; value: T } | { done:
true; value?: T | undefined }`) so it accepts every native reader
shape — `bun-types` (`value?: undefined`), `lib.dom` (`value?: T`),
and `node:stream/web`. The previous flat shape was rejected by
consumer projects with `exactOptionalPropertyTypes: true` because
the present-branch required `value: T`. **Fixes "Type
ReadableStreamReadResult<Uint8Array> is not assignable to
{ value: Uint8Array | undefined; done: boolean }".**
- `client/streams-bridge.ts`, `server/streams-bridge.ts`: stash the
`setTimeout(...)` return value in a local before calling `.unref?.()`
through an explicit `{ unref?: () => void }` cast. The previous
fluent `.unref?.()` failed under `lib: ["DOM"]` because DOM types
`setTimeout` to `number`, which has no `.unref` even as an optional
property.
#### `@shade/sdk`
- `background.ts`: same `setTimeout` / `setInterval` `.unref?.()` fix.
### Tooling
- New `tests/consumer-strict/` — a tiny "as if I were a downstream app"
TypeScript project with its own `tsconfig.json`:
`lib: ["ES2022", "DOM", "DOM.Iterable"]`, `types: ["bun-types"]`,
`exactOptionalPropertyTypes: true`, `strict: true`,
`paths`-mapped to the workspace's `packages/*/src/index.ts`.
Three smoke files exercise `@shade/files`, `@shade/sdk`, and
`@shade/key-transparency` against the consumer-strict tsconfig.
- `scripts/typecheck-all.ts` now runs the consumer-strict smoke after
the per-package internal type-check. Both must pass before
`prepublish:check` (and therefore `publish:dry` / `publish:all`)
succeeds.
### Migration
`4.0.1 → 4.0.2` is wire-compatible and source-compatible. No API shape
changed; only internal typing was tightened.
## [4.0.1] — 2026-05-03 — Strict-TS publishability fixes
`4.0.0` shipped TypeScript source files as the published `main` /