CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ts-morph

TypeScript compiler wrapper for static analysis and code manipulation.

Pending
Overview
Eval results
Files

file-system.mddocs/

File System Operations

Comprehensive file system operations and directory management capabilities integrated with the project structure. Provides seamless integration between TypeScript code manipulation and file system operations.

Capabilities

Directory Class

Represents a directory within the project with full manipulation capabilities.

class Directory {
  /** Get the directory name */
  getName(): string;
  
  /** Get the full path */
  getPath(): string;
  
  /** Get the base name (same as getName) */
  getBaseName(): string;
  
  /** Get the parent directory */
  getParent(): Directory | undefined;
  
  /** Get all child directories */
  getDirectories(): Directory[];
  
  /** Get a child directory by name */
  getDirectory(name: string): Directory | undefined;
  
  /** Get a child directory by name, throwing if not found */
  getDirectoryOrThrow(name: string): Directory;
  
  /** Get all source files in this directory */
  getSourceFiles(): SourceFile[];
  
  /** Get a source file by name */
  getSourceFile(name: string): SourceFile | undefined;
  
  /** Get a source file by name, throwing if not found */
  getSourceFileOrThrow(name: string): SourceFile;
  
  /** Create a child directory */
  createDirectory(name: string): Directory;
  
  /** Create a source file in this directory */
  createSourceFile(fileName: string, text?: string, options?: SourceFileCreateOptions): SourceFile;
  
  /** Add an existing source file to this directory */
  addSourceFileAtPath(filePath: string): SourceFile;
  
  /** Add an existing source file to this directory if it exists */
  addSourceFileAtPathIfExists(filePath: string): SourceFile | undefined;
  
  /** Add existing source files matching a glob pattern */
  addSourceFilesAtPaths(fileGlobs: string | string[]): SourceFile[];
  
  /** Copy this directory to a new location */
  copy(dirPath: string, options?: DirectoryCopyOptions): Directory;
  
  /** Move this directory to a new location */
  move(dirPath: string, options?: DirectoryMoveOptions): Directory;
  
  /** Delete this directory */
  delete(): void;
  
  /** Check if this directory exists on the file system */
  exists(): boolean;
  
  /** Check if this directory exists on the file system asynchronously */
  existsAsync(): Promise<boolean>;
  
  /** Emit all TypeScript files in this directory */
  emit(options?: { emitOnlyDtsFiles?: boolean }): Promise<DirectoryEmitResult>;
  
  /** Emit all TypeScript files in this directory synchronously */
  emitSync(options?: { emitOnlyDtsFiles?: boolean }): DirectoryEmitResult;
  
  /** Save all unsaved source files in this directory */
  save(): Promise<void>;
  
  /** Save all unsaved source files in this directory synchronously */
  saveSync(): void;
  
  /** Get descendants (all nested directories and files) */
  getDescendants(): (Directory | SourceFile)[];
  
  /** Get descendant directories */
  getDescendantDirectories(): Directory[];
  
  /** Get descendant source files */
  getDescendantSourceFiles(): SourceFile[];
}

interface DirectoryCopyOptions {
  /** Whether to overwrite existing files */
  overwrite?: boolean;
  
  /** Whether to include directories */
  includeUntrackedFiles?: boolean;
}

interface DirectoryMoveOptions {
  /** Whether to overwrite existing files */
  overwrite?: boolean;
}

interface DirectoryAddOptions {
  /** Whether to recursively add subdirectories */
  recursive?: boolean;
}

Directory Emit Result

Result of emitting TypeScript files in a directory.

class DirectoryEmitResult {
  /** Get all emit results for files in the directory */
  getEmitResults(): EmitResult[];
  
  /** Check if any emits were skipped */
  getEmitSkipped(): boolean;
  
  /** Get all diagnostics from the emit operation */
  getDiagnostics(): Diagnostic[];
  
  /** Get output file paths that were created */
  getOutputFilePaths(): string[];
}

File System Host

Interface for custom file system implementations.

interface FileSystemHost {
  /** Check if a file or directory exists */
  exists(path: string): boolean;
  
  /** Check if a file or directory exists asynchronously */
  existsAsync(path: string): Promise<boolean>;
  
  /** Read a file as text */
  readFileSync(path: string, encoding?: string): string;
  
  /** Read a file as text asynchronously */
  readFile(path: string, encoding?: string): Promise<string>;
  
  /** Write text to a file */
  writeFileSync(path: string, data: string): void;
  
