5.5 CLI Factory

In addition to crafting a module specifier, the "run" command in Deno also gives rise to what's known as CLIFactory, generated via a CLIFactory. These CLIFactory encompass various settings and objects used widely across the program. These valuable CLIFactory stem from the very options provided through the command line when Deno is invoked. This essentially means that the way you configure and set up Deno through its command line has a direct impact on the makeup of CLIFactory and subsequently influences the behavior of the program.
The CLIFactory act as a central hub for crucial configurations and resources that Deno requires to function effectively.
let factory = CliFactory::from_flags(flags).await?;

Attributes

The CLIFactory play a crucial role within the Deno ecosystem, serving as a fundamental component. It comes into play immediately after generating the module specifier for the main module. Within the realm of CLIFactory, several significant elements come to the fore, each contributing to Deno's functionality in its own unique way. Let's delve into these essential aspects:
  • Deno Directory: This particular facet pertains to the working directory of Deno. Within this directory, all the downloaded modules find their home and undergo the compilation process. It serves as a central repository for Deno's operations.
  • Caches: Deno manages distinct types of caches, and the CLIFactory helps keep track of their paths. These caches encompass various categories such as Dependency, Gen (generation), and HTTP cache. The Dependency cache stores vital dependencies, the Gen cache handles generated code, and the HTTP cache maintains data fetched from the web.
  • File Fetcher: A versatile tool, the file fetcher, proves invaluable for procuring files, whether they are located locally or reside on remote servers. This function underpins Deno's capability to seamlessly access and work with diverse sources.
  • HTTP Client: An integral part of CLIFactory, the HTTP Client empowers Deno to interact with web resources. This feature facilitates tasks such as making HTTP requests and handling responses from various online services.
  • Certificate Store: Security is of paramount importance, and the CLIFactory include a certificate store. This repository safeguards the certificates necessary for securing connections, assuring the authenticity and integrity of data exchanges.
  • Module Resolver: The module resolver within CLIFactory tackles the intricate task of determining module dependencies. It navigates the network of interconnected modules, ensuring that the correct modules are fetched and utilized.
  • Module Graph Builder: This component aids in constructing the module graph, which outlines the relationships and dependencies among different modules. The module graph builder ensures the organized and systematic interaction between various components.
  • NPM Cache and Resolver: Deno interfaces with the popular NPM package manager, and the CLIFactory oversees the NPM cache and resolver. This facilitates seamless integration and utilization of NPM packages within Deno projects.
  • Package.json Support and Installer: CLIFactory encompasses support for the widely used package.json configuration format. It also includes an installer that streamlines the process of adding and managing dependencies through package.json.
  • Type Checker: Type checking is a crucial step in maintaining code quality. CLIFactory includes a type checker that assists in detecting type-related issues, promoting reliable and well-structured code.
  • Common JS Resolver: In the landscape of JavaScript, CommonJS modules hold significance. CLIFactory is equipped with a resolver that harmonizes the integration of CommonJS modules into Deno projects.
In summation, the CLIFactory offer an array of indispensable services, collectively contributing to the seamless functioning of Deno. By overseeing diverse operations, from caching to module resolution, Deno's CLIFactory ensure a robust and comprehensive environment for developers to create and deploy their projects effectively.
Below is the comprehensive list of services that the CLIFactory offers:
struct CliFactoryServices {
deno_dir_provider: Deferred<Arc<DenoDirProvider>>,
caches: Deferred<Arc<Caches>>,
file_fetcher: Deferred<Arc<FileFetcher>>,
global_http_cache: Deferred<Arc<GlobalHttpCache>>,
http_cache: Deferred<Arc<dyn HttpCache>>,
http_client: Deferred<Arc<HttpClient>>,
emit_cache: Deferred<EmitCache>,
emitter: Deferred<Arc<Emitter>>,
fs: Deferred<Arc<dyn deno_fs::FileSystem>>,
graph_container: Deferred<Arc<ModuleGraphContainer>>,
lockfile: Deferred<Option<Arc<Mutex<Lockfile>>>>,
maybe_import_map: Deferred<Option<Arc<ImportMap>>>,
maybe_inspector_server: Deferred<Option<Arc<InspectorServer>>>,
root_cert_store_provider: Deferred<Arc<dyn RootCertStoreProvider>>,
blob_store: Deferred<Arc<BlobStore>>,
parsed_source_cache: Deferred<Arc<ParsedSourceCache>>,
resolver: Deferred<Arc<CliGraphResolver>>,
maybe_file_watcher_reporter: Deferred<Option<FileWatcherReporter>>,
module_graph_builder: Deferred<Arc<ModuleGraphBuilder>>,
module_load_preparer: Deferred<Arc<ModuleLoadPreparer>>,
node_code_translator: Deferred<Arc<CliNodeCodeTranslator>>,
node_resolver: Deferred<Arc<NodeResolver>>,
npm_api: Deferred<Arc<CliNpmRegistryApi>>,
npm_cache: Deferred<Arc<NpmCache>>,
npm_resolver: Deferred<Arc<CliNpmResolver>>,
npm_resolution: Deferred<Arc<NpmResolution>>,
package_json_deps_provider: Deferred<Arc<PackageJsonDepsProvider>>,
package_json_deps_installer: Deferred<Arc<PackageJsonDepsInstaller>>,
text_only_progress_bar: Deferred<ProgressBar>,
type_checker: Deferred<Arc<TypeChecker>>,
cjs_resolutions: Deferred<Arc<CjsResolutionStore>>,
}

