diff --git a/.vscode/config.code-snippets b/.vscode/config.code-snippets new file mode 100644 index 0000000..2abbf4f --- /dev/null +++ b/.vscode/config.code-snippets @@ -0,0 +1,28 @@ +{ + "config": { + "prefix": "config", + "body": [ + "import { ModuleConfig } from '@cool-midway/core';", + "", + "/**", + " * 模块配置", + " */", + "export default () => {", + " return {", + " // 模块名称", + " name: 'xxx',", + " // 模块描述", + " description: 'xxx',", + " // 中间件,只对本模块有效", + " middlewares: [],", + " // 中间件,全局有效", + " globalMiddlewares: [],", + " // 模块加载顺序,默认为0,值越大越优先加载", + " order: 0,", + " } as ModuleConfig;", + "};", + "" + ], + "description": "cool-admin config代码片段" + } +} diff --git a/.vscode/controller.code-snippets b/.vscode/controller.code-snippets new file mode 100644 index 0000000..5bd7095 --- /dev/null +++ b/.vscode/controller.code-snippets @@ -0,0 +1,19 @@ +{ + "controller": { + "prefix": "controller", + "body": [ + "import { CoolController, BaseController } from '@cool-midway/core';", + "", + "/**", + " * 描述", + " */", + "@CoolController({", + " api: ['add', 'delete', 'update', 'info', 'list', 'page'],", + " entity: 实体,", + "})", + "export class XxxController extends BaseController {}", + "" + ], + "description": "cool-admin controller代码片段" + } +} diff --git a/.vscode/entity.code-snippets b/.vscode/entity.code-snippets new file mode 100644 index 0000000..0a362e1 --- /dev/null +++ b/.vscode/entity.code-snippets @@ -0,0 +1,20 @@ +{ + "entity": { + "prefix": "entity", + "body": [ + "import { BaseEntity } from '../../base/entity/base';", + "import { Column, Entity } from 'typeorm';", + "", + "/**", + " * 描述", + " */", + "@Entity('xxx_xxx_xxx')", + "export class XxxEntity extends BaseEntity {", + " @Column({ comment: '描述' })", + " xxx: string;", + "}", + "" + ], + "description": "cool-admin entity代码片段" + } +} diff --git a/.vscode/event.code-snippets b/.vscode/event.code-snippets new file mode 100644 index 0000000..dae6473 --- /dev/null +++ b/.vscode/event.code-snippets @@ -0,0 +1,21 @@ +{ + "event": { + "prefix": "event", + "body": [ + "import { CoolEvent, Event } from '@cool-midway/core';", + "", + "/**", + " * 接收事件", + " */", + "@CoolEvent()", + "export class xxxEvent {", + " @Event('updateUser')", + " async updateUser(msg, a) {", + " console.log('ImEvent', 'updateUser', msg, a);", + " }", + "}", + "" + ], + "description": "cool-admin event代码片段" + } +} diff --git a/.vscode/middleware.code-snippets b/.vscode/middleware.code-snippets new file mode 100644 index 0000000..367be90 --- /dev/null +++ b/.vscode/middleware.code-snippets @@ -0,0 +1,29 @@ +{ + "middleware": { + "prefix": "middleware", + "body": [ + "import { Middleware } from '@midwayjs/decorator';", + "import { NextFunction, Context } from '@midwayjs/koa';", + "import { IMiddleware } from '@midwayjs/core';", + "", + "/**", + " * 描述", + " */", + "@Middleware()", + "export class XxxMiddleware implements IMiddleware {", + " resolve() {", + " return async (ctx: Context, next: NextFunction) => {", + " // 控制器前执行的逻辑", + " const startTime = Date.now();", + " // 执行下一个 Web 中间件,最后执行到控制器", + " await next();", + " // 控制器之后执行的逻辑", + " console.log(Date.now() - startTime);", + " };", + " }", + "}", + "" + ], + "description": "cool-admin middleware代码片段" + } +} diff --git a/.vscode/queue.code-snippets b/.vscode/queue.code-snippets new file mode 100644 index 0000000..3518633 --- /dev/null +++ b/.vscode/queue.code-snippets @@ -0,0 +1,21 @@ +{ + "queue": { + "prefix": "queue", + "body": [ + "import { BaseCoolQueue, CoolQueue } from '@cool-midway/task';", + "", + "/**", + " * 队列", + " */", + "@CoolQueue()", + "export abstract class xxxQueue extends BaseCoolQueue {", + " async data(job: any, done: any) {", + " console.log('收到的数据', job.data);", + " done();", + " }", + "}", + "" + ], + "description": "cool-admin service代码片段" + } +} diff --git a/.vscode/service.code-snippets b/.vscode/service.code-snippets new file mode 100644 index 0000000..54ffe0c --- /dev/null +++ b/.vscode/service.code-snippets @@ -0,0 +1,32 @@ +{ + "service": { + "prefix": "service", + "body": [ + "import { BaseService, Init, Provide } from '@cool-midway/core';", + "import { InjectEntityModel } from '@midwayjs/typeorm';", + "import { Repository } from 'typeorm';", + "", + "/**", + " * 描述", + " */", + "@Provide()", + "export class XxxService extends BaseService {", + " @InjectEntityModel(实体)", + " xxxEntity: Repository<实体>;", + "" + " @Init()" + " async init() {", + " await super.init();", + " this.setEntity(this.xxxEntity);", + " }", + "", + " /**", + " * 描述", + " */", + " async xxx() {}", + "}", + "" + ], + "description": "cool-admin service代码片段" + } +} \ No newline at end of file diff --git a/src/config/config.default.ts b/src/config/config.default.ts index 970c620..7ca802e 100644 --- a/src/config/config.default.ts +++ b/src/config/config.default.ts @@ -61,6 +61,9 @@ export default { cool: { // 已经插件化,本地文件上传查看 plugin/config.ts,其他云存储查看对应插件的使用 file: {}, + rpc: { + name: 'main', + }, // redis配置 redis: { port: 6379, diff --git a/src/config/config.prod.ts b/src/config/config.prod.ts index 796966e..4cafd44 100644 --- a/src/config/config.prod.ts +++ b/src/config/config.prod.ts @@ -23,7 +23,7 @@ export default { }, cool: { // 实体与路径,跟生成代码、前端请求、swagger文档相关 注意:线上不建议开启,以免暴露敏感信息 - eps: false, + eps: true, // 是否自动导入模块数据库 initDB: true, // 判断是否初始化的方式 diff --git a/src/configuration.ts b/src/configuration.ts index 814215b..e1a165d 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -19,7 +19,7 @@ import * as ProdConfig from './config/config.prod'; import * as cool from '@cool-midway/core'; import * as upload from '@midwayjs/upload'; import * as task from '@cool-midway/task'; -// import * as rpc from '@cool-midway/rpc'; +import * as rpc from '@cool-midway/rpc'; @Configuration({ imports: [ @@ -40,7 +40,7 @@ import * as task from '@cool-midway/task'; // cool-admin 官方组件 https://cool-js.com cool, // rpc 微服务 远程调用 - // rpc, + rpc, // 任务与队列 task, { diff --git a/src/entities.ts b/src/entities.ts index ca11496..c1361ab 100644 --- a/src/entities.ts +++ b/src/entities.ts @@ -10,17 +10,18 @@ import * as entity7 from './modules/recycle/entity/data'; import * as entity8 from './modules/plugin/entity/info'; import * as entity9 from './modules/dict/entity/type'; import * as entity10 from './modules/dict/entity/info'; -import * as entity11 from './modules/base/entity/base'; -import * as entity12 from './modules/base/entity/sys/user_role'; -import * as entity13 from './modules/base/entity/sys/user'; -import * as entity14 from './modules/base/entity/sys/role_menu'; -import * as entity15 from './modules/base/entity/sys/role_department'; -import * as entity16 from './modules/base/entity/sys/role'; -import * as entity17 from './modules/base/entity/sys/param'; -import * as entity18 from './modules/base/entity/sys/menu'; -import * as entity19 from './modules/base/entity/sys/log'; -import * as entity20 from './modules/base/entity/sys/department'; -import * as entity21 from './modules/base/entity/sys/conf'; +import * as entity11 from './modules/demo/entity/goods'; +import * as entity12 from './modules/base/entity/base'; +import * as entity13 from './modules/base/entity/sys/user_role'; +import * as entity14 from './modules/base/entity/sys/user'; +import * as entity15 from './modules/base/entity/sys/role_menu'; +import * as entity16 from './modules/base/entity/sys/role_department'; +import * as entity17 from './modules/base/entity/sys/role'; +import * as entity18 from './modules/base/entity/sys/param'; +import * as entity19 from './modules/base/entity/sys/menu'; +import * as entity20 from './modules/base/entity/sys/log'; +import * as entity21 from './modules/base/entity/sys/department'; +import * as entity22 from './modules/base/entity/sys/conf'; export const entities = [ ...Object.values(entity0), ...Object.values(entity1), @@ -44,4 +45,5 @@ export const entities = [ ...Object.values(entity19), ...Object.values(entity20), ...Object.values(entity21), + ...Object.values(entity22), ]; diff --git a/src/modules/demo/controller/admin/goods.ts b/src/modules/demo/controller/admin/goods.ts new file mode 100644 index 0000000..2bf6fdb --- /dev/null +++ b/src/modules/demo/controller/admin/goods.ts @@ -0,0 +1,11 @@ +import { CoolController, BaseController } from '@cool-midway/core'; +import { DemoGoodsEntity } from '../../entity/goods'; + +/** + * 商品模块-商品信息 + */ +@CoolController({ + api: ['add', 'delete', 'update', 'info', 'list', 'page'], + entity: DemoGoodsEntity, +}) +export class AdminDemoGoodsController extends BaseController {} diff --git a/src/modules/demo/controller/open/cache.ts b/src/modules/demo/controller/open/cache.ts new file mode 100644 index 0000000..7fea241 --- /dev/null +++ b/src/modules/demo/controller/open/cache.ts @@ -0,0 +1,37 @@ +import { DemoCacheService } from '../../service/cache'; +import { Inject, Post, Provide, Get, InjectClient } from '@midwayjs/core'; +import { CoolController, BaseController } from '@cool-midway/core'; +import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager'; + +/** + * 缓存 + */ +@CoolController() +export class OpenDemoCacheController extends BaseController { + @InjectClient(CachingFactory, 'default') + midwayCache: MidwayCache; + + @Inject() + demoCacheService: DemoCacheService; + + /** + * 设置缓存 + * @returns + */ + @Post('/set', { summary: '设置缓存' }) + async set() { + await this.midwayCache.set('a', 1); + // 缓存10秒 + await this.midwayCache.set('a', 1, 10 * 1000); + return this.ok(await this.midwayCache.get('a')); + } + + /** + * 获得缓存 + * @returns + */ + @Get('/get', { summary: '获得缓存' }) + async get() { + return this.ok(await this.demoCacheService.get()); + } +} diff --git a/src/modules/demo/controller/open/event.ts b/src/modules/demo/controller/open/event.ts new file mode 100644 index 0000000..552f0aa --- /dev/null +++ b/src/modules/demo/controller/open/event.ts @@ -0,0 +1,27 @@ +import { Inject, Post } from '@midwayjs/core'; +import { + CoolController, + BaseController, + CoolEventManager, +} from '@cool-midway/core'; + +/** + * 事件 + */ +@CoolController() +export class OpenDemoEventController extends BaseController { + @Inject() + coolEventManager: CoolEventManager; + + @Post('/comm', { summary: '普通事件,本进程生效' }) + async comm() { + await this.coolEventManager.emit('demo', { a: 2 }, 1); + return this.ok(); + } + + @Post('/global', { summary: '全局事件,多进程都有效' }) + async global() { + await this.coolEventManager.globalEmit('demo', false, { a: 2 }, 1); + return this.ok(); + } +} diff --git a/src/modules/demo/controller/open/goods.ts b/src/modules/demo/controller/open/goods.ts new file mode 100644 index 0000000..5d4ac71 --- /dev/null +++ b/src/modules/demo/controller/open/goods.ts @@ -0,0 +1,32 @@ +import { DemoGoodsService } from '../../service/goods'; +import { DemoGoodsEntity } from '../../entity/goods'; +import { Body, Config, Inject, Post, Provide } from '@midwayjs/core'; +import { CoolController, BaseController } from '@cool-midway/core'; +import { InjectEntityModel } from '@midwayjs/typeorm'; +import { Repository } from 'typeorm'; + +/** + * 测试 + */ +@CoolController({ + api: ['add', 'delete', 'update', 'info', 'list', 'page'], + entity: DemoGoodsEntity, + service: DemoGoodsService, +}) +export class OpenDemoGoodsController extends BaseController { + @InjectEntityModel(DemoGoodsEntity) + demoGoodsEntity: Repository; + + @Inject() + demoGoodsService: DemoGoodsService; + + @Post('/sqlPage', { summary: 'sql分页查询' }) + async sqlPage(@Body() query) { + return this.ok(await this.demoGoodsService.sqlPage(query)); + } + + @Post('/entityPage', { summary: 'entity分页查询' }) + async entityPage(@Body() query) { + return this.ok(await this.demoGoodsService.entityPage(query)); + } +} diff --git a/src/modules/demo/controller/open/plugin.ts b/src/modules/demo/controller/open/plugin.ts index ed381d7..c2d3310 100644 --- a/src/modules/demo/controller/open/plugin.ts +++ b/src/modules/demo/controller/open/plugin.ts @@ -13,13 +13,17 @@ export class OpenDemoPluginController extends BaseController { @Get('/invoke', { summary: '调用插件' }) async invoke() { // 获取插件实例 - const instance = await this.pluginService.getInstance('feishu'); - instance.sendByHook({ - msg_type: 'text', - content: { - text: '测试', - }, - }); + const instance: any = await this.pluginService.getInstance('ollama'); + // 调用chat + const messages = [ + { role: 'system', content: '你叫小酷,是一个智能助理' }, + { role: 'user', content: '写一个1000字的关于春天的文章' }, + ]; + for (let i = 0; i < 3; i++) { + instance.chat(messages, { stream: true }, res => { + console.log(i, res.content); + }); + } return this.ok(); } } diff --git a/src/modules/demo/controller/open/queue.ts b/src/modules/demo/controller/open/queue.ts new file mode 100644 index 0000000..92550c8 --- /dev/null +++ b/src/modules/demo/controller/open/queue.ts @@ -0,0 +1,49 @@ +import { Get, Inject, Post, Provide } from '@midwayjs/core'; +import { CoolController, BaseController } from '@cool-midway/core'; +import { DemoCommQueue } from '../../queue/comm'; +import { DemoGetterQueue } from '../../queue/getter'; + +/** + * 队列 + */ +@CoolController() +export class OpenDemoQueueController extends BaseController { + // 普通队列 + @Inject() + demoCommQueue: DemoCommQueue; + + // 主动消费队列 + @Inject() + demoGetterQueue: DemoGetterQueue; + + /** + * 发送数据到队列 + */ + @Post('/add', { summary: '发送队列数据' }) + async queue() { + this.demoCommQueue.add({ a: 2 }); + return this.ok(); + } + + @Post('/addGetter') + async addGetter() { + await this.demoGetterQueue.add({ a: new Date() }); + return this.ok(); + } + + /** + * 获得队列中的数据,只有当队列类型为getter时有效 + */ + @Get('/getter') + async getter() { + const job = await this.demoGetterQueue.getters.getJobs( + ['wait'], + 0, + 0, + true + ); + // 获得完将数据从队列移除 + await job[0]?.remove(); + return this.ok(job[0]?.data); + } +} diff --git a/src/modules/demo/controller/open/rpc.ts b/src/modules/demo/controller/open/rpc.ts new file mode 100644 index 0000000..3023b0e --- /dev/null +++ b/src/modules/demo/controller/open/rpc.ts @@ -0,0 +1,29 @@ +import { Inject, Provide, Get } from '@midwayjs/core'; +import { CoolController, BaseController } from '@cool-midway/core'; +import { DemoRpcService } from '../../service/rpc'; + +/** + * 远程RPC调用 + */ +@CoolController() +export class OpenDemoRpcController extends BaseController { + @Inject() + demoRpcService: DemoRpcService; + + @Get('/call', { summary: '远程调用' }) + async call() { + return this.ok(await this.demoRpcService.call()); + } + + @Get('/event', { summary: '集群事件' }) + async event() { + await this.demoRpcService.event(); + return this.ok(); + } + + @Get('/transaction', { summary: '分布式事务' }) + async transaction() { + await this.demoRpcService.transaction({ a: 1 }); + return this.ok(); + } +} diff --git a/src/modules/demo/controller/open/sse.ts b/src/modules/demo/controller/open/sse.ts new file mode 100644 index 0000000..8d0cef6 --- /dev/null +++ b/src/modules/demo/controller/open/sse.ts @@ -0,0 +1,49 @@ +import { CoolController, BaseController } from '@cool-midway/core'; +import { Get, Inject } from '@midwayjs/core'; +import { PluginService } from '../../../plugin/service/info'; +import { PassThrough } from 'stream'; +import { IMidwayKoaContext } from '@midwayjs/koa'; + +/** + * 事件流 服务端主动推送 + */ +@CoolController() +export class OpenDemoSSEController extends BaseController { + @Inject() + ctx: IMidwayKoaContext; + + @Inject() + pluginService: PluginService; + + @Get('/call', { summary: '事件流 服务端主动推送' }) + async call() { + // 设置响应头 + this.ctx.set('Content-Type', 'text/event-stream'); + this.ctx.set('Cache-Control', 'no-cache'); + this.ctx.set('Connection', 'keep-alive'); + + const stream = new PassThrough(); + + // 发送数据 + const send = (data: any) => { + stream.write(`data: ${JSON.stringify(data)}\n\n`); + }; + + // 获取插件实例 + const instance: any = await this.pluginService.getInstance('ollama'); + // 调用chat + const messages = [ + { role: 'system', content: '你叫小酷,是个编程助手' }, + { role: 'user', content: '用js写个Hello World' }, + ]; + instance.chat(messages, { stream: true }, res => { + send(res); + if (res.isEnd) { + this.ctx.res.end(); + } + }); + + this.ctx.status = 200; + this.ctx.body = stream; + } +} diff --git a/src/modules/demo/controller/open/transaction.ts b/src/modules/demo/controller/open/transaction.ts new file mode 100644 index 0000000..0fdada3 --- /dev/null +++ b/src/modules/demo/controller/open/transaction.ts @@ -0,0 +1,14 @@ +import { DemoGoodsEntity } from '../../entity/goods'; +import { Provide } from '@midwayjs/core'; +import { CoolController, BaseController } from '@cool-midway/core'; +import { DemoTransactionService } from '../../service/transaction'; + +/** + * 事务 + */ +@CoolController({ + api: ['add', 'delete', 'update', 'info', 'list', 'page'], + entity: DemoGoodsEntity, + service: DemoTransactionService, +}) +export class OpenDemoTransactionController extends BaseController {} diff --git a/src/modules/demo/entity/goods.ts b/src/modules/demo/entity/goods.ts new file mode 100644 index 0000000..d031bbd --- /dev/null +++ b/src/modules/demo/entity/goods.ts @@ -0,0 +1,32 @@ +import { BaseEntity } from '../../base/entity/base'; +import { Column, Entity, Index } from 'typeorm'; + +/** + * 商品模块-商品信息 + */ +@Entity('demo_goods') +export class DemoGoodsEntity extends BaseEntity { + @Index() + @Column({ comment: '标题', length: 50 }) + title: string; + + @Column({ + comment: '价格', + type: 'decimal', + precision: 5, + scale: 2, + }) + price: number; + + @Column({ comment: '描述', nullable: true }) + description: string; + + @Column({ comment: '主图', nullable: true }) + mainImage: string; + + @Column({ comment: '示例图', nullable: true, type: 'json' }) + exampleImages: string[]; + + @Column({ comment: '库存', default: 0 }) + stock: number; +} diff --git a/src/modules/demo/event/comm.ts b/src/modules/demo/event/comm.ts new file mode 100644 index 0000000..ae00a64 --- /dev/null +++ b/src/modules/demo/event/comm.ts @@ -0,0 +1,27 @@ +import { CoolEvent, Event } from '@cool-midway/core'; +import { EVENT_PLUGIN_READY } from '../../plugin/service/center'; + +/** + * 普通事件 + */ +@CoolEvent() +export class DemoCommEvent { + /** + * 根据事件名接收事件 + * @param msg + * @param a + */ + @Event('demo') + async demo(msg, a) { + console.log(`comm当前进程的ID是: ${process.pid}`); + console.log('comm收到消息', msg, a); + } + + /** + * 插件已就绪 + */ + @Event(EVENT_PLUGIN_READY) + async pluginReady() { + // TODO 插件已就绪 + } +} diff --git a/src/modules/demo/queue/comm.ts b/src/modules/demo/queue/comm.ts new file mode 100644 index 0000000..5b2f87d --- /dev/null +++ b/src/modules/demo/queue/comm.ts @@ -0,0 +1,20 @@ +import { BaseCoolQueue, CoolQueue } from '@cool-midway/task'; +import { IMidwayApplication } from '@midwayjs/core'; +import { App } from '@midwayjs/core'; + +/** + * 普通队列 + */ +@CoolQueue() +export class DemoCommQueue extends BaseCoolQueue { + @App() + app: IMidwayApplication; + + async data(job: any, done: any): Promise { + // 这边可以执行定时任务具体的业务或队列的业务 + console.log('数据', job.data); + // 抛出错误 可以让队列重试,默认重试5次 + //throw new Error('错误'); + done(); + } +} diff --git a/src/modules/demo/queue/getter.ts b/src/modules/demo/queue/getter.ts new file mode 100644 index 0000000..8da42c9 --- /dev/null +++ b/src/modules/demo/queue/getter.ts @@ -0,0 +1,7 @@ +import { BaseCoolQueue, CoolQueue } from '@cool-midway/task'; + +/** + * 主动消费队列 + */ +@CoolQueue({ type: 'getter' }) +export class DemoGetterQueue extends BaseCoolQueue {} diff --git a/src/modules/demo/queue/single.ts b/src/modules/demo/queue/single.ts new file mode 100644 index 0000000..c26f746 --- /dev/null +++ b/src/modules/demo/queue/single.ts @@ -0,0 +1,20 @@ +import { BaseCoolQueue, CoolQueue } from '@cool-midway/task'; +import { IMidwayApplication } from '@midwayjs/core'; +import { App } from '@midwayjs/core'; + +/** + * 单例队列,cluster 或 集群模式下 只会有一个实例消费数据 + */ +@CoolQueue({ type: 'single' }) +export class DemoSingleQueue extends BaseCoolQueue { + @App() + app: IMidwayApplication; + + async data(job: any, done: any): Promise { + // 这边可以执行定时任务具体的业务或队列的业务 + console.log('数据', job.data); + // 抛出错误 可以让队列重试,默认重试5次 + //throw new Error('错误'); + done(); + } +} diff --git a/src/modules/demo/service/cache.ts b/src/modules/demo/service/cache.ts new file mode 100644 index 0000000..d97d23d --- /dev/null +++ b/src/modules/demo/service/cache.ts @@ -0,0 +1,18 @@ +import { Provide } from '@midwayjs/core'; +import { CoolCache } from '@cool-midway/core'; + +/** + * 缓存 + */ +@Provide() +export class DemoCacheService { + // 数据缓存5秒 + @CoolCache(5) + async get() { + console.log('执行方法'); + return { + a: 1, + b: 2, + }; + } +} diff --git a/src/modules/demo/service/goods.ts b/src/modules/demo/service/goods.ts new file mode 100644 index 0000000..bd0877e --- /dev/null +++ b/src/modules/demo/service/goods.ts @@ -0,0 +1,40 @@ +import { DemoGoodsEntity } from './../entity/goods'; +import { Provide } from '@midwayjs/core'; +import { BaseService } from '@cool-midway/core'; +import { InjectEntityModel } from '@midwayjs/typeorm'; +import { Repository } from 'typeorm'; + +/** + * 商品示例 + */ +@Provide() +export class DemoGoodsService extends BaseService { + @InjectEntityModel(DemoGoodsEntity) + demoGoodsEntity: Repository; + + /** + * 执行sql分页 + */ + async sqlPage(query) { + await this.demoGoodsEntity.save({ + id: 1, + title: '标题', + price: 99.0, + description: '商品描述', + mainImage: 'https://cool-js.com/logo.png', + }); + return this.sqlRenderPage( + 'select * from demo_goods ORDER BY id ASC', + query, + false + ); + } + + /** + * 执行entity分页 + */ + async entityPage(query) { + const find = this.demoGoodsEntity.createQueryBuilder(); + return this.entityRenderPage(find, query); + } +} diff --git a/src/modules/demo/service/rpc.ts b/src/modules/demo/service/rpc.ts new file mode 100644 index 0000000..c37bbf9 --- /dev/null +++ b/src/modules/demo/service/rpc.ts @@ -0,0 +1,70 @@ +import { App, Provide } from '@midwayjs/core'; +import { DemoGoodsEntity } from '../entity/goods'; +import { IMidwayApplication, Inject } from '@midwayjs/core'; +import { + BaseRpcService, + CoolRpc, + CoolRpcService, + CoolRpcTransaction, +} from '@cool-midway/rpc'; +import { QueryRunner } from 'typeorm'; + +@Provide() +@CoolRpcService({ + entity: DemoGoodsEntity, + method: ['info', 'add', 'page'], +}) +export class DemoRpcService extends BaseRpcService { + @App() + app: IMidwayApplication; + + @Inject() + rpc: CoolRpc; + + /** + * 远程调用 + * @returns + */ + async call() { + return await this.rpc.call('goods', 'demoGoodsService', 'test', { + a: 1, + }); + } + + /** + * 集群事件 + */ + async event() { + this.rpc.event('test', { a: 1 }); + } + + async info(params) { + return params; + } + async getUser() { + return { + uid: '123', + username: 'mockedName', + phone: '12345678901', + email: 'xxx.xxx@xxx.com', + }; + } + + @CoolRpcTransaction() + async transaction(params, rpcTransactionId?, queryRunner?: QueryRunner) { + console.log('获得的参数', params); + const data = { + title: '商品标题', + pic: 'https://xxx', + price: 99.0, + type: 1, + }; + await queryRunner.manager.save(DemoGoodsEntity, data); + + // 将事务id传给调用的远程服务方法 + await this.rpc.call('goods', 'demoGoodsService', 'transaction', { + rpcTransactionId, + ...params, + }); + } +} diff --git a/src/modules/demo/service/transaction.ts b/src/modules/demo/service/transaction.ts new file mode 100644 index 0000000..a39ccad --- /dev/null +++ b/src/modules/demo/service/transaction.ts @@ -0,0 +1,23 @@ +import { DemoGoodsEntity } from './../entity/goods'; +import { Provide } from '@midwayjs/core'; +import { BaseService, CoolTransaction } from '@cool-midway/core'; +import { QueryRunner } from 'typeorm'; + +/** + * 操作事务 + */ +@Provide() +export class DemoTransactionService extends BaseService { + /** + * 事务操作 + */ + @CoolTransaction({ + connectionName: 'default', + }) + async add(param, queryRunner?: QueryRunner) { + await queryRunner.manager.insert(DemoGoodsEntity, param); + return { + id: param.id, + }; + } +} diff --git a/src/modules/swagger/builder.ts b/src/modules/swagger/builder.ts index bbada4c..576db92 100644 --- a/src/modules/swagger/builder.ts +++ b/src/modules/swagger/builder.ts @@ -24,7 +24,7 @@ export class SwaggerBuilder { */ async init() { if (this.epsConfig) { - await this.build(); + this.build(); } } @@ -257,6 +257,21 @@ export class SwaggerBuilder { }, ], tags: [moduleName || '其他'], + requestBody: + method == 'post' + ? { + description: '请求体', + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: {}, + }, + }, + }, + } + : {}, responses: schemas ? { '200': {