@axiosleo/orm-mysql 0.13.2 → 0.14.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/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.13.2',
12
+ version: '0.14.1',
13
13
  commands_dir: path.join(__dirname, '../commands'),
14
14
  });
15
15
 
package/index.d.ts CHANGED
@@ -640,9 +640,20 @@ export declare class MigrationInterface {
640
640
  createForeignKey(table: string, options: {
641
641
  foreignKey?: string,
642
642
  columnName: string,
643
- reference: {
644
- tableName: string,
645
- columnName: string,
643
+ references?: {
644
+ table: string,
645
+ column: string,
646
+ onDelete?: CascadeType,
647
+ onUpdate?: CascadeType,
648
+ },
649
+ /** @deprecated Use `references` instead */
650
+ reference?: {
651
+ table?: string,
652
+ column?: string,
653
+ /** @deprecated Use `table` instead */
654
+ tableName?: string,
655
+ /** @deprecated Use `column` instead */
656
+ columnName?: string,
646
657
  onDelete?: CascadeType,
647
658
  onUpdate?: CascadeType,
648
659
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axiosleo/orm-mysql",
3
- "version": "0.13.2",
3
+ "version": "0.14.1",
4
4
  "description": "MySQL ORM tool",
5
5
  "keywords": [
6
6
  "mysql",
package/src/builder.js CHANGED
@@ -582,8 +582,17 @@ class ManageSQLBuilder extends Builder {
582
582
  });
583
583
  }
584
584
 
585
- createForeignKey(options) {
585
+ createForeignKey(options, onCreateTable = false) {
586
+ if (options.reference && !options.references) {
587
+ options.references = options.reference;
588
+ }
586
589
  if (options.references) {
590
+ if (options.references.tableName && !options.references.table) {
591
+ options.references.table = options.references.tableName;
592
+ }
593
+ if (options.references.columnName && !options.references.column) {
594
+ options.references.column = options.references.columnName;
595
+ }
587
596
  options.references.onDelete = options.references.onDelete ? options.references.onDelete.toUpperCase() : 'NO ACTION';
588
597
  options.references.onUpdate = options.references.onUpdate ? options.references.onUpdate.toUpperCase() : 'NO ACTION';
589
598
  }
@@ -591,17 +600,27 @@ class ManageSQLBuilder extends Builder {
591
600
  name: 'required|string',
592
601
  table: 'required|string',
593
602
  column: 'required|string',
594
- 'references.tableName': 'required|string',
595
- 'references.columnName': 'required|string',
603
+ 'references.table': 'required|string',
604
+ 'references.column': 'required|string',
596
605
  'references.onUpdate': [{ in: ['RESTRICT', 'CASCADE', 'SET NULL', 'NO ACTION'] }],
597
606
  'references.onDelete': [{ in: ['RESTRICT', 'CASCADE', 'SET NULL', 'NO ACTION'] }]
598
607
  });
608
+ if (onCreateTable === true) {
609
+ return _render('CONSTRAINT `${name}` FOREIGN KEY (`${column_name}`) REFERENCES `${foreign_table}` (`${foreign_column}`) ON DELETE ${on_delete} ON UPDATE ${on_update}', {
610
+ name: options.name,
611
+ column_name: options.column,
612
+ foreign_table: options.references.table,
613
+ foreign_column: options.references.column,
614
+ on_delete: options.references.onDelete || 'NO ACTION',
615
+ on_update: options.references.onUpdate || 'NO ACTION',
616
+ });
617
+ }
599
618
  return _render('ALTER TABLE `${table_name}` ADD CONSTRAINT `${name}` FOREIGN KEY (`${column_name}`) REFERENCES `${foreign_table}` (`${foreign_column}`) ON DELETE ${on_delete} ON UPDATE ${on_update}', {
600
- table_name: options.tableName,
619
+ table_name: options.table,
601
620
  name: options.name,
602
- column_name: options.columnName,
603
- foreign_table: options.references.tableName,
604
- foreign_column: options.references.columnName,
621
+ column_name: options.column,
622
+ foreign_table: options.references.table,
623
+ foreign_column: options.references.column,
605
624
  on_delete: options.references.onDelete || 'NO ACTION',
606
625
  on_update: options.references.onUpdate || 'NO ACTION',
607
626
  });
@@ -663,6 +682,12 @@ class ManageSQLBuilder extends Builder {
663
682
  column.references = column.reference;
664
683
  }
665
684
  if (column.references) {
685
+ if (column.references.tableName && !column.references.table) {
686
+ column.references.table = column.references.tableName;
687
+ }
688
+ if (column.references.columnName && !column.references.column) {
689
+ column.references.column = column.references.columnName;
690
+ }
666
691
  column.references.onDelete = column.references.onDelete ? column.references.onDelete.toUpperCase() : 'NO ACTION';
667
692
  column.references.onUpdate = column.references.onUpdate ? column.references.onUpdate.toUpperCase() : 'NO ACTION';
668
693
 
@@ -677,8 +702,8 @@ class ManageSQLBuilder extends Builder {
677
702
  table,
678
703
  column: column.name,
679
704
  references: {
680
- tableName: column.references.table,
681
- columnName: column.references.column,
705
+ table: column.references.table,
706
+ column: column.references.column,
682
707
  onDelete: column.references.onDelete,
683
708
  onUpdate: column.references.onUpdate
684
709
  }
@@ -697,7 +722,7 @@ class ManageSQLBuilder extends Builder {
697
722
  }
698
723
  if (referenceColumns.length) {
699
724
  referenceColumns.forEach((r) => {
700
- strs.push(this.createForeignKey(r));
725
+ strs.push(this.createForeignKey(r, true));
701
726
  });
702
727
  }
703
728
  return strs.join(', ');
package/src/migration.js CHANGED
@@ -227,13 +227,22 @@ function _initMigration(file, queries = {}) {
227
227
 
228
228
  Object.defineProperty(migration, 'createForeignKey', {
229
229
  value: function (table, options = {}) {
230
+ const refs = options.references || options.reference;
231
+ if (refs) {
232
+ if (refs.tableName && !refs.table) {
233
+ refs.table = refs.tableName;
234
+ }
235
+ if (refs.columnName && !refs.column) {
236
+ refs.column = refs.columnName;
237
+ }
238
+ }
230
239
  _assign(options, {
231
240
  operator: 'create',
232
241
  target: 'foreignKey',
233
242
  name: options.foreignKey ? options.foreignKey : 'fk_' + table + '_' + options.columnName,
234
243
  table: table,
235
244
  column: options.columnName,
236
- references: options.references || options.reference // 兼容性处理
245
+ references: refs
237
246
  });
238
247
  const builder = new ManageSQLBuilder(options);
239
248
  queries[file].push({ sql: builder.sql, values: builder.values });
@@ -1,14 +0,0 @@
1
- {
2
- "recommendations": [
3
- "vscode-icons-team.vscode-icons",
4
- "formulahendry.docker-extension-pack",
5
- "mikestead.dotenv",
6
- "dbaeumer.vscode-eslint",
7
- "codezombiech.gitignore",
8
- "eamodio.gitlens",
9
- "esbenp.prettier-vscode",
10
- "wayou.vscode-todo-highlight",
11
- "octref.vetur",
12
- "pflannery.vscode-versionlens"
13
- ]
14
- }
@@ -1,5 +0,0 @@
1
- {
2
- "cSpell.words": [
3
- "fulltext"
4
- ]
5
- }
package/dist/orm-mysql DELETED
Binary file
@@ -1,28 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * @returns {Record<string, import('@axiosleo/orm-mysql').ColumnItem>}
5
- */
6
- module.exports = {
7
- id: {
8
- type: 'int',
9
- allowNull: false,
10
- primaryKey: true,
11
- autoIncrement: true
12
- },
13
- created_at: {
14
- type: 'TIMESTAMP',
15
- allowNull: false,
16
- default: 'CURRENT_TIMESTAMP'
17
- },
18
- updated_at: {
19
- type: 'TIMESTAMP',
20
- allowNull: false,
21
- default: 'CURRENT_TIMESTAMP',
22
- onUpdate: 'CURRENT_TIMESTAMP'
23
- },
24
- disabled_at: {
25
- type: 'TIMESTAMP',
26
- allowNull: true
27
- }
28
- };
@@ -1,16 +0,0 @@
1
- 'use strict';
2
-
3
- const path = require('path');
4
-
5
- const dotenv = require('dotenv');
6
- dotenv.config({
7
- path: path.join(__dirname, '../../../.env')
8
- });
9
-
10
- module.exports = {
11
- host: process.env.MYSQL_HOST,
12
- port: process.env.MYSQL_PORT,
13
- user: process.env.MYSQL_USER,
14
- password: process.env.MYSQL_PASS,
15
- database: process.env.MYSQL_DB
16
- };
@@ -1,108 +0,0 @@
1
- 'use strict';
2
-
3
- const baseColumn = require('../base_column');
4
-
5
- /**
6
- * @param {import('@axiosleo/orm-mysql').MigrationInterface} migration
7
- */
8
- function up(migration) {
9
- migration.createTable('orgs', {
10
- ...baseColumn,
11
- code: {
12
- type: 'varchar',
13
- length: 64,
14
- allowNull: false,
15
- uniqIndex: true
16
- },
17
- name: {
18
- type: 'VARCHAR',
19
- allowNull: false
20
- },
21
- type: {
22
- type: 'VARCHAR',
23
- comment: '集团 group;公司 company;',
24
- allowNull: false
25
- },
26
- });
27
-
28
- migration.createTable('account', {
29
- ...baseColumn,
30
- uuid: {
31
- type: 'VARCHAR',
32
- length: 36,
33
- allowNull: false,
34
- uniqIndex: true,
35
- comment: 'uuid'
36
- },
37
- username: {
38
- type: 'varchar',
39
- length: 64,
40
- allowNull: false,
41
- },
42
- name: {
43
- type: 'VARCHAR',
44
- length: 100,
45
- allowNull: false,
46
- comment: '姓名',
47
- },
48
- avatar: {
49
- type: 'VARCHAR',
50
- allowNull: true,
51
- comment: '头像文件索引'
52
- },
53
- password: {
54
- type: 'varchar',
55
- length: 64,
56
- allowNull: false
57
- },
58
- last_token: {
59
- type: 'VARCHAR',
60
- length: 36,
61
- allowNull: true,
62
- comment: '最后一次登录的token'
63
- }
64
- });
65
- migration.createIndex('account', ['username asc']);
66
-
67
- migration.createTable('account_orgs', {
68
- id: baseColumn.id,
69
- account_id: {
70
- type: 'int',
71
- allowNull: false,
72
- references: {
73
- table: 'account',
74
- column: 'id'
75
- }
76
- },
77
- org_id: {
78
- type: 'int',
79
- allowNull: false,
80
- references: {
81
- table: 'orgs',
82
- column: 'id'
83
- }
84
- },
85
- type: {
86
- type: 'varchar',
87
- length: 32,
88
- allowNull: false,
89
- comment: '组织创建者creator;组织管理员admin;组织用户user;',
90
- default: 'user'
91
- }
92
- });
93
- migration.createColumn('created_at', 'TIMESTAMP', 'account_orgs');
94
- }
95
-
96
- /**
97
- * @param {import('@axiosleo/orm-mysql').MigrationInterface} migration
98
- */
99
- function down(migration) {
100
- migration.dropTable('account_orgs');
101
- migration.dropTable('account');
102
- migration.dropTable('orgs');
103
- }
104
-
105
- module.exports = {
106
- up,
107
- down
108
- };
@@ -1,228 +0,0 @@
1
- /* eslint-disable no-console */
2
- 'use strict';
3
-
4
- /**
5
- * 事务使用示例
6
- *
7
- * 这个示例展示了如何正确使用事务,避免连接阻塞问题
8
- */
9
-
10
- const mysql = require('mysql2/promise');
11
- const { QueryHandler } = require('../src/operator');
12
-
13
- /**
14
- * 示例 1: 使用连接池(推荐)
15
- * 优点:自动从池中获取新连接,不会阻塞其他操作
16
- */
17
- async function exampleWithPool() {
18
- const pool = mysql.createPool({
19
- host: 'localhost',
20
- port: 3306,
21
- user: 'root',
22
- password: 'password',
23
- database: 'test_db',
24
- connectionLimit: 10
25
- });
26
-
27
- const queryHandler = new QueryHandler(pool);
28
-
29
- try {
30
- // 方式 1: 使用 QueryHandler.beginTransaction()(推荐)
31
- // 这会自动从连接池获取一个新连接用于事务
32
- const transaction = await queryHandler.beginTransaction({ level: 'RC' });
33
-
34
- try {
35
- // 执行事务操作
36
- await transaction.table('users').insert({ name: 'John', age: 30 });
37
- await transaction.table('orders').insert({ user_id: 1, total: 100 });
38
-
39
- // 提交事务(会自动释放连接回池)
40
- await transaction.commit();
41
- console.log('Transaction committed successfully');
42
- } catch (err) {
43
- // 回滚事务(会自动释放连接回池)
44
- await transaction.rollback();
45
- console.error('Transaction rolled back:', err.message);
46
- throw err;
47
- }
48
-
49
- // 同时,其他操作不会被阻塞
50
- const users = await queryHandler.table('users').select();
51
- console.log('Users:', users);
52
-
53
- } finally {
54
- await pool.end();
55
- }
56
- }
57
-
58
- /**
59
- * 示例 2: 使用单一连接(不推荐用于生产环境)
60
- * 注意:事务执行期间会阻塞该连接的其他操作
61
- */
62
- async function exampleWithSingleConnection() {
63
- const connection = await mysql.createConnection({
64
- host: 'localhost',
65
- port: 3306,
66
- user: 'root',
67
- password: 'password',
68
- database: 'test_db'
69
- });
70
-
71
- const queryHandler = new QueryHandler(connection);
72
-
73
- try {
74
- // 使用单一连接创建事务
75
- const transaction = await queryHandler.beginTransaction({ level: 'RR' });
76
-
77
- try {
78
- await transaction.table('users').insert({ name: 'Jane', age: 25 });
79
- await transaction.commit();
80
- console.log('Transaction committed');
81
- } catch (err) {
82
- await transaction.rollback();
83
- console.error('Transaction rolled back:', err);
84
- throw err;
85
- }
86
-
87
- } finally {
88
- await connection.end();
89
- }
90
- }
91
-
92
- /**
93
- * 示例 3: 直接使用 TransactionHandler
94
- * 适用于需要更多控制的场景
95
- */
96
- async function exampleWithTransactionHandler() {
97
- const { TransactionHandler } = require('../src/transaction');
98
-
99
- const connection = await mysql.createConnection({
100
- host: 'localhost',
101
- port: 3306,
102
- user: 'root',
103
- password: 'password',
104
- database: 'test_db'
105
- });
106
-
107
- const transaction = new TransactionHandler(connection, { level: 'SERIALIZABLE' });
108
-
109
- try {
110
- await transaction.begin();
111
-
112
- // 执行多个操作
113
- await transaction.table('users').insert({ name: 'Bob', age: 35 });
114
- await transaction.table('user_profiles').insert({ user_id: 1, bio: 'Developer' });
115
-
116
- // 使用锁
117
- const lockedRows = await transaction.table('products')
118
- .where('id', [1, 2, 3], 'IN')
119
- .append('FOR UPDATE')
120
- .select();
121
-
122
- console.log('Locked rows:', lockedRows);
123
-
124
- await transaction.commit();
125
- console.log('Transaction completed');
126
- } catch (err) {
127
- await transaction.rollback();
128
- console.error('Error:', err);
129
- throw err;
130
- } finally {
131
- await connection.end();
132
- }
133
- }
134
-
135
- /**
136
- * 示例 4: 并发事务(使用连接池)
137
- * 展示多个事务可以同时执行而不相互阻塞
138
- */
139
- async function exampleConcurrentTransactions() {
140
- const pool = mysql.createPool({
141
- host: 'localhost',
142
- port: 3306,
143
- user: 'root',
144
- password: 'password',
145
- database: 'test_db',
146
- connectionLimit: 10
147
- });
148
-
149
- const queryHandler = new QueryHandler(pool);
150
-
151
- try {
152
- // 并发执行多个事务
153
- const results = await Promise.all([
154
- // 事务 1
155
- (async () => {
156
- const tx = await queryHandler.beginTransaction();
157
- try {
158
- await tx.table('users').insert({ name: 'User1', age: 20 });
159
- await tx.commit();
160
- return 'Transaction 1 completed';
161
- } catch (err) {
162
- await tx.rollback();
163
- throw err;
164
- }
165
- })(),
166
-
167
- // 事务 2
168
- (async () => {
169
- const tx = await queryHandler.beginTransaction();
170
- try {
171
- await tx.table('users').insert({ name: 'User2', age: 21 });
172
- await tx.commit();
173
- return 'Transaction 2 completed';
174
- } catch (err) {
175
- await tx.rollback();
176
- throw err;
177
- }
178
- })(),
179
-
180
- // 事务 3
181
- (async () => {
182
- const tx = await queryHandler.beginTransaction();
183
- try {
184
- await tx.table('users').insert({ name: 'User3', age: 22 });
185
- await tx.commit();
186
- return 'Transaction 3 completed';
187
- } catch (err) {
188
- await tx.rollback();
189
- throw err;
190
- }
191
- })()
192
- ]);
193
-
194
- console.log('All transactions completed:', results);
195
- } finally {
196
- await pool.end();
197
- }
198
- }
199
-
200
- /**
201
- * 最佳实践总结:
202
- *
203
- * 1. 生产环境推荐使用连接池(Pool)
204
- * 2. 使用 QueryHandler.beginTransaction() 自动管理连接
205
- * 3. 始终在 try-catch-finally 中使用事务
206
- * 4. 确保调用 commit() 或 rollback()
207
- * 5. 连接池会自动释放连接,无需手动管理
208
- * 6. 避免在事务中执行长时间运行的操作
209
- * 7. 根据需要选择合适的隔离级别:
210
- * - 'RU' / 'READ UNCOMMITTED': 最低隔离级别,性能最好,可能读到脏数据
211
- * - 'RC' / 'READ COMMITTED': 避免脏读
212
- * - 'RR' / 'REPEATABLE READ': MySQL 默认级别,避免不可重复读
213
- * - 'S' / 'SERIALIZABLE': 最高隔离级别,完全串行化,性能最差
214
- */
215
-
216
- // 运行示例(取消注释以运行)
217
- // exampleWithPool().catch(console.error);
218
- // exampleWithSingleConnection().catch(console.error);
219
- // exampleWithTransactionHandler().catch(console.error);
220
- // exampleConcurrentTransactions().catch(console.error);
221
-
222
- module.exports = {
223
- exampleWithPool,
224
- exampleWithSingleConnection,
225
- exampleWithTransactionHandler,
226
- exampleConcurrentTransactions
227
- };
228
-