@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.
@@ -5,6 +5,7 @@ interface InitAppOptions {
5
5
  useHeroUI: boolean;
6
6
  withAuth?: boolean;
7
7
  interactive?: boolean;
8
+ isMonorepoProject?: boolean;
8
9
  }
9
10
  export declare function initApp(options: InitAppOptions): Promise<void>;
10
11
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"init-app.d.ts","sourceRoot":"","sources":["../../src/scripts/init-app.ts"],"names":[],"mappings":"AAcA,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,iBA0NpD"}
1
+ {"version":3,"file":"init-app.d.ts","sourceRoot":"","sources":["../../src/scripts/init-app.ts"],"names":[],"mappings":"AAcA,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;IACtB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,iBA+QpD"}
@@ -9,7 +9,7 @@ const __filename = fileURLToPath(import.meta.url);
9
9
  const __dirname = path.dirname(__filename);
10
10
  export async function initApp(options) {
11
11
  const { targetDir, force, projectName, useHeroUI, interactive = true, } = options;
12
- let { withAuth = false } = options;
12
+ let { withAuth = false, isMonorepoProject = false } = options;
13
13
  console.log(chalk.blue("\n🚀 LastBrain App Init\n"));
14
14
  console.log(chalk.gray(`📁 Dossier cible: ${targetDir}`));
15
15
  if (useHeroUI) {
@@ -33,15 +33,41 @@ export async function initApp(options) {
33
33
  checked: false,
34
34
  })),
35
35
  },
36
+ {
37
+ type: "rawlist",
38
+ name: "projectType",
39
+ message: "Type de projet ?",
40
+ choices: [
41
+ {
42
+ name: "📦 Indépendant (créer une nouvelle BDD Supabase)",
43
+ value: "independent",
44
+ },
45
+ {
46
+ name: "🏢 Monorepo (utiliser la BDD existante)",
47
+ value: "monorepo",
48
+ },
49
+ ],
50
+ default: "independent",
51
+ },
36
52
  ]);
37
53
  selectedModules.push(...answers.modules);
38
54
  withAuth = selectedModules.includes("auth");
55
+ isMonorepoProject = answers.projectType === "monorepo";
56
+ if (isMonorepoProject) {
57
+ console.log(chalk.cyan("\n💡 Mode monorepo activé:"), chalk.gray("Votre app utilisera la base de données centralisée du monorepo."));
58
+ console.log(chalk.gray(" Aucune configuration Supabase locale ne sera créée.\n"));
59
+ }
60
+ else {
61
+ console.log(chalk.cyan("\n💡 Mode projet indépendant activé:"), chalk.gray("Votre app aura sa propre instance Supabase locale."));
62
+ console.log(chalk.gray(" Configuration complète sera créée.\n"));
63
+ }
39
64
  console.log();
40
65
  }
41
66
  else if (!interactive) {
42
67
  // En mode non-interactif, installer auth et ai par défaut
43
68
  selectedModules.push("auth", "ai");
44
69
  withAuth = true;
70
+ isMonorepoProject = false;
45
71
  console.log(chalk.blue("📦 Modules installés par défaut : Authentication, AI Generation\n"));
46
72
  }
47
73
  // Créer le dossier s'il n'existe pas
@@ -59,9 +85,16 @@ export async function initApp(options) {
59
85
  // 6. Créer .gitignore et .env.local.example
60
86
  await createGitIgnore(targetDir, force);
61
87
  await createEnvExample(targetDir, force);
62
- await createEnvLocal(targetDir, force);
63
- // 7. Créer la structure Supabase avec migrations
64
- await createSupabaseStructure(targetDir, force);
88
+ await createEnvLocal(targetDir, force, isMonorepoProject);
89
+ await createEnvProd(targetDir, force);
90
+ // 7. Créer la structure Supabase avec migrations (seulement pour projets indépendants)
91
+ if (!isMonorepoProject) {
92
+ console.log(chalk.blue("🗄️ Création de la structure Supabase locale...\n"));
93
+ await createSupabaseStructure(targetDir, force);
94
+ }
95
+ else {
96
+ console.log(chalk.yellow("⏭️ Projet monorepo détecté - pas de configuration Supabase locale requise\n"));
97
+ }
65
98
  // 8. Ajouter les scripts NPM
66
99
  await addScriptsToPackageJson(targetDir);
67
100
  // 9. Enregistrer les modules sélectionnés
@@ -145,7 +178,7 @@ export async function initApp(options) {
145
178
  console.log(chalk.white(" pnpm build:modules"));
146
179
  console.log(chalk.white(" pnpm db:migrations:sync"));
147
180
  console.log(chalk.white(" pnpm db:init"));
148
- console.log(chalk.white(" pnpm dev\n"));
181
+ console.log(chalk.white(" pnpm dev:local (ou pnpm dev:prod)\n"));
149
182
  }
150
183
  }
