@hienlh/ppm 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/bun.lock +3 -0
  3. package/dist/web/assets/{chat-tab-C24nbKz1.js → chat-tab-BdiG3Gnr.js} +3 -3
  4. package/dist/web/assets/code-editor-soN1frMc.js +1 -0
  5. package/dist/web/assets/{diff-viewer-BnvcXY3g.js → diff-viewer-DJEB1zOd.js} +1 -1
  6. package/dist/web/assets/dist-CJbcT4CK.js +16 -0
  7. package/dist/web/assets/{git-graph-iAf_zaqe.js → git-graph-CrU7vGxw.js} +1 -1
  8. package/dist/web/assets/{index-BwLVvoev.js → index-CmrE0Xoy.js} +5 -5
  9. package/dist/web/assets/index-g11aaU-x.css +2 -0
  10. package/dist/web/assets/{input-DV4tynJq.js → input-DMu1FA4M.js} +1 -1
  11. package/dist/web/assets/{markdown-renderer-CIfiE3o8.js → markdown-renderer-BPKEwysz.js} +1 -1
  12. package/dist/web/assets/postgres-viewer-lBV4F44Q.js +1 -0
  13. package/dist/web/assets/{settings-store-BGF8--S9.js → settings-store-BRFvbsHd.js} +1 -1
  14. package/dist/web/assets/settings-tab-Div5NL2d.js +1 -0
  15. package/dist/web/assets/sqlite-viewer-BbgWU-v3.js +1 -0
  16. package/dist/web/assets/{tab-store-L0a7ao4c.js → tab-store-Bf9z6T8D.js} +1 -1
  17. package/dist/web/assets/{terminal-tab-4-DINw_B.js → terminal-tab-Dt9bjwC8.js} +1 -1
  18. package/dist/web/assets/{use-monaco-theme-RFoGvnp0.js → use-monaco-theme-yxUtuNlu.js} +1 -1
  19. package/dist/web/index.html +8 -8
  20. package/dist/web/sw.js +1 -1
  21. package/package.json +2 -1
  22. package/src/server/index.ts +2 -0
  23. package/src/server/routes/postgres.ts +92 -0
  24. package/src/services/postgres.service.ts +170 -0
  25. package/src/services/sqlite.service.ts +5 -4
  26. package/src/web/components/editor/code-editor.tsx +8 -0
  27. package/src/web/components/layout/command-palette.tsx +2 -0
  28. package/src/web/components/layout/editor-panel.tsx +1 -0
  29. package/src/web/components/layout/mobile-nav.tsx +1 -1
  30. package/src/web/components/layout/tab-bar.tsx +1 -0
  31. package/src/web/components/layout/tab-content.tsx +5 -0
  32. package/src/web/components/postgres/postgres-viewer.tsx +264 -0
  33. package/src/web/components/postgres/use-postgres.ts +128 -0
  34. package/src/web/components/sqlite/sqlite-data-grid.tsx +1 -0
  35. package/src/web/components/sqlite/use-sqlite.ts +1 -1
  36. package/src/web/stores/tab-store.ts +1 -0
  37. package/dist/web/assets/code-editor-DjIL6ta3.js +0 -1
  38. package/dist/web/assets/index-CP_2zE5O.css +0 -2
  39. package/dist/web/assets/settings-tab-B_QwULcp.js +0 -1
  40. package/dist/web/assets/sqlite-viewer-DpGb3i2g.js +0 -16
  41. /package/dist/web/assets/{api-client-ANLU-Irq.js → api-client-DPWUomlf.js} +0 -0
  42. /package/dist/web/assets/{react-WvgCEYPV.js → react-Bo97Lrzq.js} +0 -0
  43. /package/dist/web/assets/{rotate-ccw-BesidNnx.js → rotate-ccw-Dx0ShAKj.js} +0 -0
  44. /package/dist/web/assets/{utils-C2KxHr1H.js → utils-CAPYyGV3.js} +0 -0
