Understanding the File System
The virtual file system in @nhtio/vue-editors is designed to provide a robust, reactive, and extensible foundation for browser-based code editing, playgrounds, and REPLs. It consists of three main abstractions:
NVEFileSystem: The reactive, in-memory file system manager.NVEDirent: The file or directory entry abstraction.NVEFileTree: The reactive file tree structure for hierarchical and flat views.
The NVEFileSystem Abstraction
NVEFileSystem is a reactive, in-memory file system that manages a collection of files and directories (dirents). It is designed for use in Vue applications and is safe for SSR and hot-reload scenarios.
Key features:
- Shallow reactivity (suitable for Vue 3's reactivity system)
- Event-driven (creation, deletion, move, commit, error, etc.)
- Supports file/directory creation, reading, moving, copying, unlinking, and globbing
- Robust disposal and serialization
- Provides a reactive file tree for UI rendering
Basic usage:
import { NVEFileSystem } from '@nhtio/vue-editors/fs'
const fs = new NVEFileSystem()
const file = fs.createDirent('App.vue', '/src', '<template>Hello</template>')See the API documentation for a full list of methods and events.
The NVEDirent Abstraction
NVEDirent represents a single file or directory in the file system. Each dirent is reactive and exposes properties such as name, parentPath, content (for files), and dirty state.
- Files have a
contentproperty (string), and can be edited directly. - Directories do not have content, but can be created and managed in the same way.
Example:
const file = fs.createDirent('main.ts', '/src', 'console.log("hi")')
file.content = 'console.log("hello world")' // marks file as dirtyThe Reactive File Tree (NVEFileTree)
The file system provides a reactive file tree structure for rendering and traversing files and directories in both flat and hierarchical forms. This is especially useful for building file explorers, tree views, and navigation components in your UI.
Accessing the File Tree
You can access the file tree via the asTree getter on your NVEFileSystem instance:
const fs = new NVEFileSystem()
const tree = fs.asTree // instance of NVEFileTreeFlat and Hierarchical Views
tree.flat: Returns a flat map of all file and directory entries (including virtual directories). The keys are full paths, and the values are dirent or virtual dirent instances.tree.tree: Returns an array of root nodes (NVEFileTreeNode), each representing a file or directory. Each node exposes its children, selection state, and more. Each node also exposes adepthproperty indicating its depth in the tree (0 for root, 1 for children, etc).
Example: Rendering a File Tree
const tree = fs.asTree
const rootNodes = tree.tree
rootNodes.forEach(node => {
console.log(node.dirent.name, node.depth) // node.depth is 0 for root, 1 for children, etc.
if (node.children) {
node.children.forEach(child => console.log(' ', child.dirent.name, child.depth))
}
})File Tree Reactivity
The file tree is fully reactive:
- Adding, removing, or moving files/dirs in the file system will automatically update the tree.
- Node properties like
selectedandfoldedare reactive and can be used for UI state.
Virtual Directories
The tree includes virtual directories to ensure a complete hierarchy, even if some parent folders do not exist as real dirents. This is useful for rendering a consistent tree structure.
Use Cases
- File explorers and sidebar navigation
- Breadcrumbs and path pickers
- Drag-and-drop reordering
- UI state management (selection, folding/collapsing)
See the NVEFileTree API Reference and NVEFileTreeNode API Reference for more details.
Reactivity
Both NVEFileSystem and NVEDirent are shallowly reactive:
- The file system instance itself is reactive (using Vue's
reactive()), so you can use it in Vue components and templates. - Each dirent is also reactive, so changes to properties like
contentordirtywill update the UI automatically. - The file tree (
asTree) is also reactive and updates in response to file system changes.
Note: Reactivity is shallow—nested objects inside dirents are not deeply reactive, but the main properties are.
Dirty State Tracking
A core feature is the ability to track unsaved changes ("dirty" state):
- Each
NVEDirenthas adirtyproperty that istrueif the file or directory has unsaved changes. - The file system exposes a reactive
dirtygetter, which istrueif any dirent is dirty.
Example:
if (fs.dirty) {
// Show a save prompt or enable a "Save" button
}This makes it easy to build UIs that reflect the save state of the editor.
The Commit Workflow
The commit workflow allows you to persist or synchronize changes in the file system:
- Per-dirent commit: You can provide an
onDirentCommithandler to the file system, which will be called for each dirty dirent whencommit()is called. - File system commit: You can provide an
onCommithandler, which will be called with all dirents for batch or atomic commits. - If both are provided, the file system-level handler takes precedence.
- Commit errors are surfaced via events (
commitError,direntCommitError).
Example:
const fs = new NVEFileSystem({
onCommit: async (dirents) => {
// Save all files to a server
await saveToServer(dirents)
return true
}
})
await fs.commit()See NVEFileSystem.commit() and NVEDirent.commit() for more details.
Events and Error Handling
The file system emits events for all major actions (creation, deletion, move, commit, errors, etc.), allowing you to build reactive UIs and handle errors gracefully.
- Listen for events using
.on(event, handler)or.once(event, handler). - Remove listeners with
.off(event, handler).
See the API documentation for a full list of events.
Serialization and Deserialization
You can serialize the entire file system to a compact string for storage or sharing, and restore it later:
const serialized = fs.toSerialized()
const restored = NVEFileSystem.fromSerialized(serialized)Integration Tips
- Use the
dirtystate to prompt users to save changes before closing or navigating away. - Use events to update UI elements (e.g., file explorer, tabs) in response to file system changes.
- Integrate with the Monaco Editor by passing file URIs and content from the file system.
- Use the file tree (
asTree) for building file explorers and navigation components. - For advanced usage, see the API docs and Quickstart.