151
184
  else {
@@ -155,7 +188,11 @@ export async function initApp(options) {
155
188
  console.log(chalk.white(" 3. pnpm build:modules (générer les routes des modules)"));
156
189
  console.log(chalk.white(" 4. pnpm db:migrations:sync (synchroniser les migrations)"));
157
190
  console.log(chalk.white(" 5. pnpm db:init (initialiser la base de données)"));
158
- console.log(chalk.white(" 6. pnpm dev (lancer le serveur)\n"));
191
+ console.log(chalk.white(" 6. pnpm dev:local (ou pnpm dev:prod)\n"));
192
+ console.log(chalk.cyan("\n💡 Scripts disponibles:"));
193
+ console.log(chalk.white(" • pnpm dev:local - Lance avec .env.local"));
194
+ console.log(chalk.white(" • pnpm dev:prod - Lance avec .env.prod"));
195
+ console.log(chalk.white(" • pnpm dev - Lance avec .env actuel\n"));
159
196
  console.log(chalk.gray("Prérequis pour Supabase :"));
160
197
  console.log(chalk.white(" - Docker Desktop installé et lancé"));
161
198
  console.log(chalk.white(" - Supabase CLI : brew install supabase/tap/supabase\n"));
@@ -343,6 +380,7 @@ async function addDependencies(targetDir, useHeroUI, withAuth, selectedModules =
343
380
  requiredDeps["lucide-react"] = "^0.554.0";
344
381
  requiredDeps["framer-motion"] = "^11.18.2";
345
382
  requiredDeps["clsx"] = "^2.1.1";
383
+ requiredDeps["env-cmd"] = "^11.0.0";
346
384
  }
347
385
  // DevDependencies
348
386
  const requiredDevDeps = {
@@ -613,9 +651,8 @@ export default function AuthLayout({
613
651
  else {
614
652
  // Layout standard pour les autres routes (ex: docs = public)
615
653
  const layoutComponent = layoutType.charAt(0).toUpperCase() + layoutType.slice(1) + "Layout";
616
- if (routeName === "docs") {
617
- // Layout docs avec footer
618
- layoutContent = `import { ${layoutComponent} } from "@lastbrain/app";
654
+ // Layout docs avec footer
655
+ layoutContent = `import { ${layoutComponent} } from "@lastbrain/app";
619
656
  import { footerConfig } from "../../config/footer";
620
657
 
621
658
  export default function DocsLayout({
@@ -625,12 +662,6 @@ export default function DocsLayout({
625
662
  }) {
626
663
  return <${layoutComponent} footerConfig={footerConfig}>{children}</${layoutComponent}>;
627
664
  }`;
628
- }
629
- else {
630
- layoutContent = `import { ${layoutComponent} } from "@lastbrain/app";
631
-
632
- export default ${layoutComponent};`;
633
- }
634
665
  }
635
666
  await fs.writeFile(layoutPath, layoutContent);
636
667
  console.log(chalk.green(`✓ app/${routeName}/layout.tsx créé`));
@@ -714,6 +745,7 @@ export function AppHeader() {
714
745
  user={user}
715
746
  onLogout={handleLogout}
716
747
  menuConfig={menuConfig}
748
+ accountMenu={menuConfig.account}
717
749
  brandName="LastBrain App"
718
750
  brandHref="/"
719
751
  isSuperAdmin={isSuperAdmin}
@@ -815,6 +847,11 @@ export async function middleware(request: NextRequest) {
815
847
  "/callback",
816
848
  ];
817
849
 
850
+ if(process.env.MAINTENANCE_MODE === "true" && !pathname.startsWith("/maintenance")) {
851
+ const redirectUrl = new URL("/maintenance", request.url);
852
+ return NextResponse.redirect(redirectUrl);
853
+ }
854
+
818
855
  const isPublicAuthPage = publicAuthPages.some((page) =>
819
856
  pathname.startsWith(page)
820
857
  );
@@ -1255,16 +1292,7 @@ tmp/
1255
1292
  coverage/
1256
1293
  *.lcov
1257
1294
 
1258
- # Generated by module-build
1259
- app/navigation.generated.ts
1260
- app/routes.generated.ts
1261
- app/menu.generated.ts
1262
1295
 
1263
- # Generated app-shell overrides
1264
- app/(public)/
1265
- app/(auth)/
1266
- app/(admin)/
1267
- app/layout.tsx
1268
1296
  `;
1269
1297
  await fs.writeFile(gitignorePath, gitignoreContent);
1270
1298
  }
@@ -1292,11 +1320,25 @@ SUPABASE_SERVICE_ROLE_KEY=YOUR_LOCAL_SERVICE_ROLE_KEY
1292
1320
  console.log(chalk.green("✓ .env.local.example créé"));
1293
1321
  }
1294
1322
  }
1295
- async function createEnvLocal(targetDir, force) {
1323
+ async function createEnvLocal(targetDir, force, isMonorepoProject = false) {
1296
1324
  const envLocalPath = path.join(targetDir, ".env.local");
1297
1325
  if (!fs.existsSync(envLocalPath) || force) {
1298
1326
  console.log(chalk.yellow("\n🔐 Création de .env.local..."));
1299
- const envContent = `# Supabase Configuration
1327
+ let envContent;
1328
+ if (isMonorepoProject) {
1329
+ // Pour les projets monorepo, utiliser les variables du monorepo
1330
+ envContent = `# Supabase Configuration (Monorepo - Centralisé)
1331
+ # Les variables Supabase sont gérées au niveau du monorepo
1332
+
1333
+ # OpenAI Configuration (clé factice pour éviter les erreurs de build)
1334
+ OPENAI_API_KEY=sk-fake-openai-key-for-development-replace-with-real-key
1335
+
1336
+ # Note: Les variables Supabase sont fournies par le monorepo parent
1337
+ `;
1338
+ }
1339
+ else {
1340
+ // Pour les projets indépendants
1341
+ envContent = `# Supabase Configuration
1300
1342
  # Valeurs par défaut pour le développement local
1301
1343
 
1302
1344
  # Supabase Local (par défaut)
@@ -1307,10 +1349,32 @@ SUPABASE_SERVICE_ROLE_KEY=eyJhbGc...
1307
1349
  # OpenAI Configuration (clé factice pour éviter les erreurs de build)
1308
1350
  OPENAI_API_KEY=sk-fake-openai-key-for-development-replace-with-real-key
1309
1351
  `;
1352
+ }
1310
1353
  await fs.writeFile(envLocalPath, envContent);
1311
1354
  console.log(chalk.green("✓ .env.local créé"));
1312
1355
  }
1313
1356
  }
1357
+ async function createEnvProd(targetDir, force) {
1358
+ const envProdPath = path.join(targetDir, ".env.prod");
1359
+ if (!fs.existsSync(envProdPath) || force) {
1360
+ console.log(chalk.yellow("\n🔐 Création de .env.prod..."));
1361
+ const envContent = `# Production Environment Configuration
1362
+ # Copy your production values here
1363
+
1364
+ # Supabase Production
1365
+ NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
1366
+ NEXT_PUBLIC_SUPABASE_ANON_KEY=your-prod-anon-key
1367
+ SUPABASE_SERVICE_ROLE_KEY=your-prod-service-role-key
1368
+
1369
+ # OpenAI Production
1370
+ OPENAI_API_KEY=sk-proj-your-prod-api-key
1371
+
1372
+ # Note: Update these values with your actual production credentials
1373
+ `;
1374
+ await fs.writeFile(envProdPath, envContent);
1375
+ console.log(chalk.green("✓ .env.prod créé"));
1376
+ }
1377
+ }
1314
1378
  async function createSupabaseStructure(targetDir, force) {
1315
1379
  console.log(chalk.yellow("\n🗄️ Création de la structure Supabase..."));
1316
1380
  const supabaseDir = path.join(targetDir, "supabase");
@@ -1356,6 +1420,8 @@ async function addScriptsToPackageJson(targetDir) {
1356
1420
  ? "pnpm --filter @lastbrain/core build && pnpm --filter @lastbrain/ui build && pnpm --filter @lastbrain/module-auth build && pnpm --filter @lastbrain/module-ai build"
1357
1421
  : "echo 'No prebuild needed outside monorepo'",
1358
1422
  dev: "next dev",
1423
+ "dev:local": "env-cmd -f .env.local next dev",
1424
+ "dev:prod": "env-cmd -f .env.prod next dev",
1359
1425
  build: "next build",
1360
1426
  start: "next start",
1361
1427
  lint: "next lint",
@@ -1 +1 @@
1
- {"version":3,"file":"module-build.d.ts","sourceRoot":"","sources":["../../src/scripts/module-build.ts"],"names":[],"mappings":"AA24CA,wBAAsB,cAAc,kBA+FnC"}
1
+ {"version":3,"file":"module-build.d.ts","sourceRoot":"","sources":["../../src/scripts/module-build.ts"],"names":[],"mappings":"AAy4CA,wBAAsB,cAAc,kBA+FnC"}
@@ -1 +1 @@
1
- {"version":3,"file":"module-create.d.ts","sourceRoot":"","sources":["../../src/scripts/module-create.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,CAAC,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAwwCD;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAiB1C;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,iBAoLhB;AAED;;GAEG;AACH,wBAAsB,YAAY,kBAsLjC"}
1
+ {"version":3,"file":"module-create.d.ts","sourceRoot":"","sources":["../../src/scripts/module-create.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,CAAC,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAswCD;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAiB1C;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,iBAoLhB;AAED;;GAEG;AACH,wBAAsB,YAAY,kBAsLjC"}
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultDoc.d.ts","sourceRoot":"","sources":["../../src/templates/DefaultDoc.tsx"],"names":[],"mappings":"AAoBA,wBAAgB,oBAAoB,4CAsoDnC"}
1
+ {"version":3,"file":"DefaultDoc.d.ts","sourceRoot":"","sources":["../../src/templates/DefaultDoc.tsx"],"names":[],"mappings":"AAoBA,wBAAgB,oBAAoB,4CAkqDnC"}
@@ -35,7 +35,7 @@ const proxyUrl = await uploadFile(
35
35
  "avatar",
36
36
  "user_128_123456.webp",
37
37
  file,
38
- "image/webp",
38
+ "image/webp"
39
39
  );
40
40
  // Retourne: "/api/storage/avatar/user_128_123456.webp"
41
41
 
@@ -236,5 +236,5 @@ export function DocUsageCustom() {
236
236
  <p>Description...</p>
237
237
  </div>
238
238
  );
239
- }` }) }), _jsx("h3", { className: "text-lg font-semibold mb-2", children: "Exporter la documentation" }), _jsxs("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-2", children: ["Dans", " ", _jsx("code", { className: "text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded", children: "src/index.ts" }), " ", ":"] }), _jsx(Alert, { hideIcon: true, color: "primary", className: "p-4 mb-4", children: _jsx("pre", { className: "whitespace-pre-wrap", children: `export { MonModuleDoc } from "./components/Doc.js";` }) })] })] }), _jsxs(Card, { id: "section-links", className: "scroll-mt-32", children: [_jsx(CardHeader, { children: _jsxs("h2", { className: "text-2xl font-semibold flex items-center gap-2", children: [_jsx(Link, { size: 24 }), "Liens utiles & remerciements \uD83D\uDE4F"] }) }), _jsx(CardBody, { children: _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: [_jsx(Card, { className: "hover:shadow-lg transition-shadow", isPressable: true, as: "a", href: "https://nextjs.org/docs", target: "_blank", rel: "noopener noreferrer", children: _jsxs(CardBody, { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Next.js" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-3", children: "Documentation officielle" }), _jsx("p", { className: "text-xs text-blue-600 dark:text-blue-400 truncate", children: "https://nextjs.org/docs" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow", isPressable: true, as: "a", href: "https://supabase.com/docs", target: "_blank", rel: "noopener noreferrer", children: _jsxs(CardBody, { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Supabase" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-3", children: "Documentation officielle" }), _jsx("p", { className: "text-xs text-blue-600 dark:text-blue-400 truncate", children: "https://supabase.com/docs" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow", isPressable: true, as: "a", href: "https://www.heroui.com/docs", target: "_blank", rel: "noopener noreferrer", children: _jsxs(CardBody, { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Heroui" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-3", children: "Composants UI" }), _jsx("p", { className: "text-xs text-blue-600 dark:text-blue-400 truncate", children: "https://www.heroui.com/docs" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow", isPressable: true, as: "a", href: "https://tailwindcss.com/docs", target: "_blank", rel: "noopener noreferrer", children: _jsxs(CardBody, { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Tailwind CSS" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-3", children: "Framework CSS" }), _jsx("p", { className: "text-xs text-blue-600 dark:text-blue-400 truncate", children: "https://tailwindcss.com/docs" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow", isPressable: true, as: "a", href: "https://lucide.dev/", target: "_blank", rel: "noopener noreferrer", children: _jsxs(CardBody, { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Lucide Icons" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-3", children: "Icones SVG" }), _jsx("p", { className: "text-xs text-blue-600 dark:text-blue-400 truncate", children: "https://lucide.dev/" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow", isPressable: true, as: "a", href: "https://stripe.com/docs", target: "_blank", rel: "noopener noreferrer", children: _jsxs(CardBody, { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Stripe" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-3", children: "Syst\u00E8me de paiement" }), _jsx("p", { className: "text-xs text-blue-600 dark:text-blue-400 truncate", children: "https://stripe.com/docs" })] }) })] }) })] }), _jsxs(Card, { id: "section-modules", className: "scroll-mt-32", children: [_jsx(CardHeader, { children: _jsxs("h2", { className: "text-2xl font-semibold flex items-center gap-2", children: [_jsx(Package, { size: 24 }), "Modules"] }) }), _jsxs(CardBody, { className: "space-y-6", children: [_jsx("p", { className: "text-slate-600 dark:text-slate-400", children: "Les modules LastBrain permettent d'ajouter des fonctionnalit\u00E9s compl\u00E8tes \u00E0 votre application de mani\u00E8re modulaire." }), _jsxs("div", { children: [_jsx("h3", { className: "text-xl font-semibold mb-4", children: "Modules Disponibles" }), _jsxs("div", { className: "grid grid-cols-1 gap-4", children: [_jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-blue-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Ai" }), _jsx("span", { className: "text-xs bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 px-2 py-1 rounded", children: "FREE" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 1 auth, 1 admin"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module ai` }), _jsx("a", { href: "https://github.com/Lastbrain-labs/lb-starter/tree/main/packages/module-ai", className: "text-sm text-blue-600 dark:text-blue-400 hover:underline inline-flex items-center gap-1", target: "_blank", rel: "noopener noreferrer", children: "\uD83D\uDCD6 Documentation \u2192" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-blue-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Auth" }), _jsx("span", { className: "text-xs bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 px-2 py-1 rounded", children: "FREE" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 3 publique(s), 4 auth, 2 admin"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module auth` }), _jsx("a", { href: "https://github.com/Lastbrain-labs/lb-starter/tree/main/packages/module-auth", className: "text-sm text-blue-600 dark:text-blue-400 hover:underline inline-flex items-center gap-1", target: "_blank", rel: "noopener noreferrer", children: "\uD83D\uDCD6 Documentation \u2192" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-purple-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Billing Pro" }), _jsx("span", { className: "text-xs bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200 px-2 py-1 rounded", children: "PRO" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 3 auth, 2 admin"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module billing-pro` }), _jsx("span", { className: "text-xs text-slate-500 dark:text-slate-400 inline-flex items-center gap-1", children: "\uD83D\uDD12 Documentation priv\u00E9e" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-purple-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Core Cart Pro" }), _jsx("span", { className: "text-xs bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200 px-2 py-1 rounded", children: "PRO" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 2 auth, 1 admin"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module core-cart-pro` }), _jsx("span", { className: "text-xs text-slate-500 dark:text-slate-400 inline-flex items-center gap-1", children: "\uD83D\uDD12 Documentation priv\u00E9e" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-purple-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Core Commerce Pro" }), _jsx("span", { className: "text-xs bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200 px-2 py-1 rounded", children: "PRO" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module core-commerce-pro` }), _jsx("span", { className: "text-xs text-slate-500 dark:text-slate-400 inline-flex items-center gap-1", children: "\uD83D\uDD12 Documentation priv\u00E9e" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-purple-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Core Order Pro" }), _jsx("span", { className: "text-xs bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200 px-2 py-1 rounded", children: "PRO" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 2 auth"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module core-order-pro` }), _jsx("span", { className: "text-xs text-slate-500 dark:text-slate-400 inline-flex items-center gap-1", children: "\uD83D\uDD12 Documentation priv\u00E9e" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-purple-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Core Payment Pro" }), _jsx("span", { className: "text-xs bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200 px-2 py-1 rounded", children: "PRO" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 1 admin"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module core-payment-pro` }), _jsx("span", { className: "text-xs text-slate-500 dark:text-slate-400 inline-flex items-center gap-1", children: "\uD83D\uDD12 Documentation priv\u00E9e" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-purple-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Core Product Pro" }), _jsx("span", { className: "text-xs bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200 px-2 py-1 rounded", children: "PRO" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 2 publique(s)"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module core-product-pro` }), _jsx("span", { className: "text-xs text-slate-500 dark:text-slate-400 inline-flex items-center gap-1", children: "\uD83D\uDD12 Documentation priv\u00E9e" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-blue-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Legal" }), _jsx("span", { className: "text-xs bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 px-2 py-1 rounded", children: "FREE" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 4 publique(s), 2 admin"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module legal` }), _jsx("a", { href: "https://github.com/Lastbrain-labs/lb-starter/tree/main/packages/module-legal", className: "text-sm text-blue-600 dark:text-blue-400 hover:underline inline-flex items-center gap-1", target: "_blank", rel: "noopener noreferrer", children: "\uD83D\uDCD6 Documentation \u2192" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-purple-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Recipes Pro" }), _jsx("span", { className: "text-xs bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200 px-2 py-1 rounded", children: "PRO" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 4 auth"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module recipes-pro` }), _jsx("span", { className: "text-xs text-slate-500 dark:text-slate-400 inline-flex items-center gap-1", children: "\uD83D\uDD12 Documentation priv\u00E9e" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-blue-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Tasks" }), _jsx("span", { className: "text-xs bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 px-2 py-1 rounded", children: "FREE" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 2 auth, 1 admin"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module nom-du-module` }), _jsx("a", { href: "https://github.com/Lastbrain-labs/lb-starter/tree/main/packages/module-tasks", className: "text-sm text-blue-600 dark:text-blue-400 hover:underline inline-flex items-center gap-1", target: "_blank", rel: "noopener noreferrer", children: "\uD83D\uDCD6 Documentation \u2192" })] }) })] })] }), _jsx("h3", { className: "text-lg font-semibold mb-2", children: "Commandes" }), _jsx("h4", { className: "font-medium mb-2", children: "Installer un module" }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: `pnpm lastbrain add-module nom-du-module` }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: `pnpm build:modules` }), _jsx("h4", { className: "font-medium mb-2", children: "Cr\u00E9er un nouveau module" }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: `pnpm lastbrain create-module nom-du-module` }), _jsx("h4", { className: "font-medium mb-2", children: "G\u00E9n\u00E9rer la documentation des modules" }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: `pnpm generate:module-docs` }), _jsx("h4", { className: "font-medium mb-2", children: "Supprimer un module" }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: `pnpm lastbrain remove-module nom-du-module` }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: `pnpm build:modules` }), _jsx("h3", { className: "text-lg font-semibold mb-2", children: "D\u00E9veloppement de modules" }), _jsxs("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-2", children: ["Pour cr\u00E9er un nouveau module, consultez la", " ", _jsx("a", { href: "./004_CREATE_MODULE.md", className: "text-blue-600 hover:underline", target: "_blank", rel: "noopener noreferrer", children: "documentation de cr\u00E9ation de modules" }), "."] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-2", children: "La documentation de chaque module est g\u00E9n\u00E9r\u00E9e automatiquement depuis :" }), _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "text-green-600", children: "\u2705" }), _jsxs("span", { children: ["Le fichier", " ", _jsx("code", { className: "text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded", children: "module-name.build.config.ts" }), " ", "pour les pages et APIs"] })] }), _jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "text-green-600", children: "\u2705" }), _jsx("span", { children: "Les fichiers de migration SQL pour les tables" })] }), _jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "text-green-600", children: "\u2705" }), _jsxs("span", { children: ["Le README.md est auto-g\u00E9n\u00E9r\u00E9 avec", " ", _jsx("code", { className: "text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded", children: "pnpm generate:module-docs" })] })] })] })] })] })] }));
239
+ }` }) }), _jsx("h3", { className: "text-lg font-semibold mb-2", children: "Exporter la documentation" }), _jsxs("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-2", children: ["Dans", " ", _jsx("code", { className: "text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded", children: "src/index.ts" }), " ", ":"] }), _jsx(Alert, { hideIcon: true, color: "primary", className: "p-4 mb-4", children: _jsx("pre", { className: "whitespace-pre-wrap", children: `export { MonModuleDoc } from "./components/Doc.js";` }) })] })] }), _jsxs(Card, { id: "section-links", className: "scroll-mt-32", children: [_jsx(CardHeader, { children: _jsxs("h2", { className: "text-2xl font-semibold flex items-center gap-2", children: [_jsx(Link, { size: 24 }), "Liens utiles & remerciements \uD83D\uDE4F"] }) }), _jsx(CardBody, { children: _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: [_jsx(Card, { className: "hover:shadow-lg transition-shadow", isPressable: true, as: "a", href: "https://nextjs.org/docs", target: "_blank", rel: "noopener noreferrer", children: _jsxs(CardBody, { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Next.js" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-3", children: "Documentation officielle" }), _jsx("p", { className: "text-xs text-blue-600 dark:text-blue-400 truncate", children: "https://nextjs.org/docs" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow", isPressable: true, as: "a", href: "https://supabase.com/docs", target: "_blank", rel: "noopener noreferrer", children: _jsxs(CardBody, { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Supabase" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-3", children: "Documentation officielle" }), _jsx("p", { className: "text-xs text-blue-600 dark:text-blue-400 truncate", children: "https://supabase.com/docs" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow", isPressable: true, as: "a", href: "https://www.heroui.com/docs", target: "_blank", rel: "noopener noreferrer", children: _jsxs(CardBody, { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Heroui" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-3", children: "Composants UI" }), _jsx("p", { className: "text-xs text-blue-600 dark:text-blue-400 truncate", children: "https://www.heroui.com/docs" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow", isPressable: true, as: "a", href: "https://tailwindcss.com/docs", target: "_blank", rel: "noopener noreferrer", children: _jsxs(CardBody, { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Tailwind CSS" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-3", children: "Framework CSS" }), _jsx("p", { className: "text-xs text-blue-600 dark:text-blue-400 truncate", children: "https://tailwindcss.com/docs" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow", isPressable: true, as: "a", href: "https://lucide.dev/", target: "_blank", rel: "noopener noreferrer", children: _jsxs(CardBody, { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Lucide Icons" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-3", children: "Icones SVG" }), _jsx("p", { className: "text-xs text-blue-600 dark:text-blue-400 truncate", children: "https://lucide.dev/" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow", isPressable: true, as: "a", href: "https://stripe.com/docs", target: "_blank", rel: "noopener noreferrer", children: _jsxs(CardBody, { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Stripe" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-3", children: "Syst\u00E8me de paiement" }), _jsx("p", { className: "text-xs text-blue-600 dark:text-blue-400 truncate", children: "https://stripe.com/docs" })] }) })] }) })] }), _jsxs(Card, { id: "section-modules", className: "scroll-mt-32", children: [_jsx(CardHeader, { children: _jsxs("h2", { className: "text-2xl font-semibold flex items-center gap-2", children: [_jsx(Package, { size: 24 }), "Modules"] }) }), _jsxs(CardBody, { className: "space-y-6", children: [_jsx("p", { className: "text-slate-600 dark:text-slate-400", children: "Les modules LastBrain permettent d'ajouter des fonctionnalit\u00E9s compl\u00E8tes \u00E0 votre application de mani\u00E8re modulaire." }), _jsxs("div", { children: [_jsx("h3", { className: "text-xl font-semibold mb-4", children: "Modules Disponibles" }), _jsxs("div", { className: "grid grid-cols-1 gap-4", children: [_jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-blue-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Ai" }), _jsx("span", { className: "text-xs bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 px-2 py-1 rounded", children: "FREE" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 1 auth, 1 admin"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module ai` }), _jsx("a", { href: "https://github.com/Lastbrain-labs/lb-starter/tree/main/packages/module-ai", className: "text-sm text-blue-600 dark:text-blue-400 hover:underline inline-flex items-center gap-1", target: "_blank", rel: "noopener noreferrer", children: "\uD83D\uDCD6 Documentation \u2192" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-blue-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Auth" }), _jsx("span", { className: "text-xs bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 px-2 py-1 rounded", children: "FREE" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 3 publique(s), 4 auth, 2 admin"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module auth` }), _jsx("a", { href: "https://github.com/Lastbrain-labs/lb-starter/tree/main/packages/module-auth", className: "text-sm text-blue-600 dark:text-blue-400 hover:underline inline-flex items-center gap-1", target: "_blank", rel: "noopener noreferrer", children: "\uD83D\uDCD6 Documentation \u2192" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-purple-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Billing Pro" }), _jsx("span", { className: "text-xs bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200 px-2 py-1 rounded", children: "PRO" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 3 auth, 2 admin"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module billing-pro` }), _jsx("span", { className: "text-xs text-slate-500 dark:text-slate-400 inline-flex items-center gap-1", children: "\uD83D\uDD12 Documentation priv\u00E9e" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-purple-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Core Cart Pro" }), _jsx("span", { className: "text-xs bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200 px-2 py-1 rounded", children: "PRO" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 2 auth, 1 admin"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module core-cart-pro` }), _jsx("span", { className: "text-xs text-slate-500 dark:text-slate-400 inline-flex items-center gap-1", children: "\uD83D\uDD12 Documentation priv\u00E9e" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-purple-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Core Commerce Pro" }), _jsx("span", { className: "text-xs bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200 px-2 py-1 rounded", children: "PRO" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module core-commerce-pro` }), _jsx("span", { className: "text-xs text-slate-500 dark:text-slate-400 inline-flex items-center gap-1", children: "\uD83D\uDD12 Documentation priv\u00E9e" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-purple-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Core Order Pro" }), _jsx("span", { className: "text-xs bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200 px-2 py-1 rounded", children: "PRO" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 2 auth"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module core-order-pro` }), _jsx("span", { className: "text-xs text-slate-500 dark:text-slate-400 inline-flex items-center gap-1", children: "\uD83D\uDD12 Documentation priv\u00E9e" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-purple-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Core Payment Pro" }), _jsx("span", { className: "text-xs bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200 px-2 py-1 rounded", children: "PRO" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 1 admin"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module core-payment-pro` }), _jsx("span", { className: "text-xs text-slate-500 dark:text-slate-400 inline-flex items-center gap-1", children: "\uD83D\uDD12 Documentation priv\u00E9e" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-purple-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Core Product Pro" }), _jsx("span", { className: "text-xs bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200 px-2 py-1 rounded", children: "PRO" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 2 publique(s)"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module core-product-pro` }), _jsx("span", { className: "text-xs text-slate-500 dark:text-slate-400 inline-flex items-center gap-1", children: "\uD83D\uDD12 Documentation priv\u00E9e" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-blue-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Legal" }), _jsx("span", { className: "text-xs bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 px-2 py-1 rounded", children: "FREE" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 4 publique(s), 2 admin"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module legal` }), _jsx("a", { href: "https://github.com/Lastbrain-labs/lb-starter/tree/main/packages/module-legal", className: "text-sm text-blue-600 dark:text-blue-400 hover:underline inline-flex items-center gap-1", target: "_blank", rel: "noopener noreferrer", children: "\uD83D\uDCD6 Documentation \u2192" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-blue-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Project Board" }), _jsx("span", { className: "text-xs bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 px-2 py-1 rounded", children: "FREE" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 2 auth"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module project-board` }), _jsx("a", { href: "https://github.com/Lastbrain-labs/lb-starter/tree/main/packages/module-project-board", className: "text-sm text-blue-600 dark:text-blue-400 hover:underline inline-flex items-center gap-1", target: "_blank", rel: "noopener noreferrer", children: "\uD83D\uDCD6 Documentation \u2192" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-purple-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Recipes Pro" }), _jsx("span", { className: "text-xs bg-purple-100 dark:bg-purple-900 text-purple-800 dark:text-purple-200 px-2 py-1 rounded", children: "PRO" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 4 auth"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module recipes-pro` }), _jsx("span", { className: "text-xs text-slate-500 dark:text-slate-400 inline-flex items-center gap-1", children: "\uD83D\uDD12 Documentation priv\u00E9e" })] }) }), _jsx(Card, { className: "hover:shadow-lg transition-shadow border-l-4 border-l-blue-500", children: _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsx("h3", { className: "text-lg font-semibold", children: "Tasks" }), _jsx("span", { className: "text-xs bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 px-2 py-1 rounded", children: "FREE" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Module LastBrain" }), _jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-500", children: [_jsx("strong", { children: "Pages:" }), " 2 auth, 1 admin"] }), _jsx(Snippet, { symbol: "\uD83D\uDCBB", hideSymbol: true, className: "text-sm", children: `pnpm lastbrain add-module nom-du-module` }), _jsx("a", { href: "https://github.com/Lastbrain-labs/lb-starter/tree/main/packages/module-tasks", className: "text-sm text-blue-600 dark:text-blue-400 hover:underline inline-flex items-center gap-1", target: "_blank", rel: "noopener noreferrer", children: "\uD83D\uDCD6 Documentation \u2192" })] }) })] })] }), _jsx("h3", { className: "text-lg font-semibold mb-2", children: "Commandes" }), _jsx("h4", { className: "font-medium mb-2", children: "Installer un module" }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: `pnpm lastbrain add-module nom-du-module` }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: `pnpm build:modules` }), _jsx("h4", { className: "font-medium mb-2", children: "Cr\u00E9er un nouveau module" }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: `pnpm lastbrain create-module nom-du-module` }), _jsx("h4", { className: "font-medium mb-2", children: "G\u00E9n\u00E9rer la documentation des modules" }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: `pnpm generate:module-docs` }), _jsx("h4", { className: "font-medium mb-2", children: "Supprimer un module" }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: `pnpm lastbrain remove-module nom-du-module` }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: `pnpm build:modules` }), _jsx("h3", { className: "text-lg font-semibold mb-2", children: "D\u00E9veloppement de modules" }), _jsxs("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-2", children: ["Pour cr\u00E9er un nouveau module, consultez la", " ", _jsx("a", { href: "./004_CREATE_MODULE.md", className: "text-blue-600 hover:underline", target: "_blank", rel: "noopener noreferrer", children: "documentation de cr\u00E9ation de modules" }), "."] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-2", children: "La documentation de chaque module est g\u00E9n\u00E9r\u00E9e automatiquement depuis :" }), _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "text-green-600", children: "\u2705" }), _jsxs("span", { children: ["Le fichier", " ", _jsx("code", { className: "text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded", children: "module-name.build.config.ts" }), " ", "pour les pages et APIs"] })] }), _jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "text-green-600", children: "\u2705" }), _jsx("span", { children: "Les fichiers de migration SQL pour les tables" })] }), _jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "text-green-600", children: "\u2705" }), _jsxs("span", { children: ["Le README.md est auto-g\u00E9n\u00E9r\u00E9 avec", " ", _jsx("code", { className: "text-sm bg-slate-100 dark:bg-slate-800 px-2 py-1 rounded", children: "pnpm generate:module-docs" })] })] })] })] })] })] }));
240
240
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lastbrain/app",
3
- "version": "0.1.45",
3
+ "version": "0.1.47",
4
4
  "description": "Framework modulaire Next.js avec CLI et système de modules",
5
5
  "private": false,
6
6
  "type": "module",
@@ -24,8 +24,7 @@
24
24
  "directory": "packages/app"
25
25
  },
