generated from tailored/router-template
	base module
This commit is contained in:
		
							
								
								
									
										13
									
								
								src/app.ts
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/app.ts
									
									
									
									
									
								
							| @@ -1,8 +1,19 @@ | ||||
| import { App } from '@kevisual/router'; | ||||
| import { useContextKey } from '@kevisual/use-config/context'; | ||||
| import { httpsConfig } from './modules/config.ts'; | ||||
|  | ||||
| const init = () => { | ||||
|   return new App(); | ||||
|   const app = new App({ | ||||
|     serverOptions: { | ||||
|       path: '/client/router', | ||||
|       httpType: 'https', | ||||
|       httpsCert: httpsConfig.cert.toString(), | ||||
|       httpsKey: httpsConfig.key.toString(), | ||||
|     }, | ||||
|   }); | ||||
|   return app; | ||||
| }; | ||||
|  | ||||
| export const app = useContextKey('app', init); | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1,16 +0,0 @@ | ||||
| import { app } from './app.ts'; | ||||
| import { useConfig } from '@kevisual/use-config'; | ||||
|  | ||||
| app | ||||
|   .route({ | ||||
|     path: 'demo', | ||||
|     key: 'demo', | ||||
|   }) | ||||
|   .define(async (ctx) => { | ||||
|     ctx.body = '123'; | ||||
|   }) | ||||
|   .addTo(app); | ||||
|  | ||||
| const config = useConfig(); | ||||
|  | ||||
| console.log('run demo: http://localhost:' + config.port + '/api/router?path=demo&key=demo'); | ||||
							
								
								
									
										18
									
								
								src/dev.ts
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								src/dev.ts
									
									
									
									
									
								
							| @@ -1,8 +1,18 @@ | ||||
