npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

a-zzlink

v1.1.10

Published

electron 项目开发基础库,便于直接开发业务逻辑

Readme

electron 项目开发基础库,便于直接开发业务逻辑

[toc]

1. 引擎初始化

1.1 主进程初始化引擎

​ 在electron主进程入口(main.ts 或 background.ts) 入增加如下代码:

import { initEngine } from '@electron-engine/engine.main'
initEngine()

​ 完整主程序入口文件如下:

import { app } from 'electron'
import { initEngine } from '@electron-engine/engine.main'
import windows from './core/windows/main'

initEngine()

app.on('ready', async () => {
  windows.LoginWindow.createWindow()
})
1.1.1 参数说明
export interface IEngineConfig {
    logger?: ILoggerConfig
    httpServer?: IHttpServerConfig
    rcElectron?: IRCElectronConfig
    appConfig?: IAppConfigConfig
    notification?: INotificationConfig
    shortcut?: IShortcutConfig
    appTray?: IAppTrayConfig
}

1.2 渲染进程初始化引擎

​ 在窗体preload.js文件中增加如下代码:

require('@electron-engine/engine.renderer')

2. Http请求

2.1 业务的http请求基类

import { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'
import HttpRequestBase from '@ultra-node/electron-engine/http-request/HttpRequestBase'
import { IResult } from '@ultra-node/electron-engine/types'
import { EErrorCode } from '@/types'

interface IServerData {
  data: any
  errCode: string
  errMsg: string
  flag: boolean
}
export default class ApiBase extends HttpRequestBase {
  constructor(apiConfig?: AxiosRequestConfig) {
    const config: AxiosRequestConfig = {
      timeout: 1000 * 15, // 15秒
      baseURL: ''
    }
    !!apiConfig && Object.assign(config, apiConfig)
    super(config)
    super.intercepReqeust({
      onBeforeRequest: this.onBeforeRequest,
      onRequestError: this.onRequestError
    })
    super.intercepResponse({
      onAfterResponse: this.onAfterResponse,
      onResponseError: this.onResponseError
    })
  }

  private onBeforeRequest(config: AxiosRequestConfig<any>): AxiosRequestConfig<any> {
    return config
  }

  private onRequestError(error: AxiosError): any {
    const code = error.message === 'canceled' ? EErrorCode.Canceled : error.response?.status
    const result: IResult = {
      isOK: false,
      data: {},
      code,
      msg: error.message
    }
    return Promise.resolve({ data: result })
  }
  /**
   * 将服务端返回格式转化成应用封装格式
   * @param result 服务原始响应数据
   * @returns 应用所需要的响应数据格式
   */
  private onAfterResponse(result: AxiosResponse<any, any>): AxiosResponse<any, any> {
    const serverData = result.data as IServerData
    const appData: IResult = {
      isOK: serverData.flag,
      data: serverData.data,
      code: serverData.flag ? 0 : serverData.errCode, // 将server的成功码统一转换成 0,为和应用其它模块保持一致
      msg: serverData.errMsg
    }
    result.data = appData
    return result
  }

  private onResponseError(error: AxiosError): any {
    const code = error.message === 'canceled' ? EErrorCode.Canceled : error.response?.status
    const msg = error.code === 'ERR_NETWORK' ? '当前网络不可用,请检查网络设置' : error.message?.includes('timeout of') ? '加载超时' : error.message
    const result: IResult = {
      isOK: false,
      data: {},
      code,
      msg
    }
    return Promise.resolve({ data: result })
  }
}

2.2 具体业务请求类

import ApiBase from './ApiBase'

export default class LoginApi extends ApiBase {
  public login(name: string, pwd: string) {
    return this.postForm('/login', { name, pwd })
  }
}

3. 窗体管理

3.1 主进程使用的窗体对象

import MainWindow from '@ultra-node/electron-engine/window/MainWindow'

export default class LoginWindow extends MainWindow {
  devUrl = (process.env.WEBPACK_DEV_SERVER_URL as string) + '/login.html'
  prodUrl = 'app://./login.html'
  windowOptions: Electron.BrowserWindowConstructorOptions = {
    width: 508,
    height: 611,
    minWidth: 508,
    minHeight: 611,
    maxWidth: 508,
    maxHeight: 611,
    frame: false,
    webPreferences: {
      preload: path.join(__dirname, '/preload-login.js'),
      nodeIntegration: true,
      contextIsolation: false
    }
  }
  constructor() {
    super(EWindowName.LoginWindow)
  }
}

3.2 渲染进程使用的窗体对象

import RendererWindow from '@ultra-node/electron-engine/window/RendererWindow'
import { EWindowName } from '..'

export default class LoginWindow extends RendererWindow {
  constructor() {
    super(EWindowName.LoginWindow)
  }
}

4. Ipc 通讯封装

4.1 渲染进程调用主进程,同步返回结果

  • 主进程中:

    import { listenFromRendererSync } from '@ultra-node/electron-engine/ipc/ipc.main'
      
    listenFromRendererSync('event-name', (event: any, param: string) => {
      return 'result'
    })
  • 渲染进程中:

    import { sendToMainSync } from '@ultra-node/electron-engine/ipc/ipc.renderer'
      
    const result = sendToMainSync('event-name','我是参数')

4.2 渲染进程调用主进程,异步返回结果

  • 主进程中:

    import { listenFromRendererAsync } from '@ultra-node/electron-engine/ipc/ipc.main'
      
    listenFromRendererAsync('event-name', (event: any, param: string) => {
      return await OtherMethod()
    })
  • 渲染进程中:

    import { sendToMainAsync } from '@ultra-node/electron-engine/ipc/ipc.renderer'
      
    const result = await sendToMainAsync('event-name','我是参数')

4.3 渲染进程调用主进程,无返回结果

  • 主进程中:

    import { listenFromRendererVoid } from '@ultra-node/electron-engine/ipc/ipc.main'
      
    listenFromRendererVoid('event-name', (event: any, param: string) => {
      OtherMethod()
    })
  • 渲染进程中:

    import { sendToMainVoid } from '@ultra-node/electron-engine/ipc/ipc.renderer'
      
    sendToMainVoid('event-name','我是参数')

4.4 主进程调用渲染进程

  • 主进程中:

    import { sendToRendererVoid } from '@ultra-node/electron-engine/ipc/ipc.main'
      
    sendToRendererVoid(webcontents, 'event-name','我是参数')
  • 渲染进程中:

    import { listenFromMainVoid } from '@ultra-node/electron-engine/ipc/ipc.renderer'
      
    listenFromMainVoid('event-name', (event: any, param: string) => {
      OtherMethod()
    })

5. 日志

5.1 日志初始化

​ 在做engine初始化时,可以添加日志相关参数

	initEngine({
        logger:{
            filePath: 'full path'
        }
    })

// export interface ILoggerConfig {
//   fileLevel?: TLoggerLevel
//   fileMaxSize?: number
//   filePath?: string
//   fileFormat?: string
// }

5.2 主进程使用日志输出

import logger from '@ultra-node/electron-engine/logger/logger.main'
logger.info('i am from main process')

5.3 渲染进程使用日志输出

import logger from '@ultra-node/electron-engine/logger/logger.renderer'
logger.info('i am from renderer process')
logger.debug('i am from renderer process')
logger.error('i am from renderer process')

6. 快捷键管理

6.1 系统快捷键

​ 只要软件存活,无轮是否被焦点,都可以监听到

import { listenSysShortcut, registerSysShortcut } from '@ultra-node/electron-engine/shortcut/shortcut.renderer'

// 注册
registerSysShortcut('shortcut-name','shift+j')
// 监听
listenSysShortcut('shortcut-name',()=>{
    console.log('shortcut-name pressed')
})

6.2 应用快捷键

​ 软件存活,且处于被焦点状态时,才可以收到监听

import { listenAppShortcut, registerAppShortcut } from '@ultra-node/electron-engine/shortcut/shortcut.renderer'

// 注册
registerAppShortcut('shortcut-name','shift+j')
// 监听
listenAppShortcut('shortcut-name',()=>{
    console.log('shortcut-name pressed')
})

7. 应用协议

​ 注册应用唤醒协议,可以将协议格式放到浏览器中进行唤醒app, 生成的协议格式为: protocol://

  • 主进程中注册协议

    import { registerProtocol, unregisterProtocol } from '@ultra-node/electron-engine/protocol/protocol.main'
      
    registerProtocol('rcbw')
  • 主进程中监听协议唤起

    import { listenProtocol } from '@ultra-node/electron-engine/protocol/protocol.main'
      
    listenProtocol('rcbw',(url: string)=> {
        console.log('用户用这个url唤醒的App', url)
    })

8. 应用托盘图标

import initAppTray, { IAppTrayOptions } from '@ultra-node/electron-engine/tray/tray.main'

// 鼠标事件
const onMouseClick = () => {
    // 鼠标点击图标
}
// 右键菜单
const contextMenuItems: MenuItemConstructorOptions[] = [
    {
        label: '退出',
        role: 'quit',
        click: () => {
            app.quit()
        }
    }
]
// 基本信息
const trayOptions: IAppTrayOptions = {
    iconPath: PathUtil.resolvePath('extraResources/icons/32x32.png'),
    toolTip: 'appName',
    contextMenuItems,
    onClick: onMouseClick
}
// 初始化托盘
initAppTray(trayOptions)

9. 系统通知

  • 主进程初始化

    initEngine({
        notification:{
            appId: 'appId',
            init: true
        }
    })
  • 渲染进程发起

    import { showNotification } from '@ultra-node/electron-engine/notification/notification.renderer'
      
    showNotification({
        title:'',
        body:''
    })

10. shell 功能

10.1 打开文件夹,并选中文件

import { showItemInFolder } from '@ultra-node/electron-engine/shell'

showItemInFolder('/data/a.txt')

11. Dictionary 字典类封装

import { Dictionary } from '@ultra-node/electron-engine/dictionary'

const dict = new Dictionary()
dict.set('key', 'value')
dict.get('key')

12. 本地 Http 服务器

​ 使用 express 在主进程搭建的 http 服务,用于资源代理,也可用于第三方应用调用此应用

12.1 服务初始化

// 初始化
initEngine({
    httpServer:{
        init: true,
        defaultControll: true // 是否开启默认处理器
    }
})

12.2 使用

import { startServer } from '@ultra-node/electron-engine/http-server/httpServer.main'

const localhost = await startServer([])
// localhost: http://localhost:8088

12.3 默认处理器

localhost/local/path/filename?url=remote_address

处理机制:当在 local/path 有 filename 资源时,直接返回,否则会从url下载完后返回,并将资源放到 local/path/filename 处

12.4 增加自定义处理

import { ControllerBase } from '@ultra-node/electron-engine/http-server'

class MyController extends ControllerBase{
  public method: 'get' | 'post' = 'get'
  public routePath: string = '/pic/*'
  public handler(req: Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>, rsp: Response<any, Record<string, any>>): void {
    throw new Error('Method not implemented.')
  }
}

await startServer([new MyController()])

13. app-config: 应用配置

​ 数据会存到本地文件,每次操作都是io, 因此存储仅用于存储简单的软件配置信息

13.1 初始化配置

initEngine({
    appConfig:{
      init: boolean // 是否开启此功能
      fileDir?: string // 文件目录
      fileName?: string // 文件名
      fileExt?: string // 文件后缀
      encryptionKey?: string // 加密字符串
      default?: T // 默认数据格式
    }
})

13.2 使用

import { appConfig } from '@ultra-node/electron-engine/app-config/appConfig.renderer'

appConfig.set('key','value')
appConfig.get('key')

14. app-session: 应用全局缓存

​ 使用主进程存储数据,使用ipc做桥梁,因此此session可用于不同窗体间数据共享,适合全局性变量,但不适合存储业务大量数据

import { appSession } from '@ultra-node/electron-engine/app-session/appSession.renderer'

appSession.set('key','value')
appSession.get('key')

15. rc-electron 融云 imsdk PC端解决方案

​ 开启后,融云 IM 将直接使用协议栈功能,代替websocket通过socket进行通讯

initEngine({
    rcElectron: {
        init: true // 开启功能
    }
})

16. utils: 工具类

16.1 快捷键打开 userdata 目录

import { useOpenUserData } from '@ultra-node/electron-engine/utils/appShortcutUtil'

useOpenUserData()

16.2 获取绝对路径

​ 自动适配开发、生产环境

import { resolvePath } from '@ultra-node/electron-engine/utils/pathUril'

resolvePath('/extraResources/icon')

16.3 获取当前文件寄宿的窗体名称

import { getHostWindowName } from '@ultra-node/electron-engine/utils/windowUtil'

const currentWindowName = getHostWindowName()