Skip to content

Commit 2236863

Browse files
authored
Custom tsconfig path for the build command, default to tsconfig.build.json and fallback to tsconfig.json (#202)
1 parent 1567b4d commit 2236863

File tree

8 files changed

+172
-4
lines changed

8 files changed

+172
-4
lines changed

.changeset/proud-hairs-promise.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'bob-the-bundler': major
3+
---
4+
5+
Custom tsconfig path for the build command, default to `tsconfig.build.json` and fallback to
6+
`tsconfig.json`.

src/commands/build.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import { presetFields, presetFieldsESM } from './bootstrap.js';
1717

1818
export const DIST_DIR = 'dist';
1919

20+
export const DEFAULT_TS_BUILD_CONFIG = 'tsconfig.build.json';
21+
2022
interface PackageInfo {
2123
packagePath: string;
2224
cwd: string;
@@ -65,10 +67,18 @@ function assertTypeScriptBuildResult(result: ExecaReturnValue) {
6567
}
6668
}
6769

68-
async function buildTypeScript(buildPath: string, options: { incremental?: boolean } = {}) {
70+
async function buildTypeScript(
71+
buildPath: string,
72+
options: { cwd: string; tsconfig?: string; incremental?: boolean },
73+
) {
74+
let tsconfig = options.tsconfig;
75+
if (!tsconfig && (await fse.exists(join(options.cwd, DEFAULT_TS_BUILD_CONFIG)))) {
76+
tsconfig = join(options.cwd, DEFAULT_TS_BUILD_CONFIG);
77+
}
6978
assertTypeScriptBuildResult(
7079
await execa('npx', [
7180
'tsc',
81+
...(tsconfig ? ['--project', tsconfig] : []),
7282
...compilerOptionsToArgs(typeScriptCompilerOptions('esm')),
7383
...(options.incremental ? ['--incremental'] : []),
7484
'--outDir',
@@ -79,6 +89,7 @@ async function buildTypeScript(buildPath: string, options: { incremental?: boole
7989
assertTypeScriptBuildResult(
8090
await execa('npx', [
8191
'tsc',
92+
...(tsconfig ? ['--project', tsconfig] : []),
8293
...compilerOptionsToArgs(typeScriptCompilerOptions('cjs')),
8394
...(options.incremental ? ['--incremental'] : []),
8495
'--outDir',
@@ -90,6 +101,7 @@ async function buildTypeScript(buildPath: string, options: { incremental?: boole
90101
export const buildCommand = createCommand<
91102
{},
92103
{
104+
tsconfig?: string;
93105
incremental?: boolean;
94106
}
95107
>(api => {
@@ -100,13 +112,17 @@ export const buildCommand = createCommand<
100112
describe: 'Build',
101113
builder(yargs) {
102114
return yargs.options({
115+
tsconfig: {
116+
describe: `Which tsconfig file to use when building TypeScript. By default bob will use ${DEFAULT_TS_BUILD_CONFIG} if it exists, otherwise the TSC's default.`,
117+
type: 'string',
118+
},
103119
incremental: {
104120
describe: 'Better performance by building only packages that had changes.',
105121
type: 'boolean',
106122
},
107123
});
108124
},
109-
async handler({ incremental }) {
125+
async handler({ tsconfig, incremental }) {
110126
const cwd = process.cwd();
111127
const rootPackageJSON = await getRootPackageJSON();
112128
const workspaces = await getWorkspaces(rootPackageJSON);
@@ -118,7 +134,7 @@ export const buildCommand = createCommand<
118134
if (!incremental) {
119135
await fse.remove(buildPath);
120136
}
121-
await buildTypeScript(buildPath, { incremental });
137+
await buildTypeScript(buildPath, { cwd, tsconfig, incremental });
122138
const pkg = await fse.readJSON(resolve(cwd, 'package.json'));
123139
const fullName: string = pkg.name;
124140

@@ -155,7 +171,7 @@ export const buildCommand = createCommand<
155171
if (!incremental) {
156172
await fse.remove(bobBuildPath);
157173
}
158-
await buildTypeScript(bobBuildPath, { incremental });
174+
await buildTypeScript(bobBuildPath, { cwd, tsconfig, incremental });
159175

160176
await Promise.all(
161177
packageInfoList.map(({ cwd, pkg, fullName }) =>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello!
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"name": "tsconfig-build-json",
3+
"type": "module",
4+
"main": "dist/cjs/index.js",
5+
"module": "dist/esm/index.js",
6+
"exports": {
7+
".": {
8+
"require": {
9+
"types": "./dist/typings/index.d.cts",
10+
"default": "./dist/cjs/index.js"
11+
},
12+
"import": {
13+
"types": "./dist/typings/index.d.ts",
14+
"default": "./dist/esm/index.js"
15+
},
16+
"default": {
17+
"types": "./dist/typings/index.d.ts",
18+
"default": "./dist/esm/index.js"
19+
}
20+
},
21+
"./*": {
22+
"require": {
23+
"types": "./dist/typings/*.d.cts",
24+
"default": "./dist/cjs/*.js"
25+
},
26+
"import": {
27+
"types": "./dist/typings/*.d.ts",
28+
"default": "./dist/esm/*.js"
29+
},
30+
"default": {
31+
"types": "./dist/typings/*.d.ts",
32+
"default": "./dist/esm/*.js"
33+
}
34+
},
35+
"./package.json": "./package.json",
36+
"./style.css": "./dist/esm/style.css"
37+
},
38+
"typings": "dist/typings/index.d.ts",
39+
"publishConfig": {
40+
"directory": "dist",
41+
"access": "public"
42+
},
43+
"typescript": {
44+
"definition": "dist/typings/index.d.ts"
45+
}
46+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const hello = 1;
2+
3+
export default 'there';
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"compilerOptions": {
4+
"module": "ESNext",
5+
"declaration": false
6+
}
7+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"compilerOptions": {
3+
"module": "ESNext",
4+
"declaration": true,
5+
"skipLibCheck": true,
6+
"outDir": "dist"
7+
}
8+
}

test/integration.spec.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,3 +636,84 @@ it('can build a monorepo pnpm project', async () => {
636636
cwd: path.resolve(fixturesFolder, 'simple-monorepo-pnpm'),
637637
});
638638
});
639+
640+
it('can bundle a tsconfig-build-json project', async () => {
641+
await fse.remove(path.resolve(fixturesFolder, 'tsconfig-build-json', 'dist'));
642+
643+
const result = await execa('node', [binaryFolder, 'build'], {
644+
cwd: path.resolve(fixturesFolder, 'tsconfig-build-json'),
645+
});
646+
expect(result.exitCode).toEqual(0);
647+
648+
const baseDistPath = path.resolve(fixturesFolder, 'tsconfig-build-json', 'dist');
649+
await expect(fse.readFile(path.resolve(baseDistPath, 'package.json'), 'utf8')).resolves
650+
.toMatchInlineSnapshot(`
651+
{
652+
"name": "tsconfig-build-json",
653+
"main": "cjs/index.js",
654+
"module": "esm/index.js",
655+
"typings": "typings/index.d.ts",
656+
"typescript": {
657+
"definition": "typings/index.d.ts"
658+
},
659+
"type": "module",
660+
"exports": {
661+
".": {
662+
"require": {
663+
"types": "./typings/index.d.cts",
664+
"default": "./cjs/index.js"
665+
},
666+
"import": {
667+
"types": "./typings/index.d.ts",
668+
"default": "./esm/index.js"
669+
},
670+
"default": {
671+
"types": "./typings/index.d.ts",
672+
"default": "./esm/index.js"
673+
}
674+
},
675+
"./*": {
676+
"require": {
677+
"types": "./typings/*.d.cts",
678+
"default": "./cjs/*.js"
679+
},
680+
"import": {
681+
"types": "./typings/*.d.ts",
682+
"default": "./esm/*.js"
683+
},
684+
"default": {
685+
"types": "./typings/*.d.ts",
686+
"default": "./esm/*.js"
687+
}
688+
},
689+
"./package.json": "./package.json",
690+
"./style.css": "./esm/style.css"
691+
}
692+
}
693+
`);
694+
await expect(
695+
fse.readFile(path.resolve(baseDistPath, 'README.md'), 'utf8'),
696+
).resolves.toMatchInlineSnapshot('Hello!');
697+
await expect(fse.readFile(path.resolve(baseDistPath, 'cjs', 'index.js'), 'utf8')).resolves
698+
.toMatchInlineSnapshot(`
699+
"use strict";
700+
exports.__esModule = true;
701+
exports.hello = void 0;
702+
exports.hello = 1;
703+
exports["default"] = 'there';
704+
`);
705+
await expect(fse.readFile(path.resolve(baseDistPath, 'esm', 'index.js'), 'utf8')).resolves
706+
.toMatchInlineSnapshot(`
707+
export var hello = 1;
708+
export default 'there';
709+
`);
710+
711+
// because the tsconfig.build.json has `declaration: false`
712+
await expect(fse.stat(path.resolve(baseDistPath, 'typings', 'index.d.ts'))).rejects.toThrowError(
713+
'ENOENT: no such file or directory',
714+
);
715+
716+
await execa('node', [binaryFolder, 'check'], {
717+
cwd: path.resolve(fixturesFolder, 'simple'),
718+
});
719+
});

0 commit comments

Comments
 (0)