validate-package-exports 0.2.1 → 0.4.0

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 CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  /*!
3
3
  * @file validate-package-exports
4
- * @version 0.2.1
4
+ * @version 0.4.0
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{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}
9
+ import{setMaxListeners as pe}from"node:events";import{Readable as me}from"node:stream";var a=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 ee}from"node:events";import{dirname as re}from"node:path";import{Readable as x}from"node:stream";import{relative as $}from"node:path";import{stat as yt}from"node:fs/promises";async function F(t){try{return(await yt(t)).isFile()}catch{return!1}}async function A(t){try{if(await F(t.resolvedPath)===!1)throw new Error(`${t.resolvedPath} is not a file`);return new a({name:"file-exists",code:0,message:`${$(process.cwd(),t.resolvedPath)} exists`,entryPoint:t})}catch(e){return new a({name:"file-exists",code:1,entryPoint:t,message:`${$(process.cwd(),t.resolvedPath)} does not exist`,error:e instanceof Error?e:new Error(String(e))})}}import{relative as N}from"node:path";import{exec as dt}from"node:child_process";import{promisify as Pt}from"node:util";var l=Pt(dt);async function B(t,e){try{return await l(`node --check ${t.resolvedPath}`,e),new a({code:0,entryPoint:t,message:`${N(process.cwd(),t.resolvedPath)} has valid syntax`,name:"check-syntax"})}catch(r){return new a({code:1,entryPoint:t,error:r instanceof Error?r:new Error(String(r)),message:`Could not validate syntax for ${N(process.cwd(),t.resolvedPath)}`,name:"check-syntax"})}}import{relative as bt,dirname as vt,basename as Rt}from"node:path";function J(t,e){return e==="."?t:`${t}/${e.replace(/^\.\//,"")}`}function M(t,e="commonjs",r){return r==="require"||t.endsWith(".cjs")?"commonjs":r==="import"||t.endsWith(".mjs")?"module":e}import{createRequire as Et}from"node:module";import{basename as gt,dirname as ht,join as xt,resolve as kt}from"node:path";function I(t){let e=new Map;return(...o)=>{let i=e.get(o[0]);if(i)return i;let n=t(...o);return e.set(o[0],n),n}}var wt=I(Et);function q(t,e){let r=kt(e.directory,t);if(e.type==="commonjs")try{let i=wt(e.directory).resolve(r);return xt(ht(r),gt(i))}catch{}return r}function p({moduleName:t,modulePath:e,packageContext:r,subpath:o,itemPath:i,condition:n}){let s=q(e,r);return{moduleName:t??(o?J(r.name,o):void 0),packagePath:r.path,type:M(e,r.type,n),fileName:Rt(s),relativePath:bt(r.directory,s),directory:vt(s),resolvedPath:s,subpath:o,condition:n,itemPath:i}}function D(t,e){return typeof t=="string"?{[e]:t}:t}function*L(t,e){if(t.bin)for(let[r,o]of Object.entries(D(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 jt}from"node:fs/promises";import{resolve as Ct}from"node:path";async function*T(t,e){if(typeof t.directories?.bin=="string"){let r=await jt(t.directories.bin);for await(let o of r)o.isFile()&&(yield p({condition:void 0,itemPath:["directories","bin"],modulePath:Ct(t.directories.bin,o.name),packageContext:e,subpath:void 0}))}}import{isObject as d}from"@webdeveric/utils/predicate/isObject";import{isOptionalString as y}from"@webdeveric/utils/predicate/isOptionalString";import{isString as w}from"@webdeveric/utils/predicate/isString";import{isStringArray as St}from"@webdeveric/utils/predicate/isStringArray";import{isStringRecord as Ot}from"@webdeveric/utils/predicate/isStringRecord";import{createStringMatchingPredicate as b}from"@webdeveric/utils/predicate-factory/createStringMatchingPredicate";import{everyItem as G}from"@webdeveric/utils/predicate-factory/everyItem";import{maybeUndefined as u}from"@webdeveric/utils/predicate-factory/maybeUndefined";function Ft(t){return t==="commonjs"||t==="module"}var $t=u(Ft),_=b(/\.\d+(\.gz)?$/),At=G(_),Nt=t=>_(t)||At(t),Bt=u(Nt);function Jt(t){return d(t)&&y(t.bin)&&y(t.man)}var Mt=u(Jt);function It(t){return w(t)||Ot(t)}var qt=u(It);function z(t){return typeof t=="string"&&t.startsWith("./")}var Dt=/^(?<before>\.\/[^*]*)\*(?<after>[^*]*)$/,Ze=b(Dt);function v(t){return t===null||z(t)}var Lt=b(/^(?![\\.0-9])./);function P(t){return d(t)?Object.entries(t).every(([r,o])=>Lt(r)&&C(o)):!1}function R(t){return d(t)?Object.entries(t).every(([r,o])=>(r==="."||z(r))&&C(o)):!1}function U(t){return v(t)||P(t)}var j=G(U);function C(t){return U(t)||j(t)}function Tt(t){return C(t)||R(t)}var Gt=u(Tt),S=t=>d(t)&&Object.entries(t).every(e=>typeof e[0]=="string"&&(typeof e[1]=="string"||typeof e[1]=="boolean"));function _t(t){return w(t)||S(t)}var zt=u(_t),Ut=u(St);function V(t){return d(t)&&w(t.name)&&y(t.version)&&y(t.main)&&y(t.module)&&zt(t.browser)&&y(t.types)&&Bt(t.man)&&Mt(t.directories)&&$t(t.type)&&Gt(t.exports)&&qt(t.bin)&&Ut(t.files)}function*W(t,e){if(t.browser){if(S(t.browser)){let r=Object.entries(t.browser).filter(o=>typeof o[0]=="string"&&typeof o[1]=="string");for(let[o,i]of r)yield p({condition:void 0,itemPath:["browser",o],modulePath:i,packageContext:e,subpath:void 0});return}yield p({condition:void 0,itemPath:["browser"],modulePath:t.browser,packageContext:e,subpath:void 0})}}var h=class{processExportsEntryPath(e,r,o){return e===null?[]:[p({modulePath:e,subpath:".",...r,packageContext:o})]}processExportsEntry(e,r,o){return P(e)?this.processConditionalExports(e,r,o):this.processExportsEntryPath(e,r,o)}processExportsEntryArray(e,r,o){return e.map((i,n)=>this.processExportsEntry(i,{...r,itemPath:[...r.itemPath,n]},o)).flat()}processSubpathExports(e,r,o){return Object.entries(e).map(([i,n])=>this.process(n,{...r,subpath:i,itemPath:[...r.itemPath,i]},o)).flat()}processConditionalExports(e,r,o){let i=(n,s,m)=>{if(P(s))return n;if(m.at(-1)==="default"){let f=m.at(-2);if(typeof f=="string")return f}return n};return Object.entries(e).map(([n,s])=>{let m=[...r.itemPath,n];return this.process(s,{...r,condition:i(n,s,m),itemPath:m},o)}).flat()}process(e,r,o){return v(e)?this.processExportsEntryPath(e,r,o):j(e)?this.processExportsEntryArray(e,r,o):R(e)?this.processSubpathExports(e,r,o):P(e)?this.processConditionalExports(e,r,o):[]}};import{opendir as Vt}from"node:fs/promises";import{resolve as Wt}from"node:path";function Ht(t,e){return["moduleName","relativePath","fileName","resolvedPath"].reduce((o,i)=>{let n=o[i];return n&&(o[i]=n.replace("*",e)),o},structuredClone(t))}async function*H(t,e,r){let o=await Vt(t);for await(let i of o){let n=Wt(t,i.name);i.isDirectory()?yield*H(n,e,r):i.isFile()&&(typeof r.suffix>"u"||i.name.endsWith(r.suffix))&&(yield Ht(e,r.findStar(n)))}}async function*K(t){if(!t.resolvedPath.includes("*")){yield t;return}let[e,r]=t.resolvedPath.split("*"),o={prefix:e,suffix:r,prefixPattern:e?new RegExp(`^${e}`,"i"):void 0,suffixPattern:r?new RegExp(`${r}$`,"i"):void 0,findStar(i){let n=i;return this.prefixPattern&&(n=n.replace(this.prefixPattern,"")),this.suffixPattern&&(n=n.replace(this.suffixPattern,"")),n}};yield*H(t.directory,t,o)}async function*Q(t,e){if(t.exports){let r=new h().process(t.exports,{itemPath:["exports"]},e);for(let o of r)yield*K(o)}}function*X(t,e){t.main&&(yield p({moduleName:e.name,condition:void 0,itemPath:["main"],modulePath:t.main,packageContext:e,subpath:void 0}))}function*Y(t,e){t.module&&(yield p({moduleName:e.name,condition:void 0,itemPath:["module"],modulePath:t.module,packageContext:e,subpath:void 0}))}function*Z(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*tt(t,e){yield*L(t,e),yield*T(t,e),yield*W(t,e),yield*X(t,e),yield*Y(t,e),yield*Z(t,e),yield*Q(t,e)}import Kt from"@npmcli/arborist";import Qt from"npm-packlist";import{sep as et}from"node:path";function rt(t){return et==="/"?t:t.replaceAll("/",et)}async function ot(t){let r=await new Kt({path:t}).loadActual();return(await Qt(r)).map(i=>rt(i))}import{AssertionError as Xt}from"node:assert";function nt(t){if(!V(t))throw new Xt({message:"input is not PackageJson",actual:t})}import{readFile as Yt}from"node:fs/promises";async function it(t){let e=await Yt(t,"utf-8");return JSON.parse(e)}async function st(t){let e=await it(t);return nt(e),e}async function at(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 l(r,e)}async function ct(t,e){try{return typeof t.moduleName=="string"?(await at(t.moduleName,e),new a({code:0,entryPoint:t,message:`"${t.moduleName}" works with import`,name:"import"})):new a({code:2,entryPoint:t,message:`Import skipped: ${t.itemPath.join(".")}`,name:"import"})}catch(r){return new a({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 pt(t,e){let r=`node --input-type=commonjs --eval="require('${t}');"`;await l(r,e)}async function mt(t,e){try{return typeof t.moduleName=="string"?(await pt(t.moduleName,e),new a({code:0,entryPoint:t,message:`"${t.moduleName}" works with require`,name:"require"})):new a({code:2,entryPoint:t,message:`Require skipped: ${t.itemPath.join(".")}`,name:"require"})}catch(r){return new a({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 Zt(t){return typeof t.condition>"u"||t.condition==="require"}function te(t){return typeof t.condition>"u"||t.condition==="import"}async function ft(t,e){let r=[];try{typeof t.moduleName=="string"&&(Zt(t)&&r.push(await mt(t,e)),te(t)&&r.push(await ct(t,e)))}catch(o){if(o instanceof Error)throw new Error(`Unable to verify "${t.moduleName}"`,{cause:o})}return r}var k=class extends ee{options;packageDirectory;#e;#t;constructor(e){super(),this.options=e,this.packageDirectory=re(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 x.from(e).map(async r=>{let o=await A(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 x.from(r).map(async o=>{let i=await B(o,{signal:this.#t.signal});return this.processResults(i),i},{signal:this.#t.signal,concurrency:this.options.concurrency}).toArray({signal:this.#t.signal})}async verifyIncludes(e){return(await x.from(e).map(async r=>{let o=await ft(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 checkPacklist(e,r){let o=new Set(await ot(r.directory)),i=e.map(n=>{let s=o.has(n.relativePath);return new a({name:"packlist",code:s?0:1,message:s?`${n.relativePath} will be packed`:`${n.relativePath} will not be packed`,error:s?void 0:new Error("EntryPoint relativePath not found in packlist files"),entryPoint:n})});return this.processResults(i),i}async run(){let e=await st(this.options.package),r={name:e.name,type:e.type??"commonjs",path:this.options.package,directory:this.packageDirectory},o=await x.from(tt(e,r),{objectMode:!0}).toArray({signal:this.#t.signal}),i=new Set,n=m=>{m.forEach(f=>{f.code===1&&i.add(f.entryPoint)})},s=m=>m.filter(f=>!i.has(f));return n(await this.checkFilesExist(o)),this.options.check&&n(await this.checkSyntax(s(o))),this.options.verify&&n(await this.verifyIncludes(s(o))),n(await this.checkPacklist(s(o),r)),this.#e}};import{parseArgs as ne}from"node:util";import{availableParallelism as oe}from"node:os";function ut(t){let e=oe(),r=Number.parseInt(`${t}`);return Number.isInteger(r)?Math.max(1,Math.min(r,e)):e}function lt(t){let e={args: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"},"no-bail":{type:"boolean",default:!1},"no-info":{type:"boolean",default:!1}}},{values:r,positionals:o}=ne(e),i=r["no-bail"]??e.options["no-bail"].default,n=r["no-info"]??e.options["no-info"].default;return{packages:o.length?o:["./package.json"],concurrency:ut(r.concurrency),bail:i?!1:r.bail??e.options.bail.default,check:r.check??e.options.check.default,verify:r.verify??e.options.verify.default,json:r.json??e.options.verify.default,info:n?!1:r.info??e.options.info.default}}import{stat as ie}from"node:fs/promises";import{basename as se,join as ae,resolve as ce}from"node:path";async function O(t){let e=await ie(t);if(e.isDirectory())return await O(ae(t,"package.json"));if(e.isFile()&&se(t)==="package.json")return ce(t);throw new Error(`Unable to resolve package.json from ${t}`)}try{let{json:t,info:e,packages:r,...o}=lt(),i=await me.from(r).map(c=>O(c),{concurrency:o.concurrency}).toArray(),n=[],s=c=>{n.push(c),!t&&(e||c.code===1)&&console.log(c.toString())},m=new AbortController;pe(100,m.signal);let f=i.map(c=>{let E=new k({...o,package:c,controller:m});return E.on("result",s),E});try{for(let c of f)await c.run()}catch(c){if(c instanceof Error&&c.name!=="AbortError")throw c}process.exitCode=n.reduce((c,E)=>E.code===1?1:c,0),t&&process.stdout.write(JSON.stringify(n.filter(c=>e||c.code===1),null,2))}catch(t){console.group("validate-package-exports"),console.dir(t,{depth:null}),console.groupEnd(),process.exitCode??=1}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "validate-package-exports",
3
- "version": "0.2.1",
3
+ "version": "0.4.0",
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",
@@ -30,19 +30,25 @@
30
30
  "./dist"
31
31
  ],
32
32
  "engines": {
33
- "node": ">=18.11.0"
33
+ "node": ">=18.14.0"
34
34
  },
35
- "packageManager": "pnpm@8.15.5+sha256.4b4efa12490e5055d59b9b9fc9438b7d581a6b7af3b5675eb5c5f447cee1a589",
35
+ "packageManager": "pnpm@8.15.7+sha256.50783dd0fa303852de2dd1557cd4b9f07cb5b018154a6e76d0f40635d6cee019",
36
36
  "sideEffects": false,
37
37
  "prettier": "@webdeveric/prettier-config",
38
+ "dependencies": {
39
+ "@npmcli/arborist": "^7.4.2",
40
+ "@webdeveric/utils": "^0.30.0",
41
+ "npm-packlist": "^8.0.2"
42
+ },
38
43
  "devDependencies": {
39
- "@types/node": "^20.12.2",
40
- "@vitest/coverage-v8": "^1.4.0",
44
+ "@types/node": "^20.12.7",
45
+ "@types/npm-packlist": "^7.0.3",
46
+ "@types/npmcli__arborist": "^5.6.5",
47
+ "@vitest/coverage-v8": "^1.5.0",
41
48
  "@webdeveric/eslint-config-ts": "^0.7.1",
42
49
  "@webdeveric/prettier-config": "^0.2.0",
43
- "@webdeveric/utils": "^0.29.1",
44
50
  "cross-env": "^7.0.3",
45
- "cspell": "^8.6.1",
51
+ "cspell": "^8.7.0",
46
52
  "esbuild": "^0.20.2",
47
53
  "esbuild-plugin-clean": "^1.0.1",
48
54
  "esbuild-plugin-environment": "^0.3.0",
@@ -53,9 +59,9 @@
53
59
  "husky": "^9.0.11",
54
60
  "lint-staged": "^15.2.2",
55
61
  "prettier": "^3.2.5",
56
- "typescript": "^5.4.3",
62
+ "typescript": "^5.4.5",
57
63
  "vite-tsconfig-paths": "^4.3.2",
58
- "vitest": "^1.4.0"
64
+ "vitest": "^1.5.0"
59
65
  },
60
66
  "scripts": {
61
67
  "prevalidate": "pnpm build:dev",
package/readme.md CHANGED
@@ -26,7 +26,9 @@ yarn add validate-package-exports -D
26
26
  | `--verify` / `-v` | Verify a module can be imported or required | `false` |
27
27
  | `--concurrency` / `-c` | Concurrency | `availableParallelism()` |
28
28
  | `--bail` / `-b` | Stop after the first error | `process.env.CI === 'true'` |
29
+ | `--no-bail` | Turn off `--bail` | `false` |
29
30
  | `--info` / `-i` | Show `info` messages.<br>The default behavior is to only show `error`. | `process.env.RUNNER_DEBUG === '1'` |
31
+ | `--no-info` | Turn off `--info` | `false` |
30
32
  | `--json` / `-j` | Use JSON output | `false` |
31
33
 
32
34
  ## Usage