Internal directories

It would be beneficial to understand the internal directory paths that Deno utilizes for its operations. Below, you will find the primary directory paths on MacOS where Deno operates:
root dir: /Users/mayankc/Library/Caches/deno
deps dir: /Users/mayankc/Library/Caches/deno/deps
gen dir: /Users/mayankc/Library/Caches/deno/gen
Below, you will find the directory paths designated for storing HTTP and HTTPS cache. These specific paths are situated within the 'deps' directory. The 'deps' directory, where these cache paths are located, serves as a storage hub for various dependencies and cached content. When Deno fetches external resources, it intelligently stores them in this directory, categorizing them based on their protocols (HTTP or HTTPS) to ensure organized and speedy retrieval when needed.
http cache: /Users/mayankc/Library/Caches/deno/deps/http
https cache: /Users/mayankc/Library/Caches/deno/deps/https
In Deno, a cache system for local files is not implemented. This is because the process of accessing local files is much more cost-effective than retrieving remote files over the network. As a result, Deno does not allocate resources to cache local files.

FileFetcher

The FileFetcher tool provides a useful function for obtaining a file and saving it within a storage area called the cache. This feature is versatile, capable of handling both local files stored on your device and remote files accessed through the internet. Interestingly, even local files are treated like fetched files, which essentially means they're read and handled in a similar manner.
The FileFetcher entity encompasses several key components, each contributing to its functionality:
  1. 1.
    FileCache: This component manages the storage of fetched files within a cache. It ensures efficient retrieval when needed.
  2. 2.
    HttpCache: Designed specifically for files acquired via HTTP requests, this element efficiently stores and handles such files within the cache.
  3. 3.
    Cache Settings: These settings define how the cache behaves. You can opt to use cached files, trigger a full reload of all files, and even configure other behaviors.
  4. 4.
    Http Client: This part of FileFetcher serves as a wrapper for the asynchronous reqwest::Client functionality. It streamlines the process of making HTTP requests and handling responses.
FileFetcher offers support for three different URI schemes, which determine the type of resource being accessed:
  • http: Used for standard HTTP resources.
  • https: Similar to HTTP, but this scheme indicates a secure and encrypted connection.
  • file: Intended for local files present on the same device.
As we delve into the module loading discussion, we will explore the intricacies of the FileFetcher in depth, understanding its role in efficiently obtaining and managing various types of files, whether they are local or remote, and how it contributes to the functionality of Deno.

Functionality

In addition to its attributes, the CLIFactory provides another very important functionality that is closely associated with ES modules:
The Module Preparer function within the CLIFactory holds paramount importance. It takes charge of the tasks involving fetching, loading, and compiling modules. This means that when you're working with Deno and its CLIFactory, this specialized function ensures that modules are efficiently handled and made ready for use. It streamlines the process of gathering the required modules, loading them into the application, and compiling them so they can be seamlessly integrated into your codebase.

Prepare Module

The process of getting a module ready for use in the JavaScript runtime is known as "module preparation" in Deno. This involves a series of steps, including fetching, loading, and compiling the module along with all its required components. This entire process ensures that the module and its dependencies are properly set up and ready to be utilized within the v8 engine.
Let's delve into some of the key activities that take place during the preparation of a module:
  1. 1.
    Initiating the Module Graph: All the ECMAScript (ES) modules are organized and managed within a structure called the "module graph." This graph keeps track of how various modules relate to each other.
  2. 2.
    Inclusion of the Main Module: The primary module, also known as the "main module," is integrated into the module graph. This marks the starting point of the entire preparation process.
  3. 3.
    Recursive Dependency Exploration: In a step-by-step manner, the system explores each module's dependencies by delving into their import statements. This recursive traversal builds up the module graph further.
  4. 4.
    Fetching and Loading Dependencies: The preparation process involves fetching and loading all the dependencies that a module relies upon. This ensures that the module has access to the necessary resources it needs to function.
  5. 5.
    Compilation Process: One of the vital stages is the compilation of the entire module graph. This step involves translating the code written in a high-level language (like JavaScript or TypeScript) into a format that can be readily executed by the v8 engine.
As you can see, the preparation of a module in Deno is a multi-faceted process that ensures all required pieces are in place for smooth execution. We'll dive deeper into these steps when we discuss the specifics of module loading later on.

Fetch compiled module

This code snippet performs the task of retrieving a compiled module by providing its specifier. It employs the file fetcher to gather the compiled source corresponding to the specifier. We will delve deeper into the intricacies of this process when we discuss module loading in subsequent sections.