tempest-db-js 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { ColumnType, DefaultValue, ModelClass, Dialect, SyncDriver, AsyncDriver } from '../index.cjs';
1
+ import { ColumnType, DefaultValue, ModelClass, Dialect, AsyncDriver, SyncDriver } from '../index.cjs';
2
2
 
3
3
  /**
4
4
  * tempest-db-js — Phase 6: the Schema IR (intermediate representation).
@@ -106,11 +106,11 @@ declare function invert(op: Operation): Operation;
106
106
  declare function invertAll(ops: readonly Operation[]): Operation[];
107
107
 
108
108
  /**
109
- * tempest-db-js — Phase 6: DDL rendering.
109
+ * tempest-db-js — Phase 6/9: DDL rendering.
110
110
  *
111
111
  * Renders the dialect-neutral IR + operations to concrete SQL per dialect. This
112
112
  * is the ONLY place migration SQL is produced — the same operation yields the
113
- * right DDL for SQLite or PostgreSQL.
113
+ * right DDL for SQLite, PostgreSQL or MySQL.
114
114
  */
115
115
 
116
116
  /** Map a column type to its SQL type string for the dialect. */
@@ -126,7 +126,7 @@ declare function renderColumnDef(col: ColumnIR, dialect: Dialect): string;
126
126
  * @param dialect The target dialect.
127
127
  * @returns The SQL statements (usually one).
128
128
  * @throws Error When the operation is unsupported on the dialect (e.g. SQLite
129
- * `alter_column`, which needs the Phase 6e batch/table-rebuild path).
129
+ * `alter_column`, which needs the table-rebuild path).
130
130
  */
131
131
  declare function renderOperation(op: Operation, dialect: Dialect): string[];
132
132
 
@@ -280,6 +280,43 @@ declare class MigrationRunner {
280
280
  */
281
281
  downgrade(migrations: readonly Migration[], steps?: number): string[];
282
282
  }
283
+ /**
284
+ * Runs migrations against an **async** driver (PostgreSQL, or any async driver),
285
+ * tracking applied revisions. Mirrors {@link MigrationRunner} but every statement
286
+ * is awaited, and identifier quoting + placeholder style follow the dialect —
287
+ * so the version table and its bookkeeping are portable across SQLite/PG/MySQL.
288
+ */
289
+ declare class AsyncMigrationRunner {
290
+ private readonly driver;
291
+ private readonly dialect;
292
+ private readonly vt;
293
+ constructor(driver: AsyncDriver, dialect: Dialect);
294
+ /** Create the version-tracking table if it does not exist. */
295
+ ensureVersionTable(): Promise<void>;
296
+ /** A portable "text" column type for the version table. */
297
+ private textType;
298
+ /** The set of applied revision ids. */
299
+ applied(): Promise<Set<string>>;
300
+ private runOps;
301
+ private record;
302
+ private forget;
303
+ /**
304
+ * Apply all pending migrations up to the head(s), in DAG order.
305
+ *
306
+ * @param migrations All known migrations.
307
+ * @param appliedAt Timestamp string to stamp on each applied revision.
308
+ * @returns The revision ids that were applied this run.
309
+ */
310
+ upgrade(migrations: readonly Migration[], appliedAt: string): Promise<string[]>;
311
+ /**
312
+ * Revert the last `steps` applied migrations (default 1), newest first.
313
+ *
314
+ * @param migrations All known migrations.
315
+ * @param steps How many applied revisions to roll back.
316
+ * @returns The revision ids that were reverted.
317
+ */
318
+ downgrade(migrations: readonly Migration[], steps?: number): Promise<string[]>;
319
+ }
283
320
 
284
321
  /**
285
322
  * tempest-db-js — Phase 6d: SQLite introspection + drift detection.
@@ -353,6 +390,56 @@ declare function applyOperation(schema: SchemaIR, op: Operation): SchemaIR;
353
390
  */
354
391
  declare function replaySchema(migrations: readonly Migration[]): SchemaIR;
355
392
 
