@axiosleo/orm-mysql 0.14.4 → 0.15.1

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
@@ -15,48 +15,8 @@ npm install @axiosleo/orm-mysql
15
15
 
16
16
  ## Usage
17
17
 
18
- ### Create MySQL client
19
-
20
- ```javascript
21
- const { createClient } = require("@axiosleo/orm-mysql");
22
-
23
- const client = createClient({
24
- host: process.env.MYSQL_HOST,
25
- port: process.env.MYSQL_PORT,
26
- user: process.env.MYSQL_USER,
27
- password: process.env.MYSQL_PASS,
28
- database: process.env.MYSQL_DB,
29
- });
30
- ```
31
-
32
- ### Initialize database handler
33
-
34
- ```javascript
35
- const { QueryHandler } = require("@axiosleo/orm-mysql");
36
-
37
- const db = new QueryHandler(client);
38
- ```
39
-
40
- ### Initialize query
41
-
42
- ```javascript
43
- const query = db.table('<table-name>');
44
-
45
- query.attr("id", "name", "age"); // set attributes
46
- query.where("name", "Joe"); // set where condition
47
- query.orWhere("age", ">", 18); // set or where condition
48
- query.andWhere("age", "<", 30); // set and where condition
49
- query.orderBy("age", "desc"); // set order by
50
- query.limit(10); // set limit
51
- query.offset(0); // set offset
52
-
53
- let rows = await query.select(); // select
54
- ```
55
-
56
- ### Some Query Examples
57
-
58
18
  ```javascript
59
- const { createClient, QueryHandler, Query } = require("@axiosleo/orm-mysql");
19
+ const { createClient, QueryHandler } = require("@axiosleo/orm-mysql");
60
20
 
61
21
  const conn = createClient({
62
22
  host: process.env.MYSQL_HOST,
@@ -66,415 +26,96 @@ const conn = createClient({
66
26
  database: process.env.MYSQL_DB,
67
27
  });
68
28
 
69
- const hanlder = new QueryHandler(conn);
29
+ const db = new QueryHandler(conn);
70
30
 
71
- async function selectExample() {
72
- const query = handler.table("users"); // init QueryOperator by table name
31
+ // SELECT
32
+ const users = await db.table("users")
33
+ .where("age", ">", 18)
34
+ .orderBy("name", "asc")
35
+ .limit(10)
36
+ .select("id", "name", "age");
73
37
 
74
- query.attr("id", "name", "age"); // set attributes
75
- query.where("name", "Joe"); // set where condition
76
- query.orWhere("age", ">", 18); // set or where condition
77
- query.andWhere("age", "<", 30); // set and where condition
78
- query.orderBy("age", "desc"); // set order by
79
- query.limit(10); // set limit
80
- query.offset(0); // set offset
38
+ // FIND single row
39
+ const user = await db.table("users").where("id", 1).find();
81
40
 
82
- let rows = await query.select(); // select
83
- }
84
-
85
- async function findExample() {
86
- const query = handler.table("users"); // init QueryOperator by table name
41
+ // INSERT
42
+ await db.table("users").insert({ name: "Joe", age: 18 });
87
43
 
88
- query.attr("id", "name", "age"); // set attributes
89
- query.where("name", "Joe"); // set where condition
90
- query.orWhere("age", ">", 18); // set or where condition
91
- query.andWhere("age", "<", 30); // set and where condition
92
- query.orderBy("age", "desc"); // set order by
93
- // query.limit(10); // not supported set limit
94
- // query.offset(10); // not supported set offset
95
-
96
- let row = await query.find(); // find single row
97
- }
44
+ // UPDATE
45
+ await db.table("users").where("id", 1).update({ name: "Joe", age: 19 });
98
46
 
99
- async function insertExample() {
100
- const query = handler.table("users");
101
-
102
- // insert
103
- let row = await query.insert({
104
- name: "Joe",
105
- age: 18,
106
- });
107
-
108
- // The insert operation will be changed to the update operation if the uuid already exists
109
- row = await query.keys('uuid').insert({
110
- uuid: 'uuid-string', // uuid is unique index
111
- name: "Joe",
112
- age: 18,
113
- })
114
- }
115
-
116
- async function updateExample() {
117
- const query = handler.table("users");
118
-
119
- // update
120
- let row = await query.where("name", "Joe").update({
121
- name: "Joe",
122
- age: 18,
123
- });
124
-
125
- // incrBy with number
126
- row = await query.where("name", "Joe").incrBy("age", 1);
127
-
128
- // incrBy with string
129
- row = await query.where("name", "Joe").incrBy("age", "1");
130
-
131
- // incrBy with Callback
132
- let result = { status: "success" };
133
- row = await query.where("id", 1).incrBy("error_times", () => {
134
- // increase error_times if result.status is not success
135
- if (result.status !== "success") {
136
- return 1;
137
- }
138
- return 0;
139
- });
140
- }
47
+ // DELETE
48
+ await db.table("users").where("id", 1).delete();
141
49
 
142
- async function deleteExample() {
143
- const query = handler.table("users");
144
-
145
- // delete with conditions
146
- let result = await query.where("name", "Joe").delete();
147
-
148
- // delete by id
149
- result = await query.delete(1);
150
- }
151
-
152
- async function subqueryExample() {
153
- const query = handler.table("users", "u");
154
- const subQuery = new Query("select");
155
- subQuery.table("users").having("COUNT(*)", ">", 1);
156
-
157
- const sql = query.where("u.name", subQuery, "IN").buildSql("select").sql;
158
- // SELECT * FROM `users` AS `u` WHERE `u`.`name` IN (SELECT * FROM `users` GROUP BY `u`.`name` HAVING COUNT(*) > ?)
159
- }
160
- ```
161
-
162
- ### Hook
163
-
164
- ```javascript
165
- const { Hook } = require("@axiosleo/orm-mysql");
166
-
167
- // opt: 'select' | 'find' | 'insert' | 'update' | 'delete' | 'count'
168
-
169
- Hook.pre(async (options) => {
170
- debug.log('options', options);
171
- }, { table: 'table_name', opt: 'insert'});
172
-
173
- Hook.post(async (options, result) => {
174
- throw new Error('some error');
175
- }, { table: 'table_name', opt: 'insert' });
176
- ```
177
-
178
- ### Transaction
179
-
180
- #### Method 1: Using Connection Pool (Recommended)
181
-
182
- ```javascript
183
- const mysql = require("mysql2");
184
- const { QueryHandler } = require("@axiosleo/orm-mysql");
185
-
186
- // Create connection pool
187
- const pool = mysql.createPool({
188
- host: process.env.MYSQL_HOST,
189
- port: process.env.MYSQL_PORT,
190
- user: process.env.MYSQL_USER,
191
- password: process.env.MYSQL_PASS,
192
- database: process.env.MYSQL_DB,
193
- connectionLimit: 10
194
- });
195
-
196
- const handler = new QueryHandler(pool);
197
-
198
- // Begin transaction - automatically gets a connection from pool
199
- const transaction = await handler.beginTransaction({
200
- level: "RC" // READ COMMITTED
201
- });
50
+ // COUNT
51
+ const total = await db.table("users").where("age", ">", 18).count();
202
52
 
53
+ // TRANSACTION
54
+ const tx = await db.beginTransaction({ level: "RC" });
203
55
  try {
204
- // Insert user info
205
- let row = await transaction.table("users").insert({
206
- name: "Joe",
207
- age: 18,
208
- });
209
- const lastInsertId = row.insertId;
210
-
211
- // Insert student info
212
- await transaction.table("students").insert({
213
- user_id: lastInsertId,
214
- });
215
-
216
- // Commit transaction - connection automatically released back to pool
217
- await transaction.commit();
56
+ await tx.table("users").insert({ name: "Joe", age: 18 });
57
+ await tx.commit();
218
58
  } catch (e) {
219
- // Rollback transaction - connection automatically released back to pool
220
- await transaction.rollback();
59
+ await tx.rollback();
221
60
  throw e;
222
61
  }
223
62
  ```
