更新缓存方案到midway最新

This commit is contained in:
cool 2024-03-06 14:33:03 +08:00
parent e23099a95e
commit a12d0a0473
43 changed files with 137 additions and 1738 deletions

View File

@ -4,14 +4,10 @@
"description": "一个项目用COOL就够了",
"private": true,
"dependencies": {
"@cool-midway/cache-manager-fs-hash": "^7.0.0",
"@cool-midway/cloud": "^7.0.0",
"@cool-midway/core": "^7.1.4",
"@cool-midway/iot": "^7.0.0",
"@cool-midway/core": "^7.1.5",
"@cool-midway/rpc": "^7.0.0",
"@cool-midway/task": "^7.0.0",
"@midwayjs/bootstrap": "^3.15.0",
"@midwayjs/cache": "^3.14.0",
"@midwayjs/core": "^3.15.0",
"@midwayjs/cron": "^3.15.0",
"@midwayjs/cross-domain": "^3.15.1",
@ -20,12 +16,12 @@
"@midwayjs/koa": "^3.15.1",
"@midwayjs/logger": "^3.3.0",
"@midwayjs/static-file": "^3.15.1",
"@midwayjs/task": "^3.6.0",
"@midwayjs/typeorm": "^3.15.0",
"@midwayjs/upload": "^3.15.1",
"@midwayjs/validate": "^3.15.1",
"@midwayjs/view-ejs": "^3.15.1",
"axios": "^1.6.7",
"cache-manager-ioredis-yet": "^2.0.1",
"decompress": "^4.2.1",
"ipip-ipdb": "^0.6.0",
"jsonwebtoken": "^9.0.2",

View File

@ -1,6 +1,9 @@
import { CoolConfig, MODETYPE } from '@cool-midway/core';
import { CoolConfig } from '@cool-midway/core';
import { MidwayConfig } from '@midwayjs/core';
import * as fsStore from '@cool-midway/cache-manager-fs-hash';
import { CoolCacheStore } from '@cool-midway/core';
// redis缓存
// import { redisStore } from 'cache-manager-ioredis-yet';
export default {
// use for cookie sign key, should change to your own and keep security
@ -23,14 +26,32 @@ export default {
fileSize: '200mb',
whitelist: null,
},
// 缓存 可切换成其他缓存如redis http://midwayjs.org/docs/extensions/cache
cache: {
store: fsStore,
options: {
path: 'cache',
ttl: -1,
// 缓存 可切换成其他缓存如redis http://www.midwayjs.org/docs/extensions/caching
cacheManager: {
clients: {
default: {
store: CoolCacheStore,
options: {
path: 'cache',
ttl: 0,
},
},
},
},
// cacheManager: {
// clients: {
// default: {
// store: redisStore,
// options: {
// port: 6379,
// host: '127.0.0.1',
// password: '',
// ttl: 0,
// db: 0,
// },
// },
// },
// },
cool: {
// 已经插件化,本地文件上传查看 plugin/config.ts其他云存储查看对应插件的使用
file: {},

View File

@ -9,14 +9,12 @@ import * as staticFile from '@midwayjs/static-file';
import * as cron from '@midwayjs/cron';
// import * as crossDomain from '@midwayjs/cross-domain';
import * as cool from '@cool-midway/core';
import * as cloud from '@cool-midway/cloud';
import { ILogger } from '@midwayjs/logger';
import * as upload from '@midwayjs/upload';
import { IMidwayApplication } from '@midwayjs/core';
// import * as swagger from '@midwayjs/swagger';
// import * as rpc from '@cool-midway/rpc';
// import * as task from '@cool-midway/task';
// import * as iot from '@cool-midway/iot';
@Configuration({
imports: [
@ -42,11 +40,7 @@ import { IMidwayApplication } from '@midwayjs/core';
// rpc,
// 任务与队列
// task,
// cool-admin 云开发组件
cloud,
// 物联网开发如MQTT支持等
// iot,
// swagger 文档
// swagger 文档 http://www.midwayjs.org/docs/extensions/swagger
// swagger,
{
component: info,

View File

@ -6,7 +6,7 @@ import { BaseSysLogService } from '../service/sys/log';
*
*/
@Job({
cronTime: FORMAT.CRONTAB.EVERY_PER_10_SECOND,
cronTime: FORMAT.CRONTAB.EVERY_DAY,
start: true,
})
export class BaseLogJob implements IJob {

View File

@ -516,347 +516,6 @@
"isShow": false,
"childMenus": []
},
{
"name": "函数开发",
"router": null,
"perms": null,
"type": 0,
"icon": "icon-fx",
"orderNum": 12,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "云数据库",
"router": "/cloud/db",
"perms": null,
"type": 1,
"icon": "icon-db",
"orderNum": 1,
"viewPath": "modules/cloud/views/db.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "初始化Entity",
"router": null,
"perms": "cloud:db:initEntity",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "删除",
"router": null,
"perms": "cloud:db:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "修改",
"router": null,
"perms": "cloud:db:update,cloud:db:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "数据操作测试",
"router": null,
"perms": "cloud:db:data",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "单个信息",
"router": null,
"perms": "cloud:db:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "列表查询",
"router": null,
"perms": "cloud:db:list",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "分页查询",
"router": null,
"perms": "cloud:db:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "新增",
"router": null,
"perms": "cloud:db:add",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
},
{
"name": "云函数",
"router": "/cloud/func/info",
"perms": null,
"type": 1,
"icon": "icon-menu",
"orderNum": 2,
"viewPath": "modules/cloud/views/func/info.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "调用云函数",
"router": null,
"perms": "cloud:func:info:invoke",
"type": 2,
"icon": null,
"orderNum": 98,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "删除",
"router": null,
"perms": "cloud:func:info:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "修改",
"router": null,
"perms": "cloud:func:info:update,cloud:func:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "单个信息",
"router": null,
"perms": "cloud:func:info:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "列表查询",
"router": null,
"perms": "cloud:func:info:list",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "分页查询",
"router": null,
"perms": "cloud:func:info:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "新增",
"router": null,
"perms": "cloud:func:info:add",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "云函数开发",
"router": null,
"perms": "cloud:func:info:info,cloud:func:info:update,cloud:func:info:invoke",
"type": 2,
"icon": null,
"orderNum": 99,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "查看日志",
"router": null,
"perms": "cloud:func:log:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
}
]
},
{
"name": "物联管理",
"router": null,
"perms": null,
"type": 0,
"icon": "icon-iot",
"orderNum": 12,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "MQTT",
"router": "/iot/device",
"perms": null,
"type": 1,
"icon": "icon-device",
"orderNum": 1,
"viewPath": "modules/iot/views/device.vue",
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "删除",
"router": null,
"perms": "iot:device:delete",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "单个信息",
"router": null,
"perms": "iot:device:info",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "列表查询",
"router": null,
"perms": "iot:device:list",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "分页查询",
"router": null,
"perms": "iot:device:page",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "修改",
"router": null,
"perms": "iot:device:info,iot:device:update",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "新增",
"router": null,
"perms": "iot:device:add",
"type": 2,
"icon": null,
"orderNum": 0,
"viewPath": null,
"keepAlive": true,
"isShow": true,
"childMenus": []
}
]
}
]
},
{
"name": "数据管理",
"router": null,
@ -1162,18 +821,6 @@
"keepAlive": true,
"isShow": true,
"childMenus": [
{
"name": "页面设计",
"router": "/design/page",
"perms": null,
"type": 1,
"icon": "icon-design",
"orderNum": 95,
"viewPath": "modules/design/views/page.vue",
"keepAlive": true,
"isShow": true,
"childMenus": []
},
{
"name": "后端插件",
"router": "/helper/plugins/serve",

View File

@ -3,8 +3,13 @@ import * as _ from 'lodash';
import { CoolUrlTagData, RESCODE, TagTypes } from '@cool-midway/core';
import * as jwt from 'jsonwebtoken';
import { NextFunction, Context } from '@midwayjs/koa';
import { IMiddleware, IMidwayApplication, Init } from '@midwayjs/core';
import { CacheManager } from '@midwayjs/cache';
import {
IMiddleware,
IMidwayApplication,
Init,
InjectClient,
} from '@midwayjs/core';
import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager';
/**
*
@ -19,8 +24,8 @@ export class BaseAuthorityMiddleware
@Config('module.base')
jwtConfig;
@Inject()
cacheManager: CacheManager;
@InjectClient(CachingFactory, 'default')
midwayCache: MidwayCache;
@Inject()
coolUrlTagData: CoolUrlTagData;
@ -61,11 +66,11 @@ export class BaseAuthorityMiddleware
return;
}
if (ctx.admin) {
const rToken = await this.cacheManager.get(
const rToken = await this.midwayCache.get(
`admin:token:${ctx.admin.userId}`
);
// 判断密码版本是否正确
const passwordV = await this.cacheManager.get(
const passwordV = await this.midwayCache.get(
`admin:passwordVersion:${ctx.admin.userId}`
);
if (passwordV != ctx.admin.passwordVersion) {
@ -119,7 +124,7 @@ export class BaseAuthorityMiddleware
if (rToken !== token && this.jwtConfig.jwt.sso) {
statusCode = 401;
} else {
let perms: string[] = await this.cacheManager.get(
let perms: string[] = await this.midwayCache.get(
`admin:perms:${ctx.admin.userId}`
);
if (!_.isEmpty(perms)) {

View File

@ -1,4 +1,4 @@
import { Inject, Provide, Config } from '@midwayjs/decorator';
import { Inject, Provide, Config, InjectClient } from '@midwayjs/decorator';
import { BaseService, CoolCommException } from '@cool-midway/core';
import { LoginDTO } from '../../dto/login';
import * as svgCaptcha from 'svg-captcha';
@ -14,7 +14,7 @@ import { BaseSysDepartmentService } from './department';
import * as jwt from 'jsonwebtoken';
import * as svgToDataURL from 'mini-svg-data-uri';
import { Context } from '@midwayjs/koa';
import { CacheManager } from '@midwayjs/cache';
import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager';
import { readFileSync } from 'fs';
const { svg2png, initialize } = require('svg2png-wasm');
initialize(readFileSync('./node_modules/svg2png-wasm/svg2png_wasm_bg.wasm'));
@ -24,8 +24,8 @@ initialize(readFileSync('./node_modules/svg2png-wasm/svg2png_wasm_bg.wasm'));
*/
@Provide()
export class BaseSysLoginService extends BaseService {
@Inject()
cacheManager: CacheManager;
@InjectClient(CachingFactory, 'default')
midwayCache: MidwayCache;
@InjectEntityModel(BaseSysUserEntity)
baseSysUserEntity: Repository<BaseSysUserEntity>;
@ -90,10 +90,10 @@ export class BaseSysLoginService extends BaseService {
roleIds,
user.username === 'admin'
);
await this.cacheManager.set(`admin:department:${user.id}`, departments);
await this.cacheManager.set(`admin:perms:${user.id}`, perms);
await this.cacheManager.set(`admin:token:${user.id}`, result.token);
await this.cacheManager.set(
await this.midwayCache.set(`admin:department:${user.id}`, departments);
await this.midwayCache.set(`admin:perms:${user.id}`, perms);
await this.midwayCache.set(`admin:token:${user.id}`, result.token);
await this.midwayCache.set(
`admin:token:refresh:${user.id}`,
result.token
);
@ -150,10 +150,10 @@ export class BaseSysLoginService extends BaseService {
Buffer.from(result.data, 'binary').toString('base64');
}
// 半小时过期
await this.cacheManager.set(
await this.midwayCache.set(
`verify:img:${result.captchaId}`,
svg.text.toLowerCase(),
{ ttl: 1800 }
1800 * 1000
);
return result;
}
@ -164,11 +164,11 @@ export class BaseSysLoginService extends BaseService {
async logout() {
if (!this.coolConfig.jwt.sso) return;
const { userId } = this.ctx.admin;
await this.cacheManager.del(`admin:department:${userId}`);
await this.cacheManager.del(`admin:perms:${userId}`);
await this.cacheManager.del(`admin:token:${userId}`);
await this.cacheManager.del(`admin:token:refresh:${userId}`);
await this.cacheManager.del(`admin:passwordVersion:${userId}`);
await this.midwayCache.del(`admin:department:${userId}`);
await this.midwayCache.del(`admin:perms:${userId}`);
await this.midwayCache.del(`admin:token:${userId}`);
await this.midwayCache.del(`admin:token:refresh:${userId}`);
await this.midwayCache.del(`admin:passwordVersion:${userId}`);
}
/**
@ -177,11 +177,11 @@ export class BaseSysLoginService extends BaseService {
* @param value
*/
async captchaCheck(captchaId, value) {
const rv = await this.cacheManager.get(`verify:img:${captchaId}`);
const rv = await this.midwayCache.get(`verify:img:${captchaId}`);
if (!rv || !value || value.toLowerCase() !== rv) {
return false;
} else {
this.cacheManager.del(`verify:img:${captchaId}`);
this.midwayCache.del(`verify:img:${captchaId}`);
return true;
}
}
@ -194,7 +194,7 @@ export class BaseSysLoginService extends BaseService {
* @param isRefresh
*/
async generateToken(user, roleIds, expire, isRefresh?) {
await this.cacheManager.set(
await this.midwayCache.set(
`admin:passwordVersion:${user.id}`,
user.passwordV
);
@ -237,11 +237,11 @@ export class BaseSysLoginService extends BaseService {
result.refreshToken = jwt.sign(decoded, this.coolConfig.jwt.secret, {
expiresIn: refreshExpire,
});
await this.cacheManager.set(
await this.midwayCache.set(
`admin:passwordVersion:${decoded['userId']}`,
decoded['passwordVersion']
);
await this.cacheManager.set(
await this.midwayCache.set(
`admin:token:${decoded['userId']}`,
result.token
);

View File

@ -1,9 +1,9 @@
import { Inject, Provide } from '@midwayjs/decorator';
import { Inject, InjectClient, Provide } from '@midwayjs/decorator';
import { BaseService, CoolCommException } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Not, Repository } from 'typeorm';
import { BaseSysParamEntity } from '../../entity/sys/param';
import { CacheManager } from '@midwayjs/cache';
import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager';
/**
*
@ -13,18 +13,18 @@ export class BaseSysParamService extends BaseService {
@InjectEntityModel(BaseSysParamEntity)
baseSysParamEntity: Repository<BaseSysParamEntity>;
@Inject()
cacheManager: CacheManager;
@InjectClient(CachingFactory, 'default')
midwayCache: MidwayCache;
/**
* key获得对应的参数
* @param key
*/
async dataByKey(key) {
let result: any = await this.cacheManager.get(`param:${key}`);
let result: any = await this.midwayCache.get(`param:${key}`);
if (!result) {
result = await this.baseSysParamEntity.findOneBy({ keyName: key });
this.cacheManager.set(`param:${key}`, result);
this.midwayCache.set(`param:${key}`, result);
}
if (result) {
if (result.dataType == 0) {
@ -50,7 +50,7 @@ export class BaseSysParamService extends BaseService {
*/
async htmlByKey(key) {
let html = '<html><title>@title</title><body>@content</body></html>';
let result: any = await this.cacheManager.get(`param:${key}`);
let result: any = await this.midwayCache.get(`param:${key}`);
if (result) {
html = html
.replace('@content', result.data)
@ -85,7 +85,7 @@ export class BaseSysParamService extends BaseService {
async modifyAfter() {
const params = await this.baseSysParamEntity.find();
for (const param of params) {
await this.cacheManager.set(`param:${param.keyName}`, param);
await this.midwayCache.set(`param:${param.keyName}`, param);
}
}
}

View File

@ -1,10 +1,10 @@
import { Inject, Provide } from '@midwayjs/decorator';
import { Inject, InjectClient, Provide } from '@midwayjs/decorator';
import { BaseService } from '@cool-midway/core';
import { BaseSysMenuService } from './menu';
import { BaseSysRoleService } from './role';
import { BaseSysDepartmentService } from './department';
import { Context } from '@midwayjs/koa';
import { CacheManager } from '@midwayjs/cache';
import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager';
import { BaseSysRoleEntity } from '../../entity/sys/role';
import { In, Repository } from 'typeorm';
import { InjectEntityModel } from '@midwayjs/typeorm';
@ -14,8 +14,8 @@ import { InjectEntityModel } from '@midwayjs/typeorm';
*/
@Provide()
export class BaseSysPermsService extends BaseService {
@Inject()
cacheManager: CacheManager;
@InjectClient(CachingFactory, 'default')
midwayCache: MidwayCache;
@Inject()
baseSysMenuService: BaseSysMenuService;
@ -40,13 +40,13 @@ export class BaseSysPermsService extends BaseService {
async refreshPerms(userId) {
const roleIds = await this.baseSysRoleService.getByUser(userId);
const perms = await this.baseSysMenuService.getPerms(roleIds);
await this.cacheManager.set(`admin:perms:${userId}`, perms);
await this.midwayCache.set(`admin:perms:${userId}`, perms);
// 更新部门权限
const departments = await this.baseSysDepartmentService.getByRoleIds(
roleIds,
await this.isAdmin(roleIds)
);
await this.cacheManager.set(`admin:department:${userId}`, departments);
await this.midwayCache.set(`admin:department:${userId}`, departments);
}
/**
@ -78,7 +78,7 @@ export class BaseSysPermsService extends BaseService {
* @return ID数组
*/
async departmentIds(userId: number) {
const department: any = await this.cacheManager.get(
const department: any = await this.midwayCache.get(
`admin:department:${userId}`
);
if (department) {

View File

@ -1,4 +1,4 @@
import { Inject, Provide } from '@midwayjs/decorator';
import { Inject, InjectClient, Provide } from '@midwayjs/decorator';
import { BaseService, CoolCommException } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { In, Repository } from 'typeorm';
@ -8,7 +8,7 @@ import * as _ from 'lodash';
import { BaseSysUserRoleEntity } from '../../entity/sys/user_role';
import * as md5 from 'md5';
import { BaseSysDepartmentEntity } from '../../entity/sys/department';
import { CacheManager } from '@midwayjs/cache';
import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager';
/**
*
@ -24,8 +24,8 @@ export class BaseSysUserService extends BaseService {
@InjectEntityModel(BaseSysDepartmentEntity)
baseSysDepartmentEntity: Repository<BaseSysDepartmentEntity>;
@Inject()
cacheManager: CacheManager;
@InjectClient(CachingFactory, 'default')
midwayCache: MidwayCache;
@Inject()
baseSysPermsService: BaseSysPermsService;
@ -186,7 +186,7 @@ export class BaseSysUserService extends BaseService {
throw new CoolCommException('原密码错误');
}
param.passwordV = userInfo.passwordV + 1;
await this.cacheManager.set(
await this.midwayCache.set(
`admin:passwordVersion:${param.id}`,
param.passwordV
);
@ -211,7 +211,7 @@ export class BaseSysUserService extends BaseService {
throw new CoolCommException('用户不存在');
}
param.passwordV = userInfo.passwordV + 1;
await this.cacheManager.set(
await this.midwayCache.set(
`admin:passwordVersion:${param.id}`,
param.passwordV
);
@ -230,6 +230,6 @@ export class BaseSysUserService extends BaseService {
* @param userId
*/
async forbidden(userId) {
await this.cacheManager.del(`admin:token:${userId}`);
await this.midwayCache.del(`admin:token:${userId}`);
}
}

View File

@ -1,19 +0,0 @@
import { ModuleConfig } from '@cool-midway/core';
/**
*
*/
export default () => {
return {
// 模块名称
name: '云服务',
// 模块描述
description: '云函数、云数据库、云存储等',
// 中间件,只对本模块有效
middlewares: [],
// 中间件,全局有效
globalMiddlewares: [],
// 模块加载顺序默认为0值越大越优先加载
order: 0,
} as ModuleConfig;
};

View File

@ -1,34 +0,0 @@
import { CloudDBService } from './../../service/db';
import { CloudDBEntity } from './../../entity/db';
import { Body, Inject, Post, Provide } from '@midwayjs/decorator';
import { CoolController, BaseController } from '@cool-midway/core';
/**
*
*/
@Provide()
@CoolController({
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
entity: CloudDBEntity,
service: CloudDBService,
pageQueryOp: {
fieldEq: ['status'],
keyWordLikeFields: ['name'],
},
})
export class CloudDBController extends BaseController {
@Inject()
cloudDBService: CloudDBService;
@Post('/initEntity', { summary: '初始化Entity' })
async initEntity() {
await this.cloudDBService.initEntity();
return this.ok();
}
@Post('/data', { summary: '数据操作' })
async data(@Body() body) {
const { id, method, params } = body;
return this.ok(await this.cloudDBService.data(id, method, params));
}
}

View File

@ -1,31 +0,0 @@
import { CloudFuncService } from './../../../service/func';
import { CloudFuncInfoEntity } from '../../../entity/func/info';
import { Body, Inject, Post, Provide } from '@midwayjs/decorator';
import { CoolController, BaseController } from '@cool-midway/core';
import { CloudReq } from '@cool-midway/cloud';
/**
*
*/
@Provide()
@CoolController({
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
entity: CloudFuncInfoEntity,
pageQueryOp: {
keyWordLikeFields: ['name'],
fieldEq: ['status'],
},
})
export class AdminCloudFuncInfoController extends BaseController {
@Inject()
cloudFuncService: CloudFuncService;
@Post('/invoke', { summary: '调用云函数' })
async invoke(
@Body() req: CloudReq,
@Body('id') id: number,
@Body('content') content: string
) {
return this.ok(await this.cloudFuncService.invoke(req, id, content));
}
}

View File

@ -1,16 +0,0 @@
import { CloudFuncLogEntity } from './../../../entity/func/log';
import { Provide } from '@midwayjs/decorator';
import { CoolController, BaseController } from '@cool-midway/core';
/**
*
*/
@Provide()
@CoolController({
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
entity: CloudFuncLogEntity,
pageQueryOp: {
fieldEq: ['infoId'],
},
})
export class AdminCloudFuncLogController extends BaseController {}

View File

@ -1,12 +0,0 @@
import { Body, Post, Provide } from '@midwayjs/decorator';
import { CoolController, BaseController } from '@cool-midway/core';
/**
*
*/
@Provide()
@CoolController()
export class AppCloudFuncController extends BaseController {
@Post('/invoke', { summary: '调用云函数' })
async invoke(@Body() body) {}
}

View File

@ -1,28 +0,0 @@
import { BaseEntity } from '@cool-midway/core';
import { Column, Entity, Index } from 'typeorm';
/**
*
*/
@Entity('cloud_db')
export class CloudDBEntity extends BaseEntity {
@Column({ comment: '名称' })
name: string;
@Column({ comment: '说明', nullable: true })
readme: string;
@Column({ comment: '内容', type: 'text' })
content: string;
@Index({ unique: true })
@Column({ comment: '类名', nullable: true })
className: string;
@Index({ unique: true })
@Column({ comment: '表名', nullable: true })
tableName: string;
@Column({ comment: '状态 0-禁用 1-启用', default: 1 })
status: number;
}

View File

@ -1,20 +0,0 @@
import { BaseEntity } from '@cool-midway/core';
import { Column, Entity } from 'typeorm';
/**
*
*/
@Entity('cloud_func_info')
export class CloudFuncInfoEntity extends BaseEntity {
@Column({ comment: '名称' })
name: string;
@Column({ comment: '说明', nullable: true })
readme: string;
@Column({ comment: '内容', type: 'text' })
content: string;
@Column({ comment: '状态 0-禁用 1-启用', default: 1 })
status: number;
}

View File

@ -1,28 +0,0 @@
import { CloudReq } from '@cool-midway/cloud';
import { BaseEntity } from '@cool-midway/core';
import { Column, Entity, Index } from 'typeorm';
/**
*
*/
@Entity('cloud_func_log')
export class CloudFuncLogEntity extends BaseEntity {
@Index()
@Column({ comment: '云函数ID' })
infoId: number;
@Column({ comment: '请求', type: 'json', nullable: true })
request: CloudReq;
@Column({ comment: '结果', type: 'json', nullable: true })
result: string;
@Column({ comment: '类型 0-失败 1-成功', default: 1 })
type: number;
@Column({ comment: '异常信息', nullable: true, type: 'text' })
error: string;
@Column({ comment: '耗时(毫秒)', default: 0 })
time: number;
}

View File

@ -1,21 +0,0 @@
import { IMidwayApplication } from '@midwayjs/core';
import { CoolEvent, Event } from '@cool-midway/core';
import { App } from '@midwayjs/decorator';
import { CloudDBService } from '../service/db';
/**
*
*/
@CoolEvent()
export class AppEvent {
@App()
app: IMidwayApplication;
@Event('onServerReady')
async initEntity() {
const cloudDBService = await this.app
.getApplicationContext()
.getAsync(CloudDBService);
cloudDBService.initEntity();
}
}

View File

@ -1,159 +0,0 @@
import { Config, Singleton } from '@midwayjs/core';
import { CloudDBEntity } from './../entity/db';
import { Inject, Provide } from '@midwayjs/decorator';
import { BaseService, CoolCommException, CoolConfig } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { CoolCloudDb } from '@cool-midway/cloud';
import * as _ from 'lodash';
/**
*
*/
@Provide()
@Singleton()
export class CloudDBService extends BaseService {
@InjectEntityModel(CloudDBEntity)
cloudDBEntity: Repository<CloudDBEntity>;
@Inject()
coolCloudDb: CoolCloudDb;
@Config('cool')
coolConfig: CoolConfig;
@Config('typeorm.dataSource.default.type')
ormType: string;
/**
*
* @param id
* @param method
* @param params
* @returns
*/
async data(id, method, params: any = {}) {
const db = await this.cloudDBEntity.findOneBy({ id });
const repository = await this.getRepository(db?.className);
if (method == 'add' || method == 'update') {
await repository.save(params);
return {
id: params.id,
};
}
if (method == 'delete') {
await repository.delete(params.ids);
}
if (method == 'clear') {
await repository.clear();
}
if (method == 'page') {
const { page = 1, size = this.coolConfig.crud.pageSize } = params;
const find = repository
.createQueryBuilder('a')
.offset((page - 1) * size)
.limit(size)
.orderBy('a.createTime', 'DESC');
return {
list: await find.getMany(),
pagination: {
page: parseInt(page),
size: parseInt(size),
total: await find.getCount(),
},
};
}
}
/**
*
* @param className
*/
async getRepository(className: string): Promise<Repository<any>> {
const info = await this.cloudDBEntity.findOneBy({
className,
});
if (!info) {
throw new CoolCommException('云数据表不存在');
}
return await this.coolCloudDb.getRepository(info.className);
}
/**
*
* @param param
* @returns
*/
async addOrUpdate(param, type) {
const { tableName, className } = this.coolCloudDb.parseCode(param.content);
// 更新
if (param.id) {
const old = await this.cloudDBEntity.findOneBy({ id: param.id });
if (tableName != old.tableName) {
const check = await this.cloudDBEntity.findOneBy({ tableName });
if (check) {
throw new CoolCommException('已存在相同的表名');
}
}
if (className != old.className) {
const checkClass = await this.cloudDBEntity.findOneBy({ className });
if (checkClass) {
throw new CoolCommException('已存在相同的类名');
}
}
} else {
const check = await this.cloudDBEntity.findOneBy({ tableName });
if (check) {
throw new CoolCommException('已存在相同的表名');
}
const checkClass = await this.cloudDBEntity.findOneBy({ className });
if (checkClass) {
throw new CoolCommException('已存在相同的类名');
}
}
await super.addOrUpdate(
{
...param,
tableName,
className: className.replace('CLOUD', ''),
},
type
);
}
/**
*
*/
async initEntity() {
if (this.ormType != 'mysql') return;
const tables = await this.cloudDBEntity.findBy({ status: 1 });
const tableNames = [];
for (const table of tables) {
const parseData = this.coolCloudDb.parseCode(table.content);
tableNames.push(parseData.tableName);
await this.coolCloudDb.createTable(table.content, true);
}
// 所有云函数表
const { database } = this.coolCloudDb.coolDataSource.options;
const allTables = (
await this.coolCloudDb.coolDataSource.query(
`SELECT table_name from information_schema.columns where table_schema like '${database}' and table_name like 'func_%' group by table_name`
)
).map(e => {
return e.TABLE_NAME || e.table_name;
});
// 需要删除的云函数表
const deleteTables = allTables.filter(e => {
return !tableNames.includes(e);
});
if (!_.isEmpty(deleteTables)) {
await this.coolCloudDb.coolDataSource.query(
`drop table ${deleteTables.join(',')}`
);
}
}
async modifyAfter() {
await this.initEntity();
}
}

View File

@ -1,130 +0,0 @@
import { CloudFuncLogEntity } from './../entity/func/log';
import { Config, IMidwayApplication } from '@midwayjs/core';
import { CloudFuncInfoEntity } from './../entity/func/info';
import { App, Provide, Inject } from '@midwayjs/decorator';
import { BaseService, CoolConfig, CoolCommException } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import * as moment from 'moment';
// eslint-disable-next-line node/no-unpublished-import
import * as ts from 'typescript';
import { Context } from '@midwayjs/koa';
import {
CloudCrud,
CloudReq,
CoolCloudDb,
CoolCloudFunc,
} from '@cool-midway/cloud';
/**
*
*/
@Provide()
export class CloudFuncService extends BaseService {
@InjectEntityModel(CloudFuncInfoEntity)
cloudFuncInfoEntity: Repository<CloudFuncInfoEntity>;
@InjectEntityModel(CloudFuncLogEntity)
cloudFuncLogEntity: Repository<CloudFuncLogEntity>;
@App()
app: IMidwayApplication;
@Inject()
ctx: Context;
@Inject()
coolCloudDb: CoolCloudDb;
@Inject()
coolCloudFunc: CoolCloudFunc;
@Config('cool')
coolConfig: CoolConfig;
/**
*
* @param req
* @param id
* @param content
* @returns
*/
async invoke(req: CloudReq, id: number, content?: string) {
const start = moment().valueOf();
let funcInfo: CloudFuncInfoEntity;
if (id) {
funcInfo = await this.cloudFuncInfoEntity
.createQueryBuilder()
.cache(true)
.where({ id, status: 1 })
.getOne();
req.name = funcInfo?.name;
} else {
funcInfo = await this.cloudFuncInfoEntity
.createQueryBuilder()
.cache(true)
.where({ name: req.name, status: 1 })
.getOne();
}
if (!funcInfo) {
throw new CoolCommException('云函数不存在或被禁用');
}
if (!req.method) {
throw new CoolCommException('调用方法不能为空');
}
let result;
let func: CloudCrud;
const code = content ? content : funcInfo.content;
const className = this.coolCloudFunc.getClassName(code);
const newCode = ts.transpile(
`${code}
func = new ${className}();
`,
{
emitDecoratorMetadata: true,
module: ts.ModuleKind.CommonJS,
target: ts.ScriptTarget.ES2018,
removeComments: true,
}
);
const log = new CloudFuncLogEntity();
try {
eval(newCode);
func.ctx = this.ctx;
func.app = this.app;
func.coolCloudDb = this.coolCloudDb;
func.coolConfig = this.coolConfig;
await func.init(req);
const apis: string[] = func.curdOption.api || [];
// 判断是否可以执行6个通用方法
if (
['add', 'delete', 'update', 'info', 'list', 'page'].includes(
req.method
) &&
!apis.includes(req.method)
) {
throw new CoolCommException(
`${req.method} 方法未在curdOption.api 中配置`
);
}
// result = func.add({ name: 'aa', age: 22, test2: 1 });
result = await func[req.method](req.params);
} catch (error) {
log.error = error.message;
}
log.infoId = funcInfo.id;
log.request = req;
log.result = result;
log.type = log.error ? 0 : 1;
const end = moment().valueOf();
log.time = end - start;
this.cloudFuncLogEntity.insert(log);
if (id) {
return log;
} else {
return result;
}
}
}

View File

@ -1,7 +1,7 @@
import { DemoCacheService } from '../../service/cache';
import { Inject, Post, Provide, Get } from '@midwayjs/decorator';
import { Inject, Post, Provide, Get, InjectClient } from '@midwayjs/decorator';
import { CoolController, BaseController } from '@cool-midway/core';
import { CacheManager } from '@midwayjs/cache';
import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager';
/**
*
@ -9,8 +9,8 @@ import { CacheManager } from '@midwayjs/cache';
@Provide()
@CoolController()
export class AppDemoCacheController extends BaseController {
@Inject()
cacheManager: CacheManager;
@InjectClient(CachingFactory, 'default')
midwayCache: MidwayCache;
@Inject()
demoCacheService: DemoCacheService;
@ -21,12 +21,10 @@ export class AppDemoCacheController extends BaseController {
*/
@Post('/set')
async set() {
await this.cacheManager.set('a', 1);
await this.midwayCache.set('a', 1);
// 缓存10秒
await this.cacheManager.set('a', 1, {
ttl: 30,
});
return this.ok(await this.cacheManager.get('a'));
await this.midwayCache.set('a', 1, 10 * 1000);
return this.ok(await this.midwayCache.get('a'));
}
/**

View File

@ -1,5 +1,6 @@
import { Provide, Scope, ScopeEnum } from '@midwayjs/decorator';
import { Provide } from '@midwayjs/decorator';
import { CoolEvent, Event } from '@cool-midway/core';
import { Scope, ScopeEnum } from '@midwayjs/core';
/**
*

View File

@ -1,19 +0,0 @@
import { ModuleConfig } from '@cool-midway/core';
/**
*
*/
export default () => {
return {
// 模块名称
name: '物联网',
// 模块描述
description: '物联网模块,主要提供物联交互,状态监测等',
// 中间件,只对本模块有效
middlewares: [],
// 中间件,全局有效
globalMiddlewares: [],
// 模块加载顺序默认为0值越大越优先加载
order: 0,
} as ModuleConfig;
};

View File

@ -1,17 +0,0 @@
import { IotDeviceEntity } from './../../entity/device';
import { Provide } from '@midwayjs/decorator';
import { CoolController, BaseController } from '@cool-midway/core';
/**
*
*/
@Provide()
@CoolController({
api: ['add', 'delete', 'update', 'info', 'list', 'page'],
entity: IotDeviceEntity,
pageQueryOp: {
keyWordLikeFields: ['label', 'uniqueId'],
fieldEq: ['status'],
},
})
export class AdminIotDeviceController extends BaseController {}

View File

@ -1,16 +0,0 @@
import { IotMessageEntity } from './../../entity/message';
import { Provide } from '@midwayjs/decorator';
import { CoolController, BaseController } from '@cool-midway/core';
/**
*
*/
@Provide()
@CoolController({
api: ['page'],
entity: IotMessageEntity,
pageQueryOp: {
fieldEq: ['deviceId'],
},
})
export class AdminIotMessageController extends BaseController {}

View File

@ -1,27 +0,0 @@
import { IotMqttService } from './../../service/mqtt';
import { Provide, Get, Post, Body, Inject } from '@midwayjs/decorator';
import { CoolController, BaseController } from '@cool-midway/core';
/**
* MQTT相关
*/
@Provide()
@CoolController()
export class AdminIotMqttController extends BaseController {
@Inject()
iotMqttService: IotMqttService;
@Get('/config', { summary: 'MQTT配置信息' })
async config() {
return this.ok(await this.iotMqttService.config());
}
@Post('/publish', { summary: '推送消息' })
async publish(
@Body('uniqueId') uniqueId: string,
@Body('data') data: string
) {
await this.iotMqttService.publish(uniqueId, data);
return this.ok();
}
}

View File

@ -1,19 +0,0 @@
import { Get, Inject, Provide } from '@midwayjs/decorator';
import { CoolController, BaseController } from '@cool-midway/core';
import { CoolMqttServe } from '@cool-midway/iot';
/**
* MQTT
*/
@Provide()
@CoolController()
export class IotMqttController extends BaseController {
@Inject()
coolMqttServe: CoolMqttServe;
@Get('/publish')
async publish() {
await this.coolMqttServe.publish('presence', 'hello');
return this.ok();
}
}

View File

@ -1,25 +0,0 @@
import { BaseEntity } from '@cool-midway/core';
import { Column, Entity, Index } from 'typeorm';
/**
*
*/
@Entity('iot_device')
export class IotDeviceEntity extends BaseEntity {
@Column({ comment: '图标', nullable: true })
icon: string;
@Column({ comment: '名称' })
name: string;
@Index({ unique: true })
@Column({ comment: '设备唯一ID' })
uniqueId: string;
@Index()
@Column({ comment: '状态 0-离线 1-在线', default: 0 })
status: number;
@Column({ comment: '客户端ID', nullable: true })
clientId: string;
}

View File

@ -1,19 +0,0 @@
import { BaseEntity } from '@cool-midway/core';
import { Column, Entity, Index } from 'typeorm';
/**
*
*/
@Entity('iot_message')
export class IotMessageEntity extends BaseEntity {
@Index()
@Column({ comment: '设备ID' })
deviceId: number;
@Column({ comment: '数据' })
data: string;
@Index()
@Column({ comment: '类型 0-推送 1-接收', default: 1 })
type: number;
}

View File

@ -1,18 +0,0 @@
import { Inject } from '@midwayjs/core';
import { CoolEvent, Event } from '@cool-midway/core';
import { IotDeviceService } from '../service/device';
/**
*
*/
@CoolEvent()
export class AppEvent {
@Inject()
iotDeviceService: IotDeviceService;
@Event('onServerReady')
async onServerReady() {
// 重置设备状态
await this.iotDeviceService.resetStatus();
}
}

View File

@ -1,86 +0,0 @@
import { IotMessageService } from './../service/message';
import { IotDeviceService } from './../service/device';
import { ILogger, Inject } from '@midwayjs/core';
import { CoolMqtt, CoolMqttEvent, CoolMqttServe } from '@cool-midway/iot';
/**
*
*/
@CoolMqtt()
export class IotMQTTEvent {
@Inject()
iotDeviceService: IotDeviceService;
@Inject()
iotMessageService: IotMessageService;
@Inject()
logger: ILogger;
@Inject()
coolMqttServe: CoolMqttServe;
/**
*
* @param client
*/
@CoolMqttEvent('client')
async client(client) {
this.logger.info('mqtt client event clientId:', client.id);
}
/**
*
* @param packet
* @param client
*/
@CoolMqttEvent('publish')
async publish(packet, client) {
if (packet.cmd) {
// console.log(11);
await this.iotMessageService.record(
packet.topic,
packet.payload.toString(),
packet.properties?.contentType == 'push' ? 0 : 1
);
if (
!packet.topic.includes('@admin') &&
packet.properties?.contentType != 'push'
) {
this.coolMqttServe.publish(
`${packet.topic}@admin`,
packet.payload.toString()
);
}
}
}
/**
*
* @param subscriptions
* @param client
*/
@CoolMqttEvent('subscribe')
async subscribe(subscriptions, client) {
await this.iotDeviceService.register(subscriptions[0].topic, client.id);
}
/**
*
* @param subscriptions
* @param client
*/
@CoolMqttEvent('unsubscribe')
async unsubscribe(subscriptions, client) {
await this.iotDeviceService.changeStatus(subscriptions[0], 0);
}
/**
*
* @param client
*/
@CoolMqttEvent('clientDisconnect')
async clientDisconnect(client) {
this.logger.info('mqtt clientDisconnect event clientId:', client.id);
}
}

View File

@ -1,49 +0,0 @@
import { IotDeviceEntity } from './../entity/device';
import { Provide, Scope, ScopeEnum } from '@midwayjs/decorator';
import { BaseService } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
/**
*
*/
@Provide()
@Scope(ScopeEnum.Request, { allowDowngrade: true })
export class IotDeviceService extends BaseService {
@InjectEntityModel(IotDeviceEntity)
iotDeviceEntity: Repository<IotDeviceEntity>;
/**
*
* @param uniqueId
* @param clientId
*/
async register(uniqueId: string, clientId: string) {
const info = await this.iotDeviceEntity.findOneBy({ uniqueId });
if (info) {
await this.iotDeviceEntity.update({ uniqueId }, { status: 1, clientId });
} else {
// await this.iotDeviceEntity.insert({ uniqueId, clientId, status: 1 });
}
}
/**
*
*/
async resetStatus() {
await this.iotDeviceEntity
.createQueryBuilder()
.update()
.set({ status: 0 })
.execute();
}
/**
*
* @param uniqueId
* @param status
*/
async changeStatus(uniqueId: string, status: number) {
await this.iotDeviceEntity.update({ uniqueId }, { status });
}
}

View File

@ -1,32 +0,0 @@
import { IotMessageEntity } from './../entity/message';
import { IotDeviceEntity } from './../entity/device';
import { BaseService } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { Provide, Singleton } from '@midwayjs/core';
/**
*
*/
@Provide()
@Singleton()
export class IotMessageService extends BaseService {
@InjectEntityModel(IotDeviceEntity)
iotDeviceEntity: Repository<IotDeviceEntity>;
@InjectEntityModel(IotMessageEntity)
iotMessageEntity: Repository<IotMessageEntity>;
/**
*
* @param uniqueId ID
* @param data
* @param type 0- 1-
*/
async record(uniqueId: string, data: string, type: number) {
const device = await this.iotDeviceEntity.findOneBy({ uniqueId });
if (device) {
await this.iotMessageEntity.insert({ deviceId: device.id, data, type });
}
}
}

View File

@ -1,43 +0,0 @@
import { CoolMqttServe } from '@cool-midway/iot';
import { IotMessageEntity } from './../entity/message';
import { Config, Inject, Provide } from '@midwayjs/decorator';
import { BaseService, CoolIotConfig } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
/**
* MQTT
*/
@Provide()
export class IotMqttService extends BaseService {
@InjectEntityModel(IotMessageEntity)
iotMessageEntity: Repository<IotMessageEntity>;
@Config('cool.iot')
coolIotConfig: CoolIotConfig;
@Inject()
coolMqttServe: CoolMqttServe;
/**
*
*/
async config() {
return {
port: this.coolIotConfig.port,
};
}
/**
*
* @param uniqueId ID
* @param data
*/
async publish(uniqueId: string, data: string) {
await this.coolMqttServe.publish(uniqueId, data, {
properties: {
contentType: 'push',
},
});
}
}

View File

@ -1,8 +1,15 @@
import { CoolEvent, Event } from '@cool-midway/core';
import { App, Config, ILogger, Inject, Logger } from '@midwayjs/core';
import {
App,
Config,
ILogger,
Inject,
InjectClient,
Logger,
} from '@midwayjs/core';
import { IMidwayKoaApplication } from '@midwayjs/koa';
import { PLUGIN_CACHE_KEY, PluginCenterService } from '../service/center';
import { CacheManager } from '@midwayjs/cache';
import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager';
/**
* jwt.secret
@ -18,15 +25,15 @@ export class BaseAppEvent {
@App()
app: IMidwayKoaApplication;
@Inject()
cacheManager: CacheManager;
@InjectClient(CachingFactory, 'default')
midwayCache: MidwayCache;
@Inject()
pluginCenterService: PluginCenterService;
@Event('onServerReady')
async onServerReady() {
await this.cacheManager.set(PLUGIN_CACHE_KEY, []);
await this.midwayCache.set(PLUGIN_CACHE_KEY, []);
this.pluginCenterService.init();
}
}

View File

@ -4,6 +4,7 @@ import {
IMidwayApplication,
Init,
Inject,
InjectClient,
Scope,
ScopeEnum,
} from '@midwayjs/core';
@ -14,10 +15,10 @@ import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { PluginInfo } from '../interface';
import * as _ from 'lodash';
import { CacheManager } from '@midwayjs/cache';
import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager';
import { CoolEventManager } from '@cool-midway/core';
export const PLUGIN_CACHE_KEY = 'PLUGIN_INIT';
export const PLUGIN_CACHE_KEY = 'plugin:init';
export const EVENT_PLUGIN_READY = 'EVENT_PLUGIN_READY';
@ -39,8 +40,8 @@ export class PluginCenterService {
@InjectEntityModel(PluginInfoEntity)
pluginInfoEntity: Repository<PluginInfoEntity>;
@Inject()
cacheManager: CacheManager;
@InjectClient(CachingFactory, 'default')
midwayCache: MidwayCache;
@Inject()
coolEventManager: CoolEventManager;
@ -50,13 +51,13 @@ export class PluginCenterService {
* @returns
*/
async init() {
const inits: any[] = (await this.cacheManager.get(PLUGIN_CACHE_KEY)) || [];
const inits: any[] = (await this.midwayCache.get(PLUGIN_CACHE_KEY)) || [];
const pid = process.pid;
if (inits.includes(pid)) return;
this.plugins.clear();
await this.initHooks();
await this.initPlugin();
await this.cacheManager.set(PLUGIN_CACHE_KEY, inits.concat([process.pid]));
await this.midwayCache.set(PLUGIN_CACHE_KEY, inits.concat([process.pid]));
this.coolEventManager.emit(EVENT_PLUGIN_READY);
}

View File

@ -3,11 +3,16 @@ import { BaseService, CoolCommException } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Equal, Not, Repository } from 'typeorm';
import { PluginInfoEntity } from '../entity/info';
import { Config, IMidwayApplication, IMidwayContext } from '@midwayjs/core';
import {
Config,
IMidwayApplication,
IMidwayContext,
InjectClient,
} from '@midwayjs/core';
import * as _ from 'lodash';
import { PluginInfo } from '../interface';
import { PLUGIN_CACHE_KEY, PluginCenterService } from './center';
import { CacheManager } from '@midwayjs/cache';
import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager';
/**
*
@ -29,8 +34,8 @@ export class PluginService extends BaseService {
@Config('module.plugin.hooks')
hooksConfig;
@Inject()
cacheManager: CacheManager;
@InjectClient(CachingFactory, 'default')
midwayCache: MidwayCache;
/**
*
@ -45,7 +50,7 @@ export class PluginService extends BaseService {
*
*/
async reInit() {
await this.cacheManager.set(PLUGIN_CACHE_KEY, []);
await this.midwayCache.set(PLUGIN_CACHE_KEY, []);
await this.pluginCenterService.init();
}

View File

@ -1,301 +0,0 @@
import { CoolEps } from '@cool-midway/core';
import { Config, Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
import * as _ from 'lodash';
/**
*
*/
@Provide()
@Scope(ScopeEnum.Singleton)
export class SwaggerBuilder {
@Config('module.swagger.base')
swaggerBase;
@Inject()
eps: CoolEps;
json = {};
@Config('cool.eps')
epsConfig: boolean;
/**
*
*/
async init() {
if (this.epsConfig) {
await this.build();
}
}
/**
*
*/
async build() {
const epsData = {
app: this.eps.app || [],
admin: this.eps.admin || [],
module: this.eps.module || {},
};
this.json = this.convertToSwagger(epsData);
}
/**
* Epss转换为Swagger
* @param dataJson
* @returns
*/
convertToSwagger(dataJson) {
const swagger = {
...this.swaggerBase,
paths: {},
tags: Object.keys(dataJson.module)
.filter(item => item != 'swagger')
.map(moduleKey => {
return {
key: moduleKey,
name: dataJson.module[moduleKey].name || '',
description: dataJson.module[moduleKey].description || '',
};
}),
};
// 添加组件
function addComponentSchemas(data) {
if (_.isEmpty(data.name)) return;
const schema = {
type: 'object',
properties: {},
required: [],
};
data.columns.forEach(column => {
const swaggerType = mapTypeToSwagger(column.type);
schema.properties[column.propertyName] = {
type: swaggerType,
description: column.comment,
};
if (!column.nullable) {
schema.required.push(column.propertyName);
}
});
swagger.components.schemas[data.name] = schema;
return data.name;
}
// 转换类型
function mapTypeToSwagger(type) {
const typeMapping = {
string: 'string',
number: 'number',
bigint: 'integer',
datetime: 'string', // assuming datetime is formatted as ISO8601 string
};
return typeMapping[type] || 'string';
}
// 添加请求体
function addRequest(path, schemas, data) {
if (path == '/info' || path == '/list' || path == '/page') {
if (path == '/info') {
data.parameters = [
{
name: 'id',
in: 'query',
description: 'ID',
required: true,
schema: {
type: 'integer',
},
},
];
} else {
data.requestBody = {
description: '动态请求体',
required: true,
content: {
'application/json': {
schema: {
type: 'object',
properties:
path == '/page'
? {
page: {
type: 'integer',
description: '第几页',
default: 1,
},
size: {
type: 'integer',
description: '每页大小',
default: 20,
},
}
: {},
},
},
},
};
}
data.responses = {
'200': {
description: '成功响应',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
code: {
type: 'integer',
description: '状态码',
},
message: {
type: 'string',
description: '响应消息',
},
data: {
$ref: `#/components/schemas/${schemas}`,
},
},
},
},
},
},
};
}
if (path == '/add' || path == '/update') {
data.requestBody = {
description: schemas,
required: true,
content: {
'application/json': {
schema: {
$ref: `#/components/schemas/${schemas}`,
},
},
},
};
data.responses = {
'200': {
description: '成功响应',
content: {
'application/json': {
example: {
code: 1000,
message: 'success',
data: {
id: 6,
},
},
},
},
},
};
}
if (path == '/delete') {
data.requestBody = {
description: schemas,
required: true,
content: {
'application/json': {
schema: {
type: 'object',
properties: {
ids: {
type: 'array',
description: 'ID数组',
items: {
type: 'integer',
},
},
},
},
},
},
};
data.responses = {
'200': {
description: '成功响应',
content: {
'application/json': {
example: {
code: 1000,
message: 'success',
},
},
},
},
};
}
}
// 处理每个模块下的API接口
function processModuleApis(moduleApis, moduleName) {
moduleApis.forEach(module => {
const schemas = addComponentSchemas({
name: module.name,
columns: module.columns,
});
if (Array.isArray(module.api)) {
module.api.forEach(api => {
const fullPath = `${api.prefix == '/' ? '' : api.prefix}${
api.path
}`;
const method = api.method.toLowerCase();
if (!swagger.paths[fullPath]) {
swagger.paths[fullPath] = {};
}
swagger.paths[fullPath][method] = {
summary:
`${module.info.type.description || module.info.type.name}` +
api.summary || '',
security: api.ignoreToken
? []
: [
{
ApiKeyAuth: [],
},
],
tags: [moduleName || '其他'],
responses: schemas
? {
'200': {
description: 'Success response',
content: {
'application/json': {
schema: {
$ref: `#/components/schemas/${schemas}`,
},
},
},
},
}
: {},
};
addRequest(api.path, schemas, swagger.paths[fullPath][method]);
});
}
});
}
// 遍历app和admin中的所有模块
Object.keys(dataJson.app).forEach(moduleKey => {
if (Array.isArray(dataJson.app[moduleKey])) {
processModuleApis(
dataJson.app[moduleKey],
dataJson.module[moduleKey]?.name
);
}
});
Object.keys(dataJson.admin).forEach(moduleKey => {
if (Array.isArray(dataJson.admin[moduleKey])) {
processModuleApis(
dataJson.admin[moduleKey],
dataJson.module[moduleKey]?.name
);
}
});
return swagger;
}
}

View File

@ -1,50 +0,0 @@
import { ModuleConfig } from '@cool-midway/core';
/**
*
*/
export default ({ app }) => {
return {
// 模块名称
name: 'Swagger',
// 模块描述
description: '处理和生成swagger文档',
// 中间件,只对本模块有效
middlewares: [],
// 中间件,全局有效
globalMiddlewares: [],
// 模块加载顺序默认为0值越大越优先加载
order: 0,
// swagger基本配置
base: {
openapi: '3.1.0',
info: {
title: 'Cool Admin 在线API文档',
version: '7.x',
description: '本文档是由Cool Admin内部自动构建完成',
contact: {
name: '开发文档',
url: 'https://cool-js.com',
},
},
// 请求地址
servers: [
{
url: `http://127.0.0.1:${app?.getConfig('koa.port') || 8001}`,
description: '本地后台地址',
},
],
paths: {},
components: {
schemas: {},
securitySchemes: {
Auth: {
type: 'apiKey',
name: 'Authorization',
in: 'header',
},
},
},
},
} as ModuleConfig;
};

View File

@ -1,35 +0,0 @@
import { Config, Controller, Get, Inject } from '@midwayjs/decorator';
import { Context } from '@midwayjs/koa';
import { SwaggerBuilder } from '../builder';
import { BaseController } from '@cool-midway/core';
/**
*
*/
@Controller('/swagger')
export class SwaggerIndexController extends BaseController {
@Inject()
ctx: Context;
@Inject()
swaggerBuilder: SwaggerBuilder;
@Config('cool.eps')
epsConfig: boolean;
@Get('/', { summary: 'swagger界面' })
public async index() {
if (!this.epsConfig) {
return this.fail('Eps未开启');
}
await this.ctx.render('swagger', {});
}
@Get('/json', { summary: '获得Swagger JSON数据' })
public async json() {
if (!this.epsConfig) {
return this.fail('Eps未开启');
}
return this.swaggerBuilder.json;
}
}

View File

@ -1,28 +0,0 @@
import { CoolEvent, Event } from '@cool-midway/core';
import { App, ILogger, Inject, Logger } from '@midwayjs/core';
import { IMidwayKoaApplication } from '@midwayjs/koa';
import { SwaggerBuilder } from '../builder';
/**
* jwt.secret
*/
@CoolEvent()
export class SwaggerAppEvent {
@Logger()
coreLogger: ILogger;
@App()
app: IMidwayKoaApplication;
@Inject()
swaggerBuilder: SwaggerBuilder;
@Event('onServerReady')
async onServerReady() {
this.swaggerBuilder.init().then(() => {
this.coreLogger.info(
'\x1B[36m [cool:module:swagger] midwayjs cool module swagger build success\x1B[0m'
);
});
}
}

View File

@ -1,7 +1,13 @@
import { Provide, Config, Inject, Init } from '@midwayjs/decorator';
import {
Provide,
Config,
Inject,
Init,
InjectClient,
} from '@midwayjs/decorator';
import { BaseService, CoolCommException } from '@cool-midway/core';
import * as _ from 'lodash';
import { CacheManager } from '@midwayjs/cache';
import { CachingFactory, MidwayCache } from '@midwayjs/cache-manager';
import { PluginService } from '../../plugin/service/info';
/**
@ -13,8 +19,8 @@ export class UserSmsService extends BaseService {
@Config('module.user.sms')
config;
@Inject()
cacheManager: CacheManager;
@InjectClient(CachingFactory, 'default')
midwayCache: MidwayCache;
@Inject()
pluginService: PluginService;
@ -54,7 +60,7 @@ export class UserSmsService extends BaseService {
code,
});
}
this.cacheManager.set(`sms:${phone}`, code, this.config.timeout);
this.midwayCache.set(`sms:${phone}`, code, this.config.timeout * 1000);
} catch (error) {
throw new CoolCommException('发送过于频繁,请稍后再试');
}
@ -67,7 +73,7 @@ export class UserSmsService extends BaseService {
* @returns
*/
async checkCode(phone, code) {
const cacheCode = await this.cacheManager.get(`sms:${phone}`);
const cacheCode = await this.midwayCache.get(`sms:${phone}`);
if (cacheCode == code) {
return true;
}