Skip to content

v4.10.0

Choose a tag to compare

@58bits 58bits released this 28 Jul 03:57

Highlights

  • @byline/clibyline init and byline setup now install onto MySQL or PostgreSQL. Choose interactively, or pass --database mysql / --database postgres for a non-interactive run. The selected adapter drives every downstream decision: which @byline/db-* and @byline/search-* packages are installed, which connection environment key is written (BYLINE_DB_MYSQL_CONNECTION_STRING or BYLINE_DB_POSTGRES_CONNECTION_STRING), which byline/server.config.ts is scaffolded, how the database and application role are provisioned, and which bundled schema baseline is applied.

    The choice is persisted in .byline-install.json and is sticky. Re-running the installer against an existing installation will not reinterpret it as the other adapter — changing database engines is a data migration, not an installer re-run, and the CLI says so rather than guessing. Installations created by earlier CLI releases are recognised as PostgreSQL automatically; a genuinely fresh state still prompts.

  • @byline/db-mysqlMySQL is now generally available. The "preliminary" qualifier introduced in 4.8.0 is removed. The storage adapter already passed the full @byline/db-conformance suite in 4.8.0 and search landed in 4.9.0; what remained was tooling, and this release supplies it. #58 is closed. MySQL 8.0.14 remains the engine floor (LATERAL joins and subqueries in a view's FROM), and MariaDB remains unsupported — the CLI now rejects both cases before provisioning anything, with the same message the adapter's boot check emits.

  • @byline/cli — a central database-adapter registry is now the single extension point for supporting another engine. Package names, admin subpath, search package, connection environment key, URL codec, default administrator database, provisioning prerequisites, and baseline kind all live in one place, with a companion provisioner registry holding the behaviour behind a DbProvisioner seam. Dependency selection, environment generation, template layering, and provisioning are all derived from those two registries rather than from engine-specific conditionals scattered across the phases. The search package is optional metadata, and the baseline kind is declared rather than assumed, so a future adapter with no search provider or no SQL baseline fits without reshaping the seam.

  • @byline/cli — scaffolding merges four template layers (byline/dialects/<adapter>/byline/byline-examples/dialects/<adapter>/byline-examples/), so common application files stay single-sourced while the database-specific server config remains explicit, readable TypeScript rather than token substitution. Example scaffolds wire the matching search provider — mysqlSearch with @byline/search-mysql, or postgresSearch with @byline/search-postgres — and apply its migration at startup, logging loudly on failure without taking the application down. Minimal scaffolds install neither. The two PostgreSQL-only maintenance scripts are confined to the PostgreSQL overlay, because the methods they call are deliberately absent from MySqlAdapter and copying them would produce a scaffold that does not compile.

Bug Fixes

  • @byline/clithe installer no longer mutates an occupied database. This affects existing PostgreSQL users, not only new MySQL ones. Previously, byline setup --force would create or alter the application role, install pgcrypto, grant privileges, and only then hand off to Drizzle — so a database that already held content was modified before anything checked whether applying a fresh baseline was safe at all.

    The target is now inspected and classified before any credentials are resolved and before any mutation. A database containing byline_* objects is refused with a release-tagged link to the matching packages/db-<adapter>/sql/README.md; a database containing unrelated tables or views is refused with a recommendation to choose a different, empty database. Neither refusal is weakened by --force, which affects phase detection only. --reset --i-mean-it remains the one explicit destructive path, and it deliberately skips inspection — documented as such in both the guide and the refusal messaging.

  • @byline/cli — the administrator connection URL must now address the same host and port as the recorded application connection. Where these diverged, the schema was created on one server while the generated .env.local pointed at another, producing an installation that appeared to succeed and was silently unreachable. The mismatch is now refused before inspection with both endpoints printed.

  • @byline/cli — the setup --force preamble no longer claims that database migrations re-apply as no-ops. They do not, and under the squashed-baseline model they never could. It now states that a forced database phase still refuses every occupied database.

Chores

  • monoreposcripts/check-native-sql-history.mjs enforces that hand-written upgrade scripts are immutable after release. It compares every numbered packages/db-*/sql/*.sql file against a base tag and fails if one was edited or deleted, while allowing new numbered scripts. It globs the adapter directory rather than naming engines, so a future adapter inherits the guard.

  • monorepo — the release procedure in all three maintained instruction surfaces now runs the baseline sync, a source-versus-bundle drift contract, and the SQL-history guard before versioning, build, or publication, and stops if any fails.

  • @byline/cli — CI gained live installation smoke coverage for both engines inside the existing test job, reusing the already-running PostgreSQL and MySQL services with no new job or matrix: fresh provision and baseline, Byline-schema refusal, and unrelated-occupied refusal, including an assertion that pgcrypto was not installed in the refused PostgreSQL target. A packed-tarball check asserts both bundled baselines ship and that no Drizzle snapshots do, and a compile-only pass covers the scaffolded server configs, which sit outside the CLI's normal tsconfig.

Migrations

  • @byline/cli@byline/db-postgres and @byline/db-mysql are now pinned exactly to the CLI release that carries their schema baseline, rather than to a compatible range. A caret or tilde range is no longer accepted as equivalent, because a baseline and an adapter that disagree about the schema is precisely the failure this release exists to prevent.

    Required action: none at runtime. Existing applications keep working. The next time you run byline setup or byline init, a pre-existing ^4.x range on your database adapter will be reported as an upgrade candidate; pin it to the CLI's version. Workspace links are preserved, but the locally resolved version must match exactly.

  • monorepo — this release documents the two-stream migration model explicitly, and it is worth reading if you operate an existing installation. Each release squashes its Drizzle history into a single fresh-install baseline bundled with the CLI; that baseline creates the target schema from scratch and is not an upgrade history. Existing installations are advanced with the numbered native SQL in packages/db-<adapter>/sql/ at the Git tag of the release you are upgrading to — never by re-applying the baseline. Search is deliberately different: each search package owns its own disposable projection and migration stream, which is why @byline/search-* exposes migrate() and @byline/db-* does not.

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