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,353 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Seeder System - Manages database seed data
|
|
4
|
+
* Provides a way to populate a database with initial or test data
|
|
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.SeederRunner = void 0;
|
|
41
|
+
exports.createSeeder = createSeeder;
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const events_1 = require("events");
|
|
45
|
+
/**
|
|
46
|
+
* Helper to create a seeder with full type safety
|
|
47
|
+
*/
|
|
48
|
+
function createSeeder(definition) {
|
|
49
|
+
return definition;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* SeederRunner manages the lifecycle of database seeders
|
|
53
|
+
*/
|
|
54
|
+
class SeederRunner extends events_1.EventEmitter {
|
|
55
|
+
constructor(prorm, options = {}) {
|
|
56
|
+
super();
|
|
57
|
+
this.prorm = prorm;
|
|
58
|
+
this.options = options;
|
|
59
|
+
this.tableName = options.seedsTableName || 'PrormData';
|
|
60
|
+
this.seedersPath = options.seedersPath || './seeders';
|
|
61
|
+
this.pattern = options.pattern || /\.(js|ts)$/;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get the dialect instance from the prorm object.
|
|
65
|
+
* Supports both the custom ORM (getDialectInstance) and a plain query wrapper.
|
|
66
|
+
*/
|
|
67
|
+
getDialect() {
|
|
68
|
+
if (this.prorm && typeof this.prorm.getDialectInstance === 'function') {
|
|
69
|
+
return this.prorm.getDialectInstance();
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Execute a raw SQL query via the prorm/dialect instance
|
|
75
|
+
*/
|
|
76
|
+
async rawQuery(sql, options) {
|
|
77
|
+
const dialect = this.getDialect();
|
|
78
|
+
if (dialect) {
|
|
79
|
+
return dialect.query(sql, options);
|
|
80
|
+
}
|
|
81
|
+
// Fallback: prorm may have a .query() method directly
|
|
82
|
+
if (typeof this.prorm.query === 'function') {
|
|
83
|
+
return this.prorm.query(sql, options);
|
|
84
|
+
}
|
|
85
|
+
throw new Error('Unable to execute query: no query interface available');
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Escape an identifier using the dialect, or fall back to simple quoting
|
|
89
|
+
*/
|
|
90
|
+
escapeId(name) {
|
|
91
|
+
const dialect = this.getDialect();
|
|
92
|
+
if (dialect && typeof dialect.escapeId === 'function') {
|
|
93
|
+
return dialect.escapeId(name);
|
|
94
|
+
}
|
|
95
|
+
return `"${name}"`;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Escape a literal value using the dialect so it can be inlined directly into
|
|
99
|
+
* SQL. Inlining avoids relying on a specific bind-placeholder style (`?`,
|
|
100
|
+
* `$1`, `:name`), which differs between dialects — Postgres-family dialects,
|
|
101
|
+
* for example, do not understand `?` — and keeps the tracking/seeder SQL
|
|
102
|
+
* portable across every dialect.
|
|
103
|
+
*/
|
|
104
|
+
escapeVal(value) {
|
|
105
|
+
const dialect = this.getDialect();
|
|
106
|
+
if (dialect && typeof dialect.escape === 'function') {
|
|
107
|
+
return dialect.escape(value);
|
|
108
|
+
}
|
|
109
|
+
// Fallback escaping when no dialect is available (rare)
|
|
110
|
+
if (value === null || value === undefined)
|
|
111
|
+
return 'NULL';
|
|
112
|
+
if (typeof value === 'number')
|
|
113
|
+
return String(value);
|
|
114
|
+
if (typeof value === 'boolean')
|
|
115
|
+
return value ? 'TRUE' : 'FALSE';
|
|
116
|
+
return `'${String(value).replace(/'/g, "''")}'`;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Resolve the current environment used for env-scoped seeders.
|
|
120
|
+
* Prefers the explicit option, then NODE_ENV; otherwise undefined.
|
|
121
|
+
*/
|
|
122
|
+
resolveEnv() {
|
|
123
|
+
return this.options.env || process.env.NODE_ENV || undefined;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Ensure the PrormData tracking table exists
|
|
127
|
+
*/
|
|
128
|
+
async ensureSeedsTable() {
|
|
129
|
+
const dialect = this.getDialect();
|
|
130
|
+
if (!dialect) {
|
|
131
|
+
throw new Error('Prorm is not connected');
|
|
132
|
+
}
|
|
133
|
+
const tableExists = await this.tableExists();
|
|
134
|
+
if (!tableExists) {
|
|
135
|
+
const sql = `CREATE TABLE IF NOT EXISTS ${this.escapeId(this.tableName)} (
|
|
136
|
+
"name" VARCHAR(255) NOT NULL UNIQUE,
|
|
137
|
+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
138
|
+
)`;
|
|
139
|
+
await this.rawQuery(sql);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Check whether the tracking table exists
|
|
144
|
+
*/
|
|
145
|
+
async tableExists() {
|
|
146
|
+
const dialect = this.getDialect();
|
|
147
|
+
if (dialect && typeof dialect.showTables === 'function') {
|
|
148
|
+
const tables = await dialect.showTables();
|
|
149
|
+
return tables.includes(this.tableName);
|
|
150
|
+
}
|
|
151
|
+
// Fallback for SQLite: query sqlite_master
|
|
152
|
+
try {
|
|
153
|
+
const result = await this.rawQuery(`SELECT name FROM sqlite_master WHERE type='table' AND name=${this.escapeVal(this.tableName)}`);
|
|
154
|
+
return result.rows && result.rows.length > 0;
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Return names of all seeders that have already been executed
|
|
162
|
+
*/
|
|
163
|
+
async getExecutedSeeds() {
|
|
164
|
+
await this.ensureSeedsTable();
|
|
165
|
+
const result = await this.rawQuery(`SELECT "name" FROM ${this.escapeId(this.tableName)} ORDER BY "createdAt" ASC`);
|
|
166
|
+
return (result.rows || []).map((r) => r.name);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Discover all seeder files in the seeders path, sorted by name
|
|
170
|
+
*/
|
|
171
|
+
discoverSeederFiles(seedersPath) {
|
|
172
|
+
if (!fs.existsSync(seedersPath)) {
|
|
173
|
+
return [];
|
|
174
|
+
}
|
|
175
|
+
return fs
|
|
176
|
+
.readdirSync(seedersPath)
|
|
177
|
+
.filter((f) => this.pattern.test(f))
|
|
178
|
+
.sort()
|
|
179
|
+
.map((f) => path.join(seedersPath, f));
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Load a seeder module from disk
|
|
183
|
+
*/
|
|
184
|
+
loadSeeder(filePath) {
|
|
185
|
+
const ext = path.extname(filePath);
|
|
186
|
+
if (ext === '.ts') {
|
|
187
|
+
// For TypeScript files, require ts-node registration or pre-compiled output
|
|
188
|
+
// In test environments ts-jest handles this automatically
|
|
189
|
+
delete require.cache[require.resolve(filePath)];
|
|
190
|
+
return require(filePath);
|
|
191
|
+
}
|
|
192
|
+
const fullPath = path.resolve(filePath);
|
|
193
|
+
delete require.cache[require.resolve(fullPath)];
|
|
194
|
+
return require(fullPath);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Build the query interface object passed to seeder functions.
|
|
198
|
+
* This mirrors the shape that seeder authors expect.
|
|
199
|
+
*/
|
|
200
|
+
buildQueryInterface() {
|
|
201
|
+
const dialect = this.getDialect();
|
|
202
|
+
const self = this;
|
|
203
|
+
return {
|
|
204
|
+
bulkInsert: async (tableName, records) => {
|
|
205
|
+
if (!records || records.length === 0)
|
|
206
|
+
return;
|
|
207
|
+
const cols = Object.keys(records[0]);
|
|
208
|
+
const colList = cols.map((c) => self.escapeId(c)).join(', ');
|
|
209
|
+
for (const record of records) {
|
|
210
|
+
const vals = cols.map((c) => self.escapeVal(record[c])).join(', ');
|
|
211
|
+
await self.rawQuery(`INSERT INTO ${self.escapeId(tableName)} (${colList}) VALUES (${vals})`);
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
bulkDelete: async (tableName, where) => {
|
|
215
|
+
let sql = `DELETE FROM ${self.escapeId(tableName)}`;
|
|
216
|
+
if (where && Object.keys(where).length > 0) {
|
|
217
|
+
const conditions = Object.entries(where)
|
|
218
|
+
.map(([k, v]) => `${self.escapeId(k)} = ${self.escapeVal(v)}`)
|
|
219
|
+
.join(' AND ');
|
|
220
|
+
sql += ` WHERE ${conditions}`;
|
|
221
|
+
await self.rawQuery(sql);
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
await self.rawQuery(sql);
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
prormQuery: async (sql, opts) => {
|
|
228
|
+
return self.rawQuery(sql, opts);
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Run all pending seeders (or a single one, via `options.only`). Returns
|
|
234
|
+
* the names of seeders that were executed.
|
|
235
|
+
*
|
|
236
|
+
* Seeders are discovered in sorted filename order (see
|
|
237
|
+
* discoverSeederFiles) and run strictly one after another. If a seeder's
|
|
238
|
+
* up() throws, the error propagates immediately: seeders already recorded
|
|
239
|
+
* in this call remain recorded (their tracking rows were only inserted
|
|
240
|
+
* after up() resolved successfully), the failing seeder is NOT recorded
|
|
241
|
+
* as executed, and no further seeders in the batch are attempted. Re-running
|
|
242
|
+
* runSeeders() afterwards will retry the failed seeder and any that never
|
|
243
|
+
* got a chance to run.
|
|
244
|
+
*/
|
|
245
|
+
async runSeeders(seedersPath, options = {}) {
|
|
246
|
+
const targetPath = seedersPath || this.seedersPath;
|
|
247
|
+
await this.ensureSeedsTable();
|
|
248
|
+
const executed = new Set(await this.getExecutedSeeds());
|
|
249
|
+
let files = this.discoverSeederFiles(targetPath);
|
|
250
|
+
if (options.only) {
|
|
251
|
+
files = files.filter((f) => path.basename(f, path.extname(f)) === options.only);
|
|
252
|
+
if (files.length === 0) {
|
|
253
|
+
throw new Error(`Seeder file not found for: ${options.only}`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const queryInterface = this.buildQueryInterface();
|
|
257
|
+
const currentEnv = this.resolveEnv();
|
|
258
|
+
const ran = [];
|
|
259
|
+
for (const filePath of files) {
|
|
260
|
+
const name = path.basename(filePath, path.extname(filePath));
|
|
261
|
+
const alreadyExecuted = executed.has(name);
|
|
262
|
+
if (alreadyExecuted && !(options.only && options.force)) {
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
const seeder = this.loadSeeder(filePath);
|
|
266
|
+
// Environment scoping: seeders with no `env` field always run. A seeder
|
|
267
|
+
// that DOES declare `env` only runs when it matches the supplied env;
|
|
268
|
+
// when no env can be resolved we skip it rather than running it
|
|
269
|
+
// unconditionally (which previously leaked dev fixtures into every env).
|
|
270
|
+
if (seeder.env) {
|
|
271
|
+
const allowed = Array.isArray(seeder.env) ? seeder.env : [seeder.env];
|
|
272
|
+
if (!options.env || !allowed.includes(options.env)) {
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
this.emit('beforeSeed', { name });
|
|
277
|
+
const start = Date.now();
|
|
278
|
+
await seeder.up(queryInterface, this.prorm);
|
|
279
|
+
// Record as executed (replace any prior record when force-re-running)
|
|
280
|
+
if (alreadyExecuted) {
|
|
281
|
+
await this.rawQuery(`DELETE FROM ${this.escapeId(this.tableName)} WHERE "name" = ?`, {
|
|
282
|
+
replacements: [name],
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
await this.rawQuery(`INSERT INTO ${this.escapeId(this.tableName)} ("name", "createdAt") VALUES (${this.escapeVal(name)}, ${this.escapeVal(new Date().toISOString())})`);
|
|
286
|
+
const duration = Date.now() - start;
|
|
287
|
+
this.emit('afterSeed', { name, duration });
|
|
288
|
+
ran.push(name);
|
|
289
|
+
}
|
|
290
|
+
return ran;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Undo a specific seeder, or the most recently executed one if no name given
|
|
294
|
+
*/
|
|
295
|
+
async undoSeeder(seederName) {
|
|
296
|
+
await this.ensureSeedsTable();
|
|
297
|
+
const executed = await this.getExecutedSeeds();
|
|
298
|
+
if (executed.length === 0) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
const targetName = seederName || executed[executed.length - 1];
|
|
302
|
+
// Find the file for this seeder
|
|
303
|
+
const files = this.discoverSeederFiles(this.seedersPath);
|
|
304
|
+
const file = files.find((f) => path.basename(f, path.extname(f)) === targetName);
|
|
305
|
+
if (!file) {
|
|
306
|
+
throw new Error(`Seeder file not found for: ${targetName}`);
|
|
307
|
+
}
|
|
308
|
+
const queryInterface = this.buildQueryInterface();
|
|
309
|
+
const seeder = this.loadSeeder(file);
|
|
310
|
+
await seeder.down(queryInterface, this.prorm);
|
|
311
|
+
await this.rawQuery(`DELETE FROM ${this.escapeId(this.tableName)} WHERE "name" = ${this.escapeVal(targetName)}`);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Undo all executed seeders in reverse order
|
|
315
|
+
*/
|
|
316
|
+
async undoAllSeeders() {
|
|
317
|
+
await this.ensureSeedsTable();
|
|
318
|
+
const executed = await this.getExecutedSeeds();
|
|
319
|
+
// Reverse order
|
|
320
|
+
const reversed = [...executed].reverse();
|
|
321
|
+
for (const name of reversed) {
|
|
322
|
+
await this.undoSeeder(name);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Return the status of all seed files (both pending and executed)
|
|
327
|
+
*/
|
|
328
|
+
async getSeedStatus() {
|
|
329
|
+
await this.ensureSeedsTable();
|
|
330
|
+
// Fetch executed records with timestamps
|
|
331
|
+
const result = await this.rawQuery(`SELECT "name", "createdAt" FROM ${this.escapeId(this.tableName)} ORDER BY "createdAt" ASC`);
|
|
332
|
+
const executedMap = new Map((result.rows || []).map((r) => [r.name, new Date(r.createdAt)]));
|
|
333
|
+
const files = this.discoverSeederFiles(this.seedersPath);
|
|
334
|
+
const statuses = [];
|
|
335
|
+
for (const filePath of files) {
|
|
336
|
+
const name = path.basename(filePath, path.extname(filePath));
|
|
337
|
+
if (executedMap.has(name)) {
|
|
338
|
+
statuses.push({ name, status: 'executed', executedAt: executedMap.get(name) });
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
statuses.push({ name, status: 'pending' });
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
// Also include any executed seeds whose files no longer exist
|
|
345
|
+
for (const [name, executedAt] of executedMap) {
|
|
346
|
+
if (!statuses.find((s) => s.name === name)) {
|
|
347
|
+
statuses.push({ name, status: 'executed', executedAt });
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return statuses;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
exports.SeederRunner = SeederRunner;
|