36
loading...
This website collects cookies to deliver better user experience
Deno is a simple, modern and secure runtime for JavaScript and TypeScript that uses V8 and is built in Rust.
Simple: as we will soon see, Deno is simple to install, being shipped as a single executable file; Deno is also simple to use for small and larger scripts thanks to its powerful CLI, modern features and standard library; finally, learning Deno is also simple thanks to its short and execellent manual
Modern: Deno is built with modern technologies and follows a modern philosophy; it natively supports TypeScript and ES modules; it doesn't require a centralized package management solution; it also provides useful developer tools out of the box such as an opinionated source code formatter and a testing framework
Secure: by default, Deno prevents access to critical resources such as files, network connections and environment variables; using these resources requires an explicit permission grant by the user
curl -fsSL https://deno.land/x/install/install.sh | sh
curl
and unzip
installed on our system.Archive: /home/<your_username>/.deno/bin/deno.zip
inflating: /home/<your_username>/.deno/bin/deno
Deno was installed successfully to /home/<your_username>/.deno/bin/deno
Manually add the directory to your $HOME/.bash_profile (or similar)
export DENO_INSTALL="/home/<your_username>/.deno"
export PATH="$DENO_INSTALL/bin:$PATH"
$HOME/.profile
or $HOME/.bash_profile
, and add these two lines at the bottom:export DENO_INSTALL="/home/<your_username>/.deno"
export PATH="$DENO_INSTALL/bin:$PATH"
deno
and press enter to see the following output:$ deno
Deno 1.11.5
exit using ctrl+d or close()
>
Ctrl
and D
together.deno run https://deno.land/std/examples/welcome.ts
in the terminal should display the following message:$ deno run https://deno.land/std/examples/welcome.ts
Welcome to Deno!
PATH
environment variable is not possible, we can still call deno
by its relative path, for example:$ .deno/bin/deno
Deno 1.11.5
exit using ctrl+d or close()
>
main.ts
(the name main
has no importance) that looks like this:// main.ts
console.log("Hello from Deno!");
deno run main.ts
to see the following output:$ deno run main.ts
Check file:///home/<your_username>/<some_directory>/main.ts
Hello from Deno!
package.json
file or any external dependencies to run this TypeScript file.deno fmt main.ts
or use the Deno extension for VSCode to automatically format the source code in this file.main.ts
file and define the baseURL
variable as follows:// main.ts
/** Base URL for all calls to the Hacker News API */
const baseURL = "https://hacker-news.firebaseio.com/v0";
id
, a unique incrementing integer number, and type
, an enumeration of different item types.// main.ts
const baseURL = "https://hacker-news.firebaseio.com/v0";
/** Item represents an item fetched from the HN API */
interface Item {
/** Unique item ID; the only required property */
readonly id: number;
/** Item type (`job`, `story`, `comment`, `poll`, or `pollopt`) */
readonly type?: string;
/** Username of the user who submitted the item */
readonly by?: string;
/** Title text for a story, poll or job */
readonly title?: string;
/** URL for a story or job */
readonly url?: string;
/** Text for a story, comment, poll, poll option or job */
readonly text?: string;
/** Unix timestamp for when the item was created */
readonly time?: number;
/** Score for a story, job or poll; votes for a poll option */
readonly score?: number;
/** Number of total comments for a story or poll */
readonly descendants?: number;
/** Set to `true` if the item is deleted */
readonly deleted?: boolean;
/** Set to `true` if the item is dead */
readonly dead?: boolean;
/** ID of the parent item of a comment (a story or another comment) */
readonly parent?: number;
/** List of IDs of the item's comments, in display order */
readonly kids?: number[];
/** ID of the poll associated to a poll option */
readonly poll?: number;
/** List of IDs of related poll options, in display order */
readonly parts?: number[];
}
id
property is required, all other properties are marked as optional with ?
. All properties are also marked as readonly
so that they cannot be reassigned.Item
, but they have been defined and documented for completeness./maxitem.json
endpoint, that is https://hacker-news.firebaseio.com/v0/maxitem.json.// main.ts
const baseURL = "https://hacker-news.firebaseio.com/v0";
interface Item {
// Omitted for brevity
}
/** getMaxItemID returns the ID of the most recent item published on HN */
async function getMaxItemID(): Promise<number> {
const endpoint = `${baseURL}/maxitem.json`;
const res = await fetch(endpoint);
const id = await res.json();
return id;
}
fetch
web API implemented by Deno to retrieve the JSON data representing the largest item ID.// main.ts
// ...
async function getMaxItemID(): Promise<number> {
const endpoint = `${baseURL}/maxitem.json`;
const res = await fetch(endpoint);
const id = await res.json();
return id;
}
// Remove this line after this step
console.log(await getMaxItemID());
deno run main.ts
:$ deno run main.ts
error: Uncaught (in promise) PermissionDenied: Requires net access to "hacker-news.firebaseio.com", run again with the --allow-net flag
const res = await fetch(endpoint);
^
at deno:core/core.js:86:46
at unwrapOpResult (deno:core/core.js:106:13)
at Object.opSync (deno:core/core.js:120:12)
at opFetch (deno:extensions/fetch/26_fetch.js:43:17)
at mainFetch (deno:extensions/fetch/26_fetch.js:170:61)
at deno:extensions/fetch/26_fetch.js:395:7
at new Promise (<anonymous>)
at fetch (deno:extensions/fetch/26_fetch.js:357:15)
at getMaxItemID (file:///home/<your_username>/<some_directory>/main.ts:43:21)
at file:///home/<your_username>/<some_directory>/main.ts:48:1
hacker-news.firebaseio.com
. As explained in the error message, we need to use the --allow-net
flag to explicitly grant this permission when running the script:$ deno run --allow-net main.ts
27121843
console.log(await getMaxItemID());
that we just added./item/<id>.json
endpoint, for example https://hacker-news.firebaseio.com/v0/item/27121843.json.getItemByID()
that fetches an item given its ID:// main.ts
// ...
/** getItemByID fetches an item from the HN API given its ID */
async function getItemByID(id: number): Promise<Item | undefined> {
const endpoint = `${baseURL}/item/${id}.json`;
const res = await fetch(endpoint);
const item = await res.json();
return item ?? undefined;
}
getItemByID()
will return an object described by the Item
interface; otherwise, it will return undefined
. The nullish coalescing operator (??
) is supported out of the box by Deno.console.log(await getItemByID(await getMaxItemID()));
as shown:// main.ts
// ...
async function getItemByID(id: number): Promise<Item | undefined> {
const endpoint = `${baseURL}/item/${id}.json`;
const res = await fetch(endpoint);
const item = await res.json();
return item ?? undefined;
}
// Remove this line after this step
console.log(await getItemByID(await getMaxItemID()));
deno run --allow-net main.ts
should display an item similar to this:$ deno run --allow-net main.ts
Check file:///home/<your_username>/<some_directory>/main.ts
{
by: "velut",
id: 27121843,
parent: 27121265,
text: "Thank you!<p>Yes, I use prism-react-renderer for syntax highlighting.<p>I did not know about Shiki, ...",
time: 1620758446,
type: "comment"
}
undefined
if the HN API has not properly updated yet internally.streamComments()
function.// main.ts
// ...
/** streamComments continuously fetches and displays the most recent comments published on HN */
async function streamComments() {
// Get the ID of the most recent item
let id = await getMaxItemID();
}
// main.ts
// ...
async function streamComments() {
let id = await getMaxItemID();
// Keep running forever
while (true) {
// Get the item
const item = await getItemByID(id);
// Increment the ID for the next item
id += 1;
}
}
sleep
function:// main.ts
// Import the `sleep` function from a remote module
import { sleep } from "https://deno.land/x/sleep/mod.ts";
// ...
async function streamComments() {
let id = await getMaxItemID();
while (true) {
const item = await getItemByID(id);
// If the item does not exist, wait 5 seconds and try again
if (!item) {
await sleep(5);
continue;
}
id += 1;
}
}
import ... from "./some/local/module.ts"
) and URLs for remote modules (for example, import ... from "https://example.com/some/remote/module.ts
).streamComments()
function by printing only comments:// main.ts
import { sleep } from "https://deno.land/x/sleep/mod.ts";
// ...
async function streamComments() {
let id = await getMaxItemID();
while (true) {
const item = await getItemByID(id);
if (!item) {
await sleep(5);
continue;
}
// Print only items that are visible comments
const { type, deleted, dead } = item;
const removed = deleted || dead || false;
if (type === "comment" && !removed) {
// Get the comment's author, if any
const author = item.by ?? "unknown author";
// Get the comment's URL on HN website
const hnURL = `https://news.ycombinator.com/item?id=${id}`;
// Print the comment
console.log(`\nRead new comment by ${author} on ${hnURL}`);
console.log(item);
}
id += 1;
}
}
await streamComments()
at the bottom:// main.ts
// ...
async function streamComments() {
// ...
}
await streamComments();
deno run --allow-net main.ts
command used before:$ deno run --allow-net main.ts
Download https://deno.land/x/sleep/mod.ts
Warning Implicitly using latest version (v1.2.0) for https://deno.land/x/sleep/mod.ts
Download https://deno.land/x/[email protected]/mod.ts
Download https://deno.land/x/[email protected]/sleep.ts
Download https://deno.land/std/log/mod.ts
<...many other downloads...>
Check file:///home/<your_username>/<some_directory>/main.ts
Read new comment by tonyedgecombe on https://news.ycombinator.com/item?id=27762774
{
by: "tonyedgecombe",
id: 27762774,
parent: 27761864,
text: ">The printer stack which has barely received an update since Windows XP is a perfect example.<p>T...",
time: 1625674491,
type: "comment"
}
Read new comment by jph on https://news.ycombinator.com/item?id=27762775
{
by: "jph",
id: 27762775,
parent: 27762699,
text: "The catchphrase is "neurons that fire together wire together".",
time: 1625674509,
type: "comment"
}
Read new comment by exo-pla-net on https://news.ycombinator.com/item?id=27762777
{
by: "exo-pla-net",
id: 27762777,
parent: 27762326,
text: "The plant kingdom is almost entirely mono-food-sourced. They almost all rely on the sun, which, pend...",
time: 1625674519,
type: "comment"
}