@flightdev/desktop 0.2.0

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2026 Flight Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,184 @@
1
+ # @flight-framework/desktop
2
+
3
+ Desktop app support for Flight Framework via Tauri. Build Windows, macOS, and Linux apps with the same codebase.
4
+
5
+ ## Philosophy
6
+
7
+ **Flight doesn't impose** - install only the Tauri plugins you need. All plugins are optional peer dependencies. Hooks gracefully degrade on web.
8
+
9
+ ## Features
10
+
11
+ - **Cross-platform** - Windows, macOS, Linux from one codebase
12
+ - **React hooks** - useWindow, useFileSystem, useDialog, and more
13
+ - **Vue composables** - Reactive wrappers for Tauri APIs
14
+ - **Tauri powered** - Rust backend, tiny bundle size
15
+ - **Plugin freedom** - Install only what you need
16
+ - **Web fallback** - Graceful degradation
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ # Core package
22
+ npm install @flight-framework/desktop
23
+
24
+ # Install Tauri CLI and plugins you need
25
+ npm install @tauri-apps/cli @tauri-apps/api
26
+ npm install @tauri-apps/plugin-dialog # Optional
27
+ npm install @tauri-apps/plugin-fs # Optional
28
+ npm install @tauri-apps/plugin-shell # Optional
29
+ npm install @tauri-apps/plugin-clipboard-manager # Optional
30
+ ```
31
+
32
+ ## Quick Start
33
+
34
+ ### React
35
+
36
+ ```tsx
37
+ import { usePlatform, useWindow, useFileSystem, useDialog } from '@flight-framework/desktop/react';
38
+
39
+ function App() {
40
+ const { isDesktop, isMac, isWindows } = usePlatform();
41
+ const { minimize, maximize, close, isMaximized } = useWindow();
42
+ const { readFile, writeFile } = useFileSystem();
43
+ const { selectFile, saveFile } = useDialog();
44
+
45
+ return (
46
+ <div>
47
+ {/* Custom titlebar */}
48
+ <div data-tauri-drag-region className="titlebar">
49
+ <button onClick={minimize}>_</button>
50
+ <button onClick={maximize}>[max]</button>
51
+ <button onClick={close}>×</button>
52
+ </div>
53
+
54
+ <button onClick={async () => {
55
+ const path = await selectFile();
56
+ if (path) {
57
+ const content = await readFile(path as string);
58
+ console.log(content);
59
+ }
60
+ }}>
61
+ Open File
62
+ </button>
63
+ </div>
64
+ );
65
+ }
66
+ ```
67
+
68
+ ### Vue
69
+
70
+ ```vue
71
+ <script setup>
72
+ import { usePlatform, useWindow, useDialog } from '@flight-framework/desktop/vue';
73
+
74
+ const { isDesktop, isMac } = usePlatform();
75
+ const { minimize, maximize, close, isMaximized } = useWindow();
76
+ const { selectFile, message } = useDialog();
77
+ </script>
78
+
79
+ <template>
80
+ <div v-if="isDesktop" class="titlebar" data-tauri-drag-region>
81
+ <button @click="minimize">_</button>
82
+ <button @click="maximize">[max]</button>
83
+ <button @click="close">×</button>
84
+ </div>
85
+ </template>
86
+ ```
87
+
88
+ ## Hooks
89
+
90
+ ### usePlatform
91
+
92
+ Detect platform.
93
+
94
+ ```typescript
95
+ const { platform, isDesktop, isWindows, isMac, isLinux, isWeb } = usePlatform();
96
+ ```
97
+
98
+ ### useWindow
99
+
100
+ Control window.
101
+
102
+ ```typescript
103
+ const { minimize, maximize, close, setTitle, isMaximized, isFullscreen } = useWindow();
104
+ ```
105
+
106
+ ### useFileSystem
107
+
108
+ Read/write files.
109
+
110
+ ```typescript
111
+ const { readFile, writeFile, exists, mkdir, readDir } = useFileSystem();
112
+
113
+ const content = await readFile('/path/to/file.txt');
114
+ await writeFile('/path/to/file.txt', 'Hello World');
115
+ ```
116
+
117
+ ### useDialog
118
+
119
+ Native dialogs.
120
+
121
+ ```typescript
122
+ const { selectFile, selectFolder, saveFile, message, confirm } = useDialog();
123
+
124
+ const path = await selectFile({ filters: [{ name: 'Text', extensions: ['txt'] }] });
125
+ const folder = await selectFolder();
126
+ const confirmed = await confirm('Delete this file?');
127
+ ```
128
+
129
+ ### useClipboard
130
+
131
+ Copy/paste.
132
+
133
+ ```typescript
134
+ const { read, write } = useClipboard();
135
+
136
+ await write('Copied text');
137
+ const text = await read();
138
+ ```
139
+
140
+ ### useShell
141
+
142
+ Open URLs and paths.
143
+
144
+ ```typescript
145
+ const { openUrl, openPath } = useShell();
146
+
147
+ await openUrl('https://example.com');
148
+ await openPath('/path/to/folder');
149
+ ```
150
+
151
+ ## Configuration
152
+
153
+ ```typescript
154
+ // tauri.conf.json helper
155
+ import { defineDesktopConfig } from '@flight-framework/desktop/config';
156
+
157
+ export default defineDesktopConfig({
158
+ identifier: 'com.example.myapp',
159
+ productName: 'My App',
160
+ mainWindow: {
161
+ title: 'My App',
162
+ width: 1200,
163
+ height: 800,
164
+ decorations: false, // Custom titlebar
165
+ },
166
+ });
167
+ ```
168
+
169
+ ## Build Commands
170
+
171
+ ```bash
172
+ # Initialize Tauri
173
+ npx tauri init
174
+
175
+ # Development
176
+ npx tauri dev
177
+
178
+ # Build for production
179
+ npx tauri build
180
+ ```
181
+
182
+ ## License
183
+
184
+ MIT
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Tauri configuration helper.
3
+ * Creates type-safe configuration for desktop builds.
4
+ */
5
+ interface DesktopConfig {
6
+ /** Bundle identifier (com.example.app) */
7
+ identifier: string;
8
+ /** Display name of the app */
9
+ productName: string;
10
+ /** App version */
11
+ version?: string;
12
+ /** App icon path */
13
+ icon?: string[];
14
+ /** Build targets */
15
+ targets?: {
16
+ windows?: ('msi' | 'nsis' | 'exe')[];
17
+ macos?: ('dmg' | 'app')[];
18
+ linux?: ('deb' | 'appimage' | 'rpm')[];
19
+ };
20
+ /** Main window configuration */
21
+ mainWindow?: {
22
+ title?: string;
23
+ width?: number;
24
+ height?: number;
25
+ minWidth?: number;
26
+ minHeight?: number;
27
+ resizable?: boolean;
28
+ fullscreen?: boolean;
29
+ transparent?: boolean;
30
+ decorations?: boolean;
31
+ alwaysOnTop?: boolean;
32
+ center?: boolean;
33
+ };
34
+ /** Security settings */
35
+ security?: {
36
+ dangerousDisableAssetCspModification?: boolean;
37
+ csp?: string;
38
+ };
39
+ /** Plugins to enable */
40
+ plugins?: {
41
+ dialog?: boolean;
42
+ fs?: boolean;
43
+ shell?: boolean;
44
+ clipboard?: boolean;
45
+ notification?: boolean;
46
+ };
47
+ }
48
+ /**
49
+ * Create a Tauri configuration.
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * // tauri.conf.json or src-tauri/tauri.conf.json
54
+ * import { defineDesktopConfig } from '@flightdev/desktop/config';
55
+ *
56
+ * export default defineDesktopConfig({
57
+ * identifier: 'com.example.myapp',
58
+ * productName: 'My App',
59
+ * mainWindow: {
60
+ * title: 'My App',
61
+ * width: 1200,
62
+ * height: 800,
63
+ * },
64
+ * });
65
+ * ```
66
+ */
67
+ declare function defineDesktopConfig(config: DesktopConfig): {
68
+ $schema: string;
69
+ productName: string;
70
+ version: string;
71
+ identifier: string;
72
+ build: {
73
+ frontendDist: string;
74
+ devUrl: string;
75
+ beforeDevCommand: string;
76
+ beforeBuildCommand: string;
77
+ };
78
+ bundle: {
79
+ active: boolean;
80
+ icon: string[];
81
+ targets: string;
82
+ };
83
+ app: {
84
+ windows: {
85
+ title: string;
86
+ width: number;
87
+ height: number;
88
+ minWidth: number | undefined;
89
+ minHeight: number | undefined;
90
+ resizable: boolean;
91
+ fullscreen: boolean;
92
+ transparent: boolean;
93
+ decorations: boolean;
94
+ alwaysOnTop: boolean;
95
+ center: boolean;
96
+ }[];
97
+ security: {
98
+ csp: string;
99
+ };
100
+ };
101
+ plugins: {};
102
+ };
103
+ /**
104
+ * Generate Cargo.toml features based on config.
105
+ */
106
+ declare function getCargoFeatures(config: DesktopConfig): string[];
107
+
108
+ export { type DesktopConfig, defineDesktopConfig, getCargoFeatures };
package/dist/config.js ADDED
@@ -0,0 +1,54 @@
1
+ // src/config.ts
2
+ function defineDesktopConfig(config) {
3
+ return {
4
+ $schema: "../node_modules/@tauri-apps/cli/config.schema.json",
5
+ productName: config.productName,
6
+ version: config.version ?? "0.1.0",
7
+ identifier: config.identifier,
8
+ build: {
9
+ frontendDist: "../dist",
10
+ devUrl: "http://localhost:5173",
11
+ beforeDevCommand: "npm run dev",
12
+ beforeBuildCommand: "npm run build"
13
+ },
14
+ bundle: {
15
+ active: true,
16
+ icon: config.icon ?? ["icons/32x32.png", "icons/128x128.png", "icons/icon.icns", "icons/icon.ico"],
17
+ targets: "all"
18
+ },
19
+ app: {
20
+ windows: [
21
+ {
22
+ title: config.mainWindow?.title ?? config.productName,
23
+ width: config.mainWindow?.width ?? 1024,
24
+ height: config.mainWindow?.height ?? 768,
25
+ minWidth: config.mainWindow?.minWidth,
26
+ minHeight: config.mainWindow?.minHeight,
27
+ resizable: config.mainWindow?.resizable ?? true,
28
+ fullscreen: config.mainWindow?.fullscreen ?? false,
29
+ transparent: config.mainWindow?.transparent ?? false,
30
+ decorations: config.mainWindow?.decorations ?? true,
31
+ alwaysOnTop: config.mainWindow?.alwaysOnTop ?? false,
32
+ center: config.mainWindow?.center ?? true
33
+ }
34
+ ],
35
+ security: {
36
+ csp: config.security?.csp ?? "default-src 'self'; style-src 'self' 'unsafe-inline'"
37
+ }
38
+ },
39
+ plugins: {}
40
+ };
41
+ }
42
+ function getCargoFeatures(config) {
43
+ const features = [];
44
+ if (config.plugins?.dialog) features.push("dialog");
45
+ if (config.plugins?.fs) features.push("fs");
46
+ if (config.plugins?.shell) features.push("shell");
47
+ if (config.plugins?.clipboard) features.push("clipboard");
48
+ if (config.plugins?.notification) features.push("notification");
49
+ return features;
50
+ }
51
+
52
+ export { defineDesktopConfig, getCargoFeatures };
53
+ //# sourceMappingURL=config.js.map
54
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts"],"names":[],"mappings":";AA4EO,SAAS,oBAAoB,MAAA,EAAuB;AACvD,EAAA,OAAO;AAAA,IACH,OAAA,EAAS,oDAAA;AAAA,IACT,aAAa,MAAA,CAAO,WAAA;AAAA,IACpB,OAAA,EAAS,OAAO,OAAA,IAAW,OAAA;AAAA,IAC3B,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB,KAAA,EAAO;AAAA,MACH,YAAA,EAAc,SAAA;AAAA,MACd,MAAA,EAAQ,uBAAA;AAAA,MACR,gBAAA,EAAkB,aAAA;AAAA,MAClB,kBAAA,EAAoB;AAAA,KACxB;AAAA,IACA,MAAA,EAAQ;AAAA,MACJ,MAAA,EAAQ,IAAA;AAAA,MACR,MAAM,MAAA,CAAO,IAAA,IAAQ,CAAC,iBAAA,EAAmB,mBAAA,EAAqB,mBAAmB,gBAAgB,CAAA;AAAA,MACjG,OAAA,EAAS;AAAA,KACb;AAAA,IACA,GAAA,EAAK;AAAA,MACD,OAAA,EAAS;AAAA,QACL;AAAA,UACI,KAAA,EAAO,MAAA,CAAO,UAAA,EAAY,KAAA,IAAS,MAAA,CAAO,WAAA;AAAA,UAC1C,KAAA,EAAO,MAAA,CAAO,UAAA,EAAY,KAAA,IAAS,IAAA;AAAA,UACnC,MAAA,EAAQ,MAAA,CAAO,UAAA,EAAY,MAAA,IAAU,GAAA;AAAA,UACrC,QAAA,EAAU,OAAO,UAAA,EAAY,QAAA;AAAA,UAC7B,SAAA,EAAW,OAAO,UAAA,EAAY,SAAA;AAAA,UAC9B,SAAA,EAAW,MAAA,CAAO,UAAA,EAAY,SAAA,IAAa,IAAA;AAAA,UAC3C,UAAA,EAAY,MAAA,CAAO,UAAA,EAAY,UAAA,IAAc,KAAA;AAAA,UAC7C,WAAA,EAAa,MAAA,CAAO,UAAA,EAAY,WAAA,IAAe,KAAA;AAAA,UAC/C,WAAA,EAAa,MAAA,CAAO,UAAA,EAAY,WAAA,IAAe,IAAA;AAAA,UAC/C,WAAA,EAAa,MAAA,CAAO,UAAA,EAAY,WAAA,IAAe,KAAA;AAAA,UAC/C,MAAA,EAAQ,MAAA,CAAO,UAAA,EAAY,MAAA,IAAU;AAAA;AACzC,OACJ;AAAA,MACA,QAAA,EAAU;AAAA,QACN,GAAA,EAAK,MAAA,CAAO,QAAA,EAAU,GAAA,IAAO;AAAA;AACjC,KACJ;AAAA,IACA,SAAS;AAAC,GACd;AACJ;AAKO,SAAS,iBAAiB,MAAA,EAAiC;AAC9D,EAAA,MAAM,WAAqB,EAAC;AAE5B,EAAA,IAAI,MAAA,CAAO,OAAA,EAAS,MAAA,EAAQ,QAAA,CAAS,KAAK,QAAQ,CAAA;AAClD,EAAA,IAAI,MAAA,CAAO,OAAA,EAAS,EAAA,EAAI,QAAA,CAAS,KAAK,IAAI,CAAA;AAC1C,EAAA,IAAI,MAAA,CAAO,OAAA,EAAS,KAAA,EAAO,QAAA,CAAS,KAAK,OAAO,CAAA;AAChD,EAAA,IAAI,MAAA,CAAO,OAAA,EAAS,SAAA,EAAW,QAAA,CAAS,KAAK,WAAW,CAAA;AACxD,EAAA,IAAI,MAAA,CAAO,OAAA,EAAS,YAAA,EAAc,QAAA,CAAS,KAAK,cAAc,CAAA;AAE9D,EAAA,OAAO,QAAA;AACX","file":"config.js","sourcesContent":["/**\r\n * Tauri configuration helper.\r\n * Creates type-safe configuration for desktop builds.\r\n */\r\n\r\n// =============================================================================\r\n// Types\r\n// =============================================================================\r\n\r\nexport interface DesktopConfig {\r\n /** Bundle identifier (com.example.app) */\r\n identifier: string;\r\n /** Display name of the app */\r\n productName: string;\r\n /** App version */\r\n version?: string;\r\n /** App icon path */\r\n icon?: string[];\r\n /** Build targets */\r\n targets?: {\r\n windows?: ('msi' | 'nsis' | 'exe')[];\r\n macos?: ('dmg' | 'app')[];\r\n linux?: ('deb' | 'appimage' | 'rpm')[];\r\n };\r\n /** Main window configuration */\r\n mainWindow?: {\r\n title?: string;\r\n width?: number;\r\n height?: number;\r\n minWidth?: number;\r\n minHeight?: number;\r\n resizable?: boolean;\r\n fullscreen?: boolean;\r\n transparent?: boolean;\r\n decorations?: boolean;\r\n alwaysOnTop?: boolean;\r\n center?: boolean;\r\n };\r\n /** Security settings */\r\n security?: {\r\n dangerousDisableAssetCspModification?: boolean;\r\n csp?: string;\r\n };\r\n /** Plugins to enable */\r\n plugins?: {\r\n dialog?: boolean;\r\n fs?: boolean;\r\n shell?: boolean;\r\n clipboard?: boolean;\r\n notification?: boolean;\r\n };\r\n}\r\n\r\n// =============================================================================\r\n// Factory\r\n// =============================================================================\r\n\r\n/**\r\n * Create a Tauri configuration.\r\n * \r\n * @example\r\n * ```typescript\r\n * // tauri.conf.json or src-tauri/tauri.conf.json\r\n * import { defineDesktopConfig } from '@flightdev/desktop/config';\r\n * \r\n * export default defineDesktopConfig({\r\n * identifier: 'com.example.myapp',\r\n * productName: 'My App',\r\n * mainWindow: {\r\n * title: 'My App',\r\n * width: 1200,\r\n * height: 800,\r\n * },\r\n * });\r\n * ```\r\n */\r\nexport function defineDesktopConfig(config: DesktopConfig) {\r\n return {\r\n $schema: '../node_modules/@tauri-apps/cli/config.schema.json',\r\n productName: config.productName,\r\n version: config.version ?? '0.1.0',\r\n identifier: config.identifier,\r\n build: {\r\n frontendDist: '../dist',\r\n devUrl: 'http://localhost:5173',\r\n beforeDevCommand: 'npm run dev',\r\n beforeBuildCommand: 'npm run build',\r\n },\r\n bundle: {\r\n active: true,\r\n icon: config.icon ?? ['icons/32x32.png', 'icons/128x128.png', 'icons/icon.icns', 'icons/icon.ico'],\r\n targets: 'all',\r\n },\r\n app: {\r\n windows: [\r\n {\r\n title: config.mainWindow?.title ?? config.productName,\r\n width: config.mainWindow?.width ?? 1024,\r\n height: config.mainWindow?.height ?? 768,\r\n minWidth: config.mainWindow?.minWidth,\r\n minHeight: config.mainWindow?.minHeight,\r\n resizable: config.mainWindow?.resizable ?? true,\r\n fullscreen: config.mainWindow?.fullscreen ?? false,\r\n transparent: config.mainWindow?.transparent ?? false,\r\n decorations: config.mainWindow?.decorations ?? true,\r\n alwaysOnTop: config.mainWindow?.alwaysOnTop ?? false,\r\n center: config.mainWindow?.center ?? true,\r\n },\r\n ],\r\n security: {\r\n csp: config.security?.csp ?? \"default-src 'self'; style-src 'self' 'unsafe-inline'\",\r\n },\r\n },\r\n plugins: {},\r\n };\r\n}\r\n\r\n/**\r\n * Generate Cargo.toml features based on config.\r\n */\r\nexport function getCargoFeatures(config: DesktopConfig): string[] {\r\n const features: string[] = [];\r\n\r\n if (config.plugins?.dialog) features.push('dialog');\r\n if (config.plugins?.fs) features.push('fs');\r\n if (config.plugins?.shell) features.push('shell');\r\n if (config.plugins?.clipboard) features.push('clipboard');\r\n if (config.plugins?.notification) features.push('notification');\r\n\r\n return features;\r\n}\r\n"]}
@@ -0,0 +1,55 @@
1
+ export { DesktopConfig, defineDesktopConfig, getCargoFeatures } from './config.js';
2
+
3
+ /**
4
+ * @flightdev/desktop
5
+ *
6
+ * Desktop app support for Flight Framework via Tauri.
7
+ * Build Windows, macOS, and Linux apps with the same codebase.
8
+ *
9
+ * Philosophy: Flight doesn't impose - install only the Tauri plugins you need.
10
+ * All plugins are optional peer dependencies.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { usePlatform, useWindow, useFileSystem } from '@flightdev/desktop/react';
15
+ *
16
+ * function App() {
17
+ * const { isDesktop, isMac, isWindows } = usePlatform();
18
+ * const { minimize, maximize, close } = useWindow();
19
+ * const { readFile, writeFile, selectFile } = useFileSystem();
20
+ *
21
+ * return isDesktop ? <DesktopApp /> : <WebApp />;
22
+ * }
23
+ * ```
24
+ */
25
+ type Platform = 'windows' | 'macos' | 'linux' | 'web';
26
+ interface DesktopPlatformInfo {
27
+ /** Current platform */
28
+ platform: Platform;
29
+ /** True if running as desktop app */
30
+ isDesktop: boolean;
31
+ /** True if running on Windows */
32
+ isWindows: boolean;
33
+ /** True if running on macOS */
34
+ isMac: boolean;
35
+ /** True if running on Linux */
36
+ isLinux: boolean;
37
+ /** True if running as web app */
38
+ isWeb: boolean;
39
+ /** True if Tauri is available */
40
+ hasTauri: boolean;
41
+ }
42
+ /**
43
+ * Check if running in Tauri desktop environment.
44
+ */
45
+ declare function isTauri(): boolean;
46
+ /**
47
+ * Get current desktop platform.
48
+ */
49
+ declare function getPlatform(): DesktopPlatformInfo;
50
+ /**
51
+ * Check if a Tauri plugin is available.
52
+ */
53
+ declare function isPluginAvailable(pluginName: string): boolean;
54
+
55
+ export { type DesktopPlatformInfo, type Platform, getPlatform, isPluginAvailable, isTauri };
package/dist/index.js ADDED
@@ -0,0 +1,102 @@
1
+ // src/config.ts
2
+ function defineDesktopConfig(config) {
3
+ return {
4
+ $schema: "../node_modules/@tauri-apps/cli/config.schema.json",
5
+ productName: config.productName,
6
+ version: config.version ?? "0.1.0",
7
+ identifier: config.identifier,
8
+ build: {
9
+ frontendDist: "../dist",
10
+ devUrl: "http://localhost:5173",
11
+ beforeDevCommand: "npm run dev",
12
+ beforeBuildCommand: "npm run build"
13
+ },
14
+ bundle: {
15
+ active: true,
16
+ icon: config.icon ?? ["icons/32x32.png", "icons/128x128.png", "icons/icon.icns", "icons/icon.ico"],
17
+ targets: "all"
18
+ },
19
+ app: {
20
+ windows: [
21
+ {
22
+ title: config.mainWindow?.title ?? config.productName,
23
+ width: config.mainWindow?.width ?? 1024,
24
+ height: config.mainWindow?.height ?? 768,
25
+ minWidth: config.mainWindow?.minWidth,
26
+ minHeight: config.mainWindow?.minHeight,
27
+ resizable: config.mainWindow?.resizable ?? true,
28
+ fullscreen: config.mainWindow?.fullscreen ?? false,
29
+ transparent: config.mainWindow?.transparent ?? false,
30
+ decorations: config.mainWindow?.decorations ?? true,
31
+ alwaysOnTop: config.mainWindow?.alwaysOnTop ?? false,
32
+ center: config.mainWindow?.center ?? true
33
+ }
34
+ ],
35
+ security: {
36
+ csp: config.security?.csp ?? "default-src 'self'; style-src 'self' 'unsafe-inline'"
37
+ }
38
+ },
39
+ plugins: {}
40
+ };
41
+ }
42
+ function getCargoFeatures(config) {
43
+ const features = [];
44
+ if (config.plugins?.dialog) features.push("dialog");
45
+ if (config.plugins?.fs) features.push("fs");
46
+ if (config.plugins?.shell) features.push("shell");
47
+ if (config.plugins?.clipboard) features.push("clipboard");
48
+ if (config.plugins?.notification) features.push("notification");
49
+ return features;
50
+ }
51
+
52
+ // src/index.ts
53
+ function getTauri() {
54
+ try {
55
+ return globalThis.__TAURI__;
56
+ } catch {
57
+ return null;
58
+ }
59
+ }
60
+ function isTauri() {
61
+ return getTauri() !== null;
62
+ }
63
+ function getPlatform() {
64
+ const tauri = getTauri();
65
+ if (!tauri) {
66
+ return {
67
+ platform: "web",
68
+ isDesktop: false,
69
+ isWindows: false,
70
+ isMac: false,
71
+ isLinux: false,
72
+ isWeb: true,
73
+ hasTauri: false
74
+ };
75
+ }
76
+ const userAgent = navigator.userAgent.toLowerCase();
77
+ let platform = "web";
78
+ if (userAgent.includes("win")) {
79
+ platform = "windows";
80
+ } else if (userAgent.includes("mac")) {
81
+ platform = "macos";
82
+ } else if (userAgent.includes("linux")) {
83
+ platform = "linux";
84
+ }
85
+ return {
86
+ platform,
87
+ isDesktop: true,
88
+ isWindows: platform === "windows",
89
+ isMac: platform === "macos",
90
+ isLinux: platform === "linux",
91
+ isWeb: false,
92
+ hasTauri: true
93
+ };
94
+ }
95
+ function isPluginAvailable(pluginName) {
96
+ const tauri = getTauri();
97
+ return tauri && typeof tauri[pluginName] !== "undefined";
98
+ }
99
+
100
+ export { defineDesktopConfig, getCargoFeatures, getPlatform, isPluginAvailable, isTauri };
101
+ //# sourceMappingURL=index.js.map
102
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * Tauri configuration helper.\r\n * Creates type-safe configuration for desktop builds.\r\n */\r\n\r\n// =============================================================================\r\n// Types\r\n// =============================================================================\r\n\r\nexport interface DesktopConfig {\r\n /** Bundle identifier (com.example.app) */\r\n identifier: string;\r\n /** Display name of the app */\r\n productName: string;\r\n /** App version */\r\n version?: string;\r\n /** App icon path */\r\n icon?: string[];\r\n /** Build targets */\r\n targets?: {\r\n windows?: ('msi' | 'nsis' | 'exe')[];\r\n macos?: ('dmg' | 'app')[];\r\n linux?: ('deb' | 'appimage' | 'rpm')[];\r\n };\r\n /** Main window configuration */\r\n mainWindow?: {\r\n title?: string;\r\n width?: number;\r\n height?: number;\r\n minWidth?: number;\r\n minHeight?: number;\r\n resizable?: boolean;\r\n fullscreen?: boolean;\r\n transparent?: boolean;\r\n decorations?: boolean;\r\n alwaysOnTop?: boolean;\r\n center?: boolean;\r\n };\r\n /** Security settings */\r\n security?: {\r\n dangerousDisableAssetCspModification?: boolean;\r\n csp?: string;\r\n };\r\n /** Plugins to enable */\r\n plugins?: {\r\n dialog?: boolean;\r\n fs?: boolean;\r\n shell?: boolean;\r\n clipboard?: boolean;\r\n notification?: boolean;\r\n };\r\n}\r\n\r\n// =============================================================================\r\n// Factory\r\n// =============================================================================\r\n\r\n/**\r\n * Create a Tauri configuration.\r\n * \r\n * @example\r\n * ```typescript\r\n * // tauri.conf.json or src-tauri/tauri.conf.json\r\n * import { defineDesktopConfig } from '@flightdev/desktop/config';\r\n * \r\n * export default defineDesktopConfig({\r\n * identifier: 'com.example.myapp',\r\n * productName: 'My App',\r\n * mainWindow: {\r\n * title: 'My App',\r\n * width: 1200,\r\n * height: 800,\r\n * },\r\n * });\r\n * ```\r\n */\r\nexport function defineDesktopConfig(config: DesktopConfig) {\r\n return {\r\n $schema: '../node_modules/@tauri-apps/cli/config.schema.json',\r\n productName: config.productName,\r\n version: config.version ?? '0.1.0',\r\n identifier: config.identifier,\r\n build: {\r\n frontendDist: '../dist',\r\n devUrl: 'http://localhost:5173',\r\n beforeDevCommand: 'npm run dev',\r\n beforeBuildCommand: 'npm run build',\r\n },\r\n bundle: {\r\n active: true,\r\n icon: config.icon ?? ['icons/32x32.png', 'icons/128x128.png', 'icons/icon.icns', 'icons/icon.ico'],\r\n targets: 'all',\r\n },\r\n app: {\r\n windows: [\r\n {\r\n title: config.mainWindow?.title ?? config.productName,\r\n width: config.mainWindow?.width ?? 1024,\r\n height: config.mainWindow?.height ?? 768,\r\n minWidth: config.mainWindow?.minWidth,\r\n minHeight: config.mainWindow?.minHeight,\r\n resizable: config.mainWindow?.resizable ?? true,\r\n fullscreen: config.mainWindow?.fullscreen ?? false,\r\n transparent: config.mainWindow?.transparent ?? false,\r\n decorations: config.mainWindow?.decorations ?? true,\r\n alwaysOnTop: config.mainWindow?.alwaysOnTop ?? false,\r\n center: config.mainWindow?.center ?? true,\r\n },\r\n ],\r\n security: {\r\n csp: config.security?.csp ?? \"default-src 'self'; style-src 'self' 'unsafe-inline'\",\r\n },\r\n },\r\n plugins: {},\r\n };\r\n}\r\n\r\n/**\r\n * Generate Cargo.toml features based on config.\r\n */\r\nexport function getCargoFeatures(config: DesktopConfig): string[] {\r\n const features: string[] = [];\r\n\r\n if (config.plugins?.dialog) features.push('dialog');\r\n if (config.plugins?.fs) features.push('fs');\r\n if (config.plugins?.shell) features.push('shell');\r\n if (config.plugins?.clipboard) features.push('clipboard');\r\n if (config.plugins?.notification) features.push('notification');\r\n\r\n return features;\r\n}\r\n","/**\r\n * @flightdev/desktop\r\n * \r\n * Desktop app support for Flight Framework via Tauri.\r\n * Build Windows, macOS, and Linux apps with the same codebase.\r\n * \r\n * Philosophy: Flight doesn't impose - install only the Tauri plugins you need.\r\n * All plugins are optional peer dependencies.\r\n * \r\n * @example\r\n * ```typescript\r\n * import { usePlatform, useWindow, useFileSystem } from '@flightdev/desktop/react';\r\n * \r\n * function App() {\r\n * const { isDesktop, isMac, isWindows } = usePlatform();\r\n * const { minimize, maximize, close } = useWindow();\r\n * const { readFile, writeFile, selectFile } = useFileSystem();\r\n * \r\n * return isDesktop ? <DesktopApp /> : <WebApp />;\r\n * }\r\n * ```\r\n */\r\n\r\n// =============================================================================\r\n// Types\r\n// =============================================================================\r\n\r\nexport type Platform = 'windows' | 'macos' | 'linux' | 'web';\r\n\r\nexport interface DesktopPlatformInfo {\r\n /** Current platform */\r\n platform: Platform;\r\n /** True if running as desktop app */\r\n isDesktop: boolean;\r\n /** True if running on Windows */\r\n isWindows: boolean;\r\n /** True if running on macOS */\r\n isMac: boolean;\r\n /** True if running on Linux */\r\n isLinux: boolean;\r\n /** True if running as web app */\r\n isWeb: boolean;\r\n /** True if Tauri is available */\r\n hasTauri: boolean;\r\n}\r\n\r\n// =============================================================================\r\n// Detection\r\n// =============================================================================\r\n\r\n/**\r\n * Check if Tauri is available.\r\n */\r\nfunction getTauri(): any {\r\n try {\r\n return (globalThis as any).__TAURI__;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Check if running in Tauri desktop environment.\r\n */\r\nexport function isTauri(): boolean {\r\n return getTauri() !== null;\r\n}\r\n\r\n/**\r\n * Get current desktop platform.\r\n */\r\nexport function getPlatform(): DesktopPlatformInfo {\r\n const tauri = getTauri();\r\n\r\n if (!tauri) {\r\n return {\r\n platform: 'web',\r\n isDesktop: false,\r\n isWindows: false,\r\n isMac: false,\r\n isLinux: false,\r\n isWeb: true,\r\n hasTauri: false,\r\n };\r\n }\r\n\r\n // Detect OS from navigator\r\n const userAgent = navigator.userAgent.toLowerCase();\r\n let platform: Platform = 'web';\r\n\r\n if (userAgent.includes('win')) {\r\n platform = 'windows';\r\n } else if (userAgent.includes('mac')) {\r\n platform = 'macos';\r\n } else if (userAgent.includes('linux')) {\r\n platform = 'linux';\r\n }\r\n\r\n return {\r\n platform,\r\n isDesktop: true,\r\n isWindows: platform === 'windows',\r\n isMac: platform === 'macos',\r\n isLinux: platform === 'linux',\r\n isWeb: false,\r\n hasTauri: true,\r\n };\r\n}\r\n\r\n/**\r\n * Check if a Tauri plugin is available.\r\n */\r\nexport function isPluginAvailable(pluginName: string): boolean {\r\n const tauri = getTauri();\r\n return tauri && typeof tauri[pluginName] !== 'undefined';\r\n}\r\n\r\n// =============================================================================\r\n// Re-exports\r\n// =============================================================================\r\n\r\nexport * from './config';\r\n"]}