@dyrected/db-mysql 2.5.5 → 2.5.7

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/LICENSE.md CHANGED
@@ -2,17 +2,17 @@ Business Source License 1.1
2
2
 
3
3
  Parameters
4
4
 
5
- Licensor: Dyrected
6
- Licensed Work: Dyrected
5
+ Licensor: Dyrected
6
+ Licensed Work: Dyrected
7
7
  Additional Use Grant: Commercial use is permitted as long as it is not used to provide a hosted or managed service that competes with Dyrected.
8
- Change Date: 2030-05-11
9
- Change License: Apache License 2.0
8
+ Change Date: 2030-05-18
9
+ Change License: Apache License 2.0
10
10
 
11
11
  ---
12
12
 
13
13
  Business Source License 1.1
14
14
 
15
- License text copyright © 2024 MariaDB plc, All Rights Reserved.
15
+ License text copyright © 2024 MariaDB plc, All Rights Reserved.
16
16
  “Business Source License” is a trademark of MariaDB plc.
17
17
 
18
18
  ### Terms
@@ -31,7 +31,7 @@ Any use of the Licensed Work in violation of this License will automatically ter
31
31
 
32
32
  This License does not grant you any right in any trademark or logo of Licensor or its affiliates (provided that you may use a trademark or logo of Licensor as expressly required by this License).
33
33
 
34
- TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE.
34
+ TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE.
35
35
 
36
36
  MariaDB hereby grants you permission to use this License’s text to license your works, and to refer to it using the trademark “Business Source License”, as long as you comply with the Covenants of Licensor below.
37
37
 
@@ -39,7 +39,7 @@ MariaDB hereby grants you permission to use this License’s text to license you
39
39
 
40
40
  In consideration of the right to use this License’s text and the “Business Source License” name and trademark, Licensor covenants to MariaDB, and to all other recipients of the licensed work to be provided by Licensor:
41
41
 
42
- 1. To specify as the Change License the GPL Version 2.0 or any later version, or a license that is compatible with GPL Version 2.0 or a later version, where “compatible” means that software provided under the Change License can be included in a program with software provided under GPL Version 2.0 or a later version. Licensor may specify additional Change Licenses without limitation.
42
+ 1. To specify as the Change License the GPL Version 2.0 or any later version, or a license that is compatible with GPL Version 2.0 or a later version, where “compatible” means that software provided under the Change License can be included in a program with software provided under GPL Version 2.0 or a later version. Licensor may specify additional Change Licenses without limitation.
43
43
 
44
44
  2. To either: (a) specify an additional grant of rights to use that does not impose any additional restriction on the right granted in this License, as the Additional Use Grant; or (b) insert the text “None”.
45
45
 
package/dist/index.cjs CHANGED
@@ -38,7 +38,74 @@ var import_core = require("@dyrected/core");
38
38
  var import_promise = __toESM(require("mysql2/promise"), 1);
