@lastbrain/app 2.0.1 → 2.0.3

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 (131) hide show
  1. package/dist/config/version.d.ts +7 -0
  2. package/dist/config/version.d.ts.map +1 -0
  3. package/dist/config/version.js +25 -0
  4. package/dist/src/__tests__/module-registry.test.d.ts +2 -0
  5. package/dist/src/__tests__/module-registry.test.d.ts.map +1 -0
  6. package/dist/src/__tests__/module-registry.test.js +53 -0
  7. package/dist/src/app-shell/(admin)/layout.d.ts +4 -0
  8. package/dist/src/app-shell/(admin)/layout.d.ts.map +1 -0
  9. package/dist/src/app-shell/(admin)/layout.js +5 -0
  10. package/dist/src/app-shell/(auth)/layout.d.ts +4 -0
  11. package/dist/src/app-shell/(auth)/layout.d.ts.map +1 -0
  12. package/dist/src/app-shell/(auth)/layout.js +5 -0
  13. package/dist/src/app-shell/(public)/page.d.ts +2 -0
  14. package/dist/src/app-shell/(public)/page.d.ts.map +1 -0
  15. package/dist/src/app-shell/(public)/page.js +5 -0
  16. package/dist/src/app-shell/layout.d.ts +3 -0
  17. package/dist/src/app-shell/layout.d.ts.map +1 -0
  18. package/dist/src/app-shell/layout.js +3 -0
  19. package/dist/src/app-shell/not-found.d.ts +2 -0
  20. package/dist/src/app-shell/not-found.d.ts.map +1 -0
  21. package/dist/src/app-shell/not-found.js +10 -0
  22. package/dist/src/auth/authHelpers.d.ts +7 -0
  23. package/dist/src/auth/authHelpers.d.ts.map +1 -0
  24. package/dist/src/auth/authHelpers.js +19 -0
  25. package/dist/src/auth/useAuthSession.d.ts +7 -0
  26. package/dist/src/auth/useAuthSession.d.ts.map +1 -0
  27. package/dist/src/auth/useAuthSession.js +49 -0
  28. package/dist/src/cli.d.ts +3 -0
  29. package/dist/src/cli.d.ts.map +1 -0
  30. package/dist/src/cli.js +143 -0
  31. package/dist/src/components/NotificationContainer.d.ts +2 -0
  32. package/dist/src/components/NotificationContainer.d.ts.map +1 -0
  33. package/dist/src/components/NotificationContainer.js +8 -0
  34. package/dist/src/hooks/useNotifications.d.ts +30 -0
  35. package/dist/src/hooks/useNotifications.d.ts.map +1 -0
  36. package/dist/src/hooks/useNotifications.js +165 -0
  37. package/dist/src/index.d.ts +22 -0
  38. package/dist/src/index.d.ts.map +1 -0
  39. package/dist/src/index.js +22 -0
  40. package/dist/src/layouts/AdminLayout.d.ts +4 -0
  41. package/dist/src/layouts/AdminLayout.d.ts.map +1 -0
  42. package/dist/src/layouts/AdminLayout.js +4 -0
  43. package/dist/src/layouts/AdminLayoutWithSidebar.d.ts +10 -0
  44. package/dist/src/layouts/AdminLayoutWithSidebar.d.ts.map +1 -0
  45. package/dist/src/layouts/AdminLayoutWithSidebar.js +62 -0
  46. package/dist/src/layouts/AppProviders.d.ts +27 -0
  47. package/dist/src/layouts/AppProviders.d.ts.map +1 -0
  48. package/dist/src/layouts/AppProviders.js +48 -0
  49. package/dist/src/layouts/AuthLayout.d.ts +4 -0
  50. package/dist/src/layouts/AuthLayout.d.ts.map +1 -0
  51. package/dist/src/layouts/AuthLayout.js +4 -0
  52. package/dist/src/layouts/AuthLayoutWithSidebar.d.ts +12 -0
  53. package/dist/src/layouts/AuthLayoutWithSidebar.d.ts.map +1 -0
  54. package/dist/src/layouts/AuthLayoutWithSidebar.js +60 -0
  55. package/dist/src/layouts/PublicLayout.d.ts +8 -0
  56. package/dist/src/layouts/PublicLayout.d.ts.map +1 -0
  57. package/dist/src/layouts/PublicLayout.js +6 -0
  58. package/dist/src/layouts/PublicLayoutWithSidebar.d.ts +9 -0
  59. package/dist/src/layouts/PublicLayoutWithSidebar.d.ts.map +1 -0
  60. package/dist/src/layouts/PublicLayoutWithSidebar.js +60 -0
  61. package/dist/src/layouts/RootLayout.d.ts +6 -0
  62. package/dist/src/layouts/RootLayout.d.ts.map +1 -0
  63. package/dist/src/layouts/RootLayout.js +9 -0
  64. package/dist/src/modules/module-loader.d.ts +5 -0
  65. package/dist/src/modules/module-loader.d.ts.map +1 -0
  66. package/dist/src/modules/module-loader.js +10 -0
  67. package/dist/src/scripts/db-init.d.ts +2 -0
  68. package/dist/src/scripts/db-init.d.ts.map +1 -0
  69. package/dist/src/scripts/db-init.js +300 -0
  70. package/dist/src/scripts/db-migrations-sync.d.ts +2 -0
  71. package/dist/src/scripts/db-migrations-sync.d.ts.map +1 -0
  72. package/dist/src/scripts/db-migrations-sync.js +84 -0
  73. package/dist/src/scripts/dev-sync.d.ts +2 -0
  74. package/dist/src/scripts/dev-sync.d.ts.map +1 -0
  75. package/dist/src/scripts/dev-sync.js +194 -0
  76. package/dist/src/scripts/init-app.d.ts +12 -0
  77. package/dist/src/scripts/init-app.d.ts.map +1 -0
  78. package/dist/src/scripts/init-app.js +2175 -0
  79. package/dist/src/scripts/module-add.d.ts +2 -0
  80. package/dist/src/scripts/module-add.d.ts.map +1 -0
  81. package/dist/src/scripts/module-add.js +232 -0
  82. package/dist/src/scripts/module-build.d.ts +2 -0
  83. package/dist/src/scripts/module-build.d.ts.map +1 -0
  84. package/dist/src/scripts/module-build.js +1280 -0
  85. package/dist/src/scripts/module-create.d.ts +28 -0
  86. package/dist/src/scripts/module-create.d.ts.map +1 -0
  87. package/dist/src/scripts/module-create.js +1429 -0
  88. package/dist/src/scripts/module-delete.d.ts +6 -0
  89. package/dist/src/scripts/module-delete.d.ts.map +1 -0
  90. package/dist/src/scripts/module-delete.js +147 -0
  91. package/dist/src/scripts/module-list.d.ts +2 -0
  92. package/dist/src/scripts/module-list.d.ts.map +1 -0
  93. package/dist/src/scripts/module-list.js +61 -0
  94. package/dist/src/scripts/module-remove.d.ts +2 -0
  95. package/dist/src/scripts/module-remove.d.ts.map +1 -0
  96. package/dist/src/scripts/module-remove.js +311 -0
  97. package/dist/src/scripts/readme-build.d.ts +2 -0
  98. package/dist/src/scripts/readme-build.d.ts.map +1 -0
  99. package/dist/src/scripts/readme-build.js +39 -0
  100. package/dist/src/scripts/script-runner.d.ts +5 -0
  101. package/dist/src/scripts/script-runner.d.ts.map +1 -0
  102. package/dist/src/scripts/script-runner.js +25 -0
  103. package/dist/src/templates/AuthGuidePage.d.ts +2 -0
  104. package/dist/src/templates/AuthGuidePage.d.ts.map +1 -0
  105. package/dist/src/templates/AuthGuidePage.js +9 -0
  106. package/dist/src/templates/DefaultDoc.d.ts +2 -0
  107. package/dist/src/templates/DefaultDoc.d.ts.map +1 -0
  108. package/dist/src/templates/DefaultDoc.js +240 -0
  109. package/dist/src/templates/DocPage.d.ts +17 -0
  110. package/dist/src/templates/DocPage.d.ts.map +1 -0
  111. package/dist/src/templates/DocPage.js +193 -0
  112. package/dist/src/templates/DocsPageWithModules.d.ts +2 -0
  113. package/dist/src/templates/DocsPageWithModules.d.ts.map +1 -0
  114. package/dist/src/templates/DocsPageWithModules.js +8 -0
  115. package/dist/src/templates/MigrationsGuidePage.d.ts +2 -0
  116. package/dist/src/templates/MigrationsGuidePage.d.ts.map +1 -0
  117. package/dist/src/templates/MigrationsGuidePage.js +11 -0
  118. package/dist/src/templates/ModuleGuidePage.d.ts +2 -0
  119. package/dist/src/templates/ModuleGuidePage.d.ts.map +1 -0
  120. package/dist/src/templates/ModuleGuidePage.js +14 -0
  121. package/dist/src/templates/SimpleDocPage.d.ts +2 -0
  122. package/dist/src/templates/SimpleDocPage.d.ts.map +1 -0
  123. package/dist/src/templates/SimpleDocPage.js +28 -0
  124. package/dist/src/templates/SimpleHomePage.d.ts +6 -0
  125. package/dist/src/templates/SimpleHomePage.d.ts.map +1 -0
  126. package/dist/src/templates/SimpleHomePage.js +7 -0
  127. package/dist/src/types/menu.d.ts +23 -0
  128. package/dist/src/types/menu.d.ts.map +1 -0
  129. package/dist/src/types/menu.js +1 -0
  130. package/package.json +4 -5
  131. package/src/scripts/init-app.ts +7 -76
