@hienlh/ppm 0.11.5 → 0.11.6

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 (23) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/web/assets/{chat-tab-CWc9ZYVY.js → chat-tab-2znvnxzD.js} +3 -3
  3. package/dist/web/assets/code-editor-CUyFYiwJ.js +8 -0
  4. package/dist/web/assets/{conflict-editor-BmuhLalI.js → conflict-editor-DXnqiS4c.js} +1 -1
  5. package/dist/web/assets/{database-viewer-CqW0fH7Q.js → database-viewer-DK4PfwVJ.js} +1 -1
  6. package/dist/web/assets/{diff-viewer-ium8zJhL.js → diff-viewer-Cy4oX3mb.js} +1 -1
  7. package/dist/web/assets/{extension-webview-AxcQX8ML.js → extension-webview-DIVrmdfu.js} +1 -1
  8. package/dist/web/assets/{index-CyciQ-Gz.js → index-oqP6ldWs.js} +3 -3
  9. package/dist/web/assets/{markdown-renderer-Ckjp96ej.js → markdown-renderer-BLhcNL42.js} +1 -1
  10. package/dist/web/assets/{port-forwarding-tab-DR5Bngg2.js → port-forwarding-tab-iZost0RL.js} +1 -1
  11. package/dist/web/assets/{postgres-viewer-hy2EksiB.js → postgres-viewer-CabnbH06.js} +1 -1
  12. package/dist/web/assets/{settings-tab-D5SXI74b.js → settings-tab-D2th4Hfj.js} +1 -1
  13. package/dist/web/assets/{sqlite-viewer-DDPZjt-X.js → sqlite-viewer-cGe2bGlF.js} +1 -1
  14. package/dist/web/assets/{terminal-tab-DSWdc4AO.js → terminal-tab-CPAMJoNK.js} +1 -1
  15. package/dist/web/index.html +1 -1
  16. package/dist/web/sw.js +1 -1
  17. package/package.json +1 -1
  18. package/src/server/ws/chat.ts +10 -0
  19. package/src/services/file-watcher.service.ts +72 -0
  20. package/src/web/components/editor/code-editor.tsx +23 -0
  21. package/src/web/components/explorer/file-tree.tsx +16 -5
  22. package/src/web/hooks/use-chat.ts +6 -0
  23. package/dist/web/assets/code-editor-CSej2S2J.js +0 -8
@@ -240,6 +240,29 @@ export const CodeEditor = memo(function CodeEditor({ metadata, tabId }: CodeEdit
240
240
  return () => { if (saveTimerRef.current) clearTimeout(saveTimerRef.current); };
241
241
  }, [filePath, projectName, isImage, isPdf, isExternalFile, isUntitled]);
242
242
 
243
+ // Real-time reload: listen for file:changed WS events, re-fetch if editor is clean
244
+ const unsavedRef = useRef(unsaved);
245
+ unsavedRef.current = unsaved;
246
+ useEffect(() => {
247
+ if (!filePath || !projectName || inlineContent != null || isUntitled) return;
248
+ const handler = (e: Event) => {
249
+ const detail = (e as CustomEvent).detail;
250
+ if (detail.projectName !== projectName || detail.path !== filePath) return;
251
+ if (unsavedRef.current) return; // don't overwrite unsaved changes
252
+ const readUrl = isExternalFile
253
+ ? `/api/fs/read?path=${encodeURIComponent(filePath)}`
254
+ : `${projectUrl(projectName)}/files/read?path=${encodeURIComponent(filePath)}`;
255
+ api.get<{ content: string; encoding?: string }>(readUrl).then((data) => {
256
+ if (data.content === latestContentRef.current) return; // skip if unchanged (e.g. self-save)
257
+ setContent(data.content);
258
+ latestContentRef.current = data.content;
259
+ if (data.encoding) setEncoding(data.encoding);
260
+ }).catch(() => {});
261
+ };
262
+ window.addEventListener("file:changed", handler);
263
+ return () => window.removeEventListener("file:changed", handler);
264
+ }, [filePath, projectName, isExternalFile, inlineContent, isUntitled]);
265
+
243
266
  // Update tab title unsaved indicator
244
267
  useEffect(() => {
245
268
  if (!ownTab) return;
@@ -277,12 +277,23 @@ export function FileTree({ onFileOpen }: FileTreeProps = {}) {
277
277
  }
278
278
  }, [activeProject?.name]); // eslint-disable-line react-hooks/exhaustive-deps
