github-stars-organizer 1.3.2 → 1.4.0

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 (26) hide show
  1. package/dist/app/assets/{backups-DrK5WGqD.js → backups-DUiBIjYh.js} +1 -1
  2. package/dist/app/assets/{badge-Drt9JvOu.js → badge-CVyqIkfu.js} +1 -1
  3. package/dist/app/assets/button-srM_gVNp.js +14 -0
  4. package/dist/app/assets/{coerce-Cxjr6MIU.js → coerce-hGm-kFoB.js} +1 -1
  5. package/dist/app/assets/explore-DfJsTl1a.js +33 -0
  6. package/dist/app/assets/{history-CN5yGwhZ.js → history-BeQkAZPX.js} +1 -1
  7. package/dist/app/assets/index-CEpF9MZu.css +2 -0
  8. package/dist/app/assets/index-Z9aIL5Tz.js +10 -0
  9. package/dist/app/assets/list._listId-BthjMh8l.js +2 -0
  10. package/dist/app/assets/{list._listId-DBB3l--n.js → list._listId-QMOV--8Q.js} +1 -1
  11. package/dist/app/assets/{local-backups-DLhiWDk4.js → local-backups-BlLTb6g5.js} +1 -1
  12. package/dist/app/assets/{local-sync-DiQe8mhd.js → local-sync-Cp5d59-N.js} +1 -1
  13. package/dist/app/assets/{registry-BKf8LDk2.js → registry-CDScSFs0.js} +2 -2
  14. package/dist/app/assets/{routes-BYr-dng4.js → routes-8llA2c3j.js} +2 -2
  15. package/dist/app/assets/{routes-DaKmAWCG.js → routes-CIYRvBg6.js} +2 -2
  16. package/dist/app/assets/{schemas-DVvZEnxp.js → schemas-CLMWt96T.js} +2 -2
  17. package/dist/app/assets/{star-BPue5Y4t.js → star-D-XjWe95.js} +1 -1
  18. package/dist/app/assets/{triangle-alert-BL8M65pd.js → triangle-alert-ILMBIuGB.js} +1 -1
  19. package/dist/app/index.html +9 -9
  20. package/dist/cli.js +167 -6
  21. package/package.json +1 -1
  22. package/dist/app/assets/button-r9cVFa0_.js +0 -14
  23. package/dist/app/assets/explore-Da5fm3tF.js +0 -33
  24. package/dist/app/assets/index-BuYchyhs.js +0 -10
  25. package/dist/app/assets/index-dVYqSW2P.css +0 -2
  26. package/dist/app/assets/list._listId-CNuYrPaQ.js +0 -2