| import { useConfig } from '@kevisual/use-config'; | ||||
| import { app } from './index.ts'; | ||||
| import { proxyRoute } from './proxy-route/index.ts'; | ||||
|  | ||||
| const config = useConfig(); | ||||
| app | ||||
|   .route({ | ||||
|     path: 'demo', | ||||
|   }) | ||||
|   .define(async (ctx) => { | ||||
|     ctx.body = 'hello world'; | ||||
|   }) | ||||
|   .addTo(app); | ||||
|  | ||||
| app.listen(config.port, () => { | ||||
|   console.log(`server is running at http://localhost:${config.port}`); | ||||
| console.log('httpsConfig', `https://localhost:51015/client/router?path=demo`); | ||||
| app.listen(51015, () => { | ||||
|   console.log('Router App is running on https://localhost:51015'); | ||||
| }); | ||||
|  | ||||
| app.server.on(proxyRoute); | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { app } from './app.ts'; | ||||
| import './demo-route.ts'; | ||||
| import './route/index.ts'; | ||||
|  | ||||
| export { app }; | ||||
							
								
								
									
										9
									
								
								src/modules/config.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/modules/config.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| import fs from 'fs'; | ||||
| import path from 'path'; | ||||
|  | ||||
| const pemDir = path.join(process.cwd(), 'pem'); | ||||
|  | ||||
| export const httpsConfig = { | ||||
|   key: fs.readFileSync(path.join(pemDir, 'https-key.pem')), | ||||
|   cert: fs.readFileSync(path.join(pemDir, 'https-cert.pem')), | ||||
| }; | ||||
							
								
								
									
										108
									
								
								src/modules/config/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/modules/config/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| import path from 'path'; | ||||
| import { homedir } from 'os'; | ||||
| import fs from 'fs'; | ||||
| import { checkFileExists, createDir } from '../file/index.ts'; | ||||
|  | ||||
| export const kevisualUrl = 'https://kevisual.xiongxiao.me'; | ||||
| const configDir = createDir(path.join(homedir(), '.config/envision')); | ||||
| export const configPath = path.join(configDir, 'assistant-config.json'); | ||||
| export const appConfigPath = path.join(configDir, 'assistant-app-config.json'); | ||||
| export const appDir = createDir(path.join(configDir, 'assistant-app/frontend')); | ||||
| export const LocalElectronAppUrl = 'https://assistant.app/user/tiptap/'; | ||||
|  | ||||
| type AssistantConfig = { | ||||
|   pageApi?: string; // https://kevisual.silkyai.cn | ||||
|   loadURL?: string; // https://assistant.app/user/tiptap/ | ||||
|   proxy?: { user: string; key: string; path: string }[]; | ||||
| }; | ||||
| let assistantConfig: AssistantConfig; | ||||
| export const getConfig = () => { | ||||
|   try { | ||||
|     if (!checkFileExists(configPath)) { | ||||
|       fs.writeFileSync(configPath, JSON.stringify({ proxy: [] }, null, 2)); | ||||
|       return { | ||||
|         loadURL: LocalElectronAppUrl, | ||||
|         pageApi: '', | ||||
|         proxy: [], | ||||
|       }; | ||||
|     } | ||||
|     assistantConfig = JSON.parse(fs.readFileSync(configPath, 'utf8')); | ||||
|     return assistantConfig; | ||||
|   } catch (error) { | ||||
|     console.error(error); | ||||
|     return { | ||||
|       loadURL: LocalElectronAppUrl, | ||||
|       pageApi: '', | ||||
|       proxy: [], | ||||
|     }; | ||||
|   } | ||||
| }; | ||||
| export const getCacheAssistantConfig = () => { | ||||
|   if (assistantConfig) { | ||||
|     return assistantConfig; | ||||
|   } | ||||
|   return getConfig(); | ||||
| }; | ||||
|  | ||||
| export const setConfig = (config?: AssistantConfig) => { | ||||
|   if (!config) { | ||||
|     return assistantConfig; | ||||
|   } | ||||
|   assistantConfig = config; | ||||
|   fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); | ||||
|   return assistantConfig; | ||||
| }; | ||||
| type AppConfig = { | ||||
|   list: any[]; | ||||
| }; | ||||
| /** | ||||
|  * 应用配置 | ||||
|  * @returns | ||||
|  */ | ||||
| export const getAppConfig = (): AppConfig => { | ||||
|   if (!checkFileExists(appConfigPath)) { | ||||
|     return { | ||||
|       list: [], | ||||
|     }; | ||||
|   } | ||||
|   return JSON.parse(fs.readFileSync(appConfigPath, 'utf8')); | ||||
| }; | ||||
|  | ||||
| export const setAppConfig = (config: AppConfig) => { | ||||
|   fs.writeFileSync(appConfigPath, JSON.stringify(config, null, 2)); | ||||
|   return config; | ||||
| }; | ||||
|  | ||||
| export const addAppConfig = (app: any) => { | ||||
|   const config = getAppConfig(); | ||||
|   const assistantConfig = getCacheAssistantConfig(); | ||||
|   const _apps = config.list; | ||||
|   const _proxy = assistantConfig.proxy || []; | ||||
|   const { user, key } = app; | ||||
|   const newProxyInfo = { | ||||
|     user, | ||||
|     key, | ||||
|     path: `/${user}/${key}`, | ||||
|   }; | ||||
|   const _proxyIndex = _proxy.findIndex((_proxy: any) => _proxy.path === newProxyInfo.path); | ||||
|   if (_proxyIndex !== -1) { | ||||
|     _proxy[_proxyIndex] = newProxyInfo; | ||||
|   } else { | ||||
|     _proxy.push(newProxyInfo); | ||||
|   } | ||||
|  | ||||
|   const _app = _apps.findIndex((_app: any) => _app.id === app.id); | ||||
|   if (_app !== -1) { | ||||
|     _apps[_app] = app; | ||||
|   } else { | ||||
|     _apps.push(app); | ||||
|   } | ||||
|   setAppConfig({ ...config, list: _apps }); | ||||
|   setConfig({ ...assistantConfig, proxy: _proxy }); | ||||
|   return config; | ||||
| }; | ||||
|  | ||||
| export const getAppList = () => { | ||||
|   const config = getAppConfig(); | ||||
|   return config.list || []; | ||||
| }; | ||||
							
								
								
									
										20
									
								
								src/modules/file/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/modules/file/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| import fs from 'fs'; | ||||
|  | ||||
| export const checkFileExists = (filePath: string, checkIsFile = false) => { | ||||
|   try { | ||||
|     fs.accessSync(filePath); | ||||
|     if (checkIsFile) { | ||||
|       return fs.statSync(filePath).isFile(); | ||||
|     } | ||||
|     return true; | ||||
|   } catch (error) { | ||||
|     return false; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| export const createDir = (dirPath: string) => { | ||||
|   if (!checkFileExists(dirPath)) { | ||||
|     fs.mkdirSync(dirPath, { recursive: true }); | ||||
|   } | ||||
|   return dirPath; | ||||
| }; | ||||
							
								
								
									
										156
									
								
								src/modules/install.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								src/modules/install.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,156 @@ | ||||
| import path from 'path'; | ||||
| import fs from 'fs'; | ||||
| import { appDir, kevisualUrl, addAppConfig, getAppConfig, setAppConfig, getCacheAssistantConfig, setConfig } from './config/index.ts'; | ||||
|  | ||||
| export const demoData = { | ||||
|   id: '471ee96f-d7d8-4da1-b84f-4a34f4732f16', | ||||
|   title: 'tiptap', | ||||
|   description: '', | ||||
|   data: { | ||||
|     files: [ | ||||
|       { | ||||
|         name: 'README.md', | ||||
|         path: 'user/tiptap/0.0.1/README.md', | ||||
|       }, | ||||
|       { | ||||
|         name: 'app.css', | ||||
|         path: 'user/tiptap/0.0.1/app.css', | ||||
|       }, | ||||
|       { | ||||
|         name: 'app.js', | ||||
|         path: 'user/tiptap/0.0.1/app.js', | ||||
|       }, | ||||
|       { | ||||
|         name: 'create-BxEwtceK.js', | ||||
|         path: 'user/tiptap/0.0.1/create-BxEwtceK.js', | ||||
|       }, | ||||
|       { | ||||
|         name: 'index.CrTXFMOJ.js', | ||||
|         path: 'user/tiptap/0.0.1/index.CrTXFMOJ.js', | ||||
|       }, | ||||
|       { | ||||
|         name: 'index.html', | ||||
|         path: 'user/tiptap/0.0.1/index.html', | ||||
|       }, | ||||
|     ], | ||||
|   }, | ||||
|   version: '0.0.1', | ||||
|   domain: '', | ||||
|   appType: '', | ||||
|   key: 'tiptap', | ||||
|   type: '', | ||||
|   uid: '2bebe6a0-3c64-4a64-89f9-cc47fd082a07', | ||||
|   pid: null, | ||||
|   proxy: false, | ||||
|   user: 'user', | ||||
|   status: 'running', | ||||
|   createdAt: '2024-12-14T15:39:30.684Z', | ||||
|   updatedAt: '2024-12-14T15:39:55.714Z', | ||||
|   deletedAt: null, | ||||
| }; | ||||
|  | ||||
| type DownloadTask = { | ||||
|   downloadPath: string; | ||||
|   downloadUrl: string; | ||||
|   user: string; | ||||
|   key: string; | ||||
|   version: string; | ||||
| }; | ||||
| export type Package = { | ||||
|   id: string; | ||||
|   name?: string; | ||||
|   version?: string; | ||||
|   description?: string; | ||||
|   title?: string; | ||||
|   user?: string; | ||||
|   key?: string; | ||||
|   [key: string]: any; | ||||
| }; | ||||
| export const installApp = async (app: Package) => { | ||||
|   // const _app = demoData; | ||||
|   const _app = app; | ||||
|   try { | ||||
|     let files = _app.data.files || []; | ||||
|     const version = _app.version; | ||||
|     const user = _app.user; | ||||
|     const key = _app.key; | ||||
|  | ||||
|     const downFiles = files.map((file: any) => { | ||||
|       const noVersionPath = file.path.replace(`/${version}`, ''); | ||||
|       return { | ||||
|         ...file, | ||||
|         downloadPath: path.join(appDir, noVersionPath), | ||||
|         downloadUrl: `${kevisualUrl}/${noVersionPath}`, | ||||
|       }; | ||||
|     }); | ||||
|     const downloadTasks: DownloadTask[] = downFiles as any; | ||||
|     for (const file of downloadTasks) { | ||||
|       const downloadPath = file.downloadPath; | ||||
|       const downloadUrl = file.downloadUrl; | ||||
|       const dir = path.dirname(downloadPath); | ||||
|       if (!fs.existsSync(dir)) { | ||||
|         fs.mkdirSync(dir, { recursive: true }); | ||||
|       } | ||||
|       const res = await fetch(downloadUrl); | ||||
|       const blob = await res.blob(); | ||||
|       fs.writeFileSync(downloadPath, Buffer.from(await blob.arrayBuffer())); | ||||
|     } | ||||
|     let indexHtml = files.find((file: any) => file.name === 'index.html'); | ||||
|     if (!indexHtml) { | ||||
|       files.push({ | ||||
|         name: 'index.html', | ||||
|         path: `${user}/${key}/index.html`, | ||||
|       }); | ||||
|       fs.writeFileSync(path.join(appDir, `${user}/${key}/index.html`), JSON.stringify(app, null, 2)); | ||||
|     } | ||||
|     _app.data.files = files; | ||||
|     addAppConfig(_app); | ||||
|     return { | ||||
|       code: 200, | ||||
|       data: _app, | ||||
|       message: 'Install app success', | ||||
|     }; | ||||
|   } catch (error) { | ||||
|     console.error(error); | ||||
|     return { | ||||
|       code: 500, | ||||
|       message: 'Install app failed', | ||||
|     }; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| export const uninstallApp = async (app: Package) => { | ||||
|   try { | ||||
|     const { user, key } = app; | ||||
|     const appConfig = getAppConfig(); | ||||
|     const index = appConfig.list.findIndex((item: any) => item.user === user && item.key === key); | ||||
|     if (index !== -1) { | ||||
|       appConfig.list.splice(index, 1); | ||||
|       setAppConfig(appConfig); | ||||
|       // 删除appDir和文件 | ||||
|       fs.rmSync(path.join(appDir, user, key), { recursive: true }); | ||||
|       // 删除proxy | ||||
|       const proxyConfig = getCacheAssistantConfig(); | ||||
|       const proxyIndex = proxyConfig.proxy.findIndex((item: any) => item.user === user && item.key === key); | ||||
|       if (proxyIndex !== -1) { | ||||
|         proxyConfig.proxy.splice(proxyIndex, 1); | ||||
|         setConfig(proxyConfig); | ||||
|       } | ||||
|     } | ||||
|     return { | ||||
|       code: 200, | ||||
|       message: 'Uninstall app success', | ||||
|     }; | ||||
|   } catch (error) { | ||||
|     console.error(error); | ||||
|     return { | ||||
|       code: 500, | ||||
|       message: 'Uninstall app failed', | ||||
|     }; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| export const getInstallList = async () => { | ||||
|   const appConfig = getAppConfig(); | ||||
|   return appConfig.list; | ||||
| }; | ||||
							
								
								
									
										61
									
								
								src/proxy-route/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/proxy-route/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| import { fileProxy, apiProxy, createApiProxy } from '@kevisual/assistant-module/proxy'; | ||||
| import { getCacheAssistantConfig, appDir } from '@kevisual/assistant-module'; | ||||
| import http from 'http'; | ||||
|  | ||||
| // https://localhost:51015/user/tiptap/ | ||||
| export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResponse) => { | ||||
|   const assistantConfig = getCacheAssistantConfig(); | ||||
|   // const { apiList } = assistantConfig; | ||||
|   const url = new URL(req.url, 'http://localhost'); | ||||
|   const pathname = url.pathname; | ||||
|   if (pathname.startsWith('/favicon.ico')) { | ||||
|     res.statusCode = 404; | ||||
|     res.end('Not Found Favicon'); | ||||
|     return; | ||||
|   } | ||||
|   if (pathname.startsWith('/client')) { | ||||
|     console.log('handle by router'); | ||||
|     return; | ||||
|   } | ||||
|   const apiProxyList = assistantConfig?.apiProxyList || []; | ||||
|   const defaultApiProxy = createApiProxy(assistantConfig?.pageApi || 'https://kevisual.xiongxiao.me'); | ||||
|   const apiBackendProxy = [...apiProxyList, ...defaultApiProxy].find((item) => pathname.startsWith(item.path)); | ||||
|   if (apiBackendProxy) { | ||||
|     console.log('apiBackendProxy', apiBackendProxy); | ||||
|     return apiProxy(req, res, { | ||||
|       path: apiBackendProxy.path, | ||||
|       target: apiBackendProxy.target, | ||||
|     }); | ||||
|   } | ||||
|   // client, api, v1, serve 开头的拦截 | ||||
|   const proxyApiList = assistantConfig?.proxy || []; | ||||
|   const proxyApi = proxyApiList.find((item) => pathname.startsWith(item.path)); | ||||
|   if (proxyApi) { | ||||
|     console.log('proxyApi', proxyApi, pathname); | ||||
|     const { user, key } = proxyApi; | ||||
|     return fileProxy(req, res, { | ||||
|       path: proxyApi.path, | ||||
|       rootPath: appDir, | ||||
|       indexPath: `${user}/${key}/index.html`, | ||||
|     }); | ||||
|   } | ||||
|   const localProxyProxy = localProxyProxyList.find((item) => pathname.startsWith(item.path)); | ||||
|   if (localProxyProxy) { | ||||
|     return fileProxy(req, res, { | ||||
|       path: localProxyProxy.path, | ||||
|       rootPath: process.cwd(), | ||||
|       indexPath: localProxyProxy.indexPath, | ||||
|     }); | ||||
|   } | ||||
|   console.log('handle by router 404'); | ||||
|   res.statusCode = 404; | ||||
|   res.end('Not Found Proxy'); | ||||
| }; | ||||
| const localProxyProxyList = [ | ||||
|   { | ||||
|     user: 'root', | ||||
|     key: 'assistant-base-app', | ||||
|     path: '/root/assistant-base-app', | ||||
|     indexPath: 'root/assistant-base-app/index.html', | ||||
|   }, | ||||
| ]; | ||||
							
								
								
									
										42
									
								
								src/proxy-route/ws-proxy.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/proxy-route/ws-proxy.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| import net from 'net'; | ||||
| import { App } from '@kevisual/router'; | ||||
|  | ||||
| export const wsProxy = (app: App, config: { apiList: any[] }) => { | ||||
|   console.log('Upgrade initialization started'); | ||||
|  | ||||
|   app.server.server.on('upgrade', (req, socket, head) => { | ||||
|     const proxyApiList = config?.apiList || []; | ||||
|     const proxyApi = proxyApiList.find((item) => req.url.startsWith(item.path)); | ||||
|  | ||||
|     if (proxyApi) { | ||||
|       const _u = new URL(req.url, `${proxyApi.target}`); | ||||
|       const options = { | ||||
|         hostname: _u.hostname, | ||||
|         port: Number(_u.port) || 80, | ||||
|         path: _u.pathname, | ||||
|         headers: req.headers, | ||||
|       }; | ||||
|  | ||||
|       const proxySocket = net.connect(options.port, options.hostname, () => { | ||||
|         proxySocket.write( | ||||
|           `GET ${options.path} HTTP/1.1\r\n` + | ||||
|             `Host: ${options.hostname}\r\n` + | ||||
|             `Connection: Upgrade\r\n` + | ||||
|             `Upgrade: websocket\r\n` + | ||||
|             `Sec-WebSocket-Key: ${req.headers['sec-websocket-key']}\r\n` + | ||||
|             `Sec-WebSocket-Version: ${req.headers['sec-websocket-version']}\r\n` + | ||||
|             `\r\n`, | ||||
|         ); | ||||
|         proxySocket.pipe(socket); | ||||
|         socket.pipe(proxySocket); | ||||
|       }); | ||||
|  | ||||
|       proxySocket.on('error', (err) => { | ||||
|         console.error(`WebSocket proxy error: ${err.message}`); | ||||
|         socket.end(); | ||||
|       }); | ||||
|     } else { | ||||
|       socket.end(); | ||||
|     } | ||||
|   }); | ||||
| }; | ||||
							
								
								
									
										10
									
								
								src/route/client/check.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/route/client/check.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| import { app } from '@/app.ts'; | ||||
|  | ||||
| app | ||||
|   .route({ | ||||
|     path: 'check', | ||||
|   }) | ||||
|   .define(async (ctx) => { | ||||
|     ctx.body = 'ok'; | ||||
|   }) | ||||
|   .addTo(app); | ||||
							
								
								
									
										25
									
								
								src/route/config/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/route/config/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| import { app } from '@/app.ts'; | ||||
| import { getCacheAssistantConfig, setConfig } from '@/modules/config/index.ts'; | ||||
|  | ||||
| app | ||||
|   .route({ | ||||
|     path: 'config', | ||||
|     description: '获取配置', | ||||
|   }) | ||||
|   .define(async (ctx) => { | ||||
|     ctx.body = getCacheAssistantConfig(); | ||||
|   }) | ||||
|   .addTo(app); | ||||
|  | ||||
| app | ||||
|   .route({ | ||||
|     path: 'config', | ||||
|     key: 'set', | ||||
|     description: '设置配置', | ||||
|   }) | ||||
|   .define(async (ctx) => { | ||||
|     const { data } = ctx.query; | ||||
|  | ||||
|     ctx.body = setConfig(data); | ||||
|   }) | ||||
|   .addTo(app); | ||||
							
								
								
									
										3
									
								
								src/route/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/route/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| import './shop-install/index.ts'; | ||||
| import './client/check.ts'; | ||||
| import './config/index.ts'; | ||||
							
								
								
									
										40
									
								
								src/route/shop-install/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/route/shop-install/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| import { app } from '@/app.ts'; | ||||
| import { getInstallList, installApp, uninstallApp } from '@/modules/install.ts'; | ||||
|  | ||||
| app | ||||
|   .route({ | ||||
|     path: 'shop', | ||||
|     key: 'list-installed', | ||||
|   }) | ||||
|   .define(async (ctx) => { | ||||
|     // https://localhost:51015/client/router?path=shop&key=list-installed | ||||
|     const list = await getInstallList(); | ||||
|     ctx.body = list; | ||||
|   }) | ||||
|   .addTo(app); | ||||
|  | ||||
| app | ||||
|   .route({ | ||||
|     path: 'shop', | ||||
|     key: 'install', | ||||
|   }) | ||||
|   .define(async (ctx) => { | ||||
|     // https://localhost:51015/client/router?path=shop&key=install | ||||
|     const { pkg } = ctx.query.data; | ||||
|     const res = await installApp(pkg); | ||||
|     ctx.body = res; | ||||
|   }) | ||||
|   .addTo(app); | ||||
|  | ||||
| app | ||||
|   .route({ | ||||
|     path: 'shop', | ||||
|     key: 'uninstall', | ||||
|   }) | ||||
|   .define(async (ctx) => { | ||||
|     // https://localhost:51015/client/router?path=shop&key=uninstall | ||||
|     const { pkg } = ctx.query.data; | ||||
|     const res = await uninstallApp(pkg); | ||||
|     ctx.body = res; | ||||
|   }) | ||||
|   .addTo(app); | ||||
							
								
								
									
										8
									
								
								src/scripts/assistant-config.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/scripts/assistant-config.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| import { getCacheAssistantConfig, appConfigPath, appDir } from '@kevisual/assistant-module'; | ||||
| import fs from 'fs'; | ||||
|  | ||||
| const assistantConfig = getCacheAssistantConfig(); | ||||
| console.log(assistantConfig); | ||||
|  | ||||
| console.log('appConfigPath', appConfigPath); | ||||
| console.log('appDir', appDir); | ||||
		Reference in New Issue
	
	Block a user