279
279
 
280
- // Auto-refresh file tree when window regains focus
281
- // TODO: Replace with fs.watch + WebSocket push for real-time sync without needing window focus
280
+ // Auto-refresh file tree on window focus and real-time file changes via WebSocket
282
281
  useEffect(() => {
283
- const handleFocus = () => { if (activeProject) fetchTree(activeProject.name); };
284
- window.addEventListener("focus", handleFocus);
285
- return () => window.removeEventListener("focus", handleFocus);
282
+ if (!activeProject) return;
283
+ const refresh = () => fetchTree(activeProject.name);
284
+ let debounceTimer: ReturnType<typeof setTimeout>;
285
+ const debouncedRefresh = () => { clearTimeout(debounceTimer); debounceTimer = setTimeout(refresh, 300); };
286
+ const handleFileChanged = (e: Event) => {
287
+ const detail = (e as CustomEvent).detail;
288
+ if (detail.projectName === activeProject.name) debouncedRefresh();
289
+ };
290
+ window.addEventListener("focus", refresh);
291
+ window.addEventListener("file:changed", handleFileChanged);
292
+ return () => {
293
+ clearTimeout(debounceTimer);
294
+ window.removeEventListener("focus", refresh);
295
+ window.removeEventListener("file:changed", handleFileChanged);
296
+ };
286
297
  }, [activeProject, fetchTree]);
287
298
 
288
299
  const uploadFiles = useCallback(async (targetDir: string, files: FileList) => {
@@ -415,6 +415,12 @@ export function useChat(sessionId: string | null, providerId = "claude", project
415
415
  // Ignore keepalive pings
416
416
  if ((data as any).type === "ping") return;
417
417
 
418
+ // Dispatch file change events for real-time editor reload
419
+ if ((data as any).type === "file:changed") {
420
+ window.dispatchEvent(new CustomEvent("file:changed", { detail: data }));
421
+ return;
422
+ }
423
+
418
424
  // Dispatch global Jira events so components can listen via window events
419
425
  if (typeof (data as any).type === "string" && (data as any).type.startsWith("jira:")) {
420
426
  window.dispatchEvent(new CustomEvent((data as any).type, { detail: data }));
@@ -1,8 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/markdown-renderer-Ckjp96ej.js","assets/rolldown-runtime-FhOqtrmT.js","assets/index-CyciQ-Gz.js","assets/vendor-mermaid-CylkVm4U.js","assets/vendor-ui-B-T_damt.js","assets/vendor-markdown-0Mxgxy0L.js","assets/input-CHRMley8.js","assets/utils-ChWX7pZv.js","assets/createLucideIcon-BjHrJDVb.js","assets/x-DlFGzN8d.js","assets/scroll-area-DwWF9FpN.js","assets/ai-settings-section-D2vqiydT.js","assets/dist-C5IgeqrV.js","assets/plus-51UQ45rf.js","assets/refresh-cw-CSFrDtiu.js","assets/trash-2-BgDIBl6f.js","assets/api-client-C3tXCh0r.js","assets/api-settings-2eTz4SgY.js","assets/chevron-right-BzAdxJRG.js","assets/database-D4DIhgi-.js","assets/react-BkWDCPD7.js","assets/extension-store-CkyOvGbF.js","assets/keybindings-store-CpP5_miA.js","assets/tab-store-Jvy1eZGM.js","assets/project-store-CczGNZyf.js","assets/settings-store-CuYjM0FF.js","assets/index-iZHWllzQ.css","assets/csv-preview-D37K2LRd.js","assets/lib-BqkcKGFq.js","assets/arrow-up-Dtrfv490.js","assets/csv-parser-BAa56Nnn.js"])))=>i.map(i=>d[i]);
2
- import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{b as t,x as n}from"./vendor-markdown-0Mxgxy0L.js";import"./vendor-ui-B-T_damt.js";import{t as r}from"./createLucideIcon-BjHrJDVb.js";import"./scroll-area-DwWF9FpN.js";import{t as i}from"./chevron-right-BzAdxJRG.js";import{a,l as o,n as s,o as c,r as l,s as u,t as d}from"./input-CHRMley8.js";import{t as f}from"./code-CuravVys.js";import{t as ee}from"./database-D4DIhgi-.js";import{n as p,r as m}from"./x-DlFGzN8d.js";import{t as h}from"./table-DbSviOmw.js";import{t as g}from"./text-wrap-DzvCTq_i.js";import{i as _,r as v,t as y}from"./api-client-C3tXCh0r.js";import{G as b}from"./vendor-mermaid-CylkVm4U.js";import{n as te}from"./settings-store-CuYjM0FF.js";import{t as x}from"./utils-ChWX7pZv.js";import{n as ne,t as re}from"./tab-store-Jvy1eZGM.js";import{n as ie}from"./project-store-CczGNZyf.js";import{B as S,E as ae,F as C,I as w,L as T,M as E,P as D,R as O,a as oe,c as se,d as k,f as A,g as j,h as M,l as N,m as P,o as F,p as ce,u as le,y as I,z as ue}from"./index-CyciQ-Gz.js";import{n as de,t as fe}from"./use-monaco-theme-kjiAwvOp.js";import{n as pe,t as me}from"./sql-completion-provider-D3acAhav.js";var he=r(`file-exclamation-point`,[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M12 9v4`,key:`juzpu7`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]]),L=e(n(),1),R=t(),ge={ts:O,tsx:O,js:O,jsx:O,py:O,rs:O,go:O,html:O,css:O,scss:O,json:ue,md:T,txt:T,yaml:w,yml:w};function z(e,t){return t?D:ge[e.split(`.`).pop()?.toLowerCase()??``]??C}function _e(e,t){let n=[],r=e;for(let e=0;e<t.length;e++){let i=t[e],a=t.slice(0,e+1).join(`/`),o=r.find(e=>e.name===i);if(n.push({name:i,fullPath:a,node:o??null,siblings:r}),o?.children)r=o.children;else{for(let r=e+1;r<t.length;r++)n.push({name:t[r],fullPath:t.slice(0,r+1).join(`/`),node:null,siblings:[]});break}}return n}function B(e){return[...e].sort((e,t)=>e.type===t.type?e.name.localeCompare(t.name):e.type===`directory`?-1:1)}function ve({filePath:e,projectName:t,tabId:n,className:r}){let a=I(e=>e.tree),{updateTab:o,openTab:s}=re(M(e=>({updateTab:e.updateTab,openTab:e.openTab}))),c=(0,L.useRef)(null),l=(0,L.useMemo)(()=>_e(a,e.split(`/`).filter(Boolean)),[a,e]);(0,L.useEffect)(()=>{c.current&&(c.current.scrollLeft=c.current.scrollWidth)},[l]);function u(e,r){let i=x(e);r.metaKey||r.ctrlKey?s({type:`editor`,title:i,metadata:{filePath:e,projectName:t},projectId:t,closable:!0}):o(n,{title:i,metadata:{filePath:e,projectName:t}})}return(0,R.jsx)(`div`,{ref:c,className:r,children:l.map((e,n)=>(0,R.jsxs)(`div`,{className:`flex items-center shrink-0`,children:[n>0&&(0,R.jsx)(i,{className:`size-3 text-muted-foreground shrink-0 mx-0.5`}),e.siblings.length>0?(0,R.jsx)(V,{segment:e,isLast:n===l.length-1,projectName:t,onFileClick:u}):(0,R.jsx)(`span`,{className:`text-xs text-muted-foreground px-1 py-0.5`,children:e.name})]},e.fullPath))})}function V({segment:e,isLast:t,projectName:n,onFileClick:r}){let i=(0,L.useMemo)(()=>B(e.siblings),[e.siblings]);return(0,R.jsxs)(se,{children:[(0,R.jsx)(P,{asChild:!0,children:(0,R.jsx)(`button`,{type:`button`,className:`text-xs px-1 py-0.5 rounded hover:bg-muted transition-colors truncate max-w-[120px] ${t?`text-foreground font-medium`:`text-muted-foreground`}`,children:e.name})}),(0,R.jsx)(N,{align:`start`,className:`max-h-[300px] p-1`,children:i.map(t=>(0,R.jsx)(H,{node:t,projectName:n,activePath:e.fullPath,onFileClick:r},t.path))})]})}function H({node:e,projectName:t,activePath:n,onFileClick:r}){let i=z(e.name,e.type===`directory`),a=e.path===n;return e.type===`directory`&&e.children&&e.children.length>0?(0,R.jsxs)(k,{children:[(0,R.jsxs)(ce,{className:`text-xs gap-1.5 ${a?`bg-muted`:``}`,children:[(0,R.jsx)(i,{className:`size-3.5 shrink-0 text-muted-foreground`}),(0,R.jsx)(`span`,{className:`truncate`,children:e.name})]}),(0,R.jsx)(A,{className:`max-h-[300px] overflow-y-auto p-1`,children:B(e.children).map(e=>(0,R.jsx)(H,{node:e,projectName:t,activePath:n,onFileClick:r},e.path))})]}):(0,R.jsxs)(le,{className:`text-xs gap-1.5 cursor-pointer ${a?`bg-muted`:``}`,onSelect:e=>{},onClick:t=>{e.type!==`directory`&&r(e.path,t)},children:[(0,R.jsx)(i,{className:`size-3.5 shrink-0 text-muted-foreground`}),(0,R.jsx)(`span`,{className:`truncate`,children:e.name})]})}function U({active:e,onClick:t,icon:n,label:r}){return(0,R.jsxs)(`button`,{type:`button`,onClick:t,className:`flex items-center gap-1 px-2 py-1 rounded text-xs transition-colors ${e?`bg-muted text-foreground`:`text-muted-foreground hover:text-foreground`}`,children:[(0,R.jsx)(n,{className:`size-3`}),(0,R.jsx)(`span`,{className:`hidden sm:inline`,children:r})]})}function ye({ext:e,mdMode:t,onMdModeChange:n,csvMode:r,onCsvModeChange:i,wordWrap:a,onToggleWordWrap:o,filePath:s,projectName:c,className:l}){return(0,R.jsxs)(`div`,{className:l,children:[(e===`md`||e===`mdx`)&&n&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(U,{active:t===`edit`,onClick:()=>n(`edit`),icon:f,label:`Edit`}),(0,R.jsx)(U,{active:t===`preview`,onClick:()=>n(`preview`),icon:p,label:`Preview`})]}),e===`csv`&&i&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(U,{active:r===`table`,onClick:()=>i(`table`),icon:h,label:`Table`}),(0,R.jsx)(U,{active:r===`raw`,onClick:()=>i(`raw`),icon:f,label:`Raw`})]}),(0,R.jsx)(U,{active:a,onClick:o,icon:g,label:`Wrap`}),s&&c&&(0,R.jsx)(U,{active:!1,onClick:()=>j(c,s),icon:m,label:`Download`})]})}function be({open:e,defaultName:t,content:n,onSave:r,onCancel:i}){let[f,ee]=(0,L.useState)(t),[p,m]=(0,L.useState)(!1),[h,g]=(0,L.useState)(``),_=ie(e=>e.activeProject),v=(0,L.useCallback)(()=>{let e=f.trim();if(!e){g(`Filename cannot be empty`);return}if(/[/\\]/.test(e)){g(`Filename cannot contain / or \\`);return}g(``),m(!0)},[f]),y=(0,L.useCallback)(e=>{let t=e.includes(`\\`)?`\\`:`/`;r(e.endsWith(t)?`${e}${f.trim()}`:`${e}${t}${f.trim()}`,n)},[f,n,r]);return p?(0,R.jsx)(F,{open:!0,mode:`folder`,root:_?.path,title:`Save "${f.trim()}" to...`,onSelect:y,onCancel:()=>m(!1)}):(0,R.jsx)(s,{open:e,onOpenChange:e=>{e||i()},children:(0,R.jsxs)(l,{className:`sm:max-w-md`,children:[(0,R.jsx)(c,{children:(0,R.jsx)(u,{children:`Save As`})}),(0,R.jsxs)(`div`,{className:`flex flex-col gap-2 py-2`,children:[(0,R.jsx)(`label`,{className:`text-sm text-muted-foreground`,children:`Filename`}),(0,R.jsx)(d,{value:f,onChange:e=>{ee(e.target.value),g(``)},onKeyDown:e=>{e.key===`Enter`&&v()},placeholder:`e.g. my-file.ts`,autoFocus:!0}),h&&(0,R.jsx)(`p`,{className:`text-xs text-destructive`,children:h})]}),(0,R.jsxs)(a,{children:[(0,R.jsx)(o,{variant:`outline`,onClick:i,children:`Cancel`}),(0,R.jsx)(o,{onClick:v,children:`Choose Folder...`})]})]})})}var xe=(0,L.lazy)(()=>b(()=>import(`./markdown-renderer-Ckjp96ej.js`).then(e=>({default:e.MarkdownRenderer})),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]))),Se=(0,L.lazy)(()=>b(()=>import(`./csv-preview-D37K2LRd.js`).then(e=>({default:e.CsvPreview})),__vite__mapDeps([27,1,4,5,28,8,29,30]))),Ce=new Set([`png`,`jpg`,`jpeg`,`gif`,`webp`,`svg`,`ico`]),we=new Set([`db`,`sqlite`,`sqlite3`]);function Te(e){return e.split(`.`).pop()?.toLowerCase()??``}function Ee(e){return{js:`javascript`,jsx:`javascript`,ts:`typescript`,tsx:`typescript`,py:`python`,html:`html`,css:`css`,scss:`scss`,json:`json`,md:`markdown`,mdx:`markdown`,yaml:`yaml`,yml:`yaml`,sh:`shell`,bash:`shell`,sql:`sql`}[Te(e)]??`plaintext`}var W=(0,L.memo)(function({metadata:e,tabId:t}){let n=e?.filePath,r=e?.projectName,i=e?.inlineContent,a=e?.inlineLanguage,[o,s]=(0,L.useState)(i??null),[c,l]=(0,L.useState)(`utf-8`),[u,d]=(0,L.useState)(!0),[f,p]=(0,L.useState)(null),[m,h]=(0,L.useState)(!1),g=(0,L.useRef)(null),v=(0,L.useRef)(``),b=(0,L.useRef)(null),{tabs:ie,updateTab:S}=re(M(e=>({tabs:e.tabs,updateTab:e.updateTab}))),{wordWrap:C,toggleWordWrap:w}=te(M(e=>({wordWrap:e.wordWrap,toggleWordWrap:e.toggleWordWrap}))),T=fe(),D=e?.isUntitled===!0,O=e?.unsavedContent,[se,k]=(0,L.useState)(!1),A=ie.find(e=>e.id===t),j=n?Te(n):``,N=Ce.has(j),P=j===`pdf`,F=we.has(j),ce=j===`md`||j===`mdx`,le=j===`csv`,I=j===`sql`,[ue,ge]=(0,L.useState)(`preview`),[z,_e]=(0,L.useState)(`table`),{connections:B,cachedTables:V,refreshTables:H}=oe(),[U,xe]=(0,L.useState)(()=>{if(!I||!n)return null;let e=localStorage.getItem(`ppm:sql-conn:${n}`);return e?Number(e):null}),W=(0,L.useRef)(null),G=(0,L.useRef)(null),K=(0,L.useMemo)(()=>B.find(e=>e.id===U)??null,[B,U]),Ae=i!=null&&(a===`json`||a===`xml`),[q,J]=(0,L.useState)(!1),je=(0,L.useCallback)(()=>{if(i)if(q)s(i),J(!1);else{let e=i.trimStart();if(a===`json`)try{s(JSON.stringify(JSON.parse(e),null,2)),J(!0)}catch{}else if(a===`xml`){let t=0;s(e.replace(/(>)(<)(\/*)/g,`$1
3
- $2$3`).split(`
4
- `).map(e=>{let n=e.trim();n.startsWith(`</`)&&(t=Math.max(0,t-1));let r=` `.repeat(t)+n;return n.startsWith(`<`)&&!n.startsWith(`</`)&&!n.endsWith(`/>`)&&!n.includes(`</`)&&t++,r}).join(`
5
- `)),J(!0)}}},[i,a,q]),Me=(0,L.useCallback)(e=>{xe(e),n&&localStorage.setItem(`ppm:sql-conn:${n}`,String(e)),H(e).catch(()=>{})},[n,H]),Y=(0,L.useMemo)(()=>{if(!I||!U)return;let e=(V.get(U)??[]).map(e=>({name:e.tableName,schema:e.schemaName}));if(e.length!==0)return{tables:e,getColumns:async(e,t)=>y.get(`/api/db/connections/${U}/schema?table=${encodeURIComponent(e)}${t?`&schema=${encodeURIComponent(t)}`:``}`)}},[I,U,V]);(0,L.useEffect)(()=>{if(!(!W.current||!Y))return G.current?.dispose(),me(),G.current=W.current.languages.registerCompletionItemProvider(`sql`,pe(W.current,Y)),()=>{G.current?.dispose()}},[Y]);let Ne=re(e=>e.openTab),X=(0,L.useCallback)(e=>{K&&Ne({type:`database`,title:`${K.name} · Query`,projectId:null,closable:!0,metadata:{connectionId:K.id,connectionName:K.name,dbType:K.type,initialSql:e}})},[K,Ne]),Pe=(0,L.useCallback)(()=>{if(!b.current||!K)return;let e=b.current,t=e.getSelection();X(t&&!t.isEmpty()?e.getModel()?.getValueInRange(t)??e.getValue():e.getValue())},[K,X]),Z=(0,L.useRef)([]),Fe=(0,L.useRef)(X);Fe.current=X,(0,L.useEffect)(()=>()=>{Z.current.forEach(e=>e.dispose()),Z.current=[]},[]),(0,L.useEffect)(()=>{F&&t&&S(t,{type:`sqlite`})},[F,t,S]);let Q=n?/^(\/|[A-Za-z]:[/\\])/.test(n):!1;(0,L.useEffect)(()=>{if(i!=null){d(!1);return}if(D){s(O??``),v.current=O??``,d(!1),O&&h(!0);return}if(!n||!Q&&!r)return;if(N||P){d(!1);return}d(!0),p(null);let e=Q?`/api/fs/read?path=${encodeURIComponent(n)}`:`${_(r)}/files/read?path=${encodeURIComponent(n)}`;return y.get(e).then(e=>{s(e.content),e.encoding&&l(e.encoding),v.current=e.content,d(!1)}).catch(e=>{p(e instanceof Error?e.message:`Failed to load file`),d(!1)}),()=>{g.current&&clearTimeout(g.current)}},[n,r,N,P,Q,D]),(0,L.useEffect)(()=>{if(!A)return;let t=D?`Untitled-${e?.untitledNumber??1}`:n?x(n):`Untitled`,r=m?`${t} \u25CF`:t;A.title!==r&&S(A.id,{title:r})},[m]);let Ie=(0,L.useCallback)(async e=>{if(n&&!(!Q&&!r))try{Q?await y.put(`/api/fs/write`,{path:n,content:e}):await y.put(`${_(r)}/files/write`,{path:n,content:e}),h(!1)}catch{}},[n,r,Q]);function Le(n){let r=n??``;s(r),v.current=r,h(!0),g.current&&clearTimeout(g.current),D?g.current=setTimeout(()=>{t&&S(t,{metadata:{...e,unsavedContent:v.current}})},2e3):g.current=setTimeout(()=>Ie(v.current),1e3)}let Re=(0,L.useCallback)(async(e,n)=>{try{if(g.current&&clearTimeout(g.current),await y.put(`/api/fs/write`,{path:e,content:n}),t){let{closeTab:n,openTab:r}=ne.getState();n(t),r({type:`editor`,title:x(e),projectId:null,metadata:{filePath:e},closable:!0})}h(!1),k(!1)}catch{}},[t]),$=e?.lineNumber,ze=(0,L.useCallback)((e,t)=>{if(b.current=e,W.current=t,$&&$>0&&setTimeout(()=>{e.revealLineInCenter($),e.setPosition({lineNumber:$,column:1}),e.focus()},100),D&&e.addCommand(t.KeyMod.CtrlCmd|t.KeyCode.KeyS,()=>k(!0)),e.addCommand(t.KeyMod.Alt|t.KeyCode.KeyZ,()=>te.getState().toggleWordWrap()),t.languages.typescript.typescriptDefaults.setDiagnosticsOptions({noSemanticValidation:!0,noSyntaxValidation:!0,noSuggestionDiagnostics:!0}),t.languages.typescript.javascriptDefaults.setDiagnosticsOptions({noSemanticValidation:!0,noSyntaxValidation:!0,noSuggestionDiagnostics:!0}),Y&&(G.current?.dispose(),G.current=t.languages.registerCompletionItemProvider(`sql`,pe(t,Y))),I){Z.current.forEach(e=>e.dispose()),Z.current=[];let n=e.getModel(),r=e.addCommand(0,(e,t)=>{t&&Fe.current(t)});if(r&&n){let e=t.languages.registerCodeLensProvider(`sql`,{provideCodeLenses:e=>{if(e!==n)return{lenses:[],dispose:()=>{}};let t=[],i=e.getValue().split(`
6
- `),a=-1,o=[],s=!1,c=(e,n)=>{let i=n.trim();!i||i.startsWith(`--`)||t.push({range:{startLineNumber:e,startColumn:1,endLineNumber:e,endColumn:1},command:{id:r,title:`▷ Run`,arguments:[i]}})};for(let e=0;e<i.length;e++){let t=i[e].trim();if(a===-1){if(!t||t.startsWith(`--`))continue;a=e+1,o=[]}o.push(i[e]),(t.match(/\$\$/g)||[]).length%2==1&&(s=!s),!s&&t.endsWith(`;`)&&(c(a,o.join(`
7
- `)),a=-1,o=[])}return a>0&&o.join(``).trim()&&c(a,o.join(`
8
- `)),{lenses:t,dispose:()=>{}}}});Z.current.push(e)}}},[Y]);if(!i&&!D&&(!n||!Q&&!r))return(0,R.jsx)(`div`,{className:`flex items-center justify-center h-full text-text-secondary text-sm`,children:`No file selected.`});if(u)return(0,R.jsxs)(`div`,{className:`flex items-center justify-center h-full gap-2 text-text-secondary`,children:[(0,R.jsx)(E,{className:`size-5 animate-spin`}),(0,R.jsx)(`span`,{className:`text-sm`,children:`Loading file...`})]});if(f)return(0,R.jsx)(`div`,{className:`flex items-center justify-center h-full text-error text-sm`,children:f});if(N)return(0,R.jsx)(Oe,{filePath:n,projectName:r});if(P)return(0,R.jsx)(ke,{filePath:n,projectName:r});if(c===`base64`)return(0,R.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-3 text-text-secondary`,children:[(0,R.jsx)(he,{className:`size-10 text-text-subtle`}),(0,R.jsx)(`p`,{className:`text-sm`,children:`This file is a binary format and cannot be displayed.`}),(0,R.jsx)(`p`,{className:`text-xs text-text-subtle`,children:n})]});let Be=I?(0,R.jsxs)(`div`,{className:`shrink-0 flex items-center gap-1 px-2 border-l border-border`,children:[(0,R.jsx)(ee,{className:`size-3 text-muted-foreground`}),(0,R.jsxs)(`select`,{value:U??``,onChange:e=>{let t=Number(e.target.value);t&&Me(t)},className:`h-5 text-[10px] bg-transparent border border-border rounded px-1 text-foreground outline-none max-w-[140px]`,title:`Select connection for autocomplete`,children:[(0,R.jsx)(`option`,{value:``,children:`Connection…`}),B.map(e=>(0,R.jsx)(`option`,{value:e.id,children:e.name},e.id))]}),(0,R.jsx)(`button`,{type:`button`,onClick:Pe,disabled:!K,className:`p-0.5 rounded text-muted-foreground hover:text-primary disabled:opacity-30 transition-colors`,title:`Run all in DB Viewer`,children:(0,R.jsx)(ae,{className:`size-3.5`})})]}):null;return(0,R.jsxs)(`div`,{className:`flex flex-col h-full w-full overflow-hidden`,children:[i!=null&&Ae&&(0,R.jsx)(`div`,{className:`flex items-center h-7 border-b border-border bg-background shrink-0 px-2 gap-2`,children:(0,R.jsx)(`button`,{type:`button`,onClick:je,className:`text-[10px] px-2 py-0.5 rounded border border-border hover:bg-muted transition-colors text-foreground`,children:q?`Raw`:`Beautify`})}),n&&r&&t&&(0,R.jsxs)(`div`,{className:`hidden md:flex items-center h-7 border-b border-border bg-background shrink-0`,children:[(0,R.jsx)(ve,{filePath:n,projectName:r,tabId:t,className:`flex items-center flex-1 min-w-0 overflow-x-auto scrollbar-none px-2 gap-0.5`}),Be,(0,R.jsx)(ye,{ext:j,mdMode:ue,onMdModeChange:ge,csvMode:z,onCsvModeChange:_e,wordWrap:C,onToggleWordWrap:w,filePath:n,projectName:r,className:`shrink-0 flex items-center gap-1 px-2`})]}),I&&(!r||!t)&&(0,R.jsxs)(`div`,{className:`hidden md:flex items-center h-7 border-b border-border bg-background shrink-0 px-2`,children:[(0,R.jsx)(`span`,{className:`text-xs text-muted-foreground truncate flex-1`,children:n?x(n):`SQL`}),Be]}),le&&z===`table`?(0,R.jsx)(L.Suspense,{fallback:(0,R.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,R.jsx)(E,{className:`size-5 animate-spin text-text-subtle`})}),children:(0,R.jsx)(Se,{content:o??``,onContentChange:Le,wordWrap:C})}):ce&&ue===`preview`?(0,R.jsx)(De,{content:o??``}):(0,R.jsx)(`div`,{className:`flex-1 overflow-hidden`,children:(0,R.jsx)(de,{height:`100%`,language:a??Ee(n??``),value:o??``,onChange:i==null?Le:void 0,onMount:ze,theme:T,options:{fontSize:13,fontFamily:`Menlo, Monaco, Consolas, monospace`,wordWrap:C?`on`:`off`,minimap:{enabled:!1},scrollBeyondLastLine:!1,automaticLayout:!0,lineNumbers:`on`,folding:!0,bracketPairColorization:{enabled:!0},readOnly:i!=null},loading:(0,R.jsx)(E,{className:`size-5 animate-spin text-text-subtle`})})}),se&&(0,R.jsx)(be,{open:se,defaultName:`Untitled-${e?.untitledNumber??1}`,content:v.current,onSave:Re,onCancel:()=>k(!1)})]})});function De({content:e}){return(0,R.jsx)(L.Suspense,{fallback:(0,R.jsx)(`div`,{className:`animate-pulse h-4 bg-muted rounded m-4`}),children:(0,R.jsx)(xe,{content:e,className:`flex-1 overflow-auto p-4`})})}function Oe({filePath:e,projectName:t}){let[n,r]=(0,L.useState)(null),[i,a]=(0,L.useState)(!1);return(0,L.useEffect)(()=>{let n,i=`${_(t)}/files/raw?path=${encodeURIComponent(e)}`,o=v();return fetch(i,{headers:o?{Authorization:`Bearer ${o}`}:{}}).then(e=>{if(!e.ok)throw Error(`Failed`);return e.blob()}).then(e=>{let t=URL.createObjectURL(e);n=t,r(t)}).catch(()=>a(!0)),()=>{n&&URL.revokeObjectURL(n)}},[e,t]),i?(0,R.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-3 text-text-secondary`,children:[(0,R.jsx)(he,{className:`size-10 text-text-subtle`}),(0,R.jsx)(`p`,{className:`text-sm`,children:`Failed to load image.`})]}):n?(0,R.jsx)(`div`,{className:`flex items-center justify-center h-full p-4 bg-surface overflow-auto`,children:(0,R.jsx)(`img`,{src:n,alt:e,className:`max-w-full max-h-full object-contain`})}):(0,R.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,R.jsx)(E,{className:`size-5 animate-spin text-text-subtle`})})}function ke({filePath:e,projectName:t}){let[n,r]=(0,L.useState)(null),[i,a]=(0,L.useState)(!1);(0,L.useEffect)(()=>{let n,i=`${_(t)}/files/raw?path=${encodeURIComponent(e)}`,o=v();return fetch(i,{headers:o?{Authorization:`Bearer ${o}`}:{}}).then(e=>{if(!e.ok)throw Error(`Failed`);return e.blob()}).then(e=>{let t=URL.createObjectURL(new Blob([e],{type:`application/pdf`}));n=t,r(t)}).catch(()=>a(!0)),()=>{n&&URL.revokeObjectURL(n)}},[e,t]);let o=(0,L.useCallback)(()=>{n&&window.open(n,`_blank`)},[n]);return i?(0,R.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-3 text-text-secondary`,children:[(0,R.jsx)(he,{className:`size-10 text-text-subtle`}),(0,R.jsx)(`p`,{className:`text-sm`,children:`Failed to load PDF.`})]}):n?(0,R.jsxs)(`div`,{className:`flex flex-col h-full`,children:[(0,R.jsxs)(`div`,{className:`flex items-center justify-between px-3 py-1.5 border-b border-border bg-background shrink-0`,children:[(0,R.jsx)(`span`,{className:`text-xs text-text-secondary truncate`,children:e}),(0,R.jsxs)(`button`,{onClick:o,className:`flex items-center gap-1 text-xs text-text-secondary hover:text-text-primary transition-colors`,children:[(0,R.jsx)(S,{className:`size-3`}),` Open in new tab`]})]}),(0,R.jsx)(`iframe`,{src:n,title:e,className:`flex-1 w-full border-none`})]}):(0,R.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,R.jsx)(E,{className:`size-5 animate-spin text-text-subtle`})})}export{W as CodeEditor};