refactor(ts): migrate deserializer to TypeScript with typed distribution - #202
Open
tvdeyen wants to merge 3 commits into
Open
refactor(ts): migrate deserializer to TypeScript with typed distribution#202tvdeyen wants to merge 3 commits into
tvdeyen wants to merge 3 commits into
Conversation
tvdeyen
force-pushed
the
typescript-pipeline
branch
2 times, most recently
from
August 21, 2026 09:02
48332cf to
69e83bb
Compare
Convert the deserializer, alchemyApiDeserializer and barrel to TypeScript and add a declaration pipeline so consumers get types. The build now runs vite for the JS bundles plus `tsc --emitDeclarationOnly` for the .d.ts files, and package exports expose types for both the root entry and the ./deserialize subpath. The JSON:API document shapes stay internal (not exported): the public entry point takes `unknown`, so exporting them would only add generically-named types that could collide in consuming apps. Specs move to .ts; the single non-redundant case from deserialize.spec.js is folded into deserialize.spec.ts so no coverage is lost.
tvdeyen
force-pushed
the
typescript-pipeline
branch
from
August 21, 2026 09:07
69e83bb to
09cae85
Compare
deserialize re-expanded every reference path, so a resource reachable via
many paths was rebuilt at each one. On densely cross-linked documents — e.g.
a navigation menu whose nodes link parent <-> children — this grew super-
linearly: a 0.57 MB payload produced a 12 MB graph in ~60 ms.
Resolve each resource once and share it by reference, stubbing only true
cycles (a reference to a resource still being resolved). The graph stays
acyclic and every resource is still fully present; the same payload now
yields 0.80 MB in ~3 ms. `{ expand: true }` keeps the previous per-path
full expansion for callers that need a fully-expanded object at every path.
Update the frontend usage to deserialize (deserializePage/Pages are now
deprecated aliases) and explain how references resolve: relationships
become nested objects or { id } stubs, the graph is acyclic by
construction via grey/black DFS marking, and { expand: true } opts into
full per-path expansion.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Migrates the deserializer to TypeScript and ships type declarations so consumers get types and editor support (including the
@deprecatedhints ondeserializePage/deserializePagesadded in #201).Source —
deserialize,alchemyApiDeserializerand the barrel become.ts. Behaviour is unchanged; the existing specs (migrated to.ts) still pass, and the folded numeric-id/absent-to-many case keeps the coverage the olddeserialize.spec.jshad.Distribution pipeline —
buildnow runsvite buildfor the JS bundles plustsc --emitDeclarationOnlyfor the.d.ts. Atsconfig.json(strict,lib: ["ES2022","DOM"]forstructuredClone) drives declaration emit and a newtypecheckscript.package.jsongains atypesfield and anexportsmap exposing types for both the root entry and the./deserializesubpath.Public type surface — the JSON:API document shapes are kept internal (not exported).
deserializeis<T = unknown>(document: unknown): T, so those shapes aren't part of the contract; exporting them would only add generically-named types (JsonApiResource,JsonApiDocument, …) that could collide with a consumer's own definitions. The emitteddeserialize.d.tstherefore exposes onlydeserialize.Based on
main(after #200 and #201).