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 🙏

© 2026 – Pkg Stats / Ryan Hefner

tauri-mw-store

v2.3.1

Published

Declarative multi-window state management for Tauri apps with React hooks, schema-driven persistence, and automatic synchronization.

Readme

tauri-mw-store

npm version License: MIT

English Documentation | 中文文档

🚀 声明式全局状态管理 + 持久化 Store + 窗口初始化配置,专为 Tauri 多窗口应用设计。

一个专为 Tauri 应用设计的声明式状态管理库,提供类型安全的全局状态、自动持久化存储和声明式窗口事件配置。

✨ 特性

  • 🔄 多窗口状态同步 - 自动在多个窗口间同步状态变化
  • 💾 持久化存储 - 支持状态持久化到本地存储
  • 🎯 类型安全 - 完整的 TypeScript 支持和类型推断
  • ⚛️ React 集成 - 提供易用的 React hooks
  • 📋 Schema 驱动 - 基于 schema 的配置,自动生成类型安全的 API
  • 🎛️ 灵活配置 - 支持立即保存和窗口关闭时保存两种策略
  • 🧹 自动清理 - 自动清理不再需要的持久化键
  • 🪟 窗口事件管理 - 声明式的窗口事件配置

📦 安装

# 使用 bun
bun add tauri-mw-store

# 使用 npm
npm install tauri-mw-store

# 使用 yarn
yarn add tauri-mw-store

依赖要求

  • React >= 18
  • @tauri-apps/api >= 1.5.0
  • @tauri-apps/plugin-store >= 2.3.0

Tauri 配置

仅当你的 Store Schema 中有键声明为持久化时才需要以下配置:

  1. 安装 store 插件:
bun tauri add store
  1. src-tauri/capabilities/default.json 中添加权限:
{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "default",
  "description": "enables the default permissions",
  "windows": ["main", "settings"],
  "permissions": [
    "store:default"
  ]
}

重要提示:

  • windows 数组中需要包含所有使用 store 的窗口标识符
  • 如果窗口 URL 路径是横杠分隔的(如 user-profile),在声明权限时必须改成驼峰命名(如 userProfile),否则会报错

注意: 如果你的应用只使用内存状态(无持久化),则无需安装 Tauri Store 插件和配置权限。

🚀 快速开始

1. 定义类型(可选)

// src/types/index.ts
export interface AppConfig {
  tips: string[];
  autoRotate: boolean;
  rotateInterval: number;
  theme: 'light' | 'dark' | 'system';
  autoStart: boolean;
}

2. 创建 Store

// src/store/appStore.ts
import { createMWStore, storeConfig } from 'tauri-mw-store';
import { AppConfig } from '@/types';

// 使用解构导出,获得类型安全的 API
export const {
  initAppStore,
  getConfig,
  setConfig,
  useConfig,
  getNewVersionDownloaded,
  setNewVersionDownloaded,
  useNewVersionDownloaded,
} = createMWStore({
  config: storeConfig({
    default: null as AppConfig | null,
    persist: true, // 窗口关闭时保存(默认策略)
  }),
  newVersionDownloaded: false, // 不持久化的临时状态
});

3. 初始化 Store

在应用入口处初始化 store(在渲染之前):

// src/main.tsx
import ReactDOM from 'react-dom/client';
import { initAppStore } from './store/appStore';
import App from './App';

// 先初始化 store,加载持久化数据
await initAppStore();

// 然后渲染应用
ReactDOM.createRoot(document.getElementById('root')!).render(<App />);

4. 在组件中使用

// src/pages/Settings.tsx
import React, { useState, useEffect } from 'react';
import { useConfig, getConfig, setConfig } from '@/store/appStore';
import { AppConfig } from '@/types';

function Settings() {
  // 使用 React hook,自动同步多窗口状态
  const config = useConfig();
  const [localTheme, setLocalTheme] = useState<'light' | 'dark'>('dark');
  
  // 当配置加载完成时,同步本地状态
  useEffect(() => {
    if (config) {
      setLocalTheme(config.theme);
    }
  }, [config]);
  
  const handleSave = async () => {
    const currentConfig = getConfig();
    if (!currentConfig) return;
    
    const updatedConfig = {
      ...currentConfig,
      theme: localTheme,
      tips: ['新的提示1', '新的提示2'],
    };
    
    // 更新配置,自动同步到所有窗口
    await setConfig(updatedConfig);
    console.log('配置已保存并同步');
  };

  if (!config) {
    return <div>加载配置中...</div>;
  }

  return (
    <div>
      <h2>设置</h2>
      <select value={localTheme} onChange={(e) => setLocalTheme(e.target.value as any)}>
        <option value="light">浅色</option>
        <option value="dark">深色</option>
      </select>
      <button onClick={handleSave}>保存设置</button>
    </div>
  );
}

5. 监听状态变化(可选)

// src/components/ConfigWatcher.tsx
import { useEffect } from 'react';
import { onConfigChange } from '@/store/appStore';

function ConfigWatcher() {
  useEffect(() => {
    // 监听配置变化
    const unsubscribe = onConfigChange((newConfig) => {
      console.log('配置已更新:', newConfig);
      // 可以在这里执行一些副作用,如更新系统托盘等
    });
    
    // 清理监听器
    return unsubscribe;
  }, []);
  
  return null; // 这是一个纯逻辑组件
}

🪟 窗口事件管理

tauri-mw-store 还提供了声明式的窗口事件管理功能,在应用入口处配置:

// src/main.tsx
import { defineWindowEvents, window } from 'tauri-mw-store';
import { initAppStore } from './store/appStore';
import VersionUpdateUtils from '@/utils/version-update';
import { EventKey } from './types';

// 先初始化 store
await initAppStore();

