plusui-native 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.
Files changed (44) hide show
  1. package/README.md +162 -0
  2. package/package.json +36 -0
  3. package/src/assets/icon-generator.js +251 -0
  4. package/src/assets/resource-embedder.js +351 -0
  5. package/src/doctor/detectors/cmake.js +84 -0
  6. package/src/doctor/detectors/compiler.js +145 -0
  7. package/src/doctor/detectors/just.js +45 -0
  8. package/src/doctor/detectors/nodejs.js +57 -0
  9. package/src/doctor/detectors/webview2.js +66 -0
  10. package/src/doctor/index.js +184 -0
  11. package/src/doctor/installers/linux.js +121 -0
  12. package/src/doctor/installers/macos.js +123 -0
  13. package/src/doctor/installers/windows.js +117 -0
  14. package/src/doctor/reporter.js +219 -0
  15. package/src/index.js +904 -0
  16. package/templates/base/Justfile +115 -0
  17. package/templates/base/README.md.template +168 -0
  18. package/templates/base/assets/README.md +88 -0
  19. package/templates/base/assets/icon.png +0 -0
  20. package/templates/manager.js +217 -0
  21. package/templates/react/.vscode/c_cpp_properties.json +24 -0
  22. package/templates/react/CMakeLists.txt.template +151 -0
  23. package/templates/react/frontend/index.html +12 -0
  24. package/templates/react/frontend/package.json.template +24 -0
  25. package/templates/react/frontend/src/App.tsx +134 -0
  26. package/templates/react/frontend/src/main.tsx +10 -0
  27. package/templates/react/frontend/src/styles/app.css +140 -0
  28. package/templates/react/frontend/tsconfig.json +21 -0
  29. package/templates/react/frontend/tsconfig.node.json +11 -0
  30. package/templates/react/frontend/vite.config.ts +14 -0
  31. package/templates/react/main.cpp.template +201 -0
  32. package/templates/react/package.json.template +23 -0
  33. package/templates/solid/.vscode/c_cpp_properties.json +24 -0
  34. package/templates/solid/CMakeLists.txt.template +151 -0
  35. package/templates/solid/frontend/index.html +12 -0
  36. package/templates/solid/frontend/package.json.template +21 -0
  37. package/templates/solid/frontend/src/App.tsx +133 -0
  38. package/templates/solid/frontend/src/main.tsx +5 -0
  39. package/templates/solid/frontend/src/styles/app.css +140 -0
  40. package/templates/solid/frontend/tsconfig.json +22 -0
  41. package/templates/solid/frontend/tsconfig.node.json +11 -0
  42. package/templates/solid/frontend/vite.config.ts +14 -0
  43. package/templates/solid/main.cpp.template +192 -0
  44. package/templates/solid/package.json.template +23 -0