393
+ /**
394
+ * tempest-db-js — Phase 6: rename detection.
395
+ *
396
+ * The differ ({@link diffSchema}) is deliberately conservative: a renamed column
397
+ * looks like a drop + add, and a renamed table like a drop + create. That is the
398
+ * *safe* default (never guesses), but it loses data. This module turns those
399
+ * add/drop pairs into rename *candidates* the CLI can confirm — interactively at
400
+ * a TTY, or explicitly via flags — and folds confirmed ones back into a single
401
+ * `rename_table` / `rename_column` operation.
402
+ *
403
+ * Everything here is pure and structural (no SQL, no DB, no I/O), so the
404
+ * detection and folding are fully testable; the actual prompting lives in the
405
+ * `tempest-db` bin.
406
+ */
407
+
408
+ /** A possible rename the differ emitted as a drop + add/create pair. */
409
+ type RenameCandidate = {
410
+ readonly kind: "table";
411
+ readonly from: string;
412
+ readonly to: string;
413
+ } | {
414
+ readonly kind: "column";
415
+ readonly table: string;
416
+ readonly from: string;
417
+ readonly to: string;
418
+ };
419
+ /**
420
+ * Detect rename candidates in a forward operation list.
421
+ *
422
+ * A table rename is a `create_table` + `drop_table` whose column shapes match
423
+ * exactly. A column rename is an `add_column` + `drop_column` on the same table
424
+ * whose column shapes match exactly. Only unambiguous 1:1 shape matches are
425
+ * reported — if two dropped columns share a shape, neither is offered (the
426
+ * mapping would be a guess).
427
+ *
428
+ * @param ops The forward operations from {@link diffSchema}.
429
+ * @returns The rename candidates found (never mutates `ops`).
430
+ */
431
+ declare function detectRenames(ops: readonly Operation[]): RenameCandidate[];
432
+ /**
433
+ * Fold confirmed renames into an operation list: each confirmed candidate's
434
+ * drop + add/create pair is removed and replaced by a single rename operation,
435
+ * inserted at the position of the first op it replaces (preserving order).
436
+ *
437
+ * @param ops The forward operations from {@link diffSchema}.
438
+ * @param confirmed The rename candidates the user accepted.
439
+ * @returns A new operation list with renames applied.
440
+ */
441
+ declare function applyRenames(ops: readonly Operation[], confirmed: readonly RenameCandidate[]): Operation[];
442
+
356
443
  /**
357
444
  * tempest-db-js — migration CLI (programmatic core).
358
445
  *
@@ -376,6 +463,30 @@ interface CliResult {
376
463
  readonly code: number;
377
464
  readonly lines: string[];
378
465
  }
466
+ /**
467
+ * Identity helper for authoring a typed migration config file. Gives editor
468
+ * autocompletion and type-checking on the object the `tempest-db` bin loads.
469
+ *
470
+ * @example
471
+ * ```ts
472
+ * // tempest-db.config.mjs
473
+ * import { defineMigrationConfig } from "tempest-db-js/migrations";
474
+ * import { NodeSqliteDriver } from "tempest-db-js";
475
+ * import { migrations } from "./migrations/index.js";
476
+ * import { User } from "./models.js";
477
+ *
478
+ * export default defineMigrationConfig({
479
+ * driver: NodeSqliteDriver.open("app.db"),
480
+ * dialect: "sqlite",
481
+ * migrations,
482
+ * models: [User],
483
+ * });
484
+ * ```
485
+ *
486
+ * @param config The migration config to pass through unchanged.
487
+ * @returns The same config, typed as `CliConfig`.
488
+ */
489
+ declare function defineMigrationConfig(config: CliConfig): CliConfig;
379
490
  /**
380
491
  * Run one CLI command.
381
492
  *
@@ -388,4 +499,4 @@ interface CliResult {
388
499
  */
389
500
  declare function runMigrationCli(argv: readonly string[], config: CliConfig): CliResult;
390
501
 
391
- export { type CliConfig, type CliResult, type ColumnIR, CyclicMigrationGraph, type DefaultIR, IrreversibleMigration, type Migration, type MigrationDraft, MigrationRunner, Op, type Operation, type RevisionNode, type SchemaIR, type SqliteAffinity, type TableIR, UnknownRevision, applyOperation, checkDrift, checkDriftPostgres, diffSchema, emptySchema, generateMigration, heads, introspectPostgres, introspectSqlite, invert, invertAll, makeRevisionId, reflectSchema, reflectTable, renderColumnDef, renderColumnType, renderDefault, renderOperation, replaySchema, runMigrationCli, sqliteAffinity, topoOrder };
502
+ export { AsyncMigrationRunner, type CliConfig, type CliResult, type ColumnIR, CyclicMigrationGraph, type DefaultIR, IrreversibleMigration, type Migration, type MigrationDraft, MigrationRunner, Op, type Operation, type RenameCandidate, type RevisionNode, type SchemaIR, type SqliteAffinity, type TableIR, UnknownRevision, applyOperation, applyRenames, checkDrift, checkDriftPostgres, defineMigrationConfig, detectRenames, diffSchema, emptySchema, generateMigration, heads, introspectPostgres, introspectSqlite, invert, invertAll, makeRevisionId, reflectSchema, reflectTable, renderColumnDef, renderColumnType, renderDefault, renderOperation, replaySchema, runMigrationCli, sqliteAffinity, topoOrder };
@@ -1,4 +1,4 @@
1
- import { ColumnType, DefaultValue, ModelClass, Dialect, SyncDriver, AsyncDriver } from '../index.js';
1
+ import { ColumnType, DefaultValue, ModelClass, Dialect, AsyncDriver, SyncDriver } from '../index.js';
2
2
 
