feat: add 动态执行模块

This commit is contained in:
xion 2024-07-01 19:31:28 +08:00
parent 9d4a4947e7
commit ee0740b2d7
5 changed files with 104 additions and 2 deletions

View File

@ -1,2 +1,3 @@
import './router.ts'; import './router.ts';
import './manager.ts'; import './manager.ts';
import './npm.ts';

26
src/admin/npm.ts Normal file
View File

@ -0,0 +1,26 @@
import { Route } from '@abearxiong/router';
import { router } from '../modules/router.ts';
import { getPackage, installPackage } from '../lib/npm.ts';
const install = new Route('admin', 'install');
install.run = async (ctx) => {
const { packageName } = ctx.query;
const data = await installPackage(packageName);
ctx.body = data;
return ctx;
};
install.validator = {
packageName: {
type: 'string',
required: true,
},
};
router.add(install);
const getNpm = new Route('admin', 'getNpm');
getNpm.run = async (ctx) => {
const data = await getPackage();
ctx.body = data['dependencies'];
return ctx;
};
router.add(getNpm);

View File

@ -1,3 +1,10 @@
import path from 'path';
export const getRequire = () => {
return eval('require') as NodeRequire;
};
export const directoryPath = path.resolve(__dirname);
export const defaultImportModules = [ export const defaultImportModules = [
{ {
name: 'sequelize', name: 'sequelize',
@ -8,3 +15,20 @@ export const defaultImportModules = [
version: '^8.12.1', version: '^8.12.1',
}, },
]; ];
export const dynamicImport = async (name: string) => {
// const nodeModules = path.resolve(directoryPath, 'node_modules');
// const nodeName = path.resolve(nodeModules, name);
const require = getRequire();
console.log(`Dynamic import module ${name}`);
try {
const nodeCache = require.cache[require.resolve(name)];
if (nodeCache) {
console.log(`${name} is cached`);
}
return require(name);
} catch (e) {
console.error(`Failed to import module ${name}: ${e.message}`);
throw `Failed to import module ${name}: ${e.message}`;
}
};

46
src/lib/npm.ts Normal file
View File

@ -0,0 +1,46 @@
import { exec } from 'child_process';
import path from 'path';
import fs from 'fs';
export const directoryPath = path.resolve(__dirname);
const packagePath = path.resolve(directoryPath, 'package.json');
const exists = (filePath: string) => {
try {
fs.accessSync(filePath);
return true;
} catch (e) {
return false;
}
};
export const installPackage = async (packageName: string) => {
if (!exists(packagePath)) {
fs.writeFileSync(packagePath, JSON.stringify({ name: 'npm-install', version: '1.0.0' }), 'utf-8');
}
return await new Promise((resolve, reject) => {
console.log(`Starting installation of ${packageName}...`);
// 在程序运行路径下执行 npm install 命令
console.log(`npm install ${packageName}`);
exec(`npm install ${packageName}`, { cwd: directoryPath }, (error, stdout, stderr) => {
if (error) {
console.error(`Error installing package: ${stderr}`);
reject(new Error(`Failed to install package ${packageName}`));
} else {
console.log(`Package ${packageName} installed successfully: ${stdout}`);
resolve(stdout);
}
});
});
};
export const getPackage = async () => {
if (!exists(packagePath)) {
return {};
}
try {
return JSON.parse(fs.readFileSync(packagePath, 'utf-8'));
} catch (e) {
console.error('Failed to read package.json');
return {};
}
};

View File

@ -3,6 +3,8 @@ import { router } from './modules/router.ts';
import './demo/index.ts'; import './demo/index.ts';
import './admin/index.ts'; import './admin/index.ts';
import { dynamicImport } from './lib/dynamic-import.ts';
type Message = { type Message = {
path: string; path: string;
key?: string; key?: string;
@ -16,8 +18,11 @@ export const handleMessage = async function (m: Message) {
}; };
} }
const res = await router.parse(m); const res = await router.parse(m, {
// @ts-ignore
import: dynamicImport,
});
const { code, body, message } = res; const { code, body, message } = res;
console.log('response', res); // console.log('response', res);
return { code, data: body, message }; return { code, data: body, message };
}; };