@magnet-cms/adapter-db-drizzle 1.0.2 → 2.0.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/index.cjs +100 -28
- package/dist/index.d.cts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +100 -29
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
require('reflect-metadata');
|
|
4
4
|
var common = require('@magnet-cms/common');
|
|
5
5
|
var common$1 = require('@nestjs/common');
|
|
6
|
+
var crypto = require('crypto');
|
|
6
7
|
var utils = require('@magnet-cms/utils');
|
|
7
8
|
var drizzleOrm = require('drizzle-orm');
|
|
8
9
|
var pgCore = require('drizzle-orm/pg-core');
|
|
9
10
|
var nodePostgres = require('drizzle-orm/node-postgres');
|
|
10
11
|
var promises = require('fs/promises');
|
|
11
12
|
var path = require('path');
|
|
12
|
-
var crypto = require('crypto');
|
|
13
13
|
|
|
14
14
|
var __create = Object.create;
|
|
15
15
|
var __defProp = Object.defineProperty;
|
|
@@ -10997,8 +10997,11 @@ function generateSchema(schemaClass) {
|
|
|
10997
10997
|
});
|
|
10998
10998
|
const columns = {
|
|
10999
10999
|
// Primary key - always UUID
|
|
11000
|
-
//
|
|
11001
|
-
|
|
11000
|
+
// $defaultFn generates UUIDs in JS (works on all dialects: PostgreSQL, MySQL, SQLite)
|
|
11001
|
+
// Note: SQL .default(gen_random_uuid()) is intentionally omitted because it conflicts
|
|
11002
|
+
// with $defaultFn when using pg-core types on non-PostgreSQL drivers.
|
|
11003
|
+
// The createTableFromConfig() method adds dialect-appropriate SQL DEFAULT for direct inserts.
|
|
11004
|
+
id: pgCore.uuid("id").primaryKey().$defaultFn(() => crypto.randomUUID())
|
|
11002
11005
|
};
|
|
11003
11006
|
if (hasI18n || hasVersioning || hasIntlProps) {
|
|
11004
11007
|
const docOptions = {
|
|
@@ -11014,8 +11017,8 @@ function generateSchema(schemaClass) {
|
|
|
11014
11017
|
columns[columnName] = column;
|
|
11015
11018
|
}
|
|
11016
11019
|
});
|
|
11017
|
-
columns.createdAt = pgCore.timestamp("created_at").
|
|
11018
|
-
columns.updatedAt = pgCore.timestamp("updated_at").
|
|
11020
|
+
columns.createdAt = pgCore.timestamp("created_at").notNull();
|
|
11021
|
+
columns.updatedAt = pgCore.timestamp("updated_at").notNull();
|
|
11019
11022
|
const table = pgCore.pgTable(tableName, columns, (table2) => {
|
|
11020
11023
|
const tableIndexes = {};
|
|
11021
11024
|
const t = table2;
|
|
@@ -11065,7 +11068,9 @@ function generateColumn(columnName, options) {
|
|
|
11065
11068
|
column = pgCore.text(snakeCaseName);
|
|
11066
11069
|
}
|
|
11067
11070
|
if (options.default !== void 0) {
|
|
11068
|
-
|
|
11071
|
+
if (Array.isArray(options.default) && options.default.length === 0) ; else {
|
|
11072
|
+
column = column.default(options.default);
|
|
11073
|
+
}
|
|
11069
11074
|
}
|
|
11070
11075
|
return column;
|
|
11071
11076
|
}
|
|
@@ -11089,8 +11094,8 @@ async function createNeonConnection(config) {
|
|
|
11089
11094
|
} catch {
|
|
11090
11095
|
throw new Error("@neondatabase/serverless is required for Neon driver. Install it with: bun add @neondatabase/serverless");
|
|
11091
11096
|
}
|
|
11092
|
-
const
|
|
11093
|
-
const db = drizzleNeon.drizzle(
|
|
11097
|
+
const sql4 = neon.neon(config.connectionString);
|
|
11098
|
+
const db = drizzleNeon.drizzle(sql4, {
|
|
11094
11099
|
logger: config.debug
|
|
11095
11100
|
});
|
|
11096
11101
|
return {
|
|
@@ -11558,6 +11563,11 @@ var DrizzleQueryBuilder = class extends common.QueryBuilder {
|
|
|
11558
11563
|
};
|
|
11559
11564
|
|
|
11560
11565
|
// src/drizzle.model.ts
|
|
11566
|
+
function isSQLiteDriver(db) {
|
|
11567
|
+
const d = db;
|
|
11568
|
+
return typeof d.run === "function" && typeof d.execute !== "function";
|
|
11569
|
+
}
|
|
11570
|
+
__name(isSQLiteDriver, "isSQLiteDriver");
|
|
11561
11571
|
function createModel(db, table, schemaClass) {
|
|
11562
11572
|
return class DrizzleModelAdapter extends common.Model {
|
|
11563
11573
|
static {
|
|
@@ -11621,8 +11631,9 @@ function createModel(db, table, schemaClass) {
|
|
|
11621
11631
|
const insertData = {
|
|
11622
11632
|
...this._prepareData(data, true)
|
|
11623
11633
|
};
|
|
11634
|
+
this._applyDeclaredEmptyArrayDefaults(insertData);
|
|
11624
11635
|
if ("documentId" in dynamicTable) {
|
|
11625
|
-
insertData.documentId = insertData.documentId ||
|
|
11636
|
+
insertData.documentId = insertData.documentId || crypto.randomUUID();
|
|
11626
11637
|
insertData.locale = insertData.locale || this.currentLocale || DEFAULT_LOCALE;
|
|
11627
11638
|
insertData.status = insertData.status || DOCUMENT_STATUS.DRAFT;
|
|
11628
11639
|
}
|
|
@@ -12009,14 +12020,29 @@ function createModel(db, table, schemaClass) {
|
|
|
12009
12020
|
* For JSONB columns (arrays/objects), ensure values are properly formatted
|
|
12010
12021
|
* @internal
|
|
12011
12022
|
*/
|
|
12023
|
+
/**
|
|
12024
|
+
* Fields declared with `default: []` omit a DB default (cross-dialect migration/runtime).
|
|
12025
|
+
* Fill missing keys so inserts match Mongoose-style expectations.
|
|
12026
|
+
*/
|
|
12027
|
+
_applyDeclaredEmptyArrayDefaults(row) {
|
|
12028
|
+
const props = getDrizzlePropsMetadata(this._schemaClass);
|
|
12029
|
+
for (const [propertyKey, options] of props) {
|
|
12030
|
+
const key = String(propertyKey);
|
|
12031
|
+
if (options.default !== void 0 && Array.isArray(options.default) && options.default.length === 0 && row[key] === void 0) {
|
|
12032
|
+
row[key] = isSQLiteDriver(this._db) ? JSON.stringify([]) : [];
|
|
12033
|
+
}
|
|
12034
|
+
}
|
|
12035
|
+
}
|
|
12012
12036
|
_prepareData(data, isCreate = false) {
|
|
12013
12037
|
const result = {};
|
|
12014
|
-
|
|
12015
|
-
|
|
12038
|
+
const isSQLite = isSQLiteDriver(this._db);
|
|
12039
|
+
if (isCreate) {
|
|
12040
|
+
result.createdAt = data.createdAt instanceof Date ? data.createdAt : /* @__PURE__ */ new Date();
|
|
12016
12041
|
}
|
|
12042
|
+
result.updatedAt = data.updatedAt instanceof Date ? data.updatedAt : /* @__PURE__ */ new Date();
|
|
12017
12043
|
for (const [key, value] of Object.entries(data)) {
|
|
12018
12044
|
if (key === "id") continue;
|
|
12019
|
-
if (key === "createdAt") continue;
|
|
12045
|
+
if (key === "createdAt" || key === "updatedAt") continue;
|
|
12020
12046
|
if (value === void 0) {
|
|
12021
12047
|
continue;
|
|
12022
12048
|
}
|
|
@@ -12024,6 +12050,10 @@ function createModel(db, table, schemaClass) {
|
|
|
12024
12050
|
result[key] = null;
|
|
12025
12051
|
continue;
|
|
12026
12052
|
}
|
|
12053
|
+
if (typeof value === "boolean" && isSQLite) {
|
|
12054
|
+
result[key] = value ? 1 : 0;
|
|
12055
|
+
continue;
|
|
12056
|
+
}
|
|
12027
12057
|
if (value instanceof Date) {
|
|
12028
12058
|
result[key] = value;
|
|
12029
12059
|
continue;
|
|
@@ -12042,7 +12072,7 @@ function createModel(db, table, schemaClass) {
|
|
|
12042
12072
|
result[key] = value;
|
|
12043
12073
|
}
|
|
12044
12074
|
} else if (Array.isArray(value)) {
|
|
12045
|
-
result[key] = value;
|
|
12075
|
+
result[key] = isSQLite ? JSON.stringify(value) : value;
|
|
12046
12076
|
} else if (value !== null && typeof value === "object") {
|
|
12047
12077
|
result[key] = value;
|
|
12048
12078
|
} else {
|
|
@@ -12102,13 +12132,13 @@ var AutoMigration = class {
|
|
|
12102
12132
|
dangerous: diffResult.dangerous,
|
|
12103
12133
|
warnings: diffResult.warnings,
|
|
12104
12134
|
async up(db) {
|
|
12105
|
-
for (const
|
|
12135
|
+
for (const sql4 of upSQL) {
|
|
12106
12136
|
try {
|
|
12107
|
-
await db.execute(
|
|
12137
|
+
await db.execute(sql4);
|
|
12108
12138
|
} catch (err) {
|
|
12109
12139
|
const msg = err instanceof Error ? err.message : String(err);
|
|
12110
12140
|
const code = err && typeof err === "object" && "code" in err ? err.code : void 0;
|
|
12111
|
-
if (code === "42P07" || msg.includes("already exists") || msg.includes("ER_TABLE_EXISTS") || msg.includes("duplicate table name")) {
|
|
12141
|
+
if (code === "42P07" || code === "42710" || msg.includes("already exists") || msg.includes("ER_TABLE_EXISTS") || msg.includes("duplicate table name") || msg.includes("duplicate key value")) {
|
|
12112
12142
|
logger.warn(`Skipping (object already exists): ${msg.slice(0, 80)}`);
|
|
12113
12143
|
continue;
|
|
12114
12144
|
}
|
|
@@ -12136,8 +12166,8 @@ var MigrationGenerator = class {
|
|
|
12136
12166
|
generate(name, upSQL, downSQL, options = {}) {
|
|
12137
12167
|
const timestamp3 = Date.now();
|
|
12138
12168
|
const id = `${timestamp3}_${name}`;
|
|
12139
|
-
const upStatements = upSQL.map((
|
|
12140
|
-
const downStatements = downSQL.length > 0 ? downSQL.map((
|
|
12169
|
+
const upStatements = upSQL.map((sql4) => ` await db.execute(\`${sql4}\`)`).join("\n");
|
|
12170
|
+
const downStatements = downSQL.length > 0 ? downSQL.map((sql4) => ` await db.execute(\`${sql4}\`)`).join("\n") : " // TODO: implement down migration";
|
|
12141
12171
|
const dangerousField = options.dangerous ? "\n dangerous: true," : "";
|
|
12142
12172
|
const warningsField = options.warnings && options.warnings.length > 0 ? `
|
|
12143
12173
|
warnings: [
|
|
@@ -12484,6 +12514,12 @@ var MigrationRunner = class {
|
|
|
12484
12514
|
};
|
|
12485
12515
|
}
|
|
12486
12516
|
};
|
|
12517
|
+
function sanitizeExecutableMigrationSql(dialect, statement) {
|
|
12518
|
+
if (dialect !== "postgresql") return statement;
|
|
12519
|
+
if (!statement.includes("$")) return statement;
|
|
12520
|
+
return statement.replace(/"locale" = \$1/g, `"locale" = 'en'`).replace(/"status" = \$2/g, `"status" = 'draft'`);
|
|
12521
|
+
}
|
|
12522
|
+
__name(sanitizeExecutableMigrationSql, "sanitizeExecutableMigrationSql");
|
|
12487
12523
|
var SNAPSHOT_FILENAME = ".schema_snapshot.json";
|
|
12488
12524
|
var SchemaBridge = class {
|
|
12489
12525
|
static {
|
|
@@ -12523,7 +12559,8 @@ var SchemaBridge = class {
|
|
|
12523
12559
|
*/
|
|
12524
12560
|
async generateSQL(prev, cur, generateSQLFn, dialect = "postgresql") {
|
|
12525
12561
|
const fn = generateSQLFn ?? await this.resolveGenerateSQLFn(dialect);
|
|
12526
|
-
|
|
12562
|
+
const statements = await fn(prev, cur);
|
|
12563
|
+
return statements.map((s) => sanitizeExecutableMigrationSql(dialect, s));
|
|
12527
12564
|
}
|
|
12528
12565
|
/**
|
|
12529
12566
|
* Load a previously saved snapshot from disk.
|
|
@@ -12652,9 +12689,9 @@ var SchemaDiff = class {
|
|
|
12652
12689
|
*/
|
|
12653
12690
|
detectDangerousOperations(sqlStatements) {
|
|
12654
12691
|
const warnings = [];
|
|
12655
|
-
for (const
|
|
12692
|
+
for (const sql4 of sqlStatements) {
|
|
12656
12693
|
for (const { pattern, message } of DANGEROUS_PATTERNS) {
|
|
12657
|
-
const match =
|
|
12694
|
+
const match = sql4.match(pattern);
|
|
12658
12695
|
if (match) {
|
|
12659
12696
|
warnings.push(message(match[1] ?? match[0]));
|
|
12660
12697
|
}
|
|
@@ -12708,14 +12745,27 @@ exports.DrizzleDatabaseAdapter = class _DrizzleDatabaseAdapter extends common.Da
|
|
|
12708
12745
|
options = null;
|
|
12709
12746
|
schemaRegistry = /* @__PURE__ */ new Map();
|
|
12710
12747
|
tablesInitialized = false;
|
|
12748
|
+
tablesInitPromise = null;
|
|
12711
12749
|
/**
|
|
12712
12750
|
* Automatically create tables for all registered schemas.
|
|
12713
12751
|
* Called lazily when first model is accessed, or can be called explicitly.
|
|
12752
|
+
* Uses a lock (Promise) to prevent concurrent execution from multiple forFeature() calls.
|
|
12714
12753
|
*/
|
|
12715
12754
|
async ensureTablesCreated() {
|
|
12716
12755
|
if (this.tablesInitialized || !this.db || this.schemaRegistry.size === 0) {
|
|
12717
12756
|
return;
|
|
12718
12757
|
}
|
|
12758
|
+
if (this.tablesInitPromise) {
|
|
12759
|
+
return this.tablesInitPromise;
|
|
12760
|
+
}
|
|
12761
|
+
this.tablesInitPromise = this._doEnsureTablesCreated();
|
|
12762
|
+
try {
|
|
12763
|
+
await this.tablesInitPromise;
|
|
12764
|
+
} finally {
|
|
12765
|
+
this.tablesInitPromise = null;
|
|
12766
|
+
}
|
|
12767
|
+
}
|
|
12768
|
+
async _doEnsureTablesCreated() {
|
|
12719
12769
|
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
12720
12770
|
const drizzleConfig = this.options;
|
|
12721
12771
|
if (drizzleConfig?.migrations) {
|
|
@@ -12734,7 +12784,7 @@ exports.DrizzleDatabaseAdapter = class _DrizzleDatabaseAdapter extends common.Da
|
|
|
12734
12784
|
...config.migrations
|
|
12735
12785
|
};
|
|
12736
12786
|
const migrationDb = {
|
|
12737
|
-
execute: /* @__PURE__ */ __name(async (
|
|
12787
|
+
execute: /* @__PURE__ */ __name(async (sql4) => this.db.execute(sql4), "execute")
|
|
12738
12788
|
};
|
|
12739
12789
|
const bridge = new SchemaBridge();
|
|
12740
12790
|
const diff = new SchemaDiff(bridge);
|
|
@@ -12764,13 +12814,20 @@ ${stack}` : ""}`);
|
|
|
12764
12814
|
}
|
|
12765
12815
|
const drizzleConfig = this.options;
|
|
12766
12816
|
const dialect = drizzleConfig?.dialect ?? "postgresql";
|
|
12767
|
-
|
|
12768
|
-
|
|
12817
|
+
const logger2 = new common$1.Logger("DrizzleAdapter");
|
|
12818
|
+
let hasErrors = false;
|
|
12819
|
+
for (const [name, { table }] of this.schemaRegistry.entries()) {
|
|
12820
|
+
try {
|
|
12769
12821
|
const config = pgCore.getTableConfig(table);
|
|
12770
12822
|
await this.createTableFromConfig(config, dialect);
|
|
12823
|
+
} catch (error) {
|
|
12824
|
+
hasErrors = true;
|
|
12825
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
12826
|
+
logger2.warn(`Error creating table for "${name}" automatically: ${msg}`);
|
|
12771
12827
|
}
|
|
12772
|
-
}
|
|
12773
|
-
|
|
12828
|
+
}
|
|
12829
|
+
if (hasErrors) {
|
|
12830
|
+
logger2.warn("Some tables could not be created. The application may not work correctly.");
|
|
12774
12831
|
}
|
|
12775
12832
|
}
|
|
12776
12833
|
/**
|
|
@@ -12827,7 +12884,7 @@ ${stack}` : ""}`);
|
|
|
12827
12884
|
${columns.join(",\n ")}
|
|
12828
12885
|
)
|
|
12829
12886
|
`);
|
|
12830
|
-
await this.
|
|
12887
|
+
await this.execRawSQL(createTableSQL);
|
|
12831
12888
|
const indexes = config.indexes;
|
|
12832
12889
|
if (indexes) {
|
|
12833
12890
|
for (const index2 of Object.values(indexes)) {
|
|
@@ -12846,13 +12903,27 @@ ${stack}` : ""}`);
|
|
|
12846
12903
|
CREATE ${uniqueKeyword} INDEX IF NOT EXISTS ${q(indexName)}
|
|
12847
12904
|
ON ${q(tableName)} (${columnsStr})
|
|
12848
12905
|
`);
|
|
12849
|
-
await this.
|
|
12906
|
+
await this.execRawSQL(createIndexSQL).catch(() => {
|
|
12850
12907
|
});
|
|
12851
12908
|
}
|
|
12852
12909
|
}
|
|
12853
12910
|
}
|
|
12854
12911
|
}
|
|
12855
12912
|
/**
|
|
12913
|
+
* Execute raw SQL across all supported dialects.
|
|
12914
|
+
* PostgreSQL/MySQL use db.execute(), SQLite uses db.run().
|
|
12915
|
+
*/
|
|
12916
|
+
async execRawSQL(rawSQL) {
|
|
12917
|
+
const db = this.db;
|
|
12918
|
+
if (typeof db.execute === "function") {
|
|
12919
|
+
await db.execute(rawSQL);
|
|
12920
|
+
} else if (typeof db.run === "function") {
|
|
12921
|
+
db.run(rawSQL);
|
|
12922
|
+
} else {
|
|
12923
|
+
throw new Error("Database instance has no execute() or run() method");
|
|
12924
|
+
}
|
|
12925
|
+
}
|
|
12926
|
+
/**
|
|
12856
12927
|
* Map PostgreSQL SQL types to dialect-specific types.
|
|
12857
12928
|
*/
|
|
12858
12929
|
mapSQLTypeForDialect(pgType, dialect) {
|
|
@@ -13562,4 +13633,5 @@ exports.getOrGenerateSchema = getOrGenerateSchema;
|
|
|
13562
13633
|
exports.getRegisteredSchemas = getRegisteredSchemas;
|
|
13563
13634
|
exports.isDraft = isDraft;
|
|
13564
13635
|
exports.isPublished = isPublished;
|
|
13636
|
+
exports.sanitizeExecutableMigrationSql = sanitizeExecutableMigrationSql;
|
|
13565
13637
|
exports.sqlGenerators = sql_generators_exports;
|
package/dist/index.d.cts
CHANGED
|
@@ -433,11 +433,14 @@ declare class DrizzleDatabaseAdapter extends DatabaseAdapter {
|
|
|
433
433
|
private options;
|
|
434
434
|
private schemaRegistry;
|
|
435
435
|
private tablesInitialized;
|
|
436
|
+
private tablesInitPromise;
|
|
436
437
|
/**
|
|
437
438
|
* Automatically create tables for all registered schemas.
|
|
438
439
|
* Called lazily when first model is accessed, or can be called explicitly.
|
|
440
|
+
* Uses a lock (Promise) to prevent concurrent execution from multiple forFeature() calls.
|
|
439
441
|
*/
|
|
440
442
|
ensureTablesCreated(): Promise<void>;
|
|
443
|
+
private _doEnsureTablesCreated;
|
|
441
444
|
/**
|
|
442
445
|
* Run the auto-migration system when `config.migrations` is configured.
|
|
443
446
|
*/
|
|
@@ -455,6 +458,11 @@ declare class DrizzleDatabaseAdapter extends DatabaseAdapter {
|
|
|
455
458
|
* Generate and execute CREATE TABLE IF NOT EXISTS statement from table config.
|
|
456
459
|
*/
|
|
457
460
|
private createTableFromConfig;
|
|
461
|
+
/**
|
|
462
|
+
* Execute raw SQL across all supported dialects.
|
|
463
|
+
* PostgreSQL/MySQL use db.execute(), SQLite uses db.run().
|
|
464
|
+
*/
|
|
465
|
+
private execRawSQL;
|
|
458
466
|
/**
|
|
459
467
|
* Map PostgreSQL SQL types to dialect-specific types.
|
|
460
468
|
*/
|
|
@@ -763,6 +771,11 @@ declare class MigrationRunner {
|
|
|
763
771
|
}>;
|
|
764
772
|
}
|
|
765
773
|
|
|
774
|
+
/**
|
|
775
|
+
* drizzle-kit emits partial unique-index WHERE clauses with `$1`/`$2` placeholders,
|
|
776
|
+
* but Magnet runs DDL as plain strings without bound parameters.
|
|
777
|
+
*/
|
|
778
|
+
declare function sanitizeExecutableMigrationSql(dialect: MigrationDialect, statement: string): string;
|
|
766
779
|
/**
|
|
767
780
|
* Default filename for persisted schema snapshot (used by auto-migration).
|
|
768
781
|
*/
|
|
@@ -1056,4 +1069,4 @@ declare class AutoMigration {
|
|
|
1056
1069
|
run(dialect: MigrationDialect, config: MigrationConfig, directory: string): Promise<void>;
|
|
1057
1070
|
}
|
|
1058
1071
|
|
|
1059
|
-
export { Adapter, AutoMigration, type ColumnChange, DEFAULT_LOCALE, DEFAULT_MIGRATION_CONFIG, DOCUMENT_STATUS, DRIZZLE_CONFIG, DRIZZLE_DB, type DiffResult, type DocumentColumnOptions, type DocumentStatus, type DrizzleConfig, type DrizzleDB, DrizzleDatabaseAdapter, type DrizzleModuleOptions, DrizzleQueryBuilder, type GenerateJsonFn, type GenerateSQLFn, type GeneratedSchema, type IndexChange, InjectModel, LazyQueryBuilder, type Migration, MigrationChecksumError, type MigrationConfig, type MigrationDb, type MigrationDialect, MigrationError, type MigrationGenerateOptions, MigrationGenerator, MigrationHistory, type MigrationHistoryRecord, MigrationLock, MigrationLockError, type MigrationMode, type MigrationResult, MigrationRunner, Prop, type PropMetadata, SNAPSHOT_FILENAME, Schema, SchemaBridge, SchemaDiff, type SchemaDiffResult, type SchemaMetadata, type SnapshotJSON, type TableDefinition, applyDocumentColumns, clearSchemaRegistry, createNeonConnection, createNeonWebSocketConnection, generateSchema, getDrizzleModelToken, getDrizzlePropsMetadata, getDrizzleSchemaMetadata, getOrGenerateSchema, getRegisteredSchemas, isDraft, isPublished, index as sqlGenerators };
|
|
1072
|
+
export { Adapter, AutoMigration, type ColumnChange, DEFAULT_LOCALE, DEFAULT_MIGRATION_CONFIG, DOCUMENT_STATUS, DRIZZLE_CONFIG, DRIZZLE_DB, type DiffResult, type DocumentColumnOptions, type DocumentStatus, type DrizzleConfig, type DrizzleDB, DrizzleDatabaseAdapter, type DrizzleModuleOptions, DrizzleQueryBuilder, type GenerateJsonFn, type GenerateSQLFn, type GeneratedSchema, type IndexChange, InjectModel, LazyQueryBuilder, type Migration, MigrationChecksumError, type MigrationConfig, type MigrationDb, type MigrationDialect, MigrationError, type MigrationGenerateOptions, MigrationGenerator, MigrationHistory, type MigrationHistoryRecord, MigrationLock, MigrationLockError, type MigrationMode, type MigrationResult, MigrationRunner, Prop, type PropMetadata, SNAPSHOT_FILENAME, Schema, SchemaBridge, SchemaDiff, type SchemaDiffResult, type SchemaMetadata, type SnapshotJSON, type TableDefinition, applyDocumentColumns, clearSchemaRegistry, createNeonConnection, createNeonWebSocketConnection, generateSchema, getDrizzleModelToken, getDrizzlePropsMetadata, getDrizzleSchemaMetadata, getOrGenerateSchema, getRegisteredSchemas, isDraft, isPublished, sanitizeExecutableMigrationSql, index as sqlGenerators };
|
package/dist/index.d.ts
CHANGED
|
@@ -433,11 +433,14 @@ declare class DrizzleDatabaseAdapter extends DatabaseAdapter {
|
|
|
433
433
|
private options;
|
|
434
434
|
private schemaRegistry;
|
|
435
435
|
private tablesInitialized;
|
|
436
|
+
private tablesInitPromise;
|
|
436
437
|
/**
|
|
437
438
|
* Automatically create tables for all registered schemas.
|
|
438
439
|
* Called lazily when first model is accessed, or can be called explicitly.
|
|
440
|
+
* Uses a lock (Promise) to prevent concurrent execution from multiple forFeature() calls.
|
|
439
441
|
*/
|
|
440
442
|
ensureTablesCreated(): Promise<void>;
|
|
443
|
+
private _doEnsureTablesCreated;
|
|
441
444
|
/**
|
|
442
445
|
* Run the auto-migration system when `config.migrations` is configured.
|
|
443
446
|
*/
|
|
@@ -455,6 +458,11 @@ declare class DrizzleDatabaseAdapter extends DatabaseAdapter {
|
|
|
455
458
|
* Generate and execute CREATE TABLE IF NOT EXISTS statement from table config.
|
|
456
459
|
*/
|
|
457
460
|
private createTableFromConfig;
|
|
461
|
+
/**
|
|
462
|
+
* Execute raw SQL across all supported dialects.
|
|
463
|
+
* PostgreSQL/MySQL use db.execute(), SQLite uses db.run().
|
|
464
|
+
*/
|
|
465
|
+
private execRawSQL;
|
|
458
466
|
/**
|
|
459
467
|
* Map PostgreSQL SQL types to dialect-specific types.
|
|
460
468
|
*/
|
|
@@ -763,6 +771,11 @@ declare class MigrationRunner {
|
|
|
763
771
|
}>;
|
|
764
772
|
}
|
|
765
773
|
|
|
774
|
+
/**
|
|
775
|
+
* drizzle-kit emits partial unique-index WHERE clauses with `$1`/`$2` placeholders,
|
|
776
|
+
* but Magnet runs DDL as plain strings without bound parameters.
|
|
777
|
+
*/
|
|
778
|
+
declare function sanitizeExecutableMigrationSql(dialect: MigrationDialect, statement: string): string;
|
|
766
779
|
/**
|
|
767
780
|
* Default filename for persisted schema snapshot (used by auto-migration).
|
|
768
781
|
*/
|
|
@@ -1056,4 +1069,4 @@ declare class AutoMigration {
|
|
|
1056
1069
|
run(dialect: MigrationDialect, config: MigrationConfig, directory: string): Promise<void>;
|
|
1057
1070
|
}
|
|
1058
1071
|
|
|
1059
|
-
export { Adapter, AutoMigration, type ColumnChange, DEFAULT_LOCALE, DEFAULT_MIGRATION_CONFIG, DOCUMENT_STATUS, DRIZZLE_CONFIG, DRIZZLE_DB, type DiffResult, type DocumentColumnOptions, type DocumentStatus, type DrizzleConfig, type DrizzleDB, DrizzleDatabaseAdapter, type DrizzleModuleOptions, DrizzleQueryBuilder, type GenerateJsonFn, type GenerateSQLFn, type GeneratedSchema, type IndexChange, InjectModel, LazyQueryBuilder, type Migration, MigrationChecksumError, type MigrationConfig, type MigrationDb, type MigrationDialect, MigrationError, type MigrationGenerateOptions, MigrationGenerator, MigrationHistory, type MigrationHistoryRecord, MigrationLock, MigrationLockError, type MigrationMode, type MigrationResult, MigrationRunner, Prop, type PropMetadata, SNAPSHOT_FILENAME, Schema, SchemaBridge, SchemaDiff, type SchemaDiffResult, type SchemaMetadata, type SnapshotJSON, type TableDefinition, applyDocumentColumns, clearSchemaRegistry, createNeonConnection, createNeonWebSocketConnection, generateSchema, getDrizzleModelToken, getDrizzlePropsMetadata, getDrizzleSchemaMetadata, getOrGenerateSchema, getRegisteredSchemas, isDraft, isPublished, index as sqlGenerators };
|
|
1072
|
+
export { Adapter, AutoMigration, type ColumnChange, DEFAULT_LOCALE, DEFAULT_MIGRATION_CONFIG, DOCUMENT_STATUS, DRIZZLE_CONFIG, DRIZZLE_DB, type DiffResult, type DocumentColumnOptions, type DocumentStatus, type DrizzleConfig, type DrizzleDB, DrizzleDatabaseAdapter, type DrizzleModuleOptions, DrizzleQueryBuilder, type GenerateJsonFn, type GenerateSQLFn, type GeneratedSchema, type IndexChange, InjectModel, LazyQueryBuilder, type Migration, MigrationChecksumError, type MigrationConfig, type MigrationDb, type MigrationDialect, MigrationError, type MigrationGenerateOptions, MigrationGenerator, MigrationHistory, type MigrationHistoryRecord, MigrationLock, MigrationLockError, type MigrationMode, type MigrationResult, MigrationRunner, Prop, type PropMetadata, SNAPSHOT_FILENAME, Schema, SchemaBridge, SchemaDiff, type SchemaDiffResult, type SchemaMetadata, type SnapshotJSON, type TableDefinition, applyDocumentColumns, clearSchemaRegistry, createNeonConnection, createNeonWebSocketConnection, generateSchema, getDrizzleModelToken, getDrizzlePropsMetadata, getDrizzleSchemaMetadata, getOrGenerateSchema, getRegisteredSchemas, isDraft, isPublished, sanitizeExecutableMigrationSql, index as sqlGenerators };
|
package/dist/index.js
CHANGED
|
@@ -2,13 +2,13 @@ import { __commonJS, __name, __require, __toESM, __export } from './chunk-AAIPPT
|
|
|
2
2
|
import 'reflect-metadata';
|
|
3
3
|
import { QueryBuilder, DatabaseAdapter, getModelToken, setDatabaseAdapter, getSchemaOptions, Model, DatabaseError, fromDrizzleError, DocumentNotFoundError } from '@magnet-cms/common';
|
|
4
4
|
import { Logger, Module, Injectable, Inject } from '@nestjs/common';
|
|
5
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
5
6
|
import { toSnakeCase, toCamelCase, pluralize } from '@magnet-cms/utils';
|
|
6
7
|
import { and, or, eq, desc, asc, sql, isNotNull, isNull, ilike, like, notInArray, inArray, lte, lt, gte, gt, ne } from 'drizzle-orm';
|
|
7
8
|
import { getTableConfig, varchar, timestamp, uuid, pgTable, uniqueIndex, index, text, doublePrecision, boolean, jsonb } from 'drizzle-orm/pg-core';
|
|
8
9
|
import { drizzle } from 'drizzle-orm/node-postgres';
|
|
9
10
|
import { readdir, mkdir, writeFile, readFile } from 'node:fs/promises';
|
|
10
11
|
import { join } from 'node:path';
|
|
11
|
-
import { createHash } from 'node:crypto';
|
|
12
12
|
|
|
13
13
|
// ../../../node_modules/postgres-array/index.js
|
|
14
14
|
var require_postgres_array = __commonJS({
|
|
@@ -5346,8 +5346,11 @@ function generateSchema(schemaClass) {
|
|
|
5346
5346
|
});
|
|
5347
5347
|
const columns = {
|
|
5348
5348
|
// Primary key - always UUID
|
|
5349
|
-
//
|
|
5350
|
-
|
|
5349
|
+
// $defaultFn generates UUIDs in JS (works on all dialects: PostgreSQL, MySQL, SQLite)
|
|
5350
|
+
// Note: SQL .default(gen_random_uuid()) is intentionally omitted because it conflicts
|
|
5351
|
+
// with $defaultFn when using pg-core types on non-PostgreSQL drivers.
|
|
5352
|
+
// The createTableFromConfig() method adds dialect-appropriate SQL DEFAULT for direct inserts.
|
|
5353
|
+
id: uuid("id").primaryKey().$defaultFn(() => randomUUID())
|
|
5351
5354
|
};
|
|
5352
5355
|
if (hasI18n || hasVersioning || hasIntlProps) {
|
|
5353
5356
|
const docOptions = {
|
|
@@ -5363,8 +5366,8 @@ function generateSchema(schemaClass) {
|
|
|
5363
5366
|
columns[columnName] = column;
|
|
5364
5367
|
}
|
|
5365
5368
|
});
|
|
5366
|
-
columns.createdAt = timestamp("created_at").
|
|
5367
|
-
columns.updatedAt = timestamp("updated_at").
|
|
5369
|
+
columns.createdAt = timestamp("created_at").notNull();
|
|
5370
|
+
columns.updatedAt = timestamp("updated_at").notNull();
|
|
5368
5371
|
const table = pgTable(tableName, columns, (table2) => {
|
|
5369
5372
|
const tableIndexes = {};
|
|
5370
5373
|
const t = table2;
|
|
@@ -5414,7 +5417,9 @@ function generateColumn(columnName, options) {
|
|
|
5414
5417
|
column = text(snakeCaseName);
|
|
5415
5418
|
}
|
|
5416
5419
|
if (options.default !== void 0) {
|
|
5417
|
-
|
|
5420
|
+
if (Array.isArray(options.default) && options.default.length === 0) ; else {
|
|
5421
|
+
column = column.default(options.default);
|
|
5422
|
+
}
|
|
5418
5423
|
}
|
|
5419
5424
|
return column;
|
|
5420
5425
|
}
|
|
@@ -5438,8 +5443,8 @@ async function createNeonConnection(config) {
|
|
|
5438
5443
|
} catch {
|
|
5439
5444
|
throw new Error("@neondatabase/serverless is required for Neon driver. Install it with: bun add @neondatabase/serverless");
|
|
5440
5445
|
}
|
|
5441
|
-
const
|
|
5442
|
-
const db = drizzleNeon.drizzle(
|
|
5446
|
+
const sql4 = neon.neon(config.connectionString);
|
|
5447
|
+
const db = drizzleNeon.drizzle(sql4, {
|
|
5443
5448
|
logger: config.debug
|
|
5444
5449
|
});
|
|
5445
5450
|
return {
|
|
@@ -5907,6 +5912,11 @@ var DrizzleQueryBuilder = class extends QueryBuilder {
|
|
|
5907
5912
|
};
|
|
5908
5913
|
|
|
5909
5914
|
// src/drizzle.model.ts
|
|
5915
|
+
function isSQLiteDriver(db) {
|
|
5916
|
+
const d = db;
|
|
5917
|
+
return typeof d.run === "function" && typeof d.execute !== "function";
|
|
5918
|
+
}
|
|
5919
|
+
__name(isSQLiteDriver, "isSQLiteDriver");
|
|
5910
5920
|
function createModel(db, table, schemaClass) {
|
|
5911
5921
|
return class DrizzleModelAdapter extends Model {
|
|
5912
5922
|
static {
|
|
@@ -5970,8 +5980,9 @@ function createModel(db, table, schemaClass) {
|
|
|
5970
5980
|
const insertData = {
|
|
5971
5981
|
...this._prepareData(data, true)
|
|
5972
5982
|
};
|
|
5983
|
+
this._applyDeclaredEmptyArrayDefaults(insertData);
|
|
5973
5984
|
if ("documentId" in dynamicTable) {
|
|
5974
|
-
insertData.documentId = insertData.documentId ||
|
|
5985
|
+
insertData.documentId = insertData.documentId || randomUUID();
|
|
5975
5986
|
insertData.locale = insertData.locale || this.currentLocale || DEFAULT_LOCALE;
|
|
5976
5987
|
insertData.status = insertData.status || DOCUMENT_STATUS.DRAFT;
|
|
5977
5988
|
}
|
|
@@ -6358,14 +6369,29 @@ function createModel(db, table, schemaClass) {
|
|
|
6358
6369
|
* For JSONB columns (arrays/objects), ensure values are properly formatted
|
|
6359
6370
|
* @internal
|
|
6360
6371
|
*/
|
|
6372
|
+
/**
|
|
6373
|
+
* Fields declared with `default: []` omit a DB default (cross-dialect migration/runtime).
|
|
6374
|
+
* Fill missing keys so inserts match Mongoose-style expectations.
|
|
6375
|
+
*/
|
|
6376
|
+
_applyDeclaredEmptyArrayDefaults(row) {
|
|
6377
|
+
const props = getDrizzlePropsMetadata(this._schemaClass);
|
|
6378
|
+
for (const [propertyKey, options] of props) {
|
|
6379
|
+
const key = String(propertyKey);
|
|
6380
|
+
if (options.default !== void 0 && Array.isArray(options.default) && options.default.length === 0 && row[key] === void 0) {
|
|
6381
|
+
row[key] = isSQLiteDriver(this._db) ? JSON.stringify([]) : [];
|
|
6382
|
+
}
|
|
6383
|
+
}
|
|
6384
|
+
}
|
|
6361
6385
|
_prepareData(data, isCreate = false) {
|
|
6362
6386
|
const result = {};
|
|
6363
|
-
|
|
6364
|
-
|
|
6387
|
+
const isSQLite = isSQLiteDriver(this._db);
|
|
6388
|
+
if (isCreate) {
|
|
6389
|
+
result.createdAt = data.createdAt instanceof Date ? data.createdAt : /* @__PURE__ */ new Date();
|
|
6365
6390
|
}
|
|
6391
|
+
result.updatedAt = data.updatedAt instanceof Date ? data.updatedAt : /* @__PURE__ */ new Date();
|
|
6366
6392
|
for (const [key, value] of Object.entries(data)) {
|
|
6367
6393
|
if (key === "id") continue;
|
|
6368
|
-
if (key === "createdAt") continue;
|
|
6394
|
+
if (key === "createdAt" || key === "updatedAt") continue;
|
|
6369
6395
|
if (value === void 0) {
|
|
6370
6396
|
continue;
|
|
6371
6397
|
}
|
|
@@ -6373,6 +6399,10 @@ function createModel(db, table, schemaClass) {
|
|
|
6373
6399
|
result[key] = null;
|
|
6374
6400
|
continue;
|
|
6375
6401
|
}
|
|
6402
|
+
if (typeof value === "boolean" && isSQLite) {
|
|
6403
|
+
result[key] = value ? 1 : 0;
|
|
6404
|
+
continue;
|
|
6405
|
+
}
|
|
6376
6406
|
if (value instanceof Date) {
|
|
6377
6407
|
result[key] = value;
|
|
6378
6408
|
continue;
|
|
@@ -6391,7 +6421,7 @@ function createModel(db, table, schemaClass) {
|
|
|
6391
6421
|
result[key] = value;
|
|
6392
6422
|
}
|
|
6393
6423
|
} else if (Array.isArray(value)) {
|
|
6394
|
-
result[key] = value;
|
|
6424
|
+
result[key] = isSQLite ? JSON.stringify(value) : value;
|
|
6395
6425
|
} else if (value !== null && typeof value === "object") {
|
|
6396
6426
|
result[key] = value;
|
|
6397
6427
|
} else {
|
|
@@ -6451,13 +6481,13 @@ var AutoMigration = class {
|
|
|
6451
6481
|
dangerous: diffResult.dangerous,
|
|
6452
6482
|
warnings: diffResult.warnings,
|
|
6453
6483
|
async up(db) {
|
|
6454
|
-
for (const
|
|
6484
|
+
for (const sql4 of upSQL) {
|
|
6455
6485
|
try {
|
|
6456
|
-
await db.execute(
|
|
6486
|
+
await db.execute(sql4);
|
|
6457
6487
|
} catch (err) {
|
|
6458
6488
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6459
6489
|
const code = err && typeof err === "object" && "code" in err ? err.code : void 0;
|
|
6460
|
-
if (code === "42P07" || msg.includes("already exists") || msg.includes("ER_TABLE_EXISTS") || msg.includes("duplicate table name")) {
|
|
6490
|
+
if (code === "42P07" || code === "42710" || msg.includes("already exists") || msg.includes("ER_TABLE_EXISTS") || msg.includes("duplicate table name") || msg.includes("duplicate key value")) {
|
|
6461
6491
|
logger.warn(`Skipping (object already exists): ${msg.slice(0, 80)}`);
|
|
6462
6492
|
continue;
|
|
6463
6493
|
}
|
|
@@ -6485,8 +6515,8 @@ var MigrationGenerator = class {
|
|
|
6485
6515
|
generate(name, upSQL, downSQL, options = {}) {
|
|
6486
6516
|
const timestamp3 = Date.now();
|
|
6487
6517
|
const id = `${timestamp3}_${name}`;
|
|
6488
|
-
const upStatements = upSQL.map((
|
|
6489
|
-
const downStatements = downSQL.length > 0 ? downSQL.map((
|
|
6518
|
+
const upStatements = upSQL.map((sql4) => ` await db.execute(\`${sql4}\`)`).join("\n");
|
|
6519
|
+
const downStatements = downSQL.length > 0 ? downSQL.map((sql4) => ` await db.execute(\`${sql4}\`)`).join("\n") : " // TODO: implement down migration";
|
|
6490
6520
|
const dangerousField = options.dangerous ? "\n dangerous: true," : "";
|
|
6491
6521
|
const warningsField = options.warnings && options.warnings.length > 0 ? `
|
|
6492
6522
|
warnings: [
|
|
@@ -6833,6 +6863,12 @@ var MigrationRunner = class {
|
|
|
6833
6863
|
};
|
|
6834
6864
|
}
|
|
6835
6865
|
};
|
|
6866
|
+
function sanitizeExecutableMigrationSql(dialect, statement) {
|
|
6867
|
+
if (dialect !== "postgresql") return statement;
|
|
6868
|
+
if (!statement.includes("$")) return statement;
|
|
6869
|
+
return statement.replace(/"locale" = \$1/g, `"locale" = 'en'`).replace(/"status" = \$2/g, `"status" = 'draft'`);
|
|
6870
|
+
}
|
|
6871
|
+
__name(sanitizeExecutableMigrationSql, "sanitizeExecutableMigrationSql");
|
|
6836
6872
|
var SNAPSHOT_FILENAME = ".schema_snapshot.json";
|
|
6837
6873
|
var SchemaBridge = class {
|
|
6838
6874
|
static {
|
|
@@ -6872,7 +6908,8 @@ var SchemaBridge = class {
|
|
|
6872
6908
|
*/
|
|
6873
6909
|
async generateSQL(prev, cur, generateSQLFn, dialect = "postgresql") {
|
|
6874
6910
|
const fn = generateSQLFn ?? await this.resolveGenerateSQLFn(dialect);
|
|
6875
|
-
|
|
6911
|
+
const statements = await fn(prev, cur);
|
|
6912
|
+
return statements.map((s) => sanitizeExecutableMigrationSql(dialect, s));
|
|
6876
6913
|
}
|
|
6877
6914
|
/**
|
|
6878
6915
|
* Load a previously saved snapshot from disk.
|
|
@@ -7001,9 +7038,9 @@ var SchemaDiff = class {
|
|
|
7001
7038
|
*/
|
|
7002
7039
|
detectDangerousOperations(sqlStatements) {
|
|
7003
7040
|
const warnings = [];
|
|
7004
|
-
for (const
|
|
7041
|
+
for (const sql4 of sqlStatements) {
|
|
7005
7042
|
for (const { pattern, message } of DANGEROUS_PATTERNS) {
|
|
7006
|
-
const match =
|
|
7043
|
+
const match = sql4.match(pattern);
|
|
7007
7044
|
if (match) {
|
|
7008
7045
|
warnings.push(message(match[1] ?? match[0]));
|
|
7009
7046
|
}
|
|
@@ -7057,14 +7094,27 @@ var DrizzleDatabaseAdapter = class _DrizzleDatabaseAdapter extends DatabaseAdapt
|
|
|
7057
7094
|
options = null;
|
|
7058
7095
|
schemaRegistry = /* @__PURE__ */ new Map();
|
|
7059
7096
|
tablesInitialized = false;
|
|
7097
|
+
tablesInitPromise = null;
|
|
7060
7098
|
/**
|
|
7061
7099
|
* Automatically create tables for all registered schemas.
|
|
7062
7100
|
* Called lazily when first model is accessed, or can be called explicitly.
|
|
7101
|
+
* Uses a lock (Promise) to prevent concurrent execution from multiple forFeature() calls.
|
|
7063
7102
|
*/
|
|
7064
7103
|
async ensureTablesCreated() {
|
|
7065
7104
|
if (this.tablesInitialized || !this.db || this.schemaRegistry.size === 0) {
|
|
7066
7105
|
return;
|
|
7067
7106
|
}
|
|
7107
|
+
if (this.tablesInitPromise) {
|
|
7108
|
+
return this.tablesInitPromise;
|
|
7109
|
+
}
|
|
7110
|
+
this.tablesInitPromise = this._doEnsureTablesCreated();
|
|
7111
|
+
try {
|
|
7112
|
+
await this.tablesInitPromise;
|
|
7113
|
+
} finally {
|
|
7114
|
+
this.tablesInitPromise = null;
|
|
7115
|
+
}
|
|
7116
|
+
}
|
|
7117
|
+
async _doEnsureTablesCreated() {
|
|
7068
7118
|
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
7069
7119
|
const drizzleConfig = this.options;
|
|
7070
7120
|
if (drizzleConfig?.migrations) {
|
|
@@ -7083,7 +7133,7 @@ var DrizzleDatabaseAdapter = class _DrizzleDatabaseAdapter extends DatabaseAdapt
|
|
|
7083
7133
|
...config.migrations
|
|
7084
7134
|
};
|
|
7085
7135
|
const migrationDb = {
|
|
7086
|
-
execute: /* @__PURE__ */ __name(async (
|
|
7136
|
+
execute: /* @__PURE__ */ __name(async (sql4) => this.db.execute(sql4), "execute")
|
|
7087
7137
|
};
|
|
7088
7138
|
const bridge = new SchemaBridge();
|
|
7089
7139
|
const diff = new SchemaDiff(bridge);
|
|
@@ -7113,13 +7163,20 @@ ${stack}` : ""}`);
|
|
|
7113
7163
|
}
|
|
7114
7164
|
const drizzleConfig = this.options;
|
|
7115
7165
|
const dialect = drizzleConfig?.dialect ?? "postgresql";
|
|
7116
|
-
|
|
7117
|
-
|
|
7166
|
+
const logger2 = new Logger("DrizzleAdapter");
|
|
7167
|
+
let hasErrors = false;
|
|
7168
|
+
for (const [name, { table }] of this.schemaRegistry.entries()) {
|
|
7169
|
+
try {
|
|
7118
7170
|
const config = getTableConfig(table);
|
|
7119
7171
|
await this.createTableFromConfig(config, dialect);
|
|
7172
|
+
} catch (error) {
|
|
7173
|
+
hasErrors = true;
|
|
7174
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
7175
|
+
logger2.warn(`Error creating table for "${name}" automatically: ${msg}`);
|
|
7120
7176
|
}
|
|
7121
|
-
}
|
|
7122
|
-
|
|
7177
|
+
}
|
|
7178
|
+
if (hasErrors) {
|
|
7179
|
+
logger2.warn("Some tables could not be created. The application may not work correctly.");
|
|
7123
7180
|
}
|
|
7124
7181
|
}
|
|
7125
7182
|
/**
|
|
@@ -7176,7 +7233,7 @@ ${stack}` : ""}`);
|
|
|
7176
7233
|
${columns.join(",\n ")}
|
|
7177
7234
|
)
|
|
7178
7235
|
`);
|
|
7179
|
-
await this.
|
|
7236
|
+
await this.execRawSQL(createTableSQL);
|
|
7180
7237
|
const indexes = config.indexes;
|
|
7181
7238
|
if (indexes) {
|
|
7182
7239
|
for (const index2 of Object.values(indexes)) {
|
|
@@ -7195,13 +7252,27 @@ ${stack}` : ""}`);
|
|
|
7195
7252
|
CREATE ${uniqueKeyword} INDEX IF NOT EXISTS ${q(indexName)}
|
|
7196
7253
|
ON ${q(tableName)} (${columnsStr})
|
|
7197
7254
|
`);
|
|
7198
|
-
await this.
|
|
7255
|
+
await this.execRawSQL(createIndexSQL).catch(() => {
|
|
7199
7256
|
});
|
|
7200
7257
|
}
|
|
7201
7258
|
}
|
|
7202
7259
|
}
|
|
7203
7260
|
}
|
|
7204
7261
|
/**
|
|
7262
|
+
* Execute raw SQL across all supported dialects.
|
|
7263
|
+
* PostgreSQL/MySQL use db.execute(), SQLite uses db.run().
|
|
7264
|
+
*/
|
|
7265
|
+
async execRawSQL(rawSQL) {
|
|
7266
|
+
const db = this.db;
|
|
7267
|
+
if (typeof db.execute === "function") {
|
|
7268
|
+
await db.execute(rawSQL);
|
|
7269
|
+
} else if (typeof db.run === "function") {
|
|
7270
|
+
db.run(rawSQL);
|
|
7271
|
+
} else {
|
|
7272
|
+
throw new Error("Database instance has no execute() or run() method");
|
|
7273
|
+
}
|
|
7274
|
+
}
|
|
7275
|
+
/**
|
|
7205
7276
|
* Map PostgreSQL SQL types to dialect-specific types.
|
|
7206
7277
|
*/
|
|
7207
7278
|
mapSQLTypeForDialect(pgType, dialect) {
|
|
@@ -7860,4 +7931,4 @@ __name(dropIndex3, "dropIndex");
|
|
|
7860
7931
|
// src/index.ts
|
|
7861
7932
|
setDatabaseAdapter("drizzle");
|
|
7862
7933
|
|
|
7863
|
-
export { Adapter, AutoMigration, DEFAULT_LOCALE, DEFAULT_MIGRATION_CONFIG, DOCUMENT_STATUS, DRIZZLE_CONFIG, DRIZZLE_DB, DrizzleDatabaseAdapter, DrizzleQueryBuilder, InjectModel, LazyQueryBuilder, MigrationChecksumError, MigrationError, MigrationGenerator, MigrationHistory, MigrationLock, MigrationLockError, MigrationRunner, Prop, SNAPSHOT_FILENAME, Schema, SchemaBridge, SchemaDiff, applyDocumentColumns, clearSchemaRegistry, createNeonConnection, createNeonWebSocketConnection, generateSchema, getDrizzleModelToken, getDrizzlePropsMetadata, getDrizzleSchemaMetadata, getOrGenerateSchema, getRegisteredSchemas, isDraft, isPublished, sql_generators_exports as sqlGenerators };
|
|
7934
|
+
export { Adapter, AutoMigration, DEFAULT_LOCALE, DEFAULT_MIGRATION_CONFIG, DOCUMENT_STATUS, DRIZZLE_CONFIG, DRIZZLE_DB, DrizzleDatabaseAdapter, DrizzleQueryBuilder, InjectModel, LazyQueryBuilder, MigrationChecksumError, MigrationError, MigrationGenerator, MigrationHistory, MigrationLock, MigrationLockError, MigrationRunner, Prop, SNAPSHOT_FILENAME, Schema, SchemaBridge, SchemaDiff, applyDocumentColumns, clearSchemaRegistry, createNeonConnection, createNeonWebSocketConnection, generateSchema, getDrizzleModelToken, getDrizzlePropsMetadata, getDrizzleSchemaMetadata, getOrGenerateSchema, getRegisteredSchemas, isDraft, isPublished, sanitizeExecutableMigrationSql, sql_generators_exports as sqlGenerators };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@magnet-cms/adapter-db-drizzle",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Drizzle ORM database adapter for Magnet CMS - supports PostgreSQL, MySQL, and SQLite",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"reflect-metadata": "0.2.2"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"@magnet-cms/common": "^0.
|
|
46
|
-
"@magnet-cms/utils": "^0.1.
|
|
45
|
+
"@magnet-cms/common": "^0.2.0",
|
|
46
|
+
"@magnet-cms/utils": "^0.1.1",
|
|
47
47
|
"@nestjs/common": "^11.1.12",
|
|
48
48
|
"drizzle-orm": "^0.38.0",
|
|
49
49
|
"reflect-metadata": "0.2.2"
|