import { ClassInfo } from '@spinajs/di'; import { Log } from '@spinajs/log-common'; import { OrmDriver } from './driver.js'; import { OrmMigration } from './interfaces.js'; import { IMigrationStatusEntry, IMigrationUnit, MigrationResolveAction, OrmMigrationService } from './migration-service.js'; /** * Re-exported from `./symbols.js` ( a leaf module ) rather than defined here, so this module can * sit in `Orm`'s require cycle without closing it one hop earlier. This is still the import path * the rest of the package - and `@spinajs/orm-cli` - use, and stays that way. */ export { MIGRATION_FILE_REGEXP } from './symbols.js'; /** * The slice of `Orm` this facade consumes. Narrow on purpose: the runner is constructible from * anything holding a migration registry and a connection map, which is what makes it testable * without booting an Orm. * * Named for its one consumer rather than for `Orm`: this is part of `@spinajs/orm`'s public * surface, and a name like `IOrmLike` would read as "the general-purpose Orm interface" to * everyone who imports it. */ export interface IMigrationRunnerHost { Migrations: Array>; Connections: Map; } export interface IMigrationUpOptions { /** * Run even for connections whose `Migration.OnStartup` is off. Public callers ( CLI, an * explicit `orm.Migration.up()` ) default to true; only the boot path passes false. */ force?: boolean; /** * Record the migrations as applied without running them. */ fake?: boolean; /** * Limit the run to one connection, by name. Absent means every configured connection. * * The name is resolved to a driver before it is compared, so an alias ( `db.Aliases` ) and the * connection it points at select the same run. A name no connection answers to throws. */ connection?: string; } export interface IMigrationDownFacadeOptions extends IMigrationUpOptions { /** * Roll every applied migration back instead of only the last batch. */ all?: boolean; } /** * Cross-connection orchestrator: validates and orders the migration registry, groups it by the * connection each migration declared, and hands each group to that connection's * `OrmMigrationService`. Everything that touches a database lives in the service; everything * that spans connections lives here. */ export declare class MigrationRunner { protected orm: IMigrationRunnerHost; protected Log: Log; constructor(orm: IMigrationRunnerHost); /** * Applies every pending migration on every configured connection, or only `name` when one is * given, in `(created, name)` order ACROSS connections. * * Across, not connection by connection: migrations on different connections often target the * same server, and one of them may read what another created - a view in one schema over a * table a migration on another connection adds. Running each connection's whole backlog in * turn applies such a pair in the wrong order whenever both are pending at once, which is * exactly the case of a deployment catching up on several releases. So the pending set is * walked in global order and handed to each connection's service in consecutive stretches; * returning to a connection continues the batch it already opened. * * A `name` that matches nothing in the registry throws rather than returning `[]`: an empty * result from a typo is indistinguishable from "already up to date", so the CLI would exit 0 * reporting "0 migrations applied" and the operator would believe the schema is current. */ up(name?: string, options?: IMigrationUpOptions): Promise; /** * The planned groups re-cut into runs of consecutive same-connection migrations, in global * `(created, name)` order. * * Only what still has to run takes part in the cut - applied migrations would split the * pending ones into many needless stretches, each one lock and one table read. A FAILED * migration does take part: its service refuses the run at that point, as it always has. * * A connection with nothing left to run still gets an empty stretch, at the end: the service's * refusal to run over a FAILED row covers every row of the connection, registered or not, and * skipping the call would quietly drop that guard for it. */ protected stretches(groups: Array<[OrmDriver, IMigrationUnit[]]>): Promise>; /** * Rolls the last applied batch back on every configured connection, or every batch with * `{ all: true }`. `name` narrows the run to a single migration and - exactly like `up` - throws * when the registry carries nothing by that name. * * KNOWN SHARP EDGE, `down(name)`: the service is handed a one-element unit list, and it treats * every applied row in the target batch that has no matching unit as an orphan. So a named * rollback warns that perfectly healthy, merely-unrequested migrations are "recorded as applied * but no registered migration matches them (file deleted or renamed)" and advises restoring the * file or removing the row by hand - guidance that is destructive if followed here, because * nothing is actually wrong with those rows. The rollback itself is correct; only the warning * lies. Fixing it means giving `IMigrationDownOptions` an "only these" notion, i.e. reshaping the * service contract, so it is deliberately not done inside this facade. */ down(name?: string, options?: IMigrationDownFacadeOptions): Promise; status(): Promise; /** * Forces a migration's recorded state on whichever connection owns it - the escape hatch for a * run that died halfway. The unit is handed down as well: the service cannot fingerprint a * migration it was only given the name of, and a resolution without it leaves `Checksum` NULL * forever, so drift is never detectable for that row again. */ resolve(name: string, action: MigrationResolveAction): Promise; /** * The connection's configured `OrmMigrationService`, or the built-in one. */ protected service(driver: OrmDriver): Promise; /** * Validates every registered migration's name, orders the set, and groups it by the connection * it declared - returning one ordered unit list per connection that is actually going to run. * * Keyed by driver rather than by connection name so aliases ( two names bound to the same * `OrmDriver` ) collapse into one group instead of running the same migration twice. * * `name` narrows the set to one migration, and is the single place all three public entry * points get their "that name is not registered" refusal from. `connection` narrows it to one * connection - the two compose, and a `name` on a connection the filter excludes runs nothing. */ protected plan(name: string | undefined, force: boolean, connection?: string): Array<[OrmDriver, IMigrationUnit[]]>; } //# sourceMappingURL=migration-runner.d.ts.map