diff --git a/src/admin/index.ts b/src/admin/index.ts index 5ce6c6a..cd6caa4 100644 --- a/src/admin/index.ts +++ b/src/admin/index.ts @@ -1,2 +1,3 @@ import './router.ts'; import './manager.ts'; +import './npm.ts'; diff --git a/src/admin/npm.ts b/src/admin/npm.ts new file mode 100644 index 0000000..13953fc --- /dev/null +++ b/src/admin/npm.ts @@ -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); diff --git a/src/lib/dynamic-import.ts b/src/lib/dynamic-import.ts index f951b28..345bfe2 100644 --- a/src/lib/dynamic-import.ts +++ b/src/lib/dynamic-import.ts @@ -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 = [ { name: 'sequelize', @@ -8,3 +15,20 @@ export const defaultImportModules = [ 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}`; + } +}; diff --git a/src/lib/npm.ts b/src/lib/npm.ts new file mode 100644 index 0000000..dcf0e86 --- /dev/null +++ b/src/lib/npm.ts @@ -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 {}; + } +}; diff --git a/src/route.ts b/src/route.ts index d8e0ad5..e5e560d 100644 --- a/src/route.ts +++ b/src/route.ts @@ -3,6 +3,8 @@ import { router } from './modules/router.ts'; import './demo/index.ts'; import './admin/index.ts'; +import { dynamicImport } from './lib/dynamic-import.ts'; + type Message = { path: 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; - console.log('response', res); + // console.log('response', res); return { code, data: body, message }; };