Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Denobyexample #448

Merged
merged 14 commits into from
May 16, 2024
51 changes: 51 additions & 0 deletions by-example/benchmarking.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* @title Benchmarking
* @difficulty beginner
* @tags cli
* @run deno bench <url>
* @resource {https://docs.deno.com/runtime/manual/tools/benchmarker} Manual: Benchmarker tool
* @resource {/http-requests} Example: HTTP Requests
* @group System
*
* When writing libraries, a very common task that needs to be done is
* testing the speed of methods, usually against other libraries. Deno
* provides an easy-to-use subcommand for this purpose.
*/

// The most basic form of deno benchmarking is providing a name and an
// anonymous function to run.
Deno.bench("URL parsing", () => {
new URL("https://deno.land");
});

// We are also able to use an async function.
Deno.bench("Async method", async () => {
await crypto.subtle.digest("SHA-256", new Uint8Array([1, 2, 3]));
});

// We can optionally use long form bench definitions.
Deno.bench({
name: "Long form",
fn: () => {
new URL("https://deno.land");
},
});

// We are also able to group certain benchmarks together
// using the optional group and baseline arguments.
Deno.bench({
name: "Date.now()",
group: "timing",
baseline: true,
fn: () => {
Date.now();
},
});

Deno.bench({
name: "performance.now()",
group: "timing",
fn: () => {
performance.now();
},
});
34 changes: 34 additions & 0 deletions by-example/byte-manipulation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* @title Manipulating byte arrays
* @difficulty beginner
* @tags cli
* @run <url>
* @resource {$std/bytes} Doc: std/bytes
* @group Encoding
*
* When working with lower-level data we often deal
* with byte arrays in the form of Uint8Arrays. There
* are some common manipulations and queries that can
* be done and are included with the standard library.
*/

// Let's initialize some byte arrays
const a = new Uint8Array([0, 1, 2, 3, 4]);
const b = new Uint8Array([5, 6, 7, 8, 9]);
const c = new Uint8Array([4, 5]);

// We can concatenate two byte arrays using the
// concat method
import { concat } from "jsr:@std/bytes/concat";
const d = concat([a, b]);
console.log(d); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

// Sometimes we need to repeat certain bytes
import { repeat } from "jsr:@std/bytes/repeat";
console.log(repeat(c, 4)); // [4, 5, 4, 5, 4, 5, 4, 5]

// Sometimes we need to mutate a Uint8Array and need a copy
import { copy } from "jsr:@std/bytes/copy";
const cpy = new Uint8Array(5);
console.log("Bytes copied:", copy(b, cpy)); // 5
console.log("Bytes:", cpy); // [5, 6, 7, 8, 9]
42 changes: 42 additions & 0 deletions by-example/checking-file-existence.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* @title Checking for file existence
* @difficulty beginner
* @tags cli, deploy
* @run --allow-read --allow-write <url>
* @group File System
*
* Sometimes we as developers think that we need to check
* if a file exists or not. More often than not, we are
* entirely wrong.
*/

// Let's say we wanted to create a folder if one doesn't
// already exist. Logically it makes sense to first verify
// that the folder exists, then try to create it right?
// Wrong. This will create a race condition where if a folder
// gets created in between when you check if the folder exists
// and when you create a folder, your program will crash.
// Instead, you should just create a folder and try to catch
// errors like so.
try {
await Deno.mkdir("new_dir");
} catch (err) {
if (!(err instanceof Deno.errors.AlreadyExists)) {
throw err;
}
}

// This applies to almost every usecase. If you have a niche
// usecase that requires you to check for existence of a file
// without doing an filesystem operations other than that
// (which is quite rare), then you can simply lstat the file
// and catch the error.
try {
await Deno.lstat("example.txt");
console.log("exists!");
} catch (err) {
if (!(err instanceof Deno.errors.NotFound)) {
throw err;
}
console.log("not exists!");
}
41 changes: 41 additions & 0 deletions by-example/color-logging.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* @title Logging with colors
* @difficulty beginner
* @tags cli, deploy, web
* @run <url>
* @resource {https://developer.mozilla.org/en-US/docs/Web/API/console#styling_console_output} MDN: Styling console output
* @group Basics
*
* Most modern terminals can display program logs in colors and with text
* decorations. This example shows how to display colors when using
* `console.log`.
*/

// Deno has support for CSS using the %c syntax in console.log. Here, the text
// "Hello World" is displayed in red. This also works in the browser.
console.log("%cHello World", "color: red");

// Not just foreground, but also background colors can be set.
console.log("%cHello World", "background-color: blue");

// Text decorations like underline and strikethrough can be set too.
console.log("%cHello World", "text-decoration: underline");
console.log("%cHello World", "text-decoration: line-through");

// Font weight can also be set (either to normal, or to bold).
console.log("%cHello World", "font-weight: bold");

// Multiple CSS rules can also be applied at once. Here the text is red and bold.
console.log("%cHello World", "color: red; font-weight: bold");

// A single console.log can also contain multiple %c values. Styling is reset at
// every %c.
console.log("%cHello %cWorld", "color: red", "color: blue");

// Instead of predefined colors, hex literals and `rgb()` are also supported.
// Note that some terminals do not support displaying these colors.
console.log("%cHello World", "color: #FFC0CB");
console.log("%cHello World", "color: rgb(255, 192, 203)");

// It is not possible to configure font size, font family, leading, or any other
// CSS attributes.
39 changes: 39 additions & 0 deletions by-example/command-line-arguments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* @title Command Line Arguments
* @difficulty beginner
* @tags cli
* @run <url> Deno Sushi --help --version=1.0.0 --no-color
* @resource {https://deno.land/api?s=Deno.args} Doc: Deno.args
* @resource {$std/cli/parse_args.ts} Doc: std/cli
* @group CLI
*
* Command line arguments are often used to pass configuration options to a
* program.
*/

// You can get the list of command line arguments from `Deno.args`.
const name = Deno.args[0];
const food = Deno.args[1];
console.log(`Hello ${name}, I like ${food}!`);

// Often you want to parse command line arguments like `--foo=bar` into
// structured data. This can be done using `std/cli`.
import { parseArgs } from "jsr:@std/cli/parse-args";

// The `parseArgs` function takes the argument list, and a list of options. In these
// options you specify the types of the accepted arguments and possibly default
// values. An object is returned with the parsed arguments.
// NOTE: this function is based on [`minimist`](https://github.com/minimistjs/minimist), not compatible with the `parseArgs()` function in `node:util`.
const flags = parseArgs(Deno.args, {
boolean: ["help", "color"],
string: ["version"],
default: { color: true },
negatable: ["color"],
});
console.log("Wants help?", flags.help);
console.log("Version:", flags.version);
console.log("Wants color?:", flags.color);

// The `_` field of the returned object contains all arguments that were not
// recognized as flags.
console.log("Other:", flags._);
36 changes: 36 additions & 0 deletions by-example/create-remove-directories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* @title Creating & Removing Directories
* @difficulty beginner
* @tags cli
* @run --allow-write <url>
* @resource {https://deno.land/api?s=Deno.mkdir} Doc: Deno.mkdir
* @resource {https://deno.land/api?s=Deno.remove} Doc: Deno.remove
* @group File System
*
* Creating and removing directories is a common task. Deno has a number of
* functions for this task.
*/

// The `Deno.mkdir()` function creates a directory at the specified path.
// If the directory already exists, it errors.
await Deno.mkdir("new_dir");

// A directory can also be created recursively. In the code below, three new
// directories are created: `./dir`, `./dir/dir2`, and `./dir/dir2/subdir`. If
// the recursive option is specified the function will not error if any of the
// directories already exist.
await Deno.mkdir("./dir/dir2/subdir", { recursive: true });

// Directories can also be removed. This function below removes the `./new_dir`
// directory. If the directory is not empty, the function will error.
await Deno.remove("./new_dir");

// To remove a directory recursively, use the `recursive` option. This will
// remove the `./dir` directory and all of its contents.
await Deno.remove("./dir", { recursive: true });

// Synchronous versions of the above functions are also available.
Deno.mkdirSync("new_dir");
Deno.removeSync("new_dir");

// Creating and removing directories requires the `write` permission.
25 changes: 25 additions & 0 deletions by-example/cron.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @title Deno Cron
* @difficulty intermediate
* @tags cli, deploy
* @run --unstable <url>
* @resource {https://docs.deno.com/deploy/kv/manual/cron} Deno Cron user guide
* @resource {https://deno.land/api?s=Deno.cron&unstable=} Deno Cron Runtime API docs
* @group Scheduled Tasks
*
* Deno Cron is a cron task scheduler built into the Deno runtime and works with
* zero configuration on Deno Deploy. There's no overlapping cron executions and
* has automatic handler retries on exceptions.
*/

// Create a cron job called "Log a message" that runs once a minute.
Deno.cron("Log a message", "* * * * *", () => {
console.log("This will print once a minute.");
});

// Create a cron job with a backoff schedule measured in milliseconds.
Deno.cron("Retry example", "* * * * *", {
backoffSchedule: [1000, 5000, 10000],
}, () => {
throw new Error("Deno.cron will retry this three times, to no avail!");
});
36 changes: 36 additions & 0 deletions by-example/deleting-files.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* @title Deleting Files
* @difficulty beginner
* @tags cli
* @resource {https://deno.land/api?s=Deno.remove} Doc: Deno.remove
* @group File System
*
* Removing files and directories is a common task. Deno has a number of
* functions for this task.
*/

// In the case that we want to remove a simple file,
// we can simply call Deno.remove with the filename as
// a parameter
await Deno.remove("example.txt");

// There is also a sync version of the api available
Deno.removeSync("example.txt");

// If we want to remove a directory, we could do exactly
// what we did above. If the directory has contents, the
// call would error out. If we want to recursively delete
// the contents of a directory, we should set recursive to
// true
await Deno.remove("./dir", { recursive: true });

// A common pattern is to remove a file or directory only
// if it already exists. The correct way of doing this is
// by just doing it and trying to catch any NotFound errors.
try {
await Deno.remove("example.txt");
} catch (err) {
if (!(err instanceof Deno.errors.NotFound)) {
throw err;
}
}
20 changes: 20 additions & 0 deletions by-example/deno-version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* @title Getting the Deno version
* @difficulty beginner
* @tags cli
* @run <url>
* @resource {https://deno.land/api?s=Deno.version} Doc: Deno.version
* @group CLI
*
* How to examine the version of Deno being used.
*/

// To print the current version of Deno, just reach into the Deno global object
// where all non-web-standard APIs reside.
console.log("Current Deno version", Deno.version.deno);

// Deno has two main dependencies: the V8 JavaScript engine (from the Chrome web
// browser) and the TypeScript compiler. The versions of these are also
// accessible in the `Deno.version` object.
console.log("Current TypeScript version", Deno.version.typescript);
console.log("Current V8 version", Deno.version.v8);
28 changes: 28 additions & 0 deletions by-example/dependency-management.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* @title Dependency Management
* @difficulty beginner
* @tags cli, deploy
* @resource {/import-export} Example: Importing & Exporting
* @run <url>
* @group Basics
*
* It is unwieldy to have to import the same remote module over and over again.
* Deno provides some conventions to make managing dependencies easier.
*/

// File: ./deps.ts

// The Deno ecosystem has a convention to re-export all remote dependencies from
// a deps.ts file at the root of the repo. This keeps remote dependencies
// organized, and in a single place.
export * as http from "jsr:@std/http";
export * as path from "jsr:@std/path";

// File: ./main.ts

// Other files can then import dependencies from the deps.ts file.
// deno-lint-ignore no-unused-vars
import { path } from "./deps.ts";

// Doing this makes package version upgrades really easy, as all external
// dependency specifiers live in the same file.
31 changes: 31 additions & 0 deletions by-example/dns-queries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* @title Running DNS Queries
* @difficulty beginner
* @tags cli, deploy
* @run --allow-net <url>
* @resource {https://deno.land/api?s=Deno.resolveDns} Doc: Deno.resolveDns
* @resource {https://developer.mozilla.org/en-US/docs/Glossary/DNS} MDN: DNS
* @group Network
*
* There are some cases when running DNS queries is useful. This is
* usually the case when one would like to use a DNS server not configured
* on the machine.
*/

// In the most basic basic case, we can query a domain's A record.
// This will give us a list of ipv4 addresses.
const a = await Deno.resolveDns("example.com", "A");
console.log(a);

// We can also query other record types. In this case we are querying
// an MX record which is related to email protocols. Deno supports querying
// A, AAAA, ANAME, CAA, CNAME, MX, NAPTR, NS, PTR, SOA, SRV, and TXT records.
const mx = await Deno.resolveDns("example.com", "MX");
console.log(mx);

// We are also optionally able to specify a nameserver via an ip address
// and (optionally) a port number. To override the system configuration.
const aaaa = await Deno.resolveDns("example.com", "AAAA", {
nameServer: { ipAddr: "8.8.8.8", port: 53 },
});
console.log(aaaa);
Loading
Loading