diff --git a/README.md b/README.md index ce8629b..6661a08 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ See the [TypeScript docs][tsconfig] for information on setting up `tsconfig.json * **loadSync(cwd: string, path?: string): { path?: string, config: any }** Synchronous `load`. * **readFile(filename: string): Promise** Read a JSON file as `tsconfig.json` (strip BOM, parse JSON and support empty contents). * **readFileSync(filename: string): any** Synchronous `readFile`. -* **parse(contents: string, filename: string): any** Parse file contents as `tsconfig.json` (strip BOM, parse JSON and support empty contents). +* **parse(contents: string): any** Parse file contents as `tsconfig.json` (strip BOM, parse JSON and support empty contents). ## Contributing diff --git a/src/tsconfig.spec.ts b/src/tsconfig.spec.ts index 2444e24..188273c 100644 --- a/src/tsconfig.spec.ts +++ b/src/tsconfig.spec.ts @@ -95,6 +95,27 @@ describe('tsconfig', function () { } }, path: join(TEST_DIR, 'cwd/tsconfig.json') + }, + { + args: [TEST_DIR, 'extends/tsconfig-third.json'], + config: { + compilerOptions: { + module: 'commonjs', + noImplicitAny: true, + outDir: 'dist-third', + removeComments: true, + sourceMap: true, + preserveConstEnums: true, + rootDirs: [ + 'src', + 'test' + ] + }, + files: [ + './src/bar.ts' + ] + }, + path: join(TEST_DIR, 'extends/tsconfig-third.json') } ] diff --git a/src/tsconfig.ts b/src/tsconfig.ts index c80d8c1..8b578ad 100644 --- a/src/tsconfig.ts +++ b/src/tsconfig.ts @@ -163,11 +163,23 @@ export function readFile (filename: string): Promise { return reject(err) } + let obj try { - return resolve(parse(contents, filename)) + obj = parse(contents) } catch (err) { return reject(err) } + + if (obj.extends !== undefined) { + const filepath = filename.replace(path.basename(filename), '') + const extendsFilename = resolveSync(filepath, obj.extends) as string + const extendsObj = readFileSync(extendsFilename) + delete obj.extends + + obj = mergeObjects(extendsObj, obj) + } + + return resolve(obj) }) }) } @@ -177,14 +189,24 @@ export function readFile (filename: string): Promise { */ export function readFileSync (filename: string): any { const contents = fs.readFileSync(filename, 'utf8') + let obj = parse(contents) + + if (obj.extends !== undefined) { + const filepath = filename.replace(path.basename(filename), '') + const extendsFilename = resolveSync(filepath, obj.extends) as string + const extendsObj = readFileSync(extendsFilename) + delete obj.extends + + obj = mergeObjects(extendsObj, obj) + } - return parse(contents, filename) + return obj } /** * Parse `tsconfig.json` file. */ -export function parse (contents: string, filename: string) { +export function parse (contents: string) { const data = stripComments(stripBom(contents)) // A tsconfig.json file is permitted to be completely empty. @@ -230,3 +252,16 @@ function isFile (stats: fs.Stats | void) { function isDirectory (stats: fs.Stats | void) { return stats ? (stats as fs.Stats).isDirectory() : false } + +/** + * Simple object merging + */ +function mergeObjects (target: any, source: any): any { + for (let key of Object.keys(source)) { + if (source[key] instanceof Object) { + Object.assign(source[key], mergeObjects(target[key], source[key])) + } + } + Object.assign(target, source) + return target +} diff --git a/tests/extends/tsconfig-second.json b/tests/extends/tsconfig-second.json new file mode 100644 index 0000000..137140b --- /dev/null +++ b/tests/extends/tsconfig-second.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "dist-second", + "rootDirs": [ + "src", + "test" + ] + }, + "files": [ + "./src/bar.ts" + ] +} + diff --git a/tests/extends/tsconfig-third.json b/tests/extends/tsconfig-third.json new file mode 100644 index 0000000..32ab6dd --- /dev/null +++ b/tests/extends/tsconfig-third.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig-second.json", + "compilerOptions": { + "outDir": "dist-third" + } +} diff --git a/tests/extends/tsconfig.json b/tests/extends/tsconfig.json new file mode 100644 index 0000000..776b061 --- /dev/null +++ b/tests/extends/tsconfig.json @@ -0,0 +1,18 @@ +{ + // Compiler options. + "compilerOptions": { + "module": "commonjs", + "noImplicitAny": true, + "removeComments": true, + "preserveConstEnums": true, + "outDir": "dist", + "sourceMap": true, + "rootDirs": [ + "src" + ] + }, + // These are the files to compile with. + "files": [ + "./src/foo.ts" /* Use `foo.ts` */ + ] +}