@lynker-desktop/electron-sdk 0.0.9-alpha.7 → 0.0.9-alpha.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +160 -1
  2. package/common/index.d.ts +96 -0
  3. package/common/index.d.ts.map +1 -1
  4. package/common/index.js.map +1 -1
  5. package/esm/common/index.d.ts +96 -0
  6. package/esm/common/index.d.ts.map +1 -1
  7. package/esm/common/index.js.map +1 -1
  8. package/esm/main/clipboard.d.ts +32 -0
  9. package/esm/main/clipboard.d.ts.map +1 -0
  10. package/esm/main/clipboard.js +1208 -0
  11. package/esm/main/clipboard.js.map +1 -0
  12. package/esm/main/downloader.d.ts +212 -0
  13. package/esm/main/downloader.d.ts.map +1 -0
  14. package/esm/main/downloader.js +674 -0
  15. package/esm/main/downloader.js.map +1 -0
  16. package/esm/main/index.d.ts +20 -67
  17. package/esm/main/index.d.ts.map +1 -1
  18. package/esm/main/index.js +51 -202
  19. package/esm/main/index.js.map +1 -1
  20. package/esm/main/resource-cache.d.ts +245 -0
  21. package/esm/main/resource-cache.d.ts.map +1 -0
  22. package/esm/main/resource-cache.js +857 -0
  23. package/esm/main/resource-cache.js.map +1 -0
  24. package/esm/main/shortcut.d.ts +14 -0
  25. package/esm/main/shortcut.d.ts.map +1 -0
  26. package/esm/main/shortcut.js +173 -0
  27. package/esm/main/shortcut.js.map +1 -0
  28. package/esm/main/store.d.ts +10 -0
  29. package/esm/main/store.d.ts.map +1 -0
  30. package/esm/main/store.js +62 -0
  31. package/esm/main/store.js.map +1 -0
  32. package/esm/main/video-downloader.d.ts +39 -0
  33. package/esm/main/video-downloader.d.ts.map +1 -0
  34. package/esm/main/video-downloader.js +505 -0
  35. package/esm/main/video-downloader.js.map +1 -0
  36. package/esm/preload/index.js +19 -1
  37. package/esm/preload/index.js.map +1 -1
  38. package/esm/renderer/index.d.ts +8 -0
  39. package/esm/renderer/index.d.ts.map +1 -1
  40. package/esm/renderer/index.js +25 -0
  41. package/esm/renderer/index.js.map +1 -1
  42. package/main/clipboard.d.ts +32 -0
  43. package/main/clipboard.d.ts.map +1 -0
  44. package/main/clipboard.js +1208 -0
  45. package/main/clipboard.js.map +1 -0
  46. package/main/downloader.d.ts +212 -0
  47. package/main/downloader.d.ts.map +1 -0
  48. package/main/downloader.js +674 -0
  49. package/main/downloader.js.map +1 -0
  50. package/main/index.d.ts +20 -67
  51. package/main/index.d.ts.map +1 -1
  52. package/main/index.js +54 -205
  53. package/main/index.js.map +1 -1
  54. package/main/resource-cache.d.ts +245 -0
  55. package/main/resource-cache.d.ts.map +1 -0
  56. package/main/resource-cache.js +857 -0
  57. package/main/resource-cache.js.map +1 -0
  58. package/main/shortcut.d.ts +14 -0
  59. package/main/shortcut.d.ts.map +1 -0
  60. package/main/shortcut.js +173 -0
  61. package/main/shortcut.js.map +1 -0
  62. package/main/store.d.ts +10 -0
  63. package/main/store.d.ts.map +1 -0
  64. package/main/store.js +64 -0
  65. package/main/store.js.map +1 -0
  66. package/main/video-downloader.d.ts +39 -0
  67. package/main/video-downloader.d.ts.map +1 -0
  68. package/main/video-downloader.js +510 -0
  69. package/main/video-downloader.js.map +1 -0
  70. package/package.json +9 -5
  71. package/preload/index.js +19 -1
  72. package/preload/index.js.map +1 -1
  73. package/renderer/index.d.ts +8 -0
  74. package/renderer/index.d.ts.map +1 -1
  75. package/renderer/index.js +25 -0
  76. package/renderer/index.js.map +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"downloader.js","sources":["../src/src/main/downloader.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport mime from 'mime-types';\nimport { DownloaderHelper } from 'node-downloader-helper';\nimport { ipcMain, dialog, BrowserWindow, app } from 'electron';\n\n/**\n * 最大重定向次数\n */\nconst MAX_REDIRECTS = 5;\n\n/**\n * 默认文件扩展名\n */\nconst DEFAULT_EXT = '.bin';\n\n/**\n * 默认 MIME 类型\n */\nconst DEFAULT_MIME_TYPE = 'application/octet-stream';\n\n/**\n * 默认超时时间(毫秒):10 分钟\n */\nconst DEFAULT_TIMEOUT = 600000;\n\n/**\n * 默认重试配置\n */\nconst DEFAULT_RETRY = {\n maxRetries: 3,\n delay: 1000\n};\n\n/**\n * 默认文件名\n */\nconst DEFAULT_FILENAME = 'download';\n\n/**\n * 最大文件名计数器(防止无限循环)\n */\nconst MAX_FILENAME_COUNTER = 10000;\n\n/**\n * 下载进度回调函数类型\n */\nexport type DownloadProgressCallback = (progress: {\n url: string; // 正在下载的 URL\n downloaded: number; // 已下载字节数\n total: number; // 总字节数(如果服务器提供 Content-Length)\n percentage: number; // 下载进度百分比 (0-100),如果 total 未知则为 -1\n speed: number; // 下载速度(字节/秒)\n}) => void;\n\n/**\n * 下载选项\n */\nexport interface DownloadOptions {\n /** 唯一标识(IPC 调用时必需) */\n id?: string;\n /** 输出文件路径(可选,如果不提供则使用 URL 的文件名) */\n outputPath?: string;\n /** 输出目录(可选,如果不提供则使用当前目录) */\n outputDir?: string;\n /** 输出文件名(可选,如果不提供则从 URL 提取) */\n fileName?: string;\n /** 是否覆盖已存在的文件(默认 true) */\n override?: boolean;\n /** 是否弹窗选择保存路径(默认 false) */\n showSaveDialog?: boolean;\n /** 保存对话框的默认文件名(可选) */\n defaultPath?: string;\n /** 超时时间(毫秒,默认 10 分钟) */\n timeout?: number;\n /** 重试配置 */\n retry?: {\n maxRetries?: number;\n delay?: number;\n };\n /** 下载进度回调函数(可选) */\n onProgress?: DownloadProgressCallback;\n /** 下载完成回调函数(可选) */\n onComplete?: (filePath: string) => void;\n /** 下载错误回调函数(可选) */\n onError?: (error: Error) => void;\n /** HTTP 请求选项 */\n httpRequestOptions?: {\n headers?: Record<string, string>;\n followRedirect?: boolean;\n maxRedirects?: number;\n };\n}\n\n/**\n * 下载结果\n */\nexport interface DownloadResult {\n /** 是否成功 */\n success: boolean;\n /** 下载的文件路径 */\n filePath?: string;\n /** 错误信息 */\n error?: string;\n /** 文件大小(字节) */\n size?: number;\n}\n\n/**\n * 下载器类:提供文件下载功能\n */\nclass Downloader {\n /** 正在下载的 URL 集合(避免重复下载) */\n private _downloadingUrls = new Map<string, DownloaderHelper>();\n /** 上一次选择的保存文件夹路径 */\n private _lastSelectedDir: string | null = null;\n\n constructor() {\n ipcMain.handle(`core:downloader`, async (event: Electron.IpcMainInvokeEvent, options: DownloadOptions & { url: string; id: string }) => {\n try {\n const { id, url } = options;\n const sender = event.sender as Electron.WebContents;\n\n // 创建进度回调,通过 IPC 发送进度更新\n const progressCallback: DownloadProgressCallback = (progress) => {\n try {\n if (sender && typeof sender.send === 'function') {\n sender.send(`core:downloader:progress`, {\n id,\n data: progress\n });\n }\n } catch (error) {\n console.error('发送下载进度失败:', error);\n }\n };\n\n const result = await this.download(url, options, progressCallback);\n return result;\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : '未知错误'\n };\n }\n });\n }\n\n /**\n * 下载文件\n * @param url 要下载的 URL\n * @param options 下载选项\n * @param onProgress 进度回调函数(可选,优先级高于 options.onProgress)\n * @returns Promise<DownloadResult> 下载结果\n */\n public async download(\n url: string,\n options: DownloadOptions = {},\n onProgress?: DownloadProgressCallback\n ): Promise<DownloadResult> {\n // 生成唯一标识:URL + ID(如果存在)\n const downloadKey = this._getDownloadKey(url, options.id);\n\n // 检查是否正在下载,避免重复下载\n if (this._downloadingUrls.has(downloadKey)) {\n return this._createErrorResult(`资源正在下载中: ${url}${options.id ? ` (ID: ${options.id})` : ''}`);\n }\n\n // 合并进度回调:优先使用传入的 onProgress,其次使用 options.onProgress\n const progressCallback = onProgress || options.onProgress;\n\n // 先检查是否是 base64 data URL(用于确定默认扩展名)\n const base64Info = this._isBase64DataUrl(url);\n const defaultExt = base64Info.isBase64 && base64Info.ext ? base64Info.ext : undefined;\n\n // 确定输出路径\n let outputPath: string;\n try {\n if (options.showSaveDialog) {\n const savePath = await this._showSaveDialog(url, options, defaultExt);\n if (!savePath) {\n return this._createErrorResult('用户取消了保存操作');\n }\n outputPath = savePath;\n } else {\n outputPath = this._resolveOutputPath(url, options, defaultExt);\n }\n } catch (error) {\n return this._createErrorResult(\n error instanceof Error ? error.message : '确定输出路径失败'\n );\n }\n\n // 准备输出路径(确保目录存在、检查文件是否已存在)\n const pathCheckResult = await this._prepareOutputPath(outputPath, options);\n if (pathCheckResult) {\n return pathCheckResult;\n }\n\n const downloadDir = path.dirname(outputPath);\n let downloadFileName = path.basename(outputPath);\n\n // 再次清理文件名,确保不包含 query 参数和特殊字符\n downloadFileName = this._cleanFileName(downloadFileName);\n\n // 更新 outputPath 使用清理后的文件名\n outputPath = path.join(downloadDir, downloadFileName);\n\n // 如果是 base64 data URL,使用已确定的输出路径进行处理\n if (base64Info.isBase64 && base64Info.ext && base64Info.mimeType && base64Info.data) {\n return await this._handleBase64Download(\n url,\n { ext: base64Info.ext, mimeType: base64Info.mimeType, data: base64Info.data },\n outputPath,\n options,\n progressCallback\n );\n }\n\n // 使用临时文件下载,避免下载中断时文件不完整\n const tempFilePath = path.join(downloadDir, downloadFileName + '.cache');\n\n return new Promise<DownloadResult>((resolve, reject) => {\n // 创建下载器实例\n const dl = new DownloaderHelper(url, downloadDir, {\n fileName: downloadFileName + '.cache',\n retry: {\n maxRetries: options.retry?.maxRetries ?? DEFAULT_RETRY.maxRetries,\n delay: options.retry?.delay ?? DEFAULT_RETRY.delay\n },\n timeout: options.timeout ?? DEFAULT_TIMEOUT,\n override: true, // 临时文件总是覆盖\n httpRequestOptions: {\n followRedirect: options.httpRequestOptions?.followRedirect ?? true,\n maxRedirects: options.httpRequestOptions?.maxRedirects ?? MAX_REDIRECTS,\n headers: options.httpRequestOptions?.headers\n }\n });\n\n // 记录正在下载的 URL(使用 URL + ID 作为 key)\n this._downloadingUrls.set(downloadKey, dl);\n\n // 监听下载进度\n if (progressCallback) {\n dl.on('progress', (stats) => {\n try {\n progressCallback({\n url,\n downloaded: stats.downloaded || 0,\n total: stats.total || 0,\n percentage: stats.progress !== undefined ? Math.round(stats.progress) : -1,\n speed: stats.speed || 0\n });\n } catch (error) {\n // 忽略回调中的错误,避免影响下载\n console.error('进度回调执行失败:', error);\n }\n });\n }\n\n // 监听下载完成\n dl.on('end', () => {\n this._downloadingUrls.delete(downloadKey);\n // 将临时文件重命名为最终文件\n fs.rename(tempFilePath, outputPath, (renameErr) => {\n if (renameErr) {\n const error = new Error(`文件重命名失败 from ${tempFilePath} to ${outputPath}: ${renameErr.message}`);\n if (options.onError) {\n options.onError(error);\n }\n reject(error);\n } else {\n // 获取文件大小并返回结果\n const stats = fs.statSync(outputPath);\n const result = this._createSuccessResult(outputPath, stats.size);\n if (options.onComplete) {\n options.onComplete(outputPath);\n }\n resolve(result);\n }\n });\n });\n\n // 统一的错误处理函数\n const handleError = (error: Error) => {\n this._downloadingUrls.delete(downloadKey);\n // 清理临时文件\n fs.promises.unlink(tempFilePath).catch(() => {\n // 忽略删除失败\n });\n if (options.onError) {\n options.onError(error);\n }\n reject(error);\n };\n\n // 监听下载错误\n dl.on('error', (err) => {\n const error = err instanceof Error ? err : new Error(`下载失败: ${url}`);\n handleError(error);\n });\n\n // 监听下载停止(取消)\n dl.on('stop', () => {\n const error = new Error(`下载已停止: ${url}`);\n handleError(error);\n });\n\n // 开始下载\n dl.start().catch((err) => {\n const error = err instanceof Error ? err : new Error(`启动下载失败: ${url}`);\n handleError(error);\n });\n }).catch((error): DownloadResult => {\n return this._createErrorResult(error instanceof Error ? error.message : '未知错误');\n });\n }\n\n /**\n * 生成下载任务的唯一标识\n * @param url 下载 URL\n * @param id 可选的任务 ID\n * @returns 唯一标识\n */\n private _getDownloadKey(url: string, id?: string): string {\n return id ? `${url}::${id}` : url;\n }\n\n /**\n * 取消下载\n * @param url 要取消的 URL\n * @param id 可选的任务 ID\n * @returns 是否成功取消\n */\n public cancel(url: string, id?: string): boolean {\n const downloadKey = this._getDownloadKey(url, id);\n const dl = this._downloadingUrls.get(downloadKey);\n if (dl) {\n dl.stop();\n this._downloadingUrls.delete(downloadKey);\n return true;\n }\n return false;\n }\n\n /**\n * 取消所有正在进行的下载\n */\n public cancelAll(): void {\n for (const [url, dl] of this._downloadingUrls.entries()) {\n dl.stop();\n }\n this._downloadingUrls.clear();\n }\n\n /**\n * 检查指定 URL 是否正在下载\n * @param url 要检查的 URL\n * @param id 可选的任务 ID\n * @returns 是否正在下载\n */\n public isDownloading(url: string, id?: string): boolean {\n const downloadKey = this._getDownloadKey(url, id);\n return this._downloadingUrls.has(downloadKey);\n }\n\n /**\n * 获取正在下载的任务列表\n * @returns 正在下载的任务信息数组,包含 URL 和 ID(如果有)\n */\n public getDownloadingUrls(): Array<{ url: string; id?: string }> {\n return Array.from(this._downloadingUrls.keys()).map(key => {\n const parts = key.split('::');\n if (parts.length === 2 && parts[0] && parts[1]) {\n return { url: parts[0], id: parts[1] };\n }\n return { url: key };\n });\n }\n\n /**\n * 获取文件名(统一处理所有来源)\n * @param url 下载 URL\n * @param options 下载选项\n * @param defaultExt 默认扩展名(可选,用于 base64 URL)\n * @returns 清理后的文件名\n */\n private _getFileName(url: string, options: DownloadOptions, defaultExt?: string): string {\n // 优先级:defaultPath > fileName > defaultExt > URL提取\n if (options.defaultPath) {\n return this._cleanFileName(path.basename(options.defaultPath));\n }\n\n if (options.fileName) {\n return this._cleanFileName(options.fileName);\n }\n\n if (defaultExt) {\n return this._cleanFileName(`${DEFAULT_FILENAME}.${defaultExt}`);\n }\n // 从 URL 中提取文件名(_extractFileNameFromUrl 已经包含清理逻辑)\n return this._extractFileNameFromUrl(url);\n }\n\n /**\n * 显示保存对话框\n * @param url 下载 URL\n * @param options 下载选项\n * @param defaultExt 默认扩展名(可选,用于 base64 URL)\n * @returns Promise<string | null> 用户选择的保存路径,如果取消则返回 null\n */\n private async _showSaveDialog(url: string, options: DownloadOptions, defaultExt?: string): Promise<string | null> {\n // 获取并清理默认文件名\n let defaultFileName = this._getFileName(url, options, defaultExt);\n\n // 获取默认目录\n let defaultDir: string | undefined;\n if (options.defaultPath) {\n defaultDir = path.dirname(options.defaultPath);\n } else if (options.outputDir) {\n defaultDir = path.resolve(options.outputDir);\n } else {\n // 如果没有指定目录,使用上一次选择的文件夹,如果没有则使用下载目录\n defaultDir = this._lastSelectedDir || app.getPath('downloads');\n }\n\n // 如果指定了目录,检查文件是否存在并生成唯一文件名\n if (defaultDir) {\n defaultFileName = this._generateUniqueFileName(defaultDir, defaultFileName);\n }\n\n // 构建默认路径\n const defaultPath = defaultDir ? path.join(defaultDir, defaultFileName) : defaultFileName;\n\n // 获取当前活动的 BrowserWindow\n const focusedWindow = BrowserWindow.getFocusedWindow();\n const allWindows = BrowserWindow.getAllWindows();\n const parentWindow = focusedWindow || (allWindows.length > 0 ? allWindows[0] : undefined);\n\n // 显示保存对话框\n const dialogOptions = {\n defaultPath,\n title: '保存文件',\n buttonLabel: '保存',\n filters: [\n // 尝试从文件名推断文件类型\n ...(path.extname(defaultFileName) ? [{\n name: '所有文件',\n extensions: ['*']\n }] : [])\n ]\n };\n\n // 根据是否有父窗口调用不同的方法\n const result = parentWindow\n ? await dialog.showSaveDialog(parentWindow, dialogOptions)\n : await dialog.showSaveDialog(dialogOptions);\n\n if (result.canceled || !result.filePath) {\n return null;\n }\n\n // 记录用户选择的文件夹路径,用于下次默认使用\n const selectedDir = path.dirname(result.filePath);\n if (selectedDir) {\n this._lastSelectedDir = selectedDir;\n }\n\n return result.filePath;\n }\n\n /**\n * 检测并处理 base64 data URL\n * @param url 资源URL\n * @returns 如果是 base64 URL,返回 true、文件扩展名、MIME 类型和数据;否则返回 false\n */\n private _isBase64DataUrl(url: string): { isBase64: boolean, ext?: string, mimeType?: string, data?: string } {\n if (!url.startsWith('data:')) {\n return { isBase64: false };\n }\n\n try {\n // 解析 data URL 格式:data:[<mediatype>][;base64],<data>\n const commaIndex = url.indexOf(',');\n if (commaIndex === -1) {\n return { isBase64: false };\n }\n\n const header = url.substring(0, commaIndex);\n const data = url.substring(commaIndex + 1);\n\n // 检查是否包含 base64 标识\n if (!header.includes('base64')) {\n return { isBase64: false };\n }\n\n // 从 mediatype 中提取文件扩展名和 MIME 类型\n // 例如:data:image/png;base64 -> png, image/png\n // 例如:data:image/jpeg;base64 -> jpeg, image/jpeg\n let ext = DEFAULT_EXT.replace(/^\\./, '');\n let mimeType = DEFAULT_MIME_TYPE;\n const mimeMatch = header.match(/data:([^;]+)/);\n if (mimeMatch && mimeMatch[1]) {\n mimeType = mimeMatch[1];\n // 使用 mime-types 包从 MIME 类型获取扩展名\n const extension = mime.extension(mimeType);\n if (extension) {\n ext = extension;\n }\n }\n\n return { isBase64: true, ext, mimeType, data };\n } catch (error) {\n return { isBase64: false };\n }\n }\n\n /**\n * 保存 base64 数据到文件\n * @param base64Data base64 编码的数据\n * @param filePath 目标文件路径\n */\n private async _saveBase64ToFile(base64Data: string, filePath: string): Promise<void> {\n try {\n // 解码 base64 数据\n const buffer = Buffer.from(base64Data, 'base64');\n\n // 使用 Promise 版本的 writeFile\n // Buffer 继承自 Uint8Array,可以直接使用\n await fs.promises.writeFile(filePath, buffer as Uint8Array);\n } catch (error) {\n throw new Error(`保存 base64 文件失败: ${error instanceof Error ? error.message : '未知错误'}`);\n }\n }\n\n /**\n * 准备输出路径(确保目录存在、检查文件是否已存在)\n * @param outputPath 输出路径\n * @param options 下载选项\n * @returns 如果文件已存在且不允许覆盖,返回结果;否则返回 null\n */\n private async _prepareOutputPath(\n outputPath: string,\n options: DownloadOptions\n ): Promise<DownloadResult | null> {\n const downloadDir = path.dirname(outputPath);\n\n // 确保目录存在\n if (!fs.existsSync(downloadDir)) {\n fs.mkdirSync(downloadDir, { recursive: true });\n }\n\n // 如果文件已存在且不允许覆盖,直接返回\n if (fs.existsSync(outputPath) && !(options.override ?? true)) {\n const stats = fs.statSync(outputPath);\n return this._createSuccessResult(outputPath, stats.size);\n }\n\n return null;\n }\n\n /**\n * 创建成功结果\n * @param filePath 文件路径\n * @param size 文件大小\n * @returns DownloadResult\n */\n private _createSuccessResult(filePath: string, size: number): DownloadResult {\n return {\n success: true,\n filePath,\n size\n };\n }\n\n /**\n * 创建错误结果\n * @param error 错误信息\n * @returns DownloadResult\n */\n private _createErrorResult(error: string): DownloadResult {\n return {\n success: false,\n error\n };\n }\n\n /**\n * 处理 base64 data URL 的下载\n * @param url base64 data URL\n * @param base64Info base64 信息\n * @param outputPath 已确定的输出路径\n * @param options 下载选项\n * @param progressCallback 进度回调\n * @returns Promise<DownloadResult> 下载结果\n */\n private async _handleBase64Download(\n url: string,\n base64Info: { ext: string; mimeType: string; data: string },\n outputPath: string,\n options: DownloadOptions,\n progressCallback?: DownloadProgressCallback\n ): Promise<DownloadResult> {\n if (!base64Info.data || !base64Info.ext) {\n return this._createErrorResult(`无效的 base64 data URL: ${url}`);\n }\n\n try {\n // 模拟进度回调(base64 数据通常很小,立即完成)\n if (progressCallback) {\n const dataLength = Buffer.from(base64Info.data, 'base64').length;\n progressCallback({\n url,\n downloaded: dataLength,\n total: dataLength,\n percentage: 100,\n speed: 0\n });\n }\n\n // 保存 base64 数据到文件\n await this._saveBase64ToFile(base64Info.data, outputPath);\n\n // 获取文件大小\n const stats = fs.statSync(outputPath);\n const result = this._createSuccessResult(outputPath, stats.size);\n\n if (options.onComplete) {\n options.onComplete(outputPath);\n }\n\n return result;\n } catch (error) {\n const err = error instanceof Error ? error : new Error('保存 base64 文件失败');\n if (options.onError) {\n options.onError(err);\n }\n return this._createErrorResult(err.message);\n }\n }\n\n /**\n * 生成唯一的文件名(如果文件已存在,添加数字后缀)\n * @param dir 目录路径\n * @param fileName 原始文件名\n * @returns 唯一的文件名\n */\n private _generateUniqueFileName(dir: string, fileName: string): string {\n // 分离文件名和扩展名\n const ext = path.extname(fileName);\n const nameWithoutExt = path.basename(fileName, ext);\n\n // 检查原始文件名是否存在\n const originalPath = path.join(dir, fileName);\n if (!fs.existsSync(originalPath)) {\n return fileName;\n }\n\n // 如果存在,尝试添加数字后缀\n let counter = 1;\n let newFileName: string;\n let newPath: string;\n\n do {\n newFileName = `${nameWithoutExt}(${counter})${ext}`;\n newPath = path.join(dir, newFileName);\n counter++;\n } while (fs.existsSync(newPath) && counter < MAX_FILENAME_COUNTER);\n\n return newFileName;\n }\n\n /**\n * 清理文件名,移除 query 参数和特殊字符\n * @param fileName 原始文件名\n * @returns 清理后的文件名\n */\n private _cleanFileName(fileName: string): string {\n if (!fileName || fileName.length === 0) {\n return DEFAULT_FILENAME;\n }\n\n // 移除 query 参数(如果文件名中包含 ?)\n const queryIndex = fileName.indexOf('?');\n if (queryIndex !== -1) {\n fileName = fileName.substring(0, queryIndex);\n }\n\n // 解码 URL 编码的字符(如 %20 -> 空格)\n try {\n fileName = decodeURIComponent(fileName);\n } catch {\n // 如果解码失败,使用原始文件名\n }\n\n // 清理文件名中的特殊字符(文件系统不允许的字符)\n // 移除或替换:/ \\ : * ? \" < > |\n fileName = fileName.replace(/[/\\\\:*?\"<>|]/g, '_');\n\n // 移除前后空格和点号(Windows 不允许)\n fileName = fileName.trim().replace(/^\\.+|\\.+$/g, '');\n\n // 如果清理后文件名为空,使用默认文件名\n if (!fileName || fileName.length === 0) {\n fileName = DEFAULT_FILENAME;\n }\n\n return fileName;\n }\n\n /**\n * 从 URL 中提取文件名\n * @param url 下载 URL\n * @returns 文件名(已清理特殊字符,不包含query参数)\n */\n private _extractFileNameFromUrl(url: string): string {\n if (!url || typeof url !== 'string' || url.trim().length === 0) {\n return `${DEFAULT_FILENAME}${DEFAULT_EXT}`;\n }\n\n try {\n // 确保 URL 是完整的(如果缺少协议,添加 https://)\n let normalizedUrl = url.trim();\n if (!normalizedUrl.match(/^https?:\\/\\//i)) {\n normalizedUrl = `https://${normalizedUrl}`;\n }\n\n const urlObj = new URL(normalizedUrl);\n\n // 验证 pathname 是否有效\n if (!urlObj.pathname || urlObj.pathname === '/' || urlObj.pathname.length === 0) {\n return `${DEFAULT_FILENAME}${DEFAULT_EXT}`;\n }\n\n // 只使用 pathname 部分,确保不包含 query 参数\n let fileName = path.basename(urlObj.pathname);\n\n // 如果 pathname 以 / 结尾或 basename 为空,尝试从路径中提取\n if (!fileName || fileName === '/' || fileName.length === 0) {\n // 移除首尾的斜杠,然后取最后一部分\n const pathParts = urlObj.pathname.replace(/^\\/+|\\/+$/g, '').split('/');\n fileName = pathParts[pathParts.length - 1] || DEFAULT_FILENAME;\n }\n\n // 如果还是没有有效的文件名,使用默认值\n if (!fileName || fileName === '/' || fileName.length === 0) {\n return `${DEFAULT_FILENAME}${DEFAULT_EXT}`;\n }\n\n // 解码 URL 编码的字符(如 %20 -> 空格)\n try {\n fileName = decodeURIComponent(fileName);\n } catch {\n // 如果解码失败,使用原始文件名\n }\n\n // 清理文件名中的特殊字符(文件系统不允许的字符)\n // 移除或替换:/ \\ : * ? \" < > |\n fileName = fileName.replace(/[/\\\\:*?\"<>|]/g, '_');\n\n // 移除前后空格和点号(Windows 不允许)\n fileName = fileName.trim().replace(/^\\.+|\\.+$/g, '');\n\n // 如果清理后文件名为空,使用默认文件名\n if (!fileName || fileName.length === 0) {\n fileName = DEFAULT_FILENAME;\n }\n\n // 确保有扩展名\n return path.extname(fileName) ? fileName : `${fileName}${DEFAULT_EXT}`;\n } catch (error) {\n // URL 解析失败,尝试手动提取\n try {\n // 移除 query 参数和 hash\n const urlWithoutQuery = url.split('?')[0];\n const cleanUrl = urlWithoutQuery ? urlWithoutQuery.split('#')[0] : url;\n if (cleanUrl) {\n // 尝试提取最后一个路径段\n const match = cleanUrl.match(/\\/([^\\/]+)$/);\n if (match && match[1]) {\n let fileName = match[1];\n // 清理文件名\n fileName = fileName.replace(/[/\\\\:*?\"<>|]/g, '_');\n fileName = fileName.trim().replace(/^\\.+|\\.+$/g, '');\n if (fileName && fileName.length > 0) {\n return path.extname(fileName) ? fileName : `${fileName}${DEFAULT_EXT}`;\n }\n }\n }\n } catch {\n // 忽略手动提取的错误\n }\n return `${DEFAULT_FILENAME}${DEFAULT_EXT}`;\n }\n }\n\n /**\n * 解析输出路径\n * @param url 下载 URL\n * @param options 下载选项\n * @param defaultExt 默认扩展名(可选,用于 base64 URL)\n * @returns 输出文件路径\n */\n private _resolveOutputPath(url: string, options: DownloadOptions, defaultExt?: string): string {\n // 如果提供了完整路径,直接使用(但需要清理文件名部分)\n if (options.outputPath) {\n const dir = path.dirname(options.outputPath);\n const fileName = this._cleanFileName(path.basename(options.outputPath));\n return path.resolve(path.join(dir, fileName));\n }\n\n // 确定输出目录:优先使用指定的目录,否则使用 Electron 的下载目录\n const outputDir = options.outputDir\n ? path.resolve(options.outputDir)\n : app.getPath('downloads');\n\n // 使用统一的文件名获取方法\n const fileName = this._getFileName(url, options, defaultExt);\n\n return path.join(outputDir, fileName);\n }\n}\n\n/**\n * 默认下载器实例(单例)\n */\nlet defaultDownloader: Downloader | null = null;\n\n/**\n * 获取默认下载器实例\n * @returns Downloader 实例\n */\nexport function getDownloader(): Downloader {\n if (!defaultDownloader) {\n defaultDownloader = new Downloader();\n }\n return defaultDownloader;\n}\n\n/**\n * 下载文件的便捷函数\n * @param url 要下载的 URL\n * @param options 下载选项\n * @param onProgress 进度回调函数(可选)\n * @returns Promise<DownloadResult> 下载结果\n */\nexport async function downloadFile(\n url: string,\n options: DownloadOptions = {},\n onProgress?: DownloadProgressCallback\n): Promise<DownloadResult> {\n const downloader = getDownloader();\n return downloader.download(url, options, onProgress);\n}\n\n"],"names":["ipcMain","DownloaderHelper","app","BrowserWindow","dialog"],"mappings":"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"}
