From 6e80985ea16e6169e818d9e96e1e40b7b143d4a9 Mon Sep 17 00:00:00 2001 From: Jens B Date: Fri, 19 Jul 2024 05:27:42 +0200 Subject: [PATCH] feat: support custom `tsconfig.json` (#75) Co-authored-by: Filippo Bovo Co-authored-by: Hiroki Osame --- README.md | 8 ++++ src/cli.ts | 9 +++- src/utils/get-rollup-configs.ts | 8 +++- src/utils/get-tsconfig.ts | 17 +++++++ src/utils/rollup-plugins/esbuild.ts | 3 -- src/utils/tsconfig.ts | 3 -- tests/specs/builds/typescript.ts | 72 ++++++++++++++++++++++++++++- 7 files changed, 111 insertions(+), 9 deletions(-) create mode 100644 src/utils/get-tsconfig.ts delete mode 100644 src/utils/tsconfig.ts diff --git a/README.md b/README.md index 229b70d..3cc5278 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,14 @@ Pass in a Node.js target that that doesn't support it to strip the `node:` proto pkgroll --target=node12.19 ``` +### Custom `tsconfig.json` path + +By default, _Pkgroll_ looks for `tsconfig.json` configuration file in the current working directory. You can pass in a custom `tsconfig.json` path with the `--tsconfig` flag: + +```sh +pkgroll --tsconfig=tsconfig.build.json +``` + ### Export condition Similarly to the target, the export condition specifies which fields to read from when evaluating [export](https://nodejs.org/api/packages.html#exports) and [import](https://nodejs.org/api/packages.html#imports) maps. diff --git a/src/cli.ts b/src/cli.ts index 7075b18..bd8407e 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -8,7 +8,7 @@ import { getAliases } from './utils/parse-package-json/get-aliases.js'; import { normalizePath } from './utils/normalize-path.js'; import { getSourcePath } from './utils/get-source-path.js'; import { getRollupConfigs } from './utils/get-rollup-configs.js'; -import { tsconfig } from './utils/tsconfig.js'; +import { getTsconfig } from './utils/get-tsconfig'; import { log } from './utils/log.js'; import { cleanDist } from './utils/clean-dist.js'; @@ -42,6 +42,11 @@ const argv = cli({ description: 'Environments to support. `target` in tsconfig.json is automatically added. Defaults to the current Node.js version.', alias: 't', }, + tsconfig: { + type: String, + description: 'Custom tsconfig.json file path', + alias: 'p', + }, watch: { type: Boolean, description: 'Watch mode', @@ -110,6 +115,7 @@ const cwd = process.cwd(); const sourcePath = normalizePath(argv.flags.src, true); const distPath = normalizePath(argv.flags.dist, true); +const tsconfig = getTsconfig(argv.flags.tsconfig); const tsconfigTarget = tsconfig?.config.compilerOptions?.target; if (tsconfigTarget) { argv.flags.target.push(tsconfigTarget); @@ -153,6 +159,7 @@ if (tsconfigTarget) { argv.flags, getAliases(packageJson, cwd), packageJson, + tsconfig, ); if (argv.flags.cleanDist) { diff --git a/src/utils/get-rollup-configs.ts b/src/utils/get-rollup-configs.ts index f7e67d8..b007192 100644 --- a/src/utils/get-rollup-configs.ts +++ b/src/utils/get-rollup-configs.ts @@ -1,12 +1,14 @@ import fs from 'fs'; import path from 'path'; import type { OutputOptions, RollupOptions, Plugin } from 'rollup'; +import type { TransformOptions } from 'esbuild'; import nodeResolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; import json from '@rollup/plugin-json'; import alias from '@rollup/plugin-alias'; import replace from '@rollup/plugin-replace'; import type { PackageJson } from 'type-fest'; +import type { TsConfigResult } from 'get-tsconfig'; import type { ExportEntry, AliasMap } from '../types.js'; import { isFormatEsm, createRequire } from './rollup-plugins/create-require.js'; import { esbuildTransform, esbuildMinify } from './rollup-plugins/esbuild.js'; @@ -76,9 +78,11 @@ const getConfig = { aliases: AliasMap, env: EnvObject, executablePaths: string[], + tsconfig: TsConfigResult | null, ) => { - const esbuildConfig = { + const esbuildConfig: TransformOptions = { target: options.target, + tsconfigRaw: tsconfig?.config, }; return { @@ -144,6 +148,7 @@ export const getRollupConfigs = async ( flags: Options, aliases: AliasMap, packageJson: PackageJson, + tsconfig: TsConfigResult | null, ) => { const executablePaths = inputs .filter(({ exportEntry }) => exportEntry.isExecutable) @@ -204,6 +209,7 @@ export const getRollupConfigs = async ( aliases, env, executablePaths, + tsconfig, ); config.external = externalDependencies; configs.app = config; diff --git a/src/utils/get-tsconfig.ts b/src/utils/get-tsconfig.ts new file mode 100644 index 0000000..917db51 --- /dev/null +++ b/src/utils/get-tsconfig.ts @@ -0,0 +1,17 @@ +import path from 'path'; +import { getTsconfig as _getTsconfig, parseTsconfig } from 'get-tsconfig'; + +export const getTsconfig = ( + tscFile?: string, +) => { + if (!tscFile) { + return _getTsconfig(); + } + + const resolvedTscFile = path.resolve(tscFile); + const config = parseTsconfig(resolvedTscFile); + return { + path: resolvedTscFile, + config, + }; +}; diff --git a/src/utils/rollup-plugins/esbuild.ts b/src/utils/rollup-plugins/esbuild.ts index 57707d7..c302d4b 100644 --- a/src/utils/rollup-plugins/esbuild.ts +++ b/src/utils/rollup-plugins/esbuild.ts @@ -1,7 +1,6 @@ import type { Plugin, InternalModuleFormat } from 'rollup'; import { createFilter } from '@rollup/pluginutils'; import { transform, type TransformOptions, type Format } from 'esbuild'; -import { tsconfig } from '../tsconfig.js'; export const esbuildTransform = ( options?: TransformOptions, @@ -24,8 +23,6 @@ export const esbuildTransform = ( // https://github.com/evanw/esbuild/issues/1932#issuecomment-1013380565 sourcefile: id.replace(/\.[cm]ts/, '.ts'), - - tsconfigRaw: tsconfig?.config as TransformOptions['tsconfigRaw'], }); return { diff --git a/src/utils/tsconfig.ts b/src/utils/tsconfig.ts deleted file mode 100644 index 48aea58..0000000 --- a/src/utils/tsconfig.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { getTsconfig } from 'get-tsconfig'; - -export const tsconfig = getTsconfig(); diff --git a/tests/specs/builds/typescript.ts b/tests/specs/builds/typescript.ts index 5ebcca1..943a869 100644 --- a/tests/specs/builds/typescript.ts +++ b/tests/specs/builds/typescript.ts @@ -1,7 +1,7 @@ import { testSuite, expect } from 'manten'; import { createFixture } from 'fs-fixture'; import { pkgroll } from '../../utils.js'; -import { createPackageJson } from '../../fixtures.js'; +import { createPackageJson, createTsconfigJson } from '../../fixtures.js'; export default testSuite(({ describe }, nodePath: string) => { describe('TypeScript', ({ test }) => { @@ -53,4 +53,74 @@ export default testSuite(({ describe }, nodePath: string) => { expect(content).toBe('console.log(1);\n'); }); }); + + describe('custom tsconfig.json path', ({ test }) => { + test('respects compile target', async () => { + await using fixture = await createFixture({ + src: { + 'index.ts': 'export default () => "foo";', + }, + 'package.json': createPackageJson({ + main: './dist/index.js', + }), + 'tsconfig.json': createTsconfigJson({ + compilerOptions: { + target: 'ES6', + }, + }), + 'tsconfig.build.json': createTsconfigJson({ + compilerOptions: { + target: 'ES5', + }, + }), + }); + + const pkgrollProcess = await pkgroll([ + '--env.NODE_ENV=test', + '--tsconfig=tsconfig.build.json', + ], { + cwd: fixture.path, + nodePath, + }); + + expect(pkgrollProcess.exitCode).toBe(0); + expect(pkgrollProcess.stderr).toBe(''); + + const content = await fixture.readFile('dist/index.js', 'utf8'); + expect(content.includes('function')).toBe(true); + }); + + test('error on invalid tsconfig.json path', async () => { + const fixture = await createFixture({ + src: { + 'index.ts': 'export default () => "foo";', + }, + 'package.json': createPackageJson({ + main: './dist/index.js', + }), + 'tsconfig.json': createTsconfigJson({ + compilerOptions: { + target: 'ES6', + }, + }), + 'tsconfig.build.json': createTsconfigJson({ + compilerOptions: { + target: 'ES5', + }, + }), + }); + + const pkgrollProcess = await pkgroll([ + '--env.NODE_ENV=test', + '--tsconfig=tsconfig.invalid.json', + ], { + cwd: fixture.path, + nodePath, + reject: false, + }); + + expect(pkgrollProcess.exitCode).toBe(1); + // expect(pkgrollProcess.stderr).toMatch('Cannot resolve tsconfig at path:'); + }); + }); });