  /** Write text to a file asynchronously */
  writeFile(path: string, data: string): Promise<void>;
  
  /** Create a directory */
  mkdirSync(path: string): void;
  
  /** Create a directory asynchronously */
  mkdir(path: string): Promise<void>;
  
  /** Delete a file or directory */
  deleteSync(path: string): void;
  
  /** Delete a file or directory asynchronously */
  delete(path: string): Promise<void>;
  
  /** Get directory entries */
  readDirSync(path: string): RuntimeDirEntry[];
  
  /** Copy a file */
  copySync(srcPath: string, destPath: string): void;
  
  /** Copy a file asynchronously */
  copy(srcPath: string, destPath: string): Promise<void>;
  
  /** Move a file */
  moveSync(srcPath: string, destPath: string): void;
  
  /** Move a file asynchronously */
  move(srcPath: string, destPath: string): Promise<void>;
  
  /** Get file or directory stats */
  statSync(path: string): StatSync;
  
  /** Get file or directory stats asynchronously */
  stat(path: string): Promise<Stat>;
  
  /** Resolve a path */
  realPathSync(path: string): string;
  
  /** Get current working directory */
  getCurrentDirectory(): string;
  
  /** Get the path separator */
  getPathSeparator(): string;
}

interface RuntimeDirEntry {
  name: string;
  isFile(): boolean;
  isDirectory(): boolean;
  isSymlink(): boolean;
}

interface StatSync {
  isFile(): boolean;
  isDirectory(): boolean;
  size: number;
  mtimeMs: number;
}

interface Stat {
  isFile(): boolean;
  isDirectory(): boolean;
  size: number;
  mtimeMs: number;
}

In-Memory File System

Built-in in-memory file system implementation for testing and virtual file operations.

class InMemoryFileSystemHost implements FileSystemHost {
  /** Create a new in-memory file system */
  constructor();
  
  /** Get all files and directories in memory */
  getFiles(): { path: string; text: string }[];
  
  /** Clear all files and directories */
  clear(): void;
  
  /** Get a file's text content */
  getFileText(path: string): string;
  
  /** Check if path is a directory */
  isDirectory(path: string): boolean;
  
  /** Check if path is a file */
  isFile(path: string): boolean;
  
  // ... implements all FileSystemHost methods
}

Source File Operations

Extended file operations available on SourceFile instances.

interface SourceFileCopyOptions {
  /** Whether to overwrite if the target exists */
  overwrite?: boolean;
}

interface SourceFileMoveOptions {
  /** Whether to overwrite if the target exists */
  overwrite?: boolean;
}

// Additional SourceFile methods for file system operations
class SourceFile extends Node {
  /** Get the directory containing this source file */
  getDirectory(): Directory;
  
  /** Get the directory path */
  getDirectoryPath(): string;
  
  /** Check if the file is in a node_modules directory */
  isInNodeModules(): boolean;
  
  /** Check if this is a declaration file (.d.ts) */
  isDeclarationFile(): boolean;
  
  /** Check if the file has been modified */
  isModified(): boolean;
  
  /** Get the last modified time */
  getModifiedTime(): Date;
  
  /** Refresh from file system */
  refreshFromFileSystemSync(): this;
  
  /** Refresh from file system asynchronously */
  refreshFromFileSystem(): Promise<this>;
  
  /** Get referenced files */
  getReferencedFiles(): SourceFile[];
  
  /** Get files that reference this file */
  getReferencingSourceFiles(): SourceFile[];
  
  /** Get files that reference this file (including library files) */
  getReferencingNodesInOtherSourceFiles(): SourceFileReferencingNodes[];
  
  /** Get the relative path from another source file */
  getRelativePathTo(sourceFile: SourceFile): string;
  
  /** Get the relative path from a directory */
  getRelativePathToDirectory(directory: Directory): string;
}

interface SourceFileReferencingNodes {
  sourceFile: SourceFile;
  nodes: Node[];
}

Usage Examples:

import { Project, InMemoryFileSystemHost } from "ts-morph";

// Working with the default file system
const project = new Project();

// Add a directory
const srcDir = project.createDirectory("src");
const utilsDir = srcDir.createDirectory("utils");

// Create files in directories
const indexFile = srcDir.createSourceFile("index.ts", `
export { Logger } from './utils/logger';
export { Calculator } from './utils/calculator';
`);

const loggerFile = utilsDir.createSourceFile("logger.ts", `
export class Logger {
  log(message: string): void {
    console.log(message);
  }
}
`);

