Content

Configure Deno

Terminal:

curl -fsSL https://deno.land/install.sh | sh

To install Deno. Then follow the terminal tips, to update the PATH variable.


Terminal:

deno upgrade

To upgrade Deno.


Terminal:

deno install -Arf jsr:@deno/deployctl

To install deployment tool.


Terminal:

deployctl --help

To check installation.


Terminal:

rm -rf $HOME/.deno

To uninstall Deno.


Terminal:

deno info

To get info about cash configuration.

DENO_DIR location: /home/user/.cache/deno Remote modules cache: /home/user/.cache/deno/deps npm modules cache: /home/user/.cache/deno/npm Emitted modules cache: /home/user/.cache/deno/gen Language server registries cache: /home/user/.cache/deno/registries Origin storage: /home/user/.cache/deno/location_data


Terminal:

rm -rf /home/user/.cache/deno

To remove recursively cashed Deno files(use previous output paths).

Manage Deno Projects

Terminal:

deno init

To create Deno project inside the terminal current folder.


Terminal:

deno init basic-project

To create Deno project inside new folder basic-project.

Execution of deno init command for already created project will skip all files created before. So your project will not be damaged.

ℹ️ Skipped creating main.ts as it already exists ℹ️ Skipped creating main_test.ts as it already exists ℹ️ Skipped creating deno.json as it already exists ✅ Project initialized Run these commands to get started # Run the program deno run main.ts # Run the program and watch for file changes deno task dev # Run the tests deno test


Terminal:

deno cache --reload my_module.ts

To force Deno to refetch and recompile modules into the cache.


Terminal:

deno vendor main.ts test.deps.ts https://deno.land/std/path/mod.ts

To download all remote dependencies of the specified modules into a local vendor folder.


Terminal:

deno run --no-remote --import-map=vendor/import_map.json main.ts

To run + force Deno use the modules in the vendor folder.


Terminal:

deno check module.ts

To type-check without execution.


Terminal:

deno run module.ts

To execute without type-check.


Terminal:

deno check --all module.ts

To also type-check remote modules and npm packages.


Terminal:

deno run --check module.ts

To type-check before execution.


Terminal:

deno run --check=all module.ts

To also type-check remote modules and npm packages before execution.


Terminal:

deno fmt file.ts

To format file.ts code according to standards.


Terminal:

deno fmt

To format recursively all files code according to standards.


At the top of the file add comment line:

// deno-lint-ignore-file

To ignore linting of this file. Can be useful in case of use any *.js libraries, f.e.vue.esm-browser.prod.js as frontend side injections, in case of soft upgrade etc.

API changes and deprecations

API changes and deprecations

Types and Type Declarations

Types and Type Declarations

Private Modules and Repositories

Private Modules and Repositories

Runtime APIs

Runtime APIs

Importing NPM Packages

main.js

import { emojify } from "npm:node-emoji@2"; console.log(emojify(":t-rex: :heart: NPM"));

Terminal:

deno run main.js

Output:

🦖 ❤️ NPM

As described in docs, using of npm packages is unstable. Do not use it without strict needs.

Copypaste from terminal:

> emojify(":heart:"); "❤️" > emojify(":t-rex:"); "🦖" >

Screenshot from terminal:

terminal screenshot

In some reasons the " symbol after the heart symbol is recolored in the black color(fail even with this simple example above). Also looks like import returns undefined which probably some trash too.

Node API Compatibility List

Node API Compatibility List

JSX import source pragma(compiler directive)

To use Preact from esm.sh, add in the source code file leading comments @jsxImportSource pragma

/** @jsxImportSource https://esm.sh/preact */ export function App() { return ( <div> <h1>Hello, world!</h1> </div> ); }

Basic Twind(tailwind-in-js) example