@@ -0,0 +1,115 @@
1
+ # PlusUI Project Justfile
2
+ # Cross-platform build automation
3
+
4
+ # Use PowerShell on Windows, bash on Unix
5
+ set windows-shell := ["powershell.exe", "-NoLogo", "-Command"]
6
+ set shell := ["bash", "-cu"]
7
+
8
+ # Project name (from directory)
9
+ project_name := file_stem(justfile_directory())
10
+
11
+ # Default recipe
12
+ default: dev
13
+
14
+ # ============================================================
15
+ # DEVELOPMENT
16
+ # ============================================================
17
+
18
+ # Start development mode (frontend HMR + C++ app)
19
+ dev:
20
+ npm run dev
21
+
22
+ # Start only frontend dev server (Vite with HMR)
23
+ dev-frontend:
24
+ npm run dev:frontend
25
+
26
+ # Start only backend in watch mode
27
+ dev-backend:
28
+ npm run dev:backend
29
+
30
+ # ============================================================
31
+ # BUILD
32
+ # ============================================================
33
+
34
+ # Build for current platform (dev mode, connects to Vite)
35
+ build:
36
+ npm run build
37
+
38
+ # Build frontend only
39
+ build-frontend:
40
+ npm run build:frontend
41
+
42
+ # Build backend only (production mode)
43
+ build-backend:
44
+ npm run build:backend
45
+
46
+ # Build for all platforms
47
+ build-all:
48
+ npm run build:all
49
+
50
+ # ============================================================
51
+ # PLATFORM-SPECIFIC BUILDS
52
+ # ============================================================
53
+
54
+ # Build for Windows
55
+ build-windows:
56
+ @echo "Building for Windows..."
57
+ cmake -S . -B build/Windows -DCMAKE_BUILD_TYPE=Release
58
+ cmake --build build/Windows --config Release
59
+
60
+ # Build for macOS
61
+ build-macos:
62
+ @echo "Building for macOS..."
63
+ cmake -S . -B build/MacOS -G Xcode -DCMAKE_BUILD_TYPE=Release
64
+ cmake --build build/MacOS --config Release
65
+
66
+ # Build for Linux
67
+ build-linux:
68
+ @echo "Building for Linux..."
69
+ cmake -S . -B build/Linux -DCMAKE_BUILD_TYPE=Release
70
+ cmake --build build/Linux --config Release
71
+
72
+ # ============================================================
73
+ # RUN
74
+ # ============================================================
75
+
76
+ # Run the built application
77
+ run:
78
+ npm run start
79
+
80
+ # ============================================================
81
+ # UTILITIES
82
+ # ============================================================
83
+
84
+ # Clean build artifacts
85
+ clean:
86
+ @echo "Cleaning build artifacts..."
87
+ rm -rf build
88
+ rm -rf frontend/dist
89
+ @echo "Done!"
90
+
91
+ # Clean everything including node_modules
92
+ clean-all: clean
93
+ rm -rf node_modules
94
+ rm -rf frontend/node_modules
95
+
96
+ # Install dependencies
97
+ install:
98
+ npm install
99
+ cd frontend && npm install
100
+
101
+ # Check development environment
102
+ doctor:
103
+ plusui doctor
104
+
105
+ # Fix development environment
106
+ doctor-fix:
107
+ plusui doctor --fix
108
+
109
+ # ============================================================
110
+ # HELP
111
+ # ============================================================
112
+
113
+ # Show available commands
114
+ help:
115
+ @just --list
@@ -0,0 +1,168 @@
1
+ # {{PROJECT_NAME}}
2
+
3
+ A desktop application built with the PlusUI framework.
4
+
5
+ ## Prerequisites
6
+
7
+ Check your development environment:
8
+ ```bash
9
+ plusui doctor
10
+ ```
11
+
12
+ If any tools are missing, run:
13
+ ```bash
14
+ plusui doctor --fix
15
+ ```
16
+
17
+ ## Development
18
+
19
+ Start development server with hot reload:
20
+ ```bash
21
+ npm run dev
22
+ ```
23
+
24
+ This will:
25
+ - Start the Vite dev server with HMR on http://localhost:5173
26
+ - Build and launch the C++ app pointing to the dev server
27
+ - Changes to frontend code reflect instantly
28
+ - Auto-refresh app bindings when `src/features` exists
29
+
30
+ Note: You can still run `npm run bind` manually anytime.
31
+
32
+ ## Bindings (App-level)
33
+
34
+ Generate bindings for your app feature headers:
35
+ ```bash
36
+ npm run bind
37
+ ```
38
+
39
+ Default bindgen paths:
40
+ - Input headers: `src/features`
41
+ - Output: `src/Bindings_Generated`
42
+
43
+ You can also pass custom paths:
44
+ ```bash
45
+ plusui bindgen <featuresDir> <outputDir>
46
+ ```
47
+
48
+ ## Assets & Icons
49
+
50
+ ### App Icon
51
+
52
+ Place your app icon at `assets/icon.png` (512x512+ recommended). Generate platform-specific icons:
53
+
54
+ ```bash
55
+ plusui icons
56
+ ```
57
+
58
+ This creates:
59
+ - **Windows**: `app.ico` for title bar, taskbar, task manager
60
+ - **macOS**: `app.icns` for dock, finder, about dialog
61
+ - **Linux**: Multiple PNG sizes for window managers
62
+ - **Tray**: Small icons for system tray (all platforms)
63
+
64
+ ### Embedded Assets
65
+
66
+ All files in `assets/` are embedded into the final executable. Access them in C++:
67
+
68
+ ```cpp
69
+ #include <plusui/resources.hpp>
70
+ std::string data = plusui::resources::getResource("path/to/file.png");
71
+ ```
72
+
73
+ See `assets/README.md` for details.
74
+
75
+ ## Build
76
+
77
+ ### Build for current platform
78
+ ```bash
79
+ npm run build
80
+ ```
81
+
82
+ Build also auto-refreshes app bindings when `src/features` exists.
83
+
84
+ ### Build for all platforms
85
+ ```bash
86
+ npm run build:all
87
+ ```
88
+
89
+ This creates platform-specific builds in:
90
+ ```
91
+ build/
92
+ ├── Windows/ # Windows executable
93
+ ├── MacOS/ # macOS app bundle
94
+ └── Linux/ # Linux binary
95
+ ```
96
+
97
+ ### Platform-specific builds
98
+ ```bash
99
+ plusui build:windows
100
+ plusui build:macos
101
+ plusui build:linux
102
+ ```
103
+
104
+ ## Run
105
+
106
+ Run the built application:
107
+ ```bash
108
+ npm run start
109
+ ```
110
+
111
+ ## Using Just (Optional)
112
+
113
+ If you have [`just`](https://github.com/casey/just) installed:
114
+
115
+ ```bash
116
+ just dev # Start development mode
117
+ just build # Build for current platform
118
+ just build-all # Build for all platforms
119
+ just run # Run the built application
120
+ just clean # Clean build artifacts
121
+ just help # Show all commands
122
+ ```
123
+
124
+ ## Project Structure
125
+
126
+ ```
127
+ {{PROJECT_NAME}}/
128
+ ├── src/ # C++ backend code
129
+ │ └── main.cpp # Application entry point
130
+ ├── frontend/ # Frontend web code (React + Vite)
131
+ │ ├── src/
132
+ │ │ ├── main.tsx # React entry point
133
+ │ │ ├── App.tsx # Main app component
134
+ │ │ └── styles/ # CSS styles
135
+ │ ├── index.html
136
+ │ └── vite.config.ts
137
+ ├── build/ # Build output (generated)
138
+ ├── CMakeLists.txt # CMake build configuration
139
+ ├── package.json # npm dependencies and scripts
140
+ └── Justfile # Build automation (optional)
141
+ ```
142
+
143
+ ## Calling C++ from TypeScript
144
+
145
+ Use the `plusui-native-core` SDK to interact with the native backend:
146
+
147
+ ```tsx
148
+ import { createPlusUI } from 'plusui-native-core';
149
+
150
+ const plusui = createPlusUI();
151
+
152
+ // Window controls
153
+ await plusui.window.minimize();
154
+ await plusui.window.maximize();
155
+ await plusui.window.close();
156
+
157
+ // Get window info
158
+ const size = await plusui.window.getSize();
159
+ console.log(`Window size: ${size.width}x${size.height}`);
160
+ ```
161
+
162
+ ## Learn More
163
+
164
+ - [PlusUI Documentation](https://github.com/yourorg/plusui)
165
+ - [React Documentation](https://react.dev/)
166
+ - [Vite Documentation](https://vitejs.dev/)
167
+
168
+
@@ -0,0 +1,88 @@
1
+ # Assets Directory
2
+
3
+ ## Icon File
4
+
5
+ Place your app icon as **`icon.png`** (512x512 or larger recommended).
6
+
7
+ This single icon will be automatically converted to all platform-specific formats:
8
+
9
+ ### Windows
10
+ - `icons/windows/app.ico` - Multi-resolution .ico file
11
+ - Used in: Title bar, taskbar, task manager, system tray
12
+
13
+ ### macOS
14
+ - `icons/macos/app.icns` - Apple icon format
15
+ - Used in: Dock, Finder, About dialog, system tray
16
+
17
+ ### Linux
18
+ - `icons/linux/icon_*.png` - Multiple PNG sizes
19
+ - Used in: Window manager, system tray, desktop files
20
+
21
+ ### Tray Icons
22
+ - `icons/tray/tray_16x16.png` - Small tray icon
23
+ - `icons/tray/tray_32x32.png` - Large tray icon
24
+ - Used in: System tray/notification area (all platforms)
25
+
26
+ ## Automatic Generation
27
+
28
+ Run this command to generate all platform icons:
29
+
30
+ ```bash
31
+ plusui icons
32
+ ```
33
+
34
+ Or specify a different source icon:
35
+
36
+ ```bash
37
+ plusui icons path/to/my-icon.png
38
+ ```
39
+
40
+ ## Icon Guidelines
41
+
42
+ - **Format**: PNG with transparency
43
+ - **Size**: 512x512 pixels minimum (1024x1024 recommended)
44
+ - **Design**: Simple, recognizable at small sizes
45
+ - **Colors**: High contrast for visibility
46
+
47
+ ## Other Assets
48
+
49
+ Any other files in this directory will be embedded into your application binary:
50
+
51
+ ```cpp
52
+ #include "generated/assets.h"
53
+
54
+ // Access embedded assets
55
+ const char* data = ASSET_MY_FILE_PNG;
56
+ size_t size = ASSET_MY_FILE_PNG_LEN;
57
+ ```
58
+
59
+ ## Build Integration
60
+
61
+ Assets are automatically processed during build:
62
+
63
+ 1. `plusui icons` - Generates platform-specific icons (manual or in build)
64
+ 2. `plusui build` - Embeds all assets into the binary
65
+ 3. Production binary includes all resources (single executable!)
66
+
67
+ ## Usage in Code
68
+
69
+ ### C++ Backend
70
+ ```cpp
71
+ #include <plusui/resources.hpp>
72
+
73
+ // Load embedded resource
74
+ std::string html = plusui::resources::getResource("index.html");
75
+ std::string icon = plusui::resources::getResource("icons/tray/tray_32x32.png");
76
+ ```
77
+
78
+ ### TypeScript Frontend
79
+ ```typescript
80
+ // Vite handles assets during dev
81
+ import icon from '../assets/icon.png';
82
+
83
+ // In production, assets are served from embedded resources
84
+ ```
85
+
86
+ ---
87
+
88
+ **Note**: The `icons/` subdirectory is auto-generated. Don't edit those files manually!
Binary file
@@ -0,0 +1,217 @@
1
+ import { mkdir, readdir, readFile, writeFile, copyFile, stat } from 'fs/promises';
2
+ import { join, dirname, resolve } from 'path';
3
+ import { existsSync } from 'fs';
4
+ import { fileURLToPath } from 'url';
5
+ import { EnvironmentDoctor } from '../src/doctor/index.js';
6
+ import chalk from 'chalk';
7
+ import { execSync, spawn } from 'child_process';
8
+
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = dirname(__filename);
11
+
12
+ export class TemplateManager {
13
+ constructor() {
14
+ this.templatesDir = __dirname;
15
+ }
16
+
17
+ async create(projectName, options = {}) {
18
+ const template = options.template || 'react';
19
+ const templatePath = join(this.templatesDir, template);
20
+
21
+ console.log(chalk.bold(`\nCreating PlusUI project: ${projectName}\n`));
22
+
23
+ // 1. Check environment first
24
+ console.log(chalk.blue('Checking environment...'));
25
+ const doctor = new EnvironmentDoctor();
26
+ const quickCheck = await doctor.quickCheck();
27
+
28
+ if (!quickCheck.ready) {
29
+ console.log(chalk.red('\n✗ Environment not ready!\n'));
30
+ console.log(chalk.yellow('Run: plusui doctor --fix\n'));
31
+ throw new Error('Environment check failed');
32
+ }
33
+
34
+ console.log(chalk.green('✓ Environment ready\n'));
35
+
36
+ // 2. Create project directory
37
+ console.log(chalk.blue('Creating project structure...'));
38
+ const projectPath = resolve(projectName);
39
+
40
+ if (existsSync(projectPath)) {
41
+ throw new Error(`Directory ${projectName} already exists`);
42
+ }
43
+
44
+ await mkdir(projectPath, { recursive: true });
45
+
46
+ // 3. Prepare template variables
47
+ const variables = {
48
+ PROJECT_NAME: projectName,
49
+ PROJECT_NAME_LOWER: projectName.toLowerCase(),
50
+ PROJECT_VERSION: '0.1.0',
51
+ PLUSUI_CORE_PATH: this.resolvePlusUIPath()
52
+ };
53
+
54
+ // 4. Copy template files
55
+ await this.copyTemplate(templatePath, projectPath, variables);
56
+
57
+ // 5. Copy base files
58
+ const basePath = join(this.templatesDir, 'base');
59
+ await this.copyTemplate(basePath, projectPath, variables, true);
60
+
61
+ console.log(chalk.green('✓ Project structure created\n'));
62
+
63
+ // 6. Install npm dependencies
64
+ console.log(chalk.blue('Installing dependencies...'));
65
+ await this.runNpmInstall(projectPath);
66
+ console.log(chalk.green('✓ Dependencies installed\n'));
67
+
68
+ // 7. Print success message
69
+ this.printSuccessMessage(projectName);
70
+
71
+ return { success: true, path: projectPath };
72
+ }
73
+
74
+ async copyTemplate(templatePath, destPath, variables, skipSubdirs = false) {
75
+ if (!existsSync(templatePath)) {
76
+ return;
77
+ }
78
+
79
+ const entries = await readdir(templatePath, { withFileTypes: true });
80
+
81
+ for (const entry of entries) {
82
+ const srcPath = join(templatePath, entry.name);
83
+ const destName = entry.name.replace('.template', '');
84
+ const destFilePath = join(destPath, destName);
85
+
86
+ if (entry.isDirectory()) {
87
+ if (!skipSubdirs) {
88
+ await mkdir(destFilePath, { recursive: true });
89
+ await this.copyTemplate(srcPath, destFilePath, variables, false);
90
+ }
91
+ } else {
92
+ // Ensure parent directory exists
93
+ await mkdir(dirname(destFilePath), { recursive: true });
94
+
95
+ // Read file content
96
+ let content = await readFile(srcPath, 'utf8');
97
+
98
+ // Replace variables
99
+ content = this.replaceVariables(content, variables);
100
+
101
+ // Write to destination
102
+ await writeFile(destFilePath, content, 'utf8');
103
+ }
104
+ }
105
+ }
106
+
107
+ replaceVariables(content, variables) {
108
+ let result = content;
109
+
110
+ for (const [key, value] of Object.entries(variables)) {
111
+ const placeholder = `{{${key}}}`;
112
+ result = result.split(placeholder).join(value);
113
+ }
114
+
115
+ return result;
116
+ }
117
+
118
+ resolvePlusUIPath() {
119
+ // Strategy:
120
+ // 1. Check for global plusui-native-core installation
121
+ // 2. Check for local development version
122
+ // 3. Fall back to npm registry
123
+
124
+ try {
125
+ // Check if running in development (from PlusUI repo)
126
+ const localCorePath = resolve(__dirname, '../../plusui-sdk/packages/core');
127
+ if (existsSync(localCorePath)) {
128
+ // Convert Windows backslashes to forward slashes for JSON compatibility
129
+ return `file:${localCorePath.replace(/\\/g, '/')}`;
130
+ }
131
+
132
+ // Check global installation
133
+ const globalPath = this.resolveGlobalPackage('plusui-native-core');
134
+ if (globalPath) {
135
+ return globalPath;
136
+ }
137
+ } catch (e) {
138
+ // Ignore errors, fall back to npm
139
+ }
140
+
141
+ // Fall back to npm registry (when published)
142
+ return 'plusui-native-core';
143
+ }
144
+
145
+ resolveGlobalPackage(packageName) {
146
+ try {
147
+ const result = execSync(`npm root -g`, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] });
148
+ const globalRoot = result.trim();
149
+ const packagePath = join(globalRoot, packageName);
150
+
151
+ if (existsSync(packagePath)) {
152
+ return packagePath;
153
+ }
154
+ } catch (e) {
155
+ // npm not available or package not found
156
+ }
157
+
158
+ return null;
159
+ }
160
+
161
+ async runNpmInstall(projectPath) {
162
+ return new Promise((resolve, reject) => {
163
+ const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
164
+
165
+ // Install root dependencies
166
+ const rootProc = spawn(npm, ['install'], {
167
+ cwd: projectPath,
168
+ stdio: 'inherit',
169
+ shell: true
170
+ });
171
+
172
+ rootProc.on('close', (code) => {
173
+ if (code !== 0) {
174
+ reject(new Error(`npm install failed with code ${code}`));
175
+ return;
176
+ }
177
+
178
+ // Install frontend dependencies
179
+ const frontendPath = join(projectPath, 'frontend');
180
+ if (existsSync(join(frontendPath, 'package.json'))) {
181
+ const frontendProc = spawn(npm, ['install'], {
182
+ cwd: frontendPath,
183
+ stdio: 'inherit',
184
+ shell: true
185
+ });
186
+
187
+ frontendProc.on('close', (feCode) => {
188
+ if (feCode === 0) {
189
+ resolve();
190
+ } else {
191
+ reject(new Error(`frontend npm install failed with code ${feCode}`));
192
+ }
193
+ });
194
+
195
+ frontendProc.on('error', reject);
196
+ } else {
197
+ resolve();
198
+ }
199
+ });
200
+
201
+ rootProc.on('error', reject);
202
+ });
203
+ }
204
+
205
+ printSuccessMessage(projectName) {
206
+ console.log(chalk.green.bold('\n✓ Project created successfully!\n'));
207
+ console.log(chalk.bold('Next steps:\n'));
208
+ console.log(chalk.cyan(` cd ${projectName}`));
209
+ console.log(chalk.cyan(` npm run dev`));
210
+ console.log();
211
+ console.log(chalk.gray('This will start the development server with hot reload.'));
212
+ console.log(chalk.gray('Edit frontend/src/App.tsx and main.cpp to get started!'));
213
+ console.log();
214
+ }
215
+ }
216
+
217
+
@@ -0,0 +1,24 @@
1
+ {
2
+ "configurations": [
3
+ {
4
+ "name": "Windows",
5
+ "includePath": [
6
+ "${workspaceFolder}/src",
7
+ "${workspaceFolder}/../Core/include",
8
+ "${workspaceFolder}/build/dev/_deps/webview2/build/native/include",
9
+ "C:/Users/${env:USERNAME}/.nuget/packages/microsoft.web.webview2/1.0.2903.40/build/native/include"
10
+ ],
11
+ "defines": [
12
+ "PLUSUI_DEV_MODE",
13
+ "_WIN32",
14
+ "NDEBUG"
15
+ ],
16
+ "compilerPath": "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.43.34808/bin/Hostx64/x64/cl.exe",
17
+ "cStandard": "c17",
18
+ "cppStandard": "c++20",
19
+ "intelliSenseMode": "windows-msvc-x64",
20
+ "compileCommands": "${workspaceFolder}/build/dev/compile_commands.json"
21
+ }
22
+ ],
23
+ "version": 4
24
+ }