@tgrv/void-cli 1.0.4 → 1.0.6

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/bin/void.js +171 -92
  2. package/package.json +1 -1
package/bin/void.js CHANGED
@@ -99,6 +99,7 @@ ${colors.bold}Usage:${colors.reset}
99
99
  ${colors.green}void publish [plugin-path]${colors.reset} - Build and publish the plugin to npm registry (default: .)
100
100
  ${colors.green}void add <plugin-name>${colors.reset} - Add a plugin from registry/local build into application
101
101
  ${colors.green}void remove <plugin-name>${colors.reset} - Remove a plugin from application and configuration
102
+ ${colors.green}void update${colors.reset} - Update all installed plugins to their latest versions
102
103
  ${colors.green}void view <plugin-name>${colors.reset} - Inspect an installed plugin and list all its exposed functions
103
104
  `);
104
105
  process.exit(0);
@@ -235,6 +236,148 @@ export default plugin;
235
236
  return buildOutputDir;
236
237
  }
237
238
 
239
+ function parsePackageSpec(spec) {
240
+ if (spec.startsWith("@")) {
241
+ const parts = spec.slice(1).split("@");
242
+ const name = "@" + parts[0];
243
+ const version = parts[1] || null;
244
+ return { name, version };
245
+ } else {
246
+ const parts = spec.split("@");
247
+ const name = parts[0];
248
+ const version = parts[1] || null;
249
+ return { name, version };
250
+ }
251
+ }
252
+
253
+ function runAdd(pluginNameInput, appDir) {
254
+ const configInfo = findConfig(appDir);
255
+ if (!configInfo) {
256
+ console.error(`${cross} ${colors.red}Error: void.config.json not found. Run 'void init' first.${colors.reset}`);
257
+ process.exit(1);
258
+ }
259
+
260
+ const { name: pluginName, version: requestedVersion } = parsePackageSpec(pluginNameInput);
261
+ const config = JSON.parse(fs.readFileSync(configInfo.configPath, "utf8"));
262
+
263
+ // Look up local build directory
264
+ let localBuildDir = null;
265
+
266
+ const scanLocations = [
267
+ path.join(workspaceDir, "plugins"),
268
+ path.join(workspaceDir, "packages"),
269
+ path.join(workspaceDir, "sdk")
270
+ ];
271
+
272
+ for (const root of scanLocations) {
273
+ if (fs.existsSync(root)) {
274
+ const subdirs = fs.readdirSync(root);
275
+ for (const subdir of subdirs) {
276
+ const pPath = path.join(root, subdir);
277
+ if (fs.statSync(pPath).isDirectory()) {
278
+ // Scans nested scopes (e.g. plugins/math/@tgrv/void-math)
279
+ const entries = fs.readdirSync(pPath);
280
+ for (const entry of entries) {
281
+ if (entry.startsWith("@")) {
282
+ const scopePath = path.join(pPath, entry);
283
+ const subfolders = fs.readdirSync(scopePath);
284
+ for (const name of subfolders) {
285
+ const pkgPath = path.join(scopePath, name, "package.json");
286
+ if (fs.existsSync(pkgPath)) {
287
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
288
+ if (pkg.name === pluginName) {
289
+ localBuildDir = path.join(scopePath, name);
290
+ break;
291
+ }
292
+ }
293
+ }
294
+ }
295
+ if (localBuildDir) break;
296
+ }
297
+ }
298
+ if (localBuildDir) break;
299
+ }
300
+ }
301
+ if (localBuildDir) break;
302
+ }
303
+
304
+ const targetPluginDir = path.join(appDir, "node_modules", pluginName);
305
+ ensureDir(path.dirname(targetPluginDir));
306
+
307
+ let resolvedVersion = "1.0.0";
308
+
309
+ if (localBuildDir) {
310
+ console.log(`${info} Installing local build of '${colors.bold}${pluginName}${colors.reset}' from ${localBuildDir} to ${targetPluginDir}...`);
311
+ if (fs.existsSync(targetPluginDir)) {
312
+ fs.rmSync(targetPluginDir, { recursive: true, force: true });
313
+ }
314
+ copyFolderRecursive(localBuildDir, targetPluginDir);
315
+
316
+ try {
317
+ const localPkgPath = path.join(localBuildDir, "package.json");
318
+ if (fs.existsSync(localPkgPath)) {
319
+ const localPkg = JSON.parse(fs.readFileSync(localPkgPath, "utf8"));
320
+ resolvedVersion = localPkg.version || "1.0.0";
321
+ }
322
+ } catch (e) {}
323
+ } else {
324
+ console.log(`${info} Installing '${colors.bold}${pluginNameInput}${colors.reset}' from NPM registry...`);
325
+ const npmSuccess = runCommand(`npm install ${pluginNameInput}`, { cwd: appDir });
326
+ if (!npmSuccess) {
327
+ console.error(`${cross} ${colors.red}Error: Failed to install package '${pluginNameInput}' via npm.${colors.reset}`);
328
+ process.exit(1);
329
+ }
330
+
331
+ try {
332
+ const installedPkgPath = path.join(appDir, "node_modules", pluginName, "package.json");
333
+ if (fs.existsSync(installedPkgPath)) {
334
+ const installedPkg = JSON.parse(fs.readFileSync(installedPkgPath, "utf8"));
335
+ resolvedVersion = installedPkg.version || "1.0.0";
336
+ }
337
+ } catch (e) {}
338
+ }
339
+
340
+ // Update package.json of the application
341
+ const pkgPath = path.join(appDir, "package.json");
342
+ if (fs.existsSync(pkgPath)) {
343
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
344
+ pkg.dependencies = pkg.dependencies || {};
345
+ pkg.dependencies[pluginName] = `^${resolvedVersion}`;
346
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
347
+ }
348
+
349
+ // Update void.config.json
350
+ config.plugins = config.plugins || {};
351
+ config.plugins[pluginName] = `^${resolvedVersion}`;
352
+ fs.writeFileSync(configInfo.configPath, JSON.stringify(config, null, 2));
353
+
354
+ console.log(`${tick} ${colors.green}Successfully added '${pluginName}' (version ^${resolvedVersion})!${colors.reset}\n`);
355
+ }
356
+
357
+ function runUpdate(appDir) {
358
+ const configInfo = findConfig(appDir);
359
+ if (!configInfo) {
360
+ console.error(`${cross} ${colors.red}Error: void.config.json not found. Run 'void init' first.${colors.reset}`);
361
+ process.exit(1);
362
+ }
363
+
364
+ const config = JSON.parse(fs.readFileSync(configInfo.configPath, "utf8"));
365
+ const plugins = config.plugins || {};
366
+ const pluginNames = Object.keys(plugins);
367
+
368
+ if (pluginNames.length === 0) {
369
+ console.log(`${info} No plugins configured to update.`);
370
+ return;
371
+ }
372
+
373
+ console.log(`\n${info} Updating plugins to latest versions...`);
374
+ for (const name of pluginNames) {
375
+ runAdd(`${name}@latest`, appDir);
376
+ }
377
+ console.log(`${tick} ${colors.green}All plugins updated successfully!${colors.reset}\n`);
378
+ }
379
+
380
+
238
381
  async function main() {
239
382
  switch (command) {
240
383
  case "init": {
@@ -244,9 +387,11 @@ async function main() {
244
387
 
245
388
  console.log(`\n${info} Initializing Void project at: ${colors.bold}${targetDir}${colors.reset}`);
246
389
 
390
+ const hasExistingPkg = fs.existsSync(path.join(targetDir, "package.json"));
391
+
247
392
  // Initialize package.json if not exists
248
393
  const pkgPath = path.join(targetDir, "package.json");
249
- if (!fs.existsSync(pkgPath)) {
394
+ if (!hasExistingPkg) {
250
395
  const defaultPkg = {
251
396
  name: path.basename(targetDir),
252
397
  version: "1.0.0",
@@ -266,10 +411,11 @@ async function main() {
266
411
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
267
412
  }
268
413
 
269
- // Write default application app.js
270
- const appPath = path.join(targetDir, "app.js");
271
- if (!fs.existsSync(appPath)) {
272
- const appContent = `import math from "@tgrv/void-math";
414
+ // If it's a fresh project, write default app.js
415
+ if (!hasExistingPkg) {
416
+ const appPath = path.join(targetDir, "app.js");
417
+ if (!fs.existsSync(appPath)) {
418
+ const appContent = `import math from "@tgrv/void-math";
273
419
 
274
420
  console.log("=== Void Application ===");
275
421
 
@@ -279,7 +425,8 @@ try {
279
425
  console.error("Error running application:", e.message);
280
426
  }
281
427
  `;
282
- fs.writeFileSync(appPath, appContent);
428
+ fs.writeFileSync(appPath, appContent);
429
+ }
283
430
  }
