add init demos

This commit is contained in:
2025-10-16 02:52:04 +08:00
parent 943d664c36
commit 5a3d11c6bc
38 changed files with 6810 additions and 121 deletions

25
server/.gitignore vendored Normal file
View File

@@ -0,0 +1,25 @@
node_modules
dist
app.config.json5
apps.config.json
deploy.tar.gz
cache-file
/apps
logs
release/*
!release/.gitkeep
.turbo
.env*
!.env.example
pack-dist
app.config.json5.envision

View File

@@ -8,6 +8,7 @@ const external = ['sequelize', 'pg', 'ioredis', 'pm2'];
/**
* @type {import('bun').BuildConfig}
*/
// @ts-ignore
await Bun.build({
target: 'node',
format: 'esm',

View File

@@ -0,0 +1,24 @@
import { QueryRouterServer } from "@kevisual/router";
const app = new QueryRouterServer();
app.route({
path: 'main'
}).define(async (ctx) => {
ctx.body = {
message: 'this is main. filename: root/light-code-demo/main.ts',
params: ctx.query
}
}).addTo(app)
app.route({
path: 'main2'
}).define(async (ctx) => {
ctx.body = {
message: 'this is main2. filename: root/light-code-demo/main.ts',
params: ctx.query
}
}).addTo(app)
app.wait()

View File

@@ -0,0 +1,46 @@
import { QueryRouterServer as Mini } from "@kevisual/router";
import { NocoApi } from "@kevisual/noco";
const config = {
NOCODB_URL: process.env.NOCODB_URL || 'https://nocodb.xiongxiao.me',
NOCODB_API_KEY: process.env.NOCODB_API_KEY || 'uca1Zx3p_0pnNUBV6ot9mBP6JCPqQ0X1TF3N3R7s'
}
const table = 'mcby44q8zrayvn9'
const nocoAPi = new NocoApi({
baseURL: config.NOCODB_URL,
token: config.NOCODB_API_KEY,
table,
});
console.log('nocoAPi', await nocoAPi.record.list())
const app = new Mini();
app.route({
path: 'sign'
}).define(async (ctx) => {
const { Title, Description } = ctx.query
// 这里可以处理签到
await nocoAPi.record.create({ Title, Description })
const list = await nocoAPi.record.list({ sort: '-CreatedAt' })
ctx.body = { message: '签到成功', list }
}).addTo(app)
app.route({
path: 'sign',
key: 'list'
}).define(async (ctx) => {
// 这里可以处理签到
ctx.body = await nocoAPi.record.list()
}).addTo(app)
app.route({
path: 'sign',
key: 'delete'
}).define(async (ctx) => {
const { id } = ctx.query
// 这里可以处理签到
await nocoAPi.record.delete({ Id: id })
const list = await nocoAPi.record.list({ sort: '-CreatedAt' })
ctx.body = { message: '删除成功', list }
}).addTo(app)
app.wait()

View File

@@ -0,0 +1,56 @@
const weatherHost = 'n65khufe5n.re.qweatherapi.com';
const token = 'fdad5aeb2ba54949a8a1df2a0f3d1efb'
const xihu = '101210113'; // 西湖
export const getWeather = async (location: string = xihu) => {
const url = `https://${weatherHost}/v7/weather/3d?location=${location}`;
const headers = {
'Authorization': `Bearer ${token}`
};
const res = await fetch(url, { headers });
if (!res.ok) {
throw new Error(`HTTP error! status: ${res.status}`);
}
const data = await res.json();
return data;
}
// getWeather().then(console.log).catch(console.error);
// https://dev.qweather.com/
class Weather {
host: string;
token: string;
constructor(opts: { host: string; token: string }) {
this.host = opts.host;
this.token = opts.token;
console.log(this.host, this.token);
}
getWeather(location: string) {
return fetch(`https://${this.host}/v7/weather/now?location=${location}`, {
headers: {
'Content-Type': 'application/json',
'X-QW-Api-Key': '<KEY>'.replace('<KEY>', this.token),
},
}).then((res) => res.json());
}
}
const newWeather = new Weather({
host: process.env?.QWEATHER_HOST || weatherHost,
token: process.env?.QWEATHER_TOKEN || token,
});
// newWeather.getWeather(xihu).then(console.log).catch(console.error);
import { QueryRouterServer as Mini } from "@kevisual/router";
const app = new Mini();
app.route({
path: 'main'
}).define(async (ctx) => {
ctx.body = await newWeather.getWeather(xihu);
}).addTo(app)
app.wait()

View File

@@ -1,10 +1,9 @@
import fs from 'node:fs'
const main = () => {
const random = Math.random().toString(36).slice(-6)
return 'hello a' + random
return 'hello a ' + random
}
fs.writeFileSync('./a.txt', main() + '\n', { flag: 'a' })
// fs.writeFileSync('./a.txt', main() + '\n', { flag: 'a' })
console.log('pwd', process.cwd())
// const value = fs.readFileSync('./bun.config.ts', 'utf-8')
// console.log('a.txt 内容:', value)
@@ -29,10 +28,10 @@ const listen = async () => {
// 发送结果回主进程
const response = {
success: true,
foo: 'bar',
params,
main: result,
success: true,
data: { code: 200, data: result },
timestamp: new Date().toISOString()
}

View File

@@ -0,0 +1,14 @@
import { QueryRouterServer } from "@kevisual/router";
const app = new QueryRouterServer();
app.route({
path: 'main'
}).define(async (ctx) => {
ctx.body = {
message: 'this is main. filename: root/listen-demo/router.ts',
params: ctx.query
}
}).addTo(app)
app.wait()

View File

@@ -0,0 +1 @@
测试静态页面

View File

@@ -5,6 +5,7 @@
"main": "index.js",
"scripts": {
"dev": "bun run --watch --hot src/index.ts",
"start": "bun run src/index.ts",
"build": "NODE_ENV=production bun bun.config.ts"
},
"keywords": [],
@@ -13,12 +14,14 @@
"packageManager": "pnpm@10.16.1",
"type": "module",
"devDependencies": {
"@kevisual/local-proxy": "^0.0.6",
"@kevisual/types": "^0.0.10",
"@kevisual/use-config": "^1.0.19",
"@types/bun": "^1.3.0",
"bun": "^1.3.0"
"@types/bun": "^1.3.0"
},
"dependencies": {
"@kevisual/router": "^0.0.28"
"@kevisual/noco": "^0.0.1",
"@kevisual/router": "^0.0.29",
"fast-glob": "^3.3.3"
}
}

3
server/src/app.ts Normal file
View File

@@ -0,0 +1,3 @@
import { App } from '@kevisual/router'
export const app = new App()

View File

@@ -1,38 +0,0 @@
import { App } from '@kevisual/router'
import { fork } from 'child_process'
const app = new App()
import path from 'path'
// http://localhost:3000/api/router?path=call
app.route({
path: 'call'
}).define(async (ctx) => {
ctx.body = 'Hello World'
const pwd = process.cwd()
const testA = path.join(pwd, 'src/test/a.ts')
const child = fork(testA, {
})
console.log('Child process started with PID:', child.pid)
child.on('message', (msg) => {
console.log('Message from child', msg)
setTimeout(() => {
console.log('child process connected:', child.connected)
console.log('child process killed:', child.killed)
console.log('child process exit code:', child.exitCode)
}, 20)
})
child.on('exit', (code, signal) => {
console.log('子进程已退出,退出码:', code, '信号:', signal)
})
child.on('close', (code, signal) => {
console.log('子进程已关闭,退出码:', code, '信号:', signal)
})
child.send({ hello: 'world' })
}).addTo(app)
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000')
})

