@lastbrain/app 0.1.25 → 0.1.27

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.
Files changed (54) hide show
  1. package/dist/app-shell/(public)/page.d.ts.map +1 -1
  2. package/dist/index.d.ts +4 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +4 -0
  5. package/dist/layouts/AdminLayoutWithSidebar.d.ts +8 -0
  6. package/dist/layouts/AdminLayoutWithSidebar.d.ts.map +1 -0
  7. package/dist/layouts/AdminLayoutWithSidebar.js +9 -0
  8. package/dist/layouts/AuthLayoutWithSidebar.d.ts +8 -0
  9. package/dist/layouts/AuthLayoutWithSidebar.d.ts.map +1 -0
  10. package/dist/layouts/AuthLayoutWithSidebar.js +9 -0
  11. package/dist/scripts/db-init.js +2 -2
  12. package/dist/scripts/dev-sync.js +23 -12
  13. package/dist/scripts/init-app.d.ts.map +1 -1
  14. package/dist/scripts/init-app.js +114 -12
  15. package/dist/scripts/module-add.d.ts.map +1 -1
  16. package/dist/scripts/module-add.js +19 -6
  17. package/dist/scripts/module-build.d.ts.map +1 -1
  18. package/dist/scripts/module-build.js +288 -30
  19. package/dist/scripts/module-create.d.ts.map +1 -1
  20. package/dist/scripts/module-create.js +25 -15
  21. package/dist/scripts/module-remove.d.ts.map +1 -1
  22. package/dist/scripts/module-remove.js +28 -15
  23. package/dist/scripts/script-runner.js +1 -1
  24. package/dist/styles.css +1 -1
  25. package/dist/templates/DefaultDoc.js +1 -7
  26. package/dist/templates/components/AppAside.d.ts +6 -0
  27. package/dist/templates/components/AppAside.d.ts.map +1 -0
  28. package/dist/templates/components/AppAside.js +9 -0
  29. package/dist/templates/layouts/admin-layout.d.ts +4 -0
  30. package/dist/templates/layouts/admin-layout.d.ts.map +1 -0
  31. package/dist/templates/layouts/admin-layout.js +6 -0
  32. package/dist/templates/layouts/auth-layout.d.ts +4 -0
  33. package/dist/templates/layouts/auth-layout.d.ts.map +1 -0
  34. package/dist/templates/layouts/auth-layout.js +6 -0
  35. package/package.json +2 -1
  36. package/src/app-shell/(public)/page.tsx +6 -2
  37. package/src/auth/useAuthSession.ts +1 -1
  38. package/src/cli.ts +1 -1
  39. package/src/index.ts +6 -0
  40. package/src/layouts/AdminLayoutWithSidebar.tsx +35 -0
  41. package/src/layouts/AppProviders.tsx +1 -1
  42. package/src/layouts/AuthLayoutWithSidebar.tsx +35 -0
  43. package/src/scripts/db-init.ts +13 -8
  44. package/src/scripts/db-migrations-sync.ts +4 -4
  45. package/src/scripts/dev-sync.ts +50 -19
  46. package/src/scripts/init-app.ts +243 -65
  47. package/src/scripts/module-add.ts +54 -22
  48. package/src/scripts/module-build.ts +412 -88
  49. package/src/scripts/module-create.ts +85 -49
  50. package/src/scripts/module-remove.ts +120 -61
  51. package/src/scripts/readme-build.ts +2 -2
  52. package/src/scripts/script-runner.ts +3 -3
  53. package/src/templates/AuthGuidePage.tsx +1 -1
  54. package/src/templates/DefaultDoc.tsx +7 -7
@@ -58,6 +58,15 @@ export async function initApp(options: InitAppOptions) {
58
58
  withAuth = selectedModules.includes("auth");
59
59
 
60
60
  console.log();
61
+ } else if (!interactive) {
62
+ // En mode non-interactif, installer auth et ai par défaut
63
+ selectedModules.push("auth", "ai");
64
+ withAuth = true;
65
+ console.log(
66
+ chalk.blue(
67
+ "📦 Modules installés par défaut : Authentication, AI Generation\n",
68
+ ),
69
+ );
61
70
  }
