Skip to content

Commit a367dcd

Browse files
authored
feat: Support user defined tsconfig paths (serverless#205)
1 parent f00781d commit a367dcd

8 files changed

+81
-6
lines changed

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ The default `tsconfig.json` file used by the plugin looks like this:
6161

6262
All files from `package/include` will be included in the final build file. See [Exclude/Include](https://serverless.com/framework/docs/providers/aws/guide/packaging#exclude--include)
6363

64+
### Non-standard tsconfig.json locations
65+
Override what tsconfig.json to use with the following snippet in your severless.yaml
66+
```
67+
custom:
68+
serverlessPluginTypescript:
69+
tsConfigFileLocation: './tsconfig.build.json'
70+
71+
```
6472
6573
## Usage
6674

src/Serverless.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ declare namespace Serverless {
1717
}
1818
package: Serverless.Package
1919
getAllFunctions(): string[]
20+
custom?: {
21+
serverlessPluginTypescript?: {
22+
tsConfigFileLocation: string
23+
}
24+
}
2025
}
2126

2227
pluginManager: PluginManager

src/index.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,16 @@ export class TypeScriptPlugin {
145145
// Fake service path so that serverless will know what to zip
146146
this.serverless.config.servicePath = path.join(this.originalServicePath, BUILD_FOLDER)
147147
}
148-
148+
let tsConfigFileLocation: string | undefined
149+
if (
150+
this.serverless.service.custom !== undefined
151+
&& this.serverless.service.custom.serverlessPluginTypescript !== undefined
152+
) {
153+
tsConfigFileLocation = this.serverless.service.custom.serverlessPluginTypescript.tsConfigFileLocation
154+
}
149155
const tsconfig = typescript.getTypescriptConfig(
150156
this.originalServicePath,
157+
tsConfigFileLocation,
151158
this.isWatching ? null : this.serverless.cli
152159
)
153160

src/typescript.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,20 @@ export function getSourceFiles(
112112

113113
export function getTypescriptConfig(
114114
cwd: string,
115+
tsConfigFileLocation: string = 'tsconfig.json',
115116
logger?: { log: (str: string) => void }
116117
): ts.CompilerOptions {
117-
const configFilePath = path.join(cwd, 'tsconfig.json')
118+
const configFilePath = path.join(cwd, tsConfigFileLocation)
118119

119120
if (fs.existsSync(configFilePath)) {
120-
121121
const configFileText = fs.readFileSync(configFilePath).toString()
122122
const result = ts.parseConfigFileTextToJson(configFilePath, configFileText)
123123
if (result.error) {
124-
throw new Error(JSON.stringify(result.error))
124+
try {
125+
throw new Error(JSON.stringify(result.error))
126+
} catch (err) {
127+
throw new Error('Invalid TSConfig file - is this file JSON format?')
128+
}
125129
}
126130

127131
const configParseResult = ts.parseJsonConfigFileContent(result.config, ts.sys, path.dirname(configFilePath))
@@ -130,7 +134,7 @@ export function getTypescriptConfig(
130134
}
131135

132136
if (logger) {
133-
logger.log(`Using local tsconfig.json`)
137+
logger.log(`Using local tsconfig.json - ${tsConfigFileLocation}`)
134138
}
135139

136140
// disallow overrriding rootDir

tests/assets/tsconfigs/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const test = 'example'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"compilerOptions": {
3+
"preserveConstEnums": true,
4+
"strictNullChecks": true,
5+
"sourceMap": true,
6+
"allowJs": true,
7+
"target": "es5",
8+
"outDir": ".build",
9+
"moduleResolution": "node",
10+
"lib": ["es2015"],
11+
"rootDir": "./"
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is not a tsconfig.json file

tests/typescript.getTypescriptConfig.test.ts

+37-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {getTypescriptConfig, makeDefaultTypescriptConfig} from '../src/typescript'
2+
import * as path from 'path'
23

34
describe('getTypescriptConfig', () => {
45
it(`returns default typescript configuration if the one provided doesn't exist`, () => {
@@ -8,4 +9,39 @@ describe('getTypescriptConfig', () => {
89
makeDefaultTypescriptConfig()
910
)
1011
})
11-
})
12+
13+
it(`returns default typescript configuration if the one provided doesn't exist when tsConfigFileLocation provided`, () => {
14+
expect(
15+
getTypescriptConfig(process.cwd(), './tests/assets/tsconfigs/tsconfig.nonexistent.json'),
16+
).toEqual(
17+
makeDefaultTypescriptConfig()
18+
)
19+
})
20+
21+
it(`returns custom typescript configuration if tsConfigFileLocation provided`, () => {
22+
const tsconfigDir = path.join(process.cwd(), './tests/assets/tsconfigs/')
23+
expect(
24+
getTypescriptConfig(tsconfigDir, 'tsconfig.default.json'),
25+
).toEqual({
26+
allowJs: true,
27+
configFilePath: undefined,
28+
lib: ["lib.es2015.d.ts"],
29+
moduleResolution: 2,
30+
outDir: path.join(tsconfigDir, '.build'),
31+
preserveConstEnums: true,
32+
rootDir: tsconfigDir,
33+
sourceMap: true,
34+
strictNullChecks: true,
35+
target: 1
36+
})
37+
})
38+
39+
it(`throws error if configuration from tsConfigFileLocation is invalid`, () => {
40+
expect.assertions(1)
41+
try {
42+
getTypescriptConfig(process.cwd(), './tests/assets/tsconfigs/tsconfig.invalid.json')
43+
} catch (e) {
44+
expect(e.message).toBe('Invalid TSConfig file - is this file JSON format?')
45+
}
46+
})
47+
})

0 commit comments

Comments
 (0)