baja-lite 1.0.4 → 1.0.5
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/cjs/boot-remote.d.ts +2 -0
- package/cjs/boot-remote.js +35 -0
- package/cjs/boot.d.ts +2 -0
- package/cjs/boot.js +152 -0
- package/cjs/code.d.ts +1 -0
- package/cjs/code.js +345 -1
- package/cjs/convert-xml.d.ts +10 -0
- package/cjs/convert-xml.js +413 -0
- package/cjs/enum.d.ts +10 -0
- package/cjs/enum.js +32 -0
- package/cjs/error.js +1 -1
- package/cjs/index.d.ts +2 -0
- package/cjs/index.js +2 -0
- package/cjs/object.d.ts +7 -1
- package/cjs/object.js +36 -2
- package/cjs/sql.d.ts +405 -148
- package/cjs/sql.js +1229 -861
- package/cjs/sqlite.d.ts +38 -0
- package/cjs/sqlite.js +194 -0
- package/cjs/test-mysql.d.ts +1 -1
- package/cjs/test-mysql.js +72 -63
- package/cjs/test-sqlite.d.ts +1 -1
- package/cjs/test-sqlite.js +3 -1
- package/cjs/test-xml.d.ts +1 -0
- package/cjs/test-xml.js +75 -0
- package/es/boot-remote.d.ts +2 -0
- package/es/boot-remote.js +31 -0
- package/es/boot.d.ts +2 -0
- package/es/boot.js +125 -0
- package/es/code.d.ts +1 -0
- package/es/code.js +341 -2
- package/es/convert-xml.d.ts +10 -0
- package/es/convert-xml.js +409 -0
- package/es/enum.d.ts +10 -0
- package/es/enum.js +28 -0
- package/es/error.js +1 -1
- package/es/index.d.ts +2 -0
- package/es/index.js +2 -0
- package/es/object.d.ts +7 -1
- package/es/object.js +28 -1
- package/es/sql.d.ts +405 -148
- package/es/sql.js +1099 -735
- package/es/sqlite.d.ts +38 -0
- package/es/sqlite.js +164 -0
- package/es/test-mysql.d.ts +1 -1
- package/es/test-mysql.js +72 -63
- package/es/test-sqlite.d.ts +1 -1
- package/es/test-sqlite.js +3 -1
- package/es/test-xml.d.ts +1 -0
- package/es/test-xml.js +70 -0
- package/package.json +10 -7
- package/src/boot-remote.ts +31 -0
- package/src/boot.ts +129 -0
- package/src/code.ts +326 -1
- package/src/convert-xml.ts +461 -0
- package/src/enum.ts +31 -0
- package/src/error.ts +1 -1
- package/src/index.ts +3 -1
- package/src/object.ts +47 -14
- package/src/sql.ts +1145 -787
- package/src/sqlite.ts +161 -0
- package/src/test-mysql.ts +72 -63
- package/src/test-sqlite.ts +3 -1
- package/src/test-xml.ts +70 -0
- package/cjs/constant.d.ts +0 -13
- package/cjs/constant.js +0 -19
- package/cjs/redis.d.ts +0 -0
- package/cjs/redis.js +0 -1
- package/es/constant.d.ts +0 -13
- package/es/constant.js +0 -16
- package/es/redis.d.ts +0 -0
- package/es/redis.js +0 -1
- package/src/constant.ts +0 -14
- package/src/redis.ts +0 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BootRomote = void 0;
|
|
4
|
+
const sql_1 = require("./sql");
|
|
5
|
+
const BootRomote = async function (options) {
|
|
6
|
+
globalThis[sql_1._GlobalSqlOption] = Object.assign({}, sql_1._defOption, options);
|
|
7
|
+
globalThis[sql_1._Hump] = globalThis[sql_1._GlobalSqlOption].columnMode === sql_1.ColumnMode.HUMP;
|
|
8
|
+
sql_1.logger.level = options.log ?? 'info';
|
|
9
|
+
globalThis[sql_1._sqlCache] = new sql_1.SqlCache();
|
|
10
|
+
if (options.sqlMap) {
|
|
11
|
+
await globalThis[sql_1._sqlCache].init(options);
|
|
12
|
+
}
|
|
13
|
+
globalThis[sql_1._dao] = {
|
|
14
|
+
[sql_1.DBType.SqliteRemote]: {},
|
|
15
|
+
};
|
|
16
|
+
if (options.SqliteRemote) {
|
|
17
|
+
if (typeof options.SqliteRemote.db === 'string') {
|
|
18
|
+
await options.SqliteRemote.service.initDB(options.SqliteRemote.db);
|
|
19
|
+
globalThis[sql_1._dao][sql_1.DBType.SqliteRemote][sql_1._primaryDB] = new sql_1.SqliteRemote(options.SqliteRemote.service, options.SqliteRemote.db);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
let flag = false;
|
|
23
|
+
for (const [key, fileName] of Object.entries(options.SqliteRemote.db)) {
|
|
24
|
+
await options.SqliteRemote.service.initDB(fileName);
|
|
25
|
+
const db = new sql_1.SqliteRemote(options.SqliteRemote.service, fileName);
|
|
26
|
+
if (flag === false) {
|
|
27
|
+
globalThis[sql_1._dao][sql_1.DBType.SqliteRemote][sql_1._primaryDB] = db;
|
|
28
|
+
flag = true;
|
|
29
|
+
}
|
|
30
|
+
globalThis[sql_1._dao][sql_1.DBType.SqliteRemote][key] = db;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
exports.BootRomote = BootRomote;
|
package/cjs/boot.d.ts
ADDED
package/cjs/boot.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.Boot = void 0;
|
|
27
|
+
const sql_1 = require("./sql");
|
|
28
|
+
const Boot = async function (options) {
|
|
29
|
+
globalThis[sql_1._GlobalSqlOption] = Object.assign({}, sql_1._defOption, options);
|
|
30
|
+
globalThis[sql_1._Hump] = globalThis[sql_1._GlobalSqlOption].columnMode === sql_1.ColumnMode.HUMP;
|
|
31
|
+
if (options.sqlDir) {
|
|
32
|
+
globalThis[sql_1._path] = await Promise.resolve().then(() => __importStar(require('path')));
|
|
33
|
+
globalThis[sql_1._fs] = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
34
|
+
}
|
|
35
|
+
sql_1.logger.level = options.log ?? 'info';
|
|
36
|
+
globalThis[sql_1._sqlCache] = new sql_1.SqlCache();
|
|
37
|
+
if (options.sqlMap || options.sqlDir) {
|
|
38
|
+
await globalThis[sql_1._sqlCache].init(options);
|
|
39
|
+
}
|
|
40
|
+
globalThis[sql_1._dao] = {
|
|
41
|
+
[sql_1.DBType.Mongo]: {},
|
|
42
|
+
[sql_1.DBType.Mysql]: {},
|
|
43
|
+
[sql_1.DBType.Sqlite]: {},
|
|
44
|
+
[sql_1.DBType.SqliteRemote]: {},
|
|
45
|
+
[sql_1.DBType.Redis]: {}
|
|
46
|
+
};
|
|
47
|
+
if (options.Mysql) {
|
|
48
|
+
const { createPool } = await Promise.resolve().then(() => __importStar(require('mysql2/promise')));
|
|
49
|
+
if (options.Mysql['host']) {
|
|
50
|
+
globalThis[sql_1._dao][sql_1.DBType.Mysql][sql_1._primaryDB] = new sql_1.Mysql(createPool({
|
|
51
|
+
...options.Mysql,
|
|
52
|
+
multipleStatements: true,
|
|
53
|
+
decimalNumbers: true,
|
|
54
|
+
supportBigNumbers: true
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
let flag = false;
|
|
59
|
+
for (const [key, option] of Object.entries(options.Mysql)) {
|
|
60
|
+
const db = new sql_1.Mysql(createPool({
|
|
61
|
+
...option,
|
|
62
|
+
multipleStatements: true,
|
|
63
|
+
decimalNumbers: true,
|
|
64
|
+
supportBigNumbers: true
|
|
65
|
+
}));
|
|
66
|
+
if (flag === false) {
|
|
67
|
+
globalThis[sql_1._dao][sql_1.DBType.Mysql][sql_1._primaryDB] = db;
|
|
68
|
+
flag = true;
|
|
69
|
+
}
|
|
70
|
+
globalThis[sql_1._dao][sql_1.DBType.Mysql][key] = db;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (options.Sqlite) {
|
|
75
|
+
const BetterSqlite3 = await Promise.resolve().then(() => __importStar(require('better-sqlite3')));
|
|
76
|
+
if (typeof options.Sqlite === 'string') {
|
|
77
|
+
globalThis[sql_1._dao][sql_1.DBType.Sqlite][sql_1._primaryDB] = new sql_1.Sqlite(new BetterSqlite3.default(options.Sqlite, { fileMustExist: false }));
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
let flag = false;
|
|
81
|
+
for (const [key, fileName] of Object.entries(options.Sqlite)) {
|
|
82
|
+
const db = new sql_1.Sqlite(new BetterSqlite3.default(fileName, { fileMustExist: false }));
|
|
83
|
+
if (flag === false) {
|
|
84
|
+
globalThis[sql_1._dao][sql_1.DBType.Sqlite][sql_1._primaryDB] = db;
|
|
85
|
+
flag = true;
|
|
86
|
+
}
|
|
87
|
+
globalThis[sql_1._dao][sql_1.DBType.Sqlite][key] = db;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (options.SqliteRemote) {
|
|
92
|
+
if (typeof options.SqliteRemote.db === 'string') {
|
|
93
|
+
await options.SqliteRemote.service.initDB(options.SqliteRemote.db);
|
|
94
|
+
globalThis[sql_1._dao][sql_1.DBType.SqliteRemote][sql_1._primaryDB] = new sql_1.SqliteRemote(options.SqliteRemote.service, options.SqliteRemote.db);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
let flag = false;
|
|
98
|
+
for (const [key, fileName] of Object.entries(options.SqliteRemote.db)) {
|
|
99
|
+
await options.SqliteRemote.service.initDB(fileName);
|
|
100
|
+
const db = new sql_1.SqliteRemote(options.SqliteRemote.service, fileName);
|
|
101
|
+
if (flag === false) {
|
|
102
|
+
globalThis[sql_1._dao][sql_1.DBType.SqliteRemote][sql_1._primaryDB] = db;
|
|
103
|
+
flag = true;
|
|
104
|
+
}
|
|
105
|
+
globalThis[sql_1._dao][sql_1.DBType.SqliteRemote][key] = db;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (options.Redis) {
|
|
110
|
+
const { Redis } = await Promise.resolve().then(() => __importStar(require('ioredis')));
|
|
111
|
+
if (options.Redis['host']) {
|
|
112
|
+
globalThis[sql_1._dao][sql_1.DBType.Redis][sql_1._primaryDB] = new Redis(options.Redis);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
let flag = false;
|
|
116
|
+
for (const [key, option] of Object.entries(options.Redis)) {
|
|
117
|
+
const db = new Redis(option);
|
|
118
|
+
if (flag === false) {
|
|
119
|
+
globalThis[sql_1._dao][sql_1.DBType.Redis][sql_1._primaryDB] = db;
|
|
120
|
+
flag = true;
|
|
121
|
+
}
|
|
122
|
+
globalThis[sql_1._dao][sql_1.DBType.Redis][key] = db;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const clients = Object.values(globalThis[sql_1._dao][sql_1.DBType.Redis]);
|
|
126
|
+
const Redlock = await Promise.resolve().then(() => __importStar(require('redlock')));
|
|
127
|
+
globalThis[sql_1._dao][sql_1.DBType.RedisLock] = new Redlock.default(clients, {
|
|
128
|
+
// The expected clock drift; for more details see:
|
|
129
|
+
// http://redis.io/topics/distlock
|
|
130
|
+
driftFactor: 0.01, // multiplied by lock ttl to determine drift time
|
|
131
|
+
// The max number of times Redlock will attempt to lock a resource
|
|
132
|
+
// before erroring.
|
|
133
|
+
retryCount: 10,
|
|
134
|
+
// the time in ms between attempts
|
|
135
|
+
retryDelay: 200, // time in ms
|
|
136
|
+
// the max time in ms randomly added to retries
|
|
137
|
+
// to improve performance under high contention
|
|
138
|
+
// see https://www.awsarchitectureblog.com/2015/03/backoff.html
|
|
139
|
+
retryJitter: 200, // time in ms
|
|
140
|
+
// The minimum remaining time on a lock before an extension is automatically
|
|
141
|
+
// attempted with the `using` API.
|
|
142
|
+
automaticExtensionThreshold: 500, // time in ms
|
|
143
|
+
});
|
|
144
|
+
const { EventEmitter } = await Promise.resolve().then(() => __importStar(require('events')));
|
|
145
|
+
const event = new EventEmitter({ captureRejections: true });
|
|
146
|
+
event.on('error', error => {
|
|
147
|
+
sql_1.logger.error('event-bus', error);
|
|
148
|
+
});
|
|
149
|
+
globalThis[sql_1._EventBus] = event;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
exports.Boot = Boot;
|
package/cjs/code.d.ts
CHANGED
package/cjs/code.js
CHANGED
|
@@ -1,3 +1,347 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const repl_1 = require("repl");
|
|
10
|
+
const promise_1 = require("mysql2/promise");
|
|
11
|
+
const mustache_1 = __importDefault(require("mustache"));
|
|
12
|
+
const lxMap = {
|
|
13
|
+
tinyint: "number",
|
|
14
|
+
smallint: "number",
|
|
15
|
+
mediumint: "number",
|
|
16
|
+
int: "number",
|
|
17
|
+
integer: "number",
|
|
18
|
+
bigint: "BigInt",
|
|
19
|
+
bit: "boolean",
|
|
20
|
+
double: "number",
|
|
21
|
+
real: "number",
|
|
22
|
+
float: "number",
|
|
23
|
+
decimal: "number",
|
|
24
|
+
numeric: "number",
|
|
25
|
+
char: "string",
|
|
26
|
+
varchar: "string",
|
|
27
|
+
date: "Date",
|
|
28
|
+
time: "string",
|
|
29
|
+
year: "string",
|
|
30
|
+
timestamp: "BigInt",
|
|
31
|
+
datetime: "Date",
|
|
32
|
+
tinyblob: "string",
|
|
33
|
+
blob: "string",
|
|
34
|
+
mediumblob: "string",
|
|
35
|
+
longblob: "string",
|
|
36
|
+
tinytext: "string",
|
|
37
|
+
text: "string",
|
|
38
|
+
mediumtext: "string",
|
|
39
|
+
longtext: "string",
|
|
40
|
+
enum: "string",
|
|
41
|
+
set: "string",
|
|
42
|
+
binary: "string",
|
|
43
|
+
varbinary: "string",
|
|
44
|
+
point: "Object",
|
|
45
|
+
linestring: "Object",
|
|
46
|
+
polygon: "Object",
|
|
47
|
+
geometry: "string",
|
|
48
|
+
multipoint: "Object",
|
|
49
|
+
multilinestring: "Object",
|
|
50
|
+
multipolygon: "Object",
|
|
51
|
+
geometrycollection: "Object"
|
|
52
|
+
};
|
|
53
|
+
let force = false;
|
|
54
|
+
const basepath = path_1.default.join(__dirname, '..', '..', '..');
|
|
55
|
+
const config = path_1.default.join(basepath, 'baja.code.json');
|
|
56
|
+
const templatePath = path_1.default.join(basepath, 'code-template');
|
|
57
|
+
console.log(`
|
|
58
|
+
**********************-----------
|
|
59
|
+
配置文件:
|
|
60
|
+
请在项目根目录添加文件:baja.code.json!配置如下:
|
|
61
|
+
{
|
|
62
|
+
"host": "",
|
|
63
|
+
"port": "",
|
|
64
|
+
"user": "",
|
|
65
|
+
"password": "",
|
|
66
|
+
"database": "",
|
|
67
|
+
|
|
68
|
+
"command": {
|
|
69
|
+
"entity": "src/{vueName}/{vueName}.entity.ts",
|
|
70
|
+
"controller": "src/{vueName}/{vueName}.controller.ts",
|
|
71
|
+
"service": "src/{vueName}/{vueName}.service.ts",
|
|
72
|
+
"sql": "src/sql/{vueName}.mu",
|
|
73
|
+
"module": "src/{vueName}/{vueName}.module.ts"
|
|
74
|
+
},
|
|
75
|
+
"commands": {
|
|
76
|
+
"s": ["entity", "controller", "service", "sql", "module"]
|
|
77
|
+
}
|
|
78
|
+
"commands": {
|
|
79
|
+
"s": ["entity", "controller", "service", "sql", "module"]
|
|
80
|
+
},
|
|
81
|
+
"output": "{ClassName}Module",
|
|
82
|
+
}
|
|
83
|
+
command是生成命令,这里声明命令同时定义文件生成路径:可用下面的变量替换.同时必须有同名模板.
|
|
84
|
+
路径是相对于项目根目录的
|
|
85
|
+
commands是组合命令,上面表示输入s,同时生成:"entity", "controller", "service", "sql", "module"
|
|
86
|
+
output 是生成后打印出的内容
|
|
87
|
+
模板转义:<%& 变量 %>
|
|
88
|
+
**********************-----------
|
|
89
|
+
**********************-----------
|
|
90
|
+
**********************-----------
|
|
91
|
+
模板文件
|
|
92
|
+
请在项目根目录的code-template添加模板文件, 按照mustache(标签定义成了[ '<%', '%>' ])进行格式化,变量:
|
|
93
|
+
title,
|
|
94
|
+
|
|
95
|
+
tableName,
|
|
96
|
+
className,
|
|
97
|
+
ClassName,
|
|
98
|
+
vueName,
|
|
99
|
+
splitName,
|
|
100
|
+
|
|
101
|
+
columns: [
|
|
102
|
+
comment:
|
|
103
|
+
name: sku_id
|
|
104
|
+
Name: skuId
|
|
105
|
+
Field
|
|
106
|
+
Type
|
|
107
|
+
], Field(类型string),表示字段的注解, Type 表示JS类型
|
|
108
|
+
columnNames_join: 'sku_id, sku_name'
|
|
109
|
+
ColumnNames_join: 'sku_id skuId, sku_name skuName'
|
|
110
|
+
|
|
111
|
+
columns_no_id: [], 同columns,没有ID而已
|
|
112
|
+
columnNames_no_id: [],
|
|
113
|
+
|
|
114
|
+
ids: [], 参见 FieldOption,多一个参数Field,表示字段的注解, Type 表示JS类型
|
|
115
|
+
idNames: [], 主键字段数组
|
|
116
|
+
idNames_join: []
|
|
117
|
+
|
|
118
|
+
modelName: 模块名称,可能为空字符串
|
|
119
|
+
modelPath: 模块名称实际就影响访问路径,所以这里会直接拼好controller的模块访问路径,如果模块为空,则该属性就是空字符串,否则是 /模块名称/
|
|
120
|
+
-----
|
|
121
|
+
命令 table1,table2,table3:模块名称
|
|
122
|
+
table=. 表示扫描全库表
|
|
123
|
+
:模块名称 可以省略
|
|
124
|
+
-----
|
|
125
|
+
force: 切换是否覆盖
|
|
126
|
+
`);
|
|
127
|
+
try {
|
|
128
|
+
const outputs = new Set();
|
|
129
|
+
const _configData = fs_1.default.readFileSync(config, { encoding: 'utf-8' }).toString();
|
|
130
|
+
const configData = JSON.parse(_configData);
|
|
131
|
+
const templates = Object.fromEntries(fs_1.default.readdirSync(templatePath).map(r => [path_1.default.basename(r, '.mu'), fs_1.default.readFileSync(path_1.default.join(templatePath, r), { encoding: 'utf-8' }).toString()]));
|
|
132
|
+
const pool = (0, promise_1.createPool)({
|
|
133
|
+
host: configData.host,
|
|
134
|
+
port: configData.port,
|
|
135
|
+
user: configData.user,
|
|
136
|
+
password: configData.password,
|
|
137
|
+
database: configData.database
|
|
138
|
+
});
|
|
139
|
+
async function getTables(tableName) {
|
|
140
|
+
const conn = await pool.getConnection();
|
|
141
|
+
const params = [configData.database];
|
|
142
|
+
let sql = `
|
|
143
|
+
SELECT TABLE_NAME tableName, IFNULL(TABLE_COMMENT, TABLE_NAME) title FROM information_schema.TABLES
|
|
144
|
+
WHERE TABLE_SCHEMA= ? AND TABLE_TYPE = 'BASE TABLE'`;
|
|
145
|
+
if (tableName !== '.') {
|
|
146
|
+
sql += ` AND TABLE_NAME IN (?)`;
|
|
147
|
+
params.push(tableName.split(/,|\s/).map(r => r.trim()));
|
|
148
|
+
}
|
|
149
|
+
const [result] = await conn.query(sql, params);
|
|
150
|
+
conn.release();
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
153
|
+
async function getColumns(tableName) {
|
|
154
|
+
const conn = await pool.getConnection();
|
|
155
|
+
const [result] = await conn.query(`
|
|
156
|
+
SELECT
|
|
157
|
+
DATA_TYPE type,
|
|
158
|
+
COLUMN_NAME \`name\`,
|
|
159
|
+
IFNULL(IFNULL(CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION),DATETIME_PRECISION) \`length\`,
|
|
160
|
+
NUMERIC_SCALE scale,
|
|
161
|
+
COLUMN_DEFAULT def,
|
|
162
|
+
IF(COLUMN_KEY = 'PRI', 1, 0) id,
|
|
163
|
+
IF(IS_NULLABLE = 'NO', 1, 0) notNull,
|
|
164
|
+
COLUMN_COMMENT \`comment\`
|
|
165
|
+
FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=? AND TABLE_NAME = ?;
|
|
166
|
+
`, [configData.database, tableName]);
|
|
167
|
+
const columns = result.map(r => {
|
|
168
|
+
if (r.id === 1) {
|
|
169
|
+
r.id = true;
|
|
170
|
+
}
|
|
171
|
+
else
|
|
172
|
+
delete r.id;
|
|
173
|
+
if (r.notNull === 1) {
|
|
174
|
+
r.notNull = true;
|
|
175
|
+
}
|
|
176
|
+
else
|
|
177
|
+
delete r.notNull;
|
|
178
|
+
r.comment = `* ${r.comment ?? ''}(\`${tableName}.${r.name}\`)`;
|
|
179
|
+
const fields = new Array(`type:SqlType.${r.type}`);
|
|
180
|
+
if (r.length !== null) {
|
|
181
|
+
fields.push(`length:${r.length}`);
|
|
182
|
+
}
|
|
183
|
+
if (r.scale !== null) {
|
|
184
|
+
fields.push(`scale:${r.scale}`);
|
|
185
|
+
}
|
|
186
|
+
if (r.def !== null) {
|
|
187
|
+
r.def ?? (r.def = '');
|
|
188
|
+
if (isNaN(r.def) || r.def === '') {
|
|
189
|
+
fields.push(`def:'${r.def}'`);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
fields.push(`def:${r.def}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (r.id === true) {
|
|
196
|
+
fields.push(`id:true`);
|
|
197
|
+
}
|
|
198
|
+
if (r.notNull === true) {
|
|
199
|
+
fields.push(`notNull:true`);
|
|
200
|
+
}
|
|
201
|
+
r.Type = lxMap[r.type];
|
|
202
|
+
r.Field = `@Field({${fields.join(',')}})`;
|
|
203
|
+
r.Name = r.name.replace(/_(\w)/g, (a, b) => b.toUpperCase());
|
|
204
|
+
return r;
|
|
205
|
+
});
|
|
206
|
+
conn.release();
|
|
207
|
+
return columns;
|
|
208
|
+
}
|
|
209
|
+
async function excute(command, input, modelName) {
|
|
210
|
+
const tables = await getTables(input);
|
|
211
|
+
if (input !== '.') {
|
|
212
|
+
const checkTable = input.split(/,|\s/).map(r => r.trim());
|
|
213
|
+
if (checkTable.length !== tables.length) {
|
|
214
|
+
console.error(`[错误] 输入的表与数据库查询返回表不符,数据库返回${tables.length}个:${tables.map(i => i.tableName).join(',')}`);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
modelName ?? (modelName = '');
|
|
219
|
+
const modelPath = modelName ? `/${modelName}/` : '';
|
|
220
|
+
for (const { tableName, title } of tables) {
|
|
221
|
+
const columns = await getColumns(tableName);
|
|
222
|
+
const className = tableName.replace(/_(\w)/g, (a, b) => b.toUpperCase());
|
|
223
|
+
const ClassName = className.replace(/\w/, (v) => v.toUpperCase());
|
|
224
|
+
const vueName = tableName.replace(/_/g, '-');
|
|
225
|
+
const splitName = tableName.replace(/_/g, '/');
|
|
226
|
+
const data = {
|
|
227
|
+
title,
|
|
228
|
+
tableName,
|
|
229
|
+
className,
|
|
230
|
+
ClassName,
|
|
231
|
+
vueName,
|
|
232
|
+
splitName,
|
|
233
|
+
columns,
|
|
234
|
+
columnNames: columns?.map(i => i.name),
|
|
235
|
+
columnNames_join: columns?.map(i => i.name).join(','),
|
|
236
|
+
ColumnNames_join: columns?.map(i => `${i.name} ${i.Name}`).join(','),
|
|
237
|
+
columns_no_id: columns?.filter(i => !i.id),
|
|
238
|
+
columnNames_no_id: columns?.filter(i => !i.id).map(i => i.name),
|
|
239
|
+
columnNames_no_id_join: columns?.filter(i => !i.id).map(i => i.name).join(','),
|
|
240
|
+
ids: columns?.filter(i => i.id),
|
|
241
|
+
idNames: columns?.filter(i => i.id).map(i => i.name),
|
|
242
|
+
idNames_join: columns?.filter(i => i.id).map(i => i.name).join(','),
|
|
243
|
+
modelName,
|
|
244
|
+
modelPath
|
|
245
|
+
};
|
|
246
|
+
const template = templates[command];
|
|
247
|
+
if (!template) {
|
|
248
|
+
console.error(`[错误] ${command} 未定义模板!`);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
const txt = mustache_1.default.render(template, data, {}, ['<%', '%>']);
|
|
252
|
+
const fileName = configData.command[command].replace(/{([a-zA-Z]+)}/g, (a, b) => data[b]);
|
|
253
|
+
const filePath = path_1.default.join(basepath, fileName);
|
|
254
|
+
const dirname = path_1.default.dirname(filePath);
|
|
255
|
+
try {
|
|
256
|
+
fs_1.default.statSync(dirname);
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
fs_1.default.mkdirSync(dirname);
|
|
260
|
+
console.info(`[生成] ${dirname}`);
|
|
261
|
+
}
|
|
262
|
+
try {
|
|
263
|
+
fs_1.default.statSync(filePath);
|
|
264
|
+
if (force === false) {
|
|
265
|
+
console.warn(`[跳过] ${filePath}`);
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
console.warn(`[覆盖] ${filePath}`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
catch (error) {
|
|
273
|
+
console.info(`[生成] ${filePath}`);
|
|
274
|
+
}
|
|
275
|
+
if (configData.output) {
|
|
276
|
+
outputs.add(configData.output.replace(/{([a-zA-Z]+)}/g, (a, b) => data[b]));
|
|
277
|
+
}
|
|
278
|
+
fs_1.default.writeFileSync(path_1.default.join(basepath, fileName), txt);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
const replServer = (0, repl_1.start)();
|
|
282
|
+
function defineCommand(command, comands) {
|
|
283
|
+
if (comands) {
|
|
284
|
+
console.log(`[组合]${command}>${comands.join(',')}注册成功`);
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
console.log(`[命令]${command}注册成功`);
|
|
288
|
+
}
|
|
289
|
+
if (comands) {
|
|
290
|
+
replServer.defineCommand(command, async (input) => {
|
|
291
|
+
outputs.clear();
|
|
292
|
+
const inputs = input.match(/([^:]+):{0,1}([a-zA-Z0-9]*)/);
|
|
293
|
+
if (inputs?.length !== 3) {
|
|
294
|
+
return console.error(`[错误]命令格式应为: table1,table2[:模块名]`);
|
|
295
|
+
}
|
|
296
|
+
const [_, tables, modelName] = inputs;
|
|
297
|
+
for (const c of comands) {
|
|
298
|
+
await excute(c, tables, modelName ?? '');
|
|
299
|
+
}
|
|
300
|
+
console.info('执行完毕!下面打印生成的输出');
|
|
301
|
+
console.info(Array.from(outputs).join(','));
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
replServer.defineCommand(command, async (input) => {
|
|
306
|
+
outputs.clear();
|
|
307
|
+
const inputs = input.match(/([^:]+):{0,1}([a-zA-Z0-9]*)/);
|
|
308
|
+
if (inputs?.length !== 3) {
|
|
309
|
+
return console.error(`[错误]命令格式应为: table1,table2[:模块名]`);
|
|
310
|
+
}
|
|
311
|
+
const [_, tables, modelName] = inputs;
|
|
312
|
+
await excute(command, tables, modelName ?? '');
|
|
313
|
+
console.info('执行完毕!下面打印生成的输出');
|
|
314
|
+
console.info(Array.from(outputs).join(','));
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
replServer.defineCommand('force', () => {
|
|
319
|
+
force = !force;
|
|
320
|
+
console.log(force ? '覆盖生成' : '不覆盖生成!');
|
|
321
|
+
});
|
|
322
|
+
if (configData.command) {
|
|
323
|
+
for (const command of Object.keys(configData.command)) {
|
|
324
|
+
if (!templates[command]) {
|
|
325
|
+
console.error(`命令:${command}没有定义模板,该命令不会生效`);
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
defineCommand(command);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
if (configData.commands) {
|
|
333
|
+
for (const [command, commands] of Object.entries(configData.commands)) {
|
|
334
|
+
const keys = commands;
|
|
335
|
+
const error = keys.filter(k => !templates[k]).join(',');
|
|
336
|
+
if (error) {
|
|
337
|
+
console.error(`组合命令:${command}定义了${commands},但是${error}没有定义模板,该命令不会生效`);
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
defineCommand(command, keys);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
console.error(error);
|
|
347
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface XML {
|
|
2
|
+
type: 'tag' | 'text';
|
|
3
|
+
name: string;
|
|
4
|
+
id?: string;
|
|
5
|
+
voidElement: boolean;
|
|
6
|
+
attrs: Record<string, string>;
|
|
7
|
+
children: XML[];
|
|
8
|
+
content: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const convert: (childrens: XML[], param: Record<string, any>, parentIds: string[], myBatisMapper: Record<string, XML[]>) => string;
|