@@ -56,49 +56,52 @@ const getEntrypoints = async (files: BuildTempatesResult[]) => {
56
56
return Array . from ( entrypoints ) . filter ( Boolean ) ;
57
57
} ;
58
58
59
- const getWatchPaths = async ( files : BuildTempatesResult [ ] ) => {
59
+ const getWatchDirectories = async ( files : BuildTempatesResult [ ] , depPaths : string [ ] ) => {
60
60
const entrypoints = await getEntrypoints ( files ) ;
61
- const paths = entrypoints . map ( ( path ) => dirname ( path ) ) ;
61
+ const paths = [
62
+ ...entrypoints . map ( ( path ) => dirname ( path ) ) ,
63
+ ...depPaths . map ( ( path ) => dirname ( path ) )
64
+ ] ;
62
65
const uniquePaths = Array . from ( new Set ( paths ) ) ;
63
66
const watchPaths = removeChildPaths ( uniquePaths ) ;
64
67
65
68
log . debug ( { watchPaths } ) ;
66
69
67
- return watchPaths ;
70
+ return { entrypoints , watchPaths } ;
68
71
} ;
69
72
70
- // const mapDeps = async (files: BuildTempatesResult[]) => {
71
- // const depPaths: string[] = [];
72
- // const metaReads = files.map(async ({ metaPath }) => {
73
- // log.debug({ exists: await exists(metaPath ?? ''), metaPath });
74
-
75
- // if (!metaPath || !(await exists(metaPath))) return null;
76
- // const contents = await readFile(metaPath, 'utf-8');
77
- // const metafile = JSON.parse(contents) as Metafile;
78
- // const { outputs } = metafile;
79
- // const result = new Map<string, Set<string>>();
80
-
81
- // Object.entries(outputs).forEach(([_, meat]) => {
82
- // const { entryPoint, inputs } = meat;
83
- // const resolvedEntry = resolve(originalCwd, entryPoint!);
84
- // depPaths.push(resolvedEntry);
85
-
86
- // for (const dep of Object.keys(inputs)) {
87
- // const resolvedDepPath = resolve(originalCwd, dep);
88
- // const set = result.get(resolvedDepPath) ?? new Set();
73
+ const mapDeps = async ( files : BuildTempatesResult [ ] ) => {
74
+ const depPaths : string [ ] = [ ] ;
75
+ const metaReads = files . map ( async ( { metaPath } ) => {
76
+ log . debug ( { exists : await exists ( metaPath ?? '' ) , metaPath } ) ;
89
77
90
- // depPaths.push(resolvedDepPath);
91
- // set.add(resolvedEntry);
92
- // result.set(resolvedDepPath, set);
93
- // }
94
- // });
78
+ if ( ! metaPath || ! ( await exists ( metaPath ) ) ) return null ;
79
+ const contents = await readFile ( metaPath , 'utf-8' ) ;
80
+ const metafile = JSON . parse ( contents ) as Metafile ;
81
+ const { outputs } = metafile ;
82
+ const result = new Map < string , Set < string > > ( ) ;
83
+
84
+ Object . entries ( outputs ) . forEach ( ( [ _ , meat ] ) => {
85
+ const { entryPoint, inputs } = meat ;
86
+ const resolvedEntry = resolve ( originalCwd , entryPoint ! ) ;
87
+ depPaths . push ( resolvedEntry ) ;
88
+
89
+ for ( const dep of Object . keys ( inputs ) ) {
90
+ const resolvedDepPath = resolve ( originalCwd , dep ) ;
91
+ const set = result . get ( resolvedDepPath ) ?? new Set ( ) ;
92
+
93
+ depPaths . push ( resolvedDepPath ) ;
94
+ set . add ( resolvedEntry ) ;
95
+ result . set ( resolvedDepPath , set ) ;
96
+ }
97
+ } ) ;
95
98
96
- // return result;
97
- // });
98
- // const deps = (await Promise.all(metaReads)).filter(Boolean);
99
+ return result ;
100
+ } ) ;
101
+ const deps = ( await Promise . all ( metaReads ) ) . filter ( Boolean ) ;
99
102
100
- // return { depPaths, deps };
101
- // };
103
+ return { depPaths, deps } ;
104
+ } ;
102
105
103
106
export const watch = async ( args : WatchArgs ) => {
104
107
newline ( ) ;
@@ -107,22 +110,40 @@ export const watch = async (args: WatchArgs) => {
107
110
const { common, files, server } = args ;
108
111
const { argv } = common ;
109
112
const extensions = [ '.css' , '.js' , '.jsx' , '.ts' , '.tsx' ] ;
110
- const watchPaths = await getWatchPaths ( files ) ;
111
-
112
- // const { depPaths, deps: metaDeps } = await mapDeps(files);
113
- // const templateDeps = new Map<string, Set<string>>();
114
-
115
- // for (const map of metaDeps) {
116
- // map!.forEach((value, key) => templateDeps.set(key, value));
117
- // }
113
+ const { depPaths, deps : metaDeps } = await mapDeps ( files ) ;
114
+ const dependencyPaths = depPaths . filter ( ( path ) => ! path . includes ( '/node_modules/' ) ) ;
115
+ const { entrypoints, watchPaths : watchDirectories } = await getWatchDirectories (
116
+ files ,
117
+ dependencyPaths
118
+ ) ;
119
+ const templateDeps = new Map < string , Set < string > > ( ) ;
120
+ const validFiles = Array . from ( new Set ( [ ...entrypoints , ...dependencyPaths ] ) ) ;
121
+
122
+ for ( const map of metaDeps ) {
123
+ map ! . forEach ( ( value , key ) => templateDeps . set ( key , value ) ) ;
124
+ }
125
+
126
+ log . info ( { validFiles } ) ;
127
+
128
+ const handler : watcher . SubscribeCallback = async ( _ , incoming ) => {
129
+ // Note: We perform this filter in case someone has a dependency of a template,
130
+ // or has templates, at a path that includes node_modules. We also don't any
131
+ // non-template files having builds attempted on them, so check to make sure
132
+ // the event path is in the set of files we want to watch, unless it's a create
133
+ // event
134
+ const events = incoming . filter ( ( event ) => {
135
+ if ( event . path . includes ( '/node_modules/' ) ) return false ;
136
+ if ( event . type !== 'create' ) return validFiles . includes ( event . path ) ;
137
+ return true ;
138
+ } ) ;
118
139
119
- const handler : watcher . SubscribeCallback = async ( _ , events ) => {
120
140
const changedFiles = events
121
141
. filter ( ( event ) => event . type !== 'create' && event . type !== 'delete' )
122
142
. map ( ( e ) => e . path )
123
143
. filter ( ( path ) => extensions . includes ( extname ( path ) ) ) ;
124
- const templateFileNames = files . map ( ( file ) => file . fileName ) ;
125
- const changedTemplates = changedFiles . filter ( ( file ) => templateFileNames . includes ( file ) ) ;
144
+ const changedTemplates = changedFiles
145
+ . flatMap ( ( file ) => [ ...( templateDeps . get ( file ) || [ ] ) ] )
146
+ . filter ( Boolean ) ;
126
147
const createdFiles = events
127
148
. filter ( ( event ) => event . type === 'create' )
128
149
. map ( ( e ) => e . path )
@@ -149,13 +170,16 @@ export const watch = async (args: WatchArgs) => {
149
170
) ;
150
171
151
172
deletedFiles . forEach ( ( path ) => {
152
- const index = files . findIndex ( ( { fileName } ) => path === fileName ) ;
173
+ let index : any = files . findIndex ( ( { fileName } ) => path === fileName ) ;
153
174
if ( index === - 1 ) return ;
154
175
const file = files [ index ] ;
155
176
files . splice ( index , 1 ) ;
156
177
// Note: Don't await either, we don't need to
157
178
unlink ( file . compiledPath ) ;
158
179
unlink ( `${ file . writePathBase } .js` ) ;
180
+
181
+ index = validFiles . find ( ( fileName ) => path === fileName ) ;
182
+ if ( index > - 1 ) validFiles . splice ( index , 1 ) ;
159
183
} ) ;
160
184
}
161
185
@@ -177,7 +201,11 @@ export const watch = async (args: WatchArgs) => {
177
201
targetPath : path
178
202
} ) ;
179
203
204
+ const mappedDeps = await mapDeps ( results ) ;
180
205
files . push ( ...results ) ;
206
+ validFiles . push (
207
+ ...[ path , ...mappedDeps . depPaths . filter ( ( p ) => ! p . includes ( '/node_modules/' ) ) ]
208
+ ) ;
181
209
182
210
await writePreviewDataFiles ( results ) ;
183
211
} )
@@ -200,14 +228,9 @@ export const watch = async (args: WatchArgs) => {
200
228
} ) ;
201
229
} ;
202
230
203
- // const watchPathSet = new Set([
204
- // ...depPaths.filter((path) => !path.includes('/node_modules/')).map((path) => dirname(path))
205
- // ]);
206
- // const watchPaths = removeChildPaths([...watchPathSet]);
207
-
208
- log . debug ( 'Watching Paths:' , watchPaths . sort ( ) ) ;
231
+ log . debug ( 'Watching Paths:' , watchDirectories . sort ( ) ) ;
209
232
210
- const subPromises = watchPaths . map ( ( path ) => watcher . subscribe ( path , handler ) ) ;
233
+ const subPromises = watchDirectories . map ( ( path ) => watcher . subscribe ( path , handler ) ) ;
211
234
const subscriptions = await Promise . all ( subPromises ) ;
212
235
213
236
server . httpServer ! . on ( 'close' , ( ) => {
0 commit comments