validate-package-exports 0.2.0 → 0.3.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 +2 -2
- package/package.json +3 -3
- package/readme.md +1 -1
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.
|
|
4
|
+
* @version 0.3.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 re}from"node:events";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 Kt}from"node:events";import{dirname as Ht}from"node:path";import{Readable as b}from"node:stream";import{relative as B}from"node:path";import{stat as xt}from"node:fs/promises";async function I(t){return(await xt(t)).isFile()}async function M(t){try{if(await I(t.resolvedPath)===!1)throw new Error(`${t.resolvedPath} is not a file`);return new a({name:"file-exists",code:0,message:`${B(process.cwd(),t.resolvedPath)} exists`,entryPoint:t})}catch(e){return new a({name:"file-exists",code:1,entryPoint:t,message:`${B(process.cwd(),t.resolvedPath)} does not exist`,error:e instanceof Error?e:new Error(String(e))})}}import{relative as D}from"node:path";import{exec as ht}from"node:child_process";import{promisify as kt}from"node:util";var g=kt(ht);async function J(t,e){try{return await g(`node --check ${t.resolvedPath}`,e),new a({code:0,entryPoint:t,message:`${D(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 ${D(process.cwd(),t.resolvedPath)}`,name:"check-syntax"})}}import{relative as bt,dirname as wt,basename as vt,resolve as jt}from"node:path";function L(t,e){return e==="."?t:`${t}/${e.replace(/^\.\//,"")}`}function q(t,e="commonjs",r){return r==="require"||t.endsWith(".cjs")?"commonjs":r==="import"||t.endsWith(".mjs")?"module":e}function c({condition:t,itemPath:e,modulePath:r,packageContext:o,subpath:s}){let i=jt(o.directory,r);return{moduleName:s?L(o.name,s):void 0,packagePath:o.path,type:q(r,o.type,t),fileName:vt(i),relativePath:bt(o.directory,i),directory:wt(i),resolvedPath:i,subpath:s,condition:t,itemPath:e}}function T(t,e){return typeof t=="string"?{[e]:t}:t}function*G(t,e){if(t.bin)for(let[r,o]of Object.entries(T(t.bin,t.name)))yield c({condition:void 0,itemPath:typeof t.bin=="string"?["bin"]:["bin",r],modulePath:o,packageContext:e,subpath:void 0})}import{opendir as Ct}from"node:fs/promises";import{resolve as Rt}from"node:path";function h(t){return Rt(t.path.endsWith(t.name)?t.path.replace(new RegExp(`[/\\\\]${t.name}$`,"i"),""):t.path,t.name)}async function*U(t,e){if(typeof t.directories?.bin=="string"){let r=await Ct(t.directories.bin);for await(let o of r)o.isFile()&&(yield c({condition:void 0,itemPath:["directories","bin"],modulePath:h(o),packageContext:e,subpath:void 0}))}}var u=t=>e=>typeof e=="string"&&t.test(e),y=t=>e=>Array.isArray(e)&&e.every(t);var p=t=>e=>typeof e>"u"||t(e);var d=t=>typeof t=="string",_=t=>typeof t=="number"&&!Number.isNaN(t),z=t=>typeof t=="bigint",V=t=>typeof t=="boolean",St=t=>typeof t>"u",W=t=>typeof t=="symbol",K=t=>t===null;var E=p(d),Be=p(_),Me=p(z),De=p(V),Je=p(W),Le=p(K),R=y(d),qe=y(_),Te=y(z),Ge=y(V),Ue=y(St),_e=y(W),ze=y(K);var At=u(/^[-+]?\d+(\.\d+)?$/),Ot=t=>typeof t=="number"||typeof t=="bigint"||At(t),Ve=y(Ot),We=u(/^[-+]?\d+$/),Ke=u(/^\d+$/);var P=t=>t!==null&&typeof t=="object"&&!Array.isArray(t);var H=t=>P(t)&&Object.entries(t).every(R);function Nt(t){return t==="commonjs"||t==="module"}var Q=u(/\.\d+(\.gz)?$/),$t=y(Q),Ft=t=>Q(t)||$t(t),It=p(Ft);function Bt(t){return P(t)&&E(t.bin)&&E(t.man)}var Mt=p(Bt);function Dt(t){return d(t)||H(t)}function X(t){return typeof t=="string"&&t.startsWith("./")}var Jt=/^(?<before>\.\/[^*]*)\*(?<after>[^*]*)$/,Ye=u(Jt);function C(t){return t===null||X(t)}var Lt=u(/^(?![\\.0-9])./);function x(t){return P(t)?Object.entries(t).every(([r,o])=>Lt(r)&&O(o)):!1}function S(t){return P(t)?Object.entries(t).every(([r,o])=>(r==="."||X(r))&&O(o)):!1}function Y(t){return C(t)||x(t)}var A=y(Y);function O(t){return Y(t)||A(t)}function qt(t){return O(t)||S(t)}var N=t=>P(t)&&Object.entries(t).every(e=>typeof e[0]=="string"&&(typeof e[1]=="string"||typeof e[1]=="boolean"));function Tt(t){return d(t)||N(t)}var Gt=p(Tt);function Z(t){return P(t)&&d(t.name)&&d(t.version)&&E(t.main)&&E(t.module)&&Gt(t.browser)&&E(t.types)&&It(t.man)&&Mt(t.directories)&&p(Nt)(t.type)&&p(qt)(t.exports)&&p(Dt)(t.bin)&&p(R)(t.files)}function*tt(t,e){if(t.browser){if(N(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 c({condition:void 0,itemPath:["browser",o],modulePath:s,packageContext:e,subpath:void 0});return}yield c({condition:void 0,itemPath:["browser"],modulePath:t.browser,packageContext:e,subpath:void 0})}}var k=class{processExportsEntryPath(e,r,o){return e===null?[]:[c({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,f,l)=>{if(x(f))return i;if(l.at(-1)==="default"){let n=l.at(-2);if(typeof n=="string")return n}return i};return Object.entries(e).map(([i,f])=>{let l=[...r.itemPath,i];return this.process(f,{...r,condition:s(i,f,l),itemPath:l},o)}).flat()}process(e,r,o){return C(e)?this.processExportsEntryPath(e,r,o):A(e)?this.processExportsEntryArray(e,r,o):S(e)?this.processSubpathExports(e,r,o):x(e)?this.processConditionalExports(e,r,o):[]}};import{opendir as Ut}from"node:fs/promises";async function*et(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"],f=n=>{let m=n;return o&&(m=m.replace(o,"")),s&&(m=m.replace(s,"")),m},l=await Ut(t.directory);for await(let n of l)if(n.isFile()&&(typeof r>"u"||n.name.endsWith(r))){let m=f(h(n));yield i.reduce((v,$)=>{let F=v[$];return F&&(v[$]=F.replace("*",m)),v},structuredClone(t))}}async function*rt(t,e){if(t.exports){let r=new k().process(t.exports,{itemPath:["exports"]},e);for(let o of r)yield*et(o)}}function*ot(t,e){t.main&&(yield c({condition:void 0,itemPath:["main"],modulePath:t.main,packageContext:e,subpath:void 0}))}function*nt(t,e){t.module&&(yield c({condition:void 0,itemPath:["module"],modulePath:t.module,packageContext:e,subpath:void 0}))}function*st(t,e){let r="types"in t?"types":"typings"in t?"typings":void 0;if(r){let o=t[r];o&&(yield c({condition:"types",itemPath:[r],modulePath:o,packageContext:e,subpath:void 0}))}}async function*it(t,e){yield*G(t,e),yield*U(t,e),yield*tt(t,e),yield*ot(t,e),yield*nt(t,e),yield*st(t,e),yield*rt(t,e)}import{AssertionError as _t}from"node:assert";function at(t){if(!Z(t))throw new _t({message:"input is not PackageJson",actual:t})}import{readFile as zt}from"node:fs/promises";async function ct(t){let e=await zt(t,"utf-8");return JSON.parse(e)}async function pt(t){let e=await ct(t);return at(e),e}async function mt(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 yt(t,e){try{return typeof t.moduleName=="string"?(await mt(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 ft(t,e){let r=`node --input-type=commonjs --eval="require('${t}');"`;await g(r,e)}async function lt(t,e){try{return typeof t.moduleName=="string"?(await ft(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 Vt(t){return typeof t.condition>"u"||t.condition==="require"}function Wt(t){return typeof t.condition>"u"||t.condition==="import"}async function ut(t,e){let r=[];try{typeof t.moduleName=="string"&&(Vt(t)&&r.push(await lt(t,e)),Wt(t)&&r.push(await yt(t,e)))}catch(o){if(o instanceof Error)throw new Error(`Unable to verify "${t.moduleName}"`,{cause:o})}return r}var w=class extends Kt{options;packageDirectory;#e;#t;constructor(e){super(),this.options=e,this.packageDirectory=Ht(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){await b.from(e).forEach(async r=>{let o=await M(r);this.processResults(o)},{signal:this.#t.signal,concurrency:this.options.concurrency})}async checkSyntax(e){let r=e.filter(o=>/\.[cm]?js$/i.test(o.resolvedPath));await b.from(r).forEach(async o=>{let s=await J(o,{signal:this.#t.signal});this.processResults(s)},{signal:this.#t.signal,concurrency:this.options.concurrency})}async verifyIncludes(e){await b.from(e).forEach(async r=>{let o=await ut(r,{cwd:this.packageDirectory,signal:this.#t.signal});this.processResults(o)},{signal:this.#t.signal,concurrency:this.options.concurrency})}async run(){let e=await pt(this.options.package),r={name:e.name,type:e.type??"commonjs",path:this.options.package,directory:this.packageDirectory},o=await b.from(it(e,r),{objectMode:!0}).toArray({signal:this.#t.signal});return await this.checkFilesExist(o),this.options.check&&await this.checkSyntax(o),this.options.verify&&await this.verifyIncludes(o),this.#e}};import{stat as Xt}from"node:fs/promises";import{basename as Yt,join as Pt,resolve as Zt}from"node:path";import{Readable as te}from"node:stream";import{parseArgs as ee}from"node:util";import{availableParallelism as Qt}from"node:os";function dt(t){let e=Qt(),r=Number.parseInt(`${t}`);return Number.isInteger(r)?Math.max(1,Math.min(r,e)):e}async function gt(t){let e=await Xt(t);if(e.isDirectory())return await gt(Pt(t,"package.json"));if(e.isFile()&&Yt(t)==="package.json")return Zt(t);throw new Error(`Unable to resolve package.json from ${t}`)}async function Et(){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}=ee(t);return{packages:await te.from(r.length?r:[Pt(process.cwd(),"package.json")]).map(s=>gt(s)).toArray(),concurrency:dt(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 Et(),s=[],i=n=>{s.push(n),!t&&(e||n.code===1)&&console.log(n.toString())},f=new AbortController;re(100,f.signal);let l=r.map(n=>{let m=new w({...o,package:n,controller:f});return m.on("result",i),m});try{for(let n of l)await n.run()}catch(n){if(n instanceof Error&&n.name!=="AbortError")throw n}process.exitCode=s.reduce((n,m)=>m.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 Kt}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 qt}from"node:events";import{dirname as Lt}from"node:path";import{Readable as b}from"node:stream";import{relative as I}from"node:path";import{stat as yt}from"node:fs/promises";async function M(t){try{return(await yt(t)).isFile()}catch{return!1}}async function D(t){try{if(await M(t.resolvedPath)===!1)throw new Error(`${t.resolvedPath} is not a file`);return new c({name:"file-exists",code:0,message:`${I(process.cwd(),t.resolvedPath)} exists`,entryPoint:t})}catch(e){return new c({name:"file-exists",code:1,entryPoint:t,message:`${I(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 lt}from"node:child_process";import{promisify as dt}from"node:util";var d=dt(lt);async function q(t,e){try{return await d(`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 Pt,dirname as Et,basename as gt,resolve as ht}from"node:path";function L(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:i,condition:s}){let a=ht(r.directory,e);return{moduleName:t??(o?L(r.name,o):void 0),packagePath:r.path,type:G(e,r.type,s),fileName:gt(a),relativePath:Pt(r.directory,a),directory:Et(a),resolvedPath:a,subpath:o,condition:s,itemPath:i}}function T(t,e){return typeof t=="string"?{[e]:t}:t}function*_(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 kt}from"node:fs/promises";import{resolve as xt}from"node:path";function h(t){return xt(t.path.endsWith(t.name)?t.path.replace(new RegExp(`[/\\\\]${t.name}$`,"i"),""):t.path,t.name)}async function*U(t,e){if(typeof t.directories?.bin=="string"){let r=await kt(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 l=t=>t!==null&&typeof t=="object"&&!Array.isArray(t);var u=t=>e=>typeof e>"u"||t(e);var y=t=>typeof t=="string";var P=u(y);var E=t=>e=>Array.isArray(e)&&e.every(t);var x=E(y);var W=t=>l(t)&&Object.entries(t).every(x);var k=t=>e=>typeof e=="string"&&t.test(e);function wt(t){return t==="commonjs"||t==="module"}var V=k(/\.\d+(\.gz)?$/),bt=E(V),vt=t=>V(t)||bt(t),jt=u(vt);function Rt(t){return l(t)&&P(t.bin)&&P(t.man)}var Ct=u(Rt);function St(t){return y(t)||W(t)}function z(t){return typeof t=="string"&&t.startsWith("./")}var Ot=/^(?<before>\.\/[^*]*)\*(?<after>[^*]*)$/,He=k(Ot);function C(t){return t===null||z(t)}var At=k(/^(?![\\.0-9])./);function g(t){return l(t)?Object.entries(t).every(([r,o])=>At(r)&&A(o)):!1}function S(t){return l(t)?Object.entries(t).every(([r,o])=>(r==="."||z(r))&&A(o)):!1}function H(t){return C(t)||g(t)}var O=E(H);function A(t){return H(t)||O(t)}function $t(t){return A(t)||S(t)}var $=t=>l(t)&&Object.entries(t).every(e=>typeof e[0]=="string"&&(typeof e[1]=="string"||typeof e[1]=="boolean"));function Nt(t){return y(t)||$(t)}var Ft=u(Nt);function K(t){return l(t)&&y(t.name)&&y(t.version)&&P(t.main)&&P(t.module)&&Ft(t.browser)&&P(t.types)&&jt(t.man)&&Ct(t.directories)&&u(wt)(t.type)&&u($t)(t.exports)&&u(St)(t.bin)&&u(x)(t.files)}function*Q(t,e){if(t.browser){if($(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 w=class{processExportsEntryPath(e,r,o){return e===null?[]:[p({modulePath:e,subpath:".",...r,packageContext:o})]}processExportsEntry(e,r,o){return g(e)?this.processConditionalExports(e,r,o):this.processExportsEntryPath(e,r,o)}processExportsEntryArray(e,r,o){return e.map((i,s)=>this.processExportsEntry(i,{...r,itemPath:[...r.itemPath,s]},o)).flat()}processSubpathExports(e,r,o){return Object.entries(e).map(([i,s])=>this.process(s,{...r,subpath:i,itemPath:[...r.itemPath,i]},o)).flat()}processConditionalExports(e,r,o){let i=(s,a,m)=>{if(g(a))return s;if(m.at(-1)==="default"){let n=m.at(-2);if(typeof n=="string")return n}return s};return Object.entries(e).map(([s,a])=>{let m=[...r.itemPath,s];return this.process(a,{...r,condition:i(s,a,m),itemPath:m},o)}).flat()}process(e,r,o){return C(e)?this.processExportsEntryPath(e,r,o):O(e)?this.processExportsEntryArray(e,r,o):S(e)?this.processSubpathExports(e,r,o):g(e)?this.processConditionalExports(e,r,o):[]}};import{opendir as Bt}from"node:fs/promises";async function*X(t){if(!t.resolvedPath.includes("*")){yield t;return}let[e,r]=t.resolvedPath.split("*"),o=e?new RegExp(`^${e}`,"i"):void 0,i=r?new RegExp(`${r}$`,"i"):void 0,s=["moduleName","relativePath","fileName","resolvedPath"],a=n=>{let f=n;return o&&(f=f.replace(o,"")),i&&(f=f.replace(i,"")),f},m=await Bt(t.directory,{recursive:!0});for await(let n of m)if(n.isFile()&&(typeof r>"u"||n.name.endsWith(r))){let f=a(h(n));yield s.reduce((j,F)=>{let B=j[F];return B&&(j[F]=B.replace("*",f)),j},structuredClone(t))}}async function*Y(t,e){if(t.exports){let r=new w().process(t.exports,{itemPath:["exports"]},e);for(let o of r)yield*X(o)}}function*Z(t,e){t.main&&(yield p({moduleName:e.name,condition:void 0,itemPath:["main"],modulePath:t.main,packageContext:e,subpath:void 0}))}function*tt(t,e){t.module&&(yield p({moduleName:e.name,condition:void 0,itemPath:["module"],modulePath:t.module,packageContext:e,subpath:void 0}))}function*et(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*rt(t,e){yield*_(t,e),yield*U(t,e),yield*Q(t,e),yield*Z(t,e),yield*tt(t,e),yield*et(t,e),yield*Y(t,e)}import{AssertionError as Mt}from"node:assert";function ot(t){if(!K(t))throw new Mt({message:"input is not PackageJson",actual:t})}import{readFile as It}from"node:fs/promises";async function nt(t){let e=await It(t,"utf-8");return JSON.parse(e)}async function it(t){let e=await nt(t);return ot(e),e}async function st(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 d(r,e)}async function at(t,e){try{return typeof t.moduleName=="string"?(await st(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 ct(t,e){let r=`node --input-type=commonjs --eval="require('${t}');"`;await d(r,e)}async function pt(t,e){try{return typeof t.moduleName=="string"?(await ct(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 Dt(t){return typeof t.condition>"u"||t.condition==="require"}function Jt(t){return typeof t.condition>"u"||t.condition==="import"}async function mt(t,e){let r=[];try{typeof t.moduleName=="string"&&(Dt(t)&&r.push(await pt(t,e)),Jt(t)&&r.push(await at(t,e)))}catch(o){if(o instanceof Error)throw new Error(`Unable to verify "${t.moduleName}"`,{cause:o})}return r}var v=class extends qt{options;packageDirectory;#e;#t;constructor(e){super(),this.options=e,this.packageDirectory=Lt(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 i=await q(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 b.from(e).map(async r=>{let o=await mt(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 it(this.options.package),r={name:e.name,type:e.type??"commonjs",path:this.options.package,directory:this.packageDirectory},o=await b.from(rt(e,r),{objectMode:!0}).toArray({signal:this.#t.signal}),i=new Set,s=m=>{m.forEach(n=>{n.code===1&&i.add(n.entryPoint)})},a=m=>m.filter(n=>!i.has(n));return s(await this.checkFilesExist(o)),this.options.check&&s(await this.checkSyntax(a(o))),this.options.verify&&s(await this.verifyIncludes(a(o))),this.#e}};import{join as Vt}from"node:path";import{Readable as zt}from"node:stream";import{parseArgs as Ht}from"node:util";import{availableParallelism as Gt}from"node:os";function ft(t){let e=Gt(),r=Number.parseInt(`${t}`);return Number.isInteger(r)?Math.max(1,Math.min(r,e)):e}import{stat as Tt}from"node:fs/promises";import{basename as _t,join as Ut,resolve as Wt}from"node:path";async function N(t){let e=await Tt(t);if(e.isDirectory())return await N(Ut(t,"package.json"));if(e.isFile()&&_t(t)==="package.json")return Wt(t);throw new Error(`Unable to resolve package.json from ${t}`)}async function ut(){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"},"no-bail":{type:"boolean",default:!1},"no-info":{type:"boolean",default:!1}}},{values:e,positionals:r}=Ht(t),o=await zt.from(r.length?r:[Vt(process.cwd(),"package.json")]).map(a=>N(a)).toArray(),i=e["no-bail"]??t.options["no-bail"].default,s=e["no-info"]??t.options["no-info"].default;return{packages:o,concurrency:ft(e.concurrency),bail:i?!1: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:s?!1:e.info??t.options.info.default}}try{let{json:t,info:e,packages:r,...o}=await ut(),i=[],s=n=>{i.push(n),!t&&(e||n.code===1)&&console.log(n.toString())},a=new AbortController;Kt(100,a.signal);let m=r.map(n=>{let f=new v({...o,package:n,controller:a});return f.on("result",s),f});try{for(let n of m)await n.run()}catch(n){if(n instanceof Error&&n.name!=="AbortError")throw n}process.exitCode=i.reduce((n,f)=>f.code===1?1:n,0),t&&process.stdout.write(JSON.stringify(i.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.
|
|
3
|
+
"version": "0.3.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",
|
|
@@ -36,11 +36,11 @@
|
|
|
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
|
-
"@webdeveric/utils": "^0.
|
|
43
|
+
"@webdeveric/utils": "^0.30.0",
|
|
44
44
|
"cross-env": "^7.0.3",
|
|
45
45
|
"cspell": "^8.6.1",
|
|
46
46
|
"esbuild": "^0.20.2",
|
package/readme.md
CHANGED
|
@@ -25,7 +25,7 @@ yarn add validate-package-exports -D
|
|
|
25
25
|
| `--check` / `-s` | Check syntax of JS files | `false` |
|
|
26
26
|
| `--verify` / `-v` | Verify a module can be imported or required | `false` |
|
|
27
27
|
| `--concurrency` / `-c` | Concurrency | `availableParallelism()` |
|
|
28
|
-
| `--bail` / `-b` |
|
|
28
|
+
| `--bail` / `-b` | Stop after the first error | `process.env.CI === 'true'` |
|
|
29
29
|
| `--info` / `-i` | Show `info` messages.<br>The default behavior is to only show `error`. | `process.env.RUNNER_DEBUG === '1'` |
|
|
30
30
|
| `--json` / `-j` | Use JSON output | `false` |
|
|
31
31
|
|