diff --git a/src/build.spec.ts b/src/build.spec.ts index 1a07154d..15a656d4 100644 --- a/src/build.spec.ts +++ b/src/build.spec.ts @@ -1,11 +1,11 @@ import * as Constants from './util/constants'; import { BuildContext } from './util/interfaces'; import * as helpers from './util/helpers'; -import * as build from './build'; +import * as build from './build'; import * as bundle from './bundle'; import * as copy from './copy'; -import * as clean from './clean'; +import * as clean from './clean'; import * as lint from './lint'; import * as minify from './minify'; import * as ngc from './ngc'; @@ -17,16 +17,15 @@ import * as transpile from './transpile'; describe('build', () => { beforeEach(() => { spyOn(clean, 'clean'); - spyOn(helpers, 'readFileAsync').and.callFake(() => { - return Promise.resolve(`{ - "compilerOptions": { + spyOn(helpers, helpers.readFileAsync.name).and.returnValue(Promise.resolve()); + spyOn(transpile, transpile.getTsConfigAsync.name).and.callFake(() => { + return Promise.resolve({ + "options": { "sourceMap": true } - } - `); + }); }); - spyOn(bundle, bundle.bundle.name).and.returnValue(Promise.resolve()); spyOn(copy, copy.copy.name).and.returnValue(Promise.resolve()); spyOn(minify, minify.minifyCss.name).and.returnValue(Promise.resolve()); @@ -135,7 +134,7 @@ describe('test project requirements before building', () => { spyOn(helpers, 'readFileAsync').and.returnValue(Promise.reject(error)); return build.build({}).catch((e) => { - expect(helpers.readFileAsync).toHaveBeenCalledTimes(2); + expect(helpers.readFileAsync).toHaveBeenCalledTimes(1); expect(e).toEqual(error); }); }); @@ -143,17 +142,14 @@ describe('test project requirements before building', () => { it('should fail if IONIC_TS_CONFIG file does not exist', () => { process.env[Constants.ENV_APP_ENTRY_POINT] = 'src/app/main.ts'; process.env[Constants.ENV_TS_CONFIG] = 'tsConfig.js'; - const error = new Error('App entry point was not found'); + const error = new Error('Config was not found'); - spyOn(helpers, 'readFileAsync').and.callFake((filePath: string) => { - if (filePath === 'src/app/main.ts') { - return Promise.resolve('allgood'); - } - return Promise.reject(error); - }); + spyOn(helpers, helpers.readFileAsync.name).and.returnValues(Promise.resolve()); + spyOn(transpile, transpile.getTsConfigAsync.name).and.returnValues(Promise.reject(error)); return build.build({}).catch((e) => { - expect(helpers.readFileAsync).toHaveBeenCalledTimes(2); + expect(transpile.getTsConfigAsync).toHaveBeenCalledTimes(1); + expect(helpers.readFileAsync).toHaveBeenCalledTimes(1); expect(e).toEqual(error); }); }); @@ -161,9 +157,9 @@ describe('test project requirements before building', () => { it('should fail fataly if IONIC_TS_CONFIG file does not contain valid JSON', () => { process.env[Constants.ENV_APP_ENTRY_POINT] = 'src/app/main.ts'; process.env[Constants.ENV_TS_CONFIG] = 'tsConfig.js'; - spyOn(helpers, 'readFileAsync').and.callFake(() => { + spyOn(transpile, transpile.getTsConfigAsync.name).and.callFake(() => { return Promise.resolve(`{ - "compilerOptions" { + "options" { "sourceMap": false } } @@ -171,7 +167,7 @@ describe('test project requirements before building', () => { }); return build.build({}).catch((e) => { - expect(helpers.readFileAsync).toHaveBeenCalledTimes(2); + expect(transpile.getTsConfigAsync).toHaveBeenCalledTimes(1); expect(e.isFatal).toBeTruthy(); }); }); @@ -179,9 +175,9 @@ describe('test project requirements before building', () => { it('should fail fataly if IONIC_TS_CONFIG file does not contain compilerOptions.sourceMap === true', () => { process.env[Constants.ENV_APP_ENTRY_POINT] = 'src/app/main.ts'; process.env[Constants.ENV_TS_CONFIG] = 'tsConfig.js'; - spyOn(helpers, 'readFileAsync').and.callFake(() => { + spyOn(transpile, transpile.getTsConfigAsync.name).and.callFake(() => { return Promise.resolve(`{ - "compilerOptions": { + "options": { "sourceMap": false } } @@ -189,7 +185,7 @@ describe('test project requirements before building', () => { }); return build.build({}).catch((e) => { - expect(helpers.readFileAsync).toHaveBeenCalledTimes(2); + expect(transpile.getTsConfigAsync).toHaveBeenCalledTimes(1); expect(e.isFatal).toBeTruthy(); }); }); @@ -208,18 +204,17 @@ describe('test project requirements before building', () => { spyOn(postprocess, postprocess.postprocess.name).and.returnValue(Promise.resolve()); spyOn(preprocess, preprocess.preprocess.name).and.returnValue(Promise.resolve()); spyOn(sass, sass.sass.name).and.returnValue(Promise.resolve()); + spyOn(helpers, helpers.readFileAsync.name).and.returnValue(Promise.resolve()); spyOn(transpile, transpile.transpile.name).and.returnValue(Promise.resolve()); - spyOn(helpers, helpers.readFileAsync.name).and.callFake(() => { - return Promise.resolve(`{ - "compilerOptions": { - "sourceMap": true - } + spyOn(transpile, transpile.getTsConfigAsync.name).and.returnValue(Promise.resolve({ + "options": { + "sourceMap": true } - `); - }); + })); return build.build({}).then(() => { - expect(helpers.readFileAsync).toHaveBeenCalledTimes(2); + expect(transpile.getTsConfigAsync).toHaveBeenCalledTimes(1); + expect(helpers.readFileAsync).toHaveBeenCalledTimes(1); }); }); }); diff --git a/src/build.ts b/src/build.ts index e53d58ac..403d2f61 100644 --- a/src/build.ts +++ b/src/build.ts @@ -10,6 +10,7 @@ import { lint, lintUpdate } from './lint'; import { Logger } from './logger/logger'; import { minifyCss, minifyJs } from './minify'; import { ngc } from './ngc'; +import { getTsConfigAsync, TsConfig } from './transpile'; import { postprocess } from './postprocess'; import { preprocess, preprocessUpdate } from './preprocess'; import { sass, sassUpdate } from './sass'; @@ -34,20 +35,20 @@ export function build(context: BuildContext) { function buildWorker(context: BuildContext) { return Promise.resolve().then(() => { // load any 100% required files to ensure they exist - return validateRequiredFilesExist(); + return validateRequiredFilesExist(context); }) - .then(([_, tsConfigContents]) => { - return validateTsConfigSettings(tsConfigContents); - }) - .then(() => { - return buildProject(context); - }); + .then(([_, tsConfigContents]) => { + return validateTsConfigSettings(tsConfigContents); + }) + .then(() => { + return buildProject(context); + }); } -function validateRequiredFilesExist() { +function validateRequiredFilesExist(context: BuildContext) { return Promise.all([ readFileAsync(process.env[Constants.ENV_APP_ENTRY_POINT]), - readFileAsync(process.env[Constants.ENV_TS_CONFIG]) + getTsConfigAsync(context, process.env[Constants.ENV_TS_CONFIG]) ]).catch((error) => { if (error.code === 'ENOENT' && error.path === process.env[Constants.ENV_APP_ENTRY_POINT]) { error = new BuildError(`${error.path} was not found. The "main.dev.ts" and "main.prod.ts" files have been deprecated. Please create a new file "main.ts" containing the content of "main.dev.ts", and then delete the deprecated files. @@ -68,15 +69,12 @@ function validateRequiredFilesExist() { }); } -function validateTsConfigSettings(tsConfigFileContents: string) { +function validateTsConfigSettings(tsConfigFileContents: TsConfig) { return new Promise((resolve, reject) => { try { - const tsConfigJson = JSON.parse(tsConfigFileContents); - const isValid = tsConfigJson.hasOwnProperty('compilerOptions') && - tsConfigJson.compilerOptions.hasOwnProperty('sourceMap') && - tsConfigJson.compilerOptions.sourceMap === true; - + const isValid = tsConfigFileContents.options && + tsConfigFileContents.options.sourceMap === true; if (!isValid) { const error = new BuildError(['The "tsconfig.json" file must have compilerOptions.sourceMap set to true.', 'For more information please see the default Ionic project tsconfig.json file here:', @@ -285,7 +283,7 @@ function buildUpdateTasks(changedFiles: ChangedFile[], context: BuildContext) { filePath: outputCssFile }; - context.fileCache.set(outputCssFile, { path: outputCssFile, content: outputCssFile}); + context.fileCache.set(outputCssFile, { path: outputCssFile, content: outputCssFile }); resolveValue.changedFiles.push(changedFile); }); @@ -299,7 +297,7 @@ function buildUpdateTasks(changedFiles: ChangedFile[], context: BuildContext) { filePath: outputCssFile }; - context.fileCache.set(outputCssFile, { path: outputCssFile, content: outputCssFile}); + context.fileCache.set(outputCssFile, { path: outputCssFile, content: outputCssFile }); resolveValue.changedFiles.push(changedFile); }); @@ -324,7 +322,7 @@ function loadFiles(changedFiles: ChangedFile[], context: BuildContext) { const promise = readFileAsync(changedFile.filePath); promises.push(promise); promise.then((content: string) => { - context.fileCache.set(changedFile.filePath, { path: changedFile.filePath, content: content}); + context.fileCache.set(changedFile.filePath, { path: changedFile.filePath, content: content }); }); } } diff --git a/src/transpile.ts b/src/transpile.ts index 576143a9..2dcbe1fa 100644 --- a/src/transpile.ts +++ b/src/transpile.ts @@ -88,7 +88,7 @@ export function transpileWorker(context: BuildContext, workerConfig: TranspileWo tsConfig.options.sourceMap = false; } else { - // build the ts source maps if the bundler is going to use source maps + // build the ts source maps if the bundler is going to use source maps tsConfig.options.sourceMap = buildJsSourceMaps(context); } @@ -113,8 +113,8 @@ export function transpileWorker(context: BuildContext, workerConfig: TranspileWo cachedProgram = program; const tsDiagnostics = program.getSyntacticDiagnostics() - .concat(program.getSemanticDiagnostics()) - .concat(program.getOptionsDiagnostics()); + .concat(program.getSemanticDiagnostics()) + .concat(program.getOptionsDiagnostics()); const diagnostics = runTypeScriptDiagnostics(context, tsDiagnostics); @@ -300,6 +300,10 @@ function writeTranspiledFilesCallback(fileCache: FileCache, sourcePath: string, } } +export async function getTsConfigAsync(context: BuildContext, tsConfigPath?: string): Promise { + return await getTsConfig(context, tsConfigPath); +} + export function getTsConfig(context: BuildContext, tsConfigPath?: string): TsConfig { let config: TsConfig = null; tsConfigPath = tsConfigPath || getTsConfigPath(context); @@ -317,9 +321,9 @@ export function getTsConfig(context: BuildContext, tsConfigPath?: string): TsCon } else { const parsedConfig = ts.parseJsonConfigFileContent( - tsConfigFile.config, - ts.sys, context.rootDir, - {}, tsConfigPath); + tsConfigFile.config, + ts.sys, context.rootDir, + {}, tsConfigPath); const diagnostics = runTypeScriptDiagnostics(context, parsedConfig.errors);