tempest-db-js 0.2.0 → 0.4.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, ForeignKeyRef, FkAction, ModelClass, Dialect, AsyncDriver, SyncDriver } from '../index.cjs';
2
2
 
3
3
  /**
4
4
  * tempest-db-js — Phase 6: the Schema IR (intermediate representation).
@@ -18,13 +18,46 @@ interface ColumnIR {
18
18
  readonly notNull: boolean;
19
19
  readonly primaryKey: boolean;
20
20
  readonly default: DefaultIR;
21
+ /** A column-level `UNIQUE` constraint. */
22
+ readonly unique: boolean;
23
+ /** A column-level foreign-key reference, or `null` for none. */
24
+ readonly references: ForeignKeyRef | null;
21
25
  }
26
+ /** A (composite) `UNIQUE` table constraint in the IR. */
27
+ interface UniqueConstraintIR {
28
+ readonly name: string;
29
+ readonly columns: readonly string[];
30
+ }
31
+ /** A (composite) foreign-key table constraint in the IR. */
32
+ interface ForeignKeyIR {
33
+ readonly name: string;
34
+ readonly columns: readonly string[];
35
+ readonly refTable: string;
36
+ readonly refColumns: readonly string[];
37
+ readonly onDelete?: FkAction | undefined;
38
+ readonly onUpdate?: FkAction | undefined;
39
+ }
40
+ /**
41
+ * A named table-level constraint, tagged by kind. Carried whole by the
42
+ * `add_constraint` / `drop_constraint` operations so each is reversible.
43
+ */
44
+ type NamedConstraint = {
45
+ readonly type: "unique";
46
+ readonly constraint: UniqueConstraintIR;
47
+ } | {
48
+ readonly type: "foreignKey";
49
+ readonly constraint: ForeignKeyIR;
50
+ };
22
51
  /** One table. */
23
52
  interface TableIR {
24
53
  readonly name: string;
25
54
  readonly columns: Record<string, ColumnIR>;
26
55
  /** Primary-key column names (composite = more than one). */
27
56
  readonly primaryKey: readonly string[];
57
+ /** Table-level unique constraints (from `tableArgs`). */
58
+ readonly uniqueConstraints: readonly UniqueConstraintIR[];
59
+ /** Table-level foreign-key constraints (from `tableArgs`). */
60
+ readonly foreignKeys: readonly ForeignKeyIR[];
28
61
  }
29
62
  /** A whole schema, keyed by table name. */
