jkunz 3f4d0bf768
Default (tags) / security (push) Failing after 1s
Default (tags) / test (push) Failing after 0s
Default (tags) / metadata (push) Skipped
v5.0.0
2026-09-23 19:52:37 +00:00
2026-09-23 19:52:37 +00:00
2026-09-23 19:52:37 +00:00
2022-03-12 21:09:33 +01:00
2022-03-12 19:32:15 +01:00
2023-08-26 15:34:42 +02:00
2026-09-23 19:52:37 +00:00

@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

pnpm add --save-dev @git.zone/tsbuild

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
Folder tsconfig.json A source folder can compile in its own environment, such as a service worker with the webworker library, and editors read the same settings
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:

pnpm exec tsbuild

Compiles ./ts/**/*.ts to ./dist_ts/

Custom directories:

pnpm exec tsbuild custom src utils

Compiles:

  • ./src/**/*.ts -> ./dist_src/
  • ./utils/**/*.ts -> ./dist_utils/

Auto-discover and compile in dependency order:

pnpm exec 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'
});

Using tsbuild's TypeScript compiler

Tooling that works on TypeScript sources - codemods, naming specs, AST assertions in tests - needs the compiler API. Importing typescript directly means declaring a second compiler dependency, and because pnpm does not hoist transitive packages that dependency is both mandatory and free to drift away from the version tsbuild builds with.

tsbuild owns the compiler version and exposes it:

import { typescript } from '@git.zone/tsbuild/typescript';

const sourceFile = typescript.createSourceFile(
  'example.ts',
  'export const answer = 42;',
  typescript.ScriptTarget.ESNext,
  true
);

typescript.forEachChild(sourceFile, (node: typescript.Node) => {
  console.log(typescript.SyntaxKind[node.kind]);
});

The @git.zone/tsbuild/typescript entry has no side effects: it loads the compiler and nothing else of tsbuild, so it is the entry to use from tooling and tests. The same compiler is also reachable as import { typescript } from '@git.zone/tsbuild', which loads all of tsbuild.

Both values are the compiler instance tsbuild compiles with, types included - the same module object tsbuild's own TsCompiler calls, not a second copy. That is the guarantee: one compiler in your tree, resolved from tsbuild's typescript dependency range instead of from a second range you declare and have to keep in sync. Because that range is a caret range, a tsbuild version does not pin one exact compiler version - your lockfile does; upgrading tsbuild is what moves the range.

CLI Commands

1. Default Build

pnpm exec 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
pnpm exec tsbuild

# Build with JSON output for CI
pnpm exec tsbuild --json --quiet

# CommonJS build
pnpm exec tsbuild --commonjs

# Strict mode
pnpm exec tsbuild --disallowimplicitany

2. Custom Directories

pnpm exec tsbuild custom <dir1> <dir2> ... [options]

Compile specific directories to their corresponding dist_ folders.

# Compile src and utils
pnpm exec tsbuild custom src utils
# Creates: ./dist_src/ and ./dist_utils/

# Multiple directories with options
pnpm exec tsbuild custom api models services --commonjs

3. TSFolders (Dependency-Aware)

pnpm exec tsbuild tsfolders [options]

Automatically discovers and compiles all ts_* folders in dependency order:

  1. Prioritizes ts_interfaces first (if no tspublish.json)
  2. Prioritizes ts_shared second (if no tspublish.json)
  3. Reads tspublish.json in each folder for order property
  4. 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

pnpm exec tsbuild emitcheck <file_or_pattern> [more...] [options]

Validates TypeScript files can be compiled without actually emitting them.

# Check specific files
pnpm exec tsbuild emitcheck src/main.ts src/utils.ts

# Check with glob patterns
pnpm exec tsbuild emitcheck "src/**/*.ts" "test/**/*.ts"

Exit codes:

  • 0 - All files can be emitted
  • 1 - One or more files have errors

5. Type Check

pnpm exec tsbuild check [pattern] [more...] [options]

Performs type checking without emitting files.

With arguments: Check specified files/patterns

pnpm exec tsbuild check "ts/**/*.ts"
pnpm exec tsbuild check "src/**/*.ts" "test/**/*.ts"

Without arguments: Two-phase default check

  1. Phase 1: Type check ts/**/* (strict, includes .d.ts)
  2. Phase 2: Type check test/**/* (relaxed, skipLibCheck: true)
pnpm exec tsbuild check
# Running default type checking sequence...
# Checking ts/**/* files...
# Checking test/**/* files with --skiplibcheck...
# All default type checks passed!

Both forms check every file under the compiler options of the folder that owns it, including files that a checked file imports from another folder; see Folder tsconfig.json.

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<ICompileResult>

interface ICompileResult {
  emittedFiles: string[];
  errorSummary: IErrorSummary;
}