import { extract, install } from "https://esm.sh/@twind/core@1.1.3"; import presetTailwind from "https://esm.sh/@twind/preset-tailwind@1.1.4"; install({ presets: [ presetTailwind(), { theme: { fontFamily: { sans: ["Helvetica", "sans-serif"], serif: ["Times", "serif"], }, }, }, ], }); function renderBody() { return `<!DOCTYPE html> <html lang="en"> <body class="font-sans"> <h1 class="text(3xl blue-500)">Hello from Deno</h1> </body> </html> `; } function ssr() { const body = renderBody(); const { html, css } = extract(body); return html.replace("</head>", `<style data-twind>${css}</style></head>`); } console.log(ssr());

Basic deno-dom(DOM and HTML parser) example

import { DOMParser, initParser, } from "https://deno.land/x/deno_dom/deno-dom-wasm-noinit.ts"; (async () => { // initialize when you need it, but not at the top level await initParser(); const doc = new DOMParser().parseFromString( `<h1>Lorem ipsum dolor...</h1>`, "text/html", ); })();

Managing Dependencies

Example:

File deps.ts (use to manage dependencies).

export * as http from "jsr:@std/http"; export * as path from "jsr:@std/path"; export { add, multiply, } as remote_lib from "https://x.nest.land/ramda@0.27.0/source/index.js"; export { add, multiply, } as local_lib from "./arithmetic.ts";


File arithmetic.ts.

/** * arithmetic.ts */ export function add(a: number, b: number): number { return a + b; } export function multiply(a: number, b: number): number { return a * b; } export interface Foo {} export class Bar {} export const bang = "bang";


File main.ts.

import { path, remote_lib } from "./deps.ts";


By using a lock file (with the --lock command line flag), you can ensure that the code pulled from a URL is the same as it was during initial development.

For production deployment use deno vendor subcommand to manage the host of the URL goes down case.

To force deno to refetch and recompile modules into the cache, use deno cache --reload target_module.ts

Permissions(manage Deno security model)

Permissions

Manage Data (Fetch, Read, Write, Append)

To make a call over the web possible, add the --allow-net flag to the deno run terminal command.

To convert a Deno file into a writable and readable stream or read and write files add --allow-read --allow-write flags to the deno run terminal command.

deno run --allow-read --allow-write --allow-net manage_data.ts


The manage_data.ts file.

/** Output: JSON Data */ const json_response = await fetch("https://api.github.com/users/denoland"); const json_data = await json_response.json(); console.log(json_data); /** Output: HTML Data */ const text_response = await fetch("https://deno.land/"); const text_data = await text_response.text(); console.log(text_data); /** Output: Error Message */ try { await fetch("https://does.not.exist/"); } catch (error) { console.log(error); } /** Receiving a file */ const file_response = await fetch("https://deno.land/logo.svg"); if (file_response.body) { const save_here = await Deno.open( "./logo.svg", { write: true, create: true } ); await file_response.body.pipeTo(save_here.writable); } /** Sending a file */ const send_file = await Deno.open( "./logo.svg", { read: true } ); await fetch( "https://example.com/", { method: "POST", body: send_file.readable } ); /** read file */ const text = await Deno.readTextFile("./people.json"); console.log(text); /** write file */ await Deno.writeTextFile("./hello.txt", "Hello World!"); console.log("File written to ./hello.txt"); /** append to the file */ await Deno.writeTextFile("./hello.txt", "This text will be appended.", { append: true, }); /** write serialized json object to a file */ function writeJson(path: string, data: object): string { try { /** can be "await Deno.writeTextFile" for async function */ Deno.writeTextFileSync(path, JSON.stringify(data)); return "written to " + path; } catch (e) { return e.message; } } console.log(writeJson("./data.json", { hello: "World" }));

Making Scripts Executable (Unix only)

Making Scripts Executable With a Hashbang (Shebang)

Manage External Environment

The env runs a program in a modified environment.


(--allow-env) Runtime Deno.Env interface to interact with the process environment variables.


(--allow-env) Runtime Deno.env provides environment variables.


(--allow-env) Runtime Deno.args accesses the command line arguments.


ReadableStream interface represents a readable stream of byte data.


WritableStream interface provides a standard abstraction for writing streaming data to a destination, known as a sink.


File System Deno.FsFile.readable is used to get a readable stream from the file. This readable stream closes the file when it is finished reading, so it is not necessary to close the file explicitly.


File System Deno.FsFile.writable is used to write the contents of the file.


(--allow-read) File System Deno.open is used to get a handle to a file.


(--allow-write) File System Deno.remove Removes the named file or directory.

await Deno.remove("/path/to/empty_dir/or/file"); await Deno.remove("/path/to/populated_dir/or/file", { recursive: true });


(--allow-read --allow-write) File System Deno.rename


(--allow-write) File System Deno.mkdir creates a new directory with the specified path.


(--allow-read --allow-write) File System Deno.create creates a new directory with the specified path.


(--allow-read) File System Deno.readDir reads the directory given by path and returns an async iterable of Deno.DirEntry information about a directory entry.

for await (const dirEntry of Deno.readDir("/")) { console.log(dirEntry.name); }


(--allow-write) File System Deno.chmod changes the permission of a specific file/directory of specified path using sequence of 3 octal numbers.

await Deno.chmod("/path/to/file", 0o666);

Manage built-in KV(key/value) Database

Steps to create the database, place it in desirable folder and use. Suitable only for debug needs. Deploy does not allow to use custom database.

1. Create database in project root folder. Include const kv = await Deno.openKv("db"); syntax in your main.ts file. After the first success execution the database files will be created in root folder.

2. Create desirable folder structure and move created database files inside destination folder. After that check the correct path to new database destination using next syntax in main.ts. Correct the appendix of join according to your file structure.

import { join } from "https://deno.land/std@0.224.0/path/mod.ts"; const db_path = join(Deno.cwd(), "some/path/to/db"); console.log(db_path); // const kv = await Deno.openKv("db"); // commented to avoid recreate in root

3. When db_path looks correct, use it to manage database.

import { join } from "https://deno.land/std@0.224.0/path/mod.ts"; const db_path = join(Deno.cwd(), "correct/path/to/db"); console.log(db_path); const kv = await Deno.openKv(db_path); console.log(kv); // to print and confirm some structure in console // create interfaces for later type assertion (as TypeName) // also interfaces can be placed in separated file f.e. "model.ts" and then imported using // import { Fruit, Product } from "./model.ts"; export interface Fruit { fruit_name: string; growed_in: string; } export interface Product { product_name: string; production_year: number; } // prepare data to use in database // ----------------- // item for database const fresh_fruit: Fruit = { name: "ice orange"; growed_in: "Antarctica"; }; // -------------------------------------- // database category, like sql table name const category = "fruits"; // ----------------------------- // unique identifier of the item const unique_key = fresh_fruit.name; // --------------------------- // set recording into database await kv.set([category, unique_key], fresh_fruit); // ---------------------- // get item from database using type assertion const polar_fruit_one = await kv.get(["fruits", "ice orange"]); const ac = r.value as Fruit; // ------------------------------------------ // get item from database using inline syntax const polar_fruit_two = await kv.get<Fruit>(["fruits", "ice_orange"]); // ----------------------- // some check (demo needs) console.log( (polar_fruit_one.growed_in === polar_fruit_two.growed_in) && (polar_fruit_two.growed_in === "Antarctica") );

After the correct settings, you can use key/value database in deno deploy as part of deployed repository. Under the hood deno uses external provider to manage built-in databases. Free plan has some limitations(according to official docs).

To implement querying based on the values(default kv database provides only unique keys for retrival the data), similar as sql, create secondary indexes, which store the same value under additional keys that include (part of) that value.

Deno KV supports key expiration, allowing developers to control time to live (TTL) for keys in a KV database. This allows an expiration timestamp to be associated with a key, after which the key will be automatically deleted from the database:

Debug Development(deno.json tasks)

A deno.json file, created using deno init command.

{ "tasks": { "dev": "deno run --watch main.ts", "test": "deno run --allow-all --unstable-kv main_test.ts", "bang": "deno run --inspect-wait --allow-all --unstable-kv main.ts" } }

The --inspect-wait flag, forcing the execution to wait up to chrome(or chromium) debugger will be connected, using chrome://inspect/ -> reload gui in browser.

 ↑