// symbolicLinkTest.ts
// src/symbolicLinkTest.ts
import * as osPath from 'path';
import { Volume, createFsFromVolume, IFs } from 'memfs';
import * as realFs from 'fs';
// Function to execute tasks
function executeTasks(fs: IFs) {
// Define directories
const testDir = osPath.join(__dirname, 'test-run');
const targetDir = osPath.join(testDir, 'target');
const linkDir = osPath.join(testDir, 'link');
const targetSubDir = osPath.join(targetDir, 'subDir');
const targetSubDirFile = osPath.join(targetSubDir, 'test.txt');
// Create directory structure
fs.mkdirSync(targetSubDir, { recursive: true });
fs.writeFileSync(targetSubDirFile, "Hello World");
fs.symlinkSync(targetDir, linkDir);
// Function to check existence of a file through a link
function checkFileExistence(linkPath: string, filePath: string) {
const resolvedFilePath = osPath.join(linkPath, filePath);
const resolvedDirPath = osPath.dirname(resolvedFilePath);
console.log(`Does '${resolvedFilePath}' exist? ${fs.existsSync(resolvedFilePath)}`);
console.log(`Of course it's a child of it's directory: ${fs.lstatSync(resolvedDirPath).isDirectory()}`);
}
// Test symbolic link
console.log("Testing symbolic link:");
checkFileExistence(linkDir, 'subDir/test.txt');
}
// Execute tasks with real file system (realFs)
console.log("Running with real file system (realFs):");
executeTasks(realFs as unknown as IFs);
// Create in-memory file system (memfs)
const vol = new Volume();
const memFs = createFsFromVolume(vol);
// Execute tasks with in-memory file system (memfs)
console.log("\nRunning with in-memory file system (memfs):");
executeTasks(memFs);
The following results are received:
% node symbolicLinkTest.js
Running with real file system (realFs):
Testing symbolic link:
Does '/Users/timothystockstill/symbolic-link-test/test-run/link/subDir/test.txt' exist? true
Of course it's a child of it's directory: true
Running with in-memory file system (memfs):
Testing symbolic link:
Does '/Users/timothystockstill/symbolic-link-test/test-run/link/subDir/test.txt' exist? true
/Users/timothystockstill/symbolic-link-test/node_modules/memfs/lib/volume.js:927
throw (0, util_1.createError)(ENOENT, 'lstat', filename);
^
Error: ENOENT: no such file or directory, lstat '/Users/timothystockstill/symbolic-link-test/test-run/link/subDir'
at createError (/Users/timothystockstill/symbolic-link-test/node_modules/memfs/lib/node/util.js:143:19)
at Volume.lstatBase (/Users/timothystockstill/symbolic-link-test/node_modules/memfs/lib/volume.js:927:42)
at Volume.lstatSync (/Users/timothystockstill/symbolic-link-test/node_modules/memfs/lib/volume.js:932:21)
at checkFileExistence (/Users/timothystockstill/symbolic-link-test/symbolicLinkTest.js:24:76)
at executeTasks (/Users/timothystockstill/symbolic-link-test/symbolicLinkTest.js:28:5)
at Object. (/Users/timothystockstill/symbolic-link-test/symbolicLinkTest.js:38:1)
at Module._compile (node:internal/modules/cjs/loader:1233:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1287:10)
at Module.load (node:internal/modules/cjs/loader:1091:32)
at Module._load (node:internal/modules/cjs/loader:938:12) {
code: 'ENOENT',
path: '/Users/timothystockstill/symbolic-link-test/test-run/link/subDir'
}
Node.js v20.5.0
Expected results:
No exception because the parent directory of the file that memFs confirmed to exist does in fact also exist (it has to).
I believe the problem is related to how getChild handles symlinks, when determining file path steps, but haven't fully investigated the code.
Is this expected behavior for memFs, is this a bug, is there a work around or will I need to look deeper at getChild?
Given the following:
The following results are received:
% node symbolicLinkTest.js
Running with real file system (realFs): Testing symbolic link: Does '/Users/timothystockstill/symbolic-link-test/test-run/link/subDir/test.txt' exist? true Of course it's a child of it's directory: true
Running with in-memory file system (memfs): Testing symbolic link: Does '/Users/timothystockstill/symbolic-link-test/test-run/link/subDir/test.txt' exist? true /Users/timothystockstill/symbolic-link-test/node_modules/memfs/lib/volume.js:927 throw (0, util_1.createError)(ENOENT, 'lstat', filename); ^
Error: ENOENT: no such file or directory, lstat '/Users/timothystockstill/symbolic-link-test/test-run/link/subDir' at createError (/Users/timothystockstill/symbolic-link-test/node_modules/memfs/lib/node/util.js:143:19) at Volume.lstatBase (/Users/timothystockstill/symbolic-link-test/node_modules/memfs/lib/volume.js:927:42) at Volume.lstatSync (/Users/timothystockstill/symbolic-link-test/node_modules/memfs/lib/volume.js:932:21) at checkFileExistence (/Users/timothystockstill/symbolic-link-test/symbolicLinkTest.js:24:76) at executeTasks (/Users/timothystockstill/symbolic-link-test/symbolicLinkTest.js:28:5) at Object. (/Users/timothystockstill/symbolic-link-test/symbolicLinkTest.js:38:1)
at Module._compile (node:internal/modules/cjs/loader:1233:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1287:10)
at Module.load (node:internal/modules/cjs/loader:1091:32)
at Module._load (node:internal/modules/cjs/loader:938:12) {
code: 'ENOENT',
path: '/Users/timothystockstill/symbolic-link-test/test-run/link/subDir'
}
Node.js v20.5.0
Expected results:
No exception because the parent directory of the file that memFs confirmed to exist does in fact also exist (it has to).
I believe the problem is related to how getChild handles symlinks, when determining file path steps, but haven't fully investigated the code.
Is this expected behavior for memFs, is this a bug, is there a work around or will I need to look deeper at getChild?