做适配
This commit is contained in:
		
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -5,4 +5,7 @@ coverage
 | 
				
			|||||||
.DS_Store
 | 
					.DS_Store
 | 
				
			||||||
upload
 | 
					upload
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.config.json5
 | 
					app.config.json5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					release/*
 | 
				
			||||||
 | 
					!release/.gitkeep
 | 
				
			||||||
							
								
								
									
										10
									
								
								app.config.json5.example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								app.config.json5.example
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  port: 3005,
 | 
				
			||||||
 | 
					  api: {
 | 
				
			||||||
 | 
					    host: 'localhost:3000', // 后台代理
 | 
				
			||||||
 | 
					    path: '/api/router',
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  allowedOrigins: ['localhost', 'xiongxiao.me', 'zxj.im'],
 | 
				
			||||||
 | 
					  domain: 'demo.kevisual.xiongxiao.me',
 | 
				
			||||||
 | 
					  resources: 'localhost:9000/resources',
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								package.json
									
									
									
									
									
								
							@@ -20,29 +20,32 @@
 | 
				
			|||||||
    "build": "rimraf dist && rollup -c",
 | 
					    "build": "rimraf dist && rollup -c",
 | 
				
			||||||
    "deploy": "rsync -avz dist/ light:~/apps/var-proxy/backend",
 | 
					    "deploy": "rsync -avz dist/ light:~/apps/var-proxy/backend",
 | 
				
			||||||
    "reload": "ssh light pm2 restart proxy",
 | 
					    "reload": "ssh light pm2 restart proxy",
 | 
				
			||||||
    "pub": "npm run build && npm run deploy && npm run reload"
 | 
					    "pub": "npm run build && npm run deploy && npm run reload",
 | 
				
			||||||
 | 
					    "demo": "rsync -avz dist/ on:~/docker/page-proxy/dist",
 | 
				
			||||||
 | 
					    "start": "pm2 start dist/app.mjs --name page-proxy",
 | 
				
			||||||
 | 
					    "release": "node ./scripts/release/index.mjs"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "keywords": [],
 | 
					  "keywords": [],
 | 
				
			||||||
  "author": "",
 | 
					  "author": "",
 | 
				
			||||||
  "license": "ISC",
 | 
					  "license": "ISC",
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@rollup/plugin-commonjs": "^28.0.1",
 | 
					    "@rollup/plugin-commonjs": "^28.0.2",
 | 
				
			||||||
    "@rollup/plugin-json": "^6.1.0",
 | 
					    "@rollup/plugin-json": "^6.1.0",
 | 
				
			||||||
    "@rollup/plugin-node-resolve": "^15.3.0",
 | 
					    "@rollup/plugin-node-resolve": "^16.0.0",
 | 
				
			||||||
    "@rollup/plugin-typescript": "^12.1.1",
 | 
					    "@rollup/plugin-typescript": "^12.1.2",
 | 
				
			||||||
    "@types/http-proxy": "^1.17.15",
 | 
					    "@types/http-proxy": "^1.17.16",
 | 
				
			||||||
    "@types/node": "^22.10.1",
 | 
					    "@types/node": "^22.13.4",
 | 
				
			||||||
    "cross-env": "^7.0.3",
 | 
					    "cross-env": "^7.0.3",
 | 
				
			||||||
    "nodemon": "^3.1.7",
 | 
					    "nodemon": "^3.1.9",
 | 
				
			||||||
    "rollup": "^4.28.1",
 | 
					    "rollup": "^4.34.8",
 | 
				
			||||||
    "tslib": "^2.8.1",
 | 
					    "tslib": "^2.8.1",
 | 
				
			||||||
    "typescript": "^5.7.2"
 | 
					    "typescript": "^5.7.3"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "@kevisual/router": "0.0.6-alpha-2",
 | 
					    "@kevisual/router": "0.0.6-alpha-5",
 | 
				
			||||||
    "@kevisual/use-config": "^1.0.7",
 | 
					    "@kevisual/use-config": "^1.0.7",
 | 
				
			||||||
    "ioredis": "^5.4.1",
 | 
					    "ioredis": "^5.5.0",
 | 
				
			||||||
    "nanoid": "^5.0.9"
 | 
					    "nanoid": "^5.1.0"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "resolutions": {
 | 
					  "resolutions": {
 | 
				
			||||||
    "picomatch": "^4.0.2"
 | 
					    "picomatch": "^4.0.2"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										0
									
								
								release/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								release/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										114
									
								
								scripts/release/index.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								scripts/release/index.mjs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
				
			|||||||
 | 
					import fs from 'fs';
 | 
				
			||||||
 | 
					import path from 'path';
 | 
				
			||||||
 | 
					import archiver from 'archiver';
 | 
				
			||||||
 | 
					import { exec } from 'child_process';
 | 
				
			||||||
 | 
					import { nanoid } from 'nanoid';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const cwd = process.cwd();
 | 
				
			||||||
 | 
					const pkgPath = path.join(cwd, 'package.json');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const checkFileExistsSync = (filePath) => {
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    // 使用 F_OK 检查文件或目录是否存在
 | 
				
			||||||
 | 
					    fs.accessSync(filePath, fs.constants.F_OK);
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  } catch (err) {
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const releasePath = path.join(cwd, 'release');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const distPath = path.join(cwd, 'dist');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const zip = archiver('zip', {
 | 
				
			||||||
 | 
					  zlib: { level: 9 },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					const zipName = `page-proxy-${pkg.version}.zip`;
 | 
				
			||||||
 | 
					const zipCache = path.join(releasePath, `page-proxy-${pkg.version}.zip`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const getZip = async () => {
 | 
				
			||||||
 | 
					  return new Promise((resolve, reject) => {
 | 
				
			||||||
 | 
					    const output = fs.createWriteStream(zipCache);
 | 
				
			||||||
 | 
					    const startTime = (new Date().getTime() / 1000).toFixed(0);
 | 
				
			||||||
 | 
					    // 监听事件
 | 
				
			||||||
 | 
					    output.on('close', async () => {
 | 
				
			||||||
 | 
					      const bytes = zip.pointer();
 | 
				
			||||||
 | 
					      const size = bytes < 1024 ? `${bytes} bytes` : `${(bytes / 1024).toFixed(2)} KB`;
 | 
				
			||||||
 | 
					      console.log(`Zip file has been created successfully. Total size: ${size} bytes.`);
 | 
				
			||||||
 | 
					      let time = (new Date().getTime() / 1000).toFixed(0);
 | 
				
			||||||
 | 
					      console.log('time', time - startTime);
 | 
				
			||||||
 | 
					      resolve();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    output.on('end', () => {
 | 
				
			||||||
 | 
					      console.log('Data has been drained.'); // 数据已被耗尽
 | 
				
			||||||
 | 
					      throw new CustomError('Data has been drained.');
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    zip.on('warning', (err) => {
 | 
				
			||||||
 | 
					      if (err.code === 'ENOENT') {
 | 
				
			||||||
 | 
					        console.warn('File not found:', err);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        throw err;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    zip.on('error', (err) => {
 | 
				
			||||||
 | 
					      throw err;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 通过管道将 zip 数据流输出到指定文件
 | 
				
			||||||
 | 
					    zip.pipe(output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 添加 sh 字符串作为文件到 zip 中
 | 
				
			||||||
 | 
					    const sh = `#!/bin/bash
 | 
				
			||||||
 | 
					    npm i -g pnpm 
 | 
				
			||||||
 | 
					    pnpm install --prod
 | 
				
			||||||
 | 
					    `;
 | 
				
			||||||
 | 
					    zip.append(sh, { name: 'start.sh' });
 | 
				
			||||||
 | 
					    // 把dist目录下的文件添加到zip中
 | 
				
			||||||
 | 
					    zip.directory(distPath, 'dist');
 | 
				
			||||||
 | 
					    // 把README.md添加到zip中
 | 
				
			||||||
 | 
					    zip.file(path.join(cwd, 'README.md'), { name: 'README.md' });
 | 
				
			||||||
 | 
					    // 把package.json添加到zip中
 | 
				
			||||||
 | 
					    zip.file(pkgPath, { name: 'package.json' });
 | 
				
			||||||
 | 
					    const ecosystemContent = `module.exports = {
 | 
				
			||||||
 | 
					  apps: [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      name: 'page-proxy', // 应用名称
 | 
				
			||||||
 | 
					      script: './dist/app.mjs', // 入口文件
 | 
				
			||||||
 | 
					      // cwd: '.', // 设置当前工作目录
 | 
				
			||||||
 | 
					      output: './logs/page-proxy.log',
 | 
				
			||||||
 | 
					      error: './logs/page-proxy.log',
 | 
				
			||||||
 | 
					      log_date_format: 'YYYY-MM-DD HH:mm:ss',
 | 
				
			||||||
 | 
					      // watch: true, // 自动监控文件变化
 | 
				
			||||||
 | 
					      watch: ['dist'], // 监控的文件夹
 | 
				
			||||||
 | 
					      ignore_watch: ['node_modules', 'logs'], // 忽略的文件夹
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					    zip.append(ecosystemContent, { name: 'ecosystem.config.cjs' });
 | 
				
			||||||
 | 
					    const json5Content = fs.readFileSync(path.join(cwd, 'app.config.json5.example'), 'utf8');
 | 
				
			||||||
 | 
					    // tokenSecret 是一个随机字符串,用于生成 token
 | 
				
			||||||
 | 
					    const tokenSecret = 'XX' + nanoid(39);
 | 
				
			||||||
 | 
					    json5Content.replace('<TOKEN_SECRET>', tokenSecret);
 | 
				
			||||||
 | 
					    // tokenSecret
 | 
				
			||||||
 | 
					    //  把app.config.json5.example添加到zip中
 | 
				
			||||||
 | 
					    // zip.file(path.join(cwd, 'app.config.json5.example'), { name: 'app.config.json5.example' });
 | 
				
			||||||
 | 
					    zip.append(json5Content, { name: 'app.config.json5.example' });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 结束归档(必须调用,否则 zip 文件无法完成)
 | 
				
			||||||
 | 
					    zip.finalize();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					getZip().then(() => {
 | 
				
			||||||
 | 
					  console.log('zip success');
 | 
				
			||||||
 | 
					  console.log(`envision switchOrg system && envision  deploy ./release/${zipName} -v 1.0.0 -k page-proxy -y y -u`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  console.log(`download zip: https://kevisual.xiongxiao.me/system/page-proxy/${zipName}`);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@@ -255,7 +255,10 @@ export const downloadUserAppFiles = async (user: string, app: string, data: type
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (data.type === 'oss') {
 | 
					  if (data.type === 'oss') {
 | 
				
			||||||
    const serverPath = 'https://' + resources + '/';
 | 
					    let serverPath = 'https://' + resources + '/';
 | 
				
			||||||
 | 
					    if(resources.includes('localhost')) {
 | 
				
			||||||
 | 
					      serverPath = 'http://' + resources + '/';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    // server download file
 | 
					    // server download file
 | 
				
			||||||
    for (let i = 0; i < files.length; i++) {
 | 
					    for (let i = 0; i < files.length; i++) {
 | 
				
			||||||
      const file = files[i];
 | 
					      const file = files[i];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,13 +24,18 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR
 | 
				
			|||||||
    res.write('proxy no favicon.ico\n');
 | 
					    res.write('proxy no favicon.ico\n');
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (req.url.startsWith('/api/router')) {
 | 
					  if (req.url.startsWith('/api/proxy')) {
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (req.url.startsWith('/api')) {
 | 
				
			||||||
    // 代理到 http://codeflow.xiongxiao.me/api
 | 
					    // 代理到 http://codeflow.xiongxiao.me/api
 | 
				
			||||||
    const _u = new URL(req.url, `http://${api.host}`);
 | 
					    const _u = new URL(req.url, `http://${api.host}`);
 | 
				
			||||||
    // 设置代理请求的目标 URL 和请求头
 | 
					    // 设置代理请求的目标 URL 和请求头
 | 
				
			||||||
    let header: any = {};
 | 
					    let header: any = {};
 | 
				
			||||||
    if (req.headers?.['Authroization']) {
 | 
					    if (req.headers?.['Authorization']) {
 | 
				
			||||||
      header.Authorization = req.headers?.['Authroization'];
 | 
					      header.authorization = req.headers['Authorization'];
 | 
				
			||||||
 | 
					    } else if(req.headers?.['authorization']) {
 | 
				
			||||||
 | 
					      header.authorization = req.headers['authorization'];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (req.headers?.['Content-Type']) {
 | 
					    if (req.headers?.['Content-Type']) {
 | 
				
			||||||
      header['Content-Type'] = req.headers?.['Content-Type'];
 | 
					      header['Content-Type'] = req.headers?.['Content-Type'];
 | 
				
			||||||
@@ -64,9 +69,6 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR
 | 
				
			|||||||
    req.pipe(proxyReq, { end: true });
 | 
					    req.pipe(proxyReq, { end: true });
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (req.url.startsWith('/api/proxy')) {
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (req.url.startsWith('/api')) {
 | 
					  if (req.url.startsWith('/api')) {
 | 
				
			||||||
    res.end('not catch api');
 | 
					    res.end('not catch api');
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user