Skip to content

Commit 63fb610

Browse files
authoredDec 5, 2024
feat: strict config file source (#6)
1 parent 55d6b8e commit 63fb610

File tree

3 files changed

+100
-7
lines changed

3 files changed

+100
-7
lines changed
 

‎README.md

+41
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,47 @@ You can change your build script in "package.json" as:
4343

4444
Now you can run `npm run build` to build.
4545

46+
### About .swcrc
47+
48+
tswc will always merge your swc configuration file on top of any of the options that were inferred from your tsconfig.
49+
By default, swc and tswc will look for a .swcrc file and tolerate if there is none found. However, tswc will respect
50+
any `--config-file` option that you provide to swc and will even make sure to throw an error if the file is missing.
51+
52+
```shell
53+
# Example of using a .development.swcrc file to override the base config from tsconfig
54+
tswc -- --config-file .development.swcrc
55+
```
56+
57+
As a naive example, if you had a tsconfig.json file that used commonjs compilation, but also wanted to compile an esm version,
58+
you could set up a .esm.swcrc so that:
59+
60+
```json
61+
// tsconfig.json
62+
{
63+
"module": "commonjs",
64+
"moduleResolution": "node",
65+
// Other options
66+
}
67+
68+
// .esm.swcrc
69+
{
70+
"module": {
71+
// This overrides the module "commonjs" of tsconfig to es6
72+
"type": "es6"
73+
}
74+
}
75+
```
76+
77+
The corresponding commands for this project might be something like:
78+
79+
```shell
80+
# Creates esm syntax compiled files
81+
tswc -- src -d dist/esm --config-file .esm.swcrc
82+
83+
# Creates commonjs syntax compiled files
84+
tswc -- src -d dist/esm
85+
```
86+
4687
## Notice
4788

4889
Only a subgroup of fields of tsconfig is supported currently. This is done with [tsconfig-to-swcconfig](https://github.com/Songkeys/tsconfig-to-swcconfig). This means that some tsc features may be missing when compiling with this.

‎src/cli.ts

+34-4
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,46 @@ import { parse } from 'jsonc-parser'
88

99
const cli = cac('tswc')
1010

11+
// These are swc cli arguments that we are also tapping in the wrapper
12+
const expectedSwcCli = cac('swc')
13+
expectedSwcCli.option(
14+
'--config-file <configFile>',
15+
'swc config file - override tsconfig',
16+
)
17+
1118
cli
1219
.command('[file]', 'file or directory to build')
13-
.allowUnknownOptions()
1420
.option('--tsconfig <filename>', 'the filename of tsconfig', {
1521
default: 'tsconfig.json',
1622
})
1723
.option('--debug', 'output the final swc config', { default: false })
18-
.action((file = '', { tsconfig, debug, configFile = '.swcrc', ...args }) => {
24+
.option(
25+
'-- <swc cli args>',
26+
'the remaining swc arguments like you would normally call',
27+
)
28+
.action((file = '', options: any) => {
29+
const { tsconfig, debug } = options
30+
const _swcArgs = options['--']
31+
// parse shared swc args here
32+
const swcParsedArgs = expectedSwcCli.parse(_swcArgs) as {
33+
options: {
34+
configFile?: string
35+
}
36+
}
37+
const { configFile } = swcParsedArgs.options
38+
39+
let oSwcrcPath: string
40+
if (configFile) {
41+
oSwcrcPath = path.resolve(process.cwd(), configFile)
42+
if (!fs.existsSync(oSwcrcPath)) {
43+
throw new Error(
44+
`Invalid option: --config-file. Could not find file: ${oSwcrcPath}`,
45+
)
46+
}
47+
} else {
48+
oSwcrcPath = path.resolve(process.cwd(), '.swcrc')
49+
}
1950
// read .swcrc
20-
const oSwcrcPath = path.resolve(process.cwd(), configFile)
2151
let oSwcOptions = fs.existsSync(oSwcrcPath)
2252
? parse(fs.readFileSync(oSwcrcPath, 'utf8'))
2353
: {}
@@ -36,7 +66,7 @@ cli
3666

3767
// compile
3868
const swcBin = require.resolve('.bin/swc')
39-
const swcArgs = [file, ...args['--'], '--config-file', SWCRC_PATH]
69+
const swcArgs = [file, ..._swcArgs, '--config-file', SWCRC_PATH]
4070
if (debug) {
4171
console.log(`> swc ${swcArgs.join(' ')}`)
4272
}

‎test/cli.test.ts

+25-3
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,21 @@ const cliBin = path.join(__dirname, '..', 'src', 'cli.ts')
99
// const cliBin = path.join(__dirname, '..', 'dist', 'cli.js')
1010

1111
describe('test suite', () => {
12-
it('generally work', ({ expect }) => {
12+
it('generally works', ({ expect }) => {
1313
const proc = spawnSync(node, [cliBin], {
1414
stdio: 'pipe',
1515
})
1616
expect(proc.stdout.toString()).toBeTypeOf('string')
1717
expect(proc.status).toBe(0)
1818
})
1919

20-
it('compile some code', ({ expect }) => {
21-
// const { stdout } = spawnSync(
20+
it('compiles some code', ({ expect }) => {
2221
const proc = spawnSync(
2322
node,
2423
[
2524
cliBin,
25+
'--',
26+
// swc args
2627
path.join(__dirname, 'fixtures', 'src', 'index.ts'),
2728
'--config-file',
2829
path.join(__dirname, 'fixtures', 'src', '.swcrc'),
@@ -61,4 +62,25 @@ describe('test suite', () => {
6162
expect(proc.stderr.toString()).toMatch(/error: unknown option/)
6263
} catch {}
6364
})
65+
it('throws if the config does not exist', ({ expect }) => {
66+
const codePath = path.join(__dirname, 'fixtures', 'src', 'index.ts')
67+
try {
68+
const proc = spawnSync(
69+
node,
70+
[
71+
cliBin,
72+
// swc arguments
73+
'--',
74+
path.join(__dirname, 'fixtures', 'src', 'index.ts'),
75+
'--config-file',
76+
path.join(__dirname, 'fixtures', 'src', 'nope.swcrc'),
77+
],
78+
{ stdio: 'pipe' },
79+
)
80+
expect(proc.status).toBe(1)
81+
expect(proc.stderr.toString()).toMatch(
82+
/Invalid option: --config-file. Could not find file:/,
83+
)
84+
} catch {}
85+
})
6486
})

0 commit comments

Comments
 (0)