pwd-fs 3.3.5 → 3.5.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.
Files changed (51) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +1 -1
  3. package/dist/powered-file-system/append.d.ts +9 -6
  4. package/dist/powered-file-system/append.js +4 -4
  5. package/dist/powered-file-system/chmod.d.ts +4 -4
  6. package/dist/powered-file-system/chmod.js +9 -10
  7. package/dist/powered-file-system/chown.d.ts +7 -4
  8. package/dist/powered-file-system/chown.js +18 -8
  9. package/dist/powered-file-system/copy.d.ts +10 -5
  10. package/dist/powered-file-system/copy.js +13 -13
  11. package/dist/powered-file-system/copy.test.js +46 -0
  12. package/dist/powered-file-system/empty-dir.d.ts +7 -0
  13. package/dist/powered-file-system/empty-dir.js +27 -0
  14. package/dist/powered-file-system/empty-dir.test.d.ts +1 -0
  15. package/dist/powered-file-system/empty-dir.test.js +61 -0
  16. package/dist/powered-file-system/mkdir.d.ts +9 -6
  17. package/dist/powered-file-system/mkdir.js +9 -10
  18. package/dist/powered-file-system/read.d.ts +10 -6
  19. package/dist/powered-file-system/read.js +9 -5
  20. package/dist/powered-file-system/readdir.d.ts +11 -6
  21. package/dist/powered-file-system/readdir.js +8 -6
  22. package/dist/powered-file-system/readlink.d.ts +13 -0
  23. package/dist/powered-file-system/readlink.js +28 -0
  24. package/dist/powered-file-system/readlink.test.d.ts +1 -0
  25. package/dist/powered-file-system/readlink.test.js +44 -0
  26. package/dist/powered-file-system/realpath.d.ts +13 -0
  27. package/dist/powered-file-system/realpath.js +28 -0
  28. package/dist/powered-file-system/realpath.test.d.ts +1 -0
  29. package/dist/powered-file-system/realpath.test.js +44 -0
  30. package/dist/powered-file-system/remove.d.ts +5 -5
  31. package/dist/powered-file-system/remove.js +11 -20
  32. package/dist/powered-file-system/rename.d.ts +5 -5
  33. package/dist/powered-file-system/rename.js +11 -7
  34. package/dist/powered-file-system/stat.d.ts +4 -4
  35. package/dist/powered-file-system/stat.js +8 -6
  36. package/dist/powered-file-system/symlink.d.ts +4 -4
  37. package/dist/powered-file-system/symlink.js +11 -4
  38. package/dist/powered-file-system/test.d.ts +10 -5
  39. package/dist/powered-file-system/test.js +8 -5
  40. package/dist/powered-file-system/write.d.ts +10 -7
  41. package/dist/powered-file-system/write.js +9 -6
  42. package/dist/powered-file-system.d.ts +117 -47
  43. package/dist/powered-file-system.js +17 -39
  44. package/dist/powered-file-system.test.js +25 -0
  45. package/dist/recurse-io-sync.d.ts +7 -2
  46. package/dist/recurse-io-sync.js +38 -32
  47. package/dist/recurse-io.d.ts +11 -2
  48. package/dist/recurse-io.js +122 -57
  49. package/dist/suite.test.js +1 -1
  50. package/package.json +11 -16
  51. package/readme.md +133 -12
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { PoweredFileSystem } from './powered-file-system';
2
2
  /**
3
- * Default file system instance rooted at the current working directory.
3
+ * Default file system instance using the current working directory as its base.
4
4
  */
5
5
  export declare const pfs: PoweredFileSystem;
6
6
  export default PoweredFileSystem;
package/dist/index.js CHANGED
@@ -17,7 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.pfs = void 0;
18
18
  const powered_file_system_1 = require("./powered-file-system");
19
19
  /**
20
- * Default file system instance rooted at the current working directory.
20
+ * Default file system instance using the current working directory as its base.
21
21
  */
22
22
  exports.pfs = new powered_file_system_1.PoweredFileSystem();
23
23
  exports.default = powered_file_system_1.PoweredFileSystem;
