edinburgh 0.4.4 → 0.4.5
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/README.md +58 -101
- package/build/src/migrate-cli.d.ts +1 -16
- package/build/src/migrate-cli.js +56 -42
- package/build/src/migrate-cli.js.map +1 -1
- package/build/src/migrate.d.ts +15 -11
- package/build/src/migrate.js +53 -39
- package/build/src/migrate.js.map +1 -1
- package/build/src/models.d.ts +1 -1
- package/build/src/models.js +2 -2
- package/build/src/models.js.map +1 -1
- package/package.json +6 -4
- package/skill/BaseIndex.md +16 -0
- package/skill/BaseIndex_batchProcess.md +10 -0
- package/skill/BaseIndex_find.md +7 -0
- package/skill/DatabaseError.md +9 -0
- package/skill/Model.md +22 -0
- package/skill/Model_delete.md +14 -0
- package/skill/Model_findAll.md +12 -0
- package/skill/Model_getPrimaryKeyHash.md +5 -0
- package/skill/Model_isValid.md +14 -0
- package/skill/Model_migrate.md +34 -0
- package/skill/Model_preCommit.md +28 -0
- package/skill/Model_preventPersist.md +15 -0
- package/skill/Model_replaceInto.md +16 -0
- package/skill/Model_validate.md +21 -0
- package/skill/PrimaryIndex.md +8 -0
- package/skill/PrimaryIndex_get.md +17 -0
- package/skill/PrimaryIndex_getLazy.md +13 -0
- package/skill/SKILL.md +90 -720
- package/skill/SecondaryIndex.md +9 -0
- package/skill/UniqueIndex.md +9 -0
- package/skill/UniqueIndex_get.md +17 -0
- package/skill/array.md +23 -0
- package/skill/dump.md +8 -0
- package/skill/field.md +29 -0
- package/skill/index.md +32 -0
- package/skill/init.md +17 -0
- package/skill/link.md +27 -0
- package/skill/literal.md +22 -0
- package/skill/opt.md +22 -0
- package/skill/or.md +22 -0
- package/skill/primary.md +26 -0
- package/skill/record.md +21 -0
- package/skill/registerModel.md +26 -0
- package/skill/runMigration.md +10 -0
- package/skill/set.md +23 -0
- package/skill/setMaxRetryCount.md +10 -0
- package/skill/setOnSaveCallback.md +12 -0
- package/skill/transact.md +49 -0
- package/skill/unique.md +32 -0
- package/src/migrate-cli.ts +44 -46
- package/src/migrate.ts +64 -46
- package/src/models.ts +2 -2
package/README.md
CHANGED
|
@@ -388,13 +388,9 @@ await Product.byCategory.batchProcess({is: "old"}, (product) => {
|
|
|
388
388
|
// Commits every ~1 second or 4096 rows (configurable via limitSeconds, limitRows)
|
|
389
389
|
```
|
|
390
390
|
|
|
391
|
-
### Schema
|
|
391
|
+
### Lazy Schema Migrations
|
|
392
392
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
- **Adding/removing fields**: Old rows are lazily migrated on read. New fields use their default value.
|
|
396
|
-
- **Changing field types**: Requires a `static migrate()` function.
|
|
397
|
-
- **Adding/removing indexes**: Requires running `npx migrate-edinburgh`.
|
|
393
|
+
When you change a model's schema, Edinburgh will lazily try to migrate old records on access. This allows you to deploy code changes without downtime or a separate migration step. Optionally, you may provide a `static migrate(record: Record<string, any>)` function on the model to transform old records during lazy migration. If there is a migration error (like a new field without a default value, or an incompatible type change), a run-time error is thrown when loading the affected model instance.
|
|
398
394
|
|
|
399
395
|
```typescript
|
|
400
396
|
@E.registerModel
|
|
@@ -402,15 +398,40 @@ class User extends E.Model<User> {
|
|
|
402
398
|
static pk = E.primary(User, "id");
|
|
403
399
|
id = E.field(E.identifier);
|
|
404
400
|
name = E.field(E.string);
|
|
405
|
-
role = E.field(E.string
|
|
401
|
+
role = E.field(E.string); // newly added field
|
|
406
402
|
|
|
407
403
|
static migrate(record: Record<string, any>) {
|
|
408
|
-
record.role ??= "user";
|
|
404
|
+
record.role ??= record.name.indexOf("admin") >= 0 ? "admin" : "user"; // set role based on name for old records
|
|
409
405
|
}
|
|
410
406
|
}
|
|
411
407
|
```
|
|
412
408
|
|
|
413
|
-
|
|
409
|
+
Edinburgh will lazily (re)run the `migrate` function on an instance whenever its implementation (the literal function code) has changed. For robustness, make sure that your `migrate` function...
|
|
410
|
+
- Is idempotent (meaning it can be safely run multiple times on the same row without changing the result after the first run), and
|
|
411
|
+
- Should perform *all* transformation steps starting from the oldest version that could possibly still be in the database. (See the next section.)
|
|
412
|
+
|
|
413
|
+
While lazy migration is convenient and often sufficient, in some cases you need migrations to happen immediately...
|
|
414
|
+
|
|
415
|
+
### Forced Schema Migrations
|
|
416
|
+
|
|
417
|
+
The `migrate-edinburgh` CLI tool will scan the entire database, pro-actively performing the following migrations:
|
|
418
|
+
- **Populate secondary indexes**: If you added or changed secondary indexes, it will build them. Until you do, the indexes will be empty (or only contain instances that have been saved since the index was created).
|
|
419
|
+
- **Migrate primary indexes**: In case you changed the primary key fields or field types (not recommended!) of a model, it will build the new primary index, as well as all secondary indexes (to point at the new primary keys). Until you do, all of your old data will appear to be missing! Note that this may fail on duplicates.
|
|
420
|
+
- **Remove orphaned indexes**: If you removed or changed an index, the stale data will be deleted from the database.
|
|
421
|
+
- **Rewrite primary data**: These are the types of migrations that would normally be done lazily on instance access. As there's usually not much benefit to doing this forcibly, and it can be very time-consuming (and generates a lot of I/O), this is *not* done by default. It may however be useful if you want to clean up the contents of your `migrate()` function, if you have control over all application deployments. Use the `--rewrite-data` flag to enable this.
|
|
422
|
+
|
|
423
|
+
```bash
|
|
424
|
+
npx migrate-edinburgh ./src/models.ts
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Run `npx migrate-edinburgh` without arguments to see all options. You can also call `runMigration()` programmatically:
|
|
428
|
+
|
|
429
|
+
```typescript
|
|
430
|
+
import { runMigration } from "edinburgh";
|
|
431
|
+
|
|
432
|
+
const result = await runMigration({ tables: ["User"] });
|
|
433
|
+
console.log(result.secondaries); // { User: 1500 }
|
|
434
|
+
```
|
|
414
435
|
|
|
415
436
|
### preCommit Hook
|
|
416
437
|
|
|
@@ -687,9 +708,6 @@ Common use cases:
|
|
|
687
708
|
|
|
688
709
|
**Signature:** `() => void`
|
|
689
710
|
|
|
690
|
-
**Parameters:**
|
|
691
|
-
|
|
692
|
-
|
|
693
711
|
**Examples:**
|
|
694
712
|
|
|
695
713
|
```typescript
|
|
@@ -710,18 +728,12 @@ class Post extends E.Model<Post> {
|
|
|
710
728
|
|
|
711
729
|
**Signature:** `() => Uint8Array<ArrayBufferLike>`
|
|
712
730
|
|
|
713
|
-
**Parameters:**
|
|
714
|
-
|
|
715
|
-
|
|
716
731
|
**Returns:** The primary key for this instance.
|
|
717
732
|
|
|
718
733
|
#### model.getPrimaryKeyHash · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
719
734
|
|
|
720
735
|
**Signature:** `() => number`
|
|
721
736
|
|
|
722
|
-
**Parameters:**
|
|
723
|
-
|
|
724
|
-
|
|
725
737
|
**Returns:** A 53-bit positive integer non-cryptographic hash of the primary key, or undefined if not yet saved.
|
|
726
738
|
|
|
727
739
|
#### model.isLazyField · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
@@ -738,9 +750,6 @@ Prevent this instance from being persisted to the database.
|
|
|
738
750
|
|
|
739
751
|
**Signature:** `() => this`
|
|
740
752
|
|
|
741
|
-
**Parameters:**
|
|
742
|
-
|
|
743
|
-
|
|
744
753
|
**Returns:** This model instance for chaining.
|
|
745
754
|
|
|
746
755
|
**Examples:**
|
|
@@ -759,9 +768,6 @@ Removes the instance and all its index entries from the database and prevents fu
|
|
|
759
768
|
|
|
760
769
|
**Signature:** `() => void`
|
|
761
770
|
|
|
762
|
-
**Parameters:**
|
|
763
|
-
|
|
764
|
-
|
|
765
771
|
**Examples:**
|
|
766
772
|
|
|
767
773
|
```typescript
|
|
@@ -797,9 +803,6 @@ Check if this model instance is valid.
|
|
|
797
803
|
|
|
798
804
|
**Signature:** `() => boolean`
|
|
799
805
|
|
|
800
|
-
**Parameters:**
|
|
801
|
-
|
|
802
|
-
|
|
803
806
|
**Returns:** true if all validations pass.
|
|
804
807
|
|
|
805
808
|
**Examples:**
|
|
@@ -813,23 +816,14 @@ if (!user.isValid()) shoutAtTheUser();
|
|
|
813
816
|
|
|
814
817
|
**Signature:** `() => "created" | "deleted" | "loaded" | "lazy"`
|
|
815
818
|
|
|
816
|
-
**Parameters:**
|
|
817
|
-
|
|
818
|
-
|
|
819
819
|
#### model.toString · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
820
820
|
|
|
821
821
|
**Signature:** `() => string`
|
|
822
822
|
|
|
823
|
-
**Parameters:**
|
|
824
|
-
|
|
825
|
-
|
|
826
823
|
#### model.[Symbol.for('nodejs.util.inspect.custom')] · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
827
824
|
|
|
828
825
|
**Signature:** `() => string`
|
|
829
826
|
|
|
830
|
-
**Parameters:**
|
|
831
|
-
|
|
832
|
-
|
|
833
827
|
### registerModel · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L113)
|
|
834
828
|
|
|
835
829
|
Register a model class with the Edinburgh ORM system.
|
|
@@ -1242,9 +1236,6 @@ Indexes enable fast queries on specific field combinations and enforce uniquenes
|
|
|
1242
1236
|
|
|
1243
1237
|
**Signature:** `() => string`
|
|
1244
1238
|
|
|
1245
|
-
**Parameters:**
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
1239
|
### UniqueIndex · [class](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L253)
|
|
1249
1240
|
|
|
1250
1241
|
Unique index that stores references to the primary key.
|
|
@@ -1352,10 +1343,10 @@ Invalid function arguments will throw TypeError.
|
|
|
1352
1343
|
|
|
1353
1344
|
**Value:** `DatabaseErrorConstructor`
|
|
1354
1345
|
|
|
1355
|
-
### runMigration · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1346
|
+
### runMigration · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L124)
|
|
1356
1347
|
|
|
1357
|
-
Run database migration:
|
|
1358
|
-
convert old primary indices, and clean up orphaned
|
|
1348
|
+
Run database migration: populate secondary indexes for old-version rows,
|
|
1349
|
+
convert old primary indices, rewrite row data, and clean up orphaned indices.
|
|
1359
1350
|
|
|
1360
1351
|
**Signature:** `(options?: MigrationOptions) => Promise<MigrationResult>`
|
|
1361
1352
|
|
|
@@ -1371,99 +1362,65 @@ Limit migration to specific table names.
|
|
|
1371
1362
|
|
|
1372
1363
|
**Type:** `string[]`
|
|
1373
1364
|
|
|
1374
|
-
#### migrationOptions.
|
|
1365
|
+
#### migrationOptions.populateSecondaries · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L23)
|
|
1375
1366
|
|
|
1376
|
-
|
|
1367
|
+
Populate secondary indexes for rows at old schema versions (default: true).
|
|
1377
1368
|
|
|
1378
1369
|
**Type:** `boolean`
|
|
1379
1370
|
|
|
1380
|
-
#### migrationOptions.
|
|
1371
|
+
#### migrationOptions.migratePrimaries · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L32)
|
|
1381
1372
|
|
|
1382
|
-
|
|
1373
|
+
Convert old primary indices when primary key fields changed (default: true).
|
|
1383
1374
|
|
|
1384
1375
|
**Type:** `boolean`
|
|
1385
1376
|
|
|
1386
|
-
#### migrationOptions.
|
|
1377
|
+
#### migrationOptions.rewriteData · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L40)
|
|
1387
1378
|
|
|
1388
|
-
|
|
1379
|
+
Rewrite all row data to the latest schema version (default: false).
|
|
1389
1380
|
|
|
1390
1381
|
**Type:** `boolean`
|
|
1391
1382
|
|
|
1392
|
-
#### migrationOptions.
|
|
1383
|
+
#### migrationOptions.removeOrphans · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L46)
|
|
1384
|
+
|
|
1385
|
+
Delete orphaned secondary/unique index entries (default: true).
|
|
1386
|
+
|
|
1387
|
+
**Type:** `boolean`
|
|
1388
|
+
|
|
1389
|
+
#### migrationOptions.onProgress · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L48)
|
|
1393
1390
|
|
|
1394
1391
|
Progress callback.
|
|
1395
1392
|
|
|
1396
1393
|
**Type:** `(info: ProgressInfo) => void`
|
|
1397
1394
|
|
|
1398
|
-
### MigrationResult · [interface](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1395
|
+
### MigrationResult · [interface](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L51)
|
|
1399
1396
|
|
|
1400
|
-
#### migrationResult.secondaries · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1397
|
+
#### migrationResult.secondaries · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L54)
|
|
1401
1398
|
|
|
1402
|
-
Per-table
|
|
1399
|
+
Per-table counts of secondary index entries populated.
|
|
1403
1400
|
|
|
1404
1401
|
**Type:** `Record<string, number>`
|
|
1405
1402
|
|
|
1406
|
-
#### migrationResult.primaries · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1403
|
+
#### migrationResult.primaries · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L59)
|
|
1407
1404
|
|
|
1408
|
-
Per-table
|
|
1405
|
+
Per-table counts of old primary rows migrated.
|
|
1409
1406
|
|
|
1410
1407
|
**Type:** `Record<string, number>`
|
|
1411
1408
|
|
|
1412
|
-
#### migrationResult.conversionFailures · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1409
|
+
#### migrationResult.conversionFailures · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L59)
|
|
1413
1410
|
|
|
1414
1411
|
Per-table conversion failure counts by reason.
|
|
1415
1412
|
|
|
1416
1413
|
**Type:** `Record<string, Record<string, number>>`
|
|
1417
1414
|
|
|
1418
|
-
#### migrationResult.
|
|
1415
|
+
#### migrationResult.rewritten · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L64)
|
|
1419
1416
|
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
**Type:** `number`
|
|
1417
|
+
Per-table counts of rows rewritten to latest version.
|
|
1423
1418
|
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
Edinburgh automatically tracks the schema version of each model. When you change fields, field types, indexes, or the `migrate()` function, Edinburgh detects a new schema version.
|
|
1427
|
-
|
|
1428
|
-
### What happens automatically (lazy migration)
|
|
1429
|
-
|
|
1430
|
-
Changes to regular (non-index) field values are migrated lazily. When a row with an old schema version is loaded from disk, it is deserialized using the old field types and transformed by the optional static `migrate()` function. This is transparent and requires no downtime.
|
|
1431
|
-
|
|
1432
|
-
```typescript
|
|
1433
|
-
@E.registerModel
|
|
1434
|
-
class User extends E.Model<User> {
|
|
1435
|
-
static pk = E.primary(User, "id");
|
|
1436
|
-
id = E.field(E.identifier);
|
|
1437
|
-
name = E.field(E.string);
|
|
1438
|
-
role = E.field(E.string); // newly added field
|
|
1439
|
-
|
|
1440
|
-
static migrate(record: Record<string, any>) {
|
|
1441
|
-
record.role ??= "user"; // provide a default for old rows
|
|
1442
|
-
}
|
|
1443
|
-
}
|
|
1444
|
-
```
|
|
1445
|
-
|
|
1446
|
-
### What requires `migrate-edinburgh`
|
|
1447
|
-
|
|
1448
|
-
The `migrate-edinburgh` CLI tool (or the `runMigration()` API) must be run when:
|
|
1449
|
-
|
|
1450
|
-
- **Adding or removing** secondary or unique indexes
|
|
1451
|
-
- **Changing the fields or types** of an existing index
|
|
1452
|
-
- A **`migrate()` function changes values** that are used in index fields
|
|
1453
|
-
|
|
1454
|
-
The tool populates new indexes, removes orphaned ones, and updates index entries whose values were changed by `migrate()`. It does *not* rewrite primary data rows - lazy migration handles that on read.
|
|
1455
|
-
|
|
1456
|
-
```bash
|
|
1457
|
-
npx migrate-edinburgh --import ./src/models.ts
|
|
1458
|
-
```
|
|
1419
|
+
**Type:** `Record<string, number>`
|
|
1459
1420
|
|
|
1460
|
-
|
|
1421
|
+
#### migrationResult.orphans · [member](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L68)
|
|
1461
1422
|
|
|
1462
|
-
|
|
1423
|
+
Number of orphaned index entries deleted.
|
|
1463
1424
|
|
|
1464
|
-
|
|
1465
|
-
import { runMigration } from "edinburgh";
|
|
1425
|
+
**Type:** `number`
|
|
1466
1426
|
|
|
1467
|
-
const result = await runMigration({ tables: ["User"] });
|
|
1468
|
-
console.log(result.upgraded); // { User: 1500 }
|
|
1469
|
-
```
|
|
@@ -1,20 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* migrate-edinburgh
|
|
4
|
-
*
|
|
5
|
-
* Runs database migrations: upgrades all rows to the latest schema version,
|
|
6
|
-
* converts old primary indices, and cleans up orphaned secondary indices.
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* npx migrate-edinburgh --import ./src/models.ts [options]
|
|
10
|
-
*
|
|
11
|
-
* Options:
|
|
12
|
-
* --import <path> Path to the module that registers all models (required)
|
|
13
|
-
* --db <path> Database directory (default: .edinburgh)
|
|
14
|
-
* --tables <names> Comma-separated list of table names to migrate
|
|
15
|
-
* --batch-size <n> Number of rows per transaction batch (default: 500)
|
|
16
|
-
* --no-convert Skip converting old primary indices
|
|
17
|
-
* --no-cleanup Skip deleting orphaned secondary indices
|
|
18
|
-
* --no-upgrade Skip upgrading rows to latest version
|
|
3
|
+
* See `npx migrate-edinburgh --help` for usage.
|
|
19
4
|
*/
|
|
20
5
|
export {};
|
package/build/src/migrate-cli.js
CHANGED
|
@@ -1,61 +1,69 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* migrate-edinburgh
|
|
4
|
-
*
|
|
5
|
-
* Runs database migrations: upgrades all rows to the latest schema version,
|
|
6
|
-
* converts old primary indices, and cleans up orphaned secondary indices.
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* npx migrate-edinburgh --import ./src/models.ts [options]
|
|
10
|
-
*
|
|
11
|
-
* Options:
|
|
12
|
-
* --import <path> Path to the module that registers all models (required)
|
|
13
|
-
* --db <path> Database directory (default: .edinburgh)
|
|
14
|
-
* --tables <names> Comma-separated list of table names to migrate
|
|
15
|
-
* --batch-size <n> Number of rows per transaction batch (default: 500)
|
|
16
|
-
* --no-convert Skip converting old primary indices
|
|
17
|
-
* --no-cleanup Skip deleting orphaned secondary indices
|
|
18
|
-
* --no-upgrade Skip upgrading rows to latest version
|
|
3
|
+
* See `npx migrate-edinburgh --help` for usage.
|
|
19
4
|
*/
|
|
20
5
|
import { runMigration } from './migrate.js';
|
|
21
6
|
function parseArgs(args) {
|
|
22
7
|
let importPath = '';
|
|
23
8
|
const options = {};
|
|
9
|
+
const tables = [];
|
|
24
10
|
for (let i = 0; i < args.length; i++) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
importPath = args[++i];
|
|
28
|
-
break;
|
|
11
|
+
const arg = args[i];
|
|
12
|
+
switch (arg) {
|
|
29
13
|
case '--db':
|
|
30
14
|
options.dbDir = args[++i];
|
|
31
15
|
break;
|
|
32
|
-
case '
|
|
33
|
-
options.
|
|
16
|
+
case '+secondaries':
|
|
17
|
+
options.populateSecondaries = true;
|
|
18
|
+
break;
|
|
19
|
+
case '-secondaries':
|
|
20
|
+
options.populateSecondaries = false;
|
|
21
|
+
break;
|
|
22
|
+
case '+primaries':
|
|
23
|
+
options.migratePrimaries = true;
|
|
24
|
+
break;
|
|
25
|
+
case '-primaries':
|
|
26
|
+
options.migratePrimaries = false;
|
|
27
|
+
break;
|
|
28
|
+
case '+data':
|
|
29
|
+
options.rewriteData = true;
|
|
34
30
|
break;
|
|
35
|
-
case '
|
|
36
|
-
options.
|
|
31
|
+
case '-data':
|
|
32
|
+
options.rewriteData = false;
|
|
37
33
|
break;
|
|
38
|
-
case '
|
|
39
|
-
options.
|
|
34
|
+
case '+orphans':
|
|
35
|
+
options.removeOrphans = true;
|
|
40
36
|
break;
|
|
41
|
-
case '
|
|
42
|
-
options.
|
|
37
|
+
case '-orphans':
|
|
38
|
+
options.removeOrphans = false;
|
|
43
39
|
break;
|
|
44
40
|
default:
|
|
45
|
-
if (
|
|
46
|
-
console.error(`Unknown option: ${
|
|
41
|
+
if (arg.startsWith('-') || arg.startsWith('+')) {
|
|
42
|
+
console.error(`Unknown option: ${arg}`);
|
|
47
43
|
process.exit(1);
|
|
48
44
|
}
|
|
45
|
+
if (!importPath) {
|
|
46
|
+
importPath = arg;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
tables.push(arg);
|
|
50
|
+
}
|
|
49
51
|
}
|
|
50
52
|
}
|
|
53
|
+
if (tables.length > 0)
|
|
54
|
+
options.tables = tables;
|
|
51
55
|
if (!importPath) {
|
|
52
|
-
console.error('Usage: npx migrate-edinburgh
|
|
53
|
-
console.error('
|
|
54
|
-
console.error('
|
|
55
|
-
console.error('
|
|
56
|
-
console.error('
|
|
57
|
-
console.error('
|
|
58
|
-
console.error(' --
|
|
56
|
+
console.error('Usage: npx migrate-edinburgh <import_path> [<table> ...] [options]');
|
|
57
|
+
console.error('');
|
|
58
|
+
console.error(' <import_path> Module that registers all models (required)');
|
|
59
|
+
console.error(' <table> Table names to migrate (default: all)');
|
|
60
|
+
console.error('');
|
|
61
|
+
console.error('Options:');
|
|
62
|
+
console.error(' --db <path> Database directory (default: .edinburgh)');
|
|
63
|
+
console.error(' -secondaries Skip populating secondary indexes');
|
|
64
|
+
console.error(' -primaries Skip migrating old primary indexes');
|
|
65
|
+
console.error(' -orphans Skip removing orphaned index entries');
|
|
66
|
+
console.error(' +data Rewrite all row data to latest schema version');
|
|
59
67
|
process.exit(1);
|
|
60
68
|
}
|
|
61
69
|
return { importPath, options };
|
|
@@ -88,13 +96,19 @@ async function main() {
|
|
|
88
96
|
console.log('\n');
|
|
89
97
|
// Report results
|
|
90
98
|
if (Object.keys(result.secondaries).length > 0) {
|
|
91
|
-
console.log('
|
|
99
|
+
console.log('Populated secondary indexes:');
|
|
92
100
|
for (const [table, count] of Object.entries(result.secondaries)) {
|
|
93
101
|
console.log(` ${table}: ${count}`);
|
|
94
102
|
}
|
|
95
103
|
}
|
|
104
|
+
if (Object.keys(result.rewritten).length > 0) {
|
|
105
|
+
console.log('Rewritten rows:');
|
|
106
|
+
for (const [table, count] of Object.entries(result.rewritten)) {
|
|
107
|
+
console.log(` ${table}: ${count}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
96
110
|
if (Object.keys(result.primaries).length > 0) {
|
|
97
|
-
console.log('
|
|
111
|
+
console.log('Migrated old primary rows:');
|
|
98
112
|
for (const [table, count] of Object.entries(result.primaries)) {
|
|
99
113
|
console.log(` ${table}: ${count}`);
|
|
100
114
|
}
|
|
@@ -107,10 +121,10 @@ async function main() {
|
|
|
107
121
|
}
|
|
108
122
|
}
|
|
109
123
|
}
|
|
110
|
-
if (result.
|
|
111
|
-
console.log(`Deleted ${result.
|
|
124
|
+
if (result.orphans > 0) {
|
|
125
|
+
console.log(`Deleted ${result.orphans} orphaned index entries`);
|
|
112
126
|
}
|
|
113
|
-
if (Object.keys(result.secondaries).length === 0 && Object.keys(result.primaries).length === 0 && result.
|
|
127
|
+
if (Object.keys(result.secondaries).length === 0 && Object.keys(result.primaries).length === 0 && Object.keys(result.rewritten).length === 0 && result.orphans === 0) {
|
|
114
128
|
console.log('No migration needed - database is up to date.');
|
|
115
129
|
}
|
|
116
130
|
console.log('Done.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-cli.js","sourceRoot":"","sources":["../../src/migrate-cli.ts"],"names":[],"mappings":";AAEA
|
|
1
|
+
{"version":3,"file":"migrate-cli.js","sourceRoot":"","sources":["../../src/migrate-cli.ts"],"names":[],"mappings":"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"}
|
package/build/src/migrate.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
export interface MigrationOptions {
|
|
2
2
|
/** Limit migration to specific table names. */
|
|
3
3
|
tables?: string[];
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
|
|
4
|
+
/** Populate secondary indexes for rows at old schema versions (default: true). */
|
|
5
|
+
populateSecondaries?: boolean;
|
|
6
|
+
/** Convert old primary indices when primary key fields changed (default: true). */
|
|
7
|
+
migratePrimaries?: boolean;
|
|
8
|
+
/** Rewrite all row data to the latest schema version (default: false). */
|
|
9
|
+
rewriteData?: boolean;
|
|
10
|
+
/** Delete orphaned secondary/unique index entries (default: true). */
|
|
11
|
+
removeOrphans?: boolean;
|
|
10
12
|
/** Progress callback. */
|
|
11
13
|
onProgress?: (info: ProgressInfo) => void;
|
|
12
14
|
}
|
|
@@ -17,17 +19,19 @@ export interface ProgressInfo {
|
|
|
17
19
|
table?: string;
|
|
18
20
|
}
|
|
19
21
|
export interface MigrationResult {
|
|
20
|
-
/** Per-table
|
|
22
|
+
/** Per-table counts of secondary index entries populated. */
|
|
21
23
|
secondaries: Record<string, number>;
|
|
22
|
-
/** Per-table
|
|
24
|
+
/** Per-table counts of old primary rows migrated. */
|
|
23
25
|
primaries: Record<string, number>;
|
|
24
26
|
/** Per-table conversion failure counts by reason. */
|
|
25
27
|
conversionFailures: Record<string, Record<string, number>>;
|
|
28
|
+
/** Per-table counts of rows rewritten to latest version. */
|
|
29
|
+
rewritten: Record<string, number>;
|
|
26
30
|
/** Number of orphaned index entries deleted. */
|
|
27
|
-
|
|
31
|
+
orphans: number;
|
|
28
32
|
}
|
|
29
33
|
/**
|
|
30
|
-
* Run database migration:
|
|
31
|
-
* convert old primary indices, and clean up orphaned
|
|
34
|
+
* Run database migration: populate secondary indexes for old-version rows,
|
|
35
|
+
* convert old primary indices, rewrite row data, and clean up orphaned indices.
|
|
32
36
|
*/
|
|
33
37
|
export declare function runMigration(options?: MigrationOptions): Promise<MigrationResult>;
|