@stacksjs/dtsx
Version:
A modern, fast .d.ts generation tool, powered by Bun.
4 lines (3 loc) • 3.91 kB
JavaScript
// @bun
import{lstat as D,realpath as A,stat as G}from"fs/promises";import{isAbsolute as w,normalize as O,relative as b,resolve as L}from"path";var Z={rootDir:process.cwd(),maxFileSize:10485760,maxTotalSize:104857600,timeout:30000,followSymlinks:!1,maxFiles:1e4,blockedPatterns:["**/.git/**","**/node_modules/**","**/.env*","**/secrets/**","**/*.key","**/*.pem"]};class W extends Error{code;path;constructor(H,J,q){super(H);this.code=J;this.path=q;this.name="SecurityError"}}function j(H,J={}){let{rootDir:q=process.cwd()}=J,K=O(H),Q=w(K)?K:L(q,K),V=L(Q),X=b(q,V);if(X.startsWith("..")||w(X))throw new W(`Path traversal detected: "${H}" resolves outside root directory`,"PATH_TRAVERSAL",H);return V}function z(H,J={}){return H.map((q)=>j(q,J))}function R(H,J={}){let q=J.blockedPatterns||Z.blockedPatterns;for(let K of q)if(U(H,K))return!0;return!1}var N=new Map;function I(H){let J=N.get(H);if(J)return J;let q=H.replace(/\*\*/g,"<<GLOBSTAR>>").replace(/\*/g,"<<STAR>>").replace(/\?/g,"<<QUESTION>>");q=q.replace(/[.+^${}()|[\]\\]/g,"\\$&"),q=q.replace(/^<<GLOBSTAR>>\//,"(.*\\/)?"),q=q.replace(/\/<<GLOBSTAR>>$/,"(\\/.*)?"),q=q.replace(/\/<<GLOBSTAR>>\//g,"(\\/.*)?\\/"),q=q.replace(/<<GLOBSTAR>>/g,".*"),q=q.replace(/<<STAR>>/g,"[^/]*"),q=q.replace(/<<QUESTION>>/g,"[^/]");let K=new RegExp(`^${q}$`);return N.set(H,K),K}function U(H,J){let q=H.indexOf("\\")===-1?H:H.replace(/\\/g,"/");return I(J).test(q)}async function _(H,J={}){let q=J.maxFileSize??Z.maxFileSize;try{let K=await G(H);if(K.size>q)throw new W(`File too large: "${H}" is ${$(K.size)}, max is ${$(q)}`,"FILE_TOO_LARGE",H);return K.size}catch(K){if(K instanceof W)throw K;throw new W(`Failed to check file size: ${H}`,"INVALID_PATH",H)}}async function T(H){try{return(await D(H)).isSymbolicLink()}catch{return!1}}async function x(H,J={}){let q=J.followSymlinks??Z.followSymlinks;if(await T(H)){if(!q)throw new W(`Symbolic links not allowed: "${H}"`,"SYMLINK_NOT_ALLOWED",H);let K=await A(H);return j(K,J)}return H}async function M(H,J={}){let q=j(H,J);if(R(q,J))throw new W(`Path matches blocked pattern: "${H}"`,"BLOCKED_PATTERN",H);let K=await x(q,J),Q=await _(K,J);return{path:K,size:Q}}async function Y(H,J={}){let q=J.maxFiles??Z.maxFiles,K=J.maxTotalSize??Z.maxTotalSize;if(H.length>q)throw new W(`Too many files: ${H.length} exceeds maximum of ${q}`,"MAX_FILES_EXCEEDED");let Q=[],V=0;for(let X of H){let B=await M(X,J);if(Q.push(B.path),V+=B.size,V>K)throw new W(`Total size exceeded: ${$(V)} exceeds maximum of ${$(K)}`,"TOTAL_SIZE_EXCEEDED")}return{paths:Q,totalSize:V}}function k(H,J,q="Operation"){return new Promise((K,Q)=>{let V=setTimeout(()=>{Q(new W(`${q} timed out after ${J}ms`,"TIMEOUT"))},J);H.then((X)=>{clearTimeout(V),K(X)}).catch((X)=>{clearTimeout(V),Q(X)})})}function F(H,J={}){let q=J.timeout??Z.timeout;return async(K)=>{let{path:Q}=await M(K,J);return k(H(Q),q,`Processing ${K}`)}}function y(H,J={}){let q=J.timeout??Z.timeout;return async(K)=>{let{paths:Q}=await Y(K,J);return k(H(Q),q,`Processing ${K.length} files`)}}function E(H){let J=H.replace(/\\/g,"/").replace(/\0/g,"").replace(/^\/+/,"").replace(/^[A-Z]:/i,""),q="";while(q!==J)q=J,J=J.replace(/\.\.\/|\.\.$/g,"").replace(/\/+/g,"/");return J.replace(/^\/+|\/+$/g,"")}function S(H){if(H.includes("\x00"))return!1;if(O(H).includes(".."))return!1;if(w(H)&&!H.startsWith(process.cwd()))return!1;return!0}function $(H){if(H===0)return"0 B";let J=["B","KB","MB","GB"],q=1024,K=Math.floor(Math.log(H)/Math.log(q));return`${Number.parseFloat((H/q**K).toFixed(2))} ${J[K]}`}function u(H={}){let J={...Z,...H};return{validatePath:(q)=>j(q,J),validatePaths:(q)=>z(q,J),validateFile:(q)=>M(q,J),validateBatch:(q)=>Y(q,J),withTimeout:(q,K)=>k(q,J.timeout,K),secureProcessor:(q)=>F(q,J),isBlocked:(q)=>R(q,J),getConfig:()=>J}}
export{Z as Kb,W as Lb,j as Mb,z as Nb,R as Ob,_ as Pb,T as Qb,x as Rb,M as Sb,Y as Tb,k as Ub,F as Vb,y as Wb,E as Xb,S as Yb,u as Zb};