@@ -1,9 +1,12 @@
1
- import type { PoweredFileSystem } from '../powered-file-system';
1
+ import type { AsyncOption, MaybeSyncOption, PoweredFileSystem, SyncOption } from '../powered-file-system';
2
+ type AppendOptions = {
3
+ encoding?: BufferEncoding | null;
4
+ umask?: number;
5
+ };
2
6
  /**
3
7
  * Backward-compatible append wrapper implemented on top of `write()`.
4
8
  */
5
- export declare function append<T extends boolean = false>(this: PoweredFileSystem, src: string, data: Buffer | string, options?: {
6
- sync?: T;
7
- encoding?: BufferEncoding | null;
8
- umask?: number;
9
- }): T extends true ? void : Promise<void>;
9
+ export declare function append(this: PoweredFileSystem, src: string, data: Buffer | string, options: SyncOption & AppendOptions): void;
10
+ export declare function append(this: PoweredFileSystem, src: string, data: Buffer | string, options?: AsyncOption & AppendOptions): Promise<void>;
11
+ export declare function append(this: PoweredFileSystem, src: string, data: Buffer | string, options?: MaybeSyncOption & AppendOptions): void | Promise<void>;
12
+ export {};
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.append = append;
4
- /**
5
- * Backward-compatible append wrapper implemented on top of `write()`.
6
- */
7
4
  function append(src, data, options) {
8
5
  const { sync = false, encoding = 'utf8', umask = 0o000 } = options ?? {};
9
- return this.write(src, data, { sync, encoding, umask, flag: 'a' });
6
+ if (sync) {
7
+ return this.write(src, data, { sync: true, encoding, umask, flag: 'a' });
8
+ }
9
+ return this.write(src, data, { encoding, umask, flag: 'a' });
10
10
  }
@@ -1,7 +1,7 @@
1
- import type { PoweredFileSystem } from '../powered-file-system';
1
+ import type { AsyncOption, MaybeSyncOption, PoweredFileSystem, SyncOption } from '../powered-file-system';
2
2
  /**
3
3
  * Resolves the target path and delegates recursive mode updates.
4
4
  */
5
- export declare function chmod<T extends boolean = false>(this: PoweredFileSystem, src: string, mode: number, options?: {
6
- sync?: T;
7
- }): T extends true ? void : Promise<void>;
5
+ export declare function chmod(this: PoweredFileSystem, src: string, mode: number, options: SyncOption): void;
6
+ export declare function chmod(this: PoweredFileSystem, src: string, mode: number, options?: AsyncOption): Promise<void>;
7
+ export declare function chmod(this: PoweredFileSystem, src: string, mode: number, options?: MaybeSyncOption): void | Promise<void>;
@@ -1,23 +1,22 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.chmod = chmod;
7
- const node_path_1 = __importDefault(require("node:path"));
8
4
  const recurse_io_1 = require("../recurse-io");
9
5
  const recurse_io_sync_1 = require("../recurse-io-sync");
