1
1
import semver from 'semver' ;
2
+ import { Remote } from 'stagehand' ;
3
+ import { connect } from 'stagehand/lib/adapters/child-process' ;
2
4
import { hasPlugin , addPlugin , AddPluginOptions } from 'ember-cli-babel-plugin-helpers' ;
3
5
import Addon from 'ember-cli/lib/models/addon' ;
4
6
import { addon } from './lib/utilities/ember-cli-entities' ;
7
+ import fork from './lib/utilities/fork' ;
8
+ import TypecheckWorker from './lib/typechecking/worker' ;
9
+ import TypecheckMiddleware from './lib/typechecking/middleware' ;
5
10
6
11
export default addon ( {
7
12
name : 'ember-cli-typescript' ,
@@ -10,6 +15,12 @@ export default addon({
10
15
this . _super . included . apply ( this , arguments ) ;
11
16
this . _checkDevelopment ( ) ;
12
17
this . _checkBabelVersion ( ) ;
18
+
19
+ // If we're a direct dependency of the host app, go ahead and start up the
20
+ // typecheck worker so we don't wait until the end of the build to check
21
+ if ( this . parent === this . project ) {
22
+ this . _getTypecheckWorker ( ) ;
23
+ }
13
24
} ,
14
25
15
26
includedCommands ( ) {
@@ -25,7 +36,30 @@ export default addon({
25
36
return `${ __dirname } /blueprints` ;
26
37
} ,
27
38
28
- setupPreprocessorRegistry ( type : string ) {
39
+ serverMiddleware ( { app } ) {
40
+ let workerPromise = this . _getTypecheckWorker ( ) ;
41
+ let middleware = new TypecheckMiddleware ( this . project , workerPromise ) ;
42
+ middleware . register ( app ) ;
43
+ } ,
44
+
45
+ async postBuild ( ) {
46
+ // This code makes the fundamental assumption that the TS compiler's fs watcher
47
+ // will notice a file change before the full Broccoli build completes. Otherwise
48
+ // the `getStatus` call here might report the status of the previous check. In
49
+ // practice, though, building takes much longer than the time to trigger the
50
+ // compiler's "hey, a file changed" hook, and once the typecheck has begun, the
51
+ // `getStatus` call will block until it's complete.
52
+ let worker = await this . _getTypecheckWorker ( ) ;
53
+ let { failed } = await worker . getStatus ( ) ;
54
+
55
+ if ( failed ) {
56
+ // The actual details of the errors will already have been printed
57
+ // with nice highlighting and formatting separately.
58
+ throw new Error ( 'Typechecking failed' ) ;
59
+ }
60
+ } ,
61
+
62
+ setupPreprocessorRegistry ( type ) {
29
63
if ( type !== 'parent' ) return ;
30
64
31
65
// Normally this is the sort of logic that would live in `included()`, but
@@ -52,10 +86,11 @@ export default addon({
52
86
53
87
_checkBabelVersion ( ) {
54
88
let babel = this . parent . addons . find ( addon => addon . name === 'ember-cli-babel' ) ;
55
- if ( ! babel || ! semver . satisfies ( babel . pkg . version , '>=7.0.0-alpha.0 <8' ) ) {
56
- let version = babel ? `version ${ babel . pkg . version } ` : `no instance of ember-cli-babel` ;
89
+ let version = babel && babel . pkg . version ;
90
+ if ( ! babel || ! ( semver . gte ( version ! , '7.1.0' ) && semver . lt ( version ! , '8.0.0' ) ) ) {
91
+ let versionString = babel ? `version ${ babel . pkg . version } ` : `no instance of ember-cli-babel` ;
57
92
this . ui . writeWarnLine (
58
- `ember-cli-typescript requires ember-cli-babel@7 , but you have ${ version } installed; ` +
93
+ `ember-cli-typescript requires ember-cli-babel ^7.1.0 , but you have ${ versionString } installed; ` +
59
94
'your TypeScript files may not be transpiled correctly.'
60
95
) ;
61
96
}
@@ -95,4 +130,29 @@ export default addon({
95
130
extensions . push ( 'ts' ) ;
96
131
}
97
132
} ,
133
+
134
+ _typecheckWorker : undefined as Promise < Remote < TypecheckWorker > > | undefined ,
135
+
136
+ _getTypecheckWorker ( ) {
137
+ if ( ! this . _typecheckWorker ) {
138
+ this . _typecheckWorker = this . _forkTypecheckWorker ( ) ;
139
+ }
140
+
141
+ return this . _typecheckWorker ;
142
+ } ,
143
+
144
+ async _forkTypecheckWorker ( ) {
145
+ let childProcess = fork ( `${ __dirname } /lib/typechecking/worker/launch` ) ;
146
+ let worker = await connect < TypecheckWorker > ( childProcess ) ;
147
+
148
+ await worker . onTypecheck ( status => {
149
+ for ( let error of status . errors ) {
150
+ this . ui . writeLine ( error ) ;
151
+ }
152
+ } ) ;
153
+
154
+ await worker . start ( this . project . root ) ;
155
+
156
+ return worker ;
157
+ } ,
98
158
} ) ;
0 commit comments