interface IErrorSummary {
  errorsByFile: Record<string, Diagnostic[]>;
  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<string[]> - 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<ICompileResult>

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<boolean> - 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<boolean> - true if can emit

createOptions(customOptions?, folderName?)

Get merged compiler options (useful for debugging). Pass a folder name to include the compiler options that folder adds in its own tsconfig.json.

const options = compiler.createOptions({ strict: true });
console.log(options); // Shows merged options

const workerOptions = compiler.createOptions({}, 'ts_web_serviceworker');
console.log(workerOptions.lib); // ['lib.webworker.d.ts', 'lib.esnext.d.ts']

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);

// Folder compiler options: what ts_web_serviceworker/tsconfig.json adds to the project's, or null without one
const folderOptions = config.loadFolder('ts_web_serviceworker');
// Every source folder with its own tsconfig.json; throws for the first invalid one
const configuredFolders = config.getConfiguredFolders(); // ['ts_web_serviceworker']
// The folder whose options govern a file, or null for files on the project options
const owner = config.getOwningFolder('./ts_web_serviceworker/index.ts'); // 'ts_web_serviceworker'
const workerOptions = config.merge({}, argvArg, 'ts_web_serviceworker');

TsPublishConfig

Reads tspublish.json for module configuration. A missing file means no configuration; a file that cannot be read, is not a JSON object, or still carries the compilerOptions key of tsbuild 4.6.0 throws with its path.

import { TsPublishConfig } from '@git.zone/tsbuild';

const pubConfig = new TsPublishConfig('./ts_core');
console.log(pubConfig.shouldUnpack);    // true/false
console.log(pubConfig.order);           // number, Infinity if unset

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 (6 Levels)

Compiler option values use TypeScript's standard JSON syntax. For example, "lib": ["ES2022"] selects the ES2022 library and replaces the default DOM/ESNext selection; Node projects can pair it with "types": ["node"]. TSBuild converts these values through TypeScript's compiler-option parser and reports invalid values with their TypeScript diagnostic codes. Each compilation task retains its own inferred source root and output layout.

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 Folder tsconfig.json What the tsconfig.json of the source folder that owns the files adds (if present), see Folder tsconfig.json
4 Protected Defaults Critical options for build integrity
5 Programmatic Options Options passed to API functions
6 CLI Flags Command-line arguments (highest priority)

Protected Options

These options cannot be overridden by tsconfig.json, and a folder tsconfig.json cannot set them at all (but they 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',
  lib: ['dom', 'esnext'],         // Browser globals and the latest ECMAScript library
  noImplicitAny: false,           // Flexible for quick development
  esModuleInterop: true,          // CJS/ESM interop
  verbatimModuleSyntax: true      // Explicit imports/exports
}

Folder tsconfig.json

A source folder - ts or ts_* - can compile in its own environment. The typical case is a service worker or web worker: its code needs the webworker library, which cannot be combined with the DOM library of the defaults because both declare the same globals differently (TS2403). Give the folder a tsconfig.json that extends the project's tsconfig.json, for example ts_web_serviceworker/tsconfig.json:

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "lib": ["webworker", "esnext"]
  }
}

The folder then compiles against the worker globals, and without the DOM:

declare const self: ServiceWorkerGlobalScope;

self.addEventListener('install', (eventArg: ExtendableEvent) => {
  eventArg.waitUntil(self.skipWaiting());
});

self.addEventListener('fetch', (eventArg: FetchEvent) => {
  eventArg.respondWith(fetch(eventArg.request));
});

What tsbuild reads. For every file below the folder, tsbuild merges what the folder's tsconfig.json adds over the project's options, in tsbuild, custom, tsfolders, check, emitcheck and the TsCompiler API. Protected options still apply, programmatic options and CLI flags still win, and a list such as lib or types replaces the inherited one. The options use the tsconfig.json syntax, comments included, and TypeScript validates them; path-valued options such as typeRoots resolve from the file that declares them. tsbuild never changes the project's tsconfig.json.

What the editor sees. An editor applies the nearest tsconfig.json to a file, so it checks the folder's files with the same settings tsbuild uses: the project's plus the folder's. tsbuild keeps it that way:

  • extends must lead to the project's tsconfig.json, directly or through other tsconfig files of the project, such as a ../tsconfig.worker.json that extends ./tsconfig.json. A folder cannot detach from the project's settings.
  • A folder tsconfig.json holds only extends and compilerOptions. tsbuild compiles every file below the folder with it, which is exactly the set of files an editor applies it to when it leaves the file selection to TypeScript's default; files, include and exclude would make the two differ and are rejected. For the same reason the project's tsconfig.json must not declare files or include, which the folder's tsconfig.json would inherit. references is rejected as well: tsbuild reads other folders through their declarations itself.
  • The defaults and protected options of tsbuild are in no tsconfig.json, for the folder as for the project.
  • At a folder boundary tsbuild is stricter than an editor: an editor that shows a file importing the folder checks the folder's sources under that file's settings, while tsbuild reads the folder's declarations (see below).

