@plyaz/db 0.1.1 → 0.2.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/dist/adapters/sql/SQLAdapter.d.ts +1 -0
- package/dist/adapters/sql/SQLAdapter.d.ts.map +1 -1
- package/dist/cli/index.js +826 -45
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +300 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +300 -18
- package/dist/index.mjs.map +1 -1
- package/dist/migrations/MigrationManager.d.ts +22 -0
- package/dist/migrations/MigrationManager.d.ts.map +1 -1
- package/dist/seeds/SeedManager.d.ts +25 -1
- package/dist/seeds/SeedManager.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/index.mjs
CHANGED
|
@@ -3597,6 +3597,7 @@ var SupabaseAdapter = class {
|
|
|
3597
3597
|
return ops[operator]();
|
|
3598
3598
|
}
|
|
3599
3599
|
};
|
|
3600
|
+
var SQL_ERROR_TRUNCATE_LENGTH = 500;
|
|
3600
3601
|
var SQLAdapter = class {
|
|
3601
3602
|
static {
|
|
3602
3603
|
__name(this, "SQLAdapter");
|
|
@@ -3607,6 +3608,7 @@ var SQLAdapter = class {
|
|
|
3607
3608
|
idColumnMap = /* @__PURE__ */ new Map();
|
|
3608
3609
|
configIdColumns;
|
|
3609
3610
|
defaultSchema;
|
|
3611
|
+
showSqlInErrors;
|
|
3610
3612
|
/**
|
|
3611
3613
|
* Creates a new SQLAdapter instance.
|
|
3612
3614
|
* @param {SQLAdapterConfig} config - Configuration for the SQL adapter.
|
|
@@ -3620,6 +3622,7 @@ var SQLAdapter = class {
|
|
|
3620
3622
|
constructor(config) {
|
|
3621
3623
|
this.config = config;
|
|
3622
3624
|
this.defaultSchema = config.schema ?? "public";
|
|
3625
|
+
this.showSqlInErrors = config.showSqlInErrors ?? true;
|
|
3623
3626
|
this.pool = new Pool({
|
|
3624
3627
|
connectionString: config.connectionString,
|
|
3625
3628
|
...config.pool
|
|
@@ -3738,16 +3741,16 @@ var SQLAdapter = class {
|
|
|
3738
3741
|
const result = await this.pool.query(sql2, params);
|
|
3739
3742
|
return result.rows;
|
|
3740
3743
|
} catch (error) {
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
);
|
|
3744
|
+
const truncatedSql = sql2.slice(0, SQL_ERROR_TRUNCATE_LENGTH);
|
|
3745
|
+
const sqlSuffix = sql2.length > SQL_ERROR_TRUNCATE_LENGTH ? "..." : "";
|
|
3746
|
+
const errorMessage = this.showSqlInErrors ? `SQL Error: ${error.message}
|
|
3747
|
+
Query: ${truncatedSql}${sqlSuffix}` : `SQL Error: ${error.message}`;
|
|
3748
|
+
throw new DatabaseError(errorMessage, DATABASE_ERROR_CODES.QUERY_FAILED, {
|
|
3749
|
+
context: {
|
|
3750
|
+
source: "SQLAdapter.query"
|
|
3751
|
+
},
|
|
3752
|
+
cause: error
|
|
3753
|
+
});
|
|
3751
3754
|
}
|
|
3752
3755
|
}
|
|
3753
3756
|
/**
|
|
@@ -10418,6 +10421,10 @@ __name(DataValidationPipe, "DataValidationPipe");
|
|
|
10418
10421
|
DataValidationPipe = __decorateClass([
|
|
10419
10422
|
Injectable()
|
|
10420
10423
|
], DataValidationPipe);
|
|
10424
|
+
var DESCRIPTION_MAX_LENGTH = 60;
|
|
10425
|
+
var FALLBACK_DESCRIPTION_LENGTH = 50;
|
|
10426
|
+
var PROGRESS_LOG_INTERVAL = 10;
|
|
10427
|
+
var ERROR_MESSAGE_MAX_LENGTH = 300;
|
|
10421
10428
|
var MigrationManager = class {
|
|
10422
10429
|
static {
|
|
10423
10430
|
__name(this, "MigrationManager");
|
|
@@ -10527,6 +10534,116 @@ var MigrationManager = class {
|
|
|
10527
10534
|
}
|
|
10528
10535
|
return { upSQL: sql2.trim(), downSQL: null };
|
|
10529
10536
|
}
|
|
10537
|
+
/**
|
|
10538
|
+
* Process dollar-quoted string delimiters ($$ or $tag$)
|
|
10539
|
+
* Returns updated state for tracking if we're inside a dollar block
|
|
10540
|
+
*/
|
|
10541
|
+
processDollarDelimiters(line, inDollarBlock, dollarTag) {
|
|
10542
|
+
const dollarMatch = line.match(/\$([a-zA-Z_]*)\$/g);
|
|
10543
|
+
if (!dollarMatch) return { inDollarBlock, dollarTag };
|
|
10544
|
+
let currentInBlock = inDollarBlock;
|
|
10545
|
+
let currentTag = dollarTag;
|
|
10546
|
+
for (const match of dollarMatch) {
|
|
10547
|
+
if (!currentInBlock) {
|
|
10548
|
+
currentInBlock = true;
|
|
10549
|
+
currentTag = match;
|
|
10550
|
+
} else if (match === currentTag) {
|
|
10551
|
+
currentInBlock = false;
|
|
10552
|
+
currentTag = "";
|
|
10553
|
+
}
|
|
10554
|
+
}
|
|
10555
|
+
return { inDollarBlock: currentInBlock, dollarTag: currentTag };
|
|
10556
|
+
}
|
|
10557
|
+
/**
|
|
10558
|
+
* Filter out comment-only statements
|
|
10559
|
+
*/
|
|
10560
|
+
isNonCommentStatement(statement) {
|
|
10561
|
+
const withoutComments = statement.replace(/--.*$/gm, "").trim();
|
|
10562
|
+
return withoutComments.length > 0;
|
|
10563
|
+
}
|
|
10564
|
+
/**
|
|
10565
|
+
* Split SQL into individual statements for better error reporting
|
|
10566
|
+
* Handles $$ delimited blocks (functions, triggers) correctly
|
|
10567
|
+
*/
|
|
10568
|
+
splitSqlStatements(sql2) {
|
|
10569
|
+
const statements = [];
|
|
10570
|
+
let current = "";
|
|
10571
|
+
let inDollarBlock = false;
|
|
10572
|
+
let dollarTag = "";
|
|
10573
|
+
for (const line of sql2.split("\n")) {
|
|
10574
|
+
const trimmedLine = line.trim();
|
|
10575
|
+
const isEmptyOrComment = trimmedLine === "" || trimmedLine.startsWith("--");
|
|
10576
|
+
current += line + "\n";
|
|
10577
|
+
if (isEmptyOrComment) continue;
|
|
10578
|
+
const dollarState = this.processDollarDelimiters(line, inDollarBlock, dollarTag);
|
|
10579
|
+
inDollarBlock = dollarState.inDollarBlock;
|
|
10580
|
+
dollarTag = dollarState.dollarTag;
|
|
10581
|
+
const isEndOfStatement = !inDollarBlock && trimmedLine.endsWith(";");
|
|
10582
|
+
if (isEndOfStatement && current.trim()) {
|
|
10583
|
+
statements.push(current.trim());
|
|
10584
|
+
current = "";
|
|
10585
|
+
}
|
|
10586
|
+
}
|
|
10587
|
+
if (current.trim()) {
|
|
10588
|
+
statements.push(current.trim());
|
|
10589
|
+
}
|
|
10590
|
+
return statements.filter((s) => this.isNonCommentStatement(s));
|
|
10591
|
+
}
|
|
10592
|
+
/**
|
|
10593
|
+
* Extract a short description from a SQL statement for logging
|
|
10594
|
+
*/
|
|
10595
|
+
getStatementDescription(statement) {
|
|
10596
|
+
const firstLine = statement.split("\n").find((l) => l.trim() && !l.trim().startsWith("--"))?.trim() ?? "";
|
|
10597
|
+
const patterns = [
|
|
10598
|
+
/^(CREATE\s+(?:OR\s+REPLACE\s+)?(?:TABLE|INDEX|UNIQUE\s+INDEX|TYPE|FUNCTION|TRIGGER|EXTENSION|SCHEMA|VIEW|POLICY))\s+(?:IF\s+NOT\s+EXISTS\s+)?([^\s(]+)/i,
|
|
10599
|
+
/^(ALTER\s+TABLE)\s+([^\s]+)/i,
|
|
10600
|
+
/^(DROP\s+(?:TABLE|INDEX|TYPE|FUNCTION|TRIGGER|EXTENSION|SCHEMA|VIEW|POLICY))\s+(?:IF\s+EXISTS\s+)?([^\s(;]+)/i,
|
|
10601
|
+
/^(INSERT\s+INTO)\s+([^\s(]+)/i,
|
|
10602
|
+
/^(COMMENT\s+ON\s+(?:TABLE|COLUMN|INDEX|FUNCTION|TYPE))\s+([^\s]+)/i,
|
|
10603
|
+
/^(GRANT|REVOKE)\s+.+\s+ON\s+([^\s]+)/i
|
|
10604
|
+
];
|
|
10605
|
+
for (const pattern of patterns) {
|
|
10606
|
+
const match = firstLine.match(pattern);
|
|
10607
|
+
if (match) {
|
|
10608
|
+
return `${match[1]} ${match[2]}`.slice(0, DESCRIPTION_MAX_LENGTH);
|
|
10609
|
+
}
|
|
10610
|
+
}
|
|
10611
|
+
const truncated = firstLine.slice(0, FALLBACK_DESCRIPTION_LENGTH);
|
|
10612
|
+
const suffix = firstLine.length > FALLBACK_DESCRIPTION_LENGTH ? "..." : "";
|
|
10613
|
+
return truncated + suffix;
|
|
10614
|
+
}
|
|
10615
|
+
/**
|
|
10616
|
+
* Execute SQL statements individually with better error reporting
|
|
10617
|
+
*/
|
|
10618
|
+
async executeSqlStatements(adapter, sql2, migrationVersion) {
|
|
10619
|
+
const statements = this.splitSqlStatements(sql2);
|
|
10620
|
+
const total = statements.length;
|
|
10621
|
+
console.log(` → ${total} statements to execute`);
|
|
10622
|
+
for (let i = 0; i < statements.length; i++) {
|
|
10623
|
+
const statement = statements[i];
|
|
10624
|
+
const description = this.getStatementDescription(statement);
|
|
10625
|
+
try {
|
|
10626
|
+
await adapter.query(statement);
|
|
10627
|
+
const isInterval = (i + 1) % PROGRESS_LOG_INTERVAL === 0;
|
|
10628
|
+
const isLast = i === total - 1;
|
|
10629
|
+
const isSignificant = Boolean(description.match(/^(CREATE TABLE|CREATE FUNCTION|CREATE TRIGGER)/i));
|
|
10630
|
+
if (isInterval || isLast || isSignificant) {
|
|
10631
|
+
console.log(` ✓ [${i + 1}/${total}] ${description}`);
|
|
10632
|
+
}
|
|
10633
|
+
} catch (error) {
|
|
10634
|
+
console.log(` ✗ [${i + 1}/${total}] ${description}`);
|
|
10635
|
+
const rawMessage = error.message;
|
|
10636
|
+
const errorMessage = rawMessage.replace(/^SQL Error:\s*/i, "").replace(/^Failed to execute query:.*?-\s*/i, "").slice(0, ERROR_MESSAGE_MAX_LENGTH);
|
|
10637
|
+
throw new DatabaseError(
|
|
10638
|
+
`Migration ${migrationVersion} failed at statement ${i + 1}/${total}:
|
|
10639
|
+
Statement: ${description}
|
|
10640
|
+
Error: ${errorMessage}`,
|
|
10641
|
+
DATABASE_ERROR_CODES.QUERY_FAILED,
|
|
10642
|
+
{ cause: error }
|
|
10643
|
+
);
|
|
10644
|
+
}
|
|
10645
|
+
}
|
|
10646
|
+
}
|
|
10530
10647
|
/**
|
|
10531
10648
|
* Load SQL migration from file
|
|
10532
10649
|
*/
|
|
@@ -10538,12 +10655,20 @@ var MigrationManager = class {
|
|
|
10538
10655
|
name: migrationFile.name,
|
|
10539
10656
|
up: /* @__PURE__ */ __name(async (adapter) => {
|
|
10540
10657
|
if (typeof adapter.query === "function") {
|
|
10541
|
-
await
|
|
10658
|
+
await this.executeSqlStatements(
|
|
10659
|
+
adapter,
|
|
10660
|
+
upSQL,
|
|
10661
|
+
migrationFile.version
|
|
10662
|
+
);
|
|
10542
10663
|
}
|
|
10543
10664
|
}, "up"),
|
|
10544
10665
|
down: /* @__PURE__ */ __name(async (adapter) => {
|
|
10545
10666
|
if (downSQL && typeof adapter.query === "function") {
|
|
10546
|
-
await
|
|
10667
|
+
await this.executeSqlStatements(
|
|
10668
|
+
adapter,
|
|
10669
|
+
downSQL,
|
|
10670
|
+
migrationFile.version
|
|
10671
|
+
);
|
|
10547
10672
|
} else {
|
|
10548
10673
|
console.warn(
|
|
10549
10674
|
`[Migrations] No DOWN migration for ${migrationFile.version}`
|
|
@@ -10650,6 +10775,7 @@ var MigrationManager = class {
|
|
|
10650
10775
|
/**
|
|
10651
10776
|
* Run all pending migrations
|
|
10652
10777
|
*/
|
|
10778
|
+
/* eslint-disable max-depth, complexity */
|
|
10653
10779
|
async up(targetVersion) {
|
|
10654
10780
|
try {
|
|
10655
10781
|
await this.initialize();
|
|
@@ -10670,9 +10796,15 @@ var MigrationManager = class {
|
|
|
10670
10796
|
const migration = await this.loadMigration(migrationFile);
|
|
10671
10797
|
const startTime = Date.now();
|
|
10672
10798
|
if (typeof this.adapter.transaction === "function") {
|
|
10673
|
-
await this.adapter.transaction(async () => {
|
|
10799
|
+
const txResult = await this.adapter.transaction(async () => {
|
|
10674
10800
|
await migration.up(this.adapter);
|
|
10675
10801
|
});
|
|
10802
|
+
if (!txResult.success) {
|
|
10803
|
+
throw txResult.error ?? new DatabaseError(
|
|
10804
|
+
`Migration ${migration.version} failed`,
|
|
10805
|
+
DATABASE_ERROR_CODES.QUERY_FAILED
|
|
10806
|
+
);
|
|
10807
|
+
}
|
|
10676
10808
|
} else {
|
|
10677
10809
|
await migration.up(this.adapter);
|
|
10678
10810
|
}
|
|
@@ -10727,9 +10859,15 @@ var MigrationManager = class {
|
|
|
10727
10859
|
const migration = await this.loadMigration(migrationFile);
|
|
10728
10860
|
const startTime = Date.now();
|
|
10729
10861
|
if (typeof this.adapter.transaction === "function") {
|
|
10730
|
-
await this.adapter.transaction(async () => {
|
|
10862
|
+
const txResult = await this.adapter.transaction(async () => {
|
|
10731
10863
|
await migration.down(this.adapter);
|
|
10732
10864
|
});
|
|
10865
|
+
if (!txResult.success) {
|
|
10866
|
+
throw txResult.error ?? new DatabaseError(
|
|
10867
|
+
`Rollback ${appliedMigration.version} failed`,
|
|
10868
|
+
DATABASE_ERROR_CODES.QUERY_FAILED
|
|
10869
|
+
);
|
|
10870
|
+
}
|
|
10733
10871
|
} else {
|
|
10734
10872
|
await migration.down(this.adapter);
|
|
10735
10873
|
}
|
|
@@ -10788,6 +10926,10 @@ var MigrationManager = class {
|
|
|
10788
10926
|
}
|
|
10789
10927
|
}
|
|
10790
10928
|
};
|
|
10929
|
+
var DESCRIPTION_MAX_LENGTH2 = 60;
|
|
10930
|
+
var FALLBACK_DESCRIPTION_LENGTH2 = 50;
|
|
10931
|
+
var PROGRESS_LOG_INTERVAL2 = 10;
|
|
10932
|
+
var ERROR_MESSAGE_MAX_LENGTH2 = 300;
|
|
10791
10933
|
var SeedManager = class {
|
|
10792
10934
|
static {
|
|
10793
10935
|
__name(this, "SeedManager");
|
|
@@ -10856,7 +10998,7 @@ var SeedManager = class {
|
|
|
10856
10998
|
const files = fs.readdirSync(this.seedsPath);
|
|
10857
10999
|
const seeds = [];
|
|
10858
11000
|
for (const file of files) {
|
|
10859
|
-
const match = file.match(/^(\d+)_(.+)\.(ts|js)$/);
|
|
11001
|
+
const match = file.match(/^(\d+)_(.+)\.(ts|js|sql)$/);
|
|
10860
11002
|
if (match) {
|
|
10861
11003
|
const [, order, name] = match;
|
|
10862
11004
|
seeds.push({
|
|
@@ -10869,9 +11011,137 @@ var SeedManager = class {
|
|
|
10869
11011
|
return seeds.sort((a, b) => a.order - b.order);
|
|
10870
11012
|
}
|
|
10871
11013
|
/**
|
|
10872
|
-
*
|
|
11014
|
+
* Process dollar-quoted string delimiters ($$ or $tag$)
|
|
11015
|
+
*/
|
|
11016
|
+
processDollarDelimiters(line, inDollarBlock, dollarTag) {
|
|
11017
|
+
const dollarMatch = line.match(/\$([a-zA-Z_]*)\$/g);
|
|
11018
|
+
if (!dollarMatch) return { inDollarBlock, dollarTag };
|
|
11019
|
+
let currentInBlock = inDollarBlock;
|
|
11020
|
+
let currentTag = dollarTag;
|
|
11021
|
+
for (const match of dollarMatch) {
|
|
11022
|
+
if (!currentInBlock) {
|
|
11023
|
+
currentInBlock = true;
|
|
11024
|
+
currentTag = match;
|
|
11025
|
+
} else if (match === currentTag) {
|
|
11026
|
+
currentInBlock = false;
|
|
11027
|
+
currentTag = "";
|
|
11028
|
+
}
|
|
11029
|
+
}
|
|
11030
|
+
return { inDollarBlock: currentInBlock, dollarTag: currentTag };
|
|
11031
|
+
}
|
|
11032
|
+
/**
|
|
11033
|
+
* Filter out comment-only statements
|
|
11034
|
+
*/
|
|
11035
|
+
isNonCommentStatement(statement) {
|
|
11036
|
+
const withoutComments = statement.replace(/--.*$/gm, "").trim();
|
|
11037
|
+
return withoutComments.length > 0;
|
|
11038
|
+
}
|
|
11039
|
+
/**
|
|
11040
|
+
* Split SQL into individual statements for better error reporting
|
|
11041
|
+
*/
|
|
11042
|
+
splitSqlStatements(sql2) {
|
|
11043
|
+
const statements = [];
|
|
11044
|
+
let current = "";
|
|
11045
|
+
let inDollarBlock = false;
|
|
11046
|
+
let dollarTag = "";
|
|
11047
|
+
for (const line of sql2.split("\n")) {
|
|
11048
|
+
const trimmedLine = line.trim();
|
|
11049
|
+
const isEmptyOrComment = trimmedLine === "" || trimmedLine.startsWith("--");
|
|
11050
|
+
current += line + "\n";
|
|
11051
|
+
if (isEmptyOrComment) continue;
|
|
11052
|
+
const dollarState = this.processDollarDelimiters(line, inDollarBlock, dollarTag);
|
|
11053
|
+
inDollarBlock = dollarState.inDollarBlock;
|
|
11054
|
+
dollarTag = dollarState.dollarTag;
|
|
11055
|
+
if (!inDollarBlock && trimmedLine.endsWith(";") && current.trim()) {
|
|
11056
|
+
statements.push(current.trim());
|
|
11057
|
+
current = "";
|
|
11058
|
+
}
|
|
11059
|
+
}
|
|
11060
|
+
if (current.trim()) {
|
|
11061
|
+
statements.push(current.trim());
|
|
11062
|
+
}
|
|
11063
|
+
return statements.filter((s) => this.isNonCommentStatement(s));
|
|
11064
|
+
}
|
|
11065
|
+
/**
|
|
11066
|
+
* Extract a short description from a SQL statement for logging
|
|
11067
|
+
*/
|
|
11068
|
+
getStatementDescription(statement) {
|
|
11069
|
+
const firstLine = statement.split("\n").find((l) => l.trim() && !l.trim().startsWith("--"))?.trim() ?? "";
|
|
11070
|
+
const patterns = [
|
|
11071
|
+
/^(CREATE\s+(?:OR\s+REPLACE\s+)?(?:TABLE|INDEX|UNIQUE\s+INDEX|TYPE|FUNCTION|TRIGGER|EXTENSION|SCHEMA|VIEW|POLICY))\s+(?:IF\s+NOT\s+EXISTS\s+)?([^\s(]+)/i,
|
|
11072
|
+
/^(ALTER\s+TABLE)\s+([^\s]+)/i,
|
|
11073
|
+
/^(DROP\s+(?:TABLE|INDEX|TYPE|FUNCTION|TRIGGER|EXTENSION|SCHEMA|VIEW|POLICY))\s+(?:IF\s+EXISTS\s+)?([^\s(;]+)/i,
|
|
11074
|
+
/^(INSERT\s+INTO)\s+([^\s(]+)/i,
|
|
11075
|
+
/^(COMMENT\s+ON\s+(?:TABLE|COLUMN|INDEX|FUNCTION|TYPE))\s+([^\s]+)/i,
|
|
11076
|
+
/^(GRANT|REVOKE)\s+.+\s+ON\s+([^\s]+)/i
|
|
11077
|
+
];
|
|
11078
|
+
for (const pattern of patterns) {
|
|
11079
|
+
const match = firstLine.match(pattern);
|
|
11080
|
+
if (match) {
|
|
11081
|
+
return `${match[1]} ${match[2]}`.slice(0, DESCRIPTION_MAX_LENGTH2);
|
|
11082
|
+
}
|
|
11083
|
+
}
|
|
11084
|
+
const truncated = firstLine.slice(0, FALLBACK_DESCRIPTION_LENGTH2);
|
|
11085
|
+
const suffix = firstLine.length > FALLBACK_DESCRIPTION_LENGTH2 ? "..." : "";
|
|
11086
|
+
return truncated + suffix;
|
|
11087
|
+
}
|
|
11088
|
+
/**
|
|
11089
|
+
* Execute SQL statements individually with better error reporting
|
|
11090
|
+
*/
|
|
11091
|
+
async executeSqlStatements(sql2, seedName) {
|
|
11092
|
+
const statements = this.splitSqlStatements(sql2);
|
|
11093
|
+
const total = statements.length;
|
|
11094
|
+
console.log(` → ${total} statements to execute`);
|
|
11095
|
+
for (let i = 0; i < statements.length; i++) {
|
|
11096
|
+
const statement = statements[i];
|
|
11097
|
+
const description = this.getStatementDescription(statement);
|
|
11098
|
+
try {
|
|
11099
|
+
await this.adapter.query(statement);
|
|
11100
|
+
const isInterval = (i + 1) % PROGRESS_LOG_INTERVAL2 === 0;
|
|
11101
|
+
const isLast = i === total - 1;
|
|
11102
|
+
const isSignificant = Boolean(description.match(/^(INSERT INTO)/i));
|
|
11103
|
+
if (isInterval || isLast || isSignificant) {
|
|
11104
|
+
console.log(` ✓ [${i + 1}/${total}] ${description}`);
|
|
11105
|
+
}
|
|
11106
|
+
} catch (error) {
|
|
11107
|
+
console.log(` ✗ [${i + 1}/${total}] ${description}`);
|
|
11108
|
+
const rawMessage = error.message;
|
|
11109
|
+
const errorMessage = rawMessage.replace(/^SQL Error:\s*/i, "").replace(/^Failed to execute query:.*?-\s*/i, "").slice(0, ERROR_MESSAGE_MAX_LENGTH2);
|
|
11110
|
+
throw new DatabaseError(
|
|
11111
|
+
`Seed "${seedName}" failed at statement ${i + 1}/${total}:
|
|
11112
|
+
Statement: ${description}
|
|
11113
|
+
Error: ${errorMessage}`,
|
|
11114
|
+
DATABASE_ERROR_CODES.QUERY_FAILED,
|
|
11115
|
+
{ cause: error }
|
|
11116
|
+
);
|
|
11117
|
+
}
|
|
11118
|
+
}
|
|
11119
|
+
}
|
|
11120
|
+
/**
|
|
11121
|
+
* Load SQL seed from file
|
|
11122
|
+
*/
|
|
11123
|
+
loadSqlSeed(seedFile) {
|
|
11124
|
+
const sql2 = fs.readFileSync(seedFile.filePath, "utf-8");
|
|
11125
|
+
return {
|
|
11126
|
+
name: seedFile.name,
|
|
11127
|
+
run: /* @__PURE__ */ __name(async () => {
|
|
11128
|
+
if (typeof this.adapter.query === "function") {
|
|
11129
|
+
await this.executeSqlStatements(sql2, seedFile.name);
|
|
11130
|
+
}
|
|
11131
|
+
}, "run"),
|
|
11132
|
+
// SQL seeds don't have cleanup by default
|
|
11133
|
+
cleanup: void 0
|
|
11134
|
+
};
|
|
11135
|
+
}
|
|
11136
|
+
/**
|
|
11137
|
+
* Load seed from file (supports .ts, .js, and .sql)
|
|
10873
11138
|
*/
|
|
11139
|
+
// eslint-disable-next-line complexity
|
|
10874
11140
|
async loadSeed(seedFile) {
|
|
11141
|
+
const ext = path.extname(seedFile.filePath);
|
|
11142
|
+
if (ext === ".sql") {
|
|
11143
|
+
return this.loadSqlSeed(seedFile);
|
|
11144
|
+
}
|
|
10875
11145
|
const importPath = seedFile.filePath.startsWith("/") ? seedFile.filePath : new URL(`file:///${seedFile.filePath.replace(/\\/g, "/")}`).href;
|
|
10876
11146
|
const seedModule = await import(importPath);
|
|
10877
11147
|
return {
|
|
@@ -10925,9 +11195,15 @@ var SeedManager = class {
|
|
|
10925
11195
|
*/
|
|
10926
11196
|
async executeSeed(seed) {
|
|
10927
11197
|
if (typeof this.adapter.transaction === "function") {
|
|
10928
|
-
await this.adapter.transaction(async () => {
|
|
11198
|
+
const txResult = await this.adapter.transaction(async () => {
|
|
10929
11199
|
await seed.run(this.adapter);
|
|
10930
11200
|
});
|
|
11201
|
+
if (!txResult.success) {
|
|
11202
|
+
throw txResult.error ?? new DatabaseError(
|
|
11203
|
+
`Seed ${seed.name} failed`,
|
|
11204
|
+
DATABASE_ERROR_CODES.QUERY_FAILED
|
|
11205
|
+
);
|
|
11206
|
+
}
|
|
10931
11207
|
} else {
|
|
10932
11208
|
await seed.run(this.adapter);
|
|
10933
11209
|
}
|
|
@@ -10984,9 +11260,15 @@ var SeedManager = class {
|
|
|
10984
11260
|
async executeCleanup(seed) {
|
|
10985
11261
|
if (!seed.cleanup) return;
|
|
10986
11262
|
if (typeof this.adapter.transaction === "function") {
|
|
10987
|
-
await this.adapter.transaction(async () => {
|
|
11263
|
+
const txResult = await this.adapter.transaction(async () => {
|
|
10988
11264
|
await seed.cleanup(this.adapter);
|
|
10989
11265
|
});
|
|
11266
|
+
if (!txResult.success) {
|
|
11267
|
+
throw txResult.error ?? new DatabaseError(
|
|
11268
|
+
`Seed cleanup for ${seed.name} failed`,
|
|
11269
|
+
DATABASE_ERROR_CODES.QUERY_FAILED
|
|
11270
|
+
);
|
|
11271
|
+
}
|
|
10990
11272
|
} else {
|
|
10991
11273
|
await seed.cleanup(this.adapter);
|
|
10992
11274
|
}
|