Skip to content

release: v2.3.0 - #57

Open
MrRefactoring wants to merge 6 commits into
masterfrom
release/v2.3.0
Open

MrRefactoring wants to merge 6 commits into
masterfrom
release/v2.3.0

Conversation

@MrRefactoring

@MrRefactoring MrRefactoring commented Sep 10, 2026 •

Copy link
Copy Markdown
Owner

Cuts v2.3.0.

What ships

Action is a union discriminated on type. Twenty-nine action types carry their own data shape, so action.data.text on a commentCard is a string and reading a field that type does not have is a compile error rather than undefined at runtime. This is a compile break in a minor release; ActionUnknown is exported as an escape hatch. The CHANGELOG opens with it.

fields on six endpoints asked for a whole object. getBoardActions, getCardActions, getListActions, getMemberActions and getOrganizationActions typed it as Action; getBoardLabels typed it as Label. Trello's spec points those parameters at the object schema instead of at the matching ActionFields and LabelFields enums. All six now take the shape the other thirty-five fields parameters already had: string | string[], widened with the documented names so autocomplete offers them.

The published API reference builds again. It did not before: every parameter and model type was expanded inline on the endpoint pages, docs/api reached 22 MB with no links in it, and VitePress ran out of an 8 GB heap after roughly fifteen minutes.

Why the docs needed a patch

type X = z.infer<typeof XSchema> resolves through a conditional type. TypeScript keeps no aliasSymbol on the result, so checker.typeToTypeNode serializes the structure instead of the name, and typedoc inlines it. Declaration emit does not have this problem, in TypeScript 6.0.3 or 7.0.2; only typeToTypeNode loses the alias.

typedoc already holds the annotation the author wrote, in maybeNode, and uses it only for mapped types. patches/typedoc@0.28.20.patch reads it and converts it as a reference. typedoc-plugin-zod then fills the pages those references point at with the fields and JSDoc the schemas carry.

The patch is not upstreamable as written: it breaks typedoc's handling of the @inline tag, transient symbols and default exports, none of which this project uses. An issue with a zod-free reproduction goes upstream separately. Scope of the patch here is the docs build; it is a devDependencies patch and reaches nothing that is published to npm.

Measured

before after
docs/api 22 MB 9.0 MB
docs:build out of memory at 8 GB passes, peak 2.4 GB

pnpm run build, pnpm run lint and pnpm vitest run (181 tests) are green.

Not in this release

feat/schema-mismatch and its breaking changes, the 3.0.0 number, and the migration page.

What the review changed

Four findings came out of the review of this branch; all four are in.

Open enums lost their own suggestions. Eighty parameter schemas and one model carried a plain z.string() next to the openEnum in the same union. It accepted nothing the open enum did not already accept, and in the type a bare string swallowed the literal names beside it — so fields: '…', filter: '…' and pos: '…' offered nothing, and only the array form still suggested anything. Fixed at the source and resynced; nothing that compiled before stops compiling.

One consequence worth naming: with the z.string() branch gone, TokenPermission.idModel is a closed z.enum(['*']) under TRELLO_STRICT_SCHEMAS. Normal mode is unchanged and consumers are unaffected — but the audit run will now speak up if a token carries a concrete id, which is what the audit is for.

The docs patch was one pnpm update from falling off. patches/typedoc@0.28.20.patch is keyed to that exact version while the manifest allowed any 0.28.x; typedoc is pinned now. The Docs workflow also watches patches/ and pnpm-workspace.yaml, so a reissued patch rebuilds the reference rather than leaving Pages on whatever last touched src/.

The comma join was untested. An array in searchParams reaches the wire as one comma-separated value through String(value) — the form this release newly advertises for six endpoints — and nothing held it in place. Two tests in buildUrl.test.ts do.

Still open, deliberately: docs:build runs only on push to master, so the reference build is not gated on a PR. It builds locally after these changes — docs/api at 9.0 MB — but adding a PR gate is a separate decision about CI time.

The changelog section is renamed from `Unreleased`, which is what the release
workflow greps for, and opens with the one warning a consumer needs: `Action`
branches on `type` now, so reading `action.data.<field>` without narrowing
first stops compiling.

That is a compile break in a minor release, so the lede names it rather than
leaving it to be found in a bullet, and it names the escape hatch too:
`ActionUnknown` is exported, and casting to it reads `data` as `any` again. It
hands back exactly the blindness this release removes, which is why it reads as
a bookmark rather than a fix.

The sections are reordered so `Changed` comes first. Nothing else in the
release competes with the breaking change for attention.
getBoardActions, getCardActions, getListActions, getMemberActions and
getOrganizationActions typed `fields` as an `Action`; getBoardLabels
typed it as a `Label`. Trello's spec points those parameters at the
object schema instead of at the matching ActionFields and LabelFields
enums, so the client asked for a request the API could never answer.

All six now take the shape the other thirty-five fields parameters
already had: `string | string[]`, widened with the documented names so
autocomplete offers them, so `fields: 'id,name'` and
`fields: ['id', 'name']` both work.
The endpoint pages expanded every parameter and model type in place, so
docs/api reached 22 MB with no links in it and VitePress ran out of an
8 GB heap before the build finished.

typedoc keeps no aliasSymbol on a type that resolves through a
conditional type, which is what `z.infer<typeof Schema>` is, so
checker.typeToTypeNode serialized the structure instead of the name it
was written under. The patch reads the annotation the author actually
wrote, which typedoc already holds in maybeNode, and converts that as a
reference. typedoc-plugin-zod then fills the pages those references
point at.

docs/api is 9.0 MB with no warnings, and the build peaks at 2.4 GB.
Eighty parameter schemas and one model paired an openEnum with a plain
z.string() branch in the same union. The branch accepted nothing the open
enum did not already accept, and in the type a bare string swallowed the
literal names beside it, so an editor offered nothing for fields: '…',
filter: '…' or pos: '…' — only the array form still suggested anything.

Any string is still accepted, and nothing that compiled before stops
compiling.
patches/typedoc@0.28.20.patch is keyed to that exact version, while the
manifest allowed any 0.28.x. The next pnpm update would have resolved past
it, dropped the patch, and taken docs/api back to 22 MB and an out-of-memory
build — the thing the patch is there to prevent.

The Docs workflow now also watches patches/ and pnpm-workspace.yaml, so a
reissued patch rebuilds the reference instead of leaving Pages on the last
build that happened to touch src/.
An array in searchParams reaches the wire as one comma-separated value
through String(value), and nothing held that in place. Swapping set for a
per-element append — the usual way arrays get "fixed" in a query builder —
would send ?fields=id&fields=name, Trello would read the last one, and no
test would have noticed.

This branch had an error being deployed

1 failed (outdated) deployment
github-pages — 8d1c7f1b Deployed Sep 10, 2026 by MrRefactoring via deploy #22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant