tsconfig-utils
Utilities for working with tsconfig
files
Contents
- What is this?
- When should I use this?
- Install
- Use
-
API
COMPILER_OPTIONS
LIB
loadCompilerOptions(tsconfig[, options])
loadLib(tsconfig[, options])
loadPaths(tsconfig[, options])
loadPlugins(tsconfig[, options])
loadTsconfig(id[, options])
normalizeCompilerOptions(option)
normalizeImportsNotUsed(option)
normalizeJsx(option)
normalizeLib(option)
normalizeModule(option)
normalizeModuleDetection(option)
normalizeModuleResolution(option)
normalizeNewLine(option)
normalizeTarget(option)
resolvePaths(code, options)
- Types
- Related
- Contribute
What is this?
This package exports a set of utilities for working with TypeScript configuration files.
When should I use this?
This package can be used to load tsconfig files, resolve path aliases, and normalize user options for the TypeScript Compiler API.
Install
This package is ESM only.
yarn add @flex-development/tsconfig-utils
From Git:
yarn add @flex-development/tsconfig-utils@flex-development/tsconfig-utils
See Git - Protocols | Yarn for details on requesting a specific branch, commit, or tag.
Use
Let's say a developer wants to run a TypeScript file using node
. The developer has a tsconfig.json
with path alias configurations.
They implement loader.mjs
(and for good measure, typings/node/loader.d.ts
too
/**
* @file Custom Loader Hooks
* @module loader
* @see https://nodejs.org/api/esm.html#loaders
*/
import * as mlly from '@flex-development/mlly'
import * as pathe from '@flex-development/pathe'
import * as tscu from '@flex-development/tsconfig-utils'
import * as tutils from '@flex-development/tutils'
import * as esbuild from 'esbuild'
import { fileURLToPath, pathToFileURL } from 'node:url'
// add support for extensionless files in "bin" scripts
// https://github.com/nodejs/modules/issues/488
mlly.EXTENSION_FORMAT_MAP.set('', mlly.Format.COMMONJS)
/**
* URL of tsconfig file.
*
* @type {import('node:url').URL}
* @const tsconfig
*/
const tsconfig = mlly.toURL('tsconfig.json')
/**
* TypeScript compiler options.
*
* @type {tscu.CompilerOptions}
* @const compilerOptions
*/
const compilerOptions = tscu.loadCompilerOptions(tsconfig)
/**
* Determines how the module at the given `url` should be interpreted,
* retrieved, and parsed.
*
* @see {@linkcode LoadHookContext}
* @see https://nodejs.org/api/esm.html#loadurl-context-nextload
*
* @async
*
* @param {string} url - Resolved module URL
* @param {LoadHookContext} context - Hook context
* @return {Promise<LoadHookResult>} Hook result
*/
export const load = async (url, context) => {
// get module format
context.format = context.format ?? (await mlly.getFormat(url))
// validate import assertions
mlly.validateAssertions(url, context.format, context.importAssertions)
/**
* File extension of {@linkcode url}.
*
* @type {pathe.Ext | tutils.EmptyString}
* @const ext
*/
const ext = pathe.extname(url)
/**
* Source code.
*
* @type {tutils.Optional<esm.Source<Uint8Array | string>>}
* @var source
*/
let source = await mlly.getSource(url, { format: context.format })
// transform typescript files
if (/^\.(?:cts|mts|tsx?)$/.test(ext) && !/\.d\.(?:cts|mts|ts)$/.test(url)) {
// resolve path aliases
source = await tscu.resolvePaths(source, {
conditions: context.conditions,
ext: '',
parent: url,
tsconfig
})
// resolve modules
source = await mlly.resolveModules(source, {
conditions: context.conditions,
parent: url
})
// transpile source code
const { code } = await esbuild.transform(source, {
format: ext === '.cts' ? 'cjs' : 'esm',
loader: ext.slice(/^\.[cm]/.test(ext) ? 2 : 1),
minify: false,
sourcefile: fileURLToPath(url),
sourcemap: 'inline',
target: `node${process.versions.node}`,
tsconfigRaw: { compilerOptions }
})
// set source code to transpiled source
source = code
}
return { format: context.format, shortCircuit: true, source }
}
/**
* Resolves the given module `specifier`.
*
* Adds supports for:
*
* - Path alias resolution
* - Extensionless file and directory index resolution
*
* @see {@linkcode ResolveHookContext}
* @see https://nodejs.org/api/esm.html#resolvespecifier-context-nextresolve
*
* @async
*
* @param {string} specifier - Module specifier
* @param {ResolveHookContext} context - Hook context
* @return {Promise<ResolveHookResult>} Hook result
* @throws {Error}
*/
export const resolve = async (specifier, context) => {
const { conditions, parentURL: parent } = context
// resolve path alias
specifier = await mlly.resolveAlias(specifier, {
aliases: tscu.loadPaths(tsconfig),
conditions,
cwd: pathToFileURL(compilerOptions.baseUrl),
parent
})
/**
* Resolved module URL.
*
* @type {import('node:url').URL}
* @const url
*/
const url = await mlly.resolveModule(specifier, {
conditions,
parent: parent?.startsWith('file:') ? parent : specifier
})
return {
format: await mlly.getFormat(url),
shortCircuit: true,
url: url.href
}
}
The developer creates scratch.ts
to test their custom loader hooks:
/**
* @file Scratch
* @module scratch
*/
import { resolvePaths } from '@flex-development/tsconfig-utils'
import { dedent } from 'ts-dedent'
const code = dedent`
import type { ResolveAliasOptions } from '#src/interfaces'
import * as internal from '#src/internal'
import loadCompilerOptions from '#src/utils/load-compiler-options'
import * as mlly from '@flex-development/mlly'
`
console.debug(await resolvePaths(code, { ext: '', parent: import.meta.url }))
Running the file with node --loader=./loader.mjs ./scratch
yields:
import type { ResolveAliasOptions } from './src/interfaces'
import * as internal from './src/internal'
import loadCompilerOptions from './src/utils/load-compiler-options'
import * as mlly from '@flex-development/mlly'
Pleased with their work, they crack open a cold Red Bull
API
This package exports the following identifiers:
COMPILER_OPTIONS
LIB
loadCompilerOptions
loadLib
loadPaths
loadPlugins
loadTsconfig
normalizeCompilerOptions
normalizeImportsNotUsed
normalizeJsx
normalizeLib
normalizeModule
normalizeModuleDetection
normalizeModuleResolution
normalizeNewLine
normalizeTarget
resolvePaths
There is no default export.
COMPILER_OPTIONS
Set containing compiler option names.
Source
LIB
Map containing type definition library names that correspond to files in the **/node_modules/typescript/lib
directory.
All keys are lowercase.
Source
loadCompilerOptions(tsconfig[, options])
Loads compilerOptions
from a tsconfig file.
Parameters
-
{mlly.ModuleId}
tsconfig
— Module id of tsconfig file -
{LoadTsconfigOptions?}
[options]
— Tsconfig loading options
Returns
{CompilerOptions}
Compiler options object.
Source
loadLib(tsconfig[, options])
Loads type definition library names from a tsconfig file.
Parameters
-
{mlly.ModuleId}
tsconfig
— Module id of tsconfig file -
{LoadTsconfigOptions?}
[options]
— Tsconfig loading options
Returns
{Lib[]}
Type definition library names array.
Source
loadPaths(tsconfig[, options])
Loads a path alias configuration from a tsconfig file.
Parameters
-
{mlly.ModuleId}
tsconfig
— Module id of tsconfig file -
{LoadTsconfigOptions?}
[options]
— Tsconfig loading options
Returns
{Paths}
Path alias configuration object.
Source
loadPlugins(tsconfig[, options])
Loads language service plugin configurations from a tsconfig file.
Parameters
-
{mlly.ModuleId}
tsconfig
— Module id of tsconfig file -
{LoadTsconfigOptions?}
[options]
— Tsconfig loading options
Returns
{Plugin[]}
Language service plugin configurations array.
Source
loadTsconfig(id[, options])
Reads and parses the tsconfig file at the given module id
.
If the tsconfig file is found, comments and byte order marks (BOMs) will be removed before parsing. If successfully parsed, an object representation of the tsconfig file will be returned.
Extending configuration files is also supported. If not overwritten, the baseUrl
, outDir
, and
rootDir
properties from the base tsconfig file will be made relative to the tsconfig file being loaded.
Parameters
-
{mlly.ModuleId}
id
— Module id of tsconfig file -
{LoadTsconfigOptions?}
[options]
— Load options
Returns
{Nullable<TSConfig>}
User configuration object or null
if tsconfig file is not found.
Source
normalizeCompilerOptions(compilerOptions)
Converts the given compilerOptions
into programmatic compiler options.
TypeScript programs expect compiler option objects to use enum values where appropriate.
Parameters
-
{unknown}
compilerOptions
— User compiler options
Returns
{ts.CompilerOptions}
Programmatic compiler options.
Source
normalizeImportsNotUsed(option)
Converts the given option
into a programmatic importsNotUsedAsValues
option.
TypeScript programs expect a ts.ImportsNotUsedAsValues
value.
If the option
is already programmatic, it will be returned unmodified. If it cannot be converted, undefined
will be
returned instead.
Parameters
-
{unknown}
option
— Option to evaluate
Returns
{ts.ImportsNotUsedAsValues | undefined}
ts.ImportsNotUsedAsValues
value or undefined
.
Source
normalizeJsx(option)
Converts the given option
into a programmatic jsx
option.
TypeScript programs expect a ts.JsxEmit
value.
If the option
is already programmatic, it will be returned unmodified. If it cannot be converted, undefined
will be
returned instead.
Parameters
-
{unknown}
option
— Option to evaluate
Returns
{ts.JsxEmit | undefined}
ts.JsxEmit
value or undefined
.
Source
normalizeLib(option)
Converts the given option
into an array containing programmatic lib
options.
TypeScript programs expect values in compilerOptions.lib
to match filenames in **/node_modules/typescript/lib
exactly.
Parameters
-
{unknown}
option
— Option to evaluate
Returns
{LibFile[]}
Lib filename array.
Source
normalizeModule(option)
Converts the given option
into a programmatic module
option.
TypeScript programs expect a ts.ModuleKind
value.
If the option
is already programmatic, it will be returned unmodified. If it cannot be converted, undefined
will be
returned instead.
Parameters
-
{unknown}
option
— Option to evaluate
Returns
{ts.ModuleKind | undefined}
ts.ModuleKind
value or undefined
.
Source
normalizeModuleDetection(option)
Converts the given option
into a programmatic moduleDetection
option.
TypeScript programs expect a ts.ModuleDetectionKind
value.
If the option
is already programmatic, it will be returned unmodified. If it cannot be converted, undefined
will be
returned instead.
Parameters
-
{unknown}
option
— Option to evaluate
Returns
{ts.ModuleDetectionKind | undefined}
ts.ModuleDetectionKind
value or undefined
.
Source
normalizeModuleResolution(option)
Converts the given option
into a programmatic moduleResolution
option.
TypeScript programs expect a ts.ModuleResolutionKind
value.
If the option
is already programmatic, it will be returned unmodified. If it cannot be converted, undefined
will be
returned instead.
Parameters
-
{unknown}
option
— Option to evaluate
Returns
{ts.ModuleResolutionKind | undefined}
ts.ModuleResolutionKind
value or undefined
.
Source
normalizeNewLine(option)
Converts the given option
into a programmatic newLine
option.
TypeScript programs expect a ts.NewLineKind
value.
If the option
is already programmatic, it will be returned unmodified. If it cannot be converted, undefined
will be
returned instead.
Parameters
-
{unknown}
option
— Option to evaluate
Returns
{ts.NewLineKind | undefined}
ts.NewLineKind
value or undefined
.
Source
normalizeTarget(option)
Converts the given option
into a programmatic target
option.
TypeScript programs expect a ts.ScriptTarget
value.
If the option
is already programmatic, it will be returned unmodified. If it cannot be converted, undefined
will be
returned instead.
Parameters
-
{unknown}
option
— Option to evaluate
Returns
{ts.ScriptTarget | undefined}
ts.ScriptTarget
value or undefined
.
Source
resolvePaths(code, options)
Resolves path aliases in export
, import
, and require
statements in the given piece of source code
.
Parameters
-
{string}
code
— Code to evaluate -
{ResolvePathsOptions}
options
— Path alias resolution options
Returns
{Promise<string>}
code
with path aliases resolved and/or unmodified.
Source
Types
This package is fully typed with TypeScript.
Interfaces
tsconfig-types
This package re-exports TypeScript definitions from tsconfig-types
. This is primarily for the convenience of
TypeScript users who do not hoist packages, but may need to import
definitions used in this package.
Related
-
mlly
— ECMAScript module utilities -
tsconfig-types
— TypeScript definitions fortsconfig.json
Contribute
See CONTRIBUTING.md
.