package/main/index.d.ts CHANGED
@@ -1,12 +1,29 @@
1
1
  import type { WebContents } from 'electron';
2
2
  import * as ipc from '@lynker-desktop/electron-ipc/main';
3
3
  import * as windowManager from '@lynker-desktop/electron-window-manager/main';
4
- import { type ServeOptions } from '../common';
4
+ import type { PreloadWebContentsConfig } from '@lynker-desktop/electron-window-manager/common';
5
+ import { type ServeOptions, type VideoDownloadOptions, type VideoProgressCallback, type VideoDownloadResult } from '../common';
6
+ import { ResourceCache, type ResourceCacheOptions } from './resource-cache';
7
+ import type ElectronStore from 'electron-store';
8
+ export { ResourceCache, type ResourceCacheOptions };
5
9
  export declare let isInitialized: boolean;
6
10
  export interface SDK_TYPE {
7
11
  ipc: typeof ipc.mainIPC;
8
12
  windowManager: windowManager.WindowsManager;
9
13
  getPreload: () => string;
14
+ downloadVideo: (options: VideoDownloadOptions, callbacks?: VideoProgressCallback) => Promise<VideoDownloadResult>;
15
+ clearVideoCache: (outputDir: string) => void;
16
+ getVideoCacheStats: (outputDir: string) => {
17
+ size: number;
18
+ entries: Array<{
19
+ fileName: string;
20
+ filePath: string;
21
+ fileSize: number;
22
+ mtime: number;
23
+ }>;
24
+ };
25
+ removeVideoCache: (options: VideoDownloadOptions) => boolean;
26
+ getAppStore: (name: string) => ElectronStore;
10
27
  }
11
28
  /**
12
29
  * 初始化
@@ -20,10 +37,11 @@ export declare const initialize: (options: {
20
37
  preload: string;
21
38
  loadingViewUrl?: string;
22
39
  errorViewUrl?: string;
23
- preloadWebContentsUrl?: string;
40
+ preloadWebContentsConfig?: PreloadWebContentsConfig;
24
41
  webviewDomainWhiteList?: string[];
25
42
  serveOptions?: ServeOptions;
26
43
  resourceCacheOptions?: ResourceCacheOptions;
44
+ ffmpegPath?: string;
27
45
  }) => SDK_TYPE;
28
46
  /** 后续再优化 */
29
47
  export declare const getSDK: () => SDK_TYPE;
@@ -37,71 +55,6 @@ export declare const registerProtocol: (protocol: string) => void;
37
55
  * @returns
38
56
  */
39
57
  export declare const serve: (options: ServeOptions) => Promise<unknown>;
40
- /**
41
- * 资源缓存配置项
42
- */
43
- export interface ResourceCacheOptions {
44
- /** 缓存目录,必填 */
45
- cacheDir: string;
46
- /** 缓存有效期(毫秒),默认24小时 */
47
- cacheTTL?: number;
48
- /** 匹配需要缓存的资源,支持正则或函数 */
49
- match?: RegExp | ((url: string) => boolean);
50
- /** 允许缓存的资源来源,支持null/数组/函数 */
51
- allowedOrigins?: null | string[] | ((url: string) => boolean);
52
- }
53
- /**
54
- * 资源缓存类:拦截并缓存静态资源,提升加载性能
55
- */
56
- export declare class ResourceCache {
57
- static scheme: string;
58
- private cacheHost;
59
- /** Electron session 实例 */
60
- private session;
61
- /** 缓存配置 */
62
- private options;
63
- /**
64
- * 构造函数
65
- * @param session Electron session
66
- * @param options 缓存配置
67
- */
68
- constructor(session: Electron.Session, options: ResourceCacheOptions);
69
- /**
70
- * 获取资源匹配函数
71
- */
72
- private _getMatchFunction;
73
- /**
74
- * 获取来源校验函数
75
- */
76
- private _getOriginAllowFunction;
77
- /**
78
- * 获取缓存文件路径
79
- * @param url 资源URL
80
- */
81
- getCachedPath(url: string): {
82
- filePath: string;
83
- hostPath: string;
84
- };
85
- /**
86
- * 判断缓存是否有效
87
- * @param filePath 缓存文件路径
88
- */
89
- isCacheValid(filePath: string): boolean;
90
- /**
91
- * 下载资源到本地缓存
92
- * @param url 资源URL
93
- * @param filePath 本地缓存路径
94
- */
95
- downloadResource(url: string, filePath: string): void;
96
- /**
97
- * 清理过期缓存文件
98
- */
99
- private _cleanOldCache;
100
- /**
101
- * 注册 Electron 请求拦截器,实现资源缓存
102
- */
103
- private _registerInterceptor;
104
- }
105
58
  /**
106
59
  * @electron/remote/main enable方法
107
60
  * @param webContents
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/main/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAW3C,OAAO,KAAK,GAAG,MAAM,mCAAmC,CAAA;AAExD,OAAO,KAAK,aAAa,MAAM,8CAA8C,CAAA;AAC7E,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAMnE,eAAO,IAAI,aAAa,SAAQ,CAAC;AAEjC,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IACxB,aAAa,EAAE,aAAa,CAAC,cAAc,CAAC;IAC5C,UAAU,EAAE,MAAM,MAAM,CAAC;CAC1B;AAkBD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,YAAa;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAAC,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAAC,oBAAoB,CAAC,EAAE,oBAAoB,CAAA;CAAE,KAAG,QAoDxQ,CAAA;AAED,YAAY;AACZ,eAAO,MAAM,MAAM,QAAO,QAOzB,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,aAGT,MAAM,SAoDtB,CAAC;AAEL;;;;GAIG;AACH,eAAO,MAAM,KAAK,YAAa,YAAY,qBAsF1C,CAAA;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,cAAc;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,uBAAuB;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC;IAC5C,6BAA6B;IAC7B,cAAc,CAAC,EAAE,IAAI,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC;CAC/D;AAYD;;GAEG;AACH,qBAAa,aAAa;IACxB,MAAM,CAAC,MAAM,SAAe;IAC5B,OAAO,CAAC,SAAS,CAAyC;IAC1D,0BAA0B;IAC1B,OAAO,CAAC,OAAO,CAAmB;IAClC,WAAW;IACX,OAAO,CAAC,OAAO,CAAiC;IAEhD;;;;OAIG;gBACS,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,oBAAoB;IA0BpE;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAOzB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAe/B;;;OAGG;IACI,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;IAWzE;;;OAGG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAM9C;;;;OAIG;IACI,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAsD5D;;OAEG;IACH,OAAO,CAAC,cAAc;IAgBtB;;OAEG;IACH,OAAO,CAAC,oBAAoB;CAyB7B;AAED;;;;GAIG;AACH,eAAO,MAAM,MAAM,gBAAiB,WAAW,SAA+B,CAAC;AAE/E;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,GAAE,MAAwB,GAAG,MAAM,CAiBnE;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,QA7gBF,SACpB,OA4gBuD,CAAC;AAE/D;;;GAGG;;AACH,wBAWG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/main/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAS3C,OAAO,KAAK,GAAG,MAAM,mCAAmC,CAAA;AAExD,OAAO,KAAK,aAAa,MAAM,8CAA8C,CAAA;AAC7E,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,gDAAgD,CAAA;AAC9F,OAAO,EAAuB,KAAK,YAAY,EAAE,KAAK,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,KAAK,mBAAmB,EAAqB,MAAM,WAAW,CAAC;AAIvK,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAG5E,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAGhD,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,CAAC;AAMpD,eAAO,IAAI,aAAa,SAAQ,CAAC;AAEjC,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IACxB,aAAa,EAAE,aAAa,CAAC,cAAc,CAAC;IAC5C,UAAU,EAAE,MAAM,MAAM,CAAC;IACzB,aAAa,EAAE,CAAC,OAAO,EAAE,oBAAoB,EAAE,SAAS,CAAC,EAAE,qBAAqB,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAClH,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,KAAK,CAAC;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC;IACrJ,gBAAgB,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC;IAC7D,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,aAAa,CAAC;CAC9C;AAkBD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,YAAa;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,wBAAwB,CAAC,EAAE,wBAAwB,CAAC;IAAC,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAAC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,QAwFlT,CAAA;AAED,YAAY;AACZ,eAAO,MAAM,MAAM,QAAO,QAOzB,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,aAGT,MAAM,SAoDtB,CAAC;AAEL;;;;GAIG;AACH,eAAO,MAAM,KAAK,YAAa,YAAY,qBAsF1C,CAAA;AAGD;;;;GAIG;AACH,eAAO,MAAM,MAAM,gBAAiB,WAAW,SAA+B,CAAC;AAE/E;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,GAAE,MAAwB,GAAG,MAAM,CAiBnE;AAGD;;GAEG;AACH,eAAO,MAAM,gBAAgB,QA9VwB,SAC7C,OA6VsD,CAAC;AAE/D;;;GAGG;;AACH,wBAeG"}
package/main/index.js CHANGED
@@ -3,8 +3,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
3
3
  const fs = require('node:fs');
4
4
  const path = require('node:path');
5
5
  const node_util = require('node:util');
6
- const http = require('node:http');
7
- const https = require('node:https');
8
6
  const electron = require('electron');
9
7
  const md5 = require('md5');
10
8
  const uuid = require('uuid');
@@ -14,6 +12,12 @@ const ipc = require('@lynker-desktop/electron-ipc/main');
14
12
  const logs = require('@lynker-desktop/electron-logs/main');
15
13
  const windowManager = require('@lynker-desktop/electron-window-manager/main');
16
14
  const index$1 = require('../common/index.js');
15
+ const store = require('./store.js');
16
+ const clipboard = require('./clipboard.js');
17
+ const shortcut = require('./shortcut.js');
18
+ const resourceCache = require('./resource-cache.js');
19
+ const videoDownloader = require('./video-downloader.js');
20
+ const downloader = require('./downloader.js');
17
21
 
18
22
  function _interopNamespaceDefault(e) {
19
23
  const n = Object.create(null);
@@ -56,7 +60,7 @@ function findWebContentsByPid(pid) {
56
60
  * @returns
57
61
  */
