feat: add app download
This commit is contained in:
		
							
								
								
									
										128
									
								
								src/module/download/install.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								src/module/download/install.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | ||||
| import path from 'path'; | ||||
| import fs from 'fs'; | ||||
|  | ||||
| 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; | ||||
| }; | ||||
| type InstallAppOpts = { | ||||
|   appDir?: string; | ||||
|   kevisualUrl?: string; | ||||
|   /** | ||||
|    * 是否是客户端, 下载到 assistant-config的下面 | ||||
|    */ | ||||
|   isClient?: boolean; | ||||
| }; | ||||
| export const installApp = async (app: Package, opts: InstallAppOpts = {}) => { | ||||
|   // const _app = demoData; | ||||
|   const { appDir = '', kevisualUrl = 'https://kevisual.cn' } = opts; | ||||
|   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; | ||||
|     return { | ||||
|       code: 200, | ||||
|       data: _app, | ||||
|       message: 'Install app success', | ||||
|     }; | ||||
|   } catch (error) { | ||||
|     console.error(error); | ||||
|     return { | ||||
|       code: 500, | ||||
|       message: 'Install app failed', | ||||
|     }; | ||||
|   } | ||||
| }; | ||||
| export const checkAppDir = (appDir: string) => { | ||||
|   const files = fs.readdirSync(appDir); | ||||
|   if (files.length === 0) { | ||||
|     fs.rmSync(appDir, { recursive: true }); | ||||
|   } | ||||
| }; | ||||
| export const checkFileExists = (path: string) => { | ||||
|   try { | ||||
|     fs.accessSync(path); | ||||
|     return true; | ||||
|   } catch (error) { | ||||
|     return false; | ||||
|   } | ||||
| }; | ||||
| type UninstallAppOpts = { | ||||
|   appDir?: string; | ||||
| }; | ||||
| export const uninstallApp = async (app: Partial<Package>, opts: UninstallAppOpts = {}) => { | ||||
|   const { appDir = '' } = opts; | ||||
|   try { | ||||
|     const { user, key } = app; | ||||
|     const keyDir = path.join(appDir, user, key); | ||||
|     const parentDir = path.join(appDir, user); | ||||
|     if (!checkFileExists(appDir) || !checkFileExists(keyDir)) { | ||||
|       return { | ||||
|         code: 200, | ||||
|         message: 'uninstall app success', | ||||
|       }; | ||||
|     } | ||||
|     try { | ||||
|       // 删除appDir和文件 | ||||
|       fs.rmSync(keyDir, { recursive: true }); | ||||
|     } catch (error) { | ||||
|       console.error(error); | ||||
|     } | ||||
|     checkAppDir(parentDir); | ||||
|     return { | ||||
|       code: 200, | ||||
|       message: 'Uninstall app success', | ||||
|     }; | ||||
|   } catch (error) { | ||||
|     console.error(error); | ||||
|     return { | ||||
|       code: 500, | ||||
|       message: 'Uninstall app failed', | ||||
|     }; | ||||
|   } | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user