@lastbrain/app 0.1.45 → 0.1.47
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/scripts/init-app.d.ts +1 -0
- package/dist/scripts/init-app.d.ts.map +1 -1
- package/dist/scripts/init-app.js +92 -26
- package/dist/scripts/module-build.d.ts.map +1 -1
- package/dist/scripts/module-create.d.ts.map +1 -1
- package/dist/templates/DefaultDoc.d.ts.map +1 -1
- package/dist/templates/DefaultDoc.js +2 -2
- package/package.json +4 -5
- package/src/auth/useAuthSession.ts +1 -1
- package/src/cli.ts +1 -1
- package/src/hooks/useNotifications.ts +7 -7
- package/src/layouts/AdminLayoutWithSidebar.tsx +3 -3
- package/src/layouts/AppProviders.tsx +1 -1
- package/src/layouts/AuthLayoutWithSidebar.tsx +3 -3
- package/src/layouts/PublicLayoutWithSidebar.tsx +3 -3
- package/src/scripts/db-init.ts +7 -7
- package/src/scripts/db-migrations-sync.ts +2 -2
- package/src/scripts/dev-sync.ts +8 -8
- package/src/scripts/init-app.ts +172 -82
- package/src/scripts/module-add.ts +26 -26
- package/src/scripts/module-build.ts +28 -30
- package/src/scripts/module-create.ts +52 -54
- package/src/scripts/module-delete.ts +13 -13
- package/src/scripts/module-list.ts +5 -5
- package/src/scripts/module-remove.ts +36 -36
- package/src/scripts/readme-build.ts +2 -2
- package/src/templates/DefaultDoc.tsx +29 -1
package/src/scripts/dev-sync.ts
CHANGED
|
@@ -29,12 +29,12 @@ const dependenciesToEnsure = {
|
|
|
29
29
|
|
|
30
30
|
const gitignoreTemplate = path.join(
|
|
31
31
|
projectRoot,
|
|
32
|
-
"packages/app/src/templates/gitignore/.gitignore"
|
|
32
|
+
"packages/app/src/templates/gitignore/.gitignore"
|
|
33
33
|
);
|
|
34
34
|
const consumerGitignore = path.join(projectRoot, "apps/web/.gitignore");
|
|
35
35
|
const envTemplate = path.join(
|
|
36
36
|
projectRoot,
|
|
37
|
-
"packages/app/src/templates/env.example/.env.example"
|
|
37
|
+
"packages/app/src/templates/env.example/.env.example"
|
|
38
38
|
);
|
|
39
39
|
const consumerEnvExample = path.join(projectRoot, "apps/web/.env.example");
|
|
40
40
|
const consumerEnvLocal = path.join(projectRoot, "apps/web/.env.local");
|
|
@@ -75,7 +75,7 @@ function _copyDirectory(srcDir: string, destDir: string) {
|
|
|
75
75
|
for (const entry of entries) {
|
|
76
76
|
_copyDirectory(
|
|
77
77
|
path.join(srcDir, entry.name),
|
|
78
|
-
path.join(destDir, entry.name)
|
|
78
|
+
path.join(destDir, entry.name)
|
|
79
79
|
);
|
|
80
80
|
}
|
|
81
81
|
} else if (stats.isFile()) {
|
|
@@ -133,7 +133,7 @@ function cleanupStaleGroupFiles() {
|
|
|
133
133
|
|
|
134
134
|
function mergeScripts(
|
|
135
135
|
base: Record<string, string>,
|
|
136
|
-
additions: Record<string, string
|
|
136
|
+
additions: Record<string, string>
|
|
137
137
|
) {
|
|
138
138
|
return { ...base, ...additions };
|
|
139
139
|
}
|
|
@@ -224,7 +224,7 @@ function main() {
|
|
|
224
224
|
console.log("✅ apps/web synced with @lastbrain/app");
|
|
225
225
|
console.log(`Copied or updated files (${copiedFiles.length}):`);
|
|
226
226
|
copiedFiles.forEach((file) =>
|
|
227
|
-
console.log(` • ${path.relative(projectRoot, file)}`)
|
|
227
|
+
console.log(` • ${path.relative(projectRoot, file)}`)
|
|
228
228
|
);
|
|
229
229
|
console.log("Scripts ensured in apps/web/package.json:");
|
|
230
230
|
changes.scripts.forEach((script) => console.log(` • ${script}`));
|
|
@@ -232,17 +232,17 @@ function main() {
|
|
|
232
232
|
changes.dependencies.forEach((dep) => console.log(` • ${dep}`));
|
|
233
233
|
if (gitignoreSynced) {
|
|
234
234
|
console.log(
|
|
235
|
-
`.gitignore ensured at ${path.relative(projectRoot, gitignoreSynced)}
|
|
235
|
+
`.gitignore ensured at ${path.relative(projectRoot, gitignoreSynced)}`
|
|
236
236
|
);
|
|
237
237
|
}
|
|
238
238
|
if (envExampleSynced) {
|
|
239
239
|
console.log(
|
|
240
|
-
`.env.example ensured at ${path.relative(projectRoot, envExampleSynced)}
|
|
240
|
+
`.env.example ensured at ${path.relative(projectRoot, envExampleSynced)}`
|
|
241
241
|
);
|
|
242
242
|
}
|
|
243
243
|
if (envLocalCreated) {
|
|
244
244
|
console.log(
|
|
245
|
-
`.env.local ensured at ${path.relative(projectRoot, envLocalCreated)}
|
|
245
|
+
`.env.local ensured at ${path.relative(projectRoot, envLocalCreated)}`
|
|
246
246
|
);
|
|
247
247
|
}
|
|
248
248
|
}
|
package/src/scripts/init-app.ts
CHANGED
|
@@ -19,6 +19,7 @@ interface InitAppOptions {
|
|
|
19
19
|
useHeroUI: boolean;
|
|
20
20
|
withAuth?: boolean;
|
|
21
21
|
interactive?: boolean;
|
|
22
|
+
isMonorepoProject?: boolean;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export async function initApp(options: InitAppOptions) {
|
|
@@ -29,7 +30,7 @@ export async function initApp(options: InitAppOptions) {
|
|
|
29
30
|
useHeroUI,
|
|
30
31
|
interactive = true,
|
|
31
32
|
} = options;
|
|
32
|
-
let { withAuth = false } = options;
|
|
33
|
+
let { withAuth = false, isMonorepoProject = false } = options;
|
|
33
34
|
|
|
34
35
|
console.log(chalk.blue("\n🚀 LastBrain App Init\n"));
|
|
35
36
|
console.log(chalk.gray(`📁 Dossier cible: ${targetDir}`));
|
|
@@ -55,20 +56,56 @@ export async function initApp(options: InitAppOptions) {
|
|
|
55
56
|
checked: false,
|
|
56
57
|
})),
|
|
57
58
|
},
|
|
59
|
+
{
|
|
60
|
+
type: "rawlist",
|
|
61
|
+
name: "projectType",
|
|
62
|
+
message: "Type de projet ?",
|
|
63
|
+
choices: [
|
|
64
|
+
{
|
|
65
|
+
name: "📦 Indépendant (créer une nouvelle BDD Supabase)",
|
|
66
|
+
value: "independent",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: "🏢 Monorepo (utiliser la BDD existante)",
|
|
70
|
+
value: "monorepo",
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
default: "independent",
|
|
74
|
+
},
|
|
58
75
|
]);
|
|
59
76
|
|
|
60
77
|
selectedModules.push(...answers.modules);
|
|
61
78
|
withAuth = selectedModules.includes("auth");
|
|
79
|
+
isMonorepoProject = answers.projectType === "monorepo";
|
|
80
|
+
|
|
81
|
+
if (isMonorepoProject) {
|
|
82
|
+
console.log(
|
|
83
|
+
chalk.cyan("\n💡 Mode monorepo activé:"),
|
|
84
|
+
chalk.gray(
|
|
85
|
+
"Votre app utilisera la base de données centralisée du monorepo."
|
|
86
|
+
)
|
|
87
|
+
);
|
|
88
|
+
console.log(
|
|
89
|
+
chalk.gray(" Aucune configuration Supabase locale ne sera créée.\n")
|
|
90
|
+
);
|
|
91
|
+
} else {
|
|
92
|
+
console.log(
|
|
93
|
+
chalk.cyan("\n💡 Mode projet indépendant activé:"),
|
|
94
|
+
chalk.gray("Votre app aura sa propre instance Supabase locale.")
|
|
95
|
+
);
|
|
96
|
+
console.log(chalk.gray(" Configuration complète sera créée.\n"));
|
|
97
|
+
}
|
|
62
98
|
|
|
63
99
|
console.log();
|
|
64
100
|
} else if (!interactive) {
|
|
65
101
|
// En mode non-interactif, installer auth et ai par défaut
|
|
66
102
|
selectedModules.push("auth", "ai");
|
|
67
103
|
withAuth = true;
|
|
104
|
+
isMonorepoProject = false;
|
|
68
105
|
console.log(
|
|
69
106
|
chalk.blue(
|
|
70
|
-
"📦 Modules installés par défaut : Authentication, AI Generation\n"
|
|
71
|
-
)
|
|
107
|
+
"📦 Modules installés par défaut : Authentication, AI Generation\n"
|
|
108
|
+
)
|
|
72
109
|
);
|
|
73
110
|
}
|
|
74
111
|
|
|
@@ -93,10 +130,22 @@ export async function initApp(options: InitAppOptions) {
|
|
|
93
130
|
// 6. Créer .gitignore et .env.local.example
|
|
94
131
|
await createGitIgnore(targetDir, force);
|
|
95
132
|
await createEnvExample(targetDir, force);
|
|
96
|
-
await createEnvLocal(targetDir, force);
|
|
133
|
+
await createEnvLocal(targetDir, force, isMonorepoProject);
|
|
134
|
+
await createEnvProd(targetDir, force);
|
|
97
135
|
|
|
98
|
-
// 7. Créer la structure Supabase avec migrations
|
|
99
|
-
|
|
136
|
+
// 7. Créer la structure Supabase avec migrations (seulement pour projets indépendants)
|
|
137
|
+
if (!isMonorepoProject) {
|
|
138
|
+
console.log(
|
|
139
|
+
chalk.blue("🗄️ Création de la structure Supabase locale...\n")
|
|
140
|
+
);
|
|
141
|
+
await createSupabaseStructure(targetDir, force);
|
|
142
|
+
} else {
|
|
143
|
+
console.log(
|
|
144
|
+
chalk.yellow(
|
|
145
|
+
"⏭️ Projet monorepo détecté - pas de configuration Supabase locale requise\n"
|
|
146
|
+
)
|
|
147
|
+
);
|
|
148
|
+
}
|
|
100
149
|
|
|
101
150
|
// 8. Ajouter les scripts NPM
|
|
102
151
|
await addScriptsToPackageJson(targetDir);
|
|
@@ -111,7 +160,7 @@ export async function initApp(options: InitAppOptions) {
|
|
|
111
160
|
}
|
|
112
161
|
|
|
113
162
|
console.log(
|
|
114
|
-
chalk.green("\n✅ Application LastBrain initialisée avec succès!\n")
|
|
163
|
+
chalk.green("\n✅ Application LastBrain initialisée avec succès!\n")
|
|
115
164
|
);
|
|
116
165
|
|
|
117
166
|
const relativePath = path.relative(process.cwd(), targetDir);
|
|
@@ -139,7 +188,7 @@ export async function initApp(options: InitAppOptions) {
|
|
|
139
188
|
console.log(chalk.green("\n✓ Routes des modules générées\n"));
|
|
140
189
|
|
|
141
190
|
console.log(
|
|
142
|
-
chalk.yellow("📜 Synchronisation des migrations des modules...\n")
|
|
191
|
+
chalk.yellow("📜 Synchronisation des migrations des modules...\n")
|
|
143
192
|
);
|
|
144
193
|
try {
|
|
145
194
|
execSync("pnpm db:migrations:sync", {
|
|
@@ -149,7 +198,7 @@ export async function initApp(options: InitAppOptions) {
|
|
|
149
198
|
console.log(chalk.green("\n✓ Migrations synchronisées\n"));
|
|
150
199
|
} catch (error) {
|
|
151
200
|
console.log(
|
|
152
|
-
chalk.yellow("\n⚠️ Erreur de synchronisation des migrations\n")
|
|
201
|
+
chalk.yellow("\n⚠️ Erreur de synchronisation des migrations\n")
|
|
153
202
|
);
|
|
154
203
|
}
|
|
155
204
|
|
|
@@ -160,8 +209,8 @@ export async function initApp(options: InitAppOptions) {
|
|
|
160
209
|
} catch {
|
|
161
210
|
console.log(
|
|
162
211
|
chalk.yellow(
|
|
163
|
-
"\n⚠️ Erreur d'initialisation de la DB (normal si Supabase pas configuré)\n"
|
|
164
|
-
)
|
|
212
|
+
"\n⚠️ Erreur d'initialisation de la DB (normal si Supabase pas configuré)\n"
|
|
213
|
+
)
|
|
165
214
|
);
|
|
166
215
|
}
|
|
167
216
|
|
|
@@ -170,19 +219,19 @@ export async function initApp(options: InitAppOptions) {
|
|
|
170
219
|
const url = `http://127.0.0.1:${port}`;
|
|
171
220
|
|
|
172
221
|
console.log(
|
|
173
|
-
chalk.yellow("🚀 Lancement du serveur de développement...\n")
|
|
222
|
+
chalk.yellow("🚀 Lancement du serveur de développement...\n")
|
|
174
223
|
);
|
|
175
224
|
console.log(chalk.cyan(`📱 Ouvrez votre navigateur sur : ${url}\n`));
|
|
176
225
|
|
|
177
226
|
console.log(chalk.blue("\n📋 Prochaines étapes après le démarrage :"));
|
|
178
227
|
console.log(
|
|
179
|
-
chalk.white(" 1. Cliquez sur 'Get Started' sur la page d'accueil")
|
|
228
|
+
chalk.white(" 1. Cliquez sur 'Get Started' sur la page d'accueil")
|
|
180
229
|
);
|
|
181
230
|
console.log(chalk.white(" 2. Lancez Docker Desktop"));
|
|
182
231
|
console.log(
|
|
183
232
|
chalk.white(
|
|
184
|
-
" 3. Installez Supabase CLI si nécessaire : brew install supabase/tap/supabase"
|
|
185
|
-
)
|
|
233
|
+
" 3. Installez Supabase CLI si nécessaire : brew install supabase/tap/supabase"
|
|
234
|
+
)
|
|
186
235
|
);
|
|
187
236
|
console.log(chalk.white(" 4. Exécutez : pnpm db:init"));
|
|
188
237
|
console.log(chalk.white(" 5. Rechargez la page\n"));
|
|
@@ -212,27 +261,32 @@ export async function initApp(options: InitAppOptions) {
|
|
|
212
261
|
console.log(chalk.white(" pnpm build:modules"));
|
|
213
262
|
console.log(chalk.white(" pnpm db:migrations:sync"));
|
|
214
263
|
console.log(chalk.white(" pnpm db:init"));
|
|
215
|
-
console.log(chalk.white(" pnpm dev\n"));
|
|
264
|
+
console.log(chalk.white(" pnpm dev:local (ou pnpm dev:prod)\n"));
|
|
216
265
|
}
|
|
217
266
|
} else {
|
|
218
267
|
console.log(chalk.cyan("\n📋 Prochaines étapes:"));
|
|
219
268
|
console.log(chalk.white(" 1. cd " + relativePath));
|
|
220
269
|
console.log(chalk.white(" 2. pnpm install (installer les dépendances)"));
|
|
221
270
|
console.log(
|
|
222
|
-
chalk.white(" 3. pnpm build:modules (générer les routes des modules)")
|
|
271
|
+
chalk.white(" 3. pnpm build:modules (générer les routes des modules)")
|
|
223
272
|
);
|
|
224
273
|
console.log(
|
|
225
|
-
chalk.white(" 4. pnpm db:migrations:sync (synchroniser les migrations)")
|
|
274
|
+
chalk.white(" 4. pnpm db:migrations:sync (synchroniser les migrations)")
|
|
226
275
|
);
|
|
227
276
|
console.log(
|
|
228
|
-
chalk.white(" 5. pnpm db:init (initialiser la base de données)")
|
|
277
|
+
chalk.white(" 5. pnpm db:init (initialiser la base de données)")
|
|
229
278
|
);
|
|
230
|
-
console.log(chalk.white(" 6. pnpm dev (
|
|
279
|
+
console.log(chalk.white(" 6. pnpm dev:local (ou pnpm dev:prod)\n"));
|
|
280
|
+
|
|
281
|
+
console.log(chalk.cyan("\n💡 Scripts disponibles:"));
|
|
282
|
+
console.log(chalk.white(" • pnpm dev:local - Lance avec .env.local"));
|
|
283
|
+
console.log(chalk.white(" • pnpm dev:prod - Lance avec .env.prod"));
|
|
284
|
+
console.log(chalk.white(" • pnpm dev - Lance avec .env actuel\n"));
|
|
231
285
|
|
|
232
286
|
console.log(chalk.gray("Prérequis pour Supabase :"));
|
|
233
287
|
console.log(chalk.white(" - Docker Desktop installé et lancé"));
|
|
234
288
|
console.log(
|
|
235
|
-
chalk.white(" - Supabase CLI : brew install supabase/tap/supabase\n")
|
|
289
|
+
chalk.white(" - Supabase CLI : brew install supabase/tap/supabase\n")
|
|
236
290
|
);
|
|
237
291
|
|
|
238
292
|
// Afficher la commande cd pour faciliter la copie
|
|
@@ -276,7 +330,7 @@ function getLastBrainVersions(targetDir: string): {
|
|
|
276
330
|
} {
|
|
277
331
|
const targetIsInMonorepo =
|
|
278
332
|
fs.existsSync(
|
|
279
|
-
path.join(targetDir, "../../../packages/core/package.json")
|
|
333
|
+
path.join(targetDir, "../../../packages/core/package.json")
|
|
280
334
|
) ||
|
|
281
335
|
fs.existsSync(path.join(targetDir, "../../packages/core/package.json"));
|
|
282
336
|
|
|
@@ -304,11 +358,11 @@ function getLastBrainVersions(targetDir: string): {
|
|
|
304
358
|
const monorepoRoot = path.join(__dirname, "../../../../");
|
|
305
359
|
const moduleAuthPkgPath = path.join(
|
|
306
360
|
monorepoRoot,
|
|
307
|
-
"packages/module-auth/package.json"
|
|
361
|
+
"packages/module-auth/package.json"
|
|
308
362
|
);
|
|
309
363
|
const moduleAiPkgPath = path.join(
|
|
310
364
|
monorepoRoot,
|
|
311
|
-
"packages/module-ai/package.json"
|
|
365
|
+
"packages/module-ai/package.json"
|
|
312
366
|
);
|
|
313
367
|
const corePkgPath = path.join(monorepoRoot, "packages/core/package.json");
|
|
314
368
|
const uiPkgPath = path.join(monorepoRoot, "packages/ui/package.json");
|
|
@@ -321,7 +375,7 @@ function getLastBrainVersions(targetDir: string): {
|
|
|
321
375
|
// Lire les vraies versions depuis les package.json du monorepo
|
|
322
376
|
if (fs.existsSync(moduleAuthPkgPath)) {
|
|
323
377
|
const moduleAuthPkg = JSON.parse(
|
|
324
|
-
fs.readFileSync(moduleAuthPkgPath, "utf-8")
|
|
378
|
+
fs.readFileSync(moduleAuthPkgPath, "utf-8")
|
|
325
379
|
);
|
|
326
380
|
moduleAuthVersion = `^${moduleAuthPkg.version}`;
|
|
327
381
|
} else {
|
|
@@ -331,7 +385,7 @@ function getLastBrainVersions(targetDir: string): {
|
|
|
331
385
|
|
|
332
386
|
if (fs.existsSync(moduleAiPkgPath)) {
|
|
333
387
|
const moduleAiPkg = JSON.parse(
|
|
334
|
-
fs.readFileSync(moduleAiPkgPath, "utf-8")
|
|
388
|
+
fs.readFileSync(moduleAiPkgPath, "utf-8")
|
|
335
389
|
);
|
|
336
390
|
moduleAiVersion = `^${moduleAiPkg.version}`;
|
|
337
391
|
} else {
|
|
@@ -360,8 +414,8 @@ function getLastBrainVersions(targetDir: string): {
|
|
|
360
414
|
} catch (error) {
|
|
361
415
|
console.warn(
|
|
362
416
|
chalk.yellow(
|
|
363
|
-
`⚠️ Impossible de lire les versions locales (${error}), utilisation de 'latest'
|
|
364
|
-
)
|
|
417
|
+
`⚠️ Impossible de lire les versions locales (${error}), utilisation de 'latest'`
|
|
418
|
+
)
|
|
365
419
|
);
|
|
366
420
|
}
|
|
367
421
|
|
|
@@ -379,7 +433,7 @@ async function addDependencies(
|
|
|
379
433
|
targetDir: string,
|
|
380
434
|
useHeroUI: boolean,
|
|
381
435
|
withAuth: boolean,
|
|
382
|
-
selectedModules: string[] = []
|
|
436
|
+
selectedModules: string[] = []
|
|
383
437
|
) {
|
|
384
438
|
const pkgPath = path.join(targetDir, "package.json");
|
|
385
439
|
const pkg = await fs.readJson(pkgPath);
|
|
@@ -466,6 +520,7 @@ async function addDependencies(
|
|
|
466
520
|
requiredDeps["lucide-react"] = "^0.554.0";
|
|
467
521
|
requiredDeps["framer-motion"] = "^11.18.2";
|
|
468
522
|
requiredDeps["clsx"] = "^2.1.1";
|
|
523
|
+
requiredDeps["env-cmd"] = "^11.0.0";
|
|
469
524
|
}
|
|
470
525
|
|
|
471
526
|
// DevDependencies
|
|
@@ -490,7 +545,7 @@ async function createNextStructure(
|
|
|
490
545
|
targetDir: string,
|
|
491
546
|
force: boolean,
|
|
492
547
|
useHeroUI: boolean,
|
|
493
|
-
withAuth: boolean
|
|
548
|
+
withAuth: boolean
|
|
494
549
|
) {
|
|
495
550
|
console.log(chalk.yellow("\n📁 Création de la structure Next.js..."));
|
|
496
551
|
|
|
@@ -550,9 +605,7 @@ export default function RootLayout({ children }: PropsWithChildren<{}>) {
|
|
|
550
605
|
console.log(chalk.green("✓ app/layout.tsx créé"));
|
|
551
606
|
} else {
|
|
552
607
|
console.log(
|
|
553
|
-
chalk.gray(
|
|
554
|
-
" app/layout.tsx existe déjà (utilisez --force pour écraser)",
|
|
555
|
-
),
|
|
608
|
+
chalk.gray(" app/layout.tsx existe déjà (utilisez --force pour écraser)")
|
|
556
609
|
);
|
|
557
610
|
}
|
|
558
611
|
|
|
@@ -646,7 +699,7 @@ export default function NotFound() {
|
|
|
646
699
|
async function createClientLayout(
|
|
647
700
|
targetDir: string,
|
|
648
701
|
force: boolean,
|
|
649
|
-
useHeroUI: boolean
|
|
702
|
+
useHeroUI: boolean
|
|
650
703
|
) {
|
|
651
704
|
const componentsDir = path.join(targetDir, "components");
|
|
652
705
|
await fs.ensureDir(componentsDir);
|
|
@@ -723,8 +776,8 @@ export function ClientLayout({ children }: { children: ReactNode }) {
|
|
|
723
776
|
} else {
|
|
724
777
|
console.log(
|
|
725
778
|
chalk.gray(
|
|
726
|
-
" components/ClientLayout.tsx existe déjà (utilisez --force pour écraser)"
|
|
727
|
-
)
|
|
779
|
+
" components/ClientLayout.tsx existe déjà (utilisez --force pour écraser)"
|
|
780
|
+
)
|
|
728
781
|
);
|
|
729
782
|
}
|
|
730
783
|
}
|
|
@@ -733,7 +786,7 @@ async function createRoute(
|
|
|
733
786
|
appDir: string,
|
|
734
787
|
routeName: string,
|
|
735
788
|
layoutType: string,
|
|
736
|
-
force: boolean
|
|
789
|
+
force: boolean
|
|
737
790
|
) {
|
|
738
791
|
const routeDir = path.join(appDir, routeName);
|
|
739
792
|
await fs.ensureDir(routeDir);
|
|
@@ -780,9 +833,8 @@ export default function AuthLayout({
|
|
|
780
833
|
const layoutComponent =
|
|
781
834
|
layoutType.charAt(0).toUpperCase() + layoutType.slice(1) + "Layout";
|
|
782
835
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
layoutContent = `import { ${layoutComponent} } from "@lastbrain/app";
|
|
836
|
+
// Layout docs avec footer
|
|
837
|
+
layoutContent = `import { ${layoutComponent} } from "@lastbrain/app";
|
|
786
838
|
import { footerConfig } from "../../config/footer";
|
|
787
839
|
|
|
788
840
|
export default function DocsLayout({
|
|
@@ -792,11 +844,6 @@ export default function DocsLayout({
|
|
|
792
844
|
}) {
|
|
793
845
|
return <${layoutComponent} footerConfig={footerConfig}>{children}</${layoutComponent}>;
|
|
794
846
|
}`;
|
|
795
|
-
} else {
|
|
796
|
-
layoutContent = `import { ${layoutComponent} } from "@lastbrain/app";
|
|
797
|
-
|
|
798
|
-
export default ${layoutComponent};`;
|
|
799
|
-
}
|
|
800
847
|
}
|
|
801
848
|
|
|
802
849
|
await fs.writeFile(layoutPath, layoutContent);
|
|
@@ -893,6 +940,7 @@ export function AppHeader() {
|
|
|
893
940
|
user={user}
|
|
894
941
|
onLogout={handleLogout}
|
|
895
942
|
menuConfig={menuConfig}
|
|
943
|
+
accountMenu={menuConfig.account}
|
|
896
944
|
brandName="LastBrain App"
|
|
897
945
|
brandHref="/"
|
|
898
946
|
isSuperAdmin={isSuperAdmin}
|
|
@@ -911,8 +959,8 @@ export function AppHeader() {
|
|
|
911
959
|
} else {
|
|
912
960
|
console.log(
|
|
913
961
|
chalk.gray(
|
|
914
|
-
" components/AppHeader.tsx existe déjà (utilisez --force pour écraser)"
|
|
915
|
-
)
|
|
962
|
+
" components/AppHeader.tsx existe déjà (utilisez --force pour écraser)"
|
|
963
|
+
)
|
|
916
964
|
);
|
|
917
965
|
}
|
|
918
966
|
}
|
|
@@ -951,8 +999,8 @@ export function AppAside({ className = "", isVisible = true }: AppAsideProps) {
|
|
|
951
999
|
} else {
|
|
952
1000
|
console.log(
|
|
953
1001
|
chalk.gray(
|
|
954
|
-
" components/AppAside.tsx existe déjà (utilisez --force pour écraser)"
|
|
955
|
-
)
|
|
1002
|
+
" components/AppAside.tsx existe déjà (utilisez --force pour écraser)"
|
|
1003
|
+
)
|
|
956
1004
|
);
|
|
957
1005
|
}
|
|
958
1006
|
}
|
|
@@ -981,8 +1029,8 @@ export function AppProviders({ children }: { children: ReactNode }) {
|
|
|
981
1029
|
} else {
|
|
982
1030
|
console.log(
|
|
983
1031
|
chalk.gray(
|
|
984
|
-
" components/AppProviders.tsx existe déjà (utilisez --force pour écraser)"
|
|
985
|
-
)
|
|
1032
|
+
" components/AppProviders.tsx existe déjà (utilisez --force pour écraser)"
|
|
1033
|
+
)
|
|
986
1034
|
);
|
|
987
1035
|
}
|
|
988
1036
|
}
|
|
@@ -991,7 +1039,7 @@ async function createConfigFiles(
|
|
|
991
1039
|
targetDir: string,
|
|
992
1040
|
force: boolean,
|
|
993
1041
|
useHeroUI: boolean,
|
|
994
|
-
projectName?: string
|
|
1042
|
+
projectName?: string
|
|
995
1043
|
) {
|
|
996
1044
|
console.log(chalk.yellow("\n⚙️ Création des fichiers de configuration..."));
|
|
997
1045
|
|
|
@@ -1014,6 +1062,11 @@ export async function middleware(request: NextRequest) {
|
|
|
1014
1062
|
"/callback",
|
|
1015
1063
|
];
|
|
1016
1064
|
|
|
1065
|
+
if(process.env.MAINTENANCE_MODE === "true" && !pathname.startsWith("/maintenance")) {
|
|
1066
|
+
const redirectUrl = new URL("/maintenance", request.url);
|
|
1067
|
+
return NextResponse.redirect(redirectUrl);
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1017
1070
|
const isPublicAuthPage = publicAuthPages.some((page) =>
|
|
1018
1071
|
pathname.startsWith(page)
|
|
1019
1072
|
);
|
|
@@ -1131,8 +1184,8 @@ export const config = {
|
|
|
1131
1184
|
await fs.writeFile(middlewarePath, middleware);
|
|
1132
1185
|
console.log(
|
|
1133
1186
|
chalk.green(
|
|
1134
|
-
"✓ middleware.ts créé (protection /auth/*, /admin/* et /api/admin/*)"
|
|
1135
|
-
)
|
|
1187
|
+
"✓ middleware.ts créé (protection /auth/*, /admin/* et /api/admin/*)"
|
|
1188
|
+
)
|
|
1136
1189
|
);
|
|
1137
1190
|
}
|
|
1138
1191
|
|
|
@@ -1418,7 +1471,7 @@ async function createGitIgnore(targetDir: string, force: boolean) {
|
|
|
1418
1471
|
// Copier le fichier .gitignore depuis le template
|
|
1419
1472
|
const templateGitignorePath = path.join(
|
|
1420
1473
|
__dirname,
|
|
1421
|
-
"../templates/gitignore/.gitignore"
|
|
1474
|
+
"../templates/gitignore/.gitignore"
|
|
1422
1475
|
);
|
|
1423
1476
|
|
|
1424
1477
|
if (fs.existsSync(templateGitignorePath)) {
|
|
@@ -1475,16 +1528,7 @@ tmp/
|
|
|
1475
1528
|
coverage/
|
|
1476
1529
|
*.lcov
|
|
1477
1530
|
|
|
1478
|
-
# Generated by module-build
|
|
1479
|
-
app/navigation.generated.ts
|
|
1480
|
-
app/routes.generated.ts
|
|
1481
|
-
app/menu.generated.ts
|
|
1482
1531
|
|
|
1483
|
-
# Generated app-shell overrides
|
|
1484
|
-
app/(public)/
|
|
1485
|
-
app/(auth)/
|
|
1486
|
-
app/(admin)/
|
|
1487
|
-
app/layout.tsx
|
|
1488
1532
|
`;
|
|
1489
1533
|
await fs.writeFile(gitignorePath, gitignoreContent);
|
|
1490
1534
|
}
|
|
@@ -1516,13 +1560,31 @@ SUPABASE_SERVICE_ROLE_KEY=YOUR_LOCAL_SERVICE_ROLE_KEY
|
|
|
1516
1560
|
}
|
|
1517
1561
|
}
|
|
1518
1562
|
|
|
1519
|
-
async function createEnvLocal(
|
|
1563
|
+
async function createEnvLocal(
|
|
1564
|
+
targetDir: string,
|
|
1565
|
+
force: boolean,
|
|
1566
|
+
isMonorepoProject: boolean = false
|
|
1567
|
+
) {
|
|
1520
1568
|
const envLocalPath = path.join(targetDir, ".env.local");
|
|
1521
1569
|
|
|
1522
1570
|
if (!fs.existsSync(envLocalPath) || force) {
|
|
1523
1571
|
console.log(chalk.yellow("\n🔐 Création de .env.local..."));
|
|
1524
1572
|
|
|
1525
|
-
|
|
1573
|
+
let envContent: string;
|
|
1574
|
+
|
|
1575
|
+
if (isMonorepoProject) {
|
|
1576
|
+
// Pour les projets monorepo, utiliser les variables du monorepo
|
|
1577
|
+
envContent = `# Supabase Configuration (Monorepo - Centralisé)
|
|
1578
|
+
# Les variables Supabase sont gérées au niveau du monorepo
|
|
1579
|
+
|
|
1580
|
+
# OpenAI Configuration (clé factice pour éviter les erreurs de build)
|
|
1581
|
+
OPENAI_API_KEY=sk-fake-openai-key-for-development-replace-with-real-key
|
|
1582
|
+
|
|
1583
|
+
# Note: Les variables Supabase sont fournies par le monorepo parent
|
|
1584
|
+
`;
|
|
1585
|
+
} else {
|
|
1586
|
+
// Pour les projets indépendants
|
|
1587
|
+
envContent = `# Supabase Configuration
|
|
1526
1588
|
# Valeurs par défaut pour le développement local
|
|
1527
1589
|
|
|
1528
1590
|
# Supabase Local (par défaut)
|
|
@@ -1533,11 +1595,37 @@ SUPABASE_SERVICE_ROLE_KEY=eyJhbGc...
|
|
|
1533
1595
|
# OpenAI Configuration (clé factice pour éviter les erreurs de build)
|
|
1534
1596
|
OPENAI_API_KEY=sk-fake-openai-key-for-development-replace-with-real-key
|
|
1535
1597
|
`;
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1536
1600
|
await fs.writeFile(envLocalPath, envContent);
|
|
1537
1601
|
console.log(chalk.green("✓ .env.local créé"));
|
|
1538
1602
|
}
|
|
1539
1603
|
}
|
|
1540
1604
|
|
|
1605
|
+
async function createEnvProd(targetDir: string, force: boolean) {
|
|
1606
|
+
const envProdPath = path.join(targetDir, ".env.prod");
|
|
1607
|
+
|
|
1608
|
+
if (!fs.existsSync(envProdPath) || force) {
|
|
1609
|
+
console.log(chalk.yellow("\n🔐 Création de .env.prod..."));
|
|
1610
|
+
|
|
1611
|
+
const envContent = `# Production Environment Configuration
|
|
1612
|
+
# Copy your production values here
|
|
1613
|
+
|
|
1614
|
+
# Supabase Production
|
|
1615
|
+
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
|
|
1616
|
+
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-prod-anon-key
|
|
1617
|
+
SUPABASE_SERVICE_ROLE_KEY=your-prod-service-role-key
|
|
1618
|
+
|
|
1619
|
+
# OpenAI Production
|
|
1620
|
+
OPENAI_API_KEY=sk-proj-your-prod-api-key
|
|
1621
|
+
|
|
1622
|
+
# Note: Update these values with your actual production credentials
|
|
1623
|
+
`;
|
|
1624
|
+
await fs.writeFile(envProdPath, envContent);
|
|
1625
|
+
console.log(chalk.green("✓ .env.prod créé"));
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1541
1629
|
async function createSupabaseStructure(targetDir: string, force: boolean) {
|
|
1542
1630
|
console.log(chalk.yellow("\n🗄️ Création de la structure Supabase..."));
|
|
1543
1631
|
|
|
@@ -1548,11 +1636,11 @@ async function createSupabaseStructure(targetDir: string, force: boolean) {
|
|
|
1548
1636
|
// Copier le fichier de migration initial depuis le template
|
|
1549
1637
|
const templateMigrationPath = path.join(
|
|
1550
1638
|
__dirname,
|
|
1551
|
-
"../templates/migrations/20201010100000_app_base.sql"
|
|
1639
|
+
"../templates/migrations/20201010100000_app_base.sql"
|
|
1552
1640
|
);
|
|
1553
1641
|
const migrationDestPath = path.join(
|
|
1554
1642
|
migrationsDir,
|
|
1555
|
-
"20201010100000_app_base.sql"
|
|
1643
|
+
"20201010100000_app_base.sql"
|
|
1556
1644
|
);
|
|
1557
1645
|
|
|
1558
1646
|
if (!fs.existsSync(migrationDestPath) || force) {
|
|
@@ -1560,35 +1648,35 @@ async function createSupabaseStructure(targetDir: string, force: boolean) {
|
|
|
1560
1648
|
if (fs.existsSync(templateMigrationPath)) {
|
|
1561
1649
|
await fs.copy(templateMigrationPath, migrationDestPath);
|
|
1562
1650
|
console.log(
|
|
1563
|
-
chalk.green("✓ supabase/migrations/20201010100000_app_base.sql créé")
|
|
1651
|
+
chalk.green("✓ supabase/migrations/20201010100000_app_base.sql créé")
|
|
1564
1652
|
);
|
|
1565
1653
|
} else {
|
|
1566
1654
|
console.log(
|
|
1567
1655
|
chalk.yellow(
|
|
1568
|
-
"⚠ Template de migration introuvable, création d'un fichier vide"
|
|
1569
|
-
)
|
|
1656
|
+
"⚠ Template de migration introuvable, création d'un fichier vide"
|
|
1657
|
+
)
|
|
1570
1658
|
);
|
|
1571
1659
|
await fs.writeFile(
|
|
1572
1660
|
migrationDestPath,
|
|
1573
|
-
"-- Initial migration\n-- Add your database schema here\n"
|
|
1661
|
+
"-- Initial migration\n-- Add your database schema here\n"
|
|
1574
1662
|
);
|
|
1575
1663
|
console.log(
|
|
1576
1664
|
chalk.green(
|
|
1577
|
-
"✓ supabase/migrations/20201010100000_app_base.sql créé (vide)"
|
|
1578
|
-
)
|
|
1665
|
+
"✓ supabase/migrations/20201010100000_app_base.sql créé (vide)"
|
|
1666
|
+
)
|
|
1579
1667
|
);
|
|
1580
1668
|
}
|
|
1581
1669
|
} catch (error) {
|
|
1582
1670
|
console.error(
|
|
1583
1671
|
chalk.red("✗ Erreur lors de la création de la migration:"),
|
|
1584
|
-
error
|
|
1672
|
+
error
|
|
1585
1673
|
);
|
|
1586
1674
|
}
|
|
1587
1675
|
} else {
|
|
1588
1676
|
console.log(
|
|
1589
1677
|
chalk.gray(
|
|
1590
|
-
" supabase/migrations/20201010100000_app_base.sql existe déjà"
|
|
1591
|
-
)
|
|
1678
|
+
" supabase/migrations/20201010100000_app_base.sql existe déjà"
|
|
1679
|
+
)
|
|
1592
1680
|
);
|
|
1593
1681
|
}
|
|
1594
1682
|
}
|
|
@@ -1602,7 +1690,7 @@ async function addScriptsToPackageJson(targetDir: string) {
|
|
|
1602
1690
|
// Détecter si le projet cible est dans un workspace
|
|
1603
1691
|
const targetIsInMonorepo =
|
|
1604
1692
|
fs.existsSync(
|
|
1605
|
-
path.join(targetDir, "../../../packages/core/package.json")
|
|
1693
|
+
path.join(targetDir, "../../../packages/core/package.json")
|
|
1606
1694
|
) ||
|
|
1607
1695
|
fs.existsSync(path.join(targetDir, "../../packages/core/package.json"));
|
|
1608
1696
|
|
|
@@ -1618,6 +1706,8 @@ async function addScriptsToPackageJson(targetDir: string) {
|
|
|
1618
1706
|
? "pnpm --filter @lastbrain/core build && pnpm --filter @lastbrain/ui build && pnpm --filter @lastbrain/module-auth build && pnpm --filter @lastbrain/module-ai build"
|
|
1619
1707
|
: "echo 'No prebuild needed outside monorepo'",
|
|
1620
1708
|
dev: "next dev",
|
|
1709
|
+
"dev:local": "env-cmd -f .env.local next dev",
|
|
1710
|
+
"dev:prod": "env-cmd -f .env.prod next dev",
|
|
1621
1711
|
build: "next build",
|
|
1622
1712
|
start: "next start",
|
|
1623
1713
|
lint: "next lint",
|
|
@@ -1639,7 +1729,7 @@ async function addScriptsToPackageJson(targetDir: string) {
|
|
|
1639
1729
|
async function saveModulesConfig(
|
|
1640
1730
|
targetDir: string,
|
|
1641
1731
|
selectedModules: string[],
|
|
1642
|
-
withAuth: boolean
|
|
1732
|
+
withAuth: boolean
|
|
1643
1733
|
) {
|
|
1644
1734
|
const modulesConfigPath = path.join(targetDir, ".lastbrain", "modules.json");
|
|
1645
1735
|
await fs.ensureDir(path.dirname(modulesConfigPath));
|
|
@@ -1660,7 +1750,7 @@ async function saveModulesConfig(
|
|
|
1660
1750
|
const modulePath = path.join(
|
|
1661
1751
|
targetDir,
|
|
1662
1752
|
"node_modules",
|
|
1663
|
-
...availableModule.package.split("/")
|
|
1753
|
+
...availableModule.package.split("/")
|
|
1664
1754
|
);
|
|
1665
1755
|
const migrationsDir = path.join(modulePath, "supabase", "migrations");
|
|
1666
1756
|
|
|
@@ -1918,7 +2008,7 @@ export function isPrivateBucket(bucket: string): boolean {
|
|
|
1918
2008
|
"api",
|
|
1919
2009
|
"storage",
|
|
1920
2010
|
"[bucket]",
|
|
1921
|
-
"[...path]"
|
|
2011
|
+
"[...path]"
|
|
1922
2012
|
);
|
|
1923
2013
|
await fs.ensureDir(apiStorageDir);
|
|
1924
2014
|
|
|
@@ -2045,7 +2135,7 @@ export async function GET(
|
|
|
2045
2135
|
|
|
2046
2136
|
await fs.writeFile(routePath, routeContent);
|
|
2047
2137
|
console.log(
|
|
2048
|
-
chalk.green("✓ app/api/storage/[bucket]/[...path]/route.ts créé")
|
|
2138
|
+
chalk.green("✓ app/api/storage/[bucket]/[...path]/route.ts créé")
|
|
2049
2139
|
);
|
|
2050
2140
|
}
|
|
2051
2141
|
|