@powersync/service-module-mysql 0.0.0-dev-20260223080959 → 0.0.0-dev-20260224151854

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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @powersync/service-module-mysql
2
2
 
3
- ## 0.0.0-dev-20260223080959
3
+ ## 0.0.0-dev-20260224151854
4
4
 
5
5
  ### Minor Changes
6
6
 
@@ -8,14 +8,21 @@
8
8
 
9
9
  ### Patch Changes
10
10
 
11
+ - 15aea77: Support connection parameters via database URL query string. PostgreSQL supports `connect_timeout`. MongoDB supports `connectTimeoutMS`, `socketTimeoutMS`, `serverSelectionTimeoutMS`, `maxPoolSize`, `maxIdleTimeMS`. MySQL supports `connectTimeout`, `connectionLimit`, `queueLimit`.
11
12
  - Updated dependencies [0998251]
13
+ - Updated dependencies [65f3c89]
12
14
  - Updated dependencies [1c45667]
15
+ - Updated dependencies [8785a3f]
13
16
  - Updated dependencies [8a4c34e]
17
+ - Updated dependencies [b440093]
18
+ - Updated dependencies [d7ff4ad]
14
19
  - Updated dependencies [8bd83e8]
15
- - @powersync/service-core@0.0.0-dev-20260223080959
16
- - @powersync/service-types@0.0.0-dev-20260223080959
17
- - @powersync/service-sync-rules@0.0.0-dev-20260223080959
18
- - @powersync/lib-services-framework@0.0.0-dev-20260223080959
20
+ - Updated dependencies [79a9729]
21
+ - Updated dependencies [5edd95f]
22
+ - @powersync/service-core@0.0.0-dev-20260224151854
23
+ - @powersync/service-types@0.0.0-dev-20260224151854
24
+ - @powersync/service-sync-rules@0.0.0-dev-20260224151854
25
+ - @powersync/lib-services-framework@0.0.0-dev-20260224151854
19
26
 
20
27
  ## 0.10.2
21
28
 
@@ -1,6 +1,17 @@
1
1
  import { LookupFunction } from 'node:net';
2
2
  import * as t from 'ts-codec';
3
3
  export declare const MYSQL_CONNECTION_TYPE: "mysql";