224
63
 
225
- #### Method 2: Using TransactionHandler Directly
226
-
227
- ```javascript
228
- const { TransactionHandler, createPromiseClient } = require("@axiosleo/orm-mysql");
64
+ > For complete API documentation including where conditions, joins, hooks, migrations, and more, install the [AI Skills](#ai-skills) for your coding assistant, or browse the skill files in [`skills/`](skills/).
229
65
 
230
- const conn = await createPromiseClient({
231
- host: process.env.MYSQL_HOST,
232
- port: process.env.MYSQL_PORT,
233
- user: process.env.MYSQL_USER,
234
- password: process.env.MYSQL_PASS,
235
- database: process.env.MYSQL_DB,
236
- });
66
+ ### Migration
237
67
 
238
- const transaction = new TransactionHandler(conn, {
239
- /*
240
- Transaction Isolation Levels:
241
- - 'READ UNCOMMITTED' | 'RU' : Lowest isolation, may read dirty data
242
- - 'READ COMMITTED' | 'RC' : Prevents dirty reads
243
- - 'REPEATABLE READ' | 'RR' : MySQL default, prevents non-repeatable reads
244
- - 'SERIALIZABLE' | 'S' : Highest isolation, full serialization
245
- */
246
- level: "SERIALIZABLE", // 'SERIALIZABLE' as default value
247
- });
248
- await transaction.begin();
68
+ ```bash
69
+ # Generate migration script
70
+ npx orm-mysql generate <name> [dir]
249
71
 