26
26
  "publishConfig": {
27
- "access": "public",
28
- "registry": "https://registry.npmjs.org"
27
+ "access": "public"
29
28
  },
30
29
  "bin": {
31
30
  "lastbrain": "./dist/cli.js"
@@ -44,8 +43,8 @@
44
43
  "inquirer": "^13.0.1",
45
44
  "lucide-react": "^0.554.0",
46
45
  "next-themes": "^0.4.6",
47
- "react": "^19.0.0",
48
- "react-dom": "^19.0.0"
46
+ "react": "^19.2.1",
47
+ "react-dom": "^19.2.1"
49
48
  },
50
49
  "peerDependencies": {
51
50
  "next": ">=15.0.0"
@@ -14,7 +14,7 @@ export function useAuthSession() {
14
14
  try {
15
15
  const { data, error } = await supabaseBrowserClient.rpc(
16
16
  "is_superadmin",
17
- { user_id: userId },
17
+ { user_id: userId }
18
18
  );
19
19
  if (!error && data) {
20
20
  setIsSuperAdmin(data);
package/src/cli.ts CHANGED
@@ -23,7 +23,7 @@ program
23
23
  .option("--with-auth", "Inclure le module d'authentification")
24
24
  .option(
25
25
  "--no-interactive",
26
- "Mode non-interactif (skip la sélection des modules)",
26
+ "Mode non-interactif (skip la sélection des modules)"
27
27
  )
28
28
  .action(async (directory: string | undefined, options) => {
29
29
  try {
@@ -66,7 +66,7 @@ export function useNotifications(user?: User | null) {
66
66
  setError(
67
67
  err instanceof Error
68
68
  ? err.message
69
- : "Erreur lors du chargement des notifications",
69
+ : "Erreur lors du chargement des notifications"
70
70
  );
71
71
  console.error("[useNotifications] Erreur:", err);
72
72
  } finally {
@@ -88,7 +88,7 @@ export function useNotifications(user?: User | null) {
88
88
  fetchNotifications();
89
89
  }
90
90
  },
91
- },
91
+ }
92
92
  );
93
93
 
94
94
  // Marquer une notification comme lue
@@ -114,7 +114,7 @@ export function useNotifications(user?: User | null) {
114
114
  setData((prev) => ({
115
115
  ...prev,
116
116
  notifications: prev.notifications.map((n) =>
117
- n.id === notificationId ? { ...n, read: true } : n,
117
+ n.id === notificationId ? { ...n, read: true } : n
118
118
  ),
119
119
  unreadCount: Math.max(0, prev.unreadCount - 1),
120
120
  }));
@@ -123,7 +123,7 @@ export function useNotifications(user?: User | null) {
123
123
  throw err;
124
124
  }
125
125
  },
126
- [user?.id],
126
+ [user?.id]
127
127
  );
128
128
 
129
129
  // Marquer toutes les notifications comme lues
@@ -175,11 +175,11 @@ export function useNotifications(user?: User | null) {
175
175
  // Mettre à jour localement
176
176
  setData((prev) => {
177
177
  const notification = prev.notifications.find(
178
- (n) => n.id === notificationId,
178
+ (n) => n.id === notificationId
179
179
  );
180
180
  return {
181
181
  notifications: prev.notifications.filter(
182
- (n) => n.id !== notificationId,
182
+ (n) => n.id !== notificationId
183
183
  ),
184
184
  unreadCount:
185
185
  notification && !notification.read
@@ -192,7 +192,7 @@ export function useNotifications(user?: User | null) {
192
192
  throw err;
193
193
  }
194
194
  },
195
- [user?.id],
195
+ [user?.id]
196
196
  );
197
197
 
198
198
  // Charger les notifications initiales
@@ -51,17 +51,17 @@ export function AdminLayoutWithSidebar({
51
51
  // Écouter l'événement custom pour les changements du même onglet
52
52
  window.addEventListener(
53
53
  "localStorage-changed",
54
- handleStorageChange as EventListener,
54
+ handleStorageChange as EventListener
55
55
  );
56
56
 
57
57
  return () => {
58
58
  window.removeEventListener(
59
59
  "storage",
60
- handleStorageChange as EventListener,
60
+ handleStorageChange as EventListener
61
61
  );
62
62
  window.removeEventListener(
63
63
  "localStorage-changed",
64
- handleStorageChange as EventListener,
64
+ handleStorageChange as EventListener
65
65
  );
66
66
  };
67
67
  }
@@ -74,7 +74,7 @@ export function AppProviders({
74
74
 
75
75
  const authValue = useMemo(
76
76
  () => ({ user, loading: authLoading, isSuperAdmin }),
77
- [user, authLoading, isSuperAdmin],
77
+ [user, authLoading, isSuperAdmin]
78
78
  ); // const handleLogout = async () => {
79
79
  // const { signOut } = await import("../auth/authHelpers.js");
80
80
  // await signOut();
@@ -49,17 +49,17 @@ export function AuthLayoutWithSidebar({
49
49
  // Écouter l'événement custom pour les changements du même onglet
50
50
  window.addEventListener(
51
51
  "localStorage-changed",
52
- handleStorageChange as EventListener,
52
+ handleStorageChange as EventListener
53
53
  );
54
54
 
55
55
  return () => {
56
56
  window.removeEventListener(
57
57
  "storage",
58
- handleStorageChange as EventListener,
58
+ handleStorageChange as EventListener
59
59
  );
60
60
  window.removeEventListener(
61
61
  "localStorage-changed",
62
- handleStorageChange as EventListener,
62
+ handleStorageChange as EventListener
63
63
  );
64
64
  };
65
65
  }
@@ -49,17 +49,17 @@ export function PublicLayoutWithSidebar({
49
49
  // Écouter l'événement custom pour les changements du même onglet
50
50
  window.addEventListener(
51
51
  "localStorage-changed",
52
- handleStorageChange as EventListener,
52
+ handleStorageChange as EventListener
53
53
  );
54
54
 
55
55
  return () => {
56
56
  window.removeEventListener(
57
57
  "storage",
58
- handleStorageChange as EventListener,
58
+ handleStorageChange as EventListener
59
59
  );
60
60
  window.removeEventListener(
61
61
  "localStorage-changed",
62
- handleStorageChange as EventListener,
62
+ handleStorageChange as EventListener
63
63
  );
64
64
  };
65
65
  }
@@ -20,7 +20,7 @@ const packageAppDir = path
20
20
  .replace(/dist\/scripts$/, "src");
21
21
  const envExampleTemplate = path.join(
22
22
  packageAppDir,
23
- "templates/env.example/.env.example",
23
+ "templates/env.example/.env.example"
24
24
  );
25
25
 
26
26
  function ensureDirectory(dir: string) {
@@ -78,7 +78,7 @@ function runSupabase(...args: any[]): Buffer | null {
78
78
  // Si le processus s'est terminé avec un code de sortie non nul, propager l'erreur
79
79
  if (result.status !== 0) {
80
80
  const error: any = new Error(
81
- `Command failed with exit code ${result.status}`,
81
+ `Command failed with exit code ${result.status}`
82
82
  );
83
83
  error.status = result.status;
84
84
  throw error;
@@ -89,7 +89,7 @@ function runSupabase(...args: any[]): Buffer | null {
89
89
  }
90
90
 
91
91
  throw new Error(
92
- "Unable to locate Supabase CLI (install it globally or via pnpm).",
92
+ "Unable to locate Supabase CLI (install it globally or via pnpm)."
93
93
  );
94
94
  }
95
95
 
@@ -110,7 +110,7 @@ function parseEnvFile(filePath: string) {
110
110
  .map((line) => {
111
111
  const [key, ...value] = line.split("=");
112
112
  return [key, value.join("=")];
113
- }),
113
+ })
114
114
  ) as Record<string, string>;
115
115
  }
116
116
 
@@ -129,7 +129,7 @@ function ensureEnvFile(values: Record<string, string>) {
129
129
  .map((line) => {
130
130
  const [key, ...value] = line.split("=");
131
131
  return [key, value.join("=")];
132
- }),
132
+ })
133
133
  );
134
134
  } catch (error) {
135
135
  console.warn(`⚠️ Erreur lors de la lecture de ${target}:`, error);
@@ -300,7 +300,7 @@ async function main() {
300
300
  stdio: "inherit",
301
301
  env: { ...process.env, PATH: enhancedPath },
302
302
  shell: true,
303
- },
303
+ }
304
304
  );
305
305
 
306
306
  if (migrationResult.error || migrationResult.status !== 0) {
@@ -338,7 +338,7 @@ async function main() {
338
338
  console.log("ℹ️ Copied .env.example into .env.local as fallback.");
339
339
  }
340
340
  console.warn(
341
- "⚠️ Impossible de récupérer automatiquement les accès Supabase.",
341
+ "⚠️ Impossible de récupérer automatiquement les accès Supabase."
342
342
  );
343
343
  }
344
344
 
@@ -67,7 +67,7 @@ function syncModuleMigrations() {
67
67
  const activeModules = modules.filter((m: any) => m.active !== false);
68
68
 
69
69
  console.log(
70
- `🔄 Syncing migrations from ${activeModules.length} active module(s)...\n`,
70
+ `🔄 Syncing migrations from ${activeModules.length} active module(s)...\n`
71
71
  );
72
72
 
73
73
  let totalCopied = 0;
@@ -87,7 +87,7 @@ function syncModuleMigrations() {
87
87
  "..",
88
88
  "..",
89
89
  "packages",
90
- moduleName.replace("@lastbrain/", "").replace("@lastbrain-labs/", ""),
90
+ moduleName.replace("@lastbrain/", "").replace("@lastbrain-labs/", "")
91
91
  ),
92
92
  ];
93
93