@snelusha/noto 1.3.4-beta.1 → 1.3.4-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +19 -19
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{createCli as
|
|
3
|
-
Please run \`noto upgrade\` to update`.trim())}var i=async(e,t=!0)=>{if(t)await
|
|
4
|
-
${
|
|
5
|
-
${
|
|
6
|
-
${
|
|
7
|
-
${g.dim(`run ${g.cyan("`git init`")} to initialize a new repository.`)}`),await i(1);if(!a.git.diff&&!n)return f.log.error(
|
|
8
|
-
${g.dim(`run ${g.cyan("`git add <file>`")} or ${g.cyan("`git add .`")} to stage changes.`)}`),await i(1);if(await j(
|
|
2
|
+
import{createCli as Ut}from"trpc-cli";var W="@snelusha/noto",I="1.3.4-beta.2";import ht from"node:fs/promises";import{initTRPC as yt}from"@trpc/server";import*as O from"@clack/prompts";import v from"picocolors";import ne from"dedent";import Qe from"simple-git";var P=Qe(),_=async()=>{return P.checkIsRepo()},K=async()=>{try{return await P.revparse(["--show-toplevel"])}catch{return null}};var fe=async(e=20,t=!1)=>{try{let a=t?{maxCount:e,"--no-merges":null}:{maxCount:e};return(await P.log(a)).all.map((r)=>r.message)}catch{return null}};var he=async()=>{try{return P.diff(["--cached","--",":!*.lock"])}catch{return null}},j=async(e,t)=>{try{let a=t?{"--amend":null}:void 0,{summary:{changes:o}}=await P.commit(e,void 0,a);return Boolean(o)}catch{return!1}},ye=async()=>{try{let e=await P.push();return e.update||e.pushed&&e.pushed.length>0}catch{return!1}},we=async()=>{try{return(await P.branch()).current}catch{return null}},be=async(e)=>{try{let t=await P.branch();return e?t.all:Object.keys(t.branches).filter((a)=>!a.startsWith("remotes/"))}catch{return null}},oe=async(e)=>{try{return await P.checkout(e,{}),!0}catch{return!1}},re=async(e)=>{try{return await P.checkoutLocalBranch(e),!0}catch{return!1}};import tt from"os";import{join as at,resolve as ot}from"path";import{z as B}from"zod";import{promises as Y}from"fs";import{dirname as Ze}from"path";function H(e){let{schema:t,path:a}=e;return class{static storagePath=a;static storage={};static async load(){try{await Y.access(this.storagePath);let r=await Y.readFile(this.storagePath,"utf-8"),n=r?JSON.parse(r):{},s=t.safeParse(n);this.storage=s.success?s.data:{}}catch{this.storage={}}return this.storage}static async save(){try{let r=Ze(this.storagePath);await Y.mkdir(r,{recursive:!0});let n=JSON.stringify(this.storage,null,2);await Y.writeFile(this.storagePath,n,"utf-8")}catch{}}static async update(r){try{await this.load();let n=await r(this.storage),s=t.safeParse(n);if(s.success)this.storage=s.data,await this.save()}catch{}return this.storage}static async get(){return await this.load(),JSON.parse(JSON.stringify(this.storage))}static async clear(){this.storage={},await this.save()}static get path(){return this.storagePath}static set path(r){this.storagePath=r}static get raw(){return this.storage}}}import{z as et}from"zod";var ve=et.enum(["gemini-1.5-flash","gemini-1.5-flash-latest","gemini-1.5-flash-8b","gemini-1.5-flash-8b-latest","gemini-1.5-pro","gemini-1.5-pro-latest","gemini-2.0-flash-001","gemini-2.0-flash","gemini-2.0-flash-lite-preview-02-05","gemini-2.5-flash-preview-04-17","gemini-2.5-pro-preview-05-06"]);var rt=B.object({llm:B.object({apiKey:B.string().optional(),model:ve.optional().or(B.string())}).optional(),lastGeneratedMessage:B.string().optional()}),p=H({path:ot(at(tt.homedir(),".config","noto"),".notorc"),schema:rt});async function xe(){try{let e=await p.get();await p.update(()=>e)}catch{}}import it from"node:fs/promises";import E from"node:path";import{fileURLToPath as st}from"node:url";var Me=(e)=>e instanceof URL?st(e):e;async function ke(e,t={}){let a=E.resolve(Me(t.cwd??"")),{root:o}=E.parse(a);t.stopAt=E.resolve(Me(t.stopAt??o));let r=E.isAbsolute(e);while(a){let n=r?e:E.join(a,e);try{let s=await it.stat(n);if(t.type===void 0||t.type==="file"&&s.isFile()||t.type==="directory"&&s.isDirectory())return n}catch{}if(a===t.stopAt||a===o)break;a=E.dirname(a)}}var X=async()=>{let e=await K();return await ke(".noto/commit-prompt.md",{stopAt:e||process.cwd(),type:"file"})};import*as Pe from"@clack/prompts";import Ce from"picocolors";import gt from"dedent";import y from"semver";import ie from"latest-version";import nt from"os";import{join as ct,resolve as lt}from"path";import{z as R}from"zod";var mt=R.object({commitGenerationCache:R.record(R.string(),R.string()).optional(),update:R.object({timestamp:R.number(),current:R.string(),latest:R.string()}).optional()}),U=H({path:lt(ct(nt.homedir(),".cache","noto"),"cache"),schema:mt});var pt=43200000;function dt(e,t){if(!e||!t)return e||t||null;let a=y.coerce(t)?.version,o=y.coerce(e)?.version;if(!a||!o)return e||t||null;return a===o||y.gt(o,a)?e:t}async function se(e=!1,t=!1){let a=(await U.get()).update;if(!t&&a){if(y.valid(a.current)&&y.valid(a.latest)){let r=y.gte(a.current,a.latest),n=Date.now()-a.timestamp<pt;if(r||n)return{latest:a.latest,current:a.current,timestamp:a.timestamp}}}try{let n={latest:I.includes("beta")?dt(...await Promise.all([ie(W,{version:"beta"}),ie(W)])):await ie(W),current:I,timestamp:Date.now()};if(e)await ut(n);return n}catch{if(a)return{latest:a.latest,current:a.current,timestamp:a.timestamp};return{latest:I,current:I,timestamp:Date.now()}}}async function ut(e){if(!e)return;await U.update((t)=>({...t,update:e&&{timestamp:e.timestamp,latest:e.latest,current:e.current}}))}async function J(e=!1,t=!1){let a=await se(e,t);if(y.valid(a.current)&&y.valid(a.latest)){if(!y.gte(a.current,a.latest))return a}return null}async function ft(){let e=await J();if(e)Pe.log.warn(gt`A new version of noto is available: ${Ce.dim(e.current)} → ${Ce.green(e.latest)}
|
|
3
|
+
Please run \`noto upgrade\` to update`.trim())}var i=async(e,t=!0)=>{if(t)await ft();await new Promise((a)=>setTimeout(a,1)),console.log(),process.exit(e)};var G=yt.meta().create({defaultMeta:{intro:!0,authRequired:!0,repoRequired:!0,diffRequired:!1,promptRequired:!1}}),Se=G.middleware(async(e)=>{let{meta:t,next:a}=e,o=await p.get(),r=process.env.NOTO_API_KEY||o.llm?.apiKey;if(t?.authRequired&&!r)return O.log.error(ne`${v.red("noto api key is missing.")}
|
|
4
|
+
${v.dim(`run ${v.cyan("`noto config key`")} to set it up.`)}`),await i(1);return a()}),Re=G.middleware(async(e)=>{let{meta:t,next:a}=e,o=await _();if(t?.repoRequired&&!o)return O.log.error(ne`${v.red("no git repository found in cwd.")}
|
|
5
|
+
${v.dim(`run ${v.cyan("`git init`")} to initialize a new repository.`)}`),await i(1);let r=o&&await he();if(t?.diffRequired&&!r)return O.log.error(ne`${v.red("no staged changes found.")}
|
|
6
|
+
${v.dim(`run ${v.cyan("`git add <file>`")} or ${v.cyan("`git add .`")} to stage changes.`)}`),await i(1);let n=null;if(t?.promptRequired){let s=await X();if(s)try{n=await ht.readFile(s,"utf-8")}catch{}}return a({ctx:{noto:{prompt:n},git:{isRepository:o,diff:r}}})}),x=G.procedure.use((e)=>{let{meta:t,next:a}=e;if(t?.intro)console.log(),O.intro(`${v.bgCyan(v.black(" @snelusha/noto "))}`);return a()}),Pa=x.use(Se),Q=x.use(Re),Z=x.use(Se).use(Re);import{z as D}from"zod";import*as c from"@clack/prompts";import u from"picocolors";import wt from"clipboardy";var Ae=Q.meta({description:"checkout a branch"}).input(D.object({copy:D.boolean().meta({description:"copy the selected branch to clipboard",alias:"c"}),create:D.union([D.boolean(),D.string()]).optional().meta({description:"create a new branch",alias:"b"}),branch:D.string().optional().meta({positional:!0})})).mutation(async(e)=>{let{input:t}=e,a=await be();if(!a)return c.log.error("failed to fetch branches"),await i(1);let o=await we(),r=typeof t.create==="string"?t.create:t.branch;if((t.create===!0||typeof t.create==="string")&&r){if(a.includes(r))return c.log.error(`branch ${u.red(r)} already exists in the repository`),await i(1);if(!await re(r))return c.log.error(`failed to create and checkout ${u.bold(r)}`),await i(1);return c.log.success(`created and checked out ${u.green(r)}`),await i(0)}if(r){if(!a.includes(r)){c.log.error(`branch ${u.red(r)} does not exist in the repository`);let T=await c.confirm({message:`do you want to create branch ${u.green(r)}?`});if(c.isCancel(T))return c.log.error("aborted"),await i(1);if(T){if(!await re(r))return c.log.error(`failed to create and checkout ${u.bold(r)}`),await i(1);return c.log.success(`created and checked out ${u.green(r)}`),await i(0)}return await i(1)}if(r===o)return c.log.error(`${u.red("already on branch")} ${u.green(r)}`),await i(1);if(!await oe(r))return c.log.error(`failed to checkout ${u.bold(r)}`),await i(1);return c.log.success(`checked out ${u.green(r)}`),await i(0)}if(a.length===0)return c.log.error("no branches found in the repository"),await i(1);let s=await c.select({message:"select a branch to checkout",options:a.map((l)=>({value:l,label:u.bold(l===o?u.green(l):l),hint:l===o?"current branch":void 0})),initialValue:o});if(c.isCancel(s))return c.log.error("nothing selected!"),await i(1);if(!s)return c.log.error("no branch selected"),await i(1);if(t.copy)return wt.writeSync(s),c.log.success(`copied ${u.green(s)} to clipboard`),await i(0);if(s===o)return c.log.error(`${u.red("already on branch")}`),await i(1);if(!await oe(s))return c.log.error(`failed to checkout ${u.bold(s)}`),await i(1);c.log.success(`checked out ${u.green(s)}`),await i(0)});import{z as bt}from"zod";import*as M from"@clack/prompts";import ce from"picocolors";var Ie=x.meta({description:"configure noto api key"}).input(bt.string().optional().describe("apiKey")).mutation(async(e)=>{let{input:t}=e,a=t;if((await p.get()).llm?.apiKey){let o=await M.confirm({message:"noto api key already configured, do you want to update it?"});if(M.isCancel(o)||!o)return M.log.error(ce.red("nothing changed!")),await i(1)}if(!a){let o=await M.text({message:"enter your noto api key"});if(M.isCancel(o))return M.log.error(ce.red("nothing changed!")),await i(1);a=o}await p.update((o)=>({...o,llm:{...o.llm,apiKey:a}})),M.log.success(ce.green("noto api key configured!")),await i(0)});import*as C from"@clack/prompts";import me from"picocolors";import{createGoogleGenerativeAI as vt}from"@ai-sdk/google";var k=vt({apiKey:process.env.NOTO_API_KEY||(await p.get()).llm?.apiKey||"api-key"}),Ge="gemini-2.0-flash",ee={"gemini-1.5-flash":k("gemini-1.5-flash"),"gemini-1.5-flash-latest":k("gemini-1.5-flash-latest"),"gemini-1.5-flash-8b":k("gemini-1.5-flash-8b"),"gemini-1.5-flash-8b-latest":k("gemini-1.5-flash-8b-latest"),"gemini-1.5-pro":k("gemini-1.5-pro"),"gemini-1.5-pro-latest":k("gemini-1.5-pro-latest"),"gemini-2.0-flash-001":k("gemini-2.0-flash-001"),"gemini-2.0-flash":k("gemini-2.0-flash"),"gemini-2.0-flash-lite-preview-02-05":k("gemini-2.0-flash-lite-preview-02-05"),"gemini-2.5-flash-preview-04-17":k("gemini-2.5-flash-preview-04-17"),"gemini-2.5-pro-preview-05-06":k("gemini-2.5-pro-preview-05-06")},xt=Object.keys(ee),le=async()=>{let e=(await p.get()).llm?.model;if(!e||!xt.includes(e))e=Ge,await p.update((t)=>({...t,llm:{...t.llm,model:Ge}}));return ee[e]};var Ne=x.meta({description:"configure model"}).mutation(async()=>{let e=await C.select({message:"select a model",initialValue:(await p.get()).llm?.model,options:Object.keys(ee).map((t)=>({label:t,value:t}))});if(C.isCancel(e))return C.log.error(me.red("nothing changed!")),await i(1);if(e==="gemini-2.5-pro-preview-05-06"){let t=await C.confirm({message:"this model does not have free quota tier, do you want to continue?"});if(C.isCancel(t)||!t)return C.log.error(me.red("nothing changed!")),await i(1)}await p.update((t)=>({...t,llm:{...t.llm,model:e}})),C.log.success(me.green("model configured!")),await i(0)});import*as N from"@clack/prompts";import $e from"picocolors";var Te=x.meta({description:"reset the configuration"}).mutation(async()=>{let e=await N.confirm({message:"are you sure you want to reset the configuration?"});if(N.isCancel(e)||!e)return N.log.error($e.red("nothing changed!")),await i(1);await p.clear(),N.log.success($e.green("configuration reset!")),await i(0)});var Ee=G.router({key:Ie,model:Ne,reset:Te});import{z as L}from"zod";import*as f from"@clack/prompts";import g from"picocolors";import Ue from"dedent";import Mt from"clipboardy";var Oe=Q.meta({description:"access the last generated commit",repoRequired:!1}).input(L.object({copy:L.boolean().meta({description:"copy the last commit to clipboard",alias:"c"}),apply:L.boolean().meta({description:"commit the last generated message",alias:"a"}),edit:L.boolean().meta({description:"edit the last generated commit message",alias:"e"}),amend:L.boolean().meta({description:"amend the last commit with the last message"})})).mutation(async(e)=>{let{input:t,ctx:a}=e,o=(await p.get()).lastGeneratedMessage;if(!o)return f.log.error(g.red("no previous commit message found")),await i(1);let{edit:r,amend:n}=t;if(n&&!r)return f.log.error(g.red("the --amend option requires the --edit option")),await i(1);if(f.log.step(r?g.white(o):g.green(o)),r){let s=await f.text({message:"edit the last generated commit message",initialValue:o,placeholder:o});if(f.isCancel(s))return f.log.error(g.red("nothing changed!")),await i(1);o=s,await p.update((b)=>({...b,lastGeneratedMessage:s})),f.log.step(g.green(o))}if(t.copy)Mt.writeSync(o),f.log.step(g.dim("copied last generated commit message to clipboard"));if(t.apply||n){if(!a.git.isRepository)return f.log.error(Ue`${g.red("no git repository found in cwd.")}
|
|
7
|
+
${g.dim(`run ${g.cyan("`git init`")} to initialize a new repository.`)}`),await i(1);if(!a.git.diff&&!n)return f.log.error(Ue`${g.red("no staged changes found.")}
|
|
8
|
+
${g.dim(`run ${g.cyan("`git add <file>`")} or ${g.cyan("`git add .`")} to stage changes.`)}`),await i(1);if(await j(o,n))f.log.step(g.dim("commit successful"));else f.log.error(g.red("failed to commit changes"))}return await i(0)});import ze from"node:fs/promises";import{z as pe}from"zod";import*as d from"@clack/prompts";import S from"picocolors";import q from"dedent";import{generateObject as je,wrapLanguageModel as Ct}from"ai";import te from"zod";import z from"dedent";import Fe from"superjson";import{createHash as kt}from"crypto";function De(e){let t=Buffer.from(e,"utf-8"),a=Buffer.from(`blob ${t.length}\x00`,"utf-8");return kt("sha1").update(a).update(t).digest("hex")}var Pt=z`
|
|
9
9
|
# System Instruction for Noto
|
|
10
10
|
|
|
11
11
|
You are a Git commit message generator for the \`noto\` CLI tool. Your role is to analyze staged code changes and generate clear, single-line commit messages that follow the user's established style.
|
|
@@ -76,7 +76,7 @@ Or whatever format matches the user's guidelines. **Must be single-line only.**
|
|
|
76
76
|
- Don't use generic or vague descriptions
|
|
77
77
|
|
|
78
78
|
**Remember:** Your output becomes permanent git history. Generate commit messages that are clear, accurate, and consistent with the user's established patterns.
|
|
79
|
-
`,
|
|
79
|
+
`,St=z`
|
|
80
80
|
# Commit Message Guidelines
|
|
81
81
|
|
|
82
82
|
## Format
|
|
@@ -148,7 +148,7 @@ For breaking changes, add \`!\` after the type/scope:
|
|
|
148
148
|
## Additional Notes
|
|
149
149
|
- If a commit addresses a specific issue, you can reference it in the description (e.g., \`fix: resolve memory leak (fixes #123)\`)
|
|
150
150
|
- Each commit should represent a single logical change
|
|
151
|
-
- Write commits as if completing the sentence: "If applied, this commit will..."`,
|
|
151
|
+
- Write commits as if completing the sentence: "If applied, this commit will..."`,Rt=z`
|
|
152
152
|
You are a commit style analyzer. Analyze the provided commit history and generate a personalized style guide that will be used to generate future commit messages.
|
|
153
153
|
|
|
154
154
|
## Task
|
|
@@ -304,27 +304,27 @@ Start with action verb (add, implement, resolve, update, simplify). Be specific
|
|
|
304
304
|
- The output will be stored as \`.noto/commit-prompt.md\` and used by an AI to generate commits
|
|
305
305
|
|
|
306
306
|
Generate the markdown guidelines now based on the commit history provided.
|
|
307
|
-
`,
|
|
307
|
+
`,At={wrapGenerate:async({doGenerate:e,params:t})=>{let a=De(JSON.stringify(t)),o=(await U.get()).commitGenerationCache;if(o&&a in o)return Fe.parse(o[a]);let r=await e();return await U.update((n)=>({...n,commitGenerationCache:{[a]:Fe.stringify(r)}})),r}},Be=async(e,t,a,o=!1)=>{let r=await le(),{object:n}=await je({model:!o?Ct({model:r,middleware:At}):r,schema:te.object({message:te.string()}),messages:[{role:"system",content:Pt},{role:"user",content:z`
|
|
308
308
|
USER GUIDELINES:
|
|
309
|
-
${t??
|
|
309
|
+
${t??St}
|
|
310
310
|
${a?`
|
|
311
311
|
USER CONTEXT:
|
|
312
312
|
${a}`:""}
|
|
313
313
|
|
|
314
314
|
GIT DIFF:
|
|
315
315
|
${e}
|
|
316
|
-
`}]});return n.message.trim()},Le=async(e)=>{let t=await
|
|
316
|
+
`}]});return n.message.trim()},Le=async(e)=>{let t=await le(),{object:a}=await je({model:t,schema:te.object({prompt:te.string()}),messages:[{role:"system",content:Rt},{role:"user",content:z`
|
|
317
317
|
COMMIT HISTORY:
|
|
318
318
|
${e.join(`
|
|
319
|
-
`)}`}]});return a.prompt.trim()};var
|
|
319
|
+
`)}`}]});return a.prompt.trim()};var It=q`
|
|
320
320
|
# Commit Message Guidelines
|
|
321
321
|
|
|
322
322
|
# Add your custom guidelines here.
|
|
323
|
-
# When no guidelines are present, noto will use conventional commits format by default.`,
|
|
324
|
-
${S.gray(n)}`);let h=await d.confirm({message:"do you want to create in the current directory instead?",initialValue:!0});if(d.isCancel(h)||!h)return d.log.error("aborted"),await i(1);r
|
|
325
|
-
${S.gray(n)}`),await i(1);if(a!==
|
|
326
|
-
${S.gray("at least 5 commits are required.")}`),await i(1)}else if(
|
|
327
|
-
${S.gray(
|
|
328
|
-
${n}`:"";
|
|
323
|
+
# When no guidelines are present, noto will use conventional commits format by default.`,qe=Z.meta({description:"initialize noto in the repository"}).input(pe.object({root:pe.boolean().meta({description:"create the prompt file in the git root"}),generate:pe.boolean().meta({description:"generate a prompt file based on existing commits"})})).mutation(async(e)=>{let{input:t}=e,a=await K(),o=a,r=process.cwd(),n=await X(),s=null;if(n)if(!n.startsWith(r)){d.log.warn(q`${S.yellow("a prompt file already exists!")}
|
|
324
|
+
${S.gray(n)}`);let h=await d.confirm({message:"do you want to create in the current directory instead?",initialValue:!0});if(d.isCancel(h)||!h)return d.log.error("aborted"),await i(1);o=r}else return d.log.error(q`${S.red("a prompt file already exists.")}
|
|
325
|
+
${S.gray(n)}`),await i(1);if(a!==r&&!t.root){let h=await d.confirm({message:"do you want to create the prompt file in the git root?",initialValue:!0});if(d.isCancel(h))return d.log.error("aborted"),await i(1);if(!h)o=r}let b=await fe(20,!0),l=t.generate;if(l){if(!b||b.length<5)return d.log.error(q`${S.red("not enough commits to generate a prompt file.")}
|
|
326
|
+
${S.gray("at least 5 commits are required.")}`),await i(1)}else if(b&&b.length>=5){let h=await d.confirm({message:"do you want to generate a prompt file based on existing commits?",initialValue:!0});if(d.isCancel(h))return d.log.error("aborted"),await i(1);l=h}let T=d.spinner();if(b&&l)T.start("generating commit message guidelines"),s=await Le(b),T.stop(S.green("generated commit message guidelines!"));else s=It;try{let h=`${o}/.noto`;await ze.mkdir(h,{recursive:!0});let ue=`${h}/commit-prompt.md`;return await ze.writeFile(ue,s,"utf-8"),d.log.success(q`${S.green("prompt file created!")}
|
|
327
|
+
${S.gray(ue)}`),await i(0)}catch{d.log.error(S.red("failed to create the prompt file!"))}});import{z as A}from"zod";import*as m from"@clack/prompts";import w from"picocolors";import Gt from"clipboardy";import{APICallError as Nt,RetryError as $t}from"ai";var Ve=Z.meta({description:"generate a commit message",default:!0,diffRequired:!0,promptRequired:!0}).input(A.object({message:A.string().or(A.boolean()).meta({description:"provide context for commit message",alias:"m"}),copy:A.boolean().meta({description:"copy the generated message to clipboard",alias:"c"}),apply:A.boolean().meta({description:"commit the generated message",alias:"a"}),push:A.boolean().meta({description:"commit and push the changes",alias:"p"}),force:A.boolean().meta({description:"bypass cache and force regeneration of commit message",alias:"f"}),manual:A.boolean().meta({description:"custom commit message"})})).mutation(async(e)=>{let{input:t,ctx:a}=e,o=m.spinner();try{if(t.manual){let l=await m.text({message:"edit the generated commit message",placeholder:"chore: init repo"});if(m.isCancel(l))return m.log.error(w.red("nothing changed!")),await i(1);if(m.log.step(w.green(l)),await p.update((h)=>({...h,lastGeneratedMessage:l})),await j(l))m.log.step(w.dim("commit successful"));else m.log.error(w.red("failed to commit changes"));return await i(0)}let n=t.message;if(typeof n==="string")n=n.trim();else if(typeof n==="boolean"&&n===!0){let l=await m.text({message:"provide context for the commit message",placeholder:"describe the changes"});if(m.isCancel(l))return m.log.error(w.red("nothing changed!")),await i(1);n=l}o.start("generating commit message");let s=null;s=await Be(a.git.diff,a.noto.prompt,typeof n==="string"?n:void 0,t.force),o.stop(w.white(s));let b=await m.text({message:"edit the generated commit message",initialValue:s,placeholder:s});if(m.isCancel(b))return m.log.error(w.red("nothing changed!")),await i(1);if(s=b,m.log.step(w.green(s)),await p.update((l)=>({...l,lastGeneratedMessage:s})),t.copy)Gt.writeSync(s),m.log.step(w.dim("copied commit message to clipboard"));if(t.apply)if(await j(s))m.log.step(w.dim("commit successful"));else m.log.error(w.red("failed to commit changes"));if(t.push)if(await ye())m.log.step(w.dim("push successful"));else m.log.error(w.red("failed to push changes"));return await i(0)}catch(r){let n;if($t.isInstance(r)&&Nt.isInstance(r.lastError))n=Tt(r.lastError.responseBody);let s=n?`
|
|
328
|
+
${n}`:"";o.stop(w.red(`failed to generate commit message${s}`),1),await i(1)}});function Tt(e){if(typeof e!=="string")return;try{let t=JSON.parse(e);return t?.error?.message??t?.message}catch{return}}import{spawn as Et}from"node:child_process";import*as F from"@clack/prompts";import ae from"picocolors";import*as $ from"node:fs";import*as V from"node:path";import*as We from"node:child_process";import de from"node:process";async function _e(){let e=de.argv[1];if(!e)return{packageManager:"unknown",isGlobal:!1};let t=de.cwd();try{let a=$.realpathSync(e).replace(/\\/g,"/"),o=t.replace(/\\/g,"/");if(await _()&&o&&a.startsWith(o)&&!a.includes("/node_modules/"))return{packageManager:"unknown",isGlobal:!1,updateMessage:'Running from a local git clone. Please update with "git pull".'};if(a.includes("/.npm/_npx")||a.includes("/npm/_npx"))return{packageManager:"npx",isGlobal:!1,updateMessage:"Running via npx, update not applicable."};if(de.platform==="darwin")try{return We.execSync('brew list -1 | grep -q "^noto$"',{stdio:"ignore"}),{packageManager:"homebrew",isGlobal:!0,updateMessage:'Installed via Homebrew. Please update with "brew upgrade".'}}catch{}if(a.includes("/pnpm/dlx")||a.includes("/pnpm-cache/dlx"))return{packageManager:"pnpx",isGlobal:!1,updateMessage:"Running via pnpx, update not applicable."};if(a.includes("/pnpm/global"))return{packageManager:"pnpm",isGlobal:!0,updateCommand:"pnpm add -g @snelusha/noto@latest",updateMessage:"Please run pnpm add -g @snelusha/noto@latest to update"};if(a.includes("/.yarn/global"))return{packageManager:"yarn",isGlobal:!0,updateCommand:"yarn global add @snelusha/noto@latest",updateMessage:"Please run yarn global add @snelusha/noto@latest to update"};if(a.includes("/bunx"))return{packageManager:"bunx",isGlobal:!1,updateMessage:"Running via bunx, update not applicable."};if(a.includes("/.bun/install/global"))return{packageManager:"bun",isGlobal:!0,updateCommand:"bun add -g @snelusha/noto@latest",updateMessage:"Please run bun add -g @snelusha/noto@latest to update"};if(o&&a.startsWith(`${o}/node_modules`)){let s="npm";if($.existsSync(V.join(t,"yarn.lock")))s="yarn";else if($.existsSync(V.join(t,"pnpm-lock.yaml")))s="pnpm";else if($.existsSync(V.join(t,"bun.lockb"))||$.existsSync(V.join(t,"bun.lock")))s="bun";return{packageManager:s,isGlobal:!1,updateMessage:"Locally installed. Please update via your project's package.json."}}let n="npm install -g @snelusha/noto@latest";return{packageManager:"npm",isGlobal:!0,updateCommand:n,updateMessage:`Please run ${n} to update`}}catch{return{packageManager:"unknown",isGlobal:!1}}}var Ke=x.meta({description:"upgrade noto"}).mutation(async()=>{let e=F.spinner();e.start("fetching latest version");let t=await J(!0,!0);if(!t)return e.stop(`You're already on the latest version of noto (${ae.dim(`which is ${I}`)})`),await i(0,!1);e.stop(`noto ${ae.green(t.latest)} is out! You are on ${ae.dim(t.current)}.`);let a=await _e();if(!a.updateCommand){if(a.updateMessage)return F.log.warn(a.updateMessage),await i(0,!1);return F.log.error("unable to determine update command for your installation."),await i(1,!1)}let o=Et(a.updateCommand,{stdio:"pipe",shell:!0});e.start("upgrading noto");try{await new Promise((r,n)=>{o.on("close",(s)=>{if(s===0)r();else n()})}),e.stop(ae.green("noto has been updated successfully!"))}catch{return F.log.error(`automatic update failed. please try updating manually by running: ${a.updateCommand}`),await i(1,!1)}return await i(0,!1)});var Ye={checkout:Ae,config:Ee,prev:Oe,init:qe,noto:Ve,upgrade:Ke};var He=G.router(Ye);var Xe=process.argv.slice(2),Je="1.3.4-beta.2";if(Xe.includes("--version")||Xe.includes("-v"))console.log(Je),process.exit(0);xe();se(!0);Ut({name:"noto",router:He,version:Je}).run();
|
|
329
329
|
|
|
330
330
|
// Made by a human on earth!
|