readme.md for @git.zone/tsbuild A powerful, modern TypeScript build tool with smart defaults, full tsconfig.json support, automatic output directory management, and cross-module import path rewriting. Issue Reporting and Security For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly. Install # Using pnpm (recommended) pnpm install @git.zone/tsbuild --save-dev # Using npm npm install @git.zone/tsbuild --save-dev Why tsbuild? Feature Description Smart tsconfig.json Integration Respects all your compiler options with intelligent merging Protected Defaults Critical build settings are safeguarded while staying flexible Zero Config Works perfectly without tsconfig.json Glob Pattern Support Compile multiple directories with a single command Dependency-Aware Automatically orders compilation based on module dependencies Type Checking Validate code without emitting files Clean Builds Automatically clears output directories before compilation Auto-Unpack Flattens nested output directories automatically Import Path Rewriting Rewrites cross-module imports to point at compiled output CI/CD Ready JSON output mode and proper exit codes Modern Defaults ESNext, NodeNext modules, decorators out of the box Quick Start CLI Usage Compile your TypeScript project: npx tsbuild Compiles ./ts/**/*.ts to ./dist_ts/ Custom directories: npx tsbuild custom src utils Compiles: ./src/**/*.ts -> ./dist_src/ ./utils/**/*.ts -> ./dist_utils/ Auto-discover and compile in dependency order: npx tsbuild tsfolders Finds all ts_* folders and compiles them respecting dependencies. Programmatic Usage Basic compilation: import { TsCompiler } from '@git.zone/tsbuild'; const compiler = new TsCompiler(); await compiler.compileFilesOrThrow([ './src/index.ts', './src/utils.ts' ], { outDir: './dist' }); Production-ready with error tracking (recommended): import { TsCompiler } from '@git.zone/tsbuild'; const compiler = new TsCompiler(); const result = await compiler.compileFiles([ './src/index.ts', './src/utils.ts' ], { outDir: './dist' }); if (result.errorSummary.totalErrors > 0) { console.error(`Compilation failed with ${result.errorSummary.totalErrors} errors`); process.exit(1); } console.log(`Compiled ${result.emittedFiles.length} files successfully!`); Glob pattern compilation: import { TsCompiler } from '@git.zone/tsbuild'; const compiler = new TsCompiler(); await compiler.compileGlob({ './ts/**/*.ts': './dist_ts', './ts_web/**/*.ts': './dist_web' }); CLI Commands 1. Default Build npx tsbuild [options] Compiles all TypeScript files from ./ts/ to ./dist_ts/ Options: Flag Description --skiplibcheck Skip type checking of declaration files --confirmskiplibcheck Skip lib check with extended warning (5s pause) --disallowimplicitany Disallow implicit any types --commonjs Use CommonJS instead of ESNext modules --json Output results as JSON (for CI/CD) --quiet Suppress console output Examples: # Standard build npx tsbuild # Build with JSON output for CI npx tsbuild --json --quiet # CommonJS build npx tsbuild --commonjs # Strict mode npx tsbuild --disallowimplicitany 2. Custom Directories npx tsbuild custom ... [options] Compile specific directories to their corresponding dist_ folders. # Compile src and utils npx tsbuild custom src utils # Creates: ./dist_src/ and ./dist_utils/ # Multiple directories with options npx tsbuild custom api models services --commonjs 3. TSFolders (Dependency-Aware) npx tsbuild tsfolders [options] Automatically discovers and compiles all ts_* folders in dependency order: Prioritizes ts_interfaces first (if no tspublish.json) Prioritizes ts_shared second (if no tspublish.json) Reads tspublish.json in each folder for order property Compiles in correct sequence Example output: TypeScript Folder Compilation Plan (5 folders) 1. ts_interfaces 2. ts_shared 3. ts_core 4. ts_utils 5. ts_modules 4. Emit Check npx tsbuild emitcheck [more...] [options] Validates TypeScript files can be compiled without actually emitting them. # Check specific files npx tsbuild emitcheck src/main.ts src/utils.ts # Check with glob patterns npx tsbuild emitcheck "src/**/*.ts" "test/**/*.ts" Exit codes: 0 - All files can be emitted 1 - One or more files have errors 5. Type Check npx tsbuild check [pattern] [more...] [options] Performs type checking without emitting files. With arguments: Check specified files/patterns npx tsbuild check "ts/**/*.ts" npx tsbuild check "src/**/*.ts" "test/**/*.ts" Without arguments: Two-phase default check Phase 1: Type check ts/**/* (strict, includes .d.ts) Phase 2: Type check test/**/* (relaxed, skipLibCheck: true) npx tsbuild check # Running default type checking sequence... # Checking ts/**/* files... # Checking test/**/* files with --skiplibcheck... # All default type checks passed! API Reference TsCompiler Class The main class for TypeScript compilation. import { TsCompiler } from '@git.zone/tsbuild'; const compiler = new TsCompiler(cwd?: string, argvArg?: any); Constructor Parameters: cwd - Working directory (defaults to process.cwd()) argvArg - CLI arguments object for flags like --skiplibcheck, --quiet, etc. compileFiles(fileNames, customOptions?, taskInfo?) Compile files with error tracking. Returns result instead of throwing. const result = await compiler.compileFiles( ['./src/index.ts', './src/utils.ts'], { outDir: './dist' } ); console.log(`Emitted: ${result.emittedFiles.length} files`); console.log(`Errors: ${result.errorSummary.totalErrors}`); Returns: Promise interface ICompileResult { emittedFiles: string[]; errorSummary: IErrorSummary; } interface IErrorSummary { errorsByFile: Record; generalErrors: Diagnostic[]; totalErrors: number; totalFiles: number; } compileFilesOrThrow(fileNames, customOptions?) Compile files and throw on error. For simple scripts. try { const emittedFiles = await compiler.compileFilesOrThrow( ['./src/index.ts'], { outDir: './dist' } ); console.log('Compiled:', emittedFiles); } catch (error) { console.error('Compilation failed!'); process.exit(1); } Returns: Promise - Array of emitted file paths compileGlob(globPatterns, customOptions?) Compile multiple glob patterns to different destinations. Automatically clears output directories before compilation, unpacks nested output, and rewrites cross-module import paths. const result = await compiler.compileGlob({ './ts/**/*.ts': './dist_ts', './ts_web/**/*.ts': './dist_web', './ts_node/**/*.ts': './dist_node' }); Returns: Promise checkTypes(fileNames, customOptions?) Type check files without emitting. Fast validation. const success = await compiler.checkTypes(['./src/**/*.ts']); if (!success) { console.error('Type errors found!'); process.exit(1); } Returns: Promise - true if no errors checkEmit(fileNames, customOptions?) Validate files can be emitted without actually emitting. const canEmit = await compiler.checkEmit(['./src/index.ts']); if (!canEmit) { console.error('Cannot emit these files!'); } Returns: Promise - true if can emit createOptions(customOptions?) Get merged compiler options (useful for debugging). const options = compiler.createOptions({ strict: true }); console.log(options); // Shows merged options Supporting Classes TsConfig TypeScript configuration management. import { TsConfig } from '@git.zone/tsbuild'; const config = new TsConfig(process.cwd()); const options = config.merge({ target: 'ES2022' }, argvArg); TsPublishConfig Reads tspublish.json for module configuration. import { TsPublishConfig } from '@git.zone/tsbuild'; const pubConfig = new TsPublishConfig('./ts_core'); console.log(pubConfig.shouldUnpack); // true/false console.log(pubConfig.order); // number or undefined TsUnpacker Flattens nested TypeScript output directories. import { TsUnpacker } from '@git.zone/tsbuild'; const unpacker = new TsUnpacker('ts_core', './dist_ts_core'); await unpacker.unpack(); TsPathRewriter Rewrites cross-module import paths in compiled output files. When TypeScript compiles files that import from sibling directories (e.g., ../ts_shared/helper.js), TsPathRewriter rewrites those paths to reference the compiled output directories ( ../dist_ts_shared/helper.js). import { TsPathRewriter } from '@git.zone/tsbuild'; // Auto-detect all ts_* folders in the project const rewriter = await TsPathRewriter.fromProjectDirectory(process.cwd()); const filesModified = await rewriter.rewriteDirectory('./dist_ts_core'); // Or from explicit glob patterns const rewriter2 = TsPathRewriter.fromGlobPatterns({ './ts_core/**/*.ts': './dist_ts_core', './ts_shared/**/*.ts': './dist_ts_shared', }); FsHelpers Static filesystem utilities. import { FsHelpers } from '@git.zone/tsbuild'; const files = await FsHelpers.listFilesWithGlob('./', 'ts/**/*.ts'); const exists = await FsHelpers.fileExists('./tsconfig.json'); const dirExists = await FsHelpers.directoryExists('./ts'); TsBuildCli CLI command handler. Used internally by the CLI. import { TsBuildCli, runCli } from '@git.zone/tsbuild'; // Run the CLI runCli(); // Or with custom working directory const cli = new TsBuildCli('/path/to/project'); cli.run(); Configuration tsconfig.json Support tsbuild fully supports all compiler options from tsconfig.json. Your project configuration is respected and intelligently merged. { "compilerOptions": { "target": "ES2022", "module": "NodeNext", "moduleResolution": "NodeNext", "strict": true, "esModuleInterop": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, "verbatimModuleSyntax": true } } Configuration Priority (5 Levels) When multiple configuration sources exist, they merge in this order (later overrides earlier): Priority Source Description 1 Default Options tsbuild's sensible defaults 2 tsconfig.json All options from your tsconfig.json (if present) 3 Protected Defaults Critical options for build integrity 4 Programmatic Options Options passed to API functions 5 CLI Flags Command-line arguments (highest priority) Protected Options These options cannot be overridden by tsconfig.json alone (but can be overridden programmatically or via CLI): Option Value Reason outDir 'dist_ts/' Required for automatic path transformations noEmitOnError true Prevents broken builds from being emitted declaration true Ensures .d.ts files for library consumers inlineSourceMap true Consistent debugging experience Default Compiler Options When no tsconfig.json exists: { declaration: true, // Generate .d.ts files inlineSourceMap: true, // Debug-friendly noEmitOnError: true, // Fail-fast on errors outDir: 'dist_ts/', // Output directory module: 'NodeNext', // Modern Node.js modules target: 'ESNext', // Latest JavaScript moduleResolution: 'NodeNext', noImplicitAny: false, // Flexible for quick development esModuleInterop: true, // CJS/ESM interop verbatimModuleSyntax: true // Explicit imports/exports } Path Transformation tsbuild automatically transforms path mappings: tsconfig.json: { "compilerOptions": { "paths": { "@models/*": ["./ts_models/*"] } } } Automatic transformation: ./ts_models/* -> ./dist_ts_models/* Features Clean Builds Output directories are automatically cleared before compilation: Clearing output directory: ./dist_ts Compiling 14 files from ./ts/**/*.ts This ensures no stale files remain from previous builds. Import Path Rewriting When working with multi-module projects (multiple ts_* folders), TypeScript compiles import paths relative to source directories. After compilation and unpacking, these paths would be wrong because the directory structure changes. tsbuild automatically detects all ts_* folders in the project and rewrites import paths in the compiled output: # Source code import { helper } from '../ts_shared/helper.js'; # Compiled output (after rewriting) import { helper } from '../dist_ts_shared/helper.js'; This works for ES module imports, dynamic import() calls, and CommonJS require() statements. The rewriting happens automatically as part of compileGlob(). Monorepo Support with tspublish tsbuild is designed to work seamlessly with @git.zone/tspublish for monorepo workflows. This enables building and publishing multiple packages from a single repository. Directory Structure my-project/ ts/ # Main package source ts_interfaces/ # Shared interfaces (order: 1) ts_shared/ # Shared utilities (order: 2) ts_core/ # Core logic (order: 3) ts_web/ # Web-specific code (order: 4) ts_node/ # Node-specific code (order: 5) Each ts_* folder can contain its own tspublish.json to configure compilation and publishing behavior. tspublish.json Configuration Create a tspublish.json in each ts_* folder: { "name": "@myorg/core", "order": 3, "unpack": true, "dependencies": ["ts_interfaces", "ts_shared"] } Option Type Default Description name string -- Package name for publishing order number Infinity Build sequence (lower builds first) unpack boolean true Flatten nested output directories dependencies string[] -- Monorepo dependencies to bundle Build Order The tsfolders command respects the order property: npx tsbuild tsfolders Default ordering (without tspublish.json): ts_interfaces - always first (shared types) ts_shared - always second (shared utilities) Other folders sorted by order property Folders without order are built last Auto-Unpack When TypeScript compiles files that import from sibling directories, it creates nested output: dist_ts_core/ ts_core/ <-- nested output ts_shared/ <-- pulled-in dependency tsbuild automatically flattens this to: dist_ts_core/ index.js <-- flat, clean structure This is especially important for monorepos where packages import from each other. Control via tspublish.json: { "unpack": true } "unpack": true (default) - Flatten nested directories after compilation "unpack": false - Keep original nested structure What gets unpacked: The source folder's contents ( ts_core/) are moved to the root of dist_ts_core/ Sibling folders ( ts_shared/) that were pulled in are removed (they have their own dist) Decorator Support tsbuild supports both TC39 standard decorators (recommended) and legacy experimental decorators. TC39 Standard Decorators (Preferred) We strongly recommend using TC39 standard decorators for all new code. They are the official JavaScript standard and provide better semantics: // TC39 standard decorator function log(target: any, context: ClassMethodDecoratorContext) { return function (...args: any[]) { console.log(`Calling ${String(context.name)}`); return target.apply(this, args); }; } class UserService { @log getUser(id: string) { return { id, name: 'John' }; } } Legacy Decorators (Backwards Compatibility) For existing projects using frameworks that still require experimental decorators: { "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true } } Structured Logging tsbuild uses a 4-level visual hierarchy for console output, making it easy to follow compilation progress: HEADER - Top-level section start (emoji + bold text + separator) STEP - Major action within a section (emoji + text) DETAIL - Supplementary info under a step (indented) SUCCESS/ERROR/WARN - Outcome indicators with color coding All output uses ANSI color codes for terminal readability. Use --quiet to suppress output or --json for machine-readable format. CI/CD Integration GitHub Actions name: Build on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '22' - run: npm install - run: npx tsbuild JSON Output npx tsbuild --json --quiet { "success": true, "totals": { "errors": 0, "filesWithErrors": 0, "tasks": 1 }, "errorsByFile": {} } Package.json Scripts { "scripts": { "build": "tsbuild", "build:prod": "tsbuild --disallowimplicitany", "typecheck": "tsbuild check", "pretest": "tsbuild emitcheck 'test/**/*.ts'" } } Troubleshooting Common Issues "Cannot find module" errors in compiled output Make sure path mappings are configured in tsconfig.json. tsbuild automatically transforms them. Decorator errors Ensure your tsconfig.json has: { "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true } } Slow compilation Use --skiplibcheck to skip declaration file checking: npx tsbuild --skiplibcheck Only use this if you trust your dependencies' type definitions. License and Legal Information This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the LICENSE file. Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file. Trademarks This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar. Company Information Task Venture Capital GmbH Registered at District Court Bremen HRB 35230 HB, Germany For any legal inquiries or further information, please contact us via email at hello@task.vc. By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.