@zintrust/db-mysql 0.1.27 → 0.1.41

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.
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@zintrust/db-mysql",
3
- "version": "0.1.15",
4
- "buildDate": "2026-01-28T12:17:02.322Z",
3
+ "version": "0.1.27",
4
+ "buildDate": "2026-02-15T07:16:38.180Z",
5
5
  "buildEnvironment": {
6
6
  "node": "v20.20.0",
7
7
  "platform": "linux",
8
8
  "arch": "x64"
9
9
  },
10
10
  "git": {
11
- "commit": "a274786",
11
+ "commit": "33b681d",
12
12
  "branch": "master"
13
13
  },
14
14
  "package": {
@@ -23,21 +23,29 @@
23
23
  ]
24
24
  },
25
25
  "files": {
26
+ "common.d.ts": {
27
+ "size": 615,
28
+ "sha256": "fafe13a87e5239d41b537dcdf23d7fc84c25d7b34207d272f149cbadfebfb417"
29
+ },
30
+ "common.js": {
31
+ "size": 580,
32
+ "sha256": "71e659214b8f208ec303756a4ed796f9904a5c2d5f6ba71ae03603be3773851c"
33
+ },
26
34
  "index.d.ts": {
27
- "size": 1380,
28
- "sha256": "0e9961f469b7a5a2ab8a2f33eaaa6220b8a9b382e6c552e2a7320399ed9de9f4"
35
+ "size": 1460,
36
+ "sha256": "e3fee6b22d26a931b8a8254267ad5621b1fcf26c606b7749190ee4ccfed24cd3"
29
37
  },
30
38
  "index.js": {
31
- "size": 7548,
32
- "sha256": "0e0c05629b71fe8bf6e271deaa58371da6b31948dc072b796903ab07ce09c416"
39
+ "size": 9907,
40
+ "sha256": "105cdfccd907351f427ee0539384ca640ba51015f46668be4edf6a1838eb5891"
33
41
  },
34
42
  "register.d.ts": {
35
43
  "size": 180,
36
44
  "sha256": "1ac7cca6cfbda8e5a65153917d4bbb4dd4fbe309dcabf9d9bdfb1eea6e97e52e"
37
45
  },
38
46
  "register.js": {
39
- "size": 1063,
40
- "sha256": "11fa6c4311766321ac9bd080ea6234756dd2fffcd767e5e69cea44bd9e8ea8fd"
47
+ "size": 1066,
48
+ "sha256": "776afb1a7728d8448454a5aee172ce123d81ccf0619cf0228578d55e10697b62"
41
49
  }
42
50
  }
43
51
  }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Common constants and utilities for MySQL adapters
3
+ */
4
+ export declare const CREATE_MIGRATIONS_TABLE_SQL = "\nCREATE TABLE IF NOT EXISTS migrations (\n id BIGINT PRIMARY KEY AUTO_INCREMENT,\n name VARCHAR(255) NOT NULL,\n scope VARCHAR(255) NOT NULL DEFAULT 'global',\n service VARCHAR(255) NOT NULL DEFAULT '',\n batch INTEGER NOT NULL,\n status VARCHAR(255) NOT NULL,\n applied_at DATETIME NULL,\n created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n UNIQUE(name, scope, service)\n )";
5
+ export declare const MYSQL_PLACEHOLDER = "?";
6
+ export declare const MYSQL_TYPE = "mysql";
package/dist/common.js ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Common constants and utilities for MySQL adapters
3
+ */
4
+ export const CREATE_MIGRATIONS_TABLE_SQL = `
5
+ CREATE TABLE IF NOT EXISTS migrations (
6
+ id BIGINT PRIMARY KEY AUTO_INCREMENT,
7
+ name VARCHAR(255) NOT NULL,
8
+ scope VARCHAR(255) NOT NULL DEFAULT 'global',
9
+ service VARCHAR(255) NOT NULL DEFAULT '',
10
+ batch INTEGER NOT NULL,
11
+ status VARCHAR(255) NOT NULL,
12
+ applied_at DATETIME NULL,
13
+ created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
14
+ UNIQUE(name, scope, service)
15
+ )`;
16
+ export const MYSQL_PLACEHOLDER = '?';
17
+ export const MYSQL_TYPE = 'mysql';
package/dist/index.d.ts CHANGED
@@ -1,12 +1,15 @@
1
1
  export type DatabaseConfig = {
2
2
  driver: 'sqlite' | 'postgresql' | 'mysql' | 'sqlserver' | 'd1';
3
3
  database?: string;
4
+ connectionString?: string;
4
5
  host?: string;
5
6
  port?: number;
6
7
  username?: string;
7
8
  password?: string;
8
9
  synchronize?: boolean;
9
10
  logging?: boolean;
11
+ ssl?: boolean;
12
+ socketTimeoutMs?: number;
10
13
  readHosts?: string[];
11
14
  };
