← All @molecule/* packages · App templates
@molecule/api-project-archive-external-state-mysqlProvider bond · project-archive-external-state · API (Node) · v1.0.1 · Apache-2.0
Back up and restore a project's MySQL or MariaDB database as part of a project archive — captures it with mysqldump (single-transaction, routines, triggers, events) and restores it with the mysql client, refusing any dump that is not provably complete. Credentials never reach argv. Zero external dependencies.
npm install @molecule/api-project-archive-external-state-mysqlnpm · Source on GitHub · Implements @molecule/api-project-archive
@molecule/api-project-archive-external-state-mysql is a provider bond on the API (Node) side: it implements the project-archive-external-state core interface (@molecule/api-project-archive) with a concrete vendor or library behind it.
Your code calls the core; you wire this provider once at startup. Swapping vendors later is one line in that wiring, not a rewrite.
Works with: @molecule/api-project-archive
Secrets: PROJECT_ARCHIVE_MYSQL_URL, PROJECT_ARCHIVE_MYSQL_DATABASE, PROJECT_ARCHIVE_MYSQL_DUMP_BIN (optional), PROJECT_ARCHIVE_MYSQL_CLIENT_BIN (optional), PROJECT_ARCHIVE_MYSQL_MAX_DUMP_BYTES (optional)
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Capture and restore a project's MySQL databases for
@molecule/api-project-archive.
It dumps to a file and loads the file back. That is the whole package —
mysqldump on the way out, mysql on the way in.
import { setExternalStateProvider } from '@molecule/api-project-archive'
import { createMysqlExternalStateProvider } from '@molecule/api-project-archive-external-state-mysql'
setExternalStateProvider(
createMysqlExternalStateProvider({
// YOUR deployment provisioned these, so it states them. Nothing is discovered.
databaseUrls: (projectId) => [`mysql://user:pw@db:3306/app_${projectId}`],
}),
)
provider
npm install @molecule/api-project-archive-external-state-mysql @molecule/api-project-archive
MysqlExternalStateConfigHow this deployment finds a project's MySQL databases.
interface MysqlExternalStateConfig {
/**
* The connection URLs of every database belonging to `projectId`.
*
* **This is a DECLARATION, not a query.** The deployment provisioned these
* databases, so it knows what they are; this provider never goes looking. An
* empty array means the project genuinely owns none — and it is the ONLY way
* to say that.
*
* Why it matters more here than anywhere: MySQL filters `information_schema`
* BY PRIVILEGE. An account without a grant on a schema sees zero rows, which
* is byte-for-byte identical to the schema not existing — and a provisioning
* race produces exactly that state transiently. An earlier version of this
* package queried `information_schema.SCHEMATA` and read zero rows as "this
* project owns no database", which, since the caller destroys the project once
* a capture succeeds, deleted live databases. There is no query that closes
* this: `TABLES`, `VIEWS`, `ROUTINES` and `mysqldump`'s own `SHOW TABLES` are
* filtered by the same privilege. Discovery was removed rather than hardened.
*
* @param projectId - The project being archived or restored.
* @returns Its database connection URLs; `[]` when it owns none.
*/
databaseUrls: (projectId: string) => readonly string[] | Promise<readonly string[]>
}
createMysqlExternalStateProvider(config)Create the provider.
function createMysqlExternalStateProvider(
config: MysqlExternalStateConfig,
): ProjectExternalStateProvider
config — How to find a project's databases.Returns: A provider ready to bond with setExternalStateProvider.
dumpToFile(command, args, destPath, env)Run command, streaming its stdout into destPath.
function dumpToFile(
command: string,
args: readonly string[],
destPath: string,
env?: NodeJS.ProcessEnv,
): Promise<number>
command — The executable, e.g. pg_dump.args — Arguments. Credentials belong in env, never here — argv is world-readable in the process list.destPath — Absolute path the dump is written to.env — Extra environment for the child (where credentials go).Returns: Bytes written.
parseConnection(url)Split a connection URL into a database name, client options and environment.
The password goes in MYSQL_PWD, never in argv — --password= is readable by
any process on the host, and the MySQL client warns about exactly this.
function parseConnection(url: string): Connection
url — A mysql://… connection URL.Returns: The database name, the shared client arguments, and the environment.
restoreFromFile(command, args, srcPath, env)Run command, streaming srcPath into its stdin.
function restoreFromFile(
command: string,
args: readonly string[],
srcPath: string,
env?: NodeJS.ProcessEnv,
): Promise<void>
command — The executable, e.g. psql.args — Arguments. Credentials belong in env.srcPath — Absolute path of the dump to feed in.env — Extra environment for the child.KINDRecorded on every record this provider produces; routes restores back here.
const KIND: 'mysql'
Implements @molecule/api-project-archive interface.
Setup function to register this provider with the bond system:
import { bond } from '@molecule/api-bond'
import { provider } from '@molecule/api-project-archive-external-state-mysql'
export function setupProjectArchiveExternalStateMysql(): void {
bond('project-archive-external-state', 'mysql', provider)
}
Peer dependencies:
@molecule/api-project-archive ^1.0.1PROJECT_ARCHIVE_MYSQL_URL (required) — MySQL connection URL (archiver)
mysql://archiver:secret@db.internal:3306PROJECT_ARCHIVE_MYSQL_DATABASE (required) — Project database name template
app_{projectId}PROJECT_ARCHIVE_MYSQL_DUMP_BIN (optional) — mysqldump binary — default: mysqldump
/usr/bin/mysqldumpPROJECT_ARCHIVE_MYSQL_CLIENT_BIN (optional) — mysql client binary — default: mysql
/usr/bin/mysqlPROJECT_ARCHIVE_MYSQL_MAX_DUMP_BYTES (optional) — Maximum dump size in bytes — default: 268435456
268435456@molecule/api-project-archiveIt never asks the server what a project owns — databaseUrls says. MySQL
filters information_schema BY PRIVILEGE, so an account missing one grant
sees zero rows, identical to the schema not existing — and a provisioning race
produces exactly that transiently. Since the caller DESTROYS the project after
a successful capture, discovering databases that way deletes live data. No
query fixes it (TABLES, VIEWS, ROUTINES and mysqldump's own
SHOW TABLES share the privilege), so discovery was removed rather than
hardened.
The dump includes routines, triggers and events, none of which
mysqldump includes by default — their absence is silent, and a restored
database would simply be missing its stored logic.
mysqldump and mysql must be on PATH. The password travels in
MYSQL_PWD, never in argv, which any process on the host can read.
restore replays the dump into an existing database. It does not create
or drop it; provision the database first.