@lastbrain/app 0.1.25 → 0.1.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app-shell/(public)/page.d.ts.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/layouts/AdminLayoutWithSidebar.d.ts +8 -0
- package/dist/layouts/AdminLayoutWithSidebar.d.ts.map +1 -0
- package/dist/layouts/AdminLayoutWithSidebar.js +9 -0
- package/dist/layouts/AuthLayoutWithSidebar.d.ts +8 -0
- package/dist/layouts/AuthLayoutWithSidebar.d.ts.map +1 -0
- package/dist/layouts/AuthLayoutWithSidebar.js +9 -0
- package/dist/scripts/db-init.js +2 -2
- package/dist/scripts/dev-sync.js +23 -12
- package/dist/scripts/init-app.d.ts.map +1 -1
- package/dist/scripts/init-app.js +114 -12
- package/dist/scripts/module-add.d.ts.map +1 -1
- package/dist/scripts/module-add.js +19 -6
- package/dist/scripts/module-build.d.ts.map +1 -1
- package/dist/scripts/module-build.js +288 -30
- package/dist/scripts/module-create.d.ts.map +1 -1
- package/dist/scripts/module-create.js +25 -15
- package/dist/scripts/module-remove.d.ts.map +1 -1
- package/dist/scripts/module-remove.js +28 -15
- package/dist/scripts/script-runner.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/templates/DefaultDoc.js +1 -7
- package/dist/templates/components/AppAside.d.ts +6 -0
- package/dist/templates/components/AppAside.d.ts.map +1 -0
- package/dist/templates/components/AppAside.js +9 -0
- package/dist/templates/layouts/admin-layout.d.ts +4 -0
- package/dist/templates/layouts/admin-layout.d.ts.map +1 -0
- package/dist/templates/layouts/admin-layout.js +6 -0
- package/dist/templates/layouts/auth-layout.d.ts +4 -0
- package/dist/templates/layouts/auth-layout.d.ts.map +1 -0
- package/dist/templates/layouts/auth-layout.js +6 -0
- package/package.json +2 -1
- package/src/app-shell/(public)/page.tsx +6 -2
- package/src/auth/useAuthSession.ts +1 -1
- package/src/cli.ts +1 -1
- package/src/index.ts +6 -0
- package/src/layouts/AdminLayoutWithSidebar.tsx +35 -0
- package/src/layouts/AppProviders.tsx +1 -1
- package/src/layouts/AuthLayoutWithSidebar.tsx +35 -0
- package/src/scripts/db-init.ts +13 -8
- package/src/scripts/db-migrations-sync.ts +4 -4
- package/src/scripts/dev-sync.ts +50 -19
- package/src/scripts/init-app.ts +243 -65
- package/src/scripts/module-add.ts +54 -22
- package/src/scripts/module-build.ts +412 -88
- package/src/scripts/module-create.ts +85 -49
- package/src/scripts/module-remove.ts +120 -61
- package/src/scripts/readme-build.ts +2 -2
- package/src/scripts/script-runner.ts +3 -3
- package/src/templates/AuthGuidePage.tsx +1 -1
- package/src/templates/DefaultDoc.tsx +7 -7
package/src/scripts/init-app.ts
CHANGED
|
@@ -58,6 +58,15 @@ export async function initApp(options: InitAppOptions) {
|
|
|
58
58
|
withAuth = selectedModules.includes("auth");
|
|
59
59
|
|
|
60
60
|
console.log();
|
|
61
|
+
} else if (!interactive) {
|
|
62
|
+
// En mode non-interactif, installer auth et ai par défaut
|
|
63
|
+
selectedModules.push("auth", "ai");
|
|
64
|
+
withAuth = true;
|
|
65
|
+
console.log(
|
|
66
|
+
chalk.blue(
|
|
67
|
+
"📦 Modules installés par défaut : Authentication, AI Generation\n",
|
|
68
|
+
),
|
|
69
|
+
);
|
|
61
70
|
}
|
|
62
71
|
|
|
63
72
|
// Créer le dossier s'il n'existe pas
|
|
@@ -89,29 +98,34 @@ export async function initApp(options: InitAppOptions) {
|
|
|
89
98
|
await addScriptsToPackageJson(targetDir);
|
|
90
99
|
|
|
91
100
|
// 9. Enregistrer les modules sélectionnés
|
|
92
|
-
if (withAuth
|
|
101
|
+
if (withAuth && !selectedModules.includes("auth")) {
|
|
102
|
+
selectedModules.push("auth");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (selectedModules.length > 0) {
|
|
93
106
|
await saveModulesConfig(targetDir, selectedModules, withAuth);
|
|
94
107
|
}
|
|
95
108
|
|
|
96
109
|
console.log(
|
|
97
|
-
chalk.green("\n✅ Application LastBrain initialisée avec succès!\n")
|
|
110
|
+
chalk.green("\n✅ Application LastBrain initialisée avec succès!\n"),
|
|
98
111
|
);
|
|
99
|
-
|
|
112
|
+
|
|
100
113
|
const relativePath = path.relative(process.cwd(), targetDir);
|
|
101
|
-
|
|
114
|
+
|
|
102
115
|
// Demander si l'utilisateur veut lancer l'installation et le dev server
|
|
103
116
|
const { launchNow } = await inquirer.prompt([
|
|
104
117
|
{
|
|
105
118
|
type: "confirm",
|
|
106
119
|
name: "launchNow",
|
|
107
|
-
message:
|
|
120
|
+
message:
|
|
121
|
+
"Voulez-vous installer les dépendances et lancer le serveur de développement maintenant ?",
|
|
108
122
|
default: true,
|
|
109
123
|
},
|
|
110
124
|
]);
|
|
111
125
|
|
|
112
126
|
if (launchNow) {
|
|
113
127
|
console.log(chalk.yellow("\n📦 Installation des dépendances...\n"));
|
|
114
|
-
|
|
128
|
+
|
|
115
129
|
try {
|
|
116
130
|
execSync("pnpm install", { cwd: targetDir, stdio: "inherit" });
|
|
117
131
|
console.log(chalk.green("\n✓ Dépendances installées\n"));
|
|
@@ -120,52 +134,86 @@ export async function initApp(options: InitAppOptions) {
|
|
|
120
134
|
execSync("pnpm build:modules", { cwd: targetDir, stdio: "inherit" });
|
|
121
135
|
console.log(chalk.green("\n✓ Routes des modules générées\n"));
|
|
122
136
|
|
|
137
|
+
console.log(chalk.yellow("🗄️ Initialisation de la base de données...\n"));
|
|
138
|
+
try {
|
|
139
|
+
execSync("pnpm db:init", { cwd: targetDir, stdio: "inherit" });
|
|
140
|
+
console.log(chalk.green("\n✓ Base de données initialisée\n"));
|
|
141
|
+
} catch {
|
|
142
|
+
console.log(
|
|
143
|
+
chalk.yellow(
|
|
144
|
+
"\n⚠️ Erreur d'initialisation de la DB (normal si Supabase pas configuré)\n",
|
|
145
|
+
),
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
123
149
|
// Détecter le port (par défaut 3000 pour Next.js)
|
|
124
150
|
const port = 3000;
|
|
125
151
|
const url = `http://127.0.0.1:${port}`;
|
|
126
152
|
|
|
127
|
-
console.log(
|
|
153
|
+
console.log(
|
|
154
|
+
chalk.yellow("🚀 Lancement du serveur de développement...\n"),
|
|
155
|
+
);
|
|
128
156
|
console.log(chalk.cyan(`📱 Ouvrez votre navigateur sur : ${url}\n`));
|
|
129
|
-
|
|
157
|
+
|
|
130
158
|
console.log(chalk.blue("\n📋 Prochaines étapes après le démarrage :"));
|
|
131
|
-
console.log(
|
|
159
|
+
console.log(
|
|
160
|
+
chalk.white(" 1. Cliquez sur 'Get Started' sur la page d'accueil"),
|
|
161
|
+
);
|
|
132
162
|
console.log(chalk.white(" 2. Lancez Docker Desktop"));
|
|
133
|
-
console.log(
|
|
163
|
+
console.log(
|
|
164
|
+
chalk.white(
|
|
165
|
+
" 3. Installez Supabase CLI si nécessaire : brew install supabase/tap/supabase",
|
|
166
|
+
),
|
|
167
|
+
);
|
|
134
168
|
console.log(chalk.white(" 4. Exécutez : pnpm db:init"));
|
|
135
169
|
console.log(chalk.white(" 5. Rechargez la page\n"));
|
|
136
170
|
|
|
137
171
|
// Ouvrir le navigateur
|
|
138
|
-
const openCommand =
|
|
172
|
+
const openCommand =
|
|
173
|
+
process.platform === "darwin"
|
|
174
|
+
? "open"
|
|
175
|
+
: process.platform === "win32"
|
|
176
|
+
? "start"
|
|
177
|
+
: "xdg-open";
|
|
139
178
|
setTimeout(() => {
|
|
140
179
|
try {
|
|
141
180
|
execSync(`${openCommand} ${url}`, { stdio: "ignore" });
|
|
142
|
-
} catch
|
|
181
|
+
} catch {
|
|
143
182
|
// Ignorer les erreurs d'ouverture du navigateur
|
|
144
183
|
}
|
|
145
184
|
}, 2000);
|
|
146
185
|
|
|
147
186
|
// Lancer pnpm dev
|
|
148
187
|
execSync("pnpm dev", { cwd: targetDir, stdio: "inherit" });
|
|
149
|
-
} catch
|
|
188
|
+
} catch {
|
|
150
189
|
console.error(chalk.red("\n❌ Erreur lors du lancement\n"));
|
|
151
190
|
console.log(chalk.cyan("\nVous pouvez lancer manuellement avec :"));
|
|
152
191
|
console.log(chalk.white(` cd ${relativePath}`));
|
|
153
192
|
console.log(chalk.white(" pnpm install"));
|
|
154
193
|
console.log(chalk.white(" pnpm build:modules"));
|
|
194
|
+
console.log(chalk.white(" pnpm db:init"));
|
|
155
195
|
console.log(chalk.white(" pnpm dev\n"));
|
|
156
196
|
}
|
|
157
197
|
} else {
|
|
158
198
|
console.log(chalk.cyan("\n📋 Prochaines étapes:"));
|
|
159
199
|
console.log(chalk.white(" 1. cd " + relativePath));
|
|
160
200
|
console.log(chalk.white(" 2. pnpm install (installer les dépendances)"));
|
|
161
|
-
console.log(
|
|
201
|
+
console.log(
|
|
202
|
+
chalk.white(" 3. pnpm build:modules (générer les routes des modules)"),
|
|
203
|
+
);
|
|
204
|
+
console.log(
|
|
205
|
+
chalk.white(" 4. pnpm db:init (initialiser la base de données)"),
|
|
206
|
+
);
|
|
207
|
+
console.log(chalk.white(" 5. pnpm dev (lancer le serveur)"));
|
|
162
208
|
console.log(chalk.white(" 4. pnpm db:init (initialiser Supabase)"));
|
|
163
209
|
console.log(chalk.white(" 5. pnpm dev (démarrer le serveur)\n"));
|
|
164
|
-
|
|
210
|
+
|
|
165
211
|
console.log(chalk.gray("Prérequis pour Supabase :"));
|
|
166
212
|
console.log(chalk.white(" - Docker Desktop installé et lancé"));
|
|
167
|
-
console.log(
|
|
168
|
-
|
|
213
|
+
console.log(
|
|
214
|
+
chalk.white(" - Supabase CLI : brew install supabase/tap/supabase\n"),
|
|
215
|
+
);
|
|
216
|
+
|
|
169
217
|
// Afficher la commande cd pour faciliter la copie
|
|
170
218
|
console.log(chalk.gray("Pour vous déplacer dans le projet :"));
|
|
171
219
|
console.log(chalk.cyan(` cd ${relativePath}\n`));
|
|
@@ -204,8 +252,11 @@ function getLastBrainVersions(targetDir: string): {
|
|
|
204
252
|
ui: string;
|
|
205
253
|
moduleAuth: string;
|
|
206
254
|
} {
|
|
207
|
-
const targetIsInMonorepo =
|
|
208
|
-
|
|
255
|
+
const targetIsInMonorepo =
|
|
256
|
+
fs.existsSync(
|
|
257
|
+
path.join(targetDir, "../../../packages/core/package.json"),
|
|
258
|
+
) ||
|
|
259
|
+
fs.existsSync(path.join(targetDir, "../../packages/core/package.json"));
|
|
209
260
|
|
|
210
261
|
if (targetIsInMonorepo) {
|
|
211
262
|
// Dans le monorepo, utiliser workspace:*
|
|
@@ -221,16 +272,16 @@ function getLastBrainVersions(targetDir: string): {
|
|
|
221
272
|
try {
|
|
222
273
|
// Essayer de lire depuis node_modules/@lastbrain (si init-app a été installé)
|
|
223
274
|
const appPkgPath = path.join(__dirname, "../../package.json");
|
|
224
|
-
|
|
275
|
+
|
|
225
276
|
if (fs.existsSync(appPkgPath)) {
|
|
226
277
|
const appPkg = JSON.parse(fs.readFileSync(appPkgPath, "utf-8"));
|
|
227
278
|
const appVersion = `^${appPkg.version}`;
|
|
228
|
-
|
|
279
|
+
|
|
229
280
|
// Lire les versions des dépendances de @lastbrain/app
|
|
230
281
|
const coreDep = appPkg.dependencies?.["@lastbrain/core"];
|
|
231
282
|
const uiDep = appPkg.dependencies?.["@lastbrain/ui"];
|
|
232
283
|
const authDep = appPkg.dependencies?.["@lastbrain/module-auth"];
|
|
233
|
-
|
|
284
|
+
|
|
234
285
|
return {
|
|
235
286
|
app: appVersion,
|
|
236
287
|
core: coreDep || appVersion,
|
|
@@ -238,8 +289,12 @@ function getLastBrainVersions(targetDir: string): {
|
|
|
238
289
|
moduleAuth: authDep || appVersion,
|
|
239
290
|
};
|
|
240
291
|
}
|
|
241
|
-
} catch
|
|
242
|
-
console.warn(
|
|
292
|
+
} catch {
|
|
293
|
+
console.warn(
|
|
294
|
+
chalk.yellow(
|
|
295
|
+
"⚠️ Impossible de lire les versions locales, utilisation de 'latest'",
|
|
296
|
+
),
|
|
297
|
+
);
|
|
243
298
|
}
|
|
244
299
|
|
|
245
300
|
// Fallback: utiliser "latest"
|
|
@@ -255,7 +310,7 @@ async function addDependencies(
|
|
|
255
310
|
targetDir: string,
|
|
256
311
|
useHeroUI: boolean,
|
|
257
312
|
withAuth: boolean,
|
|
258
|
-
selectedModules: string[] = []
|
|
313
|
+
selectedModules: string[] = [],
|
|
259
314
|
) {
|
|
260
315
|
const pkgPath = path.join(targetDir, "package.json");
|
|
261
316
|
const pkg = await fs.readJson(pkgPath);
|
|
@@ -263,7 +318,7 @@ async function addDependencies(
|
|
|
263
318
|
console.log(chalk.yellow("\n📦 Configuration des dépendances..."));
|
|
264
319
|
|
|
265
320
|
const versions = getLastBrainVersions(targetDir);
|
|
266
|
-
|
|
321
|
+
|
|
267
322
|
// Dependencies
|
|
268
323
|
const requiredDeps: Record<string, string> = {
|
|
269
324
|
next: "^15.0.3",
|
|
@@ -282,7 +337,7 @@ async function addDependencies(
|
|
|
282
337
|
|
|
283
338
|
// Ajouter les autres modules sélectionnés
|
|
284
339
|
for (const moduleName of selectedModules) {
|
|
285
|
-
const moduleInfo = AVAILABLE_MODULES.find(m => m.name === moduleName);
|
|
340
|
+
const moduleInfo = AVAILABLE_MODULES.find((m) => m.name === moduleName);
|
|
286
341
|
if (moduleInfo && moduleInfo.package !== "@lastbrain/module-auth") {
|
|
287
342
|
// Pour les autres modules, utiliser "latest" ou la version depuis le package
|
|
288
343
|
requiredDeps[moduleInfo.package] = versions.app; // Utiliser la même version que app
|
|
@@ -359,7 +414,7 @@ async function createNextStructure(
|
|
|
359
414
|
targetDir: string,
|
|
360
415
|
force: boolean,
|
|
361
416
|
useHeroUI: boolean,
|
|
362
|
-
withAuth: boolean
|
|
417
|
+
withAuth: boolean,
|
|
363
418
|
) {
|
|
364
419
|
console.log(chalk.yellow("\n📁 Création de la structure Next.js..."));
|
|
365
420
|
|
|
@@ -456,7 +511,9 @@ export default function RootLayout({ children }: PropsWithChildren<{}>) {
|
|
|
456
511
|
console.log(chalk.green("✓ app/layout.tsx créé"));
|
|
457
512
|
} else {
|
|
458
513
|
console.log(
|
|
459
|
-
chalk.gray(
|
|
514
|
+
chalk.gray(
|
|
515
|
+
" app/layout.tsx existe déjà (utilisez --force pour écraser)",
|
|
516
|
+
),
|
|
460
517
|
);
|
|
461
518
|
}
|
|
462
519
|
|
|
@@ -524,17 +581,21 @@ export default function NotFound() {
|
|
|
524
581
|
|
|
525
582
|
// Créer les routes avec leurs layouts
|
|
526
583
|
await createRoute(appDir, "admin", "admin", force);
|
|
584
|
+
await createRoute(appDir, "auth", "auth", force);
|
|
527
585
|
await createRoute(appDir, "docs", "public", force);
|
|
528
586
|
|
|
529
587
|
// Créer le composant AppHeader
|
|
530
588
|
await createAppHeader(targetDir, force);
|
|
589
|
+
|
|
590
|
+
// Créer le composant AppAside
|
|
591
|
+
await createAppAside(targetDir, force);
|
|
531
592
|
}
|
|
532
593
|
|
|
533
594
|
async function createRoute(
|
|
534
595
|
appDir: string,
|
|
535
596
|
routeName: string,
|
|
536
597
|
layoutType: string,
|
|
537
|
-
force: boolean
|
|
598
|
+
force: boolean,
|
|
538
599
|
) {
|
|
539
600
|
const routeDir = path.join(appDir, routeName);
|
|
540
601
|
await fs.ensureDir(routeDir);
|
|
@@ -542,13 +603,49 @@ async function createRoute(
|
|
|
542
603
|
// Layout pour la route
|
|
543
604
|
const layoutPath = path.join(routeDir, "layout.tsx");
|
|
544
605
|
if (!fs.existsSync(layoutPath) || force) {
|
|
545
|
-
|
|
546
|
-
layoutType.charAt(0).toUpperCase() + layoutType.slice(1) + "Layout";
|
|
606
|
+
let layoutContent = "";
|
|
547
607
|
|
|
548
|
-
|
|
608
|
+
if (routeName === "admin") {
|
|
609
|
+
// Layout admin avec sidebar
|
|
610
|
+
layoutContent = `import { AdminLayoutWithSidebar } from "@lastbrain/app";
|
|
611
|
+
import { menuConfig } from "../../config/menu";
|
|
612
|
+
|
|
613
|
+
export default function AdminLayout({
|
|
614
|
+
children,
|
|
615
|
+
}: {
|
|
616
|
+
children: React.ReactNode;
|
|
617
|
+
}) {
|
|
618
|
+
return (
|
|
619
|
+
<AdminLayoutWithSidebar menuConfig={menuConfig}>
|
|
620
|
+
{children}
|
|
621
|
+
</AdminLayoutWithSidebar>
|
|
622
|
+
);
|
|
623
|
+
}`;
|
|
624
|
+
} else if (routeName === "auth") {
|
|
625
|
+
// Layout auth avec sidebar
|
|
626
|
+
layoutContent = `import { AuthLayoutWithSidebar } from "@lastbrain/app";
|
|
627
|
+
import { menuConfig } from "../../config/menu";
|
|
628
|
+
|
|
629
|
+
export default function AuthLayout({
|
|
630
|
+
children,
|
|
631
|
+
}: {
|
|
632
|
+
children: React.ReactNode;
|
|
633
|
+
}) {
|
|
634
|
+
return (
|
|
635
|
+
<AuthLayoutWithSidebar menuConfig={menuConfig}>
|
|
636
|
+
{children}
|
|
637
|
+
</AuthLayoutWithSidebar>
|
|
638
|
+
);
|
|
639
|
+
}`;
|
|
640
|
+
} else {
|
|
641
|
+
// Layout standard pour les autres routes
|
|
642
|
+
const layoutComponent =
|
|
643
|
+
layoutType.charAt(0).toUpperCase() + layoutType.slice(1) + "Layout";
|
|
644
|
+
layoutContent = `import { ${layoutComponent} } from "@lastbrain/app";
|
|
645
|
+
|
|
646
|
+
export default ${layoutComponent};`;
|
|
647
|
+
}
|
|
549
648
|
|
|
550
|
-
export default ${layoutComponent};
|
|
551
|
-
`;
|
|
552
649
|
await fs.writeFile(layoutPath, layoutContent);
|
|
553
650
|
console.log(chalk.green(`✓ app/${routeName}/layout.tsx créé`));
|
|
554
651
|
}
|
|
@@ -616,7 +713,7 @@ async function createAppHeader(targetDir: string, force: boolean) {
|
|
|
616
713
|
await fs.ensureDir(componentsDir);
|
|
617
714
|
|
|
618
715
|
const headerPath = path.join(componentsDir, "AppHeader.tsx");
|
|
619
|
-
|
|
716
|
+
|
|
620
717
|
if (!fs.existsSync(headerPath) || force) {
|
|
621
718
|
const headerContent = `"use client";
|
|
622
719
|
|
|
@@ -652,7 +749,49 @@ export function AppHeader() {
|
|
|
652
749
|
console.log(chalk.green("✓ components/AppHeader.tsx créé"));
|
|
653
750
|
} else {
|
|
654
751
|
console.log(
|
|
655
|
-
chalk.gray(
|
|
752
|
+
chalk.gray(
|
|
753
|
+
" components/AppHeader.tsx existe déjà (utilisez --force pour écraser)",
|
|
754
|
+
),
|
|
755
|
+
);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
async function createAppAside(targetDir: string, force: boolean) {
|
|
760
|
+
const componentsDir = path.join(targetDir, "components");
|
|
761
|
+
await fs.ensureDir(componentsDir);
|
|
762
|
+
|
|
763
|
+
const asidePath = path.join(componentsDir, "AppAside.tsx");
|
|
764
|
+
if (!fs.existsSync(asidePath) || force) {
|
|
765
|
+
const asideContent = `"use client";
|
|
766
|
+
|
|
767
|
+
import { AppAside as UIAppAside } from "@lastbrain/app";
|
|
768
|
+
import { useAuthSession } from "@lastbrain/app";
|
|
769
|
+
import { menuConfig } from "../config/menu";
|
|
770
|
+
|
|
771
|
+
interface AppAsideProps {
|
|
772
|
+
className?: string;
|
|
773
|
+
isVisible?: boolean;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
export function AppAside({ className = "", isVisible = true }: AppAsideProps) {
|
|
777
|
+
const { isSuperAdmin } = useAuthSession();
|
|
778
|
+
|
|
779
|
+
return (
|
|
780
|
+
<UIAppAside
|
|
781
|
+
className={className}
|
|
782
|
+
menuConfig={menuConfig}
|
|
783
|
+
isSuperAdmin={isSuperAdmin}
|
|
784
|
+
isVisible={isVisible}
|
|
785
|
+
/>
|
|
786
|
+
);
|
|
787
|
+
}`;
|
|
788
|
+
await fs.writeFile(asidePath, asideContent);
|
|
789
|
+
console.log(chalk.green("✓ components/AppAside.tsx créé"));
|
|
790
|
+
} else {
|
|
791
|
+
console.log(
|
|
792
|
+
chalk.gray(
|
|
793
|
+
" components/AppAside.tsx existe déjà (utilisez --force pour écraser)",
|
|
794
|
+
),
|
|
656
795
|
);
|
|
657
796
|
}
|
|
658
797
|
}
|
|
@@ -660,7 +799,7 @@ export function AppHeader() {
|
|
|
660
799
|
async function createConfigFiles(
|
|
661
800
|
targetDir: string,
|
|
662
801
|
force: boolean,
|
|
663
|
-
useHeroUI: boolean
|
|
802
|
+
useHeroUI: boolean,
|
|
664
803
|
) {
|
|
665
804
|
console.log(chalk.yellow("\n⚙️ Création des fichiers de configuration..."));
|
|
666
805
|
|
|
@@ -745,7 +884,9 @@ export const config = {
|
|
|
745
884
|
};
|
|
746
885
|
`;
|
|
747
886
|
await fs.writeFile(middlewarePath, middleware);
|
|
748
|
-
console.log(
|
|
887
|
+
console.log(
|
|
888
|
+
chalk.green("✓ middleware.ts créé (protection /auth/* et /admin/*)"),
|
|
889
|
+
);
|
|
749
890
|
}
|
|
750
891
|
|
|
751
892
|
// next.config.mjs
|
|
@@ -904,7 +1045,7 @@ async function createGitIgnore(targetDir: string, force: boolean) {
|
|
|
904
1045
|
// Copier le fichier .gitignore depuis le template
|
|
905
1046
|
const templateGitignorePath = path.join(
|
|
906
1047
|
__dirname,
|
|
907
|
-
"../templates/gitignore/.gitignore"
|
|
1048
|
+
"../templates/gitignore/.gitignore",
|
|
908
1049
|
);
|
|
909
1050
|
|
|
910
1051
|
if (fs.existsSync(templateGitignorePath)) {
|
|
@@ -1012,35 +1153,48 @@ async function createSupabaseStructure(targetDir: string, force: boolean) {
|
|
|
1012
1153
|
// Copier le fichier de migration initial depuis le template
|
|
1013
1154
|
const templateMigrationPath = path.join(
|
|
1014
1155
|
__dirname,
|
|
1015
|
-
"../templates/migrations/20201010100000_app_base.sql"
|
|
1156
|
+
"../templates/migrations/20201010100000_app_base.sql",
|
|
1016
1157
|
);
|
|
1017
1158
|
const migrationDestPath = path.join(
|
|
1018
1159
|
migrationsDir,
|
|
1019
|
-
"20201010100000_app_base.sql"
|
|
1160
|
+
"20201010100000_app_base.sql",
|
|
1020
1161
|
);
|
|
1021
1162
|
|
|
1022
1163
|
if (!fs.existsSync(migrationDestPath) || force) {
|
|
1023
1164
|
try {
|
|
1024
1165
|
if (fs.existsSync(templateMigrationPath)) {
|
|
1025
1166
|
await fs.copy(templateMigrationPath, migrationDestPath);
|
|
1026
|
-
console.log(
|
|
1167
|
+
console.log(
|
|
1168
|
+
chalk.green("✓ supabase/migrations/20201010100000_app_base.sql créé"),
|
|
1169
|
+
);
|
|
1027
1170
|
} else {
|
|
1028
1171
|
console.log(
|
|
1029
1172
|
chalk.yellow(
|
|
1030
|
-
"⚠ Template de migration introuvable, création d'un fichier vide"
|
|
1031
|
-
)
|
|
1173
|
+
"⚠ Template de migration introuvable, création d'un fichier vide",
|
|
1174
|
+
),
|
|
1032
1175
|
);
|
|
1033
1176
|
await fs.writeFile(
|
|
1034
1177
|
migrationDestPath,
|
|
1035
|
-
"-- Initial migration\n-- Add your database schema here\n"
|
|
1178
|
+
"-- Initial migration\n-- Add your database schema here\n",
|
|
1179
|
+
);
|
|
1180
|
+
console.log(
|
|
1181
|
+
chalk.green(
|
|
1182
|
+
"✓ supabase/migrations/20201010100000_app_base.sql créé (vide)",
|
|
1183
|
+
),
|
|
1036
1184
|
);
|
|
1037
|
-
console.log(chalk.green("✓ supabase/migrations/20201010100000_app_base.sql créé (vide)"));
|
|
1038
1185
|
}
|
|
1039
1186
|
} catch (error) {
|
|
1040
|
-
console.error(
|
|
1187
|
+
console.error(
|
|
1188
|
+
chalk.red("✗ Erreur lors de la création de la migration:"),
|
|
1189
|
+
error,
|
|
1190
|
+
);
|
|
1041
1191
|
}
|
|
1042
1192
|
} else {
|
|
1043
|
-
console.log(
|
|
1193
|
+
console.log(
|
|
1194
|
+
chalk.gray(
|
|
1195
|
+
" supabase/migrations/20201010100000_app_base.sql existe déjà",
|
|
1196
|
+
),
|
|
1197
|
+
);
|
|
1044
1198
|
}
|
|
1045
1199
|
}
|
|
1046
1200
|
|
|
@@ -1051,25 +1205,30 @@ async function addScriptsToPackageJson(targetDir: string) {
|
|
|
1051
1205
|
const pkg = await fs.readJson(pkgPath);
|
|
1052
1206
|
|
|
1053
1207
|
// Détecter si le projet cible est dans un workspace
|
|
1054
|
-
const targetIsInMonorepo =
|
|
1055
|
-
|
|
1208
|
+
const targetIsInMonorepo =
|
|
1209
|
+
fs.existsSync(
|
|
1210
|
+
path.join(targetDir, "../../../packages/core/package.json"),
|
|
1211
|
+
) ||
|
|
1212
|
+
fs.existsSync(path.join(targetDir, "../../packages/core/package.json"));
|
|
1056
1213
|
|
|
1057
1214
|
let scriptsPrefix = "lastbrain";
|
|
1058
|
-
|
|
1215
|
+
|
|
1059
1216
|
if (!targetIsInMonorepo) {
|
|
1060
1217
|
// Hors monorepo, utiliser le chemin direct vers le CLI
|
|
1061
1218
|
scriptsPrefix = "node node_modules/@lastbrain/app/dist/cli.js";
|
|
1062
1219
|
}
|
|
1063
1220
|
|
|
1064
1221
|
const scripts = {
|
|
1065
|
-
predev: targetIsInMonorepo
|
|
1222
|
+
predev: targetIsInMonorepo
|
|
1066
1223
|
? "pnpm --filter @lastbrain/core build && pnpm --filter @lastbrain/ui build && pnpm --filter @lastbrain/module-auth build && pnpm --filter @lastbrain/module-ai build"
|
|
1067
1224
|
: "echo 'No prebuild needed outside monorepo'",
|
|
1068
1225
|
dev: "next dev",
|
|
1069
1226
|
build: "next build",
|
|
1070
1227
|
start: "next start",
|
|
1071
1228
|
lint: "next lint",
|
|
1072
|
-
lastbrain: targetIsInMonorepo
|
|
1229
|
+
lastbrain: targetIsInMonorepo
|
|
1230
|
+
? "lastbrain"
|
|
1231
|
+
: "node node_modules/@lastbrain/app/dist/cli.js",
|
|
1073
1232
|
"build:modules": `${scriptsPrefix} module:build`,
|
|
1074
1233
|
"db:migrations:sync": `${scriptsPrefix} db:migrations:sync`,
|
|
1075
1234
|
"db:init": `${scriptsPrefix} db:init`,
|
|
@@ -1085,26 +1244,36 @@ async function addScriptsToPackageJson(targetDir: string) {
|
|
|
1085
1244
|
async function saveModulesConfig(
|
|
1086
1245
|
targetDir: string,
|
|
1087
1246
|
selectedModules: string[],
|
|
1088
|
-
withAuth: boolean
|
|
1247
|
+
withAuth: boolean,
|
|
1089
1248
|
) {
|
|
1090
1249
|
const modulesConfigPath = path.join(targetDir, ".lastbrain", "modules.json");
|
|
1091
1250
|
await fs.ensureDir(path.dirname(modulesConfigPath));
|
|
1092
1251
|
|
|
1093
|
-
const modules: Array<{
|
|
1252
|
+
const modules: Array<{
|
|
1253
|
+
package: string;
|
|
1254
|
+
active: boolean;
|
|
1255
|
+
migrations?: string[];
|
|
1256
|
+
}> = [];
|
|
1094
1257
|
|
|
1095
1258
|
// Ajouter TOUS les modules disponibles
|
|
1096
1259
|
for (const availableModule of AVAILABLE_MODULES) {
|
|
1097
|
-
const isSelected =
|
|
1098
|
-
|
|
1260
|
+
const isSelected =
|
|
1261
|
+
selectedModules.includes(availableModule.name) ||
|
|
1262
|
+
(withAuth && availableModule.name === "auth");
|
|
1263
|
+
|
|
1099
1264
|
// Vérifier si le module a des migrations
|
|
1100
1265
|
const modulePath = path.join(
|
|
1101
1266
|
targetDir,
|
|
1102
1267
|
"node_modules",
|
|
1103
|
-
...availableModule.package.split("/")
|
|
1268
|
+
...availableModule.package.split("/"),
|
|
1104
1269
|
);
|
|
1105
1270
|
const migrationsDir = path.join(modulePath, "supabase", "migrations");
|
|
1106
|
-
|
|
1107
|
-
const moduleConfig: {
|
|
1271
|
+
|
|
1272
|
+
const moduleConfig: {
|
|
1273
|
+
package: string;
|
|
1274
|
+
active: boolean;
|
|
1275
|
+
migrations?: string[];
|
|
1276
|
+
} = {
|
|
1108
1277
|
package: availableModule.package,
|
|
1109
1278
|
active: isSelected,
|
|
1110
1279
|
};
|
|
@@ -1113,7 +1282,7 @@ async function saveModulesConfig(
|
|
|
1113
1282
|
const migrationFiles = fs
|
|
1114
1283
|
.readdirSync(migrationsDir)
|
|
1115
1284
|
.filter((f) => f.endsWith(".sql"));
|
|
1116
|
-
|
|
1285
|
+
|
|
1117
1286
|
if (migrationFiles.length > 0) {
|
|
1118
1287
|
moduleConfig.migrations = isSelected ? migrationFiles : [];
|
|
1119
1288
|
}
|
|
@@ -1341,9 +1510,16 @@ export function isPrivateBucket(bucket: string): boolean {
|
|
|
1341
1510
|
}
|
|
1342
1511
|
|
|
1343
1512
|
// 3. Créer app/api/storage/[bucket]/[...path]/route.ts
|
|
1344
|
-
const apiStorageDir = path.join(
|
|
1513
|
+
const apiStorageDir = path.join(
|
|
1514
|
+
targetDir,
|
|
1515
|
+
"app",
|
|
1516
|
+
"api",
|
|
1517
|
+
"storage",
|
|
1518
|
+
"[bucket]",
|
|
1519
|
+
"[...path]",
|
|
1520
|
+
);
|
|
1345
1521
|
await fs.ensureDir(apiStorageDir);
|
|
1346
|
-
|
|
1522
|
+
|
|
1347
1523
|
const routePath = path.join(apiStorageDir, "route.ts");
|
|
1348
1524
|
if (!fs.existsSync(routePath) || force) {
|
|
1349
1525
|
const routeContent = `import { NextRequest, NextResponse } from "next/server";
|
|
@@ -1466,7 +1642,9 @@ export async function GET(
|
|
|
1466
1642
|
}`;
|
|
1467
1643
|
|
|
1468
1644
|
await fs.writeFile(routePath, routeContent);
|
|
1469
|
-
console.log(
|
|
1645
|
+
console.log(
|
|
1646
|
+
chalk.green("✓ app/api/storage/[bucket]/[...path]/route.ts créé"),
|
|
1647
|
+
);
|
|
1470
1648
|
}
|
|
1471
1649
|
|
|
1472
1650
|
console.log(chalk.green("✓ Système de proxy storage configuré"));
|