// 然后配置窗口事件
await defineWindowEvents({
  // 主窗口配置
  main: window({
    onInit: () => {
      const updater = new VersionUpdateUtils();
      return { updater }; // 返回共享上下文,供事件处理器使用
    },
    listeners: {
      // 完整的类型提示:({ updater }: { updater: VersionUpdateUtils }) => void
      [EventKey.CHECK_UPDATE]: ({ updater }) => updater.checkForUpdates(),
      [EventKey.INSTALL_REQUEST]: ({ updater }) => updater.askAndInstall(),
    },
  }),
  
  // 设置窗口配置
  settings: window({
    onInit: () => {
      console.log('✅ 设置窗口初始化完成');
    },
    emitOnInit: [EventKey.CHECK_UPDATE], // 初始化时触发检查更新
  }),
});

事件类型定义:

// src/types/index.ts
export enum EventKey {
  CHECK_UPDATE = 'check-update',
  INSTALL_REQUEST = 'install-request',
}

📚 API 参考

createMWStore(schema)

创建一个基于 schema 的多窗口 store。

参数:

  • schema: Store schema 对象

返回: Store API 对象,包含以下方法:

Store API 方法

  • initAppStore(): 初始化 store,加载持久化数据
  • getXxx(): 获取状态值
  • setXxx(value, emitToWindows?): 设置状态值
  • useXxx(options?): React hook,获取状态并监听变化
  • onXxxChange(callback): 监听状态变化

storeConfig(config)

创建 store 配置对象的辅助函数。

参数:

{
  default: T;           // 默认值
  persist?: boolean | { // 持久化配置
    saveStrategy?: 'immediate' | 'onClose'; // 保存策略
  };
}

useStoreState(key, options?)

底层 React hook,通常不需要直接使用。

参数:

  • key: 状态键名
  • options.syncOnMount: 窗口创建时是否从其他窗口同步当前状态(默认 true)
    • true: 窗口创建时会从其他窗口获取最新状态值
    • false: 窗口创建时使用默认值,不从其他窗口同步

defineWindowEvents(config)

定义窗口事件配置。

参数:

  • config: 窗口事件配置对象

返回: 控制器对象,包含 dispose() 方法用于清理

window(config)

创建窗口配置的辅助函数,提供类型安全。

🔧 高级用法

自定义持久化策略

// src/store/appStore.ts
export const {
  initAppStore,
  getConfig,
  setConfig,
  useConfig,
  getUserSession,
  setUserSession,
  useUserSession,
  getTempData,
  setTempData,
  useTempData,
} = createMWStore({
  // 立即保存:每次状态变化都立即持久化(适合重要配置)
  config: storeConfig({
    default: null as AppConfig | null,
    persist: { saveStrategy: 'immediate' }
  }),
  
  // 延迟保存:窗口关闭时才持久化(默认策略,适合用户偏好)
  userSession: storeConfig({
    default: { isLoggedIn: false, username: '' },
    persist: true // 等同于 { saveStrategy: 'onClose' }
  }),
  
  // 不持久化:仅在内存中(适合临时状态)
  tempData: { message: '', timestamp: Date.now() }
});

条件同步和窗口特定操作

// src/components/LocalSettings.tsx
import { useConfig, setConfig } from '@/store/appStore';

function LocalSettings() {
  // syncOnMount: false - 窗口创建时不从其他窗口同步状态,使用默认值
  // 适用于需要独立配置或临时设置的场景
  const config = useConfig({ syncOnMount: false });
  
  const saveAndSync = async () => {
    // 手动同步到所有窗口
    await setConfig(newConfig, "all");
  };
  
  const saveToSpecificWindow = async () => {
    // 只同步到特定窗口
    await setConfig(newConfig, ["settings", "main"]);
  };
  
  return (
    <div>
      {/* 本地配置界面 */}
      <button onClick={saveAndSync}>保存并同步到所有窗口</button>
      <button onClick={saveToSpecificWindow}>保存到指定窗口</button>
    </div>
  );
}

获取所有存储的键

import { getAllStoredKeys } from 'tauri-mw-store';

// 调试:查看所有持久化的键
const keys = await getAllStoredKeys();
console.log('Stored keys:', keys);

📖 实际项目示例

以下是 FloatingOne 项目中的实际使用案例:

项目结构

src/
├── types/
│   └── index.ts          # 类型定义
├── store/
│   └── appStore.ts       # Store 配置
├── pages/
│   └── settings.tsx      # 设置页面
└── main.tsx              # 应用入口

完整的使用流程

  1. 定义应用配置类型src/types/index.ts
  2. 创建 Storesrc/store/appStore.ts
  3. 在入口初始化src/main.tsx
  4. 在组件中使用src/pages/settings.tsx

这种模式特别适合需要在多个窗口间同步配置的桌面应用,如设置窗口、主窗口等。

🛠️ 开发

本地开发

# 克隆仓库
git clone https://github.com/Huaguang-XinZhe/tauri-mw-store.git
cd tauri-mw-store

# 安装依赖
bun install

# 构建库
bun run build

# 在你的 Tauri 项目中测试
cd /path/to/your-tauri-app
bun add file:../tauri-mw-store

发布新版本

# 发布补丁版本(bug 修复)
bun run release:patch

# 发布次要版本(新功能)
bun run release:minor

# 发布主要版本(破坏性更改)
bun run release:major

详细的发布流程请参考 RELEASE.md

📄 许可证

MIT License - 查看 LICENSE 文件了解详情。

🤝 贡献

欢迎提交 Issue 和 Pull Request!

📞 支持

如果你觉得这个项目有用,请给它一个 ⭐️!


作者: huaguang [email protected]
仓库: https://github.com/Huaguang-XinZhe/tauri-mw-store