58
62
  const initialize = (options) => {
59
- let { protocol, preload, loadingViewUrl, serveOptions = [], errorViewUrl, preloadWebContentsUrl, webviewDomainWhiteList, resourceCacheOptions } = options;
63
+ let { protocol, preload, loadingViewUrl, serveOptions = [], errorViewUrl, preloadWebContentsConfig, webviewDomainWhiteList, resourceCacheOptions } = options;
60
64
  if (exports.isInitialized) {
61
65
  // @ts-ignore
62
66
  return global['__GLBOAL_ELECTRON_SDK__'];
@@ -64,7 +68,13 @@ const initialize = (options) => {
64
68
  exports.isInitialized = true;
65
69
  ipc__namespace.initialize();
66
70
  logs__namespace.initialize();
67
- const wm = windowManager__namespace.initialize(preload, loadingViewUrl, errorViewUrl, preloadWebContentsUrl, webviewDomainWhiteList || []);
71
+ store.initializeStore();
72
+ clipboard.initializeClipboard();
73
+ shortcut.initializeShortcut();
74
+ if (options.ffmpegPath) {
75
+ videoDownloader.setFFmpegPath(options.ffmpegPath);
76
+ }
77
+ const wm = windowManager__namespace.initialize(preload, loadingViewUrl, errorViewUrl, preloadWebContentsConfig, webviewDomainWhiteList || []);
68
78
  if (protocol) {
69
79
  registerProtocol(protocol);
70
80
  }
@@ -74,7 +84,7 @@ const initialize = (options) => {
74
84
  if (resourceCacheOptions) {
75
85
  if (resourceCacheOptions.cacheDir) {
76
86
  serveOptions.push({
77
- scheme: ResourceCache.scheme,
87
+ scheme: resourceCache.ResourceCache.scheme,
78
88
  directory: resourceCacheOptions.cacheDir,
79
89
  });
80
90
  }
@@ -84,7 +94,7 @@ const initialize = (options) => {
84
94
  }
85
95
  if (resourceCacheOptions) {
86
96
  electron.app.on('ready', () => {
87
- new ResourceCache(electron.session.defaultSession, resourceCacheOptions);
97
+ new resourceCache.ResourceCache(electron.session.defaultSession, resourceCacheOptions);
88
98
  });
89
99
  }
90
100
  class SDK {
@@ -92,6 +102,12 @@ const initialize = (options) => {
92
102
  SDK.ipc = ipc__namespace.mainIPC;
93
103
  SDK.windowManager = wm;
94
104
  SDK.getPreload = () => preload;
105
+ SDK.downloader = downloader.getDownloader();
106
+ SDK.downloadVideo = videoDownloader.downloadVideo;
107
+ SDK.clearVideoCache = videoDownloader.clearVideoCache;
108
+ SDK.getVideoCacheStats = videoDownloader.getVideoCacheStats;
109
+ SDK.removeVideoCache = videoDownloader.removeVideoCache;
110
+ SDK.getAppStore = store.getAppStore;
95
111
  ipc__namespace.mainIPC.handleRenderer(index$1.IPC_GET_APP_METRICS, async () => {
96
112
  const metrics = electron.app.getAppMetrics().map(i => {
97
113
  const webContents = findWebContentsByPid(i.pid || 0);
@@ -104,6 +120,30 @@ const initialize = (options) => {
104
120
  });
105
121
  return JSON.stringify(metrics);
106
122
  });
123
+ ipc__namespace.mainIPC.handleRenderer(`__sdk_transcode_video__`, async (options) => {
124
+ const md5Options = md5(JSON.stringify(options.url));
125
+ videoDownloader.downloadVideo(options, {
126
+ onDownloadProgress: (progress) => {
127
+ ipc__namespace.mainIPC.invokeAllRenderer(`__sdk_transcode_video_callback_${md5Options}__`, {
128
+ type: 'downloadProgress',
129
+ data: progress
130
+ });
131
+ },
132
+ onTranscodeProgress: (progress) => {
133
+ ipc__namespace.mainIPC.invokeAllRenderer(`__sdk_transcode_video_callback_${md5Options}__`, {
134
+ type: 'transcodeProgress',
135
+ data: progress
136
+ });
137
+ },
138
+ onComplete: (result) => {
139
+ ipc__namespace.mainIPC.invokeAllRenderer(`__sdk_transcode_video_callback_${md5Options}__`, {
140
+ type: 'complete',
141
+ data: result
142
+ });
143
+ },
144
+ });
145
+ return true;
146
+ });
107
147
  // @ts-ignore
108
148
  global['__GLBOAL_ELECTRON_SDK__'] = SDK;
109
149
  return SDK;
@@ -260,201 +300,6 @@ const serve = (options) => {
260
300
  }
261
301
  });
262
302
  };
263
- /**
264
- * 默认配置
265
- */
266
- const DEFAULT_OPTIONS = {
267
- cacheDir: '',
268
- cacheTTL: 24 * 60 * 60 * 1000,
269
- match: /\.(png|jpe?g|webp|gif|svg|woff2?|ttf|mp4|webm|ogg|css|js)(\?.*)?$/i,
270
- allowedOrigins: null,
271
- };
272
- /**
273
- * 资源缓存类:拦截并缓存静态资源,提升加载性能
274
- */
275
- class ResourceCache {
276
- /**
277
- * 构造函数
278
- * @param session Electron session
279
- * @param options 缓存配置
280
- */
281
- constructor(session, options) {
282
- this.cacheHost = `${ResourceCache.scheme}://-`;
283
- if (!session)
284
- throw new Error('ResourceCache: session is required');
285
- this.session = session;
286
- // 合并配置,保证类型安全
287
- this.options = {
288
- ...DEFAULT_OPTIONS,
289
- ...options,
290
- cacheDir: options.cacheDir,
291
- cacheTTL: options.cacheTTL ?? DEFAULT_OPTIONS.cacheTTL,
292
- match: options.match ?? DEFAULT_OPTIONS.match,
293
- allowedOrigins: options.allowedOrigins ?? DEFAULT_OPTIONS.allowedOrigins,
294
- };
295
- if (!this.options.cacheDir) {
296
- throw new Error('ResourceCache: cacheDir is required');
297
- }
298
- // 确保缓存目录存在
299
- if (!fs.existsSync(this.options.cacheDir)) {
300
- fs.mkdirSync(this.options.cacheDir, { recursive: true });
301
- }
302
- this._registerInterceptor();
303
- this._cleanOldCache();
304
- }
305
- /**
306
- * 获取资源匹配函数
307
- */
308
- _getMatchFunction() {
309
- const matcher = this.options.match;
310
- if (typeof matcher === 'function')
311
- return matcher;
312
- if (matcher instanceof RegExp)
313
- return (url) => matcher.test(url);
314
- return () => false;
315
- }
316
- /**
317
- * 获取来源校验函数
318
- */
319
- _getOriginAllowFunction() {
320
- const origins = this.options.allowedOrigins;
321
- if (!origins)
322
- return () => true;
323
- if (typeof origins === 'function')
324
- return origins;
325
- const prefixList = origins.map(o => o.toLowerCase());
326
- return (url) => {
327
- try {
328
- const origin = new URL(url).origin.toLowerCase();
329
- return prefixList.some(prefix => origin.startsWith(prefix));
330
- }
331
- catch {
332
- return false;
333
- }
334
- };
335
- }
336
- /**
337
- * 获取缓存文件路径
338
- * @param url 资源URL
339
- */
340
- getCachedPath(url) {
341
- const md5Str = md5(url);
342
- const urlObj = new URL(url);
343
- // 取文件扩展名,若无则用 .res
344
- const ext = path.extname(urlObj.pathname) || '.res';
345
- return {
346
- filePath: path.join(this.options.cacheDir, `${md5Str}${ext}`),
347
- hostPath: `${this.cacheHost}/${md5Str}${ext}`,
348
- };
349
- }
350
- /**
351
- * 判断缓存是否有效
352
- * @param filePath 缓存文件路径
353
- */
354
- isCacheValid(filePath) {
355
- if (!fs.existsSync(filePath))
356
- return false;
357
- const stat = fs.statSync(filePath);
358
- return Date.now() - stat.mtimeMs < this.options.cacheTTL;
359
- }
360
- /**
361
- * 下载资源到本地缓存
362
- * @param url 资源URL
363
- * @param filePath 本地缓存路径
364
- */
365
- downloadResource(url, filePath) {
366
- const tempFilePath = `${filePath}.cache`;
367
- const lib = url.startsWith('https') ? https : http;
368
- const file = fs.createWriteStream(tempFilePath);
369
- let request;
370
- const cleanupAndAbort = (errMsg, err) => {
371
- if (err) {
372
- console.log(errMsg, err);
373
- }
374
- else {
375
- console.log(errMsg);
376
- }
377
- if (request) {
378
- request.destroy();
379
- }
380
- file.close(() => {
381
- // 使用 existsSync 避免在文件不存在时 unlink 抛出错误
382
- if (fs.existsSync(tempFilePath)) {
383
- fs.unlink(tempFilePath, () => { });
384
- }
385
- });
386
- };
387
- request = lib.get(url, (res) => {
388
- if (res.statusCode !== 200) {
389
- res.resume(); // 消费响应数据以释放内存
390
- cleanupAndAbort(`下载失败,状态码: ${res.statusCode} for ${url}`);
391
- return;
392
- }
393
- res.pipe(file);
394
- });
395
- file.on('finish', () => {
396
- file.close((err) => {
397
- if (err) {
398
- return cleanupAndAbort(`关闭临时文件流失败: ${tempFilePath}`, err);
399
- }
400
- fs.rename(tempFilePath, filePath, (renameErr) => {
401
- if (renameErr) {
402
- cleanupAndAbort(`缓存文件重命名失败 from ${tempFilePath} to ${filePath}`, renameErr);
403
- }
404
- });
405
- });
406
- });
407
- file.on('error', (err) => {
408
- cleanupAndAbort(`写入临时文件失败: ${tempFilePath}`, err);
409
- });
410
- request.on('error', (err) => {
411
- cleanupAndAbort(`下载资源请求失败: ${url}`, err);
412
- });
413
- }
414
- /**
415
- * 清理过期缓存文件
416
- */
417
- _cleanOldCache() {
418
- const files = fs.readdirSync(this.options.cacheDir);
419
- const now = Date.now();
420
- files.forEach(file => {
421
- const fullPath = path.join(this.options.cacheDir, file);
422
- try {
423
- const stat = fs.statSync(fullPath);
424
- if (now - stat.mtimeMs > this.options.cacheTTL) {
425
- fs.unlinkSync(fullPath);
426
- }
427
- }
428
- catch {
429
- // 忽略单个文件异常
430
- }
431
- });
432
- }
433
- /**
434
- * 注册 Electron 请求拦截器,实现资源缓存
435
- */
436
- _registerInterceptor() {
437
- const shouldCache = this._getMatchFunction();
438
- const isAllowedOrigin = this._getOriginAllowFunction();
439
- this.session.webRequest.onBeforeRequest({ urls: ['http://*/*', 'https://*/*'] }, (details, callback) => {
440
- const url = details.url;
441
- // 不匹配或来源不允许,直接放行
442
- if (details.method !== 'GET' || !shouldCache(url) || !isAllowedOrigin(url))
443
- return callback({});
444
- const cachePath = this.getCachedPath(url);
445
- // 命中缓存,直接重定向到本地文件
446
- if (this.isCacheValid(cachePath.filePath)) {
447
- console.log('命中缓存: ', url, cachePath);
448
- return callback({ redirectURL: cachePath.hostPath });
449
- }
450
- console.log('未命中缓存: ', url);
451
- // 未命中则异步下载,当前请求正常放行
452
- this.downloadResource(url, cachePath.filePath);
453
- return callback({});
454
- });
455
- }
456
- }
457
- ResourceCache.scheme = 'cachefile';
458
303
  /**
459
304
  * @electron/remote/main enable方法
460
305
  * @param webContents
@@ -493,19 +338,23 @@ const getCustomSession = windowManager__namespace.getCustomSession;
493
338
  * @returns
494
339
  */
495
340
  const index = new Proxy({}, {
496
- get() {
341
+ get(_target, prop) {
497
342
  if (!exports.isInitialized) {
498
343
  throw new Error('请在ready前先调用initialize');
499
344
  }
345
+ if (!prop) {
346
+ // @ts-ignore
347
+ return global['__GLBOAL_ELECTRON_SDK__'];
348
+ }
500
349
  // @ts-ignore
501
- return global['__GLBOAL_ELECTRON_SDK__'];
350
+ return global['__GLBOAL_ELECTRON_SDK__'][prop];
502
351
  },
503
352
  set() {
504
- return true;
353
+ return false;
505
354
  }
506
355
  });
507
356
 
508
- exports.ResourceCache = ResourceCache;
357
+ exports.ResourceCache = resourceCache.ResourceCache;
509
358
  exports.default = index;
510
359
  exports.enable = enable;
511
360
  exports.getCustomSession = getCustomSession;