@@ -4,16 +4,24 @@ import { BuildContext } from './build-ctx';
4
4
import { compilerRequest } from '../bundle/dev-module' ;
5
5
import { createTsWatchProgram } from '../transpile/create-watch-program' ;
6
6
import { dirname , resolve } from 'path' ;
7
- import { filesChanged , hasHtmlChanges , hasScriptChanges , hasStyleChanges , scriptsAdded , scriptsDeleted } from '../fs-watch/fs-watch-rebuild' ;
7
+ import {
8
+ filesChanged ,
9
+ hasHtmlChanges ,
10
+ hasScriptChanges ,
11
+ hasStyleChanges ,
12
+ scriptsAdded ,
13
+ scriptsDeleted ,
14
+ } from '../fs-watch/fs-watch-rebuild' ;
8
15
import { hasServiceWorkerChanges } from '../service-worker/generate-sw' ;
16
+ import { isString } from '@utils' ;
9
17
import type ts from 'typescript' ;
10
18
11
19
export const createWatchBuild = async ( config : d . Config , compilerCtx : d . CompilerCtx ) : Promise < d . CompilerWatcher > => {
12
20
let isRebuild = false ;
13
- let tsWatchProgram : { program : ts . WatchOfConfigFile < ts . EmitAndSemanticDiagnosticsBuilderProgram > ; rebuild : ( ) => void } ;
14
- let srcFileWatchCloser : ( ) => void ;
15
- let otherFileWatchCloser : ( ) => void ;
16
-
21
+ let tsWatchProgram : {
22
+ program : ts . WatchOfConfigFile < ts . EmitAndSemanticDiagnosticsBuilderProgram > ;
23
+ rebuild : ( ) => void ;
24
+ } ;
17
25
let closeResolver : Function ;
18
26
const watchWaiter = new Promise < d . WatcherCloseResults > ( resolve => ( closeResolver = resolve ) ) ;
19
27
@@ -23,31 +31,6 @@ export const createWatchBuild = async (config: d.Config, compilerCtx: d.Compiler
23
31
const filesUpdated = new Set < string > ( ) ;
24
32
const filesDeleted = new Set < string > ( ) ;
25
33
26
- const onSrcFileChange : d . CompilerFileWatcherCallback = ( p , eventKind ) => {
27
- updateCompilerCtxCache ( config , compilerCtx , p , eventKind ) ;
28
-
29
- switch ( eventKind ) {
30
- case 'dirAdd' :
31
- dirsAdded . add ( p ) ;
32
- break ;
33
- case 'dirDelete' :
34
- dirsDeleted . add ( p ) ;
35
- break ;
36
- case 'fileAdd' :
37
- filesAdded . add ( p ) ;
38
- break ;
39
- case 'fileUpdate' :
40
- filesUpdated . add ( p ) ;
41
- break ;
42
- case 'fileDelete' :
43
- filesDeleted . add ( p ) ;
44
- break ;
45
- }
46
-
47
- config . logger . debug ( `${ eventKind } : ${ p } ` ) ;
48
- tsWatchProgram . rebuild ( ) ;
49
- } ;
50
-
51
34
const onBuild = async ( tsBuilder : ts . BuilderProgram ) => {
52
35
const buildCtx = new BuildContext ( config , compilerCtx ) ;
53
36
buildCtx . isRebuild = isRebuild ;
@@ -83,27 +66,61 @@ export const createWatchBuild = async (config: d.Config, compilerCtx: d.Compiler
83
66
} ;
84
67
85
68
const start = async ( ) => {
86
- const srcRead = watchSrcDirectory ( config , compilerCtx , onSrcFileChange ) ;
87
- const otherRead = watchOtherFiles ( config , compilerCtx ) ;
88
- srcFileWatchCloser = await srcRead ;
89
- otherFileWatchCloser = await otherRead ;
69
+ const srcRead = watchSrcDirectory ( config , compilerCtx ) ;
70
+ const otherRead = watchRootFiles ( config , compilerCtx ) ;
71
+ await srcRead ;
72
+ await otherRead ;
90
73
tsWatchProgram = await createTsWatchProgram ( config , onBuild ) ;
91
74
return watchWaiter ;
92
75
} ;
93
76
94
- const close = async ( ) => {
95
- if ( srcFileWatchCloser ) {
96
- srcFileWatchCloser ( ) ;
77
+ const watchingDirs = new Map < string , d . CompilerFileWatcher > ( ) ;
78
+ const watchingFiles = new Map < string , d . CompilerFileWatcher > ( ) ;
79
+
80
+ const onFsChange : d . CompilerFileWatcherCallback = ( p , eventKind ) => {
81
+ if ( tsWatchProgram ) {
82
+ updateCompilerCtxCache ( config , compilerCtx , p , eventKind ) ;
83
+
84
+ switch ( eventKind ) {
85
+ case 'dirAdd' :
86
+ dirsAdded . add ( p ) ;
87
+ break ;
88
+ case 'dirDelete' :
89
+ dirsDeleted . add ( p ) ;
90
+ break ;
91
+ case 'fileAdd' :
92
+ filesAdded . add ( p ) ;
93
+ break ;
94
+ case 'fileUpdate' :
95
+ filesUpdated . add ( p ) ;
96
+ break ;
97
+ case 'fileDelete' :
98
+ filesDeleted . add ( p ) ;
99
+ break ;
100
+ }
101
+
102
+ config . logger . debug ( `onFsChange ${ eventKind } : ${ p } ` ) ;
103
+ tsWatchProgram . rebuild ( ) ;
97
104
}
98
- if ( otherFileWatchCloser ) {
99
- otherFileWatchCloser ( ) ;
105
+ } ;
106
+
107
+ const onDirChange : d . CompilerFileWatcherCallback = ( p , eventKind ) => {
108
+ if ( eventKind != null ) {
109
+ onFsChange ( p , eventKind ) ;
100
110
}
111
+ } ;
112
+
113
+ const close = async ( ) => {
114
+ watchingDirs . forEach ( w => w . close ( ) ) ;
115
+ watchingFiles . forEach ( w => w . close ( ) ) ;
116
+ watchingDirs . clear ( ) ;
117
+ watchingFiles . clear ( ) ;
118
+
101
119
if ( tsWatchProgram ) {
102
120
tsWatchProgram . program . close ( ) ;
121
+ tsWatchProgram = null ;
103
122
}
104
123
105
- srcFileWatchCloser = otherFileWatchCloser = tsWatchProgram = null ;
106
-
107
124
const watcherCloseResults : d . WatcherCloseResults = {
108
125
exitCode : 0 ,
109
126
} ;
@@ -113,6 +130,18 @@ export const createWatchBuild = async (config: d.Config, compilerCtx: d.Compiler
113
130
114
131
const request = async ( data : d . CompilerRequest ) => compilerRequest ( config , compilerCtx , data ) ;
115
132
133
+ compilerCtx . addWatchFile = filePath => {
134
+ if ( isString ( filePath ) && ! watchingFiles . has ( filePath ) ) {
135
+ watchingFiles . set ( filePath , config . sys . watchFile ( filePath , onFsChange ) ) ;
136
+ }
137
+ } ;
138
+
139
+ compilerCtx . addWatchDir = ( dirPath , recursive ) => {
140
+ if ( isString ( dirPath ) && ! watchingDirs . has ( dirPath ) ) {
141
+ watchingDirs . set ( dirPath , config . sys . watchDirectory ( dirPath , onDirChange , recursive ) ) ;
142
+ }
143
+ } ;
144
+
116
145
config . sys . addDestory ( close ) ;
117
146
118
147
return {
@@ -123,90 +152,47 @@ export const createWatchBuild = async (config: d.Config, compilerCtx: d.Compiler
123
152
} ;
124
153
} ;
125
154
126
- const watchSrcDirectory = async ( config : d . Config , compilerCtx : d . CompilerCtx , callback : d . CompilerFileWatcherCallback ) => {
127
- const watching = new Map ( ) ;
128
- const watchFile = ( path : string ) => {
129
- if ( ! watching . has ( path ) ) {
130
- watching . set ( path , config . sys . watchFile ( path , callback ) ) ;
131
- }
132
- } ;
133
-
155
+ const watchSrcDirectory = async ( config : d . Config , compilerCtx : d . CompilerCtx ) => {
134
156
const srcFiles = await compilerCtx . fs . readdir ( config . srcDir , {
135
157
recursive : true ,
136
158
excludeDirNames : [ '.cache' , '.git' , '.github' , '.stencil' , '.vscode' , 'node_modules' ] ,
137
- excludeExtensions : [ '.md' , '.markdown' , '.txt' , '.spec.ts' , '.spec.tsx' , '.e2e.ts' , '.e2e.tsx' , '.gitignore' , '.editorconfig' ] ,
159
+ excludeExtensions : [
160
+ '.md' ,
161
+ '.markdown' ,
162
+ '.txt' ,
163
+ '.spec.ts' ,
164
+ '.spec.tsx' ,
165
+ '.e2e.ts' ,
166
+ '.e2e.tsx' ,
167
+ '.gitignore' ,
168
+ '.editorconfig' ,
169
+ ] ,
138
170
} ) ;
139
171
140
- srcFiles . filter ( ( { isFile } ) => isFile ) . forEach ( ( { absPath } ) => watchFile ( absPath ) ) ;
141
-
142
- watching . set (
143
- config . srcDir ,
144
- config . sys . watchDirectory ( config . srcDir , ( filename , kind ) => {
145
- if ( kind != null ) {
146
- watchFile ( filename ) ;
147
- callback ( filename , kind ) ;
148
- }
149
- } ) ,
150
- ) ;
172
+ srcFiles . filter ( ( { isFile } ) => isFile ) . forEach ( ( { absPath } ) => compilerCtx . addWatchFile ( absPath ) ) ;
151
173
152
- return ( ) => {
153
- watching . forEach ( w => w . close ( ) ) ;
154
- } ;
174
+ compilerCtx . addWatchDir ( config . srcDir , true ) ;
155
175
} ;
156
176
157
- const watchOtherFiles = async ( config : d . Config , compilerCtx : d . CompilerCtx ) => {
177
+ const watchRootFiles = async ( config : d . Config , compilerCtx : d . CompilerCtx ) => {
158
178
// non-src files that cause a rebuild
159
179
// mainly for root level config files, and getting an event when they change
160
- const onFileChange : d . CompilerFileWatcherCallback = ( p , eventKind ) => {
161
- const data : d . FsWatchResults = {
162
- dirsAdded : [ ] ,
163
- dirsDeleted : [ ] ,
164
- filesUpdated : [ ] ,
165
- filesAdded : [ ] ,
166
- filesDeleted : [ ] ,
167
- } ;
168
-
169
- switch ( eventKind ) {
170
- case 'dirAdd' :
171
- data . dirsAdded . push ( p ) ;
172
- break ;
173
- case 'dirDelete' :
174
- data . dirsDeleted . push ( p ) ;
175
- break ;
176
- case 'fileAdd' :
177
- data . filesAdded . push ( p ) ;
178
- break ;
179
- case 'fileUpdate' :
180
- data . filesUpdated . push ( p ) ;
181
- break ;
182
- case 'fileDelete' :
183
- data . filesDeleted . push ( p ) ;
184
- break ;
185
- }
186
-
187
- compilerCtx . events . emit ( 'fsChange' , data ) ;
188
- } ;
189
- const watching = new Map ( ) ;
190
- const watchFile = ( path : string ) => {
191
- if ( ! watching . has ( path ) ) {
192
- watching . set ( path , config . sys . watchFile ( path , onFileChange ) ) ;
193
- }
194
- } ;
195
-
196
180
const rootFiles = await compilerCtx . fs . readdir ( config . rootDir , {
197
181
recursive : false ,
198
182
excludeDirNames : [ '.cache' , '.git' , '.github' , '.stencil' , '.vscode' , 'node_modules' ] ,
199
183
} ) ;
200
184
201
- rootFiles . filter ( ( { isFile } ) => isFile ) . forEach ( ( { absPath } ) => watchFile ( absPath ) ) ;
202
-
203
- return ( ) => {
204
- watching . forEach ( w => w . close ( ) ) ;
205
- } ;
185
+ rootFiles . filter ( ( { isFile } ) => isFile ) . forEach ( ( { absPath } ) => compilerCtx . addWatchFile ( absPath ) ) ;
206
186
} ;
207
187
208
188
const emitFsChange = ( compilerCtx : d . CompilerCtx , buildCtx : BuildContext ) => {
209
- if ( buildCtx . dirsAdded . length > 0 || buildCtx . dirsDeleted . length > 0 || buildCtx . filesUpdated . length > 0 || buildCtx . filesAdded . length > 0 || buildCtx . filesDeleted . length > 0 ) {
189
+ if (
190
+ buildCtx . dirsAdded . length > 0 ||
191
+ buildCtx . dirsDeleted . length > 0 ||
192
+ buildCtx . filesUpdated . length > 0 ||
193
+ buildCtx . filesAdded . length > 0 ||
194
+ buildCtx . filesDeleted . length > 0
195
+ ) {
210
196
compilerCtx . events . emit ( 'fsChange' , {
211
197
dirsAdded : buildCtx . dirsAdded . slice ( ) ,
212
198
dirsDeleted : buildCtx . dirsDeleted . slice ( ) ,
@@ -217,7 +203,12 @@ const emitFsChange = (compilerCtx: d.CompilerCtx, buildCtx: BuildContext) => {
217
203
}
218
204
} ;
219
205
220
- const updateCompilerCtxCache = ( config : d . Config , compilerCtx : d . CompilerCtx , path : string , kind : d . CompilerFileWatcherEvent ) => {
206
+ const updateCompilerCtxCache = (
207
+ config : d . Config ,
208
+ compilerCtx : d . CompilerCtx ,
209
+ path : string ,
210
+ kind : d . CompilerFileWatcherEvent ,
211
+ ) => {
221
212
compilerCtx . fs . clearFileCache ( path ) ;
222
213
compilerCtx . changedFiles . add ( path ) ;
223
214
0 commit comments