CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-projen

CDK for software projects - synthesizes configuration files from well-typed JavaScript/TypeScript definitions.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

file-management.mddocs/

File Management

Abstract file system for managing configuration files, source code, and generated content. Projen provides a comprehensive file management system that handles different file types with synthesis markers and read-only protection.

Capabilities

FileBase Class

Abstract base class for all file types in projen, providing common file operations and synthesis lifecycle.

/**
 * Base class for all file types in projen
 * Provides common file operations and synthesis lifecycle
 */
abstract class FileBase extends Component {
  constructor(scope: IConstruct, filePath: string, options?: FileBaseOptions);
  
  /** Relative file path from project root */
  readonly path: string;
  /** Absolute file path on disk */
  readonly absolutePath: string;
  /** Whether the file is read-only (has projen marker) */
  readonly readonly: boolean;
  /** Whether the file has executable permissions */
  readonly executable: boolean;
  /** Projen marker text (null if not a generated file) */
  readonly marker?: string;
  
  /** Called during synthesis to write file content */
  protected abstract synthesizeContent(resolver: IResolver): string | undefined;
}

interface FileBaseOptions {
  /** Whether the file is read-only (default: true for generated files) */
  readonly?: boolean;
  /** Whether the file should be executable */
  executable?: boolean;
  /** Custom marker text for generated files */
  marker?: string;
  /** Whether to commit this file to git */
  committed?: boolean;
}

JsonFile Class

JSON file management with object manipulation and projen marker support.

/**
 * Represents a JSON file with projen marker support
 * Provides object-based manipulation of JSON content
 */
class JsonFile extends ObjectFile {
  constructor(scope: IConstruct, filePath: string, options?: JsonFileOptions);
  
  /** The JSON object content */
  readonly obj: any;
  
  /** Add or update a property in the JSON object */
  addOverride(path: string, value: any): void;
  /** Add to an array property */
  addToArray(path: string, ...values: any[]): void;
  /** Remove a property from the JSON object */
  removeProperty(path: string): void;
  /** Get a property value */
  getProperty(path: string): any;
}

interface JsonFileOptions extends ObjectFileOptions {
  /** JSON object content */
  obj?: any;
  /** Custom JSON formatting options */
  formatting?: JsonFormattingOptions;
}

interface JsonFormattingOptions {
  /** Number of spaces for indentation (default: 2) */
  indent?: number;
  /** Whether to add trailing newline */
  newline?: boolean;
}

JSON File Example:

import { Project, JsonFile } from "projen";

const project = new Project({ name: "json-example" });

// Create package.json
const packageJson = new JsonFile(project, "package.json", {
  obj: {
    name: "my-package",
    version: "1.0.0",
    main: "index.js",
    scripts: {},
    dependencies: {},
  },
});

// Modify JSON content
packageJson.addOverride("scripts.build", "tsc");
packageJson.addOverride("scripts.test", "jest");
packageJson.addToArray("keywords", "typescript", "projen");

// Add nested properties
packageJson.addOverride("author.name", "Jane Developer");
packageJson.addOverride("author.email", "jane@example.com");

// Remove properties
packageJson.removeProperty("main");

YamlFile Class

YAML file management with object manipulation.

/**
 * Represents a YAML file with projen marker support
 * Provides object-based manipulation of YAML content
 */
class YamlFile extends ObjectFile {
  constructor(scope: IConstruct, filePath: string, options?: YamlFileOptions);
  
  /** The YAML object content */
  readonly obj: any;
  
  /** Add or update a property in the YAML object */
  addOverride(path: string, value: any): void;
  /** Add to an array property */
  addToArray(path: string, ...values: any[]): void;
}

interface YamlFileOptions extends ObjectFileOptions {
  /** YAML object content */
  obj?: any;
  /** Line width for YAML formatting */
  lineWidth?: number;
  /** Whether to use flow style for sequences */
  flowSequences?: boolean;
}

YAML File Example:

import { Project, YamlFile } from "projen";

const project = new Project({ name: "yaml-example" });

// Create GitHub workflow
const workflow = new YamlFile(project, ".github/workflows/ci.yml", {
  obj: {
    name: "CI",
    on: {
      push: { branches: ["main"] },
      pull_request: { branches: ["main"] },
    },
    jobs: {
      test: {
        "runs-on": "ubuntu-latest",
        steps: [],
      },
    },
  },
});

// Add steps to workflow
workflow.addToArray("jobs.test.steps", {
  uses: "actions/checkout@v3",
});

workflow.addToArray("jobs.test.steps", {
  uses: "actions/setup-node@v3",
  with: {
    "node-version": "18",
  },
});

TextFile Class

Plain text file management with line-based manipulation.

/**
 * Plain text file with line-based manipulation
 * Suitable for configuration files, source code, and documentation
 */
class TextFile extends FileBase {
  constructor(scope: IConstruct, filePath: string, options?: TextFileOptions);
  
  /** All lines in the file */
  readonly lines: string[];
  
  /** Add a line to the file */
  addLine(line: string): void;
  /** Add multiple lines to the file */
  addLines(...lines: string[]): void;
  /** Insert a line at specific position */
  insertLine(index: number, line: string): void;
  /** Remove a line by content */
  removeLine(line: string): void;
  /** Remove a line by index */
  removeLineAt(index: number): void;
  /** Check if file contains a line */
  hasLine(line: string): boolean;
}

interface TextFileOptions extends FileBaseOptions {
  /** Initial lines for the file */
  lines?: string[];
  /** Line ending style */
  lineEnding?: LineEnding;
}

