@chimerai/cli 0.2.88 → 0.2.90
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/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +76 -0
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +121 -48
- package/dist/templates/chat.d.ts +1 -0
- package/dist/templates/chat.d.ts.map +1 -1
- package/dist/templates/chat.js +135 -0
- package/dist/templates/components.d.ts.map +1 -1
- package/dist/templates/components.js +0 -6
- package/dist/templates/index.d.ts +4 -4
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/index.js +8 -3
- package/dist/templates/layout.d.ts +8 -0
- package/dist/templates/layout.d.ts.map +1 -1
- package/dist/templates/layout.js +149 -0
- package/dist/templates/middleware.d.ts +7 -0
- package/dist/templates/middleware.d.ts.map +1 -1
- package/dist/templates/middleware.js +63 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAiBH,UAAU,UAAU;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAiBH,UAAU,UAAU;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAk5ED,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,iBAyHtE"}
|
package/dist/commands/add.js
CHANGED
|
@@ -185,6 +185,18 @@ model ApiKey {
|
|
|
185
185
|
@@index([keyHash])
|
|
186
186
|
}
|
|
187
187
|
`,
|
|
188
|
+
filePatches: [
|
|
189
|
+
{
|
|
190
|
+
marker: '// @chimerai component=AppPageNoAuth version=1.0',
|
|
191
|
+
target: 'app/page.tsx',
|
|
192
|
+
generator: () => templates.generateAppPage(),
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
marker: '// @chimerai component=MiddlewareNoAuth version=1.0',
|
|
196
|
+
target: 'middleware.ts',
|
|
197
|
+
generator: () => templates.generateMiddleware(),
|
|
198
|
+
},
|
|
199
|
+
],
|
|
188
200
|
envVars: [
|
|
189
201
|
{
|
|
190
202
|
key: 'DATABASE_URL',
|
|
@@ -285,6 +297,7 @@ Next steps:
|
|
|
285
297
|
name: 'chat-ui',
|
|
286
298
|
displayName: 'Chat UI',
|
|
287
299
|
description: 'Full-featured chat interface with streaming, conversation management, and multi-provider support',
|
|
300
|
+
requiredFeatures: ['auth'],
|
|
288
301
|
requiredUtils: [
|
|
289
302
|
{ generator: () => templates.generateUseAppNameHook(), target: 'lib/use-app-name.ts' },
|
|
290
303
|
],
|
|
@@ -774,6 +787,7 @@ Next steps:
|
|
|
774
787
|
name: 'billing',
|
|
775
788
|
displayName: 'Billing System',
|
|
776
789
|
description: 'Stripe integration for subscriptions',
|
|
790
|
+
requiredFeatures: ['auth'],
|
|
777
791
|
files: [
|
|
778
792
|
{
|
|
779
793
|
generator: () => templates.generateBillingPage(),
|
|
@@ -884,6 +898,7 @@ Next steps:
|
|
|
884
898
|
name: 'audit-log',
|
|
885
899
|
displayName: 'Audit Log',
|
|
886
900
|
description: 'Compliance audit logging — track all admin and user actions',
|
|
901
|
+
requiredFeatures: ['auth', 'admin-dashboard'],
|
|
887
902
|
files: [
|
|
888
903
|
{
|
|
889
904
|
generator: () => templates.generateAdminLogsPage(),
|
|
@@ -904,6 +919,7 @@ Next steps:
|
|
|
904
919
|
name: 'admin-dashboard',
|
|
905
920
|
displayName: 'Admin Dashboard',
|
|
906
921
|
description: 'Complete admin panel with user/role management, settings, audit logs, and RBAC',
|
|
922
|
+
requiredFeatures: ['auth'],
|
|
907
923
|
files: [
|
|
908
924
|
// Admin layout with session + admin role guard
|
|
909
925
|
{
|
|
@@ -1159,7 +1175,50 @@ function transformSchemaForSqlite(schema) {
|
|
|
1159
1175
|
* Generic component addition function (PHASE 4 refactoring)
|
|
1160
1176
|
* Uses inline template generators — no fs.copy(), no dependency on templates/ folder
|
|
1161
1177
|
*/
|
|
1178
|
+
/**
|
|
1179
|
+
* Checks if a given feature marker exists anywhere in the project's package.json
|
|
1180
|
+
* or in a generated file (by scanning for the @chimerai marker convention).
|
|
1181
|
+
* We use presence of installed packages as a proxy:
|
|
1182
|
+
* - 'auth' → next-auth in dependencies
|
|
1183
|
+
* - 'rbac' → @chimerai/rbac or lib/rbac.ts present
|
|
1184
|
+
* - 'admin-dashboard'→ @chimerai/admin-ui or app/admin present
|
|
1185
|
+
* - 'billing' → stripe in dependencies
|
|
1186
|
+
*/
|
|
1187
|
+
async function hasFeature(feature, targetDir) {
|
|
1188
|
+
const pkgPath = path_1.default.join(targetDir, 'package.json');
|
|
1189
|
+
try {
|
|
1190
|
+
const pkg = await fs_extra_1.default.readJson(pkgPath);
|
|
1191
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
1192
|
+
if (feature === 'auth')
|
|
1193
|
+
return 'next-auth' in deps;
|
|
1194
|
+
if (feature === 'billing')
|
|
1195
|
+
return 'stripe' in deps;
|
|
1196
|
+
if (feature === 'rbac') {
|
|
1197
|
+
return '@chimerai/rbac' in deps || (await fs_extra_1.default.pathExists(path_1.default.join(targetDir, 'lib/rbac.ts')));
|
|
1198
|
+
}
|
|
1199
|
+
if (feature === 'admin-dashboard') {
|
|
1200
|
+
return ('@chimerai/admin-ui' in deps || (await fs_extra_1.default.pathExists(path_1.default.join(targetDir, 'app/admin'))));
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
catch {
|
|
1204
|
+
// ignore — treat as missing
|
|
1205
|
+
}
|
|
1206
|
+
return false;
|
|
1207
|
+
}
|
|
1162
1208
|
async function addComponent(config, targetDir) {
|
|
1209
|
+
// ── Pre-flight: check required features ────────────────────────────────
|
|
1210
|
+
if (config.requiredFeatures && config.requiredFeatures.length > 0) {
|
|
1211
|
+
const missing = [];
|
|
1212
|
+
for (const req of config.requiredFeatures) {
|
|
1213
|
+
if (!(await hasFeature(req, targetDir)))
|
|
1214
|
+
missing.push(req);
|
|
1215
|
+
}
|
|
1216
|
+
if (missing.length > 0) {
|
|
1217
|
+
console.error(chalk_1.default.red(`\n✗ Cannot add "${config.name}" — missing required feature(s): ${missing.map((f) => `"${f}"`).join(', ')}`));
|
|
1218
|
+
console.error(chalk_1.default.yellow(` Run first: ${missing.map((f) => `chimerai add ${f}`).join(' then ')}`));
|
|
1219
|
+
process.exit(1);
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1163
1222
|
const spinner = (0, ora_1.default)(`Adding ${config.displayName}...`).start();
|
|
1164
1223
|
try {
|
|
1165
1224
|
// 1. Generate and write all required files
|
|
@@ -1200,6 +1259,23 @@ async function addComponent(config, targetDir) {
|
|
|
1200
1259
|
}
|
|
1201
1260
|
// 1.6 (removed) — We no longer patch the user's root layout.
|
|
1202
1261
|
// Instead, the postAddMessage tells the user how to add SessionProvider.
|
|
1262
|
+
// 1.6b Apply filePatches — upgrade existing no-auth files to auth-aware versions
|
|
1263
|
+
if (config.filePatches) {
|
|
1264
|
+
for (const patch of config.filePatches) {
|
|
1265
|
+
const targetPath = path_1.default.join(targetDir, patch.target);
|
|
1266
|
+
if (!(await fs_extra_1.default.pathExists(targetPath)))
|
|
1267
|
+
continue;
|
|
1268
|
+
const existing = await fs_extra_1.default.readFile(targetPath, 'utf-8');
|
|
1269
|
+
if (existing.includes(patch.marker)) {
|
|
1270
|
+
// File has the no-auth marker \u2014 replace it with auth-aware version
|
|
1271
|
+
const bakPath = targetPath + '.bak';
|
|
1272
|
+
await fs_extra_1.default.writeFile(bakPath, existing); // backup
|
|
1273
|
+
await fs_extra_1.default.writeFile(targetPath, patch.generator());
|
|
1274
|
+
spinner.text = `Adding ${config.displayName}... (upgraded ${patch.target})`;
|
|
1275
|
+
}
|
|
1276
|
+
// If marker absent, file is already the auth-aware version \u2014 skip
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1203
1279
|
// 1.7 Auto-write environment variables to .env
|
|
1204
1280
|
if (config.envVars && config.envVars.length > 0) {
|
|
1205
1281
|
const envPath = path_1.default.join(targetDir, '.env');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmBH,UAAU,aAAa;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmBH,UAAU,aAAa;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAmED,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,iBAyI9E"}
|
package/dist/commands/create.js
CHANGED
|
@@ -54,14 +54,34 @@ const license_js_1 = require("../license.js");
|
|
|
54
54
|
/** Canonical feature definitions for `chimerai create` */
|
|
55
55
|
const AVAILABLE_FEATURES = [
|
|
56
56
|
{ name: '🔐 Authentication (NextAuth)', value: 'auth', licenseKey: 'auth', checked: true },
|
|
57
|
-
{
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
{
|
|
58
|
+
name: '👥 RBAC System (Users, Roles, Permissions)',
|
|
59
|
+
value: 'rbac',
|
|
60
|
+
licenseKey: 'rbac',
|
|
61
|
+
checked: true,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: '🔌 Model Providers Management',
|
|
65
|
+
value: 'model-providers',
|
|
66
|
+
licenseKey: 'model-providers',
|
|
67
|
+
checked: true,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: '📝 Prompt Template Management',
|
|
71
|
+
value: 'prompt-management',
|
|
72
|
+
licenseKey: 'prompt-management',
|
|
73
|
+
checked: true,
|
|
74
|
+
},
|
|
60
75
|
{ name: '💬 AI Chat Interface', value: 'ai-chat', licenseKey: 'ai-chat', checked: false },
|
|
61
76
|
{ name: '🔍 RAG / Vector Store (FAISS)', value: 'rag', licenseKey: 'rag', checked: false },
|
|
62
77
|
{ name: '💳 Billing System (Stripe)', value: 'billing', licenseKey: 'billing', checked: false },
|
|
63
78
|
{ name: '📊 API Usage Analytics', value: 'analytics', licenseKey: 'analytics', checked: true },
|
|
64
|
-
{
|
|
79
|
+
{
|
|
80
|
+
name: '🎨 Admin Dashboard',
|
|
81
|
+
value: 'admin-dashboard',
|
|
82
|
+
licenseKey: 'admin-dashboard',
|
|
83
|
+
checked: true,
|
|
84
|
+
},
|
|
65
85
|
];
|
|
66
86
|
function getRequiredTierLabel(licenseKey) {
|
|
67
87
|
if (license_js_1.FREE_COMPONENTS.has(licenseKey))
|
|
@@ -133,6 +153,22 @@ async function createCommand(projectName, options) {
|
|
|
133
153
|
if (selectedFeatures.length === 0) {
|
|
134
154
|
(0, utils_js_1.handleCliError)('No features selected');
|
|
135
155
|
}
|
|
156
|
+
// Validate feature combinations and warn about missing dependencies
|
|
157
|
+
const featureWarnings = validateFeatureCombination(selectedFeatures);
|
|
158
|
+
if (featureWarnings.length > 0) {
|
|
159
|
+
console.warn(chalk_1.default.yellow('\n⚠️ Feature combination warnings:'));
|
|
160
|
+
featureWarnings.forEach((w) => console.warn(chalk_1.default.yellow(` • ${w}`)));
|
|
161
|
+
const answers = await inquirer_1.default.prompt([
|
|
162
|
+
{
|
|
163
|
+
type: 'confirm',
|
|
164
|
+
name: 'confirmed',
|
|
165
|
+
message: 'Continue anyway?',
|
|
166
|
+
default: true,
|
|
167
|
+
},
|
|
168
|
+
]);
|
|
169
|
+
if (!answers.confirmed)
|
|
170
|
+
process.exit(0);
|
|
171
|
+
}
|
|
136
172
|
console.log(chalk_1.default.bold.green('\n✨ Creating project with features:'));
|
|
137
173
|
selectedFeatures.forEach((f) => {
|
|
138
174
|
const feature = AVAILABLE_FEATURES.find((feat) => feat.value === f);
|
|
@@ -156,9 +192,11 @@ async function createCommand(projectName, options) {
|
|
|
156
192
|
console.log(chalk_1.default.white(` cd ${projectName}`));
|
|
157
193
|
console.log(chalk_1.default.white(' npm run dev'));
|
|
158
194
|
console.log(chalk_1.default.gray('\n Server will run on http://localhost:3001\n'));
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
195
|
+
if (selectedFeatures.includes('auth')) {
|
|
196
|
+
console.log(chalk_1.default.yellow('Login with:'));
|
|
197
|
+
console.log(chalk_1.default.white(' Email: admin@example.com'));
|
|
198
|
+
console.log(chalk_1.default.white(' Password: admin123\n'));
|
|
199
|
+
}
|
|
162
200
|
}
|
|
163
201
|
catch (error) {
|
|
164
202
|
console.log(chalk_1.default.red('\n❌ Installation failed'));
|
|
@@ -187,6 +225,33 @@ async function createCommand(projectName, options) {
|
|
|
187
225
|
}
|
|
188
226
|
console.log(chalk_1.default.gray('\n Server will run on http://localhost:3001\n'));
|
|
189
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Validates that the selected feature combination makes sense.
|
|
230
|
+
* Returns an array of human-readable warning strings (empty = OK).
|
|
231
|
+
*/
|
|
232
|
+
function validateFeatureCombination(features) {
|
|
233
|
+
const warnings = [];
|
|
234
|
+
const authRequired = [
|
|
235
|
+
'rbac',
|
|
236
|
+
'admin-dashboard',
|
|
237
|
+
'billing',
|
|
238
|
+
'mfa',
|
|
239
|
+
'gdpr',
|
|
240
|
+
'audit-log',
|
|
241
|
+
'chat-ui',
|
|
242
|
+
];
|
|
243
|
+
if (!features.includes('auth')) {
|
|
244
|
+
authRequired.forEach((f) => {
|
|
245
|
+
if (features.includes(f)) {
|
|
246
|
+
warnings.push(`"${f}" requires "auth" — it may not work correctly without it`);
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
if (features.includes('audit-log') && !features.includes('admin-dashboard')) {
|
|
251
|
+
warnings.push('"audit-log" works best with "admin-dashboard"');
|
|
252
|
+
}
|
|
253
|
+
return warnings;
|
|
254
|
+
}
|
|
190
255
|
async function createProject(targetDir, projectName, features, sqlite) {
|
|
191
256
|
const spinner = (0, ora_1.default)('Creating project structure...').start();
|
|
192
257
|
try {
|
|
@@ -238,7 +303,7 @@ async function createProject(targetDir, projectName, features, sqlite) {
|
|
|
238
303
|
}
|
|
239
304
|
catch (error) {
|
|
240
305
|
spinner.fail(chalk_1.default.red('Failed to create project'));
|
|
241
|
-
console.error(error.message);
|
|
306
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
242
307
|
throw error;
|
|
243
308
|
}
|
|
244
309
|
}
|
|
@@ -282,7 +347,9 @@ async function createBaseStructure(targetDir, projectName, features) {
|
|
|
282
347
|
: templates.generateAppLayout(projectName);
|
|
283
348
|
await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/layout.tsx'), layoutContent);
|
|
284
349
|
// Create app/page.tsx using template generator
|
|
285
|
-
const pageContent =
|
|
350
|
+
const pageContent = features.includes('auth')
|
|
351
|
+
? templates.generateAppPage()
|
|
352
|
+
: templates.generateAppPageNoAuth();
|
|
286
353
|
await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/page.tsx'), pageContent);
|
|
287
354
|
// Create globals.css using template generator
|
|
288
355
|
const globalsCss = templates.generateGlobalsCss();
|
|
@@ -294,18 +361,19 @@ async function createPackageJson(targetDir, projectName, features) {
|
|
|
294
361
|
react: '^18.3.1',
|
|
295
362
|
'react-dom': '^18.3.1',
|
|
296
363
|
'@prisma/client': '^5.22.0',
|
|
297
|
-
// Auth is core infrastructure — routes, middleware, and API handlers all depend on it
|
|
298
|
-
'next-auth': '^4.24.10',
|
|
299
|
-
'@auth/prisma-adapter': '^2.11.1',
|
|
300
|
-
'bcryptjs': '^2.4.3',
|
|
301
|
-
'next-themes': '^0.4.4',
|
|
302
|
-
'sonner': '^1.7.0',
|
|
303
364
|
};
|
|
365
|
+
// Auth dependencies — only when auth feature is selected
|
|
366
|
+
if (features.includes('auth')) {
|
|
367
|
+
dependencies['next-auth'] = '^4.24.10';
|
|
368
|
+
dependencies['@auth/prisma-adapter'] = '^2.11.1';
|
|
369
|
+
dependencies['bcryptjs'] = '^2.4.3';
|
|
370
|
+
dependencies['next-themes'] = '^0.4.4';
|
|
371
|
+
dependencies['sonner'] = '^1.7.0';
|
|
372
|
+
}
|
|
304
373
|
const devDependencies = {
|
|
305
374
|
'@types/node': '^20',
|
|
306
375
|
'@types/react': '^18',
|
|
307
376
|
'@types/react-dom': '^18',
|
|
308
|
-
'@types/bcryptjs': '^2.4.6',
|
|
309
377
|
typescript: '^5',
|
|
310
378
|
tailwindcss: '^3.4.0',
|
|
311
379
|
postcss: '^8.5.10',
|
|
@@ -313,6 +381,9 @@ async function createPackageJson(targetDir, projectName, features) {
|
|
|
313
381
|
prisma: '^5.22.0',
|
|
314
382
|
tsx: '^4.20.6',
|
|
315
383
|
};
|
|
384
|
+
if (features.includes('auth')) {
|
|
385
|
+
devDependencies['@types/bcryptjs'] = '^2.4.6';
|
|
386
|
+
}
|
|
316
387
|
// Note: ChimerAI workspace packages are not yet published to npm
|
|
317
388
|
// For standalone projects, these features will need manual implementation
|
|
318
389
|
// or you can use the complete starter kit with 'chimerai init'
|
|
@@ -358,10 +429,8 @@ async function createPackageJson(targetDir, projectName, features) {
|
|
|
358
429
|
},
|
|
359
430
|
dependencies,
|
|
360
431
|
devDependencies,
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
uuid: '^11',
|
|
364
|
-
},
|
|
432
|
+
// uuid override only needed when next-auth is installed (suppresses uuid@8 deprecation warning)
|
|
433
|
+
...(features.includes('auth') ? { overrides: { uuid: '^11' } } : {}),
|
|
365
434
|
prisma: {
|
|
366
435
|
seed: 'tsx prisma/seed.ts',
|
|
367
436
|
},
|
|
@@ -857,8 +926,10 @@ async function copyFeatureFiles(targetDir, features) {
|
|
|
857
926
|
}
|
|
858
927
|
// Health check endpoint (used by Docker healthcheck and monitoring)
|
|
859
928
|
const healthRoute = templates.generateHealthRoute();
|
|
860
|
-
// Next.js middleware
|
|
861
|
-
const middleware =
|
|
929
|
+
// Next.js middleware — auth-aware version when auth selected, CORS-only otherwise
|
|
930
|
+
const middleware = features.includes('auth')
|
|
931
|
+
? templates.generateMiddleware()
|
|
932
|
+
: templates.generateMiddlewareNoAuth();
|
|
862
933
|
await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'middleware.ts'), middleware);
|
|
863
934
|
await fs_extra_1.default.ensureDir(path_1.default.join(targetDir, 'app/api/health'));
|
|
864
935
|
await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/api/health/route.ts'), healthRoute);
|
|
@@ -941,6 +1012,14 @@ async function copyFeatureFiles(targetDir, features) {
|
|
|
941
1012
|
const providersPage = templates.generateModelProvidersPage();
|
|
942
1013
|
await fs_extra_1.default.ensureDir(path_1.default.join(targetDir, 'app/dashboard/providers'));
|
|
943
1014
|
await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/dashboard/providers/page.tsx'), providersPage);
|
|
1015
|
+
// No-auth dashboard landing page + layout (when auth is not selected)
|
|
1016
|
+
if (!features.includes('auth')) {
|
|
1017
|
+
const noAuthDashPage = templates.generateDashboardPageNoAuth(features);
|
|
1018
|
+
await fs_extra_1.default.ensureDir(path_1.default.join(targetDir, 'app/dashboard'));
|
|
1019
|
+
await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/dashboard/page.tsx'), noAuthDashPage);
|
|
1020
|
+
const noAuthDashLayout = templates.generateDashboardLayoutNoAuth();
|
|
1021
|
+
await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/dashboard/layout.tsx'), noAuthDashLayout);
|
|
1022
|
+
}
|
|
944
1023
|
if (features.includes('admin')) {
|
|
945
1024
|
// Admin layout with session check + admin role guard
|
|
946
1025
|
const adminLayout = templates.generateAdminLayout();
|
|
@@ -1155,7 +1234,7 @@ async function getServerSessionWithPermissions() {
|
|
|
1155
1234
|
].join('\n') + '\n');
|
|
1156
1235
|
// Chat page
|
|
1157
1236
|
await fs_extra_1.default.ensureDir(path_1.default.join(targetDir, 'app/(app)/chat'));
|
|
1158
|
-
await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/(app)/chat/page.tsx'), templates.generateChatPage());
|
|
1237
|
+
await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/(app)/chat/page.tsx'), features.includes('auth') ? templates.generateChatPage() : templates.generateChatPageNoAuth());
|
|
1159
1238
|
// API routes
|
|
1160
1239
|
await fs_extra_1.default.ensureDir(path_1.default.join(targetDir, 'app/api/v1/chat/stream'));
|
|
1161
1240
|
await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/api/v1/chat/stream/route.ts'), templates.generateChatStreamRouteWithPersistence());
|
|
@@ -1214,8 +1293,20 @@ async function getServerSessionWithPermissions() {
|
|
|
1214
1293
|
}
|
|
1215
1294
|
}
|
|
1216
1295
|
async function createSeedScript(targetDir, features, sqlite) {
|
|
1296
|
+
// Without auth there are no users/providers to seed — write a minimal placeholder
|
|
1297
|
+
if (!features.includes('auth')) {
|
|
1298
|
+
const minimalSeed = `import { PrismaClient } from '@prisma/client';
|
|
1299
|
+
const prisma = new PrismaClient();
|
|
1300
|
+
async function main() {
|
|
1301
|
+
console.log('🌱 No auth feature selected — nothing to seed yet.');
|
|
1302
|
+
console.log(' Run: chimerai add auth to add authentication.');
|
|
1303
|
+
}
|
|
1304
|
+
main().catch(console.error).finally(() => prisma.$disconnect());
|
|
1305
|
+
`;
|
|
1306
|
+
await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'prisma/seed.ts'), minimalSeed);
|
|
1307
|
+
return;
|
|
1308
|
+
}
|
|
1217
1309
|
// Generate seed script with feature-specific configuration
|
|
1218
|
-
// next-auth / bcryptjs are always installed (core infrastructure)
|
|
1219
1310
|
const seedScript = `import { PrismaClient } from '@prisma/client';
|
|
1220
1311
|
import * as bcrypt from 'bcryptjs';
|
|
1221
1312
|
import crypto from 'crypto';
|
|
@@ -1472,10 +1563,7 @@ echo Next steps:
|
|
|
1472
1563
|
echo npm run dev
|
|
1473
1564
|
echo Open: http://localhost:3001
|
|
1474
1565
|
echo.
|
|
1475
|
-
echo Login with:
|
|
1476
|
-
echo Email: admin@example.com
|
|
1477
|
-
echo Password: admin123
|
|
1478
|
-
echo.
|
|
1566
|
+
${features.includes('auth') ? 'echo Login with:\necho Email: admin@example.com\necho Password: admin123\necho.' : ''}
|
|
1479
1567
|
pause
|
|
1480
1568
|
`
|
|
1481
1569
|
: `@echo off
|
|
@@ -1544,10 +1632,7 @@ echo Next steps:
|
|
|
1544
1632
|
echo npm run dev
|
|
1545
1633
|
echo Open: http://localhost:3001
|
|
1546
1634
|
echo.
|
|
1547
|
-
echo Login with:
|
|
1548
|
-
echo Email: admin@example.com
|
|
1549
|
-
echo Password: admin123
|
|
1550
|
-
echo.
|
|
1635
|
+
${features.includes('auth') ? 'echo Login with:\necho Email: admin@example.com\necho Password: admin123\necho.' : ''}
|
|
1551
1636
|
pause
|
|
1552
1637
|
`;
|
|
1553
1638
|
// Linux/macOS install.sh
|
|
@@ -1585,10 +1670,7 @@ echo "Next steps:"
|
|
|
1585
1670
|
echo " npm run dev"
|
|
1586
1671
|
echo " Open: http://localhost:3001"
|
|
1587
1672
|
echo ""
|
|
1588
|
-
echo "Login with:"
|
|
1589
|
-
echo " Email: admin@example.com"
|
|
1590
|
-
echo " Password: admin123"
|
|
1591
|
-
echo ""
|
|
1673
|
+
${features.includes('auth') ? 'echo "Login with:"\necho " Email: admin@example.com"\necho " Password: admin123"\necho ""' : ''}
|
|
1592
1674
|
`
|
|
1593
1675
|
: `#!/bin/bash
|
|
1594
1676
|
set -e
|
|
@@ -1635,10 +1717,7 @@ echo "Next steps:"
|
|
|
1635
1717
|
echo " npm run dev"
|
|
1636
1718
|
echo " Open: http://localhost:3001"
|
|
1637
1719
|
echo ""
|
|
1638
|
-
echo "Login with:"
|
|
1639
|
-
echo " Email: admin@example.com"
|
|
1640
|
-
echo " Password: admin123"
|
|
1641
|
-
echo ""
|
|
1720
|
+
${features.includes('auth') ? 'echo "Login with:"\necho " Email: admin@example.com"\necho " Password: admin123"\necho ""' : ''}
|
|
1642
1721
|
`;
|
|
1643
1722
|
await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'install.bat'), installBat);
|
|
1644
1723
|
await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'install.sh'), installSh);
|
|
@@ -1723,12 +1802,7 @@ npm run dev
|
|
|
1723
1802
|
|
|
1724
1803
|
Open [http://localhost:3001](http://localhost:3001) in your browser.
|
|
1725
1804
|
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
- Email: admin@example.com
|
|
1729
|
-
- Password: admin123
|
|
1730
|
-
|
|
1731
|
-
⚠️ Change these in production!
|
|
1805
|
+
${features.includes('auth') ? `### Default Admin Credentials\n\n- Email: admin@example.com\n- Password: admin123\n\n⚠️ Change these in production!` : ''}
|
|
1732
1806
|
|
|
1733
1807
|
## Available Scripts
|
|
1734
1808
|
|
|
@@ -1790,8 +1864,7 @@ Commercial License - See LICENSE file
|
|
|
1790
1864
|
5. \`pnpm dev\`
|
|
1791
1865
|
|
|
1792
1866
|
## Default Login
|
|
1793
|
-
- Email: admin@example.com
|
|
1794
|
-
- Password: admin123
|
|
1867
|
+
${features.includes('auth') ? '- Email: admin@example.com\n- Password: admin123' : '- No auth configured. Run: `chimerai add auth`'}
|
|
1795
1868
|
|
|
1796
1869
|
## CLI Commands
|
|
1797
1870
|
- \`chimerai add <component>\` — Add features
|
package/dist/templates/chat.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* Displays conversations, allows provider selection, integrates StreamingChat component
|
|
8
8
|
* @returns TypeScript/JSX content for app/dashboard/chat/page.tsx
|
|
9
9
|
*/
|
|
10
|
+
export declare function generateChatPageNoAuth(): string;
|
|
10
11
|
export declare function generateChatPage(): string;
|
|
11
12
|
/**
|
|
12
13
|
* Generates the streaming Chat API route — Direct LLM provider communication with DB persistence
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/templates/chat.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAuLzC;AAED;;;;GAIG;AACH,wBAAgB,sCAAsC,IAAI,MAAM,CAwa/D;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CAwEnD;AAMD;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAkb5C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAuQ5C;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAwH1C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CA+O5C;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CA+D9C;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,IAAI,MAAM,CAyGxD"}
|
|
1
|
+
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/templates/chat.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAqI/C;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAuLzC;AAED;;;;GAIG;AACH,wBAAgB,sCAAsC,IAAI,MAAM,CAwa/D;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CAwEnD;AAMD;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAkb5C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAuQ5C;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAwH1C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CA+O5C;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CA+D9C;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,IAAI,MAAM,CAyGxD"}
|
package/dist/templates/chat.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Generates streaming chat UI, conversation management, and AI model integration
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.generateChatPageNoAuth = generateChatPageNoAuth;
|
|
7
8
|
exports.generateChatPage = generateChatPage;
|
|
8
9
|
exports.generateChatStreamRouteWithPersistence = generateChatStreamRouteWithPersistence;
|
|
9
10
|
exports.generateConversationsRoute = generateConversationsRoute;
|
|
@@ -18,6 +19,140 @@ exports.generateConversationDetailRoute = generateConversationDetailRoute;
|
|
|
18
19
|
* Displays conversations, allows provider selection, integrates StreamingChat component
|
|
19
20
|
* @returns TypeScript/JSX content for app/dashboard/chat/page.tsx
|
|
20
21
|
*/
|
|
22
|
+
function generateChatPageNoAuth() {
|
|
23
|
+
return `// @chimerai component=ChatPageNoAuth version=1.0
|
|
24
|
+
'use client';
|
|
25
|
+
|
|
26
|
+
import { useRef, useState } from 'react';
|
|
27
|
+
import { useAppName } from '@/lib/use-app-name';
|
|
28
|
+
import { useChat } from '@/components/chat/use-chat';
|
|
29
|
+
import { ChatMessage } from '@/components/chat/chat-message';
|
|
30
|
+
import { ChatInput } from '@/components/chat/chat-input';
|
|
31
|
+
import { ChatSidebar } from '@/components/chat/chat-sidebar';
|
|
32
|
+
import { ModelSelector } from '@/components/chat/model-selector';
|
|
33
|
+
import type { MessageActions } from '@/components/chat/chat-message';
|
|
34
|
+
|
|
35
|
+
export default function ChatPage() {
|
|
36
|
+
const messagesEndRef = useRef<HTMLDivElement>(null);
|
|
37
|
+
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
38
|
+
const appName = useAppName();
|
|
39
|
+
|
|
40
|
+
const {
|
|
41
|
+
messages,
|
|
42
|
+
isStreaming,
|
|
43
|
+
conversations,
|
|
44
|
+
selectedConversationId,
|
|
45
|
+
models,
|
|
46
|
+
selectedModelId,
|
|
47
|
+
creditBalance,
|
|
48
|
+
isLoadingConversation,
|
|
49
|
+
sendMessage,
|
|
50
|
+
stopStreaming,
|
|
51
|
+
selectConversation,
|
|
52
|
+
startNewChat,
|
|
53
|
+
deleteConversation,
|
|
54
|
+
renameConversation,
|
|
55
|
+
setSelectedModelId,
|
|
56
|
+
regenerateMessage,
|
|
57
|
+
editMessage,
|
|
58
|
+
deleteMessage,
|
|
59
|
+
} = useChat();
|
|
60
|
+
|
|
61
|
+
const handleSelectConversation = (id: string) => {
|
|
62
|
+
selectConversation(id);
|
|
63
|
+
setSidebarOpen(false);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const handleNewChat = () => {
|
|
67
|
+
startNewChat();
|
|
68
|
+
setSidebarOpen(false);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const messageActions: MessageActions = {
|
|
72
|
+
onRegenerate: regenerateMessage,
|
|
73
|
+
onEdit: editMessage,
|
|
74
|
+
onDelete: deleteMessage,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<div className="flex h-screen bg-white dark:bg-gray-950 relative">
|
|
79
|
+
{sidebarOpen && (
|
|
80
|
+
<div
|
|
81
|
+
className="fixed inset-0 bg-black/50 z-30 md:hidden"
|
|
82
|
+
onClick={() => setSidebarOpen(false)}
|
|
83
|
+
/>
|
|
84
|
+
)}
|
|
85
|
+
<aside className={\`fixed inset-y-0 left-0 z-40 w-72 border-r border-gray-200 dark:border-gray-800 transform transition-transform duration-200 ease-in-out
|
|
86
|
+
\${sidebarOpen ? 'translate-x-0' : '-translate-x-full'}
|
|
87
|
+
md:relative md:translate-x-0 md:z-auto\`}>
|
|
88
|
+
<ChatSidebar
|
|
89
|
+
conversations={conversations}
|
|
90
|
+
selectedId={selectedConversationId}
|
|
91
|
+
onSelect={handleSelectConversation}
|
|
92
|
+
onNewChat={handleNewChat}
|
|
93
|
+
onDelete={deleteConversation}
|
|
94
|
+
onRename={renameConversation}
|
|
95
|
+
/>
|
|
96
|
+
</aside>
|
|
97
|
+
<main className="flex-1 flex flex-col min-w-0">
|
|
98
|
+
<div className="flex items-center gap-3 border-b border-gray-200 dark:border-gray-800 px-4 py-2">
|
|
99
|
+
<button
|
|
100
|
+
onClick={() => setSidebarOpen(!sidebarOpen)}
|
|
101
|
+
className="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-500 md:hidden"
|
|
102
|
+
aria-label="Toggle sidebar"
|
|
103
|
+
>
|
|
104
|
+
<svg className="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
105
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
|
|
106
|
+
</svg>
|
|
107
|
+
</button>
|
|
108
|
+
<ModelSelector
|
|
109
|
+
models={models}
|
|
110
|
+
value={selectedModelId}
|
|
111
|
+
onValueChange={setSelectedModelId}
|
|
112
|
+
disabled={isStreaming}
|
|
113
|
+
/>
|
|
114
|
+
<div className="flex-1" />
|
|
115
|
+
<span className="text-xs text-gray-400">{appName}</span>
|
|
116
|
+
</div>
|
|
117
|
+
<div className="flex-1 overflow-y-auto">
|
|
118
|
+
{isLoadingConversation ? (
|
|
119
|
+
<div className="flex items-center justify-center h-full">
|
|
120
|
+
<div className="text-gray-400">Loading conversation...</div>
|
|
121
|
+
</div>
|
|
122
|
+
) : messages.length === 0 ? (
|
|
123
|
+
<div className="flex flex-col items-center justify-center h-full text-center px-4">
|
|
124
|
+
<svg className="h-12 w-12 text-gray-300 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
125
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z" />
|
|
126
|
+
</svg>
|
|
127
|
+
<h2 className="text-lg font-medium text-gray-700 dark:text-gray-300 mb-1">Start a conversation</h2>
|
|
128
|
+
<p className="text-sm text-gray-400">Send a message to begin chatting with AI</p>
|
|
129
|
+
</div>
|
|
130
|
+
) : (
|
|
131
|
+
<div className="max-w-3xl mx-auto">
|
|
132
|
+
{messages.map((msg, idx) => (
|
|
133
|
+
<ChatMessage
|
|
134
|
+
key={msg.id || idx}
|
|
135
|
+
message={msg}
|
|
136
|
+
index={idx}
|
|
137
|
+
actions={messageActions}
|
|
138
|
+
/>
|
|
139
|
+
))}
|
|
140
|
+
<div ref={messagesEndRef} />
|
|
141
|
+
</div>
|
|
142
|
+
)}
|
|
143
|
+
</div>
|
|
144
|
+
<ChatInput
|
|
145
|
+
onSend={sendMessage}
|
|
146
|
+
onStop={stopStreaming}
|
|
147
|
+
isStreaming={isStreaming}
|
|
148
|
+
creditBalance={creditBalance}
|
|
149
|
+
/>
|
|
150
|
+
</main>
|
|
151
|
+
</div>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
`;
|
|
155
|
+
}
|
|
21
156
|
function generateChatPage() {
|
|
22
157
|
return `// @chimerai component=ChatPage version=2.0
|
|
23
158
|
'use client';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/templates/components.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/templates/components.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CAyTnD;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,IAAI,MAAM,CA2QrD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CA4D/C"}
|
|
@@ -18,7 +18,6 @@ function generateModelProvidersPage() {
|
|
|
18
18
|
'use client';
|
|
19
19
|
|
|
20
20
|
import { useState, useEffect, useCallback } from 'react';
|
|
21
|
-
import { useSession } from 'next-auth/react';
|
|
22
21
|
|
|
23
22
|
interface ProviderModel {
|
|
24
23
|
id: string;
|
|
@@ -64,7 +63,6 @@ const PROVIDER_TYPES = [
|
|
|
64
63
|
const emptyForm: ProviderFormData = { name: '', type: 'openai', apiKey: '', baseUrl: '', defaultModel: '' };
|
|
65
64
|
|
|
66
65
|
export default function ProvidersPage() {
|
|
67
|
-
const { data: session } = useSession();
|
|
68
66
|
const [providers, setProviders] = useState<Provider[]>([]);
|
|
69
67
|
const [loading, setLoading] = useState(true);
|
|
70
68
|
const [showForm, setShowForm] = useState(false);
|
|
@@ -190,10 +188,6 @@ export default function ProvidersPage() {
|
|
|
190
188
|
setShowForm(true);
|
|
191
189
|
};
|
|
192
190
|
|
|
193
|
-
if (!session?.user?.id) {
|
|
194
|
-
return <div className="container mx-auto py-8"><p className="text-center text-gray-500">Please sign in to manage model providers.</p></div>;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
191
|
return (
|
|
198
192
|
<div className="container mx-auto py-8 max-w-5xl">
|
|
199
193
|
<div className="flex items-center justify-between mb-6">
|
|
@@ -6,15 +6,15 @@
|
|
|
6
6
|
* written to a file in the generated project.
|
|
7
7
|
*/
|
|
8
8
|
export { generateNextConfig, generateTsConfig, generateTailwindConfig, generatePostcssConfig, generateGlobalsCss, } from './config.js';
|
|
9
|
-
export { generateAppLayout, generateAppLayoutWithAuth, generateAppPage, generateAuthBasicLayout, generateDashboardLayout, generateDashboardPage, generateProfilePage, generateUserProfileRoute, generateSettingsPage, generateUseAppNameHook, } from './layout.js';
|
|
9
|
+
export { generateAppLayout, generateAppLayoutWithAuth, generateAppPage, generateAppPageNoAuth, generateAuthBasicLayout, generateDashboardLayout, generateDashboardLayoutNoAuth, generateDashboardPage, generateDashboardPageNoAuth, generateProfilePage, generateUserProfileRoute, generateSettingsPage, generateUseAppNameHook, } from './layout.js';
|
|
10
10
|
export { generateNextAuthRoute, generateLoginPage, generateSessionProvider, generateLogoutButton, generateNextAuthTypes, generateAuthLib, generateResolveAuth, } from './auth.js';
|
|
11
|
-
export { generateChatPage, generateUseChatHook, generateChatMessage, generateChatInput, generateChatSidebar, generateModelSelector, generateChatStreamRouteWithPersistence, generateConversationsRoute, generateConversationDetailRoute, } from './chat.js';
|
|
11
|
+
export { generateChatPage, generateChatPageNoAuth, generateUseChatHook, generateChatMessage, generateChatInput, generateChatSidebar, generateModelSelector, generateChatStreamRouteWithPersistence, generateConversationsRoute, generateConversationDetailRoute, } from './chat.js';
|
|
12
12
|
export { generateAdminLayout, generateAdminDashboardPage, generateAdminUsersPage, generateAdminRolesPage, generateAdminSettingsPage, generateAdminLogsPage, generateAuditLogHelper, generatePermissionsLib, generateRequirePermissionLib, } from './admin.js';
|
|
13
|
-
export { generateModelProvidersPage, generatePromptManagementPage, generatePromptSelector } from './components.js';
|
|
13
|
+
export { generateModelProvidersPage, generatePromptManagementPage, generatePromptSelector, } from './components.js';
|
|
14
14
|
export { generateAdminUsersRoute, generateAdminUsersIdRoute, generateAdminRolesRoute, generateAdminRolesIdRoute, generatePromptsRoute, generatePromptsIdRoute, generatePromptsSetDefaultRoute, generateHealthRoute, generateModelsRoute, generateV1ModelsRoute, generateAuditLogRoute, generateGdprDataExportRoute, generateGdprAccountDeleteRoute, generateAdminSettingsRoute, generateAppSettingsRoute, } from './api-routes.js';
|
|
15
15
|
export { generateProviderCrudRoute, generateProviderIdRoute, generateProviderTestRoute, generateProviderSyncRoute, generateInternalProvidersRoute, generateInternalProviderIdRoute, generateInternalProviderUsageRoute, generateNotifyProviderChangeLib, } from './provider-routes.js';
|
|
16
16
|
export { generatePrismaLib, generateEncryptionLib, generateApiKeyAuthLib, generateApiProtectionLib, generatePrismaSchema, } from './prisma.js';
|
|
17
|
-
export { generateMiddleware } from './middleware.js';
|
|
17
|
+
export { generateMiddleware, generateMiddlewareNoAuth } from './middleware.js';
|
|
18
18
|
export { generateStripeLib, generateBillingPage, generateCheckoutRoute, generatePortalRoute, generateSubscriptionRoute, generateStripeWebhookRoute, } from './billing.js';
|
|
19
19
|
export { generateRagLib, generateRagPage, generateRagUploadRoute, generateRagQueryRoute, generateRagStatsRoute, generateRagClearRoute, generateRagDeleteRoute, } from './rag.js';
|
|
20
20
|
export { generateWidgetBundle, generateWidgetLoader, generateApiKeyManagementPage, generateApiKeysRoute, generateApiKeyIdRoute, generateRateLimiter, } from './widget.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,qBAAqB,EACrB,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,GACpB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,sCAAsC,EACtC,0BAA0B,EAC1B,+BAA+B,GAChC,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,sBAAsB,EACtB,sBAAsB,EACtB,yBAAyB,EACzB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,4BAA4B,GAC7B,MAAM,YAAY,CAAC;AAGpB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,eAAe,EACf,qBAAqB,EACrB,uBAAuB,EACvB,uBAAuB,EACvB,6BAA6B,EAC7B,qBAAqB,EACrB,2BAA2B,EAC3B,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,GACpB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,sCAAsC,EACtC,0BAA0B,EAC1B,+BAA+B,GAChC,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,sBAAsB,EACtB,sBAAsB,EACtB,yBAAyB,EACzB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,4BAA4B,GAC7B,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,EAC5B,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,uBAAuB,EACvB,yBAAyB,EACzB,oBAAoB,EACpB,sBAAsB,EACtB,8BAA8B,EAC9B,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,2BAA2B,EAC3B,8BAA8B,EAC9B,0BAA0B,EAC1B,wBAAwB,GAEzB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,yBAAyB,EACzB,yBAAyB,EACzB,8BAA8B,EAC9B,+BAA+B,EAC/B,kCAAkC,EAClC,+BAA+B,GAChC,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAG/E,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,cAAc,EACd,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,4BAA4B,EAC5B,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,oBAAoB,EACpB,eAAe,GAChB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,cAAc,EACd,eAAe,EACf,SAAS,EACT,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,yBAAyB,EACzB,wBAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,yBAAyB,EACzB,qBAAqB,EACrB,uBAAuB,EACvB,uBAAuB,EACvB,6BAA6B,EAC7B,2BAA2B,EAC3B,uBAAuB,EACvB,8BAA8B,EAC9B,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAGnE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,yBAAyB,EACzB,qBAAqB,EACrB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAE/B;;;GAGG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;CA8DzB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2E7B,CAAC"}
|
package/dist/templates/index.js
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
* written to a file in the generated project.
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.
|
|
11
|
-
exports.
|
|
12
|
-
exports.FEATURE_TEMPLATES = exports.ALL_TEMPLATES = exports.TOOL_GENERATORS = exports.generateToolsInit = exports.generateWebhookTools = exports.generateDeeplTools = exports.generateAirtableTools = exports.generateGoogleSheetsTools = exports.generateVisionTools = exports.generateNlpTools = exports.generateCodeTools = exports.generateDocumentTools = exports.generateWebTools = exports.generateRoutesInit = exports.generateToolsRoutes = exports.generateGuardrailsRoutes = exports.generateRagRoutes = exports.generateChatRoutes = exports.generateFileExtractor = exports.generateDockerComposeAiService = exports.generateAiServiceReadme = exports.generateAiServiceDockerfile = exports.generateAiServiceRequirements = exports.generateAiServiceModels = exports.generateAiServiceConfig = exports.generateAiServiceMain = exports.generateGuardrailsService = exports.generateVectorStore = exports.generateRagService = exports.generateEmbeddingService = exports.generateModerationService = exports.generateModelService = exports.generateChatService = exports.generateServicesInit = exports.generateProviderClient = exports.TOOL_INFO = exports.writeAiManifest = exports.readAiManifest = exports.generateDockerComposeDev = exports.generateDockerComposeProd = exports.generateDockerignore = exports.generateDockerfile = exports.GDPR_SCHEMA_EXTENSION = exports.generateGdprConsentRoute = void 0;
|
|
10
|
+
exports.generateAdminRolesRoute = exports.generateAdminUsersIdRoute = exports.generateAdminUsersRoute = exports.generatePromptSelector = exports.generatePromptManagementPage = exports.generateModelProvidersPage = exports.generateRequirePermissionLib = exports.generatePermissionsLib = exports.generateAuditLogHelper = exports.generateAdminLogsPage = exports.generateAdminSettingsPage = exports.generateAdminRolesPage = exports.generateAdminUsersPage = exports.generateAdminDashboardPage = exports.generateAdminLayout = exports.generateConversationDetailRoute = exports.generateConversationsRoute = exports.generateChatStreamRouteWithPersistence = exports.generateModelSelector = exports.generateChatSidebar = exports.generateChatInput = exports.generateChatMessage = exports.generateUseChatHook = exports.generateChatPageNoAuth = exports.generateChatPage = exports.generateResolveAuth = exports.generateAuthLib = exports.generateNextAuthTypes = exports.generateLogoutButton = exports.generateSessionProvider = exports.generateLoginPage = exports.generateNextAuthRoute = exports.generateUseAppNameHook = exports.generateSettingsPage = exports.generateUserProfileRoute = exports.generateProfilePage = exports.generateDashboardPageNoAuth = exports.generateDashboardPage = exports.generateDashboardLayoutNoAuth = exports.generateDashboardLayout = exports.generateAuthBasicLayout = exports.generateAppPageNoAuth = exports.generateAppPage = exports.generateAppLayoutWithAuth = exports.generateAppLayout = exports.generateGlobalsCss = exports.generatePostcssConfig = exports.generateTailwindConfig = exports.generateTsConfig = exports.generateNextConfig = void 0;
|
|
11
|
+
exports.generateMfaDisableRoute = exports.generateMfaVerifyRoute = exports.generateMfaSetupRoute = exports.generateMfaLib = exports.generateRateLimiter = exports.generateApiKeyIdRoute = exports.generateApiKeysRoute = exports.generateApiKeyManagementPage = exports.generateWidgetLoader = exports.generateWidgetBundle = exports.generateRagDeleteRoute = exports.generateRagClearRoute = exports.generateRagStatsRoute = exports.generateRagQueryRoute = exports.generateRagUploadRoute = exports.generateRagPage = exports.generateRagLib = exports.generateStripeWebhookRoute = exports.generateSubscriptionRoute = exports.generatePortalRoute = exports.generateCheckoutRoute = exports.generateBillingPage = exports.generateStripeLib = exports.generateMiddlewareNoAuth = exports.generateMiddleware = exports.generatePrismaSchema = exports.generateApiProtectionLib = exports.generateApiKeyAuthLib = exports.generateEncryptionLib = exports.generatePrismaLib = exports.generateNotifyProviderChangeLib = exports.generateInternalProviderUsageRoute = exports.generateInternalProviderIdRoute = exports.generateInternalProvidersRoute = exports.generateProviderSyncRoute = exports.generateProviderTestRoute = exports.generateProviderIdRoute = exports.generateProviderCrudRoute = exports.generateAppSettingsRoute = exports.generateAdminSettingsRoute = exports.generateGdprAccountDeleteRoute = exports.generateGdprDataExportRoute = exports.generateAuditLogRoute = exports.generateV1ModelsRoute = exports.generateModelsRoute = exports.generateHealthRoute = exports.generatePromptsSetDefaultRoute = exports.generatePromptsIdRoute = exports.generatePromptsRoute = exports.generateAdminRolesIdRoute = void 0;
|
|
12
|
+
exports.FEATURE_TEMPLATES = exports.ALL_TEMPLATES = exports.TOOL_GENERATORS = exports.generateToolsInit = exports.generateWebhookTools = exports.generateDeeplTools = exports.generateAirtableTools = exports.generateGoogleSheetsTools = exports.generateVisionTools = exports.generateNlpTools = exports.generateCodeTools = exports.generateDocumentTools = exports.generateWebTools = exports.generateRoutesInit = exports.generateToolsRoutes = exports.generateGuardrailsRoutes = exports.generateRagRoutes = exports.generateChatRoutes = exports.generateFileExtractor = exports.generateDockerComposeAiService = exports.generateAiServiceReadme = exports.generateAiServiceDockerfile = exports.generateAiServiceRequirements = exports.generateAiServiceModels = exports.generateAiServiceConfig = exports.generateAiServiceMain = exports.generateGuardrailsService = exports.generateVectorStore = exports.generateRagService = exports.generateEmbeddingService = exports.generateModerationService = exports.generateModelService = exports.generateChatService = exports.generateServicesInit = exports.generateProviderClient = exports.TOOL_INFO = exports.writeAiManifest = exports.readAiManifest = exports.generateDockerComposeDev = exports.generateDockerComposeProd = exports.generateDockerignore = exports.generateDockerfile = exports.GDPR_SCHEMA_EXTENSION = exports.generateGdprConsentRoute = exports.generateGdprPage = exports.generateGdprLib = exports.MFA_USER_FIELDS = exports.MFA_SCHEMA_EXTENSION = exports.generateMfaPage = void 0;
|
|
13
13
|
// Config templates
|
|
14
14
|
var config_js_1 = require("./config.js");
|
|
15
15
|
Object.defineProperty(exports, "generateNextConfig", { enumerable: true, get: function () { return config_js_1.generateNextConfig; } });
|
|
@@ -22,9 +22,12 @@ var layout_js_1 = require("./layout.js");
|
|
|
22
22
|
Object.defineProperty(exports, "generateAppLayout", { enumerable: true, get: function () { return layout_js_1.generateAppLayout; } });
|
|
23
23
|
Object.defineProperty(exports, "generateAppLayoutWithAuth", { enumerable: true, get: function () { return layout_js_1.generateAppLayoutWithAuth; } });
|
|
24
24
|
Object.defineProperty(exports, "generateAppPage", { enumerable: true, get: function () { return layout_js_1.generateAppPage; } });
|
|
25
|
+
Object.defineProperty(exports, "generateAppPageNoAuth", { enumerable: true, get: function () { return layout_js_1.generateAppPageNoAuth; } });
|
|
25
26
|
Object.defineProperty(exports, "generateAuthBasicLayout", { enumerable: true, get: function () { return layout_js_1.generateAuthBasicLayout; } });
|
|
26
27
|
Object.defineProperty(exports, "generateDashboardLayout", { enumerable: true, get: function () { return layout_js_1.generateDashboardLayout; } });
|
|
28
|
+
Object.defineProperty(exports, "generateDashboardLayoutNoAuth", { enumerable: true, get: function () { return layout_js_1.generateDashboardLayoutNoAuth; } });
|
|
27
29
|
Object.defineProperty(exports, "generateDashboardPage", { enumerable: true, get: function () { return layout_js_1.generateDashboardPage; } });
|
|
30
|
+
Object.defineProperty(exports, "generateDashboardPageNoAuth", { enumerable: true, get: function () { return layout_js_1.generateDashboardPageNoAuth; } });
|
|
28
31
|
Object.defineProperty(exports, "generateProfilePage", { enumerable: true, get: function () { return layout_js_1.generateProfilePage; } });
|
|
29
32
|
Object.defineProperty(exports, "generateUserProfileRoute", { enumerable: true, get: function () { return layout_js_1.generateUserProfileRoute; } });
|
|
30
33
|
Object.defineProperty(exports, "generateSettingsPage", { enumerable: true, get: function () { return layout_js_1.generateSettingsPage; } });
|
|
@@ -41,6 +44,7 @@ Object.defineProperty(exports, "generateResolveAuth", { enumerable: true, get: f
|
|
|
41
44
|
// Chat templates
|
|
42
45
|
var chat_js_1 = require("./chat.js");
|
|
43
46
|
Object.defineProperty(exports, "generateChatPage", { enumerable: true, get: function () { return chat_js_1.generateChatPage; } });
|
|
47
|
+
Object.defineProperty(exports, "generateChatPageNoAuth", { enumerable: true, get: function () { return chat_js_1.generateChatPageNoAuth; } });
|
|
44
48
|
Object.defineProperty(exports, "generateUseChatHook", { enumerable: true, get: function () { return chat_js_1.generateUseChatHook; } });
|
|
45
49
|
Object.defineProperty(exports, "generateChatMessage", { enumerable: true, get: function () { return chat_js_1.generateChatMessage; } });
|
|
46
50
|
Object.defineProperty(exports, "generateChatInput", { enumerable: true, get: function () { return chat_js_1.generateChatInput; } });
|
|
@@ -102,6 +106,7 @@ Object.defineProperty(exports, "generatePrismaSchema", { enumerable: true, get:
|
|
|
102
106
|
// Middleware template
|
|
103
107
|
var middleware_js_1 = require("./middleware.js");
|
|
104
108
|
Object.defineProperty(exports, "generateMiddleware", { enumerable: true, get: function () { return middleware_js_1.generateMiddleware; } });
|
|
109
|
+
Object.defineProperty(exports, "generateMiddlewareNoAuth", { enumerable: true, get: function () { return middleware_js_1.generateMiddlewareNoAuth; } });
|
|
105
110
|
// Billing templates
|
|
106
111
|
var billing_js_1 = require("./billing.js");
|
|
107
112
|
Object.defineProperty(exports, "generateStripeLib", { enumerable: true, get: function () { return billing_js_1.generateStripeLib; } });
|
|
@@ -16,6 +16,12 @@ export declare function generateAppLayout(projectName?: string): string;
|
|
|
16
16
|
* @returns TypeScript/JSX content for app/layout.tsx with SessionProvider
|
|
17
17
|
*/
|
|
18
18
|
export declare function generateAppLayoutWithAuth(projectName?: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Generates a simple landing page for projects WITHOUT auth.
|
|
21
|
+
* No useSession, no redirect — just renders immediately.
|
|
22
|
+
* @returns TypeScript/JSX content for app/page.tsx
|
|
23
|
+
*/
|
|
24
|
+
export declare function generateAppPageNoAuth(): string;
|
|
19
25
|
/**
|
|
20
26
|
* Generates the home page component that handles session-based routing
|
|
21
27
|
* Redirects unauthenticated users to /login, authenticated users to /dashboard
|
|
@@ -34,6 +40,8 @@ export declare function generateAuthBasicLayout(): string;
|
|
|
34
40
|
* Provides structure for authenticated application pages
|
|
35
41
|
* @returns TypeScript/JSX content for app/(dashboard)/layout.tsx
|
|
36
42
|
*/
|
|
43
|
+
export declare function generateDashboardLayoutNoAuth(): string;
|
|
44
|
+
export declare function generateDashboardPageNoAuth(features?: string[]): string;
|
|
37
45
|
export declare function generateDashboardLayout(): string;
|
|
38
46
|
/**
|
|
39
47
|
* Generates the main dashboard page shown after login
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../src/templates/layout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,GAAE,MAAuB,GAAG,MAAM,CAyB9E;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,GAAE,MAAuB,GAAG,MAAM,CAmCtF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAiCxC;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CA2BhD;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAuGhD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,GAAE,MAAM,EAAO,GAAG,MAAM,CAgErE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAkG5C;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CA6BjD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAyJ7C;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAkC/C"}
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../src/templates/layout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,GAAE,MAAuB,GAAG,MAAM,CAyB9E;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,GAAE,MAAuB,GAAG,MAAM,CAmCtF;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAkC9C;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAiCxC;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CA2BhD;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,IAAI,MAAM,CA4DtD;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,GAAE,MAAM,EAAO,GAAG,MAAM,CA+C3E;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAuGhD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,GAAE,MAAM,EAAO,GAAG,MAAM,CAgErE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAkG5C;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CA6BjD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAyJ7C;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAkC/C"}
|
package/dist/templates/layout.js
CHANGED
|
@@ -6,8 +6,11 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.generateAppLayout = generateAppLayout;
|
|
8
8
|
exports.generateAppLayoutWithAuth = generateAppLayoutWithAuth;
|
|
9
|
+
exports.generateAppPageNoAuth = generateAppPageNoAuth;
|
|
9
10
|
exports.generateAppPage = generateAppPage;
|
|
10
11
|
exports.generateAuthBasicLayout = generateAuthBasicLayout;
|
|
12
|
+
exports.generateDashboardLayoutNoAuth = generateDashboardLayoutNoAuth;
|
|
13
|
+
exports.generateDashboardPageNoAuth = generateDashboardPageNoAuth;
|
|
11
14
|
exports.generateDashboardLayout = generateDashboardLayout;
|
|
12
15
|
exports.generateDashboardPage = generateDashboardPage;
|
|
13
16
|
exports.generateProfilePage = generateProfilePage;
|
|
@@ -88,6 +91,46 @@ export default function RootLayout({
|
|
|
88
91
|
}
|
|
89
92
|
`;
|
|
90
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Generates a simple landing page for projects WITHOUT auth.
|
|
96
|
+
* No useSession, no redirect — just renders immediately.
|
|
97
|
+
* @returns TypeScript/JSX content for app/page.tsx
|
|
98
|
+
*/
|
|
99
|
+
function generateAppPageNoAuth() {
|
|
100
|
+
return `// @chimerai component=AppPageNoAuth version=1.0
|
|
101
|
+
import Link from 'next/link';
|
|
102
|
+
|
|
103
|
+
export default function Home() {
|
|
104
|
+
return (
|
|
105
|
+
<main className="flex min-h-screen flex-col items-center justify-center p-24">
|
|
106
|
+
<div className="text-center">
|
|
107
|
+
<h1 className="text-4xl font-bold mb-4">Welcome</h1>
|
|
108
|
+
<p className="text-muted-foreground mb-8">
|
|
109
|
+
Your ChimerAI application is running.
|
|
110
|
+
</p>
|
|
111
|
+
<div className="flex gap-4 justify-center flex-wrap">
|
|
112
|
+
<Link
|
|
113
|
+
href="/chat"
|
|
114
|
+
className="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-medium"
|
|
115
|
+
>
|
|
116
|
+
💬 Open Chat
|
|
117
|
+
</Link>
|
|
118
|
+
<Link
|
|
119
|
+
href="/dashboard/providers"
|
|
120
|
+
className="px-6 py-3 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors font-medium"
|
|
121
|
+
>
|
|
122
|
+
🔌 Manage Providers
|
|
123
|
+
</Link>
|
|
124
|
+
</div>
|
|
125
|
+
<p className="text-xs text-muted-foreground mt-8">
|
|
126
|
+
To add authentication later, run: <code className="bg-gray-100 px-1 rounded">chimerai add auth</code>
|
|
127
|
+
</p>
|
|
128
|
+
</div>
|
|
129
|
+
</main>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
`;
|
|
133
|
+
}
|
|
91
134
|
/**
|
|
92
135
|
* Generates the home page component that handles session-based routing
|
|
93
136
|
* Redirects unauthenticated users to /login, authenticated users to /dashboard
|
|
@@ -166,6 +209,112 @@ export default function AuthLayout({
|
|
|
166
209
|
* Provides structure for authenticated application pages
|
|
167
210
|
* @returns TypeScript/JSX content for app/(dashboard)/layout.tsx
|
|
168
211
|
*/
|
|
212
|
+
function generateDashboardLayoutNoAuth() {
|
|
213
|
+
return `// @chimerai component=DashboardLayoutNoAuth version=1.0
|
|
214
|
+
'use client';
|
|
215
|
+
|
|
216
|
+
import { useState } from 'react';
|
|
217
|
+
import Link from 'next/link';
|
|
218
|
+
import { useAppName } from '@/lib/use-app-name';
|
|
219
|
+
|
|
220
|
+
export default function DashboardLayout({
|
|
221
|
+
children,
|
|
222
|
+
}: {
|
|
223
|
+
children: React.ReactNode;
|
|
224
|
+
}) {
|
|
225
|
+
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
226
|
+
const appName = useAppName();
|
|
227
|
+
|
|
228
|
+
return (
|
|
229
|
+
<div className="flex min-h-screen bg-white dark:bg-gray-900">
|
|
230
|
+
<button
|
|
231
|
+
onClick={() => setSidebarOpen(!sidebarOpen)}
|
|
232
|
+
className="fixed top-4 left-4 z-50 md:hidden p-2 rounded-lg bg-gray-100 dark:bg-gray-800 shadow"
|
|
233
|
+
aria-label="Toggle menu"
|
|
234
|
+
>
|
|
235
|
+
<svg className="h-5 w-5 dark:text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
236
|
+
{sidebarOpen ? (
|
|
237
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
238
|
+
) : (
|
|
239
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
|
|
240
|
+
)}
|
|
241
|
+
</svg>
|
|
242
|
+
</button>
|
|
243
|
+
{sidebarOpen && (
|
|
244
|
+
<div className="fixed inset-0 z-30 bg-black/50 md:hidden" onClick={() => setSidebarOpen(false)} />
|
|
245
|
+
)}
|
|
246
|
+
<aside className={\`fixed z-40 inset-y-0 left-0 w-64 border-r border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 p-4 flex flex-col transform transition-transform duration-200 ease-in-out md:relative md:translate-x-0 \${sidebarOpen ? 'translate-x-0' : '-translate-x-full'}\`}>
|
|
247
|
+
<div className="mb-4 mt-12 md:mt-0">
|
|
248
|
+
<h2 className="text-lg font-bold dark:text-white">{appName}</h2>
|
|
249
|
+
</div>
|
|
250
|
+
<nav className="space-y-2 flex-1">
|
|
251
|
+
<Link href="/dashboard" onClick={() => setSidebarOpen(false)} className="block px-4 py-2 rounded hover:bg-gray-200 dark:hover:bg-gray-700 dark:text-gray-200">
|
|
252
|
+
Dashboard
|
|
253
|
+
</Link>
|
|
254
|
+
<Link href="/chat" onClick={() => setSidebarOpen(false)} className="block px-4 py-2 rounded hover:bg-gray-200 dark:hover:bg-gray-700 dark:text-gray-200">
|
|
255
|
+
💬 Chat
|
|
256
|
+
</Link>
|
|
257
|
+
<Link href="/dashboard/providers" onClick={() => setSidebarOpen(false)} className="block px-4 py-2 rounded hover:bg-gray-200 dark:hover:bg-gray-700 dark:text-gray-200">
|
|
258
|
+
🔌 AI Providers
|
|
259
|
+
</Link>
|
|
260
|
+
</nav>
|
|
261
|
+
<div className="border-t border-gray-200 dark:border-gray-700 pt-3 text-xs text-gray-400 px-2">
|
|
262
|
+
<code>chimerai add auth</code> to add login
|
|
263
|
+
</div>
|
|
264
|
+
</aside>
|
|
265
|
+
<main className="flex-1 p-8 pt-16 md:pt-8 dark:text-white">
|
|
266
|
+
{children}
|
|
267
|
+
</main>
|
|
268
|
+
</div>
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
`;
|
|
272
|
+
}
|
|
273
|
+
function generateDashboardPageNoAuth(features = []) {
|
|
274
|
+
const links = [
|
|
275
|
+
` { href: '/chat', label: 'Chat', icon: '💬', description: 'AI-powered chat conversations' },`,
|
|
276
|
+
` { href: '/dashboard/providers', label: 'AI Providers', icon: '🔌', description: 'Manage AI model providers and API keys' },`,
|
|
277
|
+
];
|
|
278
|
+
if (features.includes('prompts')) {
|
|
279
|
+
links.push(` { href: '/dashboard/prompts', label: 'Prompt Templates', icon: '📝', description: 'Create and manage system prompts' },`);
|
|
280
|
+
}
|
|
281
|
+
return `// @chimerai component=DashboardPageNoAuth version=1.0
|
|
282
|
+
'use client';
|
|
283
|
+
|
|
284
|
+
import Link from 'next/link';
|
|
285
|
+
|
|
286
|
+
export default function DashboardPage() {
|
|
287
|
+
const links = [
|
|
288
|
+
${links.join('\n')}
|
|
289
|
+
];
|
|
290
|
+
|
|
291
|
+
return (
|
|
292
|
+
<div className="container mx-auto py-8 px-4">
|
|
293
|
+
<div className="mb-8">
|
|
294
|
+
<h1 className="text-3xl font-bold mb-2 dark:text-white">Dashboard</h1>
|
|
295
|
+
<p className="text-gray-600 dark:text-gray-400">Your ChimerAI Application</p>
|
|
296
|
+
</div>
|
|
297
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
298
|
+
{links.map((link) => (
|
|
299
|
+
<Link
|
|
300
|
+
key={link.href}
|
|
301
|
+
href={link.href}
|
|
302
|
+
className="block p-6 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 shadow-sm hover:shadow-md hover:border-blue-300 dark:hover:border-blue-600 transition-all"
|
|
303
|
+
>
|
|
304
|
+
<div className="text-3xl mb-3">{link.icon}</div>
|
|
305
|
+
<h2 className="text-xl font-semibold mb-2 dark:text-white">{link.label}</h2>
|
|
306
|
+
<p className="text-gray-600 dark:text-gray-400 text-sm">{link.description}</p>
|
|
307
|
+
</Link>
|
|
308
|
+
))}
|
|
309
|
+
</div>
|
|
310
|
+
<p className="mt-8 text-sm text-gray-400">
|
|
311
|
+
Run <code className="bg-gray-100 dark:bg-gray-700 px-1 rounded">chimerai add auth</code> to enable authentication.
|
|
312
|
+
</p>
|
|
313
|
+
</div>
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
`;
|
|
317
|
+
}
|
|
169
318
|
function generateDashboardLayout() {
|
|
170
319
|
return `// @chimerai component=DashboardLayout version=1.2
|
|
171
320
|
'use client';
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
* Next.js middleware template with security headers and CORS for widget endpoints.
|
|
3
3
|
* Generates middleware.ts for the root of the Next.js project.
|
|
4
4
|
*/
|
|
5
|
+
/**
|
|
6
|
+
* Generates a minimal Next.js middleware WITHOUT auth enforcement.
|
|
7
|
+
* Used when auth feature is not selected — only CORS + security headers.
|
|
8
|
+
* No getToken / next-auth/jwt import.
|
|
9
|
+
* @returns TypeScript content for middleware.ts
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateMiddlewareNoAuth(): string;
|
|
5
12
|
/**
|
|
6
13
|
* Generates the Next.js middleware with security headers and CORS.
|
|
7
14
|
* Widget endpoints (/api/v1/*) get CORS headers from CORS_ALLOWED_ORIGINS env.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/templates/middleware.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAsG3C"}
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/templates/middleware.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAuDjD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAsG3C"}
|
|
@@ -4,7 +4,70 @@
|
|
|
4
4
|
* Generates middleware.ts for the root of the Next.js project.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.generateMiddlewareNoAuth = generateMiddlewareNoAuth;
|
|
7
8
|
exports.generateMiddleware = generateMiddleware;
|
|
9
|
+
/**
|
|
10
|
+
* Generates a minimal Next.js middleware WITHOUT auth enforcement.
|
|
11
|
+
* Used when auth feature is not selected — only CORS + security headers.
|
|
12
|
+
* No getToken / next-auth/jwt import.
|
|
13
|
+
* @returns TypeScript content for middleware.ts
|
|
14
|
+
*/
|
|
15
|
+
function generateMiddlewareNoAuth() {
|
|
16
|
+
return `// @chimerai component=MiddlewareNoAuth version=1.0
|
|
17
|
+
import { NextResponse } from 'next/server';
|
|
18
|
+
import type { NextRequest } from 'next/server';
|
|
19
|
+
|
|
20
|
+
/** Merge CORS_ALLOWED_ORIGINS + WIDGET_ALLOWED_ORIGINS (legacy alias) */
|
|
21
|
+
function getAllowedOrigins(): string[] {
|
|
22
|
+
const raw = [
|
|
23
|
+
process.env.CORS_ALLOWED_ORIGINS || '',
|
|
24
|
+
process.env.WIDGET_ALLOWED_ORIGINS || '',
|
|
25
|
+
].filter(Boolean).join(',');
|
|
26
|
+
if (!raw) return ['*'];
|
|
27
|
+
return raw.split(',').map(o => o.trim()).filter(Boolean);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function middleware(request: NextRequest) {
|
|
31
|
+
const { pathname } = request.nextUrl;
|
|
32
|
+
|
|
33
|
+
// --- CORS for Widget/Public API Endpoints (/api/v1/*) ---
|
|
34
|
+
if (pathname.startsWith('/api/v1/')) {
|
|
35
|
+
const allowedOrigins = getAllowedOrigins();
|
|
36
|
+
const origin = request.headers.get('origin') || '';
|
|
37
|
+
|
|
38
|
+
if (request.method === 'OPTIONS') {
|
|
39
|
+
const res = new NextResponse(null, { status: 204 });
|
|
40
|
+
const allowOrigin = allowedOrigins.includes('*') ? '*' : (allowedOrigins.includes(origin) ? origin : '');
|
|
41
|
+
if (allowOrigin) res.headers.set('Access-Control-Allow-Origin', allowOrigin);
|
|
42
|
+
res.headers.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
43
|
+
res.headers.set('Access-Control-Allow-Headers', 'Content-Type, x-api-key, Authorization');
|
|
44
|
+
res.headers.set('Access-Control-Max-Age', '86400');
|
|
45
|
+
return res;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const response = NextResponse.next();
|
|
49
|
+
const allowOrigin = allowedOrigins.includes('*') ? '*' : (allowedOrigins.includes(origin) ? origin : '');
|
|
50
|
+
if (allowOrigin) response.headers.set('Access-Control-Allow-Origin', allowOrigin);
|
|
51
|
+
return response;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// --- Standard security headers for all routes ---
|
|
55
|
+
const response = NextResponse.next();
|
|
56
|
+
response.headers.set('X-Frame-Options', 'DENY');
|
|
57
|
+
response.headers.set('X-Content-Type-Options', 'nosniff');
|
|
58
|
+
response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
|
|
59
|
+
response.headers.set('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');
|
|
60
|
+
if (process.env.NODE_ENV === 'production') {
|
|
61
|
+
response.headers.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
|
|
62
|
+
}
|
|
63
|
+
return response;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export const config = {
|
|
67
|
+
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
|
|
68
|
+
};
|
|
69
|
+
`;
|
|
70
|
+
}
|
|
8
71
|
/**
|
|
9
72
|
* Generates the Next.js middleware with security headers and CORS.
|
|
10
73
|
* Widget endpoints (/api/v1/*) get CORS headers from CORS_ALLOWED_ORIGINS env.
|
package/package.json
CHANGED