10
- /**
11
- * Resolves the target path and delegates recursive mode updates.
12
- */
13
6
  function chmod(src, mode, options) {
14
7
  const { sync = false } = options ?? {};
15
- src = node_path_1.default.resolve(this.pwd, src);
16
8
  if (sync) {
17
- (0, recurse_io_sync_1.chmodSync)(src, mode);
18
- return undefined;
9
+ (0, recurse_io_sync_1.chmodSync)(this.resolve(src), mode);
10
+ return;
19
11
  }
20
12
  return new Promise((resolve, reject) => {
13
+ try {
14
+ src = this.resolve(src);
15
+ }
16
+ catch (err) {
17
+ reject(err);
18
+ return;
19
+ }
21
20
  (0, recurse_io_1.chmod)(src, mode, (err) => {
22
21
  if (err) {
23
22
  return reject(err);
@@ -1,9 +1,12 @@
1
- import type { PoweredFileSystem } from '../powered-file-system';
1
+ import type { AsyncOption, MaybeSyncOption, PoweredFileSystem, SyncOption } from '../powered-file-system';
2
2
  /**
3
3
  * Resolves the target path and applies recursive ownership changes where supported.
4
4
  */
5
- export declare function chown<T extends boolean = false>(this: PoweredFileSystem, src: string, options?: {
6
- sync?: T;
5
+ type ChownOptions = {
7
6
  uid?: number;
8
7
  gid?: number;
9
- }): T extends true ? void : Promise<void>;
8
+ };
9
+ export declare function chown(this: PoweredFileSystem, src: string, options: SyncOption & ChownOptions): void;
10
+ export declare function chown(this: PoweredFileSystem, src: string, options?: AsyncOption & ChownOptions): Promise<void>;
11
+ export declare function chown(this: PoweredFileSystem, src: string, options?: MaybeSyncOption & ChownOptions): void | Promise<void>;
12
+ export {};
@@ -5,26 +5,29 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.chown = chown;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
- const node_path_1 = __importDefault(require("node:path"));
9
8
  const recurse_io_1 = require("../recurse-io");
10
9
  const recurse_io_sync_1 = require("../recurse-io-sync");
11
- /**
12
- * Resolves the target path and applies recursive ownership changes where supported.
13
- */
14
10
  function chown(src, options) {
15
- const { sync = false, uid = 0, gid = 0 } = options ?? {};
16
- src = node_path_1.default.resolve(this.pwd, src);
11
+ const { sync = false, uid, gid } = options ?? {};
17
12
  if (sync) {
13
+ src = this.resolve(src);
18
14
  if (process.platform === 'win32') {
19
15
  // Windows does not expose POSIX ownership changes; keep existence checks consistent.
20
16
  node_fs_1.default.lstatSync(src);
21
- return undefined;
17
+ return;
22
18
  }
23
19
  (0, recurse_io_sync_1.chownSync)(src, uid, gid);
24
- return undefined;
20
+ return;
25
21
  }
26
22
  if (process.platform === 'win32') {
27
23
  return new Promise((resolve, reject) => {
24
+ try {
25
+ src = this.resolve(src);
26
+ }
27
+ catch (err) {
28
+ reject(err);
29
+ return;
30
+ }
28
31
  // Match Unix behavior by validating the path even when ownership cannot be changed.
29
32
  node_fs_1.default.lstat(src, (err) => {
30
33
  if (err) {
@@ -35,6 +38,13 @@ function chown(src, options) {
35
38
  });
36
39
  }
37
40
  return new Promise((resolve, reject) => {
41
+ try {
42
+ src = this.resolve(src);
43
+ }
44
+ catch (err) {
45
+ reject(err);
46
+ return;
47
+ }
38
48
  (0, recurse_io_1.chown)(src, uid, gid, (err) => {
39
49
  if (err) {
40
50
  return reject(err);
@@ -1,8 +1,13 @@
1
- import type { PoweredFileSystem } from '../powered-file-system';
1
+ import type { AsyncOption, CopyFilter, MaybeSyncOption, PoweredFileSystem, SyncOption } from '../powered-file-system';
2
+ type CopyOptions = {
3
+ umask?: number;
4
+ overwrite?: boolean;
5
+ filter?: CopyFilter;
6
+ };
2
7
  /**
3
8
  * Resolves source and destination paths before delegating recursive copy work.
4
9
  */
5
- export declare function copy<T extends boolean = false>(this: PoweredFileSystem, src: string, dest: string, options?: {
6
- sync?: T;
7
- umask?: number;
8
- }): T extends true ? void : Promise<void>;
10
+ export declare function copy(this: PoweredFileSystem, src: string, dest: string, options: SyncOption & CopyOptions): void;
11
+ export declare function copy(this: PoweredFileSystem, src: string, dest: string, options?: AsyncOption & CopyOptions): Promise<void>;
12
+ export declare function copy(this: PoweredFileSystem, src: string, dest: string, options?: MaybeSyncOption & CopyOptions): void | Promise<void>;
13
+ export {};
@@ -1,25 +1,25 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.copy = copy;
7
- const node_path_1 = __importDefault(require("node:path"));
8
4
  const recurse_io_1 = require("../recurse-io");
9
5
  const recurse_io_sync_1 = require("../recurse-io-sync");
10
- /**
11
- * Resolves source and destination paths before delegating recursive copy work.
12
- */
13
6
  function copy(src, dest, options) {
14
- src = node_path_1.default.resolve(this.pwd, src);
15
- dest = node_path_1.default.resolve(this.pwd, dest);
16
- const { sync = false, umask = 0o000 } = options ?? {};
7
+ const { sync = false, umask = 0o000, overwrite = false, filter } = options ?? {};
8
+ const copyOptions = filter ? { umask, overwrite, filter } : { umask, overwrite };
17
9
  if (sync) {
18
- (0, recurse_io_sync_1.copySync)(src, dest, umask);
19
- return undefined;
10
+ (0, recurse_io_sync_1.copySync)(this.resolve(src), this.resolve(dest), copyOptions);
11
+ return;
20
12
  }
21
13
  return new Promise((resolve, reject) => {
22
- (0, recurse_io_1.copy)(src, dest, umask, (err) => {
14
+ try {
15
+ src = this.resolve(src);
16
+ dest = this.resolve(dest);
17
+ }
18
+ catch (err) {
19
+ reject(err);
20
+ return;
21
+ }
22
+ (0, recurse_io_1.copy)(src, dest, copyOptions, (err) => {
23
23
  if (err) {
24
24
  return reject(err);
25
25
  }
@@ -50,6 +50,28 @@ const test_utils_1 = require("../test-utils");
50
50
  await index_1.pfs.copy(tmpDir, node_path_1.default.dirname(tmpDir));
51
51
  });
52
52
  });
53
+ (0, node_test_1.it)('Positive: Overwrite should replace an existing target file', async () => {
54
+ node_fs_1.default.writeFileSync(node_path_1.default.join(tmpDir, 'digest', 'tings.txt'), 'old');
55
+ await index_1.pfs.copy(node_path_1.default.join(tmpDir, 'tings.txt'), node_path_1.default.join(tmpDir, 'digest'), {
56
+ overwrite: true
57
+ });
58
+ const content = node_fs_1.default.readFileSync(node_path_1.default.join(tmpDir, 'digest', 'tings.txt'), 'utf8');
59
+ (0, node_assert_1.default)(content !== 'old');
60
+ });
61
+ (0, node_test_1.it)('Positive: Filter should skip matching entries', async () => {
62
+ const destRoot = (0, test_utils_1.createTmpDir)();
63
+ try {
64
+ await index_1.pfs.copy(tmpDir, destRoot, {
65
+ overwrite: true,
66
+ filter: (src) => node_path_1.default.basename(src) !== 'tings.txt'
67
+ });
68
+ (0, node_assert_1.default)(node_fs_1.default.existsSync(node_path_1.default.join(destRoot, node_path_1.default.basename(tmpDir), 'digest')));
69
+ (0, node_assert_1.default)(node_fs_1.default.existsSync(node_path_1.default.join(destRoot, node_path_1.default.basename(tmpDir), 'tings.txt')) === false);
70
+ }
71
+ finally {
72
+ (0, test_utils_1.restore)(destRoot);
73
+ }
74
+ });
53
75
  (0, node_test_1.it)('[sync] Positive: Copying a file', () => {
54
76
  index_1.pfs.copy(node_path_1.default.join(tmpDir, 'tings.txt'), node_path_1.default.join(tmpDir, 'digest'), {
55
77
  sync: true
@@ -79,4 +101,28 @@ const test_utils_1 = require("../test-utils");
79
101
  });
80
102
  });
81
103
  });
104
+ (0, node_test_1.it)('[sync] Positive: Overwrite should replace an existing target file', () => {
105
+ node_fs_1.default.writeFileSync(node_path_1.default.join(tmpDir, 'digest', 'tings.txt'), 'old');
106
+ index_1.pfs.copy(node_path_1.default.join(tmpDir, 'tings.txt'), node_path_1.default.join(tmpDir, 'digest'), {
107
+ sync: true,
108
+ overwrite: true
109
+ });
110
+ const content = node_fs_1.default.readFileSync(node_path_1.default.join(tmpDir, 'digest', 'tings.txt'), 'utf8');
111
+ (0, node_assert_1.default)(content !== 'old');
112
+ });
113
+ (0, node_test_1.it)('[sync] Positive: Filter should skip matching entries', () => {
114
+ const destRoot = (0, test_utils_1.createTmpDir)();
115
+ try {
116
+ index_1.pfs.copy(tmpDir, destRoot, {
117
+ sync: true,
118
+ overwrite: true,
119
+ filter: (src) => node_path_1.default.basename(src) !== 'tings.txt'
120
+ });
121
+ (0, node_assert_1.default)(node_fs_1.default.existsSync(node_path_1.default.join(destRoot, node_path_1.default.basename(tmpDir), 'digest')));
122
+ (0, node_assert_1.default)(node_fs_1.default.existsSync(node_path_1.default.join(destRoot, node_path_1.default.basename(tmpDir), 'tings.txt')) === false);
123
+ }
124
+ finally {
125
+ (0, test_utils_1.restore)(destRoot);
126
+ }
127
+ });
82
128
  });
@@ -0,0 +1,7 @@
1
+ import type { AsyncOption, MaybeSyncOption, PoweredFileSystem, SyncOption } from '../powered-file-system';
2
+ /**
3
+ * Removes directory contents while preserving the directory itself.
4
+ */
5
+ export declare function emptyDir(this: PoweredFileSystem, src: string, options: SyncOption): void;
6
+ export declare function emptyDir(this: PoweredFileSystem, src: string, options?: AsyncOption): Promise<void>;
7
+ export declare function emptyDir(this: PoweredFileSystem, src: string, options?: MaybeSyncOption): void | Promise<void>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.emptyDir = emptyDir;
4
+ const recurse_io_1 = require("../recurse-io");
5
+ const recurse_io_sync_1 = require("../recurse-io-sync");
6
+ function emptyDir(src, options) {
7
+ const { sync = false } = options ?? {};
8
+ if (sync) {
9
+ (0, recurse_io_sync_1.emptyDirSync)(this.resolve(src));
10
+ return;
11
+ }
12
+ return new Promise((resolve, reject) => {
13
+ try {
14
+ src = this.resolve(src);
15
+ }
16
+ catch (err) {
17
+ reject(err);
18
+ return;
19
+ }
20
+ (0, recurse_io_1.emptyDir)(src, (err) => {
21
+ if (err) {
22
+ return reject(err);
23
+ }
24
+ resolve();
25
+ });
26
+ });
27
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_assert_1 = __importDefault(require("node:assert"));
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const chance_1 = __importDefault(require("chance"));
10
+ const node_test_1 = require("node:test");
11
+ const index_1 = require("../index");
12
+ const test_utils_1 = require("../test-utils");
13
+ /**
14
+ * Verifies directory cleanup while preserving the directory itself.
15
+ */
16
+ (0, node_test_1.describe)('emptyDir(src [, options])', () => {
17
+ const chance = new chance_1.default();
18
+ let tmpDir = '';
19
+ (0, node_test_1.beforeEach)(() => {
20
+ tmpDir = (0, test_utils_1.createTmpDir)();
21
+ const frame = {
22
+ [node_path_1.default.join(tmpDir, 'tings.txt')]: {
23
+ type: 'file',
24
+ data: chance.string()
25
+ },
26
+ [node_path_1.default.join(tmpDir, 'digest')]: { type: 'directory' },
27
+ [node_path_1.default.join(tmpDir, 'digest', 'nested.txt')]: {
28
+ type: 'file',
29
+ data: chance.string()
30
+ }
31
+ };
32
+ (0, test_utils_1.fmock)(frame);
33
+ });
34
+ (0, node_test_1.afterEach)(() => {
35
+ (0, test_utils_1.restore)(tmpDir);
36
+ });
37
+ (0, node_test_1.it)('Positive: Removes all directory contents but preserves the directory', async () => {
38
+ await index_1.pfs.emptyDir(tmpDir);
39
+ (0, node_assert_1.default)(node_fs_1.default.existsSync(tmpDir));
40
+ node_assert_1.default.deepStrictEqual(node_fs_1.default.readdirSync(tmpDir), []);
41
+ });
42
+ (0, node_test_1.it)('Negative: Throw if resource is not directory', async () => {
43
+ await node_assert_1.default.rejects(async () => {
44
+ await index_1.pfs.emptyDir(node_path_1.default.join(tmpDir, 'tings.txt'));
45
+ });
46
+ });
47
+ (0, node_test_1.it)('[sync] Positive: Removes all directory contents but preserves the directory', () => {
48
+ index_1.pfs.emptyDir(tmpDir, {
49
+ sync: true
50
+ });
51
+ (0, node_assert_1.default)(node_fs_1.default.existsSync(tmpDir));
52
+ node_assert_1.default.deepStrictEqual(node_fs_1.default.readdirSync(tmpDir), []);
53
+ });
54
+ (0, node_test_1.it)('[sync] Negative: Throw if resource is not directory', () => {
55
+ node_assert_1.default.throws(() => {
56
+ index_1.pfs.emptyDir(node_path_1.default.join(tmpDir, 'tings.txt'), {
57
+ sync: true
58
+ });
59
+ });
60
+ });
61
+ });
@@ -1,8 +1,11 @@
1
- import type { PoweredFileSystem } from '../powered-file-system';
1
+ import type { AsyncOption, MaybeSyncOption, PoweredFileSystem, SyncOption } from '../powered-file-system';
2
+ type MkdirOptions = {
3
+ umask?: number;
4
+ };
2
5
  /**
3
- * Creates directories relative to the instance root.
6
+ * Creates directories relative to the instance base path.
4
7
  */
5
- export declare function mkdir<T extends boolean = false>(this: PoweredFileSystem, dir: string, options?: {
6
- sync?: T;
7
- umask?: number;
8
- }): T extends true ? void : Promise<void>;
8
+ export declare function mkdir(this: PoweredFileSystem, dir: string, options: SyncOption & MkdirOptions): void;
9
+ export declare function mkdir(this: PoweredFileSystem, dir: string, options?: AsyncOption & MkdirOptions): Promise<void>;
10
+ export declare function mkdir(this: PoweredFileSystem, dir: string, options?: MaybeSyncOption & MkdirOptions): void | Promise<void>;
11
+ export {};
@@ -1,23 +1,22 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.mkdir = mkdir;
7
- const node_path_1 = __importDefault(require("node:path"));
8
4
  const recurse_io_1 = require("../recurse-io");
9
5
  const recurse_io_sync_1 = require("../recurse-io-sync");
10
- /**
11
- * Creates directories relative to the instance root.
12
- */
13
6
  function mkdir(dir, options) {
14
7
  const { sync = false, umask = 0o000 } = options ?? {};
15
- dir = node_path_1.default.resolve(this.pwd, dir);
16
8
  if (sync) {
17
- (0, recurse_io_sync_1.mkdirSync)(dir, umask);
18
- return undefined;
9
+ (0, recurse_io_sync_1.mkdirSync)(this.resolve(dir), umask);
10
+ return;
19
11
  }
20
12
  return new Promise((resolve, reject) => {
13
+ try {
14
+ dir = this.resolve(dir);
15
+ }
16
+ catch (err) {
17
+ reject(err);
18
+ return;
19
+ }
21
20
  (0, recurse_io_1.mkdir)(dir, umask, (err) => {
22
21
  if (err) {
23
22
  return reject(err);
@@ -1,9 +1,13 @@
1
- import type { Flag, PoweredFileSystem } from '../powered-file-system';
1
+ import type { AsyncOption, MaybeSyncOption, PoweredFileSystem, ReadOptions, SyncOption } from '../powered-file-system';
2
2
  /**
3
3
  * Reads a file relative to `pwd` and preserves Buffer mode when `encoding` is `null`.
4
4
  */
5
- export declare function read<T extends boolean = false>(this: PoweredFileSystem, src: string, options?: {
6
- sync?: T;
7
- encoding?: BufferEncoding | null;
8
- flag?: Flag;
9
- }): T extends true ? string | Buffer : Promise<string | Buffer>;
5
+ export declare function read(this: PoweredFileSystem, src: string, options: SyncOption & ReadOptions<true, null> & {
6
+ encoding: null;
7
+ }): Buffer;
8
+ export declare function read(this: PoweredFileSystem, src: string, options: SyncOption & ReadOptions<true, BufferEncoding>): string;
9
+ export declare function read(this: PoweredFileSystem, src: string, options: AsyncOption & ReadOptions<false, null> & {
10
+ encoding: null;
11
+ }): Promise<Buffer>;
12
+ export declare function read(this: PoweredFileSystem, src: string, options?: AsyncOption & ReadOptions<false, BufferEncoding>): Promise<string>;
13
+ export declare function read(this: PoweredFileSystem, src: string, options?: MaybeSyncOption & ReadOptions<boolean, BufferEncoding | null>): string | Buffer | Promise<string | Buffer>;
@@ -5,20 +5,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.read = read;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
- const node_path_1 = __importDefault(require("node:path"));
9
- /**
10
- * Reads a file relative to `pwd` and preserves Buffer mode when `encoding` is `null`.
11
- */
12
8
  function read(src, options) {
13
9
  const { sync = false, encoding = 'utf8', flag = 'r' } = options ?? {};
14
- const resolved = node_path_1.default.resolve(this.pwd, src);
15
10
  if (sync) {
11
+ const resolved = this.resolve(src);
16
12
  if (encoding === null) {
17
13
  return node_fs_1.default.readFileSync(resolved, { encoding: null, flag });
18
14
  }
19
15
  return node_fs_1.default.readFileSync(resolved, { encoding, flag });
20
16
  }
21
17
  return new Promise((resolve, reject) => {
18
+ let resolved;
19
+ try {
20
+ resolved = this.resolve(src);
21
+ }
22
+ catch (err) {
23
+ reject(err);
24
+ return;
25
+ }
22
26
  node_fs_1.default.readFile(resolved, { encoding, flag }, (err, raw) => {
23
27
  if (err) {
24
28
  return reject(err);
@@ -1,8 +1,13 @@
1
- import type { PoweredFileSystem } from '../powered-file-system';
1
+ import type { AsyncOption, MaybeSyncOption, PoweredFileSystem, ReaddirOptions, SyncOption } from '../powered-file-system';
2
2
  /**
3
- * Lists directory entries relative to the current instance root.
3
+ * Lists directory entries relative to the instance base path.
4
4
  */
5
- export declare function readdir<T extends boolean = false>(this: PoweredFileSystem, dir: string, options?: {
6
- sync?: T;
7
- encoding?: BufferEncoding | null;
8
- }): T extends true ? string[] : Promise<string[]>;
5
+ export declare function readdir(this: PoweredFileSystem, dir: string, options: SyncOption & ReaddirOptions<true, null> & {
6
+ encoding: null;
7
+ }): Buffer[];
8
+ export declare function readdir(this: PoweredFileSystem, dir: string, options: SyncOption & ReaddirOptions<true, BufferEncoding>): string[];
9
+ export declare function readdir(this: PoweredFileSystem, dir: string, options: AsyncOption & ReaddirOptions<false, null> & {
10
+ encoding: null;
11
+ }): Promise<Buffer[]>;
12
+ export declare function readdir(this: PoweredFileSystem, dir: string, options?: AsyncOption & ReaddirOptions<false, BufferEncoding>): Promise<string[]>;
13
+ export declare function readdir(this: PoweredFileSystem, dir: string, options?: MaybeSyncOption & ReaddirOptions<boolean, BufferEncoding | null>): string[] | Buffer[] | Promise<string[] | Buffer[]>;
@@ -5,17 +5,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.readdir = readdir;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
- const node_path_1 = __importDefault(require("node:path"));
9
- /**
10
- * Lists directory entries relative to the current instance root.
11
- */
12
8
  function readdir(dir, options) {
13
9
  const { sync = false, encoding = 'utf8' } = options ?? {};
14
- dir = node_path_1.default.resolve(this.pwd, dir);
15
10
  if (sync) {
16
- return node_fs_1.default.readdirSync(dir, { encoding });
11
+ return node_fs_1.default.readdirSync(this.resolve(dir), { encoding });
17
12
  }
18
13
  return new Promise((resolve, reject) => {
14
+ try {
15
+ dir = this.resolve(dir);
16
+ }
17
+ catch (err) {
18
+ reject(err);
19
+ return;
20
+ }
19
21
  node_fs_1.default.readdir(dir, { encoding }, (err, list) => {
20
22
  if (err) {
21
23
  return reject(err);
@@ -0,0 +1,13 @@
1
+ import type { AsyncOption, MaybeSyncOption, PoweredFileSystem, SyncOption } from '../powered-file-system';
2
+ /**
3
+ * Reads the target path stored in a symbolic link.
4
+ */
5
+ export declare function readlink(this: PoweredFileSystem, src: string, options: SyncOption & {
6
+ encoding?: BufferEncoding;
7
+ }): string;
8
+ export declare function readlink(this: PoweredFileSystem, src: string, options?: AsyncOption & {
9
+ encoding?: BufferEncoding;
10
+ }): Promise<string>;
11
+ export declare function readlink(this: PoweredFileSystem, src: string, options?: MaybeSyncOption & {
12
+ encoding?: BufferEncoding;
13
+ }): string | Promise<string>;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.readlink = readlink;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ function readlink(src, options) {
9
+ const { sync = false, encoding = 'utf8' } = options ?? {};
10
+ if (sync) {
11
+ return node_fs_1.default.readlinkSync(this.resolve(src), { encoding });
12
+ }
13
+ return new Promise((resolve, reject) => {
14
+ try {
15
+ src = this.resolve(src);
16
+ }
17
+ catch (err) {
18
+ reject(err);
19
+ return;
20
+ }
21
+ node_fs_1.default.readlink(src, { encoding }, (err, resolved) => {
22
+ if (err) {
23
+ return reject(err);
24
+ }
25
+ resolve(resolved);
26
+ });
27
+ });
28
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_assert_1 = __importDefault(require("node:assert"));
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const chance_1 = __importDefault(require("chance"));
9
+ const node_test_1 = require("node:test");
10
+ const index_1 = require("../index");
11
+ const test_utils_1 = require("../test-utils");
12
+ /**
13
+ * Verifies symbolic link target resolution without dereferencing it.
14
+ */
15
+ (0, node_test_1.describe)('readlink(src [, options])', () => {
16
+ const chance = new chance_1.default();
17
+ let tmpDir = '';
18
+ (0, node_test_1.beforeEach)(() => {
19
+ tmpDir = (0, test_utils_1.createTmpDir)();
20
+ (0, test_utils_1.fmock)({
21
+ [node_path_1.default.join(tmpDir, 'tings.txt')]: {
22
+ type: 'file',
23
+ data: chance.string()
24
+ },
25
+ [node_path_1.default.join(tmpDir, 'flexapp')]: {
26
+ type: 'symlink',
27
+ target: node_path_1.default.join(tmpDir, 'tings.txt')
28
+ }
29
+ });
30
+ });
31
+ (0, node_test_1.afterEach)(() => {
32
+ (0, test_utils_1.restore)(tmpDir);
33
+ });
34
+ (0, node_test_1.it)('Positive: Reads the stored symlink target', async () => {
35
+ const target = await index_1.pfs.readlink(node_path_1.default.join(tmpDir, 'flexapp'));
36
+ (0, node_assert_1.default)(target === node_path_1.default.join(tmpDir, 'tings.txt'));
37
+ });
38
+ (0, node_test_1.it)('[sync] Positive: Reads the stored symlink target', () => {
39
+ const target = index_1.pfs.readlink(node_path_1.default.join(tmpDir, 'flexapp'), {
40
+ sync: true
41
+ });
42
+ (0, node_assert_1.default)(target === node_path_1.default.join(tmpDir, 'tings.txt'));
43
+ });
44
+ });