UNPKG

@buildappolis/env-manager

Version:

Enterprise-grade environment variable management system with encryption, snapshots, and validation

24 lines (17 loc) 10.9 kB
import{j as e}from"./jsx-runtime.BjG_zV1W.js";import{r as n}from"./index.B7KzZMbc.js";import{c as S,F as N,R as I,K as L,G as M,L as V,T as $}from"./trash-2.DSZTeR6u.js";import G from"./VersionFooter.IbdQVJoN.js";/** * @license lucide-react v0.540.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const H=[["path",{d:"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z",key:"10ikf1"}]],J=S("play",H);/** * @license lucide-react v0.540.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. */const B=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]],q=S("square",B);function Y({onProjectSelect:l}){const[i,x]=n.useState([]),[w,m]=n.useState(!0),[h,k]=n.useState(null),[C,c]=n.useState(!1),[a,u]=n.useState("setup"),[r,d]=n.useState({password:"",newPassword:"",confirmPassword:"",recoveryPhrase:"",projectPassword:""}),[j,o]=n.useState(""),[_,g]=n.useState(""),[E,P]=n.useState(!1),[R,b]=n.useState(!1);n.useEffect(()=>{f(),T()},[]);const f=async()=>{try{const t=await(await fetch("/api/projects")).json();x(t.projects||[])}catch(s){console.error("Failed to load projects:",s)}finally{m(!1)}},T=async()=>{try{const t=await(await fetch("/api/password")).json();P(t.hasGlobalPassword)}catch(s){console.error("Failed to check password status:",s)}},A=async s=>{k(s),s.hasProjectPassword?(u("verify"),c(!0)):l&&l(s)},O=async()=>{o("");try{if(a==="setup"){if(r.password!==r.confirmPassword){o("Passwords do not match");return}const s=await fetch("/api/password",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"setup",password:r.password})}),t=await s.json();if(!s.ok){o(t.error);return}g(t.recoveryPhrase),P(!0),alert(`Password set! Your recovery phrase is: ${t.recoveryPhrase} SAVE THIS PHRASE! You'll need it to recover your password.`),c(!1),p()}if(a==="verify"){const s=await fetch("/api/password",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"verify",password:r.password,projectPath:h?.path})}),t=await s.json();if(!s.ok||!t.valid){o("Invalid password");return}if(t.requiresProjectPassword&&!t.projectValid){o("Project password required");return}c(!1),p(),h&&l&&l(h)}if(a==="change"){if(r.newPassword!==r.confirmPassword){o("New passwords do not match");return}const s=await fetch("/api/password",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"change",password:r.password,newPassword:r.newPassword})}),t=await s.json();if(!s.ok){o(t.error);return}g(t.recoveryPhrase),alert(`Password changed! Your new recovery phrase is: ${t.recoveryPhrase} SAVE THIS PHRASE!`),c(!1),p()}if(a==="recover"){if(r.newPassword!==r.confirmPassword){o("New passwords do not match");return}const s=await fetch("/api/password",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"recover",recoveryPhrase:r.recoveryPhrase,newPassword:r.newPassword})}),t=await s.json();if(!s.ok){o(t.error);return}g(t.recoveryPhrase),alert(`Password recovered! Your new recovery phrase is: ${t.recoveryPhrase} SAVE THIS PHRASE!`),c(!1),p()}}catch{o("Operation failed. Please try again.")}},y=async(s,t)=>{try{(await fetch("/api/projects",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:t,projectPath:s.path,port:s.port})})).ok&&await f()}catch(v){console.error(`Failed to ${t} project:`,v)}},p=()=>{d({password:"",newPassword:"",confirmPassword:"",recoveryPhrase:"",projectPassword:""}),o("")},F=async()=>{b(!0),await f(),setTimeout(()=>b(!1),500)};return w?e.jsx("div",{className:"flex items-center justify-center p-8",children:e.jsx("div",{className:"animate-pulse text-yellow-400",children:"Loading projects..."})}):e.jsxs("div",{className:"pixel-borders bg-gray-900 p-6 rounded-lg",children:[e.jsxs("div",{className:"flex items-center justify-between mb-6",children:[e.jsxs("h2",{className:"text-xl text-yellow-400 flex items-center gap-2",children:[e.jsx(N,{className:"w-6 h-6"}),"Projects"]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("button",{onClick:F,className:`pixel-button bg-blue-600 hover:bg-blue-700 text-white p-2 ${R?"animate-spin":""}`,title:"Refresh",children:e.jsx(I,{className:"w-4 h-4"})}),E&&e.jsxs("button",{onClick:()=>{u("change"),c(!0)},className:"pixel-button bg-purple-600 hover:bg-purple-700 text-white px-3 py-2 flex items-center gap-2",children:[e.jsx(L,{className:"w-4 h-4"}),"Change Password"]})]})]}),i.length===0?e.jsxs("div",{className:"text-center py-8 text-gray-400",children:[e.jsx("p",{className:"mb-2",children:"No projects found"}),e.jsx("p",{className:"text-sm",children:'Run "env-manager init" in a project directory to get started'})]}):e.jsx("div",{className:"grid gap-4",children:i.map(s=>e.jsx("div",{className:`pixel-borders bg-gray-800 p-4 rounded-lg transition-all hover:bg-gray-700 ${s.isActive?"ring-2 ring-yellow-400":""}`,children:e.jsxs("div",{className:"flex items-start justify-between",children:[e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-2",children:[e.jsx("h3",{className:"text-lg text-cyan-400",children:s.packageInfo?.name||s.name}),s.isRunning&&e.jsxs("span",{className:"flex items-center gap-1 text-green-400 text-xs",children:[e.jsx("span",{className:"w-2 h-2 bg-green-400 rounded-full animate-pulse"}),"LIVE"]}),s.gitBranch&&e.jsxs("span",{className:"flex items-center gap-1 text-purple-400 text-xs",children:[e.jsx(M,{className:"w-3 h-3"}),s.gitBranch]}),s.hasProjectPassword&&e.jsx(V,{className:"w-4 h-4 text-yellow-400"})]}),e.jsxs("div",{className:"text-xs text-gray-400 space-y-1",children:[s.packageInfo?.version&&e.jsxs("p",{children:["Version: ",s.packageInfo.version]}),e.jsxs("p",{className:"truncate",title:`Full path: ${s.path}`,children:["Path: ",s.path]}),e.jsxs("p",{children:["Port: ",s.port]}),e.jsxs("p",{children:["Last accessed: ",new Date(s.lastAccessed).toLocaleDateString()]})]})]}),e.jsx("div",{className:"flex gap-2",children:s.exists?e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:()=>A(s),className:"pixel-button bg-green-600 hover:bg-green-700 text-white p-2",title:"Open project",children:e.jsx(N,{className:"w-4 h-4"})}),s.isRunning?e.jsx("button",{onClick:()=>y(s,"stop"),className:"pixel-button bg-red-600 hover:bg-red-700 text-white p-2",title:"Stop project",children:e.jsx(q,{className:"w-4 h-4"})}):e.jsx("button",{onClick:()=>y(s,"start"),className:"pixel-button bg-blue-600 hover:bg-blue-700 text-white p-2",title:"Start project",children:e.jsx(J,{className:"w-4 h-4"})})]}):e.jsx("button",{onClick:()=>y(s,"remove"),className:"pixel-button bg-red-600 hover:bg-red-700 text-white p-2",title:"Remove from list (project not found)",children:e.jsx($,{className:"w-4 h-4"})})})]})},s.id))}),C&&e.jsx("div",{className:"fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50 p-4",children:e.jsxs("div",{className:"pixel-borders bg-gray-900 p-6 rounded-lg max-w-md w-full",children:[e.jsxs("h3",{className:"text-xl text-yellow-400 mb-4",children:[a==="setup"&&"🔐 Setup Master Password",a==="verify"&&"🔓 Enter Password",a==="change"&&"🔄 Change Password",a==="recover"&&"🔑 Recover Password"]}),j&&e.jsx("div",{className:"mb-4 p-2 bg-red-900 border border-red-400 rounded text-red-300 text-sm",children:j}),e.jsxs("form",{onSubmit:s=>{s.preventDefault(),O()},children:[e.jsxs("div",{className:"space-y-4",children:[a==="recover"?e.jsx(e.Fragment,{children:e.jsxs("div",{children:[e.jsx("label",{className:"block text-cyan-400 text-sm mb-1",children:"Recovery Phrase"}),e.jsx("input",{type:"text",value:r.recoveryPhrase,onChange:s=>d({...r,recoveryPhrase:s.target.value}),className:"pixel-input w-full bg-gray-800 text-white p-2 rounded",placeholder:"Enter your recovery phrase"})]})}):e.jsx(e.Fragment,{children:(a==="verify"||a==="change")&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-cyan-400 text-sm mb-1",children:a==="change"?"Current Password":"Password"}),e.jsx("input",{type:"password",value:r.password,onChange:s=>d({...r,password:s.target.value}),className:"pixel-input w-full bg-gray-800 text-white p-2 rounded",placeholder:"Enter password"})]})}),(a==="setup"||a==="change"||a==="recover")&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-cyan-400 text-sm mb-1",children:a==="setup"?"Password":"New Password"}),e.jsx("input",{type:"password",value:a==="setup"?r.password:r.newPassword,onChange:s=>d({...r,[a==="setup"?"password":"newPassword"]:s.target.value}),className:"pixel-input w-full bg-gray-800 text-white p-2 rounded",placeholder:"Enter new password (min 6 chars)"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-cyan-400 text-sm mb-1",children:"Confirm Password"}),e.jsx("input",{type:"password",value:r.confirmPassword,onChange:s=>d({...r,confirmPassword:s.target.value}),className:"pixel-input w-full bg-gray-800 text-white p-2 rounded",placeholder:"Confirm password"})]})]}),h?.hasProjectPassword&&a==="verify"&&e.jsxs("div",{children:[e.jsx("label",{className:"block text-cyan-400 text-sm mb-1",children:"Project Password (if different)"}),e.jsx("input",{type:"password",value:r.projectPassword,onChange:s=>d({...r,projectPassword:s.target.value}),className:"pixel-input w-full bg-gray-800 text-white p-2 rounded",placeholder:"Enter project-specific password"})]})]}),e.jsxs("div",{className:"flex justify-between items-center mt-6",children:[a==="verify"&&e.jsx("button",{onClick:()=>{u("recover"),p()},className:"text-purple-400 hover:text-purple-300 text-sm",children:"Forgot password?"}),e.jsxs("div",{className:"flex gap-2 ml-auto",children:[a!=="setup"&&e.jsx("button",{onClick:()=>{c(!1),p()},className:"pixel-button bg-gray-600 hover:bg-gray-700 text-white px-4 py-2",children:"Cancel"}),e.jsxs("button",{type:"submit",className:"pixel-button bg-green-600 hover:bg-green-700 text-white px-4 py-2",children:[a==="setup"&&"Setup Password",a==="verify"&&"Unlock",a==="change"&&"Change Password",a==="recover"&&"Reset Password"]})]})]})]})]})})]})}function Q(){const l=i=>{const x=i.packageInfo?.name||i.name||"project",w=i.gitBranch||"main",m=x.replace(/^@[^/]+\//,"").replace(/[^a-z0-9-]/gi,"-").toLowerCase();window.location.href=`/${m}/${w}`};return e.jsxs("div",{className:"min-h-screen bg-gray-900 p-4 pb-16",children:[e.jsxs("div",{className:"container mx-auto max-w-4xl",children:[e.jsxs("div",{className:"mb-8 text-center",children:[e.jsx("h1",{className:"text-4xl mb-2 text-yellow-400 animate-pulse",children:"🔧 ENV MANAGER"}),e.jsx("p",{className:"text-cyan-300 text-sm",children:"SELECT A PROJECT TO MANAGE ENVIRONMENT VARIABLES"})]}),e.jsx(Y,{onProjectSelect:l})]}),e.jsx(G,{})]})}export{Q as default};