634 lines
15 KiB
Markdown
634 lines
15 KiB
Markdown
# @git.zone/tsbuild
|
|
|
|
A powerful, modern TypeScript build tool with smart defaults, full tsconfig.json support, and automatic output directory management.
|
|
|
|
## Install
|
|
|
|
```bash
|
|
# Using pnpm (recommended)
|
|
pnpm install @git.zone/tsbuild --save-dev
|
|
|
|
# Using npm
|
|
npm install @git.zone/tsbuild --save-dev
|
|
```
|
|
|
|
## Why tsbuild?
|
|
|
|
- **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
|
|
- **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:**
|
|
```bash
|
|
npx tsbuild
|
|
```
|
|
Compiles `./ts/**/*.ts` to `./dist_ts/`
|
|
|
|
**Custom directories:**
|
|
```bash
|
|
npx tsbuild custom src utils
|
|
```
|
|
Compiles:
|
|
- `./src/**/*.ts` to `./dist_src/`
|
|
- `./utils/**/*.ts` to `./dist_utils/`
|
|
|
|
**Auto-discover and compile in dependency order:**
|
|
```bash
|
|
npx tsbuild tsfolders
|
|
```
|
|
Finds all `ts_*` folders and compiles them respecting dependencies.
|
|
|
|
### Programmatic Usage
|
|
|
|
**Basic compilation:**
|
|
```typescript
|
|
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):**
|
|
```typescript
|
|
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:**
|
|
```typescript
|
|
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
|
|
|
|
```bash
|
|
npx tsbuild [options]
|
|
```
|
|
|
|
Compiles all TypeScript files from `./ts/` to `./dist_ts/`
|
|
|
|
**Options:**
|
|
- `--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:**
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
npx tsbuild custom <dir1> <dir2> ... [options]
|
|
```
|
|
|
|
Compile specific directories to their corresponding `dist_` folders.
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```bash
|
|
npx 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/5 ts_interfaces
|
|
2/5 ts_shared
|
|
3/5 ts_core
|
|
4/5 ts_utils
|
|
5/5 ts_modules
|
|
```
|
|
|
|
### 4. Emit Check
|
|
|
|
```bash
|
|
npx tsbuild emitcheck <file_or_pattern> [more...] [options]
|
|
```
|
|
|
|
Validates TypeScript files can be compiled without actually emitting them.
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
npx tsbuild check [pattern] [more...] [options]
|
|
```
|
|
|
|
Performs type checking without emitting files.
|
|
|
|
**With arguments:** Check specified files/patterns
|
|
```bash
|
|
npx tsbuild check "ts/**/*.ts"
|
|
npx 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)
|
|
|
|
```bash
|
|
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.
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```typescript
|
|
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>`
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```typescript
|
|
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 and unpacks nested output.
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```typescript
|
|
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?)
|
|
|
|
Get merged compiler options (useful for debugging).
|
|
|
|
```typescript
|
|
const options = compiler.createOptions({ strict: true });
|
|
console.log(options); // Shows merged options
|
|
```
|
|
|
|
### Supporting Classes
|
|
|
|
#### TsConfig
|
|
|
|
TypeScript configuration management.
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```typescript
|
|
import { TsUnpacker } from '@git.zone/tsbuild';
|
|
|
|
const unpacker = new TsUnpacker('./dist_ts', './ts');
|
|
await unpacker.unpack();
|
|
```
|
|
|
|
#### FsHelpers
|
|
|
|
Static filesystem utilities.
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```json
|
|
{
|
|
"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):
|
|
|
|
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):
|
|
|
|
- **`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:
|
|
|
|
```typescript
|
|
{
|
|
declaration: true, // Generate .d.ts files
|
|
emitDecoratorMetadata: true, // Support DI frameworks
|
|
experimentalDecorators: true, // Enable decorators
|
|
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:**
|
|
```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.
|
|
|
|
### 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
|
|
```
|
|
|
|
Configure via `tspublish.json` in source folder:
|
|
```json
|
|
{
|
|
"unpack": true
|
|
}
|
|
```
|
|
|
|
Set `"unpack": false` to disable.
|
|
|
|
### Decorator Support
|
|
|
|
First-class decorator support out of the box:
|
|
|
|
```typescript
|
|
@Injectable()
|
|
class UserService {
|
|
constructor(
|
|
@Inject('CONFIG') private config: Config,
|
|
private logger: Logger
|
|
) {}
|
|
}
|
|
```
|
|
|
|
Works with NestJS, TypeORM, Inversify, Angular, and other DI frameworks.
|
|
|
|
## CI/CD Integration
|
|
|
|
### GitHub Actions
|
|
|
|
```yaml
|
|
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: '20'
|
|
|
|
- run: npm install
|
|
- run: npx tsbuild
|
|
```
|
|
|
|
### JSON Output
|
|
|
|
```bash
|
|
npx tsbuild --json --quiet
|
|
```
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"totals": {
|
|
"errors": 0,
|
|
"filesWithErrors": 0,
|
|
"tasks": 1
|
|
},
|
|
"errorsByFile": {}
|
|
}
|
|
```
|
|
|
|
### Package.json Scripts
|
|
|
|
```json
|
|
{
|
|
"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:
|
|
```json
|
|
{
|
|
"compilerOptions": {
|
|
"experimentalDecorators": true,
|
|
"emitDecoratorMetadata": true
|
|
}
|
|
}
|
|
```
|
|
|
|
**Slow compilation**
|
|
|
|
Use `--skiplibcheck` to skip declaration file checking:
|
|
```bash
|
|
npx tsbuild --skiplibcheck
|
|
```
|
|
|
|
Only use this if you trust your dependencies' type definitions.
|
|
|
|
## Issue Reporting
|
|
|
|
For reporting issues or vulnerabilities, please visit our community at [community.foss.global](https://community.foss.global). We're looking forward to your contribution!
|
|
|
|
For repository access: [code.foss.global/git.zone/tsbuild](https://code.foss.global/git.zone/tsbuild)
|
|
|
|
## License and Legal Information
|
|
|
|
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository.
|
|
|
|
**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 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, and any usage must be approved in writing by Task Venture Capital GmbH.
|
|
|
|
### Company Information
|
|
|
|
Task Venture Capital GmbH
|
|
Registered at District Court Bremen HRB 35230 HB, Germany
|
|
|
|
For any legal inquiries or if you require 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.
|