4
+ /**
5
+ * Connection parameters that can be parsed from the MySQL URI query string.
6
+ *
7
+ * All values are in milliseconds (for timeouts) or counts (for limits).
8
+ * MySQL uses camelCase naming convention.
9
+ */
10
+ export interface MySQLConnectionParams {
11
+ connectTimeout?: number;
12
+ connectionLimit?: number;
13
+ queueLimit?: number;
14
+ }
4
15
  export interface NormalizedMySQLConnectionConfig {
5
16
  id: string;
6
17
  tag: string;
@@ -15,6 +26,7 @@ export interface NormalizedMySQLConnectionConfig {
15
26
  client_private_key?: string;
16
27
  lookup?: LookupFunction;
17
28
  binlog_queue_memory_limit: number;
29
+ connectionParams: MySQLConnectionParams;
18
30
  }
19
31
  export declare const MySQLConnectionConfig: t.Intersection<t.Codec<{
20
32
  type: string;
@@ -55,3 +67,16 @@ export type ResolvedConnectionConfig = MySQLConnectionConfig & NormalizedMySQLCo
55
67
  * Returns destructured options.
56
68
  */
57
69
  export declare function normalizeConnectionConfig(options: MySQLConnectionConfig): NormalizedMySQLConnectionConfig;
70
+ /**
71
+ * Parse a single numeric connection parameter from a URI query string value.
72
+ *
73
+ * Returns undefined if the value is missing, not a valid number, NaN, negative, zero, or Infinity.
74
+ */
75
+ export declare function parseMySQLConnectionParam(value: string | null | undefined): number | undefined;
76
+ /**
77
+ * Parse connection parameters from a MySQL URI's query string.
78
+ *
79
+ * MySQL uses camelCase naming convention.
80
+ * Invalid values (NaN, negative, non-numeric) are silently ignored.
81
+ */
82
+ export declare function parseMySQLConnectionParams(searchParams: URLSearchParams | undefined): MySQLConnectionParams;
@@ -54,6 +54,9 @@ export function normalizeConnectionConfig(options) {
54
54
  throw new ServiceError(ErrorCode.PSYNC_S1105, `MySQL connection: database required`);
55
55
  }
56
56
  const lookup = makeHostnameLookupFunction(hostname, { reject_ip_ranges: options.reject_ip_ranges ?? [] });
57
+ // Parse connection parameters from URL query string
58
+ const uriQuery = uri.query ? new URLSearchParams(uri.query) : undefined;
59
+ const connectionParams = parseMySQLConnectionParams(uriQuery);
57
60
  return {
58
61
  id: options.id ?? 'default',
59
62
  tag: options.tag ?? 'default',
@@ -65,7 +68,48 @@ export function normalizeConnectionConfig(options) {
65
68
  server_id: options.server_id ?? 1,
66
69
  // Binlog processing queue memory limit before throttling is applied.
67
70
  binlog_queue_memory_limit: options.binlog_queue_memory_limit ?? 50,
68
- lookup
71
+ lookup,
72
+ connectionParams
69
73
  };
70
74
  }
75
+ /**
76
+ * Parse a single numeric connection parameter from a URI query string value.
77
+ *
78
+ * Returns undefined if the value is missing, not a valid number, NaN, negative, zero, or Infinity.
79
+ */
80
+ export function parseMySQLConnectionParam(value) {
81
+ if (value == null) {
82
+ return undefined;
83
+ }
84
+ const parsed = Number(value);
85
+ if (isFinite(parsed) && parsed > 0) {
86
+ return parsed;
87
+ }
88
+ return undefined;
89
+ }
90
+ /**
91
+ * Parse connection parameters from a MySQL URI's query string.
92
+ *
93
+ * MySQL uses camelCase naming convention.
94
+ * Invalid values (NaN, negative, non-numeric) are silently ignored.
95
+ */
96
+ export function parseMySQLConnectionParams(searchParams) {
97
+ const params = {};
98
+ if (searchParams == null) {
99
+ return params;
100
+ }
101
+ const connectTimeout = parseMySQLConnectionParam(searchParams.get('connectTimeout'));
102
+ if (connectTimeout != null) {
103
+ params.connectTimeout = connectTimeout;
104
+ }
105
+ const connectionLimit = parseMySQLConnectionParam(searchParams.get('connectionLimit'));
106
+ if (connectionLimit != null) {
107
+ params.connectionLimit = connectionLimit;
108
+ }
109
+ const queueLimit = parseMySQLConnectionParam(searchParams.get('queueLimit'));
110
+ if (queueLimit != null) {
111
+ params.queueLimit = queueLimit;
112
+ }
113
+ return params;
114
+ }
71
115
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types/types.ts"],"names":[],"mappings":"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"}
@@ -26,6 +26,8 @@ export function createPool(config, options) {
26
26
  cert: config.client_certificate
27
27
  };
28
28
  const hasSSLOptions = Object.values(sslOptions).some((v) => !!v);
29
+ // URL connection parameters provide defaults; explicit options take precedence
30
+ const params = config.connectionParams;
29
31
  // TODO: Use config.lookup for DNS resolution
30
32
  return mysql.createPool({
31
33
  host: config.hostname,
@@ -39,6 +41,10 @@ export function createPool(config, options) {
39
41
  timezone: 'Z', // Ensure no auto timezone manipulation of the dates occur
40
42
  jsonStrings: true, // Return JSON columns as strings
41
43
  dateStrings: true, // We parse and format them ourselves
44
+ // Apply URL connection parameters (explicit options override these via spread below)
45
+ ...(params.connectTimeout != null ? { connectTimeout: params.connectTimeout } : {}),
46
+ ...(params.connectionLimit != null ? { connectionLimit: params.connectionLimit } : {}),
47
+ ...(params.queueLimit != null ? { queueLimit: params.queueLimit } : {}),
42
48
  ...(options || {})
43
49
  });
44
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mysql-utils.js","sourceRoot":"","sources":["../../src/utils/mysql-utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mysql-utils.js","sourceRoot":"","sources":["../../src/utils/mysql-utils.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@powersync/service-module-mysql",
3
3
  "repository": "https://github.com/powersync-ja/powersync-service",
4
4
  "types": "dist/index.d.ts",
5
- "version": "0.0.0-dev-20260223080959",
5
+ "version": "0.0.0-dev-20260224151854",
6
6
  "license": "FSL-1.1-ALv2",
7
7
  "main": "dist/index.js",
8
8
  "type": "module",
@@ -30,18 +30,18 @@
30
30
  "ts-codec": "^1.3.0",
31
31
  "uri-js": "^4.4.1",
32
32
  "uuid": "^11.1.0",
33
- "@powersync/lib-services-framework": "0.0.0-dev-20260223080959",
34
- "@powersync/service-core": "0.0.0-dev-20260223080959",
35
- "@powersync/service-sync-rules": "0.0.0-dev-20260223080959",
36
- "@powersync/service-types": "0.0.0-dev-20260223080959",
33
+ "@powersync/lib-services-framework": "0.0.0-dev-20260224151854",
34
+ "@powersync/service-core": "0.0.0-dev-20260224151854",
35
+ "@powersync/service-sync-rules": "0.0.0-dev-20260224151854",
36
+ "@powersync/service-types": "0.0.0-dev-20260224151854",
37
37
  "@powersync/service-jsonbig": "0.17.12"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/async": "^3.2.24",
41
41
  "@types/semver": "^7.7.1",
42
- "@powersync/service-core-tests": "0.0.0-dev-20260223080959",
43
- "@powersync/service-module-mongodb-storage": "0.0.0-dev-20260223080959",
44
- "@powersync/service-module-postgres-storage": "0.0.0-dev-20260223080959"
42
+ "@powersync/service-core-tests": "0.0.0-dev-20260224151854",
43
+ "@powersync/service-module-mongodb-storage": "0.0.0-dev-20260224151854",
44
+ "@powersync/service-module-postgres-storage": "0.0.0-dev-20260224151854"
45
45
  },
46
46
  "scripts": {
47
47
  "build": "tsc -b",
@@ -6,6 +6,18 @@ import * as urijs from 'uri-js';
6
6
 
7
7
  export const MYSQL_CONNECTION_TYPE = 'mysql' as const;
8
8
 
9
+ /**
10
+ * Connection parameters that can be parsed from the MySQL URI query string.
11
+ *
12
+ * All values are in milliseconds (for timeouts) or counts (for limits).
13
+ * MySQL uses camelCase naming convention.
14
+ */
15
+ export interface MySQLConnectionParams {
16
+ connectTimeout?: number;
17
+ connectionLimit?: number;
18
+ queueLimit?: number;
19
+ }
20
+
9
21
  export interface NormalizedMySQLConnectionConfig {
10
22
  id: string;
11
23
  tag: string;
@@ -25,6 +37,8 @@ export interface NormalizedMySQLConnectionConfig {
25
37
  lookup?: LookupFunction;
26
38
 
27
39
  binlog_queue_memory_limit: number;
40
+
41
+ connectionParams: MySQLConnectionParams;
28
42
  }
29
43
 
30
44
  export const MySQLConnectionConfig = service_types.configFile.DataSourceConfig.and(
@@ -105,6 +119,10 @@ export function normalizeConnectionConfig(options: MySQLConnectionConfig): Norma
105
119
 
106
120
  const lookup = makeHostnameLookupFunction(hostname, { reject_ip_ranges: options.reject_ip_ranges ?? [] });
107
121
 
122
+ // Parse connection parameters from URL query string
123
+ const uriQuery = uri.query ? new URLSearchParams(uri.query) : undefined;
124
+ const connectionParams = parseMySQLConnectionParams(uriQuery);
125
+
108
126
  return {
109
127
  id: options.id ?? 'default',
110
128
  tag: options.tag ?? 'default',
@@ -121,6 +139,55 @@ export function normalizeConnectionConfig(options: MySQLConnectionConfig): Norma
121
139
  // Binlog processing queue memory limit before throttling is applied.
122
140
  binlog_queue_memory_limit: options.binlog_queue_memory_limit ?? 50,
123
141
 
124
- lookup
142
+ lookup,
143
+
144
+ connectionParams
125
145
  };
126
146
  }
147
+
148
+ /**
149
+ * Parse a single numeric connection parameter from a URI query string value.
150
+ *
151
+ * Returns undefined if the value is missing, not a valid number, NaN, negative, zero, or Infinity.
152
+ */
153
+ export function parseMySQLConnectionParam(value: string | null | undefined): number | undefined {
154
+ if (value == null) {
155
+ return undefined;
156
+ }
157
+ const parsed = Number(value);
158
+ if (isFinite(parsed) && parsed > 0) {
159
+ return parsed;
160
+ }
161
+ return undefined;
162
+ }
163
+
164
+ /**
165
+ * Parse connection parameters from a MySQL URI's query string.
166
+ *
167
+ * MySQL uses camelCase naming convention.
168
+ * Invalid values (NaN, negative, non-numeric) are silently ignored.
169
+ */
170
+ export function parseMySQLConnectionParams(searchParams: URLSearchParams | undefined): MySQLConnectionParams {
171
+ const params: MySQLConnectionParams = {};
172
+
173
+ if (searchParams == null) {
174
+ return params;
175
+ }
176
+
177
+ const connectTimeout = parseMySQLConnectionParam(searchParams.get('connectTimeout'));
178
+ if (connectTimeout != null) {
179
+ params.connectTimeout = connectTimeout;
180
+ }
181
+
182
+ const connectionLimit = parseMySQLConnectionParam(searchParams.get('connectionLimit'));
183
+ if (connectionLimit != null) {
184
+ params.connectionLimit = connectionLimit;
185
+ }
186
+
187
+ const queueLimit = parseMySQLConnectionParam(searchParams.get('queueLimit'));
188
+ if (queueLimit != null) {
189
+ params.queueLimit = queueLimit;
190
+ }
191
+
192
+ return params;
193
+ }
@@ -37,6 +37,10 @@ export function createPool(config: types.NormalizedMySQLConnectionConfig, option
37
37
  cert: config.client_certificate
38
38
  };
39
39
  const hasSSLOptions = Object.values(sslOptions).some((v) => !!v);
40
+
41
+ // URL connection parameters provide defaults; explicit options take precedence
42
+ const params = config.connectionParams;
43
+
40
44
  // TODO: Use config.lookup for DNS resolution
41
45
  return mysql.createPool({
42
46
  host: config.hostname,
@@ -50,6 +54,10 @@ export function createPool(config: types.NormalizedMySQLConnectionConfig, option
50
54
  timezone: 'Z', // Ensure no auto timezone manipulation of the dates occur
51
55
  jsonStrings: true, // Return JSON columns as strings
52
56
  dateStrings: true, // We parse and format them ourselves
57
+ // Apply URL connection parameters (explicit options override these via spread below)
58
+ ...(params.connectTimeout != null ? { connectTimeout: params.connectTimeout } : {}),
59
+ ...(params.connectionLimit != null ? { connectionLimit: params.connectionLimit } : {}),
60
+ ...(params.queueLimit != null ? { queueLimit: params.queueLimit } : {}),
53
61
  ...(options || {})
54
62
  });
55
63
  }
@@ -0,0 +1,165 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import {
3
+ normalizeConnectionConfig,
4
+ parseMySQLConnectionParam,
5
+ parseMySQLConnectionParams
6
+ } from '@module/types/types.js';
7
+
8
+ describe('config', () => {
9
+ test('Should resolve database', () => {
10
+ const normalized = normalizeConnectionConfig({
11
+ type: 'mysql',
12
+ uri: 'mysql://user:pass@localhost:3306/mydb'
13
+ });
14
+ expect(normalized.database).equals('mydb');
15
+ });
16
+
17
+ describe('connection parameters', () => {
18
+ test('parses all connection parameters from URL query string', () => {
19
+ const normalized = normalizeConnectionConfig({
20
+ type: 'mysql',
21
+ uri: 'mysql://user:pass@localhost:3306/mydb?connectTimeout=5000&connectionLimit=20&queueLimit=100'
22
+ });
23
+ expect(normalized.connectionParams.connectTimeout).equals(5000);
24
+ expect(normalized.connectionParams.connectionLimit).equals(20);
25
+ expect(normalized.connectionParams.queueLimit).equals(100);
26
+ });
27
+
28
+ test('URL without connection parameters returns empty connectionParams', () => {
29
+ const normalized = normalizeConnectionConfig({
30
+ type: 'mysql',
31
+ uri: 'mysql://user:pass@localhost:3306/mydb'
32
+ });
33
+ expect(normalized.connectionParams).toEqual({});
34
+ });
35
+
36
+ test('parameters can be partially specified', () => {
37
+ const normalized = normalizeConnectionConfig({
38
+ type: 'mysql',
39
+ uri: 'mysql://user:pass@localhost:3306/mydb?connectTimeout=5000&queueLimit=50'
40
+ });
41
+ expect(normalized.connectionParams.connectTimeout).equals(5000);
42
+ expect(normalized.connectionParams.queueLimit).equals(50);
43
+ expect(normalized.connectionParams.connectionLimit).toBeUndefined();
44
+ });
45
+
46
+ test('ignores invalid (non-numeric) connection parameter values', () => {
47
+ const normalized = normalizeConnectionConfig({
48
+ type: 'mysql',
49
+ uri: 'mysql://user:pass@localhost:3306/mydb?connectTimeout=abc&connectionLimit=xyz'
50
+ });
51
+ expect(normalized.connectionParams.connectTimeout).toBeUndefined();
52
+ expect(normalized.connectionParams.connectionLimit).toBeUndefined();
53
+ });
54
+
55
+ test('ignores negative connection parameter values', () => {
56
+ const normalized = normalizeConnectionConfig({
57
+ type: 'mysql',
58
+ uri: 'mysql://user:pass@localhost:3306/mydb?connectTimeout=-5000&connectionLimit=-10'
59
+ });
60
+ expect(normalized.connectionParams.connectTimeout).toBeUndefined();
61
+ expect(normalized.connectionParams.connectionLimit).toBeUndefined();
62
+ });
63
+
64
+ test('ignores zero connection parameter values', () => {
65
+ const normalized = normalizeConnectionConfig({
66
+ type: 'mysql',
67
+ uri: 'mysql://user:pass@localhost:3306/mydb?connectTimeout=0&connectionLimit=0&queueLimit=0'
68
+ });
69
+ expect(normalized.connectionParams.connectTimeout).toBeUndefined();
70
+ expect(normalized.connectionParams.connectionLimit).toBeUndefined();
71
+ expect(normalized.connectionParams.queueLimit).toBeUndefined();
72
+ });
73
+
74
+ test('works without URI (config-only)', () => {
75
+ const normalized = normalizeConnectionConfig({
76
+ type: 'mysql',
77
+ hostname: 'localhost',
78
+ port: 3306,
79
+ database: 'mydb',
80
+ username: 'user',
81
+ password: 'pass'
82
+ });
83
+ expect(normalized.connectionParams).toEqual({});
84
+ });
85
+ });
86
+ });
87
+
88
+ describe('parseMySQLConnectionParam', () => {
89
+ test('returns undefined when no value provided', () => {
90
+ expect(parseMySQLConnectionParam(undefined)).toBeUndefined();
91
+ expect(parseMySQLConnectionParam(null)).toBeUndefined();
92
+ });
93
+
94
+ test('parses valid numeric string', () => {
95
+ expect(parseMySQLConnectionParam('5000')).equals(5000);
96
+ });
97
+
98
+ test('parses fractional values', () => {
99
+ expect(parseMySQLConnectionParam('1500.5')).equals(1500.5);
100
+ });
101
+
102
+ test('ignores non-numeric string', () => {
103
+ expect(parseMySQLConnectionParam('abc')).toBeUndefined();
104
+ });
105
+
106
+ test('ignores empty string', () => {
107
+ expect(parseMySQLConnectionParam('')).toBeUndefined();
108
+ });
109
+
110
+ test('ignores negative value', () => {
111
+ expect(parseMySQLConnectionParam('-5000')).toBeUndefined();
112
+ });
113
+
114
+ test('ignores zero', () => {
115
+ expect(parseMySQLConnectionParam('0')).toBeUndefined();
116
+ });
117
+
118
+ test('ignores Infinity', () => {
119
+ expect(parseMySQLConnectionParam('Infinity')).toBeUndefined();
120
+ });
121
+
122
+ test('ignores NaN', () => {
123
+ expect(parseMySQLConnectionParam('NaN')).toBeUndefined();
124
+ });
125
+ });
126
+
127
+ describe('parseMySQLConnectionParams', () => {
128
+ test('parses all supported parameters', () => {
129
+ const params = new URLSearchParams('connectTimeout=5000&connectionLimit=20&queueLimit=100');
130
+ const result = parseMySQLConnectionParams(params);
131
+ expect(result).toEqual({
132
+ connectTimeout: 5000,
133
+ connectionLimit: 20,
134
+ queueLimit: 100
135
+ });
136
+ });
137
+
138
+ test('returns empty object when no connection params present', () => {
139
+ const params = new URLSearchParams('someOther=value');
140
+ const result = parseMySQLConnectionParams(params);
141
+ expect(result).toEqual({});
142
+ });
143
+
144
+ test('returns empty object for undefined searchParams', () => {
145
+ const result = parseMySQLConnectionParams(undefined);
146
+ expect(result).toEqual({});
147
+ });
148
+
149
+ test('ignores invalid values and only includes valid ones', () => {
150
+ const params = new URLSearchParams('connectTimeout=5000&connectionLimit=abc&queueLimit=-10');
151
+ const result = parseMySQLConnectionParams(params);
152
+ expect(result).toEqual({
153
+ connectTimeout: 5000
154
+ });
155
+ });
156
+
157
+ test('handles partial parameter specification', () => {
158
+ const params = new URLSearchParams('connectTimeout=5000&queueLimit=100');
159
+ const result = parseMySQLConnectionParams(params);
160
+ expect(result).toEqual({
161
+ connectTimeout: 5000,
162
+ queueLimit: 100
163
+ });
164
+ });
165
+ });