@lastbrain/module-ai 0.1.10 → 0.1.13

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 (40) hide show
  1. package/README.md +1 -2
  2. package/dist/ai.build.config.d.ts.map +1 -1
  3. package/dist/ai.build.config.js +24 -6
  4. package/dist/api/admin/user-token/[id].d.ts +6 -1
  5. package/dist/api/admin/user-token/[id].d.ts.map +1 -1
  6. package/dist/api/admin/user-token/[id].js +16 -14
  7. package/dist/api/admin/user-token.d.ts +19 -3
  8. package/dist/api/admin/user-token.d.ts.map +1 -1
  9. package/dist/api/admin/user-token.js +85 -26
  10. package/dist/api/auth/generate-text.js +1 -1
  11. package/dist/api/auth/user-tokens.d.ts +17 -0
  12. package/dist/api/auth/user-tokens.d.ts.map +1 -0
  13. package/dist/api/auth/user-tokens.js +34 -0
  14. package/dist/components/Doc.d.ts.map +1 -1
  15. package/dist/components/Doc.js +2 -5
  16. package/dist/components/DocUsageCustom.d.ts +9 -0
  17. package/dist/components/DocUsageCustom.d.ts.map +1 -0
  18. package/dist/components/DocUsageCustom.js +70 -0
  19. package/dist/components/admin/UserTokenTab.d.ts +6 -0
  20. package/dist/components/admin/UserTokenTab.d.ts.map +1 -0
  21. package/dist/components/admin/UserTokenTab.js +112 -0
  22. package/dist/index.d.ts +1 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +2 -1
  25. package/dist/web/admin/UserTokenPage.d.ts.map +1 -1
  26. package/dist/web/admin/UserTokenPage.js +103 -2
  27. package/dist/web/auth/TokenPage.d.ts.map +1 -1
  28. package/dist/web/auth/TokenPage.js +110 -2
  29. package/dist/web/components/ImageGenerative.d.ts +6 -3
  30. package/dist/web/components/ImageGenerative.d.ts.map +1 -1
  31. package/dist/web/components/ImageGenerative.js +51 -12
  32. package/dist/web/components/TextareaGenerative.d.ts +5 -3
  33. package/dist/web/components/TextareaGenerative.d.ts.map +1 -1
  34. package/dist/web/components/TextareaGenerative.js +33 -12
  35. package/package.json +4 -4
  36. package/supabase/migrations-down/20251125000000_ai_tokens.sql +45 -0
  37. package/supabase/migrations/20251121093113_module-ai_init.sql +0 -122
  38. package/supabase/migrations-down/20251121000000_ai_tokens.sql +0 -23
  39. package/supabase/migrations-down/20251121093113_module-ai_init.sql +0 -11
  40. /package/supabase/migrations/{20251121000000_ai_tokens.sql → 20251125000000_ai_tokens.sql} +0 -0
