@lastbrain/app 0.1.43 → 0.1.44
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.
- package/dist/__tests__/module-registry.test.js +1 -1
- package/dist/layouts/AdminLayoutWithSidebar.d.ts +2 -1
- package/dist/layouts/AdminLayoutWithSidebar.d.ts.map +1 -1
- package/dist/layouts/AdminLayoutWithSidebar.js +10 -4
- package/dist/layouts/AuthLayoutWithSidebar.d.ts +2 -1
- package/dist/layouts/AuthLayoutWithSidebar.d.ts.map +1 -1
- package/dist/layouts/AuthLayoutWithSidebar.js +10 -4
- package/dist/layouts/PublicLayout.d.ts +2 -1
- package/dist/layouts/PublicLayout.d.ts.map +1 -1
- package/dist/layouts/PublicLayoutWithSidebar.d.ts +2 -1
- package/dist/layouts/PublicLayoutWithSidebar.d.ts.map +1 -1
- package/dist/layouts/PublicLayoutWithSidebar.js +10 -4
- package/dist/scripts/db-migrations-sync.js +67 -38
- package/dist/scripts/dev-sync.js +1 -0
- package/dist/scripts/init-app.d.ts.map +1 -1
- package/dist/scripts/init-app.js +41 -9
- package/dist/scripts/module-build.d.ts.map +1 -1
- package/dist/scripts/module-build.js +15 -5
- package/dist/scripts/module-create.d.ts.map +1 -1
- package/dist/scripts/module-create.js +19 -0
- package/dist/scripts/module-delete.d.ts.map +1 -1
- package/dist/scripts/module-delete.js +6 -2
- package/dist/scripts/module-list.d.ts.map +1 -1
- package/dist/scripts/module-list.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/templates/DefaultDoc.d.ts.map +1 -1
- package/dist/templates/DefaultDoc.js +6 -13
- package/dist/templates/DocPage.d.ts.map +1 -1
- package/dist/templates/DocPage.js +3 -5
- package/dist/templates/SimpleDocPage.js +2 -2
- package/dist/templates/SimpleHomePage.js +1 -1
- package/package.json +7 -2
- package/src/__tests__/module-registry.test.ts +1 -1
- package/src/layouts/AdminLayoutWithSidebar.tsx +13 -6
- package/src/layouts/AuthLayoutWithSidebar.tsx +13 -6
- package/src/layouts/PublicLayout.tsx +2 -2
- package/src/layouts/PublicLayoutWithSidebar.tsx +13 -6
- package/src/scripts/db-migrations-sync.ts +86 -57
- package/src/scripts/dev-sync.ts +1 -0
- package/src/scripts/init-app.ts +47 -9
- package/src/scripts/module-build.ts +17 -5
- package/src/scripts/module-create.ts +25 -2
- package/src/scripts/module-delete.ts +8 -6
- package/src/scripts/module-list.ts +1 -4
- package/src/templates/DefaultDoc.tsx +346 -492
- package/src/templates/DocPage.tsx +37 -19
- package/src/templates/SimpleDocPage.tsx +2 -2
- package/src/templates/SimpleHomePage.tsx +3 -3
package/src/scripts/init-app.ts
CHANGED
|
@@ -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:
|
|
225
|
+
chalk.white(" 4. pnpm db:migrations:sync (synchroniser les migrations)"),
|
|
210
226
|
);
|
|
211
|
-
console.log(
|
|
212
|
-
|
|
213
|
-
|
|
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 /
|
|
1034
|
+
// Pas de session → nettoyage des cookies + redirection vers /signin
|
|
1000
1035
|
if (!session) {
|
|
1001
|
-
const redirectUrl = new 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("/
|
|
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 /
|
|
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("/
|
|
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
|
-
|
|
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,10 @@ 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-pro)
|
|
163
167
|
const modulePrefix = moduleConfig.moduleName
|
|
164
168
|
.replace(/^@lastbrain\/module-/, "")
|
|
169
|
+
.replace(/^@lastbrain-labs\/module-/, "")
|
|
165
170
|
.toLowerCase();
|
|
166
171
|
|
|
167
172
|
if (isDebugMode) {
|
|
@@ -593,7 +598,14 @@ function generateDocsPage(moduleConfigs: ModuleBuildConfig[]) {
|
|
|
593
598
|
|
|
594
599
|
allModules.forEach((moduleEntry) => {
|
|
595
600
|
const moduleName = moduleEntry.package;
|
|
596
|
-
|
|
601
|
+
// Extraire le nom du module sans le scope et sans "module-"
|
|
602
|
+
// Ex: @lastbrain/module-auth -> auth
|
|
603
|
+
// Ex: @lastbrain-labs/module-recipes-pro -> recipes
|
|
604
|
+
const moduleId = moduleName
|
|
605
|
+
.replace("@lastbrain-labs/module-", "")
|
|
606
|
+
.replace("@lastbrain/module-", "")
|
|
607
|
+
.replace(/-pro$/, ""); // Retirer le suffix -pro pour avoir le nom de base
|
|
608
|
+
|
|
597
609
|
const docComponentName = `${toPascalCase(moduleId)}ModuleDoc`;
|
|
598
610
|
|
|
599
611
|
// Trouver la config du module pour obtenir la description
|
|
@@ -610,8 +622,8 @@ function generateDocsPage(moduleConfigs: ModuleBuildConfig[]) {
|
|
|
610
622
|
}
|
|
611
623
|
|
|
612
624
|
const config = {
|
|
613
|
-
id:
|
|
614
|
-
name: `Module ${
|
|
625
|
+
id: moduleName, // Utiliser le nom complet du package comme ID
|
|
626
|
+
name: `Module ${toPascalCase(moduleId)}`,
|
|
615
627
|
description: description,
|
|
616
628
|
component: docComponentName,
|
|
617
629
|
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(
|
|
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: "
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
"
|
|
79
|
-
|
|
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"));
|