@mountsqli/mysql 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,260 @@
1
+ // src/mysql-core/dialect.ts
2
+ import { Dialect, SQL } from "@mountsqli/core";
3
+ var MysqlDialect = class extends Dialect {
4
+ dialect = "mysql";
5
+ escapeName(name) {
6
+ return `\`${name}\``;
7
+ }
8
+ escapeParam(index) {
9
+ return `?`;
10
+ }
11
+ buildSelectQuery(config) {
12
+ const parts = ["SELECT"];
13
+ if (config.distinct) parts.push("DISTINCT");
14
+ if (config.columns.length > 0) {
15
+ const colSqls = config.columns.map((col) => {
16
+ const tableName2 = col._.tableName || config.table?.[/* @__PURE__ */ Symbol.for("name")];
17
+ if (tableName2) {
18
+ return `${this.escapeName(tableName2)}.${this.escapeName(col.name)}`;
19
+ }
20
+ return this.escapeName(col.name);
21
+ });
22
+ parts.push(colSqls.join(", "));
23
+ } else {
24
+ parts.push("*");
25
+ }
26
+ const tableName = config.table?.[/* @__PURE__ */ Symbol.for("name")];
27
+ parts.push(`FROM ${this.escapeName(tableName)}`);
28
+ if (config.joins) {
29
+ for (const join of config.joins) {
30
+ const joinTableName = join.table?.[/* @__PURE__ */ Symbol.for("name")];
31
+ const joinType = join.type.toUpperCase();
32
+ const onSql = join.on.toQuery(this.getBuildQueryConfig()).sql;
33
+ parts.push(`${joinType} JOIN ${this.escapeName(joinTableName)} ON ${onSql}`);
34
+ }
35
+ }
36
+ if (config.where) {
37
+ parts.push(`WHERE ${config.where.toQuery(this.getBuildQueryConfig()).sql}`);
38
+ }
39
+ if (config.groupBy && config.groupBy.length > 0) {
40
+ parts.push(`GROUP BY ${config.groupBy.map((g) => g.toQuery(this.getBuildQueryConfig()).sql).join(", ")}`);
41
+ }
42
+ if (config.having) {
43
+ parts.push(`HAVING ${config.having.toQuery(this.getBuildQueryConfig()).sql}`);
44
+ }
45
+ if (config.orderBy && config.orderBy.length > 0) {
46
+ parts.push(`ORDER BY ${config.orderBy.map((o) => o.toQuery(this.getBuildQueryConfig()).sql).join(", ")}`);
47
+ }
48
+ if (config.limit !== void 0) parts.push(`LIMIT ${config.limit}`);
49
+ if (config.offset !== void 0) parts.push(`OFFSET ${config.offset}`);
50
+ return new SQL([parts.join(" ")]);
51
+ }
52
+ buildInsertQuery(config) {
53
+ const tableName = config.table?.[/* @__PURE__ */ Symbol.for("name")];
54
+ const columns = Object.keys(config.values[0] ?? {});
55
+ const escapedCols = columns.map((c) => this.escapeName(c));
56
+ const placeholders = columns.map(() => "?");
57
+ let sql = `INSERT INTO ${this.escapeName(tableName)} (${escapedCols.join(", ")}) VALUES (${placeholders.join(", ")})`;
58
+ if (config.onConflict) {
59
+ sql += ` ${config.onConflict.toQuery(this.getBuildQueryConfig()).sql}`;
60
+ }
61
+ const params = [];
62
+ for (const row of config.values) {
63
+ for (const col of columns) {
64
+ params.push(row[col]);
65
+ }
66
+ }
67
+ return new SQL([sql]);
68
+ }
69
+ buildUpdateQuery(config) {
70
+ const tableName = config.table?.[/* @__PURE__ */ Symbol.for("name")];
71
+ const setClauses = Object.keys(config.set).map((k) => `${this.escapeName(k)} = ?`);
72
+ let sql = `UPDATE ${this.escapeName(tableName)} SET ${setClauses.join(", ")}`;
73
+ if (config.where) {
74
+ sql += ` WHERE ${config.where.toQuery(this.getBuildQueryConfig()).sql}`;
75
+ }
76
+ return new SQL([sql]);
77
+ }
78
+ buildDeleteQuery(config) {
79
+ const tableName = config.table?.[/* @__PURE__ */ Symbol.for("name")];
80
+ let sql = `DELETE FROM ${this.escapeName(tableName)}`;
81
+ if (config.where) {
82
+ sql += ` WHERE ${config.where.toQuery(this.getBuildQueryConfig()).sql}`;
83
+ }
84
+ return new SQL([sql]);
85
+ }
86
+ buildCreateTable(config) {
87
+ const tableName = config.table?.[/* @__PURE__ */ Symbol.for("name")];
88
+ const ifNotExists = config.ifNotExists ? " IF NOT EXISTS" : "";
89
+ const columns = config.table.getSQLColumns();
90
+ const colDefs = Object.values(columns).map(
91
+ (col) => ` ${this.escapeName(col.name)} ${col.sqlType}`
92
+ );
93
+ const pkCols = [];
94
+ for (const [, col] of Object.entries(config.table.columns)) {
95
+ if (col.isPrimaryKey) pkCols.push(this.escapeName(col.name));
96
+ }
97
+ if (pkCols.length > 0) colDefs.push(` PRIMARY KEY (${pkCols.join(", ")})`);
98
+ return new SQL([`CREATE TABLE${ifNotExists} ${this.escapeName(tableName)} (
99
+ ${colDefs.join(",\n")}
100
+ )`]);
101
+ }
102
+ buildDropTable(config) {
103
+ const tableName = config.table?.[/* @__PURE__ */ Symbol.for("name")];
104
+ const ifExists = config.ifExists ? " IF EXISTS" : "";
105
+ return new SQL([`DROP TABLE${ifExists} ${this.escapeName(tableName)}`]);
106
+ }
107
+ buildCreateIndex(config) {
108
+ const tableName = config.table?.[/* @__PURE__ */ Symbol.for("name")];
109
+ const unique = config.unique ? "UNIQUE " : "";
110
+ const colNames = config.columns.map((c) => this.escapeName(c.name)).join(", ");
111
+ return new SQL([`CREATE ${unique}INDEX ${this.escapeName(config.name)} ON ${this.escapeName(tableName)} (${colNames})`]);
112
+ }
113
+ };
114
+
115
+ // src/mysql-core/session.ts
116
+ import { Session } from "@mountsqli/core";
117
+ var MysqlPreparedQuery = class {
118
+ _query;
119
+ _pool;
120
+ constructor(pool, query) {
121
+ this._query = query;
122
+ this._pool = pool;
123
+ }
124
+ async execute() {
125
+ return this._pool.execute(this._query.sql, this._query.params);
126
+ }
127
+ async all() {
128
+ const [rows] = await this._pool.execute(this._query.sql, this._query.params);
129
+ return rows;
130
+ }
131
+ async values() {
132
+ const [rows] = await this._pool.execute(this._query.sql, this._query.params);
133
+ return rows.map((row) => Object.values(row));
134
+ }
135
+ getQuery() {
136
+ return this._query;
137
+ }
138
+ };
139
+ var MysqlTransaction = class _MysqlTransaction extends Session {
140
+ _conn;
141
+ constructor(conn, logger) {
142
+ super(logger);
143
+ this._conn = conn;
144
+ this.inTransaction = true;
145
+ }
146
+ async execute(query) {
147
+ const [rows] = await this._conn.execute(query.sql, query.params);
148
+ return rows;
149
+ }
150
+ prepare(query) {
151
+ return new MysqlPreparedQuery({ execute: this._conn.execute.bind(this._conn) }, query);
152
+ }
153
+ async transaction(fn) {
154
+ await this._conn.beginTransaction();
155
+ const tx = new _MysqlTransaction(this._conn, this.logger);
156
+ try {
157
+ const result = await fn(tx);
158
+ await this._conn.commit();
159
+ return result;
160
+ } catch (err) {
161
+ await this._conn.rollback();
162
+ throw err;
163
+ }
164
+ }
165
+ async rollback() {
166
+ await this._conn.rollback();
167
+ throw new Error("Transaction rolled back");
168
+ }
169
+ async commit() {
170
+ await this._conn.commit();
171
+ }
172
+ async setTransactionIsolation(level) {
173
+ await this._conn.execute(`SET TRANSACTION ISOLATION LEVEL ${level.toUpperCase()}`);
174
+ }
175
+ async dispose() {
176
+ this._conn.release();
177
+ }
178
+ };
179
+ var MysqlSession = class extends Session {
180
+ _pool;
181
+ constructor(pool, logger) {
182
+ super(logger);
183
+ this._pool = pool;
184
+ }
185
+ async execute(query) {
186
+ const [rows] = await this._pool.execute(query.sql, query.params);
187
+ return rows;
188
+ }
189
+ prepare(query) {
190
+ return new MysqlPreparedQuery(this._pool, query);
191
+ }
192
+ async transaction(fn, config) {
193
+ const conn = await this._pool.getConnection();
194
+ try {
195
+ if (config?.isolationLevel) {
196
+ await conn.execute(`SET TRANSACTION ISOLATION LEVEL ${config.isolationLevel.toUpperCase()}`);
197
+ }
198
+ await conn.beginTransaction();
199
+ this.inTransaction = true;
200
+ const tx = new MysqlTransaction(conn, this.logger);
201
+ const result = await fn(tx);
202
+ await conn.commit();
203
+ return result;
204
+ } catch (err) {
205
+ await conn.rollback();
206
+ throw err;
207
+ } finally {
208
+ conn.release();
209
+ }
210
+ }
211
+ async dispose() {
212
+ await this._pool.end();
213
+ }
214
+ };
215
+
216
+ // src/drivers/mysql2/driver.ts
217
+ import { createLogger } from "@mountsqli/core";
218
+ var Mysql2Driver = class {
219
+ dialect = "mysql";
220
+ _config;
221
+ _pool = null;
222
+ _logger;
223
+ constructor(config) {
224
+ this._config = config;
225
+ this._logger = typeof config.logger === "boolean" ? createLogger({ enabled: config.logger }) : config.logger ?? createLogger({ enabled: false });
226
+ }
227
+ createSession() {
228
+ if (!this._pool) throw new Error("Not connected");
229
+ return new MysqlSession(this._pool, this._logger);
230
+ }
231
+ async connect() {
232
+ const mysql = await import("mysql2/promise");
233
+ if (typeof this._config.connection === "string") {
234
+ this._pool = await mysql.createPool(this._config.connection);
235
+ } else {
236
+ this._pool = await mysql.createPool(this._config.connection);
237
+ }
238
+ }
239
+ async disconnect() {
240
+ if (this._pool) {
241
+ await this._pool.end();
242
+ this._pool = null;
243
+ }
244
+ }
245
+ async ping() {
246
+ try {
247
+ await this._pool?.execute("SELECT 1");
248
+ return true;
249
+ } catch {
250
+ return false;
251
+ }
252
+ }
253
+ };
254
+
255
+ export {
256
+ MysqlDialect,
257
+ MysqlTransaction,
258
+ MysqlSession,
259
+ Mysql2Driver
260
+ };
@@ -0,0 +1,61 @@
1
+ import { Session, Logger, QueryWithTypings, PreparedQuery, TransactionConfig, Driver } from '@mountsqli/core';
2
+
3
+ /**
4
+ * MySQL session — wraps mysql2 connection/pool.
5
+ */
6
+
7
+ interface MysqlPool {
8
+ execute(sql: string, params?: any[]): Promise<[any[], any]>;
9
+ query(sql: string, params?: any[]): Promise<[any[], any]>;
10
+ getConnection(): Promise<MysqlConnection>;
11
+ end(): Promise<void>;
12
+ }
13
+ interface MysqlConnection {
14
+ execute(sql: string, params?: any[]): Promise<[any[], any]>;
15
+ query(sql: string, params?: any[]): Promise<[any[], any]>;
16
+ release(): void;
17
+ beginTransaction(): Promise<void>;
18
+ commit(): Promise<void>;
19
+ rollback(): Promise<void>;
20
+ }
21
+ declare class MysqlTransaction extends Session {
22
+ private _conn;
23
+ constructor(conn: MysqlConnection, logger: Logger);
24
+ execute<T>(query: QueryWithTypings): Promise<T>;
25
+ prepare<T>(query: QueryWithTypings): PreparedQuery<T>;
26
+ transaction<T>(fn: (tx: any) => Promise<T>): Promise<T>;
27
+ rollback(): Promise<never>;
28
+ commit(): Promise<void>;
29
+ setTransactionIsolation(level: string): Promise<void>;
30
+ dispose(): Promise<void>;
31
+ }
32
+ declare class MysqlSession extends Session {
33
+ private _pool;
34
+ constructor(pool: MysqlPool, logger: Logger);
35
+ execute<T>(query: QueryWithTypings): Promise<T>;
36
+ prepare<T>(query: QueryWithTypings): PreparedQuery<T>;
37
+ transaction<T>(fn: (tx: any) => Promise<T>, config?: TransactionConfig): Promise<T>;
38
+ dispose(): Promise<void>;
39
+ }
40
+
41
+ /**
42
+ * mysql2 driver.
43
+ */
44
+
45
+ interface Mysql2DriverConfig {
46
+ connection: string | Record<string, any>;
47
+ logger?: Logger | boolean;
48
+ }
49
+ declare class Mysql2Driver implements Driver {
50
+ readonly dialect: "mysql";
51
+ private _config;
52
+ private _pool;
53
+ private _logger;
54
+ constructor(config: Mysql2DriverConfig);
55
+ createSession(): MysqlSession;
56
+ connect(): Promise<void>;
57
+ disconnect(): Promise<void>;
58
+ ping(): Promise<boolean>;
59
+ }
60
+
61
+ export { type Mysql2DriverConfig as M, Mysql2Driver as a, MysqlSession as b, MysqlTransaction as c };
@@ -0,0 +1,11 @@
1
+ import { DatabaseConfig, Database } from '@mountsqli/core';
2
+ import { M as Mysql2DriverConfig } from '../../driver-BNL3tH8k.js';
3
+ export { a as Mysql2Driver } from '../../driver-BNL3tH8k.js';
4
+
5
+ /**
6
+ * mysql2 driver entry point.
7
+ */
8
+
9
+ declare function mountsqli(connectionOrConfig: string | Mysql2DriverConfig, options?: DatabaseConfig): Database;
10
+
11
+ export { Mysql2DriverConfig, mountsqli };
@@ -0,0 +1,19 @@
1
+ import {
2
+ Mysql2Driver,
3
+ MysqlDialect
4
+ } from "../../chunk-CO3DMWOJ.js";
5
+
6
+ // src/drivers/mysql2/index.ts
7
+ import { Database, createLogger } from "@mountsqli/core";
8
+ function mountsqli(connectionOrConfig, options) {
9
+ const logger = typeof options?.logger === "boolean" ? createLogger({ enabled: options.logger }) : options?.logger ?? createLogger({ enabled: false });
10
+ const driverConfig = typeof connectionOrConfig === "string" ? { connection: connectionOrConfig, logger } : { ...connectionOrConfig, logger };
11
+ const driver = new Mysql2Driver(driverConfig);
12
+ const dialect = new MysqlDialect();
13
+ const session = driver.createSession();
14
+ return new Database(session, dialect, { ...options, logger });
15
+ }
16
+ export {
17
+ Mysql2Driver,
18
+ mountsqli
19
+ };
@@ -0,0 +1,77 @@
1
+ import { Table, TableConfig, Column, Dialect, AnyColumn, SQL } from '@mountsqli/core';
2
+ export { a as Mysql2Driver, b as MysqlSession, c as MysqlTransaction } from './driver-BNL3tH8k.js';
3
+
4
+ /**
5
+ * MySQL table factory.
6
+ */
7
+
8
+ declare class MysqlTable extends Table<TableConfig & {
9
+ dialect: 'mysql';
10
+ }> {
11
+ }
12
+ type MysqlTableColumns = Record<string, Column>;
13
+ declare function mysqlTable<TColumns extends MysqlTableColumns>(name: string, columns: TColumns, config?: {
14
+ schema?: string;
15
+ }): MysqlTable & {
16
+ columns: TColumns;
17
+ };
18
+
19
+ /**
20
+ * MySQL dialect — SQL generation for MySQL.
21
+ */
22
+
23
+ declare class MysqlDialect extends Dialect {
24
+ readonly dialect: "mysql";
25
+ escapeName(name: string): string;
26
+ escapeParam(index: number): string;
27
+ buildSelectQuery(config: {
28
+ table: Table;
29
+ columns: AnyColumn[];
30
+ where?: SQL;
31
+ orderBy?: SQL[];
32
+ groupBy?: SQL[];
33
+ having?: SQL;
34
+ limit?: number;
35
+ offset?: number;
36
+ joins?: Array<{
37
+ table: Table;
38
+ on: SQL;
39
+ type: 'inner' | 'left' | 'right' | 'full';
40
+ }>;
41
+ distinct?: boolean;
42
+ }): SQL;
43
+ buildInsertQuery(config: {
44
+ table: Table;
45
+ values: Record<string, unknown>[];
46
+ onConflict?: SQL;
47
+ returning?: AnyColumn[];
48
+ }): SQL;
49
+ buildUpdateQuery(config: {
50
+ table: Table;
51
+ set: Record<string, unknown>;
52
+ where?: SQL;
53
+ returning?: AnyColumn[];
54
+ }): SQL;
55
+ buildDeleteQuery(config: {
56
+ table: Table;
57
+ where?: SQL;
58
+ returning?: AnyColumn[];
59
+ }): SQL;
60
+ buildCreateTable(config: {
61
+ table: Table;
62
+ ifNotExists?: boolean;
63
+ }): SQL;
64
+ buildDropTable(config: {
65
+ table: Table;
66
+ ifExists?: boolean;
67
+ }): SQL;
68
+ buildCreateIndex(config: {
69
+ name: string;
70
+ table: Table;
71
+ columns: AnyColumn[];
72
+ unique?: boolean;
73
+ concurrently?: boolean;
74
+ }): SQL;
75
+ }
76
+
77
+ export { MysqlDialect, MysqlTable, type MysqlTableColumns, mysqlTable };
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
1
+ import {
2
+ Mysql2Driver,
3
+ MysqlDialect,
4
+ MysqlSession,
5
+ MysqlTransaction
6
+ } from "./chunk-CO3DMWOJ.js";
7
+
8
+ // src/mysql-core/table.ts
9
+ import { Table } from "@mountsqli/core";
10
+ var MysqlTable = class extends Table {
11
+ };
12
+ function mysqlTable(name, columns, config) {
13
+ const table = new MysqlTable(name, config?.schema, name);
14
+ for (const [key, col] of Object.entries(columns)) {
15
+ table.columns[key] = col;
16
+ col.tableName = name;
17
+ }
18
+ const result = table;
19
+ result.columns = columns;
20
+ return result;
21
+ }
22
+ export {
23
+ Mysql2Driver,
24
+ MysqlDialect,
25
+ MysqlSession,
26
+ MysqlTransaction,
27
+ mysqlTable
28
+ };
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@mountsqli/mysql",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "import": "./dist/index.js",
8
+ "types": "./dist/index.d.ts"
9
+ },
10
+ "./mysql2": {
11
+ "import": "./dist/drivers/mysql2/index.js",
12
+ "types": "./dist/drivers/mysql2/index.d.ts"
13
+ }
14
+ },
15
+ "main": "./dist/index.js",
16
+ "types": "./dist/index.d.ts",
17
+ "files": ["dist", "LICENSE", "README.md"],
18
+ "scripts": {
19
+ "build": "tsup src/index.ts src/drivers/mysql2/index.ts --format esm --dts --clean",
20
+ "dev": "tsup --watch",
21
+ "clean": "rm -rf dist"
22
+ },
23
+ "dependencies": {
24
+ "@mountsqli/core": "workspace:*",
25
+ "@mountsqli/shared": "workspace:*"
26
+ },
27
+ "peerDependencies": {
28
+ "mysql2": "^3.0.0"
29
+ },
30
+ "peerDependenciesMeta": {
31
+ "mysql2": { "optional": true }
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^22.0.0",
35
+ "typescript": "^5.7.0",
36
+ "tsup": "^8.0.0",
37
+ "vitest": "^3.0.0"
38
+ }
39
+ }