enum LineEnding {
  /** Unix line endings (\n) */
  LF = "lf",
  /** Windows line endings (\r\n) */
  CRLF = "crlf",
  /** Automatic based on platform */
  AUTO = "auto"
}

Text File Example:

import { Project, TextFile } from "projen";

const project = new Project({ name: "text-example" });

// Create .gitignore file
const gitignore = new TextFile(project, ".gitignore", {
  lines: [
    "node_modules/",
    "*.log",
    ".env",
  ],
});

// Add more patterns
gitignore.addLine("dist/");
gitignore.addLine("coverage/");
gitignore.addLines(
  "# IDE files",
  ".vscode/",
  ".idea/",
);

// Create README
const readme = new TextFile(project, "README.md", {
  lines: [
    "# My Project",
    "",
    "Description of my project.",
  ],
});

readme.addLines(
  "",
  "## Installation",
  "",
  "```bash",
  "npm install",
  "```",
);

SampleFile Class

Sample code files that are only created if they don't exist.

/**
 * Sample code files that are only created if they don't already exist
 * Used for generating example code and configuration templates
 */
class SampleFile extends FileBase {
  constructor(scope: IConstruct, filePath: string, options?: SampleFileOptions);
  
  /** File content */
  readonly content: string;
}

interface SampleFileOptions extends FileBaseOptions {
  /** File content */
  content: string;
  /** Source file to copy from */
  sourcePath?: string;
}

Sample File Example:

import { TypeScriptProject, SampleFile } from "projen";

const project = new TypeScriptProject({
  name: "sample-example",
  sampleCode: false, // Disable automatic samples
});

// Create custom sample files
new SampleFile(project, "src/hello.ts", {
  content: `export function hello(name: string): string {
  return \`Hello, \${name}!\`;
}
`,
});

new SampleFile(project, "test/hello.test.ts", {
  content: `import { hello } from '../src/hello';

describe('hello', () => {
  test('should greet correctly', () => {
    expect(hello('World')).toBe('Hello, World!');
  });
});
`,
});

// Sample configuration file
new SampleFile(project, ".env.example", {
  content: `# Environment variables
API_KEY=your_api_key_here
DATABASE_URL=postgresql://localhost:5432/mydb
`,
});

IgnoreFile Class

Manages ignore pattern files like .gitignore, .npmignore.

/**
 * Manages ignore pattern files (.gitignore, .npmignore, etc.)
 * Provides pattern-based file exclusion functionality
 */
class IgnoreFile extends TextFile {
  constructor(scope: IConstruct, filePath: string, options?: IgnoreFileOptions);
  
  /** Add ignore pattern */
  addPattern(pattern: string): void;
  /** Add multiple ignore patterns */
  addPatterns(...patterns: string[]): void;
  /** Remove ignore pattern */
  removePattern(pattern: string): void;
  /** Check if pattern exists */
  hasPattern(pattern: string): boolean;
  /** Add comment */
  addComment(comment: string): void;
}

interface IgnoreFileOptions extends TextFileOptions {
  /** Initial ignore patterns */
  ignorePatterns?: string[];
}

Ignore File Example:

import { Project, IgnoreFile } from "projen";

const project = new Project({ name: "ignore-example" });

// Create custom .gitignore
const gitignore = new IgnoreFile(project, ".gitignore", {
  ignorePatterns: [
    "node_modules/",
    "*.log",
  ],
});

gitignore.addComment("Build artifacts");
gitignore.addPatterns(
  "dist/",
  "build/",
  "lib/",
);

gitignore.addComment("Environment files");
gitignore.addPattern(".env*");

// Create .dockerignore
const dockerignore = new IgnoreFile(project, ".dockerignore", {
  ignorePatterns: [
    "node_modules/",
    ".git/",
    "README.md",
    "Dockerfile",
    ".dockerignore",
  ],
});

ObjectFile Class

Base class for files that represent structured objects (JSON, YAML, etc.).

/**
 * Base class for files that represent structured objects
 * Provides common functionality for JSON, YAML, and other object files
 */
abstract class ObjectFile extends FileBase {
  constructor(scope: IConstruct, filePath: string, options?: ObjectFileOptions);
  
  /** The object content */
  readonly obj: any;
  
  /** Add or update a property using dot notation */
  addOverride(path: string, value: any): void;
  /** Remove a property using dot notation */
  removeProperty(path: string): void;
  /** Get a property value using dot notation */
  getProperty(path: string): any;
  /** Check if property exists */
  hasProperty(path: string): boolean;
  /** Add to array property */
  addToArray(path: string, ...values: any[]): void;
  /** Merge object into property */
  mergeObject(path: string, obj: any): void;
}

interface ObjectFileOptions extends FileBaseOptions {
  /** Initial object content */
  obj?: any;
  /** Whether to omit empty values */
  omitEmpty?: boolean;
}

Types

File-Related Types

interface IResolver {
  /** Resolve tokens in content */
  resolve(obj: any): any;
}

interface FileSystemOptions {
  /** Base directory for file operations */
  baseDir?: string;
  /** Default file permissions */
  defaultPermissions?: string;
  /** Whether to create directories automatically */
  autoCreateDirs?: boolean;
}

enum FileType {
  TEXT = "text",
  JSON = "json",
  YAML = "yaml",
  BINARY = "binary"
}

Install with Tessl CLI

npx tessl i tessl/npm-projen

docs

awscdk-projects.md

core-project.md

dependency-management.md

file-management.md

github-integration.md

index.md

java-projects.md

nodejs-projects.md

python-projects.md

task-management.md

typescript-projects.md

web-projects.md

tile.json