284
431
 
285
432
  // Install void-runtime via NPM
@@ -289,11 +436,19 @@ try {
289
436
  console.error(`${cross} ${colors.red}Failed to install @tgrv/void-runtime via npm.${colors.reset}`);
290
437
  }
291
438
 
439
+ // If it's a fresh project, also install @tgrv/void-math using the shared installer logic
440
+ if (!hasExistingPkg) {
441
+ runAdd("@tgrv/void-math", targetDir);
442
+ }
443
+
292
444
  console.log(`${tick} ${colors.green}Successfully initialized Void project!${colors.reset}`);
293
- console.log(`\nTo add plugins, you can run:`);
294
- console.log(` ${colors.cyan}npx void add <plugin-name>${colors.reset}`);
295
- console.log(`For example:`);
296
- console.log(` ${colors.cyan}npx void add @tgrv/void-math${colors.reset}\n`);
445
+ if (!hasExistingPkg) {
446
+ console.log(`\nTo run the starter app, execute:`);
447
+ console.log(` ${colors.cyan}node app.js${colors.reset}\n`);
448
+ } else {
449
+ console.log(`\nTo add plugins, you can run:`);
450
+ console.log(` ${colors.cyan}npx void add <plugin-name>${colors.reset}\n`);
451
+ }
297
452
  break;