View File

@@ -1,51 +1,16 @@
import { App } from '@kevisual/router'
import { fork } from 'child_process'
const app = new App()
import path from 'path'
import { proxyRoute, initProxy } from '@kevisual/local-proxy/proxy.ts';
// http://localhost:4005/test/a/index.html
initProxy({
pagesDir: './demo',
watch: true,
});
// http://localhost:3000/api/router?path=call
app.route({
path: 'call'
}).define(async (ctx) => {
ctx.body = 'Hello World'
const pwd = process.cwd()
const testA = path.join(pwd, 'src/test/a.ts')
import { app } from './app.ts'
import './routes/index.ts'
// 使用 Bun 的 fork 模式启动子进程
const child = fork(testA, [], {
execArgv: [],
cwd: "/tmp", // 限制工作目录
})
console.log('Child process started with PID:', child.pid)
app.listen(4005, () => {
console.log('Server is running on http://localhost:4005')
})
// 监听来自子进程的消息
child.on('message', (msg) => {
console.log('Message from child:', msg)
setTimeout(() => {
console.log('child process connected:', child.connected)
console.log('child process killed:', child.killed)
console.log('child process exit code:', child.exitCode)
}, 20)
})
child.on('exit', (code, signal) => {
console.log('子进程已退出,退出码:', code, '信号:', signal)
})
child.on('close', (code, signal) => {
console.log('子进程已关闭,退出码:', code, '信号:', signal)
})
child.on('error', (error) => {
console.error('子进程错误:', error)
})
// 向子进程发送消息
child.send({ hello: 'world' })
}).addTo(app)
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000')
})
app.onServerRequest(proxyRoute);

