Tauriの基礎 - その他プラグイン
概要
Tauri v2は、デスクトップアプリケーション開発に必要な様々な機能を公式プラグインとして提供している。
| プラグイン | 説明 |
|---|---|
| shellMacOS (外部コマンド実行) | 外部プログラムの実行やシェルコマンドの実行を可能にする。 |
| notificationMacOS (デスクトップ通知) | OS標準の通知システムを使用してユーザーに通知を送信する。 |
| clipboard-managerMacOS (クリップボード操作) | システムクリップボードの読み書きを行う。 |
| autostartMacOS (自動起動) | OS起動時の自動起動設定を管理する。 |
| logMacOS (ログ出力) | アプリケーションのログをファイルに出力する。 |
| processMacOS (プロセス管理) | アプリケーション自身の終了や再起動を制御する。 |
これらのプラグインは、npm run tauri add <プラグイン名> コマンドでインストールできる。
各プラグインはRust crateとnpmパッケージの2層構造で提供され、TypeScript/JavaScript APIを通じてフロントエンドから操作できる。
セキュリティのため、ほとんどのプラグインはCapabilities設定で権限を明示的に付与する必要がある。
shell (外部コマンド実行)
Shellプラグインは、外部プログラムの実行やシェルコマンドの実行を可能にする。
また、アプリケーションにバンドルしたサイドカーバイナリの実行にも対応している。
主な機能は以下の通りである。
- 外部コマンドの実行
- システムにインストールされているプログラムを実行できる。
- システムにインストールされているプログラムを実行できる。
- 出力の取得
- 標準出力と標準エラー出力を取得できる。
- 標準出力と標準エラー出力を取得できる。
- サイドカーの実行
- アプリケーションに同梱した実行ファイルを実行できる。
- アプリケーションに同梱した実行ファイルを実行できる。
- URLのオープン
- デフォルトのブラウザやアプリケーションでURLを開く。
- デフォルトのブラウザやアプリケーションでURLを開く。
インストールと設定
# プラグインのインストール npm run tauri add shell
src-tauri/capabilities/default.json ファイルに権限を設定する。
{
"permissions": [
"shell:allow-open",
"shell:allow-execute",
{
"identifier": "shell:allow-execute",
"allow": [
{
"name": "git",
"cmd": "git",
"args": true
},
{
"name": "npm",
"cmd": "npm",
"args": true
}
]
}
]
}
Command APIの基本
Command クラスを使用して外部コマンドを実行する。
// lib/shellExecutor.ts
import { Command } from '@tauri-apps/plugin-shell';
// 基本的なコマンド実行
export async function executeCommand() {
// コマンドの作成
const command = Command.create('git', ['status', '--short']);
// コマンドの実行
const output = await command.execute();
// 出力の確認
console.log('Exit code:', output.code);
console.log('Stdout:', output.stdout);
console.log('Stderr:', output.stderr);
return output;
}
// エラーハンドリング付きの実行
export async function executeWithErrorHandling() {
try {
const command = Command.create('npm', ['--version']);
const output = await command.execute();
if (output.code !== 0) {
throw new Error(`Command failed: ${output.stderr}`);
}
return output.stdout.trim();
}
catch (error) {
console.error('Command execution failed:', error);
throw error;
}
}
引数と環境変数
コマンドに引数と環境変数を渡す方法を示す。
// lib/advancedCommand.ts
import { Command } from '@tauri-apps/plugin-shell';
export async function executeWithEnv() {
const command = Command.create('node', ['--version'], {
// 環境変数の設定
env: {
NODE_ENV: 'production',
DEBUG: 'true',
},
// 現在の環境変数を継承 (デフォルト: true)
// clearEnv: false で明示的に指定
});
const output = await command.execute();
return output.stdout;
}
// 複数の引数を渡す
export async function gitClone(repoUrl: string, targetDir: string) {
const command = Command.create('git', [
'clone',
'--depth',
'1',
repoUrl,
targetDir,
]);
const output = await command.execute();
if (output.code !== 0) {
throw new Error(`Git clone failed: ${output.stderr}`);
}
return output;
}
出力のストリーミング
長時間実行されるコマンドの出力をリアルタイムで取得する方法を示す。
// lib/streamingCommand.ts
import { Command } from '@tauri-apps/plugin-shell';
import { useEffect, useState } from 'react';
export async function executeWithStreaming(
onStdout: (data: string) => void,
onStderr: (data: string) => void
) {
const command = Command.create('npm', ['run', 'build']);
// 標準出力のリスナー
command.on('stdout', (data) => {
onStdout(data);
});
// 標準エラー出力のリスナー
command.on('stderr', (data) => {
onStderr(data);
});
// コマンドの実行
const output = await command.execute();
return output;
}
// Reactコンポーネントでの使用例
function BuildLog() {
const [logs, setLogs] = useState<string[]>([]);
const runBuild = async () => {
setLogs([]);
await executeWithStreaming(
(data) => setLogs(prev => [...prev, `[OUT] ${data}`]),
(data) => setLogs(prev => [...prev, `[ERR] ${data}`])
);
};
return (
<div>
<button onClick={runBuild}>Run Build</button>
<pre>
{logs.join('\n')}
</pre>
</div>
);
}
URLのオープン
open 関数を使用してURLを開く。
// lib/urlOpener.ts
import { open } from '@tauri-apps/plugin-shell';
// デフォルトブラウザでURLを開く
export async function openInBrowser(url: string) {
await open(url);
}
// 使用例
async function openDocumentation() {
await openInBrowser('https://v2.tauri.app/start/');
}
// メールアプリを開く
export async function openMail(to: string, subject?: string) {
let mailto = `mailto:${to}`;
if (subject) {
mailto += `?subject=${encodeURIComponent(subject)}`;
}
await open(mailto);
}
notification (デスクトップ通知)
Notificationプラグインは、OS標準の通知システムを使用してデスクトップ通知を送信する。
主な機能は以下の通りである。
- 通知の送信
- タイトルと本文を含む通知を送信できる。
- タイトルと本文を含む通知を送信できる。
- 通知の許可管理
- 通知の許可状態を確認・要求できる。
- 通知の許可状態を確認・要求できる。
- アイコンの指定
- カスタムアイコンを表示できる (プラットフォーム依存)。
- カスタムアイコンを表示できる (プラットフォーム依存)。
インストールと設定
# プラグインのインストール npm run tauri add notification
src-tauri/capabilities/default.json ファイルに権限を設定する。
{
"permissions": [
"notification:default",
"notification:allow-is-permission-granted",
"notification:allow-request-permission",
"notification:allow-notify"
]
}
基本的な通知の送信
// lib/notifier.ts
import {
isPermissionGranted,
requestPermission,
sendNotification,
} from '@tauri-apps/plugin-notification';
// 通知の許可を確認・要求
export async function ensureNotificationPermission(): Promise<boolean> {
// 既に許可されているか確認
let permissionGranted = await isPermissionGranted();
if (!permissionGranted) {
// 許可を要求
const permission = await requestPermission();
permissionGranted = permission === 'granted';
}
return permissionGranted;
}
// シンプルな通知の送信
export async function showNotification(title: string, body: string) {
const granted = await ensureNotificationPermission();
if (!granted) {
console.warn('Notification permission not granted');
return;
}
// 通知を送信
sendNotification({ title, body });
}
// 使用例
async function notifyBuildComplete() {
await showNotification(
'Build Complete',
'Your project has been built successfully!'
);
}
通知オプション
通知の各種オプションを指定する方法を示す。
// lib/advancedNotification.ts
import {
sendNotification,
Options,
} from '@tauri-apps/plugin-notification';
// 詳細な通知オプション
export async function showAdvancedNotification() {
const options: Options = {
title: 'Important Update',
body: 'A new version is available for download.',
// 通知ID (同じIDの通知は置き換えられる)
id: 'update-notification',
// アイコンのパス (プラットフォーム依存)
icon: 'icons/icon.png',
// 通知音を再生するか
sound: true,
};
await sendNotification(options);
}
// プログレス通知 (一部プラットフォームのみ)
export async function showProgressNotification(
progress: number,
total: number
) {
const percentage = Math.round((progress / total) * 100);
await sendNotification({
title: 'Download Progress',
body: `${percentage}% complete (${progress}/${total})`,
id: 'download-progress', // 同じIDで更新
});
}
Reactフックでの実装
通知機能をReactコンポーネントで使いやすくするカスタムフックの定義例を示す。
// hooks/useNotification.ts
import { useState, useCallback } from 'react';
import {
isPermissionGranted,
requestPermission,
sendNotification,
} from '@tauri-apps/plugin-notification';
export function useNotification() {
const [permissionGranted, setPermissionGranted] = useState<boolean | null>(null);
// 初期化時に許可状態を確認
const checkPermission = useCallback(async () => {
const granted = await isPermissionGranted();
setPermissionGranted(granted);
return granted;
}, []);
// 許可を要求
const askPermission = useCallback(async () => {
const permission = await requestPermission();
const granted = permission === 'granted';
setPermissionGranted(granted);
return granted;
}, []);
// 通知を送信
const notify = useCallback(async (title: string, body: string) => {
let granted = permissionGranted;
if (granted === null) {
granted = await checkPermission();
}
if (!granted) {
granted = await askPermission();
}
if (granted) {
sendNotification({ title, body });
return true;
}
return false;
}, [permissionGranted, checkPermission, askPermission]);
return {
permissionGranted,
checkPermission,
askPermission,
notify,
};
}
// 使用例
function TaskManager() {
const { notify } = useNotification();
const handleTaskComplete = async () => {
// タスク完了処理...
await notify('Task Complete', 'Your task has been processed.');
};
return (
<button onClick={handleTaskComplete}>
Complete Task
</button>
);
}
clipboard-manager (クリップボード操作)
Clipboard Managerプラグインは、システムクリップボードの読み書きを行う。
主な機能は以下の通りである。
- テキストのコピーとペースト
- クリップボードにテキストを書き込む、または読み取る。
- 画像のコピーとペースト
- 画像データのクリップボード操作に対応する。(一部プラットフォーム)
- クリップボードの監視
- クリップボードの内容が変更されたことを検知する。
インストールと設定
# プラグインのインストール npm run tauri add clipboard-manager
src-tauri/capabilities/default.json ファイルに権限を設定する。
{
"permissions": [
"clipboard-manager:default",
"clipboard-manager:allow-read-text",
"clipboard-manager:allow-write-text"
]
}
テキストのコピーとペースト
// lib/clipboard.ts
import { writeText, readText } from '@tauri-apps/plugin-clipboard-manager';
// テキストをクリップボードにコピー
export async function copyToClipboard(text: string): Promise<void> {
await writeText(text);
}
// クリップボードからテキストを取得
export async function pasteFromClipboard(): Promise<string | null> {
try {
const text = await readText();
return text;
}
catch (error) {
console.error('Failed to read clipboard:', error);
return null;
}
}
// 使用例
async function copyEmail() {
await copyToClipboard('user@example.com');
console.log('Email copied!');
}
Reactコンポーネントでの使用
クリップボード操作を備えたReactコンポーネントの例を示す。
// components/CopyButton.tsx
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
import { useState } from 'react';
interface CopyButtonProps {
text: string;
label?: string;
}
export function CopyButton({ text, label = 'Copy' }: CopyButtonProps) {
const [copied, setCopied] = useState(false);
const handleCopy = async () => {
await writeText(text);
setCopied(true);
// 2秒後にリセット
setTimeout(() => setCopied(false), 2000);
};
return (
<button onClick={handleCopy}>
{copied ? 'Copied!' : label}
</button>
);
}
// components/PasteInput.tsx
import { readText } from '@tauri-apps/plugin-clipboard-manager';
import { useState } from 'react';
export function PasteInput() {
const [value, setValue] = useState('');
const handlePaste = async () => {
const clipboardText = await readText();
if (clipboardText) {
setValue(clipboardText);
}
};
return (
<div>
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Paste text here..."
/>
<button onClick={handlePaste}>Paste</button>
</div>
);
}
autostart (自動起動)
Autostartプラグインは、OS起動時の自動起動設定を管理する。
主な機能は以下の通りである。
- 自動起動の有効化/無効化
- アプリケーションをOS起動時に自動的に開始するかどうかを設定する。
- 自動起動状態の確認
- 現在の自動起動設定を確認する。
インストールと設定
# プラグインのインストール npm run tauri add autostart
src-tauri/capabilities/default.json ファイルに権限を設定する。
{
"permissions": [
"autostart:default",
"autostart:allow-enable",
"autostart:allow-disable",
"autostart:allow-is-enabled"
]
}
自動起動の有効化/無効化
// lib/autostartManager.ts
import {
enable,
disable,
isEnabled,
} from '@tauri-apps/plugin-autostart';
// 自動起動を有効化
export async function enableAutostart(): Promise<void> {
await enable();
}
// 自動起動を無効化
export async function disableAutostart(): Promise<void> {
await disable();
}
// 自動起動の状態を確認
export async function checkAutostartStatus(): Promise<boolean> {
return await isEnabled();
}
// トグル
export async function toggleAutostart(): Promise<boolean> {
const currentlyEnabled = await isEnabled();
if (currentlyEnabled) {
await disable();
return false;
}
else {
await enable();
return true;
}
}
Reactコンポーネントでの実装
自動起動設定のトグルスイッチコンポーネントの例を示す。
// components/AutostartToggle.tsx
import { useState, useEffect } from 'react';
import {
enable,
disable,
isEnabled,
} from '@tauri-apps/plugin-autostart';
export function AutostartToggle() {
const [enabled, setEnabled] = useState(false);
const [loading, setLoading] = useState(true);
// 初期状態の読み込み
useEffect(() => {
isEnabled()
.then(setEnabled)
.catch(console.error)
.finally(() => setLoading(false));
}, []);
// トグル処理
const handleToggle = async () => {
try {
if (enabled) {
await disable();
setEnabled(false);
}
else {
await enable();
setEnabled(true);
}
}
catch (error) {
console.error('Failed to toggle autostart:', error);
}
};
if (loading) {
return <div>Loading...</div>;
}
return (
<div className="autostart-toggle">
<label>
<input
type="checkbox"
checked={enabled}
onChange={handleToggle}
/>
Start automatically on system boot
</label>
<p className="hint">
{enabled
? 'The app will start when you log in.'
: 'The app will not start automatically.'}
</p>
</div>
);
}
プラットフォームごとの注意点
| プラットフォーム | 実装方法 | 注意点 |
|---|---|---|
| Windows | レジストリ または スタートアップフォルダ | 管理者権限が必要な場合がある。 |
| MacOS | LaunchAgent | plistファイルが生成される。 |
| Linux | XDG Autostart | ~/.config/autostart/ ディレクトリにdesktopファイルが作成される。 |
※注意
モバイルプラットフォーム (Android/iOS) は、自動起動をサポートしていない。
log (ログ出力)
Logプラグインは、アプリケーションのログをファイルに出力する。
主な機能は以下の通りである。
- 複数のログレベル
- trace、debug、info、warn、errorの5レベルに対応
- ファイルへの出力
- ログは自動的にファイルに保存される。
- Rust側との統合
- Rust側のログも同じファイルに出力可能
インストールと設定
# プラグインのインストール npm run tauri add log
Rust側でロガーを初期化する。
// src-tauri/src/lib.rs
use tauri_plugin_log::{Target, TargetKind};
fn main() {
tauri::Builder::default()
.plugin(
tauri_plugin_log::Builder::default()
.targets([
Target::new(TargetKind::Stdout),
Target::new(TargetKind::LogDir { file_name: None }),
Target::new(TargetKind::Webview),
])
.build(),
)
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
ログ出力の基本
// lib/logger.ts
import {
trace,
debug,
info,
warn,
error,
attachConsole,
} from '@tauri-apps/plugin-log';
// コンソール出力をログに転送 (開発時用)
export async function setupLogger() {
await attachConsole();
}
// 各レベルのログ出力
export const logger = {
trace: (message: string) => trace(message),
debug: (message: string) => debug(message),
info: (message: string) => info(message),
warn: (message: string) => warn(message),
error: (message: string) => error(message),
};
// 使用例
async function example() {
await logger.info('Application started');
await logger.debug('Processing data...');
await logger.warn('Low disk space');
await logger.error('Failed to connect to server');
}
ログファイルの場所
ログファイルはアプリケーションのログディレクトリに保存される。
| プラットフォーム | パス |
|---|---|
| Windows | %APPDATA%/{appName}/logs/ |
| MacOS | ~/Library/Logs/{appName}/ |
| Linux | ~/.local/share/{appName}/logs/ |
ログラッパーの実装
より使用しやすいロガーの例を示す。
// lib/advancedLogger.ts
import { info, warn, error, debug, trace } from '@tauri-apps/plugin-log';
type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error';
class Logger {
private context: string;
private level: LogLevel;
private levelPriority: Record<LogLevel, number> = {
trace: 0,
debug: 1,
info: 2,
warn: 3,
error: 4,
};
constructor(context: string, level: LogLevel = 'info') {
this.context = context;
this.level = level;
}
private shouldLog(level: LogLevel): boolean {
return this.levelPriority[level] >= this.levelPriority[this.level];
}
private formatMessage(level: LogLevel, message: string): string {
const timestamp = new Date().toISOString();
return `[${timestamp}] [${level.toUpperCase()}] [${this.context}] ${message}`;
}
async log(level: LogLevel, message: string): Promise<void> {
if (!this.shouldLog(level)) return;
const formatted = this.formatMessage(level, message);
switch (level) {
case 'trace':
await trace(formatted);
break;
case 'debug':
await debug(formatted);
break;
case 'info':
await info(formatted);
break;
case 'warn':
await warn(formatted);
break;
case 'error':
await error(formatted);
break;
}
}
// 便利メソッド
async trace(message: string) { await this.log('trace', message); }
async debug(message: string) { await this.log('debug', message); }
async info(message: string) { await this.log('info', message); }
async warn(message: string) { await this.log('warn', message); }
async error(message: string) { await this.log('error', message); }
}
// 使用例
const apiLogger = new Logger('API', 'debug');
async function fetchData() {
await apiLogger.debug('Fetching data from server...');
try {
// API呼び出し...
await apiLogger.info('Data fetched successfully');
}
catch (err) {
await apiLogger.error(`Failed to fetch data: ${err}`);
}
}
process (プロセス管理)
Processプラグインは、アプリケーション自身の終了や再起動を制御する。
主な機能は以下の通りである。
- アプリケーションの終了
- アプリケーションを正常に終了する。
- アプリケーションの再起動
- アプリケーションを再起動する。
- プロセス情報の取得
- 現在のプロセスに関する情報を取得する。
インストールと設定
# プラグインのインストール npm run tauri add process
src-tauri/capabilities/default.json ファイルに権限を設定する。
{
"permissions": [
"process:default",
"process:allow-exit",
"process:allow-restart"
]
}
アプリケーションの終了
// lib/appControl.ts
import { exit } from '@tauri-apps/plugin-process';
// アプリケーションを終了
export async function quitApp(exitCode: number = 0): Promise<void> {
await exit(exitCode);
}
// 確認ダイアログ付きで終了
export async function confirmAndQuit(): Promise<void> {
const confirmed = confirm('Are you sure you want to quit?');
if (confirmed) {
await quitApp();
}
}
アプリケーションの再起動
// lib/appRestart.ts
import { restart } from '@tauri-apps/plugin-process';
// アプリケーションを再起動
export async function restartApp(): Promise<void> {
await restart();
}
// 設定変更後の再起動プロンプト
export async function promptRestart(message: string = 'Restart to apply changes?'): Promise<void> {
const confirmed = confirm(message);
if (confirmed) {
await restart();
}
}
Reactコンポーネントでの実装
アプリケーション制御ボタンの例を示す。
// components/AppControls.tsx
import { exit, restart } from '@tauri-apps/plugin-process';
import { useState } from 'react';
export function AppControls() {
const [restarting, setRestarting] = useState(false);
const handleQuit = async () => {
const confirmed = confirm('Quit application?');
if (confirmed) {
await exit(0);
}
};
const handleRestart = async () => {
const confirmed = confirm('Restart application?');
if (confirmed) {
setRestarting(true);
await restart();
}
};
return (
<div className="app-controls">
<button onClick={handleRestart} disabled={restarting}>
{restarting ? 'Restarting...' : 'Restart App'}
</button>
<button onClick={handleQuit} className="danger">
Quit
</button>
</div>
);
}
// 設定画面での使用例
function SettingsPage() {
const [themeChanged, setThemeChanged] = useState(false);
const handleThemeChange = async (newTheme: string) => {
// テーマ設定を保存...
setThemeChanged(true);
};
return (
<div>
<h1>Settings</h1>
{/* 設定項目... */}
{themeChanged && (
<div className="restart-prompt">
<p>Theme change requires restart.</p>
<button onClick={() => restart()}>
Restart Now
</button>
</div>
)}
</div>
);
}
サンプルコード : 複数のプラグインの組み合わせ
複数のプラグインを組み合わせた例を示す。
// lib/taskRunner.ts
import { Command } from '@tauri-apps/plugin-shell';
import { sendNotification } from '@tauri-apps/plugin-notification';
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
import { info, error } from '@tauri-apps/plugin-log';
// ビルドタスクの実行と通知
export async function runBuildTask(projectPath: string): Promise<boolean> {
await info(`Starting build for: ${projectPath}`);
try {
// ビルドコマンドの実行
const command = Command.create('npm', ['run', 'build'], {
cwd: projectPath,
});
let output = '';
command.on('stdout', (data) => {
output += data;
});
const result = await command.execute();
if (result.code === 0) {
// 成功通知
await sendNotification({
title: 'Build Succeeded',
body: 'Your project has been built successfully.',
});
await info('Build completed successfully');
return true;
}
else {
// エラー通知
await sendNotification({
title: 'Build Failed',
body: 'Check the log for details.',
});
await error(`Build failed: ${result.stderr}`);
return false;
}
}
catch (err) {
await error(`Build error: ${err}`);
return false;
}
}
// ログをクリップボードにコピー
export async function copyLogToClipboard(logContent: string): Promise<void> {
await writeText(logContent);
await sendNotification({
title: 'Copied',
body: 'Log has been copied to clipboard.',
});
}
トラブルシューティング
shell : コマンドが見つからないエラー
Command not foundエラーが発生する場合、Capabilities設定を確認する。
{
"identifier": "shell:allow-execute",
"allow": [
{
"name": "git",
"cmd": "git",
"args": true
}
]
}
notification : 通知が表示されない
以下に示す項目を確認する。
- OSの通知設定
- アプリケーションの通知が有効になっているか確認する。
- 権限の確認
isPermissionGranted()で許可状態を確認する。
- フォーカスモード
- MacOSやWindowsのフォーカスモード中は通知が抑制される場合がある。
autostart : 設定が反映されない
以下に示す項目を確認する。
- アプリケーションの署名
- MacOSでは署名されていないアプリの自動起動がブロックされる場合がある。
- 権限の確認
- 自動起動に必要なOS権限があるか確認する。
関連情報
- Tauri公式ドキュメント - Plugins
- GitHub - Tauri Plugins Workspace
- Tauriの基礎 - プラグインシステム
- Tauriの基礎 - HTTPクライアント
- Tauriの基礎 - ストア