3
3
  /**
4
4
  * tempest-db-js — Phase 6: the Schema IR (intermediate representation).
@@ -106,11 +106,11 @@ declare function invert(op: Operation): Operation;
106
106
  declare function invertAll(ops: readonly Operation[]): Operation[];
107
107
 
108
108
  /**
109
- * tempest-db-js — Phase 6: DDL rendering.
109
+ * tempest-db-js — Phase 6/9: DDL rendering.
110
110
  *
111
111
  * Renders the dialect-neutral IR + operations to concrete SQL per dialect. This
112
112
  * is the ONLY place migration SQL is produced — the same operation yields the
113
- * right DDL for SQLite or PostgreSQL.
113
+ * right DDL for SQLite, PostgreSQL or MySQL.
114
114
  */
115
115
 
116
116
  /** Map a column type to its SQL type string for the dialect. */
@@ -126,7 +126,7 @@ declare function renderColumnDef(col: ColumnIR, dialect: Dialect): string;
126
126
  * @param dialect The target dialect.
127
127
  * @returns The SQL statements (usually one).
128
128
  * @throws Error When the operation is unsupported on the dialect (e.g. SQLite
129
- * `alter_column`, which needs the Phase 6e batch/table-rebuild path).
129
+ * `alter_column`, which needs the table-rebuild path).
130
130
  */
131
131
  declare function renderOperation(op: Operation, dialect: Dialect): string[];
132
132
 
@@ -280,6 +280,43 @@ declare class MigrationRunner {
280
280
  */
281
281
  downgrade(migrations: readonly Migration[], steps?: number): string[];
282
282
  }
283
+ /**
284
+ * Runs migrations against an **async** driver (PostgreSQL, or any async driver),
285
+ * tracking applied revisions. Mirrors {@link MigrationRunner} but every statement
286
+ * is awaited, and identifier quoting + placeholder style follow the dialect —
287
+ * so the version table and its bookkeeping are portable across SQLite/PG/MySQL.
288
+ */
289
+ declare class AsyncMigrationRunner {
290
+ private readonly driver;
291
+ private readonly dialect;
292
+ private readonly vt;
293
+ constructor(driver: AsyncDriver, dialect: Dialect);
294
+ /** Create the version-tracking table if it does not exist. */
295
+ ensureVersionTable(): Promise<void>;
296
+ /** A portable "text" column type for the version table. */
297
+ private textType;
298
+ /** The set of applied revision ids. */
299
+ applied(): Promise<Set<string>>;
300
+ private runOps;
301
+ private record;
302
+ private forget;
303
+ /**
304
+ * Apply all pending migrations up to the head(s), in DAG order.
305
+ *
306
+ * @param migrations All known migrations.
307
+ * @param appliedAt Timestamp string to stamp on each applied revision.
308
+ * @returns The revision ids that were applied this run.
309
+ */
310
+ upgrade(migrations: readonly Migration[], appliedAt: string): Promise<string[]>;
311
+ /**
312
+ * Revert the last `steps` applied migrations (default 1), newest first.
313
+ *
314
+ * @param migrations All known migrations.
315
+ * @param steps How many applied revisions to roll back.
316
+ * @returns The revision ids that were reverted.
317
+ */
318
+ downgrade(migrations: readonly Migration[], steps?: number): Promise<string[]>;
319
+ }
283
320
 
284
321
  /**
285
322
  * tempest-db-js — Phase 6d: SQLite introspection + drift detection.
@@ -353,6 +390,56 @@ declare function applyOperation(schema: SchemaIR, op: Operation): SchemaIR;
353
390
  */
354
391
  declare function replaySchema(migrations: readonly Migration[]): SchemaIR;
355
392
 
