mysql2-core 0.3.2 → 0.3.4

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/README.md CHANGED
@@ -1 +1,608 @@
1
- # mysql2-core
1
+ # mysql2-core
2
+
3
+ A lightweight MySQL database adapter built on top of **mysql2** for the **SQL Repository** framework.
4
+
5
+ This library provides connection management, transaction handling, query execution, object mapping, batch operations, streaming, exporting, and health checking while remaining completely independent from SQL generation.
6
+
7
+ Unlike traditional ORMs, this library **does not build SQL**. Instead, it executes SQL generated by the SQL Repository library (or any SQL source) and provides a clean, type-safe runtime layer.
8
+
9
+ ---
10
+
11
+ # Philosophy
12
+
13
+ This library has one responsibility:
14
+
15
+ > **Execute SQL efficiently.**
16
+
17
+ It intentionally separates SQL execution from SQL generation.
18
+
19
+ ```
20
+ Application
21
+ │
22
+ ▼
23
+ SQL Repository Library
24
+ (SQL Generation)
25
+ │
26
+ ▼
27
+ Executor Interface
28
+ │
29
+ ▼
30
+ MySQL Adapter
31
+ │
32
+ ▼
33
+ mysql2
34
+ │
35
+ ▼
36
+ MySQL
37
+ ```
38
+
39
+ This separation makes the entire stack easier to maintain, test, and extend.
40
+
41
+ ---
42
+
43
+ # Features
44
+
45
+ - Built on top of **mysql2**
46
+ - Connection Pool Management
47
+ - Transaction Management
48
+ - Query Execution
49
+ - Command Execution
50
+ - Batch Execution
51
+ - Streaming Query Results
52
+ - Bulk Data Import
53
+ - CSV/Data Export
54
+ - Object Mapping
55
+ - Boolean Conversion
56
+ - Database Health Check
57
+ - Promise-based API
58
+ - Repository Friendly
59
+ - Zero ORM Dependencies
60
+
61
+ ---
62
+
63
+ # Why Another MySQL Library?
64
+
65
+ Most MySQL libraries are either:
66
+
67
+ - Low-level drivers (`mysql2`)
68
+ - Full-featured ORMs (TypeORM, Prisma, Sequelize)
69
+
70
+ This library focuses on infrastructure.
71
+
72
+ It provides:
73
+
74
+ - Connection management
75
+ - Transactions
76
+ - Streaming
77
+ - Batch execution
78
+ - Repository integration
79
+
80
+ without hiding SQL from developers.
81
+
82
+ ---
83
+
84
+ # Architecture
85
+
86
+ ```
87
+ Application
88
+ │
89
+ ▼
90
+ SQL Repository Layer
91
+ │
92
+ ▼
93
+ Executor Interface
94
+ │
95
+ ▼
96
+ MySQL Adapter
97
+ ┌──────────────┼──────────────┐
98
+ ▼ ▼ ▼
99
+ Connection Transaction Stream
100
+ │ │ │
101
+ └──────────────┼──────────────┘
102
+ ▼
103
+ mysql2
104
+ │
105
+ ▼
106
+ MySQL
107
+ ```
108
+
109
+ ---
110
+
111
+ # Installation
112
+
113
+ ```bash
114
+ npm install mysql2
115
+ ```
116
+
117
+ ```bash
118
+ npm install mysql2-core
119
+ ```
120
+
121
+ ---
122
+
123
+ # Creating a Database
124
+
125
+ ```ts
126
+ import { MySQLDB } from "mysql2-core"
127
+
128
+ const db = new MySQLDB({
129
+
130
+ host: "localhost",
131
+
132
+ port: 3306,
133
+
134
+ database: "demo",
135
+
136
+ user: "root",
137
+
138
+ password: "password"
139
+
140
+ })
141
+ ```
142
+
143
+ ---
144
+
145
+ # Query
146
+
147
+ ```ts
148
+ const users = await db.query<User>(
149
+
150
+ `
151
+ SELECT *
152
+ FROM users
153
+ WHERE age > ?
154
+ `,
155
+
156
+ [18]
157
+
158
+ )
159
+ ```
160
+
161
+ ---
162
+
163
+ # Execute
164
+
165
+ ```ts
166
+ await db.execute(
167
+
168
+ `
169
+ UPDATE users
170
+ SET active = ?
171
+ WHERE id = ?
172
+ `,
173
+
174
+ [true, 10]
175
+
176
+ )
177
+ ```
178
+
179
+ ---
180
+
181
+ # Transactions
182
+
183
+ ```ts
184
+ const tx = await db.beginTransaction()
185
+
186
+ try {
187
+
188
+ await tx.execute(
189
+
190
+ `
191
+ INSERT INTO users(name)
192
+ VALUES(?)
193
+ `,
194
+
195
+ ["John"]
196
+
197
+ )
198
+
199
+ await tx.commit()
200
+
201
+ }
202
+ catch (err) {
203
+
204
+ await tx.rollback()
205
+
206
+ }
207
+ ```
208
+
209
+ ---
210
+
211
+ # Batch Execution
212
+
213
+ ```ts
214
+ await db.executeBatch([
215
+
216
+ {
217
+
218
+ query:
219
+ "INSERT INTO users(name) VALUES(?)",
220
+
221
+ params:
222
+ ["John"]
223
+
224
+ },
225
+
226
+ {
227
+
228
+ query:
229
+ "INSERT INTO users(name) VALUES(?)",
230
+
231
+ params:
232
+ ["Jane"]
233
+
234
+ }
235
+
236
+ ])
237
+ ```
238
+
239
+ ---
240
+
241
+ # Streaming
242
+
243
+ Stream large result sets without loading everything into memory.
244
+
245
+ ```ts
246
+ await db.stream(
247
+
248
+ "SELECT * FROM users",
249
+
250
+ [],
251
+
252
+ async user => {
253
+
254
+ console.log(user)
255
+
256
+ }
257
+
258
+ )
259
+ ```
260
+
261
+ Ideal for:
262
+
263
+ - ETL
264
+ - Migration
265
+ - Reporting
266
+ - Exporting millions of rows
267
+
268
+ ---
269
+
270
+ # Bulk Writer
271
+
272
+ Insert data efficiently.
273
+
274
+ ```ts
275
+ const writer = new MySQLWriter(db)
276
+
277
+ await writer.write(users)
278
+ ```
279
+
280
+ ---
281
+
282
+ # Batch Writer
283
+
284
+ ```ts
285
+ const writer = new MySQLBatchWriter(db)
286
+
287
+ await writer.write(users)
288
+ ```
289
+
290
+ ---
291
+
292
+ # Stream Writer
293
+
294
+ ```ts
295
+ const writer = new MySQLStreamWriter(db)
296
+
297
+ await writer.write(stream)
298
+ ```
299
+
300
+ Useful for importing very large datasets.
301
+
302
+ ---
303
+
304
+ # Export
305
+
306
+ Export query results without loading everything into memory.
307
+
308
+ ```ts
309
+ await exporter.export(
310
+
311
+ `
312
+ SELECT *
313
+ FROM users
314
+ `,
315
+
316
+ "users.csv"
317
+
318
+ )
319
+ ```
320
+
321
+ ---
322
+
323
+ # Object Mapping
324
+
325
+ Rows are automatically mapped into TypeScript objects.
326
+
327
+ ```ts
328
+ interface User {
329
+
330
+ id: number
331
+
332
+ name: string
333
+
334
+ active: boolean
335
+
336
+ }
337
+ ```
338
+
339
+ ```ts
340
+ const users = await db.query<User>(
341
+ sql
342
+ )
343
+ ```
344
+
345
+ ---
346
+
347
+ # Boolean Conversion
348
+
349
+ Automatically converts database values.
350
+
351
+ ```
352
+ 0 -> false
353
+
354
+ 1 -> true
355
+
356
+ NULL -> null
357
+ ```
358
+
359
+ ---
360
+
361
+ # Health Check
362
+
363
+ ```ts
364
+ const ok = await checker.check()
365
+ ```
366
+
367
+ Perfect for
368
+
369
+ - Kubernetes
370
+ - Docker
371
+ - Load Balancers
372
+ - Monitoring
373
+
374
+ ---
375
+
376
+ # Repository Integration
377
+
378
+ Designed to work seamlessly with **SQL Repository**.
379
+
380
+ ```
381
+ Application
382
+
383
+ │
384
+
385
+ ▼
386
+
387
+ SqlRepository
388
+
389
+ │
390
+
391
+ ▼
392
+
393
+ Executor
394
+
395
+ │
396
+
397
+ ▼
398
+
399
+ MySQL Adapter
400
+
401
+ │
402
+
403
+ ▼
404
+
405
+ mysql2
406
+ ```
407
+
408
+ The repository layer never depends directly on mysql2.
409
+
410
+ ---
411
+
412
+ # Connection Pool
413
+
414
+ Internally the adapter manages a connection pool.
415
+
416
+ ```
417
+ Application
418
+
419
+ │
420
+
421
+ ▼
422
+
423
+ Pool Manager
424
+
425
+ │
426
+
427
+ ▼
428
+
429
+ mysql2 Pool
430
+ ```
431
+
432
+ Connection reuse improves performance.
433
+
434
+ ---
435
+
436
+ # Transaction Model
437
+
438
+ ```
439
+ Application
440
+
441
+ │
442
+
443
+ ▼
444
+
445
+ Transaction
446
+
447
+ │
448
+
449
+ ▼
450
+
451
+ PoolConnection
452
+
453
+ │
454
+
455
+ ▼
456
+
457
+ mysql2
458
+ ```
459
+
460
+ Transactions are isolated from application code.
461
+
462
+ ---
463
+
464
+ # Error Handling
465
+
466
+ Database errors are propagated as Promise rejections.
467
+
468
+ ```ts
469
+ try {
470
+
471
+ await db.execute(sql)
472
+
473
+ }
474
+ catch(err){
475
+
476
+ console.error(err)
477
+
478
+ }
479
+ ```
480
+
481
+ ---
482
+
483
+ # Performance
484
+
485
+ The adapter is designed for high throughput.
486
+
487
+ Features include:
488
+
489
+ - Connection Pooling
490
+ - Prepared Statement Parameters
491
+ - Batch Execution
492
+ - Streaming Queries
493
+ - Minimal Object Allocation
494
+ - Thin Wrapper over mysql2
495
+
496
+ ---
497
+
498
+ # Design Goals
499
+
500
+ - Lightweight
501
+ - Predictable
502
+ - SQL-first
503
+ - Repository Friendly
504
+ - Driver Independent
505
+ - Easy to Debug
506
+ - Easy to Extend
507
+ - High Performance
508
+ - Low Memory Usage
509
+
510
+ ---
511
+
512
+ # Comparison
513
+
514
+ | Feature | mysql2-core | mysql2 | TypeORM |
515
+ |----------|---------------|---------|----------|
516
+ | Connection Pool | ✅ | ✅ | ✅ |
517
+ | Transactions | ✅ | ✅ | ✅ |
518
+ | Streaming | ✅ | ✅ | Partial |
519
+ | Repository Support | ✅ | ❌ | ✅ |
520
+ | Batch Execution | ✅ | Manual | Partial |
521
+ | SQL Generation | ❌ | ❌ | ORM |
522
+ | ORM | ❌ | ❌ | ✅ |
523
+ | Lightweight | ✅ | ✅ | ❌ |
524
+
525
+ ---
526
+
527
+ # Project Structure
528
+
529
+ ```
530
+ MySQLDB
531
+ │
532
+ ├── Connection Pool
533
+ ├── Transactions
534
+ ├── Query Execution
535
+ ├── Execute
536
+ ├── Batch Execute
537
+ ├── Stream
538
+ ├── Exporter
539
+ ├── Object Mapper
540
+ ├── Health Checker
541
+ └── Utilities
542
+ ```
543
+
544
+ ---
545
+
546
+ # Future Roadmap
547
+
548
+ Future versions will introduce:
549
+
550
+ - SQL AST Compiler integration
551
+ - PostgreSQL Adapter
552
+ - SQL Server Adapter
553
+ - Oracle Adapter
554
+ - SQLite Adapter
555
+ - Dialect Abstraction
556
+ - Prepared Statement Cache
557
+ - Retry Policies
558
+ - Metrics & Tracing
559
+ - Connection Observability
560
+
561
+ ---
562
+
563
+ # Relationship with SQL Repository
564
+
565
+ This library is intended to be used together with the SQL Repository library.
566
+
567
+ ```
568
+ SQL Repository
569
+ (Metadata + SQL Builder)
570
+
571
+ │
572
+
573
+ ▼
574
+
575
+ Executor Interface
576
+
577
+ │
578
+
579
+ ┌─────────────┴─────────────┐
580
+
581
+ ▼ ▼
582
+
583
+ MySQL Adapter PostgreSQL Adapter
584
+
585
+ ▼ ▼
586
+
587
+ mysql2 pg
588
+ ```
589
+
590
+ The SQL Repository library generates SQL.
591
+
592
+ This library executes SQL.
593
+
594
+ Together they provide a lightweight, SQL-first data access framework.
595
+
596
+ ---
597
+
598
+ # License
599
+
600
+ MIT License
601
+
602
+ ---
603
+
604
+ # Contributing
605
+
606
+ Contributions are welcome!
607
+
608
+ Feel free to submit issues, feature requests, or pull requests to improve the project.
package/lib/build.js CHANGED
@@ -5,7 +5,7 @@ function param(i) {
5
5
  }
