plusui-native 0.2.7 → 0.2.8

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 (2) hide show
  1. package/package.json +4 -4
  2. package/src/index.js +66 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plusui-native",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
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.7",
31
- "plusui-native-bindgen": "^0.1.7"
30
+ "plusui-native-builder": "^0.1.8",
31
+ "plusui-native-bindgen": "^0.1.8"
32
32
  },
33
33
  "peerDependencies": {
34
- "plusui-native-bindgen": "^0.1.7"
34
+ "plusui-native-bindgen": "^0.1.8"
35
35
  },
36
36
  "publishConfig": {
37
37
  "access": "public"
package/src/index.js CHANGED
@@ -203,6 +203,57 @@ function getAppBindgenPaths() {
203
203
  };
204
204
  }
205
205
 
206
+ function findLikelyProjectDirs(baseDir) {
207
+ try {
208
+ const entries = execSync('npm pkg get name', { cwd: baseDir, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
209
+ if (entries) {
210
+ // noop; just to ensure cwd is a Node project when possible
211
+ }
212
+ } catch {}
213
+
214
+ const candidates = [];
215
+ try {
216
+ const dirs = execSync(process.platform === 'win32' ? 'dir /b /ad' : 'ls -1 -d */', {
217
+ cwd: baseDir,
218
+ encoding: 'utf8',
219
+ stdio: ['ignore', 'pipe', 'ignore'],
220
+ shell: true,
221
+ })
222
+ .split(/\r?\n/)
223
+ .map(s => s.trim().replace(/[\\/]$/, ''))
224
+ .filter(Boolean);
225
+
226
+ for (const dirName of dirs) {
227
+ const fullDir = join(baseDir, dirName);
228
+ if (existsSync(join(fullDir, 'CMakeLists.txt')) && existsSync(join(fullDir, 'package.json'))) {
229
+ candidates.push(dirName);
230
+ }
231
+ }
232
+ } catch {}
233
+
234
+ return candidates;
235
+ }
236
+
237
+ function ensureProjectRoot(commandName) {
238
+ const hasCMake = existsSync(join(process.cwd(), 'CMakeLists.txt'));
239
+ const hasPackage = existsSync(join(process.cwd(), 'package.json'));
240
+
241
+ if (hasCMake && hasPackage) {
242
+ return;
243
+ }
244
+
245
+ const likelyDirs = findLikelyProjectDirs(process.cwd());
246
+ let hint = '';
247
+
248
+ if (likelyDirs.length === 1) {
249
+ hint = `\n\nHint: you may be in a parent folder. Try:\n cd ${likelyDirs[0]}\n plusui ${commandName}`;
250
+ } else if (likelyDirs.length > 1) {
251
+ hint = `\n\nHint: run this command from your app folder (one containing CMakeLists.txt and package.json).`;
252
+ }
253
+
254
+ error(`This command must be run from a PlusUI project root (missing CMakeLists.txt and/or package.json in ${process.cwd()}).${hint}`);
255
+ }
256
+
206
257
  function ensureBuildLayout() {
207
258
  const buildRoot = join(process.cwd(), 'build');
208
259
  for (const platform of Object.values(PLATFORMS)) {
@@ -275,6 +326,7 @@ async function createProject(name, options = {}) {
275
326
  // ============================================================
276
327
 
277
328
  function buildFrontend() {
329
+ ensureProjectRoot('build:frontend');
278
330
  logSection('Building Frontend');
279
331
 
280
332
  if (existsSync('frontend')) {
@@ -287,6 +339,7 @@ function buildFrontend() {
287
339
  }
288
340
 
289
341
  function buildBackend(platform = null, devMode = false) {
342
+ ensureProjectRoot(devMode ? 'dev:backend' : 'build:backend');
290
343
  const targetPlatform = platform || process.platform;
291
344
  const platformConfig = PLATFORMS[targetPlatform] || PLATFORMS[Object.keys(PLATFORMS).find(k => PLATFORMS[k].folder.toLowerCase() === targetPlatform?.toLowerCase())];
292
345
 
@@ -329,6 +382,7 @@ function buildBackend(platform = null, devMode = false) {
329
382
  }
330
383
 
331
384
  async function generateIcons(inputPath = null) {
385
+ ensureProjectRoot('icons');
332
386
  logSection('Generating Platform Icons');
333
387
 
334
388
  const { IconGenerator } = await import('./assets/icon-generator.js');
@@ -347,6 +401,7 @@ async function generateIcons(inputPath = null) {
347
401
  }
348
402
 
349
403
  async function embedResources(platform = null) {
404
+ ensureProjectRoot('embed');
350
405
  const targetPlatform = platform || process.platform;
351
406
  logSection(`Embedding Resources (${targetPlatform})`);
352
407
 
@@ -369,6 +424,7 @@ async function embedResources(platform = null) {
369
424
  }
370
425
 
371
426
  async function embedAssets() {
427
+ ensureProjectRoot('build');
372
428
  const assetsDir = join(process.cwd(), 'assets');
373
429
  if (!existsSync(assetsDir)) {
374
430
  try {
@@ -417,6 +473,7 @@ async function embedAssets() {
417
473
 
418
474
 
419
475
  async function build(production = true) {
476
+ ensureProjectRoot('build');
420
477
  logSection('Building PlusUI Application');
421
478
 
422
479
  // Embed assets
@@ -435,6 +492,7 @@ async function build(production = true) {
435
492
  }
436
493
 
437
494
  function buildAll() {
495
+ ensureProjectRoot('build:all');
438
496
  logSection('Building for All Platforms');
439
497
 
440
498
  ensureBuildLayout();
@@ -474,6 +532,7 @@ let viteServer = null;
474
532
  let cppProcess = null;
475
533
 
476
534
  async function startViteServer() {
535
+ ensureProjectRoot('dev:frontend');
477
536
  log('Starting Vite dev server...', 'blue');
478
537
 
479
538
  viteServer = await createViteServer({
@@ -491,6 +550,7 @@ async function startViteServer() {
491
550
  }
492
551
 
493
552
  async function startBackend() {
553
+ ensureProjectRoot('dev');
494
554
  logSection('Building C++ Backend (Dev Mode)');
495
555
 
496
556
  const projectName = getProjectName();
@@ -598,6 +658,7 @@ function killProcessByName(name) {
598
658
  }
599
659
 
600
660
  async function dev() {
661
+ ensureProjectRoot('dev');
601
662
  logSection('PlusUI Development Mode');
602
663
 
603
664
  const toolCheck = checkTools();
@@ -643,6 +704,7 @@ async function dev() {
643
704
  }
644
705
 
645
706
  async function devFrontend() {
707
+ ensureProjectRoot('dev:frontend');
646
708
  logSection('Frontend Development Mode');
647
709
 
648
710
  // specific port cleaning
@@ -665,6 +727,7 @@ async function devFrontend() {
665
727
  }
666
728
 
667
729
  function devBackend() {
730
+ ensureProjectRoot('dev:backend');
668
731
  logSection('Backend Development Mode');
669
732
 
670
733
  const projectName = getProjectName();
@@ -742,6 +805,7 @@ function devBackend() {
742
805
  // ============================================================
743
806
 
744
807
  function run() {
808
+ ensureProjectRoot('run');
745
809
  const projectName = getProjectName();
746
810
  const platform = PLATFORMS[process.platform];
747
811
  const buildDir = `build/${platform?.folder || 'Windows'}`;
@@ -774,6 +838,7 @@ function run() {
774
838
  // ============================================================
775
839
 
776
840
  async function clean() {
841
+ ensureProjectRoot('clean');
777
842
  logSection('Cleaning Build Artifacts');
778
843
 
779
844
  const dirs = ['build', 'frontend/dist'];
@@ -793,6 +858,7 @@ async function clean() {
793
858
  // ============================================================
794
859
 
795
860
  async function runBindgen(providedArgs = null, options = {}) {
861
+ ensureProjectRoot('bindgen');
796
862
  logSection('Running Binding Generator');
797
863
 
798
864
  const { skipIfNoInput = false, source = 'manual' } = options;