View File

@@ -0,0 +1,50 @@
import { fork } from 'child_process'
export type RunCodeParams = {
path?: string;
key?: string;
payload?: string;
[key: string]: any
}
type RunCode = {
// 调用进程的功能
success?: boolean
data?: {
// 调用router的结果
code?: number
data?: any
message?: string
[key: string]: any
};
error?: any
timestamp?: string
[key: string]: any
}
export const runCode = async (tsPath: string, params: RunCodeParams = {}): Promise<RunCode> => {
return new Promise((resolve, reject) => {
// 使用 Bun 的 fork 模式启动子进程
const child = fork(tsPath)
// 监听来自子进程的消息
child.on('message', (msg: RunCode) => {
resolve(msg)
})
// child.on('exit', (code, signal) => {
// console.log('子进程已退出,退出码:', code, '信号:', signal)
// })
// child.on('close', (code, signal) => {
// console.log('子进程已关闭,退出码:', code, '信号:', signal)
// })
child.on('error', (error) => {
resolve({
success: false, error: error?.message
})
})
// 向子进程发送消息
child.send(params)
});
}

View File

@@ -0,0 +1,24 @@
import { app } from '../../app.ts'
import path from 'path'
import { runCode } from '../../modules/run-code/run.ts'
// http://localhost:4005/api/router?path=call
app.route({
path: 'call'
}).define(async (ctx) => {
const filename = ctx.query?.filename || 'root/listen-demo/router.ts'
const data = ctx.query?.data || {}
const pwd = process.cwd()
const testA = path.join(pwd, 'code', filename)
const resulst = await runCode(testA, data)
if (resulst.success) {
const callResult = resulst.data;
if (callResult.code === 200) ctx.body = callResult.data
else {
const callError = `调用程序错误: ${callResult.message}`
ctx.throw(callResult.code, callError)
}
} else {
ctx.body = `执行脚本错误: ${resulst.error}`
}
}).addTo(app)

View File

@@ -0,0 +1,28 @@
import { app } from '@/app.ts';
import path from 'node:path'
import glob from 'fast-glob';
import fs from 'node:fs'
const list = async () => {
const root = path.join(process.cwd(), 'code');
const files = await glob('**/*.ts', { cwd: root });
type FileContent = {
path: string;
content: string;
}
const filesContent: FileContent[] = [];
for (const file of files) {
if (file.startsWith('node_modules') || file.startsWith('dist') || file.startsWith('.git')) continue;
const fullPath = path.join(root, file);
const content = fs.readFileSync(fullPath, 'utf-8');
if (content) {
filesContent.push({ path: file, content: content });
}
}
return filesContent;
}
app.route({
path: 'file-code'
}).define(async (ctx) => {
const files = await list();
ctx.body = files
}).addTo(app);

View File

@@ -0,0 +1,3 @@
import './call/index.ts';
import './file-code/index.ts';

View File

@@ -9,11 +9,11 @@
],
"paths": {
"@/*": [
"server/src/*"
"src/*"
]
},
},
"include": [
"server/src/**/*",
"src/**/*", "code/**/*",
],
}