evaengine 1.0.14 → 2.0.0
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 +15 -1
- package/bin/engine +2 -31
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +40 -0
- package/dist/bin.js.map +1 -0
- package/{src/commands/index.js → dist/commands/index.d.ts} +1 -8
- package/dist/commands/index.js +6 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/interface.d.ts +18 -0
- package/dist/commands/interface.js +40 -0
- package/dist/commands/interface.js.map +1 -0
- package/dist/commands/make_entity.d.ts +47 -0
- package/dist/commands/make_entity.js +410 -0
- package/dist/commands/make_entity.js.map +1 -0
- package/dist/commands/tramp.d.ts +7 -0
- package/dist/commands/tramp.js +29 -0
- package/dist/commands/tramp.js.map +1 -0
- package/dist/config/index.d.ts +92 -0
- package/dist/config/index.js +96 -0
- package/dist/config/index.js.map +1 -0
- package/dist/di.d.ts +73 -0
- package/dist/di.js +76 -0
- package/dist/di.js.map +1 -0
- package/dist/engine.d.ts +85 -0
- package/dist/engine.js +404 -0
- package/dist/engine.js.map +1 -0
- package/dist/entities/index.d.ts +54 -0
- package/dist/entities/index.js +228 -0
- package/dist/entities/index.js.map +1 -0
- package/dist/exceptions/index.d.ts +153 -0
- package/dist/exceptions/index.js +439 -0
- package/dist/exceptions/index.js.map +1 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/middlewares/auth.d.ts +5 -0
- package/dist/middlewares/auth.js +63 -0
- package/dist/middlewares/auth.js.map +1 -0
- package/dist/middlewares/auth_kong.d.ts +2 -0
- package/dist/middlewares/auth_kong.js +24 -0
- package/dist/middlewares/auth_kong.js.map +1 -0
- package/dist/middlewares/debug.d.ts +3 -0
- package/dist/middlewares/debug.js +50 -0
- package/dist/middlewares/debug.js.map +1 -0
- package/{src/middlewares/index.js → dist/middlewares/index.d.ts} +1 -11
- package/dist/middlewares/index.js +9 -0
- package/dist/middlewares/index.js.map +1 -0
- package/dist/middlewares/providers.d.ts +25 -0
- package/dist/middlewares/providers.js +63 -0
- package/dist/middlewares/providers.js.map +1 -0
- package/dist/middlewares/session.d.ts +6 -0
- package/dist/middlewares/session.js +51 -0
- package/dist/middlewares/session.js.map +1 -0
- package/dist/middlewares/trace.d.ts +52 -0
- package/dist/middlewares/trace.js +225 -0
- package/dist/middlewares/trace.js.map +1 -0
- package/dist/middlewares/validator.d.ts +10 -0
- package/dist/middlewares/validator.js +43 -0
- package/dist/middlewares/validator.js.map +1 -0
- package/dist/middlewares/view_cache.d.ts +14 -0
- package/dist/middlewares/view_cache.js +102 -0
- package/dist/middlewares/view_cache.js.map +1 -0
- package/dist/services/cache.d.ts +66 -0
- package/dist/services/cache.js +207 -0
- package/dist/services/cache.js.map +1 -0
- package/dist/services/config.d.ts +25 -0
- package/dist/services/config.js +88 -0
- package/dist/services/config.js.map +1 -0
- package/dist/services/env.d.ts +12 -0
- package/dist/services/env.js +24 -0
- package/dist/services/env.js.map +1 -0
- package/dist/services/event_manager.d.ts +29 -0
- package/dist/services/event_manager.js +75 -0
- package/dist/services/event_manager.js.map +1 -0
- package/dist/services/http_client.d.ts +66 -0
- package/dist/services/http_client.js +62 -0
- package/dist/services/http_client.js.map +1 -0
- package/{src/services/index.js → dist/services/index.d.ts} +1 -15
- package/dist/services/index.js +14 -0
- package/dist/services/index.js.map +1 -0
- package/{src/services/interface.js → dist/services/interface.d.ts} +1 -3
- package/dist/services/interface.js +6 -0
- package/dist/services/interface.js.map +1 -0
- package/{src/services/joi.js → dist/services/joi.d.ts} +2 -9
- package/dist/services/joi.js +11 -0
- package/dist/services/joi.js.map +1 -0
- package/dist/services/jwt_token.d.ts +24 -0
- package/dist/services/jwt_token.js +77 -0
- package/dist/services/jwt_token.js.map +1 -0
- package/dist/services/jwt_token_kong.d.ts +25 -0
- package/dist/services/jwt_token_kong.js +65 -0
- package/dist/services/jwt_token_kong.js.map +1 -0
- package/dist/services/logger.d.ts +30 -0
- package/dist/services/logger.js +126 -0
- package/dist/services/logger.js.map +1 -0
- package/dist/services/namespace.d.ts +55 -0
- package/dist/services/namespace.js +157 -0
- package/dist/services/namespace.js.map +1 -0
- package/dist/services/now.d.ts +14 -0
- package/dist/services/now.js +43 -0
- package/dist/services/now.js.map +1 -0
- package/dist/services/providers.d.ts +55 -0
- package/dist/services/providers.js +134 -0
- package/dist/services/providers.js.map +1 -0
- package/dist/services/redis.d.ts +18 -0
- package/dist/services/redis.js +53 -0
- package/dist/services/redis.js.map +1 -0
- package/dist/services/rest_client.d.ts +48 -0
- package/dist/services/rest_client.js +96 -0
- package/dist/services/rest_client.js.map +1 -0
- package/dist/swagger/index.d.ts +223 -0
- package/dist/swagger/index.js +564 -0
- package/dist/swagger/index.js.map +1 -0
- package/dist/types/express.d.ts +14 -0
- package/dist/types/vendor.d.ts +102 -0
- package/dist/utils/api_scaffold.d.ts +74 -0
- package/dist/utils/api_scaffold.js +220 -0
- package/dist/utils/api_scaffold.js.map +1 -0
- package/dist/utils/case_converter.d.ts +7 -0
- package/dist/utils/case_converter.js +29 -0
- package/dist/utils/case_converter.js.map +1 -0
- package/dist/utils/crc32.d.ts +2 -0
- package/dist/utils/crc32.js +43 -0
- package/dist/utils/crc32.js.map +1 -0
- package/dist/utils/cron.d.ts +27 -0
- package/dist/utils/cron.js +186 -0
- package/dist/utils/cron.js.map +1 -0
- package/dist/utils/datetime.d.ts +4 -0
- package/dist/utils/datetime.js +6 -0
- package/dist/utils/datetime.js.map +1 -0
- package/dist/utils/host.d.ts +18 -0
- package/dist/utils/host.js +33 -0
- package/dist/utils/host.js.map +1 -0
- package/{src/utils/index.js → dist/utils/index.d.ts} +2 -26
- package/dist/utils/index.js +12 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/pagination.d.ts +150 -0
- package/dist/utils/pagination.js +242 -0
- package/dist/utils/pagination.js.map +1 -0
- package/dist/utils/random.d.ts +3 -0
- package/dist/utils/random.js +18 -0
- package/dist/utils/random.js.map +1 -0
- package/dist/utils/request_client.d.ts +33 -0
- package/dist/utils/request_client.js +153 -0
- package/dist/utils/request_client.js.map +1 -0
- package/dist/utils/smart_query.d.ts +144 -0
- package/dist/utils/smart_query.js +310 -0
- package/dist/utils/smart_query.js.map +1 -0
- package/dist/utils/test.d.ts +14 -0
- package/dist/utils/test.js +37 -0
- package/dist/utils/test.js.map +1 -0
- package/dist/utils/wrapper.d.ts +3 -0
- package/dist/utils/wrapper.js +5 -0
- package/dist/utils/wrapper.js.map +1 -0
- package/package.json +24 -10
- package/index.js +0 -2
- package/src/commands/interface.js +0 -45
- package/src/commands/make_entity.js +0 -490
- package/src/commands/tramp.js +0 -34
- package/src/config/index.js +0 -95
- package/src/di.js +0 -96
- package/src/engine.js +0 -556
- package/src/entities/index.js +0 -272
- package/src/exceptions/index.js +0 -501
- package/src/index.js +0 -55
- package/src/middlewares/auth.js +0 -67
- package/src/middlewares/auth_kong.js +0 -28
- package/src/middlewares/debug.js +0 -88
- package/src/middlewares/providers.js +0 -73
- package/src/middlewares/session.js +0 -63
- package/src/middlewares/trace.js +0 -254
- package/src/middlewares/validator.js +0 -50
- package/src/middlewares/view_cache.js +0 -127
- package/src/services/cache.js +0 -223
- package/src/services/config.js +0 -115
- package/src/services/env.js +0 -28
- package/src/services/event_manager.js +0 -84
- package/src/services/http_client.js +0 -69
- package/src/services/jwt_token.js +0 -89
- package/src/services/jwt_token_kong.js +0 -75
- package/src/services/logger.js +0 -150
- package/src/services/namespace.js +0 -176
- package/src/services/now.js +0 -49
- package/src/services/providers.js +0 -158
- package/src/services/redis.js +0 -63
- package/src/services/rest_client.js +0 -112
- package/src/swagger/index.js +0 -665
- package/src/utils/api_scaffold.js +0 -240
- package/src/utils/case_converter.js +0 -33
- package/src/utils/crc32.js +0 -44
- package/src/utils/cron.js +0 -208
- package/src/utils/datetime.js +0 -13
- package/src/utils/host.js +0 -39
- package/src/utils/pagination.js +0 -260
- package/src/utils/random.js +0 -23
- package/src/utils/request_client.js +0 -179
- package/src/utils/smart_query.js +0 -352
- package/src/utils/test.js +0 -48
- package/src/utils/wrapper.js +0 -8
package/README.md
CHANGED
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
npm install evaengine
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
本包源码为 TypeScript,npm 发布 `dist/` 编译产物并自带 `.d.ts` 类型声明(`@types/express`、`@types/lodash` 随 dependencies 自动安装,严格模式下类型开箱即用);上述导入契约不受影响。
|
|
26
|
+
|
|
25
27
|
可选脚手架:[EvaSkeleton.js](https://github.com/EvaEngine/EvaSkeleton.js)。
|
|
26
28
|
|
|
27
29
|
## 导入方式(重要)
|
|
@@ -130,6 +132,8 @@ await engine.runCLI();
|
|
|
130
132
|
// node app.js user:create --name=Ada
|
|
131
133
|
```
|
|
132
134
|
|
|
135
|
+
命令不存在或 `run()` 抛出异常时,进程以退出码 1 结束。
|
|
136
|
+
|
|
133
137
|
### 定时任务
|
|
134
138
|
|
|
135
139
|
```js
|
|
@@ -361,7 +365,15 @@ entities.init(); // 按 config.db 构建 Sequelize 并扫描目录
|
|
|
361
365
|
|
|
362
366
|
const User = entities.get('user');
|
|
363
367
|
const all = entities.getAll();
|
|
364
|
-
|
|
368
|
+
|
|
369
|
+
const transaction = await entities.getTransaction();
|
|
370
|
+
try {
|
|
371
|
+
await User.create({ name: 'Ada' }, { transaction });
|
|
372
|
+
await transaction.commit();
|
|
373
|
+
} catch (error) {
|
|
374
|
+
await transaction.rollback();
|
|
375
|
+
throw error;
|
|
376
|
+
}
|
|
365
377
|
```
|
|
366
378
|
|
|
367
379
|
实体文件(经 `require` 加载的 CJS 或 ESM 工厂):
|
|
@@ -441,4 +453,6 @@ npm run build
|
|
|
441
453
|
npm test # 部分测试需要本机 Redis 127.0.0.1:6379
|
|
442
454
|
```
|
|
443
455
|
|
|
456
|
+
仓库源码为严格 TypeScript(仅可擦除语法),Node ≥24 原生直接运行 `src/**/*.ts`,日常开发无转译步骤;`npm run build` 用 tsc 编译发布产物 `dist/` 并生成声明文件。本地 CLI 可直接 `node src/bin.ts`,或先 build 后走 `./bin/engine`(shim → `dist/bin.js`)。
|
|
457
|
+
|
|
444
458
|
发版:在 `main` 上由 semantic-release(Conventional Commits)执行——仅发布 npm,不创建 GitHub Release。维护者文档在 git 的 `docs/` 下,**npm 消费方无需阅读**。
|
package/bin/engine
CHANGED
|
@@ -1,32 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const engine = new EvaEngine({
|
|
5
|
-
projectRoot: process.cwd()
|
|
6
|
-
}, 'cli');
|
|
7
|
-
engine.registerCommands([commands]);
|
|
8
|
-
|
|
9
|
-
const logger = DI.get('logger');
|
|
10
|
-
try {
|
|
11
|
-
if (process.env.SPRING_CONFIG_ENDPOINT) {
|
|
12
|
-
await DI.get('config').resolveSpringConfig({
|
|
13
|
-
endpoint: process.env.SPRING_CONFIG_ENDPOINT,
|
|
14
|
-
name: process.env.SPRING_CONFIG_NAME || 'unknown-spring-config-name',
|
|
15
|
-
profiles: process.env.SPRING_CONFIG_PROFILES || process.env.NODE_ENV,
|
|
16
|
-
label: process.env.SPRING_CONFIG_LABEL || 'main'
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
await engine.runCLI();
|
|
20
|
-
} catch (error) {
|
|
21
|
-
if (error instanceof exceptions.StandardException) {
|
|
22
|
-
logger.warn(error.getDetails());
|
|
23
|
-
logger.warn(error.message);
|
|
24
|
-
} else {
|
|
25
|
-
logger.error(error);
|
|
26
|
-
}
|
|
27
|
-
} finally {
|
|
28
|
-
const redis = DI.get('redis');
|
|
29
|
-
if (redis.isConnected()) {
|
|
30
|
-
await redis.cleanup();
|
|
31
|
-
}
|
|
32
|
-
}
|
|
2
|
+
//Thin launcher: the CLI implementation lives in src/bin.ts and is compiled to dist
|
|
3
|
+
import '../dist/bin.js';
|
package/dist/bin.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/bin.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
//The package entry only exports the core object, so the CLI imports its
|
|
2
|
+
//building blocks directly (the legacy bin/engine named imports were broken)
|
|
3
|
+
import EvaEngine from "./engine.js";
|
|
4
|
+
import DI from "./di.js";
|
|
5
|
+
import * as exceptions from "./exceptions/index.js";
|
|
6
|
+
import * as commands from "./commands/index.js";
|
|
7
|
+
const engine = new EvaEngine({
|
|
8
|
+
projectRoot: process.cwd()
|
|
9
|
+
}, 'cli');
|
|
10
|
+
engine.registerCommands([commands]);
|
|
11
|
+
const logger = DI.get('logger');
|
|
12
|
+
try {
|
|
13
|
+
if (process.env.SPRING_CONFIG_ENDPOINT) {
|
|
14
|
+
await DI.get('config').resolveSpringConfig({
|
|
15
|
+
endpoint: process.env.SPRING_CONFIG_ENDPOINT,
|
|
16
|
+
name: process.env.SPRING_CONFIG_NAME || 'unknown-spring-config-name',
|
|
17
|
+
profiles: process.env.SPRING_CONFIG_PROFILES || process.env.NODE_ENV,
|
|
18
|
+
label: process.env.SPRING_CONFIG_LABEL || 'main'
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
await engine.runCLI();
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
//用 exitCode 而非 process.exit,让 finally 里的 Redis 清理自然完成后进程才结束
|
|
25
|
+
process.exitCode = 1;
|
|
26
|
+
if (error instanceof exceptions.StandardException) {
|
|
27
|
+
logger.warn(error.getDetails());
|
|
28
|
+
logger.warn(error.message);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
logger.error(error);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
const redis = DI.get('redis');
|
|
36
|
+
if (redis.isConnected()) {
|
|
37
|
+
await redis.cleanup();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=bin.js.map
|
package/dist/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,4EAA4E;AAC5E,OAAO,SAAS,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAC;AAEhD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,WAAW,EAAE,OAAO,CAAC,GAAG,EAAE;CAC3B,EAAE,KAAK,CAAC,CAAC;AACV,MAAM,CAAC,gBAAgB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;AAEpC,MAAM,MAAM,GAAG,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAChC,IAAI,CAAC;IACH,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC;QACvC,MAAM,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,mBAAmB,CAAC;YACzC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB;YAC5C,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,4BAA4B;YACpE,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ;YACpE,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,MAAM;SACjD,CAAC,CAAC;IACL,CAAC;IACD,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;AACxB,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACrB,IAAI,KAAK,YAAY,UAAU,CAAC,iBAAiB,EAAE,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;QAAS,CAAC;IACT,MAAM,KAAK,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC9B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QACxB,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
|
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
import Command from './interface.js';
|
|
2
2
|
import { MakeEntity, MakeDbView, MakeGraphql } from './make_entity.js';
|
|
3
3
|
import TrampConfig from './tramp.js';
|
|
4
|
-
|
|
5
4
|
export default Command;
|
|
6
|
-
|
|
7
|
-
export {
|
|
8
|
-
MakeEntity,
|
|
9
|
-
MakeDbView,
|
|
10
|
-
MakeGraphql,
|
|
11
|
-
TrampConfig
|
|
12
|
-
};
|
|
5
|
+
export { MakeEntity, MakeDbView, MakeGraphql, TrampConfig };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import Command from "./interface.js";
|
|
2
|
+
import { MakeEntity, MakeDbView, MakeGraphql } from "./make_entity.js";
|
|
3
|
+
import TrampConfig from "./tramp.js";
|
|
4
|
+
export default Command;
|
|
5
|
+
export { MakeEntity, MakeDbView, MakeGraphql, TrampConfig };
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,WAAW,MAAM,YAAY,CAAC;AAErC,eAAe,OAAO,CAAC;AAEvB,OAAO,EACL,UAAU,EACV,UAAU,EACV,WAAW,EACX,WAAW,EACZ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface CommandArgv {
|
|
2
|
+
$0: string;
|
|
3
|
+
[key: string]: unknown;
|
|
4
|
+
}
|
|
5
|
+
export default class Command {
|
|
6
|
+
argv: CommandArgv;
|
|
7
|
+
options: Record<string, unknown> | null;
|
|
8
|
+
constructor(argv: CommandArgv);
|
|
9
|
+
getArgv(): CommandArgv;
|
|
10
|
+
setArgv(argv: CommandArgv): this;
|
|
11
|
+
setOptions(options: Record<string, unknown>): this;
|
|
12
|
+
getOptions(): Record<string, unknown>;
|
|
13
|
+
static getName(): string;
|
|
14
|
+
static getDescription(): string;
|
|
15
|
+
static getSpec(): object;
|
|
16
|
+
run(): void;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export default class Command {
|
|
2
|
+
argv;
|
|
3
|
+
options;
|
|
4
|
+
constructor(argv) {
|
|
5
|
+
this.argv = argv;
|
|
6
|
+
this.options = null;
|
|
7
|
+
}
|
|
8
|
+
getArgv() {
|
|
9
|
+
return this.argv;
|
|
10
|
+
}
|
|
11
|
+
setArgv(argv) {
|
|
12
|
+
this.argv = argv;
|
|
13
|
+
return this;
|
|
14
|
+
}
|
|
15
|
+
setOptions(options) {
|
|
16
|
+
this.options = options;
|
|
17
|
+
return this;
|
|
18
|
+
}
|
|
19
|
+
getOptions() {
|
|
20
|
+
const options = {};
|
|
21
|
+
Object.keys(this.argv).forEach((key) => {
|
|
22
|
+
if (key !== '$0' && ['string', 'number'].includes(typeof this.argv[key])) {
|
|
23
|
+
options[key] = this.argv[key];
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
return options;
|
|
27
|
+
}
|
|
28
|
+
static getName() {
|
|
29
|
+
return '';
|
|
30
|
+
}
|
|
31
|
+
static getDescription() {
|
|
32
|
+
return '';
|
|
33
|
+
}
|
|
34
|
+
static getSpec() {
|
|
35
|
+
return {};
|
|
36
|
+
}
|
|
37
|
+
run() {
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=interface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interface.js","sourceRoot":"","sources":["../../src/commands/interface.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,OAAO,OAAO,OAAO;IAC1B,IAAI,CAAc;IAClB,OAAO,CAAiC;IAExC,YAAY,IAAiB;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,OAAO,CAAC,IAAiB;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,UAAU,CAAC,OAAgC;QACzC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,UAAU;QACR,MAAM,OAAO,GAA4B,EAAE,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YACrC,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBACzE,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,OAAO;QACZ,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,CAAC,cAAc;QACnB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,CAAC,OAAO;QACZ,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,GAAG;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import Command from './interface.js';
|
|
2
|
+
type SequelizeInstance = import('sequelize').Sequelize & {
|
|
3
|
+
QueryTypes: typeof import('sequelize').QueryTypes;
|
|
4
|
+
};
|
|
5
|
+
interface RawColumn {
|
|
6
|
+
Field: string;
|
|
7
|
+
Key: string;
|
|
8
|
+
Comment: unknown;
|
|
9
|
+
Collation: unknown;
|
|
10
|
+
Extra: string;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
interface GeneratedIndex {
|
|
14
|
+
name: string;
|
|
15
|
+
unique?: boolean;
|
|
16
|
+
fields?: string[];
|
|
17
|
+
}
|
|
18
|
+
export declare class MakeDbView extends Command {
|
|
19
|
+
static getName(): string;
|
|
20
|
+
static getDescription(): string;
|
|
21
|
+
static getSpec(): object;
|
|
22
|
+
getSql(tableName: string, attributes: Array<{
|
|
23
|
+
fieldName: string;
|
|
24
|
+
}>): string;
|
|
25
|
+
run(): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
export declare class MakeEntity extends Command {
|
|
28
|
+
static getName(): string;
|
|
29
|
+
static getDescription(): string;
|
|
30
|
+
static getSpec(): object;
|
|
31
|
+
static typeMapping(_type: string): string;
|
|
32
|
+
static typeAdditional(_type: string, sequlizeType: string, rawColumn: RawColumn): string;
|
|
33
|
+
static getIndexes(tableName: string, sequelize: SequelizeInstance): Promise<GeneratedIndex[]>;
|
|
34
|
+
run(): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
export declare class MakeGraphql extends Command {
|
|
37
|
+
static getName(): string;
|
|
38
|
+
static getDescription(): string;
|
|
39
|
+
static getSpec(): object;
|
|
40
|
+
static typeMapping(_type: string, _mappedTableName?: string): string;
|
|
41
|
+
getEnums(_type: string, columnName: string, tableName: string): {
|
|
42
|
+
name: string;
|
|
43
|
+
values: string[];
|
|
44
|
+
};
|
|
45
|
+
run(): Promise<void>;
|
|
46
|
+
}
|
|
47
|
+
export {};
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
import groupBy from 'lodash/groupBy.js';
|
|
2
|
+
import template from 'lodash/template.js';
|
|
3
|
+
import Sequelize from 'sequelize';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import Command from "./interface.js";
|
|
6
|
+
import DI from "../di.js";
|
|
7
|
+
import Entities from "../entities/index.js";
|
|
8
|
+
export class MakeDbView extends Command {
|
|
9
|
+
static getName() {
|
|
10
|
+
return 'make:dbview';
|
|
11
|
+
}
|
|
12
|
+
static getDescription() {
|
|
13
|
+
return 'Generate db views';
|
|
14
|
+
}
|
|
15
|
+
static getSpec() {
|
|
16
|
+
return {
|
|
17
|
+
entity_path: {
|
|
18
|
+
required: false,
|
|
19
|
+
description: 'Entity path'
|
|
20
|
+
},
|
|
21
|
+
dir: {
|
|
22
|
+
required: false,
|
|
23
|
+
description: 'Where view.sql to be generated'
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
getSql(tableName, attributes) {
|
|
28
|
+
const attrs = attributes.map((attr) => {
|
|
29
|
+
const { fieldName } = attr;
|
|
30
|
+
if (fieldName.endsWith('At')) {
|
|
31
|
+
return ` FROM_UNIXTIME(IF(${fieldName} > 0, ${fieldName}, NULL)) AS ${fieldName}`;
|
|
32
|
+
}
|
|
33
|
+
return ` \`${fieldName}\` AS \`${fieldName}\``;
|
|
34
|
+
});
|
|
35
|
+
return `DROP VIEW IF EXISTS view_${tableName};
|
|
36
|
+
CREATE ALGORITHM=UNDEFINED SQL SECURITY DEFINER VIEW view_${tableName}
|
|
37
|
+
AS SELECT
|
|
38
|
+
${attrs.join(',\n ')}
|
|
39
|
+
FROM ${tableName};
|
|
40
|
+
|
|
41
|
+
`;
|
|
42
|
+
}
|
|
43
|
+
async run() {
|
|
44
|
+
const logger = DI.get('logger');
|
|
45
|
+
const { dir, entity_path: entityPath = `${process.cwd()}/build/entities` } = this.getArgv();
|
|
46
|
+
const path = dir ? `${process.cwd()}/${dir}` : `${process.cwd()}/sql`;
|
|
47
|
+
const file = [path, 'views.sql'].join('/');
|
|
48
|
+
logger.info('Scan entity files under %s', entityPath);
|
|
49
|
+
const entities = new Entities(entityPath);
|
|
50
|
+
logger.info('Start generate db views to %s', file);
|
|
51
|
+
fs.mkdirSync(path, { recursive: true });
|
|
52
|
+
const models = Object.values(entities.getInstance().models);
|
|
53
|
+
const sql = [];
|
|
54
|
+
models.forEach((model) => {
|
|
55
|
+
//运行时 model.attributes 携带 fieldName、getTableName 为静态方法;sequelize 类型未完整声明
|
|
56
|
+
const entityModel = model;
|
|
57
|
+
logger.info(`Creating ${entityModel.getTableName()} view`);
|
|
58
|
+
sql.push(this.getSql(entityModel.getTableName(), Object.values(entityModel.attributes)));
|
|
59
|
+
});
|
|
60
|
+
fs.writeFileSync(file, sql.join(''));
|
|
61
|
+
logger.info('Views created');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export class MakeEntity extends Command {
|
|
65
|
+
static getName() {
|
|
66
|
+
return 'make:entity';
|
|
67
|
+
}
|
|
68
|
+
static getDescription() {
|
|
69
|
+
return 'Generate entities';
|
|
70
|
+
}
|
|
71
|
+
static getSpec() {
|
|
72
|
+
return {
|
|
73
|
+
timestamp: {
|
|
74
|
+
required: false,
|
|
75
|
+
description: 'Sequelize timestamp enabled'
|
|
76
|
+
},
|
|
77
|
+
dir: {
|
|
78
|
+
required: false,
|
|
79
|
+
description: 'Where entity files to be generated'
|
|
80
|
+
},
|
|
81
|
+
prefix: {
|
|
82
|
+
required: false,
|
|
83
|
+
description: 'Table prefix'
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
static typeMapping(_type) {
|
|
88
|
+
const type = _type.toLowerCase();
|
|
89
|
+
if (type === 'tinyint(1)' || type === 'boolean' || type === 'bit(1)') {
|
|
90
|
+
return 'DataTypes.BOOLEAN';
|
|
91
|
+
}
|
|
92
|
+
if (type.match(/^(smallint|mediumint|tinyint|int)/)) {
|
|
93
|
+
const length = type.match(/\(\d+\)/) || '';
|
|
94
|
+
return `DataTypes.INTEGER${length}`;
|
|
95
|
+
}
|
|
96
|
+
if (type.startsWith('bigint')) {
|
|
97
|
+
return 'DataTypes.BIGINT';
|
|
98
|
+
}
|
|
99
|
+
if (type.startsWith('enum')) {
|
|
100
|
+
return type.replace('enum', 'DataTypes.ENUM').replace(/,/g, ', ');
|
|
101
|
+
}
|
|
102
|
+
if (type.match(/^string|varchar|varying|nvarchar/)) {
|
|
103
|
+
const length = type.match(/\(\d+\)/) || '';
|
|
104
|
+
return length ? `DataTypes.STRING${length}` : 'DataTypes.STRING';
|
|
105
|
+
}
|
|
106
|
+
if (type.startsWith('char')) {
|
|
107
|
+
const length = type.match(/\(\d+\)/) || '';
|
|
108
|
+
return `DataTypes.CHAR${length}`;
|
|
109
|
+
}
|
|
110
|
+
if (type.match(/text|ntext$/)) {
|
|
111
|
+
return 'DataTypes.TEXT';
|
|
112
|
+
}
|
|
113
|
+
if (type.startsWith('year')) {
|
|
114
|
+
return 'DataTypes.INTEGER(4)';
|
|
115
|
+
}
|
|
116
|
+
if (type.startsWith('datetime')) {
|
|
117
|
+
return 'DataTypes.DATE';
|
|
118
|
+
}
|
|
119
|
+
if (type.startsWith('date')) {
|
|
120
|
+
return 'DataTypes.DATEONLY';
|
|
121
|
+
}
|
|
122
|
+
if (type.startsWith('time')) {
|
|
123
|
+
return 'DataTypes.TIME';
|
|
124
|
+
}
|
|
125
|
+
if (type.match(/^(float8|double precision)/)) {
|
|
126
|
+
return 'DataTypes.DOUBLE';
|
|
127
|
+
}
|
|
128
|
+
if (type.match(/^(float|float4)/)) {
|
|
129
|
+
return 'DataTypes.FLOAT';
|
|
130
|
+
}
|
|
131
|
+
if (type.startsWith('decimal')) {
|
|
132
|
+
const [, length, bits] = /\((\d+),(\d+)\)/g.exec(type) || [];
|
|
133
|
+
return length ? `DataTypes.DECIMAL(${length}, ${bits})` : 'DataTypes.DECIMAL';
|
|
134
|
+
}
|
|
135
|
+
if (type.match(/^uuid|uniqueidentifier/)) {
|
|
136
|
+
return 'DataTypes.UUIDV4';
|
|
137
|
+
}
|
|
138
|
+
if (type.startsWith('jsonb')) {
|
|
139
|
+
return 'DataTypes.JSONB';
|
|
140
|
+
}
|
|
141
|
+
if (type.startsWith('json')) {
|
|
142
|
+
return 'DataTypes.JSON';
|
|
143
|
+
}
|
|
144
|
+
if (type.startsWith('geometry')) {
|
|
145
|
+
return 'DataTypes.GEOMETRY';
|
|
146
|
+
}
|
|
147
|
+
return type;
|
|
148
|
+
}
|
|
149
|
+
static typeAdditional(_type, sequlizeType, rawColumn) {
|
|
150
|
+
const type = _type.toLowerCase();
|
|
151
|
+
let finalType = sequlizeType;
|
|
152
|
+
if (type.match(/unsigned/)) {
|
|
153
|
+
finalType += '.UNSIGNED';
|
|
154
|
+
}
|
|
155
|
+
if (type.match(/zerofill/)) {
|
|
156
|
+
finalType += '.ZEROFILL';
|
|
157
|
+
}
|
|
158
|
+
if (rawColumn.Collation === 'utf8_bin') {
|
|
159
|
+
finalType += '.BINARY';
|
|
160
|
+
}
|
|
161
|
+
return finalType;
|
|
162
|
+
}
|
|
163
|
+
static async getIndexes(tableName, sequelize) {
|
|
164
|
+
let rawIndexes = await sequelize.query(`SHOW INDEX FROM ${tableName}`, {
|
|
165
|
+
type: sequelize.QueryTypes.SELECT,
|
|
166
|
+
raw: true
|
|
167
|
+
});
|
|
168
|
+
if (!rawIndexes) {
|
|
169
|
+
return [];
|
|
170
|
+
}
|
|
171
|
+
rawIndexes = groupBy(rawIndexes, 'Key_name');
|
|
172
|
+
return Object.entries(rawIndexes).filter(([key]) => key !== 'PRIMARY').map(([name, columns]) => {
|
|
173
|
+
const index = columns[0].Non_unique !== 1 ? { name, unique: true } : { name };
|
|
174
|
+
index.fields = columns.map(c => c.Column_name);
|
|
175
|
+
return index;
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
async run() {
|
|
179
|
+
const config = DI.get('config').get();
|
|
180
|
+
const logger = DI.get('logger');
|
|
181
|
+
const sequelize = new Sequelize(config.db.database, null, null, Object.assign({}, config.sequelize, config.db, { logging: logger.getInstance().verbose }));
|
|
182
|
+
const query = sequelize.getQueryInterface();
|
|
183
|
+
let tables = await query.showAllTables();
|
|
184
|
+
const views = await sequelize.query(`SHOW FULL TABLES IN ${config.db.database} WHERE TABLE_TYPE LIKE 'VIEW'`, {
|
|
185
|
+
type: sequelize.QueryTypes.SELECT,
|
|
186
|
+
raw: true
|
|
187
|
+
});
|
|
188
|
+
if (views) {
|
|
189
|
+
const viewNames = views.map(v => Object.values(v)[0]);
|
|
190
|
+
tables = tables.filter(t => !viewNames.includes(t));
|
|
191
|
+
}
|
|
192
|
+
const { dir, timestamp = true, prefix } = this.getArgv();
|
|
193
|
+
if (prefix) {
|
|
194
|
+
tables = tables.filter(t => t.startsWith(prefix));
|
|
195
|
+
}
|
|
196
|
+
const path = dir ? `${process.cwd()}/${dir}` : `${process.cwd()}/src/entities`;
|
|
197
|
+
const schemaPath = `${path}/schemas`;
|
|
198
|
+
const entityTemplate = fs.readFileSync(`${import.meta.dirname}/../../template/entity.ejs`, 'utf8');
|
|
199
|
+
const schemaTemplate = fs.readFileSync(`${import.meta.dirname}/../../template/schema.ejs`, 'utf8');
|
|
200
|
+
fs.mkdirSync(path, { recursive: true });
|
|
201
|
+
fs.mkdirSync(schemaPath, { recursive: true });
|
|
202
|
+
logger.info('Start generate DB schemas to dir %s', path);
|
|
203
|
+
const tableHandler = async (table) => {
|
|
204
|
+
//describeTable 的 ColumnsDescription 与可回写形态不直接可比,运行时字段同源
|
|
205
|
+
const columns = (await query.describeTable(table));
|
|
206
|
+
const rawColumns = await sequelize.query(`SHOW FULL COLUMNS FROM ${table}`, {
|
|
207
|
+
type: sequelize.QueryTypes.SELECT,
|
|
208
|
+
raw: true
|
|
209
|
+
});
|
|
210
|
+
Object.values(rawColumns).forEach((rawColumn) => {
|
|
211
|
+
const columnName = rawColumn.Field;
|
|
212
|
+
columns[columnName].type = MakeEntity.typeAdditional(columns[columnName].type, MakeEntity.typeMapping(columns[columnName].type), rawColumn);
|
|
213
|
+
columns[columnName].unique = rawColumn.Key === 'UNI';
|
|
214
|
+
columns[columnName].comment = rawColumn.Comment;
|
|
215
|
+
columns[columnName].autoIncrement = rawColumn.Extra.startsWith('auto_increment') === true;
|
|
216
|
+
});
|
|
217
|
+
const indexes = await MakeEntity.getIndexes(table, sequelize);
|
|
218
|
+
const entityFile = `${path}/${table}.js`;
|
|
219
|
+
const schemaFile = `${schemaPath}/${table}.js`;
|
|
220
|
+
try {
|
|
221
|
+
fs.accessSync(entityFile);
|
|
222
|
+
logger.info('Entity file %s generate skipped, already exists by %s', table, entityFile);
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
fs.writeFileSync(entityFile, template(entityTemplate)({ table }));
|
|
226
|
+
logger.info('Entity file %s generated as %s', table, entityFile);
|
|
227
|
+
}
|
|
228
|
+
try {
|
|
229
|
+
fs.accessSync(schemaFile);
|
|
230
|
+
logger.info('Schema file %s generate override, already exists by %s', table, schemaFile);
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
logger.info('Schema file %s generated as %s', table, schemaFile);
|
|
234
|
+
}
|
|
235
|
+
//argv 值为 unknown;parseInt 对非字符串(如默认 true)按原语义得到 NaN
|
|
236
|
+
fs.writeFileSync(schemaFile, template(schemaTemplate)({
|
|
237
|
+
columns,
|
|
238
|
+
table,
|
|
239
|
+
indexes,
|
|
240
|
+
timestamp: parseInt(timestamp, 10) > 0
|
|
241
|
+
}));
|
|
242
|
+
};
|
|
243
|
+
//Skip sequelize migrate table
|
|
244
|
+
await Promise.all(Object.values(tables).filter(t => !['sequelizemeta', 'tramp_migrations'].includes(t)).map(tableHandler));
|
|
245
|
+
logger.info('All DB schemas generated');
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
export class MakeGraphql extends Command {
|
|
249
|
+
static getName() {
|
|
250
|
+
return 'make:graphql';
|
|
251
|
+
}
|
|
252
|
+
static getDescription() {
|
|
253
|
+
return 'Generate graphql schema';
|
|
254
|
+
}
|
|
255
|
+
static getSpec() {
|
|
256
|
+
return {
|
|
257
|
+
dir: {
|
|
258
|
+
required: false,
|
|
259
|
+
description: 'Where entity files to be generated'
|
|
260
|
+
},
|
|
261
|
+
prefix: {
|
|
262
|
+
required: false,
|
|
263
|
+
description: 'Table prefix'
|
|
264
|
+
},
|
|
265
|
+
mapping: {
|
|
266
|
+
required: false,
|
|
267
|
+
description: 'Mapping file path'
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
// 原调用传入 mappedTableName 但未使用(JS 实参多于形参),可选参数保持调用形态且不改变函数 length
|
|
272
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
273
|
+
static typeMapping(_type, _mappedTableName) {
|
|
274
|
+
const type = _type.toLowerCase();
|
|
275
|
+
if (type === 'tinyint(1)' || type === 'boolean' || type === 'bit(1)') {
|
|
276
|
+
return 'Boolean';
|
|
277
|
+
}
|
|
278
|
+
if (type.match(/^(smallint|mediumint|tinyint|int)/)) {
|
|
279
|
+
return 'Int';
|
|
280
|
+
}
|
|
281
|
+
if (type.startsWith('bigint')) {
|
|
282
|
+
return 'Int';
|
|
283
|
+
}
|
|
284
|
+
if (type.startsWith('enum')) {
|
|
285
|
+
return 'Enum';
|
|
286
|
+
}
|
|
287
|
+
if (type.match(/^string|varchar|varying|nvarchar/)) {
|
|
288
|
+
return 'String';
|
|
289
|
+
}
|
|
290
|
+
if (type.startsWith('char')) {
|
|
291
|
+
return 'String';
|
|
292
|
+
}
|
|
293
|
+
if (type.match(/text|ntext$/)) {
|
|
294
|
+
return 'String';
|
|
295
|
+
}
|
|
296
|
+
if (type.startsWith('year')) {
|
|
297
|
+
return 'Int';
|
|
298
|
+
}
|
|
299
|
+
if (type.startsWith('datetime')) {
|
|
300
|
+
return 'String';
|
|
301
|
+
}
|
|
302
|
+
if (type.startsWith('date')) {
|
|
303
|
+
return 'String';
|
|
304
|
+
}
|
|
305
|
+
if (type.startsWith('time')) {
|
|
306
|
+
return 'String';
|
|
307
|
+
}
|
|
308
|
+
if (type.match(/^(float8|double precision)/)) {
|
|
309
|
+
return 'Float';
|
|
310
|
+
}
|
|
311
|
+
if (type.match(/^(float|float4)/)) {
|
|
312
|
+
return 'Float';
|
|
313
|
+
}
|
|
314
|
+
if (type.startsWith('decimal')) {
|
|
315
|
+
return 'Float';
|
|
316
|
+
}
|
|
317
|
+
if (type.match(/^uuid|uniqueidentifier/)) {
|
|
318
|
+
return 'String';
|
|
319
|
+
}
|
|
320
|
+
if (type.startsWith('jsonb')) {
|
|
321
|
+
return 'JSON';
|
|
322
|
+
}
|
|
323
|
+
if (type.startsWith('json')) {
|
|
324
|
+
return 'JSON';
|
|
325
|
+
}
|
|
326
|
+
if (type.startsWith('geometry')) {
|
|
327
|
+
return 'String';
|
|
328
|
+
}
|
|
329
|
+
return type;
|
|
330
|
+
}
|
|
331
|
+
getEnums(_type, columnName, tableName) {
|
|
332
|
+
const type = _type.toLowerCase();
|
|
333
|
+
const values = type.slice(5, -1).split(',').map(v => v.slice(1, -1));
|
|
334
|
+
return {
|
|
335
|
+
name: `ENUM_${tableName}_${columnName}`,
|
|
336
|
+
values
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
async run() {
|
|
340
|
+
const config = DI.get('config').get();
|
|
341
|
+
const logger = DI.get('logger');
|
|
342
|
+
const sequelize = new Sequelize(config.db.database, null, null, Object.assign({}, config.sequelize, config.db, { logging: logger.getInstance().verbose }));
|
|
343
|
+
const query = sequelize.getQueryInterface();
|
|
344
|
+
let tables = await query.showAllTables();
|
|
345
|
+
const views = await sequelize.query(`SHOW FULL TABLES IN ${config.db.database} WHERE TABLE_TYPE LIKE 'VIEW'`, {
|
|
346
|
+
type: sequelize.QueryTypes.SELECT,
|
|
347
|
+
raw: true
|
|
348
|
+
});
|
|
349
|
+
if (views) {
|
|
350
|
+
const viewNames = views.map(v => Object.values(v)[0]);
|
|
351
|
+
tables = tables.filter(t => !viewNames.includes(t));
|
|
352
|
+
}
|
|
353
|
+
const { dir, prefix, mapping } = this.getArgv();
|
|
354
|
+
if (prefix) {
|
|
355
|
+
tables = tables.filter(t => t.startsWith(prefix));
|
|
356
|
+
}
|
|
357
|
+
const path = dir ? `${process.cwd()}/${dir}` : `${process.cwd()}/src/graphql`;
|
|
358
|
+
const schemaPath = `${path}/entities`;
|
|
359
|
+
const schemaTemplate = fs.readFileSync(`${import.meta.dirname}/../../template/graphql.ejs`, 'utf8');
|
|
360
|
+
const mappingFile = mapping ? `${process.cwd()}/${mapping}` : `${process.cwd()}/src/graphql/mapping.json`;
|
|
361
|
+
const mappingContent = JSON.parse(fs.readFileSync(mappingFile, 'utf8'));
|
|
362
|
+
const getMappedTableName = (tableName) => (mappingContent[tableName] ? mappingContent[tableName] : tableName);
|
|
363
|
+
fs.mkdirSync(path, { recursive: true });
|
|
364
|
+
fs.mkdirSync(schemaPath, { recursive: true });
|
|
365
|
+
logger.info('Start generate GraphQL schemas to dir %s', path);
|
|
366
|
+
const tableHandler = async (tableName) => {
|
|
367
|
+
const enums = [];
|
|
368
|
+
//describeTable 的 ColumnsDescription 与可回写形态不直接可比,运行时字段同源
|
|
369
|
+
const columns = (await query.describeTable(tableName));
|
|
370
|
+
const rawColumns = await sequelize.query(`SHOW FULL COLUMNS FROM ${tableName}`, {
|
|
371
|
+
type: sequelize.QueryTypes.SELECT,
|
|
372
|
+
raw: true
|
|
373
|
+
});
|
|
374
|
+
const mappedTableName = getMappedTableName(tableName);
|
|
375
|
+
Object.values(rawColumns).forEach((rawColumn) => {
|
|
376
|
+
const columnName = rawColumn.Field;
|
|
377
|
+
let type = MakeGraphql.typeMapping(columns[columnName].type, mappedTableName);
|
|
378
|
+
if (type === 'Enum') {
|
|
379
|
+
const enumObj = this.getEnums(columns[columnName].type, columnName, mappedTableName);
|
|
380
|
+
type = enumObj.name;
|
|
381
|
+
enums.push(enumObj);
|
|
382
|
+
}
|
|
383
|
+
columns[columnName].type = type;
|
|
384
|
+
columns[columnName].unique = rawColumn.Key === 'UNI';
|
|
385
|
+
columns[columnName].comment = rawColumn.Comment;
|
|
386
|
+
columns[columnName].autoIncrement = rawColumn.Extra.startsWith('auto_increment') === true;
|
|
387
|
+
});
|
|
388
|
+
const indexes = await MakeEntity.getIndexes(tableName, sequelize);
|
|
389
|
+
const schemaFile = `${schemaPath}/${tableName}.graphqls`;
|
|
390
|
+
try {
|
|
391
|
+
fs.accessSync(schemaFile);
|
|
392
|
+
logger.info('Graphql schema file %s generate override, already exists by %s', tableName, schemaFile);
|
|
393
|
+
}
|
|
394
|
+
catch {
|
|
395
|
+
logger.info('Graphql schema file %s generated as %s', tableName, schemaFile);
|
|
396
|
+
}
|
|
397
|
+
fs.writeFileSync(schemaFile, template(schemaTemplate)({
|
|
398
|
+
tableName,
|
|
399
|
+
mappedTableName,
|
|
400
|
+
columns,
|
|
401
|
+
indexes,
|
|
402
|
+
enums
|
|
403
|
+
}));
|
|
404
|
+
};
|
|
405
|
+
//Skip sequelize migrate table
|
|
406
|
+
await Promise.all(Object.values(tables).filter(t => !['sequelizemeta', 'tramp_migrations'].includes(t)).map(tableHandler));
|
|
407
|
+
logger.info('All DB schemas generated');
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
//# sourceMappingURL=make_entity.js.map
|