@jarenjs/db 0.87.0 → 0.89.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.
- package/ARCHITECTURE.md +29 -12
- package/README.md +12 -4
- package/docs/MIGRATION-FORMAT.md +259 -70
- package/docs/MODEL-FORMAT.md +38 -6
- package/docs/SQLITE-RELATIONAL.md +31 -2
- package/package.json +4 -4
- package/schemas/jaren-migration.draft-07.schema.json +169 -5
- package/schemas/jaren-migration.schema.json +164 -0
- package/src/ddl.js +8 -86
- package/src/dialects/sqlite.js +1 -0
- package/src/document-steps.js +23 -5
- package/src/drivers/bun.js +13 -3
- package/src/drivers/file-identity.js +14 -0
- package/src/drivers/node.js +2 -0
- package/src/foreign-key-scope.js +50 -0
- package/src/migrate.js +291 -497
- package/src/migration-target.js +104 -0
- package/src/physical-transform.js +207 -0
- package/src/schema-sql.js +184 -0
- package/src/table-migration.js +17 -17
- package/types/index.d.ts +113 -13
package/types/index.d.ts
CHANGED
|
@@ -1169,6 +1169,10 @@ export interface Dialect {
|
|
|
1169
1169
|
export interface Driver {
|
|
1170
1170
|
readonly name: string;
|
|
1171
1171
|
readonly dialect: Dialect;
|
|
1172
|
+
/** Optional storage identity for shadow isolation. Equal non-null values
|
|
1173
|
+
* identify the same database; private memory databases return null. Native
|
|
1174
|
+
* SQLite bindings use filesystem device/inode identity. */
|
|
1175
|
+
databaseIdentity?(connection: unknown): string | null | Promise<string | null>;
|
|
1172
1176
|
/** Open a connection (value-or-promise) at `path` (`':memory:'` for
|
|
1173
1177
|
* none) with the driver's own options. */
|
|
1174
1178
|
open(path: string, options?: unknown): unknown;
|
|
@@ -1259,6 +1263,37 @@ export interface MigrationTarget {
|
|
|
1259
1263
|
path?: string;
|
|
1260
1264
|
/** `PRAGMA busy_timeout` for the run's connection, ms (default 5000). */
|
|
1261
1265
|
busyTimeout?: number;
|
|
1266
|
+
connection?: never;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
/** A caller-owned connection, never closed or reopened by migration entry points. */
|
|
1270
|
+
export interface BorrowedMigrationTarget {
|
|
1271
|
+
connection: unknown;
|
|
1272
|
+
driver?: never;
|
|
1273
|
+
path?: never;
|
|
1274
|
+
busyTimeout?: never;
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
/** One physical catalog object. Some dialects cannot supply declaration text. */
|
|
1278
|
+
export interface SchemaObject {
|
|
1279
|
+
readonly type: 'table' | 'view' | 'index' | 'trigger';
|
|
1280
|
+
readonly name: string;
|
|
1281
|
+
readonly owner: string;
|
|
1282
|
+
readonly sql: string | null;
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
export interface SchemaInventory {
|
|
1286
|
+
readonly tables: readonly unknown[];
|
|
1287
|
+
readonly views: readonly string[];
|
|
1288
|
+
readonly objects: readonly SchemaObject[];
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
/** Complete reviewed SQLite objects in an explicitly owned scope.
|
|
1292
|
+
* Every object must carry SQL text; missing declaration text refuses at runtime. */
|
|
1293
|
+
export interface PhysicalMigrationTarget {
|
|
1294
|
+
readonly objects: readonly SchemaObject[];
|
|
1295
|
+
/** Defaults to the object owners; an absent named table records an intended drop. */
|
|
1296
|
+
readonly tables?: readonly string[];
|
|
1262
1297
|
}
|
|
1263
1298
|
|
|
1264
1299
|
/** One progress event: the migration and collection a data step is
|
|
@@ -1302,7 +1337,7 @@ export declare function introspectModel(connection: unknown, options?: {
|
|
|
1302
1337
|
* model cannot declare. */
|
|
1303
1338
|
export declare function readSchema(connection: unknown, options?: {
|
|
1304
1339
|
tables?: readonly string[];
|
|
1305
|
-
}):
|
|
1340
|
+
}): SchemaInventory | Promise<SchemaInventory>;
|
|
1306
1341
|
|
|
1307
1342
|
export interface AssertionBounds {
|
|
1308
1343
|
maxRows?: number | null;
|
|
@@ -1328,6 +1363,10 @@ export interface MigrateOptions {
|
|
|
1328
1363
|
dryRun?: boolean;
|
|
1329
1364
|
batchSize?: number;
|
|
1330
1365
|
shadow?: boolean;
|
|
1366
|
+
/** Complete owned target; also checked when there are no pending steps. */
|
|
1367
|
+
physicalTarget?: PhysicalMigrationTarget;
|
|
1368
|
+
/** Initialize the disposable shadow with the actual historical schema and rows. */
|
|
1369
|
+
shadowFixture?: (connection: unknown) => unknown;
|
|
1331
1370
|
/** Where the shadow replay runs (default `':memory:'`). */
|
|
1332
1371
|
shadowPath?: string;
|
|
1333
1372
|
/** The host's declared index-expression functions, by name — the same
|
|
@@ -1337,7 +1376,7 @@ export interface MigrateOptions {
|
|
|
1337
1376
|
* A file engine's shadow is another file; a SERVER engine's is another
|
|
1338
1377
|
* schema, and only the host can name one — the baseline shape the
|
|
1339
1378
|
* replay creates would otherwise collide with the real store's. */
|
|
1340
|
-
shadowDriver?:
|
|
1379
|
+
shadowDriver?: Driver;
|
|
1341
1380
|
/** Called once per batch a data step walks (transform, derive, or a
|
|
1342
1381
|
* per-document assertion). */
|
|
1343
1382
|
onProgress?: (progress: MigrationProgress) => void;
|
|
@@ -1381,7 +1420,33 @@ export declare function classifyAssertion(query: unknown, options?: { expect?: s
|
|
|
1381
1420
|
|
|
1382
1421
|
export declare function migrate(
|
|
1383
1422
|
target: MigrationTarget, migrations: readonly unknown[], options: MigrateOptions,
|
|
1384
|
-
): Promise<
|
|
1423
|
+
): Promise<MigrationResult>;
|
|
1424
|
+
/** Borrowed synchronous work stays synchronous when shadow replay is disabled;
|
|
1425
|
+
* async connections or hooks retain their promise boundary. */
|
|
1426
|
+
export declare function migrate(
|
|
1427
|
+
target: BorrowedMigrationTarget, migrations: readonly unknown[], options: MigrateOptions,
|
|
1428
|
+
): MigrationResult | Promise<MigrationResult>;
|
|
1429
|
+
|
|
1430
|
+
export interface AppliedMigrationReport {
|
|
1431
|
+
applied: string[];
|
|
1432
|
+
skipped: string[];
|
|
1433
|
+
shape: string;
|
|
1434
|
+
}
|
|
1435
|
+
export interface UpToDateMigrationReport {
|
|
1436
|
+
applied: [];
|
|
1437
|
+
skipped: string[];
|
|
1438
|
+
upToDate: true;
|
|
1439
|
+
}
|
|
1440
|
+
export interface DryRunMigrationReport {
|
|
1441
|
+
dryRun: true;
|
|
1442
|
+
pending: string[];
|
|
1443
|
+
statements: string[];
|
|
1444
|
+
/** Current rows by transform collection; null when its mapped relation does
|
|
1445
|
+
* not exist yet. These are not predictions after pending SQL runs. */
|
|
1446
|
+
counts: Record<string, number | null>;
|
|
1447
|
+
shadowValidated: boolean;
|
|
1448
|
+
}
|
|
1449
|
+
export type MigrationResult = AppliedMigrationReport | UpToDateMigrationReport | DryRunMigrationReport;
|
|
1385
1450
|
/** Whether an assertion step is a per-document predicate (a FLWOR over
|
|
1386
1451
|
* `$[*]` whose body reads only its binding), which the runner evaluates
|
|
1387
1452
|
* per batch; anything else reads the collection whole. */
|
|
@@ -1396,20 +1461,33 @@ export interface MigrationStatusReport {
|
|
|
1396
1461
|
drift: string | null;
|
|
1397
1462
|
upToDate: boolean;
|
|
1398
1463
|
}
|
|
1464
|
+
export interface MigrationStatusOptions {
|
|
1465
|
+
model?: unknown;
|
|
1466
|
+
physicalTarget?: PhysicalMigrationTarget;
|
|
1467
|
+
/** Reference driver required by borrowed model-only comparison. */
|
|
1468
|
+
shadowDriver?: Driver;
|
|
1469
|
+
registerFunctions?: (connection: unknown) => unknown;
|
|
1470
|
+
signal?: AbortSignal;
|
|
1471
|
+
deadline?: number;
|
|
1472
|
+
runtime?: Partial<Runtime>;
|
|
1473
|
+
}
|
|
1399
1474
|
/** Report a database's migration state without touching it: the
|
|
1400
1475
|
* history table is probed, never created. `model` enables the drift
|
|
1401
1476
|
* comparison once the chain is fully applied. */
|
|
1402
1477
|
export declare function migrationStatus(
|
|
1403
1478
|
target: MigrationTarget,
|
|
1404
1479
|
migrations: readonly unknown[],
|
|
1405
|
-
options?:
|
|
1406
|
-
registerFunctions?: (connection: unknown) => unknown;
|
|
1407
|
-
signal?: AbortSignal; deadline?: number; runtime?: Partial<Runtime> },
|
|
1480
|
+
options?: MigrationStatusOptions,
|
|
1408
1481
|
): Promise<MigrationStatusReport>;
|
|
1482
|
+
export declare function migrationStatus(
|
|
1483
|
+
target: BorrowedMigrationTarget,
|
|
1484
|
+
migrations: readonly unknown[],
|
|
1485
|
+
options?: MigrationStatusOptions,
|
|
1486
|
+
): MigrationStatusReport | Promise<MigrationStatusReport>;
|
|
1409
1487
|
/** Create a model's whole physical shape on a connection. */
|
|
1410
1488
|
export declare function createModelShape(connection: unknown, model: unknown): unknown;
|
|
1411
|
-
/** The declared schema,
|
|
1412
|
-
export declare function schemaShapeOf(connection: unknown):
|
|
1489
|
+
/** The declared schema, preserving physical column order unless explicitly relaxed. */
|
|
1490
|
+
export declare function schemaShapeOf(connection: unknown, options?: DeclaredSqlOptions):
|
|
1413
1491
|
Promise<Array<{ type: string; name: string; owner: string; sql: string }>>
|
|
1414
1492
|
| Array<{ type: string; name: string; owner: string; sql: string }>;
|
|
1415
1493
|
/** Null when the database's shape equals a fresh build of the model. */
|
|
@@ -1473,7 +1551,7 @@ export interface DocumentMigrationOptions {
|
|
|
1473
1551
|
* source is rewindable, so the steps run exactly as a Store runs them —
|
|
1474
1552
|
* every step over the whole collection, in step order — which is what
|
|
1475
1553
|
* makes the answer, and the refusal, identical to the Store's. A step
|
|
1476
|
-
* that needs tables (`ddl`, `sql`, `rebuild`, `derive`) is refused
|
|
1554
|
+
* that needs tables (`ddl`, `sql`, `rebuild`, `derive`, `table`) is refused
|
|
1477
1555
|
* (`JD0023`) before the first document is read. */
|
|
1478
1556
|
export declare function migrateDocuments(
|
|
1479
1557
|
collections: Record<string, readonly unknown[]>,
|
|
@@ -1522,8 +1600,13 @@ export declare function stepFailure(
|
|
|
1522
1600
|
|
|
1523
1601
|
export declare function planCollection(name: string, collection: unknown, dialect: Dialect): unknown;
|
|
1524
1602
|
export declare function compileIndexPath(expression: string, docPath: string): unknown;
|
|
1603
|
+
/** Conservative declaration comparison policy. Index, trigger and constraint order is always preserved. */
|
|
1604
|
+
export interface DeclaredSqlOptions {
|
|
1605
|
+
/** Preserve physical order by default; ignore only safe managed named-column order. */
|
|
1606
|
+
columnOrder?: 'preserve' | 'ignore';
|
|
1607
|
+
}
|
|
1525
1608
|
export declare function normalizeDeclaredSql(sql: string): string;
|
|
1526
|
-
export declare function comparableDeclaredSql(sql: string): string;
|
|
1609
|
+
export declare function comparableDeclaredSql(sql: string, options?: DeclaredSqlOptions): string;
|
|
1527
1610
|
/** The comparison kind a declared schema type implies — what a column
|
|
1528
1611
|
* over that member holds, and how its expression must read it. */
|
|
1529
1612
|
export declare function columnKindFor(
|
|
@@ -2041,8 +2124,25 @@ export interface TrustedSyncSql {
|
|
|
2041
2124
|
export declare function planInvariants(model: unknown, options: { dialect: Dialect }): {
|
|
2042
2125
|
type: 'trigger'; name: string; owner: string; rule: string; sql: string;
|
|
2043
2126
|
}[];
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2127
|
+
/** A reviewed preservation document. The supplied steps retain their types;
|
|
2128
|
+
* untyped saved steps remain unknown until the caller validates them. */
|
|
2129
|
+
export interface PhysicalMigrationDocument<Steps extends readonly unknown[] = readonly unknown[]> {
|
|
2130
|
+
readonly $migration: '0.1';
|
|
2131
|
+
readonly id: string;
|
|
2132
|
+
readonly from: string;
|
|
2133
|
+
readonly to: string;
|
|
2134
|
+
readonly steps: Steps;
|
|
2135
|
+
readonly physical: {
|
|
2136
|
+
readonly source: readonly SchemaObject[];
|
|
2137
|
+
readonly dispositions: Readonly<Record<string, 'preserve' | 'replace' | 'drop'>>;
|
|
2138
|
+
readonly assertions: readonly { readonly sql: string; readonly params?: readonly unknown[]; readonly expected: readonly unknown[] }[];
|
|
2139
|
+
readonly target?: PhysicalMigrationTarget;
|
|
2140
|
+
};
|
|
2141
|
+
}
|
|
2142
|
+
/** Planning retains a synchronous connection's value boundary. */
|
|
2143
|
+
export declare function planPhysicalMigration<const Steps extends readonly unknown[]>(connection: unknown, fromModel: unknown, toModel: unknown,
|
|
2144
|
+
options: { id: string; steps: Steps; dispositions: Readonly<Record<string, 'preserve' | 'replace' | 'drop'>>;
|
|
2145
|
+
assertions?: readonly { sql: string; params?: readonly unknown[]; expected: readonly unknown[] }[];
|
|
2146
|
+
physicalTarget?: PhysicalMigrationTarget }): PhysicalMigrationDocument<Steps> | Promise<PhysicalMigrationDocument<Steps>>;
|
|
2047
2147
|
|
|
2048
2148
|
export { sql, relational, planRelational, defineTable, planTable, planTableMigration, applyTableMigration, withForeignKeysSuspended, planSchemaChange, applySchemaChange } from './relational.js';
|