@@ -1,26 +1,31 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useCallback } from "react";
4
- import { Textarea, Button, Chip, Progress } from "@lastbrain/ui";
5
- import { Sparkles, Loader2, AlertCircle } from "lucide-react";
6
- export function TextareaGenerative({ prompt, model = "gpt-4o-mini", placeholder = "Générer du texte...", defaultValue = "", onChange, onError, className, disabled = false, minRows = 4, maxRows = 20, apiEndpoint = "/api/ai/generate-text", showTokenBalance = true, }) {
4
+ import { Textarea, Button, Chip, Progress, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Select, SelectItem, Skeleton, } from "@lastbrain/ui";
5
+ import { Sparkles, Loader2, AlertCircle, Wand2 } from "lucide-react";
6
+ export function TextareaGenerative({ defaultPrompt = "", model = "gpt-4o-mini", placeholder = "Saisissez votre texte ou générez avec l'IA...", defaultValue = "", onChange, onError, className, disabled = false, minRows = 4, maxRows = 20, apiEndpoint = "/api/ai/generate-text", showTokenBalance = true, label, description, }) {
7
7
  const [value, setValue] = useState(defaultValue);
8
8
  const [isGenerating, setIsGenerating] = useState(false);
9
9
  const [lastResponse, setLastResponse] = useState(null);
10
10
  const [error, setError] = useState(null);
11
11
  const [tokenBalance, setTokenBalance] = useState(null);
12
+ // Modal state
13
+ const [isModalOpen, setIsModalOpen] = useState(false);
14
+ const [userPrompt, setUserPrompt] = useState(defaultPrompt);
15
+ const [selectedModel, setSelectedModel] = useState(model);
12
16
  const handleGenerate = useCallback(async () => {
13
- if (!prompt || isGenerating)
17
+ if (!userPrompt || isGenerating)
14
18
  return;
15
19
  setIsGenerating(true);
16
20
  setError(null);
21
+ setIsModalOpen(false);
17
22
  try {
18
23
  const response = await fetch(apiEndpoint, {
19
24
  method: "POST",
20
25
  headers: { "Content-Type": "application/json" },
21
26
  body: JSON.stringify({
22
- prompt,
23
- model,
27
+ prompt: userPrompt,
28
+ model: selectedModel,
24
29
  context: value,
25
30
  }),
26
31
  });
@@ -33,14 +38,14 @@ export function TextareaGenerative({ prompt, model = "gpt-4o-mini", placeholder
33
38
  text: data.text,
34
39
  tokensUsed: data.tokensUsed || 0,
35
40
  tokensRemaining: data.tokensRemaining || 0,
36
- model: data.model || model,
41
+ model: data.model || selectedModel,
37
42
  cost: data.cost,
38
43
  };
39
44
  setValue(data.text);
40
45
  setLastResponse(generativeResponse);
41
46
  setTokenBalance(data.tokensRemaining);
42
47
  if (onChange) {
43
- onChange(generativeResponse);
48
+ onChange(data.text, generativeResponse);
44
49
  }
45
50
  }
46
51
  catch (err) {
@@ -53,8 +58,24 @@ export function TextareaGenerative({ prompt, model = "gpt-4o-mini", placeholder
53
58
  finally {
54
59
  setIsGenerating(false);
55
60
  }
56
- }, [prompt, model, value, apiEndpoint, onChange, onError, isGenerating]);
57
- return (_jsx("div", { className: className, children: _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Textarea, { value: value, onChange: (e) => setValue(e.target.value), placeholder: placeholder, disabled: disabled || isGenerating, minRows: minRows, maxRows: maxRows, classNames: {
58
- input: "resize-y",
59
- } }), _jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Button, { color: "primary", size: "sm", onClick: handleGenerate, disabled: disabled || isGenerating || !prompt, startContent: isGenerating ? (_jsx(Loader2, { className: "animate-spin", size: 16 })) : (_jsx(Sparkles, { size: 16 })), children: isGenerating ? "Génération..." : "Générer" }), showTokenBalance && tokenBalance !== null && (_jsxs(Chip, { size: "sm", variant: "flat", color: "success", children: [tokenBalance.toLocaleString(), " tokens restants"] }))] }), lastResponse && (_jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsxs(Chip, { size: "sm", variant: "flat", children: [lastResponse.tokensUsed, " tokens utilis\u00E9s"] }), _jsx(Chip, { size: "sm", variant: "flat", color: "primary", children: lastResponse.model }), lastResponse.cost && (_jsxs(Chip, { size: "sm", variant: "flat", color: "warning", children: ["$", lastResponse.cost.toFixed(4)] }))] }))] }), isGenerating && (_jsx(Progress, { size: "sm", isIndeterminate: true, "aria-label": "G\u00E9n\u00E9ration en cours...", className: "max-w-md" })), error && (_jsxs("div", { className: "flex items-center gap-2 text-danger text-sm p-2 bg-danger-50 rounded-md", children: [_jsx(AlertCircle, { size: 16 }), _jsx("span", { children: error })] }))] }) }));
61
+ }, [
62
+ userPrompt,
63
+ selectedModel,
64
+ value,
65
+ apiEndpoint,
66
+ onChange,
67
+ onError,
68
+ isGenerating,
69
+ ]);
70
+ const handleValueChange = (newValue) => {
71
+ setValue(newValue);
72
+ if (onChange) {
73
+ onChange(newValue);
74
+ }
75
+ };
76
+ return (_jsxs("div", { className: className, children: [_jsxs("div", { className: "flex flex-col gap-2", children: [label && _jsx("label", { className: "text-sm font-medium", children: label }), description && (_jsx("p", { className: "text-sm text-gray-500 mb-2", children: description })), !isGenerating && (_jsx(Textarea, { value: value, onChange: (e) => handleValueChange(e.target.value), placeholder: placeholder, disabled: disabled || isGenerating, minRows: minRows, maxRows: maxRows,
77
+ // classNames={{
78
+ // input: "resize-y",
79
+ // }}
80
+ endContent: _jsx(Button, { isIconOnly: true, size: "sm", color: "primary", variant: "light", onClick: () => setIsModalOpen(true), disabled: disabled || isGenerating, title: "G\u00E9n\u00E9rer avec l'IA", children: _jsx(Wand2, { size: 18 }) }) })), isGenerating && (_jsxs("div", { className: "w-full h-md border border-default-200 p-5 rounded-xl", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Skeleton, { className: "w-lg bg-content-2 h-8 rounded-lg" }), _jsx(Skeleton, { className: "w-md bg-content-2 h-4 rounded-lg" }), _jsx(Skeleton, { className: "w-sm bg-content-2 h-4 rounded-lg" })] }), _jsx("div", { className: "mt-2", children: _jsx(Progress, { size: "sm", isIndeterminate: true, "aria-label": "G\u00E9n\u00E9ration en cours...", label: "G\u00E9n\u00E9ration en cours..." }) })] })), _jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [_jsx("div", { className: "flex items-center gap-2", children: showTokenBalance && tokenBalance !== null && (_jsxs(Chip, { size: "sm", variant: "flat", color: "success", children: [tokenBalance.toLocaleString(), " tokens restants"] })) }), lastResponse && (_jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsxs(Chip, { size: "sm", variant: "flat", children: [lastResponse.tokensUsed, " tokens utilis\u00E9s"] }), _jsx(Chip, { size: "sm", variant: "flat", color: "primary", children: lastResponse.model }), lastResponse.cost && (_jsxs(Chip, { size: "sm", variant: "flat", color: "warning", children: ["$", lastResponse.cost.toFixed(4)] }))] }))] }), error && (_jsxs("div", { className: "flex items-center gap-2 text-danger text-sm p-2 bg-danger-50 rounded-md", children: [_jsx(AlertCircle, { size: 16 }), _jsx("span", { children: error })] }))] }), _jsx(Modal, { isOpen: isModalOpen, onClose: () => setIsModalOpen(false), size: "2xl", backdrop: "blur", children: _jsxs(ModalContent, { children: [_jsx(ModalHeader, { children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Sparkles, { size: 20 }), _jsx("span", { children: "G\u00E9n\u00E9rer du texte avec l'IA" })] }) }), _jsx(ModalBody, { children: _jsxs("div", { className: "space-y-4", children: [_jsx(Textarea, { label: "Prompt de g\u00E9n\u00E9ration", placeholder: "D\u00E9crivez ce que vous souhaitez g\u00E9n\u00E9rer...", value: userPrompt, onChange: (e) => setUserPrompt(e.target.value), minRows: 3, description: "Soyez pr\u00E9cis pour obtenir de meilleurs r\u00E9sultats" }), _jsxs(Select, { label: "Mod\u00E8le IA", selectedKeys: [selectedModel], onSelectionChange: (keys) => setSelectedModel(Array.from(keys)[0]), description: "GPT-4o-mini est plus rapide et \u00E9conomique", children: [_jsx(SelectItem, { children: "GPT-4o Mini (Rapide)" }, "gpt-4o-mini"), _jsx(SelectItem, { children: "GPT-4o (Avanc\u00E9)" }, "gpt-4o"), _jsx(SelectItem, { children: "GPT-3.5 Turbo (\u00C9conomique)" }, "gpt-3.5-turbo")] }), value && (_jsxs("div", { className: "p-3 bg-gray-50 dark:bg-gray-800 rounded-lg", children: [_jsx("p", { className: "text-sm font-medium mb-1", children: "Contexte actuel:" }), _jsx("p", { className: "text-xs text-gray-600 dark:text-gray-400 line-clamp-3", children: value })] }))] }) }), _jsxs(ModalFooter, { children: [_jsx(Button, { variant: "light", onClick: () => setIsModalOpen(false), children: "Annuler" }), _jsx(Button, { color: "primary", onClick: handleGenerate, disabled: !userPrompt.trim() || isGenerating, startContent: isGenerating ? (_jsx(Loader2, { className: "animate-spin", size: 16 })) : (_jsx(Sparkles, { size: 16 })), children: isGenerating ? "Génération..." : "Générer" })] })] }) })] }));
60
81
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lastbrain/module-ai",
3
- "version": "0.1.10",
3
+ "version": "0.1.13",
4
4
  "description": "Module de génération IA (texte et images) avec gestion de tokens pour LastBrain",