62
71
 
63
72
  // Créer le dossier s'il n'existe pas
@@ -89,29 +98,34 @@ export async function initApp(options: InitAppOptions) {
89
98
  await addScriptsToPackageJson(targetDir);
90
99
 
91
100
  // 9. Enregistrer les modules sélectionnés
92
- if (withAuth || selectedModules.length > 0) {
101
+ if (withAuth && !selectedModules.includes("auth")) {
102
+ selectedModules.push("auth");
103
+ }
104
+
105
+ if (selectedModules.length > 0) {
93
106
  await saveModulesConfig(targetDir, selectedModules, withAuth);
94
107
  }
95
108
 
96
109
  console.log(
97
- chalk.green("\n✅ Application LastBrain initialisée avec succès!\n")
110
+ chalk.green("\n✅ Application LastBrain initialisée avec succès!\n"),
98
111
  );
99
-
112
+
100
113
  const relativePath = path.relative(process.cwd(), targetDir);
101
-
114
+
102
115
  // Demander si l'utilisateur veut lancer l'installation et le dev server
103
116
  const { launchNow } = await inquirer.prompt([
104
117
  {
105
118
  type: "confirm",
106
119
  name: "launchNow",
107
- message: "Voulez-vous installer les dépendances et lancer le serveur de développement maintenant ?",
120
+ message:
121
+ "Voulez-vous installer les dépendances et lancer le serveur de développement maintenant ?",
108
122
  default: true,
109
123
  },
110
124
  ]);
111
125
 
112
126
  if (launchNow) {
113
127
  console.log(chalk.yellow("\n📦 Installation des dépendances...\n"));
114
-
128
+
115
129
  try {
116
130
  execSync("pnpm install", { cwd: targetDir, stdio: "inherit" });
117
131
  console.log(chalk.green("\n✓ Dépendances installées\n"));
@@ -120,52 +134,86 @@ export async function initApp(options: InitAppOptions) {
120
134
  execSync("pnpm build:modules", { cwd: targetDir, stdio: "inherit" });
121
135
  console.log(chalk.green("\n✓ Routes des modules générées\n"));
122
136
 
137
+ console.log(chalk.yellow("🗄️ Initialisation de la base de données...\n"));
138
+ try {
139
+ execSync("pnpm db:init", { cwd: targetDir, stdio: "inherit" });
140
+ console.log(chalk.green("\n✓ Base de données initialisée\n"));
141
+ } catch {
142
+ console.log(
143
+ chalk.yellow(
144
+ "\n⚠️ Erreur d'initialisation de la DB (normal si Supabase pas configuré)\n",
145
+ ),
146
+ );
147
+ }
148
+
123
149
  // Détecter le port (par défaut 3000 pour Next.js)
124
150
  const port = 3000;
125
151
  const url = `http://127.0.0.1:${port}`;
126
152
 
127
- console.log(chalk.yellow("🚀 Lancement du serveur de développement...\n"));
153
+ console.log(
154
+ chalk.yellow("🚀 Lancement du serveur de développement...\n"),
155
+ );
128
156
  console.log(chalk.cyan(`📱 Ouvrez votre navigateur sur : ${url}\n`));
129
-
157
+
130
158
  console.log(chalk.blue("\n📋 Prochaines étapes après le démarrage :"));
131
- console.log(chalk.white(" 1. Cliquez sur 'Get Started' sur la page d'accueil"));
159
+ console.log(
160
+ chalk.white(" 1. Cliquez sur 'Get Started' sur la page d'accueil"),
161
+ );
132
162
  console.log(chalk.white(" 2. Lancez Docker Desktop"));
133
- console.log(chalk.white(" 3. Installez Supabase CLI si nécessaire : brew install supabase/tap/supabase"));
163
+ console.log(
164
+ chalk.white(
165
+ " 3. Installez Supabase CLI si nécessaire : brew install supabase/tap/supabase",
166
+ ),
167
+ );
134
168
  console.log(chalk.white(" 4. Exécutez : pnpm db:init"));
135
169
  console.log(chalk.white(" 5. Rechargez la page\n"));
136
170
 
137
171
  // Ouvrir le navigateur
138
- const openCommand = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
172
+ const openCommand =
173
+ process.platform === "darwin"
174
+ ? "open"
175
+ : process.platform === "win32"
176
+ ? "start"
177
+ : "xdg-open";
139
178
  setTimeout(() => {
140
179
  try {
141
180
  execSync(`${openCommand} ${url}`, { stdio: "ignore" });
142
- } catch (error) {
181
+ } catch {
143
182
  // Ignorer les erreurs d'ouverture du navigateur
144
183
  }
145
184
  }, 2000);
146
185
 
147
186
  // Lancer pnpm dev
148
187
  execSync("pnpm dev", { cwd: targetDir, stdio: "inherit" });
149
- } catch (error) {
188
+ } catch {
150
189
  console.error(chalk.red("\n❌ Erreur lors du lancement\n"));
151
190
  console.log(chalk.cyan("\nVous pouvez lancer manuellement avec :"));
152
191
  console.log(chalk.white(` cd ${relativePath}`));
153
192
  console.log(chalk.white(" pnpm install"));
154
193
  console.log(chalk.white(" pnpm build:modules"));
194
+ console.log(chalk.white(" pnpm db:init"));
155
195
  console.log(chalk.white(" pnpm dev\n"));
156
196
  }
157
197
  } else {
158
198
  console.log(chalk.cyan("\n📋 Prochaines étapes:"));
159
199
  console.log(chalk.white(" 1. cd " + relativePath));
160
200
  console.log(chalk.white(" 2. pnpm install (installer les dépendances)"));
161
- console.log(chalk.white(" 3. pnpm build:modules (générer les routes des modules)"));
201
+ console.log(
202
+ chalk.white(" 3. pnpm build:modules (générer les routes des modules)"),
203
+ );
204
+ console.log(
205
+ chalk.white(" 4. pnpm db:init (initialiser la base de données)"),
206
+ );
207
+ console.log(chalk.white(" 5. pnpm dev (lancer le serveur)"));
162
208
  console.log(chalk.white(" 4. pnpm db:init (initialiser Supabase)"));
163
209
  console.log(chalk.white(" 5. pnpm dev (démarrer le serveur)\n"));
164
-
210
+
165
211
  console.log(chalk.gray("Prérequis pour Supabase :"));
166
212
  console.log(chalk.white(" - Docker Desktop installé et lancé"));
167
- console.log(chalk.white(" - Supabase CLI : brew install supabase/tap/supabase\n"));
168
-
213
+ console.log(
214
+ chalk.white(" - Supabase CLI : brew install supabase/tap/supabase\n"),
215
+ );
216
+
169
217
  // Afficher la commande cd pour faciliter la copie
170
218
  console.log(chalk.gray("Pour vous déplacer dans le projet :"));
171
219
  console.log(chalk.cyan(` cd ${relativePath}\n`));
@@ -204,8 +252,11 @@ function getLastBrainVersions(targetDir: string): {
204
252
  ui: string;
205
253
  moduleAuth: string;
206
254
  } {
207
- const targetIsInMonorepo = fs.existsSync(path.join(targetDir, "../../../packages/core/package.json")) ||
208
- fs.existsSync(path.join(targetDir, "../../packages/core/package.json"));
255
+ const targetIsInMonorepo =
256
+ fs.existsSync(
257
+ path.join(targetDir, "../../../packages/core/package.json"),
258
+ ) ||
259
+ fs.existsSync(path.join(targetDir, "../../packages/core/package.json"));
209
260
 
210
261
  if (targetIsInMonorepo) {
211
262
  // Dans le monorepo, utiliser workspace:*
@@ -221,16 +272,16 @@ function getLastBrainVersions(targetDir: string): {
221
272
  try {
222
273
  // Essayer de lire depuis node_modules/@lastbrain (si init-app a été installé)
223
274
  const appPkgPath = path.join(__dirname, "../../package.json");
224
-
275
+
225
276
  if (fs.existsSync(appPkgPath)) {
226
277
  const appPkg = JSON.parse(fs.readFileSync(appPkgPath, "utf-8"));
227
278
  const appVersion = `^${appPkg.version}`;
228
-
279
+
229
280
  // Lire les versions des dépendances de @lastbrain/app
230
281
  const coreDep = appPkg.dependencies?.["@lastbrain/core"];
231
282
  const uiDep = appPkg.dependencies?.["@lastbrain/ui"];
232
283
  const authDep = appPkg.dependencies?.["@lastbrain/module-auth"];
233
-
284
+
234
285
  return {
235
286
  app: appVersion,
236
287
  core: coreDep || appVersion,
@@ -238,8 +289,12 @@ function getLastBrainVersions(targetDir: string): {
238
289
  moduleAuth: authDep || appVersion,
239
290
  };
240
291
  }
241
- } catch (error) {
242
- console.warn(chalk.yellow("⚠️ Impossible de lire les versions locales, utilisation de 'latest'"));
292
+ } catch {
293
+ console.warn(
294
+ chalk.yellow(
295
+ "⚠️ Impossible de lire les versions locales, utilisation de 'latest'",
296
+ ),
297
+ );
243
298
  }
244
299
 
245
300
  // Fallback: utiliser "latest"
@@ -255,7 +310,7 @@ async function addDependencies(
255
310
  targetDir: string,
256
311
  useHeroUI: boolean,
257
312
  withAuth: boolean,
258
- selectedModules: string[] = []
313
+ selectedModules: string[] = [],
259
314
  ) {
260
315
  const pkgPath = path.join(targetDir, "package.json");
261
316
  const pkg = await fs.readJson(pkgPath);
@@ -263,7 +318,7 @@ async function addDependencies(
263
318
  console.log(chalk.yellow("\n📦 Configuration des dépendances..."));
264
319
 
265
320
  const versions = getLastBrainVersions(targetDir);
266
-
321
+
267
322
  // Dependencies
268
323
  const requiredDeps: Record<string, string> = {
269
324
  next: "^15.0.3",
@@ -282,7 +337,7 @@ async function addDependencies(
282
337
 
283
338
  // Ajouter les autres modules sélectionnés
284
339
  for (const moduleName of selectedModules) {
285
- const moduleInfo = AVAILABLE_MODULES.find(m => m.name === moduleName);
340
+ const moduleInfo = AVAILABLE_MODULES.find((m) => m.name === moduleName);
286
341
  if (moduleInfo && moduleInfo.package !== "@lastbrain/module-auth") {
287
342
  // Pour les autres modules, utiliser "latest" ou la version depuis le package
288
343
  requiredDeps[moduleInfo.package] = versions.app; // Utiliser la même version que app
@@ -359,7 +414,7 @@ async function createNextStructure(
359
414
  targetDir: string,
360
415
  force: boolean,
361
416
  useHeroUI: boolean,
362
- withAuth: boolean
417
+ withAuth: boolean,
363
418
  ) {
364
419
  console.log(chalk.yellow("\n📁 Création de la structure Next.js..."));
365
420
 
@@ -456,7 +511,9 @@ export default function RootLayout({ children }: PropsWithChildren<{}>) {
456
511
  console.log(chalk.green("✓ app/layout.tsx créé"));
457
512
  } else {
458
513
  console.log(
459
- chalk.gray(" app/layout.tsx existe déjà (utilisez --force pour écraser)")
514
+ chalk.gray(
515
+ " app/layout.tsx existe déjà (utilisez --force pour écraser)",
516
+ ),
460
517
  );
461
518
  }
462
519
 
@@ -524,17 +581,21 @@ export default function NotFound() {
524
581
 
525
582
  // Créer les routes avec leurs layouts
526
583
  await createRoute(appDir, "admin", "admin", force);
584
+ await createRoute(appDir, "auth", "auth", force);
527
585
  await createRoute(appDir, "docs", "public", force);
528
586
 
529
587
  // Créer le composant AppHeader
530
588
  await createAppHeader(targetDir, force);
589
+
590
+ // Créer le composant AppAside
591
+ await createAppAside(targetDir, force);
531
592
  }
532
593
 
533
594
  async function createRoute(
534
595
  appDir: string,
535
596
  routeName: string,
536
597
  layoutType: string,
537
- force: boolean
598
+ force: boolean,
538
599
  ) {
539
600
  const routeDir = path.join(appDir, routeName);
540
601
  await fs.ensureDir(routeDir);
@@ -542,13 +603,49 @@ async function createRoute(
542
603
  // Layout pour la route
543
604
  const layoutPath = path.join(routeDir, "layout.tsx");
544
605
  if (!fs.existsSync(layoutPath) || force) {
545
- const layoutComponent =
546
- layoutType.charAt(0).toUpperCase() + layoutType.slice(1) + "Layout";
606
+ let layoutContent = "";
547
607
 
548
- const layoutContent = `import { ${layoutComponent} } from "@lastbrain/app";
608
+ if (routeName === "admin") {
609
+ // Layout admin avec sidebar
610
+ layoutContent = `import { AdminLayoutWithSidebar } from "@lastbrain/app";
611
+ import { menuConfig } from "../../config/menu";
612
+
613
+ export default function AdminLayout({
614
+ children,
615
+ }: {
616
+ children: React.ReactNode;
617
+ }) {
618
+ return (
619
+ <AdminLayoutWithSidebar menuConfig={menuConfig}>
620
+ {children}
621
+ </AdminLayoutWithSidebar>
622
+ );
623
+ }`;
624
+ } else if (routeName === "auth") {
625
+ // Layout auth avec sidebar
626
+ layoutContent = `import { AuthLayoutWithSidebar } from "@lastbrain/app";
627
+ import { menuConfig } from "../../config/menu";
628
+
629
+ export default function AuthLayout({
630
+ children,
631
+ }: {
632
+ children: React.ReactNode;
633
+ }) {
634
+ return (
635
+ <AuthLayoutWithSidebar menuConfig={menuConfig}>
636
+ {children}
637
+ </AuthLayoutWithSidebar>
638
+ );
639
+ }`;
640
+ } else {
641
+ // Layout standard pour les autres routes
642
+ const layoutComponent =
643
+ layoutType.charAt(0).toUpperCase() + layoutType.slice(1) + "Layout";
644
+ layoutContent = `import { ${layoutComponent} } from "@lastbrain/app";
645
+
646
+ export default ${layoutComponent};`;
647
+ }
549
648
 
550
- export default ${layoutComponent};
551
- `;
552
649
  await fs.writeFile(layoutPath, layoutContent);
553
650
  console.log(chalk.green(`✓ app/${routeName}/layout.tsx créé`));
554
651
  }
@@ -616,7 +713,7 @@ async function createAppHeader(targetDir: string, force: boolean) {
616
713
  await fs.ensureDir(componentsDir);
617
714
 
618
715
  const headerPath = path.join(componentsDir, "AppHeader.tsx");
619
-
716
+
620
717
  if (!fs.existsSync(headerPath) || force) {
621
718
  const headerContent = `"use client";
622
719
 
@@ -652,7 +749,49 @@ export function AppHeader() {
652
749
  console.log(chalk.green("✓ components/AppHeader.tsx créé"));
653
750
  } else {
654
751
  console.log(
655
- chalk.gray(" components/AppHeader.tsx existe déjà (utilisez --force pour écraser)")
752
+ chalk.gray(
753
+ " components/AppHeader.tsx existe déjà (utilisez --force pour écraser)",
754
+ ),
755
+ );
756
+ }
757
+ }
758
+
759
+ async function createAppAside(targetDir: string, force: boolean) {
760
+ const componentsDir = path.join(targetDir, "components");
761
+ await fs.ensureDir(componentsDir);
762
+
763
+ const asidePath = path.join(componentsDir, "AppAside.tsx");
764
+ if (!fs.existsSync(asidePath) || force) {
765
+ const asideContent = `"use client";
766
+
767
+ import { AppAside as UIAppAside } from "@lastbrain/app";
768
+ import { useAuthSession } from "@lastbrain/app";
769
+ import { menuConfig } from "../config/menu";
770
+
771
+ interface AppAsideProps {
772
+ className?: string;
773
+ isVisible?: boolean;
774
+ }
775
+
776
+ export function AppAside({ className = "", isVisible = true }: AppAsideProps) {
777
+ const { isSuperAdmin } = useAuthSession();
778
+
779
+ return (
780
+ <UIAppAside
781
+ className={className}
782
+ menuConfig={menuConfig}
783
+ isSuperAdmin={isSuperAdmin}
784
+ isVisible={isVisible}
785
+ />
786
+ );
787
+ }`;
788
+ await fs.writeFile(asidePath, asideContent);
789
+ console.log(chalk.green("✓ components/AppAside.tsx créé"));
790
+ } else {
791
+ console.log(
792
+ chalk.gray(
793
+ " components/AppAside.tsx existe déjà (utilisez --force pour écraser)",
794
+ ),
656
795
  );
657
796
  }
658
797
  }
@@ -660,7 +799,7 @@ export function AppHeader() {
660
799
  async function createConfigFiles(
661
800
  targetDir: string,
662
801
  force: boolean,
663
- useHeroUI: boolean
802
+ useHeroUI: boolean,
664
803
  ) {
665
804
  console.log(chalk.yellow("\n⚙️ Création des fichiers de configuration..."));
666
805
 
@@ -745,7 +884,9 @@ export const config = {
745
884
  };
746
885
  `;
747
886
  await fs.writeFile(middlewarePath, middleware);
748
- console.log(chalk.green("✓ middleware.ts créé (protection /auth/* et /admin/*)"));
887
+ console.log(
888
+ chalk.green("✓ middleware.ts créé (protection /auth/* et /admin/*)"),
889
+ );
749
890
  }
750
891
 
751
892
  // next.config.mjs
@@ -904,7 +1045,7 @@ async function createGitIgnore(targetDir: string, force: boolean) {
904
1045
  // Copier le fichier .gitignore depuis le template
905
1046
  const templateGitignorePath = path.join(
906
1047
  __dirname,
907
- "../templates/gitignore/.gitignore"
1048
+ "../templates/gitignore/.gitignore",
908
1049
  );
909
1050
 
910
1051
  if (fs.existsSync(templateGitignorePath)) {
@@ -1012,35 +1153,48 @@ async function createSupabaseStructure(targetDir: string, force: boolean) {
1012
1153
  // Copier le fichier de migration initial depuis le template
1013
1154
  const templateMigrationPath = path.join(
1014
1155
  __dirname,
1015
- "../templates/migrations/20201010100000_app_base.sql"
1156
+ "../templates/migrations/20201010100000_app_base.sql",
1016
1157
  );
1017
1158
  const migrationDestPath = path.join(
1018
1159
  migrationsDir,
1019
- "20201010100000_app_base.sql"
1160
+ "20201010100000_app_base.sql",
1020
1161
  );
1021
1162
 
1022
1163
  if (!fs.existsSync(migrationDestPath) || force) {
1023
1164
  try {
1024
1165
  if (fs.existsSync(templateMigrationPath)) {
1025
1166
  await fs.copy(templateMigrationPath, migrationDestPath);
1026
- console.log(chalk.green("✓ supabase/migrations/20201010100000_app_base.sql créé"));
1167
+ console.log(
1168
+ chalk.green("✓ supabase/migrations/20201010100000_app_base.sql créé"),
1169
+ );
1027
1170
  } else {
1028
1171
  console.log(
1029
1172
  chalk.yellow(
1030
- "⚠ Template de migration introuvable, création d'un fichier vide"
1031
- )
1173
+ "⚠ Template de migration introuvable, création d'un fichier vide",
1174
+ ),
1032
1175
  );
1033
1176
  await fs.writeFile(
1034
1177
  migrationDestPath,
1035
- "-- Initial migration\n-- Add your database schema here\n"
1178
+ "-- Initial migration\n-- Add your database schema here\n",
1179
+ );
1180
+ console.log(
1181
+ chalk.green(
1182
+ "✓ supabase/migrations/20201010100000_app_base.sql créé (vide)",
1183
+ ),
1036
1184
  );
1037
- console.log(chalk.green("✓ supabase/migrations/20201010100000_app_base.sql créé (vide)"));
1038
1185
  }
1039
1186
  } catch (error) {
1040
- console.error(chalk.red("✗ Erreur lors de la création de la migration:"), error);
1187
+ console.error(
1188
+ chalk.red("✗ Erreur lors de la création de la migration:"),
1189
+ error,
1190
+ );
1041
1191
  }
1042
1192
  } else {
1043
- console.log(chalk.gray(" supabase/migrations/20201010100000_app_base.sql existe déjà"));
1193
+ console.log(
1194
+ chalk.gray(
1195
+ " supabase/migrations/20201010100000_app_base.sql existe déjà",
1196
+ ),
1197
+ );
1044
1198
  }
1045
1199
  }
1046
1200
 
@@ -1051,25 +1205,30 @@ async function addScriptsToPackageJson(targetDir: string) {
1051
1205
  const pkg = await fs.readJson(pkgPath);
1052
1206
 
1053
1207
  // Détecter si le projet cible est dans un workspace
1054
- const targetIsInMonorepo = fs.existsSync(path.join(targetDir, "../../../packages/core/package.json")) ||
1055
- fs.existsSync(path.join(targetDir, "../../packages/core/package.json"));
1208
+ const targetIsInMonorepo =
1209
+ fs.existsSync(
1210
+ path.join(targetDir, "../../../packages/core/package.json"),
1211
+ ) ||
1212
+ fs.existsSync(path.join(targetDir, "../../packages/core/package.json"));
1056
1213
 
1057
1214
  let scriptsPrefix = "lastbrain";
1058
-
1215
+
1059
1216
  if (!targetIsInMonorepo) {
1060
1217
  // Hors monorepo, utiliser le chemin direct vers le CLI
1061
1218
  scriptsPrefix = "node node_modules/@lastbrain/app/dist/cli.js";
1062
1219
  }
1063
1220
 
1064
1221
  const scripts = {
1065
- predev: targetIsInMonorepo
1222
+ predev: targetIsInMonorepo
1066
1223
  ? "pnpm --filter @lastbrain/core build && pnpm --filter @lastbrain/ui build && pnpm --filter @lastbrain/module-auth build && pnpm --filter @lastbrain/module-ai build"
1067
1224
  : "echo 'No prebuild needed outside monorepo'",
1068
1225
  dev: "next dev",
1069
1226
  build: "next build",
1070
1227
  start: "next start",
1071
1228
  lint: "next lint",
1072
- lastbrain: targetIsInMonorepo ? "lastbrain" : "node node_modules/@lastbrain/app/dist/cli.js",
1229
+ lastbrain: targetIsInMonorepo
1230
+ ? "lastbrain"
1231
+ : "node node_modules/@lastbrain/app/dist/cli.js",
1073
1232
  "build:modules": `${scriptsPrefix} module:build`,
1074
1233
  "db:migrations:sync": `${scriptsPrefix} db:migrations:sync`,
1075
1234
  "db:init": `${scriptsPrefix} db:init`,
@@ -1085,26 +1244,36 @@ async function addScriptsToPackageJson(targetDir: string) {
1085
1244
  async function saveModulesConfig(
1086
1245
  targetDir: string,
1087
1246
  selectedModules: string[],
1088
- withAuth: boolean
1247
+ withAuth: boolean,
1089
1248
  ) {
1090
1249
  const modulesConfigPath = path.join(targetDir, ".lastbrain", "modules.json");
1091
1250
  await fs.ensureDir(path.dirname(modulesConfigPath));
1092
1251
 
1093
- const modules: Array<{ package: string; active: boolean; migrations?: string[] }> = [];
1252
+ const modules: Array<{
1253
+ package: string;
1254
+ active: boolean;
1255
+ migrations?: string[];
1256
+ }> = [];
1094
1257
 
1095
1258
  // Ajouter TOUS les modules disponibles
1096
1259
  for (const availableModule of AVAILABLE_MODULES) {
1097
- const isSelected = selectedModules.includes(availableModule.name) || (withAuth && availableModule.name === 'auth');
1098
-
1260
+ const isSelected =
1261
+ selectedModules.includes(availableModule.name) ||
1262
+ (withAuth && availableModule.name === "auth");
1263
+
1099
1264
  // Vérifier si le module a des migrations
1100
1265
  const modulePath = path.join(
1101
1266
  targetDir,
1102
1267
  "node_modules",
1103
- ...availableModule.package.split("/")
1268
+ ...availableModule.package.split("/"),
1104
1269
  );
1105
1270
  const migrationsDir = path.join(modulePath, "supabase", "migrations");
1106
-
1107
- const moduleConfig: { package: string; active: boolean; migrations?: string[] } = {
1271
+
1272
+ const moduleConfig: {
1273
+ package: string;
1274
+ active: boolean;
1275
+ migrations?: string[];
1276
+ } = {
1108
1277
  package: availableModule.package,
1109
1278
  active: isSelected,
1110
1279
  };
@@ -1113,7 +1282,7 @@ async function saveModulesConfig(
1113
1282
  const migrationFiles = fs
1114
1283
  .readdirSync(migrationsDir)
1115
1284
  .filter((f) => f.endsWith(".sql"));
1116
-
1285
+
1117
1286
  if (migrationFiles.length > 0) {
1118
1287
  moduleConfig.migrations = isSelected ? migrationFiles : [];
1119
1288
  }
@@ -1341,9 +1510,16 @@ export function isPrivateBucket(bucket: string): boolean {
1341
1510
  }
1342
1511
 
1343
1512
  // 3. Créer app/api/storage/[bucket]/[...path]/route.ts
1344
- const apiStorageDir = path.join(targetDir, "app", "api", "storage", "[bucket]", "[...path]");
1513
+ const apiStorageDir = path.join(
1514
+ targetDir,
1515
+ "app",
1516
+ "api",
1517
+ "storage",
1518
+ "[bucket]",
1519
+ "[...path]",
1520
+ );
1345
1521
  await fs.ensureDir(apiStorageDir);
1346
-
1522
+
1347
1523
  const routePath = path.join(apiStorageDir, "route.ts");
1348
1524
  if (!fs.existsSync(routePath) || force) {
1349
1525
  const routeContent = `import { NextRequest, NextResponse } from "next/server";
@@ -1466,7 +1642,9 @@ export async function GET(
1466
1642
  }`;
1467
1643
 
1468
1644
  await fs.writeFile(routePath, routeContent);
1469
- console.log(chalk.green("✓ app/api/storage/[bucket]/[...path]/route.ts créé"));
1645
+ console.log(
1646
+ chalk.green("✓ app/api/storage/[bucket]/[...path]/route.ts créé"),
1647
+ );
1470
1648
  }
1471
1649
 
1472
1650
  console.log(chalk.green("✓ Système de proxy storage configuré"));