feat: add admin router manager
This commit is contained in:
1
src/admin/dashboard/index.ts
Normal file
1
src/admin/dashboard/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { manager } from './manager.ts';
|
||||
57
src/admin/dashboard/load.ts
Normal file
57
src/admin/dashboard/load.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { router } from '../../modules/router.ts';
|
||||
import { Route } from '@abearxiong/router';
|
||||
import { RouterCodeModel, RouterCode } from '../../models/code.ts';
|
||||
|
||||
enum CodeStatus {
|
||||
success = 0,
|
||||
fail = 1,
|
||||
}
|
||||
|
||||
export type CodeManager = {
|
||||
fn?: any;
|
||||
status?: CodeStatus;
|
||||
errorMsg?: string;
|
||||
} & Partial<RouterCode>;
|
||||
const codeDemoRun = `async function run(ctx) {
|
||||
ctx.body = 'test js';
|
||||
return ctx;
|
||||
}`;
|
||||
export const load = async function () {
|
||||
const codes = await RouterCodeModel.findAll();
|
||||
const codeManager: CodeManager[] = codes.map((item) => {
|
||||
const { path, key, id, code, project } = item.toJSON();
|
||||
console.log('item', item, 'code', item.code);
|
||||
try {
|
||||
const fn: any = new Function(
|
||||
'ctx',
|
||||
`
|
||||
${code}
|
||||
return run(ctx);
|
||||
`,
|
||||
);
|
||||
// run code
|
||||
const codeRunRoute = new Route(path, key, { id });
|
||||
codeRunRoute.run = fn;
|
||||
router.add(codeRunRoute);
|
||||
return {
|
||||
path,
|
||||
key,
|
||||
id,
|
||||
project,
|
||||
fn,
|
||||
status: CodeStatus.success,
|
||||
};
|
||||
} catch (e) {
|
||||
console.error('error id:', id, '\n', e);
|
||||
return {
|
||||
path,
|
||||
key,
|
||||
id,
|
||||
project,
|
||||
status: CodeStatus.fail,
|
||||
errorMsg: e.message.toString(),
|
||||
};
|
||||
}
|
||||
});
|
||||
return codeManager;
|
||||
};
|
||||
33
src/admin/dashboard/manager.ts
Normal file
33
src/admin/dashboard/manager.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { EventEmitter, once } from 'stream';
|
||||
import { load, CodeManager } from './load.ts';
|
||||
|
||||
export enum LoadStatus {
|
||||
LOADING = 'loading',
|
||||
LOADED = 'loaded',
|
||||
ERROR = 'error',
|
||||
}
|
||||
export const manager = {
|
||||
loaded: LoadStatus.LOADING, // 是否已经加载
|
||||
list: [] as CodeManager[],
|
||||
};
|
||||
|
||||
export const events = new EventEmitter();
|
||||
|
||||
once(events, 'loaded')
|
||||
.then(() => {
|
||||
manager.loaded = LoadStatus.LOADED;
|
||||
console.log('manager loaded');
|
||||
})
|
||||
.catch((e) => {
|
||||
manager.loaded = LoadStatus.ERROR;
|
||||
console.error('manager loaded error', e);
|
||||
});
|
||||
|
||||
const init = async function () {
|
||||
const r = await load();
|
||||
manager.list = r;
|
||||
|
||||
events.emit('loaded');
|
||||
};
|
||||
|
||||
init();
|
||||
@@ -1,7 +1,7 @@
|
||||
// admin 需要最后运行,并在route中进行过滤。
|
||||
import { Route } from '@abearxiong/router';
|
||||
import { router } from '../modules/router.ts';
|
||||
|
||||
import { manager } from './dashboard/manager.ts';
|
||||
|
||||
export const getRouterList = new Route('admin', 'getRouterList');
|
||||
|
||||
@@ -17,10 +17,10 @@ router.add(getRouterList);
|
||||
export const removeRouter = new Route('admin', 'removeRouter');
|
||||
removeRouter.run = async (ctx) => {
|
||||
const { path, key } = ctx.query;
|
||||
router.remove({path, key});
|
||||
router.remove({ path, key });
|
||||
ctx.body = 'success';
|
||||
return ctx;
|
||||
}
|
||||
};
|
||||
router.add(removeRouter);
|
||||
|
||||
// remove router by id
|
||||
@@ -30,7 +30,7 @@ removeRouterById.run = async (ctx) => {
|
||||
router.removeById(id);
|
||||
ctx.body = 'success';
|
||||
return ctx;
|
||||
}
|
||||
};
|
||||
router.add(removeRouterById);
|
||||
|
||||
// add router
|
||||
@@ -41,7 +41,7 @@ addRouter.run = async (ctx) => {
|
||||
router.add(new Route(path, key));
|
||||
ctx.body = 'success';
|
||||
return ctx;
|
||||
}
|
||||
};
|
||||
router.add(addRouter);
|
||||
|
||||
// update router
|
||||
@@ -51,5 +51,21 @@ updateRouter.run = async (ctx) => {
|
||||
router.add(new Route(path, key));
|
||||
ctx.body = 'success';
|
||||
return ctx;
|
||||
}
|
||||
};
|
||||
router.add(updateRouter);
|
||||
|
||||
// get manager status
|
||||
export const managerRouter = new Route('admin', 'getManagerStatus');
|
||||
managerRouter.run = async (ctx) => {
|
||||
ctx.body = manager.loaded;
|
||||
return ctx;
|
||||
};
|
||||
router.add(managerRouter);
|
||||
|
||||
// get manager list
|
||||
export const managerList = new Route('admin', 'getManagerList');
|
||||
managerList.run = async (ctx) => {
|
||||
ctx.body = manager.list;
|
||||
return ctx;
|
||||
};
|
||||
router.add(managerList);
|
||||
25
src/demo/index.ts
Normal file
25
src/demo/index.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { router } from '../modules/router.ts';
|
||||
import { Route } from '@abearxiong/router';
|
||||
|
||||
const getList = new Route('test', 'getList');
|
||||
getList.run = async (ctx) => {
|
||||
ctx.body = 'test';
|
||||
return ctx;
|
||||
};
|
||||
router.add(getList);
|
||||
|
||||
const codeRun = `async function run(ctx) {
|
||||
ctx.body = 'test js';
|
||||
return ctx;
|
||||
}`;
|
||||
const fn: any = new Function(
|
||||
'ctx',
|
||||
`
|
||||
${codeRun}
|
||||
return run(ctx);
|
||||
`,
|
||||
);
|
||||
const codeRunRoute = new Route('test', 'run');
|
||||
codeRunRoute.run = fn;
|
||||
|
||||
router.add(codeRunRoute);
|
||||
55
src/models/code.ts
Normal file
55
src/models/code.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { sequelize } from '../modules/sequelize.ts';
|
||||
import { DataTypes, Model } from 'sequelize';
|
||||
|
||||
export type RouterCode = {
|
||||
id: string;
|
||||
path: string;
|
||||
key: string;
|
||||
active: boolean;
|
||||
project: string;
|
||||
code: string;
|
||||
};
|
||||
|
||||
export class RouterCodeModel extends Model {
|
||||
declare id: string;
|
||||
path: string;
|
||||
key: string;
|
||||
active: boolean;
|
||||
project: string;
|
||||
public code: string;
|
||||
}
|
||||
RouterCodeModel.init(
|
||||
{
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
primaryKey: true,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
comment: '用户id',
|
||||
},
|
||||
path: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
key: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
active: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
defaultValue: false,
|
||||
},
|
||||
project: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: 'default',
|
||||
},
|
||||
code: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: '',
|
||||
},
|
||||
},
|
||||
{
|
||||
sequelize,
|
||||
tableName: 'cf_router_code',
|
||||
},
|
||||
);
|
||||
// RouterCodeModel.sync({ alter: true });
|
||||
63
src/models/user.ts
Normal file
63
src/models/user.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { sequelize } from '@/modules/sequelize.ts';
|
||||
import { DataTypes, Model } from 'sequelize';
|
||||
|
||||
export class User extends Model {
|
||||
declare id: number;
|
||||
username: string;
|
||||
password: string;
|
||||
salt: string;
|
||||
remark: string;
|
||||
}
|
||||
User.init(
|
||||
{
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
},
|
||||
|
||||
username: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
password: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
salt: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
remark: {
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
},
|
||||
{
|
||||
sequelize,
|
||||
tableName: 'cf_user',
|
||||
},
|
||||
);
|
||||
// User.sync({ alter: true });
|
||||
|
||||
export const initializeUser = async () => {
|
||||
const w = await User.findOne();
|
||||
const password = '2e8a305521bba54f49638ed25e46adf3';
|
||||
const salt = '123';
|
||||
const users = [
|
||||
{ username: 'admin' },
|
||||
{ username: 'user' },
|
||||
{ username: 'root' },
|
||||
];
|
||||
if (!w) {
|
||||
const newUsers = await User.bulkCreate(
|
||||
users.map((user) => {
|
||||
return {
|
||||
...user,
|
||||
password,
|
||||
salt,
|
||||
};
|
||||
}),
|
||||
);
|
||||
console.info('[create new Users]', newUsers);
|
||||
}
|
||||
};
|
||||
1
src/modules/index.ts
Normal file
1
src/modules/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { sequelize } from './sequelize.ts';
|
||||
26
src/modules/sequelize.ts
Normal file
26
src/modules/sequelize.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { useConfig } from '@abearxiong/use-config';
|
||||
import { Sequelize } from 'sequelize';
|
||||
|
||||
type PostgresConfig = {
|
||||
postgres: {
|
||||
username: string;
|
||||
password: string;
|
||||
host: string;
|
||||
port: number;
|
||||
database: string;
|
||||
};
|
||||
};
|
||||
const config = useConfig<PostgresConfig>();
|
||||
|
||||
const postgresConfig = config.postgres;
|
||||
|
||||
if (!postgresConfig) {
|
||||
console.error('postgres config is required');
|
||||
process.exit(1);
|
||||
}
|
||||
// connect to db
|
||||
export const sequelize = new Sequelize({
|
||||
dialect: 'postgres',
|
||||
...postgresConfig,
|
||||
// logging: false,
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
import { router } from './modules/router.ts';
|
||||
|
||||
import './test/index.ts';
|
||||
import './demo/index.ts';
|
||||
import './admin/index.ts';
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import { router } from '../modules/router.ts';
|
||||
import { Route } from '@abearxiong/router';
|
||||
|
||||
const getList = new Route('test', 'getList');
|
||||
getList.run = async (ctx) => {
|
||||
ctx.body = 'test';
|
||||
return ctx;
|
||||
};
|
||||
router.add(getList);
|
||||
Reference in New Issue
Block a user