@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.cjs
CHANGED
|
@@ -3621,6 +3621,7 @@ var SupabaseAdapter = class {
|
|
|
3621
3621
|
return ops[operator]();
|
|
3622
3622
|
}
|
|
3623
3623
|
};
|
|
3624
|
+
var SQL_ERROR_TRUNCATE_LENGTH = 500;
|
|
3624
3625
|
var SQLAdapter = class {
|
|
3625
3626
|
static {
|
|
3626
3627
|
__name(this, "SQLAdapter");
|
|
@@ -3631,6 +3632,7 @@ var SQLAdapter = class {
|
|
|
3631
3632
|
idColumnMap = /* @__PURE__ */ new Map();
|
|
3632
3633
|
configIdColumns;
|
|
3633
3634
|
defaultSchema;
|
|
3635
|
+
showSqlInErrors;
|
|
3634
3636
|
/**
|
|
3635
3637
|
* Creates a new SQLAdapter instance.
|
|
3636
3638
|
* @param {SQLAdapterConfig} config - Configuration for the SQL adapter.
|
|
@@ -3644,6 +3646,7 @@ var SQLAdapter = class {
|
|
|
3644
3646
|
constructor(config) {
|
|
3645
3647
|
this.config = config;
|
|
3646
3648
|
this.defaultSchema = config.schema ?? "public";
|
|
3649
|
+
this.showSqlInErrors = config.showSqlInErrors ?? true;
|
|
3647
3650
|
this.pool = new pg.Pool({
|
|
3648
3651
|
connectionString: config.connectionString,
|
|
3649
3652
|
...config.pool
|
|
@@ -3762,16 +3765,16 @@ var SQLAdapter = class {
|
|
|
3762
3765
|
const result = await this.pool.query(sql2, params);
|
|
3763
3766
|
return result.rows;
|
|
3764
3767
|
} catch (error) {
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
);
|
|
3768
|
+
const truncatedSql = sql2.slice(0, SQL_ERROR_TRUNCATE_LENGTH);
|
|
3769
|
+
const sqlSuffix = sql2.length > SQL_ERROR_TRUNCATE_LENGTH ? "..." : "";
|
|
3770
|
+
const errorMessage = this.showSqlInErrors ? `SQL Error: ${error.message}
|
|
3771
|
+
Query: ${truncatedSql}${sqlSuffix}` : `SQL Error: ${error.message}`;
|
|
3772
|
+
throw new errors.DatabaseError(errorMessage, errors$1.DATABASE_ERROR_CODES.QUERY_FAILED, {
|
|
3773
|
+
context: {
|
|
3774
|
+
source: "SQLAdapter.query"
|
|
3775
|
+
},
|
|
3776
|
+
cause: error
|
|
3777
|
+
});
|
|
3775
3778
|
}
|
|
3776
3779
|
}
|
|
3777
3780
|
/**
|
|
@@ -10442,6 +10445,10 @@ __name(exports.DataValidationPipe, "DataValidationPipe");
|
|
|
10442
10445
|
exports.DataValidationPipe = __decorateClass([
|
|
10443
10446
|
common.Injectable()
|
|
10444
10447
|
], exports.DataValidationPipe);
|
|
10448
|
+
var DESCRIPTION_MAX_LENGTH = 60;
|
|
10449
|
+
var FALLBACK_DESCRIPTION_LENGTH = 50;
|
|
10450
|
+
var PROGRESS_LOG_INTERVAL = 10;
|
|
10451
|
+
var ERROR_MESSAGE_MAX_LENGTH = 300;
|
|
10445
10452
|
var MigrationManager = class {
|
|
10446
10453
|
static {
|
|
10447
10454
|
__name(this, "MigrationManager");
|
|
@@ -10551,6 +10558,116 @@ var MigrationManager = class {
|
|
|
10551
10558
|
}
|
|
10552
10559
|
return { upSQL: sql2.trim(), downSQL: null };
|
|
10553
10560
|
}
|
|
10561
|
+
/**
|
|
10562
|
+
* Process dollar-quoted string delimiters ($$ or $tag$)
|
|
10563
|
+
* Returns updated state for tracking if we're inside a dollar block
|
|
10564
|
+
*/
|
|
10565
|
+
processDollarDelimiters(line, inDollarBlock, dollarTag) {
|
|
10566
|
+
const dollarMatch = line.match(/\$([a-zA-Z_]*)\$/g);
|
|
10567
|
+
if (!dollarMatch) return { inDollarBlock, dollarTag };
|
|
10568
|
+
let currentInBlock = inDollarBlock;
|
|
10569
|
+
let currentTag = dollarTag;
|
|
10570
|
+
for (const match of dollarMatch) {
|
|
10571
|
+
if (!currentInBlock) {
|
|
10572
|
+
currentInBlock = true;
|
|
10573
|
+
currentTag = match;
|
|
10574
|
+
} else if (match === currentTag) {
|
|
10575
|
+
currentInBlock = false;
|
|
10576
|
+
currentTag = "";
|
|
10577
|
+
}
|
|
10578
|
+
}
|
|
10579
|
+
return { inDollarBlock: currentInBlock, dollarTag: currentTag };
|
|
10580
|
+
}
|
|
10581
|
+
/**
|
|
10582
|
+
* Filter out comment-only statements
|
|
10583
|
+
*/
|
|
10584
|
+
isNonCommentStatement(statement) {
|
|
10585
|
+
const withoutComments = statement.replace(/--.*$/gm, "").trim();
|
|
10586
|
+
return withoutComments.length > 0;
|
|
10587
|
+
}
|
|
10588
|
+
/**
|
|
10589
|
+
* Split SQL into individual statements for better error reporting
|
|
10590
|
+
* Handles $$ delimited blocks (functions, triggers) correctly
|
|
10591
|
+
*/
|
|
10592
|
+
splitSqlStatements(sql2) {
|
|
10593
|
+
const statements = [];
|
|
10594
|
+
let current = "";
|
|
10595
|
+
let inDollarBlock = false;
|
|
10596
|
+
let dollarTag = "";
|
|
10597
|
+
for (const line of sql2.split("\n")) {
|
|
10598
|
+
const trimmedLine = line.trim();
|
|
10599
|
+
const isEmptyOrComment = trimmedLine === "" || trimmedLine.startsWith("--");
|
|
10600
|
+
current += line + "\n";
|
|
10601
|
+
if (isEmptyOrComment) continue;
|
|
10602
|
+
const dollarState = this.processDollarDelimiters(line, inDollarBlock, dollarTag);
|
|
10603
|
+
inDollarBlock = dollarState.inDollarBlock;
|
|
10604
|
+
dollarTag = dollarState.dollarTag;
|
|
10605
|
+
const isEndOfStatement = !inDollarBlock && trimmedLine.endsWith(";");
|
|
10606
|
+
if (isEndOfStatement && current.trim()) {
|
|
10607
|
+
statements.push(current.trim());
|
|
10608
|
+
current = "";
|
|
10609
|
+
}
|
|
10610
|
+
}
|
|
10611
|
+
if (current.trim()) {
|
|
10612
|
+
statements.push(current.trim());
|
|
10613
|
+
}
|
|
10614
|
+
return statements.filter((s) => this.isNonCommentStatement(s));
|
|
10615
|
+
}
|
|
10616
|
+
/**
|
|
10617
|
+
* Extract a short description from a SQL statement for logging
|
|
10618
|
+
*/
|
|
10619
|
+
getStatementDescription(statement) {
|
|
10620
|
+
const firstLine = statement.split("\n").find((l) => l.trim() && !l.trim().startsWith("--"))?.trim() ?? "";
|
|
10621
|
+
const patterns = [
|
|
10622
|
+
/^(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,
|
|
10623
|
+
/^(ALTER\s+TABLE)\s+([^\s]+)/i,
|
|
10624
|
+
/^(DROP\s+(?:TABLE|INDEX|TYPE|FUNCTION|TRIGGER|EXTENSION|SCHEMA|VIEW|POLICY))\s+(?:IF\s+EXISTS\s+)?([^\s(;]+)/i,
|
|
10625
|
+
/^(INSERT\s+INTO)\s+([^\s(]+)/i,
|
|
10626
|
+
/^(COMMENT\s+ON\s+(?:TABLE|COLUMN|INDEX|FUNCTION|TYPE))\s+([^\s]+)/i,
|
|
10627
|
+
/^(GRANT|REVOKE)\s+.+\s+ON\s+([^\s]+)/i
|
|
10628
|
+
];
|
|
10629
|
+
for (const pattern of patterns) {
|
|
10630
|
+
const match = firstLine.match(pattern);
|
|
10631
|
+
if (match) {
|
|
10632
|
+
return `${match[1]} ${match[2]}`.slice(0, DESCRIPTION_MAX_LENGTH);
|
|
10633
|
+
}
|
|
10634
|
+
}
|
|
10635
|
+
const truncated = firstLine.slice(0, FALLBACK_DESCRIPTION_LENGTH);
|
|
10636
|
+
const suffix = firstLine.length > FALLBACK_DESCRIPTION_LENGTH ? "..." : "";
|
|
10637
|
+
return truncated + suffix;
|
|
10638
|
+
}
|
|
10639
|
+
/**
|
|
10640
|
+
* Execute SQL statements individually with better error reporting
|
|
10641
|
+
*/
|
|
10642
|
+
async executeSqlStatements(adapter, sql2, migrationVersion) {
|
|
10643
|
+
const statements = this.splitSqlStatements(sql2);
|
|
10644
|
+
const total = statements.length;
|
|
10645
|
+
console.log(` → ${total} statements to execute`);
|
|
10646
|
+
for (let i = 0; i < statements.length; i++) {
|
|
10647
|
+
const statement = statements[i];
|
|
10648
|
+
const description = this.getStatementDescription(statement);
|
|
10649
|
+
try {
|
|
10650
|
+
await adapter.query(statement);
|
|
10651
|
+
const isInterval = (i + 1) % PROGRESS_LOG_INTERVAL === 0;
|
|
10652
|
+
const isLast = i === total - 1;
|
|
10653
|
+
const isSignificant = Boolean(description.match(/^(CREATE TABLE|CREATE FUNCTION|CREATE TRIGGER)/i));
|
|
10654
|
+
if (isInterval || isLast || isSignificant) {
|
|
10655
|
+
console.log(` ✓ [${i + 1}/${total}] ${description}`);
|
|
10656
|
+
}
|
|
10657
|
+
} catch (error) {
|
|
10658
|
+
console.log(` ✗ [${i + 1}/${total}] ${description}`);
|
|
10659
|
+
const rawMessage = error.message;
|
|
10660
|
+
const errorMessage = rawMessage.replace(/^SQL Error:\s*/i, "").replace(/^Failed to execute query:.*?-\s*/i, "").slice(0, ERROR_MESSAGE_MAX_LENGTH);
|
|
10661
|
+
throw new errors.DatabaseError(
|
|
10662
|
+
`Migration ${migrationVersion} failed at statement ${i + 1}/${total}:
|
|
10663
|
+
Statement: ${description}
|
|
10664
|
+
Error: ${errorMessage}`,
|
|
10665
|
+
errors$1.DATABASE_ERROR_CODES.QUERY_FAILED,
|
|
10666
|
+
{ cause: error }
|
|
10667
|
+
);
|
|
10668
|
+
}
|
|
10669
|
+
}
|
|
10670
|
+
}
|
|
10554
10671
|
/**
|
|
10555
10672
|
* Load SQL migration from file
|
|
10556
10673
|
*/
|
|
@@ -10562,12 +10679,20 @@ var MigrationManager = class {
|
|
|
10562
10679
|
name: migrationFile.name,
|
|
10563
10680
|
up: /* @__PURE__ */ __name(async (adapter) => {
|
|
10564
10681
|
if (typeof adapter.query === "function") {
|
|
10565
|
-
await
|
|
10682
|
+
await this.executeSqlStatements(
|
|
10683
|
+
adapter,
|
|
10684
|
+
upSQL,
|
|
10685
|
+
migrationFile.version
|
|
10686
|
+
);
|
|
10566
10687
|
}
|
|
10567
10688
|
}, "up"),
|
|
10568
10689
|
down: /* @__PURE__ */ __name(async (adapter) => {
|
|
10569
10690
|
if (downSQL && typeof adapter.query === "function") {
|
|
10570
|
-
await
|
|
10691
|
+
await this.executeSqlStatements(
|
|
10692
|
+
adapter,
|
|
10693
|
+
downSQL,
|
|
10694
|
+
migrationFile.version
|
|
10695
|
+
);
|
|
10571
10696
|
} else {
|
|
10572
10697
|
console.warn(
|
|
10573
10698
|
`[Migrations] No DOWN migration for ${migrationFile.version}`
|
|
@@ -10674,6 +10799,7 @@ var MigrationManager = class {
|
|
|
10674
10799
|
/**
|
|
10675
10800
|
* Run all pending migrations
|
|
10676
10801
|
*/
|
|
10802
|
+
/* eslint-disable max-depth, complexity */
|
|
10677
10803
|
async up(targetVersion) {
|
|
10678
10804
|
try {
|
|
10679
10805
|
await this.initialize();
|
|
@@ -10694,9 +10820,15 @@ var MigrationManager = class {
|
|
|
10694
10820
|
const migration = await this.loadMigration(migrationFile);
|
|
10695
10821
|
const startTime = Date.now();
|
|
10696
10822
|
if (typeof this.adapter.transaction === "function") {
|
|
10697
|
-
await this.adapter.transaction(async () => {
|
|
10823
|
+
const txResult = await this.adapter.transaction(async () => {
|
|
10698
10824
|
await migration.up(this.adapter);
|
|
10699
10825
|
});
|
|
10826
|
+
if (!txResult.success) {
|
|
10827
|
+
throw txResult.error ?? new errors.DatabaseError(
|
|
10828
|
+
`Migration ${migration.version} failed`,
|
|
10829
|
+
errors$1.DATABASE_ERROR_CODES.QUERY_FAILED
|
|
10830
|
+
);
|
|
10831
|
+
}
|
|
10700
10832
|
} else {
|
|
10701
10833
|
await migration.up(this.adapter);
|
|
10702
10834
|
}
|
|
@@ -10751,9 +10883,15 @@ var MigrationManager = class {
|
|
|
10751
10883
|
const migration = await this.loadMigration(migrationFile);
|
|
10752
10884
|
const startTime = Date.now();
|
|
10753
10885
|
if (typeof this.adapter.transaction === "function") {
|
|
10754
|
-
await this.adapter.transaction(async () => {
|
|
10886
|
+
const txResult = await this.adapter.transaction(async () => {
|
|
10755
10887
|
await migration.down(this.adapter);
|
|
10756
10888
|
});
|
|
10889
|
+
if (!txResult.success) {
|
|
10890
|
+
throw txResult.error ?? new errors.DatabaseError(
|
|
10891
|
+
`Rollback ${appliedMigration.version} failed`,
|
|
10892
|
+
errors$1.DATABASE_ERROR_CODES.QUERY_FAILED
|
|
10893
|
+
);
|
|
10894
|
+
}
|
|
10757
10895
|
} else {
|
|
10758
10896
|
await migration.down(this.adapter);
|
|
10759
10897
|
}
|
|
@@ -10812,6 +10950,10 @@ var MigrationManager = class {
|
|
|
10812
10950
|
}
|
|
10813
10951
|
}
|
|
10814
10952
|
};
|
|
10953
|
+
var DESCRIPTION_MAX_LENGTH2 = 60;
|
|
10954
|
+
var FALLBACK_DESCRIPTION_LENGTH2 = 50;
|
|
10955
|
+
var PROGRESS_LOG_INTERVAL2 = 10;
|
|
10956
|
+
var ERROR_MESSAGE_MAX_LENGTH2 = 300;
|
|
10815
10957
|
var SeedManager = class {
|
|
10816
10958
|
static {
|
|
10817
10959
|
__name(this, "SeedManager");
|
|
@@ -10880,7 +11022,7 @@ var SeedManager = class {
|
|
|
10880
11022
|
const files = fs__namespace.readdirSync(this.seedsPath);
|
|
10881
11023
|
const seeds = [];
|
|
10882
11024
|
for (const file of files) {
|
|
10883
|
-
const match = file.match(/^(\d+)_(.+)\.(ts|js)$/);
|
|
11025
|
+
const match = file.match(/^(\d+)_(.+)\.(ts|js|sql)$/);
|
|
10884
11026
|
if (match) {
|
|
10885
11027
|
const [, order, name] = match;
|
|
10886
11028
|
seeds.push({
|
|
@@ -10893,9 +11035,137 @@ var SeedManager = class {
|
|
|
10893
11035
|
return seeds.sort((a, b) => a.order - b.order);
|
|
10894
11036
|
}
|
|
10895
11037
|
/**
|
|
10896
|
-
*
|
|
11038
|
+
* Process dollar-quoted string delimiters ($$ or $tag$)
|
|
11039
|
+
*/
|
|
11040
|
+
processDollarDelimiters(line, inDollarBlock, dollarTag) {
|
|
11041
|
+
const dollarMatch = line.match(/\$([a-zA-Z_]*)\$/g);
|
|
11042
|
+
if (!dollarMatch) return { inDollarBlock, dollarTag };
|
|
11043
|
+
let currentInBlock = inDollarBlock;
|
|
11044
|
+
let currentTag = dollarTag;
|
|
11045
|
+
for (const match of dollarMatch) {
|
|
11046
|
+
if (!currentInBlock) {
|
|
11047
|
+
currentInBlock = true;
|
|
11048
|
+
currentTag = match;
|
|
11049
|
+
} else if (match === currentTag) {
|
|
11050
|
+
currentInBlock = false;
|
|
11051
|
+
currentTag = "";
|
|
11052
|
+
}
|
|
11053
|
+
}
|
|
11054
|
+
return { inDollarBlock: currentInBlock, dollarTag: currentTag };
|
|
11055
|
+
}
|
|
11056
|
+
/**
|
|
11057
|
+
* Filter out comment-only statements
|
|
11058
|
+
*/
|
|
11059
|
+
isNonCommentStatement(statement) {
|
|
11060
|
+
const withoutComments = statement.replace(/--.*$/gm, "").trim();
|
|
11061
|
+
return withoutComments.length > 0;
|
|
11062
|
+
}
|
|
11063
|
+
/**
|
|
11064
|
+
* Split SQL into individual statements for better error reporting
|
|
11065
|
+
*/
|
|
11066
|
+
splitSqlStatements(sql2) {
|
|
11067
|
+
const statements = [];
|
|
11068
|
+
let current = "";
|
|
11069
|
+
let inDollarBlock = false;
|
|
11070
|
+
let dollarTag = "";
|
|
11071
|
+
for (const line of sql2.split("\n")) {
|
|
11072
|
+
const trimmedLine = line.trim();
|
|
11073
|
+
const isEmptyOrComment = trimmedLine === "" || trimmedLine.startsWith("--");
|
|
11074
|
+
current += line + "\n";
|
|
11075
|
+
if (isEmptyOrComment) continue;
|
|
11076
|
+
const dollarState = this.processDollarDelimiters(line, inDollarBlock, dollarTag);
|
|
11077
|
+
inDollarBlock = dollarState.inDollarBlock;
|
|
11078
|
+
dollarTag = dollarState.dollarTag;
|
|
11079
|
+
if (!inDollarBlock && trimmedLine.endsWith(";") && current.trim()) {
|
|
11080
|
+
statements.push(current.trim());
|
|
11081
|
+
current = "";
|
|
11082
|
+
}
|
|
11083
|
+
}
|
|
11084
|
+
if (current.trim()) {
|
|
11085
|
+
statements.push(current.trim());
|
|
11086
|
+
}
|
|
11087
|
+
return statements.filter((s) => this.isNonCommentStatement(s));
|
|
11088
|
+
}
|
|
11089
|
+
/**
|
|
11090
|
+
* Extract a short description from a SQL statement for logging
|
|
11091
|
+
*/
|
|
11092
|
+
getStatementDescription(statement) {
|
|
11093
|
+
const firstLine = statement.split("\n").find((l) => l.trim() && !l.trim().startsWith("--"))?.trim() ?? "";
|
|
11094
|
+
const patterns = [
|
|
11095
|
+
/^(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,
|
|
11096
|
+
/^(ALTER\s+TABLE)\s+([^\s]+)/i,
|
|
11097
|
+
/^(DROP\s+(?:TABLE|INDEX|TYPE|FUNCTION|TRIGGER|EXTENSION|SCHEMA|VIEW|POLICY))\s+(?:IF\s+EXISTS\s+)?([^\s(;]+)/i,
|
|
11098
|
+
/^(INSERT\s+INTO)\s+([^\s(]+)/i,
|
|
11099
|
+
/^(COMMENT\s+ON\s+(?:TABLE|COLUMN|INDEX|FUNCTION|TYPE))\s+([^\s]+)/i,
|
|
11100
|
+
/^(GRANT|REVOKE)\s+.+\s+ON\s+([^\s]+)/i
|
|
11101
|
+
];
|
|
11102
|
+
for (const pattern of patterns) {
|
|
11103
|
+
const match = firstLine.match(pattern);
|
|
11104
|
+
if (match) {
|
|
11105
|
+
return `${match[1]} ${match[2]}`.slice(0, DESCRIPTION_MAX_LENGTH2);
|
|
11106
|
+
}
|
|
11107
|
+
}
|
|
11108
|
+
const truncated = firstLine.slice(0, FALLBACK_DESCRIPTION_LENGTH2);
|
|
11109
|
+
const suffix = firstLine.length > FALLBACK_DESCRIPTION_LENGTH2 ? "..." : "";
|
|
11110
|
+
return truncated + suffix;
|
|
11111
|
+
}
|
|
11112
|
+
/**
|
|
11113
|
+
* Execute SQL statements individually with better error reporting
|
|
11114
|
+
*/
|
|
11115
|
+
async executeSqlStatements(sql2, seedName) {
|
|
11116
|
+
const statements = this.splitSqlStatements(sql2);
|
|
11117
|
+
const total = statements.length;
|
|
11118
|
+
console.log(` → ${total} statements to execute`);
|
|
11119
|
+
for (let i = 0; i < statements.length; i++) {
|
|
11120
|
+
const statement = statements[i];
|
|
11121
|
+
const description = this.getStatementDescription(statement);
|
|
11122
|
+
try {
|
|
11123
|
+
await this.adapter.query(statement);
|
|
11124
|
+
const isInterval = (i + 1) % PROGRESS_LOG_INTERVAL2 === 0;
|
|
11125
|
+
const isLast = i === total - 1;
|
|
11126
|
+
const isSignificant = Boolean(description.match(/^(INSERT INTO)/i));
|
|
11127
|
+
if (isInterval || isLast || isSignificant) {
|
|
11128
|
+
console.log(` ✓ [${i + 1}/${total}] ${description}`);
|
|
11129
|
+
}
|
|
11130
|
+
} catch (error) {
|
|
11131
|
+
console.log(` ✗ [${i + 1}/${total}] ${description}`);
|
|
11132
|
+
const rawMessage = error.message;
|
|
11133
|
+
const errorMessage = rawMessage.replace(/^SQL Error:\s*/i, "").replace(/^Failed to execute query:.*?-\s*/i, "").slice(0, ERROR_MESSAGE_MAX_LENGTH2);
|
|
11134
|
+
throw new errors.DatabaseError(
|
|
11135
|
+
`Seed "${seedName}" failed at statement ${i + 1}/${total}:
|
|
11136
|
+
Statement: ${description}
|
|
11137
|
+
Error: ${errorMessage}`,
|
|
11138
|
+
errors$1.DATABASE_ERROR_CODES.QUERY_FAILED,
|
|
11139
|
+
{ cause: error }
|
|
11140
|
+
);
|
|
11141
|
+
}
|
|
11142
|
+
}
|
|
11143
|
+
}
|
|
11144
|
+
/**
|
|
11145
|
+
* Load SQL seed from file
|
|
11146
|
+
*/
|
|
11147
|
+
loadSqlSeed(seedFile) {
|
|
11148
|
+
const sql2 = fs__namespace.readFileSync(seedFile.filePath, "utf-8");
|
|
11149
|
+
return {
|
|
11150
|
+
name: seedFile.name,
|
|
11151
|
+
run: /* @__PURE__ */ __name(async () => {
|
|
11152
|
+
if (typeof this.adapter.query === "function") {
|
|
11153
|
+
await this.executeSqlStatements(sql2, seedFile.name);
|
|
11154
|
+
}
|
|
11155
|
+
}, "run"),
|
|
11156
|
+
// SQL seeds don't have cleanup by default
|
|
11157
|
+
cleanup: void 0
|
|
11158
|
+
};
|
|
11159
|
+
}
|
|
11160
|
+
/**
|
|
11161
|
+
* Load seed from file (supports .ts, .js, and .sql)
|
|
10897
11162
|
*/
|
|
11163
|
+
// eslint-disable-next-line complexity
|
|
10898
11164
|
async loadSeed(seedFile) {
|
|
11165
|
+
const ext = path__namespace.extname(seedFile.filePath);
|
|
11166
|
+
if (ext === ".sql") {
|
|
11167
|
+
return this.loadSqlSeed(seedFile);
|
|
11168
|
+
}
|
|
10899
11169
|
const importPath = seedFile.filePath.startsWith("/") ? seedFile.filePath : new URL(`file:///${seedFile.filePath.replace(/\\/g, "/")}`).href;
|
|
10900
11170
|
const seedModule = await import(importPath);
|
|
10901
11171
|
return {
|
|
@@ -10949,9 +11219,15 @@ var SeedManager = class {
|
|
|
10949
11219
|
*/
|
|
10950
11220
|
async executeSeed(seed) {
|
|
10951
11221
|
if (typeof this.adapter.transaction === "function") {
|
|
10952
|
-
await this.adapter.transaction(async () => {
|
|
11222
|
+
const txResult = await this.adapter.transaction(async () => {
|
|
10953
11223
|
await seed.run(this.adapter);
|
|
10954
11224
|
});
|
|
11225
|
+
if (!txResult.success) {
|
|
11226
|
+
throw txResult.error ?? new errors.DatabaseError(
|
|
11227
|
+
`Seed ${seed.name} failed`,
|
|
11228
|
+
errors$1.DATABASE_ERROR_CODES.QUERY_FAILED
|
|
11229
|
+
);
|
|
11230
|
+
}
|
|
10955
11231
|
} else {
|
|
10956
11232
|
await seed.run(this.adapter);
|
|
10957
11233
|
}
|
|
@@ -11008,9 +11284,15 @@ var SeedManager = class {
|
|
|
11008
11284
|
async executeCleanup(seed) {
|
|
11009
11285
|
if (!seed.cleanup) return;
|
|
11010
11286
|
if (typeof this.adapter.transaction === "function") {
|
|
11011
|
-
await this.adapter.transaction(async () => {
|
|
11287
|
+
const txResult = await this.adapter.transaction(async () => {
|
|
11012
11288
|
await seed.cleanup(this.adapter);
|
|
11013
11289
|
});
|
|
11290
|
+
if (!txResult.success) {
|
|
11291
|
+
throw txResult.error ?? new errors.DatabaseError(
|
|
11292
|
+
`Seed cleanup for ${seed.name} failed`,
|
|
11293
|
+
errors$1.DATABASE_ERROR_CODES.QUERY_FAILED
|
|
11294
|
+
);
|
|
11295
|
+
}
|
|
11014
11296
|
} else {
|
|
11015
11297
|
await seed.cleanup(this.adapter);
|
|
11016
11298
|
}
|