gitwarren 0.1.7

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.
@@ -0,0 +1 @@
1
+ class o extends Error{code;fieldErrors;constructor(r,t,s){super(t),this.name="AppError",this.code=r,s&&(this.fieldErrors=s)}toSerialized(){return{code:this.code,message:this.message,...this.fieldErrors?{fieldErrors:this.fieldErrors}:{}}}static from(r){if(r instanceof o)return r;const t=r instanceof Error?r.message:String(r);return new o("INTERNAL",t)}}function h(e){return new o(e.code,e.message,e.fieldErrors)}const A={reviewsChanged:"reviews.changed",commentsChanged:"comments.changed",hostState:"host.state"};function U(e){return"event"in e}const $=new Set(["app.instance","app.mcp","hosts.list","hosts.get","hosts.distros","hosts.discover","hosts.tailnet","fs.list","repositories.list","repositories.get","repositories.refs","reviews.list","reviews.open","reviews.get","reviews.commits","reviews.diff","reviews.tree","reviews.file","reviews.image","reviews.filePath","reviews.reviewedFiles","comments.list","attachments.read"]);function _(e){return $.has(e)}function C(e){if("error"in e)throw h(e.error);return e.result}async function M(e){try{return{result:await e()}}catch(r){return{error:o.from(r).toSerialized()}}}const u="gitwarren://attachment/",p=/^[a-f0-9]{64}\.[a-z0-9]{2,4}$/;function H(e){if(!e.startsWith(u))return null;const r=e.slice(u.length);return p.test(r)?r:null}const y="host";function O(e){return e.editorTarget!==null?e.editorTarget:e.kind==="wsl"?`wsl+${e.target}`:`ssh-remote+${e.target}`}const c=[{id:"vscode",label:"VS Code",url:(e,r)=>`vscode://file${encodeURI(e)}:${r}`,remoteUrl:(e,r,t)=>`vscode://vscode-remote/${encodeURI(e)}${encodeURI(r)}:${t}`},{id:"cursor",label:"Cursor",url:(e,r)=>`cursor://file${encodeURI(e)}:${r}`,remoteUrl:(e,r,t)=>`cursor://vscode-remote/${encodeURI(e)}${encodeURI(r)}:${t}`},{id:"windsurf",label:"Windsurf",url:(e,r)=>`windsurf://file${encodeURI(e)}:${r}`,remoteUrl:(e,r,t)=>`windsurf://vscode-remote/${encodeURI(e)}${encodeURI(r)}:${t}`},{id:"zed",label:"Zed",url:(e,r)=>`zed://file${encodeURI(e)}:${r}`},{id:"sublime",label:"Sublime Text",url:(e,r)=>`subl://open?url=file://${encodeURIComponent(e)}&line=${r}`},{id:"jetbrains",label:"JetBrains IDE"}];function P(e){return e===void 0?void 0:c.find(r=>r.id===e)}function L(){return c.filter(e=>e.url!==void 0).map(({id:e,label:r})=>({id:e,label:r}))}function w(e){return e==="custom"?!0:c.some(r=>r.id===e&&"remoteUrl"in r)}function k(e){const r=e.editors.filter(s=>w(s.id)),t=e.defaultId!==null&&r.some(s=>s.id===e.defaultId)?e.defaultId:r[0]?.id??null;return{editors:r,defaultId:t}}const E=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;function I(e){return E.test(e)}const T=["conversation","commits","files","browse"],f={name:"repositories"},l="h",m="agent",v="hosts";function R(e){return e.host===void 0?"":`${l}/${e.host}/`}function F(e){const r=R(e);switch(e.name){case"repositories":return`#/${r}`;case"agent":return`#/${r}${m}`;case"hosts":return`#/${v}`;case"repository":return`#/${r}repositories/${e.repositoryId}`;case"review":{const t=`#/${r}reviews/${e.reviewId}/${e.tab}`;if(!e.focus)return t;const{filePath:s,side:i,line:n}=e.focus,a=i===void 0||n===void 0?"":`/${i}/${n}`;return`${t}/${encodeURIComponent(s)}${a}`}}}function b(e){return T.includes(e)}function g(e){return e===""||e.startsWith("/")||e.startsWith("\\")||/^[a-zA-Z]:/.test(e)?!1:!e.split(/[\\/]/).includes("..")}function N(e){const[r,t,s]=e;if(!r)return;let i;try{i=decodeURIComponent(r)}catch{return}if(!g(i))return;if(t===void 0&&s===void 0)return{filePath:i};if(t!=="base"&&t!=="head")return;const n=Number(s);if(!(!Number.isInteger(n)||n<=0))return{filePath:i,side:t,line:n}}function S(e){if(e[0]!==l)return{rest:e};const r=e[1];return r===void 0||!I(r)?{rest:e}:{host:r,rest:e.slice(2)}}function x(e){const r=e.replace(/^#\/?/,"").split("/").filter(Boolean),{host:t,rest:s}=S(r),i=t===void 0?{}:{host:t};if(s.length===0)return t===void 0?f:{name:"repositories",host:t};if(s[0]===m)return{name:"agent",...i};if(s[0]===v)return{name:"hosts"};if(s[0]==="repositories"&&s[1]){const n=Number(s[1]);if(Number.isInteger(n)&&n>0)return{name:"repository",repositoryId:n,...i}}if(s[0]==="reviews"&&s[1]){const n=Number(s[1]);if(Number.isInteger(n)&&n>0){const a=b(s[2])?s[2]:"conversation",d=N(s.slice(3));return d?{name:"review",reviewId:n,tab:a,focus:d,...i}:{name:"review",reviewId:n,tab:a,...i}}}return t===void 0?f:{name:"repositories",host:t}}export{y as A,f as H,T as R,H as a,U as b,o as c,O as d,P as e,I as f,p as g,F as h,_ as i,u as j,k,L as l,A as m,M as o,x as p,C as r};
package/web/index.html ADDED
@@ -0,0 +1,76 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <!--
6
+ `interactive-widget=resizes-content` is the whole of the keyboard fix, and
7
+ it is here rather than in the Electron document because a window has no
8
+ on-screen keyboard to be resized by.
9
+
10
+ The default, `resizes-visual`, leaves the layout viewport at its full
11
+ height when the keyboard opens and shrinks only the visual one, so the
12
+ page is unchanged and merely partly hidden behind the keyboard. That is a
13
+ sensible default for a document that scrolls in the window - the browser
14
+ pans it and everything is reachable - and it is the wrong one here,
15
+ because this app scrolls inside `<main>` and the window itself never
16
+ scrolls at all. A pan cannot move content within a scroller, so the
17
+ composer stayed under the keyboard with no gesture able to retrieve it.
18
+
19
+ `resizes-content` shrinks the layout viewport instead. The `height: 100%`
20
+ chain in `index.css` comes down with it, `<main>` becomes a shorter
21
+ scrollport, and there is somewhere for the composer to be scrolled to -
22
+ which `lib/keyboard-inset.ts` then does.
23
+ -->
24
+ <meta
25
+ name="viewport"
26
+ content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
27
+ />
28
+ <!--
29
+ The same lockdown as the Electron window, with one difference that is the
30
+ whole of M3 in a header.
31
+
32
+ `connect-src 'self'` still means "this origin and nothing else", and in a
33
+ browser that now has to cover the WebSocket as well: CSP level 3 matches a
34
+ same-origin `ws://` against `'self'`, which is exactly the carrier this
35
+ shell uses and exactly nothing more. No remote origin can be reached from
36
+ this page whatever a comment body asks for.
37
+
38
+ `img-src` keeps `data:` - image diffs arrive as data URLs from
39
+ `reviews.image` - and drops the `gitwarren:` scheme, which is a custom
40
+ protocol only the Electron main process serves. Attachments reach this
41
+ shell over HTTP instead, from `/gitwarren/attachments/…` on this very
42
+ origin, so `'self'` already covers them and no source had to be added.
43
+ Note what is still absent: no remote `img-src`, so an image in a comment
44
+ body cannot reach the network in a tab either.
45
+ -->
46
+ <meta
47
+ http-equiv="Content-Security-Policy"
48
+ content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'"
49
+ />
50
+ <!--
51
+ The tab icon, and the reason it is a `<link>` rather than a file dropped
52
+ at the root.
53
+
54
+ A browser with no declared icon asks for `/favicon.ico` on its own, and
55
+ every verification of this shell since M3.2 has recorded that request
56
+ 404ing - the one failed request in an otherwise clean run, in a project
57
+ where "no failed requests" is the thing being checked. Answering the probe
58
+ would mean serving a root path the daemon owns and the app does not: the
59
+ app mounts this build at `/app/`, so `/favicon.ico` there belongs to the
60
+ link server, and a build that depends on a sibling route being answered
61
+ for it is a build that is wrong in one of its two mounts. Naming the icon
62
+ here instead means the probe never happens: the document says what its
63
+ icon is before the browser has to guess.
64
+
65
+ Relative, like every other asset in this build, so it resolves under `/`
66
+ and under `/app/` alike - see the note on `base` in vite.web.config.ts.
67
+ -->
68
+ <link rel="icon" type="image/png" href="./assets/favicon-CjI0QwVD.png" />
69
+ <title>GitWarren</title>
70
+ <script type="module" crossorigin src="./assets/index-CGYJoNWO.js"></script>
71
+ <link rel="modulepreload" crossorigin href="./assets/routes-DFoqib84.js">
72
+ </head>
73
+ <body>
74
+ <div id="root"></div>
75
+ </body>
76
+ </html>