@axiosleo/orm-mysql 0.9.5 → 0.9.7
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/.vscode/extensions.json +15 -0
- package/README.md +1 -0
- package/bin/orm-mysql.js +1 -1
- package/examples/migration/1706764048.init.js +8 -18
- package/index.d.ts +32 -23
- package/package.json +15 -13
- package/src/builder.js +64 -22
- package/src/migration.d.ts +11 -0
- package/src/migration.js +4 -4
- package/src/query.js +43 -12
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
"vue.vscode-typescript-vue-plugin",
|
|
12
|
+
"octref.vetur",
|
|
13
|
+
"pflannery.vscode-versionlens"
|
|
14
|
+
]
|
|
15
|
+
}
|
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
[](https://npmjs.org/package/@axiosleo/orm-mysql)
|
|
5
5
|
[](https://npmjs.org/package/@axiosleo/orm-mysql)
|
|
6
|
+
[](http://nodejs.org/download/)
|
|
6
7
|
[](LICENSE)
|
|
7
8
|
[](https://app.fossa.com/projects/git%2Bgithub.com%2FAxiosLeo%2Fnode-orm-mysql?ref=badge_shield)
|
|
8
9
|
|
package/bin/orm-mysql.js
CHANGED
|
@@ -69,10 +69,18 @@ function up(migration) {
|
|
|
69
69
|
account_id: {
|
|
70
70
|
type: 'int',
|
|
71
71
|
allowNull: false,
|
|
72
|
+
references: {
|
|
73
|
+
table: 'account',
|
|
74
|
+
column: 'id'
|
|
75
|
+
}
|
|
72
76
|
},
|
|
73
77
|
org_id: {
|
|
74
78
|
type: 'int',
|
|
75
79
|
allowNull: false,
|
|
80
|
+
references: {
|
|
81
|
+
table: 'orgs',
|
|
82
|
+
column: 'id'
|
|
83
|
+
}
|
|
76
84
|
},
|
|
77
85
|
type: {
|
|
78
86
|
type: 'varchar',
|
|
@@ -83,24 +91,6 @@ function up(migration) {
|
|
|
83
91
|
}
|
|
84
92
|
});
|
|
85
93
|
migration.createColumn('created_at', 'TIMESTAMP', 'account_orgs');
|
|
86
|
-
migration.createForeignKey({
|
|
87
|
-
tableName: 'account_orgs',
|
|
88
|
-
columnName: 'account_id',
|
|
89
|
-
reference: {
|
|
90
|
-
tableName: 'account',
|
|
91
|
-
columnName: 'id',
|
|
92
|
-
onDelete: 'CASCADE'
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
migration.createForeignKey({
|
|
96
|
-
tableName: 'account_orgs',
|
|
97
|
-
columnName: 'org_id',
|
|
98
|
-
reference: {
|
|
99
|
-
tableName: 'orgs',
|
|
100
|
-
columnName: 'id',
|
|
101
|
-
onDelete: 'CASCADE'
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
94
|
}
|
|
105
95
|
|
|
106
96
|
/**
|
package/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
PoolOptions,
|
|
6
6
|
QueryOptions,
|
|
7
7
|
RowDataPacket,
|
|
8
|
+
ResultSetHeader,
|
|
8
9
|
ConnectionOptions
|
|
9
10
|
} from 'mysql2';
|
|
10
11
|
|
|
@@ -12,6 +13,8 @@ import {
|
|
|
12
13
|
Connection as PromiseConnection,
|
|
13
14
|
} from 'mysql2/promise';
|
|
14
15
|
|
|
16
|
+
type MySQLQueryResult = OkPacket | ResultSetHeader;
|
|
17
|
+
|
|
15
18
|
export type Clients = {
|
|
16
19
|
[key: string]: Connection | Pool
|
|
17
20
|
}
|
|
@@ -34,13 +37,16 @@ export interface OrderByOptions {
|
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
export type OperatorType = 'select' | 'find' | 'insert' | 'update' | 'delete' | 'count';
|
|
40
|
+
export type CascadeType = 'RESTRICT' | 'CASCADE' | 'SET NULL' | 'NO ACTION' | 'restrict' | 'cascade' | 'set null' | 'no action';
|
|
41
|
+
export type JoinType = 'left' | 'right' | 'inner' | 'LEFT' | 'RIGHT' | 'INNER';
|
|
37
42
|
|
|
38
43
|
export interface JoinOption {
|
|
39
44
|
table: string | Query;
|
|
40
45
|
table_alias?: string;
|
|
41
|
-
self_column
|
|
42
|
-
foreign_column
|
|
43
|
-
join_type?:
|
|
46
|
+
self_column?: string;
|
|
47
|
+
foreign_column?: string;
|
|
48
|
+
join_type?: JoinType;
|
|
49
|
+
on?: string;
|
|
44
50
|
}
|
|
45
51
|
|
|
46
52
|
export interface TableOption {
|
|
@@ -54,7 +60,7 @@ export type QueryOperatorBaseOptions = {
|
|
|
54
60
|
};
|
|
55
61
|
|
|
56
62
|
export type AttrSubQuery = () => Query;
|
|
57
|
-
export type Attr = string | AttrSubQuery;
|
|
63
|
+
export type Attr = string | AttrSubQuery | Query;
|
|
58
64
|
|
|
59
65
|
export type QueryOperatorOptions = QueryOperatorBaseOptions & {
|
|
60
66
|
conditions: WhereOptions[];
|
|
@@ -108,9 +114,15 @@ export declare class Query {
|
|
|
108
114
|
set(data: any): this;
|
|
109
115
|
|
|
110
116
|
join(opt: JoinOption): this;
|
|
117
|
+
|
|
118
|
+
leftJoin(table: string, on: string, options?: { alias?: string }): this;
|
|
119
|
+
|
|
120
|
+
rightJoin(table: string, on: string, options?: { alias?: string }): this;
|
|
121
|
+
|
|
122
|
+
innerJoin(table: string, on: string, options?: { alias?: string }): this;
|
|
111
123
|
}
|
|
112
124
|
|
|
113
|
-
export type QueryResult = any | undefined | RowDataPacket[] | RowDataPacket |
|
|
125
|
+
export type QueryResult = any | undefined | RowDataPacket[] | RowDataPacket | MySQLQueryResult;
|
|
114
126
|
|
|
115
127
|
export declare class QueryOperator extends Query {
|
|
116
128
|
conn: Connection | Pool;
|
|
@@ -126,9 +138,9 @@ export declare class QueryOperator extends Query {
|
|
|
126
138
|
|
|
127
139
|
find<T>(): Promise<T>;
|
|
128
140
|
|
|
129
|
-
update(data?: any): Promise<
|
|
141
|
+
update(data?: any): Promise<MySQLQueryResult>;
|
|
130
142
|
|
|
131
|
-
insert(data?: any): Promise<
|
|
143
|
+
insert(data?: any): Promise<MySQLQueryResult>;
|
|
132
144
|
|
|
133
145
|
count(): Promise<number>;
|
|
134
146
|
|
|
@@ -137,7 +149,7 @@ export declare class QueryOperator extends Query {
|
|
|
137
149
|
* @param id
|
|
138
150
|
* @param index_field_name default is 'id'
|
|
139
151
|
*/
|
|
140
|
-
delete(id?: number, index_field_name?: string): Promise<
|
|
152
|
+
delete(id?: number, index_field_name?: string): Promise<MySQLQueryResult>;
|
|
141
153
|
}
|
|
142
154
|
|
|
143
155
|
export declare class QueryHandler {
|
|
@@ -165,7 +177,7 @@ export declare class QueryHandler {
|
|
|
165
177
|
* @param data
|
|
166
178
|
* @param condition
|
|
167
179
|
*/
|
|
168
|
-
upsert(tableName: string, data: any, condition: Record<string, ConditionValueType>): Promise<
|
|
180
|
+
upsert(tableName: string, data: any, condition: Record<string, ConditionValueType>): Promise<MySQLQueryResult>;
|
|
169
181
|
|
|
170
182
|
/**
|
|
171
183
|
* @param database default is options.database
|
|
@@ -211,7 +223,7 @@ export declare class TransactionHandler {
|
|
|
211
223
|
|
|
212
224
|
rollback(): Promise<void>;
|
|
213
225
|
|
|
214
|
-
upsert(tableName: string, data: any, condition: Record<string, ConditionValueType>): Promise<
|
|
226
|
+
upsert(tableName: string, data: any, condition: Record<string, ConditionValueType>): Promise<MySQLQueryResult>;
|
|
215
227
|
}
|
|
216
228
|
|
|
217
229
|
export function createClient(options: ConnectionOptions, name?: string | null | undefined): Connection;
|
|
@@ -299,7 +311,13 @@ interface ColumnItem {
|
|
|
299
311
|
comment?: string,
|
|
300
312
|
autoIncrement?: boolean,
|
|
301
313
|
primaryKey?: boolean,
|
|
302
|
-
uniqIndex?: boolean
|
|
314
|
+
uniqIndex?: boolean,
|
|
315
|
+
references?: {
|
|
316
|
+
table: string,
|
|
317
|
+
column: string,
|
|
318
|
+
onDelete?: CascadeType,
|
|
319
|
+
onUpdate?: CascadeType
|
|
320
|
+
}
|
|
303
321
|
}
|
|
304
322
|
|
|
305
323
|
interface CreateColumnOptions {
|
|
@@ -319,12 +337,6 @@ interface CreateIndexOptions {
|
|
|
319
337
|
spatial?: boolean
|
|
320
338
|
}
|
|
321
339
|
|
|
322
|
-
export type ManageBuilderOptions = {
|
|
323
|
-
operator: 'create' | 'drop' | 'alter';
|
|
324
|
-
columns: Record<string, ColumnItem>;
|
|
325
|
-
target: 'table' | 'column' | 'index' | 'foreign_key';
|
|
326
|
-
}
|
|
327
|
-
|
|
328
340
|
export declare class MigrationInterface {
|
|
329
341
|
|
|
330
342
|
/**
|
|
@@ -348,7 +360,7 @@ export declare class MigrationInterface {
|
|
|
348
360
|
unsigned?: boolean,
|
|
349
361
|
allowNull?: boolean,
|
|
350
362
|
default?: string | number | boolean | null | 'timestamp',
|
|
351
|
-
onUpdate?:
|
|
363
|
+
onUpdate?: boolean,
|
|
352
364
|
comment?: string,
|
|
353
365
|
autoIncrement?: boolean,
|
|
354
366
|
primaryKey?: boolean,
|
|
@@ -370,8 +382,8 @@ export declare class MigrationInterface {
|
|
|
370
382
|
reference: {
|
|
371
383
|
tableName: string,
|
|
372
384
|
columnName: string,
|
|
373
|
-
onDelete?:
|
|
374
|
-
onUpdate?:
|
|
385
|
+
onDelete?: CascadeType,
|
|
386
|
+
onUpdate?: CascadeType,
|
|
375
387
|
}
|
|
376
388
|
}): void;
|
|
377
389
|
|
|
@@ -383,6 +395,3 @@ export declare class MigrationInterface {
|
|
|
383
395
|
|
|
384
396
|
dropForeignKey(foreign_key: string, tableName: string): void;
|
|
385
397
|
}
|
|
386
|
-
|
|
387
|
-
export declare function up(migration: MigrationInterface): Promise<void>;
|
|
388
|
-
export declare function down(migration: MigrationInterface): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axiosleo/orm-mysql",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.7",
|
|
4
4
|
"description": "MySQL ORM tool",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mysql",
|
|
@@ -19,12 +19,15 @@
|
|
|
19
19
|
"test-cov": "nyc -r=lcov -r=html -r=text -r=json mocha -t 10000 -R spec tests/*.tests.js",
|
|
20
20
|
"test-one": "mocha --reporter spec --timeout 3000 ",
|
|
21
21
|
"ci": "npm run lint && npm run test-cov",
|
|
22
|
-
"clear": "rm -rf ./nyc_output ./coverage"
|
|
22
|
+
"clear": "rm -rf ./nyc_output ./coverage && rm -rf ./node_modules && npm cache clean --force"
|
|
23
23
|
},
|
|
24
24
|
"license": "MIT",
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=16.0.0"
|
|
27
|
+
},
|
|
25
28
|
"dependencies": {
|
|
26
|
-
"@axiosleo/cli-tool": "^1.6.
|
|
27
|
-
"mysql2": "^
|
|
29
|
+
"@axiosleo/cli-tool": "^1.6.1",
|
|
30
|
+
"mysql2": "^3.9.1",
|
|
28
31
|
"validatorjs": "^3.22.1"
|
|
29
32
|
},
|
|
30
33
|
"repository": {
|
|
@@ -32,19 +35,18 @@
|
|
|
32
35
|
"url": "https://github.com/AxiosLeo/node-orm-mysql"
|
|
33
36
|
},
|
|
34
37
|
"devDependencies": {
|
|
35
|
-
"@types/node": "^20.
|
|
36
|
-
"chai": "^
|
|
37
|
-
"
|
|
38
|
-
"eslint": "^7.0",
|
|
38
|
+
"@types/node": "^20.11.16",
|
|
39
|
+
"chai": "^5.0.3",
|
|
40
|
+
"eslint": "^8.56.0",
|
|
39
41
|
"expect.js": "^0.3.1",
|
|
40
|
-
"has-flag": "^
|
|
41
|
-
"mm": "^3.
|
|
42
|
-
"mocha": "^
|
|
42
|
+
"has-flag": "^5.0.1",
|
|
43
|
+
"mm": "^3.4.0",
|
|
44
|
+
"mocha": "^10.2.0",
|
|
43
45
|
"mocha-sinon": "^2.1.2",
|
|
44
46
|
"nyc": "^15.1.0",
|
|
45
47
|
"pre-commit": "^1.2.2",
|
|
46
|
-
"sinon": "^
|
|
47
|
-
"typescript": "^
|
|
48
|
+
"sinon": "^17.0.1",
|
|
49
|
+
"typescript": "^5.3.3"
|
|
48
50
|
},
|
|
49
51
|
"pre-commit": {
|
|
50
52
|
"silent": false,
|
package/src/builder.js
CHANGED
|
@@ -17,6 +17,8 @@ const emit = (arr, res) => {
|
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
+
const operations = ['find', 'select', 'insert', 'update', 'delete', 'count', 'manage'];
|
|
21
|
+
|
|
20
22
|
class Builder {
|
|
21
23
|
/**
|
|
22
24
|
* @param {import('../index').QueryOperatorOptions} options
|
|
@@ -35,13 +37,15 @@ class Builder {
|
|
|
35
37
|
options.attrs = options.attrs || [];
|
|
36
38
|
const attrs = options.attrs.map((attr) => {
|
|
37
39
|
if (attr instanceof Function) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
attr = attr();
|
|
41
|
+
}
|
|
42
|
+
if (attr instanceof Query) {
|
|
43
|
+
const builder = new Builder(attr.options);
|
|
40
44
|
this.values = this.values.concat(builder.values);
|
|
41
45
|
let s = `(${builder.sql})`;
|
|
42
|
-
if (
|
|
43
|
-
return
|
|
44
|
-
: s + ' AS ' + this._buildFieldKey(
|
|
46
|
+
if (attr.alias) {
|
|
47
|
+
return attr.alias.indexOf(' ') > -1 ? s + ' ' + this._buildFieldKey(attr.alias)
|
|
48
|
+
: s + ' AS ' + this._buildFieldKey(attr.alias);
|
|
45
49
|
}
|
|
46
50
|
return s;
|
|
47
51
|
}
|
|
@@ -71,6 +75,9 @@ class Builder {
|
|
|
71
75
|
break;
|
|
72
76
|
}
|
|
73
77
|
case 'update': {
|
|
78
|
+
if (is.invalid(options.data)) {
|
|
79
|
+
throw new Error('Data is required for update operation');
|
|
80
|
+
}
|
|
74
81
|
const fields = this._buildValues(options.data);
|
|
75
82
|
emit(tmp, `UPDATE ${this._buildTables(options.tables)}`);
|
|
76
83
|
emit(tmp, `SET ${fields.map((f) => `\`${f}\` = ?`).join(',')}`);
|
|
@@ -95,7 +102,7 @@ class Builder {
|
|
|
95
102
|
emit(tmp, this._buildJoins(options.joins));
|
|
96
103
|
emit(tmp, this._buildCondition(options.conditions));
|
|
97
104
|
if (options.having && options.having.length && !options.groupField.length) {
|
|
98
|
-
throw new Error('
|
|
105
|
+
throw new Error('"HAVING" is not allowed without "GROUP BY"');
|
|
99
106
|
}
|
|
100
107
|
emit(tmp, this._buildGroupField(options.groupField));
|
|
101
108
|
emit(tmp, this._buildHaving(options.having));
|
|
@@ -154,7 +161,11 @@ class Builder {
|
|
|
154
161
|
sql = 'INNER JOIN ';
|
|
155
162
|
break;
|
|
156
163
|
}
|
|
157
|
-
|
|
164
|
+
if (j.on) {
|
|
165
|
+
sql += `${table} ON ${j.on}`;
|
|
166
|
+
} else {
|
|
167
|
+
sql += `${table} ON ${this._buildFieldWithTableName(self_column)} = ${this._buildFieldWithTableName(foreign_column)}`;
|
|
168
|
+
}
|
|
158
169
|
return sql;
|
|
159
170
|
}).join(' ');
|
|
160
171
|
}
|
|
@@ -326,21 +337,24 @@ class Builder {
|
|
|
326
337
|
|
|
327
338
|
class ManageSQLBuilder extends Builder {
|
|
328
339
|
/**
|
|
329
|
-
* @param {import('
|
|
340
|
+
* @param {import('./migration').ManageBuilderOptions} options
|
|
330
341
|
*/
|
|
331
342
|
constructor(options) {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
343
|
+
if (operations.indexOf(options.operator) > -1) {
|
|
344
|
+
super(options);
|
|
345
|
+
} else {
|
|
346
|
+
super({ operator: 'manage' });
|
|
347
|
+
const action = `${options.operator}_${options.target}`;
|
|
348
|
+
const method = _caml_case(action, false);
|
|
349
|
+
if (!this[method]) {
|
|
350
|
+
throw new Error(`'${options.target}' Unsupported '${options.operator}' operation.`);
|
|
351
|
+
}
|
|
352
|
+
try {
|
|
353
|
+
this.sql = this[method].call(this, options);
|
|
354
|
+
} catch (err) {
|
|
355
|
+
debug.dump(`${options.operator} ${options.target} error: ${err.message}`);
|
|
356
|
+
throw err;
|
|
357
|
+
}
|
|
344
358
|
}
|
|
345
359
|
}
|
|
346
360
|
|
|
@@ -366,7 +380,7 @@ class ManageSQLBuilder extends Builder {
|
|
|
366
380
|
engine: 'InnoDB',
|
|
367
381
|
charset: 'utf8mb4'
|
|
368
382
|
}, options, {
|
|
369
|
-
columns: this.createColumns(columns)
|
|
383
|
+
columns: this.createColumns(columns, options.name)
|
|
370
384
|
});
|
|
371
385
|
return _render('CREATE TABLE `${name}` ( ${columns} ) ENGINE=${engine} DEFAULT CHARSET=${charset}', options);
|
|
372
386
|
}
|
|
@@ -468,9 +482,10 @@ class ManageSQLBuilder extends Builder {
|
|
|
468
482
|
return _render('ALTER TABLE `${table}` DROP FOREIGN KEY `${name}`', options);
|
|
469
483
|
}
|
|
470
484
|
|
|
471
|
-
createColumns(columns) {
|
|
485
|
+
createColumns(columns, table) {
|
|
472
486
|
let primaryColumn = null;
|
|
473
487
|
let indexColumns = [];
|
|
488
|
+
let referenceColumns = [];
|
|
474
489
|
let strs = columns.map(column => {
|
|
475
490
|
let str = this.renderSingleColumn(column);
|
|
476
491
|
if (column.primaryKey === true) {
|
|
@@ -478,6 +493,28 @@ class ManageSQLBuilder extends Builder {
|
|
|
478
493
|
} else if (column.uniqIndex === true) {
|
|
479
494
|
indexColumns.push(column);
|
|
480
495
|
}
|
|
496
|
+
if (column.reference) {
|
|
497
|
+
column.reference.onDelete = column.reference.onDelete ? column.reference.onDelete.toUpperCase() : 'NO ACTION';
|
|
498
|
+
column.reference.onUpdate = column.reference.onUpdate ? column.reference.onUpdate.toUpperCase() : 'NO ACTION';
|
|
499
|
+
|
|
500
|
+
_validate(column.reference, {
|
|
501
|
+
table: 'required|string',
|
|
502
|
+
column: 'required|string',
|
|
503
|
+
onDelete: [{ in: ['RESTRICT', 'CASCADE', 'SET NULL', 'NO ACTION'] }],
|
|
504
|
+
onUpdate: [{ in: ['RESTRICT', 'CASCADE', 'SET NULL', 'NO ACTION'] }]
|
|
505
|
+
});
|
|
506
|
+
referenceColumns.push({
|
|
507
|
+
name: 'fk_' + table + '_' + column.name,
|
|
508
|
+
table,
|
|
509
|
+
column: column.name,
|
|
510
|
+
reference: {
|
|
511
|
+
tableName: column.reference.table,
|
|
512
|
+
columnName: column.reference.column,
|
|
513
|
+
onDelete: column.reference.onDelete,
|
|
514
|
+
onUpdate: column.reference.onUpdate
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
}
|
|
481
518
|
return str;
|
|
482
519
|
});
|
|
483
520
|
if (primaryColumn) {
|
|
@@ -489,6 +526,11 @@ class ManageSQLBuilder extends Builder {
|
|
|
489
526
|
strs.push(`UNIQUE INDEX \`${i.name}\` (\`${i.name}\` ASC) VISIBLE`);
|
|
490
527
|
});
|
|
491
528
|
}
|
|
529
|
+
if (referenceColumns.length) {
|
|
530
|
+
referenceColumns.forEach((r) => {
|
|
531
|
+
strs.push(this.createForeignKey(r));
|
|
532
|
+
});
|
|
533
|
+
}
|
|
492
534
|
return strs.join(', ');
|
|
493
535
|
}
|
|
494
536
|
|
package/src/migration.d.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
|
+
import { ColumnItem } from '../index';
|
|
2
|
+
|
|
1
3
|
type QueryItem = {
|
|
2
4
|
sql: string,
|
|
3
5
|
values: any[],
|
|
4
6
|
};
|
|
5
7
|
|
|
8
|
+
export type ManageBuilderOptions = {
|
|
9
|
+
operator: 'create' | 'drop' | 'alter';
|
|
10
|
+
columns: Record<string, ColumnItem>;
|
|
11
|
+
target: 'table' | 'column' | 'index' | 'foreign_key';
|
|
12
|
+
name?: string;
|
|
13
|
+
engine?: 'InnoDB' | 'MyISAM' | 'MEMORY',
|
|
14
|
+
charset?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
6
17
|
export type Context = {
|
|
7
18
|
action: 'up' | 'down',
|
|
8
19
|
connection: {
|
package/src/migration.js
CHANGED
|
@@ -114,16 +114,16 @@ async function _exec(context, queries) {
|
|
|
114
114
|
try {
|
|
115
115
|
const files = Object.keys(queries);
|
|
116
116
|
await _foreach(files, async (file) => {
|
|
117
|
-
const
|
|
117
|
+
const hasMigrated = await transaction.table(context.task_key)
|
|
118
118
|
.where('migration_key', context.task_key)
|
|
119
119
|
.where('filename', file)
|
|
120
120
|
.count();
|
|
121
|
-
if (context.action === 'up' &&
|
|
122
|
-
if (
|
|
121
|
+
if (context.action === 'up' && hasMigrated) {
|
|
122
|
+
if (hasMigrated) {
|
|
123
123
|
printer.yellow(`Migration file "${file}" has been migrated.`).println();
|
|
124
124
|
return;
|
|
125
125
|
}
|
|
126
|
-
} else if (context.action === 'down' && !
|
|
126
|
+
} else if (context.action === 'down' && !hasMigrated) {
|
|
127
127
|
return;
|
|
128
128
|
}
|
|
129
129
|
|
package/src/query.js
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { _assign } = require('@axiosleo/cli-tool/src/helper/obj');
|
|
4
|
+
const { _validate } = require('./utils');
|
|
5
|
+
const is = require('@axiosleo/cli-tool/src/helper/is');
|
|
6
|
+
|
|
7
|
+
function joinOn(table, on, options = {}) {
|
|
8
|
+
let o = _assign({ alias: null, join_type: 'INNER', table, on }, options);
|
|
9
|
+
if (!table) {
|
|
10
|
+
throw new Error('table is required');
|
|
11
|
+
}
|
|
12
|
+
if (!on) {
|
|
13
|
+
throw new Error('on is required');
|
|
14
|
+
}
|
|
15
|
+
this.options.joins.push(o);
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
|
|
3
19
|
class Query {
|
|
4
20
|
constructor(operator = 'select', alias = null) {
|
|
5
21
|
this.options = {
|
|
@@ -109,6 +125,10 @@ class Query {
|
|
|
109
125
|
}
|
|
110
126
|
|
|
111
127
|
attr(...attr) {
|
|
128
|
+
if (attr.length === 1 && is.array(attr)) {
|
|
129
|
+
this.options.attrs = attr;
|
|
130
|
+
return this;
|
|
131
|
+
}
|
|
112
132
|
if (!attr.length) {
|
|
113
133
|
return this;
|
|
114
134
|
}
|
|
@@ -164,22 +184,33 @@ class Query {
|
|
|
164
184
|
* @returns
|
|
165
185
|
*/
|
|
166
186
|
join(opt = {}) {
|
|
187
|
+
let types = ['left', 'right', 'inner'];
|
|
188
|
+
opt.join_type = opt.join_type ? opt.join_type.toLowerCase() : 'inner';
|
|
189
|
+
if (types.indexOf(opt.join_type) === -1) {
|
|
190
|
+
throw new Error('Invalid join type : ' + opt.join_type + '; only supported ' + types.join(', '));
|
|
191
|
+
}
|
|
192
|
+
_validate(opt, {
|
|
193
|
+
table: 'required',
|
|
194
|
+
self_column: 'required',
|
|
195
|
+
foreign_column: 'required_if:on',
|
|
196
|
+
join_type: [{ in: types }]
|
|
197
|
+
});
|
|
167
198
|
let { table, table_alias, self_column, foreign_column, join_type } = opt;
|
|
168
|
-
if (!table) {
|
|
169
|
-
throw new Error('table is required');
|
|
170
|
-
}
|
|
171
|
-
if (!self_column) {
|
|
172
|
-
throw new Error('self_column is required');
|
|
173
|
-
}
|
|
174
|
-
if (!foreign_column) {
|
|
175
|
-
throw new Error('foreign_column is required');
|
|
176
|
-
}
|
|
177
|
-
if (join_type && ['left', 'right', 'inner'].indexOf(join_type) === -1) {
|
|
178
|
-
throw new Error('Invalid join type : ' + join_type + '; only supported left, right, inner');
|
|
179
|
-
}
|
|
180
199
|
this.options.joins.push({ table, alias: table_alias, self_column, foreign_column, join_type });
|
|
181
200
|
return this;
|
|
182
201
|
}
|
|
202
|
+
|
|
203
|
+
leftJoin(table, on, options = {}) {
|
|
204
|
+
return joinOn.call(this, table, on, { ...options, join_type: 'LEFT' });
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
rightJoin(table, on, options = {}) {
|
|
208
|
+
return joinOn.call(this, table, on, { ...options, join_type: 'RIGHT' });
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
innerJoin(table, on, options = {}) {
|
|
212
|
+
return joinOn.call(this, table, on, { ...options, join_type: 'INNER' });
|
|
213
|
+
}
|
|
183
214
|
}
|
|
184
215
|
|
|
185
216
|
module.exports = Query;
|