Allowed options. A folder tsconfig.json may add environment settings and switch on stricter checks, never weaken checking:

Kind Options
Environment lib, types, typeRoots, target, jsx, jsxFactory, jsxFragmentFactory, jsxImportSource
Stricter checks, true only strict, noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, strictBuiltinIteratorReturn, noImplicitThis, useUnknownInCatchVariables, alwaysStrict, noUnusedLocals, noUnusedParameters, exactOptionalPropertyTypes, noImplicitReturns, noFallthroughCasesInSwitch, noUncheckedIndexedAccess, noImplicitOverride, noPropertyAccessFromIndexSignature, noUncheckedSideEffectImports, isolatedModules, isolatedDeclarations, erasableSyntaxOnly, verbatimModuleSyntax, forceConsistentCasingInFileNames
Stricter checks, false only allowUnreachableCode, allowUnusedLabels

Every other option - rootDir, outDir, paths, baseUrl, module, moduleResolution, declaration, noEmitOnError, inlineSourceMap and the rest - belongs in the project's tsconfig.json; options that weaken checking, such as skipLibCheck and noCheck, belong nowhere. tsbuild rejects it, and a strictness flag set to its weaker value, with an error that names the option and the file. Only ts and ts_* folders carry their own tsconfig.json; tsbuild does not read one in another folder such as test/, whose files compile with the project's options.

Imports across folders. A file that imports a folder with its own tsconfig.json reads it through the declarations that folder emits under its own options - the .d.ts files its dist_ folder publishes, generated in memory, so the build order does not matter:

  • Types keep their meaning across the boundary, including types the folder infers from its own environment. A type the importing side cannot express, such as FetchEvent in a DOM folder or a test, is an error in those declarations, reported with the source file and the folder's tsconfig.json, instead of silently turning into any. Keep what both sides use expressible in both environments, or in a folder without its own tsconfig.json such as ts_interfaces.
  • The imported files are type-checked under their own folder's options: by the folder's own task when the same tsbuild, custom, tsfolders or compileGlob() run compiles that folder, otherwise by the compilation or check that imports them. Their errors fail it.
  • A compilation never emits the imported folder's files; its output imports the folder's dist_ folder.
  • Folders with their own tsconfig.json cannot import each other in a cycle, just as TypeScript project references cannot.
  • skipLibCheck skips declaration files, and with them the declarations read at a folder boundary, as it does for project references in tsc --build.
  • compileFiles() refuses root files of folders with different options, because one program has one set of options. Compile such folders as separate tasks, as compileGlob() and tsfolders do.

Errors before cleaning. Before compileGlob() - and with it every build command - clears an output directory, it reads the project's tsconfig.json, every folder tsconfig.json, the owning folder of every task and the tspublish.json that decides how a task's output is unpacked. An invalid configuration fails the build and leaves the previous output in place; the CLI prints the error, or {"success": false, "error": "..."} under --json, and exits with code 1.

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 publishable ts_* folder. @git.zone/tspublish expects publishing fields, while tsbuild additionally reads order and unpack for build ordering and output flattening. A folder's compiler options live in its own tsconfig.json, not here; a compilerOptions key in tspublish.json fails the build with a message naming that file:

{
  "name": "@myorg/core",
  "order": 3,
  "unpack": true,
  "dependencies": ["@myorg/interfaces", "@myorg/shared"],
  "registries": ["useBase"],
  "bin": []
}
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[] [] Published package dependencies resolved from the monorepo package.json
registries string[] -- Publish destination; gitzone release requires ["useBase"] and publishes to the registries in release.targets.npm of .smartconfig.json
bin string[] [] CLI binary names generated by @git.zone/tspublish

Build Order

The tsfolders command respects the order property:

pnpm exec tsbuild tsfolders

Default ordering (without tspublish.json):

  1. ts_interfaces - always first (shared types)
  2. ts_shared - always second (shared utilities)
  3. Other folders sorted by order property
  4. 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: pnpm install
      - run: pnpm exec tsbuild

JSON Output

pnpm exec tsbuild --json --quiet
{
  "success": true,
  "totals": {
    "errors": 0,
    "filesWithErrors": 0,
    "tasks": 1
  },
  "errorsByFile": {}
}

When the build cannot start, for example because a folder tsconfig.json is invalid, the output is the error instead, and the exit code is 1:

{
  "success": false,
  "error": "/path/to/project/ts_web_serviceworker/tsconfig.json: compilerOptions.skipLibCheck is not allowed in a folder tsconfig.json. ..."
}

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:

pnpm exec tsbuild --skiplibcheck

Only use this if you trust your dependencies' type definitions.

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.

S
Description
No description provided
Readme
2.5 MiB
Languages
TypeScript 99.7%
JavaScript 0.3%