393
+ /**
394
+ * tempest-db-js — Phase 6: rename detection.
395
+ *
396
+ * The differ ({@link diffSchema}) is deliberately conservative: a renamed column
397
+ * looks like a drop + add, and a renamed table like a drop + create. That is the
398
+ * *safe* default (never guesses), but it loses data. This module turns those
399
+ * add/drop pairs into rename *candidates* the CLI can confirm — interactively at
400
+ * a TTY, or explicitly via flags — and folds confirmed ones back into a single
401
+ * `rename_table` / `rename_column` operation.
402
+ *
403
+ * Everything here is pure and structural (no SQL, no DB, no I/O), so the
404
+ * detection and folding are fully testable; the actual prompting lives in the
405
+ * `tempest-db` bin.
406
+ */
407
+
408
+ /** A possible rename the differ emitted as a drop + add/create pair. */
409
+ type RenameCandidate = {
410
+ readonly kind: "table";
411
+ readonly from: string;
412
+ readonly to: string;
413
+ } | {
414
+ readonly kind: "column";
415
+ readonly table: string;
416
+ readonly from: string;
417
+ readonly to: string;
418
+ };
419
+ /**
420
+ * Detect rename candidates in a forward operation list.
421
+ *
422
+ * A table rename is a `create_table` + `drop_table` whose column shapes match
423
+ * exactly. A column rename is an `add_column` + `drop_column` on the same table
424
+ * whose column shapes match exactly. Only unambiguous 1:1 shape matches are
425
+ * reported — if two dropped columns share a shape, neither is offered (the
426
+ * mapping would be a guess).
427
+ *
428
+ * @param ops The forward operations from {@link diffSchema}.
429
+ * @returns The rename candidates found (never mutates `ops`).
430
+ */
431
+ declare function detectRenames(ops: readonly Operation[]): RenameCandidate[];
432
+ /**
433
+ * Fold confirmed renames into an operation list: each confirmed candidate's
434
+ * drop + add/create pair is removed and replaced by a single rename operation,
435
+ * inserted at the position of the first op it replaces (preserving order).
436
+ *
437
+ * @param ops The forward operations from {@link diffSchema}.
438
+ * @param confirmed The rename candidates the user accepted.
439
+ * @returns A new operation list with renames applied.
440
+ */
441
+ declare function applyRenames(ops: readonly Operation[], confirmed: readonly RenameCandidate[]): Operation[];
442
+
356
443
  /**
357
444
  * tempest-db-js — migration CLI (programmatic core).
358
445
  *
@@ -376,6 +463,30 @@ interface CliResult {
376
463
  readonly code: number;
377
464
  readonly lines: string[];
378
465
  }
466
+ /**
467
+ * Identity helper for authoring a typed migration config file. Gives editor
468
+ * autocompletion and type-checking on the object the `tempest-db` bin loads.
469
+ *
470
+ * @example
471
+ * ```ts
472
+ * // tempest-db.config.mjs
473
+ * import { defineMigrationConfig } from "tempest-db-js/migrations";
474
+ * import { NodeSqliteDriver } from "tempest-db-js";
475
+ * import { migrations } from "./migrations/index.js";
476
+ * import { User } from "./models.js";
477
+ *
478
+ * export default defineMigrationConfig({
479
+ * driver: NodeSqliteDriver.open("app.db"),
480
+ * dialect: "sqlite",
481
+ * migrations,
482
+ * models: [User],
483
+ * });
484
+ * ```
485
+ *
486
+ * @param config The migration config to pass through unchanged.
487
+ * @returns The same config, typed as `CliConfig`.
488
+ */
489
+ declare function defineMigrationConfig(config: CliConfig): CliConfig;
379
490
  /**
380
491
  * Run one CLI command.
381
492
  *
@@ -388,4 +499,4 @@ interface CliResult {
388
499
  */
389
500
  declare function runMigrationCli(argv: readonly string[], config: CliConfig): CliResult;
390
501
 
391
- export { type CliConfig, type CliResult, type ColumnIR, CyclicMigrationGraph, type DefaultIR, IrreversibleMigration, type Migration, type MigrationDraft, MigrationRunner, Op, type Operation, type RevisionNode, type SchemaIR, type SqliteAffinity, type TableIR, UnknownRevision, applyOperation, checkDrift, checkDriftPostgres, diffSchema, emptySchema, generateMigration, heads, introspectPostgres, introspectSqlite, invert, invertAll, makeRevisionId, reflectSchema, reflectTable, renderColumnDef, renderColumnType, renderDefault, renderOperation, replaySchema, runMigrationCli, sqliteAffinity, topoOrder };
502
+ export { AsyncMigrationRunner, type CliConfig, type CliResult, type ColumnIR, CyclicMigrationGraph, type DefaultIR, IrreversibleMigration, type Migration, type MigrationDraft, MigrationRunner, Op, type Operation, type RenameCandidate, type RevisionNode, type SchemaIR, type SqliteAffinity, type TableIR, UnknownRevision, applyOperation, applyRenames, checkDrift, checkDriftPostgres, defineMigrationConfig, detectRenames, diffSchema, emptySchema, generateMigration, heads, introspectPostgres, introspectSqlite, invert, invertAll, makeRevisionId, reflectSchema, reflectTable, renderColumnDef, renderColumnType, renderDefault, renderOperation, replaySchema, runMigrationCli, sqliteAffinity, topoOrder };