const calculatorFile = utilsDir.createSourceFile("calculator.ts", `
export class Calculator {
  add(a: number, b: number): number {
    return a + b;
  }
  
  multiply(a: number, b: number): number {
    return a * b;
  }
}
`);

// Work with directories
console.log("Source directory name:", srcDir.getName());
console.log("Source directory path:", srcDir.getPath());

// Get files and subdirectories
const srcFiles = srcDir.getSourceFiles();
console.log("Files in src:", srcFiles.map(f => f.getBaseName()));

const subdirs = srcDir.getDirectories();
console.log("Subdirectories:", subdirs.map(d => d.getName()));

// Get all descendant files
const allFiles = srcDir.getDescendantSourceFiles();
console.log("All files recursively:", allFiles.map(f => f.getBaseName()));

// File operations
const backupDir = project.createDirectory("backup");
loggerFile.copy("backup/logger-backup.ts");

// Directory operations
const utilsCopy = utilsDir.copy("src/utils-backup");
console.log("Copied utils to:", utilsCopy.getPath());

// Save all files
project.saveSync();

// Emit TypeScript files
const emitResult = await srcDir.emit();
console.log("Emit successful:", !emitResult.getEmitSkipped());
console.log("Output files:", emitResult.getOutputFilePaths());

Working with In-Memory File System:

import { Project, InMemoryFileSystemHost } from "ts-morph";

// Create project with in-memory file system
const fileSystem = new InMemoryFileSystemHost();
const project = new Project({
  fileSystem,
  useInMemoryFileSystem: true,
});

// Create virtual files
const sourceFile = project.createSourceFile("/virtual/app.ts", `
class VirtualApp {
  run(): void {
    console.log('Running in memory!');
  }
}
`);

// Work with virtual directories
const virtualDir = project.createDirectory("/virtual");
const configFile = virtualDir.createSourceFile("config.ts", `
export const config = {
  port: 3000,
  host: 'localhost'
};
`);

// Check file system state
console.log("Virtual files:", fileSystem.getFiles());

// The files exist only in memory
console.log("App file exists:", fileSystem.exists("/virtual/app.ts"));
console.log("App file content:", fileSystem.getFileText("/virtual/app.ts"));

// Clear the virtual file system
fileSystem.clear();
console.log("Files after clear:", fileSystem.getFiles());

Advanced File System Operations:

import { Project } from "ts-morph";

const project = new Project();

// Add files from glob patterns
const srcDir = project.createDirectory("src");
srcDir.addSourceFilesAtPaths(["**/*.ts", "!**/*.test.ts"]);

// Get file relationships
const indexFile = srcDir.getSourceFile("index.ts");
if (indexFile) {
  // Get files that this file references
  const referenced = indexFile.getReferencedFiles();
  console.log("Referenced files:", referenced.map(f => f.getFilePath()));
  
  // Get files that reference this file
  const referencing = indexFile.getReferencingSourceFiles();
  console.log("Files referencing index:", referencing.map(f => f.getFilePath()));
  
  // Get relative paths
  const utilsFile = srcDir.getSourceFile("utils/helper.ts");
  if (utilsFile) {
    const relativePath = indexFile.getRelativePathTo(utilsFile);
    console.log("Relative path to utils:", relativePath);
  }
}

// Monitor file changes
const watchedFile = srcDir.getSourceFile("watched.ts");
if (watchedFile) {
  const initialModTime = watchedFile.getModifiedTime();
  
  // Modify the file
  watchedFile.addClass({ name: "NewClass" });
  
  // Check if modified
  console.log("File is modified:", watchedFile.isModified());
  console.log("Modified time changed:", 
    watchedFile.getModifiedTime() > initialModTime);
}

// Batch operations on directories
const testDir = project.createDirectory("tests");

// Create multiple test files
const testFiles = [
  "user.test.ts",
  "auth.test.ts", 
  "api.test.ts"
].map(name => testDir.createSourceFile(name, `
describe('${name.replace('.test.ts', '')}', () => {
  test('should work', () => {
    expect(true).toBe(true);
  });
});
`));

// Save all test files at once
await testDir.save();

// Emit only declaration files
const emitResult = await testDir.emit({ emitOnlyDtsFiles: true });
console.log("Declaration files emitted:", emitResult.getOutputFilePaths());

Install with Tessl CLI

npx tessl i tessl/npm-ts-morph

docs

ast-nodes.md

code-generation.md

file-system.md

index.md

project-management.md

type-system.md

tile.json