@hedystia/db 2.0.0 → 2.0.1
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/_virtual/_rolldown/runtime.cjs +13 -0
- package/dist/_virtual/_rolldown/runtime.mjs +17 -0
- package/dist/cache/manager.cjs +137 -0
- package/dist/cache/manager.cjs.map +1 -0
- package/dist/cache/manager.d.cts +72 -0
- package/dist/cache/manager.d.mts +72 -0
- package/dist/cache/manager.mjs +140 -0
- package/dist/cache/manager.mjs.map +1 -0
- package/dist/cache/memory-store.cjs +122 -0
- package/dist/cache/memory-store.cjs.map +1 -0
- package/dist/cache/memory-store.mjs +122 -0
- package/dist/cache/memory-store.mjs.map +1 -0
- package/dist/cli/commands/migration.cjs +22 -0
- package/dist/cli/commands/migration.cjs.map +1 -0
- package/dist/cli/commands/migration.mjs +32 -0
- package/dist/cli/commands/migration.mjs.map +1 -0
- package/dist/cli/commands/schema.cjs +21 -0
- package/dist/cli/commands/schema.cjs.map +1 -0
- package/dist/cli/commands/schema.mjs +30 -0
- package/dist/cli/commands/schema.mjs.map +1 -0
- package/dist/cli.cjs +50 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +57 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/constants.cjs +16 -0
- package/dist/constants.cjs.map +1 -0
- package/dist/constants.mjs +16 -0
- package/dist/constants.mjs.map +1 -0
- package/dist/core/database.cjs +158 -0
- package/dist/core/database.cjs.map +1 -0
- package/dist/core/database.d.cts +74 -0
- package/dist/core/database.d.mts +74 -0
- package/dist/core/database.mjs +159 -0
- package/dist/core/database.mjs.map +1 -0
- package/dist/core/repository.cjs +362 -0
- package/dist/core/repository.cjs.map +1 -0
- package/dist/core/repository.d.cts +100 -0
- package/dist/core/repository.d.mts +100 -0
- package/dist/core/repository.mjs +362 -0
- package/dist/core/repository.mjs.map +1 -0
- package/dist/drivers/driver.cjs +11 -0
- package/dist/drivers/driver.cjs.map +1 -0
- package/dist/drivers/driver.mjs +11 -0
- package/dist/drivers/driver.mjs.map +1 -0
- package/dist/drivers/file.cjs +336 -0
- package/dist/drivers/file.cjs.map +1 -0
- package/dist/drivers/file.mjs +337 -0
- package/dist/drivers/file.mjs.map +1 -0
- package/dist/drivers/index.cjs +28 -0
- package/dist/drivers/index.cjs.map +1 -0
- package/dist/drivers/index.d.cts +14 -0
- package/dist/drivers/index.d.mts +14 -0
- package/dist/drivers/index.mjs +28 -0
- package/dist/drivers/index.mjs.map +1 -0
- package/dist/drivers/mysql.cjs +272 -0
- package/dist/drivers/mysql.cjs.map +1 -0
- package/dist/drivers/mysql.mjs +272 -0
- package/dist/drivers/mysql.mjs.map +1 -0
- package/dist/drivers/sql-compiler.cjs +284 -0
- package/dist/drivers/sql-compiler.cjs.map +1 -0
- package/dist/drivers/sql-compiler.d.cts +66 -0
- package/dist/drivers/sql-compiler.d.mts +66 -0
- package/dist/drivers/sql-compiler.mjs +276 -0
- package/dist/drivers/sql-compiler.mjs.map +1 -0
- package/dist/drivers/sqlite.cjs +262 -0
- package/dist/drivers/sqlite.cjs.map +1 -0
- package/dist/drivers/sqlite.mjs +262 -0
- package/dist/drivers/sqlite.mjs.map +1 -0
- package/dist/errors.cjs +74 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.cts +46 -0
- package/dist/errors.d.mts +46 -0
- package/dist/errors.mjs +68 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/index.cjs +55 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +15 -0
- package/dist/index.d.mts +15 -0
- package/dist/index.mjs +21 -0
- package/dist/index.mjs.map +1 -0
- package/dist/migrations/definition.cjs +20 -0
- package/dist/migrations/definition.cjs.map +1 -0
- package/dist/migrations/definition.d.cts +18 -0
- package/dist/migrations/definition.d.mts +18 -0
- package/dist/migrations/definition.mjs +23 -0
- package/dist/migrations/definition.mjs.map +1 -0
- package/dist/migrations/index.mjs +12 -0
- package/dist/migrations/index.mjs.map +1 -0
- package/dist/migrations/templates.cjs +39 -0
- package/dist/migrations/templates.cjs.map +1 -0
- package/dist/migrations/templates.d.cts +16 -0
- package/dist/migrations/templates.d.mts +16 -0
- package/dist/migrations/templates.mjs +41 -0
- package/dist/migrations/templates.mjs.map +1 -0
- package/dist/schema/column.cjs +129 -0
- package/dist/schema/column.cjs.map +1 -0
- package/dist/schema/column.d.cts +96 -0
- package/dist/schema/column.d.mts +96 -0
- package/dist/schema/column.mjs +129 -0
- package/dist/schema/column.mjs.map +1 -0
- package/dist/schema/columns/index.cjs +110 -0
- package/dist/schema/columns/index.cjs.map +1 -0
- package/dist/schema/columns/index.d.cts +91 -0
- package/dist/schema/columns/index.d.mts +91 -0
- package/dist/schema/columns/index.mjs +104 -0
- package/dist/schema/columns/index.mjs.map +1 -0
- package/dist/schema/registry.cjs +101 -0
- package/dist/schema/registry.cjs.map +1 -0
- package/dist/schema/registry.d.cts +52 -0
- package/dist/schema/registry.d.mts +52 -0
- package/dist/schema/registry.mjs +101 -0
- package/dist/schema/registry.mjs.map +1 -0
- package/dist/schema/table.cjs +36 -0
- package/dist/schema/table.cjs.map +1 -0
- package/dist/schema/table.d.cts +17 -0
- package/dist/schema/table.d.mts +17 -0
- package/dist/schema/table.mjs +36 -0
- package/dist/schema/table.mjs.map +1 -0
- package/dist/sync/synchronizer.cjs +43 -0
- package/dist/sync/synchronizer.cjs.map +1 -0
- package/dist/sync/synchronizer.d.cts +22 -0
- package/dist/sync/synchronizer.d.mts +22 -0
- package/dist/sync/synchronizer.mjs +43 -0
- package/dist/sync/synchronizer.mjs.map +1 -0
- package/dist/types.d.cts +227 -0
- package/dist/types.d.mts +227 -0
- package/dist/utils/fs.cjs +24 -0
- package/dist/utils/fs.cjs.map +1 -0
- package/dist/utils/fs.mjs +26 -0
- package/dist/utils/fs.mjs.map +1 -0
- package/dist/utils/index.mjs +14 -0
- package/dist/utils/index.mjs.map +1 -0
- package/dist/utils/naming.cjs +13 -0
- package/dist/utils/naming.cjs.map +1 -0
- package/dist/utils/naming.mjs +16 -0
- package/dist/utils/naming.mjs.map +1 -0
- package/dist/utils/stable-stringify.cjs +19 -0
- package/dist/utils/stable-stringify.cjs.map +1 -0
- package/dist/utils/stable-stringify.mjs +22 -0
- package/dist/utils/stable-stringify.mjs.map +1 -0
- package/package.json +64 -27
- package/readme.md +86 -106
- package/index.d.ts +0 -65
- package/index.js +0 -1
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
const require_errors = require("../errors.cjs");
|
|
2
|
+
const require_driver = require("./driver.cjs");
|
|
3
|
+
const require_sql_compiler = require("./sql-compiler.cjs");
|
|
4
|
+
//#region src/drivers/mysql.ts
|
|
5
|
+
/**
|
|
6
|
+
* MySQL database driver supporting mysql2 and mysql
|
|
7
|
+
*/
|
|
8
|
+
var MySQLDriver = class extends require_driver.BaseDriver {
|
|
9
|
+
pool = null;
|
|
10
|
+
config;
|
|
11
|
+
provider;
|
|
12
|
+
constructor(config, provider) {
|
|
13
|
+
super();
|
|
14
|
+
this.config = config;
|
|
15
|
+
this.provider = provider;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Connect to the MySQL/MariaDB database
|
|
19
|
+
*/
|
|
20
|
+
async connect() {
|
|
21
|
+
if (this.connected) return;
|
|
22
|
+
const provider = this.provider;
|
|
23
|
+
try {
|
|
24
|
+
if (!provider || provider === "mysql2") try {
|
|
25
|
+
this.pool = (await import("mysql2/promise")).createPool({
|
|
26
|
+
host: this.config.host,
|
|
27
|
+
port: this.config.port ?? 3306,
|
|
28
|
+
user: this.config.user,
|
|
29
|
+
password: this.config.password,
|
|
30
|
+
database: this.config.database,
|
|
31
|
+
waitForConnections: true,
|
|
32
|
+
connectionLimit: 10,
|
|
33
|
+
enableKeepAlive: true,
|
|
34
|
+
keepAliveInitialDelay: 1e4
|
|
35
|
+
});
|
|
36
|
+
this.connected = true;
|
|
37
|
+
return;
|
|
38
|
+
} catch (err) {
|
|
39
|
+
if (provider === "mysql2") throw err;
|
|
40
|
+
}
|
|
41
|
+
if (!provider || provider === "mysql") try {
|
|
42
|
+
const pool = (await import("mysql")).createPool({
|
|
43
|
+
host: this.config.host,
|
|
44
|
+
port: this.config.port ?? 3306,
|
|
45
|
+
user: this.config.user,
|
|
46
|
+
password: this.config.password,
|
|
47
|
+
database: this.config.database,
|
|
48
|
+
connectionLimit: 10,
|
|
49
|
+
waitForConnections: true,
|
|
50
|
+
acquireTimeout: 1e4
|
|
51
|
+
});
|
|
52
|
+
this.pool = {
|
|
53
|
+
execute: (sql, params) => new Promise((resolve, reject) => {
|
|
54
|
+
pool.query(sql, params, (err, results, fields) => {
|
|
55
|
+
if (err) return reject(err);
|
|
56
|
+
resolve([results, fields]);
|
|
57
|
+
});
|
|
58
|
+
}),
|
|
59
|
+
query: (sql, params) => new Promise((resolve, reject) => {
|
|
60
|
+
pool.query(sql, params, (err, results, fields) => {
|
|
61
|
+
if (err) return reject(err);
|
|
62
|
+
resolve([results, fields]);
|
|
63
|
+
});
|
|
64
|
+
}),
|
|
65
|
+
getConnection: () => new Promise((resolve, reject) => {
|
|
66
|
+
pool.getConnection((err, conn) => {
|
|
67
|
+
if (err) return reject(err);
|
|
68
|
+
resolve({
|
|
69
|
+
beginTransaction: () => new Promise((res, rej) => conn.beginTransaction((e) => e ? rej(e) : res())),
|
|
70
|
+
commit: () => new Promise((res, rej) => conn.commit((e) => e ? rej(e) : res())),
|
|
71
|
+
rollback: () => new Promise((res, rej) => conn.rollback((e) => e ? rej(e) : res())),
|
|
72
|
+
release: () => conn.release(),
|
|
73
|
+
query: (sql, params) => new Promise((res, rej) => {
|
|
74
|
+
conn.query(sql, params, (e, results, fields) => e ? rej(e) : res([results, fields]));
|
|
75
|
+
}),
|
|
76
|
+
execute: (sql, params) => new Promise((res, rej) => {
|
|
77
|
+
conn.query(sql, params, (e, results, fields) => e ? rej(e) : res([results, fields]));
|
|
78
|
+
})
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
}),
|
|
82
|
+
end: () => new Promise((res, rej) => pool.end((e) => e ? rej(e) : res()))
|
|
83
|
+
};
|
|
84
|
+
this.connected = true;
|
|
85
|
+
} catch (err) {
|
|
86
|
+
if (provider === "mysql") throw err;
|
|
87
|
+
throw new Error("No MySQL driver found. Please install mysql2 or mysql.");
|
|
88
|
+
}
|
|
89
|
+
} catch (err) {
|
|
90
|
+
throw new require_errors.DriverError(`Failed to connect to MySQL database: ${err.message}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async disconnect() {
|
|
94
|
+
if (this.pool) {
|
|
95
|
+
await this.pool.end();
|
|
96
|
+
this.pool = null;
|
|
97
|
+
this.connected = false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
getPool() {
|
|
101
|
+
if (!this.pool) throw new require_errors.DriverError("Database not connected");
|
|
102
|
+
return this.pool;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Execute a SQL statement
|
|
106
|
+
* @param {string} sql - SQL statement
|
|
107
|
+
* @param {unknown[]} [params] - Query parameters
|
|
108
|
+
* @returns {Promise<any>} Execution result
|
|
109
|
+
*/
|
|
110
|
+
async execute(sql, params = []) {
|
|
111
|
+
try {
|
|
112
|
+
const [result] = await this.getPool().query(sql, this.formatParams(params));
|
|
113
|
+
return {
|
|
114
|
+
insertId: result.insertId,
|
|
115
|
+
affectedRows: result.affectedRows
|
|
116
|
+
};
|
|
117
|
+
} catch (err) {
|
|
118
|
+
throw new require_errors.DriverError(`MySQL execute error: ${err.message}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Execute a SQL query
|
|
123
|
+
* @param {string} sql - SQL query
|
|
124
|
+
* @param {unknown[]} [params] - Query parameters
|
|
125
|
+
* @returns {Promise<any[]>} Query results
|
|
126
|
+
*/
|
|
127
|
+
async query(sql, params = []) {
|
|
128
|
+
try {
|
|
129
|
+
const [rows] = await this.getPool().query(sql, this.formatParams(params));
|
|
130
|
+
return rows;
|
|
131
|
+
} catch (err) {
|
|
132
|
+
throw new require_errors.DriverError(`MySQL query error: ${err.message}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
formatParams(params) {
|
|
136
|
+
return params.map((p) => {
|
|
137
|
+
if (p instanceof Date) return p.toISOString().slice(0, 19).replace("T", " ");
|
|
138
|
+
return p;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Check if a table exists
|
|
143
|
+
* @param {string} name - Table name
|
|
144
|
+
* @returns {Promise<boolean>} Whether the table exists
|
|
145
|
+
*/
|
|
146
|
+
async tableExists(name) {
|
|
147
|
+
return (await this.query("SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?", [this.config.database, name])).length > 0;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get column metadata for a table
|
|
151
|
+
* @param {string} name - Table name
|
|
152
|
+
* @returns {Promise<ColumnMetadata[]>} Column metadata
|
|
153
|
+
*/
|
|
154
|
+
async getTableColumns(name) {
|
|
155
|
+
return (await this.query("SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? ORDER BY ORDINAL_POSITION", [this.config.database, name])).map((row) => ({
|
|
156
|
+
name: row.COLUMN_NAME,
|
|
157
|
+
type: this.mapMySQLType(row.DATA_TYPE),
|
|
158
|
+
primaryKey: row.COLUMN_KEY === "PRI",
|
|
159
|
+
autoIncrement: row.EXTRA?.includes("auto_increment") ?? false,
|
|
160
|
+
notNull: row.IS_NULLABLE === "NO",
|
|
161
|
+
unique: row.COLUMN_KEY === "UNI",
|
|
162
|
+
defaultValue: row.COLUMN_DEFAULT
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Create a table from metadata
|
|
167
|
+
* @param {TableMetadata} meta - Table metadata
|
|
168
|
+
*/
|
|
169
|
+
async createTable(meta) {
|
|
170
|
+
const sql = require_sql_compiler.compileCreateTable(meta, "mysql");
|
|
171
|
+
await this.execute(sql);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Drop a table
|
|
175
|
+
* @param {string} name - Table name
|
|
176
|
+
*/
|
|
177
|
+
async dropTable(name) {
|
|
178
|
+
await this.execute(`DROP TABLE IF EXISTS \`${name}\``);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Add a column to a table
|
|
182
|
+
* @param {string} table - Table name
|
|
183
|
+
* @param {ColumnMetadata} column - Column metadata
|
|
184
|
+
*/
|
|
185
|
+
async addColumn(table, column) {
|
|
186
|
+
const colDef = require_sql_compiler.compileColumnDef(column, "mysql");
|
|
187
|
+
await this.execute(`ALTER TABLE \`${table}\` ADD COLUMN ${colDef}`);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Drop a column from a table
|
|
191
|
+
* @param {string} table - Table name
|
|
192
|
+
* @param {string} name - Column name
|
|
193
|
+
*/
|
|
194
|
+
async dropColumn(table, name) {
|
|
195
|
+
await this.execute(`ALTER TABLE \`${table}\` DROP COLUMN \`${name}\``);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Rename a column
|
|
199
|
+
* @param {string} table - Table name
|
|
200
|
+
* @param {string} oldName - Current name
|
|
201
|
+
* @param {string} newName - New name
|
|
202
|
+
*/
|
|
203
|
+
async renameColumn(table, oldName, newName) {
|
|
204
|
+
await this.execute(`ALTER TABLE \`${table}\` RENAME COLUMN \`${oldName}\` TO \`${newName}\``);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Execute within a transaction
|
|
208
|
+
* @param {() => Promise<T>} fn - Function to execute
|
|
209
|
+
* @returns {Promise<T>} Result
|
|
210
|
+
*/
|
|
211
|
+
async transaction(fn) {
|
|
212
|
+
const conn = await this.getPool().getConnection();
|
|
213
|
+
try {
|
|
214
|
+
await conn.beginTransaction();
|
|
215
|
+
const result = await fn();
|
|
216
|
+
await conn.commit();
|
|
217
|
+
return result;
|
|
218
|
+
} catch (err) {
|
|
219
|
+
await conn.rollback();
|
|
220
|
+
throw err;
|
|
221
|
+
} finally {
|
|
222
|
+
conn.release();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Fetch all column metadata for all tables in the database in a single query
|
|
227
|
+
* @returns {Promise<Record<string, ColumnMetadata[]>>} Columns grouped by table name
|
|
228
|
+
*/
|
|
229
|
+
async getAllTableColumns() {
|
|
230
|
+
try {
|
|
231
|
+
const rows = await this.query("SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? ORDER BY TABLE_NAME, ORDINAL_POSITION", [this.config.database]);
|
|
232
|
+
const result = {};
|
|
233
|
+
for (let i = 0; i < rows.length; i++) {
|
|
234
|
+
const row = rows[i];
|
|
235
|
+
if (!row || !row.TABLE_NAME) continue;
|
|
236
|
+
const tableName = row.TABLE_NAME;
|
|
237
|
+
if (!result[tableName]) result[tableName] = [];
|
|
238
|
+
result[tableName].push({
|
|
239
|
+
name: row.COLUMN_NAME,
|
|
240
|
+
type: this.mapMySQLType(row.DATA_TYPE),
|
|
241
|
+
primaryKey: row.COLUMN_KEY === "PRI",
|
|
242
|
+
autoIncrement: row.EXTRA?.includes("auto_increment") ?? false,
|
|
243
|
+
notNull: row.IS_NULLABLE === "NO",
|
|
244
|
+
unique: row.COLUMN_KEY === "UNI",
|
|
245
|
+
defaultValue: row.COLUMN_DEFAULT
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
return result;
|
|
249
|
+
} catch (err) {
|
|
250
|
+
throw new require_errors.DriverError(`Failed to fetch all table columns: ${err.message}`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
mapMySQLType(type) {
|
|
254
|
+
const lower = type.toLowerCase();
|
|
255
|
+
if (lower === "int" || lower === "integer" || lower === "tinyint" || lower === "smallint" || lower === "mediumint") return "integer";
|
|
256
|
+
if (lower === "bigint") return "bigint";
|
|
257
|
+
if (lower === "varchar") return "varchar";
|
|
258
|
+
if (lower === "char") return "char";
|
|
259
|
+
if (lower === "text" || lower === "mediumtext" || lower === "longtext") return "text";
|
|
260
|
+
if (lower === "json") return "json";
|
|
261
|
+
if (lower === "datetime") return "datetime";
|
|
262
|
+
if (lower === "timestamp") return "timestamp";
|
|
263
|
+
if (lower === "decimal" || lower === "numeric") return "decimal";
|
|
264
|
+
if (lower === "float" || lower === "double" || lower === "real") return "float";
|
|
265
|
+
if (lower === "blob" || lower === "mediumblob" || lower === "longblob") return "blob";
|
|
266
|
+
return "text";
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
//#endregion
|
|
270
|
+
exports.MySQLDriver = MySQLDriver;
|
|
271
|
+
|
|
272
|
+
//# sourceMappingURL=mysql.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mysql.cjs","names":["BaseDriver","DriverError","compileCreateTable","compileColumnDef"],"sources":["../../src/drivers/mysql.ts"],"sourcesContent":["import { DriverError } from \"../errors\";\nimport type { ColumnMetadata, MySQLConnectionConfig, TableMetadata } from \"../types\";\nimport { BaseDriver } from \"./driver\";\nimport { compileColumnDef, compileCreateTable } from \"./sql-compiler\";\n\ninterface MySQLPool {\n query(sql: string, params?: any[]): Promise<[any, any]>;\n execute(sql: string, params?: any[]): Promise<[any, any]>;\n getConnection(): Promise<MySQLConnection>;\n end(): Promise<void>;\n}\n\ninterface MySQLConnection {\n beginTransaction(): Promise<void>;\n commit(): Promise<void>;\n rollback(): Promise<void>;\n release(): void;\n query(sql: string, params?: any[]): Promise<[any, any]>;\n execute(sql: string, params?: any[]): Promise<[any, any]>;\n}\n\n/**\n * MySQL database driver supporting mysql2 and mysql\n */\nexport class MySQLDriver extends BaseDriver {\n private pool: MySQLPool | null = null;\n private config: MySQLConnectionConfig;\n private provider?: \"mysql\" | \"mysql2\";\n\n constructor(config: MySQLConnectionConfig, provider?: \"mysql\" | \"mysql2\") {\n super();\n this.config = config;\n this.provider = provider;\n }\n\n /**\n * Connect to the MySQL/MariaDB database\n */\n async connect(): Promise<void> {\n if (this.connected) {\n return;\n }\n\n const provider = this.provider;\n\n try {\n if (!provider || provider === \"mysql2\") {\n try {\n const mysql2 = await import(\"mysql2/promise\");\n this.pool = mysql2.createPool({\n host: this.config.host,\n port: this.config.port ?? 3306,\n user: this.config.user,\n password: this.config.password,\n database: this.config.database,\n waitForConnections: true,\n connectionLimit: 10,\n enableKeepAlive: true,\n keepAliveInitialDelay: 10000,\n });\n this.connected = true;\n return;\n } catch (err) {\n if (provider === \"mysql2\") {\n throw err;\n }\n }\n }\n\n if (!provider || provider === \"mysql\") {\n try {\n const mysql = await import(\"mysql\");\n const pool = mysql.createPool({\n host: this.config.host,\n port: this.config.port ?? 3306,\n user: this.config.user,\n password: this.config.password,\n database: this.config.database,\n connectionLimit: 10,\n waitForConnections: true,\n acquireTimeout: 10000,\n });\n\n this.pool = {\n execute: (sql: string, params: any[]) =>\n new Promise((resolve, reject) => {\n pool.query(sql, params, (err, results, fields) => {\n if (err) {\n return reject(err);\n }\n resolve([results, fields]);\n });\n }),\n query: (sql: string, params: any[]) =>\n new Promise((resolve, reject) => {\n pool.query(sql, params, (err, results, fields) => {\n if (err) {\n return reject(err);\n }\n resolve([results, fields]);\n });\n }),\n getConnection: () =>\n new Promise((resolve, reject) => {\n pool.getConnection((err, conn) => {\n if (err) {\n return reject(err);\n }\n const wrappedConn: MySQLConnection = {\n beginTransaction: () =>\n new Promise<void>((res, rej) =>\n conn.beginTransaction((e) => (e ? rej(e) : res())),\n ),\n commit: () =>\n new Promise<void>((res, rej) => conn.commit((e) => (e ? rej(e) : res()))),\n rollback: () =>\n new Promise<void>((res, rej) => conn.rollback((e) => (e ? rej(e) : res()))),\n release: () => conn.release(),\n query: (sql: string, params: any[]) =>\n new Promise((res, rej) => {\n conn.query(sql, params, (e, results, fields) =>\n e ? rej(e) : res([results, fields]),\n );\n }),\n execute: (sql: string, params: any[]) =>\n new Promise((res, rej) => {\n conn.query(sql, params, (e, results, fields) =>\n e ? rej(e) : res([results, fields]),\n );\n }),\n };\n resolve(wrappedConn);\n });\n }),\n end: () => new Promise<void>((res, rej) => pool.end((e) => (e ? rej(e) : res()))),\n };\n this.connected = true;\n } catch (err) {\n if (provider === \"mysql\") {\n throw err;\n }\n throw new Error(\"No MySQL driver found. Please install mysql2 or mysql.\");\n }\n }\n } catch (err: any) {\n throw new DriverError(`Failed to connect to MySQL database: ${err.message}`);\n }\n }\n\n async disconnect(): Promise<void> {\n if (this.pool) {\n await this.pool.end();\n this.pool = null;\n this.connected = false;\n }\n }\n\n private getPool(): MySQLPool {\n if (!this.pool) {\n throw new DriverError(\"Database not connected\");\n }\n return this.pool;\n }\n\n /**\n * Execute a SQL statement\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n async execute(sql: string, params: unknown[] = []): Promise<any> {\n try {\n const [result] = await this.getPool().query(sql, this.formatParams(params));\n return {\n insertId: result.insertId,\n affectedRows: result.affectedRows,\n };\n } catch (err: any) {\n throw new DriverError(`MySQL execute error: ${err.message}`);\n }\n }\n\n /**\n * Execute a SQL query\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n async query(sql: string, params: unknown[] = []): Promise<any[]> {\n try {\n const [rows] = await this.getPool().query(sql, this.formatParams(params));\n return rows as any[];\n } catch (err: any) {\n throw new DriverError(`MySQL query error: ${err.message}`);\n }\n }\n\n private formatParams(params: unknown[]): unknown[] {\n return params.map((p) => {\n if (p instanceof Date) {\n return p.toISOString().slice(0, 19).replace(\"T\", \" \");\n }\n return p;\n });\n }\n\n /**\n * Check if a table exists\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n async tableExists(name: string): Promise<boolean> {\n const rows = await this.query(\n \"SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?\",\n [this.config.database, name],\n );\n return rows.length > 0;\n }\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata\n */\n async getTableColumns(name: string): Promise<ColumnMetadata[]> {\n const rows = await this.query(\n \"SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? ORDER BY ORDINAL_POSITION\",\n [this.config.database, name],\n );\n return rows.map((row: any) => ({\n name: row.COLUMN_NAME,\n type: this.mapMySQLType(row.DATA_TYPE),\n primaryKey: row.COLUMN_KEY === \"PRI\",\n autoIncrement: row.EXTRA?.includes(\"auto_increment\") ?? false,\n notNull: row.IS_NULLABLE === \"NO\",\n unique: row.COLUMN_KEY === \"UNI\",\n defaultValue: row.COLUMN_DEFAULT,\n }));\n }\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n async createTable(meta: TableMetadata): Promise<void> {\n const sql = compileCreateTable(meta, \"mysql\");\n await this.execute(sql);\n }\n\n /**\n * Drop a table\n * @param {string} name - Table name\n */\n async dropTable(name: string): Promise<void> {\n await this.execute(`DROP TABLE IF EXISTS \\`${name}\\``);\n }\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n async addColumn(table: string, column: ColumnMetadata): Promise<void> {\n const colDef = compileColumnDef(column, \"mysql\");\n await this.execute(`ALTER TABLE \\`${table}\\` ADD COLUMN ${colDef}`);\n }\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n async dropColumn(table: string, name: string): Promise<void> {\n await this.execute(`ALTER TABLE \\`${table}\\` DROP COLUMN \\`${name}\\``);\n }\n\n /**\n * Rename a column\n * @param {string} table - Table name\n * @param {string} oldName - Current name\n * @param {string} newName - New name\n */\n async renameColumn(table: string, oldName: string, newName: string): Promise<void> {\n await this.execute(`ALTER TABLE \\`${table}\\` RENAME COLUMN \\`${oldName}\\` TO \\`${newName}\\``);\n }\n\n /**\n * Execute within a transaction\n * @param {() => Promise<T>} fn - Function to execute\n * @returns {Promise<T>} Result\n */\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n const conn = await this.getPool().getConnection();\n try {\n await conn.beginTransaction();\n const result = await fn();\n await conn.commit();\n return result;\n } catch (err) {\n await conn.rollback();\n throw err;\n } finally {\n conn.release();\n }\n }\n\n /**\n * Fetch all column metadata for all tables in the database in a single query\n * @returns {Promise<Record<string, ColumnMetadata[]>>} Columns grouped by table name\n */\n async getAllTableColumns(): Promise<Record<string, ColumnMetadata[]>> {\n try {\n const rows = await this.query(\n \"SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? ORDER BY TABLE_NAME, ORDINAL_POSITION\",\n [this.config.database],\n );\n\n const result: Record<string, ColumnMetadata[]> = {};\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i] as any;\n if (!row || !row.TABLE_NAME) {\n continue;\n }\n const tableName = row.TABLE_NAME;\n if (!result[tableName]) {\n result[tableName] = [];\n }\n result[tableName].push({\n name: row.COLUMN_NAME,\n type: this.mapMySQLType(row.DATA_TYPE),\n primaryKey: row.COLUMN_KEY === \"PRI\",\n autoIncrement: row.EXTRA?.includes(\"auto_increment\") ?? false,\n notNull: row.IS_NULLABLE === \"NO\",\n unique: row.COLUMN_KEY === \"UNI\",\n defaultValue: row.COLUMN_DEFAULT,\n });\n }\n return result;\n } catch (err: any) {\n throw new DriverError(`Failed to fetch all table columns: ${err.message}`);\n }\n }\n\n private mapMySQLType(type: string): ColumnMetadata[\"type\"] {\n const lower = type.toLowerCase();\n if (\n lower === \"int\" ||\n lower === \"integer\" ||\n lower === \"tinyint\" ||\n lower === \"smallint\" ||\n lower === \"mediumint\"\n ) {\n return \"integer\";\n }\n if (lower === \"bigint\") {\n return \"bigint\";\n }\n if (lower === \"varchar\") {\n return \"varchar\";\n }\n if (lower === \"char\") {\n return \"char\";\n }\n if (lower === \"text\" || lower === \"mediumtext\" || lower === \"longtext\") {\n return \"text\";\n }\n if (lower === \"json\") {\n return \"json\";\n }\n if (lower === \"datetime\") {\n return \"datetime\";\n }\n if (lower === \"timestamp\") {\n return \"timestamp\";\n }\n if (lower === \"decimal\" || lower === \"numeric\") {\n return \"decimal\";\n }\n if (lower === \"float\" || lower === \"double\" || lower === \"real\") {\n return \"float\";\n }\n if (lower === \"blob\" || lower === \"mediumblob\" || lower === \"longblob\") {\n return \"blob\";\n }\n return \"text\";\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { DriverError } from "../errors.mjs";
|
|
2
|
+
import { BaseDriver } from "./driver.mjs";
|
|
3
|
+
import { compileColumnDef, compileCreateTable } from "./sql-compiler.mjs";
|
|
4
|
+
//#region src/drivers/mysql.ts
|
|
5
|
+
/**
|
|
6
|
+
* MySQL database driver supporting mysql2 and mysql
|
|
7
|
+
*/
|
|
8
|
+
var MySQLDriver = class extends BaseDriver {
|
|
9
|
+
pool = null;
|
|
10
|
+
config;
|
|
11
|
+
provider;
|
|
12
|
+
constructor(config, provider) {
|
|
13
|
+
super();
|
|
14
|
+
this.config = config;
|
|
15
|
+
this.provider = provider;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Connect to the MySQL/MariaDB database
|
|
19
|
+
*/
|
|
20
|
+
async connect() {
|
|
21
|
+
if (this.connected) return;
|
|
22
|
+
const provider = this.provider;
|
|
23
|
+
try {
|
|
24
|
+
if (!provider || provider === "mysql2") try {
|
|
25
|
+
this.pool = (await import("mysql2/promise")).createPool({
|
|
26
|
+
host: this.config.host,
|
|
27
|
+
port: this.config.port ?? 3306,
|
|
28
|
+
user: this.config.user,
|
|
29
|
+
password: this.config.password,
|
|
30
|
+
database: this.config.database,
|
|
31
|
+
waitForConnections: true,
|
|
32
|
+
connectionLimit: 10,
|
|
33
|
+
enableKeepAlive: true,
|
|
34
|
+
keepAliveInitialDelay: 1e4
|
|
35
|
+
});
|
|
36
|
+
this.connected = true;
|
|
37
|
+
return;
|
|
38
|
+
} catch (err) {
|
|
39
|
+
if (provider === "mysql2") throw err;
|
|
40
|
+
}
|
|
41
|
+
if (!provider || provider === "mysql") try {
|
|
42
|
+
const pool = (await import("mysql")).createPool({
|
|
43
|
+
host: this.config.host,
|
|
44
|
+
port: this.config.port ?? 3306,
|
|
45
|
+
user: this.config.user,
|
|
46
|
+
password: this.config.password,
|
|
47
|
+
database: this.config.database,
|
|
48
|
+
connectionLimit: 10,
|
|
49
|
+
waitForConnections: true,
|
|
50
|
+
acquireTimeout: 1e4
|
|
51
|
+
});
|
|
52
|
+
this.pool = {
|
|
53
|
+
execute: (sql, params) => new Promise((resolve, reject) => {
|
|
54
|
+
pool.query(sql, params, (err, results, fields) => {
|
|
55
|
+
if (err) return reject(err);
|
|
56
|
+
resolve([results, fields]);
|
|
57
|
+
});
|
|
58
|
+
}),
|
|
59
|
+
query: (sql, params) => new Promise((resolve, reject) => {
|
|
60
|
+
pool.query(sql, params, (err, results, fields) => {
|
|
61
|
+
if (err) return reject(err);
|
|
62
|
+
resolve([results, fields]);
|
|
63
|
+
});
|
|
64
|
+
}),
|
|
65
|
+
getConnection: () => new Promise((resolve, reject) => {
|
|
66
|
+
pool.getConnection((err, conn) => {
|
|
67
|
+
if (err) return reject(err);
|
|
68
|
+
resolve({
|
|
69
|
+
beginTransaction: () => new Promise((res, rej) => conn.beginTransaction((e) => e ? rej(e) : res())),
|
|
70
|
+
commit: () => new Promise((res, rej) => conn.commit((e) => e ? rej(e) : res())),
|
|
71
|
+
rollback: () => new Promise((res, rej) => conn.rollback((e) => e ? rej(e) : res())),
|
|
72
|
+
release: () => conn.release(),
|
|
73
|
+
query: (sql, params) => new Promise((res, rej) => {
|
|
74
|
+
conn.query(sql, params, (e, results, fields) => e ? rej(e) : res([results, fields]));
|
|
75
|
+
}),
|
|
76
|
+
execute: (sql, params) => new Promise((res, rej) => {
|
|
77
|
+
conn.query(sql, params, (e, results, fields) => e ? rej(e) : res([results, fields]));
|
|
78
|
+
})
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
}),
|
|
82
|
+
end: () => new Promise((res, rej) => pool.end((e) => e ? rej(e) : res()))
|
|
83
|
+
};
|
|
84
|
+
this.connected = true;
|
|
85
|
+
} catch (err) {
|
|
86
|
+
if (provider === "mysql") throw err;
|
|
87
|
+
throw new Error("No MySQL driver found. Please install mysql2 or mysql.");
|
|
88
|
+
}
|
|
89
|
+
} catch (err) {
|
|
90
|
+
throw new DriverError(`Failed to connect to MySQL database: ${err.message}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async disconnect() {
|
|
94
|
+
if (this.pool) {
|
|
95
|
+
await this.pool.end();
|
|
96
|
+
this.pool = null;
|
|
97
|
+
this.connected = false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
getPool() {
|
|
101
|
+
if (!this.pool) throw new DriverError("Database not connected");
|
|
102
|
+
return this.pool;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Execute a SQL statement
|
|
106
|
+
* @param {string} sql - SQL statement
|
|
107
|
+
* @param {unknown[]} [params] - Query parameters
|
|
108
|
+
* @returns {Promise<any>} Execution result
|
|
109
|
+
*/
|
|
110
|
+
async execute(sql, params = []) {
|
|
111
|
+
try {
|
|
112
|
+
const [result] = await this.getPool().query(sql, this.formatParams(params));
|
|
113
|
+
return {
|
|
114
|
+
insertId: result.insertId,
|
|
115
|
+
affectedRows: result.affectedRows
|
|
116
|
+
};
|
|
117
|
+
} catch (err) {
|
|
118
|
+
throw new DriverError(`MySQL execute error: ${err.message}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Execute a SQL query
|
|
123
|
+
* @param {string} sql - SQL query
|
|
124
|
+
* @param {unknown[]} [params] - Query parameters
|
|
125
|
+
* @returns {Promise<any[]>} Query results
|
|
126
|
+
*/
|
|
127
|
+
async query(sql, params = []) {
|
|
128
|
+
try {
|
|
129
|
+
const [rows] = await this.getPool().query(sql, this.formatParams(params));
|
|
130
|
+
return rows;
|
|
131
|
+
} catch (err) {
|
|
132
|
+
throw new DriverError(`MySQL query error: ${err.message}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
formatParams(params) {
|
|
136
|
+
return params.map((p) => {
|
|
137
|
+
if (p instanceof Date) return p.toISOString().slice(0, 19).replace("T", " ");
|
|
138
|
+
return p;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Check if a table exists
|
|
143
|
+
* @param {string} name - Table name
|
|
144
|
+
* @returns {Promise<boolean>} Whether the table exists
|
|
145
|
+
*/
|
|
146
|
+
async tableExists(name) {
|
|
147
|
+
return (await this.query("SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?", [this.config.database, name])).length > 0;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get column metadata for a table
|
|
151
|
+
* @param {string} name - Table name
|
|
152
|
+
* @returns {Promise<ColumnMetadata[]>} Column metadata
|
|
153
|
+
*/
|
|
154
|
+
async getTableColumns(name) {
|
|
155
|
+
return (await this.query("SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? ORDER BY ORDINAL_POSITION", [this.config.database, name])).map((row) => ({
|
|
156
|
+
name: row.COLUMN_NAME,
|
|
157
|
+
type: this.mapMySQLType(row.DATA_TYPE),
|
|
158
|
+
primaryKey: row.COLUMN_KEY === "PRI",
|
|
159
|
+
autoIncrement: row.EXTRA?.includes("auto_increment") ?? false,
|
|
160
|
+
notNull: row.IS_NULLABLE === "NO",
|
|
161
|
+
unique: row.COLUMN_KEY === "UNI",
|
|
162
|
+
defaultValue: row.COLUMN_DEFAULT
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Create a table from metadata
|
|
167
|
+
* @param {TableMetadata} meta - Table metadata
|
|
168
|
+
*/
|
|
169
|
+
async createTable(meta) {
|
|
170
|
+
const sql = compileCreateTable(meta, "mysql");
|
|
171
|
+
await this.execute(sql);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Drop a table
|
|
175
|
+
* @param {string} name - Table name
|
|
176
|
+
*/
|
|
177
|
+
async dropTable(name) {
|
|
178
|
+
await this.execute(`DROP TABLE IF EXISTS \`${name}\``);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Add a column to a table
|
|
182
|
+
* @param {string} table - Table name
|
|
183
|
+
* @param {ColumnMetadata} column - Column metadata
|
|
184
|
+
*/
|
|
185
|
+
async addColumn(table, column) {
|
|
186
|
+
const colDef = compileColumnDef(column, "mysql");
|
|
187
|
+
await this.execute(`ALTER TABLE \`${table}\` ADD COLUMN ${colDef}`);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Drop a column from a table
|
|
191
|
+
* @param {string} table - Table name
|
|
192
|
+
* @param {string} name - Column name
|
|
193
|
+
*/
|
|
194
|
+
async dropColumn(table, name) {
|
|
195
|
+
await this.execute(`ALTER TABLE \`${table}\` DROP COLUMN \`${name}\``);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Rename a column
|
|
199
|
+
* @param {string} table - Table name
|
|
200
|
+
* @param {string} oldName - Current name
|
|
201
|
+
* @param {string} newName - New name
|
|
202
|
+
*/
|
|
203
|
+
async renameColumn(table, oldName, newName) {
|
|
204
|
+
await this.execute(`ALTER TABLE \`${table}\` RENAME COLUMN \`${oldName}\` TO \`${newName}\``);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Execute within a transaction
|
|
208
|
+
* @param {() => Promise<T>} fn - Function to execute
|
|
209
|
+
* @returns {Promise<T>} Result
|
|
210
|
+
*/
|
|
211
|
+
async transaction(fn) {
|
|
212
|
+
const conn = await this.getPool().getConnection();
|
|
213
|
+
try {
|
|
214
|
+
await conn.beginTransaction();
|
|
215
|
+
const result = await fn();
|
|
216
|
+
await conn.commit();
|
|
217
|
+
return result;
|
|
218
|
+
} catch (err) {
|
|
219
|
+
await conn.rollback();
|
|
220
|
+
throw err;
|
|
221
|
+
} finally {
|
|
222
|
+
conn.release();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Fetch all column metadata for all tables in the database in a single query
|
|
227
|
+
* @returns {Promise<Record<string, ColumnMetadata[]>>} Columns grouped by table name
|
|
228
|
+
*/
|
|
229
|
+
async getAllTableColumns() {
|
|
230
|
+
try {
|
|
231
|
+
const rows = await this.query("SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? ORDER BY TABLE_NAME, ORDINAL_POSITION", [this.config.database]);
|
|
232
|
+
const result = {};
|
|
233
|
+
for (let i = 0; i < rows.length; i++) {
|
|
234
|
+
const row = rows[i];
|
|
235
|
+
if (!row || !row.TABLE_NAME) continue;
|
|
236
|
+
const tableName = row.TABLE_NAME;
|
|
237
|
+
if (!result[tableName]) result[tableName] = [];
|
|
238
|
+
result[tableName].push({
|
|
239
|
+
name: row.COLUMN_NAME,
|
|
240
|
+
type: this.mapMySQLType(row.DATA_TYPE),
|
|
241
|
+
primaryKey: row.COLUMN_KEY === "PRI",
|
|
242
|
+
autoIncrement: row.EXTRA?.includes("auto_increment") ?? false,
|
|
243
|
+
notNull: row.IS_NULLABLE === "NO",
|
|
244
|
+
unique: row.COLUMN_KEY === "UNI",
|
|
245
|
+
defaultValue: row.COLUMN_DEFAULT
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
return result;
|
|
249
|
+
} catch (err) {
|
|
250
|
+
throw new DriverError(`Failed to fetch all table columns: ${err.message}`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
mapMySQLType(type) {
|
|
254
|
+
const lower = type.toLowerCase();
|
|
255
|
+
if (lower === "int" || lower === "integer" || lower === "tinyint" || lower === "smallint" || lower === "mediumint") return "integer";
|
|
256
|
+
if (lower === "bigint") return "bigint";
|
|
257
|
+
if (lower === "varchar") return "varchar";
|
|
258
|
+
if (lower === "char") return "char";
|
|
259
|
+
if (lower === "text" || lower === "mediumtext" || lower === "longtext") return "text";
|
|
260
|
+
if (lower === "json") return "json";
|
|
261
|
+
if (lower === "datetime") return "datetime";
|
|
262
|
+
if (lower === "timestamp") return "timestamp";
|
|
263
|
+
if (lower === "decimal" || lower === "numeric") return "decimal";
|
|
264
|
+
if (lower === "float" || lower === "double" || lower === "real") return "float";
|
|
265
|
+
if (lower === "blob" || lower === "mediumblob" || lower === "longblob") return "blob";
|
|
266
|
+
return "text";
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
//#endregion
|
|
270
|
+
export { MySQLDriver };
|
|
271
|
+
|
|
272
|
+
//# sourceMappingURL=mysql.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mysql.mjs","names":[],"sources":["../../src/drivers/mysql.ts"],"sourcesContent":["import { DriverError } from \"../errors\";\nimport type { ColumnMetadata, MySQLConnectionConfig, TableMetadata } from \"../types\";\nimport { BaseDriver } from \"./driver\";\nimport { compileColumnDef, compileCreateTable } from \"./sql-compiler\";\n\ninterface MySQLPool {\n query(sql: string, params?: any[]): Promise<[any, any]>;\n execute(sql: string, params?: any[]): Promise<[any, any]>;\n getConnection(): Promise<MySQLConnection>;\n end(): Promise<void>;\n}\n\ninterface MySQLConnection {\n beginTransaction(): Promise<void>;\n commit(): Promise<void>;\n rollback(): Promise<void>;\n release(): void;\n query(sql: string, params?: any[]): Promise<[any, any]>;\n execute(sql: string, params?: any[]): Promise<[any, any]>;\n}\n\n/**\n * MySQL database driver supporting mysql2 and mysql\n */\nexport class MySQLDriver extends BaseDriver {\n private pool: MySQLPool | null = null;\n private config: MySQLConnectionConfig;\n private provider?: \"mysql\" | \"mysql2\";\n\n constructor(config: MySQLConnectionConfig, provider?: \"mysql\" | \"mysql2\") {\n super();\n this.config = config;\n this.provider = provider;\n }\n\n /**\n * Connect to the MySQL/MariaDB database\n */\n async connect(): Promise<void> {\n if (this.connected) {\n return;\n }\n\n const provider = this.provider;\n\n try {\n if (!provider || provider === \"mysql2\") {\n try {\n const mysql2 = await import(\"mysql2/promise\");\n this.pool = mysql2.createPool({\n host: this.config.host,\n port: this.config.port ?? 3306,\n user: this.config.user,\n password: this.config.password,\n database: this.config.database,\n waitForConnections: true,\n connectionLimit: 10,\n enableKeepAlive: true,\n keepAliveInitialDelay: 10000,\n });\n this.connected = true;\n return;\n } catch (err) {\n if (provider === \"mysql2\") {\n throw err;\n }\n }\n }\n\n if (!provider || provider === \"mysql\") {\n try {\n const mysql = await import(\"mysql\");\n const pool = mysql.createPool({\n host: this.config.host,\n port: this.config.port ?? 3306,\n user: this.config.user,\n password: this.config.password,\n database: this.config.database,\n connectionLimit: 10,\n waitForConnections: true,\n acquireTimeout: 10000,\n });\n\n this.pool = {\n execute: (sql: string, params: any[]) =>\n new Promise((resolve, reject) => {\n pool.query(sql, params, (err, results, fields) => {\n if (err) {\n return reject(err);\n }\n resolve([results, fields]);\n });\n }),\n query: (sql: string, params: any[]) =>\n new Promise((resolve, reject) => {\n pool.query(sql, params, (err, results, fields) => {\n if (err) {\n return reject(err);\n }\n resolve([results, fields]);\n });\n }),\n getConnection: () =>\n new Promise((resolve, reject) => {\n pool.getConnection((err, conn) => {\n if (err) {\n return reject(err);\n }\n const wrappedConn: MySQLConnection = {\n beginTransaction: () =>\n new Promise<void>((res, rej) =>\n conn.beginTransaction((e) => (e ? rej(e) : res())),\n ),\n commit: () =>\n new Promise<void>((res, rej) => conn.commit((e) => (e ? rej(e) : res()))),\n rollback: () =>\n new Promise<void>((res, rej) => conn.rollback((e) => (e ? rej(e) : res()))),\n release: () => conn.release(),\n query: (sql: string, params: any[]) =>\n new Promise((res, rej) => {\n conn.query(sql, params, (e, results, fields) =>\n e ? rej(e) : res([results, fields]),\n );\n }),\n execute: (sql: string, params: any[]) =>\n new Promise((res, rej) => {\n conn.query(sql, params, (e, results, fields) =>\n e ? rej(e) : res([results, fields]),\n );\n }),\n };\n resolve(wrappedConn);\n });\n }),\n end: () => new Promise<void>((res, rej) => pool.end((e) => (e ? rej(e) : res()))),\n };\n this.connected = true;\n } catch (err) {\n if (provider === \"mysql\") {\n throw err;\n }\n throw new Error(\"No MySQL driver found. Please install mysql2 or mysql.\");\n }\n }\n } catch (err: any) {\n throw new DriverError(`Failed to connect to MySQL database: ${err.message}`);\n }\n }\n\n async disconnect(): Promise<void> {\n if (this.pool) {\n await this.pool.end();\n this.pool = null;\n this.connected = false;\n }\n }\n\n private getPool(): MySQLPool {\n if (!this.pool) {\n throw new DriverError(\"Database not connected\");\n }\n return this.pool;\n }\n\n /**\n * Execute a SQL statement\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n async execute(sql: string, params: unknown[] = []): Promise<any> {\n try {\n const [result] = await this.getPool().query(sql, this.formatParams(params));\n return {\n insertId: result.insertId,\n affectedRows: result.affectedRows,\n };\n } catch (err: any) {\n throw new DriverError(`MySQL execute error: ${err.message}`);\n }\n }\n\n /**\n * Execute a SQL query\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n async query(sql: string, params: unknown[] = []): Promise<any[]> {\n try {\n const [rows] = await this.getPool().query(sql, this.formatParams(params));\n return rows as any[];\n } catch (err: any) {\n throw new DriverError(`MySQL query error: ${err.message}`);\n }\n }\n\n private formatParams(params: unknown[]): unknown[] {\n return params.map((p) => {\n if (p instanceof Date) {\n return p.toISOString().slice(0, 19).replace(\"T\", \" \");\n }\n return p;\n });\n }\n\n /**\n * Check if a table exists\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n async tableExists(name: string): Promise<boolean> {\n const rows = await this.query(\n \"SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?\",\n [this.config.database, name],\n );\n return rows.length > 0;\n }\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata\n */\n async getTableColumns(name: string): Promise<ColumnMetadata[]> {\n const rows = await this.query(\n \"SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? ORDER BY ORDINAL_POSITION\",\n [this.config.database, name],\n );\n return rows.map((row: any) => ({\n name: row.COLUMN_NAME,\n type: this.mapMySQLType(row.DATA_TYPE),\n primaryKey: row.COLUMN_KEY === \"PRI\",\n autoIncrement: row.EXTRA?.includes(\"auto_increment\") ?? false,\n notNull: row.IS_NULLABLE === \"NO\",\n unique: row.COLUMN_KEY === \"UNI\",\n defaultValue: row.COLUMN_DEFAULT,\n }));\n }\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n async createTable(meta: TableMetadata): Promise<void> {\n const sql = compileCreateTable(meta, \"mysql\");\n await this.execute(sql);\n }\n\n /**\n * Drop a table\n * @param {string} name - Table name\n */\n async dropTable(name: string): Promise<void> {\n await this.execute(`DROP TABLE IF EXISTS \\`${name}\\``);\n }\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n async addColumn(table: string, column: ColumnMetadata): Promise<void> {\n const colDef = compileColumnDef(column, \"mysql\");\n await this.execute(`ALTER TABLE \\`${table}\\` ADD COLUMN ${colDef}`);\n }\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n async dropColumn(table: string, name: string): Promise<void> {\n await this.execute(`ALTER TABLE \\`${table}\\` DROP COLUMN \\`${name}\\``);\n }\n\n /**\n * Rename a column\n * @param {string} table - Table name\n * @param {string} oldName - Current name\n * @param {string} newName - New name\n */\n async renameColumn(table: string, oldName: string, newName: string): Promise<void> {\n await this.execute(`ALTER TABLE \\`${table}\\` RENAME COLUMN \\`${oldName}\\` TO \\`${newName}\\``);\n }\n\n /**\n * Execute within a transaction\n * @param {() => Promise<T>} fn - Function to execute\n * @returns {Promise<T>} Result\n */\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n const conn = await this.getPool().getConnection();\n try {\n await conn.beginTransaction();\n const result = await fn();\n await conn.commit();\n return result;\n } catch (err) {\n await conn.rollback();\n throw err;\n } finally {\n conn.release();\n }\n }\n\n /**\n * Fetch all column metadata for all tables in the database in a single query\n * @returns {Promise<Record<string, ColumnMetadata[]>>} Columns grouped by table name\n */\n async getAllTableColumns(): Promise<Record<string, ColumnMetadata[]>> {\n try {\n const rows = await this.query(\n \"SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_KEY, EXTRA, COLUMN_DEFAULT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? ORDER BY TABLE_NAME, ORDINAL_POSITION\",\n [this.config.database],\n );\n\n const result: Record<string, ColumnMetadata[]> = {};\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i] as any;\n if (!row || !row.TABLE_NAME) {\n continue;\n }\n const tableName = row.TABLE_NAME;\n if (!result[tableName]) {\n result[tableName] = [];\n }\n result[tableName].push({\n name: row.COLUMN_NAME,\n type: this.mapMySQLType(row.DATA_TYPE),\n primaryKey: row.COLUMN_KEY === \"PRI\",\n autoIncrement: row.EXTRA?.includes(\"auto_increment\") ?? false,\n notNull: row.IS_NULLABLE === \"NO\",\n unique: row.COLUMN_KEY === \"UNI\",\n defaultValue: row.COLUMN_DEFAULT,\n });\n }\n return result;\n } catch (err: any) {\n throw new DriverError(`Failed to fetch all table columns: ${err.message}`);\n }\n }\n\n private mapMySQLType(type: string): ColumnMetadata[\"type\"] {\n const lower = type.toLowerCase();\n if (\n lower === \"int\" ||\n lower === \"integer\" ||\n lower === \"tinyint\" ||\n lower === \"smallint\" ||\n lower === \"mediumint\"\n ) {\n return \"integer\";\n }\n if (lower === \"bigint\") {\n return \"bigint\";\n }\n if (lower === \"varchar\") {\n return \"varchar\";\n }\n if (lower === \"char\") {\n return \"char\";\n }\n if (lower === \"text\" || lower === \"mediumtext\" || lower === \"longtext\") {\n return \"text\";\n }\n if (lower === \"json\") {\n return \"json\";\n }\n if (lower === \"datetime\") {\n return \"datetime\";\n }\n if (lower === \"timestamp\") {\n return \"timestamp\";\n }\n if (lower === \"decimal\" || lower === \"numeric\") {\n return \"decimal\";\n }\n if (lower === \"float\" || lower === \"double\" || lower === \"real\") {\n return \"float\";\n }\n if (lower === \"blob\" || lower === \"mediumblob\" || lower === \"longblob\") {\n return \"blob\";\n }\n return \"text\";\n }\n}\n"],"mappings":"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"}
|