@fudrouter/fsrouter 0.6.6 → 0.6.8
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/bin/cli.cjs +3 -3
- package/package.json +1 -1
- package/public/assets/EndpointPageClient.BoapE5zm.js +6 -0
- package/public/assets/Loading.dETQxP6N.js +1 -0
- package/public/assets/NoAuthProxyCard.Ep103MXh.js +89 -0
- package/public/assets/index.hce0krcP.js +89 -0
- package/public/assets/page.6ndooo4E.js +2 -0
- package/public/assets/page.B6CR1D5-.js +1 -0
- package/public/assets/page.BXhjXgLk.js +6 -0
- package/public/assets/page.BYIiMO45.js +6 -0
- package/public/assets/page.BYgHervZ.js +1 -0
- package/public/assets/page.BeZrxayi.js +1 -0
- package/public/assets/page.BekIW_5T.js +1 -0
- package/public/assets/page.BinRrByA.js +1 -0
- package/public/assets/page.BlGXsG2L.js +1 -0
- package/public/assets/page.C0_v7KzZ.js +31 -0
- package/public/assets/page.C3pP0aOJ.js +23 -0
- package/public/assets/page.C5eZPTqa.js +4 -0
- package/public/assets/page.CNidxkml.js +1 -0
- package/public/assets/page.CPtT_5jj.js +1 -0
- package/public/assets/page.CUqBYrnf.js +1 -0
- package/public/assets/page.Czgn2r1Z.js +1 -0
- package/public/assets/page.D-EhIqA4.js +1 -0
- package/public/assets/page.D1Aeg3zE.js +1 -0
- package/public/assets/page.D8KrBGhe.js +1 -0
- package/public/assets/page.DG-3a9ka.js +1 -0
- package/public/assets/page.DHhxRzaB.js +1 -0
- package/public/assets/page.DNXs8x7D.js +1 -0
- package/public/assets/page.DRsqyy-7.js +1 -0
- package/public/assets/page.DTWgrCWB.js +1 -0
- package/public/assets/page.DVLrVlRO.js +1 -0
- package/public/assets/page.DdApKjPz.js +1 -0
- package/public/assets/page.DnMWNKYE.js +1 -0
- package/public/assets/page.Dz8fCNSm.js +1 -0
- package/public/assets/page.K_UbTzUl.js +5 -0
- package/public/assets/page.OOT7TYfM.js +64 -0
- package/public/assets/page.TuGfTvdk.js +1 -0
- package/public/assets/page.aFgeXm5h.js +2 -0
- package/public/assets/page.hvdU1tpC.js +1 -0
- package/public/assets/page.jBFzDjyD.js +5 -0
- package/public/assets/page.mNrO0xzV.js +1 -0
- package/src/lib/appUpdater.js +9 -2
- package/src/routes/version/route.ts +7 -9
- package/src/server.ts +1 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index.1VBQU7rF.js","assets/router.Cjj1--8t.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{u as z,j as t,B as c,_ as F}from"./index.hce0krcP.js";import{b as x}from"./router.Cjj1--8t.js";import{C as $}from"./NoAuthProxyCard.Ep103MXh.js";import"./zustand.akaTi5uX.js";const B=x.lazy(()=>F(()=>import("./index.1VBQU7rF.js"),__vite__mapDeps([0,1]))),v=[{id:1,label:"Client Request",file:"1_req_client.json",lang:"json",desc:"Raw request from client"},{id:2,label:"Source Body",file:"2_req_source.json",lang:"json",desc:"After initial conversion"},{id:3,label:"OpenAI Intermediate",file:"3_req_openai.json",lang:"json",desc:"source → openai"},{id:4,label:"Target Request",file:"4_req_target.json",lang:"json",desc:"openai → target + URL + headers"},{id:5,label:"Provider Response",file:"5_res_provider.txt",lang:"text",desc:"Raw SSE from provider"},{id:6,label:"OpenAI Response",file:"6_res_openai.txt",lang:"text",desc:"target → openai (response)"},{id:7,label:"Client Response",file:"7_res_client.txt",lang:"text",desc:"Final response to client"}],I={minimap:{enabled:!1},fontSize:12,lineNumbers:"on",scrollBeyondLastLine:!1,wordWrap:"on",automaticLayout:!0};function W(){const[i,h]=x.useState({}),[g,u]=x.useState({1:!0}),[p,S]=x.useState({}),[o,w]=x.useState(null),l=(e,s)=>S(a=>({...a,[e]:s})),d=(e,s)=>h(a=>({...a,[e]:s})),O=e=>u(s=>({...s,[e]:!s[e]})),j=e=>u(s=>{const a={};return v.forEach(n=>{a[n.id]=!1}),a[e]=!0,a}),_=async e=>{const s=v.find(a=>a.id===e);l(`load-${e}`,!0);try{const n=await(await fetch(`/api/translator/load?file=${s.file}`)).json();n.success?(d(e,n.content),e===1&&await N(n.content)):alert(n.error||"File not found")}catch(a){alert(a.message)}l(`load-${e}`,!1)},N=async e=>{try{const s=typeof e=="string"?JSON.parse(e):e,n=await(await fetch("/api/translator/translate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({step:1,body:s})})).json();n.success&&w(n.result)}catch{}},f=(e,s)=>fetch("/api/translator/save",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({file:e,content:s})}).catch(()=>{}),T=async()=>{l("toOpenAI",!0);try{const e=i[1],s=JSON.parse(e);f("1_req_client.json",e),f("2_req_source.json",JSON.stringify({timestamp:new Date().toISOString(),headers:{},body:s.body||s},null,2));const n=await(await fetch("/api/translator/translate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({step:2,body:s})})).json();if(!n.success){alert(n.error);return}const r=JSON.stringify(n.result.body,null,2);d(3,r),j(3)}catch(e){alert(e.message)}l("toOpenAI",!1)},C=async()=>{l("toTarget",!0);try{const e=i[3],s=JSON.parse(e);f("3_req_openai.json",e);const n=await(await fetch("/api/translator/translate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({step:3,body:{...s,provider:o==null?void 0:o.provider,model:o==null?void 0:o.model}})})).json();if(!n.success){alert(n.error);return}const r={...n.result,provider:o==null?void 0:o.provider,model:o==null?void 0:o.model};d(4,JSON.stringify(r,null,2)),j(4)}catch(e){alert(e.message)}l("toTarget",!1)},J=async()=>{l("send",!0);try{const e=i[4],s=JSON.parse(e);f("4_req_target.json",e);const a=s.provider||(o==null?void 0:o.provider),n=s.model||(o==null?void 0:o.model);if(!a||!n){alert("Missing provider or model. Please run step 1 first to detect them.");return}const r=await fetch("/api/translator/send",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:a,model:n,body:s.body||s})});if(!r.ok){const b=await r.json().catch(()=>({error:r.statusText}));alert(b.error||"Send failed");return}const E=r.body.getReader(),A=new TextDecoder;let y="";for(;;){const{done:b,value:L}=await E.read();if(b)break;y+=A.decode(L,{stream:!0})}d(5,y),j(5),await fetch("/api/translator/save",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({file:"5_res_provider.txt",content:y})})}catch(e){alert(e.message)}finally{l("send",!1)}},{copy:P}=z(),R=async e=>{i[e]&&P(i[e],`translator-step-${e}`)},k=e=>{try{const s=JSON.parse(i[e]);d(e,JSON.stringify(s,null,2))}catch{}},q=e=>e===1?t.jsx(c,{size:"sm",icon:"arrow_forward",loading:p.toOpenAI,onClick:T,children:"→ OpenAI"}):e===3?t.jsx(c,{size:"sm",icon:"arrow_forward",loading:p.toTarget,onClick:C,children:"→ Target"}):e===4?t.jsx(c,{size:"sm",icon:"send",loading:p.send,onClick:J,children:"Send"}):null;return t.jsxs("div",{className:"p-8 space-y-3",children:[t.jsxs("div",{className:"flex items-center justify-between mb-2",children:[t.jsxs("div",{children:[t.jsx("h1",{className:"text-2xl font-bold text-text-main",children:"Translator Debug"}),t.jsx("p",{className:"text-sm text-text-muted mt-1",children:"Replay request flow — matches log files"})]}),o&&t.jsxs("div",{className:"flex items-center gap-2 flex-wrap justify-end",children:[t.jsx(m,{label:"src",value:o.sourceFormat,color:"blue"}),t.jsx("span",{className:"material-symbols-outlined text-text-muted text-[14px]",children:"arrow_forward"}),t.jsx(m,{label:"dst",value:o.targetFormat,color:"orange"}),t.jsx(m,{label:"provider",value:o.provider,color:"green"}),t.jsx(m,{label:"model",value:o.model,color:"purple"})]})]}),v.map(e=>{const s=q(e.id),a=!!g[e.id],n=i[e.id]||"";return t.jsx($,{children:t.jsxs("div",{className:"p-4 space-y-3",children:[t.jsxs("div",{className:"flex items-center justify-between",children:[t.jsxs("button",{onClick:()=>O(e.id),className:"flex items-center gap-2 flex-1 text-left group",children:[t.jsx("span",{className:"material-symbols-outlined text-[20px] text-text-muted group-hover:text-primary transition-colors",children:a?"expand_more":"chevron_right"}),t.jsx("span",{className:"text-xs font-mono text-text-muted/60 w-4",children:e.id}),t.jsx("h3",{className:"text-sm font-semibold text-text-main",children:e.label}),t.jsx("span",{className:"text-xs text-text-muted/60 font-mono",children:e.file}),n&&t.jsxs("span",{className:"text-xs text-green-500",children:["(",n.length," chars)"]})]}),!a&&t.jsxs("div",{className:"flex gap-1 shrink-0",children:[t.jsx(c,{size:"sm",variant:"ghost",icon:"folder_open",loading:p[`load-${e.id}`],onClick:()=>_(e.id)}),s]})]}),a&&t.jsxs(t.Fragment,{children:[t.jsx("div",{className:"border border-border rounded-lg overflow-hidden",children:t.jsx(B,{height:"400px",defaultLanguage:e.lang==="text"?"plaintext":"json",value:n,onChange:r=>{d(e.id,r||""),e.id===1&&N(r||"")},theme:"vs-dark",options:I})}),t.jsxs("div",{className:"flex gap-2 flex-wrap",children:[t.jsx(c,{size:"sm",variant:"outline",icon:"folder_open",loading:p[`load-${e.id}`],onClick:()=>_(e.id),children:"Load"}),t.jsx(c,{size:"sm",variant:"outline",icon:"data_object",onClick:()=>k(e.id),children:"Format"}),t.jsx(c,{size:"sm",variant:"outline",icon:"content_copy",onClick:()=>R(e.id),children:"Copy"}),s]})]})]})},e.id)})]})}function m({label:i,value:h,color:g}){const u={blue:"bg-blue-500/10 text-blue-500",orange:"bg-orange-500/10 text-orange-500",green:"bg-green-500/10 text-green-500",purple:"bg-purple-500/10 text-purple-500"};return t.jsxs("span",{className:`inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-mono ${u[g]}`,children:[t.jsxs("span",{className:"text-text-muted/70 font-sans text-[10px]",children:[i,":"]}),h]})}export{W as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{g as v,j as e,B as c,m as j}from"./index.hce0krcP.js";import{d as N,b as u,L as h}from"./router.Cjj1--8t.js";import{C as p,S as k,I as x,T as A}from"./NoAuthProxyCard.Ep103MXh.js";import"./zustand.akaTi5uX.js";const P=Object.values(v).map(a=>({value:a.id,label:a.name})),S=Object.values(j).map(a=>({value:a.id,label:a.name}));function E(){const a=N(),[b,m]=u.useState(!1),[t,y]=u.useState({provider:"",authMethod:"api_key",apiKey:"",displayName:"",isActive:!0}),[s,n]=u.useState({}),i=(r,o)=>{y(l=>({...l,[r]:o})),s[r]&&n(l=>({...l,[r]:null}))},f=()=>{const r={};return t.provider||(r.provider="Please select a provider"),t.authMethod==="api_key"&&!t.apiKey&&(r.apiKey="API Key is required"),n(r),Object.keys(r).length===0},g=async r=>{if(r.preventDefault(),!!f()){m(!0);try{const o=await fetch("/api/providers",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(o.ok)a("/dashboard/providers");else{const l=await o.json();n({submit:l.error||"Failed to create provider"})}}catch{n({submit:"An error occurred. Please try again."})}finally{m(!1)}}},d=v[t.provider];return e.jsxs("div",{className:"max-w-2xl mx-auto",children:[e.jsxs("div",{className:"mb-8",children:[e.jsxs(h,{to:"/dashboard/providers",className:"inline-flex items-center gap-1 text-sm text-text-muted hover:text-primary transition-colors mb-4",children:[e.jsx("span",{className:"material-symbols-outlined text-lg",children:"arrow_back"}),"Back to Providers"]}),e.jsx("h1",{className:"text-3xl font-semibold tracking-tight",children:"Add New Provider"}),e.jsx("p",{className:"text-text-muted mt-2",children:"Configure a new AI provider to use with your applications."})]}),e.jsx(p,{children:e.jsxs("form",{onSubmit:g,className:"flex flex-col gap-6",children:[e.jsx(k,{label:"Provider",options:P,value:t.provider,onChange:r=>i("provider",r.target.value),placeholder:"Select a provider",error:s.provider,required:!0}),d&&e.jsxs(p.Section,{className:"flex items-center gap-3",children:[e.jsx("div",{className:"size-10 rounded-lg flex items-center justify-center bg-bg border border-border",children:e.jsx("span",{className:"material-symbols-outlined text-xl",style:{color:d.color},children:d.icon})}),e.jsxs("div",{children:[e.jsx("p",{className:"font-medium",children:d.name}),e.jsx("p",{className:"text-sm text-text-muted",children:"Selected provider"})]})]}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsxs("label",{className:"text-sm font-medium",children:["Authentication Method ",e.jsx("span",{className:"text-red-500",children:"*"})]}),e.jsx("div",{className:"flex gap-3",children:S.map(r=>e.jsxs("button",{type:"button",onClick:()=>i("authMethod",r.value),className:`flex-1 flex items-center justify-center gap-2 p-4 rounded-lg border transition-all ${t.authMethod===r.value?"border-primary bg-primary/5 text-primary":"border-border hover:border-primary/50"}`,children:[e.jsx("span",{className:"material-symbols-outlined",children:r.value==="api_key"?"key":"lock"}),e.jsx("span",{className:"font-medium",children:r.label})]},r.value))})]}),t.authMethod==="api_key"&&e.jsx(x,{label:"API Key",type:"password",placeholder:"Enter your API key",value:t.apiKey,onChange:r=>i("apiKey",r.target.value),error:s.apiKey,hint:"Your API key will be encrypted and stored securely.",required:!0}),t.authMethod==="oauth2"&&e.jsxs(p.Section,{children:[e.jsx("p",{className:"text-sm text-text-muted mb-4",children:"Connect your account using OAuth2 authentication."}),e.jsx(c,{type:"button",variant:"secondary",icon:"link",children:"Connect with OAuth2"})]}),e.jsx(x,{label:"Display Name",placeholder:"e.g., Production API, Dev Environment",value:t.displayName,onChange:r=>i("displayName",r.target.value),hint:"Optional. A friendly name to identify this configuration."}),e.jsx(A,{checked:t.isActive,onChange:r=>i("isActive",r),label:"Active",description:"Enable this provider for use in your applications"}),s.submit&&e.jsx("div",{className:"p-4 rounded-lg bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 text-red-600 dark:text-red-400 text-sm",children:s.submit}),e.jsxs("div",{className:"flex gap-3 pt-4 border-t border-border",children:[e.jsx(h,{to:"/dashboard/providers",className:"flex-1",children:e.jsx(c,{type:"button",variant:"ghost",fullWidth:!0,children:"Cancel"})}),e.jsx(c,{type:"submit",loading:b,fullWidth:!0,className:"flex-1",children:"Create Provider"})]})]})})]})}export{E as default};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{j as e}from"./index.hce0krcP.js";import{b as l}from"./router.Cjj1--8t.js";import"./zustand.akaTi5uX.js";function b({value:r,label:d="Copy"}){const[t,i]=l.useState(!1),a=async()=>{if(r)try{await navigator.clipboard.writeText(r),i(!0),setTimeout(()=>i(!1),1500)}catch{const n=document.createElement("textarea");n.value=r,document.body.appendChild(n),n.select(),document.execCommand("copy"),document.body.removeChild(n),i(!0),setTimeout(()=>i(!1),1500)}};return e.jsx("button",{onClick:a,disabled:!r,title:r?r.slice(0,60)+(r.length>60?"…":""):"Tidak tersedia",style:{padding:"2px 10px",fontSize:11,borderRadius:4,border:"1px solid",cursor:r?"pointer":"not-allowed",borderColor:t?"#22c55e":r?"#6366f1":"#374151",background:t?"#166534":r?"#1e1b4b":"#111827",color:t?"#86efac":r?"#a5b4fc":"#4b5563",transition:"all 0.15s",whiteSpace:"nowrap",minWidth:60},children:t?"✓ Copied!":d})}function y({value:r,maxLen:d=22}){const[t,i]=l.useState(!1);if(!r)return e.jsx("span",{style:{color:"#6b7280",fontSize:12},children:"—"});const a=t?r:r.slice(0,d)+"…";return e.jsxs("span",{style:{fontFamily:"monospace",fontSize:11,color:"#d1d5db"},children:[a,e.jsx("button",{onClick:()=>i(n=>!n),style:{marginLeft:4,fontSize:10,color:"#6366f1",background:"none",border:"none",cursor:"pointer"},children:t?"hide":"show"})]})}function w(r){const d=r.map(s=>({email:s.email,firebase_refresh_token:s.firebaseRefreshToken,firebase_api_key:s.firebaseApiKey,jwt:s.jwt,jwt_expires_at:s.jwtExpiresAt,balance:s.balance})),t=JSON.stringify(d,null,2),i=new Blob([t],{type:"application/json"}),a=URL.createObjectURL(i),n=document.createElement("a");n.href=a,n.download=`weavy-tokens-${Date.now()}.json`,n.click(),URL.revokeObjectURL(a)}function S(r){const t=`email,firebase_refresh_token,firebase_api_key
|
|
2
|
+
`+r.filter(s=>s.firebaseRefreshToken&&s.firebaseApiKey).map(s=>`${s.email},${s.firebaseRefreshToken},${s.firebaseApiKey}`).join(`
|
|
3
|
+
`),i=new Blob([t],{type:"text/csv"}),a=URL.createObjectURL(i),n=document.createElement("a");n.href=a,n.download=`weavy-refresh-tokens-${Date.now()}.csv`,n.click(),URL.revokeObjectURL(a)}function C(){const[r,d]=l.useState([]),[t,i]=l.useState(null),[a,n]=l.useState(!0),[s,g]=l.useState(""),[x,m]=l.useState(""),[p,j]=l.useState("all"),h=l.useCallback(async()=>{n(!0),g("");try{const c=await(await fetch("/api/providers/weavy/pool")).json();if(!c.ok)throw new Error(c.error||"Failed");d(c.pool||[]),i(c.stats||null)}catch(o){g(o.message)}finally{n(!1)}},[]);l.useEffect(()=>{h()},[h]);const u=r.filter(o=>{const c=!x||o.email.toLowerCase().includes(x.toLowerCase()),k=p==="all"?!0:p==="hasToken"?!!o.firebaseRefreshToken:p==="noToken"?!o.firebaseRefreshToken:p==="validJwt"?o.jwtValid:!0;return c&&k}),v={background:"#111827",border:"1px solid #1f2937",borderRadius:8,padding:"10px 14px",marginBottom:8},f=(o,c,k="#6366f1")=>e.jsxs("div",{style:{background:"#0f172a",borderRadius:8,padding:"12px 20px",border:"1px solid #1f2937",textAlign:"center",minWidth:100},children:[e.jsx("div",{style:{fontSize:28,fontWeight:700,color:k},children:c}),e.jsx("div",{style:{fontSize:11,color:"#9ca3af",marginTop:2},children:o})]});return e.jsxs("div",{style:{minHeight:"100vh",background:"#030712",color:"#e5e7eb",padding:"24px 32px",fontFamily:"Inter, sans-serif"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:24},children:[e.jsxs("div",{children:[e.jsx("h1",{style:{margin:0,fontSize:22,fontWeight:700,color:"#f9fafb"},children:"🪄 Weavy Token Pool"}),e.jsx("p",{style:{margin:"4px 0 0",fontSize:13,color:"#6b7280"},children:"Copy firebase_refresh_token + firebase_api_key ke kliperspro atau sistem lain"})]}),e.jsxs("div",{style:{display:"flex",gap:8},children:[e.jsx("button",{onClick:h,style:{padding:"6px 14px",borderRadius:6,background:"#1f2937",border:"1px solid #374151",color:"#d1d5db",cursor:"pointer",fontSize:13},children:"↻ Refresh"}),e.jsx("button",{onClick:()=>S(r),style:{padding:"6px 14px",borderRadius:6,background:"#1e1b4b",border:"1px solid #4338ca",color:"#a5b4fc",cursor:"pointer",fontSize:13},children:"⬇ Export CSV"}),e.jsx("button",{onClick:()=>w(r),style:{padding:"6px 14px",borderRadius:6,background:"#14532d",border:"1px solid #166534",color:"#86efac",cursor:"pointer",fontSize:13},children:"⬇ Export JSON"})]})]}),t&&e.jsxs("div",{style:{display:"flex",gap:12,marginBottom:24,flexWrap:"wrap"},children:[f("Total Akun",t.total,"#e5e7eb"),f("Aktif",t.active,"#22c55e"),f("JWT Valid",t.jwtValid,"#6366f1"),f("Punya Refresh Token",t.hasRefreshToken,"#f59e0b")]}),t&&t.hasRefreshToken===0&&e.jsxs("div",{style:{background:"#431407",border:"1px solid #7c2d12",borderRadius:8,padding:"12px 16px",marginBottom:20,fontSize:13,color:"#fed7aa"},children:["⚠️ ",e.jsx("strong",{children:"firebase_refresh_token masih kosong"})," untuk semua akun. Jalankan ulang signup untuk akun-akun ini agar refresh token tertangkap dari IndexedDB."]}),e.jsxs("div",{style:{background:"#0c1a2e",border:"1px solid #1e3a5f",borderRadius:8,padding:"12px 16px",marginBottom:20,fontSize:12},children:[e.jsx("strong",{style:{color:"#60a5fa"},children:"📋 Cara pakai di kliperspro (production):"}),e.jsx("pre",{style:{margin:"8px 0 0",color:"#93c5fd",fontSize:11,overflow:"auto"},children:`POST https://securetoken.googleapis.com/v1/token?key=<firebase_api_key>
|
|
4
|
+
Body: grant_type=refresh_token&refresh_token=<firebase_refresh_token>
|
|
5
|
+
→ Response: { id_token: "<JWT baru>", refresh_token: "<update ini>" }
|
|
6
|
+
→ Gunakan id_token sebagai: Authorization: Bearer <JWT>`})]}),e.jsxs("div",{style:{display:"flex",gap:10,marginBottom:16,flexWrap:"wrap"},children:[e.jsx("input",{value:x,onChange:o=>m(o.target.value),placeholder:"Cari email…",style:{flex:1,minWidth:200,background:"#111827",border:"1px solid #374151",borderRadius:6,padding:"6px 12px",color:"#e5e7eb",fontSize:13}}),["all","hasToken","noToken","validJwt"].map(o=>e.jsx("button",{onClick:()=>j(o),style:{padding:"6px 12px",borderRadius:6,fontSize:12,cursor:"pointer",border:"1px solid",borderColor:p===o?"#6366f1":"#374151",background:p===o?"#1e1b4b":"#111827",color:p===o?"#a5b4fc":"#9ca3af"},children:{all:"Semua",hasToken:"✅ Punya Token",noToken:"❌ Tanpa Token",validJwt:"🔑 JWT Valid"}[o]},o))]}),a?e.jsx("div",{style:{textAlign:"center",color:"#6b7280",padding:40},children:"Memuat…"}):s?e.jsxs("div",{style:{color:"#f87171",padding:20},children:["Error: ",s]}):e.jsxs("div",{children:[e.jsxs("div",{style:{color:"#6b7280",fontSize:12,marginBottom:8},children:["Menampilkan ",u.length," dari ",r.length," akun"]}),u.map(o=>e.jsxs("div",{style:{...v,opacity:o.isActive?1:.5},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap"},children:[e.jsx("span",{style:{fontWeight:600,fontSize:13,minWidth:220,color:o.isActive?"#f9fafb":"#6b7280"},children:o.email}),e.jsx("span",{style:{fontSize:10,padding:"2px 7px",borderRadius:4,fontWeight:600,background:o.jwtValid?"#14532d":"#7f1d1d",color:o.jwtValid?"#86efac":"#fca5a5"},children:o.jwtValid?`JWT valid ${Math.ceil(o.jwtSecondsLeft/60)}m`:"JWT expired"}),e.jsx("span",{style:{fontSize:10,padding:"2px 7px",borderRadius:4,fontWeight:600,background:o.firebaseRefreshToken?"#1c1917":"#1f2937",color:o.firebaseRefreshToken?"#fbbf24":"#4b5563"},children:o.firebaseRefreshToken?"🔑 refresh_token ✓":"❌ no refresh_token"}),e.jsxs("span",{style:{fontSize:11,color:"#6b7280"},children:["💰 ",o.balance," credits"]}),e.jsxs("div",{style:{marginLeft:"auto",display:"flex",gap:6,flexWrap:"wrap"},children:[e.jsx(b,{value:o.firebaseRefreshToken,label:"Copy refresh_token"}),e.jsx(b,{value:o.firebaseApiKey,label:"Copy api_key"}),e.jsx(b,{value:o.jwt,label:"Copy JWT"}),e.jsx(b,{value:o.firebaseRefreshToken&&o.firebaseApiKey?JSON.stringify({email:o.email,firebase_refresh_token:o.firebaseRefreshToken,firebase_api_key:o.firebaseApiKey},null,2):"",label:"Copy All"})]})]}),e.jsxs("div",{style:{marginTop:6,display:"flex",gap:16,flexWrap:"wrap"},children:[e.jsxs("div",{children:[e.jsx("span",{style:{fontSize:10,color:"#9ca3af"},children:"refresh_token: "}),e.jsx(y,{value:o.firebaseRefreshToken})]}),e.jsxs("div",{children:[e.jsx("span",{style:{fontSize:10,color:"#9ca3af"},children:"api_key: "}),e.jsx(y,{value:o.firebaseApiKey,maxLen:16})]}),e.jsxs("div",{children:[e.jsx("span",{style:{fontSize:10,color:"#9ca3af"},children:"JWT: "}),e.jsx(y,{value:o.jwt})]})]})]},o.id)),u.length===0&&e.jsx("div",{style:{textAlign:"center",color:"#6b7280",padding:40},children:"Tidak ada akun ditemukan"})]})]})}export{C as default};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{a as ot,j as e,B as i,M as I,C as lt}from"./index.hce0krcP.js";import{b as l}from"./router.Cjj1--8t.js";import{C as Pe,B as k,T as ie,I as y}from"./NoAuthProxyCard.Ep103MXh.js";import{C as Se}from"./Loading.dETQxP6N.js";import"./zustand.akaTi5uX.js";function at(x){return x==="active"?"success":x==="error"?"error":"default"}function nt(x){if(!x)return"Never";const W=new Date(x);return Number.isNaN(W.getTime())?"Never":W.toLocaleString()}function ce(x={}){return{name:x.name||"",proxyUrl:x.proxyUrl||"",noProxy:x.noProxy||"",isActive:x.isActive!==!1,strictProxy:x.strictProxy===!0}}function ht(){const[x,W]=l.useState([]),[De,A]=l.useState(!1),[$,B]=l.useState(""),[b,L]=l.useState([]),[E,Y]=l.useState(null),[c,U]=l.useState([]),[Te,Ie]=l.useState(!0),[Ae,K]=l.useState(!1),[$e,Q]=l.useState(!1),[Ee,de]=l.useState(!1),[Ue,xe]=l.useState(!1),[Oe,me]=l.useState(!1),[O,M]=l.useState(!1),[V,he]=l.useState(null),[u,C]=l.useState(ce()),[X,ue]=l.useState(""),[F,Z]=l.useState({vercelToken:"",projectName:"vercel-relay"}),[j,_]=l.useState({accountId:"",apiToken:"",projectName:"cloudflare-relay"}),[N,q]=l.useState({denoToken:"",orgDomain:"",projectName:""}),[R,pe]=l.useState(!1),[J,fe]=l.useState(!1),[p,S]=l.useState(!1),[ee,ye]=l.useState(null),[h,H]=l.useState([]),[v,ge]=l.useState(!1),[be,te]=l.useState({current:0,total:0}),[z,D]=l.useState(!1),[g,w]=l.useState(null),se=l.useRef(null),n=ot();l.useEffect(()=>{const t=s=>{se.current&&!se.current.contains(s.target)&&M(!1)};return O&&document.addEventListener("mousedown",t),()=>document.removeEventListener("mousedown",t)},[O]);const f=l.useCallback(async()=>{try{const t=await fetch("/api/proxy-pools?includeUsage=true",{cache:"no-store"}),s=await t.json();t.ok&&U(s.proxyPools||[])}catch(t){console.log("Error fetching proxy pools:",t)}finally{Ie(!1)}},[]),G=l.useCallback(async()=>{try{const t=await fetch("/api/proxy-combos",{cache:"no-store"}),s=await t.json();t.ok&&W(s.combos||[])}catch{}},[]);l.useEffect(()=>{f(),G()},[f,G]);const je=()=>{he(null),C(ce())},ve=()=>{je(),K(!0)},Me=t=>{he(t),C(ce(t)),K(!0)},re=()=>{K(!1),je()},Fe=async()=>{const t={name:u.name.trim(),proxyUrl:u.proxyUrl.trim(),noProxy:u.noProxy.trim(),isActive:u.isActive===!0,strictProxy:u.strictProxy===!0};if(!(!t.name||!t.proxyUrl)){pe(!0);try{const s=!!V,r=await fetch(s?`/api/proxy-pools/${V.id}`:"/api/proxy-pools",{method:s?"PUT":"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(r.ok)await f(),re(),n.success(V?"Proxy pool updated":"Proxy pool created");else{const o=await r.json();n.error(o.error||"Failed to save proxy pool")}}catch(s){console.log("Error saving proxy pool:",s)}finally{pe(!1)}}},Re=async t=>{w({title:"Delete Proxy Pool",message:`Delete proxy pool "${t.name}"?`,onConfirm:async()=>{w(null);try{const s=await fetch(`/api/proxy-pools/${t.id}`,{method:"DELETE"});if(s.ok){U(o=>o.filter(a=>a.id!==t.id)),n.success("Proxy pool deleted");return}const r=await s.json();s.status===409?n.warning(`Cannot delete: ${r.boundConnectionCount||0} connection(s) are still using this pool.`):n.error(r.error||"Failed to delete proxy pool")}catch(s){console.log("Error deleting proxy pool:",s),n.error("Failed to delete proxy pool")}}})},ze=async t=>{ye(t);try{const s=await fetch(`/api/proxy-pools/${t}/test`,{method:"POST"}),r=await s.json();if(!s.ok){n.error(r.error||"Failed to test proxy");return}await f(),n.success(r.ok?"Proxy test passed":"Proxy test failed")}catch(s){console.log("Error testing proxy pool:",s),n.error("Failed to test proxy")}finally{ye(null)}},We=async t=>{const s=!t.isActive;U(r=>r.map(o=>o.id===t.id?{...o,isActive:s}:o));try{(await fetch(`/api/proxy-pools/${t.id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({isActive:s})})).ok||(U(o=>o.map(a=>a.id===t.id?{...a,isActive:t.isActive}:a)),n.error("Failed to update active state"))}catch(r){console.log("Error toggling active:",r),U(o=>o.map(a=>a.id===t.id?{...a,isActive:t.isActive}:a))}},oe=c.length>0&&h.length===c.length,Be=t=>H(s=>s.includes(t)?s.filter(r=>r!==t):[...s,t]),Le=()=>H(oe?[]:c.map(t=>t.id)),ke=()=>H([]),Ce=async t=>{const s=h.length>0?h:c.map(r=>r.id);if(s.length!==0){D(!0);try{let r=0,o=0;for(const a of s)try{(await fetch(`/api/proxy-pools/${a}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({isActive:t})})).ok?r+=1:o+=1}catch{o+=1}await f(),n.success(`${t?"Activated":"Deactivated"} ${r}${o?`, failed ${o}`:""}`)}finally{D(!1)}}},Ve=async()=>{h.length!==0&&w({title:"Delete Proxy Pools",message:`Delete ${h.length} proxy pool(s)?`,onConfirm:async()=>{w(null),D(!0);try{let t=0,s=0,r=0;for(const o of h)try{const a=await fetch(`/api/proxy-pools/${o}`,{method:"DELETE"});a.ok?t+=1:a.status===409?s+=1:r+=1}catch{r+=1}await f(),ke(),n.success(`Deleted ${t}${s?`, ${s} bound`:""}${r?`, ${r} failed`:""}`)}finally{D(!1)}}})},_e=async()=>{const t=h.length>0?c.filter(d=>h.includes(d.id)):c;if(t.length===0)return;ge(!0),te({current:0,total:t.length});let s=0;const r=[];let o=0;const a=10,m=[...t],P=async()=>{for(;m.length>0;){const d=m.shift();if(!d)break;try{const T=await fetch(`/api/proxy-pools/${d.id}/test`,{method:"POST"}),we=await T.json();T.ok&&we.ok?s+=1:r.push(d.id)}catch{r.push(d.id)}finally{o+=1,te({current:o,total:t.length})}}};await Promise.all(Array.from({length:Math.min(a,t.length)},P)),await f(),ge(!1),te({current:0,total:0}),r.length>0?w({title:"Disable Dead Proxies",message:`Alive: ${s}, Dead: ${r.length}.
|
|
2
|
+
|
|
3
|
+
Disable ${r.length} dead proxies?`,onConfirm:async()=>{w(null),D(!0);try{for(const d of r)try{await fetch(`/api/proxy-pools/${d}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({isActive:!1})})}catch{}await f(),n.success(`Disabled ${r.length} dead proxies`)}finally{D(!1)}}}):n.success(`Health check done. Alive: ${s}, Dead: ${r.length}`)};l.useEffect(()=>{H(t=>t.filter(s=>c.some(r=>r.id===s)))},[c]);const qe=()=>{ue(""),Q(!0)},Ne=()=>{J||Q(!1)},Je=()=>{Z({vercelToken:"",projectName:"vercel-relay"}),de(!0)},le=()=>{p||de(!1)},He=()=>{_({accountId:"",apiToken:"",projectName:"cloudflare-relay"}),xe(!0)},ae=()=>{p||xe(!1)},Ge=()=>{q({denoToken:"",orgDomain:"",projectName:""}),me(!0)},ne=()=>{p||me(!1)},Ye=async()=>{if(F.vercelToken.trim()){S(!0);try{const t=await fetch("/api/proxy-pools/vercel-deploy",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(F)}),s=await t.json();t.ok?(await f(),le(),n.success(`Deployed: ${s.deployUrl}`)):n.error(s.error||"Deploy failed")}catch(t){console.log("Error deploying Vercel relay:",t),n.error("Deploy failed")}finally{S(!1)}}},Ke=async()=>{if(!(!j.accountId.trim()||!j.apiToken.trim())){S(!0);try{const t=await fetch("/api/proxy-pools/cloudflare-deploy",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(j)}),s=await t.json();t.ok?(await f(),ae(),n.success(`Deployed: ${s.deployUrl}`)):n.error(s.error||"Deploy failed")}catch(t){console.log("Error deploying Cloudflare relay:",t),n.error("Deploy failed")}finally{S(!1)}}},Qe=async()=>{if(N.denoToken.trim()){S(!0);try{const t=await fetch("/api/proxy-pools/deno-deploy",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(N)}),s=await t.json();t.ok?(await f(),ne(),n.success(`Deployed: ${s.deployUrl}`)):n.error(s.error||"Deploy failed")}catch(t){console.log("Error deploying Deno relay:",t),n.error("Deploy failed")}finally{S(!1)}}},Xe=t=>{const s=t.trim();if(!s)return null;if(s.includes("://")){const o=new URL(s),a=o.port?`${o.hostname}:${o.port}`:o.hostname;return{proxyUrl:o.toString(),name:`Imported ${a}`}}const r=s.split(":");if(r.length===4){const[o,a,m,P]=r;if(!o||!a||!m||!P)throw new Error("Invalid host:port:user:pass format");const d=`http://${encodeURIComponent(m)}:${encodeURIComponent(P)}@${o}:${a}`;return{proxyUrl:new URL(d).toString(),name:`Imported ${o}:${a}`}}throw new Error("Unsupported format")},Ze=async()=>{const t=X.split(/\r?\n/).map(o=>o.trim()).filter(Boolean);if(t.length===0){n.warning("Please paste at least one proxy line.");return}const s=[],r=[];if(t.forEach((o,a)=>{try{const m=Xe(o);m&&s.push({...m,lineNumber:a+1})}catch(m){r.push(`Line ${a+1}: ${m.message}`)}}),r.length>0){n.error(`Invalid proxy format:
|
|
4
|
+
${r.join(`
|
|
5
|
+
`)}`);return}fe(!0);try{const o=new Set(c.map(d=>`${(d.proxyUrl||"").trim()}|||${(d.noProxy||"").trim()}`));let a=0,m=0,P=0;for(const d of s){const T=`${d.proxyUrl}|||`;if(o.has(T)){m+=1;continue}(await fetch("/api/proxy-pools",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:d.name,proxyUrl:d.proxyUrl,noProxy:"",isActive:!0})})).ok?(a+=1,o.add(T)):P+=1}await f(),Q(!1),n.success(`Batch import completed: Created ${a}, Skipped ${m}, Failed ${P}`)}catch(o){console.log("Error batch importing proxies:",o),n.error("Batch import failed")}finally{fe(!1)}},et=l.useMemo(()=>c.filter(t=>t.isActive===!0).length,[c]);if(Te)return e.jsxs("div",{className:"mx-auto flex w-full max-w-5xl flex-col gap-4 px-1 sm:gap-6 sm:px-0",children:[e.jsx(Se,{}),e.jsx(Se,{})]});const tt=async()=>{if(!$.trim()||b.length===0)return;const t=E?"PUT":"POST",s=E?{id:E.id,name:$,poolIds:b}:{name:$,poolIds:b};await fetch("/api/proxy-combos",{method:t,headers:{"Content-Type":"application/json"},body:JSON.stringify(s)}),A(!1),B(""),L([]),Y(null),G()},st=async t=>{await fetch("/api/proxy-combos",{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:t})}),G()},rt=t=>{var s;return((s=c.find(r=>r.id===t))==null?void 0:s.name)||t.slice(0,8)};return e.jsxs("div",{className:"mx-auto flex w-full max-w-5xl flex-col gap-4 px-1 sm:gap-6 sm:px-0",children:[e.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between",children:[e.jsx("div",{className:"min-w-0",children:e.jsx("h1",{className:"text-xl font-semibold sm:text-2xl",children:"Proxy Pools"})}),e.jsxs("div",{className:"grid grid-cols-1 gap-2 sm:flex sm:items-center",children:[e.jsxs("div",{className:"relative",ref:se,children:[e.jsxs(i,{size:"sm",variant:"secondary",icon:"rocket_launch",onClick:()=>M(!O),children:["Deploy Relay",e.jsx("span",{className:"material-symbols-outlined ml-1 text-[18px]",children:O?"expand_less":"expand_more"})]}),O&&e.jsxs("div",{className:"absolute left-0 top-full z-50 mt-1 w-48 rounded-xl border border-black/10 bg-white p-1 shadow-xl dark:border-white/10 dark:bg-zinc-900 sm:left-auto sm:right-0",children:[e.jsxs("button",{onClick:()=>{He(),M(!1)},className:"flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm text-text-main transition-colors hover:bg-black/5 dark:hover:bg-white/5",children:[e.jsx("span",{className:"material-symbols-outlined text-[20px] text-orange-500",children:"cloud"}),"Cloudflare Relay"]}),e.jsxs("button",{onClick:()=>{Je(),M(!1)},className:"flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm text-text-main transition-colors hover:bg-black/5 dark:hover:bg-white/5",children:[e.jsx("span",{className:"material-symbols-outlined text-[20px] text-blue-500",children:"cloud_upload"}),"Vercel Relay"]}),e.jsxs("button",{onClick:()=>{Ge(),M(!1)},className:"flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm text-text-main transition-colors hover:bg-black/5 dark:hover:bg-white/5",children:[e.jsx("span",{className:"material-symbols-outlined text-[20px] text-green-500",children:"terminal"}),"Deno Relay"]})]})]}),e.jsx(i,{size:"sm",variant:"secondary",icon:"upload",onClick:qe,children:"Batch Import"}),e.jsx(i,{size:"sm",icon:"add",onClick:ve,children:"Add Proxy Pool"})]})]}),e.jsxs(Pe,{children:[e.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-2",children:[c.length>0&&e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-text-muted cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:oe,onChange:Le,className:"size-4 rounded border-black/20 dark:border-white/20"}),oe?"Unselect all":"Select all"]}),e.jsxs(k,{variant:"default",children:["Total: ",c.length]}),e.jsxs(k,{variant:"success",children:["Active: ",et]})]}),(h.length>0||v)&&e.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-2 rounded-lg border border-primary/30 bg-primary/5 px-3 py-2",children:[e.jsx("span",{className:"material-symbols-outlined text-[18px] text-primary",children:"checklist"}),e.jsx("span",{className:"text-xs font-medium text-primary",children:h.length>0?`${h.length} selected`:"All pools"}),e.jsxs("div",{className:"ml-auto flex flex-wrap items-center gap-2",children:[e.jsx(i,{size:"sm",icon:v?"progress_activity":"health_and_safety",onClick:_e,disabled:v||z||c.length===0,children:v?`Checking ${be.current}/${be.total}`:"Health Check"}),h.length>0&&e.jsxs(e.Fragment,{children:[e.jsx(i,{size:"sm",variant:"secondary",icon:"toggle_on",onClick:()=>Ce(!0),disabled:z||v,children:"Activate"}),e.jsx(i,{size:"sm",variant:"secondary",icon:"toggle_off",onClick:()=>Ce(!1),disabled:z||v,children:"Deactivate"}),e.jsx(i,{size:"sm",variant:"secondary",icon:"delete",onClick:Ve,disabled:z||v,children:"Delete"}),e.jsx(i,{size:"sm",variant:"ghost",onClick:ke,disabled:z||v,children:"Clear"})]})]})]}),c.length===0?e.jsxs("div",{className:"text-center py-10",children:[e.jsx("p",{className:"text-text-main font-medium mb-1",children:"No proxy pool entries yet"}),e.jsx("p",{className:"text-sm text-text-muted mb-4",children:"Create a proxy pool entry, then assign it to connections."}),e.jsx(i,{icon:"add",onClick:ve,children:"Add Proxy Pool"})]}):e.jsx("div",{className:"flex flex-col divide-y divide-black/[0.04] dark:divide-white/[0.05]",children:c.map(t=>e.jsxs("div",{className:"flex flex-col gap-3 py-3 sm:flex-row sm:items-center sm:justify-between",children:[e.jsxs("div",{className:"flex items-start gap-3 min-w-0 flex-1",children:[e.jsx("input",{type:"checkbox",checked:h.includes(t.id),onChange:()=>Be(t.id),className:"mt-1 size-4 shrink-0 rounded border-black/20 dark:border-white/20"}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("p",{className:"min-w-0 max-w-full truncate text-sm font-medium sm:max-w-[18rem]",children:t.name}),e.jsx(k,{variant:at(t.testStatus),size:"sm",dot:!0,children:t.testStatus||"unknown"}),e.jsx(k,{variant:t.isActive?"success":"default",size:"sm",children:t.isActive?"active":"inactive"}),t.type==="vercel"&&e.jsx(k,{variant:"default",size:"sm",children:"vercel relay"}),t.type==="cloudflare"&&e.jsx(k,{variant:"default",size:"sm",children:"cloudflare relay"}),e.jsxs(k,{variant:"default",size:"sm",children:[t.boundConnectionCount||0," bound"]})]}),e.jsx("p",{className:"text-xs text-text-muted truncate mt-1",children:t.proxyUrl}),t.noProxy?e.jsxs("p",{className:"text-xs text-text-muted truncate",children:["No proxy: ",t.noProxy]}):null,e.jsxs("p",{className:"text-[11px] text-text-muted mt-1",children:["Last tested: ",nt(t.lastTestedAt),t.lastError?` · ${t.lastError}`:""]})]})]}),e.jsxs("div",{className:"flex items-center justify-end gap-1",children:[e.jsx(ie,{size:"sm",checked:t.isActive===!0,onChange:()=>We(t),title:t.isActive?"Disable":"Enable"}),e.jsx("button",{onClick:()=>ze(t.id),className:"p-2 rounded hover:bg-black/5 dark:hover:bg-white/5 text-text-muted hover:text-primary",title:"Test proxy",disabled:ee===t.id,children:e.jsx("span",{className:"material-symbols-outlined text-[18px]",style:ee===t.id?{animation:"spin 1s linear infinite"}:void 0,children:ee===t.id?"progress_activity":"science"})}),e.jsx("button",{onClick:()=>Me(t),className:"p-2 rounded hover:bg-black/5 dark:hover:bg-white/5 text-text-muted hover:text-primary",title:"Edit",children:e.jsx("span",{className:"material-symbols-outlined text-[18px]",children:"edit"})}),e.jsx("button",{onClick:()=>Re(t),className:"p-2 rounded hover:bg-red-500/10 text-red-500",title:"Delete",children:e.jsx("span",{className:"material-symbols-outlined text-[18px]",children:"delete"})})]})]},t.id))})]}),e.jsx(I,{isOpen:$e,title:"Batch Import Proxies",onClose:Ne,children:e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"text-sm font-medium text-text-main mb-1 block",children:"Paste Proxy List (One per line)"}),e.jsx("textarea",{value:X,onChange:t=>ue(t.target.value),placeholder:`http://user:pass@127.0.0.1:7897
|
|
6
|
+
127.0.0.1:7897:user:pass`,className:"w-full min-h-[180px] py-2 px-3 text-sm text-text-main bg-white dark:bg-white/5 border border-black/10 dark:border-white/10 rounded-md focus:ring-1 focus:ring-primary/30 focus:border-primary/50 focus:outline-none transition-all"}),e.jsx("p",{className:"text-xs text-text-muted mt-1",children:"Supported formats: protocol://user:pass@host:port, host:port:user:pass"})]}),e.jsxs("div",{className:"grid grid-cols-1 gap-2 sm:grid-cols-2",children:[e.jsx(i,{fullWidth:!0,onClick:Ze,disabled:!X.trim()||J,children:J?"Importing...":"Import"}),e.jsx(i,{fullWidth:!0,variant:"ghost",onClick:Ne,disabled:J,children:"Cancel"})]})]})}),e.jsx(I,{isOpen:Ee,title:"Deploy Vercel Relay",onClose:le,children:e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"rounded-lg bg-blue-500/5 border border-blue-500/10 p-3 flex flex-col gap-1.5",children:[e.jsx("p",{className:"text-sm text-text-main font-medium",children:"What is Vercel Relay?"}),e.jsx("p",{className:"text-xs text-text-muted",children:"Deploys an edge relay function to Vercel. All AI provider requests will be forwarded through Vercel's edge network, masking your real IP from providers."}),e.jsxs("ul",{className:"text-xs text-text-muted list-disc pl-4 space-y-0.5",children:[e.jsx("li",{children:"Your IP is replaced by Vercel's dynamic edge IPs (hundreds of IPs across 20+ global regions)"}),e.jsx("li",{children:"Vercel serves millions of apps — providers can't block Vercel IPs without affecting legitimate traffic"}),e.jsx("li",{children:"Free tier: 100GB bandwidth/month, 500K edge invocations"}),e.jsx("li",{children:"Deploy multiple relays on different accounts for more IP diversity"})]})]}),e.jsx(y,{label:"Vercel API Token",value:F.vercelToken,onChange:t=>Z(s=>({...s,vercelToken:t.target.value})),placeholder:"your-vercel-api-token",hint:e.jsxs(e.Fragment,{children:["Token is used once for deployment and not stored. ",e.jsx("a",{href:"https://vercel.com/account/tokens",target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",children:"Get token →"})]}),type:"password"}),e.jsx(y,{label:"Project Name",value:F.projectName,onChange:t=>Z(s=>({...s,projectName:t.target.value})),placeholder:"my-relay",hint:"Unique name for your Vercel project. Leave empty for auto-generated name."}),e.jsxs("div",{className:"grid grid-cols-1 gap-2 sm:grid-cols-2",children:[e.jsx(i,{fullWidth:!0,onClick:Ye,disabled:!F.vercelToken.trim()||p,children:p?"Deploying... (may take ~1 min)":"Deploy"}),e.jsx(i,{fullWidth:!0,variant:"ghost",onClick:le,disabled:p,children:"Cancel"})]})]})}),e.jsx(I,{isOpen:Ue,title:"Deploy Cloudflare Relay",onClose:ae,children:e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"rounded-lg bg-orange-500/5 border border-orange-500/10 p-3 flex flex-col gap-1.5",children:[e.jsx("p",{className:"text-sm text-text-main font-medium",children:"What is Cloudflare Relay?"}),e.jsx("p",{className:"text-xs text-text-muted",children:"Deploys a Cloudflare Worker as a proxy relay. All AI provider requests will be forwarded through Cloudflare's global edge network."}),e.jsxs("ul",{className:"text-xs text-text-muted list-disc pl-4 space-y-0.5",children:[e.jsx("li",{children:"High performance global routing and IP masking via Cloudflare Workers"}),e.jsx("li",{children:"Free tier: 100,000 requests per day"}),e.jsx("li",{children:"Requires Cloudflare Account ID and a Workers API Token (Edit Workers permission)"})]}),e.jsxs("div",{className:"mt-2 pt-2 border-t border-orange-500/10 text-xs text-text-muted",children:[e.jsx("p",{className:"font-medium text-text-main mb-1",children:"How to generate your API Token:"}),e.jsxs("ol",{className:"list-decimal pl-4 space-y-0.5",children:[e.jsxs("li",{children:["Go to ",e.jsx("b",{children:"My Profile"})," → ",e.jsx("b",{children:"API Tokens"})," → ",e.jsx("b",{children:"Create Token"})]}),e.jsxs("li",{children:["Scroll down to ",e.jsx("b",{children:"Custom Token"})," and click ",e.jsx("b",{children:"Get started"})]}),e.jsxs("li",{children:["Under ",e.jsx("b",{children:"Permissions"}),": Account | Workers Scripts | Edit"]}),e.jsxs("li",{children:["Under ",e.jsx("b",{children:"Account Resources"}),": Include | Account | ",e.jsx("i",{children:"Your Account Name"})]}),e.jsxs("li",{children:["Click ",e.jsx("b",{children:"Continue to summary"})," → ",e.jsx("b",{children:"Create Token"})]})]})]})]}),e.jsx(y,{label:"Account ID",value:j.accountId,onChange:t=>_(s=>({...s,accountId:t.target.value})),placeholder:"your-cloudflare-account-id",hint:e.jsx(e.Fragment,{children:"Found on the right side of the Cloudflare dashboard overview page."})}),e.jsx(y,{label:"API Token",value:j.apiToken,onChange:t=>_(s=>({...s,apiToken:t.target.value})),placeholder:"your-cloudflare-api-token",hint:e.jsxs(e.Fragment,{children:['Requires "Workers Scripts: Edit" permission. ',e.jsx("a",{href:"https://dash.cloudflare.com/profile/api-tokens",target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",children:"Get token →"})]}),type:"password"}),e.jsx(y,{label:"Worker Name",value:j.projectName,onChange:t=>_(s=>({...s,projectName:t.target.value})),placeholder:"my-relay",hint:"Unique name for your Cloudflare Worker. Leave empty for auto-generated name."}),e.jsxs("div",{className:"grid grid-cols-1 gap-2 sm:grid-cols-2",children:[e.jsx(i,{fullWidth:!0,onClick:Ke,disabled:!j.accountId.trim()||!j.apiToken.trim()||p,children:p?"Deploying...":"Deploy Worker"}),e.jsx(i,{fullWidth:!0,variant:"ghost",onClick:ae,disabled:p,children:"Cancel"})]})]})}),e.jsx(I,{isOpen:Oe,title:"Deploy Deno Relay",onClose:ne,children:e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"rounded-lg bg-black/5 dark:bg-white/5 border border-black/10 dark:border-white/10 p-3 flex flex-col gap-1.5",children:[e.jsx("p",{className:"text-sm text-text-main font-medium",children:"What is Deno Relay?"}),e.jsx("p",{className:"text-xs text-text-muted",children:"Deploys a relay worker to Deno Deploy's global edge network. All AI provider requests are forwarded through Deno's edge, masking your real IP."}),e.jsxs("ul",{className:"text-xs text-text-muted list-disc pl-4 space-y-0.5",children:[e.jsx("li",{children:"Deno Deploy v2 runs on a high-performance global edge network"}),e.jsx("li",{children:"Free tier: 1M requests & 100GiB outbound traffic per month"}),e.jsx("li",{children:"No per-request CPU time limits (unlike Vercel/Cloudflare)"}),e.jsx("li",{children:"Support up to 20 active apps & 50 custom domains"}),e.jsx("li",{children:"Deploy multiple relays for maximum IP diversity"})]}),e.jsxs("div",{className:"mt-2 pt-2 border-t border-black/10 dark:border-white/10 text-xs text-text-muted",children:[e.jsx("p",{className:"font-medium text-text-main mb-1",children:"How to generate API token:"}),e.jsxs("ol",{className:"list-decimal pl-4 space-y-0.5",children:[e.jsxs("li",{children:["Go to ",e.jsx("b",{children:"console.deno.com"})]}),e.jsxs("li",{children:["Select your ",e.jsx("b",{children:"Organization"})," → ",e.jsx("b",{children:"Settings"})," → ",e.jsx("b",{children:"Organization Tokens"})]}),e.jsxs("li",{children:["Create a ",e.jsx("b",{children:"Organization Token"})," (prefix ",e.jsx("b",{children:"ddo_"}),")"]})]})]})]}),e.jsx(y,{label:"Deno Deploy API Token",value:N.denoToken,onChange:t=>q(s=>({...s,denoToken:t.target.value})),placeholder:"ddo_xxxxxxxxxxxxxxxx",hint:e.jsx(e.Fragment,{children:"Token is used once for deployment, not stored. Found in Organization Settings."}),type:"password"}),e.jsx(y,{label:"Organization Domain",value:N.orgDomain,onChange:t=>q(s=>({...s,orgDomain:t.target.value})),placeholder:"your-org.deno.net",hint:"Organization's default domain. Your relay URL will be in the format: https://my-relay.your-org.deno.net"}),e.jsx(y,{label:"App Name",value:N.projectName,onChange:t=>q(s=>({...s,projectName:t.target.value})),placeholder:"deno-relay",hint:"Unique app name. Leave empty for auto-generated name."}),e.jsxs("div",{className:"grid grid-cols-1 gap-2 sm:grid-cols-2",children:[e.jsx(i,{fullWidth:!0,onClick:Qe,disabled:!N.denoToken.trim()||!N.orgDomain.trim()||p,children:p?"Deploying...":"Deploy Relay"}),e.jsx(i,{fullWidth:!0,variant:"ghost",onClick:ne,disabled:p,children:"Cancel"})]})]})}),e.jsx(I,{isOpen:Ae,title:V?"Edit Proxy Pool":"Add Proxy Pool",onClose:re,children:e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx(y,{label:"Name",value:u.name,onChange:t=>C(s=>({...s,name:t.target.value})),placeholder:"Office Proxy"}),e.jsx(y,{label:"Proxy URL",value:u.proxyUrl,onChange:t=>C(s=>({...s,proxyUrl:t.target.value})),placeholder:"http://127.0.0.1:7897"}),e.jsx(y,{label:"No Proxy",value:u.noProxy,onChange:t=>C(s=>({...s,noProxy:t.target.value})),placeholder:"localhost,127.0.0.1,.internal",hint:"Comma-separated hosts/domains to bypass proxy"}),e.jsxs("div",{className:"flex flex-col gap-3 rounded-lg border border-border/50 p-3 sm:flex-row sm:items-center sm:justify-between",children:[e.jsxs("div",{children:[e.jsx("p",{className:"font-medium text-sm",children:"Active"}),e.jsx("p",{className:"text-xs text-text-muted",children:"Inactive pools are ignored by runtime resolution."})]}),e.jsx(ie,{checked:u.isActive===!0,onChange:()=>C(t=>({...t,isActive:!t.isActive})),disabled:R})]}),e.jsxs("div",{className:"flex flex-col gap-3 rounded-lg border border-border/50 p-3 sm:flex-row sm:items-center sm:justify-between",children:[e.jsxs("div",{children:[e.jsx("p",{className:"font-medium text-sm",children:"Strict Proxy"}),e.jsx("p",{className:"text-xs text-text-muted",children:"Fail request if proxy is unreachable instead of falling back to direct."})]}),e.jsx(ie,{checked:u.strictProxy===!0,onChange:()=>C(t=>({...t,strictProxy:!t.strictProxy})),disabled:R})]}),e.jsxs("div",{className:"grid grid-cols-1 gap-2 sm:grid-cols-2",children:[e.jsx(i,{fullWidth:!0,onClick:Fe,disabled:!u.name.trim()||!u.proxyUrl.trim()||R,children:R?"Saving...":"Save"}),e.jsx(i,{fullWidth:!0,variant:"ghost",onClick:re,disabled:R,children:"Cancel"})]})]})}),e.jsxs(Pe,{children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-semibold",children:"Proxy Combos"}),e.jsx("p",{className:"text-xs text-text-muted",children:"Round-robin rotation across multiple pools"})]}),e.jsx(i,{size:"sm",icon:"add",onClick:()=>{Y(null),B(""),L([]),A(!0)},children:"Add Combo"})]}),x.length===0?e.jsx("p",{className:"text-sm text-text-muted py-4 text-center",children:"No combos yet. Create one to rotate proxies automatically."}):e.jsx("div",{className:"space-y-2",children:x.map(t=>e.jsxs("div",{className:"flex items-center justify-between p-3 rounded-lg border border-border-subtle bg-surface hover:bg-surface/50",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("p",{className:"font-medium text-sm text-text-main",children:t.name}),e.jsx("p",{className:"text-xs text-text-muted mt-0.5",children:(t.poolIds||[]).map((s,r)=>e.jsxs("span",{children:[r>0?" → ":"",rt(s)]},s))})]}),e.jsxs("div",{className:"flex items-center gap-2 ml-3",children:[e.jsxs(k,{variant:"success",size:"sm",children:[(t.poolIds||[]).length," pools"]}),e.jsx("button",{onClick:()=>{Y(t),B(t.name),L(t.poolIds||[]),A(!0)},className:"text-xs text-brand-400 hover:text-brand-300 cursor-pointer",children:"Edit"}),e.jsx("button",{onClick:()=>st(t.id),className:"text-xs text-red-400 hover:text-red-300 cursor-pointer",children:"Delete"})]})]},t.id))})]}),e.jsx(I,{isOpen:De,onClose:()=>A(!1),title:E?"Edit Combo":"Create Proxy Combo",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"text-xs font-medium text-text-muted block mb-1",children:"Combo Name"}),e.jsx(y,{value:$,onChange:t=>B(t.target.value),placeholder:"e.g. Free Proxy Round Robin"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-xs font-medium text-text-muted block mb-2",children:"Select Pools (click to toggle)"}),e.jsx("div",{className:"max-h-48 overflow-y-auto space-y-1 rounded-lg border border-border-subtle p-2",children:c.map(t=>e.jsxs("label",{className:`flex items-center gap-2 p-2 rounded cursor-pointer text-sm transition-colors ${b.includes(t.id)?"bg-primary/10 text-primary":"hover:bg-surface-2 text-text-main"}`,children:[e.jsx("input",{type:"checkbox",checked:b.includes(t.id),onChange:s=>{L(s.target.checked?[...b,t.id]:b.filter(r=>r!==t.id))},className:"rounded"}),t.name]},t.id))})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(i,{fullWidth:!0,onClick:tt,disabled:!$.trim()||b.length===0,children:E?"Save Changes":"Create Combo"}),e.jsx(i,{fullWidth:!0,variant:"ghost",onClick:()=>A(!1),children:"Cancel"})]})]})}),e.jsx(lt,{isOpen:!!g,onClose:()=>w(null),onConfirm:g==null?void 0:g.onConfirm,title:(g==null?void 0:g.title)||"Confirm",message:g==null?void 0:g.message,variant:"danger"})]})}export{ht as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as e}from"./index.hce0krcP.js";import{b as t,d as H}from"./router.Cjj1--8t.js";import"./zustand.akaTi5uX.js";function z(){const[x,N]=t.useState(""),[m,c]=t.useState(""),[W,b]=t.useState(""),[r,f]=t.useState(0),[g,w]=t.useState(!1),[y,u]=t.useState(null),[n,k]=t.useState("password"),[i,L]=t.useState(!1),[S,C]=t.useState("Sign in with OIDC"),[h,M]=t.useState(!1),l=H();t.useEffect(()=>{if(r<=0)return;const a=setInterval(()=>f(s=>s>0?s-1:0),1e3);return()=>clearInterval(a)},[r]),t.useEffect(()=>{async function a(){const s=new AbortController,o=setTimeout(()=>s.abort(),5e3),R=typeof window<"u"?window.location.origin:"";try{const v=await fetch(`${R}/api/auth/status`,{signal:s.signal});if(clearTimeout(o),v.ok){const d=await v.json(),j=new URLSearchParams(window.location.search),E=j.get("force")==="true"||j.get("force")==="1";if(d.requireLogin===!1&&!E){localStorage.setItem("9r_authed","1"),l("/dashboard"),l(0);return}u(!!d.hasPassword),k(d.authMode||"password"),L(d.oidcConfigured===!0),C(d.oidcLoginLabel||"Sign in with OIDC")}else u(!0)}catch{clearTimeout(o),u(!0)}}a()},[l]);const P=async a=>{a.preventDefault(),w(!0),c(""),b("");try{const s=await fetch("/api/auth/login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({password:x})});if(s.ok)localStorage.setItem("9r_authed","1"),l("/dashboard"),l(0);else{const o=await s.json();c(o.error||"Invalid password"),o.resetHint&&b(o.resetHint),o.retryAfter&&f(Number(o.retryAfter))}}catch{c("An error occurred. Please try again.")}finally{w(!1)}},I=()=>{window.location.href="/api/auth/oidc/start"},A=i&&["oidc","both"].includes(n),p=n!=="oidc"||!i,O=n==="oidc"&&!i||n==="both"&&!i,D=n==="both"&&i;return y===null?e.jsx("div",{className:"min-h-screen flex items-center justify-center bg-gradient-to-br from-slate-50 to-slate-100",children:e.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-slate-400"})}):e.jsxs("div",{className:"min-h-screen flex items-center justify-center bg-gradient-to-br from-slate-50 via-white to-slate-100 p-4",children:[e.jsxs("div",{className:"absolute inset-0 overflow-hidden pointer-events-none",children:[e.jsx("div",{className:"absolute -top-40 -right-40 w-80 h-80 bg-violet-200/30 rounded-full blur-3xl"}),e.jsx("div",{className:"absolute -bottom-40 -left-40 w-80 h-80 bg-blue-200/30 rounded-full blur-3xl"})]}),e.jsxs("div",{className:"relative w-full max-w-sm",children:[e.jsxs("div",{className:"bg-white rounded-2xl shadow-lg shadow-slate-200/50 border border-slate-200/60 p-8",children:[e.jsxs("div",{className:"text-center mb-8",children:[e.jsx("div",{className:"inline-flex items-center justify-center w-12 h-12 rounded-xl bg-gradient-to-br from-violet-500 to-blue-500 mb-4 shadow-lg shadow-violet-500/25",children:e.jsx("svg",{className:"w-6 h-6 text-white",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M13 10V3L4 14h7v7l9-11h-7z"})})}),e.jsx("h1",{className:"text-2xl font-bold text-slate-900 tracking-tight",children:"FSRouter"}),e.jsx("p",{className:"text-sm text-slate-500 mt-1",children:n==="oidc"&&i?"Sign in with your OIDC provider":"Enter your password to continue"})]}),O&&e.jsx("div",{className:"mb-4 p-3 rounded-lg bg-amber-50 border border-amber-200 text-xs text-amber-700",children:"OIDC not configured yet. Password login is available."}),D&&e.jsx("div",{className:"mb-4 p-3 rounded-lg bg-violet-50 border border-violet-200 text-xs text-violet-700 text-center",children:"Password and OIDC login are both enabled."}),p&&e.jsxs("form",{onSubmit:P,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"text-xs font-medium text-slate-600 block mb-1.5",children:"Password"}),e.jsxs("div",{className:"relative",children:[e.jsx("input",{name:"password",type:h?"text":"password",placeholder:"••••••••",value:x,onChange:a=>N(a.target.value),required:!0,autoFocus:!0,className:"w-full bg-slate-50 border border-slate-200 text-slate-900 text-sm p-3 pr-10 rounded-xl focus:outline-none focus:border-violet-400 focus:ring-2 focus:ring-violet-100 placeholder-slate-400 transition-all"}),e.jsx("button",{type:"button",onClick:()=>M(!h),className:"absolute inset-y-0 right-3 flex items-center text-slate-400 hover:text-slate-600",children:h?e.jsx("svg",{className:"w-4 h-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.878 9.878L3 3m6.878 6.878l4.242 4.242M21 21l-3.122-3.122"})}):e.jsxs("svg",{className:"w-4 h-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:[e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M15 12a3 3 0 11-6 0 3 3 0 016 0z"}),e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"})]})})]}),m&&e.jsx("p",{className:"text-xs text-red-500 mt-1.5",children:m}),r>0&&e.jsxs("p",{className:"text-xs text-amber-600 mt-1.5",children:["Locked. Retry in ",r,"s."]})]}),e.jsx("button",{type:"submit",disabled:g||r>0,className:"w-full bg-gradient-to-r from-violet-500 to-blue-500 hover:from-violet-600 hover:to-blue-600 text-white font-medium text-sm py-3 rounded-xl transition-all shadow-lg shadow-violet-500/25 disabled:opacity-50 cursor-pointer",children:g?"Logging in...":r>0?`Wait ${r}s`:"Login"}),e.jsxs("p",{className:"text-center text-xs text-slate-400",children:["Default password is ",e.jsx("code",{className:"bg-slate-100 px-1.5 py-0.5 rounded text-slate-500 font-mono",children:"123456"})]})]}),A&&e.jsxs(e.Fragment,{children:[p&&e.jsxs("div",{className:"relative flex items-center justify-center py-4",children:[e.jsx("span",{className:"w-full border-t border-slate-200"}),e.jsx("span",{className:"px-3 text-xs text-slate-400 bg-white absolute",children:"or"})]}),e.jsxs("button",{onClick:I,type:"button",className:"w-full flex items-center justify-center gap-2 border border-slate-200 rounded-xl py-3 hover:bg-slate-50 transition-colors text-slate-600 text-sm cursor-pointer",children:[e.jsx("svg",{className:"w-4 h-4",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:e.jsx("path",{d:"M15 3h4a2 2 0 012 2v14a2 2 0 01-2 2h-4M10 17l5-5-5-5M15 12H3"})}),S]})]})]}),e.jsx("p",{className:"text-center text-xs text-slate-400 mt-6",children:"Powered by FSRouter"})]})]})}export{z as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{h as et,j as e,U as tt,P as Ae}from"./index.hce0krcP.js";import{b as c}from"./router.Cjj1--8t.js";import{C as rt}from"./Loading.dETQxP6N.js";import{C as ce,T as st,E as nt}from"./NoAuthProxyCard.Ep103MXh.js";import"./zustand.akaTi5uX.js";function at(s){if(!s)return"-";try{const u=(typeof s=="string"?new Date(s):s)-new Date;if(u<=0)return"-";const l=Math.ceil(u/(1e3*60));if(l<60)return`${l}m`;const a=Math.floor(l/60),x=l%60;if(a<24)return`${a}h ${x}m`;const h=Math.floor(a/24),p=a%24;return`${h}d ${p}h ${x}m`}catch{return"-"}}function $e(s,n){return!n||n===0?0:!s||s<0?100:s>=n?0:Math.round((n-s)/n*100)}function it(s){return(s==null?void 0:s.remaining)!==void 0?Math.max(0,Math.round(s.remaining)):(s==null?void 0:s.remainingPercentage)!==void 0?Math.round(s.remainingPercentage):$e(s==null?void 0:s.used,s==null?void 0:s.total)}function ot(s,n){if(!n||typeof n!="object")return[];const o=[];try{switch(s.toLowerCase()){case"github":n.quotas&&Object.entries(n.quotas).forEach(([l,a])=>{o.push({name:l,used:a.used||0,total:a.total||0,resetAt:a.resetAt||null})});break;case"antigravity":n.quotas&&Object.entries(n.quotas).forEach(([l,a])=>{o.push({name:a.displayName||l,modelKey:l,used:a.used||0,total:a.total||0,resetAt:a.resetAt||null,remainingPercentage:a.remainingPercentage})});break;case"codex":if(n.quotas){const l={session:"Session (5h)",weekly:"Weekly (7d)",code_review:"Code Review",code_review_weekly:"Code Review Weekly",spark:"Spark",spark_weekly:"Spark Weekly"};Object.entries(n.quotas).forEach(([a,x])=>{o.push({name:x.displayName||l[a]||a,used:x.used||0,total:x.total||0,remaining:x.remaining,resetAt:x.resetAt||null})})}n.bankedResetCredits!==void 0&&n.bankedResetCredits>0&&o.push({name:"Banked Reset Credits",used:0,total:n.bankedResetCredits,remaining:n.bankedResetCredits,resetAt:null});break;case"kiro":n.quotas&&Object.entries(n.quotas).forEach(([l,a])=>{o.push({name:l,used:a.used||0,total:a.total||0,resetAt:a.resetAt||null})});break;case"qoder":n.quotas&&Object.entries(n.quotas).forEach(([l,a])=>{l==="organization"&&(!a||(Number(a.total)||0)===0)||o.push({name:l==="user"?"Personal":l==="organization"?"Organization":l,used:a.used||0,total:a.total||0,unit:a.unit,resetAt:a.resetAt||null})});break;case"claude":n.message?o.push({name:"error",used:0,total:0,resetAt:null,message:n.message}):n.quotas&&Object.entries(n.quotas).forEach(([l,a])=>{o.push({name:l,used:a.used||0,total:a.total||0,resetAt:a.resetAt||null})});break;case"leonardo":n.quotas&&Object.entries(n.quotas).forEach(([l,a])=>{o.push({name:l==="tokens"?"Tokens":l,used:a.used||0,total:a.total||0,resetAt:a.resetAt||null,unit:a.unit||null,remaining:a.remaining!==void 0?a.remaining:null})});break;case"weavy":n.quotas&&Object.entries(n.quotas).forEach(([l,a])=>{o.push({name:l==="tokens"?"tokens":l,used:a.used||0,total:a.total||0,resetAt:a.resetAt||null,unit:a.unit||null,remaining:a.remaining!==void 0?a.remaining:null})});break;case"cloudflare-ai":n.quotas&&Object.entries(n.quotas).forEach(([l,a])=>{o.push({name:l,used:a.used||0,total:a.total||0,resetAt:a.resetAt||null,unit:a.unit||"neurons"})});break;default:n.quotas&&Object.entries(n.quotas).forEach(([l,a])=>{o.push({name:l,used:a.used||0,total:a.total||0,resetAt:a.resetAt||null,unit:a.unit||null,remaining:a.remaining!==void 0?a.remaining:null})})}}catch(l){return console.error(`Error parsing quota data for ${s}:`,l),[]}const u=et(s);if(u.length>0){const l=new Map(u.map((a,x)=>[a.id,x]));o.sort((a,x)=>{const h=a.modelKey||a.name,p=x.modelKey||x.name,U=l.get(h)??999,G=l.get(p)??999;return U-G})}return o}const W=10;function lt(s){if(!s)return null;try{const n=new Date(s),o=new Date,u=new Date(o.getFullYear(),o.getMonth(),o.getDate()),l=new Date(u);l.setDate(l.getDate()+1);let a="";n>=u&&n<l?a="Today":n>=l&&n<new Date(l.getTime()+1440*60*1e3)?a="Tomorrow":a=n.toLocaleDateString("en-US",{month:"short",day:"numeric"});const x=n.toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit",hour12:!0});return`${a}, ${x}`}catch{return null}}function ct(s){return s>70?{text:"text-green-600 dark:text-green-400",bg:"bg-green-500",bgLight:"bg-green-500/10",emoji:"🟢"}:s>=30?{text:"text-yellow-600 dark:text-yellow-400",bg:"bg-yellow-500",bgLight:"bg-yellow-500/10",emoji:"🟡"}:{text:"text-red-600 dark:text-red-400",bg:"bg-red-500",bgLight:"bg-red-500/10",emoji:"🔴"}}function dt(s,n){return n==="remaining-asc"?[...s].sort((o,u)=>o.remaining-u.remaining||o.name.localeCompare(u.name)):n==="remaining-desc"?[...s].sort((o,u)=>u.remaining-o.remaining||o.name.localeCompare(u.name)):s}function ut({quotas:s=[],compact:n=!1,sortMode:o="default",showSortLabel:u=!1}){const[l,a]=c.useState(1),x=c.useMemo(()=>s.map((m,f)=>({...m,index:f,remaining:it(m)})),[s]),h=c.useMemo(()=>dt(x,o),[x,o]),p=Math.max(1,Math.ceil(h.length/W));if(c.useEffect(()=>{a(1)},[o,s]),c.useEffect(()=>{a(m=>Math.min(m,p))},[p]),!s||s.length===0)return null;const U=h.slice((l-1)*W,l*W),G=h.length===0?0:(l-1)*W+1,V=Math.min(l*W,h.length),b=n?"py-1 px-1.5":"py-2 px-3",q=n?"text-[11px]":"text-sm",v=n?"text-[11px]":"text-sm",J=n?"text-[10px] leading-tight":"text-xs";return e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("div",{className:"text-[10px] text-text-muted",children:[h.length," quota",h.length>1?"s":""]}),u&&e.jsx("div",{className:"rounded-md border border-black/10 bg-black/[0.02] px-2 py-1 text-[10px] text-text-muted dark:border-white/10 dark:bg-white/[0.03]",children:"Sorted by account remaining"})]}),e.jsx("div",{className:"overflow-x-auto",children:e.jsx("table",{className:"w-full table-fixed text-left",children:e.jsx("tbody",{children:U.map(m=>{var B;const f=ct(m.remaining),I=at(m.resetAt),D=lt(m.resetAt),te=((B=m.name)==null?void 0:B.toLowerCase())==="tokens"?Math.max(0,m.total-m.used):m.used;return e.jsxs("tr",{className:"border-b border-black/5 dark:border-white/5 hover:bg-black/[0.02] dark:hover:bg-white/[0.02] transition-colors",children:[e.jsx("td",{className:`${b} w-[30%]`,children:e.jsxs("div",{className:"flex items-center gap-1.5 min-w-0",children:[e.jsx("span",{className:"text-[10px] shrink-0",children:f.emoji}),e.jsx("span",{className:`${q} font-medium text-text-primary truncate`,children:m.name})]})}),e.jsx("td",{className:`${b} w-[45%]`,children:e.jsxs("div",{className:n?"space-y-1":"space-y-1.5",children:[e.jsx("div",{className:`${n?"h-1":"h-1.5"} rounded-full overflow-hidden border ${f.bgLight} ${m.remaining===0?"border-black/10 dark:border-white/10":"border-transparent"}`,children:e.jsx("div",{className:`h-full transition-all duration-300 ${f.bg}`,style:{width:`${Math.min(m.remaining,100)}%`}})}),e.jsxs("div",{className:`flex items-center justify-between ${n?"text-[10px]":"text-xs"}`,children:[e.jsxs("span",{className:"text-text-muted",children:[te.toLocaleString()," / ",m.total>0?m.total.toLocaleString():"∞"]}),e.jsxs("span",{className:`font-medium ${f.text}`,children:[m.remaining,"%"]})]})]})}),e.jsx("td",{className:`${b} w-[25%]`,children:I!=="-"||D?n?e.jsx("div",{className:`${v} text-text-primary font-medium truncate`,title:D||"",children:I!=="-"?`in ${I}`:D}):e.jsxs("div",{className:"space-y-0.5",children:[I!=="-"&&e.jsxs("div",{className:`${v} text-text-primary font-medium`,children:["in ",I]}),D&&e.jsx("div",{className:`${J} text-text-muted`,children:D})]}):e.jsx("div",{className:`${v} text-text-muted italic`,children:"N/A"})})]},`${m.name}-${m.index}`)})})})}),p>1&&e.jsxs("div",{className:"rounded-md border border-black/10 bg-black/[0.02] px-2 py-1.5 dark:border-white/10 dark:bg-white/[0.03]",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2 text-[10px] text-text-muted",children:[e.jsxs("span",{children:["Showing ",G,"-",V," of ",h.length]}),e.jsxs("span",{children:["Page ",l," / ",p]})]}),e.jsxs("div",{className:"mt-1.5 flex items-center justify-end gap-1",children:[e.jsx("button",{type:"button",onClick:()=>a(m=>Math.max(1,m-1)),disabled:l===1,className:"flex h-6 items-center rounded-md border border-black/10 px-2 text-[10px] text-text-primary transition-colors hover:bg-black/5 disabled:cursor-not-allowed disabled:opacity-40 dark:border-white/10 dark:hover:bg-white/5",children:"Prev"}),e.jsx("button",{type:"button",onClick:()=>a(m=>Math.min(p,m+1)),disabled:l===p,className:"flex h-6 items-center rounded-md border border-black/10 px-2 text-[10px] text-text-primary transition-colors hover:bg-black/5 disabled:cursor-not-allowed disabled:opacity-40 dark:border-white/10 dark:hover:bg-white/5",children:"Next"})]})]})]})}function X(s){const n=o=>typeof o=="string"&&/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(o);return n(s.email)?s.email:(n(s.name),s.name)}function mt(s,n,o){if(!o)return s;const u=l=>{var x;const a=(((x=n[l.id])==null?void 0:x.quotas)||[]).map(h=>h.resetAt?new Date(h.resetAt).getTime():Number.POSITIVE_INFINITY).filter(h=>Number.isFinite(h));return a.length>0?Math.min(...a):Number.POSITIVE_INFINITY};return[...s].sort((l,a)=>{const x=u(l)-u(a);return x!==0?x:(l.provider||"").localeCompare(a.provider||"")||(X(l)||"").localeCompare(X(a)||"")})}function Pe(s){const n={};return s.forEach(o=>{n[o.id]=!0}),n}function Z(s,n){const o=new Set(n.map(u=>u.id));return Object.fromEntries(Object.entries(s).filter(([u])=>o.has(u)))}function xt(s){if(!s.total)return{start:0,end:0};const n=(s.page-1)*s.pageSize+1,o=Math.min(s.page*s.pageSize,s.total);return{start:n,end:o}}function ht(s,n,o){return s.eligibleConnections?s.providerFilteredConnections?{icon:"filter_alt_off",title:"No Accounts On This Page",description:"Try moving to another page or refreshing the current filters."}:{icon:"filter_alt_off",title:"No Accounts Match Current Filters",description:n==="all"?"Try changing the account status filter to see more quota trackers.":`No ${o==="inactive"?"turned off":o==="active"?"active":"matching"} accounts found for ${n}.`}:{icon:"cloud_off",title:"No Providers Connected",description:"Connect to providers with OAuth to track your API quota limits and usage."}}function pt(s){const{start:n,end:o}=xt(s);return`Showing ${n}-${o} of ${s.total}`}function bt(s,n){return s||{page:1,pageSize:n,total:0,totalPages:1}}function gt(s,n=0){return s||{eligibleConnections:n,providerFilteredConnections:n}}function de(s,n){return s!==n}function ft(s,n){return(s==null?void 0:s.page)||n}function yt(s){return s||[]}async function ue(s,n){return await s(n)}const he="quotaCacheData";function Me(){if(typeof window>"u")return{};try{const s=window.localStorage.getItem(he);return s?JSON.parse(s):{}}catch(s){return console.error("Error reading quota cache:",s),{}}}function Te(s,n){if(!(typeof window>"u"))try{const o=Me();o[s]={...n,cachedAt:new Date().toISOString()},window.localStorage.setItem(he,JSON.stringify(o))}catch(o){console.error("Error writing quota cache:",o)}}const Oe=6e4,vt=5,Ie="quotaAutoRefresh",wt=[{value:"all",label:"All accounts"},{value:"active",label:"Active"},{value:"inactive",label:"Turned off"}],kt=[{value:"default",label:"Default order"},{value:"remaining-asc",label:"Least credits first"},{value:"remaining-desc",label:"Most credits first"},{value:"balance-asc",label:"Saldo Terendah (Lowest Balance)"},{value:"balance-desc",label:"Saldo Tertinggi (Highest Balance)"}],me=20,De=[10,20,50,100],xe=500;function jt(){const[s,n]=c.useState([]),[o,u]=c.useState({}),[l,a]=c.useState({}),[x,h]=c.useState({}),[p,U]=c.useState(!0),[G,V]=c.useState(null),[b,q]=c.useState(!1),[v,J]=c.useState(!1),[pe,m]=c.useState(60),[f,I]=c.useState(!0),[D,ee]=c.useState(null),[te,B]=c.useState(null),[_e,re]=c.useState(!1),[R,se]=c.useState(null),[Re,Le]=c.useState([]),[A,ne]=c.useState("all"),[Fe,be]=c.useState([]),[L,ge]=c.useState("all"),[P,fe]=c.useState("default"),[F,ze]=c.useState(!1),[Nt,St]=c.useState(!1),[Y,ye]=c.useState(!1),[w,C]=c.useState(1),[$,ae]=c.useState(me),[ie,Q]=c.useState(String(me)),[E,ve]=c.useState({page:1,pageSize:me,total:0,totalPages:1}),[k,we]=c.useState({eligibleConnections:0,providerFilteredConnections:0}),T=c.useRef(null),O=c.useRef(null),j=c.useCallback(async(t=w)=>{try{let r="priority";F?r="expiring":P==="remaining-asc"?r="usage-asc":P==="remaining-desc"?r="usage-desc":P==="balance-asc"?r="balance-asc":P==="balance-desc"&&(r="balance-desc");const i=new URLSearchParams({page:String(t),pageSize:String($),accountStatus:L,sort:r});A!=="all"&&i.set("provider",A);const d=await fetch(`/api/providers/client?${i.toString()}`);if(!d.ok)throw new Error("Failed to fetch connections");const N=await d.json(),g=N.connections||[],y=bt(N.pagination,$),S=gt(N.totals,g.length);return n(g),be(yt(N.providerOptions)),ve(y),we(S),C(ft(N.pagination,t)),g}catch(r){return console.error("Error fetching connections:",r),n([]),be([]),ve({page:1,pageSize:$,total:0,totalPages:1}),we({eligibleConnections:0,providerFilteredConnections:0}),[]}},[L,F,w,$,A,P]),M=c.useCallback(async(t,r)=>{a(i=>({...i,[t]:!0})),h(i=>({...i,[t]:null}));try{const i=await fetch(`/api/usage/${t}`);if(!i.ok){const S=(await i.json().catch(()=>({}))).error||i.statusText;if(i.status===404)return;if(i.status===401){const _={quotas:[],message:S};u(H=>({...H,[t]:_})),Te(t,_);return}throw new Error(`HTTP ${i.status}: ${S}`)}const d=await i.json(),g={quotas:ot(r,d),plan:d.plan||null,message:d.message||null,raw:d};u(y=>({...y,[t]:g})),Te(t,g)}catch(i){h(d=>({...d,[t]:i.message||"Failed to fetch quota"}))}finally{a(i=>({...i,[t]:!1}))}},[]),Ue=c.useCallback(async(t,r)=>{await M(t,r),V(new Date)},[M]),Qe=c.useCallback(async t=>{if(confirm("Delete this connection?")){ee(t);try{if((await fetch(`/api/providers/${t}`,{method:"DELETE"})).ok){if(u(i=>{const d={...i};return delete d[t],d}),a(i=>{const d={...i};return delete d[t],d}),h(i=>{const d={...i};return delete d[t],d}),typeof window<"u")try{const i=Me();i[t]&&(delete i[t],window.localStorage.setItem(he,JSON.stringify(i)))}catch(i){console.error("Error deleting cache entry:",i)}await ue(j,w)}}catch(r){console.error("Error deleting connection:",r)}finally{ee(null)}}},[j,w]),He=c.useCallback(async(t,r)=>{B(t);try{(await fetch(`/api/providers/${t}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({isActive:r})})).ok&&(u(d=>({...d})),await ue(j,w))}catch(i){console.error("Error updating connection status:",i)}finally{B(null)}},[j,w]),Ve=c.useCallback(async t=>{if(!(R!=null&&R.id))return;const r=R.id,i=R.provider;try{(await fetch(`/api/providers/${r}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})).ok&&(await j(),re(!1),se(null),tt.includes(i)&&await M(r,i))}catch(d){console.error("Error saving connection:",d)}},[R,j,M]);c.useEffect(()=>{let t=!1;return fetch("/api/proxy-pools?isActive=true",{cache:"no-store"}).then(r=>r.json()).then(r=>{!t&&(r!=null&&r.proxyPools)&&Le(r.proxyPools)}).catch(()=>{}),()=>{t=!0}},[]);const K=c.useCallback(async()=>{if(!v){J(!0),m(60);try{const t=await j(w);a(Pe(t)),h(r=>Z(r,t)),u(r=>Z(r,t)),await Promise.all(t.map(r=>M(r.id,r.provider))),V(new Date)}catch(t){console.error("Error refreshing all providers:",t)}finally{J(!1)}}},[v,j,M,w]);c.useEffect(()=>{if(!b)return;(async()=>{I(!0);const r=await j(w);I(!1),a(Pe(r)),h(i=>Z(i,r)),u(i=>Z(i,r)),await Promise.all(r.map(i=>M(i.id,i.provider))),V(new Date)})()},[j,M,w,b]);const ke="quotaProviderFilter",je="quotaAccountFilter",Ne="quotaSortMode";c.useEffect(()=>{if(typeof window>"u")return;const t=window.localStorage.getItem(Ie);U(t===null?!0:t==="true");const r=window.localStorage.getItem(ke);r&&ne(r);const i=window.localStorage.getItem(je);i&&ge(i);const d=window.localStorage.getItem(Ne);d&&fe(d),q(!0)},[]),c.useEffect(()=>{typeof window>"u"||!b||window.localStorage.setItem(Ie,String(p))},[p,b]),c.useEffect(()=>{typeof window>"u"||!b||window.localStorage.setItem(ke,A)},[A,b]),c.useEffect(()=>{typeof window>"u"||!b||window.localStorage.setItem(je,L)},[L,b]),c.useEffect(()=>{typeof window>"u"||!b||window.localStorage.setItem(Ne,P)},[P,b]),c.useEffect(()=>{if(!b||!p){T.current&&(clearInterval(T.current),T.current=null),O.current&&(clearInterval(O.current),O.current=null);return}return T.current=setInterval(()=>{K()},Oe),O.current=setInterval(()=>{m(t=>t<=1?60:t-1)},1e3),()=>{T.current&&clearInterval(T.current),O.current&&clearInterval(O.current)}},[p,K,b]),c.useEffect(()=>{const t=()=>{document.hidden?(T.current&&(clearInterval(T.current),T.current=null),O.current&&(clearInterval(O.current),O.current=null)):p&&b&&(T.current=setInterval(K,Oe),O.current=setInterval(()=>{m(r=>r<=1?60:r-1)},1e3))};return document.addEventListener("visibilitychange",t),()=>{document.removeEventListener("visibilitychange",t)}},[p,K,b]);const z=c.useMemo(()=>mt(s,o,F),[s,o,F]),Se=t=>{var i;const r=(i=o[t.id])==null?void 0:i.quotas;return r!=null&&r.length?r.some(d=>!d.total||d.total<=0?!1:$e(d.used,d.total)<=vt):!1},Ce=t=>{const r=o[t.id];return r&&r.message==="Account disabled (Credits exhausted)"},oe=c.useCallback(async(t,r)=>{if(!(!t.length||Y)){ye(!0);try{await Promise.all(t.map(i=>fetch(`/api/providers/${i}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({isActive:r})}))),await ue(j,w)}catch(i){console.error("Error bulk toggling connections:",i)}finally{ye(!1)}}},[Y,j,w]),Be=()=>{const t=z.filter(r=>(r.isActive??!0)&&Se(r)).map(r=>r.id);oe(t,!1)},Ye=()=>{const t=z.filter(r=>(r.isActive??!0)&&Ce(r)).map(r=>r.id);oe(t,!1)},Ke=()=>{const t=z.filter(r=>!(r.isActive??!0)&&!Se(r)&&!Ce(r)).map(r=>r.id);oe(t,!0)},{totalCredits:We,providerStats:Ge,exhaustedCount:Ee}=c.useMemo(()=>{var N;let t=0;const r={};let i=0;z.forEach(g=>{const y=o[g.id];if(y&&y.message==="Account disabled (Credits exhausted)"&&(i+=1),!y)return;const S=g.provider;r[S]||(r[S]={accounts:0,credits:0}),r[S].accounts+=1,y.quotas&&y.quotas.forEach(_=>{let H=typeof _.remaining=="number"&&Number.isFinite(_.remaining)?_.remaining:Math.max(0,(_.total||0)-(_.used||0));Number.isFinite(H)&&H>0&&S!=="cloudflare-ai"&&(t+=H,r[S].credits+=H)})});const d=((N=k==null?void 0:k.providerCounts)==null?void 0:N["cloudflare-ai"])||0;if(d>0){const g=(k==null?void 0:k.cloudflareAi)!==void 0?Math.max(0,k.cloudflareAi.total-k.cloudflareAi.used):d*1e4;r["cloudflare-ai"]||(r["cloudflare-ai"]={accounts:d,credits:0}),r["cloudflare-ai"].accounts=d,r["cloudflare-ai"].credits=g,t+=g}return{totalCredits:t,providerStats:r,exhaustedCount:i}},[o,z,k]),Je=k.eligibleConnections>0,Ze=z.length>0,le=ht(k,A,L),Xe=pt(E),qe=!De.includes($);return!f&&!Je?e.jsx(ce,{padding:"lg",children:e.jsxs("div",{className:"text-center py-12",children:[e.jsx("span",{className:"material-symbols-outlined text-[64px] text-text-muted opacity-20",children:"cloud_off"}),e.jsx("h3",{className:"mt-4 text-lg font-semibold text-text-primary",children:"No Providers Connected"}),e.jsx("p",{className:"mt-2 text-sm text-text-muted max-w-md mx-auto",children:"Connect to providers with OAuth to track your API quota limits and usage."})]})}):e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-sm font-medium text-text-primary px-1",children:[e.jsxs("div",{className:"flex items-center gap-1.5 bg-black/5 dark:bg-white/10 px-2.5 py-1 rounded-md",title:"Total active accounts on this page",children:[e.jsx("span",{className:"material-symbols-outlined text-[16px] text-text-muted",children:"group"}),e.jsxs("span",{children:[k.providerFilteredConnections," Accounts"]})]}),e.jsxs("div",{className:"flex items-center gap-1.5 bg-primary/10 px-2.5 py-1 rounded-md",title:"Total credits across these accounts",children:[e.jsx("span",{className:"material-symbols-outlined text-[16px] text-primary",children:"database"}),e.jsxs("span",{className:"text-primary",children:[Math.floor(We)," Credits"]})]}),Ee>0&&e.jsxs("div",{className:"flex items-center gap-1.5 bg-red-500/10 px-2.5 py-1 rounded-md",title:"Total exhausted accounts",children:[e.jsx("span",{className:"material-symbols-outlined text-[16px] text-red-500",children:"warning"}),e.jsxs("span",{className:"text-red-500",children:[Ee," Exhausted"]})]}),e.jsx("div",{className:"flex flex-wrap items-center gap-1 ml-2",children:Object.entries(Ge).map(([t,r])=>e.jsxs("div",{className:"flex items-center gap-1 bg-black/5 dark:bg-white/5 px-2 py-0.5 rounded text-xs text-text-muted border border-black/10 dark:border-white/10",title:`${r.accounts} accounts`,children:[e.jsx("span",{className:"capitalize",children:t}),": ",e.jsx("span",{className:"font-semibold text-text-primary",children:Math.floor(r.credits)})]},t))})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-1 justify-end",children:[e.jsxs("div",{className:"flex flex-wrap gap-1",children:[e.jsxs("button",{type:"button",onClick:()=>{de(A,"all")&&C(1),ne("all")},className:`flex h-8 items-center gap-1.5 rounded-lg px-2.5 text-xs font-medium transition-colors ${A==="all"?"bg-primary/15 text-primary border border-primary/30":"bg-black/5 text-text-muted border border-transparent hover:bg-black/10 dark:bg-white/5 dark:hover:bg-white/10"}`,children:[e.jsx("span",{className:"material-symbols-outlined text-[14px]",children:"apps"}),e.jsx("span",{children:"All"})]}),Fe.map(t=>e.jsxs("button",{type:"button",onClick:()=>{de(A,t)&&C(1),ne(t)},className:`flex h-8 items-center gap-1.5 rounded-lg px-2.5 text-xs font-medium transition-colors ${A===t?"bg-primary/15 text-primary border border-primary/30":"bg-black/5 text-text-muted border border-transparent hover:bg-black/10 dark:bg-white/5 dark:hover:bg-white/10"}`,children:[e.jsx(Ae,{src:t==="codebuddy"||t==="cb"?"/providers/codebuddy.svg":`/providers/${t}.png`,alt:t,size:16,className:"size-4 rounded object-contain",fallbackText:t.slice(0,2).toUpperCase()}),e.jsx("span",{className:"capitalize",children:t})]},t))]}),e.jsx("select",{value:L,onChange:t=>{const r=t.target.value;de(L,r)&&C(1),ge(r)},className:"h-8 rounded-lg border border-black/10 bg-black/[0.02] px-2 text-xs text-text-primary outline-none transition-colors hover:bg-black/5 dark:border-white/10 dark:bg-white/[0.03] dark:hover:bg-white/10","aria-label":"Filter accounts by status",children:wt.map(t=>e.jsx("option",{value:t.value,children:t.label},t.value))}),e.jsx("select",{value:P,onChange:t=>fe(t.target.value),className:"h-8 rounded-lg border border-black/10 bg-black/[0.02] px-2 text-xs text-text-primary outline-none transition-colors hover:bg-black/5 dark:border-white/10 dark:bg-white/[0.03] dark:hover:bg-white/10","aria-label":"Sort quotas by remaining",children:kt.map(t=>e.jsx("option",{value:t.value,children:t.label},t.value))}),e.jsxs("button",{type:"button",onClick:()=>ze(t=>!t),"aria-pressed":F,className:`flex h-8 shrink-0 items-center gap-1 rounded-lg border px-2 text-xs transition-colors ${F?"border-amber-500/40 bg-amber-500/10 text-amber-500":"border-black/10 text-text-primary hover:bg-black/5 dark:border-white/10 dark:hover:bg-white/5"}`,title:"Sort accounts by earliest quota reset time",children:[e.jsx("span",{className:"material-symbols-outlined text-[14px]",children:"hourglass_top"}),e.jsx("span",{className:"hidden sm:inline",children:"Expiring first"})]}),e.jsxs("button",{type:"button",onClick:Be,disabled:Y,className:"flex h-8 shrink-0 items-center gap-1 rounded-lg border border-red-500/30 px-2 text-xs text-red-500 transition-colors hover:bg-red-500/10 disabled:opacity-50",title:"Disable connections with depleted quota on the current page",children:[e.jsx("span",{className:"material-symbols-outlined text-[14px]",children:"block"}),e.jsx("span",{className:"hidden sm:inline",children:"Turn off Empty"})]}),e.jsxs("button",{type:"button",onClick:Ye,disabled:Y,className:"flex h-8 shrink-0 items-center gap-1 rounded-lg border border-red-500/30 px-2 text-xs text-red-500 transition-colors hover:bg-red-500/10 disabled:opacity-50",title:"Disable connections that are exhausted",children:[e.jsx("span",{className:"material-symbols-outlined text-[14px]",children:"block"}),e.jsx("span",{className:"hidden sm:inline",children:"Disable Exhausted"})]}),e.jsxs("button",{type:"button",onClick:Ke,disabled:Y,className:"flex h-8 shrink-0 items-center gap-1 rounded-lg border border-emerald-500/30 px-2 text-xs text-emerald-500 transition-colors hover:bg-emerald-500/10 disabled:opacity-50",title:"Enable connections that still have quota on the current page",children:[e.jsx("span",{className:"material-symbols-outlined text-[14px]",children:"check_circle"}),e.jsx("span",{className:"hidden sm:inline",children:"Turn on Available"})]}),e.jsxs("button",{onClick:()=>U(t=>!t),className:"flex h-8 shrink-0 items-center gap-1 rounded-lg border border-black/10 px-2 text-xs transition-colors hover:bg-black/5 dark:border-white/10 dark:hover:bg-white/5",title:p?"Disable auto-refresh":"Enable auto-refresh",children:[e.jsx("span",{className:`material-symbols-outlined text-[14px] ${p?"text-primary":"text-text-muted"}`,children:p?"toggle_on":"toggle_off"}),e.jsx("span",{className:"hidden text-text-primary sm:inline",children:"Auto-refresh"}),p&&e.jsxs("span",{className:"text-[10px] text-text-muted tabular-nums",children:["(",pe,"s)"]})]}),e.jsx("button",{type:"button",onClick:K,disabled:v,className:"flex h-8 shrink-0 items-center gap-1 rounded-lg border border-black/10 px-2 text-xs text-text-primary transition-colors hover:bg-black/5 dark:border-white/10 dark:hover:bg-white/5 disabled:opacity-50",title:"Refresh all",children:e.jsx("span",{className:`material-symbols-outlined text-[14px] ${v?"animate-spin":""}`,children:"refresh"})})]})]}),(F||P!=="default")&&e.jsx("div",{className:"rounded-xl border border-amber-500/20 bg-amber-500/10 px-3 py-2 text-xs text-amber-700 dark:text-amber-300 mb-3",children:"Sorting currently reorders accounts inside the current page. Cross-page ordering still follows backend pagination. Try increasing the page size to sort across more accounts."}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:!f&&!Ze?e.jsx("div",{className:"col-span-1 md:col-span-2",children:e.jsx(ce,{padding:"lg",children:e.jsxs("div",{className:"text-center py-12",children:[e.jsx("span",{className:"material-symbols-outlined text-[64px] text-text-muted opacity-20",children:le.icon}),e.jsx("h3",{className:"mt-4 text-lg font-semibold text-text-primary",children:le.title}),e.jsx("p",{className:"mt-2 text-sm text-text-muted max-w-md mx-auto",children:le.description})]})})}):z.map(t=>{var y;const r=o[t.id],i=l[t.id],d=x[t.id],N=t.isActive===!1,g=D===t.id||te===t.id;return e.jsxs(ce,{padding:"none",className:`min-w-0 ${N?"opacity-60":""}`,children:[e.jsx("div",{className:"px-3 py-2 border-b border-black/10 dark:border-white/10",children:e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx("div",{className:"w-8 h-8 shrink-0 rounded-md flex items-center justify-center overflow-hidden",children:e.jsx(Ae,{src:t.provider==="codebuddy"||t.provider==="cb"?"/providers/codebuddy.svg":`/providers/${t.provider}.png`,alt:t.provider,size:32,className:"object-contain",fallbackText:((y=t.provider)==null?void 0:y.slice(0,2).toUpperCase())||"PR"})}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("h3",{className:"text-sm font-semibold text-text-primary capitalize truncate",children:t.provider}),X(t)?e.jsx("p",{className:"text-xs text-text-muted truncate",children:X(t)}):null]})]}),e.jsxs("div",{className:"flex items-center gap-1 shrink-0",children:[e.jsx("button",{type:"button",onClick:()=>Ue(t.id,t.provider),disabled:i||g,"aria-label":"Refresh quota",className:"p-1.5 rounded-lg hover:bg-black/5 dark:hover:bg-white/5 transition-colors disabled:opacity-50",title:"Refresh quota",children:e.jsx("span",{className:`material-symbols-outlined text-[18px] text-text-muted ${i?"animate-spin":""}`,children:"refresh"})}),e.jsx("button",{type:"button",onClick:()=>{se(t),re(!0)},disabled:g,"aria-label":"Edit connection",className:"p-1.5 rounded-lg hover:bg-black/5 dark:hover:bg-white/5 text-text-muted hover:text-primary transition-colors disabled:opacity-50",title:"Edit connection",children:e.jsx("span",{className:"material-symbols-outlined text-[18px]",children:"edit"})}),e.jsx("button",{type:"button",onClick:()=>Qe(t.id),disabled:g,"aria-label":"Delete connection",className:"p-1.5 rounded-lg hover:bg-red-500/10 text-red-500 transition-colors disabled:opacity-50",title:"Delete connection",children:e.jsx("span",{className:`material-symbols-outlined text-[18px] ${D===t.id?"animate-pulse":""}`,children:"delete"})}),e.jsx("div",{className:"inline-flex items-center pl-0.5",title:t.isActive??!0?"Disable connection":"Enable connection",children:e.jsx(st,{size:"sm",checked:t.isActive??!0,disabled:g,onChange:S=>He(t.id,S)})})]})]})}),e.jsx("div",{className:"px-2 py-1.5",children:i?e.jsx("div",{className:"text-center py-5 text-text-muted",children:e.jsx("span",{className:"material-symbols-outlined text-[28px] animate-spin",children:"progress_activity"})}):d?e.jsxs("div",{className:"text-center py-5",children:[e.jsx("span",{className:"material-symbols-outlined text-[28px] text-red-500",children:"error"}),e.jsx("p",{className:"mt-1.5 text-xs text-text-muted",children:d})]}):r!=null&&r.message?e.jsx("div",{className:"text-center py-5",children:e.jsx("p",{className:"text-xs text-text-muted",children:r.message})}):e.jsx(ut,{quotas:r==null?void 0:r.quotas,compact:!0,sortMode:"default",showSortLabel:t.provider==="codex"&&P!=="default"})})]},t.id)})}),e.jsx("div",{className:"rounded-xl border border-black/10 bg-black/[0.02] px-3 py-2 dark:border-white/10 dark:bg-white/[0.03]",children:e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[e.jsx("span",{className:"text-xs text-text-muted",children:Xe}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("select",{value:qe?"custom":String($),onChange:t=>{const r=t.target.value;if(r==="custom")return;const i=Number.parseInt(r,10);Number.isFinite(i)&&(C(1),ae(i),Q(String(i)))},className:"h-8 rounded-lg border border-black/10 bg-black/[0.02] px-2 text-xs text-text-primary outline-none transition-colors hover:bg-black/5 dark:border-white/10 dark:bg-white/[0.03] dark:hover:bg-white/10","aria-label":"Accounts per page",children:[De.map(t=>e.jsxs("option",{value:String(t),children:[t," / page"]},t)),e.jsx("option",{value:"500",children:"500 / page"}),e.jsx("option",{value:"1000",children:"1000 / page"}),e.jsx("option",{value:"custom",children:"Custom"})]}),e.jsx("input",{type:"number",min:"1",max:String(xe),inputMode:"numeric",value:ie,onChange:t=>Q(t.target.value),onBlur:()=>{const t=Number.parseInt(ie,10);if(!Number.isFinite(t)){Q(String($));return}const r=Math.min(xe,Math.max(1,t));C(1),ae(r),Q(String(r))},onKeyDown:t=>{if(t.key!=="Enter")return;const r=Number.parseInt(ie,10);if(!Number.isFinite(r)){Q(String($));return}const i=Math.min(xe,Math.max(1,r));C(1),ae(i),Q(String(i))},className:"h-8 w-20 rounded-lg border border-black/10 bg-black/[0.02] px-2 text-xs text-text-primary outline-none transition-colors hover:bg-black/5 dark:border-white/10 dark:bg-white/[0.03] dark:hover:bg-white/10","aria-label":"Custom accounts per page",placeholder:"Custom"}),e.jsxs("span",{className:"text-xs text-text-muted",children:["Page ",E.page," / ",E.totalPages]})]}),e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("button",{suppressHydrationWarning:!0,type:"button",onClick:()=>C(1),disabled:E.page<=1||f||v,className:"flex h-8 items-center rounded-lg border border-black/10 px-3 text-xs text-text-primary transition-colors hover:bg-black/5 disabled:cursor-not-allowed disabled:opacity-40 dark:border-white/10 dark:hover:bg-white/5",children:"First Page"}),e.jsx("button",{suppressHydrationWarning:!0,type:"button",onClick:()=>C(t=>Math.max(1,t-1)),disabled:E.page<=1||f||v,className:"flex h-8 w-8 items-center justify-center rounded-lg border border-black/10 text-text-primary transition-colors hover:bg-black/5 disabled:cursor-not-allowed disabled:opacity-40 dark:border-white/10 dark:hover:bg-white/5","aria-label":"Previous accounts page",children:e.jsx("span",{className:"material-symbols-outlined text-[16px]",children:"chevron_left"})}),e.jsx("button",{suppressHydrationWarning:!0,type:"button",onClick:()=>C(t=>Math.min(E.totalPages,t+1)),disabled:E.page>=E.totalPages||f||v,className:"flex h-8 w-8 items-center justify-center rounded-lg border border-black/10 text-text-primary transition-colors hover:bg-black/5 disabled:cursor-not-allowed disabled:opacity-40 dark:border-white/10 dark:hover:bg-white/5","aria-label":"Next accounts page",children:e.jsx("span",{className:"material-symbols-outlined text-[16px]",children:"chevron_right"})}),e.jsx("button",{suppressHydrationWarning:!0,type:"button",onClick:()=>C(E.totalPages),disabled:E.page>=E.totalPages||f||v,className:"flex h-8 items-center rounded-lg border border-black/10 px-3 text-xs text-text-primary transition-colors hover:bg-black/5 disabled:cursor-not-allowed disabled:opacity-40 dark:border-white/10 dark:hover:bg-white/5",children:"Last Page"})]})]})}),e.jsx(nt,{isOpen:_e,connection:R,proxyPools:Re,onSave:Ve,onClose:()=>{re(!1),se(null)}})]})}function Ot(){return e.jsx(c.Suspense,{fallback:e.jsx(rt,{}),children:e.jsx(jt,{})})}export{Ot as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as e}from"./index.hce0krcP.js";import{b as n}from"./router.Cjj1--8t.js";import"./zustand.akaTi5uX.js";function x(){const[s,a]=n.useState(null),[c,r]=n.useState(!1),i=async m=>{const o=m.target.files[0];if(!o)return;r(!0);const l=new FormData;l.append("file",o);try{const t=await fetch("/api/ocr",{method:"POST",body:l});a(await t.json())}catch(t){a({error:t.message})}r(!1)};return e.jsxs("div",{className:"space-y-6 p-6",children:[e.jsx("h1",{className:"text-2xl font-bold",children:"OCR"}),e.jsx("p",{className:"text-text-muted",children:"Extract text from images using Mistral OCR API"}),e.jsx("input",{type:"file",accept:"image/*,.pdf",onChange:i,className:"block"}),c&&e.jsx("p",{children:"Processing..."}),s&&e.jsx("pre",{className:"p-4 bg-black/5 rounded-lg text-sm overflow-auto max-h-96",children:JSON.stringify(s,null,2)})]})}export{x as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as o}from"./index.hce0krcP.js";import{b as r}from"./router.Cjj1--8t.js";import{g as a}from"./machine.CagOtseJ.js";import{A as i}from"./EndpointPageClient.BoapE5zm.js";import"./zustand.akaTi5uX.js";import"./NoAuthProxyCard.Ep103MXh.js";import"./Loading.dETQxP6N.js";function d(){const[t,e]=r.useState("");return r.useEffect(()=>{a().then(e)},[]),t?o.jsx(i,{machineId:t}):null}export{d as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as e,P as i,u as d}from"./index.hce0krcP.js";import{b as l,d as n}from"./router.Cjj1--8t.js";import"./zustand.akaTi5uX.js";function c(){const[t,r]=l.useState(!1),s=n();return e.jsxs("nav",{className:"fixed top-0 z-50 w-full bg-[#181411]/80 backdrop-blur-md border-b border-[#3a2f27]",children:[e.jsxs("div",{className:"max-w-7xl mx-auto px-6 h-16 flex items-center justify-between",children:[e.jsxs("button",{type:"button",className:"flex items-center gap-3 cursor-pointer bg-transparent border-none p-0",onClick:()=>s("/"),"aria-label":"Navigate to home",children:[e.jsx("img",{src:"/logo_fsrouter.png",alt:"FSRouter v2",className:"size-8 rounded object-cover"}),e.jsx("h2",{className:"text-white text-xl font-bold tracking-tight",children:"FSRouter"})]}),e.jsxs("div",{className:"hidden md:flex items-center gap-8",children:[e.jsx("a",{className:"text-gray-300 hover:text-white text-sm font-medium transition-colors",href:"#features",children:"Features"}),e.jsx("a",{className:"text-gray-300 hover:text-white text-sm font-medium transition-colors",href:"#how-it-works",children:"How it Works"}),e.jsx("a",{className:"text-gray-300 hover:text-white text-sm font-medium transition-colors",href:"https://github.com/nexusrouters/fsrouter#readme",target:"_blank",rel:"noopener noreferrer",children:"Docs"}),e.jsxs("a",{className:"text-gray-300 hover:text-white text-sm font-medium transition-colors flex items-center gap-1",href:"https://github.com/nexusrouters/fsrouter",target:"_blank",rel:"noopener noreferrer",children:["GitHub ",e.jsx("span",{className:"material-symbols-outlined text-[14px]",children:"open_in_new"})]})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("button",{onClick:()=>s("/dashboard"),className:"hidden sm:flex h-9 items-center justify-center rounded-lg px-4 bg-[#f97815] hover:bg-[#e0650a] transition-all text-[#181411] text-sm font-bold shadow-[0_0_15px_rgba(249,120,21,0.4)] hover:shadow-[0_0_20px_rgba(249,120,21,0.6)]",children:"Get Started"}),e.jsx("button",{className:"md:hidden text-white",onClick:()=>r(!t),children:e.jsx("span",{className:"material-symbols-outlined",children:t?"close":"menu"})})]})]}),t&&e.jsx("div",{className:"md:hidden border-t border-[#3a2f27] bg-[#181411]/95 backdrop-blur-md",children:e.jsxs("div",{className:"flex flex-col gap-4 p-6",children:[e.jsx("a",{className:"text-gray-300 hover:text-white text-sm font-medium transition-colors",href:"#features",onClick:()=>r(!1),children:"Features"}),e.jsx("a",{className:"text-gray-300 hover:text-white text-sm font-medium transition-colors",href:"#how-it-works",onClick:()=>r(!1),children:"How it Works"}),e.jsx("a",{className:"text-gray-300 hover:text-white text-sm font-medium transition-colors",href:"https://github.com/nexusrouters/fsrouter#readme",target:"_blank",rel:"noopener noreferrer",children:"Docs"}),e.jsx("a",{className:"text-gray-300 hover:text-white text-sm font-medium transition-colors",href:"https://github.com/nexusrouters/fsrouter",target:"_blank",rel:"noopener noreferrer",children:"GitHub"}),e.jsx("button",{onClick:()=>s("/dashboard"),className:"h-9 rounded-lg bg-[#f97815] hover:bg-[#e0650a] text-[#181411] text-sm font-bold",children:"Get Started"})]})})]})}function x(){return e.jsxs("section",{className:"relative pt-32 pb-20 px-6 min-h-[90vh] flex flex-col items-center justify-center overflow-hidden",children:[e.jsx("div",{className:"absolute top-0 left-1/2 -translate-x-1/2 w-[1000px] h-[500px] bg-[#f97815]/10 rounded-full blur-[120px] pointer-events-none"}),e.jsxs("div",{className:"relative z-10 max-w-4xl w-full text-center flex flex-col items-center gap-8",children:[e.jsxs("div",{className:"inline-flex items-center gap-2 rounded-full border border-[#3a2f27] bg-[#23180f]/50 px-3 py-1 text-xs font-medium text-[#f97815]",children:[e.jsx("span",{className:"flex h-2 w-2 rounded-full bg-[#f97815] animate-pulse"}),"v1.0 is now live"]}),e.jsxs("h1",{className:"text-5xl md:text-7xl font-black leading-[1.1] tracking-tight",children:["One Endpoint for ",e.jsx("br",{}),e.jsx("span",{className:"text-[#f97815]",children:"All AI Providers"})]}),e.jsx("p",{className:"text-lg md:text-xl text-gray-400 max-w-2xl mx-auto font-light",children:"AI endpoint proxy with web dashboard - A JavaScript port of CLIProxyAPI. Works seamlessly with Claude Code, OpenAI Codex, Cline, RooCode, and other CLI tools."}),e.jsxs("div",{className:"flex flex-wrap items-center justify-center gap-4 w-full",children:[e.jsxs("button",{className:"h-12 px-8 rounded-lg bg-[#f97815] hover:bg-[#e0650a] text-[#181411] text-base font-bold transition-all shadow-[0_0_15px_rgba(249,120,21,0.4)] flex items-center gap-2",children:[e.jsx("span",{className:"material-symbols-outlined",children:"rocket_launch"}),"Get Started"]}),e.jsxs("a",{href:"https://github.com/nexusrouters/fsrouter",target:"_blank",rel:"noopener noreferrer",className:"h-12 px-8 rounded-lg border border-[#3a2f27] bg-[#23180f] hover:bg-[#3a2f27] text-white text-base font-bold transition-all flex items-center gap-2",children:[e.jsx("span",{className:"material-symbols-outlined",children:"code"}),"View on GitHub"]})]})]})]})}const m=[{id:"claude",name:"Claude Code",image:"/providers/claude.png"},{id:"codex",name:"OpenAI Codex",image:"/providers/codex.png"},{id:"cline",name:"Cline",image:"/providers/cline.png"},{id:"cursor",name:"Cursor",image:"/providers/cursor.png"}],o=[{id:"openai",name:"OpenAI",color:"bg-emerald-500",textColor:"text-white"},{id:"anthropic",name:"Anthropic",color:"bg-orange-400",textColor:"text-white"},{id:"gemini",name:"Gemini",color:"bg-blue-500",textColor:"text-white"},{id:"github",name:"GitHub Copilot",color:"bg-gray-700",textColor:"text-white"}];function h(){const[t,r]=l.useState(0);return l.useEffect(()=>{const s=setInterval(()=>{r(a=>(a+1)%o.length)},2e3);return()=>clearInterval(s)},[]),e.jsxs("div",{className:"mt-16 w-full max-w-4xl relative h-[360px] hidden md:flex items-center justify-center animate-[float_6s_ease-in-out_infinite]",children:[e.jsxs("div",{className:"relative z-20 w-32 h-32 rounded-full bg-[#23180f] border-2 border-[#f97815] shadow-[0_0_40px_rgba(249,120,21,0.3)] flex flex-col items-center justify-center gap-1 group cursor-pointer hover:scale-105 transition-transform duration-500",children:[e.jsx("span",{className:"material-symbols-outlined text-4xl text-[#f97815]",children:"hub"}),e.jsx("span",{className:"text-xs font-bold text-white tracking-widest uppercase",children:"FSRouter"}),e.jsx("div",{className:"absolute inset-0 rounded-full border border-[#f97815]/30 animate-ping opacity-20"})]}),e.jsx("div",{className:"absolute left-0 top-1/2 -translate-y-1/2 flex flex-col gap-7",children:m.map(s=>e.jsx("div",{className:"flex items-center gap-3 opacity-70 hover:opacity-100 transition-opacity group",children:e.jsx("div",{className:"w-16 h-16 rounded-2xl bg-[#23180f] border border-[#3a2f27] flex items-center justify-center overflow-hidden p-2 hover:border-[#f97815]/50 transition-all hover:scale-105",children:e.jsx(i,{src:s.image,alt:s.name,size:48,className:"object-contain rounded-xl max-w-[48px] max-h-[48px]",fallbackText:s.name.slice(0,2).toUpperCase()})})},s.id))}),e.jsxs("svg",{className:"absolute inset-0 w-full h-full z-10 pointer-events-none stroke-yellow-700",xmlns:"http://www.w3.org/2000/svg",children:[e.jsx("path",{className:"animate-[dash_2s_linear_infinite]",d:"M 60 50 C 250 70, 250 180, 360 180",fill:"none",strokeDasharray:"5,5",strokeWidth:"2"}),e.jsx("path",{className:"animate-[dash_2s_linear_infinite]",d:"M 60 140 C 250 140, 250 180, 360 180",fill:"none",strokeDasharray:"5,5",strokeWidth:"2"}),e.jsx("path",{className:"animate-[dash_2s_linear_infinite]",d:"M 60 210 C 250 210, 250 180, 360 180",fill:"none",strokeDasharray:"5,5",strokeWidth:"2"}),e.jsx("path",{className:"animate-[dash_2s_linear_infinite]",d:"M 60 300 C 250 280, 250 180, 360 180",fill:"none",strokeDasharray:"5,5",strokeWidth:"2"})]}),e.jsxs("svg",{className:"absolute inset-0 w-full h-full z-10 pointer-events-none",xmlns:"http://www.w3.org/2000/svg",children:[e.jsx("path",{d:"M 440 180 C 550 180, 550 50, 740 50",fill:"none",stroke:t===0?"#f97815":"rgb(75, 85, 99)",strokeWidth:t===0?"3":"2",className:t===0?"animate-pulse":""}),e.jsx("path",{d:"M 440 180 C 550 180, 550 130, 740 130",fill:"none",stroke:t===1?"#f97815":"rgb(75, 85, 99)",strokeWidth:t===1?"3":"2",className:t===1?"animate-pulse":""}),e.jsx("path",{d:"M 440 180 C 550 180, 550 230, 740 230",fill:"none",stroke:t===2?"#f97815":"rgb(75, 85, 99)",strokeWidth:t===2?"3":"2",className:t===2?"animate-pulse":""}),e.jsx("path",{d:"M 440 180 C 550 180, 550 310, 740 310",fill:"none",stroke:t===3?"#f97815":"rgb(75, 85, 99)",strokeWidth:t===3?"3":"2",className:t===3?"animate-pulse":""})]}),e.jsx("div",{className:"absolute right-0 top-0 bottom-0 flex flex-col justify-between py-6",children:o.map((s,a)=>e.jsx("div",{className:`px-4 py-2 rounded-lg ${s.color} ${s.textColor} flex items-center justify-center font-bold text-xs shadow-lg hover:scale-110 transition-all cursor-help min-w-[140px] ${t===a?"ring-4 ring-[#f97815]/50 scale-110":""}`,title:s.name,children:s.name},s.id))}),e.jsx("div",{className:"md:hidden mt-8 w-full p-4 rounded-lg bg-[#23180f] border border-[#3a2f27]",children:e.jsx("p",{className:"text-sm text-center text-gray-400",children:"Interactive diagram visible on desktop"})})]})}function u(){return e.jsx("section",{className:"py-24 border-y border-[#3a2f27] bg-[#23180f]/30",id:"how-it-works",children:e.jsxs("div",{className:"max-w-7xl mx-auto px-6",children:[e.jsxs("div",{className:"mb-16",children:[e.jsx("h2",{className:"text-3xl md:text-4xl font-bold mb-4",children:"How FSRouter Works"}),e.jsx("p",{className:"text-gray-400 max-w-xl text-lg",children:"Data flows seamlessly from your application through our intelligent routing layer to the best provider for the job."})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-8 relative",children:[e.jsx("div",{className:"hidden md:block absolute top-12 left-[16%] right-[16%] h-[2px] bg-linear-to-r from-gray-700 via-[#f97815] to-gray-700 -z-10"}),e.jsxs("div",{className:"flex flex-col gap-6 relative group",children:[e.jsx("div",{className:"w-24 h-24 rounded-2xl bg-[#181411] border border-[#3a2f27] flex items-center justify-center shadow-xl group-hover:border-gray-500 transition-colors z-10 mx-auto md:mx-0",children:e.jsx("span",{className:"material-symbols-outlined text-4xl text-gray-300",children:"terminal"})}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-bold mb-2",children:"1. CLI & SDKs"}),e.jsx("p",{className:"text-sm text-gray-400",children:"Your requests start from your favorite tools or our unified SDK. Just change the base URL."})]})]}),e.jsxs("div",{className:"flex flex-col gap-6 relative group md:items-center md:text-center",children:[e.jsx("div",{className:"w-24 h-24 rounded-2xl bg-[#181411] border-2 border-[#f97815] flex items-center justify-center shadow-[0_0_30px_rgba(249,120,21,0.2)] z-10 mx-auto",children:e.jsx("span",{className:"material-symbols-outlined text-4xl text-[#f97815] animate-pulse",children:"hub"})}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-bold mb-2 text-[#f97815]",children:"2. FSRouter Hub"}),e.jsx("p",{className:"text-sm text-gray-400",children:"Our engine analyzes the prompt, checks provider health, and routes for lowest latency or cost."})]})]}),e.jsxs("div",{className:"flex flex-col gap-6 relative group md:items-end md:text-right",children:[e.jsx("div",{className:"w-24 h-24 rounded-2xl bg-[#181411] border border-[#3a2f27] flex items-center justify-center shadow-xl group-hover:border-gray-500 transition-colors z-10 mx-auto md:mx-0",children:e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsx("div",{className:"w-6 h-6 rounded bg-white/10"}),e.jsx("div",{className:"w-6 h-6 rounded bg-white/10"}),e.jsx("div",{className:"w-6 h-6 rounded bg-white/10"}),e.jsx("div",{className:"w-6 h-6 rounded bg-white/10"})]})}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-bold mb-2",children:"3. AI Providers"}),e.jsx("p",{className:"text-sm text-gray-400",children:"The request is fulfilled by OpenAI, Anthropic, Gemini, or others instantly."})]})]})]})]})})}const f=[{icon:"link",title:"Unified Endpoint",desc:"Access all providers via a single standard API URL.",colors:{border:"hover:border-blue-500/50",bg:"hover:bg-blue-500/5",iconBg:"bg-blue-500/10",iconText:"text-blue-500",titleHover:"group-hover:text-blue-400"}},{icon:"bolt",title:"Easy Setup",desc:"Get up and running in minutes with npx command.",colors:{border:"hover:border-orange-500/50",bg:"hover:bg-orange-500/5",iconBg:"bg-orange-500/10",iconText:"text-orange-500",titleHover:"group-hover:text-orange-400"}},{icon:"shield_with_heart",title:"Model Fallback",desc:"Automatically switch providers on failure or high latency.",colors:{border:"hover:border-rose-500/50",bg:"hover:bg-rose-500/5",iconBg:"bg-rose-500/10",iconText:"text-rose-500",titleHover:"group-hover:text-rose-400"}},{icon:"monitoring",title:"Usage Tracking",desc:"Detailed analytics and cost monitoring across all models.",colors:{border:"hover:border-purple-500/50",bg:"hover:bg-purple-500/5",iconBg:"bg-purple-500/10",iconText:"text-purple-500",titleHover:"group-hover:text-purple-400"}},{icon:"key",title:"OAuth & API Keys",desc:"Securely manage credentials in one vault.",colors:{border:"hover:border-amber-500/50",bg:"hover:bg-amber-500/5",iconBg:"bg-amber-500/10",iconText:"text-amber-500",titleHover:"group-hover:text-amber-400"}},{icon:"cloud_sync",title:"Cloud Sync",desc:"Sync your configurations across devices instantly.",colors:{border:"hover:border-sky-500/50",bg:"hover:bg-sky-500/5",iconBg:"bg-sky-500/10",iconText:"text-sky-500",titleHover:"group-hover:text-sky-400"}},{icon:"terminal",title:"CLI Support",desc:"Works with Claude Code, Codex, Cline, Cursor, and more.",colors:{border:"hover:border-emerald-500/50",bg:"hover:bg-emerald-500/5",iconBg:"bg-emerald-500/10",iconText:"text-emerald-500",titleHover:"group-hover:text-emerald-400"}},{icon:"dashboard",title:"Dashboard",desc:"Visual dashboard for real-time traffic analysis.",colors:{border:"hover:border-fuchsia-500/50",bg:"hover:bg-fuchsia-500/5",iconBg:"bg-fuchsia-500/10",iconText:"text-fuchsia-500",titleHover:"group-hover:text-fuchsia-400"}}];function g(){return e.jsx("section",{className:"py-24 px-6",id:"features",children:e.jsxs("div",{className:"max-w-7xl mx-auto",children:[e.jsxs("div",{className:"mb-16",children:[e.jsx("h2",{className:"text-3xl md:text-4xl font-bold mb-4",children:"Powerful Features"}),e.jsx("p",{className:"text-gray-400 max-w-xl text-lg",children:"Everything you need to manage your AI infrastructure in one place, built for scale."})]}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4",children:f.map(t=>e.jsxs("div",{className:`p-6 rounded-xl bg-[#23180f] border border-[#3a2f27] ${t.colors.border} ${t.colors.bg} transition-all duration-300 group`,children:[e.jsx("div",{className:`w-10 h-10 rounded-lg ${t.colors.iconBg} flex items-center justify-center mb-4 ${t.colors.iconText} group-hover:scale-110 transition-transform duration-300`,children:e.jsx("span",{className:"material-symbols-outlined",children:t.icon})}),e.jsx("h3",{className:`text-lg font-bold mb-2 ${t.colors.titleHover} transition-colors`,children:t.title}),e.jsx("p",{className:"text-sm text-gray-400 leading-relaxed",children:t.desc})]},t.title))})]})})}function b(){const{copied:t,copy:r}=d(),s=a=>{r(a,"landing")};return e.jsx("section",{className:"py-24 px-6 bg-[#120f0d]",children:e.jsx("div",{className:"max-w-7xl mx-auto",children:e.jsxs("div",{className:"flex flex-col lg:flex-row gap-16 items-start",children:[e.jsxs("div",{className:"flex-1",children:[e.jsx("h2",{className:"text-3xl md:text-4xl font-bold mb-6",children:"Get Started in 30 Seconds"}),e.jsx("p",{className:"text-gray-400 text-lg mb-8",children:"Install FSRouter, configure your providers via web dashboard, and start routing AI requests."}),e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsxs("div",{className:"flex gap-4",children:[e.jsx("div",{className:"flex-none w-8 h-8 rounded-full bg-[#f97815]/20 text-[#f97815] flex items-center justify-center font-bold",children:"1"}),e.jsxs("div",{children:[e.jsx("h4",{className:"font-bold text-lg",children:"Install FSRouter"}),e.jsx("p",{className:"text-sm text-gray-500 mt-1",children:"Run npx command to start the server instantly"})]})]}),e.jsxs("div",{className:"flex gap-4",children:[e.jsx("div",{className:"flex-none w-8 h-8 rounded-full bg-[#f97815]/20 text-[#f97815] flex items-center justify-center font-bold",children:"2"}),e.jsxs("div",{children:[e.jsx("h4",{className:"font-bold text-lg",children:"Open Dashboard"}),e.jsx("p",{className:"text-sm text-gray-500 mt-1",children:"Configure providers and API keys via web interface"})]})]}),e.jsxs("div",{className:"flex gap-4",children:[e.jsx("div",{className:"flex-none w-8 h-8 rounded-full bg-[#f97815]/20 text-[#f97815] flex items-center justify-center font-bold",children:"3"}),e.jsxs("div",{children:[e.jsx("h4",{className:"font-bold text-lg",children:"Route Requests"}),e.jsx("p",{className:"text-sm text-gray-500 mt-1",children:"Point your CLI tools to http://localhost:20128"})]})]})]})]}),e.jsx("div",{className:"flex-1 w-full",children:e.jsxs("div",{className:"rounded-xl overflow-hidden bg-[#1e1e1e] border border-[#3a2f27] shadow-2xl",children:[e.jsxs("div",{className:"flex items-center gap-2 px-4 py-3 bg-[#252526] border-b border-gray-700",children:[e.jsx("div",{className:"w-3 h-3 rounded-full bg-red-500"}),e.jsx("div",{className:"w-3 h-3 rounded-full bg-yellow-500"}),e.jsx("div",{className:"w-3 h-3 rounded-full bg-green-500"}),e.jsx("div",{className:"ml-2 text-xs text-gray-500 font-mono",children:"terminal"})]}),e.jsxs("div",{className:"p-6 font-mono text-sm leading-relaxed overflow-x-auto",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-4 group cursor-pointer",onClick:()=>s("npx fsrouter"),children:[e.jsx("span",{className:"text-green-400",children:"$"}),e.jsx("span",{className:"text-white",children:"npx fsrouter"}),e.jsx("span",{className:"ml-auto text-gray-500 text-xs opacity-0 group-hover:opacity-100",children:t==="landing"?"✓ Copied":"Copy"})]}),e.jsxs("div",{className:"text-gray-400 mb-6",children:[e.jsx("span",{className:"text-[#f97815]",children:">"})," Starting FSRouter...",e.jsx("br",{}),e.jsx("span",{className:"text-[#f97815]",children:">"})," Server running on ",e.jsx("span",{className:"text-blue-400",children:"http://localhost:20128"}),e.jsx("br",{}),e.jsx("span",{className:"text-[#f97815]",children:">"})," Dashboard: ",e.jsx("span",{className:"text-blue-400",children:"http://localhost:20128/dashboard"}),e.jsx("br",{}),e.jsx("span",{className:"text-green-400",children:">"})," Ready to route! ✓"]}),e.jsx("div",{className:"text-xs text-gray-500 mb-2 border-t border-gray-700 pt-4",children:"📝 Configure providers in dashboard or use environment variables"}),e.jsxs("div",{className:"text-gray-400 text-xs",children:[e.jsx("span",{className:"text-purple-400",children:"Data Location:"}),e.jsx("br",{}),e.jsx("span",{className:"text-gray-500",children:" macOS/Linux:"})," ~/.fsrouter/db/data.sqlite",e.jsx("br",{}),e.jsx("span",{className:"text-gray-500",children:" Windows:"})," %APPDATA%/fsrouter/db/data.sqlite"]})]})]})})]})})})}function p(){return e.jsx("footer",{className:"border-t border-[#3a2f27] bg-[#120f0d] pt-16 pb-8 px-6",children:e.jsxs("div",{className:"max-w-7xl mx-auto",children:[e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 lg:grid-cols-5 gap-8 mb-16",children:[e.jsxs("div",{className:"col-span-2 lg:col-span-2",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-6",children:[e.jsx("div",{className:"size-6 rounded bg-[#f97815] flex items-center justify-center text-white",children:e.jsx("span",{className:"material-symbols-outlined text-[16px]",children:"hub"})}),e.jsx("h3",{className:"text-white text-lg font-bold",children:"FSRouter"})]}),e.jsx("p",{className:"text-gray-500 text-sm max-w-xs mb-6",children:"The unified endpoint for AI generation. Connect, route, and manage your AI providers with ease."}),e.jsx("div",{className:"flex gap-4",children:e.jsx("a",{className:"text-gray-400 hover:text-white transition-colors",href:"https://github.com/nexusrouters/fsrouter",target:"_blank",rel:"noopener noreferrer",children:e.jsx("span",{className:"material-symbols-outlined",children:"code"})})})]}),e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx("h4",{className:"font-bold text-white",children:"Product"}),e.jsx("a",{className:"text-gray-400 hover:text-[#f97815] text-sm transition-colors",href:"#features",children:"Features"}),e.jsx("a",{className:"text-gray-400 hover:text-[#f97815] text-sm transition-colors",href:"/dashboard",children:"Dashboard"}),e.jsx("a",{className:"text-gray-400 hover:text-[#f97815] text-sm transition-colors",href:"https://github.com/nexusrouters/fsrouter",target:"_blank",rel:"noopener noreferrer",children:"Changelog"})]}),e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx("h4",{className:"font-bold text-white",children:"Resources"}),e.jsx("a",{className:"text-gray-400 hover:text-[#f97815] text-sm transition-colors",href:"https://github.com/nexusrouters/fsrouter#readme",target:"_blank",rel:"noopener noreferrer",children:"Documentation"}),e.jsx("a",{className:"text-gray-400 hover:text-[#f97815] text-sm transition-colors",href:"https://github.com/nexusrouters/fsrouter",target:"_blank",rel:"noopener noreferrer",children:"GitHub"}),e.jsx("a",{className:"text-gray-400 hover:text-[#f97815] text-sm transition-colors",href:"https://www.npmjs.com/package/fsrouter",target:"_blank",rel:"noopener noreferrer",children:"NPM"})]}),e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx("h4",{className:"font-bold text-white",children:"Legal"}),e.jsx("a",{className:"text-gray-400 hover:text-[#f97815] text-sm transition-colors",href:"https://github.com/nexusrouters/fsrouter/blob/main/LICENSE",target:"_blank",rel:"noopener noreferrer",children:"MIT License"})]})]}),e.jsxs("div",{className:"border-t border-[#3a2f27] pt-8 flex flex-col md:flex-row justify-between items-center gap-4",children:[e.jsx("p",{className:"text-gray-600 text-sm",children:"© 2025 FSRouter. All rights reserved."}),e.jsxs("div",{className:"flex gap-6",children:[e.jsx("a",{className:"text-gray-600 hover:text-white text-sm transition-colors",href:"https://github.com/nexusrouters/fsrouter",target:"_blank",rel:"noopener noreferrer",children:"GitHub"}),e.jsx("a",{className:"text-gray-600 hover:text-white text-sm transition-colors",href:"https://www.npmjs.com/package/fsrouter",target:"_blank",rel:"noopener noreferrer",children:"NPM"})]})]})]})})}function w(){const t=n();return e.jsxs("div",{className:"relative text-white font-sans overflow-x-hidden antialiased selection:bg-[#f97815] selection:text-white",children:[e.jsxs("div",{className:"fixed inset-0 z-0 overflow-hidden pointer-events-none bg-[#181411]",children:[e.jsx("div",{className:"absolute inset-0 opacity-[0.06]",style:{backgroundImage:"linear-gradient(to right, #f97815 1px, transparent 1px), linear-gradient(to bottom, #f97815 1px, transparent 1px)",backgroundSize:"50px 50px"}}),e.jsx("div",{className:"absolute top-0 left-1/4 w-[700px] h-[700px] bg-[#f97815]/12 rounded-full blur-[130px] animate-blob"}),e.jsx("div",{className:"absolute top-1/3 right-1/4 w-[600px] h-[600px] bg-purple-500/10 rounded-full blur-[130px] animate-blob",style:{animationDelay:"2s",animationDuration:"22s"}}),e.jsx("div",{className:"absolute bottom-0 left-1/2 w-[650px] h-[650px] bg-blue-500/8 rounded-full blur-[130px] animate-blob",style:{animationDelay:"4s",animationDuration:"25s"}}),e.jsx("div",{className:"absolute inset-0",style:{background:"radial-gradient(circle at center, transparent 0%, rgba(24, 20, 17, 0.4) 100%)"}})]}),e.jsxs("div",{className:"relative z-10",children:[e.jsx(c,{}),e.jsxs("main",{children:[e.jsxs("div",{className:"relative",children:[e.jsx(x,{}),e.jsx("div",{className:"flex justify-center pb-20",children:e.jsx(h,{})})]}),e.jsx(b,{}),e.jsx(u,{}),e.jsx(g,{}),e.jsxs("section",{className:"py-32 px-6 relative overflow-hidden",children:[e.jsx("div",{className:"absolute inset-0 bg-linear-to-t from-[#f97815]/5 to-transparent pointer-events-none"}),e.jsxs("div",{className:"max-w-4xl mx-auto text-center relative z-10",children:[e.jsx("h2",{className:"text-4xl md:text-5xl font-black mb-6",children:"Ready to Simplify Your AI Infrastructure?"}),e.jsx("p",{className:"text-xl text-gray-400 mb-10 max-w-2xl mx-auto",children:"Join developers who are streamlining their AI integrations with FSRouter. Open source and free to start."}),e.jsxs("div",{className:"flex flex-col sm:flex-row items-center justify-center gap-4",children:[e.jsx("button",{onClick:()=>t("/dashboard"),className:"w-full sm:w-auto h-14 px-10 rounded-lg bg-[#f97815] hover:bg-[#e0650a] text-[#181411] text-lg font-bold transition-all shadow-[0_0_20px_rgba(249,120,21,0.5)]",children:"Start Free"}),e.jsx("button",{onClick:()=>window.open("https://github.com/nexusrouters/fsrouter#readme","_blank"),className:"w-full sm:w-auto h-14 px-10 rounded-lg border border-[#3a2f27] hover:bg-[#23180f] text-white text-lg font-bold transition-all",children:"Read Documentation"})]})]})]})]}),e.jsx(p,{})]})]})}export{w as default};
|