@lastbrain/app 0.1.42 → 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.
Files changed (55) hide show
  1. package/dist/__tests__/module-registry.test.js +1 -1
  2. package/dist/layouts/AdminLayout.d.ts.map +1 -1
  3. package/dist/layouts/AdminLayout.js +0 -1
  4. package/dist/layouts/AdminLayoutWithSidebar.d.ts +2 -1
  5. package/dist/layouts/AdminLayoutWithSidebar.d.ts.map +1 -1
  6. package/dist/layouts/AdminLayoutWithSidebar.js +10 -4
  7. package/dist/layouts/AuthLayout.d.ts.map +1 -1
  8. package/dist/layouts/AuthLayout.js +0 -1
  9. package/dist/layouts/AuthLayoutWithSidebar.d.ts +2 -1
  10. package/dist/layouts/AuthLayoutWithSidebar.d.ts.map +1 -1
  11. package/dist/layouts/AuthLayoutWithSidebar.js +10 -4
  12. package/dist/layouts/PublicLayout.d.ts +6 -2
  13. package/dist/layouts/PublicLayout.d.ts.map +1 -1
  14. package/dist/layouts/PublicLayout.js +4 -3
  15. package/dist/layouts/PublicLayoutWithSidebar.d.ts +2 -1
  16. package/dist/layouts/PublicLayoutWithSidebar.d.ts.map +1 -1
  17. package/dist/layouts/PublicLayoutWithSidebar.js +10 -4
  18. package/dist/scripts/db-migrations-sync.js +67 -38
  19. package/dist/scripts/dev-sync.js +1 -0
  20. package/dist/scripts/init-app.d.ts.map +1 -1
  21. package/dist/scripts/init-app.js +172 -59
  22. package/dist/scripts/module-build.d.ts.map +1 -1
  23. package/dist/scripts/module-build.js +67 -6
  24. package/dist/scripts/module-create.d.ts.map +1 -1
  25. package/dist/scripts/module-create.js +19 -0
  26. package/dist/scripts/module-delete.d.ts.map +1 -1
  27. package/dist/scripts/module-delete.js +6 -2
  28. package/dist/scripts/module-list.d.ts.map +1 -1
  29. package/dist/scripts/module-list.js +1 -1
  30. package/dist/styles.css +1 -1
  31. package/dist/templates/DefaultDoc.d.ts.map +1 -1
  32. package/dist/templates/DefaultDoc.js +6 -13
  33. package/dist/templates/DocPage.d.ts.map +1 -1
  34. package/dist/templates/DocPage.js +3 -5
  35. package/dist/templates/SimpleDocPage.js +2 -2
  36. package/dist/templates/SimpleHomePage.js +1 -1
  37. package/package.json +7 -2
  38. package/src/__tests__/module-registry.test.ts +1 -1
  39. package/src/layouts/AdminLayout.tsx +0 -2
  40. package/src/layouts/AdminLayoutWithSidebar.tsx +13 -6
  41. package/src/layouts/AuthLayout.tsx +0 -2
  42. package/src/layouts/AuthLayoutWithSidebar.tsx +13 -6
  43. package/src/layouts/PublicLayout.tsx +14 -2
  44. package/src/layouts/PublicLayoutWithSidebar.tsx +13 -6
  45. package/src/scripts/db-migrations-sync.ts +86 -57
  46. package/src/scripts/dev-sync.ts +1 -0
  47. package/src/scripts/init-app.ts +191 -58
  48. package/src/scripts/module-build.ts +77 -6
  49. package/src/scripts/module-create.ts +25 -2
  50. package/src/scripts/module-delete.ts +8 -6
  51. package/src/scripts/module-list.ts +1 -4
  52. package/src/templates/DefaultDoc.tsx +346 -455
  53. package/src/templates/DocPage.tsx +40 -22
  54. package/src/templates/SimpleDocPage.tsx +2 -2
  55. package/src/templates/SimpleHomePage.tsx +3 -3
@@ -46,7 +46,7 @@ describe("Module Registry", () => {
46
46
  });