39
39
  var MysqlAdapter = class {
40
40
  pool;
41
+ config;
42
+ initPromise = null;
41
43
  constructor(config) {
44
+ this.config = config;
45
+ this.ensureInitialized().catch((err) => {
46
+ if (err.code === "EADDRNOTAVAIL" || err.message?.includes("EADDRNOTAVAIL")) {
47
+ this.handleConnectionError(err);
48
+ }
49
+ });
50
+ }
51
+ handleConnectionError(err) {
52
+ if (err && (err.code === "EADDRNOTAVAIL" || err.message?.includes("EADDRNOTAVAIL"))) {
53
+ const customMessage = `
54
+ [dyrected/db-mysql] ERROR: MySQL connection failed with EADDRNOTAVAIL.
55
+ --------------------------------------------------------------------------------
56
+ This error often occurs when:
57
+ 1. 'localhost' is resolved to an IPv6 address (::1) but MySQL is only listening on IPv4 (127.0.0.1).
58
+ 2. The MySQL server is not running or is bound to a different port.
59
+
60
+ FIX INSTRUCTIONS:
61
+ - Try changing your host configuration in '.env' or config from 'localhost' to '127.0.0.1'.
62
+ - Make sure your local MySQL service is active and running on the configured port.
63
+ --------------------------------------------------------------------------------
64
+ `;
65
+ console.error(customMessage);
66
+ throw new Error(`MySQL Connection Failed: EADDRNOTAVAIL. Hint: Try using '127.0.0.1' instead of 'localhost'. Original: ${err.message}`);
67
+ }
68
+ throw err;
69
+ }
70
+ async ensureInitialized() {
71
+ if (!this.initPromise) {
72
+ this.initPromise = this.initialize();
73
+ }
74
+ await this.initPromise;
75
+ }
76
+ async initialize() {
77
+ const config = this.config;
78
+ let dbName = config.database;
79
+ let serverConfig = null;
80
+ if (config.url) {
81
+ try {
82
+ const parsed = new URL(config.url);
83
+ dbName = parsed.pathname.replace(/^\//, "");
84
+ const serverUrl = `${parsed.protocol}//${parsed.username}:${parsed.password}@${parsed.host}`;
85
+ serverConfig = serverUrl;
86
+ } catch (err) {
87
+ }
88
+ } else {
89
+ serverConfig = {
90
+ host: config.host ?? "localhost",
91
+ port: config.port ?? 3306,
92
+ user: config.user,
93
+ password: config.password
94
+ };
95
+ }
96
+ if (dbName && serverConfig) {
97
+ try {
98
+ const tempConn = await import_promise.default.createConnection(serverConfig);
99
+ await tempConn.query(`CREATE DATABASE IF NOT EXISTS \`${dbName}\``);
100
+ await tempConn.end();
101
+ console.log(`[dyrected/db-mysql] Database "${dbName}" checked/created successfully`);
102
+ } catch (err) {
103
+ console.warn(`[dyrected/db-mysql] Auto-creation of database "${dbName}" skipped/failed:`, err.message);
104
+ if (err.code === "EADDRNOTAVAIL" || err.message?.includes("EADDRNOTAVAIL")) {
105
+ this.handleConnectionError(err);
106
+ }
107
+ }
108
+ }
42
109
  if (config.url) {
43
110
  this.pool = import_promise.default.createPool(config.url);
44
111
  } else {
@@ -48,26 +115,42 @@ var MysqlAdapter = class {
48
115
  user: config.user,
49
116
  password: config.password,
50
117
  database: config.database,
51
- // Return dates as strings for consistency with other adapters
52
118
  dateStrings: true
53
119
  });
54
120
  }
55
- this.initInternalTables().catch((err) => console.error("[dyrected/db-mysql] Failed to init internal tables:", err));
121
+ try {
122
+ await this.pool.query(`
123
+ CREATE TABLE IF NOT EXISTS dyrected_internal (
124
+ \`key\` VARCHAR(255) PRIMARY KEY,
125
+ value JSON NOT NULL
126
+ )
127
+ `);
128
+ } catch (err) {
129
+ this.handleConnectionError(err);
130
+ }
56
131
  }
57
- async initInternalTables() {
58
- await this.pool.query(`
59
- CREATE TABLE IF NOT EXISTS dyrected_internal (
60
- \`key\` VARCHAR(255) PRIMARY KEY,
61
- value JSON NOT NULL
62
- )
63
- `);
132
+ async query(sql, params) {
133
+ await this.ensureInitialized();
134
+ try {
135
+ return await this.pool.query(sql, params);
136
+ } catch (err) {
137
+ this.handleConnectionError(err);
138
+ }
139
+ }
140
+ async execute(sql, params) {
141
+ await this.ensureInitialized();
142
+ try {
143
+ return await this.pool.execute(sql, params);
144
+ } catch (err) {
145
+ this.handleConnectionError(err);
146
+ }
64
147
  }
65
148
  getTableName(slug) {
66
149
  return `collection_${slug}`;
67
150
  }
68
151
  async ensureTable(slug, fields = []) {
69
152
  const tableName = this.getTableName(slug);
70
- await this.pool.query(`
153
+ await this.query(`
71
154
  CREATE TABLE IF NOT EXISTS \`${tableName}\` (
72
155
  id VARCHAR(36) PRIMARY KEY,
73
156
  data JSON NOT NULL,
@@ -75,7 +158,7 @@ var MysqlAdapter = class {
75
158
  updated_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)
76
159
  )
77
160
  `);
78
- const [cols] = await this.pool.query(`SHOW COLUMNS FROM \`${tableName}\``);
161
+ const [cols] = await this.query(`SHOW COLUMNS FROM \`${tableName}\``);
79
162
  const existingCols = cols.map((c) => c.Field);
80
163
  for (const field of fields) {
81
164
  if (field.promoted && !existingCols.includes(field.name)) {
@@ -83,7 +166,7 @@ var MysqlAdapter = class {
83
166
  let sqlType = "TEXT";
84
167
  if (field.type === "number") sqlType = "DECIMAL(19,4)";
85
168
  if (field.type === "boolean") sqlType = "TINYINT(1)";
86
- await this.pool.query(`ALTER TABLE \`${tableName}\` ADD COLUMN \`${field.name}\` ${sqlType}`);
169
+ await this.query(`ALTER TABLE \`${tableName}\` ADD COLUMN \`${field.name}\` ${sqlType}`);
87
170
  }
88
171
  }
89
172
  }
@@ -93,7 +176,7 @@ var MysqlAdapter = class {
93
176
  const limit = args.limit ?? 10;
94
177
  const page = args.page ?? 1;
95
178
  const offset = (page - 1) * limit;
96
- const [cols] = await this.pool.query(`SHOW COLUMNS FROM \`${tableName}\``);
179
+ const [cols] = await this.query(`SHOW COLUMNS FROM \`${tableName}\``);
97
180
  const existingCols = cols.map((c) => c.Field);
98
181
  let whereSql = "";
99
182
  let whereParams = [];
@@ -113,12 +196,12 @@ var MysqlAdapter = class {
113
196
  }
114
197
  const rawSort = args.sort ?? "created_at DESC";
115
198
  const sort = rawSort.replace(/\bcreatedAt\b/g, "created_at").replace(/\bupdatedAt\b/g, "updated_at");
116
- const [countRows] = await this.pool.query(
199
+ const [countRows] = await this.query(
117
200
  `SELECT COUNT(*) AS total FROM \`${tableName}\` ${whereSql}`,
118
201
  whereParams
119
202
  );
120
203
  const total = Number(countRows[0].total);
121
- const [rows] = await this.pool.query(
204
+ const [rows] = await this.query(
122
205
  `SELECT * FROM \`${tableName}\` ${whereSql} ORDER BY ${sort} LIMIT ? OFFSET ?`,
123
206
  [...whereParams, limit, offset]
124
207
  );
@@ -142,7 +225,7 @@ var MysqlAdapter = class {
142
225
  async findOne(params) {
143
226
  await this.ensureTable(params.collection);
144
227
  const tableName = this.getTableName(params.collection);
145
- const [rows] = await this.pool.query(`SELECT * FROM \`${tableName}\` WHERE id = ?`, [params.id]);
228
+ const [rows] = await this.query(`SELECT * FROM \`${tableName}\` WHERE id = ?`, [params.id]);
146
229
  const row = rows[0];
147
230
  if (!row) return null;
148
231
  return {
@@ -155,7 +238,7 @@ var MysqlAdapter = class {
155
238
  async create(params) {
156
239
  await this.ensureTable(params.collection);
157
240
  const tableName = this.getTableName(params.collection);
158
- const [cols] = await this.pool.query(`SHOW COLUMNS FROM \`${tableName}\``);
241
+ const [cols] = await this.query(`SHOW COLUMNS FROM \`${tableName}\``);
159
242
  const existingCols = cols.map((c) => c.Field);
160
243
  const id = params.data.id ?? Math.random().toString(36).substring(7);
161
244
  const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").replace("Z", "");
@@ -173,13 +256,13 @@ var MysqlAdapter = class {
173
256
  const colNames = ["id", "data", "created_at", "updated_at", ...Object.keys(promotedValues).map((k) => `\`${k}\``)];
174
257
  const placeholders = colNames.map(() => "?").join(", ");
175
258
  const values = [id, JSON.stringify(data), now, now, ...Object.values(promotedValues)];
176
- await this.pool.query(`INSERT INTO \`${tableName}\` (${colNames.join(", ")}) VALUES (${placeholders})`, values);
259
+ await this.query(`INSERT INTO \`${tableName}\` (${colNames.join(", ")}) VALUES (${placeholders})`, values);
177
260
  return { id, ...data, createdAt: now, updatedAt: now };
178
261
  }
179
262
  async update(params) {
180
263
  await this.ensureTable(params.collection);
181
264
  const tableName = this.getTableName(params.collection);
182
- const [cols] = await this.pool.query(`SHOW COLUMNS FROM \`${tableName}\``);
265
+ const [cols] = await this.query(`SHOW COLUMNS FROM \`${tableName}\``);
183
266
  const existingCols = cols.map((c) => c.Field);
184
267
  const existing = await this.findOne({ collection: params.collection, id: params.id });
185
268
  const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").replace("Z", "");
@@ -196,7 +279,7 @@ var MysqlAdapter = class {
196
279
  }
197
280
  const setClauses = ["data = ?", "updated_at = ?", ...Object.keys(promotedValues).map((k) => `\`${k}\` = ?`)];
198
281
  const values = [JSON.stringify(merged), now, ...Object.values(promotedValues), params.id];
199
- await this.pool.query(`UPDATE \`${tableName}\` SET ${setClauses.join(", ")} WHERE id = ?`, values);
282
+ await this.query(`UPDATE \`${tableName}\` SET ${setClauses.join(", ")} WHERE id = ?`, values);
200
283
  return { id: params.id, ...merged, createdAt: existing?.createdAt, updatedAt: now };
201
284
  }
202
285
  async sync(collections) {
@@ -207,10 +290,10 @@ var MysqlAdapter = class {
207
290
  async delete(params) {
208
291
  await this.ensureTable(params.collection);
209
292
  const tableName = this.getTableName(params.collection);
210
- await this.pool.query(`DELETE FROM \`${tableName}\` WHERE id = ?`, [params.id]);
293
+ await this.query(`DELETE FROM \`${tableName}\` WHERE id = ?`, [params.id]);
211
294
  }
212
295
  async getGlobal(params) {
213
- const [rows] = await this.pool.query("SELECT value FROM dyrected_internal WHERE `key` = ?", [
296
+ const [rows] = await this.query("SELECT value FROM dyrected_internal WHERE `key` = ?", [
214
297
  `global_${params.slug}`
215
298
  ]);
216
299
  const row = rows[0];
@@ -218,7 +301,7 @@ var MysqlAdapter = class {
218
301
  return typeof row.value === "string" ? JSON.parse(row.value) : row.value;
219
302
  }
220
303
  async updateGlobal(params) {
221
- await this.pool.execute(
304
+ await this.execute(
222
305
  "INSERT INTO dyrected_internal (`key`, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value = VALUES(value)",
223
306
  [`global_${params.slug}`, JSON.stringify(params.data)]
224
307
  );
@@ -226,7 +309,9 @@ var MysqlAdapter = class {
226
309
  }
227
310
  /** Gracefully close the connection pool. Call on process exit. */
228
311
  async close() {
229
- await this.pool.end();
312
+ if (this.pool) {
313
+ await this.pool.end();
314
+ }
230
315
  }
231
316
  };
232
317
  var mysqlAdapter = (config) => new MysqlAdapter(config);
package/dist/index.d.cts CHANGED
@@ -12,8 +12,14 @@ interface MysqlAdapterConfig {
12
12
  }
13
13
  declare class MysqlAdapter implements DatabaseAdapter {
14
14
  private pool;
15
+ private config;
16
+ private initPromise;
15
17
  constructor(config: MysqlAdapterConfig);
16
- private initInternalTables;
18
+ private handleConnectionError;
19
+ private ensureInitialized;
20
+ private initialize;
21
+ private query;
22
+ execute(sql: string, params?: any[]): Promise<any>;
17
23
  private getTableName;
18
24
  private ensureTable;
19
25
  find(args: {
package/dist/index.d.ts CHANGED
@@ -12,8 +12,14 @@ interface MysqlAdapterConfig {
12
12
  }
13
13
  declare class MysqlAdapter implements DatabaseAdapter {
14
14
  private pool;
15
+ private config;
16
+ private initPromise;
15
17
  constructor(config: MysqlAdapterConfig);
16
- private initInternalTables;
18
+ private handleConnectionError;
19
+ private ensureInitialized;
20
+ private initialize;
21
+ private query;
22
+ execute(sql: string, params?: any[]): Promise<any>;
17
23
  private getTableName;
18
24
  private ensureTable;
19
25
  find(args: {
package/dist/index.js CHANGED
@@ -3,7 +3,74 @@ import { parseSqlWhere } from "@dyrected/core";
3
3
  import mysql from "mysql2/promise";
4
4
  var MysqlAdapter = class {
5
5
  pool;
6
+ config;
7
+ initPromise = null;
6
8
  constructor(config) {
9
+ this.config = config;
10
+ this.ensureInitialized().catch((err) => {
11
+ if (err.code === "EADDRNOTAVAIL" || err.message?.includes("EADDRNOTAVAIL")) {
12
+ this.handleConnectionError(err);
13
+ }
14
+ });
15
+ }
16
+ handleConnectionError(err) {
17
+ if (err && (err.code === "EADDRNOTAVAIL" || err.message?.includes("EADDRNOTAVAIL"))) {
18
+ const customMessage = `
19
+ [dyrected/db-mysql] ERROR: MySQL connection failed with EADDRNOTAVAIL.
20
+ --------------------------------------------------------------------------------
21
+ This error often occurs when:
22
+ 1. 'localhost' is resolved to an IPv6 address (::1) but MySQL is only listening on IPv4 (127.0.0.1).
23
+ 2. The MySQL server is not running or is bound to a different port.
24
+
25
+ FIX INSTRUCTIONS:
26
+ - Try changing your host configuration in '.env' or config from 'localhost' to '127.0.0.1'.
27
+ - Make sure your local MySQL service is active and running on the configured port.
28
+ --------------------------------------------------------------------------------
29
+ `;
30
+ console.error(customMessage);
31
+ throw new Error(`MySQL Connection Failed: EADDRNOTAVAIL. Hint: Try using '127.0.0.1' instead of 'localhost'. Original: ${err.message}`);
32
+ }
33
+ throw err;
34
+ }
35
+ async ensureInitialized() {
36
+ if (!this.initPromise) {
37
+ this.initPromise = this.initialize();
38
+ }
39
+ await this.initPromise;
40
+ }
41
+ async initialize() {
42
+ const config = this.config;
43
+ let dbName = config.database;
44
+ let serverConfig = null;
45
+ if (config.url) {
46
+ try {
47
+ const parsed = new URL(config.url);
48
+ dbName = parsed.pathname.replace(/^\//, "");
49
+ const serverUrl = `${parsed.protocol}//${parsed.username}:${parsed.password}@${parsed.host}`;
50
+ serverConfig = serverUrl;
51
+ } catch (err) {
52
+ }
53
+ } else {
54
+ serverConfig = {
55
+ host: config.host ?? "localhost",
56
+ port: config.port ?? 3306,
57
+ user: config.user,
58
+ password: config.password
59
+ };
60
+ }
61
+ if (dbName && serverConfig) {
62
+ try {
63
+ const tempConn = await mysql.createConnection(serverConfig);
64
+ await tempConn.query(`CREATE DATABASE IF NOT EXISTS \`${dbName}\``);
65
+ await tempConn.end();
66
+ console.log(`[dyrected/db-mysql] Database "${dbName}" checked/created successfully`);
67
+ } catch (err) {
68
+ console.warn(`[dyrected/db-mysql] Auto-creation of database "${dbName}" skipped/failed:`, err.message);
69
+ if (err.code === "EADDRNOTAVAIL" || err.message?.includes("EADDRNOTAVAIL")) {
70
+ this.handleConnectionError(err);
71
+ }
72
+ }
73
+ }
7
74
  if (config.url) {
8
75
  this.pool = mysql.createPool(config.url);
9
76
  } else {
@@ -13,26 +80,42 @@ var MysqlAdapter = class {
13
80
  user: config.user,
14
81
  password: config.password,
15
82
  database: config.database,
16
- // Return dates as strings for consistency with other adapters
17
83
  dateStrings: true
18
84
  });
19
85
  }
20
- this.initInternalTables().catch((err) => console.error("[dyrected/db-mysql] Failed to init internal tables:", err));
86
+ try {
87
+ await this.pool.query(`
88
+ CREATE TABLE IF NOT EXISTS dyrected_internal (
89
+ \`key\` VARCHAR(255) PRIMARY KEY,
90
+ value JSON NOT NULL
91
+ )
92
+ `);
93
+ } catch (err) {
94
+ this.handleConnectionError(err);
95
+ }
21
96
  }
22
- async initInternalTables() {
23
- await this.pool.query(`
24
- CREATE TABLE IF NOT EXISTS dyrected_internal (
25
- \`key\` VARCHAR(255) PRIMARY KEY,
26
- value JSON NOT NULL
27
- )
28
- `);
97
+ async query(sql, params) {
98
+ await this.ensureInitialized();
99
+ try {
100
+ return await this.pool.query(sql, params);
101
+ } catch (err) {
102
+ this.handleConnectionError(err);
103
+ }
104
+ }
105
+ async execute(sql, params) {
106
+ await this.ensureInitialized();
107
+ try {
108
+ return await this.pool.execute(sql, params);
109
+ } catch (err) {
110
+ this.handleConnectionError(err);
111
+ }
29
112
  }
30
113
  getTableName(slug) {
31
114
  return `collection_${slug}`;
32
115
  }
33
116
  async ensureTable(slug, fields = []) {
34
117
  const tableName = this.getTableName(slug);
35
- await this.pool.query(`
118
+ await this.query(`
36
119
  CREATE TABLE IF NOT EXISTS \`${tableName}\` (
37
120
  id VARCHAR(36) PRIMARY KEY,
38
121
  data JSON NOT NULL,
@@ -40,7 +123,7 @@ var MysqlAdapter = class {
40
123
  updated_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)
41
124
  )
42
125
  `);
43
- const [cols] = await this.pool.query(`SHOW COLUMNS FROM \`${tableName}\``);
126
+ const [cols] = await this.query(`SHOW COLUMNS FROM \`${tableName}\``);
44
127
  const existingCols = cols.map((c) => c.Field);
45
128
  for (const field of fields) {
46
129
  if (field.promoted && !existingCols.includes(field.name)) {
@@ -48,7 +131,7 @@ var MysqlAdapter = class {
48
131
  let sqlType = "TEXT";
49
132
  if (field.type === "number") sqlType = "DECIMAL(19,4)";
50
133
  if (field.type === "boolean") sqlType = "TINYINT(1)";
51
- await this.pool.query(`ALTER TABLE \`${tableName}\` ADD COLUMN \`${field.name}\` ${sqlType}`);
134
+ await this.query(`ALTER TABLE \`${tableName}\` ADD COLUMN \`${field.name}\` ${sqlType}`);
52
135
  }
53
136
  }
54
137
  }
@@ -58,7 +141,7 @@ var MysqlAdapter = class {
58
141
  const limit = args.limit ?? 10;
59
142
  const page = args.page ?? 1;
60
143
  const offset = (page - 1) * limit;
61
- const [cols] = await this.pool.query(`SHOW COLUMNS FROM \`${tableName}\``);
144
+ const [cols] = await this.query(`SHOW COLUMNS FROM \`${tableName}\``);
62
145
  const existingCols = cols.map((c) => c.Field);
63
146
  let whereSql = "";
64
147
  let whereParams = [];
@@ -78,12 +161,12 @@ var MysqlAdapter = class {
78
161
  }
79
162
  const rawSort = args.sort ?? "created_at DESC";
80
163
  const sort = rawSort.replace(/\bcreatedAt\b/g, "created_at").replace(/\bupdatedAt\b/g, "updated_at");
81
- const [countRows] = await this.pool.query(
164
+ const [countRows] = await this.query(
82
165
  `SELECT COUNT(*) AS total FROM \`${tableName}\` ${whereSql}`,
83
166
  whereParams
84
167
  );
85
168
  const total = Number(countRows[0].total);
86
- const [rows] = await this.pool.query(
169
+ const [rows] = await this.query(
87
170
  `SELECT * FROM \`${tableName}\` ${whereSql} ORDER BY ${sort} LIMIT ? OFFSET ?`,
88
171
  [...whereParams, limit, offset]
89
172
  );
@@ -107,7 +190,7 @@ var MysqlAdapter = class {
107
190
  async findOne(params) {
108
191
  await this.ensureTable(params.collection);
109
192
  const tableName = this.getTableName(params.collection);
110
- const [rows] = await this.pool.query(`SELECT * FROM \`${tableName}\` WHERE id = ?`, [params.id]);
193
+ const [rows] = await this.query(`SELECT * FROM \`${tableName}\` WHERE id = ?`, [params.id]);
111
194
  const row = rows[0];
112
195
  if (!row) return null;
113
196
  return {
@@ -120,7 +203,7 @@ var MysqlAdapter = class {
120
203
  async create(params) {
121
204
  await this.ensureTable(params.collection);
122
205
  const tableName = this.getTableName(params.collection);
123
- const [cols] = await this.pool.query(`SHOW COLUMNS FROM \`${tableName}\``);
206
+ const [cols] = await this.query(`SHOW COLUMNS FROM \`${tableName}\``);
124
207
  const existingCols = cols.map((c) => c.Field);
125
208
  const id = params.data.id ?? Math.random().toString(36).substring(7);
126
209
  const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").replace("Z", "");
@@ -138,13 +221,13 @@ var MysqlAdapter = class {
138
221
  const colNames = ["id", "data", "created_at", "updated_at", ...Object.keys(promotedValues).map((k) => `\`${k}\``)];
139
222
  const placeholders = colNames.map(() => "?").join(", ");
140
223
  const values = [id, JSON.stringify(data), now, now, ...Object.values(promotedValues)];
141
- await this.pool.query(`INSERT INTO \`${tableName}\` (${colNames.join(", ")}) VALUES (${placeholders})`, values);
224
+ await this.query(`INSERT INTO \`${tableName}\` (${colNames.join(", ")}) VALUES (${placeholders})`, values);
142
225
  return { id, ...data, createdAt: now, updatedAt: now };
143
226
  }
144
227
  async update(params) {
145
228
  await this.ensureTable(params.collection);
146
229
  const tableName = this.getTableName(params.collection);
147
- const [cols] = await this.pool.query(`SHOW COLUMNS FROM \`${tableName}\``);
230
+ const [cols] = await this.query(`SHOW COLUMNS FROM \`${tableName}\``);
148
231
  const existingCols = cols.map((c) => c.Field);
149
232
  const existing = await this.findOne({ collection: params.collection, id: params.id });
150
233
  const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").replace("Z", "");
@@ -161,7 +244,7 @@ var MysqlAdapter = class {
161
244
  }
162
245
  const setClauses = ["data = ?", "updated_at = ?", ...Object.keys(promotedValues).map((k) => `\`${k}\` = ?`)];
163
246
  const values = [JSON.stringify(merged), now, ...Object.values(promotedValues), params.id];
164
- await this.pool.query(`UPDATE \`${tableName}\` SET ${setClauses.join(", ")} WHERE id = ?`, values);
247
+ await this.query(`UPDATE \`${tableName}\` SET ${setClauses.join(", ")} WHERE id = ?`, values);
165
248
  return { id: params.id, ...merged, createdAt: existing?.createdAt, updatedAt: now };
166
249
  }
167
250
  async sync(collections) {
@@ -172,10 +255,10 @@ var MysqlAdapter = class {
172
255
  async delete(params) {
173
256
  await this.ensureTable(params.collection);
174
257
  const tableName = this.getTableName(params.collection);
175
- await this.pool.query(`DELETE FROM \`${tableName}\` WHERE id = ?`, [params.id]);
258
+ await this.query(`DELETE FROM \`${tableName}\` WHERE id = ?`, [params.id]);
176
259
  }
177
260
  async getGlobal(params) {
178
- const [rows] = await this.pool.query("SELECT value FROM dyrected_internal WHERE `key` = ?", [
261
+ const [rows] = await this.query("SELECT value FROM dyrected_internal WHERE `key` = ?", [
179
262
  `global_${params.slug}`
180
263
  ]);
181
264
  const row = rows[0];
@@ -183,7 +266,7 @@ var MysqlAdapter = class {
183
266
  return typeof row.value === "string" ? JSON.parse(row.value) : row.value;
184
267
  }
185
268
  async updateGlobal(params) {
186
- await this.pool.execute(
269
+ await this.execute(
187
270
  "INSERT INTO dyrected_internal (`key`, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value = VALUES(value)",
188
271
  [`global_${params.slug}`, JSON.stringify(params.data)]
189
272
  );
@@ -191,7 +274,9 @@ var MysqlAdapter = class {
191
274
  }
192
275
  /** Gracefully close the connection pool. Call on process exit. */
193
276
  async close() {
194
- await this.pool.end();
277
+ if (this.pool) {
278
+ await this.pool.end();
279
+ }
195
280
  }
196
281
  };
197
282
  var mysqlAdapter = (config) => new MysqlAdapter(config);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dyrected/db-mysql",
3
- "version": "2.5.5",
3
+ "version": "2.5.7",
4
4
  "description": "MySQL adapter for Dyrected CMS",
5
5
  "type": "module",
6
6
  "files": [
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "mysql2": "^3.22.3",
21
- "@dyrected/core": "^2.5.5"
21
+ "@dyrected/core": "^2.5.7"
22
22
  },
23
23
  "devDependencies": {
24
24
  "tsup": "^8.0.0",