feat: add delete route
This commit is contained in:
parent
c0a1460ad8
commit
60653a5ba8
13
dockerfile
13
dockerfile
@ -4,15 +4,17 @@ FROM node:22-alpine
|
||||
# 设置工作目录
|
||||
WORKDIR /app
|
||||
|
||||
COPY script/package/package.json ./
|
||||
# 复制 package.json 和 package-lock.json
|
||||
COPY package*.json ./
|
||||
|
||||
# 安装依赖
|
||||
# RUN npm install --production
|
||||
# COPY package*.json ./
|
||||
|
||||
# 复制 dist 文件夹
|
||||
COPY dist ./dist
|
||||
COPY app.config.json5 ./dist/app.config.json5
|
||||
COPY app.config.json5 ./app.config.json5
|
||||
COPY .npmrc .
|
||||
|
||||
# 安装依赖
|
||||
RUN npm install --production --registry=https://registry.npmmirror.com/
|
||||
|
||||
# 如果有其他静态资源文件夹,也可以一并复制
|
||||
# COPY public ./public
|
||||
@ -22,3 +24,4 @@ EXPOSE 4000
|
||||
|
||||
# 启动应用
|
||||
CMD ["node", "dist/app.cjs"]
|
||||
# CMD ["tail", "-f", "/dev/null"]
|
1732
package-lock.json
generated
1732
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
23
package.json
23
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "code-flow",
|
||||
"version": "1.0.0",
|
||||
"version": "0.0.2",
|
||||
"description": "code的flow流程成图",
|
||||
"type": "module",
|
||||
"main": "index.js",
|
||||
@ -14,17 +14,21 @@
|
||||
"deploy:sh": "",
|
||||
"clean": "rm -rf dist",
|
||||
"reload": "ssh light pm2 restart codeflow",
|
||||
"docker:build": "docker build -t docker.xiongxiao.me/code-flow:v0.0.1 .",
|
||||
"docker:push": "docker push docker.xiongxiao.me/code-flow:v0.0.1",
|
||||
"docker:build:gitea": "docker build -t git.xiongxiao.me/abearxiong/code-flow:v0.0.1 .",
|
||||
"docker:push:gitea": "docker push git.xiongxiao.me/abearxiong/code-flow:v0.0.1"
|
||||
"docker:build": "docker build -t docker.xiongxiao.me/code-flow:v0.0.2 .",
|
||||
"docker:push": "docker push docker.xiongxiao.me/code-flow:v0.0.2",
|
||||
"docker:run": "docker run -it --name code-flow -p 4000:4000 docker.xiongxiao.me/code-flow:v0.0.2",
|
||||
"docker:build:gitea": "docker build -t git.xiongxiao.me/abearxiong/code-flow:v0.0.2 .",
|
||||
"docker:push:gitea": "docker push git.xiongxiao.me/abearxiong/code-flow:v0.0.2"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@abearxiong/router": "^0.0.1-alpha.6",
|
||||
"@abearxiong/router": "^0.0.1-alpha.8",
|
||||
"@abearxiong/use-config": "^0.0.1",
|
||||
"@babel/core": "^7.24.7",
|
||||
"@babel/preset-env": "^7.24.7",
|
||||
"@babel/preset-typescript": "^7.24.7",
|
||||
"dayjs": "^1.11.11",
|
||||
"json5": "^2.2.3",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
@ -32,14 +36,15 @@
|
||||
"nanoid": "^5.0.7",
|
||||
"pg": "^8.12.0",
|
||||
"sequelize": "^6.37.3",
|
||||
"socket.io": "^4.7.5"
|
||||
"socket.io": "^4.7.5",
|
||||
"strip-ansi": "^7.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/jsonwebtoken": "^9.0.6",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^20.14.8",
|
||||
"@types/node": "^20.14.9",
|
||||
"@types/superagent": "^8.1.7",
|
||||
"@types/supertest": "^6.0.2",
|
||||
"@types/webpack-env": "^1.18.5",
|
||||
@ -59,4 +64,4 @@
|
||||
"webpack-node-externals": "^3.0.0"
|
||||
},
|
||||
"packageManager": "yarn@1.22.19+sha1.4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447"
|
||||
}
|
||||
}
|
26
script/package/index.mjs
Normal file
26
script/package/index.mjs
Normal file
@ -0,0 +1,26 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
const currentPath = process.cwd();
|
||||
const packagePath = path.join(currentPath, 'script/package/package.json');
|
||||
|
||||
fs.writeFileSync(
|
||||
packagePath,
|
||||
JSON.stringify(
|
||||
{
|
||||
name: 'codeflow',
|
||||
version: '1.0.0',
|
||||
dependencies: {
|
||||
'@babel/core': '^7.24.7',
|
||||
'@babel/preset-env': '^7.24.7',
|
||||
'@babel/preset-typescript': '^7.24.7',
|
||||
sequelize: '^6.37.3',
|
||||
'socket.io': '^4.7.5',
|
||||
pg: '^8.12.0'
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
'utf-8',
|
||||
);
|
12
script/package/package.json
Normal file
12
script/package/package.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "codeflow",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.24.7",
|
||||
"@babel/preset-env": "^7.24.7",
|
||||
"@babel/preset-typescript": "^7.24.7",
|
||||
"sequelize": "^6.37.3",
|
||||
"socket.io": "^4.7.5",
|
||||
"pg": "^8.12.0"
|
||||
}
|
||||
}
|
@ -17,21 +17,30 @@ const codeDemoRun = `async function run(ctx) {
|
||||
ctx.body = 'test js';
|
||||
return ctx;
|
||||
}`;
|
||||
export const loadOne = async (item: RouterCodeModel) => {
|
||||
const { path, key, id, code, project } = item.toJSON();
|
||||
try {
|
||||
const fn: any = new Function(
|
||||
'ctx',
|
||||
`
|
||||
${code}
|
||||
const templateFn = (codeStr: string) => {
|
||||
return `
|
||||
${codeStr}
|
||||
if(run) {
|
||||
return run(ctx);
|
||||
`,
|
||||
);
|
||||
}
|
||||
if(main) {
|
||||
return main(ctx);
|
||||
}
|
||||
return 'no run or main function';
|
||||
`;
|
||||
};
|
||||
export const loadOne = async (item: RouterCodeModel) => {
|
||||
const { path, key, id, code, exec, project } = item.toJSON();
|
||||
const codeStr = exec || code;
|
||||
try {
|
||||
const fn: any = new Function('ctx', templateFn(codeStr));
|
||||
// run code
|
||||
const codeRunRoute = new Route(path, key, { id });
|
||||
codeRunRoute.run = fn;
|
||||
router.removeById(id); // TODO:
|
||||
router.add(codeRunRoute);
|
||||
return {
|
||||
...item.toJSON(),
|
||||
path,
|
||||
key,
|
||||
id,
|
||||
@ -54,9 +63,10 @@ export const loadOne = async (item: RouterCodeModel) => {
|
||||
export const load = async function () {
|
||||
const codes = await RouterCodeModel.findAll();
|
||||
const codeManager: CodeManager[] = codes.map((item) => {
|
||||
const { path, key, id, code, project, active } = item.toJSON();
|
||||
const { path, key, id, code, exec, project, active } = item.toJSON();
|
||||
if (!active) {
|
||||
return {
|
||||
...item.toJSON(),
|
||||
path,
|
||||
key,
|
||||
id,
|
||||
@ -66,18 +76,14 @@ export const load = async function () {
|
||||
};
|
||||
}
|
||||
try {
|
||||
const fn: any = new Function(
|
||||
'ctx',
|
||||
`
|
||||
${code}
|
||||
return run(ctx);
|
||||
`,
|
||||
);
|
||||
const codeStr = exec || code;
|
||||
const fn: any = new Function('ctx', templateFn(codeStr));
|
||||
// run code
|
||||
const codeRunRoute = new Route(path, key, { id });
|
||||
codeRunRoute.run = fn;
|
||||
router.add(codeRunRoute);
|
||||
return {
|
||||
...item.toJSON(),
|
||||
path,
|
||||
key,
|
||||
id,
|
||||
|
@ -36,6 +36,7 @@ export const stopCode = (id: string) => {
|
||||
};
|
||||
export const startCode = async (code: RouterCodeModel) => {
|
||||
const index = manager.list.findIndex((item) => item.id === code.id);
|
||||
console.log('index', index, code.toJSON())
|
||||
if (index !== -1) {
|
||||
manager.list[index] = await loadOne(code);
|
||||
} else {
|
||||
|
@ -5,6 +5,7 @@ import { manager, updateNewCode, removeCode, stopCode, startCode } from './dashb
|
||||
import { loadOne } from './dashboard/load.ts';
|
||||
import { RouterCodeModel } from '../models/code.ts';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { convertTsToJs as transform } from '../lib/ts2js.ts';
|
||||
|
||||
export const getRouterList = new Route('admin', 'getRouterList');
|
||||
|
||||
@ -58,11 +59,14 @@ stopRouterById.run = async (ctx) => {
|
||||
ctx.body = 'success';
|
||||
return ctx;
|
||||
};
|
||||
router.add(stopRouterById);
|
||||
|
||||
// start router by id
|
||||
export const startRouterById = new Route('admin', 'startRouterById');
|
||||
startRouterById.run = async (ctx) => {
|
||||
const { id } = ctx.query;
|
||||
const routerCode = await RouterCodeModel.findByPk(id);
|
||||
console.log('routerCode', id, routerCode.toJSON());
|
||||
if (routerCode) {
|
||||
routerCode.active = true;
|
||||
await routerCode.save();
|
||||
@ -71,10 +75,12 @@ startRouterById.run = async (ctx) => {
|
||||
ctx.body = 'success';
|
||||
return ctx;
|
||||
};
|
||||
router.add(startRouterById);
|
||||
|
||||
// add or update router
|
||||
export const updateRouter = new Route('admin', 'updateRouter');
|
||||
updateRouter.run = async (ctx) => {
|
||||
let { path, key, id, code } = ctx.query;
|
||||
let { path, key, id, code, type = 'route' } = ctx.query;
|
||||
if (!path && !key) {
|
||||
ctx.body = 'path and key is required';
|
||||
ctx.code = 500;
|
||||
@ -85,16 +91,32 @@ updateRouter.run = async (ctx) => {
|
||||
if (codeRouteCheck && codeRouteCheck.id !== id) {
|
||||
key = `${key}-${nanoid(6)}`;
|
||||
}
|
||||
|
||||
if (id) {
|
||||
codeRouter = await RouterCodeModel.findByPk(id);
|
||||
codeRouter.path = path;
|
||||
codeRouter.key = key;
|
||||
codeRouter.code = code;
|
||||
try {
|
||||
codeRouter.exec = await transform(code);
|
||||
} catch (e) {
|
||||
ctx.body = e.message.toString();
|
||||
ctx.code = 500;
|
||||
return ctx;
|
||||
}
|
||||
codeRouter.type = type;
|
||||
await codeRouter.save();
|
||||
} else {
|
||||
const newCodeRouter = new RouterCodeModel({ path, key, code });
|
||||
await newCodeRouter.save();
|
||||
codeRouter = newCodeRouter;
|
||||
try {
|
||||
const exec = await transform(code);
|
||||
const newCodeRouter = new RouterCodeModel({ path, key, code, exec, type });
|
||||
await newCodeRouter.save();
|
||||
codeRouter = newCodeRouter;
|
||||
} catch (e) {
|
||||
ctx.body = e.message.toString();
|
||||
ctx.code = 500;
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
|
||||
const codeOne = await loadOne(codeRouter);
|
||||
@ -120,6 +142,11 @@ router.add(managerRouter);
|
||||
export const managerList = new Route('admin', 'getManagerList');
|
||||
managerList.run = async (ctx) => {
|
||||
ctx.body = manager.list;
|
||||
const routerList = router.getList().filter((r) => !r.path.startsWith('admin'));
|
||||
ctx.body = {
|
||||
list: manager.list,
|
||||
routerList,
|
||||
};
|
||||
return ctx;
|
||||
};
|
||||
router.add(managerList);
|
||||
|
@ -13,6 +13,7 @@ const server = http.createServer((req, res) => {
|
||||
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
||||
res.setHeader('Access-Control-Max-Age', '86400');
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
|
||||
// routerServer.handle(req, res);
|
||||
return routerServer.callback()(req, res);
|
||||
});
|
||||
|
1
src/lib/index.ts
Normal file
1
src/lib/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './ts2js.ts';
|
32
src/lib/ts2js.ts
Normal file
32
src/lib/ts2js.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import * as babel from '@babel/core';
|
||||
import stripAnsi from 'strip-ansi';
|
||||
/**
|
||||
* 转换 ts 代码为 js 代码
|
||||
* @param tsCode
|
||||
* @returns
|
||||
*/
|
||||
export const convertTsToJs = async (tsCode: string) => {
|
||||
const presetEnv = await import('@babel/preset-env');
|
||||
const presetTypescript = await import('@babel/preset-typescript');
|
||||
|
||||
try {
|
||||
const result = babel.transformSync(tsCode, {
|
||||
presets: [
|
||||
presetTypescript.default,
|
||||
[
|
||||
presetEnv.default,
|
||||
{
|
||||
targets: {
|
||||
node: 20,
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
filename: 'temp.ts',
|
||||
});
|
||||
return result.code;
|
||||
} catch (e) {
|
||||
const message = e.message.split('temp.ts:')[1] || e.message;
|
||||
throw new Error(stripAnsi(message));
|
||||
}
|
||||
};
|
@ -8,6 +8,7 @@ export type RouterCode = {
|
||||
active: boolean;
|
||||
project: string;
|
||||
code: string;
|
||||
exec: string;
|
||||
type: RouterCodeType;
|
||||
middleware: string[];
|
||||
next: string;
|
||||
@ -25,6 +26,7 @@ export class RouterCodeModel extends Model {
|
||||
declare active: boolean;
|
||||
declare project: string;
|
||||
declare code: string;
|
||||
declare exec: string;
|
||||
declare type: RouterCodeType;
|
||||
declare middleware: string[];
|
||||
declare next: string; // 如果是中间件,不存在
|
||||
@ -57,6 +59,10 @@ RouterCodeModel.init(
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: '',
|
||||
},
|
||||
exec: {
|
||||
type: DataTypes.STRING, // 对代码进行编译后的代码
|
||||
defaultValue: '',
|
||||
},
|
||||
type: {
|
||||
type: DataTypes.ENUM(RouterCodeType.route, RouterCodeType.middleware),
|
||||
defaultValue: RouterCodeType.route,
|
||||
|
@ -3,14 +3,18 @@ import { router } from './modules/router.ts';
|
||||
import './demo/index.ts';
|
||||
import './admin/index.ts';
|
||||
|
||||
|
||||
type Message = {
|
||||
path: string;
|
||||
key?: string;
|
||||
};
|
||||
|
||||
export const handleMessage = async function (m: Message) {
|
||||
console.log('message', m);
|
||||
if (!m) {
|
||||
return {
|
||||
code: 400,
|
||||
message: 'message is empty',
|
||||
};
|
||||
}
|
||||
|
||||
const res = await router.parse(m);
|
||||
const { code, body, message } = res;
|
||||
|
@ -28,15 +28,17 @@ describe('RouterCodeModel', () => {
|
||||
// yarn test --testNamePattern='RouterCodeModel:create'
|
||||
test('RouterCodeModel:create', async () => {
|
||||
try {
|
||||
const demoCode = `async function run(ctx) {
|
||||
ctx.body = 'test js';
|
||||
return ctx;
|
||||
}`;
|
||||
const file = await RouterCodeModel.create({
|
||||
path: 'demo',
|
||||
key: 'returnDemo',
|
||||
active: true,
|
||||
project: 'default',
|
||||
code: `async function run(ctx) {
|
||||
ctx.body = 'test js';
|
||||
return ctx;
|
||||
}`,
|
||||
code: demoCode,
|
||||
exec: demoCode,
|
||||
});
|
||||
console.log('create success', file);
|
||||
await sleep(2000);
|
||||
|
@ -9,9 +9,7 @@ const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
|
||||
const ENV = process.env.ENV;
|
||||
|
||||
const plugins = [
|
||||
new ForkTsCheckerWebpackPlugin(),
|
||||
];
|
||||
const plugins = [new ForkTsCheckerWebpackPlugin()];
|
||||
if (ENV === 'init') {
|
||||
plugins.push(
|
||||
new CopyPlugin({
|
||||
@ -19,6 +17,9 @@ if (ENV === 'init') {
|
||||
}),
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @type {webpack.Configuration}
|
||||
*/
|
||||
module.exports = {
|
||||
mode: 'production',
|
||||
entry: path.join(__dirname, './src/app.ts'),
|
||||
@ -56,16 +57,21 @@ module.exports = {
|
||||
extensions: ['.ts', '.js'],
|
||||
alias: {
|
||||
'@': path.join(__dirname, './src'),
|
||||
"hexoid": "hexoid/dist/index.js",
|
||||
hexoid: 'hexoid/dist/index.js',
|
||||
},
|
||||
},
|
||||
// externals: [
|
||||
// externals: [
|
||||
// // nodeExternals(),
|
||||
// ],
|
||||
externals: {
|
||||
sequelize: 'commonjs sequelize',
|
||||
'socket.io': 'commonjs socket.io',
|
||||
'@babel/preset-env': 'commonjs @babel/preset-env',
|
||||
'@babel/preset-typescript': 'commonjs @babel/preset-typescript',
|
||||
},
|
||||
plugins: [...plugins],
|
||||
node: {},
|
||||
stats: {
|
||||
errorDetails: true,
|
||||
},
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user