{"_id":"@roberts_lando/vfs","_rev":"4-0861bcb4a5586cb0c9c3a3889ad4c1b1","name":"@roberts_lando/vfs","dist-tags":{"latest":"0.3.3"},"versions":{"0.3.0":{"name":"@roberts_lando/vfs","version":"0.3.0","keywords":["vfs","virtual-filesystem","in-memory-fs","fs","mount"],"author":{"url":"https://platformatic.dev","name":"Platformatic Inc.","email":"oss@platformatic.dev"},"license":"MIT","_id":"@roberts_lando/vfs@0.3.0","maintainers":[{"name":"roberts_lando","email":"daniel.sorridi@gmail.com"}],"homepage":"https://github.com/robertsLando/vfs","bugs":{"url":"https://github.com/robertsLando/vfs/issues"},"dist":{"shasum":"e0f975ae5e75b5384e418dda5f4b71e79c2c9198","tarball":"https://registry.npmjs.org/@roberts_lando/vfs/-/vfs-0.3.0.tgz","fileCount":18,"integrity":"sha512-lXOgbSdVWmqSng5QdAhUaD6mxkDXg93vc1t9a42Yy05N+HVxFj1EVk+yQ8EqQv/2xv4UbfX3AS3jast2iw8UXA==","signatures":[{"sig":"MEYCIQCDUPCRNKFvGrd5/9TREzNjfyP9H99l9u1LUbrD2r4ppQIhAIzUi1jK+BUz19sJ4IfeEEw/DRXO68SRkg8iAl5Jw72l","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":168626},"main":"index.js","types":"index.d.ts","engines":{"node":">= 22"},"exports":"./index.js","gitHead":"1ce60fb7f169a81fe2a93598b69067712c1c48a7","private":false,"scripts":{"ci":"npm run lint && npm run test:types && npm run test","lint":"eslint --cache","test":"c8 -c test/config/c8.json node  --test --test-reporter=cleaner-spec-reporter --test-timeout=60000 'test/*.test.js'","typecheck":"tsc -p . --noEmit","test:types":"tstyche","postpublish":"git push origin && git push origin -f --tags","prepublishOnly":"npm run lint"},"_npmUser":{"name":"roberts_lando","email":"daniel.sorridi@gmail.com"},"repository":{"url":"git+https://github.com/robertsLando/vfs.git","type":"git"},"_npmVersion":"10.9.4","description":"Virtual File System for Node.js - userland shim for node:vfs","directories":{},"_nodeVersion":"22.22.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","eslint":"^10.0.2","semver":"^7.7.4","tstyche":"^3.5.0","@eslint/js":"^10.0.1","typescript":"^5.8.2","@types/node":"^25.3.2","@types/semver":"^7.7.1","cleaner-spec-reporter":"^1.0.3","@stylistic/eslint-plugin-js":"^4.4.1"},"_npmOperationalInternal":{"tmp":"tmp/vfs_0.3.0_1775655882489_0.08568774444625116","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"@roberts_lando/vfs","version":"0.3.1","keywords":["vfs","virtual-filesystem","in-memory-fs","fs","mount"],"author":{"url":"https://platformatic.dev","name":"Platformatic Inc.","email":"oss@platformatic.dev"},"license":"MIT","_id":"@roberts_lando/vfs@0.3.1","maintainers":[{"name":"roberts_lando","email":"daniel.sorridi@gmail.com"}],"homepage":"https://github.com/robertsLando/vfs","bugs":{"url":"https://github.com/robertsLando/vfs/issues"},"dist":{"shasum":"fccf70beff7b4fc730de963ab42f86e126d306d2","tarball":"https://registry.npmjs.org/@roberts_lando/vfs/-/vfs-0.3.1.tgz","fileCount":18,"integrity":"sha512-JpTa6PKdy8a+AZI4TU1Kn2sx4QT02v8AcXFGIYM7FSay8Ji0IDl22BPAQkNdAgRjWyl+pfH9J+4AFWupNDXALg==","signatures":[{"sig":"MEYCIQCMQ8CkdemmWhCPsO/hv1qeyU+N5pgb7dbmRMKIQke7pgIhAJ5ozQ10xdpdZF1QGljMngPwWawschrrf18D8mZo+aiZ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":171284},"main":"index.js","types":"index.d.ts","engines":{"node":">= 22"},"exports":"./index.js","gitHead":"a22472f2a4f82c54762f4a1d0e688c50dc166ba1","private":false,"scripts":{"ci":"npm run lint && npm run test:types && npm run test","lint":"eslint --cache","test":"c8 -c test/config/c8.json node  --test --test-reporter=cleaner-spec-reporter --test-timeout=60000 'test/*.test.js'","typecheck":"tsc -p . --noEmit","test:types":"tstyche","postpublish":"git push origin && git push origin -f --tags","prepublishOnly":"npm run lint"},"_npmUser":{"name":"roberts_lando","email":"daniel.sorridi@gmail.com"},"repository":{"url":"git+https://github.com/robertsLando/vfs.git","type":"git"},"_npmVersion":"10.9.4","description":"Virtual File System for Node.js - userland shim for node:vfs","directories":{},"_nodeVersion":"22.22.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","eslint":"^10.0.2","semver":"^7.7.4","tstyche":"^3.5.0","@eslint/js":"^10.0.1","typescript":"^5.8.2","@types/node":"^25.3.2","@types/semver":"^7.7.1","cleaner-spec-reporter":"^1.0.3","@stylistic/eslint-plugin-js":"^4.4.1"},"_npmOperationalInternal":{"tmp":"tmp/vfs_0.3.1_1775659710631_0.7958471647379683","host":"s3://npm-registry-packages-npm-production"}},"0.3.2":{"name":"@roberts_lando/vfs","version":"0.3.2","keywords":["vfs","virtual-filesystem","in-memory-fs","fs","mount"],"author":{"url":"https://platformatic.dev","name":"Platformatic Inc.","email":"oss@platformatic.dev"},"license":"MIT","_id":"@roberts_lando/vfs@0.3.2","maintainers":[{"name":"roberts_lando","email":"daniel.sorridi@gmail.com"}],"homepage":"https://github.com/robertsLando/vfs","bugs":{"url":"https://github.com/robertsLando/vfs/issues"},"dist":{"shasum":"a552390c4a64bd42dfcb54f0e897b240acdce074","tarball":"https://registry.npmjs.org/@roberts_lando/vfs/-/vfs-0.3.2.tgz","fileCount":18,"integrity":"sha512-whXj9v78S4n3t0RvoTGj8vui27VVtK/oy8YfBL+gDWdlfRFkKpPjry+U8p+3XM++5rAIpXEtXcTUgUAEHZVoFA==","signatures":[{"sig":"MEQCIFoXmu52MW2KiwWJSdQCEYSLgRQ7vpDOC4J6R8tS4aErAiAKGyZ4OYiWO03LpeWyPIylKq6yi929ws2qB0edtpUOkw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":173224},"main":"index.js","types":"index.d.ts","engines":{"node":">= 22"},"exports":"./index.js","gitHead":"1331f53a1ac8c53c12a5759062a08ad831ece76a","private":false,"scripts":{"ci":"npm run lint && npm run test:types && npm run test","lint":"eslint --cache","test":"c8 -c test/config/c8.json node  --test --test-reporter=cleaner-spec-reporter --test-timeout=60000 'test/*.test.js'","typecheck":"tsc -p . --noEmit","test:types":"tstyche","postpublish":"git push origin && git push origin -f --tags","prepublishOnly":"npm run lint"},"_npmUser":{"name":"roberts_lando","email":"daniel.sorridi@gmail.com"},"repository":{"url":"git+https://github.com/robertsLando/vfs.git","type":"git"},"_npmVersion":"10.9.4","description":"Virtual File System for Node.js - userland shim for node:vfs","directories":{},"_nodeVersion":"22.22.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^10.1.3","eslint":"^10.0.2","semver":"^7.7.4","tstyche":"^3.5.0","@eslint/js":"^10.0.1","typescript":"^5.8.2","@types/node":"^25.3.2","@types/semver":"^7.7.1","cleaner-spec-reporter":"^1.0.3","@stylistic/eslint-plugin-js":"^4.4.1"},"_npmOperationalInternal":{"tmp":"tmp/vfs_0.3.2_1775660303398_0.09255574374939202","host":"s3://npm-registry-packages-npm-production"}},"0.3.3":{"name":"@roberts_lando/vfs","version":"0.3.3","description":"Virtual File System for Node.js - userland shim for node:vfs","homepage":"https://github.com/robertsLando/vfs","author":{"name":"Platformatic Inc.","email":"oss@platformatic.dev","url":"https://platformatic.dev"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/robertsLando/vfs.git"},"keywords":["vfs","virtual-filesystem","in-memory-fs","fs","mount"],"bugs":{"url":"https://github.com/robertsLando/vfs/issues"},"private":false,"main":"index.js","types":"index.d.ts","exports":"./index.js","scripts":{"lint":"eslint --cache","typecheck":"tsc -p . --noEmit","test":"c8 -c test/config/c8.json node  --test --test-reporter=cleaner-spec-reporter --test-timeout=60000 'test/*.test.js'","test:types":"tstyche","ci":"npm run lint && npm run test:types && npm run test","prepublishOnly":"npm run lint","postpublish":"git push origin && git push origin -f --tags"},"devDependencies":{"@eslint/js":"^10.0.1","@stylistic/eslint-plugin-js":"^4.4.1","@types/node":"^25.3.2","@types/semver":"^7.7.1","c8":"^10.1.3","cleaner-spec-reporter":"^1.0.3","eslint":"^10.0.2","semver":"^7.7.4","tstyche":"^3.5.0","typescript":"^5.8.2"},"publishConfig":{"access":"public"},"engines":{"node":">= 22"},"_id":"@roberts_lando/vfs@0.3.3","gitHead":"65be1c8854e1931ebc5fd2a4acb0d87322795ac6","_nodeVersion":"22.20.0","_npmVersion":"10.9.3","dist":{"integrity":"sha512-YjkxVSLw5WMZQoARaryRAjcxA+GbBzWMJdwYZX5oLUt9cC/gew9as4Dn7tcLzPp7BPoR221VpTZ+78TRPawnjg==","shasum":"6359feed30e3773041279cb11be82ca60f4ff1f1","tarball":"https://registry.npmjs.org/@roberts_lando/vfs/-/vfs-0.3.3.tgz","fileCount":18,"unpackedSize":173681,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCi90NvXZFRMFBtSehr4iBhkOYJNuhlGZ994NtP0Ww5lwIhAMqePD+k9QuqotB0DgQII1+Nvg/aUHnR7eGWefvlFtby"}]},"_npmUser":{"name":"roberts_lando","email":"daniel.sorridi@gmail.com"},"directories":{},"maintainers":[{"name":"roberts_lando","email":"daniel.sorridi@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/vfs_0.3.3_1776954615874_0.3396045234859706"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-08T13:44:42.385Z","modified":"2026-04-23T14:30:16.178Z","0.3.0":"2026-04-08T13:44:42.680Z","0.3.1":"2026-04-08T14:48:30.785Z","0.3.2":"2026-04-08T14:58:23.556Z","0.3.3":"2026-04-23T14:30:16.069Z"},"bugs":{"url":"https://github.com/robertsLando/vfs/issues"},"author":{"name":"Platformatic Inc.","email":"oss@platformatic.dev","url":"https://platformatic.dev"},"license":"MIT","homepage":"https://github.com/robertsLando/vfs","keywords":["vfs","virtual-filesystem","in-memory-fs","fs","mount"],"repository":{"type":"git","url":"git+https://github.com/robertsLando/vfs.git"},"description":"Virtual File System for Node.js - userland shim for node:vfs","maintainers":[{"name":"roberts_lando","email":"daniel.sorridi@gmail.com"}],"readme":"# @platformatic/vfs\n\nA Virtual File System for Node.js. Provides an in-memory `fs`-compatible API with mount points, overlay mode, symlinks, module loading hooks, and custom storage providers.\n\n## Install\n\n```\nnpm install @platformatic/vfs\n```\n\nRequires Node.js >= 22.\n\n## Quick start\n\n```js\nconst { create } = require('@platformatic/vfs');\n\nconst vfs = create();\n\nvfs.writeFileSync('/app/index.js', 'module.exports = \"hello\"');\n\n// Mount the VFS at /app — patches require() and fs so that\n// the rest of the process sees virtual files transparently.\nvfs.mount('/app');\n\nconst mod = require('/app/index.js'); // 'hello'\n\nvfs.unmount();\n```\n\n## API\n\n### `create([provider], [options])`\n\nCreates a new `VirtualFileSystem` instance.\n\n- **provider** — a `VirtualProvider` instance (defaults to `MemoryProvider`)\n- **options.moduleHooks** `<boolean>` — patch `require()`/`import` and core `fs` functions so the process can load modules from the VFS (default `true`)\n- **options.overlay** `<boolean>` — when `true`, only files that exist in the VFS are intercepted; everything else falls through to the real filesystem (default `false`)\n- **options.virtualCwd** `<boolean>` — enable a virtual working directory that intercepts `process.cwd()` and `process.chdir()` (default `false`)\n\nReturns a `VirtualFileSystem`.\n\n### `VirtualFileSystem`\n\n#### Properties\n\n| Property | Type | Description |\n|---|---|---|\n| `provider` | `VirtualProvider` | The underlying storage provider |\n| `mountPoint` | `string \\| null` | Current mount prefix, or `null` |\n| `mounted` | `boolean` | Whether the VFS is currently mounted |\n| `readonly` | `boolean` | Whether the provider is read-only |\n| `overlay` | `boolean` | Whether overlay mode is enabled |\n\n#### Mount / Unmount\n\n```js\nvfs.mount('/prefix');   // Start intercepting paths under /prefix\nvfs.unmount();          // Stop intercepting\n```\n\n`mount()` returns the VFS instance for chaining. When mounted with `moduleHooks: true` (the default), `require()`, `import`, and core `fs` functions (`readFileSync`, `statSync`, `existsSync`, `readdirSync`, `realpathSync`, `watch`, etc.) are patched to serve files from the VFS.\n\nEmits `vfs-mount` and `vfs-unmount` events on `process`.\n\nSupports `Symbol.dispose` — works with `using` declarations in environments that support it.\n\n#### `shouldHandle(path)`\n\nReturns `true` if the given path would be handled by this VFS instance. In overlay mode, only returns `true` for paths that actually exist in the VFS.\n\n#### Sync API\n\nThe full synchronous `fs` API:\n\n```js\nvfs.writeFileSync(path, data[, options])\nvfs.readFileSync(path[, options])          // returns Buffer or string\nvfs.existsSync(path)\nvfs.statSync(path[, options])\nvfs.lstatSync(path[, options])\nvfs.readdirSync(path[, options])           // supports { withFileTypes: true }\nvfs.mkdirSync(path[, options])             // supports { recursive: true }\nvfs.rmdirSync(path)\nvfs.unlinkSync(path)\nvfs.renameSync(oldPath, newPath)\nvfs.copyFileSync(src, dest)\nvfs.appendFileSync(path, data[, options])\nvfs.accessSync(path[, mode])\nvfs.realpathSync(path[, options])\nvfs.symlinkSync(target, path[, type])\nvfs.readlinkSync(path[, options])\n```\n\n#### File descriptors\n\n```js\nconst fd = vfs.openSync(path[, flags[, mode]]);\nvfs.readSync(fd, buffer, offset, length, position);\nvfs.fstatSync(fd[, options]);\nvfs.closeSync(fd);\n```\n\n#### Callback API\n\nEvery sync method has a callback counterpart following the standard Node.js `(err, result)` convention:\n\n```js\nvfs.readFile(path, options, callback)\nvfs.writeFile(path, data, options, callback)\nvfs.stat(path, options, callback)\nvfs.readdir(path, options, callback)\n// ...\n```\n\n#### Promises API\n\n```js\nconst content = await vfs.promises.readFile('/file.txt', 'utf8');\nawait vfs.promises.writeFile('/file.txt', 'data');\nawait vfs.promises.mkdir('/dir', { recursive: true });\nconst entries = await vfs.promises.readdir('/dir');\nconst stats = await vfs.promises.stat('/file.txt');\nawait vfs.promises.unlink('/file.txt');\nawait vfs.promises.rename('/old', '/new');\nawait vfs.promises.copyFile('/src', '/dest');\nawait vfs.promises.appendFile('/file.txt', 'more');\nawait vfs.promises.access('/file.txt');\nawait vfs.promises.symlink('/target', '/link');\nconst target = await vfs.promises.readlink('/link');\nawait vfs.promises.lstat('/link');\nawait vfs.promises.realpath('/link');\nawait vfs.promises.rmdir('/dir');\n```\n\n#### Streams\n\n```js\nconst stream = vfs.createReadStream(path[, options]);\n```\n\nReturns a `Readable` stream. Options support `start`, `end`, and `autoClose`.\n\n#### Watch\n\n```js\nconst watcher = vfs.watch(path[, options][, listener]);\nvfs.watchFile(path[, options], listener);\nvfs.unwatchFile(path[, listener]);\n```\n\n#### Virtual working directory\n\nWhen created with `{ virtualCwd: true }`:\n\n```js\nconst vfs = create({ virtualCwd: true });\nvfs.writeFileSync('/app/file.txt', 'data');\nvfs.mount('/app');\n\nvfs.chdir('/app');\nvfs.cwd(); // '/app'\n```\n\nWhen mounted, `process.cwd()` and `process.chdir()` are patched to work with the virtual directory.\n\n### Providers\n\n#### `MemoryProvider`\n\nThe default provider. Stores everything in memory. Supports symlinks, watching, and read-only mode.\n\n```js\nconst { MemoryProvider, create } = require('@platformatic/vfs');\n\nconst provider = new MemoryProvider();\nconst vfs = create(provider);\n\nvfs.writeFileSync('/file.txt', 'hello');\n\n// Freeze the provider to prevent writes\nprovider.setReadOnly();\nvfs.writeFileSync('/other.txt', 'fail'); // throws EROFS\n```\n\n#### `SqliteProvider`\n\nA persistent provider backed by Node.js built-in `node:sqlite`. Stores files, directories, and symlinks in a SQLite database. Supports both in-memory and file-backed databases.\n\n```js\nconst { SqliteProvider, create } = require('@platformatic/vfs');\n\n// In-memory (default)\nconst mem = new SqliteProvider();\nconst vfs1 = create(mem);\n\n// File-backed — data persists across restarts\nconst disk = new SqliteProvider('/tmp/myfs.db');\nconst vfs2 = create(disk);\n\nvfs2.writeFileSync('/file.txt', 'hello');\ndisk.close();\n\n// Reopen later — files are still there\nconst disk2 = new SqliteProvider('/tmp/myfs.db');\nconst vfs3 = create(disk2);\nvfs3.readFileSync('/file.txt', 'utf8'); // 'hello'\ndisk2.close();\n```\n\nRequires Node.js >= 22. Call `provider.close()` when done to close the database.\n\n#### `RealFSProvider`\n\nDelegates to the real filesystem, sandboxed under a root directory. Directory traversal outside the root is prevented.\n\n```js\nconst { RealFSProvider, create } = require('@platformatic/vfs');\n\nconst provider = new RealFSProvider('/tmp/sandbox');\nconst vfs = create(provider);\n\n// All paths are resolved relative to /tmp/sandbox\nvfs.writeFileSync('/file.txt', 'data'); // writes to /tmp/sandbox/file.txt\n```\n\n#### Custom providers\n\nExtend `VirtualProvider` and implement the essential primitives:\n\n```js\nconst { VirtualProvider, create } = require('@platformatic/vfs');\n\nclass MyProvider extends VirtualProvider {\n  openSync(path, flags, mode) { /* ... */ }\n  statSync(path, options) { /* ... */ }\n  readdirSync(path, options) { /* ... */ }\n  mkdirSync(path, options) { /* ... */ }\n  rmdirSync(path) { /* ... */ }\n  unlinkSync(path) { /* ... */ }\n  renameSync(oldPath, newPath) { /* ... */ }\n}\n\nconst vfs = create(new MyProvider());\n```\n\nHigher-level operations (`readFile`, `writeFile`, `copyFile`, `exists`, `access`, etc.) are provided automatically by the base class using the primitives above.\n\n## Module hooks\n\nWhen `moduleHooks` is enabled (the default), mounting a VFS instance:\n\n1. **Patches `require()` and `import`** — On Node.js 23.5+ uses `Module.registerHooks()`. On older versions falls back to `Module._resolveFilename` + `Module._extensions` patching.\n2. **Patches core `fs` functions** — `readFileSync`, `statSync`, `lstatSync`, `readdirSync`, `existsSync`, `realpathSync`, `watch`, `watchFile`, `unwatchFile`.\n\nThis means third-party code using `require()` or `fs.readFileSync()` will transparently pick up files from the VFS.\n\nModule resolution supports package.json `exports`, `main`, and bare specifier resolution walking `node_modules`.\n\n## Node.js core VFS support\n\nThis package is a direct extraction of the Virtual File System being added to Node.js core ([nodejs/node#61478](https://github.com/nodejs/node/pull/61478)), allowing it to be used on Node.js 22+. Once the core PR lands, this package will no longer be necessary (except for `SqliteProvider`).\n\n## License\n\nMIT\n","readmeFilename":"README.md"}