@amirsavand/ts-barrel

CLI and Node.js API that generates barrel files (index.ts) for TypeScript projects.

npm Changelog

Changelog

See what changed in each version on the ts-barrel changelog.

What It Does

A barrel is an index.ts that re-exports a folder's files and subfolders, so code can import from the folder instead of from each file. ts-barrel writes one into every folder you include, and keeps them up to date.

src/core/                 src/core/index.ts
├── app.ts                export * from './app';
├── config.ts             export * from './config';
└── utils/                export * from './utils';
    └── format.ts

Installation

npm install --save-dev @amirsavand/ts-barrel

Quick Start

# Create .ts-barrel.json
npx ts-barrel init
# Generate the barrel files
npx ts-barrel

Run it again after creating, deleting or renaming a file. It only writes barrels whose content changed.

Configuration

.ts-barrel.json, in the folder you run ts-barrel from:

{
  "$schema": "./node_modules/@amirsavand/ts-barrel/schema.json",
  "version": 2,
  "include": ["src"],
  "exclude": []
}
Property Required Description
version yes Configuration version, always 2.
include yes Globs of folders and files to give barrels.
exclude no Globs of folders and files to leave out.
$schema no JSON schema, for autocomplete and validation in your editor.

How patterns work

Examples

Every folder in src/:

{ "version": 2, "include": ["src"] }

Several folders, with globs:

{
  "version": 2,
  "include": [
    "projects/libs/*/src/lib",
    "projects/apps/*/src/app/shared"
  ]
}

Exclude a folder's barrel, keep its subfolders' barrels. Exclude the folder's index.ts: src/legacy/ gets no barrel and src/index.ts doesn't export it, but src/legacy/part/index.ts is still generated.

{ "version": 2, "include": ["src"], "exclude": ["src/legacy/index.ts"] }

The same for every folder with a given name:

{ "version": 2, "include": ["src"], "exclude": ["**/modules/index.ts"] }

Exclude a whole folder. Nothing inside src/mocks/ gets a barrel or is exported:

{ "version": 2, "include": ["src"], "exclude": ["src/mocks"] }

Or every folder with a given name, anywhere: "**/mocks".

Exclude a single file. src/core/main.ts gets no line in src/core/index.ts; every other file still does:

{ "version": 2, "include": ["src"], "exclude": ["src/core/main.ts"] }

Exclude files by pattern, in every folder:

{ "version": 2, "include": ["src"], "exclude": ["**/*.stories.ts", "**/internal-*.ts"] }

Include only some files. Only *.model.ts files are exported, from barrels in the folders that hold them:

{ "version": 2, "include": ["src/models/*.model.ts"] }

A monorepo, everything together:

{
  "$schema": "./node_modules/@amirsavand/ts-barrel/schema.json",
  "version": 2,
  "include": [
    "scripts/common",
    "projects/libs/*/src/lib",
    "projects/apps/*/src/app/shared",
    "projects/apps/*/src/app/*/shared"
  ],
  "exclude": [
    "**/modules/index.ts",
    "projects/apps/legacy/src/app/shared",
    "**/*.stories.ts"
  ]
}

CLI

ts-barrel [command] [options]
Command Description
(none) Generate barrel files
init Create a configuration file (never overwrites one)
migrate Update a configuration file to the current version
Option Description
-c, --config <path> Configuration file (default: .ts-barrel.json)
--check Write nothing; exit 1 if any barrel is out of date
-s, --silent Print nothing but errors
-h, --help Show help
-v, --version Show the version

It prints one line per barrel: WRITE, SKIP (already up to date) or, with --check, STALE. Warnings (e.g. a pattern that matches nothing) don't change the exit code; errors exit 1.

Typical package.json scripts:

{
  "scripts": {
    "ts-barrel": "ts-barrel",
    "ts-barrel-check": "ts-barrel --check"
  }
}

Node.js API

The API can do everything the CLI can, with the same options:

CLI API
ts-barrel generateBarrelFiles(config?, options?)
ts-barrel init initConfig(options?)
ts-barrel migrate migrateConfig(options?)
--config <path> config (a path, or the config itself)
--check { check: true }
--silent { silent: true }
import { generateBarrelFiles, initConfig, migrateConfig } from '@amirsavand/ts-barrel';

// Same as `ts-barrel`: reads .ts-barrel.json in the working directory
generateBarrelFiles();

// Same as `ts-barrel --config app/barrel.json --check --silent`
const result = generateBarrelFiles('app/barrel.json', { check: true, silent: true });
if (!result.ok) {
  console.log(result.barrels.filter((barrel) => barrel.status === 'stale'));
}

// A configuration object, relative to `cwd` (default: process.cwd())
generateBarrelFiles({ version: 2, include: ['src'], exclude: ['src/core/main.ts'] }, { cwd: 'packages/core' });

// Same as `ts-barrel init` and `ts-barrel migrate`
initConfig({ config: 'app/barrel.json' });
migrateConfig();

generateBarrelFiles() returns { barrels, warnings, ok }: every barrel with its path, status (write, skip or stale) and content, and ok is false only when check found a stale barrel. Every function prints the same lines as the CLI unless silent is set, and throws a TsBarrelError for a missing or invalid configuration.

Migrating from 2.x

ts-barrel 3 still runs a 2.x configuration (roots and ignore, no version) exactly as 2.x did, and warns until you migrate it:

npx ts-barrel migrate

That rewrites the file as version 2 with the same output:

2.x 3.x
"roots": ["src"] "include": ["src"]
"ignore": ["modules"] "exclude": ["**/modules/index.ts"]
"ignore": ["a/b"] "exclude": ["src/a/b/index.ts"] (per root)

Afterwards, simplify it: list folders with globs instead of one by one, and exclude a whole folder ("src/mocks") instead of each folder inside it.

Other changes in 3.0:

Built With

About

Made with 💖 by Savand Bros © 2023-present.