@yusoltsev/flint-cli 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/flint.js +2 -2
- package/package.json +1 -1
package/dist/flint.js
CHANGED
|
@@ -40,7 +40,7 @@ Comments:
|
|
|
40
40
|
${dt(r)}`}},Cn=new Set(["assignee","priority","status","title"]),An=async(e,t,{fromValue:n,kind:s,toValue:i})=>{let r=async(o)=>{if(o===null)return"none";if(s==="priority")return oe[Number(o)]??String(o);let a=String(o);if(s==="status")return $e(t,a)||a;if(s==="assignee")return`@${(await e.members(t.workspaceSlug)).find((c)=>c.userId===a)?.username??a}`;return(await e.labels(t.workspaceSlug)).find((u)=>u.id===a)?.name??a};if(s==="label_added"||s==="label_removed")return await r(i??n);return Cn.has(s)?`${await r(n)} → ${await r(i)}`:""},In=async(e)=>{let t=j(await m()),n=await p(t.config,"GET /issues/:issueKey/activity",{params:{issueKey:e}});return{result:n,text:async()=>{let s=await t.project(le(e)),i=await Promise.all(n.map(async(r)=>[O(r.createdAt),`@${r.actor?.username??"system"}${r.viaApi?" via API":""}`,r.kind.replace("_"," "),await An(t,s,r)]));return w(i)}}},Pn=async(e,t,n)=>{let s=j(await m()),i=await ue(s.config,e),r=t.join(" "),o=it(i.description,r,n.uncheck!==!0);if("matches"in o){let a=o.matches.map(({done:l,number:u,text:c})=>`${u} [${l?"x":" "}] ${c}`).join("; ");throw d(o.matches.length===0?`No checklist item “${r}” in ${i.key}`:`“${r}” matches ${o.matches.length} checklist items in ${i.key}: ${a}; pass the number`)}return ce(s,await Te(s.config,e,{description:o.markdown,version:i.version}))},De=(e)=>e.map(({contentType:t,filename:n,url:s})=>`${t.startsWith("image/")?"!":""}[${n.replaceAll(/[[\]]/gu,"")}](${s})`),Sn=async(e,t,n)=>{let s=j(await m()),i={issueKey:e},r=await ie(t,async(a)=>await p(s.config,"POST /issues/:issueKey/attachments",{body:a,params:i})),o=()=>r.map(({filename:a,url:l})=>`${a} ${l}`).join(`
|
|
41
41
|
`);if(n.inline!==!0)return{result:r,text:o};try{let a=await ue(s.config,e),l=[a.description,...De(r)].filter((c)=>c!=="").join(`
|
|
42
42
|
|
|
43
|
-
`),u=await Te(s.config,e,{description:l,version:a.version});return{result:{attachments:r,issue:u},text:o}}catch(a){throw a instanceof g?B(a,r):a}},Tn=async(e,t)=>{await b(`Delete ${e.join(", ")}?`,t.yes);let n=j(await m());return await je(n,e,async(s)=>await p(n.config,"DELETE /issues/:issueKey",{params:{issueKey:s}}))},$n=async(e)=>{let t=j(await m());return await je(t,e,async(n)=>await p(t.config,"POST /issues/:issueKey/restore",{params:{issueKey:n}}))},ut=(e)=>e.option("-d, --description <text>","the text").option("-F, --file <file>","read the text from a file, - for stdin"),lt=async(e,t)=>{let n=await L(e,t);if(n===void 0)throw d("Pass the text as arguments, -d <text> or -F <file|->");return n},yt=(e)=>{let t=e.command("issue").description("Work with issues");t.command("list").description("List issues: the working set (open plus closed in the last 14 days), or --closed").option("-p, --project <key>","project key").option("-w, --workspace <slug>","workspace, for issues across its projects").option("-s, --status <name>","status name (repeat for any of several)",x).option("-a, --assignee <user>","@me, none, a username or id (repeatable)",x).option(Ie,"label name or id (repeatable)",x).option("--priority <priority>","none|urgent|high|medium|low or 0-4 (repeatable)",x).option("-q, --query <text>","title text, an exact key or full-text search").option("--closed","list completed and canceled issues, newest first").option("--limit <n>","page size with --closed (default 50, max 200)").option("--offset <n>","page offset with --closed").action(f(xn)),t.command("view").description("Show an issue with its properties and Git links").argument("<key>","issue key, such as ENG-12").option("--comments","include the comments").action(f(On)),ot(t.command("create").description("Create an issue").option("-p, --project <key>","project key (default: flint link)").option("-w, --workspace <slug>","check that the project is in this workspace")).option(Ie,"label name (repeatable)",x).action(f(async(s)=>{if(s.title===void 0)throw d("issue create needs -t <title>");return ct(s.title),await En(s)})),ot(t.command("update").alias("edit").description("Change one issue, or the same properties of several (bulk)").argument(...ae)).option(Ie,"replace the labels (repeatable)",x).option("--add-label <name>","add a label (repeatable)",x).option("--remove-label <name>","remove a label (repeatable)",x).option("--if-version <n>","fail with conflict unless the issue is still at this version").action(f(at)),t.command("status").description("Set the status of one or more issues").argument("<status>","status name, quoted when it has spaces").argument(...ae).action(f(async(s,i)=>{if(rt(s)&&!i.every(rt))throw d(`Unknown status “${s}”; the status comes first: flint issue status <status> <keys...>`);return await at(i,{status:s})})),t.command("check").description("Tick a checklist item by number or text").argument(...V).argument("<item...>","item number (1-based) or text it contains").option("--uncheck","clear the box instead").action(f(Pn)),t.command("activity").description("Show the history of an issue").argument(...V).action(f(In)),t.command("attach").description("Upload files to an issue").argument(...V).argument("<files...>","files to upload").option("--inline","also append Markdown links to the description").action(f(Sn)),t.command("branch").description("Print a Git branch name that links to the issue").argument(...V).action(f(async(s)=>{let i=await m(),[r,o]=await Promise.all([ue(i,s),p(i,"GET /me")]),a=st(o.username,r.key,r.title);return{raw:a,result:a}})),t.command("delete").description("Delete issues (restorable with issue restore)").argument(...ae).option(...k).action(f(Tn)),t.command("restore").description("Restore deleted issues").argument(...ae).action(f($n));let n=e.command("comment").description("Work with issue comments");n.command("list").description("List the comments of an issue").argument(...V).action(f(async(s)=>{let i=await p(await m(),"GET /issues/:issueKey/comments",{params:{issueKey:s}});return{result:i,text:()=>dt(i)}})),ut(n.command("add").description("Comment on an issue").argument(...V).argument("[text...]","comment text (Markdown)")).action(f(async(s,i,r)=>{let o=await p(await m(),"POST /issues/:issueKey/comments",{body:{body:await lt(r,i)},params:{issueKey:s}});return{result:o,text:()=>`Commented on ${s} (${o.id})`}})),ut(n.command("edit").description("Replace the text of your comment").argument("<id>","comment id").argument("[text...]","new text (Markdown)")).action(f(async(s,i,r)=>({result:await p(await m(),"PATCH /comments/:commentId",{body:{body:await lt(r,i)},params:{commentId:s}}),text:()=>`Edited comment ${s}`}))),n.command("delete").description("Delete your comment").argument("<id>","comment id").option(...k).action(f(async(s,i)=>(await b(`Delete comment ${s}?`,i.yes),await p(await m(),"DELETE /comments/:commentId",{params:{commentId:s}}),{result:{deleted:s},text:()=>`Deleted comment ${s}`})))};var gt={name:"@yusoltsev/flint-cli",version:"0.0.
|
|
43
|
+
`),u=await Te(s.config,e,{description:l,version:a.version});return{result:{attachments:r,issue:u},text:o}}catch(a){throw a instanceof g?B(a,r):a}},Tn=async(e,t)=>{await b(`Delete ${e.join(", ")}?`,t.yes);let n=j(await m());return await je(n,e,async(s)=>await p(n.config,"DELETE /issues/:issueKey",{params:{issueKey:s}}))},$n=async(e)=>{let t=j(await m());return await je(t,e,async(n)=>await p(t.config,"POST /issues/:issueKey/restore",{params:{issueKey:n}}))},ut=(e)=>e.option("-d, --description <text>","the text").option("-F, --file <file>","read the text from a file, - for stdin"),lt=async(e,t)=>{let n=await L(e,t);if(n===void 0)throw d("Pass the text as arguments, -d <text> or -F <file|->");return n},yt=(e)=>{let t=e.command("issue").description("Work with issues");t.command("list").description("List issues: the working set (open plus closed in the last 14 days), or --closed").option("-p, --project <key>","project key").option("-w, --workspace <slug>","workspace, for issues across its projects").option("-s, --status <name>","status name (repeat for any of several)",x).option("-a, --assignee <user>","@me, none, a username or id (repeatable)",x).option(Ie,"label name or id (repeatable)",x).option("--priority <priority>","none|urgent|high|medium|low or 0-4 (repeatable)",x).option("-q, --query <text>","title text, an exact key or full-text search").option("--closed","list completed and canceled issues, newest first").option("--limit <n>","page size with --closed (default 50, max 200)").option("--offset <n>","page offset with --closed").action(f(xn)),t.command("view").description("Show an issue with its properties and Git links").argument("<key>","issue key, such as ENG-12").option("--comments","include the comments").action(f(On)),ot(t.command("create").description("Create an issue").option("-p, --project <key>","project key (default: flint link)").option("-w, --workspace <slug>","check that the project is in this workspace")).option(Ie,"label name (repeatable)",x).action(f(async(s)=>{if(s.title===void 0)throw d("issue create needs -t <title>");return ct(s.title),await En(s)})),ot(t.command("update").alias("edit").description("Change one issue, or the same properties of several (bulk)").argument(...ae)).option(Ie,"replace the labels (repeatable)",x).option("--add-label <name>","add a label (repeatable)",x).option("--remove-label <name>","remove a label (repeatable)",x).option("--if-version <n>","fail with conflict unless the issue is still at this version").action(f(at)),t.command("status").description("Set the status of one or more issues").argument("<status>","status name, quoted when it has spaces").argument(...ae).action(f(async(s,i)=>{if(rt(s)&&!i.every(rt))throw d(`Unknown status “${s}”; the status comes first: flint issue status <status> <keys...>`);return await at(i,{status:s})})),t.command("check").description("Tick a checklist item by number or text").argument(...V).argument("<item...>","item number (1-based) or text it contains").option("--uncheck","clear the box instead").action(f(Pn)),t.command("activity").description("Show the history of an issue").argument(...V).action(f(In)),t.command("attach").description("Upload files to an issue").argument(...V).argument("<files...>","files to upload").option("--inline","also append Markdown links to the description").action(f(Sn)),t.command("branch").description("Print a Git branch name that links to the issue").argument(...V).action(f(async(s)=>{let i=await m(),[r,o]=await Promise.all([ue(i,s),p(i,"GET /me")]),a=st(o.username,r.key,r.title);return{raw:a,result:a}})),t.command("delete").description("Delete issues (restorable with issue restore)").argument(...ae).option(...k).action(f(Tn)),t.command("restore").description("Restore deleted issues").argument(...ae).action(f($n));let n=e.command("comment").description("Work with issue comments");n.command("list").description("List the comments of an issue").argument(...V).action(f(async(s)=>{let i=await p(await m(),"GET /issues/:issueKey/comments",{params:{issueKey:s}});return{result:i,text:()=>dt(i)}})),ut(n.command("add").description("Comment on an issue").argument(...V).argument("[text...]","comment text (Markdown)")).action(f(async(s,i,r)=>{let o=await p(await m(),"POST /issues/:issueKey/comments",{body:{body:await lt(r,i)},params:{issueKey:s}});return{result:o,text:()=>`Commented on ${s} (${o.id})`}})),ut(n.command("edit").description("Replace the text of your comment").argument("<id>","comment id").argument("[text...]","new text (Markdown)")).action(f(async(s,i,r)=>({result:await p(await m(),"PATCH /comments/:commentId",{body:{body:await lt(r,i)},params:{commentId:s}}),text:()=>`Edited comment ${s}`}))),n.command("delete").description("Delete your comment").argument("<id>","comment id").option(...k).action(f(async(s,i)=>(await b(`Delete comment ${s}?`,i.yes),await p(await m(),"DELETE /comments/:commentId",{params:{commentId:s}}),{result:{deleted:s},text:()=>`Deleted comment ${s}`})))};var gt={name:"@yusoltsev/flint-cli",version:"0.0.4",description:"Command-line client for the Flint issue tracker and wiki",keywords:["ai-agents","cli","flint","gitea","issue-tracker","wiki"],homepage:"https://github.com/yegor-usoltsev/flint/tree/main/cli#readme",bugs:"https://github.com/yegor-usoltsev/flint/issues",license:"MIT",author:"Yegor Usoltsev (https://github.com/yegor-usoltsev)",repository:{type:"git",url:"git+https://github.com/yegor-usoltsev/flint.git",directory:"cli"},bin:{flint:"dist/flint.js"},files:["dist/flint.js","dist/licenses.md"],type:"module",scripts:{prepack:"cd .. && bun run cli:build"},engines:{node:">=22.12"}};var vt="issue key such as ENG-12, or a wiki page id from trash list",Dn=/^[a-z][a-z0-9]*-\d+$/iu,Nn=/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu,kt=(e)=>{if(Dn.test(e))return"issue";if(Nn.test(e))return"page";throw d(`${e} is neither an issue key nor a wiki page id`)},wt=(e)=>e===null?"":`@${e.username}`,Fn=(e)=>{let t=e.kind==="folder"?"/":"",n=e.descendants>0?` (+${String(e.descendants)})`:"";return e.path+t+n},Gn=async(e)=>{let t=await m(),n=await v(t,e),s=await p(t,"GET /workspaces/:slug/trash",{params:{slug:n}});return{result:s,text:()=>w([["ITEM","TITLE","DELETED","BY","PURGED"],...s.issues.map((i)=>[i.key,i.title,O(i.deletedAt),wt(i.deletedBy),O(i.purgeAt)]),...s.pages.map((i)=>[i.id,`${i.title} · ${Fn(i)}`,O(i.deletedAt),wt(i.deletedBy),O(i.purgeAt)])])}},Ln=async(e)=>{let t=await m();if(kt(e)==="issue"){let s=await p(t,"POST /issues/:issueKey/restore",{params:{issueKey:e}});return{result:s,text:()=>`Restored ${s.key}`}}let n=await p(t,"POST /wiki/:pageId/restore",{params:{pageId:e}});return{result:n,text:()=>`Restored ${n.path}`}},Rn=async(e,t)=>{let n=kt(e);await b(`Delete ${e} forever? This cannot be undone.`,t.yes);let s=await m();return await(n==="issue"?p(s,"DELETE /trash/issues/:issueKey",{params:{issueKey:e}}):p(s,"DELETE /trash/wiki/:pageId",{params:{pageId:e}})),{result:{deleted:e},text:()=>`Deleted ${e} forever`}},bt=(e)=>{let t=e.command("trash").description("Deleted issues and wiki pages, kept for the instance's retention period (default 30 days)");t.command("list").description("List the trash of a workspace").option("-w, --workspace <slug>","workspace (default: flint link)").option("-p, --project <key>","use the workspace of this project").action(f(Gn)),t.command("restore").description("Restore an issue or a wiki page with the pages under it").argument("<item>",vt).action(f(Ln)),t.command("delete").description("Delete an item in the trash forever (workspace admins)").argument("<item>",vt).option(...k).action(f(Rn))};var I=(e)=>e.option("-w, --workspace <slug>","workspace (default: flint link)").option("-p, --project <key>","use the workspace of this project"),pe=async(e,t,n)=>({_splat:n.split("/").filter(Boolean).join("/"),slug:await v(e,t)}),U=async(e,t,n)=>await p(e,"GET /workspaces/:slug/wiki/*",{params:await pe(e,t,n)}),_t=(e)=>()=>`${e.title} (${"path"in e?e.path:"revision"} r${e.revision})
|
|
44
44
|
|
|
45
45
|
${e.body}`,Z=(e)=>({result:e,text:_t(e)}),Mn=(e)=>{let t=new Map;for(let r of e){let o=r.path.includes("/")?r.path.slice(0,r.path.lastIndexOf("/")):"";t.set(o,[...t.get(o)??[],r])}let n=new Set(e.map((r)=>r.path)),s=(r,o)=>(t.get(r)??[]).toSorted((a,l)=>a.sortKey<l.sortKey?-1:1).flatMap((a)=>[[`${" ".repeat(o)}${a.path.slice(a.path.lastIndexOf("/")+1)}${a.kind==="folder"?"/":""}`,a.title],...s(a.path,o+1)]),i=[...t.keys()].filter((r)=>r!==""&&!n.has(r));return[...s("",0),...i.flatMap((r)=>[[`${r}/`,""],...s(r,1)])]},qn=async(e)=>{let t=await m(),n=await p(t,"GET /workspaces/:slug/wiki",{params:{slug:await v(t,e)},query:{prefix:e.prefix}});return{result:n,text:()=>w(Mn(n))}},Wn=async(e,t)=>{let n=await m(),s=await U(n,t,e),i=t.revision===void 0?s:await p(n,"GET /wiki/:pageId/revisions/:revision",{params:{pageId:s.id,revision:String(A(t.revision,"--revision"))}});return{raw:t.raw===!0?i.body:void 0,result:i,text:_t(i)}},Hn=async(e,t,n)=>{let s=await L(n,t);if(s===void 0)throw d("wiki put needs the page text: -F <file|->, -d <text> or arguments");let i=await m(),r=await p(i,"PUT /workspaces/:slug/wiki/*",{body:{baseRevision:n.baseRevision===void 0?void 0:A(n.baseRevision,"--base-revision"),body:s,id:n.id,title:n.title},params:await pe(i,n,e)});return Z(r)},Vn=async(e,t,n)=>{let s=await L(n,t);if(s===void 0||s==="")throw d("wiki append needs text: arguments, -d <text> or -F <file|->");let i=await m();return Z(await p(i,"PATCH /workspaces/:slug/wiki/*",{body:{append:s},params:await pe(i,n,e)}))},Un=async(e,t)=>{let n=await m();return Z(await p(n,"PUT /workspaces/:slug/wiki/*",{body:{kind:"folder",title:t.title},params:await pe(n,t,e)}))},zn=async(e,t,n)=>{let s=await m(),i=await U(s,n,e);return Z(await p(s,"POST /wiki/:pageId/move",{body:{path:t,sortKey:n.sortKey},params:{pageId:i.id}}))},Kn=async(e,t)=>{let n=await m(),s=await U(n,t,e),i=await p(n,"GET /wiki/:pageId/revisions",{params:{pageId:s.id}});return{result:i,text:()=>w(i.map((r)=>[`r${r.revision}`,O(r.updatedAt),`@${r.author.username}${r.viaApi?" via API":""}`,r.title]))}},Jn=async(e,t,n)=>{let s=A(t,"revision"),i=await m(),r=await U(i,n,e);return Z(await p(i,"POST /wiki/:pageId/revisions/:revision/restore",{params:{pageId:r.id,revision:String(s)}}))},Bn=async(e,t)=>{await b(`Move wiki page ${e} and the pages under it to the trash?`,t.yes);let n=await m(),s=await U(n,t,e);return await p(n,"DELETE /wiki/:pageId",{params:{pageId:s.id}}),{result:{deleted:s.path,id:s.id},text:()=>`Moved ${s.path} to the trash (restore: flint trash restore ${s.id})`}},Xn=T({error:T({code:ve("conflict")})}),Zn=async(e,t,n)=>{let s=await m(),i=await U(s,n,e),r=await ie(t,async(u)=>await p(s,"POST /wiki/:pageId/attachments",{body:u,params:{pageId:i.id}})),o=()=>r.map(({filename:u,url:c})=>`${u} ${c}`).join(`
|
|
46
46
|
`);if(n.inline!==!0)return{result:r,text:o};let a=`
|
|
@@ -89,6 +89,6 @@ compdef _flint flint
|
|
|
89
89
|
Load it in your shell profile:
|
|
90
90
|
bash eval "$(flint completion bash)"
|
|
91
91
|
zsh source <(flint completion zsh) (after compinit)
|
|
92
|
-
fish flint completion fish | source`).action(f(async(t)=>{let n=ds[t];return await Promise.resolve({raw:n,result:n})})),e.command("__complete",{hidden:!0}).argument("[words...]").action((t)=>{for(let n of gs(e,t))console.log(n)})},ws=()=>{let e=new q("flint").description("Flint issue tracker and wiki from the command line").version(`${gt.version} (
|
|
92
|
+
fish flint completion fish | source`).action(f(async(t)=>{let n=ds[t];return await Promise.resolve({raw:n,result:n})})),e.command("__complete",{hidden:!0}).argument("[words...]").action((t)=>{for(let n of gs(e,t))console.log(n)})},ws=()=>{let e=new q("flint").description("Flint issue tracker and wiki from the command line").version(`${gt.version} (6957463)`).option("--json","print JSON (the default when stdout is not a terminal)").option("--human","print text even when stdout is not a terminal").exitOverride().configureOutput({outputError:()=>{}}).addHelpText("after",cs);return ms(e),yt(e),xt(e),bt(e),Tt(e),hs(e),vs(e),e},ks=new Map([["close",["status Done <keys...>"]],["get",["view","get"]],["ls",["list"]],["new",["create"]],["open",["view","get"]],["remove",["delete"]],["rm",["delete"]],["show",["view","get"]]]),bs=(e,t,n)=>{let s=e;for(let i of t){if(i===n)return s;s=s.commands.find((r)=>r.name()===i||r.aliases().includes(i))??s}return s},_s=(e,t,n)=>{let s=/^unknown command '(?<word>[^']+)'$/u.exec(n)?.groups?.word;if(s===void 0)return n;let i=bs(e,t,s),r=new Set(i.commands.flatMap((a)=>[a.name(),...a.aliases()])),o=ks.get(s)?.find((a)=>r.has(a.split(" ")[0]??""));return o===void 0?n:`${n}
|
|
93
93
|
(Did you mean ${[i.name(),o].filter((a)=>a!=="flint").join(" ")}?)`},$t=async(e)=>{let t=ws();try{return await t.parseAsync(e,{from:"user"}),0}catch(n){if(n instanceof C&&n.exitCode===0)return 0;let s=new g(n instanceof Error?n.message:String(n),1);if(n instanceof g)s=n;else if(n instanceof C)s=d(n.code==="commander.help"?"Missing command":_s(t,e,n.message.replace(/^error: /u,"")));if(be(e))console.log(JSON.stringify(s.body));else console.error(s.exitCode===2?`${s.message}
|
|
94
94
|
Run flint --help for usage.`:s.message);return s.exitCode}};process.exitCode=await $t(process.argv.slice(2));
|