fs-fixture 2.0.0 → 2.2.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/README.md CHANGED
@@ -1,4 +1,11 @@
1
- # fs-fixture [![Latest version](https://badgen.net/npm/v/fs-fixture)](https://npm.im/fs-fixture) [![npm downloads](https://badgen.net/npm/dm/fs-fixture)](https://npm.im/fs-fixture)
1
+ <p align="center">
2
+ <img width="160" src=".github/logo.webp">
3
+ </p>
4
+ <h1 align="center">
5
+ <sup>fs-fixture</sup>
6
+ <br>
7
+ <a href="https://npm.im/fs-fixture"><img src="https://badgen.net/npm/v/fs-fixture"></a> <a href="https://npm.im/fs-fixture"><img src="https://badgen.net/npm/dm/fs-fixture"></a>
8
+ </h1>
2
9
 
3
10
  Simple API to create disposable test fixtures on disk.
4
11
 
@@ -35,8 +42,10 @@ import { createFixture } from 'fs-fixture'
35
42
  const fixture = await createFixture({
36
43
  // Nested directory syntax
37
44
  'dir-a': {
45
+ 'file-a.txt': 'hello world',
38
46
  'dir-b': {
39
- 'file-a.txt': 'hello world'
47
+ 'file-b.txt': ({ fixturePath }) => `Fixture path: ${fixturePath}`,
48
+ 'symlink-c': ({ symlink }) => symlink('../file-a.txt')
40
49
  }
41
50
  },
42
51
 
@@ -92,7 +101,21 @@ Path to a template fixture path, or a `FileTree` object that represents the fixt
92
101
 
93
102
  ```ts
94
103
  type FileTree = {
95
- [path: string]: string | FileTree
104
+ [path: string]: string | FileTree | ((api: Api) => string)
105
+ }
106
+
107
+ type Api = {
108
+ // Fixture root path
109
+ fixturePath: string
110
+
111
+ // Current file path
112
+ filePath: string
113
+
114
+ // Get path from the root of the fixture
115
+ getPath: (subpath: string) => string
116
+
117
+ // Create a symlink
118
+ symlink: (target: string) => Symlink
96
119
  }
97
120
  ```
98
121
 
@@ -103,7 +126,7 @@ class FsFixture {
103
126
  /**
104
127
  Path to the fixture directory.
105
128
  */
106
- path: string
129
+ readonly path: string
107
130
 
108
131
  /**
109
132
  Create a Fixture instance from a path. Does not create the fixture directory.
@@ -111,8 +134,8 @@ class FsFixture {
111
134
  constructor(fixturePath: string)
112
135
 
113
136
  /**
114
- Get the full path to a subpath in the fixture directory.
115
- */
137
+ Get the full path to a subpath in the fixture directory.
138
+ */
116
139
  getPath(subpath: string): string
117
140
 
118
141
  /**
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var i=require("fs/promises"),s=require("path"),u=require("fs"),l=require("os");typeof Symbol.asyncDispose!="symbol"&&Object.defineProperty(Symbol,"asyncDispose",{configurable:!1,enumerable:!1,writable:!1,value:Symbol.for("asyncDispose")});class h{path;constructor(t){this.path=t}getPath(t){return s.join(this.path,t)}exists(t=""){return i.access(this.getPath(t)).then(()=>!0,()=>!1)}rm(t=""){return i.rm(this.getPath(t),{recursive:!0,force:!0})}writeFile(t,e){return i.writeFile(this.getPath(t),e)}writeJson(t,e){return this.writeFile(t,JSON.stringify(e,null,2))}readFile(t,e){return i.readFile(this.getPath(t),e)}async[Symbol.asyncDispose](){await this.rm()}}const f=u.realpathSync(l.tmpdir()),p=`fs-fixture-${Date.now()}`;let o=0;const y=()=>(o+=1,o),c=(r,t)=>{const e=[];for(const a in r){if(!Object.hasOwn(r,a))continue;const n=r[a];typeof n=="string"?e.push({path:s.join(t,a),content:n}):e.push(...c(n,s.join(t,a)))}return e},m=async r=>{const t=s.join(f,`${p}-${y()}`);return await i.mkdir(t,{recursive:!0}),r&&(typeof r=="string"?await i.cp(r,t,{recursive:!0}):typeof r=="object"&&await Promise.all(c(r,t).map(async e=>{await i.mkdir(s.dirname(e.path),{recursive:!0}),await i.writeFile(e.path,e.content)}))),new h(t)};exports.createFixture=m;
1
+ "use strict";var s=require("fs/promises"),n=require("path"),y=require("fs"),m=require("os");typeof Symbol.asyncDispose!="symbol"&&Object.defineProperty(Symbol,"asyncDispose",{configurable:!1,enumerable:!1,writable:!1,value:Symbol.for("asyncDispose")});class w{path;constructor(t){this.path=t}getPath(t){return n.join(this.path,t)}exists(t=""){return s.access(this.getPath(t)).then(()=>!0,()=>!1)}rm(t=""){return s.rm(this.getPath(t),{recursive:!0,force:!0})}writeFile(t,i){return s.writeFile(this.getPath(t),i)}writeJson(t,i){return this.writeFile(t,JSON.stringify(i,null,2))}readFile(t,i){return s.readFile(this.getPath(t),i)}async[Symbol.asyncDispose](){await this.rm()}}const g=y.realpathSync(m.tmpdir()),b=`fs-fixture-${Date.now()}`;let l=0;const F=()=>(l+=1,l);class h{target;path;constructor(t){this.target=t}}const p=(r,t,i)=>{const e=[];for(const u in r){if(!Object.hasOwn(r,u))continue;const o=n.join(t,u);let a=r[u];if(typeof a=="function"){const f=Object.assign(Object.create(i),{filePath:o}),c=a(f);if(c instanceof h){c.path=o,e.push(c);continue}else a=c}typeof a=="string"?e.push({path:o,content:a}):e.push(...p(a,o,i))}return e},P=async r=>{const t=n.join(g,`${b}-${F()}/`);if(await s.mkdir(t,{recursive:!0}),r){if(typeof r=="string")await s.cp(r,t,{recursive:!0});else if(typeof r=="object"){const i={fixturePath:t,getPath:e=>n.join(t,e),symlink:e=>new h(e)};await Promise.all(p(r,t,i).map(async e=>{await s.mkdir(n.dirname(e.path),{recursive:!0}),e instanceof h?await s.symlink(e.target,e.path):await s.writeFile(e.path,e.content)}))}}return new w(t)};exports.createFixture=P;
package/dist/index.d.cts CHANGED
@@ -2,7 +2,7 @@ declare class FsFixture {
2
2
  /**
3
3
  Path to the fixture directory.
4
4
  */
5
- path: string;
5
+ readonly path: string;
6
6
  /**
7
7
  Create a Fixture instance from a path. Does not create the fixture directory.
8
8
  */
@@ -30,7 +30,8 @@ declare class FsFixture {
30
30
  /**
31
31
  Read a file from the fixture directory.
32
32
  */
33
- readFile(filePath: string, encoding?: BufferEncoding): Promise<string | Buffer>;
33
+ readFile(filePath: string, encoding?: null): Promise<Buffer>;
34
+ readFile(filePath: string, encoding: BufferEncoding): Promise<string>;
34
35
  /**
35
36
  * Resource management cleanup
36
37
  * https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html
@@ -38,8 +39,21 @@ declare class FsFixture {
38
39
  [Symbol.asyncDispose](): Promise<void>;
39
40
  }
40
41
 
42
+ declare class Symlink {
43
+ target: string;
44
+ path?: string;
45
+ constructor(target: string);
46
+ }
47
+ type ApiBase = {
48
+ fixturePath: string;
49
+ getPath(subpath: string): string;
50
+ symlink(targetPath: string): Symlink;
51
+ };
52
+ type Api = ApiBase & {
53
+ filePath: string;
54
+ };
41
55
  type FileTree = {
42
- [path: string]: string | FileTree;
56
+ [path: string]: string | FileTree | ((api: Api) => string | Symlink);
43
57
  };
44
58
  declare const createFixture: (source?: string | FileTree) => Promise<FsFixture>;
45
59
 
package/dist/index.d.mts CHANGED
@@ -2,7 +2,7 @@ declare class FsFixture {
2
2
  /**
3
3
  Path to the fixture directory.
4
4
  */
5
- path: string;
5
+ readonly path: string;
6
6
  /**
7
7
  Create a Fixture instance from a path. Does not create the fixture directory.
8
8
  */
@@ -30,7 +30,8 @@ declare class FsFixture {
30
30
  /**
31
31
  Read a file from the fixture directory.
32
32
  */
33
- readFile(filePath: string, encoding?: BufferEncoding): Promise<string | Buffer>;
33
+ readFile(filePath: string, encoding?: null): Promise<Buffer>;
34
+ readFile(filePath: string, encoding: BufferEncoding): Promise<string>;
34
35
  /**
35
36
  * Resource management cleanup
36
37
  * https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html
@@ -38,8 +39,21 @@ declare class FsFixture {
38
39
  [Symbol.asyncDispose](): Promise<void>;
39
40
  }
40
41
 
42
+ declare class Symlink {
43
+ target: string;
44
+ path?: string;
45
+ constructor(target: string);
46
+ }
47
+ type ApiBase = {
48
+ fixturePath: string;
49
+ getPath(subpath: string): string;
50
+ symlink(targetPath: string): Symlink;
51
+ };
52
+ type Api = ApiBase & {
53
+ filePath: string;
54
+ };
41
55
  type FileTree = {
42
- [path: string]: string | FileTree;
56
+ [path: string]: string | FileTree | ((api: Api) => string | Symlink);
43
57
  };
44
58
  declare const createFixture: (source?: string | FileTree) => Promise<FsFixture>;
45
59
 
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import i from"fs/promises";import s from"path";import l from"fs";import f from"os";typeof Symbol.asyncDispose!="symbol"&&Object.defineProperty(Symbol,"asyncDispose",{configurable:!1,enumerable:!1,writable:!1,value:Symbol.for("asyncDispose")});class p{path;constructor(t){this.path=t}getPath(t){return s.join(this.path,t)}exists(t=""){return i.access(this.getPath(t)).then(()=>!0,()=>!1)}rm(t=""){return i.rm(this.getPath(t),{recursive:!0,force:!0})}writeFile(t,e){return i.writeFile(this.getPath(t),e)}writeJson(t,e){return this.writeFile(t,JSON.stringify(e,null,2))}readFile(t,e){return i.readFile(this.getPath(t),e)}async[Symbol.asyncDispose](){await this.rm()}}const u=l.realpathSync(f.tmpdir()),h=`fs-fixture-${Date.now()}`;let o=0;const m=()=>(o+=1,o),c=(r,t)=>{const e=[];for(const a in r){if(!Object.hasOwn(r,a))continue;const n=r[a];typeof n=="string"?e.push({path:s.join(t,a),content:n}):e.push(...c(n,s.join(t,a)))}return e},y=async r=>{const t=s.join(u,`${h}-${m()}`);return await i.mkdir(t,{recursive:!0}),r&&(typeof r=="string"?await i.cp(r,t,{recursive:!0}):typeof r=="object"&&await Promise.all(c(r,t).map(async e=>{await i.mkdir(s.dirname(e.path),{recursive:!0}),await i.writeFile(e.path,e.content)}))),new p(t)};export{y as createFixture};
1
+ import s from"fs/promises";import n from"path";import m from"fs";import y from"os";typeof Symbol.asyncDispose!="symbol"&&Object.defineProperty(Symbol,"asyncDispose",{configurable:!1,enumerable:!1,writable:!1,value:Symbol.for("asyncDispose")});class w{path;constructor(t){this.path=t}getPath(t){return n.join(this.path,t)}exists(t=""){return s.access(this.getPath(t)).then(()=>!0,()=>!1)}rm(t=""){return s.rm(this.getPath(t),{recursive:!0,force:!0})}writeFile(t,i){return s.writeFile(this.getPath(t),i)}writeJson(t,i){return this.writeFile(t,JSON.stringify(i,null,2))}readFile(t,i){return s.readFile(this.getPath(t),i)}async[Symbol.asyncDispose](){await this.rm()}}const g=m.realpathSync(y.tmpdir()),b=`fs-fixture-${Date.now()}`;let l=0;const P=()=>(l+=1,l);class h{target;path;constructor(t){this.target=t}}const f=(r,t,i)=>{const e=[];for(const p in r){if(!Object.hasOwn(r,p))continue;const o=n.join(t,p);let a=r[p];if(typeof a=="function"){const u=Object.assign(Object.create(i),{filePath:o}),c=a(u);if(c instanceof h){c.path=o,e.push(c);continue}else a=c}typeof a=="string"?e.push({path:o,content:a}):e.push(...f(a,o,i))}return e},d=async r=>{const t=n.join(g,`${b}-${P()}/`);if(await s.mkdir(t,{recursive:!0}),r){if(typeof r=="string")await s.cp(r,t,{recursive:!0});else if(typeof r=="object"){const i={fixturePath:t,getPath:e=>n.join(t,e),symlink:e=>new h(e)};await Promise.all(f(r,t,i).map(async e=>{await s.mkdir(n.dirname(e.path),{recursive:!0}),e instanceof h?await s.symlink(e.target,e.path):await s.writeFile(e.path,e.content)}))}}return new w(t)};export{d as createFixture};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fs-fixture",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
4
  "description": "Easily create test fixtures at a temporary file-system path",
5
5
  "keywords": [
6
6
  "test",