@@ -0,0 +1,7 @@
1
+ /**
2
+ * AUTO-GENERATED FILE - Généré par scripts/version.js
3
+ * NE PAS MODIFIER MANUELLEMENT
4
+ * Mise à jour automatique lors de pnpm version:patch/minor/major
5
+ */
6
+ export declare const PACKAGE_VERSIONS: Record<string, string>;
7
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../config/version.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAmBnD,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * AUTO-GENERATED FILE - Généré par scripts/version.js
3
+ * NE PAS MODIFIER MANUELLEMENT
4
+ * Mise à jour automatique lors de pnpm version:patch/minor/major
5
+ */
6
+ export const PACKAGE_VERSIONS = {
7
+ "@lastbrain-labs/module-billing-pro": "^2.0.3",
8
+ "@lastbrain-labs/module-core-cart-pro": "^2.0.3",
9
+ "@lastbrain-labs/module-core-commerce-pro": "^2.0.3",
10
+ "@lastbrain-labs/module-core-order-pro": "^2.0.3",
11
+ "@lastbrain-labs/module-core-payment-pro": "^2.0.3",
12
+ "@lastbrain-labs/module-core-product-pro": "^2.0.3",
13
+ "@lastbrain-labs/module-recipes-pro": "^2.0.3",
14
+ "@lastbrain/app": "^2.0.3",
15
+ "@lastbrain/core": "^2.0.3",
16
+ "@lastbrain/module-ai": "^2.0.3",
17
+ "@lastbrain/module-auth": "^2.0.3",
18
+ "@lastbrain/module-legal": "^2.0.3",
19
+ "@lastbrain/module-project-board": "^2.0.3",
20
+ "@lastbrain/module-tasks": "^2.0.3",
21
+ "@lastbrain/ui": "^2.0.3",
22
+ "apps/recipe": "^2.0.3",
23
+ "apps/test-app": "^2.0.3",
24
+ "apps/test-module": "^2.0.3",
25
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=module-registry.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-registry.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/module-registry.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { AVAILABLE_MODULES } from "@lastbrain/core/config/modules";
3
+ describe("Module Registry", () => {
4
+ describe("AVAILABLE_MODULES", () => {
5
+ it("should have at least one module defined", () => {
6
+ expect(AVAILABLE_MODULES.length).toBeGreaterThan(0);
7
+ });
8
+ it("should have auth module defined", () => {
9
+ const authModule = AVAILABLE_MODULES.find((m) => m.name === "auth");
10
+ expect(authModule).toBeDefined();
11
+ expect(authModule?.package).toBe("@lastbrain/module-auth");
12
+ });
13
+ it("should have ai module defined", () => {
14
+ const aiModule = AVAILABLE_MODULES.find((m) => m.name === "ai");
15
+ expect(aiModule).toBeDefined();
16
+ expect(aiModule?.package).toBe("@lastbrain/module-ai");
17
+ });
18
+ it("should have all required properties for each module", () => {
19
+ AVAILABLE_MODULES.forEach((module) => {
20
+ expect(module.name).toBeDefined();
21
+ expect(module.package).toBeDefined();
22
+ expect(module.emoji).toBeDefined();
23
+ expect(module.description).toBeDefined();
24
+ });
25
+ });
26
+ it("should have unique module names", () => {
27
+ const names = AVAILABLE_MODULES.map((m) => m.name);
28
+ const uniqueNames = new Set(names);
29
+ expect(names.length).toBe(uniqueNames.size);
30
+ });
31
+ it("should have unique package names", () => {
32
+ const packages = AVAILABLE_MODULES.map((m) => m.package);
33
+ const uniquePackages = new Set(packages);
34
+ expect(packages.length).toBe(uniquePackages.size);
35
+ });
36
+ it("should have emoji", () => {
37
+ AVAILABLE_MODULES.forEach((module) => {
38
+ // Check if emoji contains at least one emoji (basic check)
39
+ expect(module.emoji).toMatch(/[\u{1F300}-\u{1F9FF}]/u);
40
+ });
41
+ });
42
+ it("should have non-empty descriptions", () => {
43
+ AVAILABLE_MODULES.forEach((module) => {
44
+ expect(module.description.length).toBeGreaterThan(0);
45
+ });
46
+ });
47
+ it("should have valid package names", () => {
48
+ AVAILABLE_MODULES.forEach((module) => {
49
+ expect(module.package).toMatch(/^@lastbrain(-labs)?\/module-/);
50
+ });
51
+ });
52
+ });
53
+ });
@@ -0,0 +1,4 @@
1
+ export default function AdminShellLayout({ children, }: {
2
+ children: React.ReactNode;
3
+ }): import("react/jsx-runtime").JSX.Element;
4
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../../src/app-shell/(admin)/layout.tsx"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACvC,QAAQ,GACT,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,2CAQA"}
@@ -0,0 +1,5 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ export default function AdminShellLayout({ children, }) {
4
+ return (_jsxs("div", { className: "mx-auto max-w-5xl px-4 py-16", children: [_jsx("h1", { className: "text-3xl font-bold", children: "Section Admin" }), _jsx("p", { className: "text-slate-600", children: "Gestion avanc\u00E9e des modules." }), children] }));
5
+ }
@@ -0,0 +1,4 @@
1
+ export default function AuthLayout({ children, }: {
2
+ children: React.ReactNode;
3
+ }): import("react/jsx-runtime").JSX.Element;
4
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../../src/app-shell/(auth)/layout.tsx"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EACjC,QAAQ,GACT,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,2CAQA"}
@@ -0,0 +1,5 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ export default function AuthLayout({ children, }) {
4
+ return (_jsxs("div", { className: "mx-auto max-w-5xl px-4 py-16", children: [_jsx("h1", { className: "text-3xl font-bold", children: "Section Auth" }), _jsx("p", { className: "text-slate-600", children: "Les pages authentifi\u00E9es regroup\u00E9es ici." }), children] }));
5
+ }
@@ -0,0 +1,2 @@
1
+ export default function PublicPage(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../../src/app-shell/(public)/page.tsx"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,UAAU,UAAU,4CAYjC"}
@@ -0,0 +1,5 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ export default function PublicPage() {
4
+ return (_jsxs("div", { className: "mx-auto max-w-3xl space-y-4 px-4 py-16 text-center", children: [_jsx("h1", { className: "text-3xl font-bold", children: "Bienvenue sur LastBrain" }), _jsx("p", { className: "text-slate-600", children: "Cette coquille publique pr\u00E9sente la structure par d\u00E9faut." }), _jsx("button", { className: "rounded-full bg-slate-900 px-5 py-2 text-white", children: "Connexion" })] }));
5
+ }
@@ -0,0 +1,3 @@
1
+ import { RootLayout } from "../layouts/RootLayout";
2
+ export default RootLayout;
3
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/app-shell/layout.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,eAAe,UAAU,CAAC"}
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ import { RootLayout } from "../layouts/RootLayout";
3
+ export default RootLayout;
@@ -0,0 +1,2 @@
1
+ export default function NotFound(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=not-found.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"not-found.d.ts","sourceRoot":"","sources":["../../../src/app-shell/not-found.tsx"],"names":[],"mappings":"AAIA,MAAM,CAAC,OAAO,UAAU,QAAQ,4CAuB/B"}
@@ -0,0 +1,10 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Button } from "@lastbrain/ui";
4
+ import { useRouter } from "next/navigation";
5
+ export default function NotFound() {
6
+ const router = useRouter();
7
+ return (_jsx("div", { className: "flex min-h-screen items-center justify-center bg-background", children: _jsxs("div", { className: "mx-auto max-w-md text-center", children: [_jsx("h1", { className: "mb-4 text-6xl font-bold text-foreground", children: "404" }), _jsx("h2", { className: "mb-4 text-2xl font-semibold text-foreground", children: "Page non trouv\u00E9e" }), _jsx("p", { className: "mb-8 text-muted-foreground", children: "La page que vous recherchez n'existe pas ou a \u00E9t\u00E9 d\u00E9plac\u00E9e." }), _jsx(Button, { onPress: () => {
8
+ router.back();
9
+ }, className: "inline-flex items-center justify-center rounded-md bg-primary px-6 py-3 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90", children: "Retour \u00E0 l'accueil" })] }) }));
10
+ }
@@ -0,0 +1,7 @@
1
+ export declare function signOut(): Promise<void>;
2
+ export declare function signIn(email: string, password: string): Promise<{
3
+ user: import("@supabase/supabase-js").AuthUser;
4
+ session: import("@supabase/supabase-js").AuthSession;
5
+ weakPassword?: import("@supabase/supabase-js").WeakPassword;
6
+ }>;
7
+ //# sourceMappingURL=authHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authHelpers.d.ts","sourceRoot":"","sources":["../../../src/auth/authHelpers.ts"],"names":[],"mappings":"AAIA,wBAAsB,OAAO,kBAM5B;AAED,wBAAsB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;GAW3D"}
@@ -0,0 +1,19 @@
1
+ "use client";
2
+ import { supabaseBrowserClient } from "@lastbrain/core";
3
+ export async function signOut() {
4
+ const { error } = await supabaseBrowserClient.auth.signOut();
5
+ if (error) {
6
+ console.error("Error signing out:", error);
7
+ throw error;
8
+ }
9
+ }
10
+ export async function signIn(email, password) {
11
+ const { data, error } = await supabaseBrowserClient.auth.signInWithPassword({
12
+ email,
13
+ password,
14
+ });
15
+ if (error) {
16
+ throw error;
17
+ }
18
+ return data;
19
+ }
@@ -0,0 +1,7 @@
1
+ import type { User } from "@supabase/supabase-js";
2
+ export declare function useAuthSession(): {
3
+ user: User | null;
4
+ loading: boolean;
5
+ isSuperAdmin: boolean;
6
+ };
7
+ //# sourceMappingURL=useAuthSession.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAuthSession.d.ts","sourceRoot":"","sources":["../../../src/auth/useAuthSession.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAElD,wBAAgB,cAAc;;;;EAmD7B"}
@@ -0,0 +1,49 @@
1
+ "use client";
2
+ import { useEffect, useState } from "react";
3
+ import { supabaseBrowserClient } from "@lastbrain/core";
4
+ export function useAuthSession() {
5
+ const [user, setUser] = useState(null);
6
+ const [loading, setLoading] = useState(true);
7
+ const [isSuperAdmin, setIsSuperAdmin] = useState(false);
8
+ useEffect(() => {
9
+ const checkSuperAdmin = async (userId) => {
10
+ try {
11
+ const { data, error } = await supabaseBrowserClient.rpc("is_superadmin", { user_id: userId });
12
+ if (!error && data) {
13
+ setIsSuperAdmin(data);
14
+ }
15
+ }
16
+ catch (error) {
17
+ console.error("Error checking superadmin status:", error);
18
+ setIsSuperAdmin(false);
19
+ }
20
+ finally {
21
+ // Ne terminer le loading qu'après avoir vérifié le status admin
22
+ setLoading(false);
23
+ }
24
+ };
25
+ // Récupérer la session initiale
26
+ supabaseBrowserClient.auth.getSession().then(({ data: { session } }) => {
27
+ setUser(session?.user ?? null);
28
+ if (session?.user) {
29
+ checkSuperAdmin(session.user.id);
30
+ }
31
+ else {
32
+ setLoading(false);
33
+ }
34
+ });
35
+ // Écouter les changements d'auth
36
+ const { data: { subscription }, } = supabaseBrowserClient.auth.onAuthStateChange((_event, session) => {
37
+ setUser(session?.user ?? null);
38
+ if (session?.user) {
39
+ checkSuperAdmin(session.user.id);
40
+ }
41
+ else {
42
+ setIsSuperAdmin(false);
43
+ setLoading(false);
44
+ }
45
+ });
46
+ return () => subscription.unsubscribe();
47
+ }, []);
48
+ return { user, loading, isSuperAdmin };
49
+ }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import path from "path";
4
+ import { initApp } from "./scripts/init-app.js";
5
+ import { addModule } from "./scripts/module-add.js";
6
+ import { removeModule } from "./scripts/module-remove.js";
7
+ import { listModules } from "./scripts/module-list.js";
8
+ import { createModule } from "./scripts/module-create.js";
9
+ const program = new Command();
10
+ program
11
+ .name("lastbrain")
12
+ .description("CLI pour créer et gérer des applications LastBrain")
13
+ .version("0.1.0");
14
+ program
15
+ .command("init [directory]")
16
+ .description("Initialise une nouvelle application Next.js LastBrain")
17
+ .option("-f, --force", "Écrase les fichiers existants")
18
+ .option("--no-heroui", "Ne pas utiliser HeroUI (Tailwind CSS uniquement)")
19
+ .option("--with-auth", "Inclure le module d'authentification")
20
+ .option("--no-interactive", "Mode non-interactif (skip la sélection des modules)")
21
+ .action(async (directory, options) => {
22
+ try {
23
+ const targetDir = directory
24
+ ? path.resolve(process.cwd(), directory)
25
+ : process.cwd();
26
+ await initApp({
27
+ force: options.force || false,
28
+ targetDir,
29
+ projectName: directory || path.basename(process.cwd()),
30
+ useHeroUI: options.heroui !== false, // Par défaut true, false si --no-heroui
31
+ withAuth: options.withAuth || false,
32
+ interactive: options.interactive !== false,
33
+ });
34
+ }
35
+ catch (error) {
36
+ console.error("❌ Erreur lors de l'initialisation:", error);
37
+ process.exit(1);
38
+ }
39
+ });
40
+ program
41
+ .command("add-module <module>")
42
+ .description("Ajoute un module à l'application")
43
+ .action(async (moduleName) => {
44
+ try {
45
+ await addModule(moduleName, process.cwd());
46
+ }
47
+ catch (error) {
48
+ console.error("❌ Erreur lors de l'ajout du module:", error);
49
+ process.exit(1);
50
+ }
51
+ });
52
+ program
53
+ .command("remove-module <module>")
54
+ .description("Supprime un module de l'application")
55
+ .action(async (moduleName) => {
56
+ try {
57
+ await removeModule(moduleName, process.cwd());
58
+ }
59
+ catch (error) {
60
+ console.error("❌ Erreur lors de la suppression du module:", error);
61
+ process.exit(1);
62
+ }
63
+ });
64
+ program
65
+ .command("list-modules")
66
+ .description("Liste les modules disponibles et installés")
67
+ .action(async () => {
68
+ try {
69
+ await listModules(process.cwd());
70
+ }
71
+ catch (error) {
72
+ console.error("❌ Erreur lors de la liste des modules:", error);
73
+ process.exit(1);
74
+ }
75
+ });
76
+ program
77
+ .command("create-module")
78
+ .description("Crée un nouveau module dans packages/")
79
+ .action(async () => {
80
+ try {
81
+ await createModule();
82
+ }
83
+ catch (error) {
84
+ console.error("❌ Erreur lors de la création du module:", error);
85
+ process.exit(1);
86
+ }
87
+ });
88
+ // Commandes de build et maintenance
89
+ program
90
+ .command("module:build")
91
+ .description("Build les configurations de modules")
92
+ .option("--debug", "Affiche tous les logs détaillés")
93
+ .action(async (options) => {
94
+ try {
95
+ // Passer le flag debug via process.argv pour que module-build puisse le lire
96
+ if (options.debug && !process.argv.includes("--debug")) {
97
+ process.argv.push("--debug");
98
+ }
99
+ const { runModuleBuild } = await import("./scripts/module-build.js");
100
+ await runModuleBuild();
101
+ }
102
+ catch (error) {
103
+ console.error("❌ Erreur lors du build des modules:", error);
104
+ process.exit(1);
105
+ }
106
+ });
107
+ program
108
+ .command("db:init")
109
+ .description("Initialise la base de données Supabase")
110
+ .action(async () => {
111
+ try {
112
+ await import("./scripts/db-init.js");
113
+ }
114
+ catch (error) {
115
+ console.error("❌ Erreur lors de l'initialisation de la DB:", error);
116
+ process.exit(1);
117
+ }
118
+ });
119
+ program
120
+ .command("db:migrations:sync")
121
+ .description("Synchronise les migrations de modules")
122
+ .action(async () => {
123
+ try {
124
+ await import("./scripts/db-migrations-sync.js");
125
+ }
126
+ catch (error) {
127
+ console.error("❌ Erreur lors de la sync des migrations:", error);
128
+ process.exit(1);
129
+ }
130
+ });
131
+ program
132
+ .command("readme:create")
133
+ .description("Génère le fichier README")
134
+ .action(async () => {
135
+ try {
136
+ await import("./scripts/readme-build.js");
137
+ }
138
+ catch (error) {
139
+ console.error("❌ Erreur lors de la création du README:", error);
140
+ process.exit(1);
141
+ }
142
+ });
143
+ program.parse();
@@ -0,0 +1,2 @@
1
+ export declare function NotificationContainer(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=NotificationContainer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotificationContainer.d.ts","sourceRoot":"","sources":["../../../src/components/NotificationContainer.tsx"],"names":[],"mappings":"AAKA,wBAAgB,qBAAqB,4CAcpC"}
@@ -0,0 +1,8 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { Notification } from "@lastbrain/ui";
4
+ import { useNotifications } from "../layouts/AppProviders";
5
+ export function NotificationContainer() {
6
+ const { data, loading, markAsRead, markAllAsRead, deleteNotification } = useNotifications();
7
+ return (_jsx(Notification, { notifications: data.notifications, unreadCount: data.unreadCount, loading: loading, onMarkAsRead: markAsRead, onMarkAllAsRead: markAllAsRead, onDelete: deleteNotification }));
8
+ }
@@ -0,0 +1,30 @@
1
+ import type { User } from "@supabase/supabase-js";
2
+ export interface UserNotification {
3
+ id: string;
4
+ owner_id: string;
5
+ title: string;
6
+ message: string;
7
+ body?: string;
8
+ type: string;
9
+ read: boolean;
10
+ created_at: string;
11
+ updated_at: string;
12
+ }
13
+ export interface NotificationsData {
14
+ notifications: UserNotification[];
15
+ unreadCount: number;
16
+ }
17
+ export declare function useNotifications(user?: User | null): {
18
+ data: NotificationsData;
19
+ loading: boolean;
20
+ error: string | null;
21
+ refetch: () => Promise<void>;
22
+ markAsRead: (notificationId: string) => Promise<void>;
23
+ markAllAsRead: () => Promise<void>;
24
+ deleteNotification: (notificationId: string) => Promise<void>;
25
+ isEmpty: boolean;
26
+ hasUnread: boolean;
27
+ realtimeActive: boolean;
28
+ lastRealtimePayload: any;
29
+ };
30
+ //# sourceMappingURL=useNotifications.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useNotifications.d.ts","sourceRoot":"","sources":["../../../src/hooks/useNotifications.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAElD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,gBAAgB,EAAE,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI;;;;;iCAwExB,MAAM;;yCAiEN,MAAM;;;;;EAwDhC"}
@@ -0,0 +1,165 @@
1
+ "use client";
2
+ import { useState, useEffect, useCallback } from "react";
3
+ import { useTableRealtime, supabaseBrowserClient } from "@lastbrain/core";
4
+ export function useNotifications(user) {
5
+ const [data, setData] = useState({
6
+ notifications: [],
7
+ unreadCount: 0,
8
+ });
9
+ const [loading, setLoading] = useState(true);
10
+ const [error, setError] = useState(null);
11
+ const fetchNotifications = useCallback(async () => {
12
+ if (!user?.id) {
13
+ if (user === null) {
14
+ // Utilisateur explicitement non connecté
15
+ setData({ notifications: [], unreadCount: 0 });
16
+ setLoading(false);
17
+ }
18
+ // Si user === undefined, on est encore en train de charger l'auth, on ne fait rien
19
+ return;
20
+ }
21
+ try {
22
+ setLoading(true);
23
+ setError(null);
24
+ // Utilisation directe du client Supabase côté navigateur
25
+ const { data: notifications, error: fetchError } = await supabaseBrowserClient
26
+ .from("user_notifications")
27
+ .select("*")
28
+ .eq("owner_id", user.id)
29
+ .order("created_at", { ascending: false });
30
+ if (fetchError) {
31
+ throw fetchError;
32
+ }
33
+ const unreadCount = notifications?.filter((n) => !n.read).length || 0;
34
+ setData({
35
+ notifications: notifications || [],
36
+ unreadCount,
37
+ });
38
+ }
39
+ catch (err) {
40
+ setError(err instanceof Error
41
+ ? err.message
42
+ : "Erreur lors du chargement des notifications");
43
+ console.error("[useNotifications] Erreur:", err);
44
+ }
45
+ finally {
46
+ setLoading(false);
47
+ }
48
+ }, [user]);
49
+ // Utiliser le hook realtime scalable pour les notifications
50
+ const { tick: realtimeTick, lastPayload } = useTableRealtime("user_notifications", {
51
+ eventName: "user_notifications_updated",
52
+ onUpdate: (payload) => {
53
+ console.log("🔔 Nouvelle notification détectée via realtime:", payload);
54
+ console.log("🔔 User ID actuel:", user?.id);
55
+ // Recharger immédiatement les notifications
56
+ if (user?.id) {
57
+ console.log("🔔 Rechargement des notifications...");
58
+ fetchNotifications();
59
+ }
60
+ },
61
+ });
62
+ // Marquer une notification comme lue
63
+ const markAsRead = useCallback(async (notificationId) => {
64
+ if (!user?.id)
65
+ return;
66
+ try {
67
+ const { error: updateError } = await supabaseBrowserClient
68
+ .from("user_notifications")
69
+ .update({
70
+ read: true,
71
+ updated_at: new Date().toISOString(),
72
+ })
73
+ .eq("id", notificationId)
74
+ .eq("owner_id", user.id);
75
+ if (updateError) {
76
+ throw updateError;
77
+ }
78
+ // Mettre à jour localement en attendant le realtime
79
+ setData((prev) => ({
80
+ ...prev,
81
+ notifications: prev.notifications.map((n) => n.id === notificationId ? { ...n, read: true } : n),
82
+ unreadCount: Math.max(0, prev.unreadCount - 1),
83
+ }));
84
+ }
85
+ catch (err) {
86
+ console.error("Erreur mark as read:", err);
87
+ throw err;
88
+ }
89
+ }, [user?.id]);
90
+ // Marquer toutes les notifications comme lues
91
+ const markAllAsRead = useCallback(async () => {
92
+ if (!user?.id || data.unreadCount === 0)
93
+ return;
94
+ try {
95
+ const { error: updateError } = await supabaseBrowserClient
96
+ .from("user_notifications")
97
+ .update({
98
+ read: true,
99
+ updated_at: new Date().toISOString(),
100
+ })
101
+ .eq("owner_id", user.id)
102
+ .eq("read", false);
103
+ if (updateError) {
104
+ throw updateError;
105
+ }
106
+ // Mettre à jour localement
107
+ setData((prev) => ({
108
+ ...prev,
109
+ notifications: prev.notifications.map((n) => ({ ...n, read: true })),
110
+ unreadCount: 0,
111
+ }));
112
+ }
113
+ catch (err) {
114
+ console.error("Erreur mark all as read:", err);
115
+ throw err;
116
+ }
117
+ }, [user?.id, data.unreadCount]);
118
+ // Supprimer une notification
119
+ const deleteNotification = useCallback(async (notificationId) => {
120
+ if (!user?.id)
121
+ return;
122
+ try {
123
+ const { error: deleteError } = await supabaseBrowserClient
124
+ .from("user_notifications")
125
+ .delete()
126
+ .eq("id", notificationId)
127
+ .eq("owner_id", user.id);
128
+ if (deleteError) {
129
+ throw deleteError;
130
+ }
131
+ // Mettre à jour localement
132
+ setData((prev) => {
133
+ const notification = prev.notifications.find((n) => n.id === notificationId);
134
+ return {
135
+ notifications: prev.notifications.filter((n) => n.id !== notificationId),
136
+ unreadCount: notification && !notification.read
137
+ ? Math.max(0, prev.unreadCount - 1)
138
+ : prev.unreadCount,
139
+ };
140
+ });
141
+ }
142
+ catch (err) {
143
+ console.error("Erreur delete notification:", err);
144
+ throw err;
145
+ }
146
+ }, [user?.id]);
147
+ // Charger les notifications initiales
148
+ useEffect(() => {
149
+ fetchNotifications();
150
+ }, [fetchNotifications]);
151
+ return {
152
+ data,
153
+ loading,
154
+ error,
155
+ refetch: fetchNotifications,
156
+ markAsRead,
157
+ markAllAsRead,
158
+ deleteNotification,
159
+ isEmpty: data.notifications.length === 0,
160
+ hasUnread: data.unreadCount > 0,
161
+ // Informations realtime
162
+ realtimeActive: realtimeTick > 0,
163
+ lastRealtimePayload: lastPayload,
164
+ };
165
+ }