250
- try {
251
- // Insert user info
252
- let row = await transaction.table("users").insert({
253
- name: "Joe",
254
- age: 18,
255
- });
256
- const lastInsertId = row[0].insertId;
257
-
258
- // Insert student info
259
- await transaction.table("students").insert({
260
- user_id: lastInsertId,
261
- });
262
- await transaction.commit();
263
- } catch (e) {
264
- await transaction.rollback();
265
- throw e;
266
- }
72
+ # Run migration
73
+ npx orm-mysql migrate up [dir] --host=localhost --port=3306 --user=root --pass=pwd --db=mydb
267
74
  ```
268
75
 
269
- #### Row Locking with FOR UPDATE
76
+ > [Migration examples](./examples/migration/)
270
77
 
271
- ```javascript
272
- const transaction = await handler.beginTransaction({ level: "RC" });
78
+ ## AI Skills
273
79
 
274
- try {
275
- // Lock rows for update
276
- const product = await transaction.table("products")
277
- .where("sku", "LAPTOP-001")
278
- .append("FOR UPDATE") // Lock the row
279
- .find();
280
-
281
- if (product.stock < 1) {
282
- throw new Error("Out of stock");
283
- }
284
-
285
- // Update stock
286
- await transaction.table("products")
287
- .where("sku", "LAPTOP-001")
288
- .update({ stock: product.stock - 1 });
289
-
290
- // Create order
291
- await transaction.table("orders").insert({
292
- product_id: product.id,
293
- quantity: 1,
294
- total: product.price
295
- });
296
-
297
- await transaction.commit();
298
- } catch (e) {
299
- await transaction.rollback();
300
- throw e;
301
- }
302
- ```
80
+ This project ships with AI Skills that teach AI coding assistants how to use this library correctly. You can install them with a single command:
303
81
 
304
- #### Concurrent Transactions
82
+ ```bash
83
+ # Cursor
84
+ npx @axiosleo/orm-mysql skills --install=cursor
305
85
 
306
- When using a connection pool, multiple transactions can run concurrently without blocking each other:
86
+ # Claude Code
87
+ npx @axiosleo/orm-mysql skills --install=claude
307
88
 
308
- ```javascript
309
- const pool = mysql.createPool({ /* ... */ });
310
- const handler = new QueryHandler(pool);
311
-
312
- // Run 3 transactions concurrently
313
- await Promise.all([
314
- (async () => {
315
- const tx = await handler.beginTransaction();
316
- try {
317
- await tx.table("users").insert({ name: "User1" });
318
- await tx.commit();
319
- } catch (err) {
320
- await tx.rollback();
321
- throw err;
322
- }
323
- })(),
324
-
325
- (async () => {
326
- const tx = await handler.beginTransaction();
327
- try {
328
- await tx.table("users").insert({ name: "User2" });
329
- await tx.commit();
330
- } catch (err) {
331
- await tx.rollback();
332
- throw err;
333
- }
334
- })(),
335
-
336
- (async () => {
337
- const tx = await handler.beginTransaction();
338
- try {
339
- await tx.table("users").insert({ name: "User3" });
340
- await tx.commit();
341
- } catch (err) {
342
- await tx.rollback();
343
- throw err;
344
- }
345
- })()
346
- ]);
89
+ # Windsurf
90
+ npx @axiosleo/orm-mysql skills --install=windsurf
347
91
  ```
348
92
 
349
- #### Best Practices
93
+ The command detects the locally installed version of `@axiosleo/orm-mysql` in your `node_modules/` and copies the matching skill files. If the package is not installed locally, it will use the bundled skills and remind you to run `npm install @axiosleo/orm-mysql`.
350
94
 