30
63
  interface SchemaIR {
@@ -85,6 +118,14 @@ type Operation = {
85
118
  readonly kind: "recreate_table";
86
119
  readonly from: TableIR;
87
120
  readonly to: TableIR;
121
+ } | {
122
+ readonly kind: "add_constraint";
123
+ readonly table: string;
124
+ readonly constraint: NamedConstraint;
125
+ } | {
126
+ readonly kind: "drop_constraint";
127
+ readonly table: string;
128
+ readonly constraint: NamedConstraint;
88
129
  } | {
89
130
  readonly kind: "execute";
90
131
  readonly up: string;
@@ -106,18 +147,21 @@ declare function invert(op: Operation): Operation;
106
147
  declare function invertAll(ops: readonly Operation[]): Operation[];
107
148
 
108
149
  /**
109
- * tempest-db-js — Phase 6: DDL rendering.
150
+ * tempest-db-js — Phase 6/9: DDL rendering.
110
151
  *
111
152
  * Renders the dialect-neutral IR + operations to concrete SQL per dialect. This
112
153
  * is the ONLY place migration SQL is produced — the same operation yields the
113
- * right DDL for SQLite or PostgreSQL.
154
+ * right DDL for SQLite, PostgreSQL or MySQL.
114
155
  */
115
156
 
116
157
  /** Map a column type to its SQL type string for the dialect. */
117
158
  declare function renderColumnType(type: ColumnType, dialect: Dialect): string;
118
159
  /** Render a default value into a SQL `DEFAULT` expression for the dialect. */
119
160
  declare function renderDefault(def: DefaultValue, dialect: Dialect): string;
120
- /** Render one column definition: `"name" TYPE [NOT NULL] [DEFAULT x]`. */
161
+ /**
162
+ * Render one column definition: `"name" TYPE [NOT NULL] [DEFAULT x] [UNIQUE]
163
+ * [REFERENCES ...]`.
164
+ */
121
165
  declare function renderColumnDef(col: ColumnIR, dialect: Dialect): string;
122
166
  /**
123
167
  * Render an operation to one or more SQL statements for the dialect.
@@ -126,7 +170,7 @@ declare function renderColumnDef(col: ColumnIR, dialect: Dialect): string;
126
170
  * @param dialect The target dialect.
127
171
  * @returns The SQL statements (usually one).
128
172
  * @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).
173
+ * `alter_column`, which needs the table-rebuild path).
130
174
  */
131
175
  declare function renderOperation(op: Operation, dialect: Dialect): string[];
132
176
 
@@ -239,6 +283,10 @@ declare class Op {
239
283
  renameColumn(table: string, from: string, to: string): void;
240
284
  /** Rebuild a table (SQLite batch-mode / PostgreSQL per-column alters). */
241
285
  recreateTable(from: TableIR, to: TableIR): void;
286
+ /** Add a table-level unique / foreign-key constraint. */
287
+ addConstraint(table: string, constraint: NamedConstraint): void;
288
+ /** Drop a table-level unique / foreign-key constraint. */
289
+ dropConstraint(table: string, constraint: NamedConstraint): void;
242
290
  /** Raw SQL escape hatch (e.g. a data migration). `down` may be `null`. */
243
291
  execute(up: string, down?: string | null): void;
244
292
  }
@@ -280,6 +328,43 @@ declare class MigrationRunner {
280
328
  */
281
329
  downgrade(migrations: readonly Migration[], steps?: number): string[];
282
330
  }
331
+ /**
332
+ * Runs migrations against an **async** driver (PostgreSQL, or any async driver),
333
+ * tracking applied revisions. Mirrors {@link MigrationRunner} but every statement
334
+ * is awaited, and identifier quoting + placeholder style follow the dialect —
335
+ * so the version table and its bookkeeping are portable across SQLite/PG/MySQL.
336
+ */
337
+ declare class AsyncMigrationRunner {
338
+ private readonly driver;
339
+ private readonly dialect;
340
+ private readonly vt;
341
+ constructor(driver: AsyncDriver, dialect: Dialect);
342
+ /** Create the version-tracking table if it does not exist. */
343
+ ensureVersionTable(): Promise<void>;
344
+ /** A portable "text" column type for the version table. */
345
+ private textType;
346
+ /** The set of applied revision ids. */
347
+ applied(): Promise<Set<string>>;
348
+ private runOps;
349
+ private record;
350
+ private forget;
351
+ /**
352
+ * Apply all pending migrations up to the head(s), in DAG order.
353
+ *
354
+ * @param migrations All known migrations.
355
+ * @param appliedAt Timestamp string to stamp on each applied revision.
356
+ * @returns The revision ids that were applied this run.
357
+ */
358
+ upgrade(migrations: readonly Migration[], appliedAt: string): Promise<string[]>;
359
+ /**
360
+ * Revert the last `steps` applied migrations (default 1), newest first.
361
+ *
362
+ * @param migrations All known migrations.
363
+ * @param steps How many applied revisions to roll back.
364
+ * @returns The revision ids that were reverted.
365
+ */
366
+ downgrade(migrations: readonly Migration[], steps?: number): Promise<string[]>;
367
+ }
283
368
 
284
369
  /**
285
370
  * tempest-db-js — Phase 6d: SQLite introspection + drift detection.
@@ -303,15 +388,6 @@ declare function sqliteAffinity(declared: string): SqliteAffinity;
303
388
  * @returns The introspected schema.
304
389
  */
305
390
  declare function introspectSqlite(driver: SyncDriver): SchemaIR;
306
- /**
307
- * Compare the live SQLite schema against the models and report drift. Comparison
308
- * is at the affinity level (so `varchar` vs `TEXT` is not flagged), plus
309
- * nullability, primary-key, and presence of tables/columns.
310
- *
311
- * @param driver A sync SQLite driver.
312
- * @param models The model classes that define the intended schema.
313
- * @returns A list of human-readable drift messages — empty means no drift.
314
- */
315
391
  declare function checkDrift(driver: SyncDriver, models: readonly ModelClass[]): string[];
316
392
  /**
317
393
  * Read the current PostgreSQL schema into a `SchemaIR` from `information_schema`.
@@ -462,4 +538,4 @@ declare function defineMigrationConfig(config: CliConfig): CliConfig;
462
538
  */
463
539
  declare function runMigrationCli(argv: readonly string[], config: CliConfig): CliResult;
464
540
 
465
- export { 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 };
541
+ export { AsyncMigrationRunner, type CliConfig, type CliResult, type ColumnIR, CyclicMigrationGraph, type DefaultIR, type ForeignKeyIR, IrreversibleMigration, type Migration, type MigrationDraft, MigrationRunner, type NamedConstraint, Op, type Operation, type RenameCandidate, type RevisionNode, type SchemaIR, type SqliteAffinity, type TableIR, type UniqueConstraintIR, 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, ForeignKeyRef, FkAction, ModelClass, Dialect, AsyncDriver, SyncDriver } from '../index.js';
2
2
 
3
3
  /**
4
4
  * tempest-db-js — Phase 6: the Schema IR (intermediate representation).
@@ -18,13 +18,46 @@ interface ColumnIR {
18
18
  readonly notNull: boolean;
19
19
  readonly primaryKey: boolean;
20
20
  readonly default: DefaultIR;
21
+ /** A column-level `UNIQUE` constraint. */
22
+ readonly unique: boolean;
23
+ /** A column-level foreign-key reference, or `null` for none. */
24
+ readonly references: ForeignKeyRef | null;
21
25
  }
26
+ /** A (composite) `UNIQUE` table constraint in the IR. */
27
+ interface UniqueConstraintIR {
28
+ readonly name: string;
29
+ readonly columns: readonly string[];
30
+ }
31
+ /** A (composite) foreign-key table constraint in the IR. */
32
+ interface ForeignKeyIR {
33
+ readonly name: string;
34
+ readonly columns: readonly string[];
35
+ readonly refTable: string;
36
+ readonly refColumns: readonly string[];
37
+ readonly onDelete?: FkAction | undefined;
38
+ readonly onUpdate?: FkAction | undefined;
39
+ }
40
+ /**
41
+ * A named table-level constraint, tagged by kind. Carried whole by the
42
+ * `add_constraint` / `drop_constraint` operations so each is reversible.
43
+ */
44
+ type NamedConstraint = {
45
+ readonly type: "unique";
46
+ readonly constraint: UniqueConstraintIR;
47
+ } | {
48
+ readonly type: "foreignKey";
49
+ readonly constraint: ForeignKeyIR;
50
+ };
22
51
  /** One table. */
23
52
  interface TableIR {
24
53
  readonly name: string;
25
54
  readonly columns: Record<string, ColumnIR>;
26
55
  /** Primary-key column names (composite = more than one). */
27
56
  readonly primaryKey: readonly string[];
57
+ /** Table-level unique constraints (from `tableArgs`). */
58
+ readonly uniqueConstraints: readonly UniqueConstraintIR[];
59
+ /** Table-level foreign-key constraints (from `tableArgs`). */
60
+ readonly foreignKeys: readonly ForeignKeyIR[];
28
61
  }
29
62
  /** A whole schema, keyed by table name. */
30
63
  interface SchemaIR {
@@ -85,6 +118,14 @@ type Operation = {
85
118
  readonly kind: "recreate_table";
86
119
  readonly from: TableIR;
87
120
  readonly to: TableIR;
121
+ } | {
122
+ readonly kind: "add_constraint";
123
+ readonly table: string;
124
+ readonly constraint: NamedConstraint;
125
+ } | {
126
+ readonly kind: "drop_constraint";
127
+ readonly table: string;
128
+ readonly constraint: NamedConstraint;
88
129
  } | {
89
130
  readonly kind: "execute";
90
131
  readonly up: string;
@@ -106,18 +147,21 @@ declare function invert(op: Operation): Operation;
106
147
  declare function invertAll(ops: readonly Operation[]): Operation[];
107
148
 
108
149
  /**
109
- * tempest-db-js — Phase 6: DDL rendering.
150
+ * tempest-db-js — Phase 6/9: DDL rendering.
110
151
  *
111
152
  * Renders the dialect-neutral IR + operations to concrete SQL per dialect. This
112
153
  * is the ONLY place migration SQL is produced — the same operation yields the
113
- * right DDL for SQLite or PostgreSQL.
154
+ * right DDL for SQLite, PostgreSQL or MySQL.
114
155
  */
115
156
 
116
157
  /** Map a column type to its SQL type string for the dialect. */
117
158
  declare function renderColumnType(type: ColumnType, dialect: Dialect): string;
118
159
  /** Render a default value into a SQL `DEFAULT` expression for the dialect. */
119
160
  declare function renderDefault(def: DefaultValue, dialect: Dialect): string;
120
- /** Render one column definition: `"name" TYPE [NOT NULL] [DEFAULT x]`. */
161
+ /**
162
+ * Render one column definition: `"name" TYPE [NOT NULL] [DEFAULT x] [UNIQUE]
163
+ * [REFERENCES ...]`.
164
+ */
121
165
  declare function renderColumnDef(col: ColumnIR, dialect: Dialect): string;
122
166
  /**
123
167
  * Render an operation to one or more SQL statements for the dialect.
@@ -126,7 +170,7 @@ declare function renderColumnDef(col: ColumnIR, dialect: Dialect): string;
126
170
  * @param dialect The target dialect.
127
171
  * @returns The SQL statements (usually one).
128
172
  * @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).
173
+ * `alter_column`, which needs the table-rebuild path).
130
174
  */
131
175
  declare function renderOperation(op: Operation, dialect: Dialect): string[];
132
176
 
@@ -239,6 +283,10 @@ declare class Op {
239
283
  renameColumn(table: string, from: string, to: string): void;
240
284
  /** Rebuild a table (SQLite batch-mode / PostgreSQL per-column alters). */
241
285
  recreateTable(from: TableIR, to: TableIR): void;
286
+ /** Add a table-level unique / foreign-key constraint. */
287
+ addConstraint(table: string, constraint: NamedConstraint): void;
288
+ /** Drop a table-level unique / foreign-key constraint. */
289
+ dropConstraint(table: string, constraint: NamedConstraint): void;
242
290
  /** Raw SQL escape hatch (e.g. a data migration). `down` may be `null`. */
243
291
  execute(up: string, down?: string | null): void;
244
292
  }
@@ -280,6 +328,43 @@ declare class MigrationRunner {
280
328
  */
281
329
  downgrade(migrations: readonly Migration[], steps?: number): string[];
282
330
  }
331
+ /**
332
+ * Runs migrations against an **async** driver (PostgreSQL, or any async driver),
333
+ * tracking applied revisions. Mirrors {@link MigrationRunner} but every statement
334
+ * is awaited, and identifier quoting + placeholder style follow the dialect —
335
+ * so the version table and its bookkeeping are portable across SQLite/PG/MySQL.
336
+ */
337
+ declare class AsyncMigrationRunner {
338
+ private readonly driver;
339
+ private readonly dialect;
340
+ private readonly vt;
341
+ constructor(driver: AsyncDriver, dialect: Dialect);
342
+ /** Create the version-tracking table if it does not exist. */
343
+ ensureVersionTable(): Promise<void>;
344
+ /** A portable "text" column type for the version table. */
345
+ private textType;
346
+ /** The set of applied revision ids. */
347
+ applied(): Promise<Set<string>>;
348
+ private runOps;
349
+ private record;
350
+ private forget;
351
+ /**
352
+ * Apply all pending migrations up to the head(s), in DAG order.
353
+ *
354
+ * @param migrations All known migrations.
355
+ * @param appliedAt Timestamp string to stamp on each applied revision.
356
+ * @returns The revision ids that were applied this run.
357
+ */
358
+ upgrade(migrations: readonly Migration[], appliedAt: string): Promise<string[]>;
359
+ /**
360
+ * Revert the last `steps` applied migrations (default 1), newest first.
361
+ *
362
+ * @param migrations All known migrations.
363
+ * @param steps How many applied revisions to roll back.
364
+ * @returns The revision ids that were reverted.
365
+ */
366
+ downgrade(migrations: readonly Migration[], steps?: number): Promise<string[]>;
367
+ }
283
368
 
284
369
  /**
285
370
  * tempest-db-js — Phase 6d: SQLite introspection + drift detection.
@@ -303,15 +388,6 @@ declare function sqliteAffinity(declared: string): SqliteAffinity;
303
388
  * @returns The introspected schema.
304
389
  */
305
390
  declare function introspectSqlite(driver: SyncDriver): SchemaIR;
306
- /**
307
- * Compare the live SQLite schema against the models and report drift. Comparison
308
- * is at the affinity level (so `varchar` vs `TEXT` is not flagged), plus
309
- * nullability, primary-key, and presence of tables/columns.
310
- *
311
- * @param driver A sync SQLite driver.
312
- * @param models The model classes that define the intended schema.
313
- * @returns A list of human-readable drift messages — empty means no drift.
314
- */
315
391
  declare function checkDrift(driver: SyncDriver, models: readonly ModelClass[]): string[];
316
392
  /**
317
393
  * Read the current PostgreSQL schema into a `SchemaIR` from `information_schema`.
@@ -462,4 +538,4 @@ declare function defineMigrationConfig(config: CliConfig): CliConfig;
462
538
  */
463
539
  declare function runMigrationCli(argv: readonly string[], config: CliConfig): CliResult;
464
540
 
465
- export { 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 };
541
+ export { AsyncMigrationRunner, type CliConfig, type CliResult, type ColumnIR, CyclicMigrationGraph, type DefaultIR, type ForeignKeyIR, IrreversibleMigration, type Migration, type MigrationDraft, MigrationRunner, type NamedConstraint, Op, type Operation, type RenameCandidate, type RevisionNode, type SchemaIR, type SqliteAffinity, type TableIR, type UniqueConstraintIR, 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
- export { CyclicMigrationGraph, IrreversibleMigration, MigrationRunner, Op, 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 } from '../chunk-QMW4NKMH.js';
2
- import '../chunk-AGDD7K3F.js';
1
+ export { AsyncMigrationRunner, CyclicMigrationGraph, IrreversibleMigration, MigrationRunner, Op, 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 } from '../chunk-43XL66JG.js';
2
+ import '../chunk-JR4MLFQN.js';
3
3
  //# sourceMappingURL=index.js.map
4
4
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tempest-db-js",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Type-safe, class-based ORM for TypeScript — SQLAlchemy 2.0 ergonomics for the JS/TS world.",
5
5
  "type": "module",
6
6
  "sideEffects": false,