ts-prorm-orm 1.1.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/CHANGELOG.md +1111 -0
- package/LICENSE +21 -0
- package/README.md +573 -0
- package/dist/audit/history-query.js +180 -0
- package/dist/audit/index.js +23 -0
- package/dist/audit/logger.js +236 -0
- package/dist/cache/cache-manager.js +84 -0
- package/dist/cache/index.js +16 -0
- package/dist/cache/redis-cluster-cache.js +557 -0
- package/dist/cli.js +2200 -0
- package/dist/compliance/audit-trail.js +68 -0
- package/dist/compliance/backup-verification.js +685 -0
- package/dist/compliance/breach-detector.js +505 -0
- package/dist/compliance/consent-record.js +227 -0
- package/dist/compliance/consent-versioning.js +331 -0
- package/dist/compliance/cross-border-log.js +530 -0
- package/dist/compliance/data-classifier.js +258 -0
- package/dist/compliance/data-lineage.js +565 -0
- package/dist/compliance/data-masker.js +303 -0
- package/dist/compliance/data-portability.js +265 -0
- package/dist/compliance/data-retention.js +195 -0
- package/dist/compliance/dsar-workflow.js +342 -0
- package/dist/compliance/field-encryption.js +223 -0
- package/dist/compliance/immutable-record.js +148 -0
- package/dist/compliance/index.js +260 -0
- package/dist/compliance/privacy-impact-assessment.js +364 -0
- package/dist/compliance/pseudonymization.js +269 -0
- package/dist/compliance/query-firewall.js +1182 -0
- package/dist/compliance/rate-limiter.js +580 -0
- package/dist/compliance/right-to-erasure.js +117 -0
- package/dist/compliance/row-level-security.js +246 -0
- package/dist/compliance/security-decorator.js +574 -0
- package/dist/compliance/security-monitor.js +525 -0
- package/dist/compliance/sensitive-data-discovery.js +476 -0
- package/dist/compliance/session-isolation.js +472 -0
- package/dist/compliance/tls-enforcer.js +108 -0
- package/dist/compliance/worm-storage.js +712 -0
- package/dist/connection-manager.js +198 -0
- package/dist/connection-pool.js +519 -0
- package/dist/decorators/audit.js +136 -0
- package/dist/decorators/belongs-to-many.js +115 -0
- package/dist/decorators/belongs-to.js +115 -0
- package/dist/decorators/check.js +435 -0
- package/dist/decorators/collate.js +329 -0
- package/dist/decorators/comment.js +205 -0
- package/dist/decorators/database-settings.js +236 -0
- package/dist/decorators/default.js +244 -0
- package/dist/decorators/encryption.js +235 -0
- package/dist/decorators/engine.js +97 -0
- package/dist/decorators/fk-constraints.js +594 -0
- package/dist/decorators/foreign-table.js +136 -0
- package/dist/decorators/generated.js +274 -0
- package/dist/decorators/has-many.js +127 -0
- package/dist/decorators/has-one.js +116 -0
- package/dist/decorators/hstore.js +129 -0
- package/dist/decorators/index.js +355 -0
- package/dist/decorators/json-column.js +83 -0
- package/dist/decorators/jsonb.js +101 -0
- package/dist/decorators/orm-decorators.js +425 -0
- package/dist/decorators/permissions.js +294 -0
- package/dist/decorators/procedure.js +210 -0
- package/dist/decorators/query-options.js +556 -0
- package/dist/decorators/range.js +167 -0
- package/dist/decorators/set-column.js +83 -0
- package/dist/decorators/spatial.js +114 -0
- package/dist/decorators/storage.js +580 -0
- package/dist/decorators/timezone.js +512 -0
- package/dist/decorators/trigger.js +90 -0
- package/dist/decorators/uuid.js +135 -0
- package/dist/decorators/view.js +258 -0
- package/dist/diagrams/chen-diagram.js +354 -0
- package/dist/diagrams/class-diagram.js +384 -0
- package/dist/diagrams/dependency-diagram.js +432 -0
- package/dist/diagrams/er-diagram.js +605 -0
- package/dist/diagrams/flow-diagram.js +394 -0
- package/dist/diagrams/gantt-diagram.js +411 -0
- package/dist/diagrams/index-diagram.js +353 -0
- package/dist/diagrams/index.js +184 -0
- package/dist/diagrams/migration-diagram.js +316 -0
- package/dist/diagrams/model-diagram.js +616 -0
- package/dist/diagrams/package-diagram.js +376 -0
- package/dist/diagrams/palette.js +85 -0
- package/dist/diagrams/relational-diagram.js +455 -0
- package/dist/diagrams/schemadoc-diagram.js +309 -0
- package/dist/diagrams/sequence-diagram.js +307 -0
- package/dist/diagrams/state-diagram.js +344 -0
- package/dist/diagrams/svg-dom.js +111 -0
- package/dist/diagrams/tree-diagram.js +250 -0
- package/dist/dialects/clickhouse/index.js +1742 -0
- package/dist/dialects/cockroachdb/index.js +4677 -0
- package/dist/dialects/cratedb/index.js +441 -0
- package/dist/dialects/databricks/index.js +517 -0
- package/dist/dialects/db2/index.js +2225 -0
- package/dist/dialects/dialect.js +720 -0
- package/dist/dialects/duckdb/index.js +2014 -0
- package/dist/dialects/exasol/index.js +357 -0
- package/dist/dialects/firebird/index.js +495 -0
- package/dist/dialects/greenplum/index.js +457 -0
- package/dist/dialects/hana/index.js +1741 -0
- package/dist/dialects/mariadb/index.js +3590 -0
- package/dist/dialects/mssql/index.js +2296 -0
- package/dist/dialects/mysql/index.js +4058 -0
- package/dist/dialects/oracle/index.js +2999 -0
- package/dist/dialects/postgres/index.js +5319 -0
- package/dist/dialects/query-stream-helper.js +152 -0
- package/dist/dialects/questdb/index.js +433 -0
- package/dist/dialects/redshift/index.js +2277 -0
- package/dist/dialects/singlestore/index.js +354 -0
- package/dist/dialects/snowflake/index.js +2082 -0
- package/dist/dialects/spanner/index.js +1768 -0
- package/dist/dialects/sqlite/index.js +3382 -0
- package/dist/dialects/tidb/index.js +377 -0
- package/dist/dialects/timescaledb/index.js +164 -0
- package/dist/dialects/trino/index.js +420 -0
- package/dist/dialects/turso/index.js +227 -0
- package/dist/dialects/vertica/index.js +317 -0
- package/dist/dialects/yugabytedb/index.js +424 -0
- package/dist/errors/index.js +472 -0
- package/dist/errors/utils.js +340 -0
- package/dist/errors.js +21 -0
- package/dist/extensions/catalog/cloud-warehouse-features.js +207 -0
- package/dist/extensions/catalog/mssql-features.js +147 -0
- package/dist/extensions/catalog/mysql-mariadb-plugins.js +229 -0
- package/dist/extensions/catalog/oracle-db2-features.js +196 -0
- package/dist/extensions/catalog/postgres-extensions.js +516 -0
- package/dist/extensions/index.js +71 -0
- package/dist/extensions/types.js +13 -0
- package/dist/foreign-data.js +173 -0
- package/dist/hooks/hooks-manager.js +350 -0
- package/dist/hooks/index.js +37 -0
- package/dist/index.js +463 -0
- package/dist/logging.js +335 -0
- package/dist/migrations/index.js +40 -0
- package/dist/migrations/migration.js +196 -0
- package/dist/migrations/migrator.js +411 -0
- package/dist/migrations/prormmigration.js +275 -0
- package/dist/migrations/query-interface.js +435 -0
- package/dist/migrations/seeder.js +353 -0
- package/dist/models/associations.js +852 -0
- package/dist/models/constraints.js +288 -0
- package/dist/models/data-types.js +2518 -0
- package/dist/models/decorators.js +445 -0
- package/dist/models/index.js +33 -0
- package/dist/models/indexes.js +531 -0
- package/dist/models/methods.js +382 -0
- package/dist/models/model-manager.js +103 -0
- package/dist/models/model.js +5349 -0
- package/dist/models/operators.js +67 -0
- package/dist/models/scopes.js +189 -0
- package/dist/models/typescript-types.js +26 -0
- package/dist/nosql/aerospike/index.js +205 -0
- package/dist/nosql/allegrograph/index.js +169 -0
- package/dist/nosql/arangodb/index.js +364 -0
- package/dist/nosql/azure-blob/index.js +206 -0
- package/dist/nosql/beanstalkd/index.js +231 -0
- package/dist/nosql/beequeue/index.js +210 -0
- package/dist/nosql/bigchaindb/index.js +195 -0
- package/dist/nosql/bigtable/index.js +224 -0
- package/dist/nosql/blazegraph/index.js +173 -0
- package/dist/nosql/bullmq/index.js +191 -0
- package/dist/nosql/cassandra/index.js +174 -0
- package/dist/nosql/chroma/index.js +190 -0
- package/dist/nosql/cloudflare-kv/index.js +220 -0
- package/dist/nosql/coherence/index.js +200 -0
- package/dist/nosql/cosmosdb/index.js +157 -0
- package/dist/nosql/couchbase/index.js +213 -0
- package/dist/nosql/dax/index.js +212 -0
- package/dist/nosql/deno-kv/index.js +206 -0
- package/dist/nosql/dgraph/index.js +171 -0
- package/dist/nosql/doris/index.js +169 -0
- package/dist/nosql/druid/index.js +162 -0
- package/dist/nosql/dynamodb/index.js +937 -0
- package/dist/nosql/elasticsearch/index.js +377 -0
- package/dist/nosql/etcd/index.js +502 -0
- package/dist/nosql/eventhubs/index.js +213 -0
- package/dist/nosql/eventstore/index.js +254 -0
- package/dist/nosql/faunadb/index.js +188 -0
- package/dist/nosql/firestore/index.js +177 -0
- package/dist/nosql/fluree/index.js +148 -0
- package/dist/nosql/fuseki/index.js +170 -0
- package/dist/nosql/gcs/index.js +172 -0
- package/dist/nosql/gearman/index.js +160 -0
- package/dist/nosql/geode/index.js +196 -0
- package/dist/nosql/graphdb/index.js +169 -0
- package/dist/nosql/graylog/index.js +188 -0
- package/dist/nosql/gridgain/index.js +171 -0
- package/dist/nosql/hazelcast/index.js +162 -0
- package/dist/nosql/hbase/index.js +230 -0
- package/dist/nosql/ignite/index.js +173 -0
- package/dist/nosql/immudb/index.js +184 -0
- package/dist/nosql/index.js +232 -0
- package/dist/nosql/infinispan/index.js +200 -0
- package/dist/nosql/influxdb/index.js +0 -0
- package/dist/nosql/kafka/index.js +234 -0
- package/dist/nosql/keyspaces/index.js +189 -0
- package/dist/nosql/kinesis/index.js +253 -0
- package/dist/nosql/leveldb/index.js +153 -0
- package/dist/nosql/lmdb/index.js +160 -0
- package/dist/nosql/loki/index.js +201 -0
- package/dist/nosql/marklogic/index.js +204 -0
- package/dist/nosql/materialize/index.js +145 -0
- package/dist/nosql/meilisearch/index.js +154 -0
- package/dist/nosql/memcached/index.js +223 -0
- package/dist/nosql/milvus/index.js +410 -0
- package/dist/nosql/minio/index.js +265 -0
- package/dist/nosql/momento/index.js +179 -0
- package/dist/nosql/mongodb/index.js +461 -0
- package/dist/nosql/nats/index.js +247 -0
- package/dist/nosql/nedb/index.js +164 -0
- package/dist/nosql/neo4j/index.js +450 -0
- package/dist/nosql/neptune/index.js +470 -0
- package/dist/nosql/nsq/index.js +200 -0
- package/dist/nosql/opensearch/index.js +186 -0
- package/dist/nosql/orientdb/index.js +175 -0
- package/dist/nosql/papertrail/index.js +200 -0
- package/dist/nosql/pinecone/index.js +0 -0
- package/dist/nosql/pinot/index.js +133 -0
- package/dist/nosql/pouchdb/index.js +172 -0
- package/dist/nosql/prometheus/index.js +174 -0
- package/dist/nosql/provendb/index.js +147 -0
- package/dist/nosql/pubsub/index.js +187 -0
- package/dist/nosql/pulsar/index.js +232 -0
- package/dist/nosql/qdrant/index.js +295 -0
- package/dist/nosql/qldb/index.js +192 -0
- package/dist/nosql/r2/index.js +281 -0
- package/dist/nosql/rabbitmq/index.js +237 -0
- package/dist/nosql/ravendb/index.js +175 -0
- package/dist/nosql/redis/index.js +607 -0
- package/dist/nosql/redpanda/index.js +237 -0
- package/dist/nosql/resque/index.js +203 -0
- package/dist/nosql/rethinkdb/index.js +232 -0
- package/dist/nosql/rocksdb/index.js +152 -0
- package/dist/nosql/rockset/index.js +126 -0
- package/dist/nosql/s3/index.js +298 -0
- package/dist/nosql/scylladb/index.js +178 -0
- package/dist/nosql/signoz/index.js +227 -0
- package/dist/nosql/sns/index.js +201 -0
- package/dist/nosql/solr/index.js +231 -0
- package/dist/nosql/splunk/index.js +227 -0
- package/dist/nosql/sqs/index.js +246 -0
- package/dist/nosql/stardog/index.js +169 -0
- package/dist/nosql/starrocks/index.js +170 -0
- package/dist/nosql/store.js +2 -0
- package/dist/nosql/sumologic/index.js +213 -0
- package/dist/nosql/surrealdb/index.js +179 -0
- package/dist/nosql/terminusdb/index.js +151 -0
- package/dist/nosql/tigergraph/index.js +469 -0
- package/dist/nosql/typesense/index.js +148 -0
- package/dist/nosql/unqlite/index.js +157 -0
- package/dist/nosql/upstash/index.js +167 -0
- package/dist/nosql/vercel-kv/index.js +166 -0
- package/dist/nosql/victoriametrics/index.js +213 -0
- package/dist/nosql/virtuoso/index.js +169 -0
- package/dist/nosql/weaviate/index.js +276 -0
- package/dist/operators/index.js +108 -0
- package/dist/operators.js +2690 -0
- package/dist/prisma-migrate/index.js +38 -0
- package/dist/prisma-migrate/migration-generator.js +125 -0
- package/dist/prisma-migrate/model-generator.js +172 -0
- package/dist/prisma-migrate/relations.js +100 -0
- package/dist/prisma-migrate/schema-parser.js +167 -0
- package/dist/prisma-migrate/type-mapper.js +40 -0
- package/dist/prorm.js +6832 -0
- package/dist/query-builders/cte-builder.js +80 -0
- package/dist/query-builders/functions/aggregate.js +390 -0
- package/dist/query-builders/functions/conditional.js +503 -0
- package/dist/query-builders/functions/datetime.js +695 -0
- package/dist/query-builders/functions/fulltext.js +439 -0
- package/dist/query-builders/functions/index.js +93 -0
- package/dist/query-builders/functions/json.js +427 -0
- package/dist/query-builders/functions/math.js +399 -0
- package/dist/query-builders/functions/string.js +518 -0
- package/dist/query-builders/functions/window.js +328 -0
- package/dist/query-builders/include-builder.js +323 -0
- package/dist/query-builders/index-expression-builder.js +242 -0
- package/dist/query-builders/index.js +161 -0
- package/dist/query-builders/insert-builder.js +164 -0
- package/dist/query-builders/model-helpers.js +38 -0
- package/dist/query-builders/order-limit-builder.js +239 -0
- package/dist/query-builders/sql-compiler.js +2040 -0
- package/dist/query-builders/subquery-builder.js +152 -0
- package/dist/query-builders/update-builder.js +182 -0
- package/dist/query-builders/view-builder.js +218 -0
- package/dist/query-builders/where-builder.js +1532 -0
- package/dist/query-interface.js +622 -0
- package/dist/query-optimizers/batch-optimizer.js +426 -0
- package/dist/query-optimizers/explain-plans.js +415 -0
- package/dist/query-optimizers/index.js +51 -0
- package/dist/query-optimizers/prepared-statement-cache.js +423 -0
- package/dist/query-optimizers/query-hints.js +438 -0
- package/dist/query-optimizers/query-optimizer.js +278 -0
- package/dist/query-optimizers/slow-query-logger.js +271 -0
- package/dist/replica-manager.js +507 -0
- package/dist/schema/index.js +15 -0
- package/dist/schema/migration-generator.js +374 -0
- package/dist/schema/schema-differ.js +549 -0
- package/dist/schema/types.js +6 -0
- package/dist/sql-constants.js +300 -0
- package/dist/sqlite-advanced.js +1047 -0
- package/dist/streams/index.js +12 -0
- package/dist/streams/transforms.js +178 -0
- package/dist/transaction.js +456 -0
- package/dist/types/index.js +180 -0
- package/dist/user-management.js +127 -0
- package/dist/utils/date.js +300 -0
- package/dist/utils/index.js +1079 -0
- package/dist/utils/string.js +161 -0
- package/dist/validators/index.js +19 -0
- package/dist/validators/validator.js +911 -0
- package/package.json +190 -0
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Migrator class - Manages the migration workflow
|
|
4
|
+
* Handles registering, running, and reverting migrations
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.Migrator = void 0;
|
|
41
|
+
exports.createMigrator = createMigrator;
|
|
42
|
+
exports.createMigration = createMigration;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const migration_1 = require("./migration");
|
|
46
|
+
const prormmigration_1 = require("./prormmigration");
|
|
47
|
+
/**
|
|
48
|
+
* Migrator class - Manages database migrations
|
|
49
|
+
*/
|
|
50
|
+
class Migrator {
|
|
51
|
+
/**
|
|
52
|
+
* Create a new Migrator instance
|
|
53
|
+
* @param options - Configuration options
|
|
54
|
+
*/
|
|
55
|
+
constructor(options) {
|
|
56
|
+
this.migrations = new Map();
|
|
57
|
+
/**
|
|
58
|
+
* Default filter for migration files
|
|
59
|
+
*/
|
|
60
|
+
this.defaultFilter = (filename) => {
|
|
61
|
+
const ext = path.extname(filename);
|
|
62
|
+
return ext === this.extension || ext === '.ts';
|
|
63
|
+
};
|
|
64
|
+
this.prorm = options.prorm;
|
|
65
|
+
this.path = options.path || './migrations';
|
|
66
|
+
this.extension = options.extension || '.js';
|
|
67
|
+
this.filter = options.filter || this.defaultFilter;
|
|
68
|
+
const migrationOptions = {
|
|
69
|
+
prorm: options.prorm,
|
|
70
|
+
tableName: options.tableName || 'PrormMeta',
|
|
71
|
+
schema: options.schema,
|
|
72
|
+
};
|
|
73
|
+
this.PrormMigration = new prormmigration_1.PrormMigration(migrationOptions);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get the PrormMigration instance
|
|
77
|
+
*/
|
|
78
|
+
getPrormMigration() {
|
|
79
|
+
return this.PrormMigration;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get the QueryInterface
|
|
83
|
+
*/
|
|
84
|
+
getQueryInterface() {
|
|
85
|
+
return this.PrormMigration.getQueryInterface();
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Register a migration file
|
|
89
|
+
* @param migrationPath - Path to the migration file
|
|
90
|
+
*/
|
|
91
|
+
async migration(migrationPath) {
|
|
92
|
+
const migration = await this.loadMigrationFile(migrationPath);
|
|
93
|
+
const name = path.basename(migrationPath, path.extname(migrationPath));
|
|
94
|
+
this.migrations.set(name, migration);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Ensure TypeScript migration files can be loaded via require().
|
|
98
|
+
* Lazily registers ts-node/register the first time a .ts migration is loaded.
|
|
99
|
+
*/
|
|
100
|
+
ensureTsNodeRegistered(filePath) {
|
|
101
|
+
if (Migrator.tsNodeRegistered) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
106
|
+
require('ts-node/register');
|
|
107
|
+
Migrator.tsNodeRegistered = true;
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
throw new Error(`Cannot load TypeScript migration "${filePath}": ts-node is required to run ` +
|
|
111
|
+
`.ts migration files but could not be loaded. Install it with ` +
|
|
112
|
+
`"npm install --save-dev ts-node", or generate migrations with a .js extension ` +
|
|
113
|
+
`instead. Original error: ${error}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Load a migration file
|
|
118
|
+
* @param filePath - Path to the migration file
|
|
119
|
+
*/
|
|
120
|
+
async loadMigrationFile(filePath) {
|
|
121
|
+
const name = path.basename(filePath, path.extname(filePath));
|
|
122
|
+
try {
|
|
123
|
+
const ext = path.extname(filePath);
|
|
124
|
+
const fullPath = path.resolve(filePath);
|
|
125
|
+
if (ext === '.ts') {
|
|
126
|
+
// Register ts-node so require() can transpile .ts migrations on the fly.
|
|
127
|
+
this.ensureTsNodeRegistered(filePath);
|
|
128
|
+
}
|
|
129
|
+
// Clear require cache to allow hot reloading
|
|
130
|
+
delete require.cache[require.resolve(fullPath)];
|
|
131
|
+
const migrationModule = require(fullPath);
|
|
132
|
+
const migration = new migration_1.Migration({ name });
|
|
133
|
+
// Support both CommonJS (module.exports = { up, down }) and
|
|
134
|
+
// ESM-interop (export const up/down) shapes, and default exports.
|
|
135
|
+
const up = migrationModule.up ?? migrationModule.default?.up;
|
|
136
|
+
const down = migrationModule.down ?? migrationModule.default?.down;
|
|
137
|
+
if (up && typeof up === 'function') {
|
|
138
|
+
migration.setUp(up);
|
|
139
|
+
}
|
|
140
|
+
if (down && typeof down === 'function') {
|
|
141
|
+
migration.setDown(down);
|
|
142
|
+
}
|
|
143
|
+
return migration;
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
throw new Error(`Failed to load migration from ${filePath}: ${error}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Find and register all migration files in a directory
|
|
151
|
+
*/
|
|
152
|
+
async findMigrations() {
|
|
153
|
+
if (!fs.existsSync(this.path)) {
|
|
154
|
+
console.log(`Migration directory not found: ${this.path}`);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const files = fs.readdirSync(this.path);
|
|
158
|
+
for (const file of files) {
|
|
159
|
+
if (this.filter(file)) {
|
|
160
|
+
const filePath = path.join(this.path, file);
|
|
161
|
+
const stat = fs.statSync(filePath);
|
|
162
|
+
if (stat.isFile()) {
|
|
163
|
+
await this.migration(filePath);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Get all registered migrations
|
|
170
|
+
*/
|
|
171
|
+
getMigrations() {
|
|
172
|
+
return Array.from(this.migrations.values());
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Get migration by name
|
|
176
|
+
*/
|
|
177
|
+
getMigration(name) {
|
|
178
|
+
return this.migrations.get(name);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* List pending (not yet executed) migrations
|
|
182
|
+
*/
|
|
183
|
+
async pending() {
|
|
184
|
+
// Load all migrations if not already loaded. Without this, calling
|
|
185
|
+
// pending() before up()/down() (e.g. from the CLI's migration:run,
|
|
186
|
+
// which inspects pending() to decide whether there's anything to do)
|
|
187
|
+
// would see an empty `this.migrations` map and always report zero
|
|
188
|
+
// pending migrations, even when migration files exist on disk.
|
|
189
|
+
if (this.migrations.size === 0) {
|
|
190
|
+
await this.findMigrations();
|
|
191
|
+
}
|
|
192
|
+
const executed = await this.PrormMigration.getExecutedMigrations();
|
|
193
|
+
const executedNames = new Set(executed.map((m) => m.name));
|
|
194
|
+
const pending = [];
|
|
195
|
+
for (const [name, migration] of this.migrations) {
|
|
196
|
+
if (!executedNames.has(name)) {
|
|
197
|
+
pending.push(migration);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// Sort by name (which typically includes timestamp)
|
|
201
|
+
return pending.sort((a, b) => a.name.localeCompare(b.name));
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* List all executed migrations
|
|
205
|
+
*/
|
|
206
|
+
async executed() {
|
|
207
|
+
// See pending() above: the migrations map must be populated from disk
|
|
208
|
+
// before we can match it up against the executed-migrations table.
|
|
209
|
+
if (this.migrations.size === 0) {
|
|
210
|
+
await this.findMigrations();
|
|
211
|
+
}
|
|
212
|
+
const executed = await this.PrormMigration.getExecutedMigrations();
|
|
213
|
+
const executedNames = new Set(executed.map((m) => m.name));
|
|
214
|
+
const executedMigrations = [];
|
|
215
|
+
for (const [name, migration] of this.migrations) {
|
|
216
|
+
if (executedNames.has(name)) {
|
|
217
|
+
executedMigrations.push(migration);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return executedMigrations.sort((a, b) => a.name.localeCompare(b.name));
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Get migration status for all migrations
|
|
224
|
+
*/
|
|
225
|
+
async status() {
|
|
226
|
+
// See pending() above: the migrations map must be populated from disk
|
|
227
|
+
// before status can be computed for each migration file.
|
|
228
|
+
if (this.migrations.size === 0) {
|
|
229
|
+
await this.findMigrations();
|
|
230
|
+
}
|
|
231
|
+
const executed = await this.PrormMigration.getExecutedMigrations();
|
|
232
|
+
const executedMap = new Map(executed.map((m) => [m.name, m]));
|
|
233
|
+
const allStatuses = [];
|
|
234
|
+
for (const [name, migration] of this.migrations) {
|
|
235
|
+
const meta = executedMap.get(name);
|
|
236
|
+
allStatuses.push({
|
|
237
|
+
name,
|
|
238
|
+
status: meta ? 'up' : 'pending',
|
|
239
|
+
batch: meta?.batch,
|
|
240
|
+
timestamp: meta?.timestamp,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
return allStatuses.sort((a, b) => a.name.localeCompare(b.name));
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Run all pending migrations
|
|
247
|
+
* @param options - Migration options
|
|
248
|
+
*/
|
|
249
|
+
async up(options) {
|
|
250
|
+
// Load all migrations if not already loaded
|
|
251
|
+
if (this.migrations.size === 0) {
|
|
252
|
+
await this.findMigrations();
|
|
253
|
+
}
|
|
254
|
+
const result = {
|
|
255
|
+
executed: 0,
|
|
256
|
+
reverted: 0,
|
|
257
|
+
migrations: [],
|
|
258
|
+
};
|
|
259
|
+
if (options?.migration) {
|
|
260
|
+
// Run specific migration
|
|
261
|
+
const migration = this.migrations.get(options.migration);
|
|
262
|
+
if (!migration) {
|
|
263
|
+
throw new Error(`Migration ${options.migration} not found`);
|
|
264
|
+
}
|
|
265
|
+
const isExecuted = await this.PrormMigration.isMigrationExecuted(migration.name);
|
|
266
|
+
if (!isExecuted) {
|
|
267
|
+
await this.PrormMigration.runMigration(migration);
|
|
268
|
+
result.executed = 1;
|
|
269
|
+
result.migrations.push(migration.name);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
// Run all pending migrations
|
|
274
|
+
const pendingMigrations = await this.pending();
|
|
275
|
+
for (const migration of pendingMigrations) {
|
|
276
|
+
await this.PrormMigration.runMigration(migration);
|
|
277
|
+
result.executed++;
|
|
278
|
+
result.migrations.push(migration.name);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return result;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Revert migrations
|
|
285
|
+
* @param options - Revert options
|
|
286
|
+
*/
|
|
287
|
+
async down(options) {
|
|
288
|
+
// Load all migrations if not already loaded
|
|
289
|
+
if (this.migrations.size === 0) {
|
|
290
|
+
await this.findMigrations();
|
|
291
|
+
}
|
|
292
|
+
const result = {
|
|
293
|
+
executed: 0,
|
|
294
|
+
reverted: 0,
|
|
295
|
+
migrations: [],
|
|
296
|
+
};
|
|
297
|
+
const executedMigrations = await this.executed();
|
|
298
|
+
if (options?.migration) {
|
|
299
|
+
// Revert specific migration
|
|
300
|
+
const migration = this.migrations.get(options.migration);
|
|
301
|
+
if (!migration) {
|
|
302
|
+
throw new Error(`Migration ${options.migration} not found`);
|
|
303
|
+
}
|
|
304
|
+
const isExecuted = await this.PrormMigration.isMigrationExecuted(migration.name);
|
|
305
|
+
if (isExecuted) {
|
|
306
|
+
await this.PrormMigration.revertMigration(migration);
|
|
307
|
+
result.reverted = 1;
|
|
308
|
+
result.migrations.push(migration.name);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
else if (options?.steps !== undefined && options.steps > 0) {
|
|
312
|
+
// Revert N migrations
|
|
313
|
+
const toRevert = executedMigrations
|
|
314
|
+
.sort((a, b) => b.name.localeCompare(a.name))
|
|
315
|
+
.slice(0, options.steps);
|
|
316
|
+
for (const migration of toRevert) {
|
|
317
|
+
await this.PrormMigration.revertMigration(migration);
|
|
318
|
+
result.reverted++;
|
|
319
|
+
result.migrations.push(migration.name);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
// Revert last migration
|
|
324
|
+
const lastMigration = executedMigrations[executedMigrations.length - 1];
|
|
325
|
+
if (lastMigration) {
|
|
326
|
+
await this.PrormMigration.revertMigration(lastMigration);
|
|
327
|
+
result.reverted = 1;
|
|
328
|
+
result.migrations.push(lastMigration.name);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return result;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Revert all executed migrations with a batch number greater than
|
|
335
|
+
* `targetBatch`, actually running each migration's `down()` function
|
|
336
|
+
* (loaded the same way `up()` is) before removing its tracking row.
|
|
337
|
+
* @param targetBatch - Batch number to revert down to
|
|
338
|
+
*/
|
|
339
|
+
async downToBatch(targetBatch) {
|
|
340
|
+
// Load all migrations if not already loaded
|
|
341
|
+
if (this.migrations.size === 0) {
|
|
342
|
+
await this.findMigrations();
|
|
343
|
+
}
|
|
344
|
+
const before = await this.PrormMigration.getExecutedMigrations();
|
|
345
|
+
await this.PrormMigration.revertToBatch(targetBatch, this.migrations);
|
|
346
|
+
const after = await this.PrormMigration.getExecutedMigrations();
|
|
347
|
+
const afterNames = new Set(after.map((m) => m.name));
|
|
348
|
+
const revertedNames = before.filter((m) => !afterNames.has(m.name)).map((m) => m.name);
|
|
349
|
+
return {
|
|
350
|
+
executed: 0,
|
|
351
|
+
reverted: revertedNames.length,
|
|
352
|
+
migrations: revertedNames,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Get database version
|
|
357
|
+
*/
|
|
358
|
+
async getDatabaseVersion() {
|
|
359
|
+
return this.PrormMigration.getDatabaseVersion();
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Sync the migrations table
|
|
363
|
+
*/
|
|
364
|
+
async syncMigrationsTable() {
|
|
365
|
+
await this.PrormMigration.syncMigrationsTable();
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Set the migration path
|
|
369
|
+
*/
|
|
370
|
+
setPath(newPath) {
|
|
371
|
+
this.path = newPath;
|
|
372
|
+
this.migrations.clear();
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Get the current migration path
|
|
376
|
+
*/
|
|
377
|
+
getPath() {
|
|
378
|
+
return this.path;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
exports.Migrator = Migrator;
|
|
382
|
+
/**
|
|
383
|
+
* Whether ts-node/register has already been registered in this process.
|
|
384
|
+
* Registering more than once is harmless but wasteful, so we only do it once.
|
|
385
|
+
*/
|
|
386
|
+
Migrator.tsNodeRegistered = false;
|
|
387
|
+
/**
|
|
388
|
+
* Create a Migrator instance
|
|
389
|
+
*/
|
|
390
|
+
function createMigrator(options) {
|
|
391
|
+
return new Migrator(options);
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Create migration file template
|
|
395
|
+
* @param name - Migration name
|
|
396
|
+
* @param options - Template options
|
|
397
|
+
*/
|
|
398
|
+
function createMigration(name, options) {
|
|
399
|
+
const timestamp = migration_1.Migration.getTimestamp();
|
|
400
|
+
const filename = `${timestamp}-${name}${options?.extension || '.js'}`;
|
|
401
|
+
const filepath = path.join(options?.path || './migrations', filename);
|
|
402
|
+
// Ensure directory exists
|
|
403
|
+
const dir = path.dirname(filepath);
|
|
404
|
+
if (!fs.existsSync(dir)) {
|
|
405
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
406
|
+
}
|
|
407
|
+
const template = (0, migration_1.buildMigrationTemplate)(name);
|
|
408
|
+
fs.writeFileSync(filepath, template);
|
|
409
|
+
console.log(`Migration created: ${filepath}`);
|
|
410
|
+
return filepath;
|
|
411
|
+
}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PrormMigration class - Integration layer between migrations and Prorm
|
|
4
|
+
* Handles running migrations with the Prorm instance
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.PrormMigration = void 0;
|
|
8
|
+
const query_interface_1 = require("./query-interface");
|
|
9
|
+
/**
|
|
10
|
+
* PrormMigration - Integrates with Prorm to manage migrations
|
|
11
|
+
*/
|
|
12
|
+
class PrormMigration {
|
|
13
|
+
/**
|
|
14
|
+
* Create a new PrormMigration instance
|
|
15
|
+
* @param options - Configuration options
|
|
16
|
+
*/
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.migrationMeta = new Map();
|
|
19
|
+
this.prorm = options.prorm;
|
|
20
|
+
this.tableName = options.tableName || 'PrormMeta';
|
|
21
|
+
this.schema = options.schema;
|
|
22
|
+
this.queryInterface = this.createQueryInterface();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Create a QueryInterface from the Prorm instance
|
|
26
|
+
*/
|
|
27
|
+
createQueryInterface() {
|
|
28
|
+
const dialect = this.prorm.getDialectInstance();
|
|
29
|
+
if (!dialect) {
|
|
30
|
+
throw new Error('Prorm is not connected. Please call prorm.connect() first.');
|
|
31
|
+
}
|
|
32
|
+
return new query_interface_1.QueryInterface(dialect);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get the QueryInterface
|
|
36
|
+
*/
|
|
37
|
+
getQueryInterface() {
|
|
38
|
+
return this.queryInterface;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get the Prorm instance
|
|
42
|
+
*/
|
|
43
|
+
getProrm() {
|
|
44
|
+
return this.prorm;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get the migrations table name
|
|
48
|
+
*/
|
|
49
|
+
getTableName() {
|
|
50
|
+
return this.tableName;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Ensure the migrations table exists
|
|
54
|
+
*/
|
|
55
|
+
async ensureMigrationsTable() {
|
|
56
|
+
const tableExists = await this.queryInterface.tableExists(this.tableName);
|
|
57
|
+
if (!tableExists) {
|
|
58
|
+
await this.queryInterface.createTable(this.tableName, {
|
|
59
|
+
name: {
|
|
60
|
+
type: 'STRING',
|
|
61
|
+
allowNull: false,
|
|
62
|
+
unique: true,
|
|
63
|
+
},
|
|
64
|
+
batch: {
|
|
65
|
+
type: 'INTEGER',
|
|
66
|
+
allowNull: false,
|
|
67
|
+
defaultValue: 0,
|
|
68
|
+
},
|
|
69
|
+
timestamp: {
|
|
70
|
+
type: 'INTEGER',
|
|
71
|
+
allowNull: false,
|
|
72
|
+
defaultValue: Math.floor(Date.now() / 1000),
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Load migration metadata from the database
|
|
79
|
+
*/
|
|
80
|
+
async loadMigrationMeta() {
|
|
81
|
+
await this.ensureMigrationsTable();
|
|
82
|
+
const result = await this.queryInterface.prormQuery(`SELECT * FROM ${this.queryInterface.getDialect().escapeId(this.tableName)} ORDER BY timestamp ASC`);
|
|
83
|
+
this.migrationMeta.clear();
|
|
84
|
+
for (const row of result.rows) {
|
|
85
|
+
const meta = {
|
|
86
|
+
id: row.id,
|
|
87
|
+
name: row.name,
|
|
88
|
+
batch: row.batch,
|
|
89
|
+
timestamp: row.timestamp,
|
|
90
|
+
};
|
|
91
|
+
this.migrationMeta.set(row.name, meta);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Record a migration as executed in the database
|
|
96
|
+
* @param migration - The migration to record
|
|
97
|
+
* @param batch - The batch number
|
|
98
|
+
*/
|
|
99
|
+
async recordMigration(migration, batch) {
|
|
100
|
+
const dialect = this.queryInterface.getDialect();
|
|
101
|
+
const timestamp = Math.floor(Date.now() / 1000);
|
|
102
|
+
await this.queryInterface.prormQuery(`INSERT INTO ${dialect.escapeId(this.tableName)} (name, batch, timestamp) VALUES (${dialect.escape(migration.name)}, ${dialect.escape(batch)}, ${dialect.escape(timestamp)})`);
|
|
103
|
+
// Update local cache
|
|
104
|
+
const meta = {
|
|
105
|
+
name: migration.name,
|
|
106
|
+
batch,
|
|
107
|
+
timestamp,
|
|
108
|
+
};
|
|
109
|
+
this.migrationMeta.set(migration.name, meta);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Remove a migration record from the database
|
|
113
|
+
* @param migrationName - Name of the migration to remove
|
|
114
|
+
*/
|
|
115
|
+
async removeMigration(migrationName) {
|
|
116
|
+
const dialect = this.queryInterface.getDialect();
|
|
117
|
+
await this.queryInterface.prormQuery(`DELETE FROM ${dialect.escapeId(this.tableName)} WHERE name = ${dialect.escape(migrationName)}`);
|
|
118
|
+
this.migrationMeta.delete(migrationName);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get all executed migrations
|
|
122
|
+
*/
|
|
123
|
+
async getExecutedMigrations() {
|
|
124
|
+
await this.loadMigrationMeta();
|
|
125
|
+
return Array.from(this.migrationMeta.values());
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Check if a migration has been executed
|
|
129
|
+
* @param migrationName - Name of the migration
|
|
130
|
+
*/
|
|
131
|
+
async isMigrationExecuted(migrationName) {
|
|
132
|
+
await this.loadMigrationMeta();
|
|
133
|
+
return this.migrationMeta.has(migrationName);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Compute the next batch number from the currently loaded migration meta.
|
|
137
|
+
* Callers are expected to have called `loadMigrationMeta()` beforehand.
|
|
138
|
+
*/
|
|
139
|
+
computeNextBatch() {
|
|
140
|
+
const migrations = Array.from(this.migrationMeta.values());
|
|
141
|
+
const maxBatch = migrations.reduce((max, m) => Math.max(max, m.batch), 0);
|
|
142
|
+
return maxBatch + 1;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Run a migration
|
|
146
|
+
* @param migration - The migration to run
|
|
147
|
+
* @param batch - Optional batch number to record this migration under. When
|
|
148
|
+
* omitted, a fresh batch number is computed for this single migration.
|
|
149
|
+
* `runMigrations()` passes an explicit shared batch so that all migrations
|
|
150
|
+
* applied in one run land in the same batch.
|
|
151
|
+
*/
|
|
152
|
+
async runMigration(migration, batch) {
|
|
153
|
+
// Load fresh meta before running
|
|
154
|
+
await this.loadMigrationMeta();
|
|
155
|
+
if (this.migrationMeta.has(migration.name)) {
|
|
156
|
+
console.log(`Migration ${migration.name} already executed`);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
// Use the caller-provided batch (shared across a run) or compute one.
|
|
160
|
+
const newBatch = batch ?? this.computeNextBatch();
|
|
161
|
+
try {
|
|
162
|
+
console.log(`Running migration: ${migration.name}`);
|
|
163
|
+
await migration.up(this.queryInterface, this.prorm);
|
|
164
|
+
await this.recordMigration(migration, newBatch);
|
|
165
|
+
console.log(`Migration ${migration.name} completed`);
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
console.error(`Migration ${migration.name} failed:`, error);
|
|
169
|
+
throw error;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Revert a migration
|
|
174
|
+
* @param migration - The migration to revert
|
|
175
|
+
*/
|
|
176
|
+
async revertMigration(migration) {
|
|
177
|
+
// Load fresh meta before reverting
|
|
178
|
+
await this.loadMigrationMeta();
|
|
179
|
+
if (!this.migrationMeta.has(migration.name)) {
|
|
180
|
+
console.log(`Migration ${migration.name} not executed`);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
if (!migration.down) {
|
|
184
|
+
console.warn(`Migration ${migration.name} has no down() function defined; removing its tracking ` +
|
|
185
|
+
`record without reverting any changes.`);
|
|
186
|
+
await this.removeMigration(migration.name);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
try {
|
|
190
|
+
console.log(`Reverting migration: ${migration.name}`);
|
|
191
|
+
await migration.down(this.queryInterface, this.prorm);
|
|
192
|
+
await this.removeMigration(migration.name);
|
|
193
|
+
console.log(`Migration ${migration.name} reverted`);
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
console.error(`Failed to revert migration ${migration.name}:`, error);
|
|
197
|
+
throw error;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Execute all pending migrations
|
|
202
|
+
* @param migrations - Array of migrations to run
|
|
203
|
+
*/
|
|
204
|
+
async runMigrations(migrations) {
|
|
205
|
+
// All migrations applied in a single run share one batch number so they
|
|
206
|
+
// can be reverted together as a unit. Compute it once up front rather than
|
|
207
|
+
// recomputing (maxBatch + 1) per migration, which would put each migration
|
|
208
|
+
// in its own batch.
|
|
209
|
+
await this.loadMigrationMeta();
|
|
210
|
+
const batch = this.computeNextBatch();
|
|
211
|
+
for (const migration of migrations) {
|
|
212
|
+
await this.runMigration(migration, batch);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Revert migrations to a specific batch
|
|
217
|
+
*
|
|
218
|
+
* For each executed migration with a batch number greater than
|
|
219
|
+
* `targetBatch`, this loads its `down()` function (via the supplied
|
|
220
|
+
* `migrations` lookup) and actually executes it before removing its
|
|
221
|
+
* tracking row. If `down()` throws, the error is logged and re-thrown, and
|
|
222
|
+
* the tracking row for that migration (and any migrations after it) is
|
|
223
|
+
* left in place so the revert can be retried.
|
|
224
|
+
*
|
|
225
|
+
* @param targetBatch - Target batch number to revert down to
|
|
226
|
+
* @param migrations - The loaded Migration definitions (with `down()`
|
|
227
|
+
* functions attached), keyed by migration name. Typically
|
|
228
|
+
* `Migrator.getMigrations()` / the Migrator's internal migrations map.
|
|
229
|
+
*/
|
|
230
|
+
async revertToBatch(targetBatch, migrations) {
|
|
231
|
+
const migrationMap = migrations instanceof Map ? migrations : new Map(migrations.map((m) => [m.name, m]));
|
|
232
|
+
await this.loadMigrationMeta();
|
|
233
|
+
const migrationsToRevert = Array.from(this.migrationMeta.values())
|
|
234
|
+
.filter((m) => m.batch > targetBatch)
|
|
235
|
+
.sort((a, b) => b.batch - a.batch || b.timestamp - a.timestamp);
|
|
236
|
+
for (const meta of migrationsToRevert) {
|
|
237
|
+
const migration = migrationMap.get(meta.name);
|
|
238
|
+
if (!migration) {
|
|
239
|
+
throw new Error(`Cannot revert migration "${meta.name}" to batch ${targetBatch}: no loaded ` +
|
|
240
|
+
`migration definition was found for it, so its down() function is unavailable. ` +
|
|
241
|
+
`Ensure the migration file still exists and has been registered (e.g. via ` +
|
|
242
|
+
`Migrator.findMigrations()) before calling revertToBatch().`);
|
|
243
|
+
}
|
|
244
|
+
if (!migration.down) {
|
|
245
|
+
console.warn(`Migration ${meta.name} has no down() function defined; removing its tracking ` +
|
|
246
|
+
`record without reverting any changes.`);
|
|
247
|
+
await this.removeMigration(meta.name);
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
console.log(`Reverting migration: ${meta.name}`);
|
|
252
|
+
await migration.down(this.queryInterface, this.prorm);
|
|
253
|
+
await this.removeMigration(meta.name);
|
|
254
|
+
console.log(`Migration ${meta.name} reverted`);
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
console.error(`Failed to revert migration ${meta.name} while reverting to batch ${targetBatch}:`, error);
|
|
258
|
+
throw error;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Get the current database version
|
|
264
|
+
*/
|
|
265
|
+
async getDatabaseVersion() {
|
|
266
|
+
return this.queryInterface.getDatabaseVersion();
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Sync the migrations table
|
|
270
|
+
*/
|
|
271
|
+
async syncMigrationsTable() {
|
|
272
|
+
await this.ensureMigrationsTable();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
exports.PrormMigration = PrormMigration;
|