12
15
  export type QueryResult = {
package/dist/index.js CHANGED
@@ -1,4 +1,9 @@
1
- import { ErrorFactory, FeatureFlags, Logger, QueryBuilder } from '@zintrust/core';
1
+ import { Cloudflare, ErrorFactory, FeatureFlags, Logger, QueryBuilder } from '@zintrust/core';
2
+ import { CREATE_MIGRATIONS_TABLE_SQL, MYSQL_PLACEHOLDER, MYSQL_TYPE } from './common.js';
3
+ const getInjectedMysqlModule = () => {
4
+ const globalAny = globalThis;
5
+ return globalAny.__zintrustMysqlModule;
6
+ };
2
7
  function isMissingEsmPackage(error, packageName) {
3
8
  if (error === null || typeof error !== 'object')
4
9
  return false;
@@ -13,9 +18,37 @@ function isMissingEsmPackage(error, packageName) {
13
18
  return false;
14
19
  }
15
20
  async function loadMysql() {
21
+ const injected = getInjectedMysqlModule();
22
+ if (injected)
23
+ return injected;
16
24
  return (await import('mysql2/promise'));
17
25
  }
26
+ async function loadCloudflareSocketFactory() {
27
+ try {
28
+ const { CloudflareSocket } = await import('@zintrust/core');
29
+ return ({ host, port, tls, timeoutMs }) => CloudflareSocket.create(host, port, { tls, timeoutMs });
30
+ }
31
+ catch (error) {
32
+ throw ErrorFactory.createConfigError('Cloudflare Workers socket support requires cloudflare:sockets compatibility (set compatibility_date >= 2024-01-15).', error);
33
+ }
34
+ }
18
35
  function getConnectionParams(config) {
36
+ if (config.connectionString !== undefined && config.connectionString.trim() !== '') {
37
+ try {
38
+ const url = new URL(config.connectionString);
39
+ const database = url.pathname.replace(/^\//, '') || 'mysql';
40
+ return {
41
+ host: url.hostname || 'localhost',
42
+ port: url.port ? Number.parseInt(url.port, 10) : 3306,
43
+ database,
44
+ user: decodeURIComponent(url.username || 'root'),
45
+ password: decodeURIComponent(url.password || ''),
46
+ };
47
+ }
48
+ catch (error) {
49
+ throw ErrorFactory.createConfigError('Invalid MySQL connection string', error);
50
+ }
51
+ }
19
52
  return {
20
53
  host: config.host ?? 'localhost',
21
54
  port: config.port ?? 3306,
@@ -62,20 +95,49 @@ async function connect(state, config) {
62
95
  try {
63
96
  const mysql = await loadMysql();
64
97
  const { host, port, database, user, password } = getConnectionParams(config);
65
- state.pool = mysql.createPool({
66
- host,
67
- port,
68
- database,
69
- user,
70
- password,
71
- waitForConnections: true,
72
- connectionLimit: 10,
73
- namedPlaceholders: false,
74
- });
98
+ const isWorkersRuntime = Cloudflare.getWorkersEnv() !== null;
99
+ const tlsEnabled = Boolean(config.ssl);
100
+ let timeoutMs;
101
+ if (typeof config.socketTimeoutMs === 'number' && config.socketTimeoutMs > 0) {
102
+ timeoutMs = config.socketTimeoutMs;
103
+ }
104
+ else {
105
+ timeoutMs = 30000; // default 30s
106
+ }
107
+ if (isWorkersRuntime) {
108
+ if (!Cloudflare.isCloudflareSocketsEnabled()) {
109
+ throw ErrorFactory.createConfigError('Cloudflare sockets are disabled. Set ENABLE_CLOUDFLARE_SOCKETS=true to use MySQL sockets on Workers.');
110
+ }
111
+ const createSocket = await loadCloudflareSocketFactory();
112
+ state.pool = mysql.createPool({
113
+ host,
114
+ port,
115
+ database,
116
+ user,
117
+ password,
118
+ waitForConnections: true,
119
+ connectionLimit: 10,
120
+ namedPlaceholders: false,
121
+ disableEval: true,
122
+ stream: () => createSocket({ host, port, tls: tlsEnabled, timeoutMs }),
123
+ });
124
+ }
125
+ else {
126
+ state.pool = mysql.createPool({
127
+ host,
128
+ port,
129
+ database,
130
+ user,
131
+ password,
132
+ waitForConnections: true,
133
+ connectionLimit: 10,
134
+ namedPlaceholders: false,
135
+ });
136
+ }
75
137
  // Probe.
76
138
  await state.pool.execute('SELECT 1');
77
139
  state.connected = true;
78
- Logger.info(`✓ MySQL connected (${host}:${port})`);
140
+ Logger.info(`✓ Cloudflare sockets MySQL connected (${host}:${port})`);
79
141
  }
80
142
  catch (error) {
81
143
  if (isMissingEsmPackage(error, 'mysql2')) {
@@ -114,6 +176,28 @@ async function rawQuery(state, sql, parameters) {
114
176
  throw ErrorFactory.createTryCatchError(`Raw SQL query failed: ${sql}`, error);
115
177
  }
116
178
  }
179
+ const createTransactionAdapter = (baseAdapter, conn) => {
180
+ return {
181
+ ...baseAdapter,
182
+ query: async (sql, parameters) => {
183
+ try {
184
+ const connection = conn;
185
+ const [rows] = await connection.execute(sql, parameters);
186
+ return normalizeQueryResult(rows);
187
+ }
188
+ catch (error) {
189
+ throw ErrorFactory.createTryCatchError(`MySQL query failed: ${sql}`, error);
190
+ }
191
+ },
192
+ queryOne: async (sql, parameters) => {
193
+ const res = await baseAdapter.query(sql, parameters);
194
+ return res.rows[0] ?? null;
195
+ },
196
+ };
197
+ };
198
+ const createMigrationsTable = async (adapter) => {
199
+ await adapter.query(CREATE_MIGRATIONS_TABLE_SQL, []);
200
+ };
117
201
  function createMySqlAdapter(config) {
118
202
  const state = { connected: false };
119
203
  const adapter = {
@@ -139,22 +223,7 @@ function createMySqlAdapter(config) {
139
223
  transaction: async (callback) => {
140
224
  const pool = ensurePool(state);
141
225
  const conn = await pool.getConnection();
142
- const txAdapter = {
143
- ...adapter,
144
- query: async (sql, parameters) => {
145
- try {
146
- const [rows] = await conn.execute(sql, parameters);
147
- return normalizeQueryResult(rows);
148
- }
149
- catch (error) {
150
- throw ErrorFactory.createTryCatchError(`MySQL query failed: ${sql}`, error);
151
- }
152
- },
153
- queryOne: async (sql, parameters) => {
154
- const res = await txAdapter.query(sql, parameters);
155
- return res.rows[0] ?? null;
156
- },
157
- };
226
+ const txAdapter = createTransactionAdapter(adapter, conn);
158
227
  try {
159
228
  await conn.beginTransaction();
160
229
  const result = await callback(txAdapter);
@@ -175,22 +244,12 @@ function createMySqlAdapter(config) {
175
244
  }
176
245
  },
177
246
  ensureMigrationsTable: async () => {
178
- await adapter.query(`CREATE TABLE IF NOT EXISTS migrations (
179
- id BIGINT PRIMARY KEY AUTO_INCREMENT,
180
- name VARCHAR(255) NOT NULL,
181
- scope VARCHAR(255) NOT NULL DEFAULT 'global',
182
- service VARCHAR(255) NOT NULL DEFAULT '',
183
- batch INTEGER NOT NULL,
184
- status VARCHAR(255) NOT NULL,
185
- applied_at DATETIME NULL,
186
- created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
187
- UNIQUE(name, scope, service)
188
- )`, []);
247
+ await createMigrationsTable(adapter);
189
248
  },
190
- getType: () => 'mysql',
249
+ getType: () => MYSQL_TYPE,
191
250
  isConnected: () => state.connected,
192
251
  rawQuery: async (sql, parameters) => rawQuery(state, sql, parameters),
193
- getPlaceholder: (_index) => '?',
252
+ getPlaceholder: (_index) => MYSQL_PLACEHOLDER,
194
253
  };
195
254
  return adapter;
196
255
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zintrust/db-mysql",
3
- "version": "0.1.27",
3
+ "version": "0.1.41",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "node": ">=20.0.0"
23
23
  },
24
24
  "peerDependencies": {
25
- "@zintrust/core": "^0.1.27"
25
+ "@zintrust/core": "^0.1.41"
26
26
  },
27
27
  "publishConfig": {
28
28
  "access": "public"