validate-package-exports 0.1.0 → 0.2.1
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/cli.mjs +2 -2
- package/package.json +7 -7
- package/readme.md +23 -9
package/dist/cli.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*!
|
|
3
3
|
* @file validate-package-exports
|
|
4
|
-
* @version 0.1
|
|
4
|
+
* @version 0.2.1
|
|
5
5
|
* @license MIT
|
|
6
6
|
* @copyright Eric King 2024
|
|
7
7
|
* @see {@link https://github.com/webdeveric/validate-package-exports/#readme}
|
|
8
8
|
*/
|
|
9
|
-
import Ye from"node:assert";import{join as Ze,resolve as et}from"node:path";import{parseArgs as tt}from"node:util";import{Console as $e}from"node:console";var x={emergency:0,alert:1,critical:2,error:3,warning:4,notice:5,info:6,debug:7};var y=e=>t=>typeof t=="string"&&e.test(t),a=e=>t=>Array.isArray(t)&&t.every(e);var i=e=>t=>typeof t>"u"||e(t);var u=e=>typeof e=="string",M=e=>typeof e=="number"&&!Number.isNaN(e),T=e=>typeof e=="bigint",F=e=>typeof e=="boolean",Ee=e=>typeof e>"u",D=e=>typeof e=="symbol",q=e=>e===null;var d=i(u),it=i(M),st=i(T),at=i(F),pt=i(D),ct=i(q),N=a(u),mt=a(M),yt=a(T),lt=a(F),ut=a(Ee),ft=a(D),dt=a(q);var he=y(/^[-+]?\d+(\.\d+)?$/),be=e=>typeof e=="number"||typeof e=="bigint"||he(e),gt=a(be),Pt=y(/^[-+]?\d+$/),xt=y(/^\d+$/);var f=e=>e!==null&&typeof e=="object"&&!Array.isArray(e);var U=e=>f(e)&&Object.entries(e).every(N);function G(e){return Object.keys(x).includes(String(e))}function W(e){return Object.values(x).includes(e)}function ke(e){return e==="commonjs"||e==="module"}var V=y(/\.\d+(\.gz)?$/),ve=a(V),we=e=>V(e)||ve(e),Re=i(we);function Ce(e){return f(e)&&d(e.bin)&&d(e.man)}var Ne=i(Ce);function Le(e){return u(e)||U(e)}function z(e){return typeof e=="string"&&e.startsWith("./")}var Se=/^(?<before>\.\/[^*]*)\*(?<after>[^*]*)$/,vt=y(Se);function L(e){return e===null||z(e)}var je=y(/^(?![\\.0-9])./);function E(e){return f(e)?Object.entries(e).every(([r,o])=>je(r)&&O(o)):!1}function S(e){return f(e)?Object.entries(e).every(([r,o])=>(r==="."||z(r))&&O(o)):!1}function h(e){return L(e)||E(e)}var j=a(h);function O(e){return h(e)||j(e)}function Oe(e){return O(e)||S(e)}var A=e=>f(e)&&Object.entries(e).every(t=>typeof t[0]=="string"&&(typeof t[1]=="string"||typeof t[1]=="boolean"));function Ae(e){return u(e)||A(e)}var Be=i(Ae);function _(e){return f(e)&&u(e.name)&&u(e.version)&&d(e.main)&&d(e.module)&&Be(e.browser)&&d(e.types)&&Re(e.man)&&Ne(e.directories)&&i(ke)(e.type)&&i(Oe)(e.exports)&&i(Le)(e.bin)&&i(N)(e.files)}function B(e){return typeof e>"u"?4:W(e)?e:G(e)?x[e]:4}var b=class extends $e{#e;constructor(t={},r){super({stdout:process.stdout,stderr:process.stderr,inspectOptions:{depth:null},...t}),this.#e=B(r)}get logLevel(){return this.#e}set logLevel(t){this.#e=B(t)}willLog(t){return this.#e>=t}emergency(...t){this.#e>=0&&super.log(...t)}alert(...t){this.#e>=1&&super.log(...t)}critical(...t){this.#e>=2&&super.log(...t)}error(...t){this.#e>=3&&super.error(...t)}warning(...t){this.warn(...t)}warn(...t){this.#e>=4&&super.warn(...t)}notice(...t){this.#e>=5&&super.info(...t)}info(...t){this.#e>=6&&super.info(...t)}debug(...t){this.#e>=7&&super.info(...t)}};import{setMaxListeners as He}from"node:events";import{dirname as Qe}from"node:path";import{Readable as w}from"node:stream";import{relative as K}from"node:path";import{stat as Ie}from"node:fs/promises";async function J(e){return(await Ie(e)).isFile()}async function H(e){try{if(await J(e.resolvedPath)===!1)throw new Error(`${e.resolvedPath} is not a file`);return{name:"file-exists",code:0,message:K(process.cwd(),e.resolvedPath),entryPoint:e}}catch(t){return{name:"file-exists",code:1,entryPoint:e,message:K(process.cwd(),e.resolvedPath),error:t instanceof Error?t:new Error(String(t))}}}import{relative as Q}from"node:path";import{exec as Me}from"node:child_process";import{promisify as Te}from"node:util";var g=Te(Me);async function X(e,t){try{return await g(`node --check ${e.resolvedPath}`,t),{code:0,entryPoint:e,message:Q(process.cwd(),e.resolvedPath),name:"check-syntax"}}catch(r){return{code:1,entryPoint:e,error:r instanceof Error?r:new Error(String(r)),message:Q(process.cwd(),e.resolvedPath),name:"check-syntax"}}}import{relative as Fe,dirname as De,basename as qe,resolve as Ue}from"node:path";function Y(e,t){return t==="."?e:`${e}/${t.replace(/^\.\//,"")}`}function Z(e,t="commonjs",r){return r==="require"||e.endsWith(".cjs")?"commonjs":r==="import"||e.endsWith(".mjs")?"module":t}function s({condition:e,itemPath:t,modulePath:r,packageDirectory:o,packageName:n,packageType:c="commonjs",subpath:p}){let m=Ue(o,r);return{moduleName:p?Y(n,p):void 0,type:Z(r,c,e),fileName:qe(m),relativePath:Fe(o,m),directory:De(m),resolvedPath:m,subpath:p,condition:e,itemPath:t}}function ee(e,t){return typeof e=="string"?{[t]:e}:e}function*te(e,t){if(e.bin)for(let[r,o]of Object.entries(ee(e.bin,e.name)))yield s({condition:void 0,itemPath:typeof e.bin=="string"?["bin"]:["bin",r],modulePath:o,packageDirectory:t,packageName:e.name,packageType:e.type,subpath:void 0})}import{opendir as We}from"node:fs/promises";import{resolve as Ge}from"node:path";function k(e){return Ge(e.path.endsWith(e.name)?e.path.replace(new RegExp(`[/\\\\]${e.name}$`,"i"),""):e.path,e.name)}async function*re(e,t){if(typeof e.directories?.bin=="string"){let r=await We(e.directories.bin);for await(let o of r)o.isFile()&&(yield s({condition:void 0,itemPath:["directories","bin"],modulePath:k(o),packageDirectory:t,packageName:e.name,packageType:e.type,subpath:void 0}))}}function*oe(e,t){if(e.browser){if(A(e.browser)){let r=Object.entries(e.browser).filter(o=>typeof o[0]=="string"&&typeof o[1]=="string");for(let[o,n]of r)yield s({condition:void 0,itemPath:["browser",o],modulePath:n,packageDirectory:t,packageName:e.name,packageType:e.type,subpath:void 0});return}yield s({condition:void 0,itemPath:["browser"],modulePath:e.browser,packageDirectory:t,packageName:e.name,packageType:e.type,subpath:void 0})}}var v=class{processExportsEntryPath(t,r){return t===null?[]:[s({modulePath:t,subpath:".",...r})]}processExportsEntry(t,r){return E(t)?this.processConditionalExports(t,r):this.processExportsEntryPath(t,r)}processExportsEntryArray(t,r){return t.map((o,n)=>this.processExportsEntry(o,{...r,itemPath:[...r.itemPath,n]})).flat()}processSubpathExports(t,r){return Object.entries(t).map(([o,n])=>this.process(n,{...r,subpath:o,itemPath:[...r.itemPath,o]})).flat()}processConditionalExports(t,r){let o=(n,c,p)=>{if(E(c))return n;if(p.at(-1)==="default"){let m=p.at(-2);if(typeof m=="string")return m}return n};return Object.entries(t).map(([n,c])=>{let p=[...r.itemPath,n];return this.process(c,{...r,condition:o(n,c,p),itemPath:p})}).flat()}process(t,r){return L(t)?this.processExportsEntryPath(t,r):j(t)?this.processExportsEntryArray(t,r):h(t)?this.processExportsEntry(t,r):S(t)?this.processSubpathExports(t,r):E(t)?this.processConditionalExports(t,r):[]}};import{opendir as Ve}from"node:fs/promises";async function*ne(e){if(!e.resolvedPath.includes("*")){yield e;return}let[t,r]=e.resolvedPath.split("*"),o=t?new RegExp(`^${t}`,"i"):void 0,n=r?new RegExp(`${r}$`,"i"):void 0,c=["moduleName","relativePath","fileName","resolvedPath"],p=P=>{let l=P;return o&&(l=l.replace(o,"")),n&&(l=l.replace(n,"")),l},m=await Ve(e.directory);for await(let P of m)if(P.isFile()&&(typeof r>"u"||P.name.endsWith(r))){let l=p(k(P));yield c.reduce((C,$)=>{let I=C[$];return I&&(C[$]=I.replace("*",l)),C},structuredClone(e))}}async function*ie(e,t){if(e.exports){let r=new v().process(e.exports,{packageType:e.type??"commonjs",packageName:e.name,packageDirectory:t,itemPath:["exports"]});for(let o of r)yield*ne(o)}}function*se(e,t){e.main&&(yield s({condition:void 0,itemPath:["main"],modulePath:e.main,packageDirectory:t,packageName:e.name,packageType:e.type,subpath:"."}))}function*ae(e,t){e.module&&(yield s({condition:void 0,itemPath:["module"],modulePath:e.module,packageDirectory:t,packageName:e.name,packageType:e.type,subpath:"."}))}function*pe(e,t){let r="types"in e?"types":"typings"in e?"typings":void 0;if(r){let o=e[r];o&&(yield s({condition:"types",itemPath:[r],modulePath:o,packageDirectory:t,packageName:e.name,packageType:e.type,subpath:void 0}))}}async function*ce(e,t){yield*te(e,t),yield*re(e,t),yield*oe(e,t),yield*se(e,t),yield*ae(e,t),yield*pe(e,t),yield*ie(e,t)}import{AssertionError as ze}from"node:assert";function me(e){if(!_(e))throw new ze({message:"input is not PackageJson",actual:e})}import{readFile as _e}from"node:fs/promises";async function ye(e){let t=await _e(e,"utf-8");return JSON.parse(t)}async function le(e){let t=await ye(e);return me(t),t}async function ue(e,t){let r=/\.json$/i.test(e)?`node --input-type=module --eval="import '${e}' assert { type: 'json' };"`:`node --input-type=module --eval="import '${e}';"`;await g(r,t)}async function fe(e,t){try{return typeof e.moduleName=="string"?(await ue(e.moduleName,t),{code:0,entryPoint:e,message:e.moduleName,name:"import"}):{code:2,entryPoint:e,message:`Import skipped: ${e.itemPath.join(".")}`,name:"import"}}catch(r){return{code:1,entryPoint:e,error:r instanceof Error?r:new Error(String(r)),message:`${e.moduleName??e.itemPath.join(".")} cannot be imported`,name:"import"}}}async function de(e,t){let r=`node --input-type=commonjs --eval="require('${e}');"`;await g(r,t)}async function ge(e,t){try{return typeof e.moduleName=="string"?(await de(e.moduleName,t),{code:0,entryPoint:e,message:e.moduleName,name:"require"}):{code:2,entryPoint:e,message:`Require skipped: ${e.itemPath.join(".")}`,name:"require"}}catch(r){return{code:1,entryPoint:e,error:r instanceof Error?r:new Error(String(r)),message:`${e.moduleName??e.itemPath.join(".")} cannot be required`,name:"require"}}}function Je(e){return typeof e.condition>"u"||e.condition==="require"}function Ke(e){return typeof e.condition>"u"||e.condition==="import"}async function Pe(e,t){let r=[];try{typeof e.moduleName=="string"&&(Je(e)&&r.push(await ge(e,t)),Ke(e)&&r.push(await fe(e,t)))}catch(o){if(o instanceof Error)throw new Error(`Unable to verify "${e.moduleName}"`,{cause:o})}return r}var R=class{options;packageDirectory;#e;#t;logger;constructor(t,r){this.options=t,this.packageDirectory=Qe(this.options.package),this.logger=r,this.#e=0,this.#t=new AbortController,He(100,this.#t.signal)}processResult(t){t.code===1&&(this.#e=1,this.options.bail&&this.#t.abort());let r=t.code===0?"\u2705":t.code===1?"\u274C":"\u{1F610}";t.code===1?(this.logger.error(`${r} ${t.name}: ${t.message} (${JSON.stringify(t.entryPoint.itemPath)})`),this.logger.error(t.error)):this.logger.info(`${r} ${t.name}: ${t.message}`)}processResults(t){[t].flat().forEach(r=>this.processResult(r))}async run(){let t=await le(this.options.package);this.logger.debug(`\u{1F4C2} package directory: ${this.packageDirectory}`),this.logger.debug({options:this.options,packageJson:t});let r=await w.from(ce(t,this.packageDirectory),{objectMode:!0}).toArray({signal:this.#t.signal});if(await w.from(r).forEach(async o=>{let n=await H(o);this.processResults(n)},{signal:this.#t.signal,concurrency:this.options.concurrency}),this.options.check){let o=r.filter(n=>/\.[cm]?js$/i.test(n.resolvedPath));await w.from(o).forEach(async n=>{let c=await X(n,{signal:this.#t.signal});this.processResults(c)},{signal:this.#t.signal,concurrency:this.options.concurrency})}return this.options.verify&&await w.from(r).forEach(async o=>{let n=await Pe(o,{cwd:this.packageDirectory,signal:this.#t.signal});this.processResults(n)},{signal:this.#t.signal,concurrency:this.options.concurrency}),this.#e}};import{availableParallelism as Xe}from"node:os";function xe(e){let t=Xe(),r=Number.parseInt(`${e}`);return Number.isInteger(r)?Math.max(1,Math.min(r,t)):t}try{let{values:e}=tt({allowPositionals:!1,strict:!0,tokens:!0,options:{package:{type:"string",short:"p",default:Ze(process.cwd(),"package.json")},concurrency:{type:"string",short:"c"},bail:{type:"boolean",short:"b",default:process.env.CI==="true"},check:{type:"boolean",default:!1,short:"s"},verify:{type:"boolean",default:!1,short:"v"},logLevel:{type:"string",short:"l",default:process.env.RUNNER_DEBUG==="1"?"debug":"info"}}});Ye(e.package,"Package not defined"),process.exitCode=await new R({package:et(e.package),concurrency:xe(e.concurrency),bail:!!e.bail,check:!!e.check,verify:!!e.verify},new b({stdout:process.stdout,stderr:process.stderr,inspectOptions:{depth:null}},e.logLevel)).run()}catch(e){console.dir(e,{depth:null}),process.exitCode??=1}
|
|
9
|
+
import{setMaxListeners as oe}from"node:events";var c=class{name;code;message;entryPoint;error;constructor(e){this.name=e.name,this.code=e.code,this.message=e.message,this.entryPoint=e.entryPoint,this.error=e.error}toString(){let e=this.code===0?"\u2705":this.code===1?"\u274C":"\u{1F610}";return this.code===1?`${e} ${this.name}: ${this.message} (${JSON.stringify(this.entryPoint.itemPath)}) ${this.error??""}`.trim():`${e} ${this.name}: ${this.message}`}};import{EventEmitter as Vt}from"node:events";import{dirname as Kt}from"node:path";import{Readable as b}from"node:stream";import{relative as M}from"node:path";import{stat as Et}from"node:fs/promises";async function B(t){try{return(await Et(t)).isFile()}catch{return!1}}async function D(t){try{if(await B(t.resolvedPath)===!1)throw new Error(`${t.resolvedPath} is not a file`);return new c({name:"file-exists",code:0,message:`${M(process.cwd(),t.resolvedPath)} exists`,entryPoint:t})}catch(e){return new c({name:"file-exists",code:1,entryPoint:t,message:`${M(process.cwd(),t.resolvedPath)} does not exist`,error:e instanceof Error?e:new Error(String(e))})}}import{relative as J}from"node:path";import{exec as xt}from"node:child_process";import{promisify as ht}from"node:util";var g=ht(xt);async function L(t,e){try{return await g(`node --check ${t.resolvedPath}`,e),new c({code:0,entryPoint:t,message:`${J(process.cwd(),t.resolvedPath)} has valid syntax`,name:"check-syntax"})}catch(r){return new c({code:1,entryPoint:t,error:r instanceof Error?r:new Error(String(r)),message:`Could not validate syntax for ${J(process.cwd(),t.resolvedPath)}`,name:"check-syntax"})}}import{relative as kt,dirname as bt,basename as wt,resolve as vt}from"node:path";function q(t,e){return e==="."?t:`${t}/${e.replace(/^\.\//,"")}`}function G(t,e="commonjs",r){return r==="require"||t.endsWith(".cjs")?"commonjs":r==="import"||t.endsWith(".mjs")?"module":e}function p({moduleName:t,modulePath:e,packageContext:r,subpath:o,itemPath:s,condition:i}){let a=vt(r.directory,e);return{moduleName:t??(o?q(r.name,o):void 0),packagePath:r.path,type:G(e,r.type,i),fileName:wt(a),relativePath:kt(r.directory,a),directory:bt(a),resolvedPath:a,subpath:o,condition:i,itemPath:s}}function T(t,e){return typeof t=="string"?{[e]:t}:t}function*U(t,e){if(t.bin)for(let[r,o]of Object.entries(T(t.bin,t.name)))yield p({condition:void 0,itemPath:typeof t.bin=="string"?["bin"]:["bin",r],modulePath:o,packageContext:e,subpath:void 0})}import{opendir as Rt}from"node:fs/promises";import{resolve as jt}from"node:path";function h(t){return jt(t.path.endsWith(t.name)?t.path.replace(new RegExp(`[/\\\\]${t.name}$`,"i"),""):t.path,t.name)}async function*_(t,e){if(typeof t.directories?.bin=="string"){let r=await Rt(t.directories.bin);for await(let o of r)o.isFile()&&(yield p({condition:void 0,itemPath:["directories","bin"],modulePath:h(o),packageContext:e,subpath:void 0}))}}var u=t=>e=>typeof e=="string"&&t.test(e),l=t=>e=>Array.isArray(e)&&e.every(t);var m=t=>e=>typeof e>"u"||t(e);var d=t=>typeof t=="string",W=t=>typeof t=="number"&&!Number.isNaN(t),z=t=>typeof t=="bigint",V=t=>typeof t=="boolean",St=t=>typeof t>"u",K=t=>typeof t=="symbol",H=t=>t===null;var E=m(d),Me=m(W),De=m(z),Je=m(V),Le=m(K),qe=m(H),R=l(d),Ge=l(W),Te=l(z),Ue=l(V),_e=l(St),We=l(K),ze=l(H);var Ct=u(/^[-+]?\d+(\.\d+)?$/),At=t=>typeof t=="number"||typeof t=="bigint"||Ct(t),Ve=l(At),Ke=u(/^[-+]?\d+$/),He=u(/^\d+$/);var P=t=>t!==null&&typeof t=="object"&&!Array.isArray(t);var Q=t=>P(t)&&Object.entries(t).every(R);function Nt(t){return t==="commonjs"||t==="module"}var X=u(/\.\d+(\.gz)?$/),Ot=l(X),$t=t=>X(t)||Ot(t),Ft=m($t);function It(t){return P(t)&&E(t.bin)&&E(t.man)}var Bt=m(It);function Mt(t){return d(t)||Q(t)}function Y(t){return typeof t=="string"&&t.startsWith("./")}var Dt=/^(?<before>\.\/[^*]*)\*(?<after>[^*]*)$/,Ze=u(Dt);function S(t){return t===null||Y(t)}var Jt=u(/^(?![\\.0-9])./);function x(t){return P(t)?Object.entries(t).every(([r,o])=>Jt(r)&&N(o)):!1}function C(t){return P(t)?Object.entries(t).every(([r,o])=>(r==="."||Y(r))&&N(o)):!1}function Z(t){return S(t)||x(t)}var A=l(Z);function N(t){return Z(t)||A(t)}function Lt(t){return N(t)||C(t)}var O=t=>P(t)&&Object.entries(t).every(e=>typeof e[0]=="string"&&(typeof e[1]=="string"||typeof e[1]=="boolean"));function qt(t){return d(t)||O(t)}var Gt=m(qt);function tt(t){return P(t)&&d(t.name)&&d(t.version)&&E(t.main)&&E(t.module)&&Gt(t.browser)&&E(t.types)&&Ft(t.man)&&Bt(t.directories)&&m(Nt)(t.type)&&m(Lt)(t.exports)&&m(Mt)(t.bin)&&m(R)(t.files)}function*et(t,e){if(t.browser){if(O(t.browser)){let r=Object.entries(t.browser).filter(o=>typeof o[0]=="string"&&typeof o[1]=="string");for(let[o,s]of r)yield p({condition:void 0,itemPath:["browser",o],modulePath:s,packageContext:e,subpath:void 0});return}yield p({condition:void 0,itemPath:["browser"],modulePath:t.browser,packageContext:e,subpath:void 0})}}var k=class{processExportsEntryPath(e,r,o){return e===null?[]:[p({modulePath:e,subpath:".",...r,packageContext:o})]}processExportsEntry(e,r,o){return x(e)?this.processConditionalExports(e,r,o):this.processExportsEntryPath(e,r,o)}processExportsEntryArray(e,r,o){return e.map((s,i)=>this.processExportsEntry(s,{...r,itemPath:[...r.itemPath,i]},o)).flat()}processSubpathExports(e,r,o){return Object.entries(e).map(([s,i])=>this.process(i,{...r,subpath:s,itemPath:[...r.itemPath,s]},o)).flat()}processConditionalExports(e,r,o){let s=(i,a,y)=>{if(x(a))return i;if(y.at(-1)==="default"){let n=y.at(-2);if(typeof n=="string")return n}return i};return Object.entries(e).map(([i,a])=>{let y=[...r.itemPath,i];return this.process(a,{...r,condition:s(i,a,y),itemPath:y},o)}).flat()}process(e,r,o){return S(e)?this.processExportsEntryPath(e,r,o):A(e)?this.processExportsEntryArray(e,r,o):C(e)?this.processSubpathExports(e,r,o):x(e)?this.processConditionalExports(e,r,o):[]}};import{opendir as Tt}from"node:fs/promises";async function*rt(t){if(!t.resolvedPath.includes("*")){yield t;return}let[e,r]=t.resolvedPath.split("*"),o=e?new RegExp(`^${e}`,"i"):void 0,s=r?new RegExp(`${r}$`,"i"):void 0,i=["moduleName","relativePath","fileName","resolvedPath"],a=n=>{let f=n;return o&&(f=f.replace(o,"")),s&&(f=f.replace(s,"")),f},y=await Tt(t.directory,{recursive:!0});for await(let n of y)if(n.isFile()&&(typeof r>"u"||n.name.endsWith(r))){let f=a(h(n));yield i.reduce((v,F)=>{let I=v[F];return I&&(v[F]=I.replace("*",f)),v},structuredClone(t))}}async function*ot(t,e){if(t.exports){let r=new k().process(t.exports,{itemPath:["exports"]},e);for(let o of r)yield*rt(o)}}function*nt(t,e){t.main&&(yield p({moduleName:e.name,condition:void 0,itemPath:["main"],modulePath:t.main,packageContext:e,subpath:void 0}))}function*st(t,e){t.module&&(yield p({moduleName:e.name,condition:void 0,itemPath:["module"],modulePath:t.module,packageContext:e,subpath:void 0}))}function*it(t,e){let r="types"in t?"types":"typings"in t?"typings":void 0;if(r){let o=t[r];o&&(yield p({condition:"types",itemPath:[r],modulePath:o,packageContext:e,subpath:void 0}))}}async function*at(t,e){yield*U(t,e),yield*_(t,e),yield*et(t,e),yield*nt(t,e),yield*st(t,e),yield*it(t,e),yield*ot(t,e)}import{AssertionError as Ut}from"node:assert";function ct(t){if(!tt(t))throw new Ut({message:"input is not PackageJson",actual:t})}import{readFile as _t}from"node:fs/promises";async function pt(t){let e=await _t(t,"utf-8");return JSON.parse(e)}async function mt(t){let e=await pt(t);return ct(e),e}async function yt(t,e){let r=/\.json$/i.test(t)?`node --input-type=module --eval="import '${t}' assert { type: 'json' };"`:`node --input-type=module --eval="import '${t}';"`;await g(r,e)}async function ft(t,e){try{return typeof t.moduleName=="string"?(await yt(t.moduleName,e),new c({code:0,entryPoint:t,message:`"${t.moduleName}" works with import`,name:"import"})):new c({code:2,entryPoint:t,message:`Import skipped: ${t.itemPath.join(".")}`,name:"import"})}catch(r){return new c({code:1,entryPoint:t,error:r instanceof Error?r:new Error(String(r)),message:`${t.moduleName??t.itemPath.join(".")} cannot be imported`,name:"import"})}}async function lt(t,e){let r=`node --input-type=commonjs --eval="require('${t}');"`;await g(r,e)}async function ut(t,e){try{return typeof t.moduleName=="string"?(await lt(t.moduleName,e),new c({code:0,entryPoint:t,message:`"${t.moduleName}" works with require`,name:"require"})):new c({code:2,entryPoint:t,message:`Require skipped: ${t.itemPath.join(".")}`,name:"require"})}catch(r){return new c({code:1,entryPoint:t,error:r instanceof Error?r:new Error(String(r)),message:`${t.moduleName??t.itemPath.join(".")} cannot be required`,name:"require"})}}function Wt(t){return typeof t.condition>"u"||t.condition==="require"}function zt(t){return typeof t.condition>"u"||t.condition==="import"}async function dt(t,e){let r=[];try{typeof t.moduleName=="string"&&(Wt(t)&&r.push(await ut(t,e)),zt(t)&&r.push(await ft(t,e)))}catch(o){if(o instanceof Error)throw new Error(`Unable to verify "${t.moduleName}"`,{cause:o})}return r}var w=class extends Vt{options;packageDirectory;#e;#t;constructor(e){super(),this.options=e,this.packageDirectory=Kt(this.options.package),this.#e=0,this.#t=e.controller}processResult(e){this.emit("result",e),e.code===1&&(this.#e=1,this.options.bail&&this.#t.abort())}processResults(e){[e].flat().forEach(r=>this.processResult(r))}async checkFilesExist(e){return await b.from(e).map(async r=>{let o=await D(r);return this.processResults(o),o},{signal:this.#t.signal,concurrency:this.options.concurrency}).toArray({signal:this.#t.signal})}async checkSyntax(e){let r=e.filter(o=>/\.[cm]?js$/i.test(o.resolvedPath));return await b.from(r).map(async o=>{let s=await L(o,{signal:this.#t.signal});return this.processResults(s),s},{signal:this.#t.signal,concurrency:this.options.concurrency}).toArray({signal:this.#t.signal})}async verifyIncludes(e){return(await b.from(e).map(async r=>{let o=await dt(r,{cwd:this.packageDirectory,signal:this.#t.signal});return this.processResults(o),o},{signal:this.#t.signal,concurrency:this.options.concurrency}).toArray({signal:this.#t.signal})).flat()}async run(){let e=await mt(this.options.package),r={name:e.name,type:e.type??"commonjs",path:this.options.package,directory:this.packageDirectory},o=await b.from(at(e,r),{objectMode:!0}).toArray({signal:this.#t.signal}),s=new Set,i=y=>{y.forEach(n=>{n.code===1&&s.add(n.entryPoint)})},a=y=>y.filter(n=>!s.has(n));return i(await this.checkFilesExist(o)),this.options.check&&i(await this.checkSyntax(a(o))),this.options.verify&&i(await this.verifyIncludes(a(o))),this.#e}};import{join as te}from"node:path";import{Readable as ee}from"node:stream";import{parseArgs as re}from"node:util";import{availableParallelism as Ht}from"node:os";function Pt(t){let e=Ht(),r=Number.parseInt(`${t}`);return Number.isInteger(r)?Math.max(1,Math.min(r,e)):e}import{stat as Qt}from"node:fs/promises";import{basename as Xt,join as Yt,resolve as Zt}from"node:path";async function $(t){let e=await Qt(t);if(e.isDirectory())return await $(Yt(t,"package.json"));if(e.isFile()&&Xt(t)==="package.json")return Zt(t);throw new Error(`Unable to resolve package.json from ${t}`)}async function gt(){let t={allowPositionals:!0,strict:!0,tokens:!1,options:{concurrency:{type:"string",short:"c"},bail:{type:"boolean",short:"b",default:process.env.CI==="true"},check:{type:"boolean",default:!1,short:"s"},verify:{type:"boolean",default:!1,short:"v"},json:{type:"boolean",default:!1,short:"j"},info:{type:"boolean",default:process.env.RUNNER_DEBUG==="1",short:"i"}}},{values:e,positionals:r}=re(t);return{packages:await ee.from(r.length?r:[te(process.cwd(),"package.json")]).map(s=>$(s)).toArray(),concurrency:Pt(e.concurrency),bail:e.bail??t.options.bail.default,check:e.check??t.options.check.default,verify:e.verify??t.options.verify.default,json:e.json??t.options.verify.default,info:e.info??t.options.info.default}}try{let{json:t,info:e,packages:r,...o}=await gt(),s=[],i=n=>{s.push(n),!t&&(e||n.code===1)&&console.log(n.toString())},a=new AbortController;oe(100,a.signal);let y=r.map(n=>{let f=new w({...o,package:n,controller:a});return f.on("result",i),f});try{for(let n of y)await n.run()}catch(n){if(n instanceof Error&&n.name!=="AbortError")throw n}process.exitCode=s.reduce((n,f)=>f.code===1?1:n,0),t&&process.stdout.write(JSON.stringify(s.filter(n=>e||n.code===1),null,2))}catch(t){console.group("validate-package-exports"),console.error(t),console.groupEnd(),process.exitCode??=1}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "validate-package-exports",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Validate your package.json exports actually exist, have valid syntax, and can be imported or required without issues.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"validate",
|
|
@@ -36,20 +36,20 @@
|
|
|
36
36
|
"sideEffects": false,
|
|
37
37
|
"prettier": "@webdeveric/prettier-config",
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@types/node": "^20.
|
|
39
|
+
"@types/node": "^20.12.2",
|
|
40
40
|
"@vitest/coverage-v8": "^1.4.0",
|
|
41
41
|
"@webdeveric/eslint-config-ts": "^0.7.1",
|
|
42
42
|
"@webdeveric/prettier-config": "^0.2.0",
|
|
43
43
|
"@webdeveric/utils": "^0.29.1",
|
|
44
44
|
"cross-env": "^7.0.3",
|
|
45
|
-
"cspell": "^8.6.
|
|
45
|
+
"cspell": "^8.6.1",
|
|
46
|
+
"esbuild": "^0.20.2",
|
|
46
47
|
"esbuild-plugin-clean": "^1.0.1",
|
|
47
48
|
"esbuild-plugin-environment": "^0.3.0",
|
|
48
|
-
"
|
|
49
|
+
"eslint": "^8.57.0",
|
|
49
50
|
"eslint-config-prettier": "^9.1.0",
|
|
50
51
|
"eslint-import-resolver-typescript": "^3.6.1",
|
|
51
52
|
"eslint-plugin-import": "^2.29.1",
|
|
52
|
-
"eslint": "^8.57.0",
|
|
53
53
|
"husky": "^9.0.11",
|
|
54
54
|
"lint-staged": "^15.2.2",
|
|
55
55
|
"prettier": "^3.2.5",
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
"vitest": "^1.4.0"
|
|
59
59
|
},
|
|
60
60
|
"scripts": {
|
|
61
|
-
"
|
|
62
|
-
"
|
|
61
|
+
"prevalidate": "pnpm build:dev",
|
|
62
|
+
"validate": "./dist/cli.mjs",
|
|
63
63
|
"format": "prettier --write .",
|
|
64
64
|
"build": "cross-env NODE_ENV=production node --experimental-json-modules --no-warnings ./build.mjs",
|
|
65
65
|
"build:dev": "cross-env NODE_ENV=development node --experimental-json-modules --no-warnings ./build.mjs",
|
package/readme.md
CHANGED
|
@@ -20,16 +20,24 @@ yarn add validate-package-exports -D
|
|
|
20
20
|
|
|
21
21
|
## Options
|
|
22
22
|
|
|
23
|
-
| Flag | Description | Default value |
|
|
24
|
-
| --- | --- | --- |
|
|
25
|
-
| `--
|
|
26
|
-
| `--
|
|
27
|
-
| `--
|
|
28
|
-
| `--
|
|
29
|
-
| `--
|
|
30
|
-
| `--
|
|
23
|
+
| Flag | Description | Default value |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| `--check` / `-s` | Check syntax of JS files | `false` |
|
|
26
|
+
| `--verify` / `-v` | Verify a module can be imported or required | `false` |
|
|
27
|
+
| `--concurrency` / `-c` | Concurrency | `availableParallelism()` |
|
|
28
|
+
| `--bail` / `-b` | Stop after the first error | `process.env.CI === 'true'` |
|
|
29
|
+
| `--info` / `-i` | Show `info` messages.<br>The default behavior is to only show `error`. | `process.env.RUNNER_DEBUG === '1'` |
|
|
30
|
+
| `--json` / `-j` | Use JSON output | `false` |
|
|
31
31
|
|
|
32
|
-
##
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
validate-package-exports [FILE]... [options]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
:information_source: If you do not provide a path to a `package.json`, it will try to find one in the current directory.
|
|
39
|
+
|
|
40
|
+
### Package scripts examples
|
|
33
41
|
|
|
34
42
|
```json
|
|
35
43
|
{
|
|
@@ -50,6 +58,12 @@ OR
|
|
|
50
58
|
}
|
|
51
59
|
```
|
|
52
60
|
|
|
61
|
+
### Using `npx`
|
|
62
|
+
|
|
63
|
+
```shell
|
|
64
|
+
npx --yes validate-package-exports ./path/to/package.json --check --verify
|
|
65
|
+
```
|
|
66
|
+
|
|
53
67
|
## Local development
|
|
54
68
|
|
|
55
69
|
```
|