Skip to content

v4.1.0

Choose a tag to compare

@58bits 58bits released this 16 Jul 04:25

Byline 4.1 is a developer-experience release focused on how applications consume Byline's typed surface. The app-local plumbing that every project previously carried — a clients.server.ts type-assertion shim and path-based imports into the generated types file — is replaced by two package imports: request-bound client getters from @byline/client/server and collection types from the new @byline/generated-types declaration-merge target. Under the hood, the entire server-side client stack moved out of the TanStack Start adapter and into the framework-neutral client SDK, behind a new three-function HostRequestBridge seam — so application read/write modules no longer import the host framework at all.

📖 Migration guide: Upgrading from 3.21 to 4.x now lands 3.21 applications directly on the 4.1 import surface (steps 5–6). Apps already on 4.0 need only the short list under Migrations below.

Highlights

  • @byline/client — a new server-only subpath, @byline/client/server, exports the four request-authority client singletons (getAdminBylineClient, getPublicBylineClient, getSystemBylineClient, getViewerBylineClient) plus isPreviewActive and getAdminRequestContext. In an app whose generated types are registered (see below), every getter returns a fully typed BylineClientclient.collection('news') autocompletes collection paths and returns the generated field shapes with no explicit generics and no type assertions. The subpath ships a browser export condition that resolves to a throwing stub, so an accidental import from client-side code fails loudly at bundle time instead of leaking session machinery to the browser.

  • @byline/client — the SDK now exposes a Register interface (the TanStack Router / Payload declaration-merge pattern). The app's generated types register their CollectionFieldsByPath on it, after which every bare BylineClient in the app's program — including createBylineClient without an explicit generic — resolves to the app's typed registry. Unaugmented programs fall back to the loose CollectionRegistry, so packages, scripts, and tests compiled outside the app keep working unchanged.

  • @byline/generated-types — a new, deliberately empty package that acts as the declaration-merge target for each application's generated collection types. Apps import their own schema-derived types by package name — import type { NewsFields } from '@byline/generated-types' — from anywhere in the program. Imports are type-only and erased at runtime; the app's tsconfig include carrying the generated file is what populates the module. Exactly one application per TypeScript program can augment it (one app per tsconfig — the supported layout — is safe).

  • @byline/core / @byline/host-tanstack-start — everything request-scoped in the server client stack (per-request memoization, session cookies with the transparent refresh dance, preview cookies) now bottoms out in a new HostRequestBridge seam in core: three functions — request identity, cookie read, cookie write — that a host adapter implements and registers at server boot (registerTanstackStartHostBridge() from @byline/host-tanstack-start/integrations/host-bridge). The whole client/preview/session stack is implemented once against the bridge in @byline/client/server, which is what makes a future non-TanStack host adapter cheap: implement three functions and the entire stack comes for free. The host adapter shrank accordingly to bridge + server fns + route factories + admin shell.

  • @byline/core — the codegen emitter moved to format 2: every generated type is declared inside the @byline/generated-types augmentation block (making the package the single canonical import path), and a second block registers the collection registry with @byline/client's Register interface via import('@byline/generated-types').CollectionFieldsByPath.

Chores

  • @byline/cli — templates (minimal and examples sets) migrated to the new import surface, template generated types regenerated to format 2, and @byline/generated-types added to the installer's dependency manifest. Template scripts dropped their explicit createBylineClient generics — the Register merge covers them.
  • @byline/cli — repaired a latent CI failure: a workspace-link test fixture pinned @byline/core at a literal 3.21.4, which the version-derived release policy (correctly) rejected once 4.0 shipped; the fixture now tracks CLI_PACKAGE_VERSION so it can never drift again. The ts-morph-heavy template-contract and scaffold suites also gained CI-runner timeout headroom.
  • @byline/host-tanstack-start — dropped the now-unused uuid dependency (its only consumer moved to @byline/client).
  • monorepo — the webapp's regenerate-media script was refactored into a tested, status-preserving operation module (also mirrored into the CLI's example templates).

Migrations

  • monorepo — to adopt the new surface in an existing 4.0 app: add @byline/generated-types to dependencies; regenerate collection types (pnpm byline:generate — output moves to format 2); respell ~/clients.server imports to @byline/client/server and ~/generated/collection-types.js imports to @byline/generated-types; add registerTanstackStartHostBridge() to byline/server.config.ts before initBylineCore(); then delete byline/clients.server.ts. Regeneration is the opt-in moment — an un-regenerated 4.0 app compiles and runs unchanged against 4.1 packages except for the removed host modules listed under Breaking Changes.

Breaking Changes

  • @byline/host-tanstack-start — the modules that moved to @byline/client/server were removed without a deprecation cycle (coordinated with all known 4.0 consumers): the ./auth/* subpath (auth-context, auth-cookies, preview-cookies, request-scope) and the integrations/byline-client, integrations/byline-public-client, and integrations/byline-viewer-client modules. Required action: import the same symbols from @byline/client/server — every export kept its name and behaviour.

All other @byline/* packages bumped to 4.1.0 in lockstep with no behavioural changes this cycle.