@lastbrain/app 0.1.43 → 0.1.45

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 (48) hide show
  1. package/dist/__tests__/module-registry.test.js +1 -1
  2. package/dist/layouts/AdminLayoutWithSidebar.d.ts +2 -1
  3. package/dist/layouts/AdminLayoutWithSidebar.d.ts.map +1 -1
  4. package/dist/layouts/AdminLayoutWithSidebar.js +10 -4
  5. package/dist/layouts/AuthLayoutWithSidebar.d.ts +2 -1
  6. package/dist/layouts/AuthLayoutWithSidebar.d.ts.map +1 -1
  7. package/dist/layouts/AuthLayoutWithSidebar.js +10 -4
  8. package/dist/layouts/PublicLayout.d.ts +2 -1
  9. package/dist/layouts/PublicLayout.d.ts.map +1 -1
  10. package/dist/layouts/PublicLayoutWithSidebar.d.ts +2 -1
  11. package/dist/layouts/PublicLayoutWithSidebar.d.ts.map +1 -1
  12. package/dist/layouts/PublicLayoutWithSidebar.js +10 -4
  13. package/dist/scripts/db-migrations-sync.js +67 -38
  14. package/dist/scripts/dev-sync.js +1 -0
  15. package/dist/scripts/init-app.d.ts.map +1 -1
  16. package/dist/scripts/init-app.js +41 -9
  17. package/dist/scripts/module-build.d.ts.map +1 -1
  18. package/dist/scripts/module-build.js +17 -5
  19. package/dist/scripts/module-create.d.ts.map +1 -1
  20. package/dist/scripts/module-create.js +19 -0
  21. package/dist/scripts/module-delete.d.ts.map +1 -1
  22. package/dist/scripts/module-delete.js +6 -2
  23. package/dist/scripts/module-list.d.ts.map +1 -1
  24. package/dist/scripts/module-list.js +1 -1
  25. package/dist/styles.css +1 -1
  26. package/dist/templates/DefaultDoc.d.ts.map +1 -1
  27. package/dist/templates/DefaultDoc.js +6 -13
  28. package/dist/templates/DocPage.d.ts.map +1 -1
  29. package/dist/templates/DocPage.js +3 -5
  30. package/dist/templates/SimpleDocPage.js +2 -2
  31. package/dist/templates/SimpleHomePage.js +1 -1
  32. package/package.json +9 -3
  33. package/src/__tests__/module-registry.test.ts +1 -1
  34. package/src/layouts/AdminLayoutWithSidebar.tsx +13 -6
  35. package/src/layouts/AuthLayoutWithSidebar.tsx +13 -6
  36. package/src/layouts/PublicLayout.tsx +2 -2
  37. package/src/layouts/PublicLayoutWithSidebar.tsx +13 -6
  38. package/src/scripts/db-migrations-sync.ts +86 -57
  39. package/src/scripts/dev-sync.ts +1 -0
  40. package/src/scripts/init-app.ts +47 -9
  41. package/src/scripts/module-build.ts +19 -5
  42. package/src/scripts/module-create.ts +25 -2
  43. package/src/scripts/module-delete.ts +8 -6
  44. package/src/scripts/module-list.ts +1 -4
  45. package/src/templates/DefaultDoc.tsx +346 -492
  46. package/src/templates/DocPage.tsx +37 -19
  47. package/src/templates/SimpleDocPage.tsx +2 -2
  48. package/src/templates/SimpleHomePage.tsx +3 -3
