diff --git a/README.md b/README.md index dbcea723..9714ffc1 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,14 @@ The default `tsconfig.json` file used by the plugin looks like this: 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) +### Non-standard tsconfig.json locations +Override what tsconfig.json to use with the following snippet in your severless.yaml +``` +custom: + serverlessPluginTypescript: + tsConfigFileLocation: './tsconfig.build.json' + +``` ## Usage diff --git a/src/Serverless.d.ts b/src/Serverless.d.ts index ec7d7049..b37fd703 100644 --- a/src/Serverless.d.ts +++ b/src/Serverless.d.ts @@ -17,6 +17,11 @@ declare namespace Serverless { } package: Serverless.Package getAllFunctions(): string[] + custom?: { + serverlessPluginTypescript?: { + tsConfigFileLocation: string + } + } } pluginManager: PluginManager diff --git a/src/index.ts b/src/index.ts index a249ce58..f8df31a9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -144,9 +144,16 @@ export class TypeScriptPlugin { // Fake service path so that serverless will know what to zip this.serverless.config.servicePath = path.join(this.originalServicePath, BUILD_FOLDER) } - + let tsConfigFileLocation: string | undefined + if ( + this.serverless.service.custom !== undefined + && this.serverless.service.custom.serverlessPluginTypescript !== undefined + ) { + tsConfigFileLocation = this.serverless.service.custom.serverlessPluginTypescript.tsConfigFileLocation + } const tsconfig = typescript.getTypescriptConfig( this.originalServicePath, + tsConfigFileLocation, this.isWatching ? null : this.serverless.cli ) diff --git a/src/typescript.ts b/src/typescript.ts index 22f7354a..b3e37d25 100644 --- a/src/typescript.ts +++ b/src/typescript.ts @@ -112,16 +112,20 @@ export function getSourceFiles( export function getTypescriptConfig( cwd: string, + tsConfigFileLocation: string = 'tsconfig.json', logger?: { log: (str: string) => void } ): ts.CompilerOptions { - const configFilePath = path.join(cwd, 'tsconfig.json') + const configFilePath = path.join(cwd, tsConfigFileLocation) if (fs.existsSync(configFilePath)) { - const configFileText = fs.readFileSync(configFilePath).toString() const result = ts.parseConfigFileTextToJson(configFilePath, configFileText) if (result.error) { - throw new Error(JSON.stringify(result.error)) + try { + throw new Error(JSON.stringify(result.error)) + } catch (err) { + throw new Error('Invalid TSConfig file - is this file JSON format?') + } } const configParseResult = ts.parseJsonConfigFileContent(result.config, ts.sys, path.dirname(configFilePath)) @@ -130,7 +134,7 @@ export function getTypescriptConfig( } if (logger) { - logger.log(`Using local tsconfig.json`) + logger.log(`Using local tsconfig.json - ${tsConfigFileLocation}`) } // disallow overrriding rootDir diff --git a/tests/assets/tsconfigs/index.ts b/tests/assets/tsconfigs/index.ts new file mode 100644 index 00000000..3866f7e5 --- /dev/null +++ b/tests/assets/tsconfigs/index.ts @@ -0,0 +1 @@ +export const test = 'example' \ No newline at end of file diff --git a/tests/assets/tsconfigs/tsconfig.default.json b/tests/assets/tsconfigs/tsconfig.default.json new file mode 100644 index 00000000..1fbb9835 --- /dev/null +++ b/tests/assets/tsconfigs/tsconfig.default.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "preserveConstEnums": true, + "strictNullChecks": true, + "sourceMap": true, + "allowJs": true, + "target": "es5", + "outDir": ".build", + "moduleResolution": "node", + "lib": ["es2015"], + "rootDir": "./" + } +} \ No newline at end of file diff --git a/tests/assets/tsconfigs/tsconfig.invalid.json b/tests/assets/tsconfigs/tsconfig.invalid.json new file mode 100644 index 00000000..22f6a3c6 --- /dev/null +++ b/tests/assets/tsconfigs/tsconfig.invalid.json @@ -0,0 +1 @@ +This is not a tsconfig.json file \ No newline at end of file diff --git a/tests/typescript.getTypescriptConfig.test.ts b/tests/typescript.getTypescriptConfig.test.ts index da80c772..45ba9f2e 100644 --- a/tests/typescript.getTypescriptConfig.test.ts +++ b/tests/typescript.getTypescriptConfig.test.ts @@ -1,4 +1,5 @@ import {getTypescriptConfig, makeDefaultTypescriptConfig} from '../src/typescript' +import * as path from 'path' describe('getTypescriptConfig', () => { it(`returns default typescript configuration if the one provided doesn't exist`, () => { @@ -8,4 +9,39 @@ describe('getTypescriptConfig', () => { makeDefaultTypescriptConfig() ) }) -}) \ No newline at end of file + + it(`returns default typescript configuration if the one provided doesn't exist when tsConfigFileLocation provided`, () => { + expect( + getTypescriptConfig(process.cwd(), './tests/assets/tsconfigs/tsconfig.nonexistent.json'), + ).toEqual( + makeDefaultTypescriptConfig() + ) + }) + + it(`returns custom typescript configuration if tsConfigFileLocation provided`, () => { + const tsconfigDir = path.join(process.cwd(), './tests/assets/tsconfigs/') + expect( + getTypescriptConfig(tsconfigDir, 'tsconfig.default.json'), + ).toEqual({ + allowJs: true, + configFilePath: undefined, + lib: ["lib.es2015.d.ts"], + moduleResolution: 2, + outDir: path.join(tsconfigDir, '.build'), + preserveConstEnums: true, + rootDir: tsconfigDir, + sourceMap: true, + strictNullChecks: true, + target: 1 + }) + }) + + it(`throws error if configuration from tsConfigFileLocation is invalid`, () => { + expect.assertions(1) + try { + getTypescriptConfig(process.cwd(), './tests/assets/tsconfigs/tsconfig.invalid.json') + } catch (e) { + expect(e.message).toBe('Invalid TSConfig file - is this file JSON format?') + } + }) +})