5.3 Main program of Deno
Deno command
We'll use the following command to run our code in Deno:
deno is the name of the executable
run is the subcommand
helloLog.ts is the program to run
In this subsection, we will explore a simple program that doesn't require special permissions. Although this program doesn't need permissions, we will discuss the concept of permissions in this chapter. Permissions are a fundamental part of Deno, creating a protective barrier around the runtime environment and ensuring security.
The 'deno run' command has a specific purpose: it converts TypeScript code into JavaScript, ready for execution. It prioritizes quick startup over type checking, preparing the code for running without extensively verifying the types involved.
For strict type checking of your application's code, Deno offers a separate command called 'deno check'. This command thoroughly examines the types in your codebase, ensuring they align correctly and your code is error-free. This additional step can help catch potential issues before they cause problems during execution.
Deno's main program
Deno is crafted using the Rust programming language, and as a result, its primary codebase is also composed in Rust. The central component of Deno, known as the main program, is housed within the CLI. This CLI serves a dual role, functioning as both the conductor that coordinates various tasks and the supplier of essential services that Deno offers.
Contained within this CLI is the heart of Deno, its main program. This program acts as the control center, governing the execution of Deno's functionalities and managing how it interacts with your commands and scripts. It's responsible for overseeing tasks such as module loading, security checks, and runtime environment management.
The deno command functions as a toolchain, but it cannot operate on its own to execute tasks. Deno relies on subcommands to perform its various functions and capabilities.
Regarding the main function code of Deno, it undertakes the following tasks:
Build flags from command line args
Initialize logger
Run the subcommand asynchronously (notice the await at the end)
Drawing a parallel between Rust's futures and JavaScript's promises can provide a clearer understanding of their roles in asynchronous programming. In the Rust programming language, futures operate similarly to promises in JavaScript. Just as promises represent values that may not be available immediately but will be fulfilled at some point, Rust futures encapsulate computations that will be completed in the future. These futures serve as powerful tools for handling asynchronous tasks, making them a important in writing efficient and responsive code.
Flags
A flag acts like a tool that examines and understands command-line details related to specific sub-commands. Its purpose is to make these details easily accessible. Deno comes with a variety of sub-commands, and each of these sub-commands comes with its own set of arguments. To simplify things, flags are used to sort through these arguments based on the specific sub-command being used. This way, the important arguments are picked out and stored for further use, all depending on which sub-command you're working with. In essence, flags help organize the command-line information so that Deno can effectively handle the various sub-commands and their unique requirements.
Each sub-command in Deno has its own set of flags, which are specific to its functions. Let's look at a few commonly used sub-commands to understand them better.
In Deno, there are certain attributes that are in the form of booleans, such as allow_read
, allow_write
, and allow_env
. These attributes can be thought of as settings that determine whether specific actions are permitted or not. For instance, allow_read
controls whether the script is allowed to read files or not, allow_write
governs the ability to write to files, and allow_env
manages access to environment variables. By setting these attributes to either "true" or "false," you can specify the permissions granted to the script.
Additionally, Deno provides attributes that are in the form of lists, such as write_allowlist
and read_allowlist
. These lists contain specific paths or resources that are explicitly permitted. When you include paths in the write_allowlist
, the script is only allowed to write to the specified paths, and similarly, when you include paths in the read_allowlist
, the script can only read from those specified paths. This mechanism allows for a more granular control over the file system and resource access, enhancing security and minimizing unintended interactions.
Below is a compilation of frequently utilized command line options in Deno. These options allow you to interact with the Deno runtime effectively:
--allow-all
--allow-read
--deny-read
--allow-write
--deny-write
--allow-net
--deny-net
--unsafely-ignore-certificate-errors
--allow-env
--deny-env
--allow-run
--deny-run
--allow-sys
--deny-sys
--allow-ffi
--deny-ffi
--allow-hrtime
--deny-hrtime
Deno offers an extensive array of subcommands, yet the primary focus of this book revolves around the execution of code. Therefore, our in-depth exploration will be solely dedicated to the 'run' command. While Deno presents a wide range of subcommands catering to various functionalities, our attention within this book remains centered on the intricacies of the 'run' command's utilization.
Run command
The run command in Deno serves the purpose of executing your program. Although the implementation of this command may appear straightforward, it actually undertakes numerous tasks behind the scenes. Let's look into the mechanics of the run command and explore its inner workings.
And that's all there is to it! The code you see here constitutes the entirety of the implementation for the run command. It may seem remarkably straightforward on the surface. Nevertheless, beneath this apparent simplicity, a significant amount of activity takes place within the functions that are invoked from the run_script function.
Now, let's delve into the essential aspects of the run_script
function and gain an overview of its crucial functions. As we proceed, we'll explore these concepts in greater depth within the upcoming sections. Our focus for now will be on the pertinent segments of the code that deserve attention.
ModuleSpecifier
The initial file used in the application, which is provided as input to the 'deno run' command, is referred to as the main file or main module of the application. This main module serves as the entry point where the application's execution begins. When you run your Deno application, Deno looks for the specified main file and starts executing the code from there.
The primary file you use in Deno can either exist on your computer (what we call "local") or be hosted on the internet (which we refer to as "remote"). Deno is smart enough to change the script's location into a special web address called a URL. URLs can come in different flavors, like file:// or http:// or even https://. Interestingly, Deno treats local files the same way as remote ones, using the file:// format. This might seem a bit strange, but it's actually a way to make sure that Deno handles all types of files in a consistent manner.
Check for upgrades
When you execute a program in Deno, you may have observed an informational message when it starts up. This message notifies you about the availability of a new version of Deno. This happens because Deno is designed to keep you updated with its latest versions, ensuring you have access to the newest features, improvements, and security enhancements.
Main worker
The following step involves launching a main worker factory, which is then used to construct a main worker. The main worker is essentially the core thread that operates the primary module. This central worker is inherently generated and consistently linked with the main module. In comparison, web workers are forged when required.
After the establishment of the main worker, the program commences its execution through the employment of the main worker's run API. This API facilitates the initiation of the program's operational journey within the main worker's domain.
--
The earlier explanation gave a basic overview of the processes in the run command. Now, let's break down each step in detail. We will start by understanding the basic concept of ModuleSpecifier.
Last updated