298
453
  }
299
454
 
@@ -385,88 +540,7 @@ try {
385
540
  console.error(`${cross} ${colors.red}Error: Please specify the plugin to add. e.g. void add @tgrv/void-math${colors.reset}`);
386
541
  process.exit(1);
387
542
  }
388
-
389
- const configInfo = findConfig(process.cwd());
390
- if (!configInfo) {
391
- console.error(`${cross} ${colors.red}Error: void.config.json not found. Run 'void init' first.${colors.reset}`);
392
- process.exit(1);
393
- }
394
-
395
- const config = JSON.parse(fs.readFileSync(configInfo.configPath, "utf8"));
396
-
397
- // Look up local build directory inside the plugins/ or packages/ directory tree
398
- let localBuildDir = null;
399
-
400
- const scanLocations = [
401
- path.join(workspaceDir, "plugins"),
402
- path.join(workspaceDir, "packages")
403
- ];
404
-
405
- for (const root of scanLocations) {
406
- if (fs.existsSync(root)) {
407
- const subdirs = fs.readdirSync(root);
408
- for (const subdir of subdirs) {
409
- const pPath = path.join(root, subdir);
410
- if (fs.statSync(pPath).isDirectory()) {
411
- // Scans nested scopes (e.g. plugins/math/@tgrv/void-math)
412
- const entries = fs.readdirSync(pPath);
413
- for (const entry of entries) {
414
- if (entry.startsWith("@")) {
415
- const scopePath = path.join(pPath, entry);
416
- const subfolders = fs.readdirSync(scopePath);
417
- for (const name of subfolders) {
418
- const pkgPath = path.join(scopePath, name, "package.json");
419
- if (fs.existsSync(pkgPath)) {
420
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
421
- if (pkg.name === pluginName) {
422
- localBuildDir = path.join(scopePath, name);
423
- break;
424
- }
425
- }
426
- }
427
- }
428
- if (localBuildDir) break;
429
- }
430
- }
431
- if (localBuildDir) break;
432
- }
433
- }
434
- if (localBuildDir) break;
435
- }
436
-
437
- const targetPluginDir = path.join(process.cwd(), "node_modules", pluginName);
438
- ensureDir(path.dirname(targetPluginDir));
439
-
440
- if (localBuildDir) {
441
- console.log(`${info} Installing local build of '${colors.bold}${pluginName}${colors.reset}' from ${localBuildDir} to ${targetPluginDir}...`);
442
- if (fs.existsSync(targetPluginDir)) {
443
- fs.rmSync(targetPluginDir, { recursive: true, force: true });
444
- }
445
- copyFolderRecursive(localBuildDir, targetPluginDir);
446
- } else {
447
- console.log(`${info} Installing '${colors.bold}${pluginName}${colors.reset}' from NPM registry...`);
448
- const npmSuccess = runCommand(`npm install ${pluginName}`, { cwd: process.cwd() });
449
- if (!npmSuccess) {
450
- console.error(`${cross} ${colors.red}Error: Failed to install package '${pluginName}' via npm.${colors.reset}`);
451
- process.exit(1);
452
- }
453
- }
454
-
455
- // Update package.json of the application
456
- const pkgPath = path.join(process.cwd(), "package.json");
457
- if (fs.existsSync(pkgPath)) {
458
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
459
- pkg.dependencies = pkg.dependencies || {};
460
- pkg.dependencies[pluginName] = "1.0.0";
461
- fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
462
- }
463
-
464
- // Update void.config.json
465
- config.plugins = config.plugins || {};
466
- config.plugins[pluginName] = "^1.0.0";
467
- fs.writeFileSync(configInfo.configPath, JSON.stringify(config, null, 2));
468
-
469
- console.log(`${tick} ${colors.green}Successfully added '${pluginName}'!${colors.reset}\n`);
543
+ runAdd(pluginName, process.cwd());
470
544
  break;
471
545
  }
472
546
 
@@ -519,6 +593,11 @@ try {
519
593
  break;
520
594
  }
521
595
 
596
+ case "update": {
597
+ runUpdate(process.cwd());
598
+ break;
599
+ }
600
+
522
601
  case "view": {
523
602
  const pluginName = args[1];
524
603
  if (!pluginName) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tgrv/void-cli",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "void": "./bin/void.js"