Skip to content

Commit

Permalink
Denobyexample (#448)
Browse files Browse the repository at this point in the history
Co-authored-by: Josh Collinsworth <[email protected]>
Co-authored-by: Yoshiya Hinosawa <[email protected]>
  • Loading branch information
3 people authored May 16, 2024
1 parent e4a0fd8 commit 327135a
Show file tree
Hide file tree
Showing 77 changed files with 4,704 additions and 30 deletions.
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,65 @@ succeeds without error before submitting a pull request. This will ensure that
there are no broken links or invalid MDX syntax in the content you have
authored.

## Examples

(https://docs.deno.com/examples)[Deno by Example] is a collection of small snippets showcasing various functions of the APIs implemented in Deno.


- Examples are written in TypeScript
- Each example should be a single file, no more than 50 lines
- Each example should be a self-contained unit, and should depend on no
dependencies other than Deno builtins and the standard library, unless a
third-party library is strictly required.
- Each example should be runnable without additional dependencies on all systems
(exceptions can be made for platform specific functionality)
- Examples should be introduce at most one (or in exceptional cases two or
three) concepts in Deno / Web APIs. Existing concepts should be linked to.
- Code should be kept _really simple_, and should be easy to read and understand
by anyone. Do not use complicated code constructs, or hard to follow builtins
like `Array.reduce`
- Concepts introduced in an example should be explained

### Adding an example

To add an example, create a file in the `by-example` directory. The file name should
be a short description of the example (in kebab case) and the contents should be the code for the example.
The file should be in the `.ts` format. The file should start with a JSDoc style
multi line comment that describes the example:

```ts
/**
* @title HTTP server: Hello World
* @difficulty intermediate
* @tags cli, deploy
* @run --allow-net <url>
* @group Basics
*
* An example of a HTTP server that serves a "Hello World" message.
*/
```

You should add a title, a difficulty level (`beginner` or `intermediate`), and a
list of tags (`cli`, `deploy`, `web` depending on where an example is runnable).
The `@run` tag should be included if the example can be run locally by just
doing `deno run <url>`. If running requires permissions, add these:

```ts
/**
* ...
* @run --allow-net --allow-read <url>
*/
```

After the pragmas, you can add a description of the example. This is optional,
but recommended for most examples. It should not be longer than one or two
lines. The description shows up at the top of the example in the example page,
and in search results.

After the JS Doc comment, you can write the code. Code can be prefixed with a
comment that describes the code. The comment will be rendered next to the code
in the example page.

## Special thanks for historical contributions

This repository was created using content from the
Expand Down
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);
Loading

0 comments on commit 327135a

Please sign in to comment.