@lastbrain/app 0.1.44 → 0.1.46

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.
@@ -37,7 +37,7 @@ export async function addModule(moduleName: string, targetDir: string) {
37
37
  const moduleMeta = AVAILABLE_MODULES.find((m) => m.name === moduleName);
38
38
  if (!moduleMeta) {
39
39
  console.error(
40
- chalk.red(`❌ Module "${moduleName}" non trouvé. Modules disponibles:`),
40
+ chalk.red(`❌ Module "${moduleName}" non trouvé. Modules disponibles:`)
41
41
  );
42
42
  AVAILABLE_MODULES.forEach((m) => {
43
43
  console.log(chalk.gray(` - ${m.emoji} ${m.name}: ${m.description}`));
@@ -99,8 +99,8 @@ export async function addModule(moduleName: string, targetDir: string) {
99
99
  if (!fs.existsSync(path.join(workspaceRoot, "pnpm-workspace.yaml"))) {
100
100
  console.log(
101
101
  chalk.gray(
102
- " ℹ️ Impossible de localiser la racine du monorepo, build ignoré",
103
- ),
102
+ " ℹ️ Impossible de localiser la racine du monorepo, build ignoré"
103
+ )
104
104
  );
105
105
  } else {
106
106
  execSync(`pnpm --filter ${module.package} build`, {
@@ -113,7 +113,7 @@ export async function addModule(moduleName: string, targetDir: string) {
113
113
  console.log(
114
114
  chalk.yellow(" ⚠️ Build du module échoué, essayez: pnpm --filter"),
115
115
  module.package,
116
- "build",
116
+ "build"
117
117
  );
118
118
  }
119
119
 
@@ -126,12 +126,12 @@ export async function addModule(moduleName: string, targetDir: string) {
126
126
  const modulePackagePath = path.join(
127
127
  targetDir,
128
128
  "node_modules",
129
- ...module.package.split("/"),
129
+ ...module.package.split("/")
130
130
  );
131
131
 
132
132
  const moduleMigrationsDir = path.join(
133
133
  modulePackagePath,
134
- module.migrationsPath || "supabase/migrations",
134
+ module.migrationsPath || "supabase/migrations"
135
135
  );
136
136
 
137
137
  const projectMigrationsDir = path.join(targetDir, "supabase", "migrations");
@@ -153,19 +153,19 @@ export async function addModule(moduleName: string, targetDir: string) {
153
153
 
154
154
  // 6. Demander comment appliquer les migrations
155
155
  console.log(
156
- chalk.yellow("\n🗄️ Application des migrations à la base de données\n"),
156
+ chalk.yellow("\n🗄️ Application des migrations à la base de données\n")
157
157
  );
158
158
 
159
159
  console.log("Choisissez une option:");
160
160
  console.log(
161
161
  chalk.cyan(
162
- " 1) 🔄 Reset complet (supabase db reset) - Recommandé en dev",
163
- ),
162
+ " 1) 🔄 Reset complet (supabase db reset) - Recommandé en dev"
163
+ )
164
164
  );
165
165
  console.log(
166
166
  chalk.cyan(
167
- " 2) ⬆️ Push uniquement les nouvelles migrations (supabase migration up)",
168
- ),
167
+ " 2) ⬆️ Push uniquement les nouvelles migrations (supabase migration up)"
168
+ )
169
169
  );
170
170
  console.log(chalk.cyan(" 3) ⏭️ Ignorer pour l'instant"));
171
171
  console.log("");
@@ -202,7 +202,7 @@ export async function addModule(moduleName: string, targetDir: string) {
202
202
  }
203
203
  } else if (migrationAction === "push") {
204
204
  console.log(
205
- chalk.yellow("\n⬆️ Application des nouvelles migrations..."),
205
+ chalk.yellow("\n⬆️ Application des nouvelles migrations...")
206
206
  );
207
207
 
208
208
  // Appliquer directement avec psql au lieu de supabase migration up
@@ -215,7 +215,7 @@ export async function addModule(moduleName: string, targetDir: string) {
215
215
 
216
216
  if (migrationFiles.length === 0) {
217
217
  console.log(
218
- chalk.yellow("⚠️ Aucune nouvelle migration à appliquer"),
218
+ chalk.yellow("⚠️ Aucune nouvelle migration à appliquer")
219
219
  );
220
220
  } else {
221
221
  try {
@@ -234,25 +234,25 @@ export async function addModule(moduleName: string, targetDir: string) {
234
234
 
235
235
  console.log(
236
236
  chalk.green(
237
- `✓ ${migrationFiles.length} migration(s) appliquée(s)`,
238
- ),
237
+ `✓ ${migrationFiles.length} migration(s) appliquée(s)`
238
+ )
239
239
  );
240
240
  } catch (error: any) {
241
241
  console.error(
242
- chalk.red("❌ Erreur lors de l'application des migrations"),
242
+ chalk.red("❌ Erreur lors de l'application des migrations")
243
243
  );
244
244
  console.log(
245
245
  chalk.gray(
246
- "\nVous pouvez essayer manuellement:\n supabase db reset\n",
247
- ),
246
+ "\nVous pouvez essayer manuellement:\n supabase db reset\n"
247
+ )
248
248
  );
249
249
  }
250
250
  }
251
251
  } else {
252
252
  console.log(
253
253
  chalk.gray(
254
- "\n⚠️ N'oubliez pas d'appliquer les migrations avec:\n supabase db reset ou supabase migration up\n",
255
- ),
254
+ "\n⚠️ N'oubliez pas d'appliquer les migrations avec:\n supabase db reset ou supabase migration up\n"
255
+ )
256
256
  );
257
257
  }
258
258
  } else {
@@ -280,7 +280,7 @@ export async function addModule(moduleName: string, targetDir: string) {
280
280
  // Initialiser tous les modules disponibles s'ils n'existent pas
281
281
  for (const availableModule of AVAILABLE_MODULES) {
282
282
  const exists = modulesConfig.modules.find(
283
- (m) => m.package === availableModule.package,
283
+ (m) => m.package === availableModule.package
284
284
  );
285
285
  if (!exists) {
286
286
  modulesConfig.modules.push({
@@ -292,7 +292,7 @@ export async function addModule(moduleName: string, targetDir: string) {
292
292
  }
293
293
 
294
294
  const existingModuleIndex = modulesConfig.modules.findIndex(
295
- (m) => m.package === module.package,
295
+ (m) => m.package === module.package
296
296
  );
297
297
 
298
298
  const migrationsList = copiedMigrationFiles;
@@ -314,7 +314,7 @@ export async function addModule(moduleName: string, targetDir: string) {
314
314
  await fs.writeJson(modulesConfigPath, modulesConfig, { spaces: 2 });
315
315
 
316
316
  console.log(
317
- chalk.green(`\n✅ Module ${module.displayName} ajouté avec succès!\n`),
317
+ chalk.green(`\n✅ Module ${module.displayName} ajouté avec succès!\n`)
318
318
  );
319
319
 
320
320
  // 7. Générer automatiquement les routes du module
@@ -326,12 +326,12 @@ export async function addModule(moduleName: string, targetDir: string) {
326
326
  console.error(chalk.red("❌ Erreur lors de la génération des routes"));
327
327
  console.error(
328
328
  chalk.gray(
329
- "Vous pouvez les générer manuellement avec: cd apps/<votre-app> && pnpm run build:modules",
330
- ),
329
+ "Vous pouvez les générer manuellement avec: cd apps/<votre-app> && pnpm run build:modules"
330
+ )
331
331
  );
332
332
  }
333
333
 
334
334
  console.log(
335
- chalk.gray("\nLe serveur de développement redémarrera automatiquement.\n"),
335
+ chalk.gray("\nLe serveur de développement redémarrera automatiquement.\n")
336
336
  );
337
337
  }
@@ -62,7 +62,7 @@ async function loadModuleConfigs(): Promise<ModuleBuildConfig[]> {
62
62
  try {
63
63
  // Résoudre le chemin du module depuis l'application
64
64
  const modulePath = projectRequire.resolve(
65
- `${packageName}/${configName}`,
65
+ `${packageName}/${configName}`
66
66
  );
67
67
  // Convertir en URL file:// pour l'import dynamique
68
68
  const moduleUrl = `file://${modulePath}`;
@@ -163,10 +163,12 @@ function toPascalCase(value: string) {
163
163
  }
164
164
 
165
165
  function buildPage(moduleConfig: ModuleBuildConfig, page: ModulePageConfig) {
166
- // Extraire le préfixe du module (ex: @lastbrain/module-auth -> auth, @lastbrain-labs/module-recipes-pro -> recipes-pro)
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
167
168
  const modulePrefix = moduleConfig.moduleName
168
169
  .replace(/^@lastbrain\/module-/, "")
169
170
  .replace(/^@lastbrain-labs\/module-/, "")
171
+ .replace(/-pro$/, "") // Enlever le suffixe -pro
170
172
  .toLowerCase();
171
173
 
172
174
  if (isDebugMode) {
@@ -195,7 +197,7 @@ function buildPage(moduleConfig: ModuleBuildConfig, page: ModulePageConfig) {
195
197
  isDebugMode
196
198
  ) {
197
199
  console.log(
198
- `🏠 Auth module in auth section, no prefix needed: ${page.path}`,
200
+ `🏠 Auth module in auth section, no prefix needed: ${page.path}`
199
201
  );
200
202
  }
201
203
 
@@ -216,7 +218,7 @@ function buildPage(moduleConfig: ModuleBuildConfig, page: ModulePageConfig) {
216
218
 
217
219
  // Vérifier si la route a des paramètres dynamiques (segments avec [])
218
220
  const hasDynamicParams = segments.some(
219
- (seg) => seg.startsWith("[") && seg.endsWith("]"),
221
+ (seg) => seg.startsWith("[") && seg.endsWith("]")
220
222
  );
221
223
 
222
224
  // Pour les pages publiques (signin, signup, etc.), utiliser dynamic import sans SSR
@@ -339,7 +341,7 @@ function generateMenuConfig(moduleConfigs: ModuleBuildConfig[]) {
339
341
  ...moduleConfig.menu.public.map((item) => ({
340
342
  ...item,
341
343
  moduleName: moduleConfig.moduleName,
342
- })),
344
+ }))
343
345
  );
344
346
  }
345
347
  if (moduleConfig.menu.auth) {
@@ -347,7 +349,7 @@ function generateMenuConfig(moduleConfigs: ModuleBuildConfig[]) {
347
349
  ...moduleConfig.menu.auth.map((item) => ({
348
350
  ...item,
349
351
  moduleName: moduleConfig.moduleName,
350
- })),
352
+ }))
351
353
  );
352
354
  }
353
355
  if (moduleConfig.menu.admin) {
@@ -355,7 +357,7 @@ function generateMenuConfig(moduleConfigs: ModuleBuildConfig[]) {
355
357
  ...moduleConfig.menu.admin.map((item) => ({
356
358
  ...item,
357
359
  moduleName: moduleConfig.moduleName,
358
- })),
360
+ }))
359
361
  );
360
362
  }
361
363
  if (moduleConfig.menu.account) {
@@ -363,7 +365,7 @@ function generateMenuConfig(moduleConfigs: ModuleBuildConfig[]) {
363
365
  ...moduleConfig.menu.account.map((item) => ({
364
366
  ...item,
365
367
  moduleName: moduleConfig.moduleName,
366
- })),
368
+ }))
367
369
  );
368
370
  }
369
371
  }