@@ -1,3 +1,3 @@
1
- import{B as e,H as t,J as n,K as r,R as i,V as a,W as o,it as s,n as c,nt as l,q as u,st as d,t as f,z as p}from"./button-r9cVFa0_.js";import{n as m}from"./star-BPue5Y4t.js";import{S as h,i as g,n as _,r as v}from"./coerce-Cxjr6MIU.js";import{E as y,S as b,T as x,_ as S,a as ee,b as C,c as te,d as ne,f as re,h as ie,i as ae,l as oe,m as w,n as T,o as se,p as ce,r as le,s as ue,t as E,u as de,v as fe,w as D,x as pe,y as me}from"./registry-BKf8LDk2.js";import{d as O,f as k,l as A,o as j,p as he,s as M,t as N,u as P}from"./local-backups-DLhiWDk4.js";import{t as F}from"./badge-Drt9JvOu.js";import{i as ge,n as _e,r as I,t as L}from"./routes-DaKmAWCG.js";import{t as ve}from"./triangle-alert-BL8M65pd.js";import{c as R,o as ye,r as z,s as B}from"./schemas-DVvZEnxp.js";import{n as be,t as V}from"./local-sync-DiQe8mhd.js";var xe=i(`bot`,[[`path`,{d:`M12 8V4H8`,key:`hb8ula`}],[`rect`,{width:`16`,height:`12`,x:`4`,y:`8`,rx:`2`,key:`enze0r`}],[`path`,{d:`M2 14h2`,key:`vft8re`}],[`path`,{d:`M20 14h2`,key:`4cs60a`}],[`path`,{d:`M15 13v2`,key:`1xurst`}],[`path`,{d:`M9 13v2`,key:`rq6x2g`}]]),Se=i(`chevron-down`,[[`path`,{d:`m6 9 6 6 6-6`,key:`qrunsl`}]]),Ce=i(`copy`,[[`rect`,{width:`14`,height:`14`,x:`8`,y:`8`,rx:`2`,ry:`2`,key:`17jyea`}],[`path`,{d:`M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2`,key:`zix9uf`}]]),we=i(`key-round`,[[`path`,{d:`M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z`,key:`1s6t7t`}],[`circle`,{cx:`16.5`,cy:`7.5`,r:`.5`,fill:`currentColor`,key:`w0ekpg`}]]),H=i(`sticky-note`,[[`path`,{d:`M21 9a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 15 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2z`,key:`1dfntj`}],[`path`,{d:`M15 3v5a1 1 0 0 0 1 1h5`,key:`6s6qgf`}]]),U=d(s(),1);function Te(e,t){return{lists:e.map(e=>({id:e.id,github_list_id:e.id,name:e.name,description:e.description,is_private:!1,created_at:e.createdAt,updated_at:e.updatedAt})),list_items:e.flatMap(e=>e.repoGithubIds.flatMap((n,r)=>{let i=t.get(n);return i?[{id:`${e.id}:${i}`,list_id:e.id,repo_id:i,position:r,added_at:e.updatedAt}]:[]}))}}var Ee=5;async function De(e){try{let t=await fetch(`/api/lists?user=${encodeURIComponent(e)}`);return t.ok?(await t.json()).lists:null}catch{return null}}async function Oe(n,r){let i=De(n),o=[];for(let e=1;e<=Ee;e++){let t=await fetch(`https://api.github.com/users/${encodeURIComponent(n)}/starred?per_page=100&page=${e}`,{headers:{Accept:`application/vnd.github.star+json`}});if(t.status===404)throw Error(`No GitHub user called ${n}.`);if(t.status===403||t.status===429)throw Error(`GitHub's limit for signed-out requests is 60 an hour. Try again later, or self-host it.`);if(!t.ok)throw Error(`GitHub returned ${t.status}.`);let i=await t.json();if(o.push(...i),r(`Read ${o.length} stars...`),i.length<100)break}if(o.length===0)throw Error(`${n} hasn't starred anything public.`);let s=new Date().toISOString(),c=o.map(({starred_at:e,repo:t})=>({id:String(t.id),github_id:t.id,node_id:t.node_id,name:t.name,full_name:t.full_name,owner:t.owner.login,description:t.description,url:t.html_url,homepage:t.homepage||null,language:t.language,stars:t.stargazers_count,forks:t.forks_count,topics:t.topics?.length?t.topics.join(`,`):null,starred_at:e,notes:null,usefulness_rating:null,imported_at:s,health_score:null,health_data:null,health_refreshed_at:null,is_archived:t.archived,pushed_at:t.pushed_at,created_at:t.created_at}));for(let n of[t,e,p,a]){let e=[...n.keys()];e.length>0&&n.delete(e)}a.insert(c),r(`Reading Lists...`);let l=await i;if(l===null)return{stars:c.length,lists:`unavailable`};let u=Te(l,new Map(c.map(e=>[e.github_id,e.id])));return u.lists.length>0&&p.insert(u.lists),u.list_items.length>0&&e.insert(u.list_items),{stars:c.length,lists:u.lists.length}}var W=l();function ke(){let[e,t]=(0,U.useState)(``),[r,i]=(0,U.useState)(n),[a,o]=(0,U.useState)(!1),[s,c]=(0,U.useState)(``);async function l(){let n=e.trim().replace(/^@/,``);if(n){o(!0),c(`Reading stars...`);try{let e=await Oe(n,c);i(n),t(``),c(e.lists===`unavailable`?`${e.stars} recent stars from @${n}. Couldn't read their Lists.`:`${e.stars} recent stars and ${e.lists} Lists from @${n}.`)}catch(e){c(e instanceof Error?e.message:`Couldn't read those stars.`)}finally{o(!1)}}}return(0,W.jsxs)(`div`,{className:`flex flex-col gap-1.5 sm:items-end`,children:[(0,W.jsxs)(`form`,{onSubmit:e=>{e.preventDefault(),l()},className:`flex w-full items-center gap-2 sm:w-auto`,children:[(0,W.jsx)(h,{value:e,onChange:e=>t(e.target.value),placeholder:`Any GitHub username`,"aria-label":`GitHub username`,autoCapitalize:`none`,autoCorrect:`off`,spellCheck:!1,enterKeyHint:`go`,className:`h-10 min-w-0 flex-1 sm:h-9 sm:w-48 sm:flex-none`}),(0,W.jsx)(f,{type:`submit`,className:`h-10 sm:h-9`,disabled:a||!e.trim(),children:a?`Loading...`:`Load`})]}),(0,W.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:s||(r?`Showing @${r}`:``)})]})}var Ae=z(B({repo_id:ye().int(),notes:R().nullish(),tags:z(B({name:R()})).default([])})),G=class extends Error{};function je(e){let t=Ae.safeParse(e);if(!t.success)throw new G(`This file isn't an Astral export. In Astral, open Settings and press Export to get one.`);if(t.data.length===0)throw new G(`This Astral export is empty. Astral only exports stars that have a tag or a note.`);return t.data}var Me=`Astral tags: `;function Ne(e){let t=e.tags.map(e=>e.name.trim()).filter(Boolean);return[...new Map(t.map(e=>[e.toLowerCase(),e])).values()]}function Pe(e,t){let n=e?.trim()??``,r=t.filter(e=>e&&!n.includes(e));return r.length===0?null:[n,...r].filter(Boolean).join(`
1
+ import{B as e,H as t,J as n,K as r,R as i,V as a,W as o,it as s,lt as c,n as l,ot as u,q as d,t as f,z as p}from"./button-srM_gVNp.js";import{n as m}from"./star-D-XjWe95.js";import{S as h,i as g,n as _,r as v}from"./coerce-hGm-kFoB.js";import{E as y,S as b,T as x,_ as S,a as ee,b as C,c as te,d as ne,f as re,h as ie,i as ae,l as oe,m as w,n as T,o as se,p as ce,r as le,s as ue,t as E,u as de,v as fe,w as D,x as pe,y as me}from"./registry-CDScSFs0.js";import{d as O,f as k,l as A,o as j,p as he,s as M,t as N,u as P}from"./local-backups-BlLTb6g5.js";import{t as F}from"./badge-CVyqIkfu.js";import{i as ge,n as _e,r as I,t as L}from"./routes-CIYRvBg6.js";import{t as ve}from"./triangle-alert-ILMBIuGB.js";import{c as R,o as ye,r as z,s as B}from"./schemas-CLMWt96T.js";import{n as be,t as V}from"./local-sync-Cp5d59-N.js";var xe=i(`bot`,[[`path`,{d:`M12 8V4H8`,key:`hb8ula`}],[`rect`,{width:`16`,height:`12`,x:`4`,y:`8`,rx:`2`,key:`enze0r`}],[`path`,{d:`M2 14h2`,key:`vft8re`}],[`path`,{d:`M20 14h2`,key:`4cs60a`}],[`path`,{d:`M15 13v2`,key:`1xurst`}],[`path`,{d:`M9 13v2`,key:`rq6x2g`}]]),Se=i(`chevron-down`,[[`path`,{d:`m6 9 6 6 6-6`,key:`qrunsl`}]]),Ce=i(`copy`,[[`rect`,{width:`14`,height:`14`,x:`8`,y:`8`,rx:`2`,ry:`2`,key:`17jyea`}],[`path`,{d:`M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2`,key:`zix9uf`}]]),we=i(`key-round`,[[`path`,{d:`M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z`,key:`1s6t7t`}],[`circle`,{cx:`16.5`,cy:`7.5`,r:`.5`,fill:`currentColor`,key:`w0ekpg`}]]),H=i(`sticky-note`,[[`path`,{d:`M21 9a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 15 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2z`,key:`1dfntj`}],[`path`,{d:`M15 3v5a1 1 0 0 0 1 1h5`,key:`6s6qgf`}]]),U=c(u(),1);function Te(e,t){return{lists:e.map(e=>({id:e.id,github_list_id:e.id,name:e.name,description:e.description,is_private:!1,created_at:e.createdAt,updated_at:e.updatedAt})),list_items:e.flatMap(e=>e.repoGithubIds.flatMap((n,r)=>{let i=t.get(n);return i?[{id:`${e.id}:${i}`,list_id:e.id,repo_id:i,position:r,added_at:e.updatedAt}]:[]}))}}var Ee=5;async function De(e){try{let t=await fetch(`/api/lists?user=${encodeURIComponent(e)}`);return t.ok?(await t.json()).lists:null}catch{return null}}async function Oe(n,r){let i=De(n),o=[];for(let e=1;e<=Ee;e++){let t=await fetch(`https://api.github.com/users/${encodeURIComponent(n)}/starred?per_page=100&page=${e}`,{headers:{Accept:`application/vnd.github.star+json`}});if(t.status===404)throw Error(`No GitHub user called ${n}.`);if(t.status===403||t.status===429)throw Error(`GitHub's limit for signed-out requests is 60 an hour. Try again later, or self-host it.`);if(!t.ok)throw Error(`GitHub returned ${t.status}.`);let i=await t.json();if(o.push(...i),r(`Read ${o.length} stars...`),i.length<100)break}if(o.length===0)throw Error(`${n} hasn't starred anything public.`);let s=new Date().toISOString(),c=o.map(({starred_at:e,repo:t})=>({id:String(t.id),github_id:t.id,node_id:t.node_id,name:t.name,full_name:t.full_name,owner:t.owner.login,description:t.description,url:t.html_url,homepage:t.homepage||null,language:t.language,stars:t.stargazers_count,forks:t.forks_count,topics:t.topics?.length?t.topics.join(`,`):null,starred_at:e,notes:null,usefulness_rating:null,imported_at:s,health_score:null,health_data:null,health_refreshed_at:null,is_archived:t.archived,pushed_at:t.pushed_at,created_at:t.created_at}));for(let n of[t,e,p,a]){let e=[...n.keys()];e.length>0&&n.delete(e)}a.insert(c),r(`Reading Lists...`);let l=await i;if(l===null)return{stars:c.length,lists:`unavailable`};let u=Te(l,new Map(c.map(e=>[e.github_id,e.id])));return u.lists.length>0&&p.insert(u.lists),u.list_items.length>0&&e.insert(u.list_items),{stars:c.length,lists:u.lists.length}}var W=s();function ke(){let[e,t]=(0,U.useState)(``),[r,i]=(0,U.useState)(n),[a,o]=(0,U.useState)(!1),[s,c]=(0,U.useState)(``);async function l(){let n=e.trim().replace(/^@/,``);if(n){o(!0),c(`Reading stars...`);try{let e=await Oe(n,c);i(n),t(``),c(e.lists===`unavailable`?`${e.stars} recent stars from @${n}. Couldn't read their Lists.`:`${e.stars} recent stars and ${e.lists} Lists from @${n}.`)}catch(e){c(e instanceof Error?e.message:`Couldn't read those stars.`)}finally{o(!1)}}}return(0,W.jsxs)(`div`,{className:`flex flex-col gap-1.5 sm:items-end`,children:[(0,W.jsxs)(`form`,{onSubmit:e=>{e.preventDefault(),l()},className:`flex w-full items-center gap-2 sm:w-auto`,children:[(0,W.jsx)(h,{value:e,onChange:e=>t(e.target.value),placeholder:`Any GitHub username`,"aria-label":`GitHub username`,autoCapitalize:`none`,autoCorrect:`off`,spellCheck:!1,enterKeyHint:`go`,className:`h-10 min-w-0 flex-1 sm:h-9 sm:w-48 sm:flex-none`}),(0,W.jsx)(f,{type:`submit`,className:`h-10 sm:h-9`,disabled:a||!e.trim(),children:a?`Loading...`:`Load`})]}),(0,W.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:s||(r?`Showing @${r}`:``)})]})}var Ae=z(B({repo_id:ye().int(),notes:R().nullish(),tags:z(B({name:R()})).default([])})),G=class extends Error{};function je(e){let t=Ae.safeParse(e);if(!t.success)throw new G(`This file isn't an Astral export. In Astral, open Settings and press Export to get one.`);if(t.data.length===0)throw new G(`This Astral export is empty. Astral only exports stars that have a tag or a note.`);return t.data}var Me=`Astral tags: `;function Ne(e){let t=e.tags.map(e=>e.name.trim()).filter(Boolean);return[...new Map(t.map(e=>[e.toLowerCase(),e])).values()]}function Pe(e,t){let n=e?.trim()??``,r=t.filter(e=>e&&!n.includes(e));return r.length===0?null:[n,...r].filter(Boolean).join(`
2
2
 
3
- `)}function K(e,t,n){let r=new Map(t.repos.map(e=>[e.github_id,e])),i=new Map(t.lists.map(e=>[e.name.toLowerCase(),e])),a=new Set(t.list_items.map(e=>`${e.list_id}:${e.repo_id}`)),o=new Set([...n].map(e=>e.toLowerCase())),s=new Map,c=[],l=0;for(let t of e){let e=r.get(t.repo_id);if(!e){l++;continue}let n=Ne(t);for(let t of n){let n=t.toLowerCase(),r=s.get(n);r||(r={name:t,existingList:i.get(n)??null,toAdd:[],starred:0},s.set(n,r)),r.starred++,(!r.existingList||!a.has(`${r.existingList.id}:${e.id}`))&&r.toAdd.push(e)}let u=n.filter(e=>!o.has(e.toLowerCase())),d=Pe(e.notes,[t.notes?.trim()??``,u.length?`${Me}${u.join(`, `)}`:``]);d!==null&&c.push({repo:e,notes:d})}return{tags:[...s.values()].sort((e,t)=>t.starred-e.starred||e.name.localeCompare(t.name)),notes:c,notStarred:l,listSlots:Math.max(0,32-t.lists.length)}}function Fe(e){let t=new Set,n=e.listSlots;for(let r of e.tags)r.existingList?t.add(r.name):n>0&&(t.add(r.name),n--);return t}function q(e,t){return e.tags.filter(e=>t.has(e.name)&&!e.existingList).length}function J(e){return e instanceof Error?e.message:String(e)}async function Ie(e,t,n,r=()=>{}){let i=e.tags.filter(e=>t.has(e.name)),a=i.reduce((e,t)=>e+t.toAdd.length+ +!t.existingList,0)+e.notes.length,o={listsCreated:0,added:0,notes:0,failed:[]},s=0,c=()=>r({done:++s,total:a});for(let e of i){let t=e.existingList;if(!t){try{t=await n.createList(e.name),o.listsCreated++}catch(t){o.failed.push({what:`List "${e.name}"`,reason:J(t)})}c()}for(let r of e.toAdd){if(t)try{await n.addToList(t,r),o.added++}catch(t){o.failed.push({what:`${r.full_name} in "${e.name}"`,reason:J(t)})}c()}}for(let t of e.notes){try{await n.setNotes(t.repo,t.notes),o.notes++}catch(e){o.failed.push({what:`Notes on ${t.repo.full_name}`,reason:J(e)})}c()}return o}var Le={createList:async e=>{let{githubListId:t}=await r.createList({name:e,description:null}),n=new Date().toISOString();return{id:t,github_list_id:t,name:e,description:null,is_private:!1,created_at:n,updated_at:n}},addToList:async(e,t)=>{if(!t.node_id||!e.github_list_id)throw Error(`Import your stars again first.`);await r.changeMembership({repoNodeId:t.node_id,repoGithubId:t.github_id,githubListId:e.github_list_id,change:`add`})},setNotes:(e,t)=>o(()=>a.update(e.id,e=>{e.notes=t}))};async function Re(){await N()}async function ze(){await V()}function Y(e){return e instanceof Error?e.message:String(e)}function X({label:e,children:t}){return(0,W.jsxs)(_,{children:[(0,W.jsx)(g,{openOnHover:!0,delay:150,render:(0,W.jsx)(`button`,{type:`button`,"aria-label":e,className:`inline-flex text-muted-foreground hover:text-foreground`}),children:(0,W.jsx)(ge,{className:`size-4`})}),(0,W.jsx)(v,{className:`w-64 p-3 text-sm`,children:t})]})}function Z({icon:e,count:t,label:n,className:r}){return(0,W.jsxs)(`span`,{title:n,"aria-label":`${t} ${n}`,className:c(`inline-flex items-center gap-1 tabular-nums [&>svg]:size-4`,r),children:[e,t]})}function Be({stored:e,onClose:t}){let[n,r]=(0,U.useState)({step:`pick`}),i=(0,U.useRef)(null),a=(0,U.useRef)(null);async function o(t){if(t)try{let n=je(JSON.parse(await t.text()));r({step:`review`,stars:n,asLists:Fe(K(n,e,new Set))})}catch(e){r({step:`failed`,message:e instanceof SyntaxError?`${t.name} isn't a JSON file.`:Y(e)})}}async function s(t,n){let i=K(t,e,n);r({step:`applying`,done:0,total:0});try{await Re();let e=await Ie(i,n,Le,({done:e,total:t})=>r({step:`applying`,done:e,total:t}));await ze(),r({step:`done`,result:e})}catch(e){r({step:`failed`,message:Y(e)})}}return(0,W.jsx)(j,{open:!0,onOpenChange:e=>{!e&&n.step!==`applying`&&t()},children:(0,W.jsxs)(M,{initialFocus:a,children:[(0,W.jsx)(P,{children:(0,W.jsxs)(O,{className:`flex items-center gap-2`,children:[`Import from Astral`,(0,W.jsx)(X,{label:`How the import works`,children:`Each tag becomes a GitHub List. Astral notes go below your own. Tags you uncheck are saved in each repo's notes instead. Nothing changes until you press Import.`})]})}),n.step===`pick`&&(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,W.jsx)(`input`,{ref:i,type:`file`,accept:`application/json,.json`,className:`hidden`,onChange:e=>{o(e.target.files?.[0]),e.target.value=``}}),(0,W.jsxs)(f,{ref:a,variant:`outline`,onClick:()=>i.current?.click(),children:[(0,W.jsx)(k,{className:`mr-1.5 size-4`}),`Choose export`]}),(0,W.jsx)(X,{label:`Where to get the export`,children:`In Astral, open Settings and press Export.`})]}),n.step===`review`&&(0,W.jsx)(He,{stars:n.stars,stored:e,asLists:n.asLists,onChange:e=>r({...n,asLists:e})}),n.step===`applying`&&(0,W.jsx)(Ue,{done:n.done,total:n.total}),n.step===`done`&&(0,W.jsx)(We,{result:n.result}),n.step===`failed`&&(0,W.jsx)(`p`,{className:`text-sm text-destructive`,children:n.message}),n.step!==`pick`&&n.step!==`applying`&&(0,W.jsxs)(A,{children:[n.step===`review`&&(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(f,{variant:`ghost`,onClick:t,children:`Cancel`}),(0,W.jsx)(f,{onClick:()=>void s(n.stars,n.asLists),disabled:!Ve(n.stars,e,n.asLists),children:`Import`})]}),(n.step===`done`||n.step===`failed`)&&(0,W.jsx)(f,{onClick:t,children:`Close`})]})]})})}function Ve(e,t,n){let r=K(e,t,n);return r.notes.length+r.tags.filter(e=>n.has(e.name)&&e.toAdd.length>0).length>0&&q(r,n)<=r.listSlots}function He({stars:e,stored:t,asLists:n,onChange:r}){let i=K(e,t,n),a=q(i,n),o=a>i.listSlots;function s(e,t){let i=new Set(n);t?i.add(e):i.delete(e),r(i)}return(0,W.jsxs)(`div`,{className:`space-y-3 text-sm`,children:[i.tags.length>0&&(0,W.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,W.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,W.jsx)(`span`,{className:`font-medium`,children:`Lists`}),(0,W.jsxs)(`span`,{className:c(`flex items-center gap-1.5 text-xs tabular-nums text-muted-foreground`,o&&`text-destructive`),children:[a,`/`,i.listSlots,` new`,(0,W.jsxs)(X,{label:`GitHub's List limit`,children:[`GitHub allows `,32,` Lists, and you have room for `,i.listSlots,` more. A tag matching a List you have adds to it instead.`]})]})]}),(0,W.jsx)(`ul`,{className:`max-h-64 space-y-1 overflow-y-auto rounded-md border border-border p-2`,children:i.tags.map(e=>(0,W.jsx)(`li`,{children:(0,W.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,W.jsx)(b,{checked:n.has(e.name),onCheckedChange:t=>s(e.name,t===!0)}),(0,W.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,children:e.name}),!e.existingList&&(0,W.jsx)(F,{variant:`outline`,children:`new`}),e.toAdd.length>0?(0,W.jsx)(Z,{icon:(0,W.jsx)(I,{}),count:e.toAdd.length,label:`repos to add`,className:`text-xs text-muted-foreground`}):(0,W.jsx)(`span`,{title:`Already in your List`,"aria-label":`Already in your List`,children:(0,W.jsx)(y,{className:`size-4 text-muted-foreground`})})]})},e.name))})]}),(0,W.jsxs)(`div`,{className:`flex items-center gap-4 text-muted-foreground`,children:[i.notes.length>0&&(0,W.jsx)(Z,{icon:(0,W.jsx)(H,{}),count:i.notes.length,label:`repos getting notes`}),i.notStarred>0&&(0,W.jsx)(Z,{icon:(0,W.jsx)(D,{}),count:i.notStarred,label:`not starred any more, skipped`})]})]})}function Ue({done:e,total:t}){return(0,W.jsxs)(`div`,{className:`space-y-1.5`,role:`progressbar`,"aria-valuemin":0,"aria-valuemax":t,"aria-valuenow":e,"aria-label":`Writing to GitHub`,children:[(0,W.jsx)(`div`,{className:`h-1.5 overflow-hidden rounded-full bg-muted`,children:(0,W.jsx)(`div`,{className:`h-full bg-primary transition-[width]`,style:{width:`${t>0?Math.round(e/t*100):0}%`}})}),(0,W.jsxs)(`p`,{className:`text-xs tabular-nums text-muted-foreground`,children:[e,`/`,t]})]})}function We({result:e}){return(0,W.jsxs)(`div`,{className:`space-y-2 text-sm`,children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-4`,children:[(0,W.jsx)(Z,{icon:(0,W.jsx)(x,{}),count:e.listsCreated,label:`Lists created`}),(0,W.jsx)(Z,{icon:(0,W.jsx)(I,{}),count:e.added,label:`repos added to Lists`}),(0,W.jsx)(Z,{icon:(0,W.jsx)(H,{}),count:e.notes,label:`repos given notes`})]}),e.failed.length>0&&(0,W.jsxs)(`details`,{className:`rounded-md border border-destructive/40 p-2 text-destructive`,children:[(0,W.jsxs)(`summary`,{className:`flex cursor-pointer items-center gap-1.5`,children:[(0,W.jsx)(ve,{className:`size-4`}),e.failed.length,` failed`]}),(0,W.jsx)(`ul`,{className:`mt-1 max-h-40 space-y-0.5 overflow-y-auto text-xs`,children:e.failed.map(e=>(0,W.jsxs)(`li`,{children:[e.what,`: `,e.reason]},e.what))})]})]})}function Ge({text:e,label:t=`Copy prompt`}){let[n,r]=(0,U.useState)(!1);async function i(){await navigator.clipboard.writeText(e),r(!0),setTimeout(()=>r(!1),1500)}return(0,W.jsxs)(f,{variant:`outline`,size:`sm`,onClick:i,children:[n?(0,W.jsx)(y,{className:`mr-2 h-3.5 w-3.5`}):(0,W.jsx)(Ce,{className:`mr-2 h-3.5 w-3.5`}),n?`Copied`:t]})}var Q=`https://github.com/armanckeser/github-stars-organizer/blob/main/AGENT-API.md`,Ke=`Suggest which List each repo in no List belongs in, and any new Lists worth creating. Show me the plan as a table and wait for my OK before changing anything.`;function qe(e){return`Stars Organizer is running at ${window.location.origin}. Read ${Q}, then fetch my stars and Lists with POST /api/local/import. ${Ke}`}var Je=`https://github.com/settings/tokens/new?scopes=repo&description=Stars%20Organizer`;function $({label:e,icon:t,children:n,onOpen:r}){return(0,W.jsxs)(_,{onOpenChange:e=>e&&r?.(),children:[(0,W.jsx)(g,{openOnHover:!0,delay:150,render:(0,W.jsx)(`button`,{type:`button`,"aria-label":e,title:e,className:`inline-flex h-9 w-9 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground`}),children:t}),(0,W.jsx)(v,{align:`end`,className:`w-80 space-y-2 p-3 text-sm`,children:n})]})}function Ye(){let[e,t]=(0,U.useState)(`idle`);function n(){e===`idle`&&(t(`loading`),w().then(t).catch(e=>t({connected:!1,error:String(e)})))}let r=typeof e==`object`&&e?.scopes&&!e.scopes.includes(`repo`);return(0,W.jsxs)($,{label:`GitHub token`,icon:(0,W.jsx)(we,{className:`h-4 w-4`}),onOpen:n,children:[(e===`idle`||e===`loading`)&&(0,W.jsx)(`p`,{className:`text-muted-foreground`,children:`Checking the token...`}),typeof e==`object`&&e?.connected&&(0,W.jsxs)(W.Fragment,{children:[(0,W.jsxs)(`p`,{children:[`Signed in to GitHub as `,(0,W.jsx)(`span`,{className:`font-medium`,children:e.login}),` through the GitHub CLI.`]}),(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1`,children:[(0,W.jsx)(`span`,{className:`text-muted-foreground`,children:`Scopes:`}),e.scopes==null?(0,W.jsx)(`span`,{className:`text-muted-foreground`,children:`not listed (fine-grained token)`}):e.scopes.map(e=>(0,W.jsx)(F,{variant:e===`repo`?`default`:`secondary`,children:e},e))]}),r&&(0,W.jsxs)(`p`,{className:`text-amber-500`,children:[`Lists and unstars need the `,(0,W.jsx)(`code`,{children:`repo`}),` scope.`]})]}),typeof e==`object`&&!e?.connected&&(0,W.jsxs)(`p`,{children:[`No working token`,e?.error?` (${e.error})`:``,`. Set `,(0,W.jsx)(`code`,{children:`GITHUB_TOKEN`}),` to a`,` `,(0,W.jsx)(`a`,{href:Je,target:`_blank`,rel:`noopener`,className:`text-primary hover:underline`,children:`classic token with the repo scope`}),` `,`and restart the app.`]}),(0,W.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`The `,(0,W.jsx)(`code`,{children:`repo`}),` scope lets Stars Organizer read your stars, edit your Lists and unstar repos. It never reads or changes code.`]})]})}function Xe(){let e=qe(_e());return(0,W.jsxs)($,{label:`Sort with an AI agent`,icon:(0,W.jsx)(xe,{className:`h-4 w-4`}),children:[(0,W.jsx)(`p`,{className:`font-medium`,children:`Sort your stars with an AI agent`}),(0,W.jsxs)(`ol`,{className:`list-decimal space-y-1.5 pl-4 text-muted-foreground`,children:[!1,(0,W.jsxs)(`li`,{children:[`Paste this prompt into Claude Code, Codex or another agent that can run commands `,`on this computer`,`:`]})]}),(0,W.jsx)(`pre`,{className:`max-h-32 overflow-y-auto whitespace-pre-wrap rounded-md bg-muted p-2 text-xs`,children:e}),(0,W.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,W.jsx)(Ge,{text:e}),(0,W.jsx)(`a`,{href:Q,target:`_blank`,rel:`noopener`,className:`text-primary hover:underline`,children:`API guide`})]}),!1,(0,W.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`The agent reads your stars and shows its plan as a table. Nothing changes until you say OK; then it sorts the repos into your GitHub Lists.`})]})}var Ze=!1,Qe=class extends Error{},$e=`https://github.com/settings/tokens/new?scopes=repo`;async function et(e){e(`Reading your stars and Lists from GitHub...`);let{stars:t,lists:n}=await V(),r=`Read ${t} stars and ${n} lists.`;e(r);let i=await be(`missing`,({scored:t,total:n})=>e(`${r} Scoring health ${t}/${n}...`));i.total>0&&e(`${r} Scored ${i.scored} repos.`)}function tt(){let t=L.useNavigate(),n=L.useSearch(),{data:r}=m(e=>e.from({repoCollection:a}).select(({repoCollection:e})=>e)),{data:i}=m(e=>e.from({listCollection:p}).select(({listCollection:e})=>e)),{data:o}=m(t=>t.from({listItemCollection:e}).select(({listItemCollection:e})=>e)),[s,c]=(0,U.useState)(!1),[l,d]=(0,U.useState)(!1),[h,g]=(0,U.useState)(``),[_,v]=(0,U.useState)(!1),[y,b]=(0,U.useState)(null),x=ie(),w=r??[],D=(0,U.useMemo)(()=>{let e=new Map;for(let t of o??[]){let n=e.get(t.repo_id)??[];n.push(t.list_id),e.set(t.repo_id,n)}return e},[o]),{registry:O,sortDefinitions:k}=(0,U.useMemo)(()=>le(w,{lists:i??[],listIdsByRepo:D}),[w,i,D]),A=(0,U.useMemo)(()=>ne(n,O,T,E),[n,O]),j=(0,U.useCallback)(e=>{t({search:re(e,O,T,E),replace:!0})},[t,O]);async function M(){c(!0),v(!1);try{await et(g)}catch(e){if(e instanceof Qe){g(``),v(!0);return}g(`Error: ${e instanceof Error?e.message:`Unknown`}`)}finally{c(!1)}}(0,U.useEffect)(()=>{Ze||(Ze=!0,M())},[]);let N=(0,U.useCallback)(e=>(0,W.jsxs)(S,{repo:e,children:[(0,W.jsx)(S.AddToList,{repo:e,lists:i??[],listItems:o??[]}),(0,W.jsx)(S.Rate,{repo:e}),(0,W.jsx)(S.Separator,{}),(0,W.jsx)(S.OpenOnGithub,{url:e.url}),(0,W.jsx)(S.CopyUrl,{url:e.url}),(0,W.jsx)(S.Separator,{}),(0,W.jsx)(S.Unstar,{repo:e})]}),[i,o]),P=(0,U.useMemo)(()=>ue({selectable:!0,onPreview:e=>b(e),renderActions:N}),[N]);return(0,W.jsxs)(`div`,{className:`space-y-6`,children:[(0,W.jsxs)(`div`,{className:`flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between`,children:[(0,W.jsxs)(`div`,{children:[(0,W.jsx)(`h1`,{className:`font-display text-2xl font-bold tracking-tight sm:text-3xl`,children:`All Stars`}),(0,W.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[w.length,` starred repositories`]})]}),u?(0,W.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,W.jsx)(Xe,{}),(0,W.jsx)(ke,{})]}):(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[h&&(0,W.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:h}),_&&(0,W.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[`Needs a GitHub token.`,` `,(0,W.jsx)(`a`,{href:$e,target:`_blank`,rel:`noopener`,className:`font-medium text-primary underline-offset-4 hover:underline`,children:`Create one`}),` `,`(classic, repo scope), set it as GITHUB_TOKEN in the app's settings, and restart the app.`]}),(0,W.jsx)(Xe,{}),(0,W.jsx)(Ye,{}),(0,W.jsxs)(fe,{children:[(0,W.jsxs)(pe,{render:(0,W.jsx)(f,{disabled:s}),children:[(0,W.jsx)(he,{className:`mr-2 h-4 w-4`}),s?`Importing...`:`Import Stars`,(0,W.jsx)(Se,{className:`ml-1 h-4 w-4`})]}),(0,W.jsxs)(me,{align:`end`,className:`w-auto min-w-48`,children:[(0,W.jsx)(C,{onClick:M,children:`From GitHub`}),(0,W.jsx)(C,{disabled:w.length===0,onClick:()=>d(!0),children:`From an Astral export`})]})]}),l&&(0,W.jsx)(Be,{stored:{repos:w,lists:i??[],list_items:o??[]},onClose:()=>d(!1)})]})]}),(0,W.jsx)(de,{items:w,registry:O,sortDefinitions:k,defaultSort:T,defaultGroupBy:E,viewState:A,onViewStateChange:j,searchFields:ae,children:(0,W.jsx)(oe,{columns:P,getRowId:e=>e.id,toolbar:(0,W.jsx)(te,{}),onRowClick:x?void 0:b,renderMobileRow:(e,t)=>(0,W.jsx)(ee,{repo:e,state:t,actions:N(e)}),renderBulkActions:(e,t)=>(0,W.jsx)(se,{selectedRepos:e,lists:i??[],listItems:o??[],clearSelection:t})})}),(0,W.jsx)(ce,{repo:y,lists:i??[],listItems:o??[],open:y!==null,onOpenChange:e=>{e||b(null)}})]})}export{tt as component};
3
+ `)}function K(e,t,n){let r=new Map(t.repos.map(e=>[e.github_id,e])),i=new Map(t.lists.map(e=>[e.name.toLowerCase(),e])),a=new Set(t.list_items.map(e=>`${e.list_id}:${e.repo_id}`)),o=new Set([...n].map(e=>e.toLowerCase())),s=new Map,c=[],l=0;for(let t of e){let e=r.get(t.repo_id);if(!e){l++;continue}let n=Ne(t);for(let t of n){let n=t.toLowerCase(),r=s.get(n);r||(r={name:t,existingList:i.get(n)??null,toAdd:[],starred:0},s.set(n,r)),r.starred++,(!r.existingList||!a.has(`${r.existingList.id}:${e.id}`))&&r.toAdd.push(e)}let u=n.filter(e=>!o.has(e.toLowerCase())),d=Pe(e.notes,[t.notes?.trim()??``,u.length?`${Me}${u.join(`, `)}`:``]);d!==null&&c.push({repo:e,notes:d})}return{tags:[...s.values()].sort((e,t)=>t.starred-e.starred||e.name.localeCompare(t.name)),notes:c,notStarred:l,listSlots:Math.max(0,32-t.lists.length)}}function Fe(e){let t=new Set,n=e.listSlots;for(let r of e.tags)r.existingList?t.add(r.name):n>0&&(t.add(r.name),n--);return t}function q(e,t){return e.tags.filter(e=>t.has(e.name)&&!e.existingList).length}function J(e){return e instanceof Error?e.message:String(e)}async function Ie(e,t,n,r=()=>{}){let i=e.tags.filter(e=>t.has(e.name)),a=i.reduce((e,t)=>e+t.toAdd.length+ +!t.existingList,0)+e.notes.length,o={listsCreated:0,added:0,notes:0,failed:[]},s=0,c=()=>r({done:++s,total:a});for(let e of i){let t=e.existingList;if(!t){try{t=await n.createList(e.name),o.listsCreated++}catch(t){o.failed.push({what:`List "${e.name}"`,reason:J(t)})}c()}for(let r of e.toAdd){if(t)try{await n.addToList(t,r),o.added++}catch(t){o.failed.push({what:`${r.full_name} in "${e.name}"`,reason:J(t)})}c()}}for(let t of e.notes){try{await n.setNotes(t.repo,t.notes),o.notes++}catch(e){o.failed.push({what:`Notes on ${t.repo.full_name}`,reason:J(e)})}c()}return o}var Le={createList:async e=>{let{githubListId:t}=await r.createList({name:e,description:null}),n=new Date().toISOString();return{id:t,github_list_id:t,name:e,description:null,is_private:!1,created_at:n,updated_at:n}},addToList:async(e,t)=>{if(!t.node_id||!e.github_list_id)throw Error(`Import your stars again first.`);await r.changeMembership({repoNodeId:t.node_id,repoGithubId:t.github_id,githubListId:e.github_list_id,change:`add`})},setNotes:(e,t)=>o(()=>a.update(e.id,e=>{e.notes=t}))};async function Re(){await N()}async function ze(){await V()}function Y(e){return e instanceof Error?e.message:String(e)}function X({label:e,children:t}){return(0,W.jsxs)(_,{children:[(0,W.jsx)(g,{openOnHover:!0,delay:150,render:(0,W.jsx)(`button`,{type:`button`,"aria-label":e,className:`inline-flex text-muted-foreground hover:text-foreground`}),children:(0,W.jsx)(ge,{className:`size-4`})}),(0,W.jsx)(v,{className:`w-64 p-3 text-sm`,children:t})]})}function Z({icon:e,count:t,label:n,className:r}){return(0,W.jsxs)(`span`,{title:n,"aria-label":`${t} ${n}`,className:l(`inline-flex items-center gap-1 tabular-nums [&>svg]:size-4`,r),children:[e,t]})}function Be({stored:e,onClose:t}){let[n,r]=(0,U.useState)({step:`pick`}),i=(0,U.useRef)(null),a=(0,U.useRef)(null);async function o(t){if(t)try{let n=je(JSON.parse(await t.text()));r({step:`review`,stars:n,asLists:Fe(K(n,e,new Set))})}catch(e){r({step:`failed`,message:e instanceof SyntaxError?`${t.name} isn't a JSON file.`:Y(e)})}}async function s(t,n){let i=K(t,e,n);r({step:`applying`,done:0,total:0});try{await Re();let e=await Ie(i,n,Le,({done:e,total:t})=>r({step:`applying`,done:e,total:t}));await ze(),r({step:`done`,result:e})}catch(e){r({step:`failed`,message:Y(e)})}}return(0,W.jsx)(j,{open:!0,onOpenChange:e=>{!e&&n.step!==`applying`&&t()},children:(0,W.jsxs)(M,{initialFocus:a,children:[(0,W.jsx)(P,{children:(0,W.jsxs)(O,{className:`flex items-center gap-2`,children:[`Import from Astral`,(0,W.jsx)(X,{label:`How the import works`,children:`Each tag becomes a GitHub List. Astral notes go below your own. Tags you uncheck are saved in each repo's notes instead. Nothing changes until you press Import.`})]})}),n.step===`pick`&&(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,W.jsx)(`input`,{ref:i,type:`file`,accept:`application/json,.json`,className:`hidden`,onChange:e=>{o(e.target.files?.[0]),e.target.value=``}}),(0,W.jsxs)(f,{ref:a,variant:`outline`,onClick:()=>i.current?.click(),children:[(0,W.jsx)(k,{className:`mr-1.5 size-4`}),`Choose export`]}),(0,W.jsx)(X,{label:`Where to get the export`,children:`In Astral, open Settings and press Export.`})]}),n.step===`review`&&(0,W.jsx)(He,{stars:n.stars,stored:e,asLists:n.asLists,onChange:e=>r({...n,asLists:e})}),n.step===`applying`&&(0,W.jsx)(Ue,{done:n.done,total:n.total}),n.step===`done`&&(0,W.jsx)(We,{result:n.result}),n.step===`failed`&&(0,W.jsx)(`p`,{className:`text-sm text-destructive`,children:n.message}),n.step!==`pick`&&n.step!==`applying`&&(0,W.jsxs)(A,{children:[n.step===`review`&&(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(f,{variant:`ghost`,onClick:t,children:`Cancel`}),(0,W.jsx)(f,{onClick:()=>void s(n.stars,n.asLists),disabled:!Ve(n.stars,e,n.asLists),children:`Import`})]}),(n.step===`done`||n.step===`failed`)&&(0,W.jsx)(f,{onClick:t,children:`Close`})]})]})})}function Ve(e,t,n){let r=K(e,t,n);return r.notes.length+r.tags.filter(e=>n.has(e.name)&&e.toAdd.length>0).length>0&&q(r,n)<=r.listSlots}function He({stars:e,stored:t,asLists:n,onChange:r}){let i=K(e,t,n),a=q(i,n),o=a>i.listSlots;function s(e,t){let i=new Set(n);t?i.add(e):i.delete(e),r(i)}return(0,W.jsxs)(`div`,{className:`space-y-3 text-sm`,children:[i.tags.length>0&&(0,W.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,W.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,W.jsx)(`span`,{className:`font-medium`,children:`Lists`}),(0,W.jsxs)(`span`,{className:l(`flex items-center gap-1.5 text-xs tabular-nums text-muted-foreground`,o&&`text-destructive`),children:[a,`/`,i.listSlots,` new`,(0,W.jsxs)(X,{label:`GitHub's List limit`,children:[`GitHub allows `,32,` Lists, and you have room for `,i.listSlots,` more. A tag matching a List you have adds to it instead.`]})]})]}),(0,W.jsx)(`ul`,{className:`max-h-64 space-y-1 overflow-y-auto rounded-md border border-border p-2`,children:i.tags.map(e=>(0,W.jsx)(`li`,{children:(0,W.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,W.jsx)(b,{checked:n.has(e.name),onCheckedChange:t=>s(e.name,t===!0)}),(0,W.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,children:e.name}),!e.existingList&&(0,W.jsx)(F,{variant:`outline`,children:`new`}),e.toAdd.length>0?(0,W.jsx)(Z,{icon:(0,W.jsx)(I,{}),count:e.toAdd.length,label:`repos to add`,className:`text-xs text-muted-foreground`}):(0,W.jsx)(`span`,{title:`Already in your List`,"aria-label":`Already in your List`,children:(0,W.jsx)(y,{className:`size-4 text-muted-foreground`})})]})},e.name))})]}),(0,W.jsxs)(`div`,{className:`flex items-center gap-4 text-muted-foreground`,children:[i.notes.length>0&&(0,W.jsx)(Z,{icon:(0,W.jsx)(H,{}),count:i.notes.length,label:`repos getting notes`}),i.notStarred>0&&(0,W.jsx)(Z,{icon:(0,W.jsx)(D,{}),count:i.notStarred,label:`not starred any more, skipped`})]})]})}function Ue({done:e,total:t}){return(0,W.jsxs)(`div`,{className:`space-y-1.5`,role:`progressbar`,"aria-valuemin":0,"aria-valuemax":t,"aria-valuenow":e,"aria-label":`Writing to GitHub`,children:[(0,W.jsx)(`div`,{className:`h-1.5 overflow-hidden rounded-full bg-muted`,children:(0,W.jsx)(`div`,{className:`h-full bg-primary transition-[width]`,style:{width:`${t>0?Math.round(e/t*100):0}%`}})}),(0,W.jsxs)(`p`,{className:`text-xs tabular-nums text-muted-foreground`,children:[e,`/`,t]})]})}function We({result:e}){return(0,W.jsxs)(`div`,{className:`space-y-2 text-sm`,children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-4`,children:[(0,W.jsx)(Z,{icon:(0,W.jsx)(x,{}),count:e.listsCreated,label:`Lists created`}),(0,W.jsx)(Z,{icon:(0,W.jsx)(I,{}),count:e.added,label:`repos added to Lists`}),(0,W.jsx)(Z,{icon:(0,W.jsx)(H,{}),count:e.notes,label:`repos given notes`})]}),e.failed.length>0&&(0,W.jsxs)(`details`,{className:`rounded-md border border-destructive/40 p-2 text-destructive`,children:[(0,W.jsxs)(`summary`,{className:`flex cursor-pointer items-center gap-1.5`,children:[(0,W.jsx)(ve,{className:`size-4`}),e.failed.length,` failed`]}),(0,W.jsx)(`ul`,{className:`mt-1 max-h-40 space-y-0.5 overflow-y-auto text-xs`,children:e.failed.map(e=>(0,W.jsxs)(`li`,{children:[e.what,`: `,e.reason]},e.what))})]})]})}function Ge({text:e,label:t=`Copy prompt`}){let[n,r]=(0,U.useState)(!1);async function i(){await navigator.clipboard.writeText(e),r(!0),setTimeout(()=>r(!1),1500)}return(0,W.jsxs)(f,{variant:`outline`,size:`sm`,onClick:i,children:[n?(0,W.jsx)(y,{className:`mr-2 h-3.5 w-3.5`}):(0,W.jsx)(Ce,{className:`mr-2 h-3.5 w-3.5`}),n?`Copied`:t]})}var Q=`https://github.com/armanckeser/github-stars-organizer/blob/main/AGENT-API.md`,Ke=`Suggest which List each repo in no List belongs in, and any new Lists worth creating. Show me the plan as a table and wait for my OK before changing anything.`;function qe(e){return`Stars Organizer is running at ${window.location.origin}. Read ${Q}, then fetch my stars and Lists with POST /api/local/import. ${Ke}`}var Je=`https://github.com/settings/tokens/new?scopes=repo&description=Stars%20Organizer`;function $({label:e,icon:t,children:n,onOpen:r}){return(0,W.jsxs)(_,{onOpenChange:e=>e&&r?.(),children:[(0,W.jsx)(g,{openOnHover:!0,delay:150,render:(0,W.jsx)(`button`,{type:`button`,"aria-label":e,title:e,className:`inline-flex h-9 w-9 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground`}),children:t}),(0,W.jsx)(v,{align:`end`,className:`w-80 space-y-2 p-3 text-sm`,children:n})]})}function Ye(){let[e,t]=(0,U.useState)(`idle`);function n(){e===`idle`&&(t(`loading`),w().then(t).catch(e=>t({connected:!1,error:String(e)})))}let r=typeof e==`object`&&e?.scopes&&!e.scopes.includes(`repo`);return(0,W.jsxs)($,{label:`GitHub token`,icon:(0,W.jsx)(we,{className:`h-4 w-4`}),onOpen:n,children:[(e===`idle`||e===`loading`)&&(0,W.jsx)(`p`,{className:`text-muted-foreground`,children:`Checking the token...`}),typeof e==`object`&&e?.connected&&(0,W.jsxs)(W.Fragment,{children:[(0,W.jsxs)(`p`,{children:[`Signed in to GitHub as `,(0,W.jsx)(`span`,{className:`font-medium`,children:e.login}),` through the GitHub CLI.`]}),(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1`,children:[(0,W.jsx)(`span`,{className:`text-muted-foreground`,children:`Scopes:`}),e.scopes==null?(0,W.jsx)(`span`,{className:`text-muted-foreground`,children:`not listed (fine-grained token)`}):e.scopes.map(e=>(0,W.jsx)(F,{variant:e===`repo`?`default`:`secondary`,children:e},e))]}),r&&(0,W.jsxs)(`p`,{className:`text-amber-500`,children:[`Lists and unstars need the `,(0,W.jsx)(`code`,{children:`repo`}),` scope.`]})]}),typeof e==`object`&&!e?.connected&&(0,W.jsxs)(`p`,{children:[`No working token`,e?.error?` (${e.error})`:``,`. Set `,(0,W.jsx)(`code`,{children:`GITHUB_TOKEN`}),` to a`,` `,(0,W.jsx)(`a`,{href:Je,target:`_blank`,rel:`noopener`,className:`text-primary hover:underline`,children:`classic token with the repo scope`}),` `,`and restart the app.`]}),(0,W.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`The `,(0,W.jsx)(`code`,{children:`repo`}),` scope lets Stars Organizer read your stars, edit your Lists and unstar repos. It never reads or changes code.`]})]})}function Xe(){let e=qe(_e());return(0,W.jsxs)($,{label:`Sort with an AI agent`,icon:(0,W.jsx)(xe,{className:`h-4 w-4`}),children:[(0,W.jsx)(`p`,{className:`font-medium`,children:`Sort your stars with an AI agent`}),(0,W.jsxs)(`ol`,{className:`list-decimal space-y-1.5 pl-4 text-muted-foreground`,children:[!1,(0,W.jsxs)(`li`,{children:[`Paste this prompt into Claude Code, Codex or another agent that can run commands `,`on this computer`,`:`]})]}),(0,W.jsx)(`pre`,{className:`max-h-32 overflow-y-auto whitespace-pre-wrap rounded-md bg-muted p-2 text-xs`,children:e}),(0,W.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,W.jsx)(Ge,{text:e}),(0,W.jsx)(`a`,{href:Q,target:`_blank`,rel:`noopener`,className:`text-primary hover:underline`,children:`API guide`})]}),!1,(0,W.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`The agent reads your stars and shows its plan as a table. Nothing changes until you say OK; then it sorts the repos into your GitHub Lists.`})]})}var Ze=!1,Qe=class extends Error{},$e=`https://github.com/settings/tokens/new?scopes=repo`;async function et(e){e(`Reading your stars and Lists from GitHub...`);let{stars:t,lists:n}=await V(),r=`Read ${t} stars and ${n} lists.`;e(r);let i=await be(`missing`,({scored:t,total:n})=>e(`${r} Scoring health ${t}/${n}...`));i.total>0&&e(`${r} Scored ${i.scored} repos.`)}function tt(){let t=L.useNavigate(),n=L.useSearch(),{data:r}=m(e=>e.from({repoCollection:a}).select(({repoCollection:e})=>e)),{data:i}=m(e=>e.from({listCollection:p}).select(({listCollection:e})=>e)),{data:o}=m(t=>t.from({listItemCollection:e}).select(({listItemCollection:e})=>e)),[s,c]=(0,U.useState)(!1),[l,u]=(0,U.useState)(!1),[h,g]=(0,U.useState)(``),[_,v]=(0,U.useState)(!1),[y,b]=(0,U.useState)(null),x=ie(),w=r??[],D=(0,U.useMemo)(()=>{let e=new Map;for(let t of o??[]){let n=e.get(t.repo_id)??[];n.push(t.list_id),e.set(t.repo_id,n)}return e},[o]),{registry:O,sortDefinitions:k}=(0,U.useMemo)(()=>le(w,{lists:i??[],listIdsByRepo:D}),[w,i,D]),A=(0,U.useMemo)(()=>ne(n,O,T,E),[n,O]),j=(0,U.useCallback)(e=>{t({search:re(e,O,T,E),replace:!0})},[t,O]);async function M(){c(!0),v(!1);try{await et(g)}catch(e){if(e instanceof Qe){g(``),v(!0);return}g(`Error: ${e instanceof Error?e.message:`Unknown`}`)}finally{c(!1)}}(0,U.useEffect)(()=>{Ze||(Ze=!0,M())},[]);let N=(0,U.useCallback)(e=>(0,W.jsxs)(S,{repo:e,children:[(0,W.jsx)(S.AddToList,{repo:e,lists:i??[],listItems:o??[]}),(0,W.jsx)(S.Rate,{repo:e}),(0,W.jsx)(S.Separator,{}),(0,W.jsx)(S.OpenOnGithub,{url:e.url}),(0,W.jsx)(S.CopyUrl,{url:e.url}),(0,W.jsx)(S.Separator,{}),(0,W.jsx)(S.Unstar,{repo:e})]}),[i,o]),P=(0,U.useMemo)(()=>ue({selectable:!0,onPreview:e=>b(e),renderActions:N}),[N]);return(0,W.jsxs)(`div`,{className:`space-y-6`,children:[(0,W.jsxs)(`div`,{className:`flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between`,children:[(0,W.jsxs)(`div`,{children:[(0,W.jsx)(`h1`,{className:`font-display text-2xl font-bold tracking-tight sm:text-3xl`,children:`All Stars`}),(0,W.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[w.length,` starred repositories`]})]}),d?(0,W.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,W.jsx)(Xe,{}),(0,W.jsx)(ke,{})]}):(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[h&&(0,W.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:h}),_&&(0,W.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[`Needs a GitHub token.`,` `,(0,W.jsx)(`a`,{href:$e,target:`_blank`,rel:`noopener`,className:`font-medium text-primary underline-offset-4 hover:underline`,children:`Create one`}),` `,`(classic, repo scope), set it as GITHUB_TOKEN in the app's settings, and restart the app.`]}),(0,W.jsx)(Xe,{}),(0,W.jsx)(Ye,{}),(0,W.jsxs)(fe,{children:[(0,W.jsxs)(pe,{render:(0,W.jsx)(f,{disabled:s}),children:[(0,W.jsx)(he,{className:`mr-2 h-4 w-4`}),s?`Importing...`:`Import Stars`,(0,W.jsx)(Se,{className:`ml-1 h-4 w-4`})]}),(0,W.jsxs)(me,{align:`end`,className:`w-auto min-w-48`,children:[(0,W.jsx)(C,{onClick:M,children:`From GitHub`}),(0,W.jsx)(C,{disabled:w.length===0,onClick:()=>u(!0),children:`From an Astral export`})]})]}),l&&(0,W.jsx)(Be,{stored:{repos:w,lists:i??[],list_items:o??[]},onClose:()=>u(!1)})]})]}),(0,W.jsx)(de,{items:w,registry:O,sortDefinitions:k,defaultSort:T,defaultGroupBy:E,viewState:A,onViewStateChange:j,searchFields:ae,children:(0,W.jsx)(oe,{columns:P,getRowId:e=>e.id,toolbar:(0,W.jsx)(te,{}),onRowClick:x?void 0:b,renderMobileRow:(e,t)=>(0,W.jsx)(ee,{repo:e,state:t,actions:N(e)}),renderBulkActions:(e,t)=>(0,W.jsx)(se,{selectedRepos:e,lists:i??[],listItems:o??[],clearSelection:t})})}),(0,W.jsx)(ce,{repo:y,lists:i??[],listItems:o??[],open:y!==null,onOpenChange:e=>{e||b(null)}})]})}export{tt as component};
@@ -1,2 +1,2 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/routes-BYr-dng4.js","assets/button-r9cVFa0_.js","assets/sync-persistence-BJbWXISF.js","assets/registry-BKf8LDk2.js","assets/schemas-DVvZEnxp.js","assets/coerce-Cxjr6MIU.js","assets/star-BPue5Y4t.js","assets/badge-Drt9JvOu.js","assets/local-backups-DLhiWDk4.js","assets/local-sync-DiQe8mhd.js","assets/triangle-alert-BL8M65pd.js"])))=>i.map(i=>d[i]);
2
- import{G as e,R as t,it as n,st as r}from"./button-r9cVFa0_.js";import{O as i,k as a,t as o}from"./coerce-Cxjr6MIU.js";import{c as s,s as c}from"./schemas-DVvZEnxp.js";var l=t(`info`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 16v-4`,key:`1dtifu`}],[`path`,{d:`M12 8h.01`,key:`e9boi3`}]]),u=t(`plus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]),d=r(n(),1);function f(){let[e,t]=(0,d.useState)(!1);return(0,d.useEffect)(()=>{},[]),e}var p=()=>e(()=>import(`./routes-BYr-dng4.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10])),m=c({sort:s().optional(),group:s().optional(),search:s().optional(),page:o().optional(),language:s().optional(),archived:s().optional(),healthMin:o().optional(),healthMax:o().optional(),starsMin:o().optional(),starsMax:o().optional(),topics:s().optional(),freshness:s().optional(),lists:s().optional()}),h=a(`/`)({component:i(p,`component`),validateSearch:m});export{l as i,f as n,u as r,h as t};
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/routes-8llA2c3j.js","assets/button-srM_gVNp.js","assets/sync-persistence-BJbWXISF.js","assets/registry-CDScSFs0.js","assets/schemas-CLMWt96T.js","assets/coerce-hGm-kFoB.js","assets/star-D-XjWe95.js","assets/badge-CVyqIkfu.js","assets/local-backups-BlLTb6g5.js","assets/local-sync-Cp5d59-N.js","assets/triangle-alert-ILMBIuGB.js"])))=>i.map(i=>d[i]);
2
+ import{G as e,R as t,lt as n,ot as r}from"./button-srM_gVNp.js";import{O as i,k as a,t as o}from"./coerce-hGm-kFoB.js";import{c as s,s as c}from"./schemas-CLMWt96T.js";var l=t(`info`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 16v-4`,key:`1dtifu`}],[`path`,{d:`M12 8h.01`,key:`e9boi3`}]]),u=t(`plus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]),d=n(r(),1);function f(){let[e,t]=(0,d.useState)(!1);return(0,d.useEffect)(()=>{},[]),e}var p=()=>e(()=>import(`./routes-8llA2c3j.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10])),m=c({sort:s().optional(),group:s().optional(),search:s().optional(),page:o().optional(),language:s().optional(),archived:s().optional(),healthMin:o().optional(),healthMax:o().optional(),starsMin:o().optional(),starsMax:o().optional(),topics:s().optional(),freshness:s().optional(),lists:s().optional()}),h=a(`/`)({component:i(p,`component`),validateSearch:m});export{l as i,f as n,u as r,h as t};