diff --git a/deno.json b/deno.json index 1f1ba6570..6c34b54b7 100644 --- a/deno.json +++ b/deno.json @@ -22,10 +22,11 @@ }, "tasks": { "dev": "LUME_LOGS=WARN deno run --env-file -A lume.ts -s", + "dev:std": "deno task generate:std-docs && LUME_LOGS=WARN deno run --env-file -A lume.ts -s", "serve": "deno task dev", "serve:style": "BUILD_TYPE=FULL deno task lume -s --config=_config-styleguide.ts", "start": "deno task dev", - "build": "deno task generate:reference && BUILD_TYPE=FULL deno run --env-file -A lume.ts && tailwindcss -i styles.css -o _site/styles.css --minify", + "build": "deno task generate:reference && deno task generate:std-docs && BUILD_TYPE=FULL deno run --env-file -A lume.ts && tailwindcss -i styles.css -o _site/styles.css --minify", "build:light": "deno run --env-file -A lume.ts", "prod": "deno run --allow-read --allow-env --allow-net server.ts", "test": "deno test -A", @@ -38,6 +39,7 @@ "generate:llms": "deno run -A generate_llms_files.ts", "generate:llms:site": "deno run -A generate_llms_files.ts _site", "generate:reference": "cd reference_gen && deno task types && deno task doc", + "generate:std-docs": "deno run -A scripts/generate_std_docs.ts", "cache:clear": "rm -f reference_gen/.gen-cache*.json reference_gen/.node-incremental-cache.json", "search:upload": "deno run -A orama/upload_orama_index.ts --full", "search:analyze": "deno run -A orama/analyze_orama_index.ts" diff --git a/examples/tutorials/snapshot.md b/examples/tutorials/snapshot.md index 47e137397..c2e6ca94c 100644 --- a/examples/tutorials/snapshot.md +++ b/examples/tutorials/snapshot.md @@ -9,7 +9,7 @@ and compares it against a stored reference version. Rather than manually writing assertions for each property, you let the test runner record the entire output structure, making it easier to detect any unexpected changes. -The [Deno Standard Library](/runtime/fundamentals/standard_library/) has a +The [Deno Standard Library](/runtime/reference/std/) has a [snapshot module](https://jsr.io/@std/testing/doc/snapshot), which enables developers to write tests which assert a value against a reference snapshot. This reference snapshot is a serialized representation of the original value and diff --git a/examples/videos/command_line_utility.md b/examples/videos/command_line_utility.md index 8bd507fb4..5c687a34b 100644 --- a/examples/videos/command_line_utility.md +++ b/examples/videos/command_line_utility.md @@ -20,8 +20,8 @@ CLI tools. ### An introduction to Deno's Standard Library If you want to create a command line tool you can do so with -[Deno's standard Library](https://docs.deno.com/runtime/fundamentals/standard_library/). -It contains dozens of stable libraries with helpful utility functions that can +[Deno's standard Library](https://docs.deno.com/runtime/reference/std/). It +contains dozens of stable libraries with helpful utility functions that can cover a lot of the basics when working with JavaScript in the web. The standard Library also works in multiple runtimes and environments like Node.js and the browser. diff --git a/oldurls.json b/oldurls.json index 82b8718e0..c9c61c1f6 100644 --- a/oldurls.json +++ b/oldurls.json @@ -146,5 +146,6 @@ "/deploy/tutorials/*": "/examples/", "/deploy/kv/tutorials/": "/examples/kv/", "/deploy/kv/tutorials/schedule_notification/": "/examples/", - "/deploy/kv/tutorials/webhook_processor/": "/examples/" + "/deploy/kv/tutorials/webhook_processor/": "/examples/", + "/runtime/fundamentals/standard_library/": "/runtime/reference/std/" } diff --git a/runtime/_data.ts b/runtime/_data.ts index c79a27cdd..b9f9b9105 100644 --- a/runtime/_data.ts +++ b/runtime/_data.ts @@ -51,10 +51,6 @@ export const sidebar = [ title: "Configuration", href: "/runtime/fundamentals/configuration/", }, - { - title: "Standard library", - href: "/runtime/fundamentals/standard_library/", - }, { title: "Web development", href: "/runtime/fundamentals/web_dev/", @@ -226,6 +222,58 @@ export const sidebar = [ }, ], }, + { + title: "Standard library", + items: [ + { title: "Overview", href: "/runtime/reference/std/" }, + ...[ + "assert", + "async", + "bytes", + "cache", + "cbor", + "cli", + "collections", + "crypto", + "csv", + "data-structures", + "datetime", + "dotenv", + "encoding", + "expect", + "fmt", + "front-matter", + "fs", + "html", + "http", + "ini", + "internal", + "io", + "json", + "jsonc", + "log", + "media-types", + "msgpack", + "net", + "path", + "random", + "regexp", + "semver", + "streams", + "tar", + "testing", + "text", + "toml", + "ulid", + "uuid", + "webgpu", + "yaml", + ].map((name) => ({ + title: name, + href: `/runtime/reference/std/${name}/`, + })), + ], + }, { title: "Configuring TypeScript", href: "/runtime/reference/ts_config_migration/", diff --git a/runtime/fundamentals/_category_.json b/runtime/fundamentals/_category_.json deleted file mode 100644 index b40be674f..000000000 --- a/runtime/fundamentals/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Fundamentals", - "position": 2, - "link": { - "type": "doc", - "id": "index" - } -} diff --git a/runtime/fundamentals/modules.md b/runtime/fundamentals/modules.md index d535ca783..4f58eb8b3 100644 --- a/runtime/fundamentals/modules.md +++ b/runtime/fundamentals/modules.md @@ -171,8 +171,7 @@ import { pascalCase } from "https://deno.land/x/case/mod.ts"; Deno recommends [JSR](https://jsr.io), the modern JavaScript registry, for third party modules. There, you'll find plenty of well documented ES modules for your -projects, including the -[Deno Standard Library](/runtime/fundamentals/standard_library/). +projects, including the [Deno Standard Library](/runtime/reference/std/). You can [read more about Deno's support for npm packages here](/runtime/fundamentals/node/#using-npm-modules). diff --git a/runtime/fundamentals/standard_library.md b/runtime/fundamentals/standard_library.md deleted file mode 100644 index ff01f9bb5..000000000 --- a/runtime/fundamentals/standard_library.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: "Standard Library" -description: "An introduction to Deno's Standard Library. Learn about TypeScript-first modules, cross-platform compatibility, versioning, package management, and how to use standard modules in your Deno projects." -oldUrl: /runtime/manual/basics/standard_library/ ---- - -Deno provides a standard library written in TypeScript. It is a set of standard -modules that can be reused by programs, allowing you to focus on your -application logic rather than "reinventing the wheel" for common tasks. All of -the modules in the Deno Standard Library are audited by the core team and are -guaranteed to work with Deno, ensuring consistency and reliability. - -See all packages on - - -Many packages in the Deno Standard Library are also compatible with Node.js, -Cloudflare Workers, and other JavaScript environments. This allows you to write -code that can be run in multiple environments without modification. - -The standard library is hosted on JSR and is available at: -[https://jsr.io/@std](https://jsr.io/@std). Packages are documented, tested, and -include usage examples. You can browse the full list of standard library -packages on JSR, but here are a few examples: - -- [@std/path](https://jsr.io/@std/path): Path manipulation utilities, akin to - Node.js's `path` module. -- [@std/jsonc](https://jsr.io/@std/jsonc): (De)serialization of JSON with - comments -- [@std/encoding](https://jsr.io/@std/encoding): Utilities for encoding and - decoding common formats like hex, base64, and variant - -## Versioning and stability - -Each package of the standard library is independently versioned. Packages follow -[semantic versioning rules](https://jsr.io/@std/semver). You can use -[version pinning or version ranges](/runtime/fundamentals/modules/#package-versions) -to prevent major releases from affecting your code. - -## Importing standard library modules - -To install packages from the Deno Standard Library, you can use the `deno add` -subcommand to add the package to your `deno.json` import map. - -```sh -deno add jsr:@std/fs jsr:@std/path -``` - -The `deno.json` `imports` field will be updated to include those imports: - -```json -{ - "imports": { - "@std/fs": "jsr:@std/fs@^1.0.2", - "@std/path": "jsr:@std/path@^1.0.3" - } -} -``` - -You can then import these packages in your source code: - -```ts -import { copy } from "@std/fs"; -import { join } from "@std/path"; - -await copy("foo.txt", join("dist", "foo.txt")); -``` - -Alternatively, you can import modules directly with the `jsr:` specifier: - -```js -import { copy } from "jsr:@std/fs@^1.0.2"; -import { join } from "jsr:@std/path@^1.0.3"; - -await copy("foo.txt", join("dist", "foo.txt")); -``` - -## Node.js compatibility - -The Deno Standard Library is designed to be compatible with Node.js, Cloudflare -Workers, and other JavaScript environments. The standard library is written in -TypeScript and compiled to JavaScript, so it can be used in any JavaScript -environment. - -```sh -npx jsr add @std/fs @std/path -``` - -Running this command will add those packages to your `package.json`: - -```json -{ - "dependencies": { - "@std/fs": "npm:@jsr/std__fs@^1.0.2", - "@std/path": "npm:@jsr/std__path@^1.0.3" - } -} -``` - -Then you can import them in your source code, just like you would with any other -Node.js package. TypeScript will automatically find the type definitions for -these packages. - -```ts -import { copy } from "@std/fs"; -import { join } from "@std/path"; - -await copy("foo.txt", join("dist", "foo.txt")); -``` diff --git a/runtime/fundamentals/testing.md b/runtime/fundamentals/testing.md index 96cda7441..17e6c7f75 100644 --- a/runtime/fundamentals/testing.md +++ b/runtime/fundamentals/testing.md @@ -384,10 +384,9 @@ deno test --junit-path=./report.xml ## Spying, mocking (test doubles), stubbing and faking time -The [Deno Standard Library](/runtime/fundamentals/standard_library/) provides a -set of functions to help you write tests that involve spying, mocking, and -stubbing. Check out the -[@std/testing documentation on JSR](https://jsr.io/@std/testing) for more +The [Deno Standard Library](/runtime/reference/std/) provides a set of functions +to help you write tests that involve spying, mocking, and stubbing. Check out +the [@std/testing documentation on JSR](https://jsr.io/@std/testing) for more information on each of these utilities or our [tutorial on mocking and spying in tests with deno](/examples/mocking_tutorial/). @@ -679,7 +678,7 @@ Deno.test({ ## Snapshot testing -The [Deno Standard Library](/runtime/fundamentals/standard_library/) includes a +The [Deno Standard Library](/runtime/reference/std/) includes a [snapshot module](https://jsr.io/@std/testing/doc/snapshot/~) that allows developers to write tests by comparing values against reference snapshots. These snapshots are serialized representations of the original values and are stored diff --git a/runtime/fundamentals/web_dev.md b/runtime/fundamentals/web_dev.md index 117b82c97..d38a0eca1 100644 --- a/runtime/fundamentals/web_dev.md +++ b/runtime/fundamentals/web_dev.md @@ -15,9 +15,8 @@ applications, making your web dev a delightful experience. 2. Deno has [built-in TypeScript support](/runtime/fundamentals/typescript/), allowing you to write TypeScript code without additional configuration or tooling. -3. Deno comes with a [standard library](/runtime/fundamentals/standard_library/) - that includes modules for common tasks like HTTP servers, file system - operations, and more. +3. Deno comes with a [standard library](/runtime/reference/std/) that includes + modules for common tasks like HTTP servers, file system operations, and more. For your vanilla TypeScript, or JavaScript, web applications, you can use the built-in Deno [HTTP server](/runtime/fundamentals/http_server/). This is a great diff --git a/runtime/index.md b/runtime/index.md index 8a3a45234..66708410d 100644 --- a/runtime/index.md +++ b/runtime/index.md @@ -28,9 +28,8 @@ experience. It's built on [V8](https://v8.dev/), runtimes give full access every script they run, Deno allows you to enforce granular permissions. - Deno has a **robust built-in toolchain.** Unlike Node or browser JavaScript, - Deno includes a [standard library](/runtime/fundamentals/standard_library/), - along with a first-party - [linter/formatter](/runtime/fundamentals/linting_and_formatting/), + Deno includes a [standard library](/runtime/reference/std/), along with a + first-party [linter/formatter](/runtime/fundamentals/linting_and_formatting/), [test runner](/runtime/fundamentals/testing/), and more. - Deno is **fully compatible with [Node and npm](/runtime/fundamentals/node/).** - Deno is **fast and reliable**. diff --git a/runtime/reference/std/_overrides/README.md b/runtime/reference/std/_overrides/README.md new file mode 100644 index 000000000..4f600b99b --- /dev/null +++ b/runtime/reference/std/_overrides/README.md @@ -0,0 +1,85 @@ +# @std Package Overrides & Custom Blocks + +This directory holds editorial _override_ markdown files that are appended to +the autogenerated Standard Library package pages. + +## How generation works + +1. The script `scripts/generate_std_docs.ts` fetches overview HTML for every + `@std/*` package from JSR. +2. It writes (or rewrites) `runtime/reference/std/.md` with: + - Frontmatter (title, description, version, stability) + - An (optional) stability banner + - The package overview (HTML fragment) + - `## Additional Examples` section containing the override markdown if a file + named `_overrides/.md` exists. + - A preserved custom block (see below). + +## Adding override content + +Create a file named after the package, e.g.: + +```text +_overrides/internal.md +``` + +Put any extra examples, guides, etc. in that file. On the next generation run it +will appear under an "Additional Examples" heading. + +Important: + +- Do not include frontmatter (`--- ... ---`) in override files. They are + appended verbatim into the generated page body; frontmatter will show up as + plain text. +- Keep overrides to content sections (headings, paragraphs, code blocks, + images). +- If you need to change title/description/stability, edit the generated page's + frontmatter or adjust upstream JSR package metadata, not here. + +Minimal example for `_overrides/internal.md`: + +### Using diff utilities + +```ts +import { diffStr } from "jsr:@std/internal"; +console.log(diffStr("a", "b")); +``` + +## Persistent custom edits inside the generated page + +If you need to add content _directly_ inside a generated page and keep it across +regenerations, use the custom block markers the generator recognizes: + +```markdown + + +Your custom content here (additional sections, notes, etc.) + + +``` + +Anything between those markers is preserved every time the generator runs. If a +page has no custom block yet, a commented placeholder will be added for +convenience. + +## Safety notes + +- Do not edit outside the custom block; those areas will be replaced. +- If you rename or remove the markers, the content will be lost on the next run. +- Overrides (`_overrides/.md`) are never modified by the generator; they + are simply read and injected. + +## Regenerating + +Run: + +```sh +deno task generate:std-docs +``` + +This will rebuild all pages and keep both overrides and custom block content. + +## Skipping generation for a page (future option) + +Currently every page is regenerated. If we later want a skip/manual mode, we can +add a frontmatter flag (e.g. `generated: false`). diff --git a/runtime/reference/std/_overrides/internal.md b/runtime/reference/std/_overrides/internal.md new file mode 100644 index 000000000..a947a692d --- /dev/null +++ b/runtime/reference/std/_overrides/internal.md @@ -0,0 +1,16 @@ +--- +title: "@std/internal" +description: "The internal package for @std. Do not use this directly." +jsr: jsr:@std/internal +pkg: internal +version: 1.0.12 +generated: true +stability: internal +--- + +:::info Internal + +This @std package is for internal use and not intended for public consumption. +APIs may change or be removed. + +::: diff --git a/runtime/reference/std/_overrides/log.md b/runtime/reference/std/_overrides/log.md new file mode 100644 index 000000000..e6a9befee --- /dev/null +++ b/runtime/reference/std/_overrides/log.md @@ -0,0 +1,16 @@ +--- +title: "@std/log" +description: "A customizable logger framework" +jsr: jsr:@std/log +pkg: log +version: 0.224.14 +generated: true +stability: unstable +--- + +:::info No longer recommended + +The @std/log package is likely to be removed in the future; consider using +[OpenTelemetry](/runtime/fundamentals/open_telemetry/) for production systems. + +::: diff --git a/runtime/reference/std/assert.md b/runtime/reference/std/assert.md new file mode 100644 index 000000000..2fa8a8f6d --- /dev/null +++ b/runtime/reference/std/assert.md @@ -0,0 +1,202 @@ +--- +title: "Standard Assertions (@std/assert)" +description: "Common assertion functions, especially useful for testing" +jsr: jsr:@std/assert +pkg: assert +version: 1.0.15 +generated: true +stability: stable +--- + + + +## Overview + +

A library of assertion functions. +If the assertion is false an AssertionError will be thrown which will +result in pretty-printed diff of the failing assertion.

+

This module is browser compatible, but do not rely on good formatting of +values for AssertionError messages in browsers.

+ +```js +import { assert } from "@std/assert"; + +assert("I am truthy"); // Doesn't throw +assert(false); // Throws `AssertionError` +``` + +### Add to your project + +```sh +deno add jsr:@std/assert +``` + +See all +symbols in @std/assert on + + + + +## What is an assertion? + +An assertion is a check that must be true. If it isn’t, the program throws an +`AssertionError` with a helpful message and diff so you can quickly spot what +went wrong. + +In tests, assertions verify behavior. In application code, they can document and +guard invariants (preconditions/postconditions). In TypeScript, some assertions +(like `assert(condition)`) also narrow types after the check. + +## When to use @std/assert? + +The utilities in this package make test failures clear and actionable ( allowing +for pretty diffs and focused messages). Improve the readability of your tests by +codifying expectations in-line. + +Assertions help to prevent silent bugs by failing fast when assumptions are +violated. + +Use assertions liberally in your tests to verify behavior and catch regressions. + +## Examples + +```ts +import { + assert, + assertAlmostEquals, + assertArrayIncludes, + assertEquals, + assertExists, + assertFalse, + assertMatch, + assertNotEquals, + assertObjectMatch, + assertRejects, + assertStrictEquals, + assertThrows, +} from "@std/assert"; + +// Basic truthiness and type narrowing +const value: unknown = "hello"; +assert(typeof value === "string", "Expected a string"); +// value is now narrowed to string + +// Deep structural equality (objects/arrays) +assertEquals({ a: 1, b: [1, 2] }, { a: 1, b: [1, 2] }); +assertNotEquals([1, 2], [1, 2, 3]); + +// Strict (reference/identity) equality for primitives/refs +assertStrictEquals(1, 1); +assertFalse(false); +assertExists("non-empty"); // not null or undefined + +// Pattern & numeric comparisons +assertMatch("deno.land", /deno/); +assertAlmostEquals(0.1 + 0.2, 0.3, 1e-15); + +// Collections +assertArrayIncludes([1, 2, 3], [2, 3]); +assertObjectMatch( + { id: 42, name: "A", meta: { ok: true } }, + { name: "A", meta: { ok: true } }, // subset must match +); + +// Errors: sync vs async +assertThrows(() => JSON.parse("not json"), SyntaxError); +await assertRejects(() => fetch("https://deno.land/404")); +``` + +## Choosing the right equality + +Assertions for equality come in two main flavors: + +### `assertEquals` + +Compares values recursively by structure and content. For arrays, order matters; +for plain objects, key order doesn’t. It’s best for comparing serialized-style +data (objects, arrays, numbers, strings, booleans). + +### `assertStrictEquals` + +Checks that both operands are the exact same value (for primitives) or reference +(for objects), using semantics similar to `Object.is`. + +For example:
`assertStrictEquals({ x: 1 }, { x: 1 })` fails (different +references)
`assertEquals({ x: 1 }, { x: 1 })` passes
+`assertStrictEquals(NaN, NaN)` passes (like `Object.is`) + +### Examples + +```ts +// Deep vs strict +assertEquals({ a: 1 }, { a: 1 }); // ✅ same structure/content +// assertStrictEquals({ a: 1 }, { a: 1 }); // ❌ different references + +const obj = { a: 1 }; +assertStrictEquals(obj, obj); // ✅ same reference + +// Arrays: order matters for equality +assertEquals([1, 2, 3], [1, 2, 3]); // ✅ +// assertEquals([1, 2, 3], [3, 2, 1]); // ❌ different order + +// Numbers: floating point +// Prefer assertAlmostEquals for inexact math +// assertEquals(0.1 + 0.2, 0.3); // ❌ +assertAlmostEquals(0.1 + 0.2, 0.3, 1e-15); // ✅ +``` + +- Use `assertEquals` for comparing data shapes and values; use + `assertStrictEquals` when you care about reference identity or exact primitive + equality. +- For partial object checks, reach for `assertObjectMatch` instead of asserting + the entire object. +- When comparing large nested structures, `assertEquals` is comprehensive but + more expensive—prefer strict or targeted checks when performance matters in + hot test suites. + +## Writing good failure messages + +All assertions accept an optional message as the last argument. Write messages +to help developers understand where the failure occured and how to fix it. Keep +messages concise and user-focused: + +```ts +assert(Array.isArray(items), "items must be an array"); +assertEquals(result.status, 200, "API should return 200 OK"); +``` + +## Testing patterns + +Use with [`Deno.test`](/runtime/fundamentals/testing/): + +```ts +Deno.test("adds numbers", () => { + assertEquals(1 + 2, 3); +}); + +Deno.test("throws on invalid JSON", () => { + assertThrows(() => JSON.parse("nope"), SyntaxError); +}); + +Deno.test("rejects for failed fetch", async () => { + await assertRejects(() => fetch("https://deno.land/404")); +}); +``` + +## Tips + +- When doing floating point maths, use `assertAlmostEquals`, which has a + tolerance for numeric comparisons. +- For partial object checks, use `assertObjectMatch` instead of asserting the + entire shape. +- `assert(condition)` has an assertion signature in TS (`asserts condition`), + which narrows types after the check. +- Prefer `assertRejects` for promises and `assertThrows` for sync code, don’t + mix them. + +## See also + +- [`@std/expect`](/runtime/reference/std/expect/) offers a Jest-style BDD + assertion API if you prefer fluent matchers. + + diff --git a/runtime/reference/std/async.md b/runtime/reference/std/async.md new file mode 100644 index 000000000..3b23f1998 --- /dev/null +++ b/runtime/reference/std/async.md @@ -0,0 +1,114 @@ +--- +title: "@std/async" +description: "Utilities for asynchronous operations, like delays, debouncing, or pooling" +jsr: jsr:@std/async +pkg: async +version: 1.0.15 +generated: true +stability: stable +--- + + + +## Overview + +

Provide helpers with asynchronous tasks like delays, +debouncing, retrying, or +pooling.

+ +```js +import { delay } from "@std/async/delay"; + +await delay(100); // waits for 100 milliseconds +``` + +### Add to your project + +```sh +deno add jsr:@std/async +``` + +See all symbols +in @std/async on + + + + +## What is async? + +Asynchronous programming lets your program start work now and finish it later +without blocking the main thread. In JavaScript this typically means Promises, +`async`/`await`, timers, and async iterables. Async code improves responsiveness +and throughput by overlapping I/O (network, disk, timers) and controlling +concurrency. + +## Why use @std/async? + +This package gives you small, focused utilities that solve common async problems +so you don’t have to re‑implement them: + +- `delay` and `deadline` for scheduling and timeouts (with cancellation via + `AbortSignal`). +- `debounce` (and `throttle` in unstable) to control call frequency for UI/CLI + events. +- `retry` with backoff/jitter for flaky operations like HTTP requests. +- `pooledMap` to cap concurrency when transforming streams of work. +- `tee`/`MuxAsyncIterator` to branch or merge async iterables. + +These helpers are tiny, predictable, and work across Deno, Node.js, Bun, +Workers, and the browser. + +## Examples + +Debounce rapid events (e.g., typeahead): + +```ts +import { debounce } from "@std/async/debounce"; + +const search = debounce(async (q: string) => { + // fetch results after the user pauses typing +}, 200); + +// call many times; only the last call after 200ms runs +search("d"); +search("de"); +search("deno"); +``` + +Retry with exponential backoff and jitter: + +```ts +import { retry } from "@std/async/retry"; + +const data = await retry(() => + fetch("/api").then((r) => { + if (!r.ok) throw new Error("bad status"); + return r.json(); + }), { + maxAttempts: 5, + minTimeout: 100, + multiplier: 2, + jitter: 0.2, +}); +``` + +Limit concurrency with pooledMap: + +```ts +import { pooledMap } from "@std/async/pool"; + +const urls = ["/a", "/b", "/c", "/d"]; // many more in practice +for await (const res of pooledMap(3, urls, (u) => fetch(u))) { + // at most 3 fetches in flight; results arrive as they complete +} +``` + +Deadlines and cancellation: + +```ts +import { deadline } from "@std/async/deadline"; + +await deadline(fetch("/slow"), 1_000); // throws DOMException("TimeoutError") after 1s +``` + + diff --git a/runtime/reference/std/bytes.md b/runtime/reference/std/bytes.md new file mode 100644 index 000000000..d1f494e32 --- /dev/null +++ b/runtime/reference/std/bytes.md @@ -0,0 +1,78 @@ +--- +title: "@std/bytes" +description: "Utilities to manipulate Uint8Arrays that are not built-in to JavaScript" +jsr: jsr:@std/bytes +pkg: bytes +version: 1.0.6 +generated: true +stability: stable +--- + + + +## Overview + +

Helper functions for working with +Uint8Array +byte slices.

+ +```js +import { concat, endsWith, indexOfNeedle } from "@std/bytes"; +import { assertEquals } from "@std/assert"; + +const a = new Uint8Array([0, 1, 2]); +const b = new Uint8Array([3, 4, 5]); + +const c = concat([a, b]); + +assertEquals(c, new Uint8Array([0, 1, 2, 3, 4, 5])); + +assertEquals(indexOfNeedle(c, new Uint8Array([2, 3])), 2); + +assertEquals(endsWith(c, b), true); +``` + +### Add to your project + +```sh +deno add jsr:@std/bytes +``` + +See all symbols +in @std/bytes on + + + + +### What is a Uint8Array? + +`Uint8Array` is a typed array view over an `ArrayBuffer` that represents raw +bytes. Each element is an unsigned 8‑bit integer (0–255). Typed arrays are +fixed‑length, efficient, and ideal for working with binary data from files, +networks, crypto, images, WASM memory, and more. + +## When to use @std/bytes + +If you are working with raw binary data (`Uint8Array`), for example searching, +slicing, comparing or concatenating. This package provides helpful utility +functions that are not built-in to JavaScript. + +## Examples + +```ts +import { concat, equals, indexOfNeedle } from "@std/bytes"; + +const a = new Uint8Array([1, 2]); +const b = new Uint8Array([3, 4]); +const all = concat([a, b]); // Uint8Array [1,2,3,4] + +console.log(equals(all, new Uint8Array([1, 2, 3, 4]))); +console.log(indexOfNeedle(all, new Uint8Array([2, 3]))); // 1 +``` + +## Tips + +- Prefer these helpers over manual loops for clarity and correctness. +- Convert text ↔ bytes using `TextEncoder`/`TextDecoder`. + + diff --git a/runtime/reference/std/cache.md b/runtime/reference/std/cache.md new file mode 100644 index 000000000..a090e37ca --- /dev/null +++ b/runtime/reference/std/cache.md @@ -0,0 +1,103 @@ +--- +title: "@std/cache" +description: "Cache utilities" +jsr: jsr:@std/cache +pkg: cache +version: 0.2.0 +generated: true +stability: unstable +--- + + + +:::info Unstable + +This @std package is experimental and its API may change without a major version +bump. + +::: + +## Overview + +

In-memory cache utilities, such as memoization and caches with different +expiration policies.

+ +```js +import { memoize, LruCache, type MemoizationCacheResult } from "@std/cache"; +import { assertEquals } from "@std/assert"; + +const cache = new LruCache>(1000); + +// fibonacci function, which is very slow for n > ~30 if not memoized +const fib = memoize((n: bigint): bigint => { + return n <= 2n ? 1n : fib(n - 1n) + fib(n - 2n); +}, { cache }); + +assertEquals(fib(100n), 354224848179261915075n); +``` + +### Add to your project + +```sh +deno add jsr:@std/cache +``` + +See all symbols +in @std/cache on + + + + +## What is caching? + +Caching stores recently used or expensive-to-compute data in memory so you can +reuse it faster next time instead of recomputing or refetching. It is helpful +when calculations are slow, network calls are frequent, or you access the same +data repeatedly. + +Memoization is caching for function results: given the same inputs, return the +previously computed output. It is great for pure functions (no side effects) +where the result depends only on the inputs. + +## Why use @std/cache? + +The package provides a ready-to-use `memoize()` helper and common cache types so +you don’t rebuild them yourself. + +The package works across Deno/Node/Bun/Workers and keeps APIs small and +predictable. + +### LRU + +LRU (Least Recently Used) evicts the entry you haven’t used for the longest +time. Use it when “recent things are likely needed again.” Good for hot working +sets. + +### TTL + +TTL (Time To Live) evicts entries after a fixed duration, regardless of access. +Use it when data becomes stale quickly (e.g., config from a service, short-lived +tokens). + +- Choose eviction by workload: LRU for temporal locality, TTL for freshness, + size-based when memory-bound. +- Memoization caches must consider argument identity—objects/functions need + stable keys (e.g., serialize or use WeakMap when appropriate). +- Beware of unbounded growth; set sensible limits and measure hit ratios to tune + capacity. +- Handle errors/timeouts explicitly—cache only successful results unless + failures should be sticky. + +## Examples + +```ts +import { LruCache, memoize } from "@std/cache"; + +const cache = new LruCache(500); +const fib = memoize( + (n: number): number => n <= 1 ? n : fib(n - 1) + fib(n - 2), + { cache }, +); +``` + + diff --git a/runtime/reference/std/cbor.md b/runtime/reference/std/cbor.md new file mode 100644 index 000000000..7a3bb304e --- /dev/null +++ b/runtime/reference/std/cbor.md @@ -0,0 +1,174 @@ +--- +title: "@std/cbor" +description: "Utilities for parsing and serializing Concise Binary Object Representation (CBOR)" +jsr: jsr:@std/cbor +pkg: cbor +version: 0.1.8 +generated: true +stability: unstable +--- + + + +:::info Unstable + +This @std package is experimental and its API may change without a major version +bump. + +::: + +## Overview + +

+Overview

+

Concise Binary Object Representation (CBOR) is a binary data serialisation +format optimised for compactness and efficiency. It is designed to encode a +wide range of data types, including integers, strings, arrays, and maps, in a +space-efficient manner. +RFC 8949 - Concise Binary Object Representation (CBOR) +spec.

+

+Limitations

+
    +
  • This implementation only supports the encoding and decoding of +"Text String" keys.
  • +
  • This implementation encodes decimal numbers with 64 bits. It takes no +effort to figure out if the decimal can be encoded with 32 or 16 bits.
  • +
  • When decoding, integers with a value below 2 ** 32 will be of type +number, with all larger integers being of type bigint.
  • +
+

Functions and classes may have more specific limitations listed.

+ +```js +import { assert, assertEquals } from "@std/assert"; +import { decodeCbor, encodeCbor } from "@std/cbor"; + +const rawMessage = "I am a raw Message!"; + +const encodedMessage = encodeCbor(rawMessage); +const decodedMessage = decodeCbor(encodedMessage); + +assert(typeof decodedMessage === "string"); +assertEquals(decodedMessage, rawMessage); +``` + +### Add to your project + +```sh +deno add jsr:@std/cbor +``` + +See all symbols +in @std/cbor on + + + + +## What is CBOR? + +CBOR (Concise Binary Object Representation) is like a binary version of JSON. It +stores data in a compact binary format instead of text, which reduces size and +speeds up parsing. + +It supports all the common types (numbers, strings, booleans, null, arrays, +maps) plus binary data and big integers. CBOR is typically used for sending data +over the network (ideal for IoT or mobile devices where there is limited +bandwidth), storing compact payloads, and interop between languages. + +## Why use @std/cbor? + +This package provides simple functions to encode JavaScript objects to CBOR +binary and decode CBOR binary back to JavaScript objects. + +## Examples + +```ts +import { decodeCbor, encodeCbor } from "@std/cbor"; + +const obj = { t: "temp", v: 21.5, ts: Date.now() }; +const bin = encodeCbor(obj); +const back = decodeCbor(bin); +``` + +### Binary data (Uint8Array) + +```ts +import { decodeCbor, encodeCbor } from "@std/cbor"; + +const bytes = new TextEncoder().encode("hello"); +const encoded = encodeCbor(bytes); +const decoded = decodeCbor(encoded); + +if (!(decoded instanceof Uint8Array)) throw new Error("expected bytes"); +console.log(new TextDecoder().decode(decoded)); // "hello" +``` + +### Big integers behavior + +Integers larger than 2**32 decode as bigint: + +```ts +import { decodeCbor, encodeCbor } from "@std/cbor"; + +const bigNumber = 5_000_000_000; // > 2**32 +const bigBytes = encodeCbor(bigNumber); +const bigValue = decodeCbor(bigBytes); + +console.log(typeof bigValue); // "bigint" +console.log(bigValue === 5_000_000_000n); // true + +const smallValue = decodeCbor(encodeCbor(42)); +console.log(typeof smallValue); // "number" +``` + +### Sequences (multiple values) + +```ts +import { decodeCborSequence, encodeCborSequence } from "@std/cbor"; + +const packet = encodeCborSequence([{ id: 1 }, { id: 2 }, "done" as const]); +const values = decodeCborSequence(packet); +// values: [{ id: 1 }, { id: 2 }, "done"] +``` + +### Tagged values (dates) + +Use CBOR Tag 1 for epoch-based time (seconds since Unix epoch). How you +interpret tags on decode is up to your app. + +```ts +import { decodeCbor, encodeCbor } from "@std/cbor"; +import { CborTag } from "@std/cbor/tag"; + +const nowSeconds = Math.floor(Date.now() / 1000); +const tagged = new CborTag(1, nowSeconds); +const buf = encodeCbor(tagged); + +const out = decodeCbor(buf) as CborTag; +console.log(out.tagNumber); // 1 +console.log(out.tagContent); // epoch seconds +``` + +### Decode guard pattern + +When consuming untrusted bytes, check shapes after decode. + +```ts +import { decodeCbor } from "@std/cbor"; + +function isRecord(x: unknown): x is Record { + return typeof x === "object" && x !== null && !Array.isArray(x); +} + +const bytesFromNetwork = new Uint8Array(/* ... */); +const value = decodeCbor(bytesFromNetwork); + +if (!isRecord(value) || typeof value.type !== "string") { + throw new Error("Unexpected payload"); +} + +// safe to use +console.log(value.type); +``` + + diff --git a/runtime/reference/std/cli.md b/runtime/reference/std/cli.md new file mode 100644 index 000000000..ce24cca02 --- /dev/null +++ b/runtime/reference/std/cli.md @@ -0,0 +1,171 @@ +--- +title: "@std/cli" +description: "Tools for creating interactive command line tools" +jsr: jsr:@std/cli +pkg: cli +version: 1.0.23 +generated: true +stability: stable +--- + + + +## Overview + +

Tools for creating interactive command line tools.

+ +```js +import { parseArgs } from "@std/cli/parse-args"; +import { assertEquals } from "@std/assert"; + +// Same as running `deno run example.ts --foo --bar=baz ./quux.txt` +const args = parseArgs(["--foo", "--bar=baz", "./quux.txt"]); +assertEquals(args, { foo: true, bar: "baz", _: ["./quux.txt"] }); +``` + +### Add to your project + +```sh +deno add jsr:@std/cli +``` + +See all symbols +in @std/cli on + + + + +## Why use @std/cli? + +This package helps you build command‑line tools with great developer experience. +It focuses on the essentials: + +- Parsing flags and arguments (`parseArgs`) without heavy frameworks +- Prompting for sensitive input (`promptSecret`) +- Measuring display width reliably (`unicodeWidth`) for clean TTY output +- Unstable extras to enhance UX: spinners, progress bars, ANSI cursor control, + and interactive selects + +Use it when you want a lightweight, composable toolkit for CLI utilities. For +more complex CLIs with subcommands, rich help, and config systems, you can still +start with `parseArgs` and layer in your own structure. + +## Examples + +```ts +import { parseArgs } from "@std/cli/parse-args"; +import { promptSecret } from "@std/cli/prompt-secret"; + +const args = parseArgs(Deno.args, { + alias: { v: "verbose" }, + boolean: ["verbose"], + string: ["out"], +}); + +if (args.verbose) console.log("Verbose mode on"); +const token = await promptSecret("Enter API token: "); +console.log(`Writing to: ${args.out ?? "stdout"}`); +``` + +- `parseArgs` is lightweight and unopinionated—great for simple tools; for + complex CLIs consider subcommands and help text patterns. +- Booleans default to false unless present; use `--no-flag` support if needed + via `booleanNegation` options. +- Use `stopEarly` to treat `--` as end of options and pass-through remaining + args. + +### parseArgs: aliases, defaults, collect, negatable, unknown, and -- + +```ts +import { parseArgs } from "@std/cli/parse-args"; + +const argv = [ + "-v", + "--out=dist/file.txt", + "--tag", + "alpha", + "--tag", + "beta", + "--no-cache", + "--", + "--literally-a-file-flag", +]; + +const args = parseArgs(argv, { + alias: { v: "verbose" }, + boolean: ["verbose", "cache"], + string: ["out"], + default: { out: "stdout" }, + collect: ["tag"], + negatable: ["cache"], + unknown: (flag) => { + if (flag.startsWith("--") && flag !== "--") { + console.warn(`Unknown flag: ${flag}`); + return false; // drop it from parsed output + } + return true; + }, + "--": true, +}); + +// args.tag -> ["alpha", "beta"] +// args.cache -> false (because of --no-cache) +// args.verbose -> true (because of -v) +// args.out -> "dist/file.txt" +// args["--"] -> ["--literally-a-file-flag"] (pass-through) +``` + +### promptSecret: masking and clearing + +```ts +import { promptSecret } from "@std/cli/prompt-secret"; + +const token = await promptSecret("Enter token: ", { mask: "*" }); +// Optionally clear the prompt line after entry +await promptSecret("Press Enter to continue", { mask: "", clear: true }); +``` + +### unicodeWidth: simple column alignment + +```ts +import { unicodeWidth } from "@std/cli/unicode-width"; + +const rows = [ + ["Name", "Width"], + ["hello", String(unicodeWidth("hello"))], + ["你好", String(unicodeWidth("你好"))], + ["🐙octo", String(unicodeWidth("🐙octo"))], +]; + +const col1Width = Math.max(...rows.map((r) => unicodeWidth(r[0]))); +for (const [a, b] of rows) { + const pad = " ".repeat(col1Width - unicodeWidth(a)); + console.log(`${a}${pad} ${b}`); +} +``` + +### Unstable UI helpers: spinner and progress bar + +These APIs are marked unstable and may change. + +```ts +// Spinner +import { Spinner } from "@std/cli/unstable-spinner"; + +const spinner = new Spinner({ message: "Fetching data..." }); +spinner.start(); +await new Promise((r) => setTimeout(r, 800)); +spinner.stop(); + +// ProgressBar +import { ProgressBar } from "@std/cli/unstable-progress-bar"; + +const bar = new ProgressBar({ max: 5 }); +for (let i = 0; i < 5; i++) { + await new Promise((r) => setTimeout(r, 300)); + bar.value = i + 1; +} +bar.stop(); +``` + + diff --git a/runtime/reference/std/collections.md b/runtime/reference/std/collections.md new file mode 100644 index 000000000..525512f28 --- /dev/null +++ b/runtime/reference/std/collections.md @@ -0,0 +1,157 @@ +--- +title: "@std/collections" +description: "Pure functions for common tasks related to collection types like arrays and objects" +jsr: jsr:@std/collections +pkg: collections +version: 1.1.3 +generated: true +stability: stable +--- + + + +## Overview + +

Pure functions for common tasks around collection types like arrays and +objects.

+

Inspired by +Kotlin's Collections +package and Lodash.

+ +```js +import { intersect, pick, sample } from "@std/collections"; +import { assertArrayIncludes, assertEquals } from "@std/assert"; + +const lisaInterests = ["Cooking", "Music", "Hiking"]; +const kimInterests = ["Music", "Tennis", "Cooking"]; + +assertEquals(intersect(lisaInterests, kimInterests), ["Cooking", "Music"]); + +assertArrayIncludes(lisaInterests, [sample(lisaInterests)]); + +const cat = { name: "Lulu", age: 3, breed: "Ragdoll" }; + +assertEquals(pick(cat, ["name", "breed"]), { name: "Lulu", breed: "Ragdoll" }); +``` + +### Add to your project + +```sh +deno add jsr:@std/collections +``` + +See all +symbols in @std/collections on + + + + +## What are collection types? + +Collection types are data structures that hold multiple values, such as arrays +and objects. They allow you to group related data together and perform +operations on them, like filtering, transforming, and aggregating. + +This package provides small, focused functions to work with these types, +allowing you to compose complex operations from simple building blocks. + +## Why use @std/collections? + +The collections package provides small, pure helpers (intersect, pick, groupBy, +partition) to use instead of pulling a large utility library. + +## Examples + +### Distinct and distinctBy + +```ts +import { distinct, distinctBy } from "@std/collections"; + +const tags = ["a", "b", "a", "c"]; +console.log(distinct(tags)); // ["a", "b", "c"] + +const people = [ + { id: 1, name: "Alice" }, + { id: 1, name: "Alice v2" }, + { id: 2, name: "Bob" }, +]; +console.log(distinctBy(people, (p) => p.id)); +// [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }] +``` + +### Map records: mapValues, mapKeys + +```ts +import { mapKeys, mapValues } from "@std/collections"; + +const rec = { a: 1, b: 2 }; +console.log(mapValues(rec, (v) => v * 2)); // { a: 2, b: 4 } +console.log(mapKeys(rec, (k) => k.toUpperCase())); // { A: 1, B: 2 } +``` + +### Deep merge nested objects + +```ts +import { deepMerge } from "@std/collections/deep-merge"; + +const a = { cfg: { retries: 2, mode: "fast" } }; +const b = { cfg: { retries: 3 } }; +console.log(deepMerge(a, b)); +// { cfg: { retries: 3, mode: "fast" } } +``` + +### Sliding windows (with options) + +```ts +import { slidingWindows } from "@std/collections"; + +console.log(slidingWindows([1, 2, 3, 4], 3)); +// [[1,2,3],[2,3,4]] + +console.log(slidingWindows([1, 2, 3, 4, 5], 3, { step: 2, partial: true })); +// [[1,2,3],[3,4,5],[5]] +``` + +### Sort by derived keys + +```ts +import { sortBy } from "@std/collections"; + +const items = [{ v: 2 }, { v: 5 }, { v: 1 }]; +console.log(sortBy(items, (i) => i.v)); +// [{ v: 1 }, { v: 2 }, { v: 5 }] +console.log(sortBy(items, (i) => i.v, { order: "desc" })); +// [{ v: 5 }, { v: 2 }, { v: 1 }] +``` + +### Partition entries of an object + +```ts +import { partitionEntries } from "@std/collections"; + +const user = { id: 1, name: "Sam", active: true, score: 42 }; +const [numbers, rest] = partitionEntries( + user, + ([, v]) => typeof v === "number", +); +// numbers: { id: 1, score: 42 } +// rest: { name: "Sam", active: true } +``` + +### Produce joined strings + +```ts +import { joinToString } from "@std/collections"; + +console.log( + joinToString([1, 2, 3], { prefix: "[", separator: ", ", suffix: "]" }), +); +// "[1, 2, 3]" +``` + +## Tips + +- Functions are pure and data-first; they don’t mutate your inputs. +- Prefer these primitives to keep dependencies light and code clear. + + diff --git a/runtime/reference/std/crypto.md b/runtime/reference/std/crypto.md new file mode 100644 index 000000000..f98f2c9be --- /dev/null +++ b/runtime/reference/std/crypto.md @@ -0,0 +1,169 @@ +--- +title: "@std/crypto" +description: "Extensions to the Web Crypto API" +jsr: jsr:@std/crypto +pkg: crypto +version: 1.0.5 +generated: true +stability: stable +--- + + + +## Overview + +

Extensions to the +Web Crypto +supporting additional encryption APIs, but also delegating to the built-in +APIs when possible.

+ +```js +import { crypto } from "@std/crypto/crypto"; + +const message = "Hello, Deno!"; +const encoder = new TextEncoder(); +const data = encoder.encode(message); + +await crypto.subtle.digest("BLAKE3", data); +``` + +### Add to your project + +```sh +deno add jsr:@std/crypto +``` + +See all +symbols in @std/crypto on + + + + +## What is web crypto? + +The Web Crypto API is a standard set of low-level cryptographic primitives +available in web browsers and other environments like Deno. It provides secure +methods for hashing, encryption, decryption, signing, and verifying data, useful +when you need to protect sensitive information. + +## Why use @std/crypto? + +This package provides Web Crypto–compatible helpers and algorithms (like +[BLAKE3](https://github.com/BLAKE3-team/BLAKE3/)) with a familiar API. Use it +in: + +- API clients and SDKs: sign/verify payloads, compute request checksums, or + derive cache validators (ETag‑like) with BLAKE3. +- CLI tools and build systems: fingerprint files and directories for caching, + artifact integrity, or change detection. +- Edge/serverless apps: verify webhooks and JWT parts, hash bodies before + storage, or compare secrets in constant time. +- Data pipelines: de‑duplicate blobs via fast hashing; generate stable IDs from + content. + +## Examples + +### Hashing + +```ts +import { crypto } from "@std/crypto/crypto"; + +const data = new TextEncoder().encode("hello"); +const hash = await crypto.subtle.digest("BLAKE3", data); +console.log(new Uint8Array(hash)); +``` + +### Hash to hex + +```ts +import { crypto } from "@std/crypto/crypto"; + +const toHex = (bytes: Uint8Array) => + Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join(""); + +const data = new TextEncoder().encode("hello"); +const buf = await crypto.subtle.digest("BLAKE3", data); +console.log(toHex(new Uint8Array(buf))); // e.g. "ea..." +``` + +### Hash a file (BLAKE3) + +```ts +import { crypto } from "@std/crypto/crypto"; + +const file = await Deno.readFile("./README.md"); +const buf = await crypto.subtle.digest("BLAKE3", file); +console.log(new Uint8Array(buf)); +``` + +### Constant‑time compare + +```ts +import { crypto } from "@std/crypto/crypto"; +import { timingSafeEqual } from "@std/crypto/timing-safe-equal"; + +const enc = new TextEncoder(); +const a = new Uint8Array( + await crypto.subtle.digest("BLAKE3", enc.encode("abc")), +); +const b = new Uint8Array( + await crypto.subtle.digest("BLAKE3", enc.encode("abd")), +); + +console.log(timingSafeEqual(a, b)); // false +``` + +### Synchronous hashing (scripts) + +```ts +import { crypto } from "@std/crypto/crypto"; + +const data = new TextEncoder().encode("fast"); +const buf = crypto.subtle.digestSync("BLAKE3", data); +console.log(new Uint8Array(buf)); +``` + +### Random bytes + +```ts +import { crypto } from "@std/crypto/crypto"; + +const iv = new Uint8Array(12); +crypto.getRandomValues(iv); +console.log(iv); +``` + +### AES‑GCM encrypt/decrypt (Web Crypto) + +```ts +import { crypto } from "@std/crypto/crypto"; + +const key = await crypto.subtle.generateKey( + { name: "AES-GCM", length: 256 }, + true, + ["encrypt", "decrypt"], +); + +const iv = crypto.getRandomValues(new Uint8Array(12)); +const data = new TextEncoder().encode("secret message"); + +const ciphertext = await crypto.subtle.encrypt( + { name: "AES-GCM", iv }, + key, + data, +); +const plaintext = await crypto.subtle.decrypt( + { name: "AES-GCM", iv }, + key, + ciphertext, +); + +console.log(new TextDecoder().decode(new Uint8Array(plaintext))); // "secret message" +``` + +## Tips + +- Prefer Web Crypto primitives; avoid rolling your own crypto. +- Encode inputs with `TextEncoder` and compare results as bytes or hex. + + diff --git a/runtime/reference/std/csv.md b/runtime/reference/std/csv.md new file mode 100644 index 000000000..624c5aac8 --- /dev/null +++ b/runtime/reference/std/csv.md @@ -0,0 +1,245 @@ +--- +title: "@std/csv" +description: "Reading and writing of comma-separated values (CSV) files" +jsr: jsr:@std/csv +pkg: csv +version: 1.0.6 +generated: true +stability: stable +--- + + + +## Overview + +

Reads and writes comma-separated values (CSV) files.

+

+Parsing CSV

+ +```js +import { parse } from "@std/csv/parse"; +import { assertEquals } from "@std/assert"; + +const string = "a,b,c\nd,e,f"; + +// Parse as array of arrays (default) +assertEquals(parse(string, { skipFirstRow: false }), [["a", "b", "c"], [ + "d", + "e", + "f", +]]); + +// Parse csv file with headers into array of objects +assertEquals(parse(string, { skipFirstRow: true }), [{ + a: "d", + b: "e", + c: "f", +}]); + +// Parse with custom column names +assertEquals(parse(string, { columns: ["x", "y", "z"] }), [ + { x: "a", y: "b", z: "c" }, + { x: "d", y: "e", z: "f" }, +]); + +// Parse tab-separated values +const tsvString = "name\tage\tcity\njohn\t30\tnew york\nmary\t25\tlos angeles"; +assertEquals(parse(tsvString, { separator: "\t", skipFirstRow: true }), [ + { name: "john", age: "30", city: "new york" }, + { name: "mary", age: "25", city: "los angeles" }, +]); + +// Parse a CSV file which has comments +const csvWithComments = + "# This is a comment\nname,age,city\n# Another comment\njohn,30,new york\nmary,25,los angeles"; +assertEquals(parse(csvWithComments, { comment: "#", skipFirstRow: true }), [ + { name: "john", age: "30", city: "new york" }, + { name: "mary", age: "25", city: "los angeles" }, +]); +``` + +

+Parsing CSV from a Stream

+ +```js +import { CsvParseStream } from "@std/csv/parse-stream"; +import { assertEquals } from "@std/assert"; + +// Parse from a stream (useful for large files) +const source = ReadableStream.from([ + "name,age,city\n", + "john,30,new york\n", + "mary,25,los angeles\n", +]); + +const csvStream = source + .pipeThrough(new CsvParseStream({ skipFirstRow: true })); + +const records = await Array.fromAsync(csvStream); +assertEquals(records, [ + { name: "john", age: "30", city: "new york" }, + { name: "mary", age: "25", city: "los angeles" }, +]); + +// Or process records one by one +// for await (const record of csvStream) { +// console.log(record); +// } +``` + +

+Stringifying Data to CSV

+ +```js +import { stringify } from "@std/csv/stringify"; +import { assertEquals } from "@std/assert"; + +// Convert array of arrays to CSV +const arrayData = [["name", "age", "city"], ["john", "30", "new york"], [ + "mary", + "25", + "los angeles", +]]; +const csvString = stringify(arrayData); +assertEquals( + csvString, + "name,age,city\r\njohn,30,new york\r\nmary,25,los angeles\r\n", +); + +// Convert array of objects to CSV +const objectData = [ + { name: "john", age: "30", city: "new york" }, + { name: "mary", age: "25", city: "los angeles" }, +]; + +// When using an array of objects, you must specify columns to use +const customColumns = stringify(objectData, { + columns: ["city", "name", "age"], +}); +assertEquals( + customColumns, + "city,name,age\r\nnew york,john,30\r\nlos angeles,mary,25\r\n", +); +``` + +

+Streaming Stringify Data to CSV

+ +```js +import { CsvStringifyStream } from "@std/csv/stringify-stream"; +import { assertEquals } from "@std/assert"; + +async function writeCsvToTempFile(): Promise { + const path = await Deno.makeTempFile(); + using file = await Deno.open(path, { write: true }); + + const readable = ReadableStream.from([ + { id: 1, name: "one" }, + { id: 2, name: "two" }, + { id: 3, name: "three" }, + ]); + + await readable + .pipeThrough(new CsvStringifyStream({ columns: ["id", "name"] })) + .pipeThrough(new TextEncoderStream()) + .pipeTo(file.writable); + + return path; +} + +const path = await writeCsvToTempFile(); +const content = await Deno.readTextFile(path); +assertEquals(content, "id,name\r\n1,one\r\n2,two\r\n3,three\r\n"); +``` + +

+CSV Format Information

+

There are many kinds of CSV files; this module supports the format described +in RFC 4180.

+

A csv file contains zero or more records of one or more fields per record. +Each record is separated by the newline character. The final record may +optionally be followed by a newline character.

+ +```js +field1, field2, field3; +``` + +

White space is considered part of a field.

+

Carriage returns before newline characters are silently removed.

+

Blank lines are ignored. A line with only whitespace characters (excluding +the ending newline character) is not considered a blank line.

+

Fields which start and stop with the quote character " are called +quoted-fields. The beginning and ending quote are not part of the field.

+

The source:

+ +```js +normal string,"quoted-field" +``` + +

results in the fields

+ +```js +[`normal string`, `quoted-field`]; +``` + +

Within a quoted-field a quote character followed by a second quote character is considered a single quote.

+ +```js +"the ""word"" is true","a ""quoted-field""" +``` + +

results in

+ +```js +[`the "word" is true`, `a "quoted-field"`]; +``` + +

Newlines and commas may be included in a quoted-field

+ +```js +"Multi-line +field","comma is ," +``` + +

results in

+ +```js +[ + `Multi-line +field`, + `comma is ,`, +]; +``` + +### Add to your project + +```sh +deno add jsr:@std/csv +``` + +See all symbols +in @std/csv on + + + + +## What is a CSV? + +CSV (Comma-Separated Values) is a simple text format for storing tabular data, +where each line represents a row and each value within the row is separated by a +comma. It’s widely used for data exchange between applications, especially +spreadsheets and databases. + +## When to use @std/csv + +This package is great for reading and writing CSV files in your applications. It +supports parsing CSV into arrays or objects, stringifying data back to CSV, and +streaming for large files. + +## Tips + +- Use `skipFirstRow: true` to treat the first row as headers. +- For objects, specify `columns` when stringifying. +- Prefer streaming parsers for multi-GB datasets. + + diff --git a/runtime/reference/std/data-structures.md b/runtime/reference/std/data-structures.md new file mode 100644 index 000000000..71516d99d --- /dev/null +++ b/runtime/reference/std/data-structures.md @@ -0,0 +1,110 @@ +--- +title: "@std/data-structures" +description: "Common data structures like red-black trees and binary heaps" +jsr: jsr:@std/data-structures +pkg: data-structures +version: 1.0.9 +generated: true +stability: stable +--- + + + +## Overview + +

Data structures for use in algorithms and other data manipulation.

+ +```js +import { BinarySearchTree } from "@std/data-structures"; +import { assertEquals } from "@std/assert"; + +const values = [3, 10, 13, 4, 6, 7, 1, 14]; +const tree = new BinarySearchTree(); +values.forEach((value) => tree.insert(value)); + +assertEquals([...tree], [1, 3, 4, 6, 7, 10, 13, 14]); +assertEquals(tree.min(), 1); +assertEquals(tree.max(), 14); +assertEquals(tree.find(42), null); +assertEquals(tree.find(7), 7); +assertEquals(tree.remove(42), false); +assertEquals(tree.remove(7), true); +assertEquals([...tree], [1, 3, 4, 6, 10, 13, 14]); +``` + +### Add to your project + +```sh +deno add jsr:@std/data-structures +``` + +See +all symbols in @std/data-structures on + + + + +## What “data structures” means here + +In this package, “data structures” are purpose-built containers with clear +invariants and predictable performance characteristics that go beyond +JavaScript’s built-ins (Array, Map, Set). They provide capabilities like +priority ordering (heaps), ordered search and iteration (trees), reversible +lookups (bidirectional maps), and fixed-shape storage (2D arrays). + +- Most structures implement `Iterable`, so you can spread or `for..of` them. +- Many accept a comparator (for example, `ascend`/`descend`) to control order. + +### When to use what + +- BinaryHeap (priority queue): schedule work, pick top-k items, + Dijkstra/Best‑First search. Default is a max‑heap; supply a custom comparator + to change priority. +- RedBlackTree (self‑balancing BST): maintain a sorted set of values with fast + min/max and in‑order iteration even under adversarial input. +- BinarySearchTree (unbalanced): simpler tree for mostly random inputs or + educational use; supports traversal orders and min/max. +- BidirectionalMap (unstable): two‑way lookups when both keys and values are + unique (for example, ID ↔ code). +- D2Array (unstable): fixed‑size 2D grid (boards, matrices) with O(1) access. + +### Examples + +```ts +import { BinaryHeap } from "@std/data-structures"; + +// Priority queue (max-heap by default) +const pq = BinaryHeap.from([5, 1, 3]); +pq.pop(); // 5 + +// Custom priority: shortest string first +const shortestFirst = new BinaryHeap((a, b) => b.length - a.length); +shortestFirst.push("bbb", "a", "cc"); +shortestFirst.pop(); // "a" +``` + +```ts +import { ascend, RedBlackTree } from "@std/data-structures"; + +const t = RedBlackTree.from([5, 1, 9], ascend); +[...t]; // [1, 5, 9] +t.min(); // 1 +t.max(); // 9 +``` + +```ts +// Unstable submodules +import { BidirectionalMap } from "@std/data-structures/unstable-bidirectional-map"; +import { D2Array } from "@std/data-structures/unstable-2d-array"; + +const bimap = new BidirectionalMap(); +bimap.set("alice", 1); +bimap.getReverse(1); // "alice" + +const grid = new D2Array(3, 2, 0); // width=3, height=2, initial=0 +grid.resize(4, 2); +grid.insert(1, 1, 42); +grid.get(1, 1); // 42 +``` + + diff --git a/runtime/reference/std/datetime.md b/runtime/reference/std/datetime.md new file mode 100644 index 000000000..6c5f50d76 --- /dev/null +++ b/runtime/reference/std/datetime.md @@ -0,0 +1,187 @@ +--- +title: "@std/datetime" +description: "Utilities for dealing with Date objects" +jsr: jsr:@std/datetime +pkg: datetime +version: 0.225.5 +generated: true +stability: unstable +--- + + + +:::info Unstable + +This @std package is experimental and its API may change without a major version +bump. + +::: + +## Overview + +

Utilities for dealing with Date objects.

+ +```js +import { + dayOfYear, + difference, + HOUR, + isLeap, + MINUTE, + SECOND, +} from "@std/datetime"; +import { assertEquals } from "@std/assert"; + +assertEquals(dayOfYear(new Date("2019-03-11T03:24:00")), 70); +assertEquals(isLeap(1970), false); + +const date0 = new Date("2018-05-14"); +const date1 = new Date("2020-05-13"); +assertEquals(difference(date0, date1).years, 1); + +assertEquals(HOUR / MINUTE, 60); +assertEquals(MINUTE / SECOND, 60); +``` + +### Add to your project + +```sh +deno add jsr:@std/datetime +``` + +See all +symbols in @std/datetime on + + + + +## What is datetime? + +In JavaScript, dates and times center around the built‑in `Date` object: + +- A `Date` stores a single point in time as milliseconds since the Unix epoch + (1970‑01‑01T00:00:00Z). Its internal value is always UTC. +- Rendering and many getters can be either local time (e.g., `getHours`) or UTC + (e.g., `getUTCHours`). Be explicit about which you need. +- Parsing with the `Date` constructor is locale/implementation‑dependent for + non‑ISO strings. Prefer ISO‑8601 (`YYYY‑MM‑DDTHH:mm:ssZ`) or a library/parser. + +The `@std/datetime` package builds on top of this to offer simple parsing, +formatting, and date arithmetic with explicit patterns and options. + +It aims to cover common needs without a large dependency and works across Deno, +Node.js, Bun, browsers, and Workers. + +## When to use @std/datetime + +If you are formatting and parsing dates/times and doing small calculations +without pulling larger libraries. Typical use cases: + +- Human‑readable timestamps for logs, filenames, or UI. +- Parsing user input safely with explicit formats instead of Date’s heuristics. +- Showing relative durations (e.g., “X days remaining”). +- Getting calendar fields like week of year or day number in year. +- Generating standards‑compliant strings (e.g., ISO‑8601) for APIs. + +## Examples + +```ts +import { + dayOfYear, + dayOfYearUtc, + difference, + format, + isLeap, + isUtcLeap, + parse, + weekOfYear, +} from "@std/datetime"; + +// Format with time zone +const nowTokyo = format( + new Date("2025-01-02T12:34:56Z"), + "yyyy-MM-dd HH:mm XXX", + { timeZone: "Asia/Tokyo" }, +); + +// Parse an explicit pattern (local time unless the pattern/offset specifies otherwise) +const parsed = parse("2025-01-02 09:30", "yyyy-MM-dd HH:mm"); +parsed instanceof Date; // true + +// Difference in specific units +const a = new Date("2024-01-01T00:00:00Z"); +const b = new Date("2025-06-01T00:00:00Z"); +difference(a, b, { units: ["years", "months", "days"] }); +// -> { years: 1, months: 5, days: 0 } + +// Week of year and day-of-year +weekOfYear(new Date("2025-01-05")); // ISO week number (1-53) +dayOfYear(new Date("2025-03-01")); // Local TZ +dayOfYearUtc(new Date(Date.UTC(2025, 2, 1))); // UTC + +// Leap year checks +isLeap(2024); // true in local rules +isUtcLeap(2024); // true (timezone-independent) +``` + +```ts +// Format in UTC vs a specific time zone +import { format } from "@std/datetime"; + +const d = new Date("2025-01-02T00:00:00Z"); +format(d, "yyyy-MM-dd HH:mm XXX", { timeZone: "UTC" }); // 2025-01-02 00:00 +00:00 +format(d, "yyyy-MM-dd HH:mm XXX", { timeZone: "Asia/Tokyo" }); // 2025-01-02 09:00 +09:00 +``` + +```ts +// Parse an ISO string with numeric offset +import { parse } from "@std/datetime"; + +const withOffset = parse( + "2025-01-02T09:30:00+09:00", + "yyyy-MM-dd'T'HH:mm:ssXXX", +); +withOffset.toISOString(); // 2025-01-02T00:30:00.000Z +``` + +```ts +// Add durations using provided constants +import { HOUR, MINUTE, SECOND } from "@std/datetime"; + +const start = new Date("2025-01-01T00:00:00Z"); +const plus90m = new Date(start.getTime() + 90 * MINUTE); +const plus1h5s = new Date(start.getTime() + HOUR + 5 * SECOND); +``` + +```ts +// Days until a deadline (countdown) +import { difference } from "@std/datetime"; + +const now = new Date("2025-01-01T00:00:00Z"); +const launch = new Date("2025-02-15T00:00:00Z"); +difference(now, launch, { units: ["days"] }); // { days: 45 } +``` + +```ts +// ISO week-of-year around year boundaries +import { weekOfYear } from "@std/datetime"; + +weekOfYear(new Date("2020-12-31")); // 53 +weekOfYear(new Date("2021-01-01")); // 53 (still the last ISO week of 2020) +weekOfYear(new Date("2021-01-04")); // 1 +``` + +```ts +// Leap-year checks with Date inputs +import { isLeap } from "@std/datetime"; + +isLeap(new Date("2000-01-01")); // true (divisible by 400) +isLeap(new Date("1900-01-01")); // false (century not divisible by 400) +``` + +## Tips + +- Be explicit about time zones in formats (e.g., include `XXX` offset tokens). +- Prefer ISO 8601 for interchange and storage. + + diff --git a/runtime/reference/std/dotenv.md b/runtime/reference/std/dotenv.md new file mode 100644 index 000000000..0818f6be3 --- /dev/null +++ b/runtime/reference/std/dotenv.md @@ -0,0 +1,106 @@ +--- +title: "@std/dotenv" +description: "Parsing and loading environment variables from a `.env` file" +jsr: jsr:@std/dotenv +pkg: dotenv +version: 0.225.5 +generated: true +stability: unstable +--- + + + +:::info Unstable + +This @std package is experimental and its API may change without a major version +bump. + +::: + +## Overview + +

Parses and loads environment variables from a .env file into the current +process, or stringify data into a .env file format.

+

Note: The key needs to match the pattern /^[a-zA-Z_][a-zA-Z0-9_]*$/.

+ +```js +// Automatically load environment variables from a `.env` file +import "@std/dotenv/load"; +``` + +```js +import { parse, stringify } from "@std/dotenv"; +import { assertEquals } from "@std/assert"; + +assertEquals(parse("GREETING=hello world"), { GREETING: "hello world" }); +assertEquals(stringify({ GREETING: "hello world" }), "GREETING='hello world'"); +``` + +### Add to your project + +```sh +deno add jsr:@std/dotenv +``` + +See all +symbols in @std/dotenv on + + + + +## What is dotenv? + +`dotenv` is a popular way to manage environment variables in development. It +loads key-value pairs from a `.env` file into `process.env`, making it easy to +configure your app without hardcoding values. + +## When to use @std/dotenv + +Use this package to load local configuration during development, for preview +builds, or in simple deployments where your platform doesn’t inject environment +variables for you, keeping secrets and config out of source code. + +## Examples + +```ts +// Auto-load from .env at process start +import "@std/dotenv/load"; + +// Or load manually +import { load } from "@std/dotenv"; + +const env = await load({ + envPath: ".env.local", // where to read variables from (default: .env) + defaultsPath: ".env.defaults", // optional defaults if a key is missing + examplePath: ".env.example", // assert required keys exist + export: true, // also export to the process environment + allowEmptyValues: true, // allow empty values in example/defaults + override: false, // do not overwrite existing env vars by default +}); + +// Values are available both from the returned object and (when export: true) +// via the runtime’s environment API (e.g., Deno.env) +console.log(env.DATABASE_URL); +// Deno.env.get("DATABASE_URL"); +``` + +```ts +// Parse and stringify +import { parse, stringify } from "@std/dotenv"; + +const text = ` +GREETING="hello world" # comment +PORT=8080 +`; + +parse(text); // { GREETING: "hello world", PORT: "8080" } + +stringify({ GREETING: "hello world" }); +// "GREETING='hello world'" +``` + +## Tips + +- Don’t commit secrets. Add `.env` to your project's `.gitignore` file. + + diff --git a/runtime/reference/std/encoding.md b/runtime/reference/std/encoding.md new file mode 100644 index 000000000..acbdad01c --- /dev/null +++ b/runtime/reference/std/encoding.md @@ -0,0 +1,211 @@ +--- +title: "@std/encoding" +description: "Utilities for encoding and decoding common formats like hex, base64, and varint" +jsr: jsr:@std/encoding +pkg: encoding +version: 1.0.10 +generated: true +stability: stable +--- + + + +## Overview + +

Utilities for encoding and decoding common formats like hex, base64, and varint.

+

+Basic Usage

+ +```js +import { decodeBase64, encodeBase64 } from "@std/encoding"; +import { assertEquals } from "@std/assert"; + +const foobar = new TextEncoder().encode("foobar"); +assertEquals(encodeBase64(foobar), "Zm9vYmFy"); +assertEquals(decodeBase64("Zm9vYmFy"), foobar); +``` + +

+Various Encoding Formats

+ +```js +import { + decodeAscii85, + decodeBase32, + decodeBase58, + decodeBase64, + decodeHex, + encodeAscii85, + encodeBase32, + encodeBase58, + encodeBase64, + encodeHex, +} from "@std/encoding"; +import { assertEquals } from "@std/assert"; + +// Many different encodings for different character sets +assertEquals(encodeHex("Hello world!"), "48656c6c6f20776f726c6421"); +assertEquals(encodeBase32("Hello world!"), "JBSWY3DPEB3W64TMMQQQ===="); +assertEquals(encodeBase58("Hello world!"), "2NEpo7TZRhna7vSvL"); +assertEquals(encodeBase64("Hello world!"), "SGVsbG8gd29ybGQh"); +assertEquals(encodeAscii85("Hello world!"), "87cURD]j7BEbo80"); + +// Decoding +assertEquals( + new TextDecoder().decode(decodeHex("48656c6c6f20776f726c6421")), + "Hello world!", +); +assertEquals( + new TextDecoder().decode(decodeBase32("JBSWY3DPEB3W64TMMQQQ====")), + "Hello world!", +); +assertEquals( + new TextDecoder().decode(decodeBase58("2NEpo7TZRhna7vSvL")), + "Hello world!", +); +assertEquals( + new TextDecoder().decode(decodeBase64("SGVsbG8gd29ybGQh")), + "Hello world!", +); +assertEquals( + new TextDecoder().decode(decodeAscii85("87cURD]j7BEbo80")), + "Hello world!", +); +``` + +

+URL-Safe Base64

+ +```js +import { encodeBase64, encodeBase64Url } from "@std/encoding"; +import { assertEquals } from "@std/assert"; + +assertEquals(encodeBase64("ice creams"), "aWNlIGNyZWFtcw=="); // Not url-safe because of `=` +assertEquals(encodeBase64Url("ice creams"), "aWNlIGNyZWFtcw"); // URL-safe! + +// Base64Url replaces + with - and / with _ +assertEquals(encodeBase64("subjects?"), "c3ViamVjdHM/"); // slash is not URL-safe +assertEquals(encodeBase64Url("subjects?"), "c3ViamVjdHM_"); // _ is URL-safe +``` + +

+Binary Data Encoding

+ +```js +import { encodeBase64, encodeHex } from "@std/encoding"; +import { assertEquals } from "@std/assert"; + +// Working with binary data +const binaryData = new Uint8Array([0xDE, 0xAD, 0xBE, 0xEF]); +assertEquals(encodeHex(binaryData), "deadbeef"); +assertEquals(encodeBase64(binaryData), "3q2+7w=="); +``` + +

+Varint Encoding

+

Learn more from the protobuf Varint encoding docs.

+ +```js +import { decodeVarint, encodeVarint } from "@std/encoding"; +import { assertEquals } from "@std/assert"; + +// Varint encoding support +assertEquals(encodeVarint(9601n), [new Uint8Array([129, 75]), 2]); + +// Decode a varint +const bytes = new Uint8Array([129, 75]); +assertEquals(decodeVarint(bytes), [9601n, 2]); +``` + +### Add to your project + +```sh +deno add jsr:@std/encoding +``` + +See all +symbols in @std/encoding on + + + + +## What is encoding? + +Encoding is the process of converting data from one format to another, often to +make it suitable for transmission or storage. Common encoding formats include +Base64, Hex, and Varint. + +## Why use @std/encoding? + +This package provides simple, reliable functions for encoding and decoding data +in various formats. You will use encoding for: + +- Interop: exchange binary data in human/transmissible forms (URLs, JSON, + command line, logs). +- Safety: decode helpers throw on malformed inputs (e.g., hex) rather than + silently truncating. +- Portability: single API surface across runtimes. +- Control: choose URL‑safe Base64 to avoid +, /, = in URLs. + +## Examples + +```ts +import { + decodeBase64Url, + decodeHex, + encodeBase64Url, + encodeHex, +} from "@std/encoding"; + +// Strings <-> bytes +const bytes = new TextEncoder().encode("hello"); +const text = new TextDecoder().decode(bytes); + +// URL-safe tokens +const token = encodeBase64Url(bytes); // aGVsbG8 +const roundtrip = new TextDecoder().decode(decodeBase64Url(token)); + +// Hex utilities +const hex = encodeHex(bytes); // 68656c6c6f +const fromHex = decodeHex(hex); +``` + +```ts +// Other supported encodings +import { + decodeAscii85, + decodeBase32, + decodeBase58, + decodeBase64, + encodeAscii85, + encodeBase32, + encodeBase58, + encodeBase64, +} from "@std/encoding"; + +encodeBase64("Hello world!"); // "SGVsbG8gd29ybGQh" +encodeBase32("Hello world!"); // "JBSWY3DPEB3W64TMMQQQ====" +encodeBase58("Hello world!"); // "2NEpo7TZRhna7vSvL" +encodeAscii85("Hello world!"); // "87cURD]j7BEbo80" + +new TextDecoder().decode(decodeBase64("SGVsbG8gd29ybGQh")); // "Hello world!" +``` + +```ts +// Varint (compact integer encoding) +import { decodeVarint, encodeVarint } from "@std/encoding"; + +const [buf, end] = encodeVarint(9601n); +const [num, next] = decodeVarint(buf); +``` + +## Tips + +- All encoders/decoders work with `Uint8Array`. Use `TextEncoder`/`TextDecoder` + for string ↔ bytes. +- Prefer Base64URL for tokens/query params; standard Base64 may include + characters that need escaping. +- Hex helpers return lowercase by default. +- Varint encodes integers compactly; it’s not for arbitrary binary payloads. + + diff --git a/runtime/reference/std/expect.md b/runtime/reference/std/expect.md new file mode 100644 index 000000000..afdba96bb --- /dev/null +++ b/runtime/reference/std/expect.md @@ -0,0 +1,179 @@ +--- +title: "@std/expect" +description: "Jest compatible `expect` assertion functions" +jsr: jsr:@std/expect +pkg: expect +version: 1.0.17 +generated: true +stability: stable +--- + + + +## Overview + +

This module provides Jest compatible expect assertion functionality.

+ +```js +import { expect } from "@std/expect"; + +const x = 6 * 7; +expect(x).toEqual(42); +expect(x).not.toEqual(0); + +await expect(Promise.resolve(x)).resolves.toEqual(42); +``` + +

Currently this module supports the following functions:

+ +

Only these functions are still not available:

+
    +
  • Matchers: +
      +
    • toMatchSnapshot
    • +
    • toMatchInlineSnapshot
    • +
    • toThrowErrorMatchingSnapshot
    • +
    • toThrowErrorMatchingInlineSnapshot
    • +
    +
  • +
+

The tracking issue to add support for unsupported parts of the API is +https://github.com/denoland/std/issues/3964.

+

This module is largely inspired by +x/expect module by +Allain Lalonde.

+ +### Add to your project + +```sh +deno add jsr:@std/expect +``` + +See all +symbols in @std/expect on + + + + +## What is expect? + +A Jest‑compatible fluent assertion API. Instead of standalone assert functions, +you write expectations like `expect(value).toBe(1)` and can chain modifiers like +`.not`, `.resolves`, and `.rejects`. + +## When to use @std/expect + +If you prefer a Jest-like API for fluent, readable assertions with rich +matchers, especially when migrating from Jest. + +## Examples + +```ts +import { expect } from "@std/expect"; + +expect({ a: 1, b: 2 }).toMatchObject({ a: 1 }); +await expect(Promise.resolve(42)).resolves.toBe(42); +expect([1, 2, 3]).toContain(2); + +// Throwing and async rejections +expect(() => JSON.parse("{")) + .toThrow(SyntaxError); +await expect(Promise.reject(new Error("boom"))) + .rejects.toThrow("boom"); + +// Close-to for floating point, regex matching +expect(0.1 + 0.2).toBeCloseTo(0.3, 15); +expect("hello world").toMatch(/world/); + +// Using asymmetric matchers +expect({ id: 1, name: "Ada" }) + .toEqual(expect.objectContaining({ name: expect.stringMatching(/^A/) })); +``` + +## Use with Deno.test + +```ts +import { expect } from "@std/expect"; +Deno.test("basic expect", () => { + const value = 2 + 2; + expect(value).toBe(4); +}); +``` + +For more information on testing in Deno, see the +[testing docs](/runtime/fundamentals/testing/). + +## Tips + +- Use `toEqual` for deep data comparisons and `toBe` for identity. +- Prefer `.resolves` / `.rejects` helpers for promises. +- Prefer `.resolves` / `.rejects` helpers for promises. +- Use `toStrictEqual` for stricter deep checks (no extra props, etc.). +- Extend with custom matchers via `expect.extend` when needed. + + diff --git a/runtime/reference/std/fmt.md b/runtime/reference/std/fmt.md new file mode 100644 index 000000000..ec66d2d42 --- /dev/null +++ b/runtime/reference/std/fmt.md @@ -0,0 +1,121 @@ +--- +title: "@std/fmt" +description: "Utilities for formatting values, such as adding colors to text, formatting durations, printf utils, formatting byte numbers." +jsr: jsr:@std/fmt +pkg: fmt +version: 1.0.8 +generated: true +stability: stable +--- + + + +## Overview + +

Provides utilities for formatting text of different types:

+ + +```js +import { format } from "@std/fmt/bytes"; +import { red } from "@std/fmt/colors"; + +console.log(red(format(1337))); // Prints "1.34 kB" +``` + +

+Runtime compatibility

+

bytes, +colors, and +duration supports all major runtimes. +printf is mostly compatible with major +runtimes, however some of features, such as %v, %i and %I format +specifiers, are only available in Deno. See the API docs for details.

+ +### Add to your project + +```sh +deno add jsr:@std/fmt +``` + +See all symbols +in @std/fmt on + + + + +## What is formatting? + +Formatting is the process of transforming data into a specific layout or style +for presentation. This can include adding colors, adjusting spacing, or +converting values into human-readable forms. + +## When to use @std/fmt + +If you need to present data in a user-friendly way, especially in command-line +applications. + +## Examples + +```ts +// Bytes: base‑10 (kB) vs binary (KiB), signed values, and locale +import { format as formatBytes } from "@std/fmt/bytes"; + +formatBytes(1337); // "1.34 kB" +formatBytes(1536, { binary: true }); // "1.50 KiB" +formatBytes(-4096, { signed: true }); // "-4.10 kB" +formatBytes(12_345_678, { locale: "de-DE" }); // e.g., "12,35 MB" +``` + +```ts +// Duration: compact display with optional zero suppression +import { format as formatDuration } from "@std/fmt/duration"; + +formatDuration(90_000); // e.g., "1m 30s" (exact style may vary) +formatDuration(3_600_000, { ignoreZero: true }); // e.g., "1h" +``` + +```ts +// printf/sprintf: Go‑style formatting +import { printf, sprintf } from "@std/fmt/printf"; + +printf("%-10s %08d 0x%X\n", "build#", 42, 3735928559); +const line = sprintf("%6.2f%% %s", 12.3456, "complete"); +// Note: some specifiers like %v/%i/%I are Deno‑only. +``` + +```ts +// Colors: compose styles; toggle and strip ANSI codes +import { + bold, + getColorEnabled, + green, + red, + setColorEnabled, + stripAnsiCode, +} from "@std/fmt/colors"; + +setColorEnabled(true); +const ok = bold(green("OK")); +const err = bold(red("ERROR")); +console.log(ok, err); + +// Remove ANSI when writing to logs +const plain = stripAnsiCode(ok); +``` + +## Tips + +- Use bytes options (`binary`, `bits`, `locale`, `minimumFractionDigits`, + `maximumFractionDigits`, `signed`) to match your UX. +- Prefer concise duration output for CLIs; suppress zeros with `ignoreZero`. +- Be conservative with colors for accessibility; strip ANSI when writing to + files or systems that don’t support it. +- Reach for printf/sprintf when you need exact widths, padding, or numeric + bases. + + diff --git a/runtime/reference/std/front-matter.md b/runtime/reference/std/front-matter.md new file mode 100644 index 000000000..9463f70dd --- /dev/null +++ b/runtime/reference/std/front-matter.md @@ -0,0 +1,202 @@ +--- +title: "@std/front-matter" +description: "Extract front matter from strings" +jsr: jsr:@std/front-matter +pkg: front-matter +version: 1.0.9 +generated: true +stability: stable +--- + + + +## Overview + +

Extracts +front matter +from strings. Adapted from +jxson/front-matter.

+

+Supported formats

+

+JSON

+ +```js +import { extractJson, test } from "@std/front-matter"; +import { assertEquals } from "@std/assert"; + +const str = '---json\n{"and": "this"}\n---\ndeno is awesome'; + +assertEquals(test(str), true); +assertEquals(extractJson(str), { + frontMatter: '{"and": "this"}', + body: "deno is awesome", + attrs: { and: "this" }, +}); +``` + +

extract and test support the following +delimiters.

+ +```js +---json +{ + "and": "this" +} +--- +``` + +```js +{ + "is": "JSON" +} +``` + +

+TOML

+ +```js +import { extractToml, test } from "@std/front-matter"; +import { assertEquals } from "@std/assert"; + +const str = "---toml\nmodule = 'front_matter'\n---\ndeno is awesome"; + +assertEquals(test(str), true); +assertEquals(extractToml(str), { + frontMatter: "module = 'front_matter'", + body: "deno is awesome", + attrs: { module: "front_matter" }, +}); +``` + +

extract and test support the following +delimiters.

+ +```js +---toml +this = 'is' +--- +``` + +```js += toml = +parsed = 'as' +toml = 'data' += toml = +``` + +```js ++++ +is = 'that' +not = 'cool?' ++++ +``` + +

+YAML

+ +```js +import { extractYaml, test } from "@std/front-matter"; +import { assertEquals } from "@std/assert"; + +const str = "---yaml\nmodule: front_matter\n---\ndeno is awesome"; + +assertEquals(test(str), true); +assertEquals(extractYaml(str), { + frontMatter: "module: front_matter", + body: "deno is awesome", + attrs: { module: "front_matter" }, +}); +``` + +

extract and test support the following +delimiters.

+ +```js +--- +these: are +--- +``` + +```js +---yaml +all: recognized +--- +``` + +```js += yaml = +as: yaml += yaml = +``` + +### Add to your project + +```sh +deno add jsr:@std/front-matter +``` + +See all +symbols in @std/front-matter on + + + + +## What is front matter? + +Front matter is metadata placed at the top of a file, typically used in Markdown +or other text files to provide information about the document. It is usually +enclosed within specific delimiters, such as `---` for YAML, `+++` for TOML, or +`---json` for JSON. The metadata can include details like the title, author, +date, tags, and other attributes that describe the content of the file. + +## Why use @std/front-matter? + +Use this package to easily parse and extract front matter from your content +files, allowing you to separate metadata from the main content. This is +especially useful in static site generators, blogging platforms, and content +management systems where front matter is commonly used to manage document +metadata. + +## Examples + +```ts +// Detect and extract YAML front matter +import { extractYaml, test } from "@std/front-matter"; + +const source = `---yaml\ntitle: Hello\nauthor: Ada\n---\nContent starts here.`; + +if (test(source)) { + const { attrs, body, frontMatter } = extractYaml(source); + // attrs: { title: "Hello", author: "Ada" } + // body: "Content starts here." + // frontMatter: "title: Hello\nauthor: Ada" +} +``` + +```ts +// JSON front matter +import { extractJson } from "@std/front-matter"; + +const jsonSource = `---json\n{ "tags": ["news", "deno"] }\n---\nPost body`; +const { attrs } = extractJson(jsonSource); +// attrs: { tags: ["news", "deno"] } +``` + +```ts +// TOML front matter +import { extractToml } from "@std/front-matter"; + +const tomlSource = `+++\ncategory = 'release'\n+++\nNotes...`; +const { attrs, body } = extractToml(tomlSource); +// attrs: { category: "release" } +// body: "Notes..." +``` + +## Tips + +- Supports JSON, TOML, and YAML delimiters—pick one and stick with it for + consistency. +- Returned `attrs` are already parsed for you; `body` is the remaining content. + + diff --git a/runtime/reference/std/fs.md b/runtime/reference/std/fs.md new file mode 100644 index 000000000..a7aaf201f --- /dev/null +++ b/runtime/reference/std/fs.md @@ -0,0 +1,71 @@ +--- +title: "@std/fs" +description: "Helpers for working with the file system" +jsr: jsr:@std/fs +pkg: fs +version: 1.0.19 +generated: true +stability: stable +--- + + + +## Overview + +

Helpers for working with the filesystem.

+ +```js +import { copy, ensureDir, ensureFile, move } from "@std/fs"; + +await ensureFile("example.txt"); + +await copy("example.txt", "example_copy.txt"); + +await ensureDir("subdir"); + +await move("example_copy.txt", "subdir/example_copy.txt"); +``` + +### Add to your project + +```sh +deno add jsr:@std/fs +``` + +See all symbols in +@std/fs on + + + + +## Why use @std/fs? + +Reach for it when you want higher-level filesystem operations (such as ensuring +files/dirs, copying, moving, walking directories) than the bare +[Deno APIs](/examples/#filesystem). + +## Examples + +```ts +import { ensureDir, expandGlob, walk } from "@std/fs"; + +await ensureDir("./out/assets"); + +for await (const entry of expandGlob("src/**/*.{ts,tsx}")) { + console.log(entry.path); +} + +for await ( + const f of walk("./content", { includeDirs: false, exts: [".md"] }) +) { + console.log(f.path); +} +``` + +## Tips + +- Most helpers are async, don’t forget the `await`! +- Combine with `@std/path` to build cross-platform paths. +- Use `copy` with `overwrite: true` explicitly when replacing files. + + diff --git a/runtime/reference/std/html.md b/runtime/reference/std/html.md new file mode 100644 index 000000000..d2615668b --- /dev/null +++ b/runtime/reference/std/html.md @@ -0,0 +1,64 @@ +--- +title: "@std/html" +description: "Functions for HTML, such as escaping or unescaping HTML entities" +jsr: jsr:@std/html +pkg: html +version: 1.0.5 +generated: true +stability: stable +--- + + + +## Overview + +

Functions for HTML tasks such as escaping or unescaping HTML entities.

+ +```js +import { unescape } from "@std/html/entities"; +import { assertEquals } from "@std/assert"; + +assertEquals(unescape("<>'&AA"), "<>'&AA"); +assertEquals(unescape("þð"), "þð"); +``` + +### Add to your project + +```sh +deno add jsr:@std/html +``` + +See all symbols +in @std/html on + + + + +## What is this package? + +A utility library for safely escaping and unescaping HTML entities to prevent +XSS vulnerabilities when inserting user-provided content into HTML. + +## Why use @std/html? + +Your application may need to display user-generated content within HTML. To +prevent cross-site scripting (XSS) attacks, it is crucial to escape special +characters like `<`, `>`, `&`, `"`, and `'` before embedding user input into +HTML. + +## Examples + +```ts +import { escape, unescape } from "@std/html/entities"; + +const safe = escape(``); // <img src=x onerror=alert(1)> +const back = unescape("&lt;b&gt;ok&lt;/b&gt;"); // ok +``` + +## Tips + +- Escaping and unescaping targets entities is not full HTML sanitization. Use a + sanitizer for removing tags/attributes. +- Escaping is idempotent when run once; avoid double-escaping (`&amp;`). + + diff --git a/runtime/reference/std/http.md b/runtime/reference/std/http.md new file mode 100644 index 000000000..d5b2eab24 --- /dev/null +++ b/runtime/reference/std/http.md @@ -0,0 +1,278 @@ +--- +title: "@std/http" +description: "Utilities for building HTTP servers" +jsr: jsr:@std/http +pkg: http +version: 1.0.21 +generated: true +stability: stable +--- + + + +## Overview + +

Provides user-friendly serve on top of Deno's native HTTP server +and other utilities for creating HTTP servers and clients.

+

+File Server

+

A small program for serving local files over HTTP.

+ +```js +deno run --allow-net --allow-read jsr:@std/http/file-server +Listening on: +- Local: http://localhost:8000 +``` + +

When the --allow-sys=networkInterfaces permission is provided, the file +server will also display the local area network addresses that can be used to +access the server.

+

+HTTP Status Code and Status Text

+

Helper for processing status code and status text.

+

+HTTP errors

+

Provides error classes for each HTTP error status code as well as utility +functions for handling HTTP errors in a structured way.

+

+Methods

+

Provides helper functions and types to work with HTTP method strings safely.

+

+Negotiation

+

A set of functions which can be used to negotiate content types, encodings and +languages when responding to requests.

+
+

Note: some libraries include accept charset functionality by analyzing the +Accept-Charset header. This is a legacy header that +clients omit and servers should ignore +therefore is not provided.

+
+

+User agent handling

+

The UserAgent class provides user agent string parsing, allowing +a user agent flag to be semantically understood.

+

For example to integrate the user agent provided in the header User-Agent +in an http request would look like this:

+ +```js +import { UserAgent } from "@std/http/user-agent"; + +Deno.serve((req) => { + const userAgent = new UserAgent(req.headers.get("user-agent") ?? ""); + return new Response(`Hello, ${userAgent.browser.name} + on ${userAgent.os.name} ${userAgent.os.version}!`); +}); +``` + +

+Routing

+

route provides an easy way to route requests to different +handlers based on the request path and method.

+ +```js +import { route, type Route } from "@std/http/unstable-route"; +import { serveDir } from "@std/http/file-server"; + +const routes: Route[] = [ + { + pattern: new URLPattern({ pathname: "/about" }), + handler: () => new Response("About page"), + }, + { + pattern: new URLPattern({ pathname: "/users/:id" }), + handler: (_req, _info, params) => new Response(params?.pathname.groups.id), + }, + { + pattern: new URLPattern({ pathname: "/static/*" }), + handler: (req: Request) => serveDir(req) + }, + { + method: ["GET", "HEAD"], + pattern: new URLPattern({ pathname: "/api" }), + handler: (req: Request) => new Response(req.method === 'HEAD' ? null : 'ok'), + }, +]; + +function defaultHandler(_req: Request) { + return new Response("Not found", { status: 404 }); +} + +Deno.serve(route(routes, defaultHandler)); +``` + +### Add to your project + +```sh +deno add jsr:@std/http +``` + +See all symbols +in @std/http on + + + + +## Why use @std/http? + +Great for small, fast HTTP servers and handlers using the Web Fetch API style. + +## Examples + +A minimal server + +```ts +import { serve } from "@std/http"; + +serve((_req) => new Response("Hello"), { port: 8000 }); +``` + +Conditional GET with ETag (304 Not Modified) + +```ts +import { serve } from "@std/http"; +import { eTag, ifNoneMatch } from "@std/http/etag"; + +const body = JSON.stringify({ message: "Hello, cached world" }); +const etag = eTag(body); + +serve((req) => { + const inm = req.headers.get("if-none-match"); + // ifNoneMatch returns false when the tag matches -> respond 304 + if (!ifNoneMatch(inm, etag)) { + return new Response(null, { status: 304, headers: { ETag: etag } }); + } + return new Response(body, { + headers: { "content-type": "application/json; charset=utf-8", ETag: etag }, + }); +}); +``` + +Content negotiation (HTML vs JSON) + +```ts +import { serve } from "@std/http"; +import { accepts } from "@std/http/negotiation"; + +serve((req) => { + const preferred = accepts(req) ?? ["*/*"]; + if (preferred.includes("application/json") || preferred.includes("*/*")) { + return Response.json({ ok: true }); + } + return new Response("

ok

", { + headers: { "content-type": "text/html; charset=utf-8" }, + }); +}); +``` + +Cookies: set, read, and delete + +```ts +import { serve } from "@std/http"; +import { deleteCookie, getCookies, setCookie } from "@std/http/cookie"; + +serve(async (req) => { + const url = new URL(req.url); + const headers = new Headers(); + + if (url.pathname === "/login" && req.method === "POST") { + // In practice, validate credentials first + setCookie(headers, { + name: "sid", + value: crypto.randomUUID(), + httpOnly: true, + secure: true, + sameSite: "Lax", + path: "/", + maxAge: 60 * 60, // 1 hour + }); + return new Response("ok", { headers }); + } + + if (url.pathname === "/me") { + const cookies = getCookies(req.headers); + const sid = cookies["sid"] ?? "(none)"; + return Response.json({ sid }); + } + + if (url.pathname === "/logout") { + deleteCookie(headers, "sid", { path: "/" }); + return new Response("bye", { headers }); + } + + return new Response("not found", { status: 404 }); +}); +``` + +Static files and CORS with `serveDir` + +```ts +import { serve } from "@std/http"; +import { serveDir } from "@std/http/file-server"; + +// Requires --allow-read for your public directory +serve((req) => + serveDir(req, { + fsRoot: "public", + showDirListing: true, + enableCors: true, // Adds basic Access-Control-* headers + urlRoot: "/static", + }) +); +``` + +Stream updates with Server-Sent Events (SSE) + +```ts +import { serve } from "@std/http"; +import { ServerSentEventStream } from "@std/http/server-sent-event-stream"; + +serve((_req) => { + const { readable, writable } = new TransformStream(); + const sse = new ServerSentEventStream(writable); + + let i = 0; + const timer = setInterval(() => { + sse.dispatchMessage({ + event: "tick", + id: String(i), + data: new Date().toISOString(), + }); + i++; + if (i === 5) { // stop after 5 messages + clearInterval(timer); + sse.close(); + } + }, 1000); + + return new Response(readable, { + headers: { + "content-type": "text/event-stream", + "cache-control": "no-cache", + "connection": "keep-alive", + }, + }); +}); +``` + +Serve a single file (Range requests supported) + +```ts +import { serve } from "@std/http"; +import { serveFile } from "@std/http/file-server"; + +serve((req) => { + const url = new URL(req.url); + if (url.pathname === "/video") { + return serveFile(req, "static/video.mp4"); + } + return new Response("not found", { status: 404 }); +}); +``` + +## Tips + +- Handlers are `(req: Request) => Response | Promise`. +- Compose with standard `URL`, `Headers`, and `Request` for parsing and + responses. + + diff --git a/runtime/reference/std/index.md b/runtime/reference/std/index.md new file mode 100644 index 000000000..d4ecb56d3 --- /dev/null +++ b/runtime/reference/std/index.md @@ -0,0 +1,166 @@ +--- +title: "Standard Library (@std)" +description: "An introduction to Deno's Standard Library. Learn about TypeScript-first modules, cross-platform compatibility, versioning, package management, and how to use standard modules in your Deno projects." +oldUrl: + - /runtime/manual/basics/standard_library/" + - /runtime/reference/std/" +--- + +Deno provides a standard library written in TypeScript. It is a set of standard +modules that can be reused by programs, allowing you to focus on your +application logic rather than "reinventing the wheel" for common tasks. All of +the modules in the Deno Standard Library are audited by the core team and are +guaranteed to work with Deno, ensuring consistency and reliability. + +Many packages in the Deno Standard Library are also compatible with Node.js, +Cloudflare Workers, and other JavaScript environments. This allows you to write +code that can be run in multiple environments without modification. + +The standard library is hosted on JSR and is available at: +[https://jsr.io/@std](https://jsr.io/@std). Packages are documented, tested, and +include usage examples. + +## Packages + + + +- [@std/assert](./assert/) – Common assertion functions, especially useful for + testing +- [@std/async](./async/) – Utilities for asynchronous operations, like delays, + debouncing, or pooling +- [@std/bytes](./bytes/) – Utilities to manipulate Uint8Arrays that are not + built-in to JavaScript +- [@std/cache](./cache/) – UNSTABLE: Cache utilities +- [@std/cbor](./cbor/) – UNSTABLE: Utilities for parsing and serializing Concise + Binary Object Representation (CBOR) +- [@std/cli](./cli/) – Tools for creating interactive command line tools +- [@std/collections](./collections/) – Pure functions for common tasks related + to collection types like arrays and objects +- [@std/crypto](./crypto/) – Extensions to the Web Crypto API +- [@std/csv](./csv/) – Reading and writing of comma-separated values (CSV) files +- [@std/data-structures](./data-structures/) – Common data structures like + red-black trees and binary heaps +- [@std/datetime](./datetime/) – UNSTABLE: Utilities for dealing with Date + objects +- [@std/dotenv](./dotenv/) – UNSTABLE: Parsing and loading environment variables + from a `.env` file +- [@std/encoding](./encoding/) – Utilities for encoding and decoding common + formats like hex, base64, and varint +- [@std/expect](./expect/) – Jest compatible `expect` assertion functions +- [@std/fmt](./fmt/) – Utilities for formatting values, such as adding colors to + text, formatting durations, printf utils, formatting byte numbers. +- [@std/front-matter](./front-matter/) – Extract front matter from strings +- [@std/fs](./fs/) – Helpers for working with the file system +- [@std/html](./html/) – Functions for HTML, such as escaping or unescaping HTML + entities +- [@std/http](./http/) – Utilities for building HTTP servers +- [@std/ini](./ini/) – UNSTABLE: Parsing and serializing of INI files +- [@std/internal](./internal/) – INTERNAL: The internal package for @std. Do not + use this directly. +- [@std/io](./io/) – UNSTABLE: The utilities for advanced I/O operations using + Reader and Writer interfaces. +- [@std/json](./json/) – (Streaming) parsing and serializing of JSON files +- [@std/jsonc](./jsonc/) – Parsing and serializing of JSONC files +- [@std/log](./log/) – UNSTABLE: A customizable logger framework +- [@std/media-types](./media-types/) – Utility functions for media types (MIME + types) +- [@std/msgpack](./msgpack/) – Encoding and decoding for the msgpack format +- [@std/net](./net/) – Utilities for working with the network +- [@std/path](./path/) – Utilities for working with file system paths +- [@std/random](./random/) – UNSTABLE: Various utilities using random number + generators. The package also provides seeded pseudo-random number generator. +- [@std/regexp](./regexp/) – Utilities for working with RegExp +- [@std/semver](./semver/) – Parsing and comparing of semantic versions (SemVer) +- [@std/streams](./streams/) – Utilities for working with the Web Streams API +- [@std/tar](./tar/) – UNSTABLE: Streaming utilities for working with tar + archives. +- [@std/testing](./testing/) – Tools for testing Deno code like snapshot + testing, bdd testing, and time mocking +- [@std/text](./text/) – Utilities for working with text +- [@std/toml](./toml/) – Parsing and serializing of TOML files +- [@std/ulid](./ulid/) – Generation of Universally Unique Lexicographically + Sortable Identifiers (ULIDs) +- [@std/uuid](./uuid/) – Generators and validators for UUIDs +- [@std/webgpu](./webgpu/) – UNSTABLE: Utilities for working with the Web GPU + API +- [@std/yaml](./yaml/) – Parsing and serializing of YAML files + + + +## Versioning and stability + +Each package of the standard library is independently versioned. Packages follow +[semantic versioning rules](https://jsr.io/@std/semver). You can use +[version pinning or version ranges](/runtime/fundamentals/modules/#package-versions) +to prevent major releases from affecting your code. + +## Importing standard library modules + +To install packages from the Deno Standard Library, you can use the `deno add` +subcommand to add the package to your `deno.json` import map. + +```sh +deno add jsr:@std/fs jsr:@std/path +``` + +The `deno.json` `imports` field will be updated to include those imports: + +```json +{ + "imports": { + "@std/fs": "jsr:@std/fs@^1.0.2", + "@std/path": "jsr:@std/path@^1.0.3" + } +} +``` + +You can then import these packages in your source code: + +```ts +import { copy } from "@std/fs"; +import { join } from "@std/path"; + +await copy("foo.txt", join("dist", "foo.txt")); +``` + +Alternatively, you can import modules directly with the `jsr:` specifier: + +```js +import { copy } from "jsr:@std/fs@^1.0.2"; +import { join } from "jsr:@std/path@^1.0.3"; + +await copy("foo.txt", join("dist", "foo.txt")); +``` + +## Node.js compatibility + +The Deno Standard Library is designed to be compatible with Node.js, Cloudflare +Workers, and other JavaScript environments. The standard library is written in +TypeScript and compiled to JavaScript, so it can be used in any JavaScript +environment. + +```sh +npx jsr add @std/fs @std/path +``` + +Running this command will add those packages to your `package.json`: + +```json +{ + "dependencies": { + "@std/fs": "npm:@jsr/std__fs@^1.0.2", + "@std/path": "npm:@jsr/std__path@^1.0.3" + } +} +``` + +Then you can import them in your source code, just like you would with any other +Node.js package. TypeScript will automatically find the type definitions for +these packages. + +```ts +import { copy } from "@std/fs"; +import { join } from "@std/path"; + +await copy("foo.txt", join("dist", "foo.txt")); +``` diff --git a/runtime/reference/std/ini.md b/runtime/reference/std/ini.md new file mode 100644 index 000000000..2d029cfab --- /dev/null +++ b/runtime/reference/std/ini.md @@ -0,0 +1,274 @@ +--- +title: "@std/ini" +description: "Parsing and serializing of INI files" +jsr: jsr:@std/ini +pkg: ini +version: 0.225.2 +generated: true +stability: unstable +--- + + + +:::info Unstable + +This @std package is experimental and its API may change without a major version +bump. + +::: + +## Overview + +

parse and stringify for handling +INI encoded data, such as the +Desktop Entry specification. +Values are parsed as strings by default to preserve data parity from the original. +Customization is possible in the form of reviver/replacer functions like those in JSON.parse and JSON.stringify. +Nested sections, repeated key names within a section, and key/value arrays are not supported, +but will be preserved when using IniMap. Multi-line values are not supported and will throw a syntax error. +White space padding and lines starting with '#', ';', or '//' will be treated as comments.

+ +```js +import * as ini from "@std/ini"; +import { assertEquals } from "@std/assert"; + +const iniFile = `# Example configuration file +Global Key=Some data here + +[Section #1] +Section Value=42 +Section Date=1977-05-25`; + +const parsed = ini.parse(iniFile, { + reviver(key, value, section) { + if (section === "Section #1") { + if (key === "Section Value") return Number(value); + if (key === "Section Date") return new Date(value); + } + return value; + }, +}); + +assertEquals(parsed, { + "Global Key": "Some data here", + "Section #1": { + "Section Value": 42, + "Section Date": new Date("1977-05-25T00:00:00.000Z"), + }, +}); + +const text = ini.stringify(parsed, { + replacer(key, value, section) { + if (section === "Section #1" && key === "Section Date") { + return (value as Date).toISOString().split("T")[0]; + } + return value; + }, +}); + +assertEquals(text, `Global Key=Some data here +[Section #1] +Section Value=42 +Section Date=1977-05-25`); +``` + +

Optionally, IniMap may be used for finer INI handling. Using this class will permit preserving +comments, accessing values like a map, iterating over key/value/section entries, and more.

+ +```js +import { IniMap } from "@std/ini/ini-map"; +import { assertEquals } from "@std/assert"; + +const ini = new IniMap(); +ini.set("section1", "keyA", 100); +assertEquals( + ini.toString(), + `[section1] +keyA=100`, +); + +ini.set("keyA", 25); +assertEquals(ini.toObject(), { + keyA: 25, + section1: { + keyA: 100, + }, +}); +``` + +

The reviver and replacer APIs can be used to extend the behavior of IniMap, such as adding support +for duplicate keys as if they were arrays of values.

+ +```js +import { IniMap } from "@std/ini/ini-map"; +import { assertEquals } from "@std/assert"; + +const iniFile = `# Example of key/value arrays +[section1] +key1=This key +key1=is non-standard +key1=but can be captured!`; + +const ini = new IniMap({ assignment: "=", deduplicate: true }); +ini.parse(iniFile, (key, value, section) => { + if (section) { + if (ini.has(section, key)) { + const exists = ini.get(section, key); + if (Array.isArray(exists)) { + exists.push(value); + return exists; + } else { + return [exists, value]; + } + } + } + return value; +}); + +assertEquals( + ini.get("section1", "key1"), + ["This key", "is non-standard", "but can be captured!"], +); + +const result = ini.toString((key, value) => { + if (Array.isArray(value)) { + return value.join( + `${ini.formatting.lineBreak}${key}${ini.formatting.assignment}`, + ); + } + return value; +}); + +assertEquals(result, iniFile); +``` + +### Add to your project + +```sh +deno add jsr:@std/ini +``` + +See all symbols +in @std/ini on + + + + +## What is an INI file? + +INI files are simple text files used for configuration. They consist of +key-value pairs grouped into sections, making them easy to read and edit by +humans. INI files are commonly used for application settings, preferences, and +other configuration data. + +## Why use @std/ini? + +- INI is loosely specified; favor simple key/value usage and flat sections for + best interoperability. +- Values parse as strings by default. Use reviver/replacer to coerce to + numbers/dates/booleans explicitly. +- Multi-line values and arrays aren’t standard; use `IniMap` plus custom + reviver/replacer to emulate if needed. +- Comments begin with `#`, `;`, or `//` and are preserved by `IniMap`. + +## Examples + +Coercing types + +```ts +import * as ini from "@std/ini"; + +const cfg = ini.parse(text, { + reviver(key, value) { + if (/^(true|false)$/i.test(value)) return value.toLowerCase() === "true"; + if (/^\d+$/.test(value)) return Number(value); + return value; + }, +}); +``` + +Custom assignment operator and pretty formatting + +```ts +import * as ini from "@std/ini"; + +const txt = `name: Deno\nversion: 1`; + +// Use ':' instead of '=' when parsing +const parsed = ini.parse(txt, { assignment: ":" }); + +// And keep using ':' and pretty spacing on write +const out = ini.stringify(parsed, { assignment: ":", pretty: true }); +// out => "name : Deno\nversion : 1" +``` + +Preserve comments and order with IniMap + +```ts +import { IniMap } from "@std/ini/ini-map"; + +const text = `# Global +[app] +# Port to listen on +port=8080`; + +const im = new IniMap(); +im.parse(text); + +// Modify a value while preserving comments and ordering +im.set("app", "port", "9090"); + +// Comments and structure are kept in the output +const roundTrip = im.toString(); +``` + +Merge layered configs (base + local overrides) + +```ts +import { IniMap } from "@std/ini/ini-map"; + +const baseText = `[db]\nhost=localhost\nport=5432\n[app]\nmode=prod`; +const localText = `[db]\nport=6543\n[app]\nmode=dev`; + +const base = new IniMap(); +base.parse(baseText); + +const local = new IniMap(); +local.parse(localText); + +// Overlay values from local onto base +const overlay = (target: IniMap, source: IniMap) => { + const obj = source.toObject() as Record; + for (const [k, v] of Object.entries(obj)) { + if (v && typeof v === "object" && !Array.isArray(v)) { + for (const [kk, vv] of Object.entries(v as Record)) { + target.set(k, kk, vv); + } + } else { + target.set(k, v as string); + } + } +}; + +overlay(base, local); +const merged = base.toString(); +``` + +Duplicate keys: last-wins vs preservation + +```ts +import * as ini from "@std/ini"; +import { IniMap } from "@std/ini/ini-map"; + +const dup = `x=1\nx=2`; + +// Simple parse: last value wins +const simple = ini.parse(dup); // { x: "2" } + +// Using IniMap preserves duplicates (you can implement custom handling) +const im = new IniMap({ deduplicate: true }); +im.parse(dup); +// e.g. im.get("x") returns "2" by default; use a custom reviver to collect all +``` + + diff --git a/runtime/reference/std/internal.md b/runtime/reference/std/internal.md new file mode 100644 index 000000000..a947a692d --- /dev/null +++ b/runtime/reference/std/internal.md @@ -0,0 +1,16 @@ +--- +title: "@std/internal" +description: "The internal package for @std. Do not use this directly." +jsr: jsr:@std/internal +pkg: internal +version: 1.0.12 +generated: true +stability: internal +--- + +:::info Internal + +This @std package is for internal use and not intended for public consumption. +APIs may change or be removed. + +::: diff --git a/runtime/reference/std/io.md b/runtime/reference/std/io.md new file mode 100644 index 000000000..1f2e17a82 --- /dev/null +++ b/runtime/reference/std/io.md @@ -0,0 +1,72 @@ +--- +title: "@std/io" +description: "The utilities for advanced I/O operations using Reader and Writer interfaces." +jsr: jsr:@std/io +pkg: io +version: 0.225.2 +generated: true +stability: unstable +--- + + + +:::info Unstable + +This @std package is experimental and its API may change without a major version +bump. + +::: + +## Overview + +

Utilities for working with Deno's readers, writers, and web streams.

+

Reader and Writer interfaces are deprecated in Deno, and so many of these +utilities are also deprecated. Consider using web streams instead.

+ +```js +import { toReadableStream, toWritableStream } from "@std/io"; + +await toReadableStream(Deno.stdin) + .pipeTo(toWritableStream(Deno.stdout)); +``` + +### Add to your project + +```sh +deno add jsr:@std/io +``` + +See all symbols in +@std/io on + + + + +## Tips + +- Prefer Web Streams for new code. `Reader`/`Writer` helpers exist mainly for + interop and are being phased out. +- Use `toReadableStream`/`toWritableStream` to bridge Deno’s classic IO to + streams without buffering everything. +- Backpressure is automatic with Streams; avoid manual read loops when piping. +- For text transforms, pair with `TextDecoderStream`/`TextEncoderStream`. + +## Examples + +```ts +import { toReadableStream, toWritableStream } from "@std/io"; + +await toReadableStream(Deno.stdin) + .pipeThrough(new TextDecoderStream()) + .pipeThrough( + new TransformStream({ + transform(chunk, ctl) { + ctl.enqueue(chunk.toUpperCase()); + }, + }), + ) + .pipeThrough(new TextEncoderStream()) + .pipeTo(toWritableStream(Deno.stdout)); +``` + + diff --git a/runtime/reference/std/json.md b/runtime/reference/std/json.md new file mode 100644 index 000000000..086666577 --- /dev/null +++ b/runtime/reference/std/json.md @@ -0,0 +1,159 @@ +--- +title: "@std/json" +description: "(Streaming) parsing and serializing of JSON files" +jsr: jsr:@std/json +pkg: json +version: 1.0.2 +generated: true +stability: stable +--- + + + +## Overview + +

Utilities for parsing streaming JSON data.

+ +```js +import { JsonStringifyStream } from "@std/json"; +import { assertEquals } from "@std/assert"; + +const stream = ReadableStream.from([{ foo: "bar" }, { baz: 100 }]) + .pipeThrough(new JsonStringifyStream()); + +assertEquals(await Array.fromAsync(stream), [ + `{"foo":"bar"}\n`, + `{"baz":100}\n`, +]); +``` + +### Add to your project + +```sh +deno add jsr:@std/json +``` + +See all symbols +in @std/json on + + + + +## What is JSON streaming? + +JSON streaming is a technique for processing JSON data in a continuous flow, +rather than loading the entire dataset into memory at once. This is particularly +useful for handling large JSON files or real-time data feeds. + +## Why use @std/json? + +To stream JSON in and out to handle large datasets without loading everything in +memory. + +## Examples + +Parse concatenated JSON (multiple JSON values back-to-back) + +```ts +import { + ConcatenatedJsonParseStream, +} from "@std/json/concatenated-json-parse-stream"; + +// Stream contains two JSON documents back-to-back without delimiters. +const input = ReadableStream.from([ + '{"a":1}{', + '"b":2}', +]); + +const parsed = input.pipeThrough(new ConcatenatedJsonParseStream()); +console.log(await Array.fromAsync(parsed)); // [{ a: 1 }, { b: 2 }] +``` + +Produce NDJSON (JSON Lines) from objects + +```ts +import { JsonStringifyStream } from "@std/json/stringify-stream"; + +const data = [{ id: 1 }, { id: 2 }, { id: 3 }]; + +// Add a trailing newline after each JSON value for NDJSON +const ndjson = ReadableStream + .from(data) + .pipeThrough(new JsonStringifyStream({ suffix: "\n" })); + +// Post to a server that accepts application/x-ndjson +await fetch("/ingest", { + method: "POST", + headers: { "content-type": "application/x-ndjson" }, + body: ndjson, +}); +``` + +Consume NDJSON safely (split lines across chunk boundaries) + +```ts +import { JsonParseStream } from "@std/json/parse-stream"; + +// Split by newlines, even if a line is split across chunks +function lineSplitter() { + let buffer = ""; + return new TransformStream({ + transform(chunk, controller) { + buffer += chunk; + const lines = buffer.split(/\r?\n/); + buffer = lines.pop() ?? ""; // keep last partial line + for (const line of lines) if (line) controller.enqueue(line); + }, + flush(controller) { + if (buffer) controller.enqueue(buffer); + }, + }); +} + +const res = await fetch("/stream.ndjson"); +const values = res.body! + .pipeThrough(new TextDecoderStream()) + .pipeThrough(lineSplitter()) + .pipeThrough(new JsonParseStream()); + +for await (const obj of values) { + // Handle each JSON object as it arrives + console.log(obj); +} +``` + +Transform a JSON stream on the fly + +```ts +import { JsonParseStream } from "@std/json/parse-stream"; +import { JsonStringifyStream } from "@std/json/stringify-stream"; + +// Incoming objects -> map -> outgoing NDJSON +function mapStream(map: (t: T) => U) { + return new TransformStream({ transform: (t, c) => c.enqueue(map(t)) }); +} + +const response = await fetch("/objects.jsonl"); +const uppercased = response.body! + .pipeThrough(new TextDecoderStream()) + .pipeThrough(lineSplitter()) // from previous example + .pipeThrough(new JsonParseStream<{ name: string }>()) + .pipeThrough(mapStream((o) => ({ name: o.name.toUpperCase() }))) + .pipeThrough(new JsonStringifyStream({ suffix: "\n" })); + +// Pipe to another request, a file, or process further +await fetch("/store", { method: "POST", body: uppercased }); +``` + +## Tips + +- Use `JsonStringifyStream`/`JsonParseStream` to compose pipelines with + `fetch()` and file streams. +- Be explicit about encoding boundaries—prefer UTF-8 and + `TextEncoder`/`TextDecoder` when bridging. +- For NDJSON, use `JsonStringifyStream({ suffix: "\n" })` when producing, and + split lines before `JsonParseStream` when consuming. +- Use `ConcatenatedJsonParseStream` when your input is a stream of back-to-back + JSON values with no separators. + + diff --git a/runtime/reference/std/jsonc.md b/runtime/reference/std/jsonc.md new file mode 100644 index 000000000..2b7e15706 --- /dev/null +++ b/runtime/reference/std/jsonc.md @@ -0,0 +1,125 @@ +--- +title: "@std/jsonc" +description: "Parsing and serializing of JSONC files" +jsr: jsr:@std/jsonc +pkg: jsonc +version: 1.0.2 +generated: true +stability: stable +--- + + + +## Overview + +

Provides tools for working with +JSONC +(JSON with comments).

+

Currently, this module only provides a means of parsing JSONC. JSONC +serialization is not yet supported.

+ +```js +import { parse } from "@std/jsonc"; +import { assertEquals } from "@std/assert"; + +assertEquals(parse('{"foo": "bar", } // comment'), { foo: "bar" }); +assertEquals(parse('{"foo": "bar", } /* comment *\/'), { foo: "bar" }); +``` + +### Add to your project + +```sh +deno add jsr:@std/jsonc +``` + +See all symbols +in @std/jsonc on + + + + +## What is JSONC? + +JSONC (JSON with Comments) is a variant of JSON that allows comments and +trailing commas. It is commonly used for configuration files where human +readability and maintainability are important, such as in Visual Studio Code +settings files. + +### Why use @std/jsonc? + +This package allows you to easily parse JSONC files, which are not supported by +the standard JSON parser. It is useful for reading configuration files that may +contain comments or trailing commas, making them more user-friendly. + +## Examples + +Parse with comments and trailing commas + +```ts +import { parse } from "@std/jsonc"; + +const text = `{ + // Service config + "host": "localhost", + "port": 8000, // trailing comma allowed +}`; + +const cfg = parse(text); +// => { host: "localhost", port: 8000 } +``` + +Merge user config over defaults + +```ts +import { parse } from "@std/jsonc"; + +const defaults = { host: "127.0.0.1", port: 3000 } as const; +const userText = `{ + // Only override port + "port": 8080, +}`; + +const user = parse(userText) as Partial; +const finalCfg = { ...defaults, ...user }; +// => { host: "127.0.0.1", port: 8080 } +``` + +Load a .jsonc file in Deno + +```ts +import { parse } from "@std/jsonc"; + +const raw = await Deno.readTextFile("config.jsonc"); +let cfg: unknown; +try { + cfg = parse(raw); +} catch (err) { + // Surface a clean error; JSONC parser points near the syntax location + throw new Error(`Failed to parse config.jsonc: ${err.message}`); +} +``` + +Strip comments to plain JSON (if you must emit JSON) + +```ts +// There is no JSONC stringify yet. To emit JSON, remove comments, then JSON.stringify +function stripJsonc(input: string): string { + // Remove /* */ and // comments (naive). Ensure you don't remove content inside strings in critical cases. + return input + .replace(/\/\*[\s\S]*?\*\//g, "") + .replace(/(^|[^:])\/\/.*$/gm, "$1"); +} + +const clean = stripJsonc(raw); +const obj = JSON.parse(clean); +``` + +### Tips + +- Only parsing is supported; for writing, strip comments or use plain JSON. +- Be strict when reading untrusted input—JSONC is for config, not wire + protocols. +- When stripping comments, be careful with naive regex in the presence of string + literals. Prefer keeping JSONC at rest and converting only when necessary. + + diff --git a/runtime/reference/std/log.md b/runtime/reference/std/log.md new file mode 100644 index 000000000..da8d9e248 --- /dev/null +++ b/runtime/reference/std/log.md @@ -0,0 +1,17 @@ +--- +title: "@std/log" +description: "A customizable logger framework" +jsr: jsr:@std/log +pkg: log +version: 0.224.14 +generated: true +stability: unstable +--- + +:::info No longer recommended + +The @std/log package is likely to be removed in the future; consider using +[OpenTelemetry](/runtime/fundamentals/open_telemetry/) for production systems. +bump. + +::: diff --git a/runtime/reference/std/media-types.md b/runtime/reference/std/media-types.md new file mode 100644 index 000000000..776648856 --- /dev/null +++ b/runtime/reference/std/media-types.md @@ -0,0 +1,135 @@ +--- +title: "@std/media-types" +description: "Utility functions for media types (MIME types)" +jsr: jsr:@std/media-types +pkg: media-types +version: 1.1.0 +generated: true +stability: stable +--- + + + +## Overview + +

Utility functions for media types (MIME types).

+

This API is inspired by the GoLang mime +package and jshttp/mime-types, +and is designed to integrate and improve the APIs from +x/media_types.

+

The vendor folder contains copy of the +jshttp/mime-db db.json file, +along with its license.

+ +```js +import { allExtensions, contentType, getCharset } from "@std/media-types"; +import { assertEquals } from "@std/assert"; + +assertEquals(allExtensions("application/json"), ["json", "map"]); + +assertEquals(contentType(".json"), "application/json; charset=UTF-8"); + +assertEquals(getCharset("text/plain"), "UTF-8"); +``` + +### Add to your project + +```sh +deno add jsr:@std/media-types +``` + +See all +symbols in @std/media-types on + + + + +## What are media types? + +Media types, also known as MIME types, are standardized identifiers used to +indicate the nature and format of a file or piece of data. They are commonly +used in HTTP headers to specify the type of content being sent or received. + +## Why use @std/media-types? + +You may need to determine the correct MIME type for a file based on its +extension, or vice versa, when handling file uploads, downloads, or serving web +content. This package provides utility functions to easily map between +extensions and MIME types and obtain charset hints. + +## Examples + +### Quick lookups + +```ts +import { allExtensions, extension, typeByExtension } from "@std/media-types"; + +console.log(typeByExtension(".png")); // "image/png" +console.log(extension("text/html")); // "html" +console.log(allExtensions("application/json")); // ["json", "map"] +``` + +### Build headers for responses + +```ts +import { contentType } from "@std/media-types"; + +// Produces a full header value with charset when appropriate +const ct = contentType(".css"); // "text/css; charset=UTF-8" + +return new Response("body", { + headers: { + "Content-Type": ct ?? "application/octet-stream", + }, +}); +``` + +### Parse and normalize a Content-Type header + +```ts +import { formatMediaType, parseMediaType } from "@std/media-types"; + +const header = "text/HTML; charset=UTF-8"; +const [type, params] = parseMediaType(header)!; // ["text/html", { charset: "UTF-8" }] + +// Re-serialize with normalized type and params (lowercased keys) +const normalized = formatMediaType(type, params); +// "text/html; charset=UTF-8" +``` + +### Extract multipart/form-data boundary from a request + +```ts +import { parseMediaType } from "@std/media-types"; + +function getBoundary(headers: Headers): string | undefined { + const value = headers.get("content-type"); + if (!value) return undefined; + const parsed = parseMediaType(value); + return parsed?.[1]?.boundary; +} +``` + +### Detect charset from an incoming request + +```ts +import { getCharset } from "@std/media-types"; + +async function readText(req: Request): Promise { + const charset = getCharset(req.headers.get("content-type") ?? "") ?? "UTF-8"; + const bytes = new Uint8Array(await req.arrayBuffer()); + const decoder = new TextDecoder(charset); + return decoder.decode(bytes); +} +``` + +## Tips + +- Prefer `contentType(extOrType)` when constructing HTTP responses. +- Use `allExtensions(type)` to support multiple possible extensions. +- `parseMediaType` throws on invalid input; wrap in try/catch if parsing user + input. +- When `contentType()` returns `undefined` for an unknown extension/type, fall + back to `application/octet-stream`. + + diff --git a/runtime/reference/std/msgpack.md b/runtime/reference/std/msgpack.md new file mode 100644 index 000000000..a5326fa45 --- /dev/null +++ b/runtime/reference/std/msgpack.md @@ -0,0 +1,124 @@ +--- +title: "@std/msgpack" +description: "Encoding and decoding for the msgpack format" +jsr: jsr:@std/msgpack +pkg: msgpack +version: 1.0.3 +generated: true +stability: stable +--- + + + +## Overview + +

This module provides functions to encode and decode MessagePack.

+

MessagePack is an efficient binary serialization format that is language +agnostic. It is like JSON, but generally produces much smaller payloads. +Learn more about MessagePack.

+ +```js +import { decode, encode } from "@std/msgpack"; +import { assertEquals } from "@std/assert"; + +const obj = { + str: "deno", + arr: [1, 2, 3], + bool: true, + nil: null, + map: { + foo: "bar", + }, +}; + +const encoded = encode(obj); +assertEquals(encoded.length, 42); + +const decoded = decode(encoded); +assertEquals(decoded, obj); +``` + +

MessagePack supports encoding and decoding the following types:

+
    +
  • number
  • +
  • bigint
  • +
  • string
  • +
  • boolean
  • +
  • null
  • +
  • Uint8Array
  • +
  • arrays of values of these types
  • +
  • objects with string or number keys, and values of these types
  • +
+ +### Add to your project + +```sh +deno add jsr:@std/msgpack +``` + +See all +symbols in @std/msgpack on + + + + +## What is MessagePack? + +MessagePack is a binary serialization format that is compact, fast, and +schema-less. It is designed to be efficient in both size and speed, making it +suitable for high-performance applications and data exchange between different +programming languages. + +## Why use @std/msgpack? + +- MessagePack is great for compact, fast, schema-less payloads between trusted + services. Useful if you need a more efficient alternative to JSON. +- Binary-safe: `Uint8Array` round-trips without base64 overhead. + +## Examples + +```ts +import { decode, encode } from "@std/msgpack"; + +const payload = { id: 1, items: ["a", "b"], data: new Uint8Array([1, 2, 3]) }; +const bin = encode(payload); +const back = decode(bin); +``` + +Custom extension types + +```ts +import { Decoder, Encoder, ExtData } from "@std/msgpack"; + +// tag 1 for Date +const enc = new Encoder({ + extensionCodec: { + tryToEncode(object) { + if (object instanceof Date) { + return new ExtData( + 1, + new Uint8Array(new BigInt64Array([BigInt(object.getTime())]).buffer), + ); + } + }, + }, +}); + +const dec = new Decoder({ + extensionCodec: { + decode(data) { + if (data.type === 1) { + return new Date(Number(new BigInt64Array(data.data.buffer)[0])); + } + }, + }, +}); +``` + +## Tips + +- Beware of bigint vs number: very large integers decode to `bigint`. +- For interop with other languages, stick to common types (number, string, + boolean, null, arrays, maps, bytes). + + diff --git a/runtime/reference/std/net.md b/runtime/reference/std/net.md new file mode 100644 index 000000000..c7f92e9b3 --- /dev/null +++ b/runtime/reference/std/net.md @@ -0,0 +1,131 @@ +--- +title: "@std/net" +description: "Utilities for working with the network" +jsr: jsr:@std/net +pkg: net +version: 1.0.6 +generated: true +stability: stable +--- + + + +## Overview + +

Network utilities.

+ +```js +import { getAvailablePort } from "@std/net"; + +const command = new Deno.Command(Deno.execPath(), { + args: ["test.ts", "--port", getAvailablePort().toString()], +}); + +// ... +``` + +### Add to your project + +```sh +deno add jsr:@std/net +``` + +See all symbols +in @std/net on + + + + +## What is @std/net? + +Utilities to help with common networking tasks that complement Deno's core APIs: + +- Finding or reserving an open port. +- Discovering a machine's LAN address to bind servers. +- Validating IP versions and checking if an address belongs to a CIDR subnet. + +## Why use @std/net? + +- To pick safe ports and interfaces: + - Prefer ephemeral ports via `Deno.listen({ port: 0 })` when you control the + listener. + - Use `getAvailablePort()` when you need a free port value to pass to other + processes before binding (then bind immediately to avoid races). +- Bind to the right network: use `getNetworkAddress()` to serve on your LAN’s + IPv4 or IPv6 address instead of loopback. +- Validate and filter traffic: `isIPv4`/`isIPv6` and `match*Subnet` helpers let + you build allow/deny lists or feature gates by IP ranges. + +## Examples + +```ts +const listener = Deno.listen({ hostname: "127.0.0.1", port: 0 }); +const { port } = listener.addr as Deno.NetAddr; +// start server on listener ... +``` + +### Bind to a LAN address (not just localhost) + +```ts +import { getNetworkAddress } from "@std/net/unstable-get-network-address"; + +const hostname = getNetworkAddress() ?? "127.0.0.1"; // default IPv4 +Deno.serve({ hostname, port: 0 }, () => new Response("Hello from LAN")); +``` + +### Validate incoming IP family + +```ts +import { isIPv4, isIPv6 } from "@std/net/unstable-ip"; + +function describe(ip: string): string { + if (isIPv4(ip)) return "IPv4"; + if (isIPv6(ip)) return "IPv6"; + return "unknown"; +} +``` + +### Allowlist requests by subnet (IPv4 and IPv6) + +```ts +import { matchSubnets } from "@std/net/unstable-ip"; + +const allowlist = [ + "192.168.1.0/24", // home LAN + "2001:db8::/64", // docs example IPv6 prefix +]; + +Deno.serve((req, info) => { + const ip = (info.remoteAddr as Deno.NetAddr).hostname; + if (!matchSubnets(ip, allowlist)) { + return new Response("Forbidden", { status: 403 }); + } + return new Response("OK"); +}); +``` + +### Pass a free port to a child process + +```ts +import { getAvailablePort } from "@std/net"; + +const port = getAvailablePort(); +// Immediately reserve it in your process if possible to avoid races +const listener = Deno.listen({ hostname: "127.0.0.1", port }); + +const child = new Deno.Command("deno", { + args: ["run", "--allow-net", "./child_server.ts", String(port)], +}); +child.spawn(); +``` + +## Tips + +- Prefer `Deno.listen({ port: 0 })` when possible; use `getAvailablePort()` only + when you must pass a port value to another process first. +- After obtaining a port number, bind right away in the same process to avoid + TOCTOU race conditions. +- `unstable-ip` helpers are great for allow/deny lists but avoid putting full + access control solely in client-controlled headers like `X-Forwarded-For`. + + diff --git a/runtime/reference/std/path.md b/runtime/reference/std/path.md new file mode 100644 index 000000000..97af4fadd --- /dev/null +++ b/runtime/reference/std/path.md @@ -0,0 +1,280 @@ +--- +title: "@std/path" +description: "Utilities for working with file system paths" +jsr: jsr:@std/path +pkg: path +version: 1.1.2 +generated: true +stability: stable +--- + + + +## Overview + +

Utilities for working with OS-specific file paths.

+

Functions from this module will automatically switch to support the path style +of the current OS, either windows for Microsoft Windows, or posix for +every other operating system, eg. Linux, MacOS, BSD etc.

+

To use functions for a specific path style regardless of the current OS +import the modules from the platform sub directory instead.

+

+Basic Path Operations

+ +```js +import * as path from "@std/path"; +import { assertEquals } from "@std/assert"; + +// Get components of a path +if (Deno.build.os === "windows") { + assertEquals(path.basename("C:\\Users\\user\\file.txt"), "file.txt"); + assertEquals(path.dirname("C:\\Users\\user\\file.txt"), "C:\\Users\\user"); + assertEquals(path.extname("C:\\Users\\user\\file.txt"), ".txt"); +} else { + assertEquals(path.basename("/home/user/file.txt"), "file.txt"); + assertEquals(path.dirname("/home/user/file.txt"), "/home/user"); + assertEquals(path.extname("/home/user/file.txt"), ".txt"); +} + +// Join path segments +if (Deno.build.os === "windows") { + assertEquals( + path.join("C:\\", "Users", "docs", "file.txt"), + "C:\\Users\\docs\\file.txt", + ); +} else { + assertEquals( + path.join("/home", "user", "docs", "file.txt"), + "/home/user/docs/file.txt", + ); +} + +// Normalize a path +if (Deno.build.os === "windows") { + assertEquals( + path.normalize("C:\\Users\\user\\..\\temp\\.\\file.txt"), + "C:\\Users\\temp\\file.txt", + ); +} else { + assertEquals( + path.normalize("/home/user/../temp/./file.txt"), + "/home/temp/file.txt", + ); +} + +// Resolve absolute path +if (Deno.build.os === "windows") { + const resolved = path.resolve("C:\\foo", "docs", "file.txt"); + assertEquals(resolved, "C:\\foo\\docs\\file.txt"); + assertEquals(path.isAbsolute(resolved), true); +} else { + const resolved = path.resolve("/foo", "docs", "file.txt"); + assertEquals(resolved, "/foo/docs/file.txt"); + assertEquals(path.isAbsolute(resolved), true); +} + +// Get relative path +if (Deno.build.os === "windows") { + assertEquals( + path.relative("C:\\Users", "C:\\Users\\docs\\file.txt"), + "docs\\file.txt", + ); + assertEquals(path.relative("C:\\Users", "D:\\Programs"), "D:\\Programs"); +} else { + assertEquals( + path.relative("/home/user", "/home/user/docs/file.txt"), + "docs/file.txt", + ); + assertEquals(path.relative("/home/user", "/var/data"), "../../var/data"); +} +``` + +

+Path Parsing and Formatting

+ +```js +import * as path from "@std/path"; +import { assertEquals } from "@std/assert"; + +if (Deno.build.os === "windows") { + const parsedWindows = path.parse("C:\\Users\\user\\file.txt"); + assertEquals(parsedWindows.root, "C:\\"); + assertEquals(parsedWindows.dir, "C:\\Users\\user"); + assertEquals(parsedWindows.base, "file.txt"); + assertEquals(parsedWindows.ext, ".txt"); + assertEquals(parsedWindows.name, "file"); + + // Format path from components (Windows) + assertEquals( + path.format({ dir: "C:\\Users\\user", base: "file.txt" }), + "C:\\Users\\user\\file.txt", + ); +} else { + const parsedPosix = path.parse("/home/user/file.txt"); + assertEquals(parsedPosix.root, "/"); + assertEquals(parsedPosix.dir, "/home/user"); + assertEquals(parsedPosix.base, "file.txt"); + assertEquals(parsedPosix.ext, ".txt"); + assertEquals(parsedPosix.name, "file"); + + // Format path from components (POSIX) + assertEquals( + path.format({ dir: "/home/user", base: "file.txt" }), + "/home/user/file.txt", + ); +} +``` + +

+URL Conversion

+ +```js +import * as path from "@std/path"; +import { assertEquals } from "@std/assert"; + +// Convert between file URLs and paths +if (Deno.build.os === "windows") { + assertEquals( + path.fromFileUrl("file:///C:/Users/user/file.txt"), + "C:\\Users\\user\\file.txt", + ); + assertEquals( + path.toFileUrl("C:\\Users\\user\\file.txt").href, + "file:///C:/Users/user/file.txt", + ); +} else { + assertEquals( + path.fromFileUrl("file:///home/user/file.txt"), + "/home/user/file.txt", + ); + assertEquals( + path.toFileUrl("/home/user/file.txt").href, + "file:///home/user/file.txt", + ); +} +``` + +

+Path Properties

+ +```js +import * as path from "@std/path"; +import { assertEquals } from "@std/assert"; + +// Check if path is absolute +if (Deno.build.os === "windows") { + assertEquals(path.isAbsolute("C:\\Users"), true); + assertEquals(path.isAbsolute("\\\\Server\\share"), true); + assertEquals(path.isAbsolute("C:relative\\path"), false); + assertEquals(path.isAbsolute("..\\relative\\path"), false); +} else { + assertEquals(path.isAbsolute("/home/user"), true); + assertEquals(path.isAbsolute("./relative/path"), false); + assertEquals(path.isAbsolute("../relative/path"), false); +} + +// Convert to namespaced path (Windows-specific) +if (Deno.build.os === "windows") { + assertEquals( + path.toNamespacedPath("C:\\Users\\file.txt"), + "\\\\?\\C:\\Users\\file.txt", + ); + assertEquals( + path.toNamespacedPath("\\\\server\\share\\file.txt"), + "\\\\?\\UNC\\server\\share\\file.txt", + ); +} else { + // On POSIX, toNamespacedPath returns the path unchanged + assertEquals( + path.toNamespacedPath("/home/user/file.txt"), + "/home/user/file.txt", + ); +} +``` + +

+Glob Pattern Utilities

+ +```js +import * as path from "@std/path"; +import { assertEquals } from "@std/assert"; + +// Check if a string is a glob pattern +assertEquals(path.isGlob("*.txt"), true); + +// Convert glob pattern to RegExp +const pattern = path.globToRegExp("*.txt"); +assertEquals(pattern.test("file.txt"), true); + +// Join multiple glob patterns +if (Deno.build.os === "windows") { + assertEquals(path.joinGlobs(["src", "**\\*.ts"]), "src\\**\\*.ts"); +} else { + assertEquals(path.joinGlobs(["src", "**\/*.ts"]), "src/**\/*.ts"); +} + +// Normalize a glob pattern +if (Deno.build.os === "windows") { + assertEquals(path.normalizeGlob("src\\..\\**\\*.ts"), "**\\*.ts"); +} else { + assertEquals(path.normalizeGlob("src/../**\/*.ts"), "**\/*.ts"); +} +``` + +

For POSIX-specific functions:

+ +```js +import { fromFileUrl } from "@std/path/posix/from-file-url"; +import { assertEquals } from "@std/assert"; + +assertEquals(fromFileUrl("file:///home/foo"), "/home/foo"); +``` + +

For Windows-specific functions:

+ +```js +import { fromFileUrl } from "@std/path/windows/from-file-url"; +import { assertEquals } from "@std/assert"; + +assertEquals(fromFileUrl("file:///home/foo"), "\\home\\foo"); +``` + +

Functions for working with URLs can be found in +@std/path/posix.

+ +### Add to your project + +```sh +deno add jsr:@std/path +``` + +See all symbols +in @std/path on + + + + +## When to use @std/path + +Use it anywhere you build, normalize, or inspect file paths. It handles POSIX +and Windows differences so your code stays portable. + +## Examples + +```ts +import { basename, dirname, extname, join, resolve } from "@std/path"; + +const file = join("content", "posts", "hello.md"); +console.log(dirname(file)); // content/posts +console.log(basename(file)); // hello.md +console.log(extname(file)); // .md +console.log(resolve(".", "assets")); // absolute path +``` + +## Tips + +- Prefer `join` over string concatenation. +- Use `fromFileUrl`/`toFileUrl` when moving between file URLs and paths. +- For OS-specific logic, import from `@std/path/posix` or `@std/path/windows`. + + diff --git a/runtime/reference/std/random.md b/runtime/reference/std/random.md new file mode 100644 index 000000000..e94075522 --- /dev/null +++ b/runtime/reference/std/random.md @@ -0,0 +1,71 @@ +--- +title: "@std/random" +description: "Various utilities using random number generators. The package also provides seeded pseudo-random number generator." +jsr: jsr:@std/random +pkg: random +version: 0.1.3 +generated: true +stability: unstable +--- + + + +:::info Unstable + +This @std package is experimental and its API may change without a major version +bump. + +::: + +## Overview + +

Utilities for generating random numbers.

+ +```js +import { randomIntegerBetween } from "@std/random"; +import { randomSeeded } from "@std/random"; +import { assertEquals } from "@std/assert"; + +const prng = randomSeeded(1n); + +assertEquals(randomIntegerBetween(1, 10, { prng }), 3); +``` + +### Add to your project + +```sh +deno add jsr:@std/random +``` + +See all +symbols in @std/random on + + + + +## Why use @std/random? + +Random number generation is useful for simulations, games, sampling,and +randomized algorithms. This package provides both convenience functions for +common use cases and a way to create reproducible pseudo-random sequences via +seeding. + +## Examples + +```ts +import { randomIntegerBetween, randomSeeded } from "@std/random"; + +const prng = randomSeeded(123n); +const roll = randomIntegerBetween(1, 6, { prng }); +``` + +## Tips + +- For reproducible tests and simulations, use `randomSeeded(seed)` and pass the + PRNG to helpers. +- For security-sensitive randomness (tokens, keys), use the Web Crypto API + (`crypto.getRandomValues`) instead of PRNG utilities. +- Distribution helpers like `randomIntegerBetween` are inclusive of both bounds; + document this in APIs to avoid off-by-one confusion. + + diff --git a/runtime/reference/std/regexp.md b/runtime/reference/std/regexp.md new file mode 100644 index 000000000..0c1a712f9 --- /dev/null +++ b/runtime/reference/std/regexp.md @@ -0,0 +1,76 @@ +--- +title: "@std/regexp" +description: "Utilities for working with RegExp" +jsr: jsr:@std/regexp +pkg: regexp +version: 1.0.1 +generated: true +stability: stable +--- + + + +## Overview + +

Functions for tasks related to +regular expression (regexp), +such as escaping text for interpolation into a regexp.

+ +```js +import { escape } from "@std/regexp/escape"; +import { assertEquals, assertMatch, assertNotMatch } from "@std/assert"; + +const re = new RegExp(`^${escape(".")}$`, "u"); + +assertEquals("^\\.$", re.source); +assertMatch(".", re); +assertNotMatch("a", re); +``` + +### Add to your project + +```sh +deno add jsr:@std/regexp +``` + +See all +symbols in @std/regexp on + + + + +## What is RegExp? + +RegExp (regular expressions) are patterns used to match character combinations +in strings. In JavaScript, they are implemented via the `RegExp` object and +literal syntax (e.g., `/pattern/flags`). + +### Why use @std/regexp? + +This package provides small utilities to make working with regexps safer and +easier: + +- Use `escape()` when interpolating user input into a RegExp to avoid unintended + meta-characters. +- Prefer the `u` (unicode) flag for correctness; it changes how escapes and + character classes behave. +- Anchors: `^` and `$` match start/end of string; use `m` flag to make them + line-based. +- When performance matters, precompile your regex once and reuse it. + +## Examples + +```ts +import { escape } from "@std/regexp/escape"; + +const user = "hello.+(world)"; +const safe = new RegExp(`^${escape(user)}$`, "u"); +safe.test("hello.+(world)"); // true +safe.test("helloX(world)"); // false + +// Multiline anchors +const re = /^error:.+$/mu; +re.test("ok\nerror: bad\nnext"); // true +``` + + diff --git a/runtime/reference/std/semver.md b/runtime/reference/std/semver.md new file mode 100644 index 000000000..10e2d02a5 --- /dev/null +++ b/runtime/reference/std/semver.md @@ -0,0 +1,293 @@ +--- +title: "@std/semver" +description: "Parsing and comparing of semantic versions (SemVer)" +jsr: jsr:@std/semver +pkg: semver +version: 1.0.6 +generated: true +stability: stable +--- + + + +## Overview + +

The Semantic Version parser.

+

Adapted directly from semver.

+ +```js +import { format, greaterThan, lessThan, parse, parseRange } from "@std/semver"; +import { assertEquals } from "@std/assert"; + +const semver = parse("1.2.3"); +assertEquals(semver, { + major: 1, + minor: 2, + patch: 3, + prerelease: [], + build: [], +}); + +assertEquals(format(semver), "1.2.3"); + +const range = parseRange("1.x || >=2.5.0 || 5.0.0 - 7.2.3"); + +const s0 = parse("1.2.3"); +const s1 = parse("9.8.7"); + +assertEquals(greaterThan(s0, s1), false); +assertEquals(lessThan(s0, s1), true); +``` + +

+Versions

+

A "version" is described by the v2.0.0 specification found at +https://semver.org.

+

A leading "=" or "v" character is stripped off and ignored.

+

+Format

+

Semantic versions can be formatted as strings, by default they +are formatted as full. Below is a diagram showing the various +formatting options.

+ +```js + full + ┌───┴───┐ + release │ + ┌───┴───┐ │ +primary │ │ + ┌─┴─┐ │ │ + 1.2.3-pre.1+b.1 + │ │ │ └─┬─┘ └┬┘ + │ │ │ │ └── build + │ │ │ └─────── pre + │ │ └─────────── patch + │ └───────────── minor + └─────────────── major +``` + +

+Ranges

+

A version Range is a set of Comparators which specify +versions that satisfy the range.

+

A Comparator is composed of an Operator and a +SemVer. The set of primitive operators is:

+
    +
  • < Less than
  • +
  • <= Less than or equal to
  • +
  • > Greater than
  • +
  • >= Greater than or equal to
  • +
  • = Equal. If no operator is specified, then equality is assumed, so this +operator is optional, but MAY be included.
  • +
+

For example, the comparator >=1.2.7 would match the versions 1.2.7, 1.2.8, +2.5.3, and 1.3.9, but not the versions 1.2.6 or 1.1.0.

+

Comparators can be joined by whitespace to form a comparator set, which is +satisfied by the intersection of all of the comparators it includes.

+

A range is composed of one or more comparator sets, joined by ||. A version +matches a range if and only if every comparator in at least one of the +||-separated comparator sets is satisfied by the version.

+

For example, the range >=1.2.7 <1.3.0 would match the versions 1.2.7, +1.2.8, and 1.2.99, but not the versions 1.2.6, 1.3.0, or 1.1.0.

+

The range 1.2.7 || >=1.2.9 <2.0.0 would match the versions 1.2.7, 1.2.9, +and 1.4.6, but not the versions 1.2.8 or 2.0.0.

+

+Prerelease Tags

+

If a version has a prerelease tag (for example, 1.2.3-alpha.3) then it will +only be allowed to satisfy comparator sets if at least one comparator with the +same [major, minor, patch] tuple also has a prerelease tag.

+

For example, the range >1.2.3-alpha.3 would be allowed to match the version +1.2.3-alpha.7, but it would not be satisfied by 3.4.5-alpha.9, even though +3.4.5-alpha.9 is technically "greater than" 1.2.3-alpha.3 according to the +SemVer sort rules. The version range only accepts prerelease tags on the 1.2.3 +version. The version 3.4.5 would satisfy the range, because it does not have +a prerelease flag, and 3.4.5 is greater than 1.2.3-alpha.7.

+

The purpose for this behavior is twofold. First, prerelease versions frequently +are updated very quickly, and contain many breaking changes that are (by the +author"s design) not yet fit for public consumption. Therefore, by default, they +are excluded from range matching semantics.

+

Second, a user who has opted into using a prerelease version has clearly +indicated the intent to use that specific set of alpha/beta/rc versions. By +including a prerelease tag in the range, the user is indicating that they are +aware of the risk. However, it is still not appropriate to assume that they have +opted into taking a similar risk on the next set of prerelease versions.

+

+Prerelease Identifiers

+

The method increment takes an additional identifier string +argument that will append the value of the string as a prerelease identifier:

+ +```js +import { increment, parse } from "@std/semver"; +import { assertEquals } from "@std/assert"; + +assertEquals( + increment(parse("1.2.3"), "prerelease", { prerelease: "alpha" }), + parse("1.2.4-alpha.0"), +); +``` + +

+Build Metadata

+

Build metadata is . delimited alpha-numeric string. +When parsing a version it is retained on the build: string[] field +of the SemVer instance. When incrementing there is an additional parameter that +can set the build metadata on the SemVer instance.

+

+Advanced Range Syntax

+

Advanced range syntax desugars to primitive comparators in deterministic ways.

+

Advanced ranges may be combined in the same way as primitive comparators using +white space or ||.

+

+Hyphen Ranges X.Y.Z - A.B.C

+

Specifies an inclusive set.

+
    +
  • 1.2.3 - 2.3.4 := >=1.2.3 <=2.3.4
  • +
+

If a partial version is provided as the first version in the inclusive range, +then the missing pieces are replaced with zeroes.

+
    +
  • 1.2 - 2.3.4 := >=1.2.0 <=2.3.4
  • +
+

If a partial version is provided as the second version in the inclusive range, +then all versions that start with the supplied parts of the tuple are accepted, +but nothing that would be greater than the provided tuple parts.

+
    +
  • 1.2.3 - 2.3 := >=1.2.3 <2.4.0
  • +
  • 1.2.3 - 2 := >=1.2.3 <3.0.0
  • +
+

+X-Ranges 1.2.x 1.X 1.2.* *

+

Any of X, x, or * may be used to "stand in" for one of the numeric values +in the [major, minor, patch] tuple.

+
    +
  • * := >=0.0.0 (Any version satisfies)
  • +
  • 1.x := >=1.0.0 <2.0.0 (Matching major version)
  • +
  • 1.2.x := >=1.2.0 <1.3.0 (Matching major and minor versions)
  • +
+

A partial version range is treated as an X-Range, so the special character is in +fact optional.

+
    +
  • "" (empty string) := * := >=0.0.0
  • +
  • 1 := 1.x.x := >=1.0.0 <2.0.0
  • +
  • 1.2 := 1.2.x := >=1.2.0 <1.3.0
  • +
+

+Tilde Ranges ~1.2.3 ~1.2 ~1

+

Allows patch-level changes if a minor version is specified on the comparator. +Allows minor-level changes if not.

+
    +
  • ~1.2.3 := >=1.2.3 <1.(2+1).0 := >=1.2.3 <1.3.0
  • +
  • ~1.2 := >=1.2.0 <1.(2+1).0 := >=1.2.0 <1.3.0 (Same as 1.2.x)
  • +
  • ~1 := >=1.0.0 <(1+1).0.0 := >=1.0.0 <2.0.0 (Same as 1.x)
  • +
  • ~0.2.3 := >=0.2.3 <0.(2+1).0 := >=0.2.3 <0.3.0
  • +
  • ~0.2 := >=0.2.0 <0.(2+1).0 := >=0.2.0 <0.3.0 (Same as 0.2.x)
  • +
  • ~0 := >=0.0.0 <(0+1).0.0 := >=0.0.0 <1.0.0 (Same as 0.x)
  • +
  • ~1.2.3-beta.2 := >=1.2.3-beta.2 <1.3.0 Note that prereleases in the +1.2.3 version will be allowed, if they are greater than or equal to +beta.2. So, 1.2.3-beta.4 would be allowed, but 1.2.4-beta.2 would not, +because it is a prerelease of a different [major, minor, patch] tuple.
  • +
+

+Caret Ranges ^1.2.3 ^0.2.5 ^0.0.4

+

Allows changes that do not modify the left-most non-zero element in the +[major, minor, patch] tuple. In other words, this allows patch and minor +updates for versions 1.0.0 and above, patch updates for versions +0.X >=0.1.0, and no updates for versions 0.0.X.

+

Many authors treat a 0.x version as if the x were the major +"breaking-change" indicator.

+

Caret ranges are ideal when an author may make breaking changes between 0.2.4 +and 0.3.0 releases, which is a common practice. However, it presumes that +there will not be breaking changes between 0.2.4 and 0.2.5. It allows for +changes that are presumed to be additive (but non-breaking), according to +commonly observed practices.

+
    +
  • ^1.2.3 := >=1.2.3 <2.0.0
  • +
  • ^0.2.3 := >=0.2.3 <0.3.0
  • +
  • ^0.0.3 := >=0.0.3 <0.0.4
  • +
  • ^1.2.3-beta.2 := >=1.2.3-beta.2 <2.0.0 Note that prereleases in the +1.2.3 version will be allowed, if they are greater than or equal to +beta.2. So, 1.2.3-beta.4 would be allowed, but 1.2.4-beta.2 would not, +because it is a prerelease of a different [major, minor, patch] tuple.
  • +
  • ^0.0.3-beta := >=0.0.3-beta <0.0.4 Note that prereleases in the 0.0.3 +version only will be allowed, if they are greater than or equal to beta. +So, 0.0.3-pr.2 would be allowed.
  • +
+

When parsing caret ranges, a missing patch value desugars to the number 0, +but will allow flexibility within that value, even if the major and minor +versions are both 0.

+
    +
  • ^1.2.x := >=1.2.0 <2.0.0
  • +
  • ^0.0.x := >=0.0.0 <0.1.0
  • +
  • ^0.0 := >=0.0.0 <0.1.0
  • +
+

A missing minor and patch values will desugar to zero, but also allow +flexibility within those values, even if the major version is zero.

+
    +
  • ^1.x := >=1.0.0 <2.0.0
  • +
  • ^0.x := >=0.0.0 <1.0.0
  • +
+

+Range Grammar

+

Putting all this together, here is a Backus-Naur grammar for ranges, for the +benefit of parser authors:

+ +```js +range-set ::= range ( logical-or range ) * +logical-or ::= ( " " ) * "||" ( " " ) * +range ::= hyphen | simple ( " " simple ) * | "" +hyphen ::= partial " - " partial +simple ::= primitive | partial | tilde | caret +primitive ::= ( "<" | ">" | ">=" | "<=" | "=" ) partial +partial ::= xr ( "." xr ( "." xr qualifier ? )? )? +xr ::= "x" | "X" | "*" | nr +nr ::= "0" | ["1"-"9"] ( ["0"-"9"] ) * +tilde ::= "~" partial +caret ::= "^" partial +qualifier ::= ( "-" pre )? ( "+" build )? +pre ::= parts +build ::= parts +parts ::= part ( "." part ) * +part ::= nr | [-0-9A-Za-z]+ +``` + +

Note that, since ranges may be non-contiguous, a version might not be greater +than a range, less than a range, or satisfy a range! For example, the range +1.2 <1.2.9 || >2.0.0 would have a hole from 1.2.9 until 2.0.0, so the +version 1.2.10 would not be greater than the range (because 2.0.1 satisfies, +which is higher), nor less than the range (since 1.2.8 satisfies, which is +lower), and it also does not satisfy the range.

+

If you want to know if a version satisfies or does not satisfy a range, use the +satisfies function.

+ +### Add to your project + +```sh +deno add jsr:@std/semver +``` + +See all +symbols in @std/semver on + + + + +## Why use @std/semver? + +Compare, sort, and test version ranges correctly—avoid ad-hoc string compares. + +## Examples + +```ts +import { parse, parseRange, satisfies } from "@std/semver"; + +const v = parse("1.2.3"); +const r = parseRange("^1.2.0"); +console.log(satisfies(v, r)); // true +``` + +## Tips + +- Use ranges (`^`, `~`, `x`, hyphen) to express compatibility windows. +- Be explicit with prereleases; range matching excludes them unless included. + + diff --git a/runtime/reference/std/streams.md b/runtime/reference/std/streams.md new file mode 100644 index 000000000..c081e3ed0 --- /dev/null +++ b/runtime/reference/std/streams.md @@ -0,0 +1,84 @@ +--- +title: "@std/streams" +description: "Utilities for working with the Web Streams API" +jsr: jsr:@std/streams +pkg: streams +version: 1.0.13 +generated: true +stability: stable +--- + + + +## Overview + +

Utilities for working with the +Streams API.

+

Includes buffering and conversion.

+ +```js +import { toText } from "@std/streams"; +import { assertEquals } from "@std/assert"; + +const stream = ReadableStream.from(["Hello, world!"]); +const text = await toText(stream); + +assertEquals(text, "Hello, world!"); +``` + +### Add to your project + +```sh +deno add jsr:@std/streams +``` + +See all +symbols in @std/streams on + + + + +## What are Web Streams? + +Web Streams provide a standard way to handle streaming data in JavaScript. They +allow you to process data piece by piece as it arrives, rather than waiting for +the entire dataset to be available. This is particularly useful for handling +large files, network requests, or any situation where data is produced over +time. + +## Why use @std/streams? + +Use for buffering, converting, and composing Web Streams efficiently. + +### Examples + +```ts +import { copy, readerFromStreamReader, writeAll } from "@std/streams"; + +// Copy from a file to another file via streams +const r = await Deno.open("input.txt"); +const w = await Deno.open("output.txt", { + create: true, + write: true, + truncate: true, +}); +await copy(r, w); +r.close(); +w.close(); + +// Convert a ReadableStreamDefaultReader to a Deno.Reader +const res = await fetch("https://deno.land"); +const denoReader = readerFromStreamReader(res.body!.getReader()); +await writeAll( + Deno.stdout, + new Uint8Array(await new Response(denoReader).arrayBuffer()), +); +``` + +## Tips + +- Prefer streaming for large payloads to reduce memory pressure. +- Use helpers like `toText`, `toArrayBuffer`, and `iterateReader` for + conversions. + + diff --git a/runtime/reference/std/tar.md b/runtime/reference/std/tar.md new file mode 100644 index 000000000..4bebdf6a8 --- /dev/null +++ b/runtime/reference/std/tar.md @@ -0,0 +1,94 @@ +--- +title: "@std/tar" +description: "Streaming utilities for working with tar archives." +jsr: jsr:@std/tar +pkg: tar +version: 0.1.9 +generated: true +stability: unstable +--- + + + +:::info Unstable + +This @std package is experimental and its API may change without a major version +bump. + +::: + +## Overview + +

Streaming utilities for working with tar archives.

+

Files are not compressed, only collected into the archive.

+ +```js +import { UntarStream } from "@std/tar/untar-stream"; +import { dirname, normalize } from "@std/path"; + +for await ( + const entry of (await Deno.open("./out.tar.gz")) + .readable + .pipeThrough(new DecompressionStream("gzip")) + .pipeThrough(new UntarStream()) +) { + const path = normalize(entry.path); + await Deno.mkdir(dirname(path), { recursive: true }); + await entry.readable?.pipeTo((await Deno.create(path)).writable); +} +``` + +### Add to your project + +```sh +deno add jsr:@std/tar +``` + +See all symbols +in @std/tar on + + + + +## What is tar? + +Tar (tape archive) is a widely-used file format for collecting multiple files +into a single archive file, often for easier distribution or backup. It +preserves file metadata like permissions and timestamps, making it suitable for +system backups and software distribution. + +## Why use @std/tar? + +Use this package to create or extract tar archives in a streaming fashion, which +is efficient for large datasets and avoids high memory usage. + +- This module is streaming-first: use Web Streams to read/write entries without + buffering whole archives. +- Security: sanitize entry paths and guard against path traversal (".." + segments) before writing to disk. +- Tar is an archive format, not compression. Layer + `CompressionStream`/`DecompressionStream` for gzip. +- Preserve permissions/mtime if present in headers when extracting to maintain + fidelity. + +## Examples + +```ts +import { UntarStream } from "@std/tar/untar-stream"; +import { dirname, isAbsolute, normalize } from "@std/path"; + +const outDir = "/safe/root"; + +for await (const entry of file.readable.pipeThrough(new UntarStream())) { + const normalized = normalize(entry.path); + // Prevent writing outside outDir + if (normalized.includes("..") || isAbsolute(normalized)) continue; + const dest = `${outDir}/${normalized}`; + await Deno.mkdir(dirname(dest), { recursive: true }); + if (entry.readable) { + await entry.readable.pipeTo((await Deno.create(dest)).writable); + } +} +``` + + diff --git a/runtime/reference/std/testing.md b/runtime/reference/std/testing.md new file mode 100644 index 000000000..837383a25 --- /dev/null +++ b/runtime/reference/std/testing.md @@ -0,0 +1,161 @@ +--- +title: "@std/testing" +description: "Tools for testing Deno code like snapshot testing, bdd testing, and time mocking" +jsr: jsr:@std/testing +pkg: testing +version: 1.0.16 +generated: true +stability: stable +--- + + + +## Overview + +

This package provides utilities for testing.

+ + +```js +import { assertSpyCalls, spy } from "@std/testing/mock"; +import { FakeTime } from "@std/testing/time"; + +function secondInterval(cb: () => void): number { + return setInterval(cb, 1000); +} + +Deno.test("secondInterval calls callback every second and stops after being cleared", () => { + using time = new FakeTime(); + + const cb = spy(); + const intervalId = secondInterval(cb); + assertSpyCalls(cb, 0); + time.tick(500); + assertSpyCalls(cb, 0); + time.tick(500); + assertSpyCalls(cb, 1); + time.tick(3500); + assertSpyCalls(cb, 4); + + clearInterval(intervalId); + time.tick(1000); + assertSpyCalls(cb, 4); +}); +``` + +### Add to your project + +```sh +deno add jsr:@std/testing +``` + +See all +symbols in @std/testing on + + + + +## Testing + +Testing is the practice of verifying that your code behaves as expected. It +helps catch bugs early, ensures code quality, and provides confidence when +making changes. + +Check out the [Deno testing examples](/examples/#testing) for practical usage. + +## Why use @std/testing + +Use these utilities alongside Deno’s built-in `Deno.test` to write clearer +specs, mock dependencies, fake timers, and create snapshots. + +## Examples + +```ts +import { afterEach, beforeEach, describe, it } from "@std/testing/bdd"; +import { assertSpyCalls, spy } from "@std/testing/mock"; +import { FakeTime } from "@std/testing/time"; + +describe("interval", () => { + let time: FakeTime; + beforeEach(() => (time = new FakeTime())); + afterEach(() => time.restore()); + + it("ticks", () => { + const cb = spy(); + const id = setInterval(cb, 1000); + time.tick(3000); + assertSpyCalls(cb, 3); + clearInterval(id); + }); +}); +``` + +### Snapshot testing + +```ts +import { assertSnapshot } from "@std/testing/snapshot"; + +Deno.test("user json snapshot", async (t) => { + const user = { id: 1, name: "Ada", tags: ["admin", "ops"] }; + await assertSnapshot(t, user); +}); +``` + +### Stub a global method + +```ts +import { stub } from "@std/testing/mock"; +import { assertEquals } from "@std/assert"; + +Deno.test("stub Math.random", () => { + const s = stub(Math, "random", () => 0.5); + try { + assertEquals(Math.random(), 0.5); + } finally { + s.restore(); + } +}); +``` + +### Program a sequence with returnsNext + +```ts +import { returnsNext } from "@std/testing/mock"; +import { assertEquals, assertThrows } from "@std/assert"; + +Deno.test("returnsNext sequences values and errors", () => { + const next = returnsNext([1, 2, new Error("boom"), 3]); + assertEquals(next(), 1); + assertEquals(next(), 2); + assertThrows(() => next(), Error, "boom"); + assertEquals(next(), 3); +}); +``` + +### Spy and assert call arguments + +```ts +import { assertSpyCallArgs, assertSpyCalls, spy } from "@std/testing/mock"; + +Deno.test("spy captures calls and args", () => { + const sum = spy((a: number, b: number) => a + b); + sum(3, 4); + sum(5, 6); + assertSpyCalls(sum, 2); + assertSpyCallArgs(sum, 0, [3, 4]); +}); +``` + +## Tips + +- Combine with `@std/assert` or `@std/expect` for assertions. +- Use `FakeTime` to deterministically test timers and `Date.now()`. +- Restore stubs/spies in `afterEach` or `finally` blocks to avoid leaking state. +- Commit snapshot files to version control to catch unintentional changes. + + diff --git a/runtime/reference/std/text.md b/runtime/reference/std/text.md new file mode 100644 index 000000000..ece55037e --- /dev/null +++ b/runtime/reference/std/text.md @@ -0,0 +1,117 @@ +--- +title: "@std/text" +description: "Utilities for working with text" +jsr: jsr:@std/text +pkg: text +version: 1.0.16 +generated: true +stability: stable +--- + + + +## Overview + +

Utility functions for working with text.

+ +```js +import { compareSimilarity, toCamelCase } from "@std/text"; +import { assertEquals } from "@std/assert"; + +assertEquals(toCamelCase("snake_case"), "snakeCase"); + +const words = ["hi", "help", "hello"]; + +// Words most similar to "hep" will be at the front +assertEquals(words.sort(compareSimilarity("hep")), ["help", "hi", "hello"]); +``` + +### Add to your project + +```sh +deno add jsr:@std/text +``` + +See all symbols +in @std/text on + + + + +## Why use @std/text? + +Reach for it when you need reliable, well-tested text manipulation utilities +such as case conversions, string similarity, and common text ops. + +## Examples + +```ts +import { compareSimilarity, toKebabCase } from "@std/text"; + +console.log(toKebabCase("HelloWorld")); + +const candidates = ["install", "init", "info"]; +console.log(candidates.sort(compareSimilarity("in"))); +``` + +### Find the closest suggestion + +```ts +import { closestString } from "@std/text/closest-string"; + +const options = ["length", "size", "help"]; +console.log(closestString("hep", options)); // "help" +``` + +### Compute edit distance + +```ts +import { levenshteinDistance } from "@std/text"; + +console.log(levenshteinDistance("kitten", "sitting")); // 3 +``` + +### Sort a list by similarity + +```ts +import { wordSimilaritySort } from "@std/text"; + +const cmds = ["install", "init", "info", "inspect"]; +console.log(wordSimilaritySort("in", cmds)); +// e.g., ["init", "info", "install", "inspect"] +``` + +### Dedent a multiline string (unstable) + +```ts +import { dedent } from "@std/text/unstable-dedent"; + +const msg = dedent` + Line one + Line two + Line three +`; +console.log(msg); +// "Line one\n Line two\nLine three\n" +``` + +### Unicode-aware reverse (unstable) + +```ts +import { reverse } from "@std/text/unstable-reverse"; + +console.log(reverse("mañana")); // "anañam" +// Preserve grapheme clusters like emoji sequences +console.log(reverse("👩‍❤️‍💋‍👨", { handleUnicode: true })); +``` + +## Tips + +- Use similarity comparisons for CLI fuzzy matching and suggestions. +- Prefer these utils over ad-hoc regex when readability matters. +- Use `closestString()` when you need one best suggestion; use + `wordSimilaritySort()` to rank many. +- Some utilities are marked unstable; import them via `@std/text/unstable-*` and + expect potential API changes. + + diff --git a/runtime/reference/std/toml.md b/runtime/reference/std/toml.md new file mode 100644 index 000000000..9556ec49e --- /dev/null +++ b/runtime/reference/std/toml.md @@ -0,0 +1,144 @@ +--- +title: "@std/toml" +description: "Parsing and serializing of TOML files" +jsr: jsr:@std/toml +pkg: toml +version: 1.0.11 +generated: true +stability: stable +--- + + + +## Overview + +

parse and stringify for handling +TOML encoded data.

+

Be sure to read the supported types as not every spec is supported at the +moment and the handling in TypeScript side is a bit different.

+

+Supported types and handling

+ +

Supported with warnings see Warning.

+

+Warning

+

+String

+

Due to the spec, there is no flag to detect regex properly in a TOML +declaration. So the regex is stored as string.

+

+Integer

+

For Binary / Octal / Hexadecimal numbers, they are stored as string +to be not interpreted as Decimal.

+

+Local Time

+

Because local time does not exist in JavaScript, the local time is stored as a +string.

+

+Array of Tables

+

At the moment only simple declarations like below are supported:

+ +```js +[[bin]]; +name = "deno"; +path = "cli/main.rs"[[bin]]; +name = "deno_core"; +path = "src/foo.rs"[[nib]]; +name = "node"; +path = "not_found"; +``` + +

will output:

+ +```js +{ + "bin": [ + { "name": "deno", "path": "cli/main.rs" }, + { "name": "deno_core", "path": "src/foo.rs" } + ], + "nib": [{ "name": "node", "path": "not_found" }] +} +``` + +```js +import { parse, stringify } from "@std/toml"; +import { assertEquals } from "@std/assert"; + +const obj = { + bin: [ + { name: "deno", path: "cli/main.rs" }, + { name: "deno_core", path: "src/foo.rs" }, + ], + nib: [{ name: "node", path: "not_found" }], +}; + +const tomlString = stringify(obj); +assertEquals( + tomlString, + ` +[[bin]] +name = "deno" +path = "cli/main.rs" + +[[bin]] +name = "deno_core" +path = "src/foo.rs" + +[[nib]] +name = "node" +path = "not_found" +`, +); + +const tomlObject = parse(tomlString); +assertEquals(tomlObject, obj); +``` + +### Add to your project + +```sh +deno add jsr:@std/toml +``` + +See all symbols +in @std/toml on + + + + +## What is TOML? + +TOML (Tom's Obvious, Minimal Language) is a configuration file format that is +easy to read due to its simple syntax. It supports various data types like +strings, numbers, booleans, dates, arrays, and tables, making it versatile for +configurations. + +## Why use @std/toml? + +This module provides a simple and efficient way to parse and stringify TOML data +in JavaScript. Use it to read configuration files or generate TOML content +programmatically. + +## Tips + +- Mind the supported types: some TOML constructs are represented as strings in + JS. +- Use arrays-of-tables for repeated sections; keep structures simple for + clarity. + + diff --git a/runtime/reference/std/ulid.md b/runtime/reference/std/ulid.md new file mode 100644 index 000000000..8f8408718 --- /dev/null +++ b/runtime/reference/std/ulid.md @@ -0,0 +1,82 @@ +--- +title: "@std/ulid" +description: "Generation of Universally Unique Lexicographically Sortable Identifiers (ULIDs)" +jsr: jsr:@std/ulid +pkg: ulid +version: 1.0.0 +generated: true +stability: stable +--- + + + +## Overview + +

Utilities for generating and working with +Universally Unique Lexicographically Sortable Identifiers (ULIDs).

+

To generate a ULID use the ulid function. This will generate a +ULID based on the current time.

+ +```js +import { ulid } from "@std/ulid"; + +ulid(); // 01HYFKMDF3HVJ4J3JZW8KXPVTY +``` + +

ulid does not guarantee that the ULIDs will be strictly +increasing for the same current time. If you need to guarantee that the ULIDs +will be strictly increasing, even for the same current time, use the +monotonicUlid function.

+ +```js +import { monotonicUlid } from "@std/ulid"; + +monotonicUlid(); // 01HYFKHG5F8RHM2PM3D7NSTDAS +monotonicUlid(); // 01HYFKHG5F8RHM2PM3D7NSTDAT +``` + +

Because each ULID encodes the time it was generated, you can extract the +timestamp from a ULID using the decodeTime function.

+ +```js +import { decodeTime, ulid } from "@std/ulid"; +import { assertEquals } from "@std/assert"; + +const timestamp = 150_000; +const ulidString = ulid(timestamp); + +assertEquals(decodeTime(ulidString), timestamp); +``` + +### Add to your project + +```sh +deno add jsr:@std/ulid +``` + +See all symbols +in @std/ulid on + + + + +## What is a ULID? + +A ULID (Universally Unique Lexicographically Sortable Identifier) is a +26-character string that serves as a unique identifier. It combines a timestamp +with random data, making it both unique and sortable based on the time of +creation. ULIDs are designed to be URL-safe and can be used in various +applications, such as databases and distributed systems. + +## Why use @std/ulid? + +Use when you need unique, time-sortable IDs that are easy to generate and share. +Great for databases, distributed systems, and user-facing tokens. + +## Tips + +- Use `monotonicUlid()` when you need strictly increasing values within the same + millisecond. +- You can extract the timestamp with `decodeTime(ulid)` to aid debugging. + + diff --git a/runtime/reference/std/uuid.md b/runtime/reference/std/uuid.md new file mode 100644 index 000000000..b62b955e2 --- /dev/null +++ b/runtime/reference/std/uuid.md @@ -0,0 +1,74 @@ +--- +title: "@std/uuid" +description: "Generators and validators for UUIDs" +jsr: jsr:@std/uuid +pkg: uuid +version: 1.0.9 +generated: true +stability: stable +--- + + + +## Overview + +

Generators and validators for +RFC 9562 UUIDs for +versions v1, v3, v4, v5, v6 and v7.

+

Use the built-in +crypto.randomUUID() +function instead of this package, if you only need to generate v4 UUIDs.

+

Based on npm:uuid.

+ +```js +import { NAMESPACE_DNS, NIL_UUID, v5 } from "@std/uuid"; +import { assert, assertFalse } from "@std/assert"; + +const data = new TextEncoder().encode("deno.land"); +const uuid = await v5.generate(NAMESPACE_DNS, data); + +assert(v5.validate(uuid)); +assertFalse(v5.validate(NIL_UUID)); +``` + +### Add to your project + +```sh +deno add jsr:@std/uuid +``` + +See all symbols +in @std/uuid on + + + + +## What is a UUID? + +A UUID (Universally Unique Identifier) is a 128-bit identifier used to uniquely +identify information in computer systems. UUIDs are designed to be globally +unique, meaning that the probability of two UUIDs being the same is extremely +low, even if they are generated independently in different systems. This makes +UUIDs useful for a variety of applications, such as database keys, session +identifiers, and distributed computing, where unique identification is crucial. + +### Why use @std/uuid? + +To generate or validate UUIDs across versions (v1, v3, v4, v5, v6, v7). Prefer +built-in `crypto.randomUUID()` if you only need v4. + +### Examples + +```ts +import { v4 } from "@std/uuid"; + +const id = v4.generate(); +console.log(v4.validate(id)); // true +``` + +### Tips + +- Namespaced IDs: use v3/v5 for deterministic IDs based on a name + namespace. +- Time-ordered IDs: consider v6/v7 for better index locality. + + diff --git a/runtime/reference/std/webgpu.md b/runtime/reference/std/webgpu.md new file mode 100644 index 000000000..589cde34c --- /dev/null +++ b/runtime/reference/std/webgpu.md @@ -0,0 +1,167 @@ +--- +title: "@std/webgpu" +description: "Utilities for working with the Web GPU API" +jsr: jsr:@std/webgpu +pkg: webgpu +version: 0.224.9 +generated: true +stability: unstable +--- + + + +:::info Unstable + +This @std package is experimental and its API may change without a major version +bump. + +::: + +## Overview + +

Utilities for interacting with the +WebGPU API.

+ +```js +import { createTextureWithData } from "@std/webgpu"; + +const adapter = await navigator.gpu.requestAdapter(); +const device = await adapter?.requestDevice()!; + +createTextureWithData(device, { + format: "bgra8unorm-srgb", + size: { + width: 3, + height: 2, + }, + usage: GPUTextureUsage.COPY_SRC, +}, new Uint8Array([1, 1, 1, 1, 1, 1, 1])); +``` + +### Add to your project + +```sh +deno add jsr:@std/webgpu +``` + +See all +symbols in @std/webgpu on + + + + +## What is the WebGPU API? + +WebGPU is a modern graphics API that provides high-performance 3D graphics and +computation capabilities in web applications. It is designed to be a successor +to WebGL, offering lower-level access to GPU hardware and improved performance +for complex graphics and compute tasks. + +## Why use @std/webgpu? + +Use for common WebGPU patterns and utilities to simplify setup and resource +management: + +- Request the adapter/device once and reuse; feature/limit negotiation up front + avoids runtime failures. +- Set texture `usage` bits to match all intended operations (COPY_SRC, COPY_DST, + TEXTURE_BINDING, RENDER_ATTACHMENT). +- Prefer `device.queue.writeBuffer`/`writeTexture` for small uploads; use + staging buffers for large transfers. + +## Examples + +### Writing to a buffer + +```ts +const buf = device.createBuffer({ + size: 16, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM, +}); +device.queue.writeBuffer(buf, 0, new Uint32Array([1, 2, 3, 4])); +``` + +### Describe a texture format + +```ts +import { describeTextureFormat } from "@std/webgpu"; + +const info = describeTextureFormat("rgba8unorm"); +console.log(info.sampleType); // e.g. "float" +console.log(info.allowedUsages.includes(GPUTextureUsage.RENDER_ATTACHMENT)); +console.log(info.blockSize, info.blockDimensions); // bytes per block and block size +``` + +### Copy a texture to a buffer (with padding) + +```ts +import { + describeTextureFormat, + getRowPadding, + resliceBufferWithPadding, +} from "@std/webgpu"; + +const format: GPUTextureFormat = "rgba8unorm"; +const size = { width: 320, height: 200 }; +const tex = device.createTexture({ + format, + size, + usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT, +}); + +// Compute bytesPerRow with required alignment for buffer copies +const { blockSize, blockDimensions } = describeTextureFormat(format); +const bytesPerPixel = blockSize / + (blockDimensions.width * blockDimensions.height); +const { padded: bytesPerRow } = getRowPadding(size.width * bytesPerPixel); +const bufferSize = bytesPerRow * size.height; + +const out = device.createBuffer({ + size: bufferSize, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ, +}); + +const encoder = device.createCommandEncoder(); +encoder.copyTextureToBuffer( + { texture: tex }, + { buffer: out, bytesPerRow, rowsPerImage: size.height }, + size, +); +device.queue.submit([encoder.finish()]); + +await out.mapAsync(GPUMapMode.READ); +const padded = out.getMappedRange(); +const pixels = resliceBufferWithPadding( + new Uint8Array(padded), + bytesPerRow, + size, +); +// `pixels` is tightly packed RGBA rows, suitable for encoding/saving +``` + +### Capture a render target into a buffer + +```ts +import { createCapture } from "@std/webgpu"; + +const { texture, outputBuffer } = createCapture(device, { + size: { width: 256, height: 256 }, + format: "rgba8unorm", +}); + +// draw to `texture` as a color attachment, then copy it into `outputBuffer` internally +// later map the buffer to read pixels +await outputBuffer.mapAsync(GPUMapMode.READ); +const data = new Uint8Array(outputBuffer.getMappedRange()); +// use `data`... +``` + +## Tips + +- Check for WebGPU support with `if (!navigator.gpu) { ... }`. +- Request the adapter/device once and reuse; feature/limit negotiation up front + avoids runtime failures. +- Set texture `usage` bits to match all intended operations (COPY_SRC, COPY_DST, + TEXTURE_BINDING, RENDER_ATTACHMENT). + + diff --git a/runtime/reference/std/yaml.md b/runtime/reference/std/yaml.md new file mode 100644 index 000000000..90fb2f054 --- /dev/null +++ b/runtime/reference/std/yaml.md @@ -0,0 +1,202 @@ +--- +title: "@std/yaml" +description: "Parsing and serializing of YAML files" +jsr: jsr:@std/yaml +pkg: yaml +version: 1.0.10 +generated: true +stability: stable +--- + + + +## Overview + +

parse and stringify for handling +YAML encoded data.

+

Ported from +js-yaml v3.13.1.

+

Use parseAll for parsing multiple documents in a single YAML +string.

+

This package generally supports +YAML 1.2.x (latest) and some +YAML 1.1 features that are +commonly used in the wild.

+

Supported YAML 1.1 features include:

+
    +
  • Merge type (<< symbol)
  • +
+

Unsupported YAML 1.1 features include:

+
    +
  • Yes, No, On, Off literals for bool type
  • +
  • Sexagesimal numbers (e.g. 3:25:45)
  • +
+ +```js +import { parse, stringify } from "@std/yaml"; +import { assertEquals } from "@std/assert"; + +const data = parse(` +foo: bar +baz: + - qux + - quux +`); +assertEquals(data, { foo: "bar", baz: ["qux", "quux"] }); + +const yaml = stringify({ foo: "bar", baz: ["qux", "quux"] }); +assertEquals( + yaml, + `foo: bar +baz: + - qux + - quux +`, +); +``` + +

+Limitations

+
    +
  • binary type is currently not stable.
  • +
+ +### Add to your project + +```sh +deno add jsr:@std/yaml +``` + +See all symbols +in @std/yaml on + + + + +## What is YAML? + +YAML (YAML Ain't Markup Language) is a human-readable data serialization format +commonly used for configuration files and data exchange between languages with +different data structures. It emphasizes simplicity and readability, making it +easy for humans to write and understand. + +### Why use @std/yaml? + +YAML is great for configuration files and data exchange where human readability +is a priority. Use it when you need to represent complex data structures in a +way that is easy to read and edit by humans. This module provides simple +functions to parse and serialize YAML data. + +## Examples + +### Read a config file (with errors handled) + +```js +import { parse } from "@std/yaml"; + +const raw = await Deno.readTextFile("config.yaml"); +let config; +try { + config = parse(raw); +} catch (err) { + if (err instanceof SyntaxError) { + console.error("Invalid YAML:", err.message); + } + throw err; +} + +// Narrow/validate as needed before using +if ( + typeof config === "object" && config !== null && + "port" in config && typeof config.port === "number" +) { + console.log("Listening on", config.port); +} +``` + +### Multiple documents in one file + +```js +import { parseAll } from "@std/yaml"; + +const docs = parseAll(` +--- +name: dev +port: 3000 +--- +name: prod +port: 80 +`); + +// e.g. map env name to port +const envToPort = Object.fromEntries(docs.map((d) => [d.name, d.port])); +console.log(envToPort.dev, envToPort.prod); +``` + +### Stringify with stable diffs (sorted keys, wrapped lines) + +```js +import { stringify } from "@std/yaml"; + +const data = { + name: "service", + description: "An example that demonstrates how long lines can be wrapped.", + tags: ["alpha", "beta", "gamma"], + nested: { z: 1, a: 2, m: 3 }, +}; + +const yaml = stringify(data, { sortKeys: true, lineWidth: 60, indent: 2 }); +console.log(yaml); +``` + +### YAML anchors and merge keys (YAML 1.1) + +```js +import { parse } from "@std/yaml"; + +const cfg = parse(` +defaults: &base + retries: 3 + timeout: 5s + +serviceA: + <<: *base + timeout: 10s + +serviceB: + <<: *base +`); + +console.log(cfg.serviceA.timeout); // "10s" +console.log(cfg.serviceB.retries); // 3 +``` + +### Skip unsupported values when stringifying + +```js +import { stringify } from "@std/yaml"; + +const obj = { ok: 1, skipMe: () => {} }; +// By default, functions cause a TypeError. Use skipInvalid to omit them. +const yaml = stringify(obj, { skipInvalid: true }); +console.log(yaml); +``` + +### Write YAML back to disk + +```js +import { stringify } from "@std/yaml"; + +const settings = { port: 8080, features: { a: true, b: false } }; +await Deno.writeTextFile("settings.yaml", stringify(settings, { indent: 2 })); +``` + +## Tips + +- Use `parseAll` when you expect multiple YAML documents in one string. +- Prefer JSON for machine↔machine interchange; YAML is great for hand-edited + config. +- For stable diffs in VCS, set `sortKeys: true` and a fixed `indent`/`lineWidth` + when using `stringify`. + + diff --git a/scripts/generate_std_docs.ts b/scripts/generate_std_docs.ts new file mode 100644 index 000000000..5665c45f2 --- /dev/null +++ b/scripts/generate_std_docs.ts @@ -0,0 +1,355 @@ +#!/usr/bin/env -S deno run -A +/** + * Generates Standard Library package documentation pages under + * `runtime/reference/std/`. + * + * Data sources: + * - List of packages: https://jsr.io/api/scopes/std/packages + * - Package docs HTML (overview): https://jsr.io/api/scopes/std/packages//versions//docs + * We extract the first
...
inner HTML and convert + * to markdown (JSR already returns markdown-rendered HTML; we keep as HTML fragment). + * + * Each generated page: + * frontmatter: title, description (first paragraph text), jsr, pkg, version, autogenerated flag + * body: (1) Overview fragment (HTML) (2) Optional override markdown appended + * from `runtime/reference/std/_overrides/.md` (if present) + * + * Additionally generates an index page `runtime/reference/std/index.md` listing + * all discovered packages with short description from the API list. + * + * All pages are generated in place. To add persistent custom content, use + * the ... block or an override file. + */ + +// Using JSR std modules (available via deno.json imports mapping) +import { ensureDir } from "@std/fs"; +import { fromFileUrl, join } from "@std/path"; + +interface PackageSummary { + name: string; + latestVersion: string; // derived + description?: string; +} + +interface PackageApiEntry { + scope: string; // "std" + name: string; // package name without @std/ + description?: string; + versions?: { tag: string; createdAt: string }[]; // Not currently returned in list endpoint + latestVersion: string; // present in list response +} + +// Derive repo root (the workspace 'docs' directory). Script lives in /scripts/, so one level up. +const REPO_ROOT = fromFileUrl(new URL("../", import.meta.url)); +const STD_ROOT = join(REPO_ROOT, "runtime", "reference", "std"); +const GENERATED_DIR = STD_ROOT; // Emit pages directly for clean /std// paths +const OVERRIDES_DIR = join(STD_ROOT, "_overrides"); + +async function fetchJson(url: string): Promise { + const res = await fetch(url); + if (!res.ok) throw new Error(`Fetch failed ${url} ${res.status}`); + return await res.json() as T; +} + +async function fetchText(url: string): Promise { + const res = await fetch(url); + if (!res.ok) throw new Error(`Fetch failed ${url} ${res.status}`); + return await res.text(); +} + +function extractFirstMarkdownDiv(html: string): string | null { + // More permissive: allow attributes ordering and additional classes. + const match = html.match( + /]*class=\"markdown\"[^>]*>([\s\S]*?)<\/div>/, + ); + if (!match) return null; + const fragment = match[1].trim(); + return fragment; +} + +// Remove UI-only markup (copy buttons, inline SVG icons) and stray empty tags +function sanitizeOverviewHtml(html: string): string { + let out = html; + // 1) Remove copy buttons injected by JSR docs (match on class copyButton) + out = out.replace( + /]*class=(?:"|')?[^"'>]*copyButton[^"'>]*(?:"|')?[^>]*>[\s\S]*?<\/button>/gi, + "", + ); + // 2) Remove any remaining inline SVGs (commonly the copy/check icons) + out = out.replace(/]*>[\s\S]*?<\/svg>/gi, ""); + // 3) Remove empty code tags (sometimes left behind after removing button) + out = out.replace(/]*>\s*<\/code>/gi, ""); + // 4) Prefix relative anchors with absolute JSR origin + // Converts href="/path" -> href="https://jsr.io/path" (preserves quote style) + out = out.replace( + /href=(["'])\/(?!\/)([^"']*)\1/gi, + (_m, q, p) => `href=${q}https://jsr.io/${p}${q}`, + ); + // 5) Convert
...
to fenced Markdown ```js blocks + const decodeHtml = (s: string) => + s + .replace(/&#x([0-9a-fA-F]+);/g, (_m, h) => + String.fromCharCode(parseInt(h, 16))) + .replace(/&#(\d+);/g, (_m, d) => + String.fromCharCode(parseInt(d, 10))) + .replace(/</g, "<") + .replace(/>/g, ">") + .replace(/&/g, "&") + .replace(/"/g, '"') + .replace(/'/g, "'"); + + out = out.replace( + /]*>\s*]*>([\s\S]*?)<\/code>\s*<\/pre>/gi, + (_m, inner) => { + const noTags = inner.replace(/<[^>]+>/g, ""); + const decoded = decodeHtml(noTags).replace(/\r\n/g, "\n"); + const trimmed = decoded.replace(/^\n+|\n+$/g, ""); + return `\n\n\`\`\`js\n${trimmed}\n\`\`\`\n\n`; + }, + ); + + // 6) Tidy up excessive blank lines + out = out.replace(/\n{3,}/g, "\n\n"); + return out.trim(); +} + +function deriveTitle(pkg: string): string { + // e.g., "assert" -> "@std/assert" + switch (pkg) { + case "assert": + return "Standard Assertions (@std/assert)"; // keep consistent with handcrafted page + default: + return `@std/${pkg}`; + } +} + +async function generatePackagePage(pkg: PackageSummary) { + const { name, latestVersion } = pkg; + // (Legacy skip logic removed; we always regenerate the page.) + + // If an override exists for this package, use it to fully replace the page. + // This allows complete editorial control (including frontmatter and body). + const overridePath = join(OVERRIDES_DIR, `${name}.md`); + try { + const overrideRaw = await Deno.readTextFile(overridePath); + await ensureDir(GENERATED_DIR); + const outPath = join(GENERATED_DIR, `${name}.md`); + await Deno.writeTextFile(outPath, overrideRaw); + console.log(`✍️ Wrote override ${outPath}`); + return; + } catch (_) { + // No override present; proceed with generation. + } + + const docsUrl = + `https://jsr.io/api/scopes/std/packages/${name}/versions/${latestVersion}/docs`; + let overviewHtml: string | null = null; + try { + // The docs endpoint returns JSON with keys: kind, version, css, comrakCss, script, breadcrumbs, toc, main, etc. + const raw = await fetchText(docsUrl); + let parsed: Record | null = null; + try { + parsed = JSON.parse(raw); + } catch (_) { + // Not JSON (unexpected) fallback treat as HTML + } + if ( + parsed && typeof parsed === "object" && typeof parsed["main"] === "string" + ) { + const mainHtml = String(parsed["main"]); + // In main section look for first markdown div. + overviewHtml = extractFirstMarkdownDiv(mainHtml) ?? null; + if (!overviewHtml) { + // Some packages may have the overview inside toc usage content; fallback search entire raw + overviewHtml = extractFirstMarkdownDiv(raw) ?? null; + } + } else { + // Fallback to legacy pattern + overviewHtml = extractFirstMarkdownDiv(raw); + } + } catch (err) { + const msg = err instanceof Error ? err.message : String(err); + console.warn(`⚠️ Failed to fetch docs for ${name}: ${msg}`); + } + + // No override: continue with generated content from JSR docs + + // (Legacy handcrafted append removed.) + + if (!overviewHtml) { + console.warn(`Skipping ${name} (no overview HTML)`); + return; + } + + // Derive a plain text first paragraph from overview for fallback only. + const overviewFirstParagraph = overviewHtml + .replace(/<[^>]+>/g, "\n") + .split(/\n+/) + .map((l) => l.trim()) + .filter(Boolean)[0] ?? ""; + + // Prefer the list API description for stability detection and description content. + const sourceDescription = (pkg as PackageSummary).description || + overviewFirstParagraph; + let stability: "unstable" | "internal" | "stable" = "stable"; + let normalizedDesc = sourceDescription; + if (/^UNSTABLE:/i.test(sourceDescription)) { + stability = "unstable"; + normalizedDesc = sourceDescription.replace(/^UNSTABLE:\s*/i, ""); + } else if (/^INTERNAL:/i.test(sourceDescription)) { + stability = "internal"; + normalizedDesc = sourceDescription.replace(/^INTERNAL:\s*/i, ""); + } + + const frontmatter = [ + "---", + `title: \"${deriveTitle(name)}\"`, + `description: \"${normalizedDesc.replaceAll(/"/g, '\\"').slice(0, 240)}\"`, + `jsr: jsr:@std/${name}`, + `pkg: ${name}`, + `version: ${latestVersion}`, + `generated: true`, + `stability: ${stability}`, + "---", + "", + ].join("\n"); + + // Attempt to extract any existing custom block from prior file (between markers) + const existingPath = join(GENERATED_DIR, `${name}.md`); + let preservedCustom = ""; + try { + const prev = await Deno.readTextFile(existingPath); + const m = prev.match(/([\s\S]*?)/); + if (m) { + preservedCustom = m[1].trim(); + } + } catch (_) { + // no previous file + } + + let body = frontmatter + + `\n\n`; + if (stability === "unstable") { + body += [ + ":::info Unstable", + "", + "This @std package is experimental and its API may change without a major version bump.", + "", + ":::", + "", + ].join("\n"); + } else if (stability === "internal") { + body += [ + ":::info Internal", + "", + "This @std package is for internal use and not intended for public consumption. APIs may change or be removed.", + "", + ":::", + "", + ].join("\n"); + } + body += `## Overview\n\n`; + // Sanitize UI-only elements from the overview HTML before writing + body += sanitizeOverviewHtml(overviewHtml) + "\n"; // keep HTML fragment + // Insert install instructions and JSR docs CTA after the overview + body += [ + "", + "### Add to your project", + "", + "```sh", + `deno add jsr:@std/${name}`, + "```", + "", + `See all symbols in @std/${name} on`, + ``, + "", + ].join("\n"); + + // Insert custom block placeholder or preserved content at end + if (preservedCustom) { + body += + `\n\n${preservedCustom}\n\n`; + } else { + body += + `\n\n\n\n\n`; + } + + await ensureDir(GENERATED_DIR); + const outPath = join(GENERATED_DIR, `${name}.md`); + await Deno.writeTextFile(outPath, body); + console.log(`✅ Generated ${outPath}`); +} + +async function generateIndex(packages: PackageSummary[]) { + const indexPath = join(STD_ROOT, "index.md"); + const rows: string[] = []; + for (const p of packages) { + const link = `./${p.name}/`; // folder-style link (Lume will map file.md -> /file/) + rows.push(`- [@std/${p.name}](${link}) – ${p.description ?? ""}`); + } + const generatedList = rows.join("\n"); + + // If an index already exists, only replace content between markers + try { + const existing = await Deno.readTextFile(indexPath); + const hasMarkers = /[\s\S]*/m + .test(existing); + if (hasMarkers) { + const updated = existing.replace( + /[\s\S]*?/m, + `\n${generatedList}\n`, + ); + await Deno.writeTextFile(indexPath, updated); + console.log(`🗂️ Updated package list in ${indexPath}`); + return; + } else { + console.log( + `ℹ️ ${indexPath} exists without markers. Skipping index overwrite. Add ... to enable auto-update.`, + ); + return; + } + } catch (_) { + // No existing file; write a default index with markers + } + + const content = [ + "---", + 'title: "Deno Standard Library (@std)"', + 'description: "Overview and guides for the modular Deno standard library packages on JSR."', + "---", + "", + "The Deno standard library is published as a set of modular JSR packages under the `@std` scope.", + "\n## Packages\n", + "", + generatedList, + "", + "", + "> This index and the individual package overview sections are generated. Add extra examples by creating files in `_overrides/.md`.", + ].join("\n"); + + await Deno.writeTextFile(indexPath, content); + console.log(`🗂️ Wrote index ${indexPath}`); +} + +async function main() { + console.log("Fetching std package list..."); + const listResponse = await fetchJson<{ items: PackageApiEntry[] }>( + "https://jsr.io/api/scopes/std/packages", + ); + const list = listResponse.items; + const summaries: PackageSummary[] = list.map((p) => ({ + name: p.name, + description: p.description, + latestVersion: p.latestVersion.replace(/^v/, ""), + })); + + // Generate each package page sequentially (can parallelize later) + for (const pkg of summaries) { + await generatePackagePage(pkg); + } + await generateIndex(summaries); +} + +if (import.meta.main) { + await main(); +} diff --git a/scripts/install-pre-commit-hook.sh b/scripts/install-pre-commit-hook.sh deleted file mode 100644 index 89b0a19da..000000000 --- a/scripts/install-pre-commit-hook.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -# Install pre-commit hook for link checking -# This script copies the pre-commit hook and makes it executable - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -HOOK_SOURCE="$SCRIPT_DIR/pre-commit" -HOOK_DEST="$REPO_ROOT/.git/hooks/pre-commit" - -echo "🚀 Installing pre-commit hook for link checking..." - -if [ ! -f "$HOOK_SOURCE" ]; then - echo "❌ Pre-commit hook source not found at $HOOK_SOURCE" - exit 1 -fi - -if [ ! -d "$REPO_ROOT/.git/hooks" ]; then - echo "❌ Git hooks directory not found. Are you in a git repository?" - exit 1 -fi - -# Backup existing pre-commit hook if it exists -if [ -f "$HOOK_DEST" ]; then - echo "📁 Backing up existing pre-commit hook..." - cp "$HOOK_DEST" "$HOOK_DEST.backup.$(date +%s)" -fi - -# Copy and make executable -cp "$HOOK_SOURCE" "$HOOK_DEST" -chmod +x "$HOOK_DEST" - -echo "✅ Pre-commit hook installed successfully!" -echo " The hook will check links whenever you commit markdown files." -echo " To disable temporarily, use: git commit --no-verify" -echo " To uninstall, delete: $HOOK_DEST" diff --git a/scripts/pre-commit b/scripts/pre-commit deleted file mode 100644 index 2f363f463..000000000 --- a/scripts/pre-commit +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# Pre-commit hook to check for broken links -# To install: cp scripts/pre-commit .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit - -echo "🔍 Running link checker before commit..." - -# Check if any markdown files were changed -CHANGED_MD_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(md|mdx)$' || true) - -if [ -n "$CHANGED_MD_FILES" ]; then - echo "📝 Markdown files changed, running link checker..." - echo "Changed files:" - echo "$CHANGED_MD_FILES" | sed 's/^/ - /' - echo - - # Run the local link checker - if ! deno task check:links:local; then - echo - echo "❌ Link checker failed! Please fix broken links before committing." - echo " You can run 'deno task check:links:local' to check links locally." - echo " Or run 'deno task dev' and manually verify the problematic links." - echo - echo " To skip this check, use: git commit --no-verify" - exit 1 - fi - - echo "✅ All links are working correctly!" -else - echo "ℹ️ No markdown files changed, skipping link check." -fi - -echo "✅ Pre-commit checks passed!" diff --git a/styles.css b/styles.css index 558d00025..f6de3b856 100644 --- a/styles.css +++ b/styles.css @@ -1662,8 +1662,8 @@ } .jsr-cta { - @apply bg-jsr-yellow-400 border-jsr-cyan-950 text-jsr-cyan-950! border-2 - hover:no-underline! hover:bg-jsr-yellow-300; + @apply bg-jsr-yellow-400 border-0 text-jsr-cyan-950! hover:no-underline! + hover:bg-jsr-yellow-400; } .deploy-button {