47
47
  it("should have valid package names", () => {
48
48
  AVAILABLE_MODULES.forEach((module) => {
49
- expect(module.package).toMatch(/^@lastbrain\/module-/);
49
+ expect(module.package).toMatch(/^@lastbrain(-labs)?\/module-/);
50
50
  });
51
51
  });
52
52
  });
@@ -1 +1 @@
1
- {"version":3,"file":"AdminLayout.d.ts","sourceRoot":"","sources":["../../src/layouts/AdminLayout.tsx"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,2CAEtE"}
1
+ {"version":3,"file":"AdminLayout.d.ts","sourceRoot":"","sources":["../../src/layouts/AdminLayout.tsx"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,2CAEtE"}
@@ -1,4 +1,3 @@
1
- "use client";
2
1
  import { jsx as _jsx } from "react/jsx-runtime";
3
2
  export function AdminLayout({ children }) {
4
3
  return _jsx("div", { className: "pt-18 px-2 md:px-5", children: children });
@@ -1,6 +1,7 @@
1
+ import { type MenuConfig } from "@lastbrain/ui";
1
2
  interface AdminLayoutWithSidebarProps {
2
3
  children: React.ReactNode;
3
- menuConfig?: any;
4
+ menuConfig?: MenuConfig;
4
5
  className?: string;
5
6
  }
6
7
  export declare function AdminLayoutWithSidebar({ children, menuConfig, className, }: AdminLayoutWithSidebarProps): import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"AdminLayoutWithSidebar.d.ts","sourceRoot":"","sources":["../../src/layouts/AdminLayoutWithSidebar.tsx"],"names":[],"mappings":"AAQA,UAAU,2BAA2B;IACnC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,UAAU,EACV,SAAc,GACf,EAAE,2BAA2B,2CA0F7B"}
1
+ {"version":3,"file":"AdminLayoutWithSidebar.d.ts","sourceRoot":"","sources":["../../src/layouts/AdminLayoutWithSidebar.tsx"],"names":[],"mappings":"AAGA,OAAO,EAA8B,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAK5E,UAAU,2BAA2B;IACnC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,UAAU,EACV,SAAc,GACf,EAAE,2BAA2B,2CAiG7B"}
@@ -44,13 +44,19 @@ export function AdminLayoutWithSidebar({ children, menuConfig, className = "", }
44
44
  }, []);
45
45
  // Détecter si on est dans la section admin pour le skeleton
46
46
  const isAdminSection = pathname.startsWith("/admin");
47
+ // Créer un menuConfig sûr avec des valeurs par défaut
48
+ const safeMenuConfig = {
49
+ public: menuConfig?.public || [],
50
+ auth: menuConfig?.auth || [],
51
+ admin: menuConfig?.admin || [],
52
+ };
47
53
  // Vérifier si menuConfig est vraiment disponible et valide
48
54
  const hasValidMenuConfig = menuConfig &&
49
55
  typeof menuConfig === "object" &&
50
- (menuConfig.admin?.length > 0 ||
51
- menuConfig.auth?.length > 0 ||
52
- menuConfig.public?.length > 0);
56
+ (safeMenuConfig.admin.length > 0 ||
57
+ safeMenuConfig.auth.length > 0 ||
58
+ safeMenuConfig.public.length > 0);
53
59
  // Afficher le skeleton pendant le chargement de la session ou si pas de menuConfig valide
54
60
  const shouldShowSkeleton = loading || !hasValidMenuConfig;
55
- return (_jsxs("div", { className: "flex min-h-screen", children: [shouldShowSkeleton ? (_jsx(AppAsideSkeleton, { className: className, isAdminSection: isAdminSection })) : (_jsx(AppAside, { menuConfig: menuConfig, isSuperAdmin: isSuperAdmin, isAuthenticated: !!user, className: className })), _jsx("div", { className: `flex-1 transition-all duration-300 ${!mounted ? "lg:ml-72" : isCollapsed ? "lg:ml-20" : "lg:ml-72"}`, children: _jsx(AdminLayout, { children: children }) })] }));
61
+ return (_jsxs("div", { className: "flex min-h-screen", children: [shouldShowSkeleton ? (_jsx(AppAsideSkeleton, { className: className, isAdminSection: isAdminSection })) : (_jsx(AppAside, { menuConfig: safeMenuConfig, isSuperAdmin: isSuperAdmin, isAuthenticated: !!user, className: className })), _jsx("div", { className: `flex-1 transition-all duration-300 ${!mounted ? "lg:ml-72" : isCollapsed ? "lg:ml-20" : "lg:ml-72"}`, children: _jsx(AdminLayout, { children: children }) })] }));
56
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AuthLayout.d.ts","sourceRoot":"","sources":["../../src/layouts/AuthLayout.tsx"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,2CAErE"}
1
+ {"version":3,"file":"AuthLayout.d.ts","sourceRoot":"","sources":["../../src/layouts/AuthLayout.tsx"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,2CAErE"}
@@ -1,4 +1,3 @@
1
- "use client";
2
1
  import { jsx as _jsx } from "react/jsx-runtime";
3
2
  export function AuthLayout({ children }) {
4
3
  return _jsx("div", { className: "pt-18 px-2 md:px-5 ", children: children });
@@ -1,6 +1,7 @@
1
+ import { type MenuConfig } from "@lastbrain/ui";
1
2
  interface AuthLayoutWithSidebarProps {
2
3
  children: React.ReactNode;
3
- menuConfig?: any;
4
+ menuConfig?: MenuConfig;
4
5
  className?: string;
5
6
  }
6
7
  export declare function AuthLayoutWithSidebar({ children, menuConfig, className, }: AuthLayoutWithSidebarProps): import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"AuthLayoutWithSidebar.d.ts","sourceRoot":"","sources":["../../src/layouts/AuthLayoutWithSidebar.tsx"],"names":[],"mappings":"AAOA,UAAU,0BAA0B;IAClC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,UAAU,EACV,SAAc,GACf,EAAE,0BAA0B,2CAwF5B"}
1
+ {"version":3,"file":"AuthLayoutWithSidebar.d.ts","sourceRoot":"","sources":["../../src/layouts/AuthLayoutWithSidebar.tsx"],"names":[],"mappings":"AAGA,OAAO,EAA8B,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAI5E,UAAU,0BAA0B;IAClC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,UAAU,EACV,SAAc,GACf,EAAE,0BAA0B,2CA+F5B"}
@@ -42,13 +42,19 @@ export function AuthLayoutWithSidebar({ children, menuConfig, className = "", })
42
42
  }, []);
43
43
  // Pour la section auth, isAdminSection sera false
44
44
  const isAdminSection = false;
45
+ // Créer un menuConfig sûr avec des valeurs par défaut
46
+ const safeMenuConfig = {
47
+ public: menuConfig?.public || [],
48
+ auth: menuConfig?.auth || [],
49
+ admin: menuConfig?.admin || [],
50
+ };
45
51
  // Vérifier si menuConfig est vraiment disponible et valide
46
52
  const hasValidMenuConfig = menuConfig &&
47
53
  typeof menuConfig === "object" &&
48
- (menuConfig.admin?.length > 0 ||
49
- menuConfig.auth?.length > 0 ||
50
- menuConfig.public?.length > 0);
54
+ (safeMenuConfig.admin.length > 0 ||
55
+ safeMenuConfig.auth.length > 0 ||
56
+ safeMenuConfig.public.length > 0);
51
57
  // Afficher le skeleton pendant le chargement de la session ou si pas de menuConfig valide
52
58
  const shouldShowSkeleton = loading || !hasValidMenuConfig;
53
- return (_jsxs("div", { className: "flex min-h-screen", children: [shouldShowSkeleton ? (_jsx(AppAsideSkeleton, { className: className, isAdminSection: isAdminSection })) : (_jsx(AppAside, { menuConfig: menuConfig, isSuperAdmin: isSuperAdmin, isAuthenticated: !!user, className: className })), _jsx("div", { className: `flex-1 transition-all duration-300 ${!mounted ? "lg:ml-72" : isCollapsed ? "lg:ml-20" : "lg:ml-72"}`, children: _jsx(AuthLayout, { children: children }) })] }));
59
+ return (_jsxs("div", { className: "flex min-h-screen", children: [shouldShowSkeleton ? (_jsx(AppAsideSkeleton, { className: className, isAdminSection: isAdminSection })) : (_jsx(AppAside, { menuConfig: safeMenuConfig, isSuperAdmin: isSuperAdmin, isAuthenticated: !!user, className: className })), _jsx("div", { className: `flex-1 transition-all duration-300 ${!mounted ? "lg:ml-72" : isCollapsed ? "lg:ml-20" : "lg:ml-72"}`, children: _jsx(AuthLayout, { children: children }) })] }));
54
60
  }
@@ -1,4 +1,8 @@
1
- export declare function PublicLayout({ children }: {
1
+ import { type FooterConfig } from "@lastbrain/ui";
2
+ interface PublicLayoutProps {
2
3
  children: React.ReactNode;
3
- }): import("react/jsx-runtime").JSX.Element;
4
+ footerConfig?: FooterConfig;
5
+ }
6
+ export declare function PublicLayout({ children, footerConfig }: PublicLayoutProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
4
8
  //# sourceMappingURL=PublicLayout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PublicLayout.d.ts","sourceRoot":"","sources":["../../src/layouts/PublicLayout.tsx"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,2CAEvE"}
1
+ {"version":3,"file":"PublicLayout.d.ts","sourceRoot":"","sources":["../../src/layouts/PublicLayout.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAE1D,UAAU,iBAAiB;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,iBAAiB,2CAOzE"}
@@ -1,5 +1,6 @@
1
1
  "use client";
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
- export function PublicLayout({ children }) {
4
- return _jsx("section", { className: "pt-16 ", children: children });
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Footer } from "@lastbrain/ui";
4
+ export function PublicLayout({ children, footerConfig }) {
5
+ return (_jsxs(_Fragment, { children: [_jsx("section", { className: "pt-16 min-h-[calc(100vh)]", children: children }), footerConfig && _jsx(Footer, { config: footerConfig })] }));
5
6
  }
@@ -1,6 +1,7 @@
1
+ import { type MenuConfig } from "@lastbrain/ui";
1
2
  interface PublicLayoutWithSidebarProps {
2
3
  children: React.ReactNode;
3
- menuConfig?: any;
4
+ menuConfig?: MenuConfig;
4
5
  className?: string;
5
6
  }
6
7
  export declare function PublicLayoutWithSidebar({ children, menuConfig, className, }: PublicLayoutWithSidebarProps): import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"PublicLayoutWithSidebar.d.ts","sourceRoot":"","sources":["../../src/layouts/PublicLayoutWithSidebar.tsx"],"names":[],"mappings":"AAOA,UAAU,4BAA4B;IACpC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,uBAAuB,CAAC,EACtC,QAAQ,EACR,UAAU,EACV,SAAc,GACf,EAAE,4BAA4B,2CAwF9B"}
1
+ {"version":3,"file":"PublicLayoutWithSidebar.d.ts","sourceRoot":"","sources":["../../src/layouts/PublicLayoutWithSidebar.tsx"],"names":[],"mappings":"AAGA,OAAO,EAA8B,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAI5E,UAAU,4BAA4B;IACpC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,uBAAuB,CAAC,EACtC,QAAQ,EACR,UAAU,EACV,SAAc,GACf,EAAE,4BAA4B,2CA+F9B"}
@@ -42,13 +42,19 @@ export function PublicLayoutWithSidebar({ children, menuConfig, className = "",
42
42
  }, []);
43
43
  // Pour la section public, isAdminSection sera false
44
44
  const isAdminSection = false;
45
+ // Créer un menuConfig sûr avec des valeurs par défaut
46
+ const safeMenuConfig = {
47
+ public: menuConfig?.public || [],
48
+ auth: menuConfig?.auth || [],
49
+ admin: menuConfig?.admin || [],
50
+ };
45
51
  // Vérifier si menuConfig est vraiment disponible et valide
46
52
  const hasValidMenuConfig = menuConfig &&
47
53
  typeof menuConfig === "object" &&
48
- (menuConfig.admin?.length > 0 ||
49
- menuConfig.auth?.length > 0 ||
50
- menuConfig.public?.length > 0);
54
+ (safeMenuConfig.admin.length > 0 ||
55
+ safeMenuConfig.auth.length > 0 ||
56
+ safeMenuConfig.public.length > 0);
51
57
  // Afficher le skeleton pendant le chargement de la session ou si pas de menuConfig valide
52
58
  const shouldShowSkeleton = loading || !hasValidMenuConfig;
53
- return (_jsxs("div", { className: "flex min-h-screen", children: [shouldShowSkeleton ? (_jsx(AppAsideSkeleton, { className: className, isAdminSection: isAdminSection })) : (_jsx(AppAside, { menuConfig: menuConfig, isSuperAdmin: false, isAuthenticated: !!user, className: className })), _jsx("div", { className: `flex-1 transition-all duration-300 ${!mounted ? "lg:ml-72" : isCollapsed ? "lg:ml-20" : "lg:ml-72"}`, children: _jsx(PublicLayout, { children: children }) })] }));
59
+ return (_jsxs("div", { className: "flex min-h-screen", children: [shouldShowSkeleton ? (_jsx(AppAsideSkeleton, { className: className, isAdminSection: isAdminSection })) : (_jsx(AppAside, { menuConfig: safeMenuConfig, isSuperAdmin: false, isAuthenticated: !!user, className: className })), _jsx("div", { className: `flex-1 transition-all duration-300 ${!mounted ? "lg:ml-72" : isCollapsed ? "lg:ml-20" : "lg:ml-72"}`, children: _jsx(PublicLayout, { children: children }) })] }));
54
60
  }
@@ -1,55 +1,84 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import { getModuleConfigs } from "../modules/module-loader.js";
4
3
  // Utiliser PROJECT_ROOT si défini (pour pnpm --filter), sinon process.cwd()
5
4
  const projectRoot = process.env.PROJECT_ROOT || process.cwd();
6
5
  const migrationsDir = path.join(projectRoot, "supabase/migrations");
7
6
  function ensureDirectory(dir) {
8
7
  fs.mkdirSync(dir, { recursive: true });
9
8
  }
10
- var _CopyStrategy;
11
- (function (_CopyStrategy) {
12
- _CopyStrategy[_CopyStrategy["overwrite"] = 0] = "overwrite";
13
- _CopyStrategy[_CopyStrategy["skip"] = 1] = "skip";
14
- })(_CopyStrategy || (_CopyStrategy = {}));
15
- function getModulePackageDir(moduleName) {
16
- return path.join(projectRoot, "node_modules", ...moduleName.split("/"));
17
- }
18
- function copyMigration(moduleConfig, migration, file, index) {
19
- const moduleDir = getModulePackageDir(moduleConfig.moduleName);
20
- const migrationsPath = migration.path ?? "supabase/migrations";
21
- const sourceDir = path.join(moduleDir, migrationsPath);
22
- const sourceFile = path.join(sourceDir, file);
23
- if (!fs.existsSync(sourceFile)) {
24
- console.warn(`⚠️ Missing migration file ${sourceFile}`);
25
- return;
9
+ /**
10
+ * Copie les migrations d'un module vers supabase/migrations
11
+ */
12
+ function copyModuleMigrations(moduleName, moduleDir) {
13
+ const sourceMigrationsDir = path.join(moduleDir, "supabase", "migrations");
14
+ if (!fs.existsSync(sourceMigrationsDir)) {
15
+ return 0;
16
+ }
17
+ const files = fs
18
+ .readdirSync(sourceMigrationsDir)
19
+ .filter((file) => file.endsWith(".sql"))
20
+ .sort();
21
+ if (files.length === 0) {
22
+ return 0;
26
23
  }
27
24
  ensureDirectory(migrationsDir);
28
- const moduleSlug = moduleConfig.moduleName.replace("@lastbrain/", "module-");
29
- const prefix = String((migration.priority ?? 0) * 10 + index + 1).padStart(3, "0");
30
- const fileName = `${prefix}_${moduleSlug}_${file}`;
31
- const targetFile = path.join(migrationsDir, fileName);
32
- fs.copyFileSync(sourceFile, targetFile);
33
- console.log(`📜 Copied migration ${fileName}`);
25
+ let copiedCount = 0;
26
+ files.forEach((file) => {
27
+ const sourceFile = path.join(sourceMigrationsDir, file);
28
+ const targetFile = path.join(migrationsDir, file);
29
+ // Ne copier que si le fichier n'existe pas déjà
30
+ if (!fs.existsSync(targetFile)) {
31
+ fs.copyFileSync(sourceFile, targetFile);
32
+ console.log(`📜 Copied migration: ${file} from ${moduleName}`);
33
+ copiedCount++;
34
+ }
35
+ else {
36
+ console.log(`⏭️ Migration already exists: ${file}`);
37
+ }
38
+ });
39
+ return copiedCount;
34
40
  }
41
+ /**
42
+ * Synchronise les migrations de tous les modules actifs
43
+ */
35
44
  function syncModuleMigrations() {
36
- const moduleConfigs = getModuleConfigs();
37
- moduleConfigs.forEach((moduleConfig) => {
38
- const migrationBlock = moduleConfig.migrations;
39
- if (!migrationBlock || !migrationBlock.enabled) {
40
- return;
45
+ // Charger modules.json
46
+ const modulesJsonPath = path.join(projectRoot, ".lastbrain", "modules.json");
47
+ if (!fs.existsSync(modulesJsonPath)) {
48
+ console.error("❌ modules.json not found");
49
+ return;
50
+ }
51
+ const modulesData = JSON.parse(fs.readFileSync(modulesJsonPath, "utf-8"));
52
+ const modules = modulesData.modules || [];
53
+ // Filtrer les modules actifs
54
+ const activeModules = modules.filter((m) => m.active !== false);
55
+ console.log(`🔄 Syncing migrations from ${activeModules.length} active module(s)...\n`);
56
+ let totalCopied = 0;
57
+ activeModules.forEach((module) => {
58
+ const moduleName = module.package;
59
+ // Essayer plusieurs chemins possibles pour trouver le module
60
+ const possiblePaths = [
61
+ // Dans node_modules local de l'app
62
+ path.join(projectRoot, "node_modules", moduleName),
63
+ // Dans node_modules à la racine du workspace
64
+ path.join(projectRoot, "..", "..", "node_modules", moduleName),
65
+ // Directement dans packages/ (pour monorepo)
66
+ path.join(projectRoot, "..", "..", "packages", moduleName.replace("@lastbrain/", "").replace("@lastbrain-labs/", "")),
67
+ ];
68
+ let moduleDir = null;
69
+ for (const possiblePath of possiblePaths) {
70
+ if (fs.existsSync(possiblePath)) {
71
+ moduleDir = possiblePath;
72
+ break;
73
+ }
41
74
  }
42
- const moduleMigrationPath = path.join(getModulePackageDir(moduleConfig.moduleName), migrationBlock.path ?? "supabase/migrations");
43
- let files = migrationBlock.files;
44
- if (!files?.length && fs.existsSync(moduleMigrationPath)) {
45
- files = fs
46
- .readdirSync(moduleMigrationPath)
47
- .filter((file) => file.endsWith(".sql"))
48
- .sort();
75
+ if (!moduleDir) {
76
+ console.warn(`⚠️ Module not found: ${moduleName}`);
77
+ return;
49
78
  }
50
- files?.forEach((file, index) => {
51
- copyMigration(moduleConfig, migrationBlock, file, index);
52
- });
79
+ const copied = copyModuleMigrations(moduleName, moduleDir);
80
+ totalCopied += copied;
53
81
  });
82
+ console.log(`\n✅ Migration sync completed: ${totalCopied} file(s) copied`);
54
83
  }
55
84
  syncModuleMigrations();
@@ -20,6 +20,7 @@ const dependenciesToEnsure = {
20
20
  "@lastbrain/app": "workspace:*",
21
21
  "@lastbrain/core": "workspace:*",
22
22
  "@lastbrain/ui": "workspace:*",
23
+ "@lastbrain/module-auth": "workspace:*",
23
24
  };
24
25
  const gitignoreTemplate = path.join(projectRoot, "packages/app/src/templates/gitignore/.gitignore");
25
26
  const consumerGitignore = path.join(projectRoot, "apps/web/.gitignore");
@@ -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,iBAyMpD"}
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"}