351
- 1. **Always use connection pools in production** - Prevents connection exhaustion and enables concurrent transactions
352
- 2. **Choose appropriate isolation level** - Balance between consistency and performance
353
- 3. **Use try-catch-finally** - Ensure transactions are always committed or rolled back
354
- 4. **Keep transactions short** - Avoid long-running operations inside transactions
355
- 5. **Use row locking when needed** - `FOR UPDATE` prevents concurrent modifications
356
- 6. **Handle errors properly** - Always rollback on errors to maintain data consistency
357
-
358
- ### Migration
359
-
360
- > [Migration examples](./examples/migration/).
361
-
362
- - Migration script example
363
-
364
- ```javascript
365
- 'use strict';
366
-
367
- /**
368
- * @param {import('@axiosleo/orm-mysql').MigrationInterface} migration
369
- */
370
- function up(migration) {
371
- migration.createTable('table1', {
372
- field1: {
373
- type: 'varchar',
374
- length: 64,
375
- allowNull: false,
376
- uniqIndex: true
377
- },
378
- field2: {
379
- type: 'VARCHAR',
380
- allowNull: false
381
- },
382
- field3: {
383
- type: 'VARCHAR',
384
- comment: 'comment',
385
- allowNull: false
386
- },
387
- });
388
- }
389
-
390
- /**
391
- * @param {import('@axiosleo/orm-mysql').MigrationInterface} migration
392
- */
393
- function down(migration) {
394
- migration.dropTable('table1');
395
- }
396
-
397
- module.exports = {
398
- up,
399
- down
400
- };
401
- ```
402
-
403
- - Generate migration script
95
+ To uninstall:
404
96
 
405
97
  ```bash
406
- orm-mysql generate -h
407
-
408
- Usage:
409
-
410
- generate [--] [name] <dir>
411
- gen
412
-
413
- Arguments:
414
-
415
- *name Migration name
416
- dir Migration scripts directory
98
+ npx @axiosleo/orm-mysql skills --uninstall=cursor
99
+ npx @axiosleo/orm-mysql skills --uninstall=claude
100
+ npx @axiosleo/orm-mysql skills --uninstall=windsurf
417
101
  ```
418
102
 
419
- - Run migration
103
+ ### Skill Files
420
104
 
421
- ```bash
422
- orm-mysql migrate -h
423
-
424
- Description:
425
-
426
- Migrate database
427
-
428
- Usage:
105
+ | File | Content |
106
+ |------|---------|
107
+ | `SKILL.md` | Setup, class hierarchy, quick start |
108
+ | `query-building.md` | table, attr, join, orderBy, limit, groupBy |
109
+ | `where-conditions.md` | where, whereIn, whereLike, whereBetween |
110
+ | `crud-operations.md` | select, find, insert, update, delete, incrBy |
111
+ | `transactions.md` | beginTransaction, isolation levels, row locking |
429
112
 
430
- migrate [options] [--] [action] <dir>
113
+ ### Manual Installation
431
114
 
432
- Options:
115
+ For other AI tools, copy the skill files from `node_modules/@axiosleo/orm-mysql/skills/` into your tool's custom instructions directory:
433
116
 
434
- -d, --debug [false] debug mode
435
- --host [localhost] mysql host
436
- --port [3306] port number to connect to the database
437
- --user [root] username for connect to the database
438
- --pass password to connect to the database
439
- --db database name
440
-
441
- Arguments:
442
-
443
- *action up or down
444
- dir migration directory
445
- ```
446
-
447
- ### Custom query driver
448
-
449
- ```javascript
450
- const {
451
- createClient,
452
- QueryHandler,
453
- Query,
454
- Builder
455
- } = require("@axiosleo/orm-mysql");
456
-
457
- const conn = createClient({
458
- host: process.env.MYSQL_HOST,
459
- port: process.env.MYSQL_PORT,
460
- user: process.env.MYSQL_USER,
461
- password: process.env.MYSQL_PASS,
462
- database: process.env.MYSQL_DB,
463
- });
464
-
465
- const hanlder = new QueryHandler(conn, {
466
- driver: 'custom',
467
- queryHandler: (con, options) => {
468
- const builder = new Builder(options);
469
- return new Promise((resolve, reject) => {
470
- if (options.operator === 'select') {
471
- resolve([{ a: 1, b: 2 }]);
472
- } else {
473
- reject(new Error('some error'));
474
- }
475
- });
476
- }
477
- });
117
+ ```bash
118
+ cp -r node_modules/@axiosleo/orm-mysql/skills/ .your-tool/skills/orm-mysql-usage/
478
119
  ```
479
120
 
480
121
  ## License
package/bin/orm-mysql.js CHANGED
@@ -9,7 +9,7 @@ const app = new App({
9
9
  name: 'MySQL ORM CLI',
10
10
  desc: 'migrate, model, seed, etc.',
11
11
  bin: 'orm-mysql',
12
- version: '0.14.4',
12
+ version: '0.15.1',
13
13
  commands_dir: path.join(__dirname, '../commands'),
14
14
  });
15
15