@@ -1 +1 @@
1
- import{n as e,o as t,r as n,t as r}from"./jsx-runtime-B4BJKQ1u.js";import{t as i}from"./input-DV4tynJq.js";import{a,t as o}from"./tab-store-L0a7ao4c.js";import{t as s}from"./rotate-ccw-BesidNnx.js";import{t as c}from"./utils-C2KxHr1H.js";import{i as l,t as u}from"./api-client-ANLU-Irq.js";import{D as d,E as f,N as p,S as m,T as h,a as g,c as ee,d as _,f as v,i as te,l as y,m as b,o as ne,p as x,s as re,u as ie,y as S,z as C}from"./index-BwLVvoev.js";var ae=e(`cherry`,[[`path`,{d:`M2 17a5 5 0 0 0 10 0c0-2.76-2.5-5-5-3-2.5-2-5 .24-5 3Z`,key:`cvxqlc`}],[`path`,{d:`M12 17a5 5 0 0 0 10 0c0-2.76-2.5-5-5-3-2.5-2-5 .24-5 3Z`,key:`1ostrc`}],[`path`,{d:`M7 14c3.22-2.91 4.29-8.75 5-12 1.66 2.38 4.94 9 5 12`,key:`hqx58h`}],[`path`,{d:`M22 9c-4.29 0-7.14-2.33-10-7 5.71 0 10 4.67 10 7Z`,key:`eykp1o`}]]),w=e(`git-merge`,[[`circle`,{cx:`18`,cy:`18`,r:`3`,key:`1xkwt0`}],[`circle`,{cx:`6`,cy:`6`,r:`3`,key:`1lh9wr`}],[`path`,{d:`M6 21V9a9 9 0 0 0 9 9`,key:`7kw0sc`}]]),T=e(`tag`,[[`path`,{d:`M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z`,key:`vktsd0`}],[`circle`,{cx:`7.5`,cy:`7.5`,r:`.5`,fill:`currentColor`,key:`kqv944`}]]),E=t(n(),1),D=r(),O=[`#4fc3f7`,`#81c784`,`#ffb74d`,`#e57373`,`#ba68c8`,`#4dd0e1`,`#aed581`,`#ff8a65`,`#f06292`,`#7986cb`],k=32,A=20,oe=5;function j({metadata:e}){let t=e?.projectName,[n,r]=(0,E.useState)(null),[a,S]=(0,E.useState)(!0),[C,w]=(0,E.useState)(null),[j,M]=(0,E.useState)(!1),[N,P]=(0,E.useState)({type:null}),[F,I]=(0,E.useState)(``),[L,R]=(0,E.useState)(null),[z,B]=(0,E.useState)([]),[ce,V]=(0,E.useState)(!1),{openTab:H}=o(),U=(0,E.useCallback)(async()=>{if(t)try{S(!0),r(await u.get(`${l(t)}/git/graph?max=200`)),w(null)}catch(e){w(e instanceof Error?e.message:`Failed to fetch graph`)}finally{S(!1)}},[t]);(0,E.useEffect)(()=>{U();let e=setInterval(U,1e4);return()=>clearInterval(e)},[U]);let W=async(e,n)=>{if(t){M(!0);try{await u.post(`${l(t)}${e}`,n),await U()}catch(e){w(e instanceof Error?e.message:`Action failed`)}finally{M(!1)}}},G=e=>W(`/git/checkout`,{ref:e}),le=e=>W(`/git/cherry-pick`,{hash:e}),ue=e=>W(`/git/revert`,{hash:e}),de=e=>W(`/git/merge`,{source:e}),fe=e=>W(`/git/branch/delete`,{name:e}),pe=e=>W(`/git/push`,{branch:e}),K=async(e,t)=>{if(n?.branches.some(t=>t.name===e||t.name.endsWith(`/${e}`))){if(!window.confirm(`Branch "${e}" already exists.\nDelete it and recreate from this commit?`))return;await W(`/git/branch/delete`,{name:e})}await W(`/git/branch/create`,{name:e,from:t})},q=(e,t)=>W(`/git/tag`,{name:e,hash:t}),me=async e=>{if(t)try{let n=await u.get(`${l(t)}/git/pr-url?branch=${encodeURIComponent(e)}`);n.url&&window.open(n.url,`_blank`)}catch{}},J=e=>{navigator.clipboard.writeText(e)},he=async e=>{if(L?.hash===e.hash){R(null);return}R(e),V(!0);try{let n=e.parents[0]??``,r=n?`ref1=${encodeURIComponent(n)}&`:``,i=await u.get(`${l(t)}/git/diff-stat?${r}ref2=${encodeURIComponent(e.hash)}`);B(Array.isArray(i)?i:[])}catch(e){console.error(`diff-stat error:`,e),B([])}finally{V(!1)}},ge=e=>{let n=e.parents[0];H({type:`git-diff`,title:`Diff ${e.abbreviatedHash}`,closable:!0,metadata:{projectName:t,ref1:n??void 0,ref2:e.hash},projectId:t??null})},{laneMap:Y,maxLane:_e}=(0,E.useMemo)(()=>{let e=new Map;if(!n)return{laneMap:e,maxLane:0};let t=0,r=new Map;for(let i of n.commits){let n=r.get(i.hash);n===void 0&&(n=t++),e.set(i.hash,n),r.delete(i.hash);for(let e=0;e<i.parents.length;e++){let a=i.parents[e];r.has(a)||r.set(a,e===0?n:t++)}}return{laneMap:e,maxLane:Math.max(t-1,0)}},[n]),X=n?.branches.find(e=>e.current),ve=(0,E.useMemo)(()=>{let e=new Map;if(!n)return e;for(let t of n.branches){let n=e.get(t.commitHash)??[];n.push({name:t.name,type:`branch`}),e.set(t.commitHash,n)}for(let t of n.commits)for(let n of t.refs)if(n.startsWith(`tag: `)){let r=n.replace(`tag: `,``),i=e.get(t.hash)??[];i.push({name:r,type:`tag`}),e.set(t.hash,i)}return e},[n]),ye=(0,E.useMemo)(()=>{if(!n)return[];let e=[];for(let t=0;t<n.commits.length;t++){let r=n.commits[t],i=Y.get(r.hash)??0,a=O[i%O.length];for(let o of r.parents){let s=n.commits.findIndex(e=>e.hash===o);if(s<0)continue;let c=Y.get(o)??0,l=O[c%O.length],u=i*A+A/2,d=t*k+k/2,f=c*A+A/2,p=s*k+k/2,m,h=r.parents.indexOf(o)>0;if(u===f)m=`M ${u} ${d} L ${f} ${p}`;else if(h){let e=d+k;m=`M ${u} ${d} C ${u} ${e} ${f} ${d} ${f} ${e} L ${f} ${p}`}else{let e=p-k;m=`M ${u} ${d} L ${u} ${e} C ${u} ${p} ${f} ${e} ${f} ${p}`}let g=r.parents.indexOf(o)===0?a:l;e.push({d:m,color:g})}}return e},[n,Y]);(_e+1)*A+A;let be=(n?.commits.length??0)*k,[Z,xe]=(0,E.useState)((typeof window<`u`&&window.innerWidth<768?6:10)*A+A),Q=(0,E.useRef)(!1),$=(0,E.useCallback)(e=>{Q.current=!0;let t=Z,n=n=>{if(!Q.current)return;let r=`touches`in n?n.touches[0].clientX:n.clientX;xe(Math.max(40,t+r-e))},r=()=>{Q.current=!1,window.removeEventListener(`mousemove`,n),window.removeEventListener(`mouseup`,r),window.removeEventListener(`touchmove`,n),window.removeEventListener(`touchend`,r)};window.addEventListener(`mousemove`,n),window.addEventListener(`mouseup`,r),window.addEventListener(`touchmove`,n,{passive:!1}),window.addEventListener(`touchend`,r)},[Z]),Se=(0,E.useCallback)(e=>{e.preventDefault(),$(e.clientX)},[$]),Ce=(0,E.useCallback)(e=>{$(e.touches[0].clientX)},[$]);if(!t)return(0,D.jsx)(`div`,{className:`flex items-center justify-center h-full text-muted-foreground text-sm`,children:`No project selected.`});if(a&&!n)return(0,D.jsxs)(`div`,{className:`flex items-center justify-center h-full gap-2 text-muted-foreground`,children:[(0,D.jsx)(h,{className:`size-5 animate-spin`}),(0,D.jsx)(`span`,{className:`text-sm`,children:`Loading git graph...`})]});if(C&&!n)return(0,D.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-2 text-destructive text-sm`,children:[(0,D.jsx)(`p`,{children:C}),(0,D.jsx)(y,{variant:`outline`,size:`sm`,onClick:U,children:`Retry`})]});function we(e){let t=new Date(e),n=new Date().getTime()-t.getTime(),r=Math.floor(n/6e4);if(r<1)return`just now`;if(r<60)return`${r}m ago`;let i=Math.floor(r/60);if(i<24)return`${i}h ago`;let a=Math.floor(i/24);if(a<30)return`${a}d ago`;let o=Math.floor(a/30);return o<12?`${o}mo ago`:`${Math.floor(o/12)}y ago`}return(0,D.jsxs)(`div`,{className:`flex flex-col h-full`,children:[(0,D.jsxs)(`div`,{className:`flex items-center justify-between px-3 py-2 border-b`,children:[(0,D.jsxs)(`span`,{className:`text-sm font-medium`,children:[`Git Graph`,X?` - ${X.name}`:``]}),(0,D.jsx)(y,{variant:`ghost`,size:`icon-xs`,onClick:U,disabled:j,children:(0,D.jsx)(m,{className:a?`animate-spin`:``})})]}),C&&(0,D.jsx)(`div`,{className:`px-3 py-1.5 text-xs text-destructive bg-destructive/10`,children:C}),(0,D.jsx)(`div`,{className:`flex-1 overflow-y-auto overflow-x-auto md:overflow-x-hidden`,children:(0,D.jsxs)(`div`,{className:`flex min-w-max md:min-w-0`,style:{height:`${be}px`},children:[(0,D.jsxs)(`div`,{className:`sticky left-0 z-10 shrink-0 bg-background`,style:{width:`${Z}px`},children:[(0,D.jsxs)(`svg`,{width:Z,height:be,children:[ye.map((e,t)=>(0,D.jsx)(`path`,{d:e.d,stroke:e.color,strokeWidth:2,fill:`none`},t)),n?.commits.map((e,t)=>{let n=Y.get(e.hash)??0,r=n*A+A/2,i=t*k+k/2,a=O[n%O.length];return(0,D.jsx)(`circle`,{cx:r,cy:i,r:oe,fill:a,stroke:`#0f1419`,strokeWidth:2},e.hash)})]}),(0,D.jsx)(`div`,{className:`absolute top-0 right-0 w-3 md:w-2 h-full cursor-col-resize hover:bg-primary/20 flex items-center justify-center bg-primary/10 md:bg-transparent`,onMouseDown:Se,onTouchStart:Ce,children:(0,D.jsx)(f,{className:`size-3 text-muted-foreground md:opacity-0 md:hover:opacity-100`})})]}),(0,D.jsx)(`div`,{className:`flex-1 min-w-[400px]`,children:n?.commits.map((e,t)=>{let n=O[(Y.get(e.hash)??0)%O.length],r=ve.get(e.hash)??[],i=r.filter(e=>e.type===`branch`),a=r.filter(e=>e.type===`tag`);return(0,D.jsxs)(ie,{children:[(0,D.jsx)(b,{asChild:!0,children:(0,D.jsx)(`div`,{className:`flex items-center hover:bg-muted/50 cursor-pointer text-sm border-b border-border/30 ${L?.hash===e.hash?`bg-primary/10`:``}`,style:{height:`${k}px`},onClick:()=>he(e),children:(0,D.jsxs)(`div`,{className:`flex items-center gap-2 flex-1 min-w-0 px-2`,children:[(0,D.jsx)(`span`,{className:`font-mono text-xs text-muted-foreground w-14 shrink-0`,children:e.abbreviatedHash}),i.map(e=>(0,D.jsx)(se,{label:e,color:n,currentBranch:X,onCheckout:G,onMerge:de,onPush:pe,onCreatePr:me,onDelete:fe},`branch-${e.name}`)),a.map(e=>(0,D.jsxs)(`span`,{className:`inline-flex items-center gap-0.5 px-1.5 py-0.5 rounded text-[10px] font-medium shrink-0 bg-amber-500/20 text-amber-500 border border-amber-500/30`,children:[(0,D.jsx)(T,{className:`size-2.5`}),e.name]},`tag-${e.name}`)),(0,D.jsx)(`span`,{className:`flex-1 truncate`,children:e.subject}),(0,D.jsx)(`span`,{className:`text-xs text-muted-foreground shrink-0 hidden sm:inline`,children:e.authorName}),(0,D.jsx)(`span`,{className:`text-xs text-muted-foreground shrink-0 w-14 text-right`,children:we(e.authorDate)})]})})}),(0,D.jsxs)(_,{children:[(0,D.jsx)(v,{onClick:()=>G(e.hash),children:`Checkout`}),(0,D.jsxs)(v,{onClick:()=>{P({type:`branch`,hash:e.hash}),I(``)},children:[(0,D.jsx)(d,{className:`size-3`}),`Create Branch...`]}),(0,D.jsx)(x,{}),(0,D.jsxs)(v,{onClick:()=>le(e.hash),children:[(0,D.jsx)(ae,{className:`size-3`}),`Cherry Pick`]}),(0,D.jsxs)(v,{onClick:()=>ue(e.hash),children:[(0,D.jsx)(s,{className:`size-3`}),`Revert`]}),(0,D.jsxs)(v,{onClick:()=>{P({type:`tag`,hash:e.hash}),I(``)},children:[(0,D.jsx)(T,{className:`size-3`}),`Create Tag...`]}),(0,D.jsx)(x,{}),(0,D.jsx)(v,{onClick:()=>ge(e),children:`View Diff`}),(0,D.jsxs)(v,{onClick:()=>J(e.hash),children:[(0,D.jsx)(p,{className:`size-3`}),`Copy Hash`]})]})]},e.hash)})})]})}),L&&(0,D.jsxs)(`div`,{className:`border-t bg-muted/30 max-h-[40%] overflow-auto`,children:[(0,D.jsxs)(`div`,{className:`px-3 py-2 border-b flex items-center justify-between`,children:[(0,D.jsxs)(`span`,{className:`text-sm font-medium truncate`,children:[L.abbreviatedHash,` — `,L.subject]}),(0,D.jsx)(y,{variant:`ghost`,size:`icon-xs`,onClick:()=>R(null),children:`✕`})]}),(0,D.jsxs)(`div`,{className:`px-3 py-2 text-xs space-y-1`,children:[(0,D.jsxs)(`div`,{className:`flex gap-4`,children:[(0,D.jsx)(`span`,{className:`text-muted-foreground`,children:`Author`}),(0,D.jsxs)(`span`,{children:[L.authorName,` <`,L.authorEmail,`>`]})]}),(0,D.jsxs)(`div`,{className:`flex gap-4`,children:[(0,D.jsx)(`span`,{className:`text-muted-foreground`,children:`Date`}),(0,D.jsx)(`span`,{children:new Date(L.authorDate).toLocaleString()})]}),(0,D.jsxs)(`div`,{className:`flex gap-4`,children:[(0,D.jsx)(`span`,{className:`text-muted-foreground`,children:`Hash`}),(0,D.jsx)(`span`,{className:`font-mono cursor-pointer hover:text-primary`,onClick:()=>J(L.hash),children:L.hash})]}),L.parents.length>0&&(0,D.jsxs)(`div`,{className:`flex gap-4`,children:[(0,D.jsx)(`span`,{className:`text-muted-foreground`,children:`Parents`}),(0,D.jsx)(`span`,{className:`font-mono`,children:L.parents.map(e=>e.slice(0,7)).join(`, `)})]}),L.body&&(0,D.jsx)(`div`,{className:`mt-2 p-2 bg-background rounded text-xs whitespace-pre-wrap`,children:L.body})]}),(0,D.jsxs)(`div`,{className:`px-3 py-1 border-t`,children:[(0,D.jsx)(`div`,{className:`text-xs text-muted-foreground py-1`,children:ce?`Loading files...`:`${z.length} file${z.length===1?``:`s`} changed`}),z.map(e=>(0,D.jsxs)(`div`,{className:`flex items-center gap-2 py-0.5 text-xs hover:bg-muted/50 rounded px-1 cursor-pointer`,onClick:()=>H({type:`git-diff`,title:`Diff ${c(e.path)}`,closable:!0,metadata:{projectName:t,ref1:L.parents[0]??void 0,ref2:L.hash,filePath:e.path},projectId:t??null}),children:[(0,D.jsx)(`span`,{className:`flex-1 truncate font-mono`,children:e.path}),e.additions>0&&(0,D.jsxs)(`span`,{className:`text-green-500`,children:[`+`,e.additions]}),e.deletions>0&&(0,D.jsxs)(`span`,{className:`text-red-500`,children:[`-`,e.deletions]})]},e.path))]})]}),(0,D.jsx)(te,{open:N.type!==null,onOpenChange:e=>{e||P({type:null})},children:(0,D.jsxs)(g,{children:[(0,D.jsx)(re,{children:(0,D.jsx)(ee,{children:N.type===`branch`?`Create Branch`:`Create Tag`})}),(0,D.jsx)(i,{placeholder:N.type===`branch`?`Branch name`:`Tag name`,value:F,onChange:e=>I(e.target.value),onKeyDown:e=>{e.key===`Enter`&&F.trim()&&(N.type===`branch`?K(F.trim(),N.hash):q(F.trim(),N.hash),P({type:null}))},autoFocus:!0}),(0,D.jsxs)(ne,{children:[(0,D.jsx)(y,{variant:`outline`,onClick:()=>P({type:null}),children:`Cancel`}),(0,D.jsx)(y,{disabled:!F.trim(),onClick:()=>{N.type===`branch`?K(F.trim(),N.hash):q(F.trim(),N.hash),P({type:null})},children:`Create`})]})]})})]})}function se({label:e,color:t,currentBranch:n,onCheckout:r,onMerge:i,onPush:o,onCreatePr:s,onDelete:c}){return(0,D.jsxs)(ie,{children:[(0,D.jsx)(b,{asChild:!0,children:(0,D.jsxs)(`span`,{className:`inline-flex items-center gap-0.5 px-1.5 py-0.5 rounded text-[10px] font-medium shrink-0 cursor-context-menu`,style:{backgroundColor:`${t}30`,color:t,border:`1px solid ${t}50`},children:[(0,D.jsx)(d,{className:`size-2.5`}),e.name]})}),(0,D.jsxs)(_,{children:[(0,D.jsx)(v,{onClick:()=>r(e.name),children:`Checkout`}),(0,D.jsxs)(v,{onClick:()=>i(e.name),disabled:e.name===n?.name,children:[(0,D.jsx)(w,{className:`size-3`}),`Merge into current`]}),(0,D.jsx)(x,{}),(0,D.jsxs)(v,{onClick:()=>o(e.name),children:[(0,D.jsx)(C,{className:`size-3`}),`Push`]}),(0,D.jsxs)(v,{onClick:()=>s(e.name),children:[(0,D.jsx)(a,{className:`size-3`}),`Create PR`]}),(0,D.jsx)(x,{}),(0,D.jsxs)(v,{variant:`destructive`,onClick:()=>c(e.name),disabled:e.name===n?.name,children:[(0,D.jsx)(S,{className:`size-3`}),`Delete`]})]})]})}export{j as GitGraph};
1
+ import{n as e,o as t,r as n,t as r}from"./jsx-runtime-B4BJKQ1u.js";import{t as i}from"./input-DMu1FA4M.js";import{a,t as o}from"./tab-store-Bf9z6T8D.js";import{t as s}from"./rotate-ccw-Dx0ShAKj.js";import{t as c}from"./utils-CAPYyGV3.js";import{i as l,t as u}from"./api-client-DPWUomlf.js";import{D as d,E as f,N as p,S as m,T as h,a as g,c as ee,d as _,f as v,i as te,l as y,m as b,o as ne,p as x,s as re,u as ie,y as S,z as C}from"./index-CmrE0Xoy.js";var ae=e(`cherry`,[[`path`,{d:`M2 17a5 5 0 0 0 10 0c0-2.76-2.5-5-5-3-2.5-2-5 .24-5 3Z`,key:`cvxqlc`}],[`path`,{d:`M12 17a5 5 0 0 0 10 0c0-2.76-2.5-5-5-3-2.5-2-5 .24-5 3Z`,key:`1ostrc`}],[`path`,{d:`M7 14c3.22-2.91 4.29-8.75 5-12 1.66 2.38 4.94 9 5 12`,key:`hqx58h`}],[`path`,{d:`M22 9c-4.29 0-7.14-2.33-10-7 5.71 0 10 4.67 10 7Z`,key:`eykp1o`}]]),w=e(`git-merge`,[[`circle`,{cx:`18`,cy:`18`,r:`3`,key:`1xkwt0`}],[`circle`,{cx:`6`,cy:`6`,r:`3`,key:`1lh9wr`}],[`path`,{d:`M6 21V9a9 9 0 0 0 9 9`,key:`7kw0sc`}]]),T=e(`tag`,[[`path`,{d:`M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z`,key:`vktsd0`}],[`circle`,{cx:`7.5`,cy:`7.5`,r:`.5`,fill:`currentColor`,key:`kqv944`}]]),E=t(n(),1),D=r(),O=[`#4fc3f7`,`#81c784`,`#ffb74d`,`#e57373`,`#ba68c8`,`#4dd0e1`,`#aed581`,`#ff8a65`,`#f06292`,`#7986cb`],k=32,A=20,oe=5;function j({metadata:e}){let t=e?.projectName,[n,r]=(0,E.useState)(null),[a,S]=(0,E.useState)(!0),[C,w]=(0,E.useState)(null),[j,M]=(0,E.useState)(!1),[N,P]=(0,E.useState)({type:null}),[F,I]=(0,E.useState)(``),[L,R]=(0,E.useState)(null),[z,B]=(0,E.useState)([]),[ce,V]=(0,E.useState)(!1),{openTab:H}=o(),U=(0,E.useCallback)(async()=>{if(t)try{S(!0),r(await u.get(`${l(t)}/git/graph?max=200`)),w(null)}catch(e){w(e instanceof Error?e.message:`Failed to fetch graph`)}finally{S(!1)}},[t]);(0,E.useEffect)(()=>{U();let e=setInterval(U,1e4);return()=>clearInterval(e)},[U]);let W=async(e,n)=>{if(t){M(!0);try{await u.post(`${l(t)}${e}`,n),await U()}catch(e){w(e instanceof Error?e.message:`Action failed`)}finally{M(!1)}}},G=e=>W(`/git/checkout`,{ref:e}),le=e=>W(`/git/cherry-pick`,{hash:e}),ue=e=>W(`/git/revert`,{hash:e}),de=e=>W(`/git/merge`,{source:e}),fe=e=>W(`/git/branch/delete`,{name:e}),pe=e=>W(`/git/push`,{branch:e}),K=async(e,t)=>{if(n?.branches.some(t=>t.name===e||t.name.endsWith(`/${e}`))){if(!window.confirm(`Branch "${e}" already exists.\nDelete it and recreate from this commit?`))return;await W(`/git/branch/delete`,{name:e})}await W(`/git/branch/create`,{name:e,from:t})},q=(e,t)=>W(`/git/tag`,{name:e,hash:t}),me=async e=>{if(t)try{let n=await u.get(`${l(t)}/git/pr-url?branch=${encodeURIComponent(e)}`);n.url&&window.open(n.url,`_blank`)}catch{}},J=e=>{navigator.clipboard.writeText(e)},he=async e=>{if(L?.hash===e.hash){R(null);return}R(e),V(!0);try{let n=e.parents[0]??``,r=n?`ref1=${encodeURIComponent(n)}&`:``,i=await u.get(`${l(t)}/git/diff-stat?${r}ref2=${encodeURIComponent(e.hash)}`);B(Array.isArray(i)?i:[])}catch(e){console.error(`diff-stat error:`,e),B([])}finally{V(!1)}},ge=e=>{let n=e.parents[0];H({type:`git-diff`,title:`Diff ${e.abbreviatedHash}`,closable:!0,metadata:{projectName:t,ref1:n??void 0,ref2:e.hash},projectId:t??null})},{laneMap:Y,maxLane:_e}=(0,E.useMemo)(()=>{let e=new Map;if(!n)return{laneMap:e,maxLane:0};let t=0,r=new Map;for(let i of n.commits){let n=r.get(i.hash);n===void 0&&(n=t++),e.set(i.hash,n),r.delete(i.hash);for(let e=0;e<i.parents.length;e++){let a=i.parents[e];r.has(a)||r.set(a,e===0?n:t++)}}return{laneMap:e,maxLane:Math.max(t-1,0)}},[n]),X=n?.branches.find(e=>e.current),ve=(0,E.useMemo)(()=>{let e=new Map;if(!n)return e;for(let t of n.branches){let n=e.get(t.commitHash)??[];n.push({name:t.name,type:`branch`}),e.set(t.commitHash,n)}for(let t of n.commits)for(let n of t.refs)if(n.startsWith(`tag: `)){let r=n.replace(`tag: `,``),i=e.get(t.hash)??[];i.push({name:r,type:`tag`}),e.set(t.hash,i)}return e},[n]),ye=(0,E.useMemo)(()=>{if(!n)return[];let e=[];for(let t=0;t<n.commits.length;t++){let r=n.commits[t],i=Y.get(r.hash)??0,a=O[i%O.length];for(let o of r.parents){let s=n.commits.findIndex(e=>e.hash===o);if(s<0)continue;let c=Y.get(o)??0,l=O[c%O.length],u=i*A+A/2,d=t*k+k/2,f=c*A+A/2,p=s*k+k/2,m,h=r.parents.indexOf(o)>0;if(u===f)m=`M ${u} ${d} L ${f} ${p}`;else if(h){let e=d+k;m=`M ${u} ${d} C ${u} ${e} ${f} ${d} ${f} ${e} L ${f} ${p}`}else{let e=p-k;m=`M ${u} ${d} L ${u} ${e} C ${u} ${p} ${f} ${e} ${f} ${p}`}let g=r.parents.indexOf(o)===0?a:l;e.push({d:m,color:g})}}return e},[n,Y]);(_e+1)*A+A;let be=(n?.commits.length??0)*k,[Z,xe]=(0,E.useState)((typeof window<`u`&&window.innerWidth<768?6:10)*A+A),Q=(0,E.useRef)(!1),$=(0,E.useCallback)(e=>{Q.current=!0;let t=Z,n=n=>{if(!Q.current)return;let r=`touches`in n?n.touches[0].clientX:n.clientX;xe(Math.max(40,t+r-e))},r=()=>{Q.current=!1,window.removeEventListener(`mousemove`,n),window.removeEventListener(`mouseup`,r),window.removeEventListener(`touchmove`,n),window.removeEventListener(`touchend`,r)};window.addEventListener(`mousemove`,n),window.addEventListener(`mouseup`,r),window.addEventListener(`touchmove`,n,{passive:!1}),window.addEventListener(`touchend`,r)},[Z]),Se=(0,E.useCallback)(e=>{e.preventDefault(),$(e.clientX)},[$]),Ce=(0,E.useCallback)(e=>{$(e.touches[0].clientX)},[$]);if(!t)return(0,D.jsx)(`div`,{className:`flex items-center justify-center h-full text-muted-foreground text-sm`,children:`No project selected.`});if(a&&!n)return(0,D.jsxs)(`div`,{className:`flex items-center justify-center h-full gap-2 text-muted-foreground`,children:[(0,D.jsx)(h,{className:`size-5 animate-spin`}),(0,D.jsx)(`span`,{className:`text-sm`,children:`Loading git graph...`})]});if(C&&!n)return(0,D.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-2 text-destructive text-sm`,children:[(0,D.jsx)(`p`,{children:C}),(0,D.jsx)(y,{variant:`outline`,size:`sm`,onClick:U,children:`Retry`})]});function we(e){let t=new Date(e),n=new Date().getTime()-t.getTime(),r=Math.floor(n/6e4);if(r<1)return`just now`;if(r<60)return`${r}m ago`;let i=Math.floor(r/60);if(i<24)return`${i}h ago`;let a=Math.floor(i/24);if(a<30)return`${a}d ago`;let o=Math.floor(a/30);return o<12?`${o}mo ago`:`${Math.floor(o/12)}y ago`}return(0,D.jsxs)(`div`,{className:`flex flex-col h-full`,children:[(0,D.jsxs)(`div`,{className:`flex items-center justify-between px-3 py-2 border-b`,children:[(0,D.jsxs)(`span`,{className:`text-sm font-medium`,children:[`Git Graph`,X?` - ${X.name}`:``]}),(0,D.jsx)(y,{variant:`ghost`,size:`icon-xs`,onClick:U,disabled:j,children:(0,D.jsx)(m,{className:a?`animate-spin`:``})})]}),C&&(0,D.jsx)(`div`,{className:`px-3 py-1.5 text-xs text-destructive bg-destructive/10`,children:C}),(0,D.jsx)(`div`,{className:`flex-1 overflow-y-auto overflow-x-auto md:overflow-x-hidden`,children:(0,D.jsxs)(`div`,{className:`flex min-w-max md:min-w-0`,style:{height:`${be}px`},children:[(0,D.jsxs)(`div`,{className:`sticky left-0 z-10 shrink-0 bg-background`,style:{width:`${Z}px`},children:[(0,D.jsxs)(`svg`,{width:Z,height:be,children:[ye.map((e,t)=>(0,D.jsx)(`path`,{d:e.d,stroke:e.color,strokeWidth:2,fill:`none`},t)),n?.commits.map((e,t)=>{let n=Y.get(e.hash)??0,r=n*A+A/2,i=t*k+k/2,a=O[n%O.length];return(0,D.jsx)(`circle`,{cx:r,cy:i,r:oe,fill:a,stroke:`#0f1419`,strokeWidth:2},e.hash)})]}),(0,D.jsx)(`div`,{className:`absolute top-0 right-0 w-3 md:w-2 h-full cursor-col-resize hover:bg-primary/20 flex items-center justify-center bg-primary/10 md:bg-transparent`,onMouseDown:Se,onTouchStart:Ce,children:(0,D.jsx)(f,{className:`size-3 text-muted-foreground md:opacity-0 md:hover:opacity-100`})})]}),(0,D.jsx)(`div`,{className:`flex-1 min-w-[400px]`,children:n?.commits.map((e,t)=>{let n=O[(Y.get(e.hash)??0)%O.length],r=ve.get(e.hash)??[],i=r.filter(e=>e.type===`branch`),a=r.filter(e=>e.type===`tag`);return(0,D.jsxs)(ie,{children:[(0,D.jsx)(b,{asChild:!0,children:(0,D.jsx)(`div`,{className:`flex items-center hover:bg-muted/50 cursor-pointer text-sm border-b border-border/30 ${L?.hash===e.hash?`bg-primary/10`:``}`,style:{height:`${k}px`},onClick:()=>he(e),children:(0,D.jsxs)(`div`,{className:`flex items-center gap-2 flex-1 min-w-0 px-2`,children:[(0,D.jsx)(`span`,{className:`font-mono text-xs text-muted-foreground w-14 shrink-0`,children:e.abbreviatedHash}),i.map(e=>(0,D.jsx)(se,{label:e,color:n,currentBranch:X,onCheckout:G,onMerge:de,onPush:pe,onCreatePr:me,onDelete:fe},`branch-${e.name}`)),a.map(e=>(0,D.jsxs)(`span`,{className:`inline-flex items-center gap-0.5 px-1.5 py-0.5 rounded text-[10px] font-medium shrink-0 bg-amber-500/20 text-amber-500 border border-amber-500/30`,children:[(0,D.jsx)(T,{className:`size-2.5`}),e.name]},`tag-${e.name}`)),(0,D.jsx)(`span`,{className:`flex-1 truncate`,children:e.subject}),(0,D.jsx)(`span`,{className:`text-xs text-muted-foreground shrink-0 hidden sm:inline`,children:e.authorName}),(0,D.jsx)(`span`,{className:`text-xs text-muted-foreground shrink-0 w-14 text-right`,children:we(e.authorDate)})]})})}),(0,D.jsxs)(_,{children:[(0,D.jsx)(v,{onClick:()=>G(e.hash),children:`Checkout`}),(0,D.jsxs)(v,{onClick:()=>{P({type:`branch`,hash:e.hash}),I(``)},children:[(0,D.jsx)(d,{className:`size-3`}),`Create Branch...`]}),(0,D.jsx)(x,{}),(0,D.jsxs)(v,{onClick:()=>le(e.hash),children:[(0,D.jsx)(ae,{className:`size-3`}),`Cherry Pick`]}),(0,D.jsxs)(v,{onClick:()=>ue(e.hash),children:[(0,D.jsx)(s,{className:`size-3`}),`Revert`]}),(0,D.jsxs)(v,{onClick:()=>{P({type:`tag`,hash:e.hash}),I(``)},children:[(0,D.jsx)(T,{className:`size-3`}),`Create Tag...`]}),(0,D.jsx)(x,{}),(0,D.jsx)(v,{onClick:()=>ge(e),children:`View Diff`}),(0,D.jsxs)(v,{onClick:()=>J(e.hash),children:[(0,D.jsx)(p,{className:`size-3`}),`Copy Hash`]})]})]},e.hash)})})]})}),L&&(0,D.jsxs)(`div`,{className:`border-t bg-muted/30 max-h-[40%] overflow-auto`,children:[(0,D.jsxs)(`div`,{className:`px-3 py-2 border-b flex items-center justify-between`,children:[(0,D.jsxs)(`span`,{className:`text-sm font-medium truncate`,children:[L.abbreviatedHash,` — `,L.subject]}),(0,D.jsx)(y,{variant:`ghost`,size:`icon-xs`,onClick:()=>R(null),children:`✕`})]}),(0,D.jsxs)(`div`,{className:`px-3 py-2 text-xs space-y-1`,children:[(0,D.jsxs)(`div`,{className:`flex gap-4`,children:[(0,D.jsx)(`span`,{className:`text-muted-foreground`,children:`Author`}),(0,D.jsxs)(`span`,{children:[L.authorName,` <`,L.authorEmail,`>`]})]}),(0,D.jsxs)(`div`,{className:`flex gap-4`,children:[(0,D.jsx)(`span`,{className:`text-muted-foreground`,children:`Date`}),(0,D.jsx)(`span`,{children:new Date(L.authorDate).toLocaleString()})]}),(0,D.jsxs)(`div`,{className:`flex gap-4`,children:[(0,D.jsx)(`span`,{className:`text-muted-foreground`,children:`Hash`}),(0,D.jsx)(`span`,{className:`font-mono cursor-pointer hover:text-primary`,onClick:()=>J(L.hash),children:L.hash})]}),L.parents.length>0&&(0,D.jsxs)(`div`,{className:`flex gap-4`,children:[(0,D.jsx)(`span`,{className:`text-muted-foreground`,children:`Parents`}),(0,D.jsx)(`span`,{className:`font-mono`,children:L.parents.map(e=>e.slice(0,7)).join(`, `)})]}),L.body&&(0,D.jsx)(`div`,{className:`mt-2 p-2 bg-background rounded text-xs whitespace-pre-wrap`,children:L.body})]}),(0,D.jsxs)(`div`,{className:`px-3 py-1 border-t`,children:[(0,D.jsx)(`div`,{className:`text-xs text-muted-foreground py-1`,children:ce?`Loading files...`:`${z.length} file${z.length===1?``:`s`} changed`}),z.map(e=>(0,D.jsxs)(`div`,{className:`flex items-center gap-2 py-0.5 text-xs hover:bg-muted/50 rounded px-1 cursor-pointer`,onClick:()=>H({type:`git-diff`,title:`Diff ${c(e.path)}`,closable:!0,metadata:{projectName:t,ref1:L.parents[0]??void 0,ref2:L.hash,filePath:e.path},projectId:t??null}),children:[(0,D.jsx)(`span`,{className:`flex-1 truncate font-mono`,children:e.path}),e.additions>0&&(0,D.jsxs)(`span`,{className:`text-green-500`,children:[`+`,e.additions]}),e.deletions>0&&(0,D.jsxs)(`span`,{className:`text-red-500`,children:[`-`,e.deletions]})]},e.path))]})]}),(0,D.jsx)(te,{open:N.type!==null,onOpenChange:e=>{e||P({type:null})},children:(0,D.jsxs)(g,{children:[(0,D.jsx)(re,{children:(0,D.jsx)(ee,{children:N.type===`branch`?`Create Branch`:`Create Tag`})}),(0,D.jsx)(i,{placeholder:N.type===`branch`?`Branch name`:`Tag name`,value:F,onChange:e=>I(e.target.value),onKeyDown:e=>{e.key===`Enter`&&F.trim()&&(N.type===`branch`?K(F.trim(),N.hash):q(F.trim(),N.hash),P({type:null}))},autoFocus:!0}),(0,D.jsxs)(ne,{children:[(0,D.jsx)(y,{variant:`outline`,onClick:()=>P({type:null}),children:`Cancel`}),(0,D.jsx)(y,{disabled:!F.trim(),onClick:()=>{N.type===`branch`?K(F.trim(),N.hash):q(F.trim(),N.hash),P({type:null})},children:`Create`})]})]})})]})}function se({label:e,color:t,currentBranch:n,onCheckout:r,onMerge:i,onPush:o,onCreatePr:s,onDelete:c}){return(0,D.jsxs)(ie,{children:[(0,D.jsx)(b,{asChild:!0,children:(0,D.jsxs)(`span`,{className:`inline-flex items-center gap-0.5 px-1.5 py-0.5 rounded text-[10px] font-medium shrink-0 cursor-context-menu`,style:{backgroundColor:`${t}30`,color:t,border:`1px solid ${t}50`},children:[(0,D.jsx)(d,{className:`size-2.5`}),e.name]})}),(0,D.jsxs)(_,{children:[(0,D.jsx)(v,{onClick:()=>r(e.name),children:`Checkout`}),(0,D.jsxs)(v,{onClick:()=>i(e.name),disabled:e.name===n?.name,children:[(0,D.jsx)(w,{className:`size-3`}),`Merge into current`]}),(0,D.jsx)(x,{}),(0,D.jsxs)(v,{onClick:()=>o(e.name),children:[(0,D.jsx)(C,{className:`size-3`}),`Push`]}),(0,D.jsxs)(v,{onClick:()=>s(e.name),children:[(0,D.jsx)(a,{className:`size-3`}),`Create PR`]}),(0,D.jsx)(x,{}),(0,D.jsxs)(v,{variant:`destructive`,onClick:()=>c(e.name),disabled:e.name===n?.name,children:[(0,D.jsx)(S,{className:`size-3`}),`Delete`]})]})]})}export{j as GitGraph};