// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. use crate::args::CliOptions; use crate::cache::ParsedSourceCache; use crate::graph_util::ModuleGraphContainer; use crate::module_loader::CjsResolutionStore; use deno_core::parking_lot::Mutex; use deno_core::ModuleSpecifier; use std::path::PathBuf; use std::sync::Arc; pub struct FileWatcher { cli_options: Arc, cjs_resolutions: Arc, graph_container: Arc, maybe_reporter: Option, parsed_source_cache: Arc, } impl FileWatcher { pub fn new( cli_options: Arc, cjs_resolutions: Arc, graph_container: Arc, maybe_reporter: Option, parsed_source_cache: Arc, ) -> Self { Self { cli_options, cjs_resolutions, parsed_source_cache, graph_container, maybe_reporter, } } /// Reset all runtime state to its default. This should be used on file /// watcher restarts. pub fn reset(&self) { self.cjs_resolutions.clear(); self.parsed_source_cache.clear(); self.graph_container.clear(); self.init_watcher(); } // Add invariant files like the import map and explicit watch flag list to // the watcher. Dedup for build_for_file_watcher and reset_for_file_watcher. pub fn init_watcher(&self) { let files_to_watch_sender = match &self.maybe_reporter { Some(reporter) => &reporter.sender, None => return, }; if let Some(watch_paths) = self.cli_options.watch_paths() { files_to_watch_sender.send(watch_paths.clone()).unwrap(); } if let Ok(Some(import_map_path)) = self .cli_options .resolve_import_map_specifier() .map(|ms| ms.and_then(|ref s| s.to_file_path().ok())) { files_to_watch_sender.send(vec![import_map_path]).unwrap(); } } } #[derive(Clone, Debug)] pub struct FileWatcherReporter { sender: tokio::sync::mpsc::UnboundedSender>, file_paths: Arc>>, } impl FileWatcherReporter { pub fn new(sender: tokio::sync::mpsc::UnboundedSender>) -> Self { Self { sender, file_paths: Default::default(), } } } impl deno_graph::source::Reporter for FileWatcherReporter { fn on_load( &self, specifier: &ModuleSpecifier, modules_done: usize, modules_total: usize, ) { let mut file_paths = self.file_paths.lock(); if specifier.scheme() == "file" { file_paths.push(specifier.to_file_path().unwrap()); } if modules_done == modules_total { self.sender.send(file_paths.drain(..).collect()).unwrap(); } } }