Import and Export

@catmint-fs/sqlite-adapter can import files from a real directory on disk into the SQLite database and export the database contents back to disk. This page covers both the adapter methods and the standalone helper functions.

Importing from Disk

Using the Adapter

The importFrom method recursively copies all files, directories, and symlinks from a source path into the virtual filesystem:

import { SqliteAdapter } from "@catmint-fs/sqlite-adapter";
import { CatmintFs } from "@catmint-fs/core";

const adapter = new SqliteAdapter({ database: ":memory:" });
const fs = new CatmintFs(adapter);

// Import an entire project
await adapter.importFrom("./my-project");

// Files are now accessible through the virtual filesystem
const files = await fs.readdir("/");
console.log(files); // ["package.json", "src", "tsconfig.json", ...]

The import operation:

  • Walks the source directory recursively
  • Preserves file permissions (mode, uid, gid)
  • Preserves symlinks (stored as symlink entries, not resolved)
  • Records file sizes and timestamps
  • Runs inside a SQLite transaction for atomicity

Using the Standalone Helper

If you are managing the database connection yourself, use the standalone importFrom function:

import Database from "better-sqlite3";
import { initializeSchema, importFrom } from "@catmint-fs/sqlite-adapter";

const db = new Database("./snapshot.sqlite");
initializeSchema(db);

await importFrom(db, "./my-project");

Import Behavior

ScenarioBehavior
File already exists in DBOverwritten with the new content and metadata
Directory already existsMerged (existing files in DB are not deleted)
Symlink on diskStored as a symlink entry with the target path
Binary fileStored as a BLOB without encoding transformation
Empty directoryCreated as a directory entry with no children

Filtering Files

The import operation copies everything in the source directory. To filter files, pre-process the source directory or use the @catmint-fs/core API to remove unwanted entries after import:

await adapter.importFrom("./my-project");

// Remove node_modules after import
await fs.rm("/node_modules", { recursive: true });

Exporting to Disk

Using the Adapter

The exportTo method writes the entire virtual filesystem to a directory on disk:

const adapter = new SqliteAdapter({ database: "./my-fs.sqlite" });

// Export to a new directory
await adapter.exportTo("./output");

The export operation:

  • Creates the destination directory if it does not exist
  • Recreates the full directory tree
  • Writes all file contents
  • Restores symlinks
  • Applies file permissions (mode)

Using the Standalone Helper

import Database from "better-sqlite3";
import { exportTo } from "@catmint-fs/sqlite-adapter";

const db = new Database("./snapshot.sqlite");
await exportTo(db, "./output");

Export Behavior

ScenarioBehavior
Destination directory existsFiles are written into it (existing files may be overwritten)
Destination does not existCreated automatically
Symlink in databaseRecreated as a symlink on disk
File permissionsApplied via chmod after writing

Round-Trip Example

A common pattern is to capture a filesystem snapshot, perform operations on it, and write the results back to disk:

import { SqliteAdapter } from "@catmint-fs/sqlite-adapter";
import { CatmintFs } from "@catmint-fs/core";

// Capture a snapshot
const adapter = new SqliteAdapter({ database: "./snapshot.sqlite" });
const fs = new CatmintFs(adapter);
await adapter.importFrom("./my-project");

// Modify files in the virtual filesystem
const pkg = JSON.parse(await fs.readFile("/package.json", "utf8"));
pkg.version = "2.0.0";
await fs.writeFile("/package.json", JSON.stringify(pkg, null, 2));

// Export the modified filesystem
await adapter.exportTo("./my-project-v2");

await adapter.close();

Performance Tips

  • Use in-memory databases for temporary work. In-memory databases avoid disk I/O during the operation and are automatically cleaned up.
  • Import runs in a transaction. Importing a large directory is efficient because all writes are batched in a single SQLite transaction.
  • Close the adapter when done. This releases the database connection and any associated file locks.

See Also