5
5
  "private": false,
6
6
  "type": "module",
@@ -33,13 +33,13 @@
33
33
  "@heroui/system": "^2.4.23",
34
34
  "@heroui/theme": "^2.4.23",
35
35
  "lucide-react": "^0.554.0",
36
- "next": "^15.5.6",
36
+ "next": "^16.0.4",
37
37
  "openai": "^4.76.0",
38
38
  "react": "^19.0.0",
39
39
  "react-dom": "^19.0.0",
40
40
  "zod": "^3.23.8",
41
- "@lastbrain/core": "0.1.11",
42
- "@lastbrain/ui": "0.1.14"
41
+ "@lastbrain/core": "0.1.14",
42
+ "@lastbrain/ui": "0.1.17"
43
43
  },
44
44
  "peerDependencies": {
45
45
  "next": ">=15.0.0"
@@ -0,0 +1,45 @@
1
+ -- AI Token System Migration - ROLLBACK
2
+ -- Suppression du système de gestion des tokens
3
+
4
+ -- =====================================================
5
+ -- Drop RLS Policies - user_prompts
6
+ -- =====================================================
7
+ DROP POLICY IF EXISTS "Users can delete own prompts" ON public.user_prompts;
8
+ DROP POLICY IF EXISTS "Users can update own prompts" ON public.user_prompts;
9
+ DROP POLICY IF EXISTS "Users can insert own prompts" ON public.user_prompts;
10
+ DROP POLICY IF EXISTS "Users can view own prompts" ON public.user_prompts;
11
+
12
+ -- =====================================================
13
+ -- Drop Triggers & Functions - user_prompts
14
+ -- =====================================================
15
+ DROP TRIGGER IF EXISTS update_user_prompts_updated_at ON public.user_prompts;
16
+ DROP FUNCTION IF EXISTS public.update_user_prompts_updated_at();
17
+
18
+ -- =====================================================
19
+ -- Drop Table - user_prompts
20
+ -- =====================================================
21
+ DROP TABLE IF EXISTS public.user_prompts CASCADE;
22
+
23
+ -- =====================================================
24
+ -- Drop RLS Policies - user_token_ledger
25
+ -- =====================================================
26
+ DROP POLICY IF EXISTS user_token_ledger_delete_admin ON public.user_token_ledger;
27
+ DROP POLICY IF EXISTS user_token_ledger_update_admin ON public.user_token_ledger;
28
+ DROP POLICY IF EXISTS user_token_ledger_insert_own ON public.user_token_ledger;
29
+ DROP POLICY IF EXISTS user_token_ledger_select_own ON public.user_token_ledger;
30
+
31
+ -- =====================================================
32
+ -- Drop Triggers & Functions - user_token_ledger
33
+ -- =====================================================
34
+ DROP TRIGGER IF EXISTS trigger_check_token_balance ON public.user_token_ledger;
35
+ DROP FUNCTION IF EXISTS public.check_token_balance();
36
+
37
+ -- =====================================================
38
+ -- Drop View
39
+ -- =====================================================
40
+ DROP VIEW IF EXISTS public.user_token_balance_v;
41
+
42
+ -- =====================================================
43
+ -- Drop Table - user_token_ledger
44
+ -- =====================================================
45
+ DROP TABLE IF EXISTS public.user_token_ledger CASCADE;
@@ -1,122 +0,0 @@
1
- -- module-ai module initial migration
2
- -- Auto-generated by module-create.ts
3
- -- NOTE: uses helper function set_updated_at() from base migration
4
-
5
- -- ===========================================================================
6
- -- Helper: set_updated_at trigger function (if not already present)
7
- -- ===========================================================================
8
- CREATE OR REPLACE FUNCTION public.set_updated_at()
9
- RETURNS trigger
10
- LANGUAGE plpgsql
11
- AS $$
12
- BEGIN
13
- NEW.updated_at := now();
14
- RETURN NEW;
15
- END;
16
- $$;
17
-
18
- -- ===========================================================================
19
- -- Table: public.user_token_ledger
20
- -- ===========================================================================
21
- CREATE TABLE IF NOT EXISTS public.user_token_ledger (
22
- id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
23
- owner_id uuid NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
24
- title text NOT NULL,
25
- description text,
26
- created_at timestamptz NOT NULL DEFAULT now(),
27
- updated_at timestamptz NOT NULL DEFAULT now()
28
- );
29
-
30
- -- RLS
31
- ALTER TABLE public.user_token_ledger ENABLE ROW LEVEL SECURITY;
32
-
33
- -- Politique: Les utilisateurs peuvent voir leurs propres enregistrements
34
- DROP POLICY IF EXISTS user_token_ledger_owner_select ON public.user_token_ledger;
35
- CREATE POLICY user_token_ledger_owner_select ON public.user_token_ledger
36
- FOR SELECT TO authenticated
37
- USING (owner_id = auth.uid());
38
-
39
- -- Politique: Les utilisateurs peuvent créer leurs propres enregistrements
40
- DROP POLICY IF EXISTS user_token_ledger_owner_insert ON public.user_token_ledger;
41
- CREATE POLICY user_token_ledger_owner_insert ON public.user_token_ledger
42
- FOR INSERT TO authenticated
43
- WITH CHECK (owner_id = auth.uid());
44
-
45
- -- Politique: Les utilisateurs peuvent modifier leurs propres enregistrements
46
- DROP POLICY IF EXISTS user_token_ledger_owner_update ON public.user_token_ledger;
47
- CREATE POLICY user_token_ledger_owner_update ON public.user_token_ledger
48
- FOR UPDATE TO authenticated
49
- USING (owner_id = auth.uid())
50
- WITH CHECK (owner_id = auth.uid());
51
-
52
- -- Politique: Les utilisateurs peuvent supprimer leurs propres enregistrements
53
- DROP POLICY IF EXISTS user_token_ledger_owner_delete ON public.user_token_ledger;
54
- CREATE POLICY user_token_ledger_owner_delete ON public.user_token_ledger
55
- FOR DELETE TO authenticated
56
- USING (owner_id = auth.uid());
57
-
58
- -- Trigger updated_at
59
- DROP TRIGGER IF EXISTS set_user_token_ledger_updated_at ON public.user_token_ledger;
60
- CREATE TRIGGER set_user_token_ledger_updated_at
61
- BEFORE UPDATE ON public.user_token_ledger
62
- FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
63
-
64
- -- Index
65
- CREATE INDEX IF NOT EXISTS idx_user_token_ledger_owner_id ON public.user_token_ledger(owner_id);
66
-
67
- -- Grants
68
- GRANT SELECT, INSERT, UPDATE, DELETE ON public.user_token_ledger TO service_role;
69
-
70
-
71
- -- ===========================================================================
72
- -- Table: public.user_prompts
73
- -- ===========================================================================
74
- CREATE TABLE IF NOT EXISTS public.user_prompts (
75
- id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
76
- owner_id uuid NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
77
- title text NOT NULL,
78
- description text,
79
- created_at timestamptz NOT NULL DEFAULT now(),
80
- updated_at timestamptz NOT NULL DEFAULT now()
81
- );
82
-
83
- -- RLS
84
- ALTER TABLE public.user_prompts ENABLE ROW LEVEL SECURITY;
85
-
86
- -- Politique: Les utilisateurs peuvent voir leurs propres enregistrements
87
- DROP POLICY IF EXISTS user_prompts_owner_select ON public.user_prompts;
88
- CREATE POLICY user_prompts_owner_select ON public.user_prompts
89
- FOR SELECT TO authenticated
90
- USING (owner_id = auth.uid());
91
-
92
- -- Politique: Les utilisateurs peuvent créer leurs propres enregistrements
93
- DROP POLICY IF EXISTS user_prompts_owner_insert ON public.user_prompts;
94
- CREATE POLICY user_prompts_owner_insert ON public.user_prompts
95
- FOR INSERT TO authenticated
96
- WITH CHECK (owner_id = auth.uid());
97
-
98
- -- Politique: Les utilisateurs peuvent modifier leurs propres enregistrements
99
- DROP POLICY IF EXISTS user_prompts_owner_update ON public.user_prompts;
100
- CREATE POLICY user_prompts_owner_update ON public.user_prompts
101
- FOR UPDATE TO authenticated
102
- USING (owner_id = auth.uid())
103
- WITH CHECK (owner_id = auth.uid());
104
-
105
- -- Politique: Les utilisateurs peuvent supprimer leurs propres enregistrements
106
- DROP POLICY IF EXISTS user_prompts_owner_delete ON public.user_prompts;
107
- CREATE POLICY user_prompts_owner_delete ON public.user_prompts
108
- FOR DELETE TO authenticated
109
- USING (owner_id = auth.uid());
110
-
111
- -- Trigger updated_at
112
- DROP TRIGGER IF EXISTS set_user_prompts_updated_at ON public.user_prompts;
113
- CREATE TRIGGER set_user_prompts_updated_at
114
- BEFORE UPDATE ON public.user_prompts
115
- FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
116
-
117
- -- Index
118
- CREATE INDEX IF NOT EXISTS idx_user_prompts_owner_id ON public.user_prompts(owner_id);
119
-
120
- -- Grants
121
- GRANT SELECT, INSERT, UPDATE, DELETE ON public.user_prompts TO service_role;
122
-
@@ -1,23 +0,0 @@
1
- -- Migration DOWN pour ai_tokens
2
- -- Supprimer tous les éléments créés dans la migration up
3
-
4
- -- Supprimer le trigger
5
- DROP TRIGGER IF EXISTS check_token_balance_trigger ON public.user_token_ledger;
6
-
7
- -- Supprimer la fonction trigger
8
- DROP FUNCTION IF EXISTS public.check_token_balance() CASCADE;
9
-
10
- -- Supprimer les policies RLS
11
- DROP POLICY IF EXISTS "Users can view their own token balance" ON public.user_token_balance_v;
12
- DROP POLICY IF EXISTS "Users can view their own token ledger" ON public.user_token_ledger;
13
-
14
- -- Supprimer la vue
15
- DROP VIEW IF EXISTS public.user_token_balance_v CASCADE;
16
-
17
- -- Supprimer les indexes
18
- DROP INDEX IF EXISTS idx_user_token_ledger_owner_id;
19
- DROP INDEX IF EXISTS idx_user_token_ledger_ts;
20
- DROP INDEX IF EXISTS idx_user_token_ledger_type;
21
-
22
- -- Supprimer la table user_token_ledger
23
- DROP TABLE IF EXISTS public.user_token_ledger CASCADE;
@@ -1,11 +0,0 @@
1
- -- Migration DOWN pour module-ai_init
2
- -- Supprimer les éléments créés dans la migration up
3
-
4
- -- Supprimer les policies RLS si elles existent
5
- DROP POLICY IF EXISTS "Users can view their own prompts" ON public.user_prompts;
6
- DROP POLICY IF EXISTS "Users can create their own prompts" ON public.user_prompts;
7
- DROP POLICY IF EXISTS "Users can update their own prompts" ON public.user_prompts;
8
- DROP POLICY IF EXISTS "Users can delete their own prompts" ON public.user_prompts;
9
-
10
- -- Supprimer la table user_prompts
11
- DROP TABLE IF EXISTS public.user_prompts CASCADE;