Skip to content

feat: Implement memfs for file system management #2281

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

irfanfaraaz
Copy link
Contributor

@irfanfaraaz irfanfaraaz commented Jun 26, 2025

Description

Migrated the sandbox file system from custom file/content maps to a proper Virtual File System (VFS) implementation using memfs. This change significantly improves performance, reduces complexity, and provides enhanced file system capabilities while maintaining 100% backward compatibility.

Replaced FileSyncManager with VFSSyncManager and virtual-fs.ts

Related Issues

fixes #2280

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Release
  • Refactor
  • Other (please describe):

Testing

VirtualFileSystem: 22 tests covering core file system functionality

image

VFSSyncManager: 21 tests ensuring compatibility and new features

image

Updated existing tests: All 82 sandbox tests passing

image

Screenshots (if applicable)

Additional Notes

Files added:

virtual-fs.ts - Core VFS implementation
vfs-sync-manager.ts - Drop-in replacement for FileSyncManager


Important

Replaces FileSyncManager with VFSSyncManager using memfs for improved file system management, adding new VFS implementation and extensive testing.

  • Behavior:
    • Replaces FileSyncManager with VFSSyncManager in sandbox/index.ts.
    • Introduces virtual-fs.ts for core VFS implementation.
    • Adds vfs-sync-manager.ts as a drop-in replacement for FileSyncManager.
    • Ensures backward compatibility with existing file system operations.
  • Testing:
    • Adds 22 tests for VirtualFileSystem covering core functionality.
    • Adds 21 tests for VFSSyncManager ensuring compatibility and new features.
    • Updates existing tests; all 82 sandbox tests passing.
  • Dependencies:
    • Adds memfs to package.json for VFS support.

This description was created by Ellipsis for 07692dd. You can customize this summary. It will automatically update as commits are pushed.

Copy link

vercel bot commented Jun 26, 2025

@irfanfaraaz is attempting to deploy a commit to the Onlook Team on Vercel.

A member of the Team first needs to authorize it.

@Kitenite
Copy link
Contributor

This is awesome! What made you choose memfs out of the other solutions? Just curious if there were tradeoffs you considered.

@irfanfaraaz
Copy link
Contributor Author

When I researched VFS libraries, memfs was the most recommended because of it's focus on in-memory use and works as a lightweight, near drop-in replacement for Node's fs. Other libraries are more focused on disk storage

@Kitenite
Copy link
Contributor

That makes sense. Seems consistent with a deep research run since I haven't used these libraries
https://chatgpt.com/s/dr_685dc0d031e48191a010568d16408ba2

Is all the behavior the same for the code tab, AI and assets management or are you seeing any differences there?

@irfanfaraaz
Copy link
Contributor Author

Yes the behavior is the same. I used Gemini for testing since i ran out of Anthropic credits, so can’t fully comment on performance. There’s a bit of inconsistency in tool calling, but it was present both before and after my changes.

}

// Path utilities
normalizePath(path: string): string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It’d be great to double-check these utility functions like normalizePath, dirname, and basename to ensure they align with our existing ones in the files utility. Currently, these functions are returning different paths compared to the existing ones.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spartan-vutrannguyen
Copy link
Contributor

It looks good overall! But could you kindly rebase with main and verify if Asset Management still works with this implementation?
Right now, it seems this change is breaking asset management, so that’ll need to be addressed as well.

@irfanfaraaz
Copy link
Contributor Author

Thanks for pointing it out. Updated the code to use existing utility functions and added separate logic for memfs, since memfs requires absolute paths.
I’ve been trying to test this for 4–5 hours, but I keep getting errors when starting the app.Same issues happen on main as well.

@spartan-vutrannguyen
Copy link
Contributor

Thanks for pointing it out. Updated the code to use existing utility functions and added separate logic for memfs, since memfs requires absolute paths. I’ve been trying to test this for 4–5 hours, but I keep getting errors when starting the app.Same issues happen on main as well.

Could you share more details about the errors you're encountering?
Any error messages, steps to reproduce, or context would be really helpful!

@irfanfaraaz
Copy link
Contributor Author

Initially i was facing this error

Screenshot 2025-06-28 224657

Then i made some changes in trpc.ts to bypass it

and now i randomly get either of the below 2

Screenshot 2025-06-28 225117

Screenshot 2025-06-28 230734

@Kitenite
Copy link
Contributor

@irfanfaraaz could you try pulling from latest and run bun run db:push?

@irfanfaraaz
Copy link
Contributor Author

irfanfaraaz commented Jun 29, 2025

Just fixed that issue.. now facing this (in main)

image

@irfanfaraaz
Copy link
Contributor Author

Oh finally it's working.. guess morphllm was down

image

above screenshot is from vfs branch
@Kitenite

@Kitenite
Copy link
Contributor

Nice! Glad it's working. We're using relace for the prod version but interesting that morph went down

@irfanfaraaz
Copy link
Contributor Author

I’ve synced with main, retested and pushed my changes. everything is working as expected, finally, after debugging for the whole day.

image

@@ -439,20 +458,23 @@ export class VirtualFileSystem implements VirtualFileSystemInterface {
for (const sandboxPath of allFiles) {
try {
const vfsPath = this.toVFSPath(sandboxPath);
// Try to read as text first
const textContent = this.volume.readFileSync(vfsPath, {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue is that readFileSync with encoding: 'utf8' will attempt to decode binary files as UTF-8 text, which often succeeds but produces garbled/corrupted text instead of throwing an error. This means the catch block never executes for binary files.

const vfsPath = this.toVFSPath(sandboxPath);

// Determine if file is binary based on extension
const isBinary = this.isBinaryFile(sandboxPath);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I wrote an utility function to check

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I wasn’t aware of that. Got to learn something. Thanks for the changes, mate! @spartan-vutrannguyen

ctime: Date;
}

export interface VirtualFileSystemInterface extends FileOperations {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand why we need to re-implement this interface instead using the direct fs api from memfs

https://github.com/streamich/memfs/blob/master/docs/node/usage.md

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here’s what I’m doing and why:
Using Volume from memfs instead of (fs,vol):
I'm using Volume so each project/sandbox has its own isolated file system.
Wrapper Methods:
The wrappers handle path normalization (so callers can use relative paths for memfs) with the underlying this.volume instance
Persistence (new commit):
I switched to memfs’s toJSON()/fromJSON() for saving/restoring the file system.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The goal I was hoping to achieve was to potentially reduce the amount of code we have implementing a file system. To potentially have a better way to mirror the files system from the sandbox without implementing file system interfaces. Looks like this would not be feasible even with using memfs?

Seems like it's essentially the same amount of work and complexity with just a different persistence layer. I was hoping we would remove this class entirely and use memfs' interface directly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[feat] Implement vfs library for file system management
3 participants