Skip to content

v4.8.0

Choose a tag to compare

@58bits 58bits released this 25 Jul 15:13

Highlights

  • @byline/db-mysql — Byline's second database adapter, published for the first time in this release. mysqlAdapter() implements the same IDbAdapter contract as @byline/db-postgres over MySQL 8.0.14+ (InnoDB only), and the subpath @byline/db-mysql/admin ships the MySQL-backed admin-store repositories that plug into @byline/admin. Document storage, versioning, patches, workflow, populate, and admin auth behave identically regardless of which database backs an installation, because both adapters pass the same shared behavioural suite — 14 suites, 141 tests, run against each adapter's own test database. Continuous integration runs the MySQL suite against a pinned mysql:8.0 service so the engine floor is genuinely exercised rather than assumed.

    This adapter is published as preliminary, not as fully supported MySQL support. The storage layer is complete and proven; the ecosystem around it is not. Most importantly there is no MySQL search provider, and this fails at boot rather than degrading quietly: initBylineCore() throws when a collection declares a search block with no provider registered, and Byline's own reference application opts five collections into search. A MySQL installation needs the no-op provider documented in the adapter README. byline init also scaffolds Postgres only. The criteria for general availability are tracked in #58. Choose MySQL for evaluation, prototypes, or installations that do not need search; choose Postgres for everything else.

    8.0.14 is not an arbitrary floor. It is the first MySQL release supporting both LEFT JOIN LATERAL (used by the field-level sort path in findDocuments) and subqueries in a view's FROM clause — which both current-version views require, since each resolves the current version per document via a ROW_NUMBER() OVER (PARTITION BY document_id) window inside a derived table. The adapter refuses to start on an older server, and rejects MariaDB by name.

  • @byline/coreIDbAdapter gained an optional classifyError seam, so core maps database failures to domain errors without inspecting driver-specific error anatomy. rethrowPathConflict now delegates to it. This is the error-side analogue of the storage normalizeRow seam, and it is what let a second adapter surface path conflicts correctly without core learning MySQL's error shapes.

Bug Fixes

  • @byline/db-postgresdate, time and datetime field values were arriving from the ordinary read path as raw driver strings rather than parsed values. Two mechanisms compounded: the store manifest's null cast collapses absent temporal columns to a TZ-less timestamp so the seven-way UNION ALL type-aligns, and drizzle's node-postgres session installs a type-parser override returning the identity function for DATE / TIMESTAMP / TIMESTAMPTZ. The adapter now coerces both temporal columns, and every coercion on both adapters throws on unparseable input instead of putting a silent Invalid Date into ClientDocument.fields. See Breaking Changes below for the consumer-visible effect.

  • @byline/db-postgresdb_init.sh now percent-decodes the user and password in BYLINE_DB_POSTGRES_CONNECTION_STRING, matching what node-postgres itself does when it parses the same string. A password written pa%40ss previously created the database role with the literal pa%40ss while the adapter connected as pa@ss — an access-denied failure with nothing pointing at the cause. The script now also rejects a malformed percent-escape with a clear message rather than passing it through. This is stricter than before: a connection string whose password contains a raw, unencoded % (which RFC 3986 requires be written %25) is now refused by db_init.sh, where node-postgres was already failing on the same input.

  • @byline/db-postgrestransactionDb is now a required parameter on the storage query builders. It previously defaulted to a manager handing back the raw connection pool, so omitting it silently caused getDocumentSystemFieldsForUpdate's SELECT … FOR UPDATE to take its lock on a pool connection outside the caller's transaction — serialising nothing, with no error and no failing test. Miswiring is now a compile error.

Chores

  • monoreponpm-run-all moved from production dependencies to devDependencies across every publishable package. It is used only by each package's dev script, so consumers were installing an unmaintained tool and its dependency tree at runtime for nothing. Consumers of any @byline/* package get a smaller runtime install footprint with no behavioural change.

  • monorepo — continuous integration gained a mysql:8.0 service container alongside Postgres, pinned to the engine floor so the oldest supported server is what gets tested rather than a version comfortably above it.

Breaking Changes

  • @byline/db-postgresbreaking: date and datetime field values now arrive as Date objects rather than raw driver strings. date values anchor to UTC midnight for their calendar day; datetime values carry the full instant; time values are unchanged and remain a string.

    Required action: check any code that reads a date or datetime field value and either calls a string method on it (.slice(), .split(), .substring(), a regex) or hands it to a date-parsing library that expects a string (parseISO, strict dayjs). Such code now receives a Date and must use Date methods, or call .toISOString() itself. Code that wraps the value in new Date(...) before formatting, or that already accepts string | Date, needs no change. Note also that serialised payload shape changes: JSON.stringify of a Date emits 2026-03-10T00:00:00.000Z where the raw driver string was 2026-03-10 00:00:00.123456+00.

    Why this is a minor rather than a major release: these values were previously undocumented raw driver output, and packages/core/src/storage/storage-row-types.ts already typed both columns as Date | string — so code written to handle either shape is unaffected. Every publishable @byline/* package is versioned in one lockstep group, and this correction does not warrant taking all sixteen packages to 5.0.0.

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