@@ -138,6 +138,21 @@ export async function initApp(options: InitAppOptions) {
138
138
  execSync("pnpm build:modules", { cwd: targetDir, stdio: "inherit" });
139
139
  console.log(chalk.green("\n✓ Routes des modules générées\n"));
140
140
 
141
+ console.log(
142
+ chalk.yellow("📜 Synchronisation des migrations des modules...\n"),
143
+ );
144
+ try {
145
+ execSync("pnpm db:migrations:sync", {
146
+ cwd: targetDir,
147
+ stdio: "inherit",
148
+ });
149
+ console.log(chalk.green("\n✓ Migrations synchronisées\n"));
150
+ } catch (error) {
151
+ console.log(
152
+ chalk.yellow("\n⚠️ Erreur de synchronisation des migrations\n"),
153
+ );
154
+ }
155
+
141
156
  console.log(chalk.yellow("🗄️ Initialisation de la base de données...\n"));
142
157
  try {
143
158
  execSync("pnpm db:init", { cwd: targetDir, stdio: "inherit" });
@@ -195,6 +210,7 @@ export async function initApp(options: InitAppOptions) {
195
210
  console.log(chalk.white(` cd ${relativePath}`));
196
211
  console.log(chalk.white(" pnpm install"));
197
212
  console.log(chalk.white(" pnpm build:modules"));
213
+ console.log(chalk.white(" pnpm db:migrations:sync"));
198
214
  console.log(chalk.white(" pnpm db:init"));
199
215
  console.log(chalk.white(" pnpm dev\n"));
200
216
  }
@@ -206,11 +222,12 @@ export async function initApp(options: InitAppOptions) {
206
222
  chalk.white(" 3. pnpm build:modules (générer les routes des modules)"),
207
223
  );
208
224
  console.log(
209
- chalk.white(" 4. pnpm db:init (initialiser la base de données)"),
225
+ chalk.white(" 4. pnpm db:migrations:sync (synchroniser les migrations)"),
210
226
  );
211
- console.log(chalk.white(" 5. pnpm dev (lancer le serveur)"));
212
- console.log(chalk.white(" 4. pnpm db:init (initialiser Supabase)"));
213
- console.log(chalk.white(" 5. pnpm dev (démarrer le serveur)\n"));
227
+ console.log(
228
+ chalk.white(" 5. pnpm db:init (initialiser la base de données)"),
229
+ );
230
+ console.log(chalk.white(" 6. pnpm dev (lancer le serveur)\n"));
214
231
 
215
232
  console.log(chalk.gray("Prérequis pour Supabase :"));
216
233
  console.log(chalk.white(" - Docker Desktop installé et lancé"));
@@ -988,6 +1005,24 @@ export async function middleware(request: NextRequest) {
988
1005
  const { pathname } = request.nextUrl;
989
1006
  const isApi = pathname.startsWith("/api/");
990
1007
 
1008
+ // Pages publiques d'authentification (ne pas protéger)
1009
+ const publicAuthPages = [
1010
+ "/signin",
1011
+ "/signup",
1012
+ "/reset-password",
1013
+ "/forgot-password",
1014
+ "/callback",
1015
+ ];
1016
+
1017
+ const isPublicAuthPage = publicAuthPages.some((page) =>
1018
+ pathname.startsWith(page)
1019
+ );
1020
+
1021
+ // Ne pas protéger les pages publiques d'authentification
1022
+ if (isPublicAuthPage) {
1023
+ return NextResponse.next();
1024
+ }
1025
+
991
1026
  // Protéger les routes /auth/* (espace membre)
992
1027
  if (pathname.startsWith("/auth")) {
993
1028
  try {
@@ -996,9 +1031,9 @@ export async function middleware(request: NextRequest) {
996
1031
  data: { session },
997
1032
  } = await supabase.auth.getSession();
998
1033
 
999
- // Pas de session → nettoyage des cookies + redirection vers /auth/signin
1034
+ // Pas de session → nettoyage des cookies + redirection vers /signin
1000
1035
  if (!session) {
1001
- const redirectUrl = new URL("/auth/signin", request.url);
1036
+ const redirectUrl = new URL("/signin", request.url);
1002
1037
  redirectUrl.searchParams.set("redirect", pathname);
1003
1038
  const res = NextResponse.redirect(redirectUrl);
1004
1039
  res.cookies.delete("sb-access-token");
@@ -1011,7 +1046,7 @@ export async function middleware(request: NextRequest) {
1011
1046
  return response;
1012
1047
  } catch (error) {
1013
1048
  console.error("Middleware auth error:", error);
1014
- const res = NextResponse.redirect(new URL("/auth/signin", request.url));
1049
+ const res = NextResponse.redirect(new URL("/signin", request.url));
1015
1050
  res.cookies.delete("sb-access-token");
1016
1051
  res.cookies.delete("sb-refresh-token");
1017
1052
  res.cookies.delete("sb:token");
@@ -1028,7 +1063,7 @@ export async function middleware(request: NextRequest) {
1028
1063
  data: { session },
1029
1064
  } = await supabase.auth.getSession();
1030
1065
 
1031
- // Pas de session → 401 JSON pour API, sinon redirection vers /auth/signin avec nettoyage cookies
1066
+ // Pas de session → 401 JSON pour API, sinon redirection vers /signin avec nettoyage cookies
1032
1067
  if (!session) {
1033
1068
  if (isApi) {
1034
1069
  const res = NextResponse.json({ error: "Non authentifié" }, { status: 401 });
@@ -1038,7 +1073,7 @@ export async function middleware(request: NextRequest) {
1038
1073
  res.cookies.delete("sb:refresh-token");
1039
1074
  return res;
1040
1075
  }
1041
- const redirectUrl = new URL("/auth/signin", request.url);
1076
+ const redirectUrl = new URL("/signin", request.url);
1042
1077
  redirectUrl.searchParams.set("redirect", pathname);
1043
1078
  const res = NextResponse.redirect(redirectUrl);
1044
1079
  res.cookies.delete("sb-access-token");
@@ -1107,6 +1142,9 @@ export const config = {
1107
1142
  const nextConfig = `/** @type {import('next').NextConfig} */
1108
1143
  const nextConfig = {
1109
1144
  reactStrictMode: true,
1145
+ devIndicators: {
1146
+ position: 'bottom-right',
1147
+ },
1110
1148
  };
1111
1149
 
1112
1150
  export default nextConfig;
@@ -47,7 +47,11 @@ async function loadModuleConfigs(): Promise<ModuleBuildConfig[]> {
47
47
  const packageName = module.package;
48
48
 
49
49
  try {
50
- const moduleSuffix = packageName.replace("@lastbrain/module-", "");
50
+ // Extraire le suffix du module (la partie après @lastbrain/module- ou @lastbrain-labs/module-)
51
+ const moduleSuffix = packageName
52
+ .replace("@lastbrain/module-", "")
53
+ .replace("@lastbrain-labs/module-", "");
54
+
51
55
  const possibleConfigNames = [
52
56
  `${moduleSuffix}.build.config`,
53
57
  "build.config",
@@ -159,9 +163,12 @@ function toPascalCase(value: string) {
159
163
  }
160
164
 
161
165
  function buildPage(moduleConfig: ModuleBuildConfig, page: ModulePageConfig) {
162
- // Extraire le préfixe du module (ex: @lastbrain/module-auth -> auth)
166
+ // Extraire le préfixe du module (ex: @lastbrain/module-auth -> auth, @lastbrain-labs/module-recipes-pro -> recipes)
167
+ // Enlever -pro pour les routes auth et admin afin d'avoir des chemins propres
163
168
  const modulePrefix = moduleConfig.moduleName
164
169
  .replace(/^@lastbrain\/module-/, "")
170
+ .replace(/^@lastbrain-labs\/module-/, "")
171
+ .replace(/-pro$/, "") // Enlever le suffixe -pro
165
172
  .toLowerCase();
166
173
 
167
174
  if (isDebugMode) {
@@ -593,7 +600,14 @@ function generateDocsPage(moduleConfigs: ModuleBuildConfig[]) {
593
600
 
594
601
  allModules.forEach((moduleEntry) => {
595
602
  const moduleName = moduleEntry.package;
596
- const moduleId = moduleName.replace("@lastbrain/module-", "");
603
+ // Extraire le nom du module sans le scope et sans "module-"
604
+ // Ex: @lastbrain/module-auth -> auth
605
+ // Ex: @lastbrain-labs/module-recipes-pro -> recipes
606
+ const moduleId = moduleName
607
+ .replace("@lastbrain-labs/module-", "")
608
+ .replace("@lastbrain/module-", "")
609
+ .replace(/-pro$/, ""); // Retirer le suffix -pro pour avoir le nom de base
610
+
597
611
  const docComponentName = `${toPascalCase(moduleId)}ModuleDoc`;
598
612
 
599
613
  // Trouver la config du module pour obtenir la description
@@ -610,8 +624,8 @@ function generateDocsPage(moduleConfigs: ModuleBuildConfig[]) {
610
624
  }
611
625
 
612
626
  const config = {
613
- id: moduleId,
614
- name: `Module ${moduleId.charAt(0).toUpperCase() + moduleId.slice(1)}`,
627
+ id: moduleName, // Utiliser le nom complet du package comme ID
628
+ name: `Module ${toPascalCase(moduleId)}`,
615
629
  description: description,
616
630
  component: docComponentName,
617
631
  active: moduleEntry.active,
@@ -1028,12 +1028,21 @@ ${pagesSection}${apisSection}${tablesSection}${installSection}${usageSection}${d
1028
1028
  /**
1029
1029
  * Generate README.md for the module
1030
1030
  */
1031
- async function generateModuleReadme(config: ModuleConfig, moduleDir: string) {
1031
+ async function generateModuleReadme(
1032
+ config: ModuleConfig & { description?: string },
1033
+ moduleDir: string,
1034
+ ) {
1032
1035
  const moduleNameClean = config.slug.replace("module-", "");
1033
1036
 
1034
1037
  let md = `# 📦 Module ${moduleNameClean}\n\n`;
1035
1038
  md += `> ${config.moduleName}\n\n`;
1036
1039
 
1040
+ // Description section
1041
+ if (config.description) {
1042
+ md += `## 📝 Description\n\n`;
1043
+ md += `${config.description}\n\n`;
1044
+ }
1045
+
1037
1046
  // Information section
1038
1047
  md += `## 📋 Informations\n\n`;
1039
1048
  md += `- **Nom du package**: \`${config.moduleName}\`\n`;
@@ -1533,6 +1542,18 @@ export async function createModule() {
1533
1542
  },
1534
1543
  filter: (input: string) => input.trim().toLowerCase(),
1535
1544
  },
1545
+ {
1546
+ type: "input",
1547
+ name: "description",
1548
+ message: "Description du module (une ligne):",
1549
+ default: "Module LastBrain",
1550
+ validate: (input) => {
1551
+ if (!input || input.trim() === "") {
1552
+ return "La description est requise";
1553
+ }
1554
+ return true;
1555
+ },
1556
+ },
1536
1557
  {
1537
1558
  type: "input",
1538
1559
  name: "pagesPublic",
@@ -1565,6 +1586,7 @@ export async function createModule() {
1565
1586
  // Construire la configuration du module
1566
1587
  const slug = `module-${answers.slug}`;
1567
1588
  const moduleName = `@lastbrain/${slug}`;
1589
+ const description = answers.description;
1568
1590
 
1569
1591
  const pages: PageConfig[] = [];
1570
1592
 
@@ -1664,11 +1686,12 @@ export async function createModule() {
1664
1686
  });
1665
1687
  }
1666
1688
 
1667
- const config: ModuleConfig = {
1689
+ const config: ModuleConfig & { description?: string } = {
1668
1690
  slug,
1669
1691
  moduleName,
1670
1692
  pages,
1671
1693
  tables,
1694
+ description,
1672
1695
  };
1673
1696
 
1674
1697
  // Trouver le répertoire racine du workspace (chercher pnpm-workspace.yaml)
@@ -38,7 +38,7 @@ export async function deleteModule() {
38
38
 
39
39
  const answers = await inquirer.prompt([
40
40
  {
41
- type: "list",
41
+ type: "select",
42
42
  name: "moduleName",
43
43
  message: "Quel module voulez-vous supprimer du monorepo ?",
44
44
  choices: AVAILABLE_MODULES.map((m) => ({
@@ -73,11 +73,13 @@ export async function deleteModule() {
73
73
  );
74
74
 
75
75
  // 1. Supprimer le répertoire du module
76
- const moduleDir = path.join(
77
- rootDir,
78
- "packages",
79
- moduleMeta.package.replace("@lastbrain/", ""),
80
- );
76
+ // Extraire le nom du package correctement (gérer @lastbrain et @lastbrain-labs)
77
+ const packageName = moduleMeta.package
78
+ .replace("@lastbrain-labs/", "")
79
+ .replace("@lastbrain/", "");
80
+
81
+ const moduleDir = path.join(rootDir, "packages", packageName);
82
+
81
83
  if (fs.existsSync(moduleDir)) {
82
84
  console.log(chalk.yellow(`📁 Suppression du répertoire: ${moduleDir}`));
83
85
  await fs.remove(moduleDir);
@@ -1,10 +1,7 @@
1
1
  import fs from "fs-extra";
2
2
  import path from "path";
3
3
  import chalk from "chalk";
4
- import {
5
- AVAILABLE_MODULES,
6
- type ModuleMetadata,
7
- } from "@lastbrain/core/config/modules";
4
+ import { AVAILABLE_MODULES } from "@lastbrain/core/config/modules";
8
5
 
9
6
  export async function listModules(targetDir: string) {
10
7
  console.log(chalk.blue("\n📦 Modules disponibles:\n"));