UNPKG

lvlup

Version:

A simple version manager solution for packages

25 lines (23 loc) 14.8 kB
#!/usr/bin/env node import Fe from"os";import{hideBin as _o}from"yargs/helpers";import yo from"yargs/yargs";var u=r=>`\x1B[${r}m`,e={black:u(30),blink:u(5),blue:u(34),bright:u(1),cyan:u(36),green:u(32),magenta:u(35),red:u(31),white:u(37),yellow:u(33),stop:"\x1B[0m"};var j={log:"",info:e.blue,warn:e.yellow,error:e.red};var P=class{log(o,t){this.printLogMessageByLevel({logLevel:"log",message:o,options:t})}info(o,t){this.printLogMessageByLevel({logLevel:"info",message:o,options:t})}warn(o,t){this.printLogMessageByLevel({logLevel:"warn",message:o,options:t})}error(o,t){this.printLogMessageByLevel({logLevel:"error",message:o,options:t})}printLogMessageByLevel(o){let{logLevel:t,message:n,options:s}=o;s?.newLineBefore&&console.log(""),console[t](`\u{1F3A9} ${j[t]}${t}${e.stop}`,n),s?.newLineAfter&&console.log("")}},i=new P;import Ne from"fs/promises";import Te from"path";import Ve from"path";var C="lvlup",g=`${e.green}${C}${e.stop}`,c=`.${C}`,B="CHANGELOG.md",y=process.cwd(),l=Ve.resolve(y,c);var D=` ${e.bright}${e.blue}________________________________ _ _ _ _ | | __ _| | | | | |_ __ | | \\ \\ / / | | | | | '_ \\ | |__\\ V /| |___ | |_| | |_) | |_____\\_/ |_____| \\___/| .__/ |_| ________________________________${e.stop}`;async function O(){try{let r=Te.resolve(l,"config.json"),o=(await Ne.readFile(r)).toString();return{configJsonAsObject:JSON.parse(o)}}catch(r){throw i.error(`Failed to read ${g}'s config.json file...`),r}}import Ie from"fs/promises";import Je from"path";async function _(){try{let r=Je.resolve(y,"package.json"),o=(await Ie.readFile(r)).toString();return{packageJsonAsObject:JSON.parse(o),packageJsonAsString:o}}catch(r){throw i.error("Failed to read the project's package.json file..."),r}}import je from"fs";import Be from"path";function x(){return je.existsSync(Be.resolve(process.cwd(),c))}function q(){if(!x())throw i.error(`There is no ${c} folder.`),i.error(`If this is the first time '${g}' have been used in this project, run 'yarn ${g} init' to get set up.`),i.error(`If you expected there to be a ${c}, you should check git history for when the folder was removed to ensure you do not lose any configuration.`),new Error(`${c} directory doesn't exists`)}import{execSync as G}from"child_process";async function W(r){let o={filenameFullPath:"no-name"};try{let{filenameFullPath:t,commitMessage:n}=r;o.filenameFullPath=t;let s=n.replace(/"/g,'\\"').replace(/`/g,"\\`");G(`git add ${t}`),G(`git commit -m "docs(lvlup): ${s}"`)}catch(t){throw i.error(`[Git Error] Failed to commit the file '${o.filenameFullPath}'...`),t}}import qe from"fs";import Ge from"path";import{humanId as We}from"human-id";function U(r){return r.replace(/\n/g,`\r `)}import De from"os";function H(){return De.platform()==="win32"}var z=`--- "{{packageName}}": {{semverLevel}} --- {{commitMessage}} `;async function Y(r){let o="no-name";try{let{packageName:t,semverLevel:n,commitMessage:s}=r;o=`${We({separator:"-",capitalize:!1})}.md`;let m=z.replace("{{packageName}}",t).replace("{{semverLevel}}",n).replace("{{commitMessage}}",s),f=H()?U(m):m,p=Ge.resolve(l,o);return qe.writeFileSync(p,f),p}catch(t){throw i.error(`Failed to create file '${o}'...`),t}}import E from"os";async function Z(r){let{packageName:o,semverLevel:t}=r;console.log(`${E.EOL}=== Summary of changes ===${E.EOL}`),console.log(`${e.green}${t}:${e.stop}`,o,E.EOL)}import S from"os";import{CreateFileError as Ue,ExternalEditor as He,LaunchEditorError as ze,ReadFileError as Ye,RemoveFileError as Ze}from"external-editor";import{input as Ke}from"@inquirer/prompts";function K(r){return r.replace(/^#.*\n?/gm,"").replace(/\n+$/g,"").replace(/\n\n+/,` `).replace(/\s\s+/g," ").trim()}function X(r){r.editor.bin="code",r.editor.args=r.editor.args.concat("--wait","--no-sandbox")}var Qe=`${S.EOL}${S.EOL}# An empty message aborts the editor.${S.EOL}# Please enter a summary for your changes.`;async function ee(r){let{editor:o}=r??{};console.log(`${e.green} \u2728 Please enter a summary for this change (this will appear in the CHANGELOG).`),console.log(`${e.black} \u2728 (submit empty line to open external editor)`);let n=await Ke({message:"Summary >"})||Xe(o);return K(n)}function Xe(r="vim"){try{let o=new He(Qe,{postfix:".md",prefix:`${C}-`});r==="code"&&X(o);let t=o.run();if(o.lastExitStatus!==0)throw new Error("The editor exited with a non-zero code");try{o.cleanup()}catch(n){if(n instanceof Ze)i.error("Failed to remove the temporary file");else throw n}return t}catch(o){throw o instanceof Ue?i.error("Failed to create the temporary file"):o instanceof Ye?i.error("Failed to read the temporary file"):o instanceof ze&&i.error("Failed to launch your editor"),o}}import{confirm as eo}from"@inquirer/prompts";async function oe(){return await eo({message:"\u2728 Is this your desired change?",default:!0,theme:{style:{defaultAnswer:()=>`${e.black}(Y/n) \u203A ${e.blue}true`}}})}import{Separator as re,select as ro}from"@inquirer/prompts";async function te(r){let{packageName:o,currentVersion:t}=r;return await ro({message:`\u2728 What kind of change is this for ${o}? (current version is ${t})`,choices:[new re,{name:"patch",value:"patch",description:"For bug fixes and patches",disabled:!1},{name:"minor",value:"minor",description:"For when adding a new feature or ability"},{name:"major",value:"major",description:"For when there are breaking changes"},new re]})}var ne="add [FLAGS]",ie="Add new change";function se(r){r.option("skip",{description:"Adding the skip option will not prompt the confirmation step, and basically skip it.",type:"boolean",default:!1}).example("lvlup add --skip","Would skip the confirmation step."),r.option("editor",{type:"string",choices:["vi","vim","nano","code"],description:"Choose the external editor for editing your message."}).example("lvlup add --editor code","Would open up VsCode as editor when you hit enter on the insert message prompt.")}async function A(r){let{skip:o,editor:t}=r,{packageJsonAsObject:n}=await _(),{version:s,name:a}=n;q();let m=await te({packageName:a,currentVersion:s}),f=await ee({editor:t});if(!f)throw i.error("commit message cannot be empty... exiting...",{newLineBefore:!0}),new Error;Z({packageName:a,semverLevel:m}),(o||await oe())&&to({packageName:a,semverLevel:m,commitMessage:f})}async function to(r){let{packageName:o,semverLevel:t,commitMessage:n}=r,{configJsonAsObject:s}=await O(),{afterAdd:a}=s.commit??{},m=await Y({packageName:o,semverLevel:t,commitMessage:n});a?(await W({filenameFullPath:m,commitMessage:n}),i.info("\u2705 LVLUP added an experience file and committed it",{newLineBefore:!0})):i.info("\u2705 LVLUP added an experience file. Please go over it and then commit it",{newLineBefore:!0}),i.info("\u2705 If you want to modify the experience, or expand its summary, you can find it here:"),i.info(`\u2705 ${e.yellow}${m}${e.stop}`,{newLineAfter:!0})}import ce from"os";import no from"fs";import io from"gray-matter";function ae(r){return r.replace(/^[\s\r\n]+|[\s\r\n]+$/g,"")}async function b(r){let{mdVersionFilePaths:o,packageName:t}=r,n={major:[],minor:[],patch:[]};return o.forEach(s=>{let a=no.readFileSync(s,"utf-8"),{data:m,content:f}=io(a),p=s.split("/").pop(),h=ae(f);if(!m?.[t])return;let d=m[t];if(d==="major")return n.major.push({level:"major",filename:p,description:h});if(d==="minor")return n.minor.push({level:"minor",filename:p,description:h});if(d==="patch")return n.patch.push({level:"patch",filename:p,description:h});throw new Error(`Couldn't find semver level on file ${e.red}${s}${e.stop} related to ${t}. File is corrupted...`)}),n}import M from"path";import{glob as so}from"glob";async function $(){return(await so(`${c}/*.md`,{ignore:[`${c}/README.md`]})).map(t=>{let n=t.replace(M.join(c,M.sep),"");return M.resolve(l,n)})}function w(r){return!r.major.length&&!r.minor.length&&!r.patch.length}function me(r){let[o,t,n]=r.split(".").map(Number);if(!(Number.isInteger(o)&&Number.isInteger(t)&&Number.isInteger(n)))throw i.error("The version listed under your package.json is corrupted! Expected to see <number>.<number>.<number>"),new Error("The value for `version` listed under your package.json is invalid... please fix it and try again");return{major:o,minor:t,patch:n}}async function k(r){let{changes:o,currentVersion:t}=r,n={...t};return o.major.length?(n.major+=1,n.minor=0,n.patch=0):o.minor.length?(n.minor+=1,n.patch=0):n.patch+=1,`${n.major}.${n.minor}.${n.patch}`}import{execSync as v}from"child_process";async function F(r){let{mdVersionFilePaths:o,version:t}=r;o.forEach(n=>{try{v(`git add -u ${n}`)}catch{i.warn(`WARNING! 'git add' operation failed. Detected an md version file which probably was not committed. Path to file was: ${e.yellow}${n}`)}}),v("git add package.json"),v("git add CHANGELOG.md"),v('git commit -m "RELEASING: Releasing 1 package"'),v(`git tag -a v${t} -m "Release version ${t}"`)}import ao from"fs/promises";async function R(r){let{mdVersionFilePaths:o}=r,t=[];o.forEach(n=>{let s=ao.unlink(n);t.push(s)}),await Promise.all(t)}import V from"fs";import L from"os";import mo from"path";function pe(r){return r.charAt(0).toUpperCase()+r.substring(1)}async function N(r){let{packageName:o,nextVersion:t,changes:n}=r,s=mo.resolve(y,B),a=`# ${o}`,m=`## ${t}`;for(let p in n)n[p].length&&(m=`${m}${L.EOL}${L.EOL}### ${pe(p)} Changes${L.EOL}`,n[p].forEach(h=>{let d=h.description.replace(/\n/,` `);m=`${m}${L.EOL}- ${d}`}));V.existsSync(s)?a=V.readFileSync(s,"utf-8"):a=`${a}${L.EOL}`;let f=a.replace(`# ${o}`,`# ${o}${L.EOL}${L.EOL}${m}`);V.writeFileSync(s,f,"utf-8")}import po from"fs/promises";import co from"path";async function T(r){let{packageJsonAsString:o,prevVersion:t,nextVersion:n}=r,s=o.replace(t,n);await po.writeFile(co.resolve(y,"package.json"),s)}var le="bump",ge="Uses all md version files added by the `add` command to calculate and bump the package's version";async function I(r){try{let{packageJsonAsObject:o,packageJsonAsString:t}=await _(),{name:n,version:s}=o,a=me(s),{configJsonAsObject:m}=await O(),{afterBump:f}=m.commit??{},p=await $(),h=await b({packageName:n,mdVersionFilePaths:p});if(w(h))return i.warn("No unreleased changes found, exiting.");let d=await k({changes:h,currentVersion:a});i.info(`New package version: ${e.yellow}${d}${e.stop}`),await T({packageJsonAsString:t,prevVersion:s,nextVersion:d}),await R({mdVersionFilePaths:p}),await N({packageName:n,nextVersion:d,changes:h}),f?(await F({mdVersionFilePaths:p,version:d}),i.info("\u2705 LVLUP - All files have been updated and committed. You're ready to publish!",{newLineBefore:!0,newLineAfter:!0})):i.info("\u2705 LVLUP - All files have been updated but not yet committed. Please review them, commit them, and then you'll be ready to publish.",{newLineBefore:!0,newLineAfter:!0})}catch(o){i.error("Something went wrong..."),console.error(o),console.log(`${ce.EOL}${e.red}Existed.${ce.EOL}`)}}import ve from"os";import fe from"fs";import de from"path";function ue(){let{dirname:r}=import.meta,o=de.resolve(r,"default.config.json"),t=de.resolve(l,"config.json"),n=fe.createReadStream(o),s=fe.createWriteStream(t);n.pipe(s)}import lo from"fs";function he(){lo.mkdirSync(l,{recursive:!0})}import _e from"fs";import ye from"path";function Le(){let{dirname:r}=import.meta,o=ye.resolve(r,"default.README.md"),t=ye.resolve(l,"README.md"),n=_e.createReadStream(o),s=_e.createWriteStream(t);n.pipe(s)}var Ce="init",Oe="To start using lvlup, you first need to run the init command.";async function J(r){x()&&(i.warn(`Looks like you've already initialized ${g}. You should be able to run ${g} commands without a problems.`),process.exit(0)),he(),ue(),Le(),i.info(`Thanks for choosing ${g} to help manage your versioning and publishing${ve.EOL}`),i.info(`You should be able to start using ${g} now!${ve.EOL}`),i.info(`info We have added a '${c}' folder, and a couple of files to help you out:`),i.info(`- ${e.blue}${c}/README.md${e.stop} contains information about using ${g}`),i.info(`- ${e.blue}${c}/config.json${e.stop} is our default config`)}import{execSync as go}from"child_process";var xe="publish",be="publishes the package to your designated registry using the rules you specified.";async function $e(r){let{packageJsonAsObject:o}=await _(),{private:t,publishConfig:n}=o;if(t)return i.warn("CANNOT publish a package that is private!");let s=n.access==="public"?"--access=public":"";go(`npm publish ${s}`)}import{Table as fo}from"console-table-printer";var uo={headerTop:{left:`${e.blue}\u250C${e.stop}`,mid:`${e.blue}\u252C${e.stop}`,right:`${e.blue}\u2510${e.stop}`,other:`${e.blue}\u2500${e.stop}`},headerBottom:{left:`${e.blue}\u251C${e.stop}`,mid:`${e.blue}\u253C${e.stop}`,right:`${e.blue}\u2524${e.stop}`,other:`${e.blue}\u2500${e.stop}`},tableBottom:{left:`${e.blue}\u2514${e.stop}`,mid:`${e.blue}\u2534${e.stop}`,right:`${e.blue}\u2518${e.stop}`,other:`${e.blue}\u2500${e.stop}`},vertical:`${e.blue}\u2502${e.stop}`};function we(r){new fo({rows:r,columns:[{name:"filename",alignment:"left",color:"yellow",title:`${e.green}Filename${e.stop}`},{name:"level",alignment:"center",color:"cyan",title:`${e.green}Level${e.stop}`},{name:"description",alignment:"left",color:"white",title:`${e.green}Description${e.stop}`,maxLen:80}],style:uo}).printTable()}function Pe(){console.log(`${e.blue} _ _ ___| |_ __ _| |_ _ _ ___ / __| __/ _\` | __| | | / __| \\__ \\ || (_| | |_| |_| \\__ \\ |___/\\__\\__,_|\\__|\\__,_|___/ ${e.stop}`)}var Ee="status",Se="Show the status before bumping the package's version";async function Ae(r){let{packageJsonAsObject:o}=await _(),{name:t}=o,n=await $(),s=await b({packageName:t,mdVersionFilePaths:n}),a=[...s.major,...s.minor,...s.patch];if(w(s))return i.info("0 changes found. You are up-to-date");Pe(),we(a)}var ho={init:J,add:A,status:Ae,bump:I,publish:$e};async function Me(r){try{let{commands:o,flags:t}=r,[n]=o;await ho[n](t)}catch(o){}}async function ke(){console.log("1.0.13")}var Re=yo(_o(process.argv)).completion().scriptName(`${e.green}lvlup${e.stop}`).version(!1).command(Ce,Oe).command(ne,ie,se).command(Ee,Se).command(le,ge).command(xe,be).options({v:{alias:"version",type:"boolean",description:"Show lvlup version",default:!1,global:!1},h:{alias:"help",type:"boolean",description:"Show help manual",default:!1,global:!0}}).showHelpOnFail(!1,"Specify --help for available options").strict().updateStrings({"Positionals:":`${e.blue}Positionals:${e.stop}`,"Commands:":`${e.blue}Commands:${e.stop}`,"Options:":`${e.blue}Flags:${e.stop}`,"Examples:":`${e.blue}Examples:${e.stop}`}).help(!1);async function Lo(){let r=Re.parse(),{$0:o,_:t,...n}=r;if(n.version&&(await ke(),process.exit(0)),n.help||!t.length){let s=await Re.getHelp(),a=`${D}${Fe.EOL}${Fe.EOL}${s}`;console.log(a),process.exit(0)}await Me({commands:t,flags:n})}Lo();