library.dr-conversion 0.3.0 → 0.3.2
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/README.md +1 -1
- package/cli.js +204 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/library.dr-conversion)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
|
|
8
|
-
**Library.DR-Conversion** (v0.2
|
|
8
|
+
**Library.DR-Conversion** (v0.3.2) 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
|
@@ -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,16 +481,15 @@ program
|
|
|
341
481
|
}
|
|
342
482
|
|
|
343
483
|
const isRootBot = platform === 'root';
|
|
344
|
-
const manifestFile =
|
|
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
|
|
|
348
488
|
// Check if manifest already exists
|
|
349
489
|
if (fs.existsSync(manifestFile)) {
|
|
350
|
-
console.log(`⚠️ ${manifestFile} already exists
|
|
351
|
-
if (
|
|
352
|
-
console.log('
|
|
353
|
-
return;
|
|
490
|
+
console.log(`⚠️ ${manifestFile} already exists — it will be overwritten.`);
|
|
491
|
+
if (options.interactive) {
|
|
492
|
+
console.log('Interactive mode will update fields and overwrite the manifest.');
|
|
354
493
|
}
|
|
355
494
|
}
|
|
356
495
|
|
|
@@ -385,6 +524,16 @@ program
|
|
|
385
524
|
description: '',
|
|
386
525
|
author: '',
|
|
387
526
|
homepage: '',
|
|
527
|
+
package: {
|
|
528
|
+
client: {
|
|
529
|
+
entry: 'dist/index.html',
|
|
530
|
+
assets: ['dist'],
|
|
531
|
+
node_modules: ['node_modules']
|
|
532
|
+
}
|
|
533
|
+
},
|
|
534
|
+
settings: {
|
|
535
|
+
ui: []
|
|
536
|
+
},
|
|
388
537
|
permissions: {
|
|
389
538
|
channel: {}
|
|
390
539
|
}
|
|
@@ -483,13 +632,21 @@ program
|
|
|
483
632
|
rl.close();
|
|
484
633
|
}
|
|
485
634
|
|
|
486
|
-
// Write manifest file
|
|
635
|
+
// Write manifest file (overwrite if exists)
|
|
487
636
|
fs.writeFileSync(
|
|
488
637
|
manifestFile,
|
|
489
638
|
JSON.stringify(manifest, null, 2)
|
|
490
639
|
);
|
|
491
|
-
|
|
492
|
-
|
|
640
|
+
|
|
641
|
+
// Validate generated manifest
|
|
642
|
+
const validation = validateManifestObject(manifest);
|
|
643
|
+
if (!validation.valid) {
|
|
644
|
+
console.error('\n❌ Generated manifest failed validation:');
|
|
645
|
+
for (const e of validation.errors) console.error(' -', e);
|
|
646
|
+
process.exit(1);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
console.log(`\n✅ Generated and validated ${manifestFile} successfully!\n`);
|
|
493
650
|
console.log('📋 Manifest Details:');
|
|
494
651
|
console.log(` Platform: ${isRootBot ? 'Root Bot (server-side)' : 'Root App (client-side)'}`);
|
|
495
652
|
console.log(` ID: ${manifest.id}`);
|
|
@@ -519,6 +676,45 @@ program
|
|
|
519
676
|
console.log('');
|
|
520
677
|
});
|
|
521
678
|
|
|
679
|
+
program
|
|
680
|
+
.command('publish')
|
|
681
|
+
.description('Validate and publish the current root-manifest.json using @rootsdk/cli')
|
|
682
|
+
.option('-f, --file <path>', 'Manifest file to publish', 'root-manifest.json')
|
|
683
|
+
.option('--no-validate', 'Skip manifest validation step')
|
|
684
|
+
.action((options) => {
|
|
685
|
+
const file = options.file || 'root-manifest.json';
|
|
686
|
+
if (!fs.existsSync(file)) {
|
|
687
|
+
console.error(`❌ Manifest not found: ${file}`);
|
|
688
|
+
process.exit(1);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
if (options.validate !== false) {
|
|
692
|
+
let manifest;
|
|
693
|
+
try {
|
|
694
|
+
manifest = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
695
|
+
} catch (err) {
|
|
696
|
+
console.error('❌ Failed to parse manifest:', err.message);
|
|
697
|
+
process.exit(1);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
const result = validateManifestObject(manifest);
|
|
701
|
+
if (!result.valid) {
|
|
702
|
+
console.error('❌ Manifest validation failed:');
|
|
703
|
+
for (const e of result.errors) console.error(' -', e);
|
|
704
|
+
process.exit(1);
|
|
705
|
+
}
|
|
706
|
+
console.log('✅ Manifest validation passed');
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
try {
|
|
710
|
+
console.log('🔁 Running publish via @rootsdk/cli...');
|
|
711
|
+
execSync('npx @rootsdk/cli publish', { stdio: 'inherit' });
|
|
712
|
+
} catch (err) {
|
|
713
|
+
console.error('❌ Publish failed:', err.message);
|
|
714
|
+
process.exit(1);
|
|
715
|
+
}
|
|
716
|
+
});
|
|
717
|
+
|
|
522
718
|
program
|
|
523
719
|
.command('setup')
|
|
524
720
|
.description('Interactive setup wizard to install only the dependencies you need')
|
package/package.json
CHANGED