npm-name-checker2
Version:
Check whether a package or organization name is available on npm
4 lines • 5.51 kB
JavaScript
import{styleText as e}from"node:util";import{Command as t}from"commander";import n from"ora";import r from"fs";import i from"os";import a from"path";import o from"synonyms";var s=`0.10.2`,c=`Check whether a package or organization name is available on npm`;const l=a.join(i.homedir(),`.npm-name-checker`),u=a.join(l,`cache.json`);function d(){r.existsSync(l)||r.mkdirSync(l,{recursive:!0})}function f(){if(d(),!r.existsSync(u))return{};try{return JSON.parse(r.readFileSync(u,`utf-8`))}catch{return{}}}function p(e){d(),r.writeFileSync(u,JSON.stringify(e,null,2))}function m(e,t){let n=f(),r=n[e];if(!r)return null;let i=Date.now()-r.timestamp;return i>t?null:r.data}function h(e,t){let n=f();n[e]={timestamp:Date.now(),data:t},p(n)}function g(){return f()}function _(){r.existsSync(u)&&r.unlinkSync(u)}async function v(e,t={},n=3){let r=0;for(;r<n;){let i=await fetch(e,t);if(i.ok||i.status===404)return i;if(i.status===429){if(r++,r>=n)throw Error(`Rate limit exceeded after `+n+` attempts`);let e=2**r*500;await new Promise(t=>setTimeout(t,e));continue}if(i.status===403){let e=i.headers.get(`X-RateLimit-Remaining`);if(e===`0`){if(r++,r>=n)throw Error(`Rate limit exceeded after `+n+` attempts`);let e=2**r*500;await new Promise(t=>setTimeout(t,e));continue}}throw Error(e+` failed with status `+i.status)}throw Error(`Rate limit exceeded after `+n+` attempts`)}function y(e){return e.replace(/([a-z])([A-Z])/g,`$1-$2`).toLowerCase().replace(/_/g,`-`)}function b(e){let t=new Set,n=y(e),r=n.split(`-`),i=[`js`,`ts`,`api`,`core`,`lib`,`kit`,`pro`,`plus`],a=[`my`,`super`,`easy`,`pro`,`ultra`],s=[`utils`,`helper`,`toolkit`,`framework`,`module`];return i.forEach(e=>{t.add(`${n}-${e}`)}),a.forEach(e=>{t.add(`${e}-${n}`)}),s.forEach(e=>{t.add(`${n}-${e}`)}),t.add(n.replace(/-/g,`_`)),r.length>1&&t.add(r.join(``)),o&&r.forEach((e,n)=>{let i=o(e),a=i?Object.values(i).flat():[];a.slice(0,3).forEach(e=>{let i=[...r];i[n]=e,t.add(i.join(`-`))})}),t.delete(n),Array.from(t).slice(0,30)}async function x(e,t){let n=`npm:${e}`,r=m(n,t);if(r)return r;let i=`https://registry.npmjs.org/${e}`;try{let e=await v(i,{method:`GET`}),t=await e.json(),r=e.status===404||t?.error?{available:!0,platform:`npm`,message:t?.error}:{available:!1,platform:`npm`,url:i};return h(n,r),r}catch(e){return{available:null,platform:`npm`,error:e.message}}}async function S(e,t,n){if(!t)return{platform:`github`,available:null,error:`Specify owner with -o to check GitHub repo`};let r=`github:${t}/${e}`,i=m(r,n);if(i)return i;let a=`https://api.github.com/repos/${t}/${e}`;try{let e=await v(a,{headers:{"User-Agent":`npm-name-checker2`}}),t=await e.json(),n=e.status===404||t.status===`404`&&t.message===`Not Found`?{available:!0,platform:`github`,message:t.message}:{available:!1,platform:`github`,url:a};return h(r,n),n}catch(e){return{platform:`github`,available:null,error:e.message}}}function C(t,n){let r=Math.max(...n.map(e=>e.status===`fulfilled`?e.value.platform.length:0));n.forEach(t=>{if(t.status===`fulfilled`){let{platform:n,available:i,error:a}=t.value,o=`${n}:`.padEnd(r+2);if(a)console.log(`${e(`red`,o)} ${a}`);else{let t=i?e(`green`,`Available`):e(`red`,`Taken`);console.log(`${e(`bold`,o)} ${t}`)}}else console.log(`${e(`red`,`Error:`)} ${t.reason.message}`)});let i=n.filter(e=>e.status===`fulfilled`&&e.value.available===!0).map(e=>e.value.platform);i.length>0&&console.log(e(`green`,`✅ Available on: ${i.join(`, `)}`))}async function w(t,r,i=60){let a=i*60*1e3,o=n(`🔍 Checking availability for ${e(`cyan`,t)} ...`).start();try{let s=await Promise.allSettled([x(t,a),S(t,r,a)]);o.stop(),o.clear(),C(t,s);let c=s.filter(e=>e.status===`fulfilled`),l=c.every(e=>e.value.available===!0||e.value.available===null);if(l)return;console.log(e(`bold`,`
Suggestions for available alternatives:`));let u=n(`Generating and checking alternatives...`).start(),d=b(t),f=[],p=e=>new Promise(t=>setTimeout(t,e));for(let e=0;e<d.length;e++){let t=d[e];if(!t)continue;await p(e*200);let n=[x(t,i)];r&&n.push(S(t,r,i));let a=await Promise.allSettled(n),o=a.filter(e=>e.status===`fulfilled`),s=o.every(e=>e.value.available===!0||e.value.available===null);if(s&&o.length===n.length&&f.push(t),f.length>=10)break}if(u.stop(),u.clear(),f.length===0)console.log(`No immediate suggestions available – try broader variations.`);else{let t=r?`npm and GitHub`:`npm`;f.forEach(n=>{console.log(`- ${e(`green`,n)} (available on ${t})`)})}}catch(t){console.error(e(`red`,`Error checking name availability: `+t.message))}}function T(){let e=new t;e.name(`name-check`).description(c).version(s).showHelpAfterError().argument(`<name>`,`package name`,e=>e.toLowerCase().trim()).option(`-o --owner <owner>`,`GitHub owner or organization name (required for checking repository name)`,e=>e.toLowerCase().trim()).option(`-t --ttl <minutes>`,`Cache time-to-live in minutes (default: 60)`,e=>parseInt(e,10),60).action((e,t)=>{w(e,t.owner)});let n=e.command(`cache`).description(`Manage cache`);return n.command(`list`).description(`List cached entries`).action(()=>{let e=g();if(Object.keys(e).length===0)console.log(`Cache is empty.`);else{console.log(`Cached entries:`);for(let[t,n]of Object.entries(e)){let e=Math.floor((Date.now()-n.timestamp)/6e4);console.log(`- ${t}: cached ${e} min ago`)}}}),n.command(`clear`).description(`Clear the cache`).action(()=>{_(),console.log(`Cache cleared.`)}),e.parse(process.argv),e}process.on(`SIGINT`,()=>{console.log(e(`yellow`,`
Ctrl + c Pressed.....`)),process.exit(0)}),T();export{};