Uh oh!
There was an error while loading. Please reload this page.
feat(api): add the Folio client, its models and its environment - #6
Merged
Conversation
Types and Zod schemas are generated from the contract Folio publishes, so the shapes cannot be hand-maintained into disagreeing with it. Model types are inferred from the schemas that parse the responses, leaving one definition rather than a type and a validator that can drift apart. Reads go through the server only. The client takes its base URL and fetch, holding no reference to the environment, so it is exercised without one. Every response is parsed at the boundary, which is where a deployment that disagrees with the published contract becomes a named error instead of an undefined three components deep. Failures are reported, not decided: a category and the API's own problem details, leaving the route to choose between a 404, a retry and an error.
Uh oh!
There was an error while loading. Please reload this page.
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 freeto 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.
The data layer the site reads Folio through: generated types and schemas, a client, an error taxonomy, and one environment variable. Nothing renders yet — no routes, no components.
Shape
pnpm api:generateregenerates fromhttps://raw.githubusercontent.com/CodeByDylan/Folio/main/docs/openapi.json. Generation is a deliberate act whose output is committed, so the build never reaches the network and a contract change arrives as a reviewable diff.Decisions
Model types are inferred from the schemas that parse the responses, not from the parallel generated types.
Siteisz.infer<typeof zGetSiteResponse>. One definition, so a validator and a type cannot drift apart.Reads happen on the server only. Server functions wrap the client, so the API origin never enters the browser bundle, CORS is never involved, and parsing costs nothing in shipped bytes.
env.tscarries theserver-onlymarker, making a leak a build error rather than a runtime one.The client holds no reference to the environment. It takes
baseUrlandfetch, which is what allowed it to be exercised against a live Folio with nothing configured. Composition lives inserver.ts.Every response is parsed at the boundary. Generated types describe the contract Folio publishes; the running service is a separate artifact that can disagree with it. Parsing is what turns that disagreement into a named error instead of an
undefinedthree components deep.Failures are reported, not decided.
FolioErrorcarries a category —invalid,unauthorized,not-found,unavailable,transport,contract— and the API's own problem details. Nothing maps 400 onto a 404; that is route policy, mirroring Folio's own division between stating facts and setting policy.Slug format is not re-validated here. Folio already rejects a malformed slug with a message, and duplicating the rule would give it two homes.
Verified against a running Folio
diagnostics()site()before the first buildunavailable(503), "The portfolio has not been built yet."diagnostics({severity: 'nope'})invalid(400), "'nope' is not a severity."transport/a~1b/c~0dper RFC 6901That exercise found two real bugs, both since fixed: a nullable-reference bug in Folio's own schema transformer (CodeByDylan/Folio#41), and an over-strict datetime in the generated Zod — Folio emits
+00:00, whichformat: date-timepermits, sodates: { offset: true }is set on the generator.Known limitation
getDiagnosticsthrows acontracterror against a live API until CodeByDylan/Folio#41 merges. The committed output is faithful to whatmainpublishes today, which still marks two omitted properties as required. Runpnpm api:generateafter that merge; the diff is two properties. The three content endpoints are unaffected.Checks
pnpm check,pnpm typecheckandpnpm buildpass. Generated output is excluded from Biome, asrouteTree.gen.tsalready is.