@chimerai/cli 0.2.73
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/LICENSE +21 -0
- package/README.md +293 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +317 -0
- package/dist/commands/add.d.ts +11 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +2126 -0
- package/dist/commands/create.d.ts +12 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +1703 -0
- package/dist/commands/deploy.d.ts +11 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +219 -0
- package/dist/commands/dev.d.ts +17 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +206 -0
- package/dist/commands/doctor.d.ts +11 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +728 -0
- package/dist/commands/generate.d.ts +19 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +429 -0
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +269 -0
- package/dist/commands/list.d.ts +12 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +328 -0
- package/dist/commands/migrate.d.ts +14 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +197 -0
- package/dist/commands/plugin.d.ts +10 -0
- package/dist/commands/plugin.d.ts.map +1 -0
- package/dist/commands/plugin.js +239 -0
- package/dist/commands/remove.d.ts +11 -0
- package/dist/commands/remove.d.ts.map +1 -0
- package/dist/commands/remove.js +472 -0
- package/dist/commands/secret.d.ts +12 -0
- package/dist/commands/secret.d.ts.map +1 -0
- package/dist/commands/secret.js +102 -0
- package/dist/commands/setup.d.ts +9 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +788 -0
- package/dist/commands/update.d.ts +14 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +211 -0
- package/dist/commands/use.d.ts +9 -0
- package/dist/commands/use.d.ts.map +1 -0
- package/dist/commands/use.js +51 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/license.d.ts +55 -0
- package/dist/license.d.ts.map +1 -0
- package/dist/license.js +258 -0
- package/dist/scanner.d.ts +31 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +113 -0
- package/dist/schema-manager.d.ts +26 -0
- package/dist/schema-manager.d.ts.map +1 -0
- package/dist/schema-manager.js +132 -0
- package/dist/templates/admin.d.ts +49 -0
- package/dist/templates/admin.d.ts.map +1 -0
- package/dist/templates/admin.js +1358 -0
- package/dist/templates/ai-routes.d.ts +17 -0
- package/dist/templates/ai-routes.d.ts.map +1 -0
- package/dist/templates/ai-routes.js +1130 -0
- package/dist/templates/ai-service-tools.d.ts +22 -0
- package/dist/templates/ai-service-tools.d.ts.map +1 -0
- package/dist/templates/ai-service-tools.js +1424 -0
- package/dist/templates/ai-service.d.ts +66 -0
- package/dist/templates/ai-service.d.ts.map +1 -0
- package/dist/templates/ai-service.js +2202 -0
- package/dist/templates/api-routes.d.ts +108 -0
- package/dist/templates/api-routes.d.ts.map +1 -0
- package/dist/templates/api-routes.js +1219 -0
- package/dist/templates/auth.d.ts +48 -0
- package/dist/templates/auth.d.ts.map +1 -0
- package/dist/templates/auth.js +381 -0
- package/dist/templates/billing.d.ts +44 -0
- package/dist/templates/billing.d.ts.map +1 -0
- package/dist/templates/billing.js +551 -0
- package/dist/templates/chat.d.ts +63 -0
- package/dist/templates/chat.d.ts.map +1 -0
- package/dist/templates/chat.js +1979 -0
- package/dist/templates/components.d.ts +22 -0
- package/dist/templates/components.d.ts.map +1 -0
- package/dist/templates/components.js +672 -0
- package/dist/templates/config.d.ts +6 -0
- package/dist/templates/config.d.ts.map +1 -0
- package/dist/templates/config.js +86 -0
- package/dist/templates/docker.d.ts +25 -0
- package/dist/templates/docker.d.ts.map +1 -0
- package/dist/templates/docker.js +165 -0
- package/dist/templates/gdpr.d.ts +16 -0
- package/dist/templates/gdpr.d.ts.map +1 -0
- package/dist/templates/gdpr.js +259 -0
- package/dist/templates/index.d.ts +77 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +339 -0
- package/dist/templates/layout.d.ts +67 -0
- package/dist/templates/layout.d.ts.map +1 -0
- package/dist/templates/layout.js +670 -0
- package/dist/templates/mfa.d.ts +23 -0
- package/dist/templates/mfa.d.ts.map +1 -0
- package/dist/templates/mfa.js +353 -0
- package/dist/templates/middleware.d.ts +12 -0
- package/dist/templates/middleware.d.ts.map +1 -0
- package/dist/templates/middleware.js +116 -0
- package/dist/templates/prisma.d.ts +35 -0
- package/dist/templates/prisma.d.ts.map +1 -0
- package/dist/templates/prisma.js +724 -0
- package/dist/templates/provider-routes.d.ts +21 -0
- package/dist/templates/provider-routes.d.ts.map +1 -0
- package/dist/templates/provider-routes.js +1203 -0
- package/dist/templates/rag.d.ts +48 -0
- package/dist/templates/rag.d.ts.map +1 -0
- package/dist/templates/rag.js +532 -0
- package/dist/templates/widget.d.ts +64 -0
- package/dist/templates/widget.d.ts.map +1 -0
- package/dist/templates/widget.js +1360 -0
- package/dist/utils/provider-db.d.ts +63 -0
- package/dist/utils/provider-db.d.ts.map +1 -0
- package/dist/utils/provider-db.js +300 -0
- package/dist/utils.d.ts +78 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +330 -0
- package/package.json +60 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Migrate Command - Simplified Prisma migration management
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.migrateCommand = migrateCommand;
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const ora_1 = __importDefault(require("ora"));
|
|
12
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const execa_1 = require("execa");
|
|
15
|
+
const utils_js_1 = require("../utils.js");
|
|
16
|
+
async function migrateCommand(options) {
|
|
17
|
+
console.log(chalk_1.default.bold.cyan('\nšļø ChimerAI Database Migration\n'));
|
|
18
|
+
const targetDir = (0, utils_js_1.resolveTargetDir)(options.dir);
|
|
19
|
+
if (!(0, utils_js_1.validateWorkspace)(targetDir))
|
|
20
|
+
return;
|
|
21
|
+
if (!(await preflightChecks(targetDir)))
|
|
22
|
+
return;
|
|
23
|
+
if (options.status)
|
|
24
|
+
await showStatus(targetDir);
|
|
25
|
+
else if (options.rollback)
|
|
26
|
+
await rollbackMigration(targetDir);
|
|
27
|
+
else if (options.reset)
|
|
28
|
+
await resetDb(targetDir, options.seed);
|
|
29
|
+
else
|
|
30
|
+
await runMigration(targetDir, options.name, options.seed);
|
|
31
|
+
}
|
|
32
|
+
async function preflightChecks(targetDir) {
|
|
33
|
+
const spinner = (0, ora_1.default)('Pre-flight checks...').start();
|
|
34
|
+
if (!fs_extra_1.default.existsSync(path_1.default.join(targetDir, 'prisma/schema.prisma'))) {
|
|
35
|
+
spinner.fail('prisma/schema.prisma not found');
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
if (!fs_extra_1.default.existsSync(path_1.default.join(targetDir, '.env'))) {
|
|
39
|
+
spinner.fail('.env file not found');
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
const envContent = await fs_extra_1.default.readFile(path_1.default.join(targetDir, '.env'), 'utf-8');
|
|
43
|
+
if (!envContent.includes('DATABASE_URL=') || envContent.includes('DATABASE_URL=""')) {
|
|
44
|
+
spinner.fail('DATABASE_URL not configured');
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
await (0, execa_1.execa)('npx', ['prisma', '--version'], { cwd: targetDir });
|
|
49
|
+
spinner.succeed('Pre-flight checks passed');
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
spinner.fail('Prisma CLI not available. Run: pnpm add -D prisma');
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function showStatus(targetDir) {
|
|
58
|
+
const spinner = (0, ora_1.default)('Checking migration status...').start();
|
|
59
|
+
try {
|
|
60
|
+
const result = await (0, execa_1.execa)('npx', ['prisma', 'migrate', 'status'], { cwd: targetDir });
|
|
61
|
+
spinner.stop();
|
|
62
|
+
console.log(chalk_1.default.bold('š Migration Status:\n'));
|
|
63
|
+
console.log(result.stdout);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
spinner.stop();
|
|
67
|
+
if (error.stderr?.includes('connect')) {
|
|
68
|
+
console.log(chalk_1.default.red('\n ā Cannot connect to database. Is it running?'));
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
console.log(chalk_1.default.yellow('\n ' + (error.stdout || error.stderr || error.message)));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async function runMigration(targetDir, name, seed) {
|
|
76
|
+
const migrationName = name || `migration_${Date.now()}`;
|
|
77
|
+
console.log(chalk_1.default.white(` Migration: ${migrationName}\n`));
|
|
78
|
+
const spinner = (0, ora_1.default)('Generating migration...').start();
|
|
79
|
+
try {
|
|
80
|
+
const result = await (0, execa_1.execa)('npx', ['prisma', 'migrate', 'dev', '--name', migrationName], {
|
|
81
|
+
cwd: targetDir,
|
|
82
|
+
});
|
|
83
|
+
spinner.succeed('Migration applied');
|
|
84
|
+
if (result.stdout)
|
|
85
|
+
console.log(chalk_1.default.gray(result.stdout));
|
|
86
|
+
spinner.start('Generating Prisma client...');
|
|
87
|
+
await (0, execa_1.execa)('npx', ['prisma', 'generate'], { cwd: targetDir });
|
|
88
|
+
spinner.succeed('Prisma client generated');
|
|
89
|
+
if (seed)
|
|
90
|
+
await runSeed(targetDir);
|
|
91
|
+
console.log(chalk_1.default.bold.green('\nā
Migration complete!\n'));
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
spinner.fail('Migration failed');
|
|
95
|
+
console.log(chalk_1.default.red(`\n ${error.stderr || error.message}`));
|
|
96
|
+
console.log(chalk_1.default.cyan('\n š” To undo: chimerai migrate --rollback'));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async function rollbackMigration(targetDir) {
|
|
100
|
+
console.log(chalk_1.default.bold.yellow(' ā ļø Rolling back the last applied migration\n'));
|
|
101
|
+
const spinner = (0, ora_1.default)('Listing applied migrations...').start();
|
|
102
|
+
try {
|
|
103
|
+
// Find the most recent migration directory
|
|
104
|
+
const migrationsDir = path_1.default.join(targetDir, 'prisma/migrations');
|
|
105
|
+
if (!fs_extra_1.default.existsSync(migrationsDir)) {
|
|
106
|
+
spinner.fail('No migrations directory found');
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const entries = await fs_extra_1.default.readdir(migrationsDir, { withFileTypes: true });
|
|
110
|
+
const migrationDirs = entries
|
|
111
|
+
.filter((e) => e.isDirectory() && e.name !== '_migration_lock.toml')
|
|
112
|
+
.map((e) => e.name)
|
|
113
|
+
.sort();
|
|
114
|
+
if (migrationDirs.length === 0) {
|
|
115
|
+
spinner.fail('No migrations found to roll back');
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const lastMigration = migrationDirs[migrationDirs.length - 1];
|
|
119
|
+
spinner.info(`Last migration: ${chalk_1.default.bold(lastMigration)}`);
|
|
120
|
+
// Mark the migration as rolled back using prisma migrate resolve
|
|
121
|
+
spinner.start('Rolling back migration...');
|
|
122
|
+
try {
|
|
123
|
+
await (0, execa_1.execa)('npx', ['prisma', 'migrate', 'resolve', '--rolled-back', lastMigration], {
|
|
124
|
+
cwd: targetDir,
|
|
125
|
+
});
|
|
126
|
+
spinner.succeed(`Marked migration as rolled back: ${lastMigration}`);
|
|
127
|
+
}
|
|
128
|
+
catch (resolveError) {
|
|
129
|
+
// If resolve fails, try db execute with the down migration
|
|
130
|
+
const downSqlPath = path_1.default.join(migrationsDir, lastMigration, 'migration.sql');
|
|
131
|
+
if (!fs_extra_1.default.existsSync(downSqlPath)) {
|
|
132
|
+
spinner.fail('Cannot roll back: migration.sql not found');
|
|
133
|
+
console.log(chalk_1.default.yellow('\n Manual rollback required:'));
|
|
134
|
+
console.log(chalk_1.default.gray(' 1. Undo schema changes in prisma/schema.prisma'));
|
|
135
|
+
console.log(chalk_1.default.gray(' 2. Run: chimerai migrate --name rollback-<description>'));
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
spinner.warn('prisma migrate resolve failed ā trying alternative approach');
|
|
139
|
+
spinner.start('Creating rollback migration...');
|
|
140
|
+
// Create a new "undo" migration by reverting schema and running migrate dev
|
|
141
|
+
console.log(chalk_1.default.yellow('\n Automatic rollback via resolve not possible for this migration.'));
|
|
142
|
+
console.log(chalk_1.default.cyan('\n Recommended manual steps:'));
|
|
143
|
+
console.log(chalk_1.default.white(' 1. Undo schema changes in prisma/schema.prisma'));
|
|
144
|
+
console.log(chalk_1.default.white(` 2. Run: ${chalk_1.default.bold('chimerai migrate --name rollback')}`));
|
|
145
|
+
console.log(chalk_1.default.white(` 3. Or: ${chalk_1.default.bold('npx prisma migrate diff')} to preview changes`));
|
|
146
|
+
spinner.stop();
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
// Regenerate Prisma client
|
|
150
|
+
spinner.start('Regenerating Prisma client...');
|
|
151
|
+
await (0, execa_1.execa)('npx', ['prisma', 'generate'], { cwd: targetDir });
|
|
152
|
+
spinner.succeed('Prisma client regenerated');
|
|
153
|
+
console.log(chalk_1.default.bold.green('\nā
Rollback complete!\n'));
|
|
154
|
+
console.log(chalk_1.default.cyan(' Next steps:'));
|
|
155
|
+
console.log(chalk_1.default.white(' 1. Revert schema changes in prisma/schema.prisma'));
|
|
156
|
+
console.log(chalk_1.default.white(' 2. Run: chimerai migrate --name <new-migration>'));
|
|
157
|
+
console.log(chalk_1.default.white(` 3. Or delete the migration folder: prisma/migrations/${lastMigration}\n`));
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
spinner.fail('Rollback failed');
|
|
161
|
+
console.log(chalk_1.default.red(`\n ${error.stderr || error.message}`));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
async function resetDb(targetDir, seed) {
|
|
165
|
+
console.log(chalk_1.default.bold.red(' ā ļø This will DELETE all data!\n'));
|
|
166
|
+
const spinner = (0, ora_1.default)('Resetting database...').start();
|
|
167
|
+
try {
|
|
168
|
+
await (0, execa_1.execa)('npx', ['prisma', 'migrate', 'reset', '--force'], { cwd: targetDir });
|
|
169
|
+
spinner.succeed('Database reset');
|
|
170
|
+
spinner.start('Generating Prisma client...');
|
|
171
|
+
await (0, execa_1.execa)('npx', ['prisma', 'generate'], { cwd: targetDir });
|
|
172
|
+
spinner.succeed('Prisma client generated');
|
|
173
|
+
if (seed)
|
|
174
|
+
await runSeed(targetDir);
|
|
175
|
+
console.log(chalk_1.default.bold.green('\nā
Database reset complete!\n'));
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
spinner.fail('Reset failed');
|
|
179
|
+
console.log(chalk_1.default.red(`\n ${error.stderr || error.message}`));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async function runSeed(targetDir) {
|
|
183
|
+
if (!fs_extra_1.default.existsSync(path_1.default.join(targetDir, 'prisma/seed.ts')) &&
|
|
184
|
+
!fs_extra_1.default.existsSync(path_1.default.join(targetDir, 'prisma/seed.js'))) {
|
|
185
|
+
console.log(chalk_1.default.yellow('\n ā ļø No seed file found'));
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const spinner = (0, ora_1.default)('Seeding database...').start();
|
|
189
|
+
try {
|
|
190
|
+
await (0, execa_1.execa)('npx', ['prisma', 'db', 'seed'], { cwd: targetDir });
|
|
191
|
+
spinner.succeed('Database seeded');
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
spinner.warn('Seeding had issues');
|
|
195
|
+
console.log(chalk_1.default.yellow(` ${error.stderr || error.message}`));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin Command - Plugin lifecycle management
|
|
3
|
+
*/
|
|
4
|
+
interface PluginOptions {
|
|
5
|
+
dir: string;
|
|
6
|
+
template: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function pluginCommand(action: string, name: string | undefined, options: PluginOptions): Promise<void>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/commands/plugin.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,UAAU,aAAa;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,EAAE,aAAa,iBAoBvB"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Plugin Command - Plugin lifecycle management
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.pluginCommand = pluginCommand;
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const ora_1 = __importDefault(require("ora"));
|
|
12
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const utils_js_1 = require("../utils.js");
|
|
15
|
+
async function pluginCommand(action, name, options) {
|
|
16
|
+
const targetDir = (0, utils_js_1.resolveTargetDir)(options.dir);
|
|
17
|
+
switch (action) {
|
|
18
|
+
case 'create':
|
|
19
|
+
if (!name) {
|
|
20
|
+
(0, utils_js_1.handleCliError)('Please provide a plugin name');
|
|
21
|
+
}
|
|
22
|
+
await createPlugin(targetDir, name, options.template);
|
|
23
|
+
break;
|
|
24
|
+
case 'list':
|
|
25
|
+
await listPlugins(targetDir);
|
|
26
|
+
break;
|
|
27
|
+
case 'scaffold':
|
|
28
|
+
await scaffoldPluginSystem(targetDir);
|
|
29
|
+
break;
|
|
30
|
+
default:
|
|
31
|
+
(0, utils_js_1.handleCliError)(`Unknown action: ${action}. Available: create <name>, list, scaffold`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function createPlugin(targetDir, name, template) {
|
|
35
|
+
console.log(chalk_1.default.bold.cyan(`\nš Creating plugin: ${name}\n`));
|
|
36
|
+
const pluginDir = path_1.default.join(targetDir, 'plugins', name);
|
|
37
|
+
if (fs_extra_1.default.existsSync(pluginDir)) {
|
|
38
|
+
(0, utils_js_1.handleCliError)(`Plugin already exists: plugins/${name}`);
|
|
39
|
+
}
|
|
40
|
+
const spinner = (0, ora_1.default)('Scaffolding plugin...').start();
|
|
41
|
+
try {
|
|
42
|
+
await fs_extra_1.default.ensureDir(path_1.default.join(pluginDir, 'src'));
|
|
43
|
+
const prettyName = name
|
|
44
|
+
.split(/[-_]/)
|
|
45
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
46
|
+
.join(' ');
|
|
47
|
+
const hooks = template === 'api'
|
|
48
|
+
? ['ai.request.pre', 'ai.response.post']
|
|
49
|
+
: template === 'ui'
|
|
50
|
+
? ['ui.render.pre', 'ui.config.load']
|
|
51
|
+
: ['ai.response.post'];
|
|
52
|
+
await fs_extra_1.default.writeJson(path_1.default.join(pluginDir, 'manifest.json'), {
|
|
53
|
+
id: name,
|
|
54
|
+
name: prettyName,
|
|
55
|
+
version: '1.0.0',
|
|
56
|
+
description: `${prettyName} plugin for ChimerAI`,
|
|
57
|
+
hooks,
|
|
58
|
+
permissions: [],
|
|
59
|
+
config: { enabled: { type: 'boolean', default: true } },
|
|
60
|
+
}, { spaces: 2 });
|
|
61
|
+
spinner.succeed('Created manifest.json');
|
|
62
|
+
spinner.start('Creating plugin source...');
|
|
63
|
+
const handlerContent = `import type { HookContext, HookHandler } from '@/lib/plugin-engine';
|
|
64
|
+
|
|
65
|
+
export const handler: HookHandler = async (ctx: HookContext) => {
|
|
66
|
+
const { data, config } = ctx;
|
|
67
|
+
return {
|
|
68
|
+
data: { ...data, _plugin: '${name}', _processedAt: new Date().toISOString() },
|
|
69
|
+
modified: true,
|
|
70
|
+
logs: ['${prettyName}: processed successfully'],
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export function onInstall(config: Record<string, unknown>) {
|
|
75
|
+
console.log('${prettyName} installed with config:', config);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function onUninstall() {
|
|
79
|
+
console.log('${prettyName} uninstalled');
|
|
80
|
+
}
|
|
81
|
+
`;
|
|
82
|
+
await fs_extra_1.default.writeFile(path_1.default.join(pluginDir, 'src/index.ts'), handlerContent);
|
|
83
|
+
if (template === 'api') {
|
|
84
|
+
await fs_extra_1.default.writeFile(path_1.default.join(pluginDir, 'src/routes.ts'), `import { NextRequest, NextResponse } from 'next/server';
|
|
85
|
+
|
|
86
|
+
export async function getStatus(req: NextRequest) {
|
|
87
|
+
return NextResponse.json({ plugin: '${name}', status: 'active', version: '1.0.0' });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export async function updateConfig(req: NextRequest) {
|
|
91
|
+
const body = await req.json();
|
|
92
|
+
return NextResponse.json({ success: true, config: body });
|
|
93
|
+
}
|
|
94
|
+
`);
|
|
95
|
+
}
|
|
96
|
+
if (template === 'ui') {
|
|
97
|
+
const compName = name
|
|
98
|
+
.split(/[-_]/)
|
|
99
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
100
|
+
.join('');
|
|
101
|
+
await fs_extra_1.default.writeFile(path_1.default.join(pluginDir, 'src/components.tsx'), `'use client';
|
|
102
|
+
import React from 'react';
|
|
103
|
+
|
|
104
|
+
interface ${compName}Props { title?: string; children?: React.ReactNode; }
|
|
105
|
+
|
|
106
|
+
export function ${compName}Panel({ title, children }: ${compName}Props) {
|
|
107
|
+
return (
|
|
108
|
+
<div className="border rounded-lg p-4 bg-white shadow-sm">
|
|
109
|
+
<h3 className="text-lg font-semibold mb-2">{title || '${prettyName}'}</h3>
|
|
110
|
+
<div>{children}</div>
|
|
111
|
+
</div>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function ${compName}Status() {
|
|
116
|
+
return (
|
|
117
|
+
<div className="flex items-center gap-2 text-sm">
|
|
118
|
+
<span className="w-2 h-2 rounded-full bg-green-500" />
|
|
119
|
+
<span className="text-gray-600">${prettyName} active</span>
|
|
120
|
+
</div>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
`);
|
|
124
|
+
}
|
|
125
|
+
spinner.succeed('Created plugin source files');
|
|
126
|
+
await fs_extra_1.default.writeFile(path_1.default.join(pluginDir, 'README.md'), `# ${prettyName}\n\nA ChimerAI plugin.\n\n## Hooks\n\n${hooks.map((h) => `- \`${h}\``).join('\n')}\n\n## Usage\n\n1. Edit \`plugins/${name}/src/index.ts\`\n2. Register in the plugin engine\n3. Test with \`chimerai plugin list\`\n`);
|
|
127
|
+
spinner.succeed('Created README.md');
|
|
128
|
+
console.log(chalk_1.default.bold.green(`\n⨠Plugin '${name}' created!\n`));
|
|
129
|
+
console.log(chalk_1.default.cyan('š Structure:'));
|
|
130
|
+
console.log(chalk_1.default.white(` plugins/${name}/`));
|
|
131
|
+
console.log(chalk_1.default.white(' āāā manifest.json'));
|
|
132
|
+
console.log(chalk_1.default.white(' āāā README.md'));
|
|
133
|
+
console.log(chalk_1.default.white(' āāā src/index.ts'));
|
|
134
|
+
if (template === 'api')
|
|
135
|
+
console.log(chalk_1.default.white(' āāā src/routes.ts'));
|
|
136
|
+
if (template === 'ui')
|
|
137
|
+
console.log(chalk_1.default.white(' āāā src/components.tsx'));
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
spinner.fail('Failed to create plugin');
|
|
141
|
+
console.error(chalk_1.default.red(error.message));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
async function listPlugins(targetDir) {
|
|
145
|
+
console.log(chalk_1.default.bold.cyan('\nš Installed Plugins\n'));
|
|
146
|
+
const pluginsDir = path_1.default.join(targetDir, 'plugins');
|
|
147
|
+
if (!fs_extra_1.default.existsSync(pluginsDir)) {
|
|
148
|
+
console.log(chalk_1.default.yellow(' No plugins directory found.\n Run: chimerai plugin create <name>\n'));
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const entries = await fs_extra_1.default.readdir(pluginsDir, { withFileTypes: true });
|
|
152
|
+
const dirs = entries.filter((e) => e.isDirectory());
|
|
153
|
+
if (dirs.length === 0) {
|
|
154
|
+
console.log(chalk_1.default.yellow(' No plugins installed.\n'));
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
for (const dir of dirs) {
|
|
158
|
+
const manifestPath = path_1.default.join(pluginsDir, dir.name, 'manifest.json');
|
|
159
|
+
if (fs_extra_1.default.existsSync(manifestPath)) {
|
|
160
|
+
try {
|
|
161
|
+
const m = await fs_extra_1.default.readJson(manifestPath);
|
|
162
|
+
console.log(` ${chalk_1.default.green('ā')} ${chalk_1.default.bold(m.name || dir.name)} ${chalk_1.default.gray(`v${m.version || '0.0.0'}`)}`);
|
|
163
|
+
console.log(chalk_1.default.gray(` ${m.description || 'No description'}`));
|
|
164
|
+
if (m.hooks?.length)
|
|
165
|
+
console.log(chalk_1.default.gray(` Hooks: ${m.hooks.join(', ')}`));
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
console.log(` ${chalk_1.default.yellow('ā')} ${chalk_1.default.bold(dir.name)} ${chalk_1.default.gray('(invalid manifest)')}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
console.log(` ${chalk_1.default.gray('ā')} ${chalk_1.default.bold(dir.name)} ${chalk_1.default.gray('(no manifest)')}`);
|
|
173
|
+
}
|
|
174
|
+
console.log('');
|
|
175
|
+
}
|
|
176
|
+
console.log(chalk_1.default.bold(` š ${dirs.length} plugin(s) found\n`));
|
|
177
|
+
}
|
|
178
|
+
async function scaffoldPluginSystem(targetDir) {
|
|
179
|
+
console.log(chalk_1.default.bold.cyan('\nšļø Scaffolding Plugin System\n'));
|
|
180
|
+
const spinner = (0, ora_1.default)('Creating plugin infrastructure...').start();
|
|
181
|
+
try {
|
|
182
|
+
await fs_extra_1.default.ensureDir(path_1.default.join(targetDir, 'plugins'));
|
|
183
|
+
spinner.succeed('Created plugins/ directory');
|
|
184
|
+
spinner.start('Creating plugin loader...');
|
|
185
|
+
const loaderContent = `import fs from 'fs';
|
|
186
|
+
import path from 'path';
|
|
187
|
+
import { registerPluginHandler } from '@/lib/plugin-engine';
|
|
188
|
+
|
|
189
|
+
interface PluginManifest { id: string; name: string; version: string; hooks: string[]; }
|
|
190
|
+
|
|
191
|
+
export async function loadPlugins() {
|
|
192
|
+
const pluginsDir = path.join(process.cwd(), 'plugins');
|
|
193
|
+
if (!fs.existsSync(pluginsDir)) return;
|
|
194
|
+
|
|
195
|
+
const entries = fs.readdirSync(pluginsDir, { withFileTypes: true });
|
|
196
|
+
for (const entry of entries) {
|
|
197
|
+
if (!entry.isDirectory()) continue;
|
|
198
|
+
const manifestPath = path.join(pluginsDir, entry.name, 'manifest.json');
|
|
199
|
+
if (!fs.existsSync(manifestPath)) continue;
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
const manifest: PluginManifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
|
|
203
|
+
|
|
204
|
+
// Try compiled .js first, then fall back to .ts (for ts-node / tsx runtimes)
|
|
205
|
+
const distEntry = path.join(pluginsDir, entry.name, 'dist/index.js');
|
|
206
|
+
const srcEntry = path.join(pluginsDir, entry.name, 'src/index.js');
|
|
207
|
+
const tsEntry = path.join(pluginsDir, entry.name, 'src/index.ts');
|
|
208
|
+
|
|
209
|
+
let modPath: string;
|
|
210
|
+
if (fs.existsSync(distEntry)) modPath = distEntry;
|
|
211
|
+
else if (fs.existsSync(srcEntry)) modPath = srcEntry;
|
|
212
|
+
else if (fs.existsSync(tsEntry)) modPath = tsEntry;
|
|
213
|
+
else {
|
|
214
|
+
console.warn(\`[plugins] No entry file found for \${entry.name}, skipping\`);
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const mod = await import(modPath);
|
|
219
|
+
for (const hook of manifest.hooks) {
|
|
220
|
+
const handler = mod.handler || mod.default;
|
|
221
|
+
if (handler) registerPluginHandler(manifest.id, hook, handler);
|
|
222
|
+
}
|
|
223
|
+
console.log(\`[plugins] Loaded \${manifest.name || entry.name} v\${manifest.version}\`);
|
|
224
|
+
} catch (error) {
|
|
225
|
+
console.error(\`[plugins] Failed to load \${entry.name}:\`, error);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
`;
|
|
230
|
+
await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'lib/plugin-loader.ts'), loaderContent);
|
|
231
|
+
spinner.succeed('Created lib/plugin-loader.ts');
|
|
232
|
+
console.log(chalk_1.default.bold.green('\n⨠Plugin system scaffolded!\n'));
|
|
233
|
+
console.log(chalk_1.default.cyan('Next: chimerai plugin create my-plugin\n'));
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
spinner.fail('Failed to scaffold plugin system');
|
|
237
|
+
console.error(chalk_1.default.red(error.message));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remove Command - Remove components from a ChimerAI project
|
|
3
|
+
*/
|
|
4
|
+
interface RemoveOptions {
|
|
5
|
+
dir: string;
|
|
6
|
+
keepData: boolean;
|
|
7
|
+
yes: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function removeCommand(component: string, options: RemoveOptions): Promise<void>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=remove.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../src/commands/remove.ts"],"names":[],"mappings":"AAAA;;GAEG;AAoBH,UAAU,aAAa;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,OAAO,CAAC;IAClB,GAAG,EAAE,OAAO,CAAC;CACd;AAoND,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,iBA0X5E"}
|