plusui-native 0.2.65 → 0.2.68

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plusui-native",
3
- "version": "0.2.65",
3
+ "version": "0.2.68",
4
4
  "description": "PlusUI CLI - Build C++ desktop apps modern UI ",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -27,11 +27,11 @@
27
27
  "semver": "^7.6.0",
28
28
  "which": "^4.0.0",
29
29
  "execa": "^8.0.1",
30
- "plusui-native-builder": "^0.1.64",
31
- "plusui-native-connect": "^0.1.64"
30
+ "plusui-native-builder": "^0.1.67",
31
+ "plusui-native-connect": "^0.1.67"
32
32
  },
33
33
  "peerDependencies": {
34
- "plusui-native-connect": "^0.1.64"
34
+ "plusui-native-connect": "^0.1.67"
35
35
  },
36
36
  "publishConfig": {
37
37
  "access": "public"
@@ -105,11 +105,20 @@ export class EnvironmentDoctor {
105
105
  for (const result of fixResults) {
106
106
  if (result.success) {
107
107
  console.log(chalk.green(`✓ ${result.name} installed successfully`));
108
+ if (result.pathRefreshNeeded) {
109
+ console.log(chalk.gray(' Note: open a new terminal for the updated PATH to take effect'));
110
+ }
108
111
  } else {
109
112
  console.log(chalk.red(`✗ ${result.name} installation failed`));
110
113
  if (result.message) {
111
114
  console.log(chalk.gray(` ${result.message}`));
112
115
  }
116
+ if (result.reason) {
117
+ console.log(chalk.gray(` Reason: ${result.reason}`));
118
+ }
119
+ if (result.downloadUrl) {
120
+ console.log(chalk.yellow(` Download manually: ${result.downloadUrl}`));
121
+ }
113
122
  if (result.instructions) {
114
123
  console.log(chalk.yellow('\n Manual installation required:'));
115
124
  result.instructions.forEach(line => {
@@ -9,7 +9,9 @@ async function tryCommand(command, timeout = 30000) {
9
9
  }).trim();
10
10
  return { success: true, output };
11
11
  } catch (error) {
12
- return { success: false, error };
12
+ const stderr = (error.stderr || '').toString().trim();
13
+ const stdout = (error.stdout || '').toString().trim();
14
+ return { success: false, error, stderr, stdout };
13
15
  }
14
16
  }
15
17
 
@@ -20,10 +22,14 @@ async function checkWinget() {
20
22
 
21
23
  const INSTALL_COMMANDS = {
22
24
  cmake: {
23
- command: 'winget install -e --id Kitware.CMake --scope user --accept-package-agreements --accept-source-agreements --disable-interactivity',
25
+ // NOTE: Kitware.CMake does NOT support --scope user; omit it so winget
26
+ // uses the package's default (machine) scope. winget will request UAC
27
+ // elevation automatically when needed.
28
+ command: 'winget install -e --id Kitware.CMake --accept-package-agreements --accept-source-agreements --disable-interactivity',
24
29
  manual: 'https://cmake.org/download/',
25
30
  name: 'CMake',
26
- timeout: 300000
31
+ timeout: 300000,
32
+ requiresElevation: true
27
33
  },
28
34
  nodejs: {
29
35
  command: 'winget install -e --id OpenJS.NodeJS --scope user --accept-package-agreements --accept-source-agreements --disable-interactivity',
@@ -91,18 +97,39 @@ export async function installTool(toolName) {
91
97
  return {
92
98
  success: true,
93
99
  message: `${tool.name} installed successfully`,
94
- output: result.output
100
+ output: result.output,
101
+ // Remind callers that the current process PATH won't include the new
102
+ // install – they should re-spawn or check known filesystem paths.
103
+ pathRefreshNeeded: true
95
104
  };
96
105
  }
97
106
 
98
- return {
107
+ // Build a human-readable reason from winget's own output
108
+ const reason = result.stderr || result.stdout ||
109
+ (result.error && result.error.message) ||
110
+ 'Unknown error';
111
+
112
+ const failResult = {
99
113
  success: false,
100
114
  autoInstallAvailable: true,
101
115
  error: result.error,
102
116
  message: `Failed to install ${tool.name} automatically`,
117
+ reason,
103
118
  manual: tool.manual,
104
119
  downloadUrl: tool.manual
105
120
  };
121
+
122
+ if (tool.requiresElevation) {
123
+ failResult.instructions = [
124
+ 'This tool requires administrator rights to install system-wide.',
125
+ 'Option 1: Re-run from an elevated (Run as Administrator) terminal:',
126
+ ' plusui doctor --fix',
127
+ `Option 2: Install manually via winget (elevated): ${tool.command}`,
128
+ `Option 3: Download from: ${tool.manual}`
129
+ ];
130
+ }
131
+
132
+ return failResult;
106
133
  }
107
134
 
108
135
  export function getInstallInstructions(toolName) {
package/src/index.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  import { mkdir, readFile, stat, rm, readdir, writeFile, copyFile } from 'fs/promises';
4
4
  import { existsSync, watch, statSync, mkdirSync } from 'fs';
@@ -16,7 +16,7 @@ function App() {
16
16
  const [currentUrl, setCurrentUrl] = useState('');
17
17
  const [canGoBack, setCanGoBack] = useState(false);
18
18
  const [canGoForward, setCanGoForward] = useState(false);
19
-
19
+
20
20
  // customFileDrop connect channel state
21
21
  const [isDragging, setIsDragging] = useState(false);
22
22
  const [droppedFiles, setDroppedFiles] = useState<{ name: string; size: number; type: string }[]>([]);
@@ -29,14 +29,14 @@ function App() {
29
29
 
30
30
  // Setup routes
31
31
  plusui.router.setRoutes(routes);
32
-
32
+
33
33
  // Listen for navigation changes
34
34
  const unsub = plusui.browser.onNavigate((url) => {
35
35
  setCurrentUrl(url);
36
36
  plusui.browser.canGoBack().then(setCanGoBack);
37
37
  plusui.browser.canGoForward().then(setCanGoForward);
38
38
  });
39
-
39
+
40
40
  // Listen for responses emitted from C++ via ch.customFileDrop.emit(...) in main.cpp
41
41
  const unsubChannel = customFileDrop.on((data: any) => {
42
42
  setBackendMsg(data?.message ?? JSON.stringify(data));
@@ -46,7 +46,7 @@ function App() {
46
46
  plusui.browser.getUrl().then(setCurrentUrl);
47
47
  plusui.browser.canGoBack().then(setCanGoBack);
48
48
  plusui.browser.canGoForward().then(setCanGoForward);
49
-
49
+
50
50
  return () => {
51
51
  unsub();
52
52
  unsubChannel();
@@ -96,7 +96,7 @@ function App() {
96
96
  return (
97
97
  <div className="app">
98
98
  <header className="app-header">
99
- <h1>{{PROJECT_NAME}}</h1>
99
+ <h1>{{ PROJECT_NAME }}</h1>
100
100
  <p>Built with PlusUI Framework</p>
101
101
  </header>
102
102
 
@@ -164,7 +164,7 @@ function App() {
164
164
  The frontend receives the reply via <code>customFileDrop.on()</code>. Run{' '}
165
165
  <code>plusui connect</code> to regenerate the channel bindings from both sides.
166
166
  </p>
167
-
167
+
168
168
  <div
169
169
  className={`filedrop-zone ${isDragging ? 'filedrop-active' : ''}`}
170
170
  onDragOver={handleDragOver}
@@ -175,7 +175,7 @@ function App() {
175
175
  <div className="filedrop-content">
176
176
  <svg className="filedrop-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor">
177
177
  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
178
- d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" />
178
+ d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" />
179
179
  </svg>
180
180
  <div className="filedrop-text">
181
181
  {isDragging ? 'Drop files here' : 'Drag & drop files to send to C++'}