longcelot-sheet-db
Version:
Google Sheets-backed staging database adapter for Node.js with schema-first design
70 lines • 4.35 kB
TypeScript
import { TableSchema } from '../../schema/types';
interface MigrateOptions {
prisma?: boolean;
sql?: boolean;
output?: string;
/** Apply the generated DDL (--sql) to a live database, or run `prisma migrate deploy` (--prisma). Phase 16.7. */
apply?: boolean;
connectionString?: string;
driver?: 'postgres' | 'mysql';
dryRun?: boolean;
}
export interface DDLOptions {
/** Column injected into every non-admin table to scope rows to a tenant (Phase 16.3 ADR — see FAQ.md #13). Default: 'tenant_id'. */
tenantColumn?: string;
/**
* Back-relation fields to append to this model — Prisma requires every explicit `@relation`
* to have a matching field on *both* sides ("missing an opposite relation field", found via
* real `prisma generate`, Phase 16.2). generatePrismaModel() only sees one schema at a time,
* so it can't discover these itself — pass the result of collectPrismaBackRelations(schemas).
*/
backRelations?: PrismaBackRelation[];
}
export interface PrismaBackRelation {
/** Field name to add on the referenced model, e.g. 'reviews_product_id_rel'. */
fieldName: string;
/** The referencing model's name, e.g. 'reviews'. */
sourceModel: string;
}
/**
* One pass over every schema, collecting — per referenced table — the list of back-relation
* fields it needs so each `ref()` column's forward `@relation` has a matching opposite field.
* Field names include both the source model and column name (not just the source model) so two
* FK columns from the same table to the same target don't collide.
*/
export declare function collectPrismaBackRelations(schemas: TableSchema[]): Map<string, PrismaBackRelation[]>;
export declare function generatePrismaModel(schema: TableSchema, options?: DDLOptions): string;
export declare function generateSQLTable(schema: TableSchema, options?: DDLOptions): string;
/**
* Foreign keys are emitted inline inside CREATE TABLE (see generateSQLTable() above), so the
* referenced table must already exist — physically, for `--apply`, or earlier in the file, for a
* manually `psql -f`'d schema.sql — before the table that references it. loadSchemas() has no
* ordering guarantee of its own (it's just fs.readdirSync() per actor directory), so a schema
* whose ref() target happens to sort after it alphabetically broke both `--apply` (live "relation
* ... does not exist") and a hand-applied schema.sql the same way. Fixed by topologically sorting
* on col.ref edges before either output is generated. A true circular FK (A references B
* references A) can't be resolved by reordering alone — one side would need its constraint
* deferred to a post-creation ALTER TABLE instead, not handled by this first pass; such schemas
* are left in their original relative order once every acyclic dependency is satisfied.
*/
export declare function sortSchemasByDependency(schemas: TableSchema[]): TableSchema[];
export declare function inferDriverFromConnectionString(connectionString: string): 'postgres' | 'mysql' | undefined;
/**
* Splits the multi-statement DDL text generateSQLTable() produces into individual statements so
* --apply can execute (and idempotency-check) each one separately — needed because MySQL doesn't
* run multi-statement query() calls without an extra multipleStatements connection flag we'd
* rather not require. Known limitation: a semicolon inside a quoted default()/enum() string
* value would be mis-split; not handled by this first-pass implementation.
*/
export declare function splitSQLStatements(ddl: string): string[];
/**
* `CREATE TABLE IF NOT EXISTS` is already idempotent at the SQL level, but plain `CREATE INDEX`
* has no such clause in MySQL (see generateSQLTable()'s comment) — so a rerun's only expected
* failure is "index already exists", which --apply treats as success rather than an error.
*/
export declare function isAlreadyExistsError(err: unknown, driver: 'postgres' | 'mysql'): boolean;
/** `--sql --apply`: execute generateSQLTable()'s output against a live database, statement by statement. */
export declare function applySQLToDatabase(schemas: TableSchema[], options: MigrateOptions): Promise<void>;
export declare function migrateCommand(options: MigrateOptions): Promise<void>;
export {};
//# sourceMappingURL=migrate.d.ts.map