189 lines
5.5 KiB
JavaScript
189 lines
5.5 KiB
JavaScript
|
const express = require('express');
|
|||
|
const router = express.Router();
|
|||
|
const fs = require('fs').promises;
|
|||
|
const path = require('path');
|
|||
|
|
|||
|
// 获取XNCore环境变量
|
|||
|
const xnCorePath = process.env.XNCore || '';
|
|||
|
|
|||
|
// 默认IDL文件保存目录,使用XNCore环境变量下的IDL子文件夹
|
|||
|
const IDL_BASE_DIR = xnCorePath ? path.join(xnCorePath, 'IDL') : path.join(process.cwd(), 'idl_files');
|
|||
|
|
|||
|
// 确保IDL文件目录存在
|
|||
|
async function ensureIdlDirExists() {
|
|||
|
try {
|
|||
|
await fs.mkdir(IDL_BASE_DIR, { recursive: true });
|
|||
|
} catch (error) {
|
|||
|
console.error('创建IDL目录失败:', error);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 初始化确保目录存在
|
|||
|
ensureIdlDirExists();
|
|||
|
|
|||
|
// 安全地获取文件路径,避免路径遍历攻击
|
|||
|
function getSafePath(filePath) {
|
|||
|
// 确保文件路径以.idl结尾
|
|||
|
if (!filePath.toLowerCase().endsWith('.idl')) {
|
|||
|
filePath += '.idl';
|
|||
|
}
|
|||
|
|
|||
|
// 使用path.join确保路径在IDL_BASE_DIR下
|
|||
|
const safePath = path.join(IDL_BASE_DIR, path.basename(filePath));
|
|||
|
|
|||
|
return safePath;
|
|||
|
}
|
|||
|
|
|||
|
// 列出所有IDL文件
|
|||
|
router.get('/list', async (req, res) => {
|
|||
|
try {
|
|||
|
// 确保目录存在
|
|||
|
await ensureIdlDirExists();
|
|||
|
|
|||
|
// 读取目录
|
|||
|
const files = await fs.readdir(IDL_BASE_DIR);
|
|||
|
|
|||
|
// 过滤出.idl文件
|
|||
|
const idlFiles = files.filter(file => file.toLowerCase().endsWith('.idl'));
|
|||
|
|
|||
|
// 获取文件信息
|
|||
|
const fileInfos = await Promise.all(idlFiles.map(async (file) => {
|
|||
|
const filePath = path.join(IDL_BASE_DIR, file);
|
|||
|
const stats = await fs.stat(filePath);
|
|||
|
|
|||
|
return {
|
|||
|
name: file,
|
|||
|
size: stats.size,
|
|||
|
modified: stats.mtime
|
|||
|
};
|
|||
|
}));
|
|||
|
|
|||
|
res.json({ files: fileInfos });
|
|||
|
} catch (error) {
|
|||
|
console.error('列出IDL文件失败:', error);
|
|||
|
res.status(500).json({ error: '列出IDL文件失败', message: error.message });
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
// 读取IDL文件内容
|
|||
|
router.get('/read', async (req, res) => {
|
|||
|
try {
|
|||
|
const filename = req.query.filename;
|
|||
|
|
|||
|
if (!filename) {
|
|||
|
return res.status(400).json({ error: '缺少文件名参数' });
|
|||
|
}
|
|||
|
|
|||
|
const filePath = getSafePath(filename);
|
|||
|
|
|||
|
// 读取文件内容
|
|||
|
const content = await fs.readFile(filePath, 'utf-8');
|
|||
|
|
|||
|
res.json({ content, filename: path.basename(filePath) });
|
|||
|
} catch (error) {
|
|||
|
console.error('读取IDL文件失败:', error);
|
|||
|
|
|||
|
if (error.code === 'ENOENT') {
|
|||
|
return res.status(404).json({ error: '文件不存在' });
|
|||
|
}
|
|||
|
|
|||
|
res.status(500).json({ error: '读取IDL文件失败', message: error.message });
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
// 保存IDL文件内容
|
|||
|
router.post('/save', async (req, res) => {
|
|||
|
try {
|
|||
|
const { filename, content } = req.body;
|
|||
|
|
|||
|
if (!filename || content === undefined) {
|
|||
|
return res.status(400).json({ error: '缺少必要参数' });
|
|||
|
}
|
|||
|
|
|||
|
// 确保目录存在
|
|||
|
await ensureIdlDirExists();
|
|||
|
|
|||
|
const filePath = getSafePath(filename);
|
|||
|
|
|||
|
// 写入文件内容
|
|||
|
await fs.writeFile(filePath, content, 'utf-8');
|
|||
|
|
|||
|
res.json({ success: true, filename: path.basename(filePath) });
|
|||
|
} catch (error) {
|
|||
|
console.error('保存IDL文件失败:', error);
|
|||
|
res.status(500).json({ error: '保存IDL文件失败', message: error.message });
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
// 新建IDL文件
|
|||
|
router.post('/create', async (req, res) => {
|
|||
|
try {
|
|||
|
const { filename } = req.body;
|
|||
|
|
|||
|
if (!filename) {
|
|||
|
return res.status(400).json({ error: '缺少文件名参数' });
|
|||
|
}
|
|||
|
|
|||
|
// 确保目录存在
|
|||
|
await ensureIdlDirExists();
|
|||
|
|
|||
|
const filePath = getSafePath(filename);
|
|||
|
|
|||
|
// 检查文件是否已存在
|
|||
|
try {
|
|||
|
await fs.access(filePath);
|
|||
|
return res.status(409).json({ error: '文件已存在' });
|
|||
|
} catch (accessError) {
|
|||
|
// 文件不存在,可以创建
|
|||
|
}
|
|||
|
|
|||
|
// 创建具有默认内容的IDL文件
|
|||
|
const defaultContent = `module XNSim
|
|||
|
{
|
|||
|
struct YourStruct
|
|||
|
{
|
|||
|
// 在此添加字段
|
|||
|
};
|
|||
|
};`;
|
|||
|
|
|||
|
// 写入文件内容
|
|||
|
await fs.writeFile(filePath, defaultContent, 'utf-8');
|
|||
|
|
|||
|
res.json({
|
|||
|
success: true,
|
|||
|
filename: path.basename(filePath),
|
|||
|
content: defaultContent
|
|||
|
});
|
|||
|
} catch (error) {
|
|||
|
console.error('创建IDL文件失败:', error);
|
|||
|
res.status(500).json({ error: '创建IDL文件失败', message: error.message });
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
// 删除IDL文件
|
|||
|
router.delete('/delete', async (req, res) => {
|
|||
|
try {
|
|||
|
const filename = req.query.filename;
|
|||
|
|
|||
|
if (!filename) {
|
|||
|
return res.status(400).json({ error: '缺少文件名参数' });
|
|||
|
}
|
|||
|
|
|||
|
const filePath = getSafePath(filename);
|
|||
|
|
|||
|
// 删除文件
|
|||
|
await fs.unlink(filePath);
|
|||
|
|
|||
|
res.json({ success: true, filename: path.basename(filePath) });
|
|||
|
} catch (error) {
|
|||
|
console.error('删除IDL文件失败:', error);
|
|||
|
|
|||
|
if (error.code === 'ENOENT') {
|
|||
|
return res.status(404).json({ error: '文件不存在' });
|
|||
|
}
|
|||
|
|
|||
|
res.status(500).json({ error: '删除IDL文件失败', message: error.message });
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
module.exports = router;
|