UNPKG

fs-fixture

Version:

Easily create test fixtures at a temporary file-system path

2 lines (1 loc) 3.97 kB
var F=Object.defineProperty;var o=(r,t)=>F(r,"name",{value:t,configurable:!0});import y from"node:fs/promises";import c from"node:path";import{fileURLToPath as b}from"node:url";import j from"node:fs";import v from"node:os";const w=o(async(r,t)=>{try{await r.unlink(t);return}catch(i){if(D(i))return}const e=await r.readdir(t,{withFileTypes:!0});await Promise.all(e.map(i=>{const n=c.join(t,i.name);return i.isDirectory()?w(r,n):r.unlink(n)})),await r.rmdir(t)},"recursiveRm"),D=o(r=>r instanceof Error&&"code"in r&&r.code==="ENOENT","isEnoent");typeof Symbol.asyncDispose!="symbol"&&Object.defineProperty(Symbol,"asyncDispose",{configurable:!1,enumerable:!1,writable:!1,value:Symbol.for("asyncDispose")});class x{static{o(this,"FsFixture")}path;fs;constructor(t,e){this.path=t,this.fs=e??y}getPath(...t){return c.join(this.path,...t)}exists(t=""){return this.fs.access(this.getPath(t)).then(()=>!0,()=>!1)}rm(t=""){const e=this.getPath(t);if(this.fs.rm)return this.fs.rm(e,{recursive:!0,force:!0});if(!this.fs.unlink||!this.fs.rmdir)throw new Error("rm() requires the fs API to support rm(), or unlink() + rmdir()");return w(this.fs,e)}cp(t,e,i){if(!this.fs.cp)throw new Error("cp() requires the fs API to support cp()");return e?(e.endsWith("/")||e.endsWith(c.sep))&&(e+=c.basename(t)):e=c.basename(t),this.fs.cp(t,this.getPath(e),i)}mkdir(t){return this.fs.mkdir(this.getPath(t),{recursive:!0})}mv(t,e){return this.fs.rename(this.getPath(t),this.getPath(e))}readFile=o(((t,e)=>this.fs.readFile(this.getPath(t),e)),"readFile");readdir=o(((t,e)=>this.fs.readdir(this.getPath(t||""),e)),"readdir");writeFile=o(((t,e,...i)=>this.fs.writeFile(this.getPath(t),e,...i)),"writeFile");async readJson(t){const e=await this.readFile(t,"utf8");return JSON.parse(e)}writeJson(t,e,i=2){return this.writeFile(t,JSON.stringify(e,null,i))}async[Symbol.asyncDispose](){await this.rm()}}const T=j.realpathSync(v.tmpdir());class p{static{o(this,"PathBase")}path;constructor(t){this.path=t}}class d extends p{static{o(this,"Directory")}}class u extends p{static{o(this,"File")}content;constructor(t,e){super(t),this.content=e}}class h extends p{static{o(this,"Symlink")}target;type;constructor(t,e,i){super(i??""),this.target=t,this.type=e}}const g=o((r,t,e)=>{const i=[];for(const n in r){if(!Object.hasOwn(r,n))continue;const f=c.join(t,n);let a=r[n];if(typeof a=="function"){const l=Object.assign(Object.create(e),{filePath:f}),m=a(l);if(m instanceof h){const s=new h(m.target,m.type,f);i.push(s);continue}else a=m}if(typeof a=="string"||Buffer.isBuffer(a))i.push(new u(f,a));else if(a&&typeof a=="object"&&!Array.isArray(a))i.push(new d(f),...g(a,f,e));else throw new TypeError(`Invalid file content for path "${f}". Functions must return a string, Buffer, Symlink, or a nested FileTree object. Received: ${String(a)}`)}return i},"flattenFileTree");let k=0;const E=o(async(r,t)=>{const e=t?.fs??y,i=t?.tempDir?c.resolve(typeof t.tempDir=="string"?t.tempDir:b(t.tempDir)):T;t?.tempDir&&await e.mkdir(i,{recursive:!0});let n;if(e.mkdtemp?n=await e.mkdtemp(c.join(i,"fs-fixture-")):(k+=1,n=c.join(i,`fs-fixture-${process.pid}-${k}`),await e.mkdir(n,{recursive:!0})),r){if(typeof r=="string"){if(!e.cp)throw new TypeError("Template directory sources require the fs API to support cp()");await e.cp(r,n,{recursive:!0,filter:t?.templateFilter})}else if(typeof r=="object"){const a=g(r,n,{fixturePath:n,getPath:o((...s)=>c.join(n,...s),"getPath"),symlink:o((s,P)=>new h(s,P),"symlink")}),l=new Set;for(const s of a)s instanceof d?l.add(s.path):(s instanceof u||s instanceof h)&&l.add(c.dirname(s.path));if(await Promise.all(Array.from(l).map(s=>e.mkdir(s,{recursive:!0}))),a.some(s=>s instanceof h)&&!e.symlink)throw new TypeError("Symlinks require the fs API to support symlink()");await Promise.all(a.map(async s=>{s instanceof h?await e.symlink(s.target,s.path,s.type):s instanceof u&&await e.writeFile(s.path,s.content)}))}}return new x(n,t?.fs)},"createFixture");export{E as createFixture};