library.dr-conversion 0.3.0 → 0.3.1

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 (3) hide show
  1. package/README.md +1 -1
  2. package/cli.js +191 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  [![npm version](https://badge.fury.io/js/library.dr-conversion.svg)](https://www.npmjs.com/package/library.dr-conversion)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
- **Library.DR-Conversion** (v0.2.9) is a TypeScript library that provides a unified, platform-agnostic interface for building chat bots that work across multiple platforms like Discord, Root, and potentially others. Write your bot logic once, and deploy it anywhere!
8
+ **Library.DR-Conversion** (v0.3.1) is a TypeScript library that provides a unified, platform-agnostic interface for building chat bots that work across multiple platforms like Discord, Root, and potentially others. Write your bot logic once, and deploy it anywhere!
9
9
 
10
10
  ## ✨ Features
11
11
 
package/cli.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  /**
4
4
  * CLI tool for Library.DR-Conversion
@@ -49,6 +49,53 @@ function detectPlatform() {
49
49
  }
50
50
  }
51
51
 
52
+ // Validate a root manifest object against minimal Root requirements
53
+ function validateManifestObject(manifest) {
54
+ const errors = [];
55
+ if (!manifest || typeof manifest !== 'object') {
56
+ errors.push('Manifest must be a JSON object');
57
+ return { valid: false, errors };
58
+ }
59
+
60
+ if (!manifest.id || typeof manifest.id !== 'string') {
61
+ errors.push('Missing or invalid "id" (string)');
62
+ }
63
+
64
+ if (!manifest.version || typeof manifest.version !== 'string') {
65
+ errors.push('Missing or invalid "version" (string)');
66
+ }
67
+
68
+ if (!manifest.package || typeof manifest.package !== 'object') {
69
+ errors.push('Missing "package" object');
70
+ } else {
71
+ if (manifest.package.server) {
72
+ const server = manifest.package.server;
73
+ if (!server.launch || typeof server.launch !== 'string') {
74
+ errors.push('package.server.launch is required and must be a string');
75
+ }
76
+ if (!Array.isArray(server.deploy) || server.deploy.length === 0) {
77
+ errors.push('package.server.deploy must be a non-empty array');
78
+ }
79
+ if (!Array.isArray(server.node_modules) || server.node_modules.length === 0) {
80
+ errors.push('package.server.node_modules must be a non-empty array');
81
+ }
82
+ }
83
+
84
+ if (manifest.package.client) {
85
+ const client = manifest.package.client;
86
+ // accept either entry or deploy
87
+ if (!client.entry && (!Array.isArray(client.deploy) || client.deploy.length === 0)) {
88
+ errors.push('package.client.entry or package.client.deploy is required');
89
+ }
90
+ if (client.assets && !Array.isArray(client.assets)) {
91
+ errors.push('package.client.assets must be an array if provided');
92
+ }
93
+ }
94
+ }
95
+
96
+ return { valid: errors.length === 0, errors };
97
+ }
98
+
52
99
  program
53
100
  .name('library.dr-conversion')
54
101
  .description('CLI tools for Library.DR-Conversion v0.2.9')
@@ -279,6 +326,62 @@ npx @rootsdk/cli publish
279
326
  fs.writeFileSync(path.join(projectDir, 'MANIFEST.md'), manifestReadme);
280
327
  }
281
328
 
329
+ // Create root-app-manifest.json for Root Apps (client-side)
330
+ if (options.platform === 'root-app') {
331
+ const appManifest = {
332
+ id: generateUUID(),
333
+ version: '1.0.0',
334
+ name: options.name,
335
+ description: `${options.name} - Root App`,
336
+ author: '',
337
+ homepage: '',
338
+ package: {
339
+ client: {
340
+ entry: 'dist/index.html',
341
+ assets: ['dist'],
342
+ node_modules: ['node_modules']
343
+ }
344
+ },
345
+ settings: {
346
+ ui: []
347
+ },
348
+ permissions: {
349
+ channel: {
350
+ CreateMessage: true,
351
+ ReadMessage: true
352
+ }
353
+ }
354
+ };
355
+
356
+ fs.writeFileSync(
357
+ path.join(projectDir, 'root-manifest.json'),
358
+ JSON.stringify(appManifest, null, 2)
359
+ );
360
+
361
+ const appManifestReadme = `# Root App Manifest
362
+
363
+ This project includes a generated root-manifest.json to help document your app.
364
+
365
+ This manifest follows the Root App manifest overview and provides the basic fields used by the Root platform:
366
+ - 'id': Unique UUID for the app
367
+ - 'version': Semver version
368
+ - 'package.client.entry': The client entry HTML for the app
369
+ - 'package.client.assets': Client assets to include in the upload
370
+ - 'permissions': Channel-level permissions used by the app
371
+
372
+ Notes:
373
+ - Update 'version' following semantic versioning when you make changes.
374
+ - Review permissions and remove any that aren't needed.
375
+ - Configure UI settings in the 'settings.ui' array (see Root docs for details):
376
+ https://docs.rootapp.com/docs/app-docs/configure/manifest-overview/
377
+
378
+ Deployment:
379
+ Build your app and follow the Root platform instructions to upload or register it.
380
+ `;
381
+
382
+ fs.writeFileSync(path.join(projectDir, 'MANIFEST.md'), appManifestReadme);
383
+ }
384
+
282
385
  console.log(`✅ Created ${options.name}`);
283
386
  console.log(`\n📝 Next steps:`);
284
387
  console.log(` cd ${options.name}`);
@@ -324,6 +427,43 @@ program
324
427
  console.log('✅ Configuration is valid');
325
428
  });
326
429
 
430
+ program
431
+ .command('validate-manifest')
432
+ .description('Validate root-manifest.json in the current folder')
433
+ .option('-f, --file <path>', 'Manifest file path', 'root-manifest.json')
434
+ .action((options) => {
435
+ const file = options.file || 'root-manifest.json';
436
+ if (!fs.existsSync(file)) {
437
+ console.error(`❌ Manifest not found: ${file}`);
438
+ process.exit(1);
439
+ }
440
+
441
+ let raw;
442
+ try {
443
+ raw = fs.readFileSync(file, 'utf8');
444
+ } catch (err) {
445
+ console.error('❌ Failed to read manifest:', err.message);
446
+ process.exit(1);
447
+ }
448
+
449
+ let manifest;
450
+ try {
451
+ manifest = JSON.parse(raw);
452
+ } catch (err) {
453
+ console.error('❌ Manifest is not valid JSON:', err.message);
454
+ process.exit(1);
455
+ }
456
+
457
+ const result = validateManifestObject(manifest);
458
+ if (!result.valid) {
459
+ console.error('❌ Manifest validation failed:');
460
+ for (const e of result.errors) console.error(' -', e);
461
+ process.exit(1);
462
+ }
463
+
464
+ console.log('✅ Manifest is valid');
465
+ });
466
+
327
467
  program
328
468
  .command('generate-manifest')
329
469
  .description('Generate a manifest file for Root Bots or Root Apps (auto-detects platform)')
@@ -341,7 +481,7 @@ program
341
481
  }
342
482
 
343
483
  const isRootBot = platform === 'root';
344
- const manifestFile = isRootBot ? 'root-manifest.json' : 'root-app-manifest.json';
484
+ const manifestFile = 'root-manifest.json';
345
485
 
346
486
  console.log(`\n🔍 Detected platform: ${isRootBot ? 'Root Bot (server-side)' : 'Root App (client-side)'}`);
347
487
 
@@ -385,6 +525,16 @@ program
385
525
  description: '',
386
526
  author: '',
387
527
  homepage: '',
528
+ package: {
529
+ client: {
530
+ entry: 'dist/index.html',
531
+ assets: ['dist'],
532
+ node_modules: ['node_modules']
533
+ }
534
+ },
535
+ settings: {
536
+ ui: []
537
+ },
388
538
  permissions: {
389
539
  channel: {}
390
540
  }
@@ -519,6 +669,45 @@ program
519
669
  console.log('');
520
670
  });
521
671
 
672
+ program
673
+ .command('publish')
674
+ .description('Validate and publish the current root-manifest.json using @rootsdk/cli')
675
+ .option('-f, --file <path>', 'Manifest file to publish', 'root-manifest.json')
676
+ .option('--no-validate', 'Skip manifest validation step')
677
+ .action((options) => {
678
+ const file = options.file || 'root-manifest.json';
679
+ if (!fs.existsSync(file)) {
680
+ console.error(`❌ Manifest not found: ${file}`);
681
+ process.exit(1);
682
+ }
683
+
684
+ if (options.validate !== false) {
685
+ let manifest;
686
+ try {
687
+ manifest = JSON.parse(fs.readFileSync(file, 'utf8'));
688
+ } catch (err) {
689
+ console.error('❌ Failed to parse manifest:', err.message);
690
+ process.exit(1);
691
+ }
692
+
693
+ const result = validateManifestObject(manifest);
694
+ if (!result.valid) {
695
+ console.error('❌ Manifest validation failed:');
696
+ for (const e of result.errors) console.error(' -', e);
697
+ process.exit(1);
698
+ }
699
+ console.log('✅ Manifest validation passed');
700
+ }
701
+
702
+ try {
703
+ console.log('🔁 Running publish via @rootsdk/cli...');
704
+ execSync('npx @rootsdk/cli publish', { stdio: 'inherit' });
705
+ } catch (err) {
706
+ console.error('❌ Publish failed:', err.message);
707
+ process.exit(1);
708
+ }
709
+ });
710
+
522
711
  program
523
712
  .command('setup')
524
713
  .description('Interactive setup wizard to install only the dependencies you need')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "library.dr-conversion",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Unified interface for building multi-platform chat bots (Discord, Root, and more)",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",