Last active
July 6, 2017 21:13
-
-
Save smac89/49f3b076cd987e0875ba9bfb3fe81ef9 to your computer and use it in GitHub Desktop.
Solution to "Error: gulp-typescript: A project cannot be used in two compilations * at the same time. Create multiple projects with createProject instead."
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {Project, CompileStream} from 'gulp-typescript'; | |
import {Duplex, PassThrough, Readable} from 'stream'; | |
import {Reporter} from 'gulp-typescript/release/reporter'; | |
type Callback = () => void; | |
/** | |
* This is used to ensure that each project object is not busy when it is to be used | |
* This prevents the annoying: | |
* "Error: gulp-typescript: A project cannot be used in two compilations | |
* at the same time. Create multiple projects with createProject instead." | |
* @param project The project | |
* @param reporter The reporter for the project | |
* @returns {CompileStream} compiled project stream | |
*/ | |
export function tsCompileQStream(project: Project, reporter?: Reporter): CompileStream { | |
return new class extends PassThrough implements CompileStream { | |
public readonly js: Duplex = this; | |
public readonly dts: Duplex = new PassThrough(); | |
private transformStream: CompileStream; | |
private signal: Callback; | |
constructor() { | |
super({ objectMode: true }); | |
this.on('pipe', this.checkExistingFlow); | |
} | |
private checkExistingFlow(src: Readable) { | |
this.removeListener('pipe', this.checkExistingFlow); | |
src.unpipe(this); | |
this.signal = CompileScheduler.scheduleCompilation(project, () => { | |
this.transformStream = project(reporter).on('finish', () => this.signal()); | |
let compileStream = src.pipe(this.transformStream); | |
compileStream.js.pipe(this.js); | |
compileStream.dts.pipe(this.dts); | |
}); | |
} | |
}; | |
} | |
class CompileScheduler { | |
private static compileGateKeeper: Map<Project, Callback[]> = new Map(); | |
public static scheduleCompilation(project: Project, beginCompilation: Callback): Callback { | |
let projectQueue = CompileScheduler.compileGateKeeper.get(project); | |
if (!projectQueue) { | |
projectQueue = []; | |
CompileScheduler.compileGateKeeper.set(project, projectQueue); | |
} | |
let ret = CompileScheduler.startNext(project); | |
if (projectQueue.length) { | |
projectQueue.push(beginCompilation); | |
} else { | |
projectQueue.push(ret); | |
beginCompilation(); | |
} | |
return ret; | |
} | |
private static startNext(project: Project): Callback { | |
return () => { | |
let projectQueue = CompileScheduler.compileGateKeeper.get(project); | |
if (projectQueue.length) { | |
let nextCompilation = projectQueue.shift(); | |
nextCompilation(); | |
} | |
}; | |
} | |
private constructor() {} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
gulp.task('build', () => { | |
let project = tsc.createProject('path/to/tsconfig.json'); | |
return project.src() | |
.pipe(sourcemaps.init()) | |
.pipe(tsCompileQStream(project)) // wrap the project with the function call | |
.js // you don't need this as the wrapper exposes the js stream by default | |
.pipe(sourcemaps.write()) | |
.pipe(gulp.dest(project.options.outDir)); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment