ドキュメント
デスクトップUI
SolidJS ワークスペース、ローカル API クライアント、およびネイティブ統合を所有する Tauri シェル。
英語から自動翻訳されています。 英語の原文を見る
アプリケーションアーキテクチャ
デスクトップ アプリケーションは、SolidJS Webview、Vite、Three.js、Tauri v2 Rust シェルを組み合わせています。 Web ビューは、画面と対話状態を所有します。 Bun サイドカーは、API ハンドラー、データベース アクセス、AI セッション、およびプロジェクト サービスを所有します。 Rust プロセスは、ウィンドウ、メニュー、トレイ、オペレーティング システム ダイアログ、キーチェーン アクセス、アップデート、サイドカー ライフサイクルを所有します。
apps/desktop/src/main.tsx アプリケーションをマウントします。 app/App.tsx aPI 接続を確立し、共有状態を提供します。 app/routes.tsx uRL を遅延ページ モジュールにマップします。機能画面が存在します features/。ルートの存在によって外部サービスの可用性が確立されるわけではありません。請求には Stripe 構成が必要で、AI には構成されたプロバイダーが必要です。
起動と接続の回復
- シェルは、生成された起動トークン、アプリケーション データ、および移行ディレクトリを使用して、バンドルされたサイドカーを開始します。
- サイドカーは一時的なポートをバインドします。
127.0.0.1、ヘルスルートが応答するのを待ち、JSONを書き込みますreadyポートを含むイベント。 - WebView が呼び出すのは、
get_sidecar_endpointaPI クライアントとマネージド エフェクト ランタイムを作成します。 - 正常性リクエストが成功すると、アプリケーション状態が作成され、ルーターとシェルがマウントされます。
Web ビューでは、接続の回復に 150 秒かかります。試行ごとのタイムアウトは 30 秒、再試行の一時停止は 750 ミリ秒です。試行が失敗すると、キャッシュされたエンドポイントが破棄され、再起動されたサイドカーが新しいポートを提供できるようになります。 Rust スーパーバイザは、準備完了のハンドシェイクごとに 60 秒待機し、1 回の自動再起動を許可します。 Webview 接続の予算が期限切れになると、再試行が可能になります。
ブラウザのプレビューはインメモリ API を使用します
Tauri 以外のブラウザでは、 VITE_SIDECAR_URL 用途 src/testing/fake-api.ts。プレビュー データは実行中のページに対してローカルです。サポートされていないコレクションは HTTP 501 を返します。ブラウザを実際のサイドカーに接続するには、両方を提供します VITE_SIDECAR_URL そして VITE_SIDECAR_TOKEN viteを起動するとき。
スクリーンルート
| エリア | ルートとモジュール |
|---|---|
| プロジェクト | /projects, /projects/create, /projects/:id、 そして /projects/:id/history;の画面 features/projects/screens. |
| 設計と製造 | /cad マウントする CadPage; /cam マウントする CamPage。保存された図面とツールパスには、個別の詳細ルートがあります。 |
| リソース | /library, /materials, /tools, /machine、その詳細ページではライブラリ機能モジュールが使用されます。コンポーネントにはリストルートと詳細ルートがあります。 |
| アシスタント | /ai ドッキングされたアシスタント パネルは AI 機能の状態を共有します。 AI アクティビティによりパネルが切り替わります。 |
| 設定 | /settings, /settings/companion、MCP 設定、サブスクリプション設定。 |
| アカウントとコラボレーション | 認証、プロファイル、組織、招待、チャット、マーケットプレイス、プラグイン、コスト、分析、および管理ルートの各ロード機能モジュール。 |
使用 app/routes.tsx 正確なパラメータ名については、 pages/ uRL にマウントされている画面を見つけます。ルート アダプターは意図的に小さくなっています。空のビューまたは失敗したアクションを診断するときに、画面とその API 呼び出しを読み取ります。
ソース組織
app/: スタートアップ、ルーター、グローバル API クライアント、ネイティブ統合、シェル、キーボード ショートカット。pages/: ルート アダプタのインポートまたは再エクスポート画面。features/: 画面、コンポーネント、フック、状態、およびドメイン固有のヘルパーを含む製品領域。shared/: 再利用可能なコントロール、シェル コンポーネント、アプリケーションの状態、クエリ キャッシュ、およびコマンド履歴。viewport/: キャンバス描画、スナップ、ツール ジェスチャ、Three.js レンダリング、メッシュ作成、および再生。i18n/,styles/、 そしてtesting/: 翻訳、グローバル スタイル、テスト フィクスチャ。
デスクトップは以下に依存します @cadcamfun/api hTTP コントラクトおよびそれ以降の場合 @cadcamfun/core ジオメトリおよび CAM 操作用。データベースの永続性はサイドカー API の背後に残ります。ローカル エディタの履歴は、永続化された図面やツールパスのバージョン、およびプロジェクトのバージョン管理とは異なります。
ネイティブシェル
デフォルトでは、本番ウィンドウは 1440 × 900 で、最小値は 960 × 600 です。 Tauri はフロントエンドを次からステージングします。 apps/desktop/dist、ターゲット固有のサイドカー src-tauri/binaries、リソースとして移行を生成しました。登録します .cadcam, .nc、 そして .gcode ファイルの関連付け。サポートされているファイルを開くか、2 番目のインスタンスを起動すると、ファイル パスが既存のウィンドウに転送されます。
src-tauri/src/sidecar.rs 子プロセスを監視します。アプリを閉じると、 {"event":"shutdown"} 子の標準入力にラインを送信し、それを取得する前に少し待機します。子は stdin クロージャも観察します。起動トークンは 32 個のランダム バイトで、64 文字として 16 進エンコードされ、認証情報が含まれる可能性のあるサイドカー ログ行は編集されます。ログは、レディ/エラー ハンドシェイクを伝送する標準出力とは別のものです。ネイティブ シークレットには次の方法でアクセスします。 src-tauri/src/secrets.rs オペレーティング システムのキーチェーンを使用します。
macOS では、シェルは Liquid Glass プラグインを登録します。 Web ビューはガラスの設定に従い、効果が利用できない場合は元に戻ります。 App Store の設定ではプライベート API オプションが無効になっています。通常の設定ではそれが有効になります。これらは別のビルド構成です。
セキュリティと永続性の境界
運用コンテンツ ポリシーでは、ローカル アセット、ループバック API 接続、データ/BLOB イメージ、および WebAssembly 評価が許可されます。任意のリモート スクリプトの実行は許可されません。ネイティブ権限の範囲は次のとおりです。 src-tauri/capabilities;開発ポリシーでは、Vite とその WebSocket もさらに許可されています。
open_path パスを正規化し、許可されたユーザー/アプリケーション ディレクトリに制限し、次のような実行可能拡張子を拒否します。 .exe, .app, .sh, .bat, .msi、 そして .jar. .. セグメントとシンボリックリンクは両方とも正規化されているため、許可されたフォルダーからエスケープできません。ファイルの選択と保存には、ネイティブのダイアログと検証が使用されます。起動トークンにより、ローカル アプリケーション API へのアクセスが許可されます。コンパニオン トークンまたはプロジェクト スコープの AI ブリッジ トークンとは別に扱います。
UI 設定、API クエリ状態、エディター コマンド、保存されたプロジェクト バージョン、およびネイティブ シークレットには異なる所有者がいます。すべてのアプリケーションの状態が SQLite に保存されていると仮定するのではなく、実際のサービスを通じてそれぞれを診断します。
機能の統合
CAD および CAM 機能モジュールは、独自のパネル、ストア、保存フローを備えた再利用可能なビューポート コンポーネントを構成します。アシスタント パネルはプロジェクトとエディターのコンテキストを受け取り、AI 機能の状態を通じてツール イベントをストリーミングします。リソース画面は、データベースに直接アクセスするのではなく、API クライアントを使用します。
UI を変更する場合は、ルート アダプターに従ってその機能画面に移動し、要求を送信する機能ストアまたはフックを検査します。既存のコントラクトがインタラクションと一致する場合にのみ、共有コンポーネントを再利用します。純粋なジオメトリをコア パッケージに保持し、ネイティブ オペレーティング システムの動作を Rust シェルに保持します。
ルートの読み込みとエラー
各ルートは Solid の遅延インポート境界を使用します。この表には、すべてを網羅したページが含まれています。 /500, /offline、および合法的なルート。クライアント ルーターが URL を解決できるように、ブラウザの直接ナビゲーションは Vite 開発サーバーまたはパッケージ化された Web ビューを通じて提供される必要があります。
プレビュー API は、限られたコレクションのセットを実装し、テストにリクエストの失敗を意図的に挿入できます。プレビュー レンダリングが成功すると、それらのフィクスチャに対する UI の動作が実証されます。永続性、権限、ストリーミング、ライブ サイドカーとの外部統合を検証します。
ネイティブコマンドインターフェース
| 指示 | 目的 |
|---|---|
get_sidecar_endpoint | 監視対象サイドカーを待ち、そのベース URL と起動トークンを返します。待機時間には 1 回の再起動が含まれます。つまり、2 回の 60 秒の準備完了タイムアウトと 5 秒 (125 秒) です。 |
get_logs_dir, open_path | アプリケーション ログ ディレクトリを文字列として解決し、オペレーティング システムのオープナーを使用して既存の絶対パスを開きます。パスは、アプリ データ、ログ、ドキュメント、ダウンロード、またはデスクトップ フォルダーの下で解決される必要があります。 |
secret_get, secret_set, secret_delete | 次のネイティブ キーチェーン エントリにアクセスします。 com.cadcamfun.app サービス。キーは、1~128 バイトの ASCII 文字、数字、および . _ - : (例えば ai.anthropic.apiKey); secret_get 返品 null 欠落しているエントリの場合。 |
pick_file, save_file | pick_file({ filters: [{ name, extensions }] }) 選択したパスを返す、または null キャンセル時。 save_file({ defaultName, contents }) uTF-8 テキストを選択したパスに書き込み、それを返します、または null キャンセル時;ディレクトリと実行可能拡張子は拒否されます。 |
set_recent_projects | トレイの最近のプロジェクト メニューを更新します。 |
check_for_updates, install_update | アップデーターのチェックをリクエストするか、保留中のアップデートをインストールします。 install_update オプションを受け入れます unsavedWork フラグ (デフォルト false) そのため、インストールによって開いているエディターが中断されることはありません。 |
The invoke handler is registered in src-tauri/src/lib.rs. Capabilities and generated command permissions also control availability; command registration alone does not establish webview access. Command errors are serialized as { kind, message } with kinds such as sidecar, invalid_path, io, dialog, and path; no command panics.
ネイティブイベント
貝殻が発する sidecar-status ライフサイクルの変化に合わせて、 open-file サポートされているパスでは、 menu メニュー選択用、および update://status アップデーターの進捗状況について。トレイの最近のプロジェクトの選択は次のように表されます。 tray.recent.<projectId> メニュー識別子。シェルのメニューおよびトレイ モジュールは、完全な識別子セットを定義します。
リスナーはコンポーネントまたはアプリケーションのライフサイクルにスコープを設定し、クリーンアップ時に削除する必要があります。 WebView は、サイドカーの再起動後に、以前のポートを使用し続けるのではなく、エンドポイントを再解決する必要があります。
開発と検証
bun run --filter @cadcamfun/desktop dev
bun run desktop:dev
bun run --filter @cadcamfun/desktop typecheck
bun test apps/desktop/src
bun run build:desktop 最初のコマンドはブラウザーのプレビューを実行します。 desktop:dev tauri を開始する前に、実際のサイドカーをコンパイルし、移行を段階的に実行します。デスクトップパッケージの tauri:dev 代わりに、スクリプトはバイナリが存在しない場合にのみスタブ バイナリを作成します。これを分離シェル作業に使用し、API 応答を解釈する前にどのバイナリが存在するかを確認します。
デスクトップ build スクリプトの実行 vite build のみ;サイドカーのコンパイルや Tauri バンドルのパッケージ化は行いません。使用 bun scripts/build.ts 完全なリリース パイプラインについては (「 リリース).
環境設定と設定
共有設定ストアには、検証されたレコードが保存されます。 cadcamfun.settings webView ローカル ストレージ内。欠落しているフィールド、無効なフィールド、または読み取り不可能なフィールドは、個別にフォールバックします。ストレージ領域がいっぱいまたはブロックされても編集は停止しませんが、環境設定の変更は保持されない可能性があります。ブラウザのプレビュー設定はブラウザのオリジンに属し、ネイティブの Web ビュー設定とは別のものです。
| 設定 | 受け入れられる値/デフォルト | 運用効果 |
|---|---|---|
| テーマ | light, dark, system;デフォルトのシステム | システム モードは、オペレーティング システムのカラースキームの変更に従います。 |
| 表示単位 | mm または in;デフォルト mm | プレゼンテーションをコントロールします。コアの描画座標はミリメートルのままです。 |
| 小数 | 整数 0 – 6;デフォルトの 3 | 長さの表示精度。 |
| デフォルトの投稿 | grbl, linuxcnc, smoothwb, gcode, fanuc;デフォルトのgrbl | 選択された出力文法は優先事項であり、マシンが構成または検証されていることを証明するものではありません。 |
| 図面公差 | 検証されたコア公差。デフォルト 0.01 mm | 図面/ツールパス利用者によって使用される共有精度設定。 |
| スナップ状態 | ブール値;デフォルトで有効になっています | 共有ステータスの設定。個々の編集者がスナップ動作を所有します。スタンドアロン Editor2D 現在、内部でグリッド スナップが有効になっています。 |
| ガラス | ブール値;デフォルトで有効になっています | ネイティブ ホストがサポートしている場合、macOS ウィンドウ マテリアルを要求します。 |
「設定」画面には、「プロファイル」、「アカウント」、「セキュリティ」、「サブスクリプション」、「通知」、「AI」、「デバイス」、および「言語」タブがあります。 [デバイス] タブには、コンパニオン ゲートウェイ パネルが組み込まれています。言語設定にはガラスの切り替えが含まれます。現在、共通ロケール ストアはデフォルト ロケールを検証しています。表示ラベルのリストから追加の翻訳対象範囲を推測しないでください。
CAM プログラムを保存して再度開く
- CAM で NC コードを生成またはロードし、既存のエントリ ポイントから保存/エクスポート ダイアログを開きます。
- ファイルのエクスポートの場合は、G コードまたはポータブル ツールパス形式を選択します。 G コードは現在の NC テキストをダウンロードします。ツールパスの選択により、構造化された
.cam.jsonスナップショット。 - アプリケーションを永続化するには、既存のプロジェクト、新しいプロジェクトを選択するか、すでに保存されているプログラムを更新します。プログラム名と必要な宛先フィールドを入力します。
- 更新する場合、保存フローは、現在のデータを置き換える前に、以前の完全なプログラムをツールパス バージョンとして記録します。
- 保存されたアイテムをそのツールパス詳細ルートで開き、バージョンを検査または復元します。
保存サマリには、証拠が現在の NC に属している場合、NC ライン、バイト、移動、工具識別子、操作名、ストック、単位、ワーク オフセット、および検証 ID が含まれます。 NC テキストが変更されると、以前に計算された証拠が陳腐化する可能性があります。概要に頼る前に、現在のコードと証拠の関係を確認してください。
新しいプロジェクトの作成は成功したが、その後の保存ステップが失敗した場合、モーダルは再試行のために作成された宛先を保持し、その識別子をエラーに含めます。そのモーダル内で再試行すると、同じプロジェクトを再度作成することが回避されます。保存フローが 1 つのアトミックなリソース間トランザクションであると想定しないでください。
ファイルのエクスポートとプロジェクトの永続化は別の操作です
ダウンロードされた G コード ファイルでは、プロジェクト ツールパス行は作成されません。ポータブル スナップショットは、単純な NC よりも豊富な状態を保持します。保存したプログラムをアプリケーションから再度開いて確認し、ダウンロードしたファイルを検査してエクスポートを確認します。
キーボードと故障診断
Cmd/Ctrl+K コマンドパレットを開き、 Cmd/Ctrl+J アシスタントパネルを切り替えます。フォーカスが入力、テキストエリア、選択、またはコンテンツ編集可能な要素にある場合、シェル ショートカットは無視されます。エディター キャンバスには独自のキーボード処理があります。汎用ショートカット テーブルの保存/エクスポートを含むいくつかのシェル コマンド コールバックはプレースホルダーです。リストされているすべてのアクセラレータがドキュメント操作を実行すると仮定するのではなく、機能の実際の保存/エクスポート コントロールを使用してください。
| 観察された動作 | チェック |
|---|---|
| 起動が待機し、「再試行」が表示されます | サイドカー エラー/準備完了出力、ターゲット バイナリ、移行リソース、およびアプリケーション ログ。キャッシュされたポートは以前のプロセスに属している場合があります。 |
| 画面はレンダリングされますが、リクエストは 501 を返します | ブラウザフィクスチャモード。実際のサイドカーを開始し、両方の Vite エンドポイント変数を渡します。 |
| デスクトップ データは手動スクリプトとは異なります | 各プロセスのデータ ディレクトリとトークン。ファイル名だけではデータベースを識別できません。 |
| ネイティブ コマンドは使用できません | 登録、機能のアクセス許可、オペレーティング システムのサポート、およびコードが Tauri 内で実行されるかどうかを呼び出します。 |
| 再起動すると設定が元に戻る | ストレージの可用性と検証。無効な保存フィールドはデフォルトに戻ります。 |
| 保存されたプログラムの証拠は NC とは異なります | NCを生成後に編集したかどうか。実際のテキスト/プログラムに対して適切な検証を再計算します。 |
実装アンカー: shared/state/settings.ts, app/shortcuts.ts, features/settings/screens/settings.tsx、 そして features/cam/components/SaveCamModal.tsx.
ネイティブ イベント ペイロード
| イベント | ペイロード | 注意事項 |
|---|---|---|
sidecar-status | { state: "starting" }, { state: "ready", port }, { state: "restarting" }, { state: "failed", message } | 後 restarting、 電話 get_sidecar_endpoint また;ポートが変わります。 |
update://status | status: checking, upToDate (version), available (version, notes, date, critical), downloading (downloaded, total), ready (version), failed (message);プラス dismissible | 重要な更新と保留中の再起動は無視できません。失敗したチェックがブロック エラーとして表示されることはありません。 |
menu | メニュー項目 ID など file.new, file.open, file.save, view.devtools, help.documentation | トレイアイテムの使用 tray.quit そして tray.recent.<projectId>. |
open-file | のパス .cadcam, .nc、 または .gcode ファイル | OS がアプリでファイルを開くとき、または 2 番目のインスタンスが起動されるときに送信されます。 |
install_update 理由を入力して拒否できます。 unsavedWork (「エディターには保存されていない作業があります。保存したら更新を適用します」)、 noneAvailable (保留中のものは何もないか、すでにインストールされています)、または failed (ダウンロードまたは署名チェックに失敗しました)。最後のチェックで通知された更新のみがインストールされます。
import { invoke } from "@tauri-apps/api/core"
import { listen } from "@tauri-apps/api/event"
const { baseUrl, token } = await invoke<{ baseUrl: string; token: string }>("get_sidecar_endpoint")
const path = await invoke<string | null>("pick_file", {
filters: [{ name: "G-code", extensions: ["nc", "gcode"] }],
}) // null when the user cancels
await invoke("save_file", { defaultName: "part.nc", contents: gcodeText })
const unlisten = await listen<{ state: string; port?: number }>("sidecar-status", (e) => {
if (e.payload.state === "ready") reconnect()
})
// later: unlisten()
try {
await invoke("install_update", { unsavedWork: editorIsDirty })
} catch (error) {
// { kind, message }: the update variant carries the refusal (unsavedWork | noneAvailable | failed)
} get_sidecar_endpoint 返品 { baseUrl, token } (からキャメルケースでシリアル化 SidecarEndpoint)。すべてのコマンドからのエラーは、拒否された値として到着します。 invoke、形をした { kind, message }.
キーボードショートカット
| ショートカット | アクション | グループ |
|---|---|---|
Cmd/Ctrl+K | コマンドパレットを開く | ナビゲーション |
Cmd/Ctrl+Shift+P | 新しいプロジェクト | ナビゲーション |
Cmd/Ctrl+Z / Cmd/Ctrl+Shift+Z | 元に戻す/やり直す | 編集 |
Cmd/Ctrl+S, Cmd/Ctrl+Shift+E | 保存、エクスポート (シェル プレースホルダー、機能独自のコントロールを使用) | 編集 |
Cmd/Ctrl+0 | ズームして合わせる | ビュー |
Cmd/Ctrl+= / Cmd/Ctrl+- | ズームイン/アウト | ビュー |
Cmd/Ctrl+J | アシスタントパネルを切り替える | あい |
Cmd macOS に適用され、 Ctrl 他の場所で。各ショートカットの ID は、その変換キーのサフィックスでもあります (たとえば、 settings.shortcut.palette)、設定画面でもこれと同じテーブルが表示されるため、ドキュメントとアプリが乖離することはありません。
すべてのスクリーンルート
のルーター apps/desktop/src/app/routes.tsx 68 ルートを宣言し、それぞれがから遅延ロードされます apps/desktop/src/pages/ (動的セグメントは _id_.tsx ファイル)。最初のセグメントごとにグループ化:
| エリア | ルート |
|---|---|
* | * |
500 | /500 |
admin | /admin/analytics /admin/feature-flags |
ai | /ai |
analytics | /analytics/history /analytics |
auth | /auth/forgot-password /auth/magic-link /auth/magic-link/verify /auth/reset-password /auth/signin /auth/signup /auth/two-factor /auth/verify-email /auth/verify |
cad | /cad |
cam | /cam |
costs | /costs |
components | /components/:id /components |
drawings | /drawings/:id |
/ | / |
invitations | /invitations/:token |
legal | /legal/privacy /legal/terms /legal/third-party-licenses |
library | /library |
machine | /machine/:id /machine |
marketplace | /marketplace /marketplace/items/:id /marketplace/purchase/success /marketplace/purchases /marketplace/seller/dashboard |
materials | /materials/:id /materials |
mcp | /mcp/directory /mcp/servers/:id |
offline | /offline |
organizations | /organizations/:id /organizations/:id/chat/:conversationId /organizations/:id/chat /organizations/:id/chat/new-group /organizations/:id/chat/new /organizations/create /organizations |
plugins | /plugins/:id /plugins |
pricing | /pricing |
profile | /profile /profile/settings |
projects | /projects/:id/history /projects/:id /projects/create /projects |
settings | /settings /settings/companion /settings/mcp/config-editor /settings/mcp/edit/:id /settings/mcp /settings/subscription |
third-party-licenses | /third-party-licenses |
toolpaths | /toolpaths/:id /toolpaths |
tools | /tools/:id /tools |
waitlist | /waitlist |
* 404 ページをレンダリングし、 /500 エラーページ。 /offline renders the offline screen;認証、招待、404、500、購入成功ページと同様に、アプリ Chrome を使用しないスタンドアロン レイアウトが使用されます。すべてのページは遅延インポートであるため、画面のコードは最初の訪問時にのみロードされます。失敗したチャンクロードは、空のアプリではなく、ルート エラーとして表面化します。