@mdxui/auth 1.1.0 → 1.4.0
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/README.md +128 -1
- package/dist/{auth-Ba2f778e.d.ts → auth-maeYSYU_.d.ts} +4 -1
- package/dist/hooks/index.d.ts +92 -2
- package/dist/hooks/index.js +84 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/{index-Bl4BwORF.d.ts → index-BOMpMKyG.d.ts} +105 -2
- package/dist/index.d.ts +8 -3
- package/dist/index.js +1651 -36
- package/dist/index.js.map +1 -1
- package/dist/providers/index.d.ts +3 -2
- package/dist/providers/index.js +85 -2
- package/dist/providers/index.js.map +1 -1
- package/dist/schemas/index.d.ts +5 -0
- package/dist/schemas/index.js +1 -1
- package/dist/schemas/index.js.map +1 -1
- package/dist/shell/index.d.ts +675 -0
- package/dist/shell/index.js +1025 -0
- package/dist/shell/index.js.map +1 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types-8tixck1H.d.ts +123 -0
- package/dist/vault/index.d.ts +192 -0
- package/dist/vault/index.js +692 -0
- package/dist/vault/index.js.map +1 -0
- package/dist/widgets/index.d.ts +1 -1
- package/package.json +27 -13
|
@@ -0,0 +1,692 @@
|
|
|
1
|
+
// src/vault/secrets-manager/secrets-manager.tsx
|
|
2
|
+
import {
|
|
3
|
+
Badge,
|
|
4
|
+
Button as Button2,
|
|
5
|
+
Card,
|
|
6
|
+
CardContent,
|
|
7
|
+
CardDescription,
|
|
8
|
+
CardHeader,
|
|
9
|
+
CardTitle,
|
|
10
|
+
Dialog,
|
|
11
|
+
DialogContent,
|
|
12
|
+
DialogHeader,
|
|
13
|
+
DialogTitle,
|
|
14
|
+
DialogTrigger,
|
|
15
|
+
Input as Input2,
|
|
16
|
+
Select as Select2,
|
|
17
|
+
SelectContent as SelectContent2,
|
|
18
|
+
SelectItem as SelectItem2,
|
|
19
|
+
SelectTrigger as SelectTrigger2,
|
|
20
|
+
SelectValue as SelectValue2,
|
|
21
|
+
Table,
|
|
22
|
+
TableBody,
|
|
23
|
+
TableCell,
|
|
24
|
+
TableHead,
|
|
25
|
+
TableHeader,
|
|
26
|
+
TableRow
|
|
27
|
+
} from "@mdxui/primitives";
|
|
28
|
+
import { cn } from "@mdxui/primitives/lib/utils";
|
|
29
|
+
import {
|
|
30
|
+
Copy,
|
|
31
|
+
Edit,
|
|
32
|
+
Eye,
|
|
33
|
+
EyeOff,
|
|
34
|
+
Filter,
|
|
35
|
+
Plus,
|
|
36
|
+
Search,
|
|
37
|
+
Trash2
|
|
38
|
+
} from "lucide-react";
|
|
39
|
+
import * as React2 from "react";
|
|
40
|
+
import { toast } from "sonner";
|
|
41
|
+
|
|
42
|
+
// src/vault/secrets-manager/secret-form.tsx
|
|
43
|
+
import {
|
|
44
|
+
Button,
|
|
45
|
+
Input,
|
|
46
|
+
Label,
|
|
47
|
+
Select,
|
|
48
|
+
SelectContent,
|
|
49
|
+
SelectItem,
|
|
50
|
+
SelectTrigger,
|
|
51
|
+
SelectValue,
|
|
52
|
+
Textarea
|
|
53
|
+
} from "@mdxui/primitives";
|
|
54
|
+
import * as React from "react";
|
|
55
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
56
|
+
function SecretForm({
|
|
57
|
+
secret,
|
|
58
|
+
environment: defaultEnvironment,
|
|
59
|
+
environments,
|
|
60
|
+
onSubmit,
|
|
61
|
+
onCancel
|
|
62
|
+
}) {
|
|
63
|
+
const [key, setKey] = React.useState(secret?.key || "");
|
|
64
|
+
const [value, setValue] = React.useState(secret?.value || "");
|
|
65
|
+
const [description, setDescription] = React.useState(
|
|
66
|
+
secret?.description || ""
|
|
67
|
+
);
|
|
68
|
+
const [environment, setEnvironment] = React.useState(
|
|
69
|
+
secret?.environment || defaultEnvironment
|
|
70
|
+
);
|
|
71
|
+
const handleSubmit = (e) => {
|
|
72
|
+
e.preventDefault();
|
|
73
|
+
if (!key.trim() || !value.trim()) return;
|
|
74
|
+
onSubmit({
|
|
75
|
+
key: key.trim(),
|
|
76
|
+
value: value.trim(),
|
|
77
|
+
description: description.trim() || void 0,
|
|
78
|
+
environment
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
|
|
82
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
83
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "key", children: "Key *" }),
|
|
84
|
+
/* @__PURE__ */ jsx(
|
|
85
|
+
Input,
|
|
86
|
+
{
|
|
87
|
+
id: "key",
|
|
88
|
+
placeholder: "DATABASE_URL",
|
|
89
|
+
value: key,
|
|
90
|
+
onChange: (e) => setKey(e.target.value.toUpperCase().replace(/[^A-Z0-9_]/g, "_")),
|
|
91
|
+
required: true,
|
|
92
|
+
autoFocus: true
|
|
93
|
+
}
|
|
94
|
+
),
|
|
95
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Use UPPER_CASE with underscores (e.g., API_KEY, DATABASE_URL)" })
|
|
96
|
+
] }),
|
|
97
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
98
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "value", children: "Value *" }),
|
|
99
|
+
/* @__PURE__ */ jsx(
|
|
100
|
+
Textarea,
|
|
101
|
+
{
|
|
102
|
+
id: "value",
|
|
103
|
+
placeholder: "Enter secret value",
|
|
104
|
+
value,
|
|
105
|
+
onChange: (e) => setValue(e.target.value),
|
|
106
|
+
rows: 3,
|
|
107
|
+
required: true,
|
|
108
|
+
className: "font-mono"
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
] }),
|
|
112
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
113
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "environment", children: "Environment *" }),
|
|
114
|
+
/* @__PURE__ */ jsxs(Select, { value: environment, onValueChange: setEnvironment, children: [
|
|
115
|
+
/* @__PURE__ */ jsx(SelectTrigger, { id: "environment", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
116
|
+
/* @__PURE__ */ jsx(SelectContent, { children: environments.map((env) => /* @__PURE__ */ jsx(SelectItem, { value: env, children: env.charAt(0).toUpperCase() + env.slice(1) }, env)) })
|
|
117
|
+
] })
|
|
118
|
+
] }),
|
|
119
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
120
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "description", children: "Description" }),
|
|
121
|
+
/* @__PURE__ */ jsx(
|
|
122
|
+
Textarea,
|
|
123
|
+
{
|
|
124
|
+
id: "description",
|
|
125
|
+
placeholder: "Optional description of this secret",
|
|
126
|
+
value: description,
|
|
127
|
+
onChange: (e) => setDescription(e.target.value),
|
|
128
|
+
rows: 2
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
] }),
|
|
132
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
|
|
133
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: onCancel, children: "Cancel" }),
|
|
134
|
+
/* @__PURE__ */ jsxs(Button, { type: "submit", disabled: !key.trim() || !value.trim(), children: [
|
|
135
|
+
secret ? "Update" : "Create",
|
|
136
|
+
" Secret"
|
|
137
|
+
] })
|
|
138
|
+
] })
|
|
139
|
+
] });
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// src/vault/secrets-manager/secrets-manager.tsx
|
|
143
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
144
|
+
function SecretsManager({
|
|
145
|
+
secrets: externalSecrets = [],
|
|
146
|
+
environments = ["development", "staging", "production"],
|
|
147
|
+
currentEnvironment = "development",
|
|
148
|
+
onEnvironmentChange,
|
|
149
|
+
onCreate,
|
|
150
|
+
onUpdate,
|
|
151
|
+
onDelete,
|
|
152
|
+
hideValues: initialHideValues = true,
|
|
153
|
+
editable = true,
|
|
154
|
+
className
|
|
155
|
+
}) {
|
|
156
|
+
const [localSecrets, setLocalSecrets] = React2.useState([]);
|
|
157
|
+
const [hideValues, setHideValues] = React2.useState(initialHideValues);
|
|
158
|
+
const [searchQuery, setSearchQuery] = React2.useState("");
|
|
159
|
+
const [environment, setEnvironment] = React2.useState(currentEnvironment);
|
|
160
|
+
const [visibleSecrets, setVisibleSecrets] = React2.useState(
|
|
161
|
+
/* @__PURE__ */ new Set()
|
|
162
|
+
);
|
|
163
|
+
const [editingSecret, setEditingSecret] = React2.useState(null);
|
|
164
|
+
const [isCreateDialogOpen, setIsCreateDialogOpen] = React2.useState(false);
|
|
165
|
+
const [isEditDialogOpen, setIsEditDialogOpen] = React2.useState(false);
|
|
166
|
+
const secrets = externalSecrets.length > 0 ? externalSecrets : localSecrets;
|
|
167
|
+
React2.useEffect(() => {
|
|
168
|
+
setEnvironment(currentEnvironment);
|
|
169
|
+
}, [currentEnvironment]);
|
|
170
|
+
const filteredSecrets = React2.useMemo(() => {
|
|
171
|
+
return secrets.filter((secret) => {
|
|
172
|
+
const matchesSearch = searchQuery ? secret.key.toLowerCase().includes(searchQuery.toLowerCase()) || secret.description?.toLowerCase().includes(searchQuery.toLowerCase()) : true;
|
|
173
|
+
const matchesEnvironment = environment === "all" || secret.environment === environment;
|
|
174
|
+
return matchesSearch && matchesEnvironment;
|
|
175
|
+
});
|
|
176
|
+
}, [secrets, searchQuery, environment]);
|
|
177
|
+
const handleEnvironmentChange = (newEnvironment) => {
|
|
178
|
+
setEnvironment(newEnvironment);
|
|
179
|
+
onEnvironmentChange?.(newEnvironment);
|
|
180
|
+
};
|
|
181
|
+
const handleCreate = async (secretData) => {
|
|
182
|
+
const newSecret = {
|
|
183
|
+
...secretData,
|
|
184
|
+
id: crypto.randomUUID(),
|
|
185
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
186
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
187
|
+
};
|
|
188
|
+
try {
|
|
189
|
+
await onCreate?.(secretData);
|
|
190
|
+
if (externalSecrets.length === 0) {
|
|
191
|
+
setLocalSecrets((prev) => [...prev, newSecret]);
|
|
192
|
+
}
|
|
193
|
+
setIsCreateDialogOpen(false);
|
|
194
|
+
toast.success("Secret created successfully");
|
|
195
|
+
} catch (error) {
|
|
196
|
+
toast.error("Failed to create secret");
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
const handleUpdate = async (id, updates) => {
|
|
200
|
+
try {
|
|
201
|
+
await onUpdate?.(id, { ...updates, updatedAt: /* @__PURE__ */ new Date() });
|
|
202
|
+
if (externalSecrets.length === 0) {
|
|
203
|
+
setLocalSecrets(
|
|
204
|
+
(prev) => prev.map(
|
|
205
|
+
(secret) => secret.id === id ? { ...secret, ...updates, updatedAt: /* @__PURE__ */ new Date() } : secret
|
|
206
|
+
)
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
setIsEditDialogOpen(false);
|
|
210
|
+
setEditingSecret(null);
|
|
211
|
+
toast.success("Secret updated successfully");
|
|
212
|
+
} catch (error) {
|
|
213
|
+
toast.error("Failed to update secret");
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
const handleDelete = async (id) => {
|
|
217
|
+
if (!confirm("Are you sure you want to delete this secret?")) return;
|
|
218
|
+
try {
|
|
219
|
+
await onDelete?.(id);
|
|
220
|
+
if (externalSecrets.length === 0) {
|
|
221
|
+
setLocalSecrets((prev) => prev.filter((secret) => secret.id !== id));
|
|
222
|
+
}
|
|
223
|
+
toast.success("Secret deleted");
|
|
224
|
+
} catch (error) {
|
|
225
|
+
toast.error("Failed to delete secret");
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
const handleCopy = (value) => {
|
|
229
|
+
navigator.clipboard.writeText(value);
|
|
230
|
+
toast.success("Value copied to clipboard");
|
|
231
|
+
};
|
|
232
|
+
const toggleSecretVisibility = (id) => {
|
|
233
|
+
setVisibleSecrets((prev) => {
|
|
234
|
+
const next = new Set(prev);
|
|
235
|
+
if (next.has(id)) {
|
|
236
|
+
next.delete(id);
|
|
237
|
+
} else {
|
|
238
|
+
next.add(id);
|
|
239
|
+
}
|
|
240
|
+
return next;
|
|
241
|
+
});
|
|
242
|
+
};
|
|
243
|
+
const toggleAllVisibility = () => {
|
|
244
|
+
setHideValues(!hideValues);
|
|
245
|
+
if (!hideValues) {
|
|
246
|
+
setVisibleSecrets(/* @__PURE__ */ new Set());
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
const isSecretVisible = (id) => {
|
|
250
|
+
return hideValues ? visibleSecrets.has(id) : true;
|
|
251
|
+
};
|
|
252
|
+
return /* @__PURE__ */ jsxs2("div", { className: cn("space-y-4", className), children: [
|
|
253
|
+
/* @__PURE__ */ jsxs2(Card, { children: [
|
|
254
|
+
/* @__PURE__ */ jsx2(CardHeader, { children: /* @__PURE__ */ jsxs2("div", { className: "flex items-start justify-between", children: [
|
|
255
|
+
/* @__PURE__ */ jsxs2("div", { children: [
|
|
256
|
+
/* @__PURE__ */ jsx2(CardTitle, { children: "Environment Variables" }),
|
|
257
|
+
/* @__PURE__ */ jsx2(CardDescription, { children: "Manage your application secrets and configuration" })
|
|
258
|
+
] }),
|
|
259
|
+
editable && /* @__PURE__ */ jsxs2(
|
|
260
|
+
Dialog,
|
|
261
|
+
{
|
|
262
|
+
open: isCreateDialogOpen,
|
|
263
|
+
onOpenChange: setIsCreateDialogOpen,
|
|
264
|
+
children: [
|
|
265
|
+
/* @__PURE__ */ jsx2(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs2(Button2, { children: [
|
|
266
|
+
/* @__PURE__ */ jsx2(Plus, { className: "mr-2 size-4" }),
|
|
267
|
+
"Add Secret"
|
|
268
|
+
] }) }),
|
|
269
|
+
/* @__PURE__ */ jsxs2(DialogContent, { children: [
|
|
270
|
+
/* @__PURE__ */ jsx2(DialogHeader, { children: /* @__PURE__ */ jsx2(DialogTitle, { children: "Create New Secret" }) }),
|
|
271
|
+
/* @__PURE__ */ jsx2(
|
|
272
|
+
SecretForm,
|
|
273
|
+
{
|
|
274
|
+
environment,
|
|
275
|
+
environments,
|
|
276
|
+
onSubmit: handleCreate,
|
|
277
|
+
onCancel: () => setIsCreateDialogOpen(false)
|
|
278
|
+
}
|
|
279
|
+
)
|
|
280
|
+
] })
|
|
281
|
+
]
|
|
282
|
+
}
|
|
283
|
+
)
|
|
284
|
+
] }) }),
|
|
285
|
+
/* @__PURE__ */ jsxs2(CardContent, { className: "space-y-4", children: [
|
|
286
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
287
|
+
/* @__PURE__ */ jsxs2("div", { className: "relative flex-1", children: [
|
|
288
|
+
/* @__PURE__ */ jsx2(Search, { className: "absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" }),
|
|
289
|
+
/* @__PURE__ */ jsx2(
|
|
290
|
+
Input2,
|
|
291
|
+
{
|
|
292
|
+
placeholder: "Search secrets...",
|
|
293
|
+
value: searchQuery,
|
|
294
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
295
|
+
className: "pl-9"
|
|
296
|
+
}
|
|
297
|
+
)
|
|
298
|
+
] }),
|
|
299
|
+
/* @__PURE__ */ jsxs2(Select2, { value: environment, onValueChange: handleEnvironmentChange, children: [
|
|
300
|
+
/* @__PURE__ */ jsxs2(SelectTrigger2, { className: "w-[180px]", children: [
|
|
301
|
+
/* @__PURE__ */ jsx2(Filter, { className: "mr-2 size-4" }),
|
|
302
|
+
/* @__PURE__ */ jsx2(SelectValue2, {})
|
|
303
|
+
] }),
|
|
304
|
+
/* @__PURE__ */ jsxs2(SelectContent2, { children: [
|
|
305
|
+
/* @__PURE__ */ jsx2(SelectItem2, { value: "all", children: "All Environments" }),
|
|
306
|
+
environments.map((env) => /* @__PURE__ */ jsx2(SelectItem2, { value: env, children: env.charAt(0).toUpperCase() + env.slice(1) }, env))
|
|
307
|
+
] })
|
|
308
|
+
] }),
|
|
309
|
+
/* @__PURE__ */ jsx2(Button2, { variant: "outline", size: "icon", onClick: toggleAllVisibility, children: hideValues ? /* @__PURE__ */ jsx2(Eye, { className: "size-4" }) : /* @__PURE__ */ jsx2(EyeOff, { className: "size-4" }) })
|
|
310
|
+
] }),
|
|
311
|
+
filteredSecrets.length > 0 ? /* @__PURE__ */ jsx2("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxs2(Table, { children: [
|
|
312
|
+
/* @__PURE__ */ jsx2(TableHeader, { children: /* @__PURE__ */ jsxs2(TableRow, { children: [
|
|
313
|
+
/* @__PURE__ */ jsx2(TableHead, { children: "Key" }),
|
|
314
|
+
/* @__PURE__ */ jsx2(TableHead, { children: "Value" }),
|
|
315
|
+
/* @__PURE__ */ jsx2(TableHead, { children: "Environment" }),
|
|
316
|
+
/* @__PURE__ */ jsx2(TableHead, { children: "Description" }),
|
|
317
|
+
/* @__PURE__ */ jsx2(TableHead, { className: "w-[100px]", children: "Actions" })
|
|
318
|
+
] }) }),
|
|
319
|
+
/* @__PURE__ */ jsx2(TableBody, { children: filteredSecrets.map((secret) => /* @__PURE__ */ jsxs2(TableRow, { children: [
|
|
320
|
+
/* @__PURE__ */ jsx2(TableCell, { children: /* @__PURE__ */ jsx2("code", { className: "rounded bg-muted px-2 py-1 font-mono text-sm", children: secret.key }) }),
|
|
321
|
+
/* @__PURE__ */ jsx2(TableCell, { children: /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
|
|
322
|
+
/* @__PURE__ */ jsx2("code", { className: "flex-1 rounded bg-muted px-2 py-1 font-mono text-sm", children: isSecretVisible(secret.id) ? secret.value : "\u2022".repeat(Math.min(secret.value.length, 20)) }),
|
|
323
|
+
/* @__PURE__ */ jsx2(
|
|
324
|
+
Button2,
|
|
325
|
+
{
|
|
326
|
+
variant: "ghost",
|
|
327
|
+
size: "icon-sm",
|
|
328
|
+
onClick: () => toggleSecretVisibility(secret.id),
|
|
329
|
+
children: isSecretVisible(secret.id) ? /* @__PURE__ */ jsx2(EyeOff, { className: "size-4" }) : /* @__PURE__ */ jsx2(Eye, { className: "size-4" })
|
|
330
|
+
}
|
|
331
|
+
),
|
|
332
|
+
/* @__PURE__ */ jsx2(
|
|
333
|
+
Button2,
|
|
334
|
+
{
|
|
335
|
+
variant: "ghost",
|
|
336
|
+
size: "icon-sm",
|
|
337
|
+
onClick: () => handleCopy(secret.value),
|
|
338
|
+
children: /* @__PURE__ */ jsx2(Copy, { className: "size-4" })
|
|
339
|
+
}
|
|
340
|
+
)
|
|
341
|
+
] }) }),
|
|
342
|
+
/* @__PURE__ */ jsx2(TableCell, { children: /* @__PURE__ */ jsx2(Badge, { variant: "secondary", children: secret.environment }) }),
|
|
343
|
+
/* @__PURE__ */ jsx2(TableCell, { children: /* @__PURE__ */ jsx2("span", { className: "text-sm text-muted-foreground", children: secret.description || "-" }) }),
|
|
344
|
+
/* @__PURE__ */ jsx2(TableCell, { children: editable && /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-1", children: [
|
|
345
|
+
/* @__PURE__ */ jsx2(
|
|
346
|
+
Button2,
|
|
347
|
+
{
|
|
348
|
+
variant: "ghost",
|
|
349
|
+
size: "icon-sm",
|
|
350
|
+
onClick: () => {
|
|
351
|
+
setEditingSecret(secret);
|
|
352
|
+
setIsEditDialogOpen(true);
|
|
353
|
+
},
|
|
354
|
+
children: /* @__PURE__ */ jsx2(Edit, { className: "size-4" })
|
|
355
|
+
}
|
|
356
|
+
),
|
|
357
|
+
/* @__PURE__ */ jsx2(
|
|
358
|
+
Button2,
|
|
359
|
+
{
|
|
360
|
+
variant: "ghost",
|
|
361
|
+
size: "icon-sm",
|
|
362
|
+
onClick: () => handleDelete(secret.id),
|
|
363
|
+
children: /* @__PURE__ */ jsx2(Trash2, { className: "size-4 text-destructive" })
|
|
364
|
+
}
|
|
365
|
+
)
|
|
366
|
+
] }) })
|
|
367
|
+
] }, secret.id)) })
|
|
368
|
+
] }) }) : /* @__PURE__ */ jsx2("div", { className: "flex h-32 items-center justify-center rounded-md border-2 border-dashed", children: /* @__PURE__ */ jsx2("p", { className: "text-sm text-muted-foreground", children: searchQuery ? "No secrets found matching your search" : "No secrets yet. Add your first secret to get started." }) })
|
|
369
|
+
] })
|
|
370
|
+
] }),
|
|
371
|
+
editingSecret && /* @__PURE__ */ jsx2(Dialog, { open: isEditDialogOpen, onOpenChange: setIsEditDialogOpen, children: /* @__PURE__ */ jsxs2(DialogContent, { children: [
|
|
372
|
+
/* @__PURE__ */ jsx2(DialogHeader, { children: /* @__PURE__ */ jsx2(DialogTitle, { children: "Edit Secret" }) }),
|
|
373
|
+
/* @__PURE__ */ jsx2(
|
|
374
|
+
SecretForm,
|
|
375
|
+
{
|
|
376
|
+
secret: editingSecret,
|
|
377
|
+
environment,
|
|
378
|
+
environments,
|
|
379
|
+
onSubmit: (data) => handleUpdate(editingSecret.id, data),
|
|
380
|
+
onCancel: () => {
|
|
381
|
+
setIsEditDialogOpen(false);
|
|
382
|
+
setEditingSecret(null);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
)
|
|
386
|
+
] }) })
|
|
387
|
+
] });
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// src/vault/vault-delete-dialog.tsx
|
|
391
|
+
import {
|
|
392
|
+
Button as Button3,
|
|
393
|
+
Dialog as Dialog2,
|
|
394
|
+
DialogContent as DialogContent2,
|
|
395
|
+
DialogDescription,
|
|
396
|
+
DialogFooter,
|
|
397
|
+
DialogHeader as DialogHeader2,
|
|
398
|
+
DialogTitle as DialogTitle2
|
|
399
|
+
} from "@mdxui/primitives";
|
|
400
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
401
|
+
function VaultDeleteDialog({ isOpen, onClose, itemName, onConfirm }) {
|
|
402
|
+
return /* @__PURE__ */ jsx3(Dialog2, { open: isOpen, onOpenChange: onClose, children: /* @__PURE__ */ jsxs3(DialogContent2, { children: [
|
|
403
|
+
/* @__PURE__ */ jsxs3(DialogHeader2, { children: [
|
|
404
|
+
/* @__PURE__ */ jsx3(DialogTitle2, { children: "Delete Credentials" }),
|
|
405
|
+
/* @__PURE__ */ jsxs3(DialogDescription, { children: [
|
|
406
|
+
"Are you sure you want to delete credentials for ",
|
|
407
|
+
itemName,
|
|
408
|
+
"? This action cannot be undone."
|
|
409
|
+
] })
|
|
410
|
+
] }),
|
|
411
|
+
/* @__PURE__ */ jsxs3(DialogFooter, { children: [
|
|
412
|
+
/* @__PURE__ */ jsx3(Button3, { variant: "outline", onClick: onClose, children: "Cancel" }),
|
|
413
|
+
/* @__PURE__ */ jsx3(Button3, { variant: "destructive", onClick: onConfirm, children: "Delete" })
|
|
414
|
+
] })
|
|
415
|
+
] }) });
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// src/vault/vault-empty-state.tsx
|
|
419
|
+
import { Button as Button4 } from "@mdxui/primitives";
|
|
420
|
+
import { Lock } from "lucide-react";
|
|
421
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
422
|
+
function VaultEmptyState({ onAddCredential }) {
|
|
423
|
+
return /* @__PURE__ */ jsxs4("div", { className: "flex flex-col items-center justify-center rounded-md border border-dashed py-24 px-4 text-center", children: [
|
|
424
|
+
/* @__PURE__ */ jsx4("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-muted mb-4", children: /* @__PURE__ */ jsx4(Lock, { className: "h-6 w-6 text-muted-foreground" }) }),
|
|
425
|
+
/* @__PURE__ */ jsx4("h3", { className: "text-lg font-semibold mb-2", children: "No saved credentials" }),
|
|
426
|
+
/* @__PURE__ */ jsx4("p", { className: "text-sm text-muted-foreground mb-6 max-w-md", children: "Add API keys and account credentials for your agents to use securely." }),
|
|
427
|
+
/* @__PURE__ */ jsx4(Button4, { onClick: onAddCredential, children: "Add Credential" })
|
|
428
|
+
] });
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// src/vault/vault-input-modal.tsx
|
|
432
|
+
import {
|
|
433
|
+
Button as Button5,
|
|
434
|
+
Dialog as Dialog3,
|
|
435
|
+
DialogContent as DialogContent3,
|
|
436
|
+
DialogFooter as DialogFooter2,
|
|
437
|
+
DialogHeader as DialogHeader3,
|
|
438
|
+
DialogTitle as DialogTitle3,
|
|
439
|
+
Input as Input3,
|
|
440
|
+
Label as Label2
|
|
441
|
+
} from "@mdxui/primitives";
|
|
442
|
+
import { Key } from "lucide-react";
|
|
443
|
+
import { useState as useState3 } from "react";
|
|
444
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
445
|
+
function VaultInputModal({
|
|
446
|
+
isOpen,
|
|
447
|
+
onClose,
|
|
448
|
+
mode,
|
|
449
|
+
integration,
|
|
450
|
+
onSave
|
|
451
|
+
}) {
|
|
452
|
+
const [values, setValues] = useState3({});
|
|
453
|
+
const [loading, setLoading] = useState3(false);
|
|
454
|
+
const handleSubmit = async (e) => {
|
|
455
|
+
e.preventDefault();
|
|
456
|
+
setLoading(true);
|
|
457
|
+
try {
|
|
458
|
+
await onSave(values);
|
|
459
|
+
setValues({});
|
|
460
|
+
onClose();
|
|
461
|
+
} catch (error) {
|
|
462
|
+
console.error("Failed to save credentials:", error);
|
|
463
|
+
} finally {
|
|
464
|
+
setLoading(false);
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
const handleClose = () => {
|
|
468
|
+
setValues({});
|
|
469
|
+
onClose();
|
|
470
|
+
};
|
|
471
|
+
if (!integration) return null;
|
|
472
|
+
const isValid = integration.fields.filter((f) => f.required).every((f) => values[f.key]?.trim());
|
|
473
|
+
return /* @__PURE__ */ jsx5(Dialog3, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs5(DialogContent3, { children: [
|
|
474
|
+
/* @__PURE__ */ jsx5(DialogHeader3, { children: /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3", children: [
|
|
475
|
+
/* @__PURE__ */ jsx5("div", { className: "flex h-10 w-10 items-center justify-center rounded-md bg-white overflow-hidden p-1 border border-border", children: integration.logoUrl ? /* @__PURE__ */ jsx5(
|
|
476
|
+
"img",
|
|
477
|
+
{
|
|
478
|
+
src: integration.logoUrl,
|
|
479
|
+
alt: integration.name,
|
|
480
|
+
width: 32,
|
|
481
|
+
height: 32,
|
|
482
|
+
className: "h-full w-full object-contain rounded-sm"
|
|
483
|
+
}
|
|
484
|
+
) : /* @__PURE__ */ jsx5(Key, { className: "h-5 w-5 text-muted-foreground" }) }),
|
|
485
|
+
/* @__PURE__ */ jsxs5(DialogTitle3, { children: [
|
|
486
|
+
mode === "create" ? "Add" : "Rotate",
|
|
487
|
+
" ",
|
|
488
|
+
integration.name,
|
|
489
|
+
" Credentials"
|
|
490
|
+
] })
|
|
491
|
+
] }) }),
|
|
492
|
+
/* @__PURE__ */ jsxs5("form", { onSubmit: handleSubmit, children: [
|
|
493
|
+
/* @__PURE__ */ jsx5("div", { className: "grid gap-4 py-4", children: integration.fields.map((field) => /* @__PURE__ */ jsxs5("div", { className: "grid gap-2", children: [
|
|
494
|
+
/* @__PURE__ */ jsxs5(Label2, { htmlFor: field.key, children: [
|
|
495
|
+
field.label,
|
|
496
|
+
field.required && /* @__PURE__ */ jsx5("span", { className: "text-destructive", children: "*" })
|
|
497
|
+
] }),
|
|
498
|
+
/* @__PURE__ */ jsx5(
|
|
499
|
+
Input3,
|
|
500
|
+
{
|
|
501
|
+
id: field.key,
|
|
502
|
+
type: field.type,
|
|
503
|
+
placeholder: field.placeholder,
|
|
504
|
+
value: values[field.key] || "",
|
|
505
|
+
onChange: (e) => setValues((prev) => ({
|
|
506
|
+
...prev,
|
|
507
|
+
[field.key]: e.target.value
|
|
508
|
+
})),
|
|
509
|
+
required: field.required
|
|
510
|
+
}
|
|
511
|
+
)
|
|
512
|
+
] }, field.key)) }),
|
|
513
|
+
/* @__PURE__ */ jsxs5(DialogFooter2, { children: [
|
|
514
|
+
/* @__PURE__ */ jsx5(Button5, { type: "button", variant: "outline", onClick: handleClose, children: "Cancel" }),
|
|
515
|
+
/* @__PURE__ */ jsx5(Button5, { type: "submit", disabled: loading || !isValid, children: loading ? "Saving..." : "Save" })
|
|
516
|
+
] })
|
|
517
|
+
] })
|
|
518
|
+
] }) });
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// src/vault/vault-item-card.tsx
|
|
522
|
+
import {
|
|
523
|
+
Button as Button6,
|
|
524
|
+
Card as Card2,
|
|
525
|
+
DropdownMenu,
|
|
526
|
+
DropdownMenuContent,
|
|
527
|
+
DropdownMenuItem,
|
|
528
|
+
DropdownMenuTrigger
|
|
529
|
+
} from "@mdxui/primitives";
|
|
530
|
+
import { Key as Key2, MoreVertical } from "lucide-react";
|
|
531
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
532
|
+
function formatDate(date) {
|
|
533
|
+
return date.toLocaleDateString("en-US", {
|
|
534
|
+
month: "short",
|
|
535
|
+
day: "numeric",
|
|
536
|
+
year: "numeric"
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
function VaultItemCard({
|
|
540
|
+
id,
|
|
541
|
+
name,
|
|
542
|
+
logoUrl,
|
|
543
|
+
createdAt,
|
|
544
|
+
updatedAt,
|
|
545
|
+
onRotate,
|
|
546
|
+
onDelete
|
|
547
|
+
}) {
|
|
548
|
+
const wasRotated = updatedAt.getTime() !== createdAt.getTime();
|
|
549
|
+
return /* @__PURE__ */ jsx6(Card2, { noPadding: true, className: "p-4", children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between", children: [
|
|
550
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3", children: [
|
|
551
|
+
/* @__PURE__ */ jsx6("div", { className: "flex h-10 w-10 items-center justify-center rounded-md bg-white overflow-hidden p-1 border border-border", children: logoUrl ? /* @__PURE__ */ jsx6(
|
|
552
|
+
"img",
|
|
553
|
+
{
|
|
554
|
+
src: logoUrl,
|
|
555
|
+
alt: name,
|
|
556
|
+
width: 32,
|
|
557
|
+
height: 32,
|
|
558
|
+
className: "h-full w-full object-contain rounded-sm"
|
|
559
|
+
}
|
|
560
|
+
) : /* @__PURE__ */ jsx6(Key2, { className: "h-5 w-5 text-muted-foreground" }) }),
|
|
561
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
562
|
+
/* @__PURE__ */ jsx6("h4", { className: "text-sm font-medium", children: name }),
|
|
563
|
+
/* @__PURE__ */ jsx6("p", { className: "text-xs text-muted-foreground", children: wasRotated ? `Rotated: ${formatDate(updatedAt)}` : `Created: ${formatDate(createdAt)}` })
|
|
564
|
+
] })
|
|
565
|
+
] }),
|
|
566
|
+
/* @__PURE__ */ jsxs6(DropdownMenu, { children: [
|
|
567
|
+
/* @__PURE__ */ jsx6(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs6(Button6, { variant: "ghost", size: "icon-sm", children: [
|
|
568
|
+
/* @__PURE__ */ jsx6(MoreVertical, { className: "h-4 w-4" }),
|
|
569
|
+
/* @__PURE__ */ jsx6("span", { className: "sr-only", children: "Open menu" })
|
|
570
|
+
] }) }),
|
|
571
|
+
/* @__PURE__ */ jsxs6(DropdownMenuContent, { align: "end", children: [
|
|
572
|
+
/* @__PURE__ */ jsx6(DropdownMenuItem, { onClick: () => onRotate(id), children: "Rotate" }),
|
|
573
|
+
/* @__PURE__ */ jsx6(
|
|
574
|
+
DropdownMenuItem,
|
|
575
|
+
{
|
|
576
|
+
className: "text-destructive focus:text-destructive",
|
|
577
|
+
onClick: () => onDelete(id),
|
|
578
|
+
children: "Delete"
|
|
579
|
+
}
|
|
580
|
+
)
|
|
581
|
+
] })
|
|
582
|
+
] })
|
|
583
|
+
] }) });
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// src/vault/vault-list.tsx
|
|
587
|
+
import { useState as useState4 } from "react";
|
|
588
|
+
import { Fragment, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
589
|
+
var defaultFields = [
|
|
590
|
+
{ key: "api_key", label: "API Key", type: "password", required: true }
|
|
591
|
+
];
|
|
592
|
+
function VaultList({
|
|
593
|
+
items,
|
|
594
|
+
onRotate,
|
|
595
|
+
onDelete,
|
|
596
|
+
onOpenAddModal,
|
|
597
|
+
getIntegrationFields
|
|
598
|
+
}) {
|
|
599
|
+
const [deleteDialogOpen, setDeleteDialogOpen] = useState4(false);
|
|
600
|
+
const [inputModalOpen, setInputModalOpen] = useState4(false);
|
|
601
|
+
const [selectedItem, setSelectedItem] = useState4(null);
|
|
602
|
+
const [modalMode, setModalMode] = useState4("create");
|
|
603
|
+
const handleRotate = (id) => {
|
|
604
|
+
const item = items.find((i) => i.id === id);
|
|
605
|
+
if (!item) return;
|
|
606
|
+
setSelectedItem(item);
|
|
607
|
+
setModalMode("rotate");
|
|
608
|
+
setInputModalOpen(true);
|
|
609
|
+
};
|
|
610
|
+
const handleDeleteClick = (id) => {
|
|
611
|
+
const item = items.find((i) => i.id === id);
|
|
612
|
+
if (!item) return;
|
|
613
|
+
setSelectedItem(item);
|
|
614
|
+
setDeleteDialogOpen(true);
|
|
615
|
+
};
|
|
616
|
+
const handleConfirmDelete = async () => {
|
|
617
|
+
if (!selectedItem) return;
|
|
618
|
+
await onDelete(selectedItem.id);
|
|
619
|
+
setDeleteDialogOpen(false);
|
|
620
|
+
setSelectedItem(null);
|
|
621
|
+
};
|
|
622
|
+
const handleSave = async (credentials) => {
|
|
623
|
+
if (modalMode === "rotate" && selectedItem) {
|
|
624
|
+
await onRotate(selectedItem.id, credentials);
|
|
625
|
+
}
|
|
626
|
+
setInputModalOpen(false);
|
|
627
|
+
setSelectedItem(null);
|
|
628
|
+
};
|
|
629
|
+
const getIntegrationForModal = () => {
|
|
630
|
+
if (!selectedItem) return void 0;
|
|
631
|
+
const fields = getIntegrationFields ? getIntegrationFields(selectedItem.integrationId) : defaultFields;
|
|
632
|
+
return {
|
|
633
|
+
id: selectedItem.integrationId,
|
|
634
|
+
name: selectedItem.name,
|
|
635
|
+
logoUrl: selectedItem.logoUrl,
|
|
636
|
+
fields
|
|
637
|
+
};
|
|
638
|
+
};
|
|
639
|
+
if (items.length === 0) {
|
|
640
|
+
return /* @__PURE__ */ jsx7(VaultEmptyState, { onAddCredential: onOpenAddModal });
|
|
641
|
+
}
|
|
642
|
+
return /* @__PURE__ */ jsxs7(Fragment, { children: [
|
|
643
|
+
/* @__PURE__ */ jsx7("div", { className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3", children: items.map((item) => /* @__PURE__ */ jsx7(
|
|
644
|
+
VaultItemCard,
|
|
645
|
+
{
|
|
646
|
+
id: item.id,
|
|
647
|
+
name: item.name,
|
|
648
|
+
logoUrl: item.logoUrl,
|
|
649
|
+
createdAt: item.createdAt,
|
|
650
|
+
updatedAt: item.updatedAt,
|
|
651
|
+
onRotate: handleRotate,
|
|
652
|
+
onDelete: handleDeleteClick
|
|
653
|
+
},
|
|
654
|
+
item.id
|
|
655
|
+
)) }),
|
|
656
|
+
/* @__PURE__ */ jsx7(
|
|
657
|
+
VaultDeleteDialog,
|
|
658
|
+
{
|
|
659
|
+
isOpen: deleteDialogOpen,
|
|
660
|
+
onClose: () => {
|
|
661
|
+
setDeleteDialogOpen(false);
|
|
662
|
+
setSelectedItem(null);
|
|
663
|
+
},
|
|
664
|
+
itemName: selectedItem?.name || "",
|
|
665
|
+
onConfirm: handleConfirmDelete
|
|
666
|
+
}
|
|
667
|
+
),
|
|
668
|
+
/* @__PURE__ */ jsx7(
|
|
669
|
+
VaultInputModal,
|
|
670
|
+
{
|
|
671
|
+
isOpen: inputModalOpen,
|
|
672
|
+
onClose: () => {
|
|
673
|
+
setInputModalOpen(false);
|
|
674
|
+
setSelectedItem(null);
|
|
675
|
+
},
|
|
676
|
+
mode: modalMode,
|
|
677
|
+
integration: getIntegrationForModal(),
|
|
678
|
+
onSave: handleSave
|
|
679
|
+
}
|
|
680
|
+
)
|
|
681
|
+
] });
|
|
682
|
+
}
|
|
683
|
+
export {
|
|
684
|
+
SecretForm,
|
|
685
|
+
SecretsManager,
|
|
686
|
+
VaultDeleteDialog,
|
|
687
|
+
VaultEmptyState,
|
|
688
|
+
VaultInputModal,
|
|
689
|
+
VaultItemCard,
|
|
690
|
+
VaultList
|
|
691
|
+
};
|
|
692
|
+
//# sourceMappingURL=index.js.map
|