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.
- package/README.md +1 -1
- package/cli.js +191 -2
- 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.
|
|
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 =
|
|
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