tsconfck
TypeScript icon, indicating that this package has built-in type declarations

3.0.3 • Public • Published

tsconfck

npm version CI

A utility to find and parse tsconfig files without depending on typescript

Why

Because no simple official api exists and tsconfig isn't actual json.

Features

  • [x] find closest tsconfig (tsconfig.json or jsconfig.json)
  • [x] convert tsconfig to actual json and parse it
  • [x] resolve "extends"
  • [x] resolve "references" of solution-style tsconfig
  • [x] optional caching for improved performance
  • [x] optional findNative and parseNative to use official typescript api
  • [x] zero dependencies (typescript optional)
  • [x] extensive testsuite
  • [x] completely async and optimized (it's fast)
  • [x] tiny 4.8KB gzip
  • [x] unbundled esm js, no sourcemaps needed
  • [x] types generated with dts-buddy

Users

Used by vite*, vite-tsconfig-paths, astro and many more

(*) vite bundles tsconfck so it is listed as a devDependency

Install

npm install --save-dev tsconfck # or pnpm, yarn

Usage

without typescript installed

import { parse } from 'tsconfck';
const {
	tsconfigFile, // full path to found tsconfig
	tsconfig, // tsconfig object including merged values from extended configs
	extended, // separate unmerged results of all tsconfig files that contributed to tsconfig
	solution, // solution result if tsconfig is part of a solution
	referenced // referenced tsconfig results if tsconfig is a solution
} = await parse('foo/bar.ts');

with typescript

import { parseNative } from 'tsconfck';
const {
	tsconfigFile, // full path to found tsconfig
	tsconfig, // tsconfig object including merged values from extended configs, normalized
	result, // output of ts.parseJsonConfigFileContent
	solution, // solution result if tsconfig is part of a solution
	referenced // referenced tsconfig results if tsconfig is a solution
} = await parseNative('foo/bar.ts');

API

see API-DOCS

Advanced

ignoring tsconfig for files inside node_modules

esbuild ignores node_modules so when you want to use tsconfck with esbuild, you can set ignoreNodeModules: true

import { find, parse } from 'tsconfck';
// returns some-lib/tsconfig.json
const fooTSConfig = await find('node_modules/some-lib/src/foo.ts');

// returns null
const fooTSConfigIgnored = await find('node_modules/some-lib/src/foo.ts', {
	ignoreNodeModules: true
});

// returns empty config
const { tsconfig } = await parse('node_modules/some-lib/src/foo.ts', { ignoreNodeModules: true });

caching

a TSConfckCache instance can be created and passed to find and parse functions to reduce overhead when they are called often within the same project

import { find, parse, TSCOnfckCache } from 'tsconfck';
// 1. create cache instance
const cache = new TSCOnfckCache();
// 2. pass cache instance in options
const fooTSConfig = await find(('src/foo.ts', { cache })); // stores tsconfig for src in cache
const barTSConfig = await find(('src/bar.ts', { cache })); // reuses tsconfig result for src without fs call

const fooResult = await parse('src/foo.ts', { cache }); // uses cached path for tsconfig, stores parse result in cache
const barResult = await parse('src/bar.ts', { cache }); // uses cached parse result without fs call or resolving

cache invalidation

You are responsible for clearing the cache if tsconfig files are added/removed/changed after reading them during the cache lifetime.

Call cache.clear() and also discard all previous compilation results based previously cached configs.

cache mutation

Returned results are direct cache objects. If you want to modify them, deep-clone first.

cache reuse

Never use the same cache instance for mixed calls of find/findNative or parse/parseNative as result structures are different

root

This option can be used to limit finding tsconfig files outside of a root directory

import { parse, TSConfckCache } from 'tsconfck';
const root = '.';
const parseOptions = { root };
// these calls are not going to look for tsconfig files outside root
const fooResult = await find('src/foo.ts', parseOptions);
const barResult = await parse('src/bar.ts', parseOptions);

Using the root option can lead to errors if there is no tsconfig found inside root.

error handling

find and parse reject for errors they encounter, but return null or empty result if no config was found

If you want them to error instead, test the result and throw

import { parse } from 'tsconfck';
find('some/path/without/tsconfig/foo.ts').then((result) => {
	if (result === null) {
		throw new Error('not found');
	}
	return result;
});
parse('some/path/without/tsconfig/foo.ts').then((result) => {
	if (result.tsconfigFile === null) {
		throw new Error('not found');
	}
	return result;
});

TSConfig type (optional, requires typescript as devDependency)

import type { TSConfig } from 'pkg-types';

Check out https://github.com/unjs/pkg-types

cli

A simple cli wrapper is included, you can use it like this

find

# prints /path/to/tsconfig.json on stdout
tsconfck find src/index.ts

find-all

# prints all tsconfig.json in dir on stdout
tsconfck find-all src/

parse

# print content of ParseResult.tsconfig on stdout
tsconfck parse src/index.ts

# print to file
tsconfck parse src/index.ts > output.json

parse-result

# print content of ParseResult on stdout
tsconfck parse-result src/index.ts

# print to file
tsconfck parse-result src/index.ts > output.json

help

# print usage
tsconfck -h # or --help, -?, help

Links

Develop

This repo uses

In every PR you have to add a changeset by running pnpm changeset and following the prompts

PRs are going to be squash-merged

# install dependencies
pnpm install
# run tests
pnpm test
#run tests in watch mode (doesn't require dev in parallel)
pnpm test:watch

License

MIT

Dependencies (0)

    Dev Dependencies (6)

    Package Sidebar

    Install

    npm i tsconfck

    Weekly Downloads

    1,900,062

    Version

    3.0.3

    License

    MIT

    Unpacked Size

    67.5 kB

    Total Files

    16

    Last publish

    Collaborators

    • dominik_g