CLI and Node.js API that generates barrel files (index.ts) for TypeScript projects.
See what changed in each version on the ts-barrel changelog.
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
npm install --save-dev @amirsavand/ts-barrel
# 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.
.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. |
*, **, ?, [abc], {a,b}), relative to the configuration file,
with forward slashes on every OS.include and exclude both match files and folders. Matching a folder
covers everything inside it.index.ts when it's included, isn't excluded, its own
index.ts path isn't excluded, and it has something to export..ts and .tsx files first, then its
subfolders that have a barrel, each sorted by name.index.ts, *.spec.ts, *.test.ts, *.d.ts (and their
.tsx forms) and node_modules.include are never touched, and neither is an existing
index.ts in an excluded folder.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"
]
}
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"
}
}
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.
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:
require() it)..tsx files are exported; *.test.ts and *.d.ts files aren't.init no longer overwrites an existing configuration.Made with 💖 by Savand Bros © 2023-present.