@@ -392,7 +394,7 @@ function generateMenuConfig(moduleConfigs: ModuleBuildConfig[]) {
392
394
  if (menu.componentExport && menu.moduleName) {
393
395
  const componentName = `MenuComponent${index}`;
394
396
  componentImports.push(
395
- `const ${componentName} = dynamic(() => import("${menu.moduleName}").then(mod => ({ default: mod.${menu.componentExport} })), { ssr: false });`,
397
+ `const ${componentName} = dynamic(() => import("${menu.moduleName}").then(mod => ({ default: mod.${menu.componentExport} })), { ssr: false });`
396
398
  );
397
399
  // Ajouter une référence au composant
398
400
  (menu as any).__componentRef = componentName;
@@ -465,7 +467,7 @@ function copyModuleMigrations(moduleConfigs: ModuleBuildConfig[]) {
465
467
  const supabaseMigrationsDir = path.join(
466
468
  projectRoot,
467
469
  "supabase",
468
- "migrations",
470
+ "migrations"
469
471
  );
470
472
 
471
473
  // S'assurer que le dossier migrations existe
@@ -500,7 +502,7 @@ function copyModuleMigrations(moduleConfigs: ModuleBuildConfig[]) {
500
502
  "..",
501
503
  "..",
502
504
  "packages",
503
- moduleName.replace("@lastbrain/", ""),
505
+ moduleName.replace("@lastbrain/", "")
504
506
  ),
505
507
  ];
506
508
 
@@ -520,7 +522,7 @@ function copyModuleMigrations(moduleConfigs: ModuleBuildConfig[]) {
520
522
  const moduleMigrationsDir = path.join(
521
523
  moduleBasePath,
522
524
  "supabase",
523
- "migrations",
525
+ "migrations"
524
526
  );
525
527
 
526
528
  if (fs.existsSync(moduleMigrationsDir)) {
@@ -544,7 +546,7 @@ function copyModuleMigrations(moduleConfigs: ModuleBuildConfig[]) {
544
546
  // Mettre à jour modules.json avec les migrations
545
547
  if (copiedMigrations.length > 0) {
546
548
  const moduleIndex = modulesConfig.modules.findIndex(
547
- (m) => m.package === moduleName,
549
+ (m) => m.package === moduleName
548
550
  );
549
551
 
550
552
  if (moduleIndex >= 0) {
@@ -559,7 +561,7 @@ function copyModuleMigrations(moduleConfigs: ModuleBuildConfig[]) {
559
561
  } catch (error) {
560
562
  console.warn(
561
563
  `⚠️ Could not copy migrations from ${moduleConfig.moduleName}:`,
562
- error,
564
+ error
563
565
  );
564
566
  }
565
567
  });
@@ -610,7 +612,7 @@ function generateDocsPage(moduleConfigs: ModuleBuildConfig[]) {
610
612
 
611
613
  // Trouver la config du module pour obtenir la description
612
614
  const moduleConfig = moduleConfigs.find(
613
- (mc) => mc.moduleName === moduleName,
615
+ (mc) => mc.moduleName === moduleName
614
616
  );
615
617
  const description = moduleConfig
616
618
  ? getModuleDescription(moduleConfig)
@@ -660,7 +662,7 @@ ${moduleConfigurations.join(",\n")}
660
662
 
661
663
  function buildGroupedApi(
662
664
  apis: Array<{ moduleConfig: ModuleBuildConfig; api: ModuleApiConfig }>,
663
- routePath: string,
665
+ routePath: string
664
666
  ) {
665
667
  const segments = routePath.replace(/^\/+/, "").split("/").filter(Boolean);
666
668
  const sanitizedSegments =
@@ -741,7 +743,7 @@ function cleanGeneratedFiles() {
741
743
  (protectedPath) =>
742
744
  (protectedPath.endsWith("/") ||
743
745
  ["lib", "config", "api/storage"].includes(protectedPath)) &&
744
- relativePath.startsWith(protectedPath),
746
+ relativePath.startsWith(protectedPath)
745
747
  );
746
748
  };
747
749
 
@@ -924,7 +926,7 @@ export default function AdminLayout({
924
926
  fs.writeFileSync(adminLayoutPath, adminLayoutContent, "utf-8");
925
927
  if (isDebugMode) {
926
928
  console.log(
927
- `✅ Generated admin layout with sidebar: ${adminLayoutPath}`,
929
+ `✅ Generated admin layout with sidebar: ${adminLayoutPath}`
928
930
  );
929
931
  }
930
932
  } catch (error) {
@@ -985,7 +987,7 @@ export default realtimeConfig;
985
987
  // Afficher un résumé
986
988
  realtimeConfigs.forEach((module) => {
987
989
  console.log(
988
- ` - ${module.moduleId}: ${module.tables.length} table(s)`,
990
+ ` - ${module.moduleId}: ${module.tables.length} table(s)`
989
991
  );
990
992
  module.tables.forEach((table) => {
991
993
  console.log(` • ${table.schema}.${table.table} (${table.event})`);
@@ -1006,7 +1008,7 @@ async function generateUserTabsConfig(moduleConfigs: ModuleBuildConfig[]) {
1006
1008
  config.userTabs!.map((tab) => ({
1007
1009
  ...tab,
1008
1010
  moduleName: config.moduleName,
1009
- })),
1011
+ }))
1010
1012
  )
1011
1013
  .sort((a, b) => (a.order || 0) - (b.order || 0));
1012
1014
 
@@ -1019,7 +1021,7 @@ async function generateUserTabsConfig(moduleConfigs: ModuleBuildConfig[]) {
1019
1021
  const importsForApp = userTabsConfigs
1020
1022
  .map(
1021
1023
  (tab) =>
1022
- `const ${tab.componentExport} = dynamic(() => import("${tab.moduleName}").then(mod => ({ default: mod.${tab.componentExport} })), { ssr: true });`,
1024
+ `const ${tab.componentExport} = dynamic(() => import("${tab.moduleName}").then(mod => ({ default: mod.${tab.componentExport} })), { ssr: true });`
1023
1025
  )
1024
1026
  .join("\n");
1025
1027
 
@@ -1031,7 +1033,7 @@ async function generateUserTabsConfig(moduleConfigs: ModuleBuildConfig[]) {
1031
1033
  title: "${tab.title}",
1032
1034
  icon: "${tab.icon || ""}",
1033
1035
  component: ${tab.componentExport},
1034
- }`,
1036
+ }`
1035
1037
  )
1036
1038
  .join(",\n");
1037
1039
 
@@ -1071,8 +1073,7 @@ async function generateBucketsConfig(moduleConfigs: ModuleBuildConfig[]) {
1071
1073
  // Extraire les configurations storage des modules
1072
1074
  const allBuckets = moduleConfigs
1073
1075
  .filter(
1074
- (config) =>
1075
- config.storage?.buckets && config.storage.buckets.length > 0,
1076
+ (config) => config.storage?.buckets && config.storage.buckets.length > 0
1076
1077
  )
1077
1078
  .flatMap((config) => config.storage!.buckets);
1078
1079
 
@@ -1208,8 +1209,7 @@ async function generateStorageProxyApi(moduleConfigs: ModuleBuildConfig[]) {
1208
1209
  // Extraire les configurations storage des modules
1209
1210
  const allBuckets = moduleConfigs
1210
1211
  .filter(
1211
- (config) =>
1212
- config.storage?.buckets && config.storage.buckets.length > 0,
1212
+ (config) => config.storage?.buckets && config.storage.buckets.length > 0
1213
1213
  )
1214
1214
  .flatMap((config) => config.storage!.buckets);
1215
1215
 
@@ -1335,7 +1335,7 @@ export async function GET(
1335
1335
  "storage",
1336
1336
  "[bucket]",
1337
1337
  "[...path]",
1338
- "route.ts",
1338
+ "route.ts"
1339
1339
  );
1340
1340
  const outputDir = path.dirname(outputPath);
1341
1341
 
@@ -1350,10 +1350,10 @@ export async function GET(
1350
1350
  if (isDebugMode) {
1351
1351
  console.log(`✅ Generated storage proxy API: ${outputPath}`);
1352
1352
  console.log(
1353
- `📊 Public buckets: ${publicBuckets.map((b) => b.name).join(", ") || "none"}`,
1353
+ `📊 Public buckets: ${publicBuckets.map((b) => b.name).join(", ") || "none"}`
1354
1354
  );
1355
1355
  console.log(
1356
- `📊 Private buckets: ${privateBuckets.map((b) => b.name).join(", ") || "none"}`,
1356
+ `📊 Private buckets: ${privateBuckets.map((b) => b.name).join(", ") || "none"}`
1357
1357
  );
1358
1358
  }
1359
1359
  } catch (error) {
@@ -1370,7 +1370,7 @@ async function generateFooterConfig(moduleConfigs: ModuleBuildConfig[]) {
1370
1370
 
1371
1371
  if (allFooterLinks.length === 0) {
1372
1372
  console.log(
1373
- "⏭️ No footer links found, skipping footer config generation",
1373
+ "⏭️ No footer links found, skipping footer config generation"
1374
1374
  );
1375
1375
  return;
1376
1376
  }
@@ -1436,7 +1436,7 @@ export async function runModuleBuild() {
1436
1436
  moduleConfigs.forEach((moduleConfig) => {
1437
1437
  if (isDebugMode) {
1438
1438
  console.log(
1439
- `📦 Processing module: ${moduleConfig.moduleName} with ${moduleConfig.pages.length} pages`,
1439
+ `📦 Processing module: ${moduleConfig.moduleName} with ${moduleConfig.pages.length} pages`
1440
1440
  );
1441
1441
  }
1442
1442
  moduleConfig.pages.forEach((page) => buildPage(moduleConfig, page));