/* Copyright 2026 Marimo. All rights reserved. */ import React from "react"; import { Button } from "@/components/ui/button"; import { DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { FormDescription } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { ExternalLink } from "@/components/ui/links"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { toast } from "@/components/ui/use-toast"; import { useRequestClient } from "@/core/network/requests"; import type { ListSecretKeysResponse } from "@/core/network/types"; // dotenv providers should be at the top export function sortProviders(providers: ListSecretKeysResponse["keys"]) { return providers.toSorted((a, b) => { if (a.provider === "env") { return 1; } if (b.provider === "env") { return -1; } return 0; }); } /** * A modal component that allows users to add a new secret */ export const WriteSecretModal: React.FC<{ providerNames: string[]; onClose: () => void; onSuccess: (secretName: string) => void; }> = ({ providerNames, onClose, onSuccess }) => { const { writeSecret } = useRequestClient(); const [key, setKey] = React.useState(""); const [value, setValue] = React.useState(""); const [location, setLocation] = React.useState( providerNames[0], ); // Only dotenv is supported for now const provider = "dotenv"; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!location) { toast({ title: "Error", description: "No location selected for the secret.", variant: "danger", }); return; } if (!key || !value || !location) { toast({ title: "Error", description: "Please fill in all fields.", variant: "danger", }); return; } try { await writeSecret({ key, value, provider, name: location, }); toast({ title: "Secret created", description: "The secret has been created successfully.", }); onSuccess(key); } catch { toast({ title: "Error", description: "Failed to create secret. Please try again.", variant: "danger", }); } }; return (
Add Secret Add a new secret to your environment variables.
{ // Remove any non-word characters from the input setKey(replaceInvalid(e.target.value)); }} placeholder="MY_SECRET_KEY" required={true} />
setValue(e.target.value)} required={true} autoComplete="off" /> {/* http is prone to man-in-the-middle */} {isHttpUrl() && ( Note: You are sending this key over http. )}
{providerNames.length === 0 && (

No dotenv locations configured.

)} {providerNames.length > 0 && ( )} You can configure the location by setting the{" "} dotenv configuration .
); }; export function replaceInvalid(input: string): string { return input.replaceAll(/\W/g, "_"); } function isHttpUrl(): boolean { const url = window.location.href; return url.startsWith("http://"); }