The MySQL and MariaDB backend of AntelopeJS. It runs the database interface's queries on MySQL or MariaDB with native column types and indexes, and serves existing tables.
The MySQL and MariaDB backend of AntelopeJS. It runs the queries of the database interface on MySQL or MariaDB with the mysql2 driver, and maps schema definitions onto relational tables with native column types and indexes. It can also serve tables that already exist in a database it does not own.
| Interface | Documentation |
|---|---|
@antelopejs/interface-database |
Database |
@antelopejs/interface-database-catalog |
The catalog |
The database interface pages document schemas, tables, queries, change feeds and atomic mutations. The catalog answers on an external instance only.
This package requires Node.js >=22.
The module supports MySQL 8.4 LTS, MySQL 9.7 LTS, MariaDB 11.8 LTS and MariaDB 12.3 LTS, and pnpm test runs every suite on all four. It reads the server's version when it connects and picks the MySQL or the MariaDB dialect. MariaDB lists every behaviour that differs between the two.
ajs project modules add @antelopejs/mysqlThe command writes the module's default configuration, the URL mysql://root@localhost:3306/antelopejs with migrations: "safe".
The account in the URL needs CREATE, ALTER, INDEX, TRIGGER, LOCK TABLES, SELECT, INSERT, UPDATE and DELETE on that one database. The module creates no database of its own.
The first changes() on a table creates triggers on it. With binary logging on, which is MySQL's default, the server refuses CREATE TRIGGER (errno 1419) unless the account holds SUPER or the server runs with log_bin_trust_function_creators = 1. Before you open a change feed, either GRANT SUPER ON *.* TO the account, or run SET GLOBAL log_bin_trust_function_creators = 1 and put it in the server's configuration file. SYSTEM_VARIABLES_ADMIN and SET_ANY_DEFINER do not replace SUPER for a trigger, on 8.4 or 9.7. Without either, the feed fails with an error that names both remedies. See Change feeds.
import { defineConfig } from "@antelopejs/interface-core/config";
export default defineConfig({
name: "my-project",
modules: {
mysql: {
source: {
type: "package",
package: "@antelopejs/mysql",
version: "latest",
},
config: {
url: "mysql://app@localhost:3306/my_project",
migrations: "safe",
pool: { connectionLimit: 10 },
},
},
},
envOverrides: {
MYSQL_URL: "modules.mysql.config.url",
},
});| Key | Description |
|---|---|
mode |
"owned" (default) creates and converges the tables. "external" serves existing tables without changing them. |
url |
MySQL connection string. Its database holds every table the module owns. |
migrations |
"safe" (default) adds columns and indexes, and also drops or swaps the indexes that the adapter owns. "destructive" also retypes and drops columns. See Schema convergence. |
schemaPrefix |
Prefix for generated table names, for several applications sharing one database. |
pool |
Optional mysql2 pool options, merged under the URL. The module refuses the options it sets itself. |
docs/configuration.md lists the options for cursors, the statement timeout and change feeds.
In the module that stores data, add the database interface:
pnpm add @antelopejs/interface-databaseThen follow the database interface guide to declare a schema and query it. The same code runs on @antelopejs/postgres, @antelopejs/mongodb and @antelopejs/rethinkdb. Behaviour worth knowing records where the backends differ.
Unlike the document-store backends, this module turns schema field declarations into DDL. Every table of every schema lives in the database the URL names, as a real table, and each declared scalar field is a column with a native type. A query compiles to a single SQL statement. Filters become WHERE clauses, joins become JOINs, and a filter or orderBy over an indexed field reaches its index.
- One table per schema table, named
<schemaPrefix><schemaId>__<tableId>. No MySQL database per schema id. - Declared scalar fields become typed columns. Objects, arrays and undeclared fields live in
JSON. - Every text column compares in
utf8mb4_0900_bin, orutf8mb4_nopad_binon MariaDB: by code point, case-sensitive, trailing spaces significant. - An index on text or on a path inside JSON keys on a generated
VIRTUALcolumn, and a dotted index field such astitle.frreads a nested JSON path. - An
_instancediscriminator column keeps schema instances apart. - Schema convergence runs one statement per step, so a crash leaves nothing half done, and builds secondary indexes online.
- Change feeds are row triggers, one log and a pull-based reader.
- Database is the
@antelopejs/interface-databasecontract that this module implements. - Configuration covers module sources,
configblocks and config variables inantelope.config.ts.
This repository documents what is specific to the MySQL backend:
| Storage and schema | What a registered schema becomes in the database, the field-type table, what reaches an index, and how registration converges |
| Configuration | Every option construct accepts |
| External mode | Reading tables the module did not create, in a database it does not own |
| Change feeds | changes(), its ordering guarantee, its retention contract and its blind spots |
| Errors and refusals | Everything the module refuses, with the message it refuses by |
| Behaviour worth knowing | Things that answer rather than throw, where the answer may surprise you, including where this backend differs from the PostgreSQL one |
| Package | Supported | Tested with |
|---|---|---|
@antelopejs/interface-core |
>=0.1.1 <1.0.0 |
0.4.1 |
@antelopejs/interface-database |
>=0.3.1 <0.4.0 |
0.3.1 |
@antelopejs/interface-database-catalog |
>=0.0.3 <0.1.0 |
0.0.3 |
CI tests every Node.js major listed under node-versions in .github/workflows/ci.yml, and .nvmrc names the version for local work. The dependencies field of package.json sets the mysql2 driver range, and scripts/test.sh names the MySQL images that the tests run against.
The engines field of package.json sets the Node.js floor. The floor comes from Testcontainers, a dev dependency whose own engines field and whose bundled undici set the same major.
pnpm install
pnpm lint
pnpm format:check
pnpm knip
pnpm test:unit # fast loop: this repository's unit specs, no Docker
pnpm test # everything, on MySQL 8.4 and 9.7 and MariaDB 11.8 and 12.3: owned, external and decorators suitespnpm test starts one server container per image with Docker, so it needs a Docker daemon. Set MYSQL_TEST_IMAGES to a space-separated list of images to test others. It tests two images at a time, since the change-feed tests measure how long a server takes; set MYSQL_TEST_PARALLEL to change that. Besides this repository's own tests, it runs the shared conformance suites of the interfaces listed in antelopeJs.implements, and the @antelopejs/interface-database-decorators suite through scripts/decorators.sh.
To test against an existing server instead of a container, set MYSQL_TEST_URL. It must point to a disposable server, because the suites create and drop databases and the external suite creates and drops an account.
MYSQL_TEST_URL=mysql://root:secret@localhost:3306/mysql pnpm testRead the contribution guidelines before opening a pull request.
This package belongs to AntelopeJS, the TypeScript framework where modules depend on contracts and the application chooses the provider. The open-source back office AntelopeJS DMS is built on it.
| Area | Contracts | Providers |
|---|---|---|
| API | interface-api · interface-api-util · interface-data-api |
api |
| Auth | interface-auth |
auth-jwt |
| Database | interface-database · interface-database-decorators · interface-database-catalog · interface-mongodb · interface-rethinkdb |
postgres · mongodb · rethinkdb |
| Redis | interface-redis · interface-redis-scheduler |
redis |
interface-email |
nodemailer · brevo |
|
| File storage | interface-file-storage |
file-storage-local · file-storage-s3 |
| Payments | interface-payment · interface-subscriptions · interface-stripe |
stripe · mollie · checkout-com · payment-subscriptions |