@lastbrain/app 0.1.26 → 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.
@@ -229,7 +229,7 @@ async function main() {
229
229
  try {
230
230
  runSupabase("start");
231
231
  }
232
- catch (_error) {
232
+ catch {
233
233
  console.warn("⚠️ Supabase start had issues, continuing...");
234
234
  }
235
235
  console.log("🔄 Resetting database...");
@@ -50,13 +50,13 @@ function syncFile(src, dest) {
50
50
  fs.writeFileSync(dest, content);
51
51
  return dest;
52
52
  }
53
- function copyDirectory(srcDir, destDir) {
53
+ function _copyDirectory(srcDir, destDir) {
54
54
  const stats = fs.statSync(srcDir);
55
55
  if (stats.isDirectory()) {
56
56
  ensureDirectory(destDir);
57
57
  const entries = fs.readdirSync(srcDir, { withFileTypes: true });
58
58
  for (const entry of entries) {
59
- copyDirectory(path.join(srcDir, entry.name), path.join(destDir, entry.name));
59
+ _copyDirectory(path.join(srcDir, entry.name), path.join(destDir, entry.name));
60
60
  }
61
61
  }
62
62
  else if (stats.isFile()) {
@@ -1 +1 @@
1
- {"version":3,"file":"init-app.d.ts","sourceRoot":"","sources":["../../src/scripts/init-app.ts"],"names":[],"mappings":"AAWA,UAAU,cAAc;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,iBAgMpD"}
1
+ {"version":3,"file":"init-app.d.ts","sourceRoot":"","sources":["../../src/scripts/init-app.ts"],"names":[],"mappings":"AAWA,UAAU,cAAc;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,iBAwMpD"}
@@ -94,7 +94,7 @@ export async function initApp(options) {
94
94
  execSync("pnpm db:init", { cwd: targetDir, stdio: "inherit" });
95
95
  console.log(chalk.green("\n✓ Base de données initialisée\n"));
96
96
  }
97
- catch (dbError) {
97
+ catch {
98
98
  console.log(chalk.yellow("\n⚠️ Erreur d'initialisation de la DB (normal si Supabase pas configuré)\n"));
99
99
  }
100
100
  // Détecter le port (par défaut 3000 pour Next.js)
@@ -491,7 +491,7 @@ export default function AdminLayout({
491
491
  }`;
492
492
  }
493
493
  else if (routeName === "auth") {
494
- // Layout auth avec sidebar
494
+ // Layout auth avec sidebar
495
495
  layoutContent = `import { AuthLayoutWithSidebar } from "@lastbrain/app";
496
496
  import { menuConfig } from "../../config/menu";
497
497
 
@@ -1 +1 @@
1
- {"version":3,"file":"module-add.d.ts","sourceRoot":"","sources":["../../src/scripts/module-add.ts"],"names":[],"mappings":"AAMA,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAGD,eAAO,MAAM,iBAAiB,EAAE,gBAAgB,EAqB/C,CAAC;AAEF,wBAAsB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,iBAmOpE"}
1
+ {"version":3,"file":"module-add.d.ts","sourceRoot":"","sources":["../../src/scripts/module-add.ts"],"names":[],"mappings":"AAMA,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAGD,eAAO,MAAM,iBAAiB,EAAE,gBAAgB,EAqB/C,CAAC;AAEF,wBAAsB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,iBAuOpE"}
@@ -183,7 +183,7 @@ export async function addModule(moduleName, targetDir) {
183
183
  execSync("pnpm build:modules", { cwd: targetDir, stdio: "inherit" });
184
184
  console.log(chalk.green("✓ Routes du module générées"));
185
185
  }
186
- catch (error) {
186
+ catch {
187
187
  console.error(chalk.red("❌ Erreur lors de la génération des routes"));
188
188
  console.error(chalk.gray("Vous pouvez les générer manuellement avec: pnpm build:modules"));
189
189
  }
@@ -1 +1 @@
1
- {"version":3,"file":"module-build.d.ts","sourceRoot":"","sources":["../../src/scripts/module-build.ts"],"names":[],"mappings":"AA+vBA,wBAAsB,cAAc,kBAuCnC"}
1
+ {"version":3,"file":"module-build.d.ts","sourceRoot":"","sources":["../../src/scripts/module-build.ts"],"names":[],"mappings":"AA6wBA,wBAAsB,cAAc,kBA4CnC"}
@@ -115,13 +115,14 @@ function toPascalCase(value) {
115
115
  function buildPage(moduleConfig, page) {
116
116
  // Extraire le préfixe du module (ex: @lastbrain/module-auth -> auth)
117
117
  const modulePrefix = moduleConfig.moduleName
118
- .replace(/^@lastbrain\/module-/, '')
118
+ .replace(/^@lastbrain\/module-/, "")
119
119
  .toLowerCase();
120
120
  console.log(`🔄 Building page for module ${modulePrefix}: ${page.path}`);
121
- // Ajouter le préfixe du module au path pour les sections admin et auth,
121
+ // Ajouter le préfixe du module au path pour les sections admin et auth,
122
122
  // MAIS seulement quand la section ne correspond PAS au module lui-même
123
123
  let effectivePath = page.path;
124
- if (page.section === 'admin' || (page.section === 'auth' && modulePrefix !== 'auth')) {
124
+ if (page.section === "admin" ||
125
+ (page.section === "auth" && modulePrefix !== "auth")) {
125
126
  // Éviter les doublons si le préfixe est déjà présent
126
127
  if (!page.path.startsWith(`/${modulePrefix}/`)) {
127
128
  effectivePath = `/${modulePrefix}${page.path}`;
@@ -131,7 +132,7 @@ function buildPage(moduleConfig, page) {
131
132
  console.log(`✅ Module prefix already present: ${page.path}`);
132
133
  }
133
134
  }
134
- else if (page.section === 'auth' && modulePrefix === 'auth') {
135
+ else if (page.section === "auth" && modulePrefix === "auth") {
135
136
  console.log(`🏠 Auth module in auth section, no prefix needed: ${page.path}`);
136
137
  }
137
138
  const segments = effectivePath.replace(/^\/+/, "").split("/").filter(Boolean);
@@ -457,7 +458,7 @@ function cleanGeneratedFiles() {
457
458
  "middleware.ts",
458
459
  // Dossiers de lib et config
459
460
  "lib",
460
- "config"
461
+ "config",
461
462
  ]);
462
463
  // Fonction pour vérifier si un chemin est protégé
463
464
  const isProtected = (filePath) => {
@@ -467,7 +468,8 @@ function cleanGeneratedFiles() {
467
468
  return true;
468
469
  }
469
470
  // Protection par préfixe pour les dossiers
470
- return Array.from(protectedFiles).some(protectedPath => (protectedPath.endsWith('/') || ['lib', 'config', 'api/storage'].includes(protectedPath)) &&
471
+ return Array.from(protectedFiles).some((protectedPath) => (protectedPath.endsWith("/") ||
472
+ ["lib", "config", "api/storage"].includes(protectedPath)) &&
471
473
  relativePath.startsWith(protectedPath));
472
474
  };
473
475
  // Fonction pour nettoyer récursivement un dossier
@@ -488,24 +490,25 @@ function cleanGeneratedFiles() {
488
490
  console.log(`🗑️ Removed empty directory: ${itemPath}`);
489
491
  }
490
492
  }
491
- catch (e) {
492
- // Ignorer les erreurs de suppression de dossiers
493
+ catch {
494
+ // Ignorer les erreurs de suppression de fichiers
493
495
  }
494
496
  }
495
- else if (item.endsWith('.tsx') || item.endsWith('.ts')) {
497
+ else if (item.endsWith(".tsx") || item.endsWith(".ts")) {
496
498
  // Vérifier si c'est un fichier généré
497
499
  if (!isProtected(itemPath)) {
498
500
  try {
499
- const content = fs.readFileSync(itemPath, 'utf-8');
501
+ const content = fs.readFileSync(itemPath, "utf-8");
500
502
  // Supprimer les fichiers générés ou les wrapper simples de modules
501
503
  if (content.includes(generatedComment) ||
502
504
  content.includes('from "@lastbrain/module-') ||
503
- content.includes('export {') && content.includes('} from "@lastbrain/module-')) {
505
+ (content.includes("export {") &&
506
+ content.includes('} from "@lastbrain/module-'))) {
504
507
  fs.unlinkSync(itemPath);
505
508
  console.log(`🗑️ Cleaned generated file: ${itemPath}`);
506
509
  }
507
510
  }
508
- catch (e) {
511
+ catch {
509
512
  // Ignorer les erreurs de lecture/suppression
510
513
  }
511
514
  }
@@ -516,16 +519,16 @@ function cleanGeneratedFiles() {
516
519
  }
517
520
  };
518
521
  // Nettoyer les dossiers de sections
519
- const sectionsToClean = ['(public)', 'auth', 'admin', 'api'];
520
- sectionsToClean.forEach(section => {
522
+ const sectionsToClean = ["(public)", "auth", "admin", "api"];
523
+ sectionsToClean.forEach((section) => {
521
524
  const sectionPath = path.join(appDirectory, section);
522
525
  if (fs.existsSync(sectionPath)) {
523
526
  cleanDirectory(sectionPath);
524
527
  }
525
528
  });
526
529
  // Nettoyer les fichiers générés à la racine
527
- const rootFiles = ['navigation.generated.ts'];
528
- rootFiles.forEach(file => {
530
+ const rootFiles = ["navigation.generated.ts"];
531
+ rootFiles.forEach((file) => {
529
532
  const filePath = path.join(appDirectory, file);
530
533
  if (fs.existsSync(filePath)) {
531
534
  fs.unlinkSync(filePath);
@@ -193,7 +193,7 @@ export async function removeModule(moduleName, targetDir) {
193
193
  }
194
194
  console.log(chalk.green(` ✓ ${downFile}`));
195
195
  }
196
- catch (error) {
196
+ catch {
197
197
  console.error(chalk.red(` ❌ Erreur avec ${downFile}`));
198
198
  }
199
199
  }
@@ -213,7 +213,7 @@ export async function removeModule(moduleName, targetDir) {
213
213
  execSync("supabase db reset", { cwd: targetDir, stdio: "inherit" });
214
214
  console.log(chalk.green("✓ Base de données réinitialisée"));
215
215
  }
216
- catch (error) {
216
+ catch {
217
217
  console.error(chalk.red("❌ Erreur lors du reset"));
218
218
  }
219
219
  }
@@ -268,7 +268,7 @@ export async function removeModule(moduleName, targetDir) {
268
268
  fs.writeFileSync(modulesJsonPath, JSON.stringify(modulesConfig, null, 2));
269
269
  console.log(chalk.gray("\n✓ Module marqué comme inactif dans modules.json"));
270
270
  }
271
- catch (error) {
271
+ catch {
272
272
  console.error(chalk.red("❌ Erreur lors de la mise à jour de modules.json"));
273
273
  }
274
274
  }
@@ -277,7 +277,7 @@ export async function removeModule(moduleName, targetDir) {
277
277
  try {
278
278
  execSync("pnpm install", { cwd: targetDir, stdio: "inherit" });
279
279
  }
280
- catch (error) {
280
+ catch {
281
281
  console.error(chalk.red("❌ Erreur lors du nettoyage"));
282
282
  process.exit(1);
283
283
  }
@@ -288,7 +288,7 @@ export async function removeModule(moduleName, targetDir) {
288
288
  execSync("pnpm run build:modules", { cwd: targetDir, stdio: "inherit" });
289
289
  console.log(chalk.green("✓ Modules mis à jour"));
290
290
  }
291
- catch (error) {
291
+ catch {
292
292
  console.warn(chalk.yellow("⚠️ Erreur lors de la mise à jour des modules"));
293
293
  }
294
294
  console.log(chalk.gray("Le serveur de développement redémarrera automatiquement.\n"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lastbrain/app",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "description": "Framework modulaire Next.js avec CLI et système de modules",
5
5
  "private": false,
6
6
  "type": "module",
@@ -287,7 +287,7 @@ async function main() {
287
287
  console.log("⚙️ Starting Supabase...");
288
288
  try {
289
289
  runSupabase("start");
290
- } catch (_error) {
290
+ } catch {
291
291
  console.warn("⚠️ Supabase start had issues, continuing...");
292
292
  }
293
293
 
@@ -1,6 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import { fileURLToPath } from "node:url";
3
+ import { fileURLToPath as _fileURLToPath } from "node:url";
4
4
 
5
5
  import { getModuleConfigs } from "../modules/module-loader.js";
6
6
  import type { ModuleBuildConfig } from "@lastbrain/core";
@@ -66,13 +66,13 @@ function syncFile(src: string, dest: string) {
66
66
  return dest;
67
67
  }
68
68
 
69
- function copyDirectory(srcDir: string, destDir: string) {
69
+ function _copyDirectory(srcDir: string, destDir: string) {
70
70
  const stats = fs.statSync(srcDir);
71
71
  if (stats.isDirectory()) {
72
72
  ensureDirectory(destDir);
73
73
  const entries = fs.readdirSync(srcDir, { withFileTypes: true });
74
74
  for (const entry of entries) {
75
- copyDirectory(
75
+ _copyDirectory(
76
76
  path.join(srcDir, entry.name),
77
77
  path.join(destDir, entry.name),
78
78
  );
@@ -62,7 +62,11 @@ export async function initApp(options: InitAppOptions) {
62
62
  // En mode non-interactif, installer auth et ai par défaut
63
63
  selectedModules.push("auth", "ai");
64
64
  withAuth = true;
65
- console.log(chalk.blue("📦 Modules installés par défaut : Authentication, AI Generation\n"));
65
+ console.log(
66
+ chalk.blue(
67
+ "📦 Modules installés par défaut : Authentication, AI Generation\n",
68
+ ),
69
+ );
66
70
  }
67
71
 
68
72
  // Créer le dossier s'il n'existe pas
@@ -97,7 +101,7 @@ export async function initApp(options: InitAppOptions) {
97
101
  if (withAuth && !selectedModules.includes("auth")) {
98
102
  selectedModules.push("auth");
99
103
  }
100
-
104
+
101
105
  if (selectedModules.length > 0) {
102
106
  await saveModulesConfig(targetDir, selectedModules, withAuth);
103
107
  }
@@ -134,8 +138,12 @@ export async function initApp(options: InitAppOptions) {
134
138
  try {
135
139
  execSync("pnpm db:init", { cwd: targetDir, stdio: "inherit" });
136
140
  console.log(chalk.green("\n✓ Base de données initialisée\n"));
137
- } catch (dbError) {
138
- console.log(chalk.yellow("\n⚠️ Erreur d'initialisation de la DB (normal si Supabase pas configuré)\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
+ );
139
147
  }
140
148
 
141
149
  // Détecter le port (par défaut 3000 pour Next.js)
@@ -578,7 +586,7 @@ export default function NotFound() {
578
586
 
579
587
  // Créer le composant AppHeader
580
588
  await createAppHeader(targetDir, force);
581
-
589
+
582
590
  // Créer le composant AppAside
583
591
  await createAppAside(targetDir, force);
584
592
  }
@@ -596,7 +604,7 @@ async function createRoute(
596
604
  const layoutPath = path.join(routeDir, "layout.tsx");
597
605
  if (!fs.existsSync(layoutPath) || force) {
598
606
  let layoutContent = "";
599
-
607
+
600
608
  if (routeName === "admin") {
601
609
  // Layout admin avec sidebar
602
610
  layoutContent = `import { AdminLayoutWithSidebar } from "@lastbrain/app";
@@ -614,7 +622,7 @@ export default function AdminLayout({
614
622
  );
615
623
  }`;
616
624
  } else if (routeName === "auth") {
617
- // Layout auth avec sidebar
625
+ // Layout auth avec sidebar
618
626
  layoutContent = `import { AuthLayoutWithSidebar } from "@lastbrain/app";
619
627
  import { menuConfig } from "../../config/menu";
620
628
 
@@ -251,15 +251,19 @@ export async function addModule(moduleName: string, targetDir: string) {
251
251
  console.log(
252
252
  chalk.green(`\n✅ Module ${module.displayName} ajouté avec succès!\n`),
253
253
  );
254
-
254
+
255
255
  // 7. Générer automatiquement les routes du module
256
256
  console.log(chalk.yellow("🔧 Génération des routes du module..."));
257
257
  try {
258
258
  execSync("pnpm build:modules", { cwd: targetDir, stdio: "inherit" });
259
259
  console.log(chalk.green("✓ Routes du module générées"));
260
- } catch (error) {
260
+ } catch {
261
261
  console.error(chalk.red("❌ Erreur lors de la génération des routes"));
262
- console.error(chalk.gray("Vous pouvez les générer manuellement avec: pnpm build:modules"));
262
+ console.error(
263
+ chalk.gray(
264
+ "Vous pouvez les générer manuellement avec: pnpm build:modules",
265
+ ),
266
+ );
263
267
  }
264
268
 
265
269
  console.log(
@@ -153,15 +153,18 @@ function toPascalCase(value: string) {
153
153
  function buildPage(moduleConfig: ModuleBuildConfig, page: ModulePageConfig) {
154
154
  // Extraire le préfixe du module (ex: @lastbrain/module-auth -> auth)
155
155
  const modulePrefix = moduleConfig.moduleName
156
- .replace(/^@lastbrain\/module-/, '')
156
+ .replace(/^@lastbrain\/module-/, "")
157
157
  .toLowerCase();
158
-
158
+
159
159
  console.log(`🔄 Building page for module ${modulePrefix}: ${page.path}`);
160
-
161
- // Ajouter le préfixe du module au path pour les sections admin et auth,
160
+
161
+ // Ajouter le préfixe du module au path pour les sections admin et auth,
162
162
  // MAIS seulement quand la section ne correspond PAS au module lui-même
163
163
  let effectivePath = page.path;
164
- if (page.section === 'admin' || (page.section === 'auth' && modulePrefix !== 'auth')) {
164
+ if (
165
+ page.section === "admin" ||
166
+ (page.section === "auth" && modulePrefix !== "auth")
167
+ ) {
165
168
  // Éviter les doublons si le préfixe est déjà présent
166
169
  if (!page.path.startsWith(`/${modulePrefix}/`)) {
167
170
  effectivePath = `/${modulePrefix}${page.path}`;
@@ -169,10 +172,12 @@ function buildPage(moduleConfig: ModuleBuildConfig, page: ModulePageConfig) {
169
172
  } else {
170
173
  console.log(`✅ Module prefix already present: ${page.path}`);
171
174
  }
172
- } else if (page.section === 'auth' && modulePrefix === 'auth') {
173
- console.log(`🏠 Auth module in auth section, no prefix needed: ${page.path}`);
175
+ } else if (page.section === "auth" && modulePrefix === "auth") {
176
+ console.log(
177
+ `🏠 Auth module in auth section, no prefix needed: ${page.path}`,
178
+ );
174
179
  }
175
-
180
+
176
181
  const segments = effectivePath.replace(/^\/+/, "").split("/").filter(Boolean);
177
182
  const sectionPath = sectionDirectoryMap[page.section] ?? ["(public)"];
178
183
 
@@ -517,16 +522,20 @@ ${moduleConfigurations.join(",\n")}
517
522
  console.log(`📚 Generated docs page: ${docsPagePath}`);
518
523
  }
519
524
 
520
- function buildGroupedApi(apis: Array<{ moduleConfig: ModuleBuildConfig; api: ModuleApiConfig }>, routePath: string) {
525
+ function buildGroupedApi(
526
+ apis: Array<{ moduleConfig: ModuleBuildConfig; api: ModuleApiConfig }>,
527
+ routePath: string,
528
+ ) {
521
529
  const segments = routePath.replace(/^\/+/, "").split("/").filter(Boolean);
522
- const sanitizedSegments = segments[0] === "api" ? segments.slice(1) : segments;
530
+ const sanitizedSegments =
531
+ segments[0] === "api" ? segments.slice(1) : segments;
523
532
  const routeDir = path.join(appDirectory, "api", ...sanitizedSegments);
524
533
  const filePath = path.join(routeDir, "route.ts");
525
534
  ensureDirectory(routeDir);
526
535
 
527
536
  // Grouper par module/entryPoint pour créer les exports
528
537
  const exportsBySource = new Map<string, string[]>();
529
-
538
+
530
539
  apis.forEach(({ moduleConfig, api }) => {
531
540
  const handler = `${moduleConfig.moduleName}/${api.entryPoint}`;
532
541
  if (!exportsBySource.has(handler)) {
@@ -542,11 +551,11 @@ function buildGroupedApi(apis: Array<{ moduleConfig: ModuleBuildConfig; api: Mod
542
551
  });
543
552
 
544
553
  const content = exportStatements.join("\n") + "\n";
545
-
554
+
546
555
  // Ajouter le marqueur de génération au début
547
556
  const contentWithMarker = `// GENERATED BY LASTBRAIN MODULE BUILD
548
557
  ${content}`;
549
-
558
+
550
559
  fs.writeFileSync(filePath, contentWithMarker);
551
560
  console.log(`🔌 Generated API route: ${filePath}`);
552
561
  }
@@ -561,77 +570,82 @@ function getModuleDescription(moduleConfig: ModuleBuildConfig): string {
561
570
 
562
571
  function cleanGeneratedFiles() {
563
572
  const generatedComment = "// GENERATED BY LASTBRAIN MODULE BUILD";
564
-
573
+
565
574
  // Fichiers de base à préserver (paths relatifs exacts)
566
575
  const protectedFiles = new Set([
567
576
  // API de base
568
577
  "api/storage",
569
578
  // Layouts de base
570
579
  "layout.tsx",
571
- "not-found.tsx",
572
- "page.tsx", // Page racine seulement
573
- "admin/page.tsx", // Page admin racine
574
- "admin/layout.tsx", // Layout admin racine
575
- "docs/page.tsx", // Page docs générée
580
+ "not-found.tsx",
581
+ "page.tsx", // Page racine seulement
582
+ "admin/page.tsx", // Page admin racine
583
+ "admin/layout.tsx", // Layout admin racine
584
+ "docs/page.tsx", // Page docs générée
576
585
  // Middleware et autres fichiers core
577
586
  "middleware.ts",
578
587
  // Dossiers de lib et config
579
588
  "lib",
580
- "config"
589
+ "config",
581
590
  ]);
582
591
 
583
592
  // Fonction pour vérifier si un chemin est protégé
584
593
  const isProtected = (filePath: string) => {
585
594
  const relativePath = path.relative(appDirectory, filePath);
586
-
595
+
587
596
  // Protection exacte pour certains fichiers
588
597
  if (protectedFiles.has(relativePath)) {
589
598
  return true;
590
599
  }
591
-
600
+
592
601
  // Protection par préfixe pour les dossiers
593
- return Array.from(protectedFiles).some(protectedPath =>
594
- (protectedPath.endsWith('/') || ['lib', 'config', 'api/storage'].includes(protectedPath)) &&
595
- relativePath.startsWith(protectedPath)
602
+ return Array.from(protectedFiles).some(
603
+ (protectedPath) =>
604
+ (protectedPath.endsWith("/") ||
605
+ ["lib", "config", "api/storage"].includes(protectedPath)) &&
606
+ relativePath.startsWith(protectedPath),
596
607
  );
597
608
  };
598
609
 
599
610
  // Fonction pour nettoyer récursivement un dossier
600
611
  const cleanDirectory = (dirPath: string) => {
601
612
  if (!fs.existsSync(dirPath)) return;
602
-
613
+
603
614
  const items = fs.readdirSync(dirPath);
604
-
615
+
605
616
  for (const item of items) {
606
617
  const itemPath = path.join(dirPath, item);
607
618
  const stat = fs.statSync(itemPath);
608
-
619
+
609
620
  if (stat.isDirectory()) {
610
621
  // Nettoyer récursivement le sous-dossier
611
622
  cleanDirectory(itemPath);
612
-
623
+
613
624
  // Supprimer le dossier s'il est vide et non protégé
614
625
  try {
615
626
  if (!isProtected(itemPath) && fs.readdirSync(itemPath).length === 0) {
616
627
  fs.rmdirSync(itemPath);
617
628
  console.log(`🗑️ Removed empty directory: ${itemPath}`);
618
629
  }
619
- } catch (e) {
620
- // Ignorer les erreurs de suppression de dossiers
630
+ } catch {
631
+ // Ignorer les erreurs de suppression de fichiers
621
632
  }
622
- } else if (item.endsWith('.tsx') || item.endsWith('.ts')) {
633
+ } else if (item.endsWith(".tsx") || item.endsWith(".ts")) {
623
634
  // Vérifier si c'est un fichier généré
624
635
  if (!isProtected(itemPath)) {
625
636
  try {
626
- const content = fs.readFileSync(itemPath, 'utf-8');
637
+ const content = fs.readFileSync(itemPath, "utf-8");
627
638
  // Supprimer les fichiers générés ou les wrapper simples de modules
628
- if (content.includes(generatedComment) ||
629
- content.includes('from "@lastbrain/module-') ||
630
- content.includes('export {') && content.includes('} from "@lastbrain/module-')) {
639
+ if (
640
+ content.includes(generatedComment) ||
641
+ content.includes('from "@lastbrain/module-') ||
642
+ (content.includes("export {") &&
643
+ content.includes('} from "@lastbrain/module-'))
644
+ ) {
631
645
  fs.unlinkSync(itemPath);
632
646
  console.log(`🗑️ Cleaned generated file: ${itemPath}`);
633
647
  }
634
- } catch (e) {
648
+ } catch {
635
649
  // Ignorer les erreurs de lecture/suppression
636
650
  }
637
651
  } else {
@@ -642,8 +656,8 @@ function cleanGeneratedFiles() {
642
656
  };
643
657
 
644
658
  // Nettoyer les dossiers de sections
645
- const sectionsToClean = ['(public)', 'auth', 'admin', 'api'];
646
- sectionsToClean.forEach(section => {
659
+ const sectionsToClean = ["(public)", "auth", "admin", "api"];
660
+ sectionsToClean.forEach((section) => {
647
661
  const sectionPath = path.join(appDirectory, section);
648
662
  if (fs.existsSync(sectionPath)) {
649
663
  cleanDirectory(sectionPath);
@@ -651,8 +665,8 @@ function cleanGeneratedFiles() {
651
665
  });
652
666
 
653
667
  // Nettoyer les fichiers générés à la racine
654
- const rootFiles = ['navigation.generated.ts'];
655
- rootFiles.forEach(file => {
668
+ const rootFiles = ["navigation.generated.ts"];
669
+ rootFiles.forEach((file) => {
656
670
  const filePath = path.join(appDirectory, file);
657
671
  if (fs.existsSync(filePath)) {
658
672
  fs.unlinkSync(filePath);
@@ -665,7 +679,7 @@ function cleanGeneratedFiles() {
665
679
 
666
680
  function generateAppAside() {
667
681
  const targetPath = path.join(appDirectory, "components", "AppAside.tsx");
668
-
682
+
669
683
  // Ne pas écraser si le fichier existe déjà
670
684
  if (fs.existsSync(targetPath)) {
671
685
  console.log(`⏭️ AppAside already exists, skipping: ${targetPath}`);
@@ -774,16 +788,21 @@ export async function runModuleBuild() {
774
788
 
775
789
  const moduleConfigs = await loadModuleConfigs();
776
790
  console.log(`🔍 Loaded ${moduleConfigs.length} module configurations`);
777
-
791
+
778
792
  // Générer les pages
779
793
  moduleConfigs.forEach((moduleConfig) => {
780
- console.log(`📦 Processing module: ${moduleConfig.moduleName} with ${moduleConfig.pages.length} pages`);
794
+ console.log(
795
+ `📦 Processing module: ${moduleConfig.moduleName} with ${moduleConfig.pages.length} pages`,
796
+ );
781
797
  moduleConfig.pages.forEach((page) => buildPage(moduleConfig, page));
782
798
  });
783
799
 
784
800
  // Grouper les APIs par chemin pour éviter les écrasements de fichier
785
- const apisByPath = new Map<string, Array<{ moduleConfig: ModuleBuildConfig; api: ModuleApiConfig }>>();
786
-
801
+ const apisByPath = new Map<
802
+ string,
803
+ Array<{ moduleConfig: ModuleBuildConfig; api: ModuleApiConfig }>
804
+ >();
805
+
787
806
  moduleConfigs.forEach((moduleConfig) => {
788
807
  moduleConfig.apis.forEach((api) => {
789
808
  if (!apisByPath.has(api.path)) {
@@ -293,7 +293,7 @@ export async function removeModule(moduleName: string, targetDir: string) {
293
293
  }
294
294
 
295
295
  console.log(chalk.green(` ✓ ${downFile}`));
296
- } catch (error) {
296
+ } catch {
297
297
  console.error(chalk.red(` ❌ Erreur avec ${downFile}`));
298
298
  }
299
299
  }
@@ -315,7 +315,7 @@ export async function removeModule(moduleName: string, targetDir: string) {
315
315
  try {
316
316
  execSync("supabase db reset", { cwd: targetDir, stdio: "inherit" });
317
317
  console.log(chalk.green("✓ Base de données réinitialisée"));
318
- } catch (error) {
318
+ } catch {
319
319
  console.error(chalk.red("❌ Erreur lors du reset"));
320
320
  }
321
321
  } else {
@@ -391,7 +391,7 @@ export async function removeModule(moduleName: string, targetDir: string) {
391
391
  console.log(
392
392
  chalk.gray("\n✓ Module marqué comme inactif dans modules.json"),
393
393
  );
394
- } catch (error) {
394
+ } catch {
395
395
  console.error(
396
396
  chalk.red("❌ Erreur lors de la mise à jour de modules.json"),
397
397
  );
@@ -402,7 +402,7 @@ export async function removeModule(moduleName: string, targetDir: string) {
402
402
  console.log(chalk.yellow("\n🧹 Nettoyage des dépendances..."));
403
403
  try {
404
404
  execSync("pnpm install", { cwd: targetDir, stdio: "inherit" });
405
- } catch (error) {
405
+ } catch {
406
406
  console.error(chalk.red("❌ Erreur lors du nettoyage"));
407
407
  process.exit(1);
408
408
  }
@@ -416,7 +416,7 @@ export async function removeModule(moduleName: string, targetDir: string) {
416
416
  try {
417
417
  execSync("pnpm run build:modules", { cwd: targetDir, stdio: "inherit" });
418
418
  console.log(chalk.green("✓ Modules mis à jour"));
419
- } catch (error) {
419
+ } catch {
420
420
  console.warn(chalk.yellow("⚠️ Erreur lors de la mise à jour des modules"));
421
421
  }
422
422