fs-fixture 2.12.0 → 2.13.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 +56 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +72 -4
- package/dist/index.d.mts +72 -4
- package/dist/index.mjs +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -17,6 +17,7 @@ Simple API to create disposable test fixtures on disk. Tiny (`1.1 kB` gzipped) w
|
|
|
17
17
|
- 💾 Binary file support with Buffers
|
|
18
18
|
- 🎯 TypeScript-first with full type safety
|
|
19
19
|
- 🔄 File methods inherit types directly from Node.js `fs` module
|
|
20
|
+
- 🔌 Pluggable filesystem — use with @platformatic/vfs, memfs, or any `fs/promises`-compatible API
|
|
20
21
|
|
|
21
22
|
## Installation
|
|
22
23
|
|
|
@@ -185,6 +186,31 @@ const fixture = await createFixture({
|
|
|
185
186
|
})
|
|
186
187
|
```
|
|
187
188
|
|
|
189
|
+
### Custom filesystem
|
|
190
|
+
|
|
191
|
+
Pass any `fs/promises`-compatible API via the `fs` option to use a virtual filesystem instead of disk:
|
|
192
|
+
|
|
193
|
+
```ts
|
|
194
|
+
import { create, MemoryProvider } from '@platformatic/vfs'
|
|
195
|
+
import { createFixture } from 'fs-fixture'
|
|
196
|
+
|
|
197
|
+
const fs = create(new MemoryProvider()).promises
|
|
198
|
+
const fixture = await createFixture({
|
|
199
|
+
'package.json': JSON.stringify({ name: 'test' }),
|
|
200
|
+
'src/index.js': 'export default 42'
|
|
201
|
+
}, { fs })
|
|
202
|
+
|
|
203
|
+
await fixture.readFile('src/index.js', 'utf8') // 'export default 42'
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Works with any library that implements the `fs/promises` API shape, including [@platformatic/vfs](https://github.com/platformatic/vfs), the future [`node:vfs`](https://github.com/nodejs/node/pull/61478), and [memfs](https://github.com/streamich/memfs).
|
|
207
|
+
|
|
208
|
+
> [!NOTE]
|
|
209
|
+
> With a custom fs, files only exist in that fs instance. Use `fixture.readFile()` or `fixture.fs` to access them — `fixture.path` is a virtual path that doesn't exist on the real disk.
|
|
210
|
+
|
|
211
|
+
> [!NOTE]
|
|
212
|
+
> Template directory sources (string paths) are not supported with custom filesystems because most virtual fs implementations lack recursive `cp`. Use a `FileTree` object instead.
|
|
213
|
+
|
|
188
214
|
## API
|
|
189
215
|
|
|
190
216
|
### `createFixture(source?, options?)`
|
|
@@ -195,6 +221,7 @@ Creates a temporary fixture directory and returns a `FsFixture` instance.
|
|
|
195
221
|
- `source` (optional): String path to template directory, or `FileTree` object defining the structure
|
|
196
222
|
- `options.tempDir` (optional): Custom temp directory. Defaults to `os.tmpdir()`
|
|
197
223
|
- `options.templateFilter` (optional): Filter function when copying from template directory
|
|
224
|
+
- `options.fs` (optional): Custom `fs/promises`-compatible API for virtual filesystem support
|
|
198
225
|
|
|
199
226
|
**Returns:** `Promise<FsFixture>`
|
|
200
227
|
|
|
@@ -210,6 +237,7 @@ const fixture = await createFixture({}, { tempDir: './custom-temp' })
|
|
|
210
237
|
| Method | Description |
|
|
211
238
|
|--------|-------------|
|
|
212
239
|
| `fixture.path` | Absolute path to the fixture directory |
|
|
240
|
+
| `fixture.fs` | The underlying `fs/promises` API used by the fixture |
|
|
213
241
|
| `getPath(...paths)` | Get absolute path to file/directory in fixture |
|
|
214
242
|
| `exists(path?)` | Check if file/directory exists |
|
|
215
243
|
| `rm(path?)` | Delete file/directory (or entire fixture if no path) |
|
|
@@ -241,6 +269,34 @@ type Api = {
|
|
|
241
269
|
```
|
|
242
270
|
</details>
|
|
243
271
|
|
|
272
|
+
<details>
|
|
273
|
+
<summary><strong>FsPromises</strong></summary>
|
|
274
|
+
|
|
275
|
+
The subset of `fs/promises` methods that custom filesystem implementations must provide:
|
|
276
|
+
|
|
277
|
+
```ts
|
|
278
|
+
type FsPromises = {
|
|
279
|
+
// Required
|
|
280
|
+
readFile(path: string, options?): Promise<Buffer | string>
|
|
281
|
+
writeFile(path: string, data: string | Buffer, options?): Promise<void>
|
|
282
|
+
readdir(path: string, options?): Promise<string[] | Dirent[]>
|
|
283
|
+
mkdir(path: string, options?): Promise<string | undefined>
|
|
284
|
+
rename(oldPath: string, newPath: string): Promise<void>
|
|
285
|
+
access(path: string, mode?: number): Promise<void>
|
|
286
|
+
|
|
287
|
+
// Optional
|
|
288
|
+
rm?(path: string, options?): Promise<void>
|
|
289
|
+
unlink?(path: string): Promise<void>
|
|
290
|
+
rmdir?(path: string): Promise<void>
|
|
291
|
+
symlink?(target: string, path: string, type?: string): Promise<void>
|
|
292
|
+
cp?(source: string, destination: string, options?): Promise<void>
|
|
293
|
+
mkdtemp?(prefix: string): Promise<string>
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
If `rm` is not available, fs-fixture falls back to recursive removal using `readdir({ withFileTypes })` + `unlink` + `rmdir`. If `mkdtemp` is not available, fixture paths are generated with a counter.
|
|
298
|
+
</details>
|
|
299
|
+
|
|
244
300
|
## Related
|
|
245
301
|
|
|
246
302
|
### [manten](https://github.com/privatenumber/manten)
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var v=Object.defineProperty;var o=(r,e)=>v(r,"name",{value:e,configurable:!0});var y=require("node:fs/promises"),c=require("node:path"),F=require("node:url"),b=require("node:fs"),j=require("node:os");const w=o(async(r,e)=>{try{await r.unlink(e);return}catch(i){if(D(i))return}const t=await r.readdir(e,{withFileTypes:!0});await Promise.all(t.map(i=>{const n=c.join(e,i.name);return i.isDirectory()?w(r,n):r.unlink(n)})),await r.rmdir(e)},"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(e,t){this.path=e,this.fs=t??y}getPath(...e){return c.join(this.path,...e)}exists(e=""){return this.fs.access(this.getPath(e)).then(()=>!0,()=>!1)}rm(e=""){const t=this.getPath(e);if(this.fs.rm)return this.fs.rm(t,{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,t)}cp(e,t,i){if(!this.fs.cp)throw new Error("cp() requires the fs API to support cp()");return t?(t.endsWith("/")||t.endsWith(c.sep))&&(t+=c.basename(e)):t=c.basename(e),this.fs.cp(e,this.getPath(t),i)}mkdir(e){return this.fs.mkdir(this.getPath(e),{recursive:!0})}mv(e,t){return this.fs.rename(this.getPath(e),this.getPath(t))}readFile=o(((e,t)=>this.fs.readFile(this.getPath(e),t)),"readFile");readdir=o(((e,t)=>this.fs.readdir(this.getPath(e||""),t)),"readdir");writeFile=o(((e,t,...i)=>this.fs.writeFile(this.getPath(e),t,...i)),"writeFile");async readJson(e){const t=await this.readFile(e,"utf8");return JSON.parse(t)}writeJson(e,t,i=2){return this.writeFile(e,JSON.stringify(t,null,i))}async[Symbol.asyncDispose](){await this.rm()}}const T=b.realpathSync(j.tmpdir());class m{static{o(this,"PathBase")}path;constructor(e){this.path=e}}class d extends m{static{o(this,"Directory")}}class p extends m{static{o(this,"File")}content;constructor(e,t){super(e),this.content=t}}class h extends m{static{o(this,"Symlink")}target;type;constructor(e,t,i){super(i??""),this.target=e,this.type=t}}const g=o((r,e,t)=>{const i=[];for(const n in r){if(!Object.hasOwn(r,n))continue;const f=c.join(e,n);let a=r[n];if(typeof a=="function"){const l=Object.assign(Object.create(t),{filePath:f}),u=a(l);if(u instanceof h){const s=new h(u.target,u.type,f);i.push(s);continue}else a=u}if(typeof a=="string"||Buffer.isBuffer(a))i.push(new p(f,a));else if(a&&typeof a=="object"&&!Array.isArray(a))i.push(new d(f),...g(a,f,t));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 q=o(async(r,e)=>{const t=e?.fs??y,i=e?.tempDir?c.resolve(typeof e.tempDir=="string"?e.tempDir:F.fileURLToPath(e.tempDir)):T;e?.tempDir&&await t.mkdir(i,{recursive:!0});let n;if(t.mkdtemp?n=await t.mkdtemp(c.join(i,"fs-fixture-")):(k+=1,n=c.join(i,`fs-fixture-${process.pid}-${k}`),await t.mkdir(n,{recursive:!0})),r){if(typeof r=="string"){if(!t.cp)throw new TypeError("Template directory sources require the fs API to support cp()");await t.cp(r,n,{recursive:!0,filter:e?.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 p||s instanceof h)&&l.add(c.dirname(s.path));if(await Promise.all(Array.from(l).map(s=>t.mkdir(s,{recursive:!0}))),a.some(s=>s instanceof h)&&!t.symlink)throw new TypeError("Symlinks require the fs API to support symlink()");await Promise.all(a.map(async s=>{s instanceof h?await t.symlink(s.target,s.path,s.type):s instanceof p&&await t.writeFile(s.path,s.content)}))}}return new x(n,e?.fs)},"createFixture");exports.createFixture=q;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,17 +1,69 @@
|
|
|
1
1
|
import { CopyOptions } from 'node:fs';
|
|
2
2
|
import fs from 'node:fs/promises';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* A subset of `fs/promises` methods used by FsFixture.
|
|
6
|
+
* Compatible with Node.js `fs/promises`, `@platformatic/vfs`,
|
|
7
|
+
* `memfs`, and other fs-compatible implementations.
|
|
8
|
+
*
|
|
9
|
+
* Pass a custom implementation to `createFixture({ fs })`
|
|
10
|
+
* to use a virtual filesystem.
|
|
11
|
+
*/
|
|
12
|
+
type FsPromises = {
|
|
13
|
+
readFile: {
|
|
14
|
+
(path: string, options?: {
|
|
15
|
+
encoding?: null;
|
|
16
|
+
} | null): Promise<Buffer>;
|
|
17
|
+
(path: string, options: BufferEncoding | {
|
|
18
|
+
encoding: BufferEncoding;
|
|
19
|
+
}): Promise<string>;
|
|
20
|
+
};
|
|
21
|
+
writeFile(path: string, data: string | Buffer, options?: BufferEncoding | {
|
|
22
|
+
encoding?: BufferEncoding;
|
|
23
|
+
} | null): Promise<void>;
|
|
24
|
+
readdir: {
|
|
25
|
+
(path: string, options?: {
|
|
26
|
+
withFileTypes?: false;
|
|
27
|
+
}): Promise<string[]>;
|
|
28
|
+
(path: string, options: {
|
|
29
|
+
withFileTypes: true;
|
|
30
|
+
}): Promise<Array<{
|
|
31
|
+
name: string;
|
|
32
|
+
isFile(): boolean;
|
|
33
|
+
isDirectory(): boolean;
|
|
34
|
+
}>>;
|
|
35
|
+
};
|
|
36
|
+
mkdir(path: string, options?: {
|
|
37
|
+
recursive?: boolean;
|
|
38
|
+
}): Promise<string | undefined>;
|
|
39
|
+
rename(oldPath: string, newPath: string): Promise<void>;
|
|
40
|
+
access(path: string, mode?: number): Promise<void>;
|
|
41
|
+
rm?(path: string, options?: {
|
|
42
|
+
recursive?: boolean;
|
|
43
|
+
force?: boolean;
|
|
44
|
+
}): Promise<void>;
|
|
45
|
+
unlink?(path: string): Promise<void>;
|
|
46
|
+
rmdir?(path: string): Promise<void>;
|
|
47
|
+
symlink?(target: string, path: string, type?: string | null): Promise<void>;
|
|
48
|
+
cp?(source: string, destination: string, options?: {
|
|
49
|
+
recursive?: boolean;
|
|
50
|
+
}): Promise<void>;
|
|
51
|
+
mkdtemp?(prefix: string): Promise<string>;
|
|
52
|
+
};
|
|
53
|
+
|
|
4
54
|
declare class FsFixture {
|
|
5
55
|
/**
|
|
6
56
|
* Path to the fixture directory.
|
|
7
57
|
*/
|
|
8
58
|
readonly path: string;
|
|
59
|
+
readonly fs: FsPromises;
|
|
9
60
|
/**
|
|
10
61
|
* Create a Fixture instance from a path. Does not create the fixture directory.
|
|
11
62
|
*
|
|
12
63
|
* @param fixturePath - The path to the fixture directory
|
|
64
|
+
* @param fsApi - Optional fs/promises-compatible API. Defaults to real node:fs/promises.
|
|
13
65
|
*/
|
|
14
|
-
constructor(fixturePath: string);
|
|
66
|
+
constructor(fixturePath: string, fsApi?: FsPromises);
|
|
15
67
|
/**
|
|
16
68
|
* Get the full path to a subpath in the fixture directory.
|
|
17
69
|
*
|
|
@@ -160,8 +212,8 @@ declare class PathBase {
|
|
|
160
212
|
type SymlinkType = 'file' | 'dir' | 'junction';
|
|
161
213
|
declare class Symlink extends PathBase {
|
|
162
214
|
readonly target: string;
|
|
163
|
-
readonly type?: SymlinkType
|
|
164
|
-
constructor(target: string, type?: SymlinkType
|
|
215
|
+
readonly type?: SymlinkType;
|
|
216
|
+
constructor(target: string, type?: SymlinkType, filePath?: string);
|
|
165
217
|
}
|
|
166
218
|
|
|
167
219
|
type ApiBase = {
|
|
@@ -196,6 +248,22 @@ type CreateFixtureOptions = {
|
|
|
196
248
|
* Return `true` to copy the item, `false` to ignore it.
|
|
197
249
|
*/
|
|
198
250
|
templateFilter?: FilterFunction;
|
|
251
|
+
/**
|
|
252
|
+
* Custom fs/promises-compatible API for fixture operations.
|
|
253
|
+
* Use this to create fixtures in a virtual filesystem instead of on disk.
|
|
254
|
+
*
|
|
255
|
+
* Required: readFile, writeFile, readdir (with withFileTypes),
|
|
256
|
+
* mkdir, rename, access.
|
|
257
|
+
* Optional: rm (or unlink + rmdir as fallback), symlink, cp, mkdtemp.
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```ts
|
|
261
|
+
* import { create, MemoryProvider } from '@platformatic/vfs'
|
|
262
|
+
* const vfs = create(new MemoryProvider())
|
|
263
|
+
* const fixture = await createFixture({ 'file.txt': 'hi' }, { fs: vfs.promises })
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
fs?: FsPromises;
|
|
199
267
|
};
|
|
200
268
|
/**
|
|
201
269
|
* Create a temporary test fixture directory.
|
|
@@ -229,4 +297,4 @@ type CreateFixtureOptions = {
|
|
|
229
297
|
declare const createFixture: (source?: string | FileTree, options?: CreateFixtureOptions) => Promise<FsFixture>;
|
|
230
298
|
|
|
231
299
|
export { createFixture };
|
|
232
|
-
export type { CreateFixtureOptions, FileTree, FsFixtureType as FsFixture };
|
|
300
|
+
export type { CreateFixtureOptions, FileTree, FsFixtureType as FsFixture, FsPromises };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,17 +1,69 @@
|
|
|
1
1
|
import { CopyOptions } from 'node:fs';
|
|
2
2
|
import fs from 'node:fs/promises';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* A subset of `fs/promises` methods used by FsFixture.
|
|
6
|
+
* Compatible with Node.js `fs/promises`, `@platformatic/vfs`,
|
|
7
|
+
* `memfs`, and other fs-compatible implementations.
|
|
8
|
+
*
|
|
9
|
+
* Pass a custom implementation to `createFixture({ fs })`
|
|
10
|
+
* to use a virtual filesystem.
|
|
11
|
+
*/
|
|
12
|
+
type FsPromises = {
|
|
13
|
+
readFile: {
|
|
14
|
+
(path: string, options?: {
|
|
15
|
+
encoding?: null;
|
|
16
|
+
} | null): Promise<Buffer>;
|
|
17
|
+
(path: string, options: BufferEncoding | {
|
|
18
|
+
encoding: BufferEncoding;
|
|
19
|
+
}): Promise<string>;
|
|
20
|
+
};
|
|
21
|
+
writeFile(path: string, data: string | Buffer, options?: BufferEncoding | {
|
|
22
|
+
encoding?: BufferEncoding;
|
|
23
|
+
} | null): Promise<void>;
|
|
24
|
+
readdir: {
|
|
25
|
+
(path: string, options?: {
|
|
26
|
+
withFileTypes?: false;
|
|
27
|
+
}): Promise<string[]>;
|
|
28
|
+
(path: string, options: {
|
|
29
|
+
withFileTypes: true;
|
|
30
|
+
}): Promise<Array<{
|
|
31
|
+
name: string;
|
|
32
|
+
isFile(): boolean;
|
|
33
|
+
isDirectory(): boolean;
|
|
34
|
+
}>>;
|
|
35
|
+
};
|
|
36
|
+
mkdir(path: string, options?: {
|
|
37
|
+
recursive?: boolean;
|
|
38
|
+
}): Promise<string | undefined>;
|
|
39
|
+
rename(oldPath: string, newPath: string): Promise<void>;
|
|
40
|
+
access(path: string, mode?: number): Promise<void>;
|
|
41
|
+
rm?(path: string, options?: {
|
|
42
|
+
recursive?: boolean;
|
|
43
|
+
force?: boolean;
|
|
44
|
+
}): Promise<void>;
|
|
45
|
+
unlink?(path: string): Promise<void>;
|
|
46
|
+
rmdir?(path: string): Promise<void>;
|
|
47
|
+
symlink?(target: string, path: string, type?: string | null): Promise<void>;
|
|
48
|
+
cp?(source: string, destination: string, options?: {
|
|
49
|
+
recursive?: boolean;
|
|
50
|
+
}): Promise<void>;
|
|
51
|
+
mkdtemp?(prefix: string): Promise<string>;
|
|
52
|
+
};
|
|
53
|
+
|
|
4
54
|
declare class FsFixture {
|
|
5
55
|
/**
|
|
6
56
|
* Path to the fixture directory.
|
|
7
57
|
*/
|
|
8
58
|
readonly path: string;
|
|
59
|
+
readonly fs: FsPromises;
|
|
9
60
|
/**
|
|
10
61
|
* Create a Fixture instance from a path. Does not create the fixture directory.
|
|
11
62
|
*
|
|
12
63
|
* @param fixturePath - The path to the fixture directory
|
|
64
|
+
* @param fsApi - Optional fs/promises-compatible API. Defaults to real node:fs/promises.
|
|
13
65
|
*/
|
|
14
|
-
constructor(fixturePath: string);
|
|
66
|
+
constructor(fixturePath: string, fsApi?: FsPromises);
|
|
15
67
|
/**
|
|
16
68
|
* Get the full path to a subpath in the fixture directory.
|
|
17
69
|
*
|
|
@@ -160,8 +212,8 @@ declare class PathBase {
|
|
|
160
212
|
type SymlinkType = 'file' | 'dir' | 'junction';
|
|
161
213
|
declare class Symlink extends PathBase {
|
|
162
214
|
readonly target: string;
|
|
163
|
-
readonly type?: SymlinkType
|
|
164
|
-
constructor(target: string, type?: SymlinkType
|
|
215
|
+
readonly type?: SymlinkType;
|
|
216
|
+
constructor(target: string, type?: SymlinkType, filePath?: string);
|
|
165
217
|
}
|
|
166
218
|
|
|
167
219
|
type ApiBase = {
|
|
@@ -196,6 +248,22 @@ type CreateFixtureOptions = {
|
|
|
196
248
|
* Return `true` to copy the item, `false` to ignore it.
|
|
197
249
|
*/
|
|
198
250
|
templateFilter?: FilterFunction;
|
|
251
|
+
/**
|
|
252
|
+
* Custom fs/promises-compatible API for fixture operations.
|
|
253
|
+
* Use this to create fixtures in a virtual filesystem instead of on disk.
|
|
254
|
+
*
|
|
255
|
+
* Required: readFile, writeFile, readdir (with withFileTypes),
|
|
256
|
+
* mkdir, rename, access.
|
|
257
|
+
* Optional: rm (or unlink + rmdir as fallback), symlink, cp, mkdtemp.
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```ts
|
|
261
|
+
* import { create, MemoryProvider } from '@platformatic/vfs'
|
|
262
|
+
* const vfs = create(new MemoryProvider())
|
|
263
|
+
* const fixture = await createFixture({ 'file.txt': 'hi' }, { fs: vfs.promises })
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
fs?: FsPromises;
|
|
199
267
|
};
|
|
200
268
|
/**
|
|
201
269
|
* Create a temporary test fixture directory.
|
|
@@ -229,4 +297,4 @@ type CreateFixtureOptions = {
|
|
|
229
297
|
declare const createFixture: (source?: string | FileTree, options?: CreateFixtureOptions) => Promise<FsFixture>;
|
|
230
298
|
|
|
231
299
|
export { createFixture };
|
|
232
|
-
export type { CreateFixtureOptions, FileTree, FsFixtureType as FsFixture };
|
|
300
|
+
export type { CreateFixtureOptions, FileTree, FsFixtureType as FsFixture, FsPromises };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
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};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fs-fixture",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.13.0",
|
|
4
4
|
"description": "Easily create test fixtures at a temporary file-system path",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"test",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"dist",
|
|
24
24
|
"skills"
|
|
25
25
|
],
|
|
26
|
+
"type": "module",
|
|
26
27
|
"main": "./dist/index.cjs",
|
|
27
28
|
"module": "./dist/index.mjs",
|
|
28
29
|
"types": "./dist/index.d.cts",
|