6
6
  exports.param = param;
7
7
  function params(length, from) {
8
- if (from === undefined || from == null) {
8
+ if (from == null) {
9
9
  from = 0;
10
10
  }
11
11
  var ps = [];
@@ -77,7 +77,7 @@ function buildToSave(obj, table, attrs, ver, buildParam, i) {
77
77
  pks.push(attr);
78
78
  }
79
79
  var v = o[k];
80
- if (v === undefined || v == null) {
80
+ if (v == null) {
81
81
  v = attr.default;
82
82
  }
83
83
  if (v !== undefined && v != null && !attr.ignored && !attr.noinsert) {
@@ -139,7 +139,7 @@ function buildToSave(obj, table, attrs, ver, buildParam, i) {
139
139
  if (attr && !attr.key && !attr.ignored && !attr.noupdate) {
140
140
  var field = attr.column ? attr.column : k;
141
141
  var x = void 0;
142
- if (v == null) {
142
+ if (v === null) {
143
143
  x = "null";
144
144
  }
145
145
  else if (v === "") {
@@ -197,7 +197,7 @@ function buildToSaveBatch(objs, table, attrs, ver, buildParam) {
197
197
  var k = ks_4[_a];
198
198
  var attr = attrs[k];
199
199
  var v = o[k];
200
- if (v === undefined || v == null) {
200
+ if (v == null) {
201
201
  v = attr.default;
202
202
  }
203
203
  if (v != null && v !== undefined && !attr.ignored && !attr.noinsert) {
@@ -249,7 +249,7 @@ function buildToSaveBatch(objs, table, attrs, ver, buildParam) {
249
249
  if (attr && !attr.key && !attr.ignored && k !== ver && !attr.noupdate) {
250
250
  var field = attr.column ? attr.column : k;
251
251
  var x = void 0;
252
- if (v == null) {
252
+ if (v === null) {
253
253
  x = "null";
254
254
  }
255
255
  else if (v === "") {
package/lib/index.js CHANGED
@@ -1071,7 +1071,7 @@ var MySQLStreamWriter = (function () {
1071
1071
  else {
1072
1072
  var total_1 = this.list.length;
1073
1073
  var stmt = build_1.buildToSaveBatch(this.list, this.table, this.attributes, this.version, this.param);
1074
- if (stmt) {
1074
+ if (stmt.length > 0) {
1075
1075
  if (this.executeBatch) {
1076
1076
  return this.executeBatch(stmt).then(function (r) {
1077
1077
  _this.list = [];
@@ -1126,7 +1126,7 @@ var MySQLBatchWriter = (function () {
1126
1126
  }
1127
1127
  }
1128
1128
  var stmts = build_1.buildToSaveBatch(list, this.table, this.attributes, this.version, this.param);
1129
- if (stmts && stmts.length > 0) {
1129
+ if (stmts.length > 0) {
1130
1130
  if (this.execute) {
1131
1131
  if (this.oneIfSuccess) {
1132
1132
  return this.execute(stmts).then(function (ct) { return stmts.length; });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mysql2-core",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "mysql2-core",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./src/index.ts",
package/src/build.ts CHANGED
@@ -4,7 +4,7 @@ export function param(i: number): string {
4
4
  return "?"
5
5
  }
6
6
  export function params(length: number, from?: number): string[] {
7
- if (from === undefined || from == null) {
7
+ if (from == null) {
8
8
  from = 0
9
9
  }
10
10
  const ps: string[] = []
@@ -80,7 +80,7 @@ export function buildToSave<T>(obj: T, table: string, attrs: Attributes, ver?: s
80
80
  pks.push(attr)
81
81
  }
82
82
  let v = o[k]
83
- if (v === undefined || v == null) {
83
+ if (v == null) {
84
84
  v = attr.default
85
85
  }
86
86
  if (v !== undefined && v != null && !attr.ignored && !attr.noinsert) {
@@ -134,7 +134,7 @@ export function buildToSave<T>(obj: T, table: string, attrs: Attributes, ver?: s
134
134
  if (attr && !attr.key && !attr.ignored && !attr.noupdate) {
135
135
  const field = attr.column ? attr.column : k
136
136
  let x: string
137
- if (v == null) {
137
+ if (v === null) {
138
138
  x = "null"
139
139
  } else if (v === "") {
140
140
  x = `''`
@@ -183,7 +183,7 @@ export function buildToSaveBatch<T>(objs: T[], table: string, attrs: Attributes,
183
183
  for (const k of ks) {
184
184
  const attr = attrs[k]
185
185
  let v = o[k]
186
- if (v === undefined || v == null) {
186
+ if (v == null) {
187
187
  v = attr.default
188
188
  }
189
189
  if (v != null && v !== undefined && !attr.ignored && !attr.noinsert) {
@@ -229,7 +229,7 @@ export function buildToSaveBatch<T>(objs: T[], table: string, attrs: Attributes,
229
229
  if (attr && !attr.key && !attr.ignored && k !== ver && !attr.noupdate) {
230
230
  const field = attr.column ? attr.column : k
231
231
  let x: string
232
- if (v == null) {
232
+ if (v === null) {
233
233
  x = "null"
234
234
  } else if (v === "") {
235
235
  x = `''`
package/src/index.ts CHANGED
@@ -902,7 +902,7 @@ export class MySQLStreamWriter<T> {
902
902
  } else {
903
903
  const total = this.list.length
904
904
  const stmt = buildToSaveBatch(this.list, this.table, this.attributes, this.version, this.param)
905
- if (stmt) {
905
+ if (stmt.length > 0) {
906
906
  if (this.executeBatch) {
907
907
  return this.executeBatch(stmt).then((r) => {
908
908
  this.list = []
@@ -961,7 +961,7 @@ export class MySQLBatchWriter<T> {
961
961
  }
962
962
  }
963
963
  const stmts = buildToSaveBatch(list, this.table, this.attributes, this.version, this.param)
964
- if (stmts && stmts.length > 0) {
964
+ if (stmts.length > 0) {
965
965
  if (this.execute) {
966
966
  if (this.oneIfSuccess) {
967
967
  return this.execute(stmts).then((ct) => stmts.length)