diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..df4d15b3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every week + interval: "weekly" diff --git a/.github/workflows/check-links.yml b/.github/workflows/check-links.yml index cd76ee58..25100509 100644 --- a/.github/workflows/check-links.yml +++ b/.github/workflows/check-links.yml @@ -11,7 +11,7 @@ jobs: broken-links: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Check Markdown Links uses: ruzickap/action-my-markdown-link-checker@v1 with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9edd1023..aa368ca8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,14 +7,25 @@ on: branches: [main] jobs: + typos: + name: spell-check + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - uses: crate-ci/typos@master + with: + config: ./typos.toml + format: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Deno - uses: denoland/setup-deno@v1.0.0 + uses: denoland/setup-deno@v1 - name: Format run: deno fmt --check @@ -23,10 +34,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up Deno - uses: denoland/setup-deno@v1.0.0 + uses: denoland/setup-deno@v1 - name: Type-check Deno manual run: deno test --doc --unstable --import-map=.github/import_map.json --no-check=remote diff --git a/.github/workflows/suggest-format.yml b/.github/workflows/suggest-format.yml index 972f73bc..e9f9bf0f 100644 --- a/.github/workflows/suggest-format.yml +++ b/.github/workflows/suggest-format.yml @@ -9,10 +9,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Deno - uses: denoland/setup-deno@v1.0.0 + uses: denoland/setup-deno@v1 - name: Format run: deno fmt diff --git a/.github/workflows/update-algolia.yml b/.github/workflows/update-algolia.yml index 2c366c5b..4189764e 100644 --- a/.github/workflows/update-algolia.yml +++ b/.github/workflows/update-algolia.yml @@ -13,10 +13,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Deno - uses: denoland/setup-deno@v1.0.0 + uses: denoland/setup-deno@v1 - name: Update Algolia working-directory: ./.tools diff --git a/.gitignore b/.gitignore index be47843e..3a4e9639 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .DS_Store .env +.vscode \ No newline at end of file diff --git a/README.md b/README.md index d90f2c1d..d937cc4c 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,8 @@ -# Deno Manual +# (DEPRECATED) Deno Manual -This repository is the official documentation for Deno, and it's available at: -https://deno.land/manual +This repository was formerly the home of the Deno manual, running at +deno.land/manual. The instructions below describe how to run the doc site and +preview changes. -## Contributing - -1. Clone this project and `dotland` in the same parent folder: - -``` -git clone https://github.com/denoland/manual.git -git clone https://github.com/denoland/dotland.git -``` - -2. Move into the `dotland` folder, and run the following command to start the - local `deno.land` website with the local manual contents: - -``` -cd dotland -MANUAL_PATH=../manual deno task start -``` - -When opening a PR, make sure the code is formatted correctly. To format the -code: - -1. Install Deno (https://deno.land/#installation) -2. Run `deno fmt` at the root of this repository - -Before creating new pages, open an issue and discuss the proposed changes. +**New contributions should be made to +[docs.deno.com](https://github.com/denoland/deno-docs)** diff --git a/advanced/continuous_integration.md b/advanced/continuous_integration.md index 7686285f..b5593814 100644 --- a/advanced/continuous_integration.md +++ b/advanced/continuous_integration.md @@ -33,7 +33,7 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 - - uses: denoland/setup-deno@v1.1.1 + - uses: denoland/setup-deno@v1 with: deno-version: v1.x # Run with latest stable Deno. ``` diff --git a/advanced/jsx_dom/css.md b/advanced/jsx_dom/css.md index 5fccd4c0..b57cd422 100644 --- a/advanced/jsx_dom/css.md +++ b/advanced/jsx_dom/css.md @@ -27,7 +27,7 @@ Then we will stringify the modified CSS AST and output it to the console: ```ts, ignore import * as css from "https://esm.sh/css@3.0.0"; -import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { assert } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; declare global { interface AbortSignal { diff --git a/advanced/jsx_dom/deno_dom.md b/advanced/jsx_dom/deno_dom.md index b9e5e786..0bac1171 100644 --- a/advanced/jsx_dom/deno_dom.md +++ b/advanced/jsx_dom/deno_dom.md @@ -1,7 +1,6 @@ # Using deno-dom with Deno [deno-dom](https://deno.land/x/deno_dom) is an implementation of DOM and HTML - parser in Deno. It is implemented in Rust (via Wasm) and TypeScript. There is also a "native" implementation, leveraging the FFI interface. @@ -21,7 +20,7 @@ first heading it encounters and print out the text content of that heading: ```ts import { DOMParser } from "https://deno.land/x/deno_dom/deno-dom-wasm.ts"; -import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { assert } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; const document = new DOMParser().parseFromString( ` diff --git a/advanced/jsx_dom/jsdom.md b/advanced/jsx_dom/jsdom.md index 18b1296a..acb6df20 100644 --- a/advanced/jsx_dom/jsdom.md +++ b/advanced/jsx_dom/jsdom.md @@ -66,7 +66,7 @@ first heading it encounters and print out the text content of that heading: ```ts, ignore import { JSDOM } from "jsdom"; -import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { assert } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; const { window: { document } } = new JSDOM( ` diff --git a/advanced/jsx_dom/linkedom.md b/advanced/jsx_dom/linkedom.md index 81e74b9a..21968a62 100644 --- a/advanced/jsx_dom/linkedom.md +++ b/advanced/jsx_dom/linkedom.md @@ -29,7 +29,7 @@ first heading it encounters and print out the text content of that heading: ```ts import { DOMParser } from "https://esm.sh/linkedom"; -import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { assert } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; const document = new DOMParser().parseFromString( ` diff --git a/advanced/language_server/overview.md b/advanced/language_server/overview.md index 76787789..5f31408a 100644 --- a/advanced/language_server/overview.md +++ b/advanced/language_server/overview.md @@ -143,7 +143,7 @@ with Deno: } ``` -- `deno/task` - Requests the return of avalaible deno tasks, see +- `deno/task` - Requests the return of available deno tasks, see [task_runner](../../tools/task_runner.md). It does not expect any parameters. diff --git a/advanced/typescript.md b/advanced/typescript.md index 33fc5b91..88c86ce3 100644 --- a/advanced/typescript.md +++ b/advanced/typescript.md @@ -1,6 +1,13 @@ # Using TypeScript -In this chapter we will discuss: +Deno not only supports TypeScript out of the box, but also treats TypeScript as +a first class language. This means the developer experience when authoring and +importing TypeScript will be as easy and straightforward as that of JavaScript. + +You can run or import TypeScript without installing anything more than the Deno +CLI. + +In this chapter, we'll discuss: - [Overview of TypeScript in Deno](./typescript/overview.md) - [Configuring TypeScript in Deno](./typescript/configuration.md) diff --git a/basics/connecting_to_databases.md b/basics/connecting_to_databases.md index 0ab31c10..e8fb08a7 100644 --- a/basics/connecting_to_databases.md +++ b/basics/connecting_to_databases.md @@ -267,7 +267,7 @@ console.log(`Started on http://localhost:3000`); To make GraphQL client calls in Deno, import the [graphql npm module](https://www.npmjs.com/package/graphql) with the [esm CDN](https://esm.sh/). To learn more about using npm modules in Deno via -CDN read [here](../node/cdns.md) +CDN read [here](../node/cdns.md). #### Make GraphQL client calls with the graphql npm module diff --git a/basics/import_maps.md b/basics/import_maps.md index 3a3ba680..d59142a3 100644 --- a/basics/import_maps.md +++ b/basics/import_maps.md @@ -40,7 +40,7 @@ written something similar in our `deno.json` configuration file: ## Example - Using deno_std's fmt module via `fmt/` -**import_map.json** +**deno.json** ```json { @@ -62,7 +62,7 @@ console.log(red("hello world")); To use your project root for absolute imports: -**import_map.json** +**deno.json** ```jsonc { diff --git a/basics/modules.md b/basics/modules.md index 9eee60a9..c6b8e184 100644 --- a/basics/modules.md +++ b/basics/modules.md @@ -136,7 +136,7 @@ The solution is to import and re-export your external libraries in a central `deps.ts` file (which serves the same purpose as Node's `package.json` file). For example, let's say you were using the above assertion library across a large project. Rather than importing -`"https://deno.land/std@$STD_VERSION/testing/asserts.ts"` everywhere, you could +`"https://deno.land/std@$STD_VERSION/assert/mod.ts"` everywhere, you could create a `deps.ts` file that exports the third-party code: **deps.ts** @@ -146,7 +146,7 @@ export { assert, assertEquals, assertStringIncludes, -} from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +} from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; ``` And throughout the same project, you can import from the `deps.ts` and avoid diff --git a/basics/modules/private.md b/basics/modules/private.md index da7ca724..ec86f8c3 100644 --- a/basics/modules/private.md +++ b/basics/modules/private.md @@ -1,31 +1,31 @@ # Private Modules and Repositories -There maybe instances where you want to load a remote module that is located in +There may be instances where you want to load a remote module that is located in a _private_ repository, like a private repository on GitHub. Deno supports sending bearer tokens when requesting a remote module. Bearer -tokens are the predominant type of access token used with OAuth 2.0 and is -broadly supported by hosting services (e.g. GitHub, Gitlab, BitBucket, +tokens are the predominant type of access token used with OAuth 2.0, and are +broadly supported by hosting services (e.g., GitHub, GitLab, Bitbucket, Cloudsmith, etc.). ## DENO_AUTH_TOKENS The Deno CLI will look for an environment variable named `DENO_AUTH_TOKENS` to determine what authentication tokens it should consider using when requesting -remote modules. The value of the environment variable is in the format of a _n_ -number of tokens deliminated by a semi-colon (`;`) where each token is either: +remote modules. The value of the environment variable is in the format of _n_ +number of tokens delimited by a semi-colon (`;`) where each token is either: -- a bearer token in the format of `{token}@{hostname[:port]}` +- a bearer token in the format of `{token}@{hostname[:port]}` or - basic auth data in the format of `{username}:{password}@{hostname[:port]}` -For example a single token for would look something like this: +For example, a single token for `deno.land` would look something like this: ```sh DENO_AUTH_TOKENS=a1b2c3d4e5f6@deno.land ``` -or +or: ```sh DENO_AUTH_TOKENS=username:password@deno.land @@ -46,9 +46,9 @@ modules on the server. ## GitHub -To be able to access private repositories on GitHub, you would need to issue -yourself a _personal access token_. You do this by logging into GitHub and going -under _Settings -> Developer settings -> Personal access tokens_: +To access private repositories on GitHub, you would need to issue yourself a +_personal access token_. You do this by logging into GitHub and going under +_Settings -> Developer settings -> Personal access tokens_: ![Personal access tokens settings on GitHub](../../images/private-pat.png) diff --git a/basics/permissions.md b/basics/permissions.md index 9fa1309a..0ec539f2 100644 --- a/basics/permissions.md +++ b/basics/permissions.md @@ -4,6 +4,18 @@ Deno is secure by default. Therefore, unless you specifically enable it, a program run with Deno has no file, network, or environment access. Access to security sensitive functionality requires that permissions have been granted to an executing script through command line flags, or a runtime permission prompt. +This is a major difference from Node, where dependencies are automatically +granting full access to everything, introducing hidden vulnerabilities in your +project. + +## Run untrusted code with confidence + +Since Deno provides no I/O access by default, it's useful for running untrusted +code and auditing third-party code. If you're building or extending a platform +that runs user generated code, you can use Deno for running third-party code +securely and host this code through +[Deno Subhosting](https://deno.com/subhosting) or any other cloud platform of +your choice. For the following example `mod.ts` has been granted read-only access to the file system. It cannot write to the file system, or perform any other security @@ -53,6 +65,41 @@ The following permissions are available: - **-A, --allow-all** Allow all permissions. This enables all security sensitive functions. Use with caution. +Starting with Deno 1.36 following flags are available: + +- **--deny-env=\** Deny environment access for things like + getting and setting of environment variables. You can specify an optional, + comma-separated list of environment variables to provide an allow-list of + allowed environment variables. Any environment variables specified here will + be denied access, even if they are specified in --allow-env. +- **--deny-sys=\** Deny access to APIs that provide information about + user's operating system. +- **--deny-hrtime** Disable high-resolution time measurement. High-resolution + time can be used in timing attacks and fingerprinting. +- **--deny-net=\** Disable network access. You can specify an + optional, comma-separated list of IP addresses or hostnames (optionally with + ports) to provide a deny-list of network addresses. Any addresses specified + here will be denied access, even if they are specified in --allow-net. +- **--deny-ffi=\** Deny loading of dynamic libraries. You can specify an + optional, comma-separated list of directories or files to provide a deny-list + of allowed dynamic libraries to load. Any libraries specified here will be + denied access, even if they are specified in --allow-ffi. Please note that + --deny-ffi is an unstable feature. +- **--deny-read=\** Deny file system read access. You can specify an + optional, comma-separated list of directories or files to provide a deny-list + of allowed file system access. Any paths specified here will be denied access, + even if they are specified in --allow-read. +- **--deny-run=\** Deny running subprocesses. You can specify an + optional, comma-separated list of subprocesses to provide a deny-list of + allowed subprocesses. Be aware that subprocesses are not run in a sandbox and + therefore do not have the same security restrictions as the Deno process. + Therefore, use with caution. Any programs specified here will be denied + access, even if they are specified in --allow-run. +- **--deny-write=\** Deny file system write access. You can specify an + optional, comma-separated list of directories or files to provide a deny-list + of allowed file system access. Any paths specified here will be denied access, + even if they are specified in --allow-write. + ## Configurable permissions Some permissions allow you to grant access to a specific list of entities @@ -65,7 +112,7 @@ This example restricts file system access by allowing read-only access to the attempting to read a file in the `/etc` directory: ```shell -$ deno run --allow-read=/usr https://deno.land/std@$STD_VERSION/examples/cat.ts /etc/passwd +$ deno run --allow-read=/usr https://deno.land/std@0.198.0/examples/cat.ts /etc/passwd error: Uncaught PermissionDenied: read access to "/etc/passwd", run again with the --allow-read flag ► $deno$/dispatch_json.ts:40:11 at DenoError ($deno$/errors.ts:20:5) @@ -76,7 +123,16 @@ Try it out again with the correct permissions by allowing access to `/etc` instead: ```shell -deno run --allow-read=/etc https://deno.land/std@$STD_VERSION/examples/cat.ts /etc/passwd +deno run --allow-read=/etc https://deno.land/std@0.198.0/examples/cat.ts /etc/passwd +``` + +You can further restrict some sub-paths to not be accessible, using +`--deny-read` flag: + +```shell +deno run --allow-read=/etc --deny-read=/etc/hosts https://deno.land/std@0.198.0/examples/cat.ts /etc/passwd +deno run --allow-read=/etc --deny-read=/etc/hosts https://deno.land/std@0.198.0/examples/cat.ts /etc/hosts +error: Uncaught PermissionDenied: read access to "/etc/hosts"... ``` `--allow-write` works the same as `--allow-read`. @@ -110,6 +166,14 @@ deno run --allow-net=1.1.1.1:443 fetch.js deno run --allow-net=[2606:4700:4700::1111] fetch.js ``` +You can restrict certain domains to never be accessible by using the +`--deny-net` flag: + +```shell +# Allow to make network connections to all addresses except myserver.com. +deno run --allow-net --deny-net=myserver.com fetch.js +``` + If `fetch.js` tries to establish network connections to any hostname or IP not explicitly allowed, the relevant call will throw an exception. @@ -139,6 +203,14 @@ deno run --allow-env=HOME env.js > Note for Windows users: environment variables are case insensitive on Windows, > so Deno also matches them case insensitively (on Windows only). +You can restrict certain env vars to never be accessible by using the +`--deny-env` flag: + +```shell +# Allow all environment variables except AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. +deno run --allow-env --deny-env=AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY env.js +``` + ### Subprocess permissions Subprocesses are very powerful, and can be a little scary: they access system @@ -170,3 +242,11 @@ deno run --allow-run run.js You can only limit the executables that are allowed; if permission is granted to execute it then any parameters can be passed. For example if you pass `--allow-run=cat` then the user can use `cat` to read any file. + +You can restrict certain executables to never be accessible by using the +`--deny-run` flag: + +```shell +# Disallow spawning `git`. +deno run --allow-run --deny-run=git run.js +``` diff --git a/basics/standard_library.md b/basics/standard_library.md index 881905e8..882ea08f 100644 --- a/basics/standard_library.md +++ b/basics/standard_library.md @@ -29,48 +29,3 @@ change: // imports from v$STD_VERSION of std, never changes import { copy } from "https://deno.land/std@$STD_VERSION/fs/copy.ts"; ``` - -## Troubleshooting - -Some of the modules provided in standard library use unstable Deno APIs. - -Trying to run such modules without `--unstable` CLI flag ends up with a lot of -TypeScript errors suggesting that some APIs in the `Deno` namespace do not -exist: - -```typescript -// main.ts -import { copy } from "https://deno.land/std@$STD_VERSION/fs/copy.ts"; - -copy("log.txt", "log-old.txt"); -``` - -```shell -$ deno run --allow-read --allow-write main.ts -Compile file:///dev/deno/main.ts -Download https://deno.land/std@$STD_VERSION/fs/copy.ts -Download https://deno.land/std@$STD_VERSION/fs/ensure_dir.ts -Download https://deno.land/std@$STD_VERSION/fs/_util.ts -error: TS2339 [ERROR]: Property 'utime' does not exist on type 'typeof Deno'. 'Deno.utime' is an unstable API. Did you forget to run with the '--unstable' flag? - await Deno.utime(dest, statInfo.atime, statInfo.mtime); - ~~~~~ - at https://deno.land/std@$STD_VERSION/fs/copy.ts:92:16 - -TS2339 [ERROR]: Property 'utimeSync' does not exist on type 'typeof Deno'. 'Deno.utimeSync' is an unstable API. Did you forget to run with the '--unstable' flag? - Deno.utimeSync(dest, statInfo.atime, statInfo.mtime); - ~~~~~~~~~ - at https://deno.land/std@$STD_VERSION/fs/copy.ts:103:10 -``` - -Solution to that problem requires adding `--unstable` flag: - -```shell -deno run --allow-read --allow-write --unstable main.ts -``` - -To make sure that API producing error is unstable check -[`lib.deno.unstable.d.ts`](https://github.com/denoland/deno/blob/$CLI_VERSION/cli/tsc/dts/lib.deno.unstable.d.ts) -declaration. - -This problem should be fixed in the near future. Feel free to omit the flag if -the particular modules you depend on compile successfully without it. diff --git a/basics/testing.md b/basics/testing.md index e91ed935..0cec1ca3 100644 --- a/basics/testing.md +++ b/basics/testing.md @@ -10,7 +10,7 @@ Firstly, let's create a file `url_test.ts` and register a test case using ```ts // url_test.ts -import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; Deno.test("url test", () => { const url = new URL("./foo.js", "https://deno.land/"); @@ -36,7 +36,7 @@ switching between the forms (eg. when you need to quickly focus a single test for debugging, using `only: true` option): ```ts -import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; // Compact form: name and function Deno.test("hello world #1", () => { @@ -107,7 +107,7 @@ The test steps API provides a way to report distinct steps within a test and do setup and teardown code within that test. ```ts -import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; import { Client } from "https://deno.land/x/postgres@v0.15.0/mod.ts"; interface User { @@ -400,6 +400,35 @@ failure, you can specify the `--fail-fast` flag when running the suite. deno test --fail-fast ``` +## Reporters + +Deno ships with three built-in reporters: + +- `pretty` (default) +- `dot` +- `junit` + +You can specify the reporter to use with the `--reporter` flag. + +```shell +# use default pretty reporter +$ deno test + +# use dot reporter with concise output +$ deno test --reporter=dot + +# use JUnit reporter +$ deno test --reporter=junit +``` + +You can also write the output of machine-readable JUnit report to a file, while +still enjoying human-readable output in the terminal. In such situations specify +`--junit-path` flag: + +```shell +$ deno test --junit-path=./report.xml +``` + ## Integration with testing libraries Deno's test runner works with popular testing libraries like @@ -441,7 +470,7 @@ around `bar` and call `foo(spy)` in the testing code: ```js, ignore import sinon from "https://cdn.skypack.dev/sinon"; -import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; import { bar, foo } from "./my_file.js"; Deno.test("calls bar during execution of foo", () => { @@ -481,7 +510,7 @@ And then `import` in a test file: ```js, ignore import sinon from "https://cdn.skypack.dev/sinon"; -import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; import { foo, funcs } from "./my_file.js"; Deno.test("calls bar during execution of foo", () => { diff --git a/basics/testing/assertions.md b/basics/testing/assertions.md index e1e6a095..7d890ea3 100644 --- a/basics/testing/assertions.md +++ b/basics/testing/assertions.md @@ -1,11 +1,11 @@ # Assertions To help developers write tests the Deno standard library comes with a built-in -[assertions module](https://deno.land/std@$STD_VERSION/testing/asserts.ts) which -can be imported from `https://deno.land/std@$STD_VERSION/testing/asserts.ts`. +[assertions module](https://deno.land/std@$STD_VERSION/assert/mod.ts) which can +be imported from `https://deno.land/std@$STD_VERSION/assert/mod.ts`. ```js -import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { assert } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; Deno.test("Hello Test", () => { assert("Hello"); @@ -128,7 +128,7 @@ That's especially true when working with decimal numbers, where import { assertStrictEquals, assertThrows, -} from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +} from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; Deno.test("Test Assert Strict Equals with float numbers", () => { assertStrictEquals(0.25 + 0.25, 0.25); @@ -145,7 +145,7 @@ it is possible to change it by passing a third optional parameter. import { assertAlmostEquals, assertThrows, -} from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +} from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; Deno.test("Test Assert Almost Equals", () => { assertAlmostEquals(0.1 + 0.2, 0.3); @@ -161,7 +161,7 @@ To check if an object is an instance of a specific constructor, you can use the passed in variable has a specific type: ```ts -import { assertInstanceOf } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { assertInstanceOf } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; Deno.test("Test Assert Instance Type", () => { const variable = new Date() as unknown; @@ -305,13 +305,13 @@ Deno.test("Test Assert Equal Fail Custom Message", () => { ## Custom Tests While Deno comes with powerful -[assertions modules](https://deno.land/std@$STD_VERSION/testing/asserts.ts) but -there is always something specific to the project you can add. Creating +[assertions modules](https://deno.land/std@$STD_VERSION/assert/mod.ts) but there +is always something specific to the project you can add. Creating `custom assertion function` can improve readability and reduce the amount of code. ```ts -import { AssertionError } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { AssertionError } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; function assertPowerOf(actual: number, expected: number, msg?: string): void { let received = actual; diff --git a/basics/testing/behavior_driven_development.md b/basics/testing/behavior_driven_development.md index 183e8b1b..fede568f 100644 --- a/basics/testing/behavior_driven_development.md +++ b/basics/testing/behavior_driven_development.md @@ -59,7 +59,7 @@ sanitization options. They work in the same way. ## Permissions option -Like `Deno.TestDefinition`, the `DescribeDefintion` and `ItDefinition` have a +Like `Deno.TestDefinition`, the `DescribeDefinition` and `ItDefinition` have a `permissions` option. They specify the permissions that should be used to run an individual test case or test suite. Set this to `"inherit"` to keep the calling thread's permissions. Set this to `"none"` to revoke all permissions. @@ -90,7 +90,7 @@ import { assertEquals, assertStrictEquals, assertThrows, -} from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +} from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; import { User } from "https://deno.land/std@$STD_VERSION/testing/bdd_examples/user.ts"; Deno.test("User.users initially empty", () => { @@ -135,7 +135,7 @@ import { assertEquals, assertStrictEquals, assertThrows, -} from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +} from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; import { afterEach, beforeEach, @@ -197,7 +197,7 @@ import { assertEquals, assertStrictEquals, assertThrows, -} from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +} from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; import { describe, it, @@ -257,7 +257,7 @@ import { assertEquals, assertStrictEquals, assertThrows, -} from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +} from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; import { describe, it, diff --git a/basics/testing/mocking.md b/basics/testing/mocking.md index 1db8a645..5dc68912 100644 --- a/basics/testing/mocking.md +++ b/basics/testing/mocking.md @@ -39,7 +39,7 @@ import { assertSpyCalls, spy, } from "https://deno.land/std@$STD_VERSION/testing/mock.ts"; -import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; import { multiply, square, @@ -92,7 +92,7 @@ import { assertSpyCalls, spy, } from "https://deno.land/std@$STD_VERSION/testing/mock.ts"; -import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; import { _internals, square, @@ -176,7 +176,7 @@ import { returnsNext, stub, } from "https://deno.land/std@$STD_VERSION/testing/mock.ts"; -import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; import { _internals, randomMultiple, diff --git a/basics/testing/snapshot_testing.md b/basics/testing/snapshot_testing.md index 42af4833..01dab5f1 100644 --- a/basics/testing/snapshot_testing.md +++ b/basics/testing/snapshot_testing.md @@ -75,7 +75,7 @@ can be limited to only include existing snapshot files, if so desired. ## Version Control -Snapshot testing works best when changes to snapshot files are comitted +Snapshot testing works best when changes to snapshot files are committed alongside other code changes. This allows for changes to reference snapshots to be reviewed along side the code changes that caused them, and ensures that when others pull your changes, their tests will pass without needing to update @@ -116,7 +116,10 @@ snapshot file. ```ts, ignore // example_test.ts -import { assertSnapshot, serialize } from "https://deno.land/std@$STD_VERSION/testing/snapshot.ts"; +import { + assertSnapshot, + serialize, +} from "https://deno.land/std@$STD_VERSION/testing/snapshot.ts"; import { stripColor } from "https://deno.land/std@$STD_VERSION/fmt/colors.ts"; /** @@ -211,7 +214,7 @@ Deno.test("isSnapshotMatch", async function (t): Promise { example: 123, }; await assertSnapshot(t, a, { - name: "Test Name" + name: "Test Name", }); }); ``` @@ -253,7 +256,7 @@ const assertSnapshot = createAssertSnapshot({ When configuring default options like this, the resulting `assertSnapshot` function will function the same as the default function exported from the snapshot module. If passed an optional options object, this will take precedence -over the default options, where the value provded for an option differs. +over the default options, where the value provided for an option differs. It is possible to "extend" an `assertSnapshot` function which has been configured with default options. diff --git a/examples/file_server.md b/examples/file_server.md index 5d953fb4..0f66c28b 100644 --- a/examples/file_server.md +++ b/examples/file_server.md @@ -16,7 +16,7 @@ memory. ## Example -**Command:** `deno run --allow-read --allow-net file_server.ts` +**Command:** `deno run --allow-read=. --allow-net file_server.ts` ```ts // Start listening on port 8080 of localhost. diff --git a/examples/http_server.md b/examples/http_server.md index 614f66bb..b4a812ff 100644 --- a/examples/http_server.md +++ b/examples/http_server.md @@ -9,7 +9,7 @@ With just a few lines of code you can run your own HTTP web server with control over the response status, request headers and more. -## Sample web server +## Using the `Deno.listen` In this example, the user-agent of the client is returned to the client: @@ -57,19 +57,11 @@ deno run --allow-net webserver.ts Then navigate to `http://localhost:8080/` in a browser. -### Using the `std/http` library - -> ℹ️ Since -> [the stabilization of _native_ HTTP bindings in -`^1.13.x`](https://deno.com/blog/v1.13#stabilize-native-http-server-api), -> std/http now supports a _native_ HTTP server from ^0.107.0. The legacy server -> module was removed in 0.117.0. +### Using the `Deno.serve` **webserver.ts**: ```ts -import { serve } from "https://deno.land/std@$STD_VERSION/http/server.ts"; - const port = 8080; const handler = (request: Request): Response => { @@ -81,7 +73,7 @@ const handler = (request: Request): Response => { }; console.log(`HTTP webserver running. Access it at: http://localhost:8080/`); -await serve(handler, { port }); +Deno.serve({ port }, handler); ``` Then run this with: diff --git a/examples/module_metadata.md b/examples/module_metadata.md index f1ff2e31..54a117ad 100644 --- a/examples/module_metadata.md +++ b/examples/module_metadata.md @@ -47,7 +47,10 @@ function outputA() { "Is module A the main module via import.meta.main?", import.meta.main, ); - console.log("Resolved specifier for ./module_b.ts", import.meta.resolve("./module_b.ts")); + console.log( + "Resolved specifier for ./module_b.ts", + import.meta.resolve("./module_b.ts"), + ); } outputA(); diff --git a/examples/tcp_server.md b/examples/tcp_server.md index a35ae201..0a0eb777 100644 --- a/examples/tcp_server.md +++ b/examples/tcp_server.md @@ -17,7 +17,7 @@ For security reasons, Deno does not allow programs to access the network without explicit permission. To allow accessing the network, use a command-line flag: ```shell -deno run --allow-net https://deno.land/std@$STD_VERSION/examples/echo_server.ts +deno run --allow-net https://deno.land/std@0.198.0/examples/echo_server.ts ``` To test it, try sending data to it with `netcat` (or `telnet` on Windows): diff --git a/examples/unix_cat.md b/examples/unix_cat.md index 1bedb68e..344a2999 100644 --- a/examples/unix_cat.md +++ b/examples/unix_cat.md @@ -30,5 +30,5 @@ for (const filename of Deno.args) { To run the program: ```shell -deno run --allow-read https://deno.land/std@$STD_VERSION/examples/cat.ts /etc/passwd +deno run --allow-read https://deno.land/std@0.198.0/examples/cat.ts /etc/passwd ``` diff --git a/getting_started/configuration_file.md b/getting_started/configuration_file.md index ecd78f79..45413353 100644 --- a/getting_started/configuration_file.md +++ b/getting_started/configuration_file.md @@ -37,7 +37,7 @@ import maps. Then your script can use the bare specifier `std`: ```js, ignore -import { assertEquals } from "std/testing/assert.ts"; +import { assertEquals } from "std/assert/mod.ts"; assertEquals(1, 2); ``` @@ -89,6 +89,7 @@ Configuration for [`deno fmt`](../tools/formatter.md) "useTabs": true, "lineWidth": 80, "indentWidth": 4, + "semiColons": true, "singleQuote": true, "proseWrap": "preserve", "include": ["src/"], diff --git a/getting_started/first_steps.md b/getting_started/first_steps.md index d367d4e7..2ce0c10e 100644 --- a/getting_started/first_steps.md +++ b/getting_started/first_steps.md @@ -32,11 +32,11 @@ deno run first_steps.ts ``` Deno also has the ability to execute scripts from URLs. Deno -[hosts a library](https://deno.land/std@$STD_VERSION/examples) of example code, -one of which is a `Hello World` program. To run that hosted code, do: +[hosts a library](https://examples.deno.land/) of example code, one of which is +a `Hello World` program. To run that hosted code, do: ```shell -deno run https://deno.land/std@$STD_VERSION/examples/welcome.ts +deno run https://examples.deno.land/hello-world.ts ``` ## Making an HTTP request @@ -50,15 +50,15 @@ make HTTP calls. In the `first_steps.ts` file you created above, paste the code below: ```ts -const res = await fetch("https://deno.land"); +const res = await fetch("https://deno.com"); const body = await res.text(); console.log(body); ``` Let's walk through what this application does: -1. We make a request to the `https://deno.land`, await the response, and store - it in the `res` constant. +1. We make a request to the `https://deno.com`, await the response, and store it + in the `res` constant. 1. We parse the response body as a text and store in the `body` constant. 1. We write the contents of the `body` constant to the console. @@ -68,29 +68,36 @@ Try it out: deno run first_steps.ts ``` -Or, try this script hosted at -`https://deno.land/std@$STD_VERSION/examples/curl.ts`: +Or, try this script hosted at `https://deno.land/std@0.198.0/examples/curl.ts`: ```shell -deno run https://deno.land/std@$STD_VERSION/examples/curl.ts https://deno.land +deno run https://deno.land/std@0.198.0/examples/curl.ts https://deno.com ``` -You will see this program returns an error regarding network access so what did -we do wrong? You might remember from the introduction that Deno is a runtime -that is secure by default. This means you need to explicitly give programs -permission to do certain 'privileged' actions, such as access the network. +The program will display a prompt like this: -Try it out again with the correct permission flag: +```shell +┌ ⚠️ Deno requests net access to "deno.com". +├ Requested by `fetch()` API. +├ Run again with --allow-net to bypass this prompt. +└ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all net permissions) > +``` + +You might remember from the introduction that Deno is a runtime that is secure +by default. This means you need to explicitly give programs permission to do +certain 'privileged' actions, such as access the network. + +You can answer 'y' to the prompt, or try it out again with the correct +permission flag: ```shell -deno run --allow-net=deno.land first_steps.ts +deno run --allow-net=deno.com first_steps.ts ``` -Or, try this script hosted at -`https://deno.land/std@$STD_VERSION/examples/curl.ts`: +Or, using the curl script: ```shell -deno run --allow-net=deno.land https://deno.land/std@$STD_VERSION/examples/curl.ts https://deno.land +deno run --allow-net=deno.com https://deno.land/std@0.198.0/examples/curl.ts https://deno.com ``` ## Reading a file @@ -124,10 +131,10 @@ Try the program: ```shell # macOS / Linux -deno run --allow-read https://deno.land/std@$STD_VERSION/examples/cat.ts /etc/hosts +deno run --allow-read https://deno.land/std@0.198.0/examples/cat.ts /etc/hosts # Windows -deno run --allow-read https://deno.land/std@$STD_VERSION/examples/cat.ts "C:\Windows\System32\Drivers\etc\hosts" +deno run --allow-read https://deno.land/std@0.198.0/examples/cat.ts "C:\Windows\System32\Drivers\etc\hosts" ``` ## Putting it all together in an HTTP server @@ -141,7 +148,7 @@ import { serve } from "https://deno.land/std@$STD_VERSION/http/server.ts"; const handler = async (_request: Request): Promise => { const resp = await fetch("https://api.github.com/users/denoland", { - // The init object here has an headers object containing a + // The init object here has a headers object containing a // header that indicates what type of response we accept. // We're not specifying the method field since by default // fetch makes a GET request. diff --git a/getting_started/installation.md b/getting_started/installation.md index a4577a56..54581ada 100644 --- a/getting_started/installation.md +++ b/getting_started/installation.md @@ -23,6 +23,12 @@ Using PowerShell (Windows): irm https://deno.land/install.ps1 | iex ``` +Using [Winget](https://winget.run) (Windows): + +```shell +winget install --id DenoLand.Deno -e +``` + Using [Scoop](https://scoop.sh/) (Windows): ```shell @@ -98,6 +104,12 @@ To update a previously installed version of Deno, you can run: deno upgrade ``` +Or using [Winget](https://winget.run) (Windows): + +```shell +winget upgrade --id DenoLand.Deno -e +``` + This will fetch the latest release from [github.com/denoland/deno/releases](https://github.com/denoland/deno/releases), unzip it, and replace your current executable with it. diff --git a/getting_started/setup_your_environment.md b/getting_started/setup_your_environment.md index 6a5e7bfc..7ac85d02 100644 --- a/getting_started/setup_your_environment.md +++ b/getting_started/setup_your_environment.md @@ -74,6 +74,7 @@ resolve this, make sure to set some unique `root_dir` for both `tsserver` and of such a configuration: ```lua +local nvim_lsp = require('lspconfig') nvim_lsp.denols.setup { on_attach = on_attach, root_dir = nvim_lsp.util.root_pattern("deno.json", "deno.jsonc"), @@ -370,11 +371,11 @@ There are several environment variables which can impact the behavior of Deno: more details. - `DENO_TLS_CA_STORE` - a list of certificate stores which will be used when establishing TLS connections. The available stores are `mozilla` and `system`. - You can specify one, both or none. The order you specify the store determines - the order in which certificate chains will be attempted to resolved. The - default value is `mozilla`. The `mozilla` store will use the bundled Mozilla - certs provided by [`webpki-roots`](https://crates.io/crates/webpki-roots). The - `system` store will use your platforms + You can specify one, both or none. Certificate chains attempt to resolve in + the same order in which you specify them. The default value is `mozilla`. The + `mozilla` store will use the bundled Mozilla certs provided by + [`webpki-roots`](https://crates.io/crates/webpki-roots). The `system` store + will use your platform's [native certificate store](https://crates.io/crates/rustls-native-certs). The exact set of Mozilla certs will depend on the version of Deno you are using. If you specify no certificate stores, then no trust will be given to any TLS @@ -386,7 +387,7 @@ There are several environment variables which can impact the behavior of Deno: - `DENO_DIR` - this will set the directory where cached information from the CLI is stored. This includes items like cached remote modules, cached transpiled modules, language server cache information and persisted data from local - storage. This defaults to the operating systems default cache location and + storage. This defaults to the operating system's default cache location and then under the `deno` path. - `DENO_INSTALL_ROOT` - When using `deno install` where the installed scripts are stored. This defaults to `$HOME/.deno/bin`. @@ -400,11 +401,11 @@ There are several environment variables which can impact the behavior of Deno: [Proxies](../basics/modules/proxies.md) section for more information. - `HTTPS_PROXY` - The proxy address to use for HTTPS requests. See the [Proxies](../basics/modules/proxies.md) section for more information. -- `NO_COLOR` - If set, this will cause the Deno CLI to not send ANSI color codes - when writing to stdout and stderr. See the website for - more information on this _de facto_ standard. The value of this flag can be - accessed at runtime without permission to read the environment variables by - checking the value of `Deno.noColor`. +- `NO_COLOR` - If set, this will prevent the Deno CLI from sending ANSI color + codes when writing to stdout and stderr. See the website + for more information on this _de facto_ standard. The + value of this flag can be accessed at runtime without permission to read the + environment variables by checking the value of `Deno.noColor`. - `NO_PROXY` - Indicates hosts which should bypass the proxy set in the other environment variables. See the [Proxies](../basics/modules/proxies.md) section for more information. diff --git a/introduction.md b/introduction.md index 8ba9264f..d10af0ba 100644 --- a/introduction.md +++ b/introduction.md @@ -11,8 +11,8 @@ It's built on V8, Rust, and Tokio. - Provides [web platform functionality](./runtime/web_platform_apis.md) and adopts web platform standards. For example using ES modules, web workers, and support `fetch()`. -- Secure by default. No file, network, or environment access unless explicitly - enabled. +- [Secure by default](./basics/permissions.md). No file, network, or environment + access unless explicitly enabled. - Supports [TypeScript](./advanced/typescript.md) out of the box. - Ships a single executable (`deno`). - Provides built-in [development tooling](./tools.md) like a code formatter @@ -27,7 +27,7 @@ It's built on V8, Rust, and Tokio. ## Philosophy -Deno aims to be a productive and secure scripting environment for the modern +Deno aims to be a productive, secure, and performant runtime for the modern programmer. Deno will always be distributed as a single executable. Given a URL to a Deno diff --git a/node/compatibility.md b/node/compatibility.md new file mode 100644 index 00000000..66348443 --- /dev/null +++ b/node/compatibility.md @@ -0,0 +1,874 @@ +# Support status for Node.js APIs and Globals + +Deno provides polyfills for a number of built-in Node.js modules and globals. +Node compatibility is an ongoing project - help us identify gaps and let us know +which modules you need by +[opening an issue on GitHub](https://github.com/denoland/deno). + +### Built-in modules + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ModuleSupport LevelNotes
+ + node:assert + + + ✅ Full +
+ + node:assert/strict + + + ✅ Full +
+ + node:async_hooks + + + ℹ️ Partial + + AsyncLocalStorage is supported. + AsyncResource, + executionAsyncId, and + createHook are non-functional stubs. +
+ + node:buffer + + + ✅ Full + +
+ + node:child_process + + + ℹ️ Partial + + The ipc and overlapped stdio options are missing. + Passing file descriptors by an integer value is missing. +
+ + node:cluster + + + ❌ Missing + + All exports are non-functional stubs. +
+ + node:console + + + ✅ Full + +
+ + node:crypto + + + ℹ️ Partial + + Missing Certificate class, + crypto.Cipheriv.prototype.setAutoPadding, + crypto.Decipheriv.prototype.setAutoPadding, + crypto.getCipherInfo, crypto.publicDecrypt, + crypto.ECDH.prototype.convertKey, + crypto.diffieHellman, x448 option for + generateKeyPair, crypto.KeyObject, + safe, add and rem options for + generatePrime, crypto.Sign.prototype.sign and + crypto.Verify.prototype.verify with non BinaryLike + input, crypto.secureHeapUsed, crypto.setEngine, + legacy methods of crypto.X509Certificate. +
+ + node:dgram + + + ℹ️ Full + +
+ + node:diagnostics_channel + + + ✅ Full + +
+ + node:dns + + + ℹ️ Partial + +

Missing dns.resolve* with ttl option.

+
+ + node:domain + + + ❌ Missing + + All exports are non-functional stubs. +
+ + node:events + + + ✅ Full + +
+ + node:fs + + + ℹ️ Partial + +

+ Missing utf16le, latin1 and ucs2 + encoding for fs.writeFile and + fs.writeFileSync. Missing Dirent.isBlockDevice, + Dirent.isCharacterDevice, + Dirent.isFIFO, Dirent.isSocket, + FSWatcher.ref, FSWatcher.unref. +

+
+ + node:fs/promises + + + ℹ️ Partial + +

+ Missing lchmod, lchown, lutimes. +

+
+ + node:http + + + ℹ️ Partial + +

+ createConnection option is currently not supported. +

+
+ + node:http2 + + + ℹ️ Partial + +

+ Partially supported, major work in progress to enable grpc-js. +

+
+ + node:https + + + ℹ️ Partial + +

+ Missing https.Server.opts.cert and + https.Server.opts.key array type. +

+
+ + node:inspector + + + ℹ️ Partial + +

+ console is supported. Other APIs are stubs and will throw an + error. Due to security implications the Deno team does not plan to + polyfill these APIs. +

+
+ + node:module + + + ✅ Full + +
+ + node:net + + + ℹ️ Partial + +

+ Missing net.Socket.prototype.constructor with fd + option. +

+
+ + node:os + + + ✅ Full + +
+ + node:path + + + ✅ Full + +
+ + node:path/posix + + + ✅ Full + +
+ + node:path/win32 + + + ✅ Full + +
+ + node:perf_hooks + + + ℹ️ Partial + +

+ Missing perf_hooks.eventLoopUtilization, + perf_hooks.timerify, + perf_hooks.monitorEventLoopDelay. +

+
+ + node:process + + + ℹ️ Partial + +

+ Missing disconnect, message, + multipleResolves, rejectionHandled and + worker events. +

+
+ + node:punycode + + + ✅ Full + +
+ + node:querystring + + + ✅ Full + +
+ + node:readline + + + ✅ Full + +
+ + node:repl + + + ℹ️ Partial + +

+ builtinModules and _builtinLibs are supported. + Missing REPLServer.prototype.constructor and + start(). +

+
+ + node:stream + + + ✅ Full + +
+ + node:stream/consumers + + + ✅ Full + +
+ + node:stream/promises + + + ✅ Full + +
+ + node:stream/web + + + ✅ Full + +
+ + node:string_decoder + + + ℹ️ Partial + +

+ Missing decoding of ascii, latin1 and + utf16le decoding options. +

+
+ + node:sys + + + ✅ Full + +

See node:util. +

+ + node:test + + + ℹ️ Partial + +

+ Currently only test API is supported. +

+
+ + node:timers + + + ✅ Full + +
+ + node:timers/promises + + + ✅ Full + +
+ + node:tls + + + ℹ️ Partial + +

+ Missing createSecurePair. +

+
+ + node:trace_events + + + ❌ Missing + +

+ All exports are non-functional stubs. +

+
+ + node:tty + + + ℹ️ Partial + +

+ Missing ReadStream and WriteStream + implementation. +

+
+ + node:url + + + ✅ Full + +
+ + node:util + + + ✅ Full + +
+ + node:util/types + + + ✅ Full + +
+ + node:v8 + + + ℹ️ Partial + +

+ cachedDataVersionTag and getHeapStatistics are + supported. setFlagsFromStrings is a noop. Other APIs are not + supported and will throw and error. The other APIs could be + polyfilled, but due inherent lack of format stability between the V8 + versions, the Deno team is considering requiring a special flag to use + them. +

+
+ + node:vm + + + ℹ️ Partial + +

+ runInThisContext is supported. Other APIs are not polyfilled + and will throw and error. +

+
+ + node:wasi + + + ❌ Missing + +

+ All exports are non-functional stubs. +

+
+ + node:worker_threads + + + ℹ️ Partial + +

+ Missing parentPort.emit, + parentPort.removeAllListeners, + markAsUntransferable, moveMessagePortToContext, + receiveMessageOnPort, + Worker.prototype.getHeapSnapshot. +

+
+ + node:zlib + + + ℹ️ Partial + +

+ Missing Options.prototype.constructor, + BrotliOptions.prototype.constructor, + BrotliDecompress.prototype.constructor, + ZlibBase.prototype.constructor. +

+
+ +## Globals + +This is the list of Node globals that Deno supports. + +These globals are only available in the `npm` package scope. In your own code +you can use them by importing them from the relevant `node:` module. + +| Global name | Status | +| ---------------------------------------------------------------------------------------------------------------- | ------ | +| [`AbortController`](https://nodejs.org/api/globals.html#class-abortcontroller) | ✅ | +| [`AbortSignal`](https://nodejs.org/api/globals.html#class-abortsignal) | ✅ | +| [`Blob`](https://nodejs.org/api/globals.html#class-blob) | ✅ | +| [`Buffer`](https://nodejs.org/api/globals.html#class-buffer) | ✅ | +| [`ByteLengthQueuingStrategy`](https://nodejs.org/api/globals.html#class-bytelengthqueuingstrategy) | ✅ | +| [`__dirname`](https://nodejs.org/api/globals.html#__dirname) | ✅ | +| [`__filename`](https://nodejs.org/api/globals.html#__filename) | ✅ | +| [`atob`](https://nodejs.org/api/globals.html#atobdata) | ✅ | +| [`BroadcastChannel`](https://nodejs.org/api/globals.html#broadcastchannel) | ✅ | +| [`btoa`](https://nodejs.org/api/globals.html#btoadata) | ✅ | +| [`clearImmediate`](https://nodejs.org/api/globals.html#clearimmediateimmediateobject) | ✅ | +| [`clearInterval`](https://nodejs.org/api/globals.html#clearintervalintervalobject) | ✅ | +| [`clearTimeout`](https://nodejs.org/api/globals.html#cleartimeouttimeoutobject) | ✅ | +| [`CompressionStream`](https://nodejs.org/api/globals.html#class-compressionstream) | ✅ | +| [`console`](https://nodejs.org/api/globals.html#console) | ✅ | +| [`CountQueuingStrategy`](https://nodejs.org/api/globals.html#class-countqueuingstrategy) | ✅ | +| [`Crypto`](https://nodejs.org/api/globals.html#crypto) | ✅ | +| [`CryptoKey`](https://nodejs.org/api/globals.html#cryptokey) | ✅ | +| [`CustomEvent`](https://nodejs.org/api/globals.html#customevent) | ✅ | +| [`CustomEvent`](https://nodejs.org/api/globals.html#customevent) | ✅ | +| [`DecompressionStream`](https://nodejs.org/api/globals.html#class-decompressionstream) | ✅ | +| [`Event`](https://nodejs.org/api/globals.html#event) | ✅ | +| [`EventTarget`](https://nodejs.org/api/globals.html#eventtarget) | ✅ | +| [`exports`](https://nodejs.org/api/globals.html#exports) | ✅ | +| [`fetch`](https://nodejs.org/api/globals.html#fetch) | ✅ | +| [`fetch`](https://nodejs.org/api/globals.html#fetch) | ✅ | +| [`File`](https://nodejs.org/api/globals.html#class-file) | ✅ | +| [`File`](https://nodejs.org/api/globals.html#class-file) | ✅ | +| [`FormData`](https://nodejs.org/api/globals.html#class-formdata) | ✅ | +| [`global`](https://nodejs.org/api/globals.html#global) | ✅ | +| [`Headers`](https://nodejs.org/api/globals.html#class-headers) | ✅ | +| [`MessageChannel`](https://nodejs.org/api/globals.html#messagechannel) | ✅ | +| [`MessageEvent`](https://nodejs.org/api/globals.html#messageevent) | ✅ | +| [`MessagePort`](https://nodejs.org/api/globals.html#messageport) | ✅ | +| [`module`](https://nodejs.org/api/globals.html#module) | ✅ | +| [`PerformanceEntry`](https://nodejs.org/api/globals.html#performanceentry) | ✅ | +| [`PerformanceMark`](https://nodejs.org/api/globals.html#performancemark) | ✅ | +| [`PerformanceMeasure`](https://nodejs.org/api/globals.html#performancemeasure) | ✅ | +| [`PerformanceObserver`](https://nodejs.org/api/globals.html#performanceobserver) | ✅ | +| [`PerformanceObserverEntryList`](https://nodejs.org/api/globals.html#performanceobserverentrylist) | ❌ | +| [`PerformanceResourceTiming`](https://nodejs.org/api/globals.html#performanceresourcetiming) | ❌ | +| [`performance`](https://nodejs.org/api/globals.html#performance) | ✅ | +| [`process`](https://nodejs.org/api/globals.html#process) | ✅ | +| [`queueMicrotask`](https://nodejs.org/api/globals.html#queuemicrotaskcallback) | ✅ | +| [`ReadableByteStreamController`](https://nodejs.org/api/globals.html#class-readablebytestreamcontroller) | ✅ | +| [`ReadableStream`](https://nodejs.org/api/globals.html#class-readablestream) | ✅ | +| [`ReadableStreamBYOBReader`](https://nodejs.org/api/globals.html#class-readablestreambyobreader) | ✅ | +| [`ReadableStreamBYOBRequest`](https://nodejs.org/api/globals.html#class-readablestreambyobrequest) | ✅ | +| [`ReadableStreamDefaultController`](https://nodejs.org/api/globals.html#class-readablestreamdefaultcontroller) | ✅ | +| [`ReadableStreamDefaultReader`](https://nodejs.org/api/globals.html#class-readablestreamdefaultreader) | ✅ | +| [`require`](https://nodejs.org/api/globals.html#require) | ✅ | +| [`Response`](https://nodejs.org/api/globals.html#response) | ✅ | +| [`Request`](https://nodejs.org/api/globals.html#request) | ✅ | +| [`setImmediate`](https://nodejs.org/api/globals.html#setimmediatecallback-args) | ✅ | +| [`setInterval`](https://nodejs.org/api/globals.html#setintervalcallback-delay-args) | ✅ | +| [`setTimeout`](https://nodejs.org/api/globals.html#settimeoutcallback-delay-args) | ✅ | +| [`structuredClone`](https://nodejs.org/api/globals.html#structuredclonevalue-options) | ✅ | +| [`structuredClone`](https://nodejs.org/api/globals.html#structuredclonevalue-options) | ✅ | +| [`SubtleCrypto`](https://nodejs.org/api/globals.html#subtlecrypto) | ✅ | +| [`DOMException`](https://nodejs.org/api/globals.html#domexception) | ✅ | +| [`TextDecoder`](https://nodejs.org/api/globals.html#textdecoder) | ✅ | +| [`TextDecoderStream`](https://nodejs.org/api/globals.html#class-textdecoderstream) | ✅ | +| [`TextEncoder`](https://nodejs.org/api/globals.html#textencoder) | ✅ | +| [`TextEncoderStream`](https://nodejs.org/api/globals.html#class-textencoderstream) | ✅ | +| [`TransformStream`](https://nodejs.org/api/globals.html#class-transformstream) | ✅ | +| [`TransformStreamDefaultController`](https://nodejs.org/api/globals.html#class-transformstreamdefaultcontroller) | ✅ | +| [`URL`](https://nodejs.org/api/globals.html#url) | ✅ | +| [`URLSearchParams`](https://nodejs.org/api/globals.html#urlsearchparams) | ✅ | +| [`URLSearchParams`](https://nodejs.org/api/globals.html#urlsearchparams) | ✅ | +| [`WebAssembly`](https://nodejs.org/api/globals.html#webassembly) | ✅ | +| [`WritableStream`](https://nodejs.org/api/globals.html#class-writablestream) | ✅ | +| [`WritableStreamDefaultController`](https://nodejs.org/api/globals.html#class-writablestreamdefaultcontroller) | ✅ | +| [`WritableStreamDefaultWriter`](https://nodejs.org/api/globals.html#class-writablestreamdefaultwriter) | ✅ | diff --git a/node/faqs.md b/node/faqs.md index 06e4dd5b..28a37822 100644 --- a/node/faqs.md +++ b/node/faqs.md @@ -1,53 +1,5 @@ # Frequently Asked Questions -### When using npm specifiers - -If you are getting this error while using npm specifiers, then add a triple -slash types reference directive to your main entry point, specifying to include -the types from the `@types/node` package: - -```ts, ignore -/// -``` - -### When using CDNs - -If you are getting this error when not using npm specifiers and instead while -importing from npm CDNs, then you can import the `@types/node` types from a CDN -as well. - -For example from UNPKG it would look something like this: - -```ts, ignore -import type {} from "https://unpkg.com/@types/node/index.d.ts"; -``` - -Or from esm.sh: - -```ts, ignore -import type {} from "https://esm.sh/@types/node/index.d.ts"; -``` - -Or from Skypack: - -```ts, ignore -import type {} from "https://cdn.skypack.dev/@types/node/index.d.ts"; -``` - -You could also try to provide only specifically what the 3rd party package is -missing. For example the package `@aws-sdk/client-dynamodb` has a dependency on -the `NodeJS.ProcessEnv` type in its type definitions. In one of the modules of -your project that imports it as a dependency, you could put something like this -in there which will solve the problem: - -```ts, ignore -declare global { - namespace NodeJS { - type ProcessEnv = Record; - } -} -``` - ## Getting type errors like cannot find `document` or `HTMLElement` The library you are using has dependencies on the DOM. This is common for diff --git a/node/how_to_with_npm/express.md b/node/how_to_with_npm/express.md index 7c0c9fae..20f0b372 100644 --- a/node/how_to_with_npm/express.md +++ b/node/how_to_with_npm/express.md @@ -80,9 +80,11 @@ app.get("/api", (req, res) => { app.get("/api/:dinosaur", (req, res) => { if (req?.params?.dinosaur) { - const found = data.find(item => item.name.toLowerCase() === req.params.dinosaur.toLowerCase()); + const found = data.find((item) => + item.name.toLowerCase() === req.params.dinosaur.toLowerCase() + ); if (found) { - res.send(found) + res.send(found); } else { res.send("No dinosaurs found."); } diff --git a/node/how_to_with_npm/react.md b/node/how_to_with_npm/react.md index 45d8a456..fb0a09e4 100644 --- a/node/how_to_with_npm/react.md +++ b/node/how_to_with_npm/react.md @@ -61,10 +61,12 @@ router }) .get("/api/:dinosaur", (context) => { if (context?.params?.dinosaur) { - const found = data.find(item => item.name.toLowerCase() === context.params.dinosaur.toLowerCase()); + const found = data.find((item) => + item.name.toLowerCase() === context.params.dinosaur.toLowerCase() + ); if (found) { context.response.body = found; - } else { + } else { context.response.body = "No dinosaurs found."; } } diff --git a/node/how_to_with_npm/vue.md b/node/how_to_with_npm/vue.md index 4aa8de27..7c2650f7 100644 --- a/node/how_to_with_npm/vue.md +++ b/node/how_to_with_npm/vue.md @@ -63,10 +63,12 @@ router }) .get("/api/:dinosaur", (context) => { if (context?.params?.dinosaur) { - const found = data.find(item => item.name.toLowerCase() === context.params.dinosaur.toLowerCase()); + const found = data.find((item) => + item.name.toLowerCase() === context.params.dinosaur.toLowerCase() + ); if (found) { context.response.body = found; - } else { + } else { context.response.body = "No dinosaurs found."; } } @@ -269,8 +271,8 @@ Tying it all together, let's update `src/App.vue`: ```tsx, ignore + +; ``` ## Add routing diff --git a/node/migrate.md b/node/migrate.md new file mode 100644 index 00000000..df5a2247 --- /dev/null +++ b/node/migrate.md @@ -0,0 +1,262 @@ +# Migrating from Node.js to Deno + +To migrate an existing Node.js program to Deno, there are a number of +differences to take into account between the Node and Deno runtimes. This guide +will attempt to call out several of those differences, and describe how you can +begin to migrate your Node.js project to work on Deno. + +> Node.js compatibility is an ongoing project in Deno - you may encounter some +> modules or packages on npm that do not work as you expect. If you do run into +> a problem with Node.js compatibility, please let us know by +> [opening an issue on GitHub](https://github.com/denoland/deno/issues). + +**On this page:** + +- [Module imports and exports](#module-imports-and-exports) +- [Node.js built-ins](#nodejs-built-ins) +- [Runtime permission system](#runtime-permissions-in-deno) +- [npm scripts](#running-npm-scripts-in-deno) +- [Using and managing npm dependencies](#using-and-managing-npm-dependencies) +- [Node.js global objects](#nodejs-global-objects) + +## Module imports and exports + +Deno supports [ECMAScript modules](../basics/modules.md) exclusively, rather +than a combination of ESM and [CommonJS](https://nodejs.org/api/modules.html), +as found in Node. If your Node.js code uses `require`, you should update it to +use `import` statements instead. If your internal code uses CommonJS-style +exports, those will need to be changed as well. + +Consider the following two files in a Node.js program, located in the same +directory: + +**`index.js`** + +```js +const addNumbers = require("./add_numbers"); +console.log(addNumbers(2, 2)); +``` + +**`add_numbers.js`** + +```js +module.exports = function addNumbers(num1, num2) { + return num1 + num2; +}; +``` + +Running `node index.js` with the files above works fine in Node.js 20 and +earlier. However, this code will not run unchanged if you attempt to use +`deno run index.js` instead. You will need to change both the code that is +consuming the module, and how you export functionality from the `add_numbers` +module. + +### Replace `require` with `import` + +Replace `require` statements with an `import`, like so: + +``` +import addNumbers from "./add_numbers.js"; +``` + +This statement uses the ES6 module standard, but does pretty much the same +thing. Also, note that we **include the full file extension when importing +modules**, much as you would in the browser. There is also no special handling +of files named `index.js`. + +### Replace `module.exports` with `export default` + +In the `add_numbers.js` file that exports the function, we would use a default +export from ES6 modules rather than the `module.exports` provided by CommonJS. + +```js +export default function addNumbers(num1, num2) { + return num1 + num2; +} +``` + +After making those two changes, this code would run successfully with +`deno run index.js`. Learn more about +[ES modules in Deno here](../basics/modules.md). + +## Node.js built-ins + +In Node.js 20 and earlier, built-in modules in the Node.js standard library +could be imported with "bare specifiers". Consider the Node program below with a +`.mjs` extension: + +**`index.mjs`** + +``` +import * as os from "os"; +console.log(os.cpus()); +``` + +The [`os` module](https://nodejs.org/api/os.html#oscpus) is built in to the +Node.js runtime, and can be imported using a bare specifier as above. + +> **NOTE:** The `.mjs` file extension is supported but not required in Deno. +> Because Node doesn't support ESM by default, it requires you to name any files +> that use ESM with a `.mjs` file extension. + +Deno provides a compatibility layer that allows the use of Node.js built-in APIs +within Deno programs. However, in order to use them, you will need to add the +[`node:` specifier](./node_specifiers.md) to any import statements that use +them. + +For example - if you update the code above to be this instead: + +```js +import * as os from "node:os"; +console.log(os.cpus()); +``` + +And run it with `deno run index.mjs` - you will notice you get the same output +as running the program in Node.js. Updating any imports in your application to +use `node:` specifiers should enable any code using Node built-ins to function +as it did in Node.js. + +## Runtime permissions in Deno + +Deno features [runtime security by default](../basics/permissions.md), meaning +that you as the developer must opt in to giving your code access to the +filesystem, network, system environment, and more. Doing this prevents supply +chain attacks and other potential vulnerabilities in your code. By comparison, +Node.js has no concept of runtime security, with all code executed with the same +level of permission as the user running the code. + +### Running your code with only the necessary flags + +When you run a Node.js project ported to Deno for the first time, the runtime +will likely prompt you for access to the permissions it needs to execute your +code. Consider the following simple [express](https://expressjs.com/) server: + +```js +import express from "npm:express"; + +const app = express(); + +app.get("/", function (_req, res) { + res.send("hello"); +}); + +app.listen(3000, () => { + console.log("Express listening on :3000"); +}); +``` + +If you run it with `deno run server.js`, it would prompt you for a number of +permissions required to execute the code and its dependencies. These prompts can +show you what runtime permission flags need to be passed in to grant the access +you need. Running the code above with the necessary permissions provided would +look like this: + +```plain +deno run --allow-net --allow-read --allow-env server.js +``` + +### Reusing runtime flag configuration with `deno task` + +A common pattern for configuring a set of runtime flags is to set up scripts to +be run with [`deno task`](../tools/task_runner.md). The following `deno.json` +file has a task called `dev` which will run the express server from above with +all the necessary flags. + +```json +{ + "tasks": { + "dev": "deno run --allow-net --allow-read --allow-env server.js" + } +} +``` + +You can then run the task with `deno task dev`. + +### Running with all permissions enabled + +It is possible, but not recommended in production or sensitive environments, to +run your programs with all runtime permissions enabled. This would be the +default behavior of Node, which lacks a permission system. To run a program with +all permissions enabled, you can do so with: + +```plain +deno run -A server.js +``` + +## Running scripts from `package.json` + +Many Node.js projects make use of +[npm scripts](https://docs.npmjs.com/cli/v9/using-npm/scripts) to drive local +development. In Deno, you can continue to use your existing npm scripts while +migrating over time to [`deno task`](../tools/task_runner.md). + +### Running npm scripts in Deno + +One of the ways [Deno supports existing `package.json` files](./package_json.md) +is by executing any scripts configured there with `deno task`. Consider the +following Node.js project with a package.json and a script configured within it. + +**`bin/my_task.mjs`** + +```js +console.log("running my task..."); +``` + +**`package.json`** + +```json +{ + "name": "test", + "scripts": { + "start": "node index.mjs" + } +} +``` + +You can execute this script with Deno by running `deno task start`. + +## Using and managing npm dependencies + +Deno supports +[managing npm dependencies through a `package.json` file](./package_json.md). +Note that unlike using npm at the command line, you can simply run your project +with `deno run`, and the first time your script runs, Deno will cache all the +necessary dependencies for your application. + +Going forward, we'd recommend that you manage dependencies through +[`deno.json`](../getting_started/configuration_file.md) instead, which supports +other types of imports as well. + +When importing npm packages, you would use the `npm:` specifier, much like you +would the `node:` specifier for any built-in Node modules. + +```js +import express from "npm:express"; + +const app = express(); + +app.get("/", function (_req, res) { + res.send("hello"); +}); + +app.listen(3000, () => { + console.log("Express listening on :3000"); +}); +``` + +## Node.js global objects + +In Node.js, there are a number of +[global objects](https://nodejs.org/api/globals.html) that are available in the +scope of all programs, like the `process` object or `__dirname` and +`__filename`. + +Deno does not add additional objects and variables to the global scope, other +than the [`Deno` namespace](../runtime/builtin_apis.md). Any API that doesn't +exist as a web standard browser API will be found in this namespace. + +The equivalent Deno expression for every Node.js built-in global object will +vary, but it should be possible to accomplish everything you can do in Node +using a slightly different method in Deno. For example, the +[process.cwd()](https://nodejs.org/api/process.html#processcwd) function in +Node.js exists in Deno as [Deno.cwd()](/api?s=Deno.cwd). diff --git a/references/contributing.md b/references/contributing.md index f2699572..55c4eb1f 100644 --- a/references/contributing.md +++ b/references/contributing.md @@ -13,8 +13,8 @@ Repositories have different scopes, use different programming languages and have varying difficulty level when it comes to contributions. To help you decide which repository might be the best to start contributing -(and/or falls into your interest), here's a short comparison (**languages in -bold comprise most of the codebase**): +(and/or falls into your interest), here's a short comparison (**codebases +primarily comprise the languages in bold**): ### [`deno`](https://github.com/denoland/deno) @@ -23,19 +23,50 @@ This is the main repository that provides the `deno` CLI. If you want to fix a bug or add a new feature to `deno` this is the repository you want to contribute to. -Languages: **Rust**, **JavaScript** +Some systems, including a large part of the Node.js compatibility layer are +implemented in JavaScript and TypeScript modules. These are a good place to +start if you are looking to make your first contribution. + +While iterating on such modules it is recommended to include +`--features __runtime_js_sources` in your `cargo` flags. This is a special +development mode where the JS/TS sources are not included in the binary but read +at runtime, meaning the binary will not have to be rebuilt if they are changed. + +```sh +# cargo build +cargo build --features __runtime_js_sources + +# cargo run -- run hello.ts +cargo run --features __runtime_js_sources -- run hello.ts + +# cargo test integration::node_unit_tests::os_test +cargo test --features __runtime_js_sources integration::node_unit_tests::os_test +``` + +Also remember to reference this feature flag in your editor settings. For VSCode +users, combine the following into your workspace file: + +```json +{ + "settings": { + "rust-analyzer.cargo.features": ["__runtime_js_sources"] + } +} +``` + +Languages: **Rust**, **JavaScript**, **TypeScript** ### [`deno_std`](https://github.com/denoland/deno_std) The standard library for Deno. -Languages: **TypeScript**, WebAssembly. +Languages: **TypeScript**, WebAssembly -### [`dotland`](https://github.com/denoland/dotland) +### [`fresh`](https://github.com/denoland/fresh) -Frontend for official Deno webpage: https://deno.land/ +The next-gen web framework. -Languages: **TypeScript**, TSX, CSS +Languages: **TypeScript**, TSX ### [`deno_lint`](https://github.com/denoland/deno_lint) @@ -62,7 +93,7 @@ Rust bindings for the V8 JavaScript engine. Very technical and low-level. Languages: **Rust** -### [`serde_v8`](https://github.com/denoland/deno/tree/main/serde_v8) +### [`serde_v8`](https://github.com/denoland/deno_core/tree/main/serde_v8) Library that provides bijection layer between V8 and Rust objects. Based on [`serde`](https://crates.io/crates/serde) library. Very technical and low-level. @@ -81,13 +112,13 @@ Official Docker images for Deno. - Ask for help in the [community chat room](https://discord.gg/deno). -- If you are going to work on an issue, mention so in the issue comments +- If you are going to work on an issue, mention so in the issue's comments _before_ you start working on the issue. - If you are going to work on a new feature, create an issue and discuss with other contributors _before_ you start working on the feature; we appreciate - all contributions, but not all proposed features are getting accepted. We - don't want you to spend hours working on a code that might not be accepted. + all contributions but not all proposed features will be accepted. We don't + want you to spend hours working on code that might not be accepted. - Please be professional in the forums. We follow [Rust's code of conduct](https://www.rust-lang.org/policies/code-of-conduct) @@ -112,12 +143,12 @@ Examples of bad PR title: - update docs - fix bugs -2. Ensure there is a related issue and it is referenced in the PR text. +2. Ensure there is a related issue and that it is referenced in the PR text. 3. Ensure there are tests that cover the changes. ## Submitting a PR to [`deno`](https://github.com/denoland/deno) -Additionally to the above make sure that: +In addition to the above make sure that: 1. `cargo test` passes - this will run full test suite for `deno` including unit tests, integration tests and Web Platform Tests @@ -130,7 +161,7 @@ Additionally to the above make sure that: ## Submitting a PR to [`deno_std`](https://github.com/denoland/deno_std) -Additionally to the above make sure that: +In addition to the above make sure that: 1. All of the code you wrote is in `TypeScript` (ie. don't use `JavaScript`) @@ -148,7 +179,13 @@ Additionally to the above make sure that: If you are submitting a PR to this manual, make sure that all imports of the standard library have the numeric version replaced with "$STD_VERSION". -For the latest version go [here](https://deno.land/std@0.178.0/version.ts). +For the latest version go [here](https://deno.land/std/version.ts). + +## Submitting a PR to [`fresh`](https://github.com/denoland/fresh) + +First, please be sure to +[install Puppeteer](https://github.com/lucacasonato/deno-puppeteer#installation). +Then, please ensure `deno task ok` is run and successfully passes. ## Documenting APIs diff --git a/references/contributing/building_from_source.md b/references/contributing/building_from_source.md index 03423e39..0e52da5e 100644 --- a/references/contributing/building_from_source.md +++ b/references/contributing/building_from_source.md @@ -7,13 +7,16 @@ chapter). ## Cloning the Repository -Clone on Linux or Mac: +> Deno uses submodules, so you must remember to clone using +> `--recurse-submodules`. + +**Linux**/**Mac**: ```shell git clone --recurse-submodules https://github.com/denoland/deno.git ``` -Extra steps for Windows users: +**Windows**: 1. [Enable "Developer Mode"](https://www.google.com/search?q=windows+enable+developer+mode) (otherwise symlinks would require administrator privileges). @@ -26,8 +29,11 @@ Extra steps for Windows users: ## Prerequisites -> Deno requires the progressively latest stable release of Rust. Deno does not -> support the Rust Nightly Releases. +### Rust + +> Deno requires a specific release of Rust. Deno may not support building on +> other versions, or on the Rust Nightly Releases. The version of Rust required +> for a particular release is specified in the `rust-toolchain.toml` file. [Update or Install Rust](https://www.rust-lang.org/tools/install). Check that Rust installed/updated correctly: @@ -37,43 +43,42 @@ rustc -V cargo -V ``` -For Apple aarch64 users `lld` must be installed. - -``` -brew install llvm -# Add /opt/homebrew/opt/llvm/bin/ to $PATH -``` +### Native Compilers and Linkers -## Building Deno +> Many components of Deno require a native compiler to build optimized native +> functions. -The easiest way to build Deno is by using a precompiled version of V8: +**Linux**: -``` -cargo build -vv +```sh +apt install --install-recommends -y clang-16 lld-16 cmake libglib2.0-dev ``` -However if you want to build Deno and V8 from source code: +**Mac**: + +Mac users must have the _XCode Command Line Tools_ installed. +([XCode](https://developer.apple.com/xcode/) already includes the _XCode Command +Line Tools_. Run `xcode-select --install` to install it without XCode.) + +[CMake](https://cmake.org/) is also required, but does not ship with the +_Command Line Tools_. ``` -V8_FROM_SOURCE=1 cargo build -vv +brew install cmake ``` -When building V8 from source, there are more dependencies: +**Mac M1/M2**: -[Python 3](https://www.python.org/downloads) for running WPT tests. Ensure that -a suffix-less `python`/`python.exe` exists in your `PATH` and it refers to -Python 3. - -For Linux users glib-2.0 development files must also be installed. (On Ubuntu, -run `apt install libglib2.0-dev`.) +For Apple aarch64 users `lld` must be installed. -Mac users must have Command Line Tools installed. -([XCode](https://developer.apple.com/xcode/) already includes CLT. Run -`xcode-select --install` to install it without XCode.) +``` +brew install llvm +# Add /opt/homebrew/opt/llvm/bin/ to $PATH +``` -For Windows users: +**Windows**: -1. Get [VS Community 2019](https://www.visualstudio.com/downloads/) with +1. Get [VS Community 2019](https://www.visualstudio.com/downloads/) with the "Desktop development with C++" toolkit and make sure to select the following required tools listed below along with all C++ tools. @@ -85,16 +90,65 @@ For Windows users: - C++/CLI support - VC++ 2015.3 v14.00 (v140) toolset for desktop -2. Enable "Debugging Tools for Windows". Go to "Control Panel" → "Programs" → - "Programs and Features" → Select "Windows Software Development Kit - Windows - 10" → "Change" → "Change" → Check "Debugging Tools For Windows" → "Change" → - "Finish". Or use: - [Debugging Tools for Windows](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/) - (Notice: it will download the files, you should install - `X64 Debuggers And Tools-x64_en-us.msi` file manually.) +2. Enable "Debugging Tools for Windows". + - Go to "Control Panel" → "Programs" → "Programs and Features" + - Select "Windows Software Development Kit - Windows 10" + - → "Change" → "Change" → Check "Debugging Tools For Windows" → "Change" + →"Finish". + - Or use: + [Debugging Tools for Windows](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/) + (Notice: it will download the files, you should install + `X64 Debuggers And Tools-x64_en-us.msi` file manually.) + +### Protobuf Compiler + +> Building Deno requires the +> [Protocol Buffers compiler](https://grpc.io/docs/protoc-installation/). + +**Linux**: + +```sh +apt install -y protobuf-compiler +protoc --version # Ensure compiler version is 3+ +``` + +**Mac**: + +```sh +brew install protobuf +protoc --version # Ensure compiler version is 3+ +``` + +**Windows** + +Windows users can download the latest binary release from +[GitHub](https://github.com/protocolbuffers/protobuf/releases/latest). + +## Python 3 + +> Deno requires [Python 3](https://www.python.org/downloads) for running WPT +> tests. Ensure that a suffix-less `python`/`python.exe` exists in your `PATH` +> and it refers to Python 3. + +## Building Deno + +The easiest way to build Deno is by using a precompiled version of V8: + +``` +cargo build -vv +``` + +However, you may also want to build Deno and V8 from source code if you are +doing lower-level V8 development, or using a platform that does not have +precompiled versions of V8: + +``` +V8_FROM_SOURCE=1 cargo build -vv +``` -See [rusty_v8's README](https://github.com/denoland/rusty_v8) for more details -about the V8 build. +When building V8 from source, there may be more dependencies. See +[rusty_v8's README](https://github.com/denoland/rusty_v8) for more details about +the V8 build. ## Building diff --git a/references/contributing/style_guide.md b/references/contributing/style_guide.md index 30de944f..99aab55b 100644 --- a/references/contributing/style_guide.md +++ b/references/contributing/style_guide.md @@ -57,12 +57,6 @@ The TypeScript portion of the code base is the standard library `std`. ### Use TypeScript instead of JavaScript. -### Use the term "module" instead of "library" or "package". - -For clarity and consistency, avoid the terms "library" and "package". Instead -use "module" to refer to a single JS or TS file and also to refer to a directory -of TS/JS code. - ### Do not use the filename `index.ts`/`index.js`. Deno does not treat "index.js" or "index.ts" in a special way. By using these @@ -319,7 +313,7 @@ test myTestFunction ... ok Example of test: ```ts, ignore -import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { assertEquals } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; import { foo } from "./mod.ts"; Deno.test("myTestFunction", function () { diff --git a/references/vscode_deno.md b/references/vscode_deno.md index 614d315a..39113472 100644 --- a/references/vscode_deno.md +++ b/references/vscode_deno.md @@ -189,7 +189,7 @@ default which provides the ability to run a test from within the editor. When you have a block of code that provides a test, like: ```ts -import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"; +import { assert } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"; Deno.test({ name: "a test case", diff --git a/references/vscode_deno/testing_api.md b/references/vscode_deno/testing_api.md index 6f6a57c4..0714c3a2 100644 --- a/references/vscode_deno/testing_api.md +++ b/references/vscode_deno/testing_api.md @@ -13,7 +13,7 @@ you with a side panel of tests that have been discovered in your project. Also, next to tests identified in the code, there will be decorations which allow you to run and see the status of each test, as well as there will be -entries in the command pallette for tests. +entries in the command palette for tests. ## Discovering tests @@ -27,7 +27,7 @@ In the future, tests will be discovered in a similar fashion to the way the ## Running tests You can run tests from the Test Explorer view, from the decorations next to the -tests when viewing the test code, or via the command pallette. You can also use +tests when viewing the test code, or via the command palette. You can also use the filter function in the Text Explorer view to exclude certain tests from a test run. diff --git a/runtime/builtin_apis.md b/runtime/builtin_apis.md index 8d3f7c66..858a5b72 100644 --- a/runtime/builtin_apis.md +++ b/runtime/builtin_apis.md @@ -78,4 +78,4 @@ The Deno runtime comes with Refer to the links below for code samples of how to create a subprocess. -- [Creating a subprocess (`Deno.run`)](../examples/subprocess.md) +- [Creating a subprocess (`Deno.Command`)](../examples/subprocess.md) diff --git a/runtime/http_server_apis.md b/runtime/http_server_apis.md index 0f9eb9ff..0cce8297 100644 --- a/runtime/http_server_apis.md +++ b/runtime/http_server_apis.md @@ -2,14 +2,11 @@ Deno currently has three HTTP Server APIs: -- [`serve` in the `std/http` module](https://deno.land/std@$STD_VERSION/http/server.ts): - part of the standard library, high-level. -- [`Deno.serve`](https://deno.land/api@$CLI_VERSION?unstable&s=Deno.serve): - native, _higher-level_, supports only http/1.1, but is fast, unstable. +- [`Deno.serve`](https://deno.land/api@$CLI_VERSION?s=Deno.serve): native, + _higher-level_, supports HTTP/1.1 and HTTP2, this is the preferred API to + write HTTP servers in Deno. - [`Deno.serveHttp`](https://deno.land/api@$CLI_VERSION?s=Deno.serveHttp): - native, _low-level_, supports http/2, stable. - -## `serve` from `std/http` + native, _low-level_, supports HTTP/1.1 and HTTP2. - [A "Hello World" server](#a-hello-world-server) - [Inspecting the incoming request](#inspecting-the-incoming-request) @@ -20,45 +17,33 @@ Deno currently has three HTTP Server APIs: ### A "Hello World" server -To start a HTTP server on a given port, you can use the `serve` function from -[`std/http`](https://deno.land/std@$STD_VERSION/http). This function takes a -handler function that will be called for each incoming request, and is expected -to return a response (or a promise resolving to a response). +To start a HTTP server on a given port, you can use the `Deno.serve` function. +This function takes a handler function that will be called for each incoming +request, and is expected to return a response (or a promise resolving to a +response). -Here is an example of a handler function that returns a "Hello, World!" response -for each request: +Here is an example of a server that returns a "Hello, World!" response for each +request: ```ts -function handler(req: Request): Response { +Deno.serve((_req) => { return new Response("Hello, World!"); -} +}); ``` > ℹ️ The handler can also return a `Promise`, which means it can be an > `async` function. -To then listen on a port and handle requests you need to call the `serve` -function from the `https://deno.land/std@$STD_VERSION/http/server.ts` module, -passing in the handler as the first argument: - -```js -import { serve } from "https://deno.land/std@$STD_VERSION/http/server.ts"; - -serve(handler); -``` - -By default `serve` will listen on port `8000`, but this can be changed by -passing in a port number in the second argument options bag: +By default `Deno.serve` will listen on port `8000`, but this can be changed by +passing in a port number in options bag as the first or second argument: ```js -import { serve } from "https://deno.land/std@$STD_VERSION/http/server.ts"; - // To listen on port 4242. -serve(handler, { port: 4242 }); -``` +Deno.serve({ port: 4242 }, handler); -This same options bag can also be used to configure some other options, such as -the hostname to listen on. +// To listen on port 4500 and bind to 0.0.0.0. +Deno.serve({ port: 4242, hostname: "0.0.0.0", handler }); +``` ### Inspecting the incoming request @@ -70,7 +55,7 @@ The request is passed in as the first argument to the handler function. Here is an example showing how to extract various parts of the request: ```ts -async function handler(req: Request): Promise { +Deno.serve(async (req) => { console.log("Method:", req.method); const url = new URL(req.url); @@ -85,7 +70,7 @@ async function handler(req: Request): Promise { } return new Response("Hello, World!"); -} +}); ``` > ⚠️ Be aware that the `req.text()` call can fail if the user hangs up the @@ -104,7 +89,7 @@ Here is an example of returning a response with a 404 status code, a JSON body, and a custom header: ```ts -function handler(req: Request): Response { +Deno.serve((req) => { const body = JSON.stringify({ message: "NOT FOUND" }); return new Response(body, { status: 404, @@ -112,14 +97,14 @@ function handler(req: Request): Response { "content-type": "application/json; charset=utf-8", }, }); -} +}); ``` Response bodies can also be streams. Here is an example of a response that returns a stream of "Hello, World!" repeated every second: ```ts -function handler(req: Request): Response { +Deno.serve((req) => { let timer: number; const body = new ReadableStream({ async start(controller) { @@ -136,7 +121,7 @@ function handler(req: Request): Response { "content-type": "text/plain; charset=utf-8", }, }); -} +}); ``` > ℹ️ Note the `cancel` function here. This is called when the client hangs up the @@ -155,40 +140,80 @@ function handler(req: Request): Response { > ℹ️ To use HTTPS, you will need a valid TLS certificate and a private key for > your server. -To use HTTPS, use `serveTls` from the -`https://deno.land/std@$STD_VERSION/http/server.ts` module instead of `serve`. -This takes two extra arguments in the options bag: `certFile` and `keyFile`. -These are paths to the certificate and key files, respectively. +To use HTTPS, pass two extra arguments in the options bag: `cert` and `key`. +These are contents of the certificate and key files, respectively. ```js -import { serveTls } from "https://deno.land/std@$STD_VERSION/http/server.ts"; - -serveTls(handler, { +Deno.serve({ port: 443, - certFile: "./cert.pem", - keyFile: "./key.pem", -}); + cert: Deno.readTextFileSync("./cert.pem"), + key: Deno.readTextFileSync("./key.pem"), +}, handler); ``` ### HTTP/2 support -HTTP/2 support is "automatic" when using the _native_ APIs with Deno. You just -need to create your server, and the server will handle HTTP/1 or HTTP/2 requests -seamlessly. +HTTP/2 support is "automatic" when using the HTTP server APIs with Deno. You +just need to create your server, and the server will handle HTTP/1 or HTTP/2 +requests seamlessly. + +HTTP/2 is also supported over cleartext with prior knowledge. + +### Automatic body compression + +The HTTP server has built in automatic compression of response bodies. When a +response is sent to a client, Deno determines if the response body can be safely +compressed. This compression happens within the internals of Deno, so it is fast +and efficient. + +Currently Deno supports gzip and brotli compression. A body is automatically +compressed if the following conditions are true: + +- The request has an + [`Accept-Encoding`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding) + header which indicates the requester supports `br` for Brotli or `gzip`. Deno + will respect the preference of the + [quality value](https://developer.mozilla.org/en-US/docs/Glossary/Quality_values) + in the header. +- The response includes a + [`Content-Type`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) + which is considered compressible. (The list is derived from + [`jshttp/mime-db`](https://github.com/jshttp/mime-db/blob/master/db.json) with + the actual list + [in the code](https://github.com/denoland/deno/blob/v1.21.0/ext/http/compressible.rs).) +- The response body is greater than 64 bytes. + +When the response body is compressed, Deno will set the Content-Encoding header +to reflect the encoding as well as ensure the Vary header is adjusted or added +to indicate what request headers affected the response. + +When is compression skipped? In addition to the logic above, there are a few +other reasons why a response won’t be compressed automatically: + +- The response contains a `Content-Encoding` header. This indicates your server + has done some form of encoding already. +- The response contains a + [`Content-Range`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Range) + header. This indicates that your server is responding to a range request, + where the bytes and ranges are negotiated outside of the control of the + internals to Deno. +- The response has a + [`Cache-Control`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) + header which contains a + [`no-transform`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#other) + value. This indicates that your server doesn’t want Deno or any downstream + proxies to modify the response. ## `Deno.serveHttp` -We generally recommnend that you use the `serve` API described above, as it +We generally recommend that you use the `Deno.serve` API described above, as it handles all of the intricacies of parallel requests on a single connection, error handling, and so on. However, if you are interested creating your own robust and performant web servers in Deno, lower-level, _native_ HTTP server APIs are available as of Deno 1.9 and later. -> ℹ️ These APIs were stabilized in Deno 1.13 and no longer require `--unstable` -> flag. - > ⚠️ You should probably not be using this API, as it is not easy to get right. -> Use the `serve` API in the `std/http` library instead. +> Use the `Deno.serve` API instead. ### Listening for a connection diff --git a/runtime/kv.md b/runtime/kv.md index 26a171c1..63dbf2d6 100644 --- a/runtime/kv.md +++ b/runtime/kv.md @@ -1,5 +1,13 @@ # Deno KV +> ⚠️ Deno KV is currently **experimental** and **subject to change**. While we do +> our best to ensure data durability, data loss is possible, especially around +> Deno updates. We recommend that you backup your data regularly and consider +> storing data in a secondary store for the time being. + +> 🌐 Deno KV is available for Deno Deploy. +> [Read the Deno Deploy KV docs](https://deno.com/deploy/docs/kv). + Since version 1.32, Deno has a built in key-value store that durably persists data on disk, allowing for data storage and access across service and system restarts. @@ -21,14 +29,6 @@ All writes to the KV store are strongly consistent and immediately durably persisted. Reads are strongly consistent by default, but alternative consistency modes are available to enable different performance tradeoffs. -> ⚠️ Deno KV is currently **experimental** and **subject to change**. While we do -> our best to ensure data durability, data loss is possible, especially around -> Deno updates. We recommend that you backup your data regularly and consider -> storing data in a secondary store for the time being. - -> 🌐 Deno KV is available in closed beta for Deno Deploy. -> [Read the Deno Deploy KV docs](https://deno.com/deploy/docs/kv). - ## Getting started > ⚠️ Because Deno KV is currently **experimental** and **subject to change**, it @@ -140,6 +140,20 @@ if (res.ok) { - [Source code](https://github.com/hashrock/kv-sketchbook) - [Live preview](https://hashrock-kv-sketchbook.deno.dev/) +**Deno KV OAuth** + +- High-level OAuth 2.0 powered by Deno KV +- [Source code](https://github.com/denoland/deno_kv_oauth) +- [Live preview](https://kv-oauth.deno.dev/) + +**Deno SaaSKit** + +- Modern SaaS template built on Fresh. +- [Hacker News](https://news.ycombinator.com/)-like demo entirely built on KV. +- Uses Deno KV OAuth for GitHub OAuth 2.0 authentication +- [Source code](https://github.com/denoland/saaskit) +- [Live preview](https://hunt.deno.land/) + ## Reference - [API Reference](https://deno.land/api?unstable&s=Deno.Kv) diff --git a/runtime/kv/key_expiration.md b/runtime/kv/key_expiration.md new file mode 100644 index 00000000..7ddede75 --- /dev/null +++ b/runtime/kv/key_expiration.md @@ -0,0 +1,52 @@ +# Key Expiration + +> ⚠️ Deno KV is currently **experimental** and **subject to change**. While we do +> our best to ensure data durability, data loss is possible, especially around +> Deno updates. We recommend that you backup your data regularly and consider +> storing data in a secondary store for the time being. + +> 🌐 Deno KV is available for Deno Deploy. +> [Read the Deno Deploy KV docs](https://deno.com/deploy/docs/kv). + +Since version 1.36.2, Deno KV supports key expiration. This allows an expiration +timestamp to be associated with a key, after which the key will be automatically +deleted from the database: + +```ts,ignore +const kv = await Deno.openKv(); + +// `expireIn` is the number of milliseconds after which the key will expire. +function addSession(session: Session, expireIn: number) { + await kv.set(["sessions", session.id], session, { expireIn }); +} +``` + +Key expiration is supported on both Deno CLI and Deno Deploy. + +## Atomic expiration of multiple keys + +If multiple keys are set in the same atomic operation and have the same +`expireIn` value, the expiration of those keys will be atomic. For example: + +```ts,ignore +const kv = await Deno.openKv(); + +function addUnverifiedUser( + user: User, + verificationToken: string, + expireIn: number, +) { + await kv.atomic() + .set(["users", user.id], user, { expireIn }) + .set(["verificationTokens", verificationToken], user.id, { expireIn }) + .commit(); +} +``` + +## Caveats + +The expire timestamp specifies the _earliest_ time after which the key can be +deleted from the database. An implementation is allowed to expire a key at any +time after the specified timestamp, but not before. If you need to strictly +enforce an expiration time (e.g. for security purposes), please also add it as a +field of your value and do a check after retrieving the value from the database. diff --git a/runtime/kv/key_space.md b/runtime/kv/key_space.md index 51814458..28983555 100644 --- a/runtime/kv/key_space.md +++ b/runtime/kv/key_space.md @@ -5,7 +5,7 @@ > Deno updates. We recommend that you backup your data regularly and consider > storing data in a secondary store for the time being. -> 🌐 Deno KV is available in closed beta for Deno Deploy. +> 🌐 Deno KV is available for Deno Deploy. > [Read the Deno Deploy KV docs](https://deno.com/deploy/docs/kv). Deno KV is a key value store. The key space is a flat namespace of @@ -81,6 +81,70 @@ of values within a type. ["teams", "engineering", "members", 1n]; // Member with ID 1n in the engineering team ``` +### Universally Unique Lexicographically Sortable Identifiers (ULIDs) + +Key part ordering allows keys consisting of timestamps and ID parts to be listed +chronologically. Typically, you can generate a key using the following: +[`Date.now()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now) +and +[`crypto.randomUUID()`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID): + +```js +async function setUser(user) { + await kv.set(["users", Date.now(), crypto.randomUUID()], user); +} +``` + +Run multiple times sequentially, this produces the following keys: + +```js +["users", 1691377037923, "8c72fa25-40ad-42ce-80b0-44f79bc7a09e"]; // First user +["users", 1691377037924, "8063f20c-8c2e-425e-a5ab-d61e7a717765"]; // Second user +["users", 1691377037925, "35310cea-58ba-4101-b09a-86232bf230b2"]; // Third user +``` + +However, having the timestamp and ID represented within a single key part may be +more straightforward in some cases. You can use a +[Universally Unique Lexicographically Sortable Identifier (ULID)](https://github.com/ulid/spec) +to do this. This type of identifier encodes a UTC timestamp, is +lexicographically sortable and is cryptographically random by default: + +```js +import { ulid } from "https://deno.land/x/ulid/mod.ts"; + +const kv = await Deno.openKv(); + +async function setUser(user) { + await kv.set(["users", ulid()], user); +} +``` + +```js +["users", "01H76YTWK3YBV020S6MP69TBEQ"]; // First user +["users", "01H76YTWK4V82VFET9YTYDQ0NY"]; // Second user +["users", "01H76YTWK5DM1G9TFR0Y5SCZQV"]; // Third user +``` + +Furthermore, you can generate ULIDs monotonically increasingly using a factory +function: + +```js +import { monotonicFactory } from "https://deno.land/x/ulid/mod.ts"; + +const ulid = monotonicFactory(); + +async function setUser(user) { + await kv.set(["users", ulid()], user); +} +``` + +```js +// Strict ordering for the same timestamp by incrementing the least-significant random bit by 1 +["users", "01H76YTWK3YBV020S6MP69TBEQ"]; // First user +["users", "01H76YTWK3YBV020S6MP69TBER"]; // Second user +["users", "01H76YTWK3YBV020S6MP69TBES"]; // Third user +``` + ## Values Values in Deno KV can be arbitrary JavaScript values that are compatible with @@ -160,8 +224,8 @@ value was modified. Versionstamps do not represent real time, but rather the order in which the values were modified. Because versionstamps are monotonically increasing, they can be used to -determine wether a given value is newer or older than another value. This can be -done by comparing the versionstamps of the two values. If versionstamp A is +determine whether a given value is newer or older than another value. This can +be done by comparing the versionstamps of the two values. If versionstamp A is greater than versionstamp B, then value A was modified more recently than value B. diff --git a/runtime/kv/operations.md b/runtime/kv/operations.md index dd63cb1a..f7605147 100644 --- a/runtime/kv/operations.md +++ b/runtime/kv/operations.md @@ -5,7 +5,7 @@ > Deno updates. We recommend that you backup your data regularly and consider > storing data in a secondary store for the time being. -> 🌐 Deno KV is available in closed beta for Deno Deploy. +> 🌐 Deno KV is available for Deno Deploy. > [Read the Deno Deploy KV docs](https://deno.com/deploy/docs/kv). The Deno KV API provides a set of operations that can be performed on the key @@ -63,14 +63,14 @@ parts, but not inclusive of an exact match of the key. The prefix selector may optionally be given a `start` OR `end` key to limit the range of keys returned. The `start` key is inclusive, and the `end` key is exclusive. -The `range` selector matches all keys that are lexographically between the given +The range selector matches all keys that are lexicographically between the given `start` and `end` keys. The `start` key is inclusive, and the `end` key is exclusive. > Note: In the case of the prefix selector, the `prefix` key must consist only > of full (not partial) key parts. For example, if the key `["foo", "bar"]` > exists in the store, then the prefix selector `["foo"]` will match it, but the -> prefix selector `["f"]` will not. +> prefix selector `["f"]` will not. The range selector can use key parts. The list operation may optionally be given a `limit` to limit the number of keys returned. @@ -109,7 +109,7 @@ for await (const res of iter) users.push(res); console.log(users[0]); // { key: ["users", "alex"], value: "alex", versionstamp: "00a44a3c3e53b9750000" } console.log(users[1]); // { key: ["users", "sam"], value: "sam", versionstamp: "00e0a2a0f0178b270000" } -// Return all users starting with characters between "a" and "n" +// Return all users starting with characters between "a" and "n" (range selector) const iter = kv.list({ start: ["users", "a"], end: ["users", "n"] }); const users = []; for await (const res of iter) users.push(res); diff --git a/runtime/kv/secondary_indexes.md b/runtime/kv/secondary_indexes.md index e14b1380..962336e5 100644 --- a/runtime/kv/secondary_indexes.md +++ b/runtime/kv/secondary_indexes.md @@ -5,7 +5,7 @@ > Deno updates. We recommend that you backup your data regularly and consider > storing data in a secondary store for the time being. -> 🌐 Deno KV is available in closed beta for Deno Deploy. +> 🌐 Deno KV is available for Deno Deploy. > [Read the Deno Deploy KV docs](https://deno.com/deploy/docs/kv). Key-value stores like Deno KV organize data as collections of key-value pairs, diff --git a/runtime/kv/transactions.md b/runtime/kv/transactions.md index 57df4fa6..2c6a65c1 100644 --- a/runtime/kv/transactions.md +++ b/runtime/kv/transactions.md @@ -5,7 +5,7 @@ > Deno updates. We recommend that you backup your data regularly and consider > storing data in a secondary store for the time being. -> 🌐 Deno KV is available in closed beta for Deno Deploy. +> 🌐 Deno KV is available for Deno Deploy. > [Read the Deno Deploy KV docs](https://deno.com/deploy/docs/kv). > A database transaction, in the context of a key-value store like Deno KV, diff --git a/runtime/permission_apis.md b/runtime/permission_apis.md index 86a8bc3b..b53228a1 100644 --- a/runtime/permission_apis.md +++ b/runtime/permission_apis.md @@ -50,15 +50,35 @@ Check, by descriptor, if a permission is granted or not. const desc1 = { name: "read", path: "/foo" } as const; console.log(await Deno.permissions.query(desc1)); -// PermissionStatus { state: "granted" } +// PermissionStatus { state: "granted", partial: false } const desc2 = { name: "read", path: "/foo/bar" } as const; console.log(await Deno.permissions.query(desc2)); -// PermissionStatus { state: "granted" } +// PermissionStatus { state: "granted", partial: false } const desc3 = { name: "read", path: "/bar" } as const; console.log(await Deno.permissions.query(desc3)); -// PermissionStatus { state: "prompt" } +// PermissionStatus { state: "prompt", partial: false } +``` + +If `--deny-read` flag was used to restrict some of the filepaths, the result +will contain `partial: true` describing that not all subpaths have permissions +granted: + +```ts +// deno run --allow-read=/foo --deny-read=/foo/bar main.ts + +const desc1 = { name: "read", path: "/foo" } as const; +console.log(await Deno.permissions.query(desc1)); +// PermissionStatus { state: "granted", partial: true } + +const desc2 = { name: "read", path: "/foo/bar" } as const; +console.log(await Deno.permissions.query(desc2)); +// PermissionStatus { state: "denied", partial: false } + +const desc3 = { name: "read", path: "/bar" } as const; +console.log(await Deno.permissions.query(desc3)); +// PermissionStatus { state: "prompt", partial: false } ``` ## Permission states @@ -73,14 +93,18 @@ This will come up in [Request permissions](#request-permissions). The intuitive understanding behind the result of the second query in [Query permissions](#query-permissions) is that read access was granted to -`/foo` and `/foo/bar` is within `/foo` so `/foo/bar` is allowed to be read. +`/foo` and `/foo/bar` is within `/foo` so `/foo/bar` is allowed to be read. This +hold true, unless the CLI-granted permission is _partial_ to the queried +permissions (as an effect of using a `--deny-*` flag). We can also say that `desc1` is _[stronger than](https://www.w3.org/TR/permissions/#ref-for-permissiondescriptor-stronger-than)_ `desc2`. This means that for any set of CLI-granted permissions: -1. If `desc1` queries to `{ state: "granted" }` then so must `desc2`. -2. If `desc2` queries to `{ state: "denied" }` then so must `desc1`. +1. If `desc1` queries to `{ state: "granted", partial: false }` then so must + `desc2`. +2. If `desc2` queries to `{ state: "denied", partial: false }` then so must + `desc1`. More examples: @@ -105,13 +129,13 @@ const desc1 = { name: "read", path: "/foo" } as const; const status1 = await Deno.permissions.request(desc1); // ⚠️ Deno requests read access to "/foo". Grant? [y/n (y = yes allow, n = no deny)] y console.log(status1); -// PermissionStatus { state: "granted" } +// PermissionStatus { state: "granted", partial: false } const desc2 = { name: "read", path: "/bar" } as const; const status2 = await Deno.permissions.request(desc2); // ⚠️ Deno requests read access to "/bar". Grant? [y/n (y = yes allow, n = no deny)] n console.log(status2); -// PermissionStatus { state: "denied" } +// PermissionStatus { state: "denied", partial: false } ``` If the current permission state is "prompt", a prompt will appear on the user's @@ -134,7 +158,7 @@ Downgrade a permission from "granted" to "prompt". const desc = { name: "read", path: "/foo" } as const; console.log(await Deno.permissions.revoke(desc)); -// PermissionStatus { state: "prompt" } +// PermissionStatus { state: "prompt", partial: false } ``` What happens when you try to revoke a permission which is _partial_ to one @@ -145,10 +169,10 @@ granted on the CLI? const desc = { name: "read", path: "/foo/bar" } as const; console.log(await Deno.permissions.revoke(desc)); -// PermissionStatus { state: "prompt" } +// PermissionStatus { state: "prompt", partial: false } const cliDesc = { name: "read", path: "/foo" } as const; console.log(await Deno.permissions.revoke(cliDesc)); -// PermissionStatus { state: "prompt" } +// PermissionStatus { state: "prompt", partial: false } ``` The CLI-granted permission, which implies the revoked permission, was also diff --git a/runtime/web_platform_apis.md b/runtime/web_platform_apis.md index f107aa46..77c46785 100644 --- a/runtime/web_platform_apis.md +++ b/runtime/web_platform_apis.md @@ -1,12 +1,13 @@ # Using Web Platform APIs -Deno aims to use web platform APIs (like `fetch`) instead of inventing a new -proprietary API where it makes sense. These APIs generally follow the -specifications and should match the implementation in Chrome and Firefox. In -some cases it makes sense to deviate from the spec slightly, because of the -different security model Deno has. +One way Deno simplifies web and cloud development is by using Web Platform APIs +(like `fetch`) over proprietary APIs. This means if you've ever built for the +browser, you're likely already familiar with Deno, and if you're learning Deno, +you're also investing in your knowledge of the web. -Here is a list of web platform APIs Deno implements: +## Supported APIs + +Here's a partial list of supported web platform APIs in Deno: - [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) - [BroadcastChannel](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel) @@ -34,7 +35,12 @@ Here is a list of web platform APIs Deno implements: - [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) You can find the Deno reference for these APIs -[here](https://deno.land/api@$CLI_VERSION). +[here](https://deno.land/api@$CLI_VERSION). To check if a Web Platform API is +available in Deno, click on +[the interface on MDN](https://developer.mozilla.org/en-US/docs/Web/API#interfaces) +and refer to +[its Browser Compatibility table](https://developer.mozilla.org/en-US/docs/Web/API/AbortController#browser_compatibility) +(link as an example). ## `fetch` API @@ -130,6 +136,7 @@ You can find documentation about this API on - Events do not bubble, because Deno does not have a DOM hierarchy, so there is no tree for Events to bubble/capture through. +- `timeStamp` property is always set to `0`. --- diff --git a/toc.json b/toc.json index 686e400a..fd3791d6 100644 --- a/toc.json +++ b/toc.json @@ -122,7 +122,9 @@ "express": "Express" } }, - "faqs": "Frequently asked questions" + "faqs": "Frequently asked questions", + "migrate": "Migrate from Node", + "compatibility": "API compatibility list" } }, "runtime": { @@ -141,7 +143,8 @@ "operations": "Operations", "transactions": "Transactions", "secondary_indexes": "Secondary indexes", - "key_space": "Key Space" + "key_space": "Key Space", + "key_expiration": "Key Expiration" } }, "location_api": "Location API", diff --git a/tools.md b/tools.md index 115d90d5..5323a300 100644 --- a/tools.md +++ b/tools.md @@ -1,18 +1,27 @@ # Built-In Tooling -Deno provides some built-in tooling that is useful when working with JavaScript -and TypeScript: - -- [start new project (`deno init`)](./tools/init.md) -- [benchmarker (`deno bench`)](./tools/benchmarker.md) -- [bundler (`deno bundle`)](./tools/bundler.md) -- [compiling executables (`deno compile`)](./tools/compiler.md) -- [installer (`deno install`)](./tools/script_installer.md) -- [dependency inspector (`deno info`)](./tools/dependency_inspector.md) -- [documentation generator (`deno doc`)](./tools/documentation_generator.md) -- [formatter (`deno fmt`)](./tools/formatter.md) -- [linter (`deno lint`)](./tools/linter.md) -- [repl (`deno repl`)](./tools/repl.md) -- [task runner (`deno task`)](./tools/task_runner.md) -- [test runner (`deno test`)](./basics/testing.md) -- [vendoring dependencies (`deno vendor`)](./tools/vendor.md) +Deno ships with a robust toolchain so you can start building immediately without +needing to setup a disparate set of tooling. + +Deno's modern tooling is categorized below: + +## Develop + +- [start a new project: `deno init`](./tools/init.md) +- [linter: `deno lint`](./tools/linter.md) +- [formatter: `deno fmt`](./tools/formatter.md) +- [typechecker: `deno check`](./advanced/typescript/overview.md#type-checking) +- [task runner: `deno task`](./tools/task_runner.md) +- [generate documentation: `deno doc`](./tools/documentation_generator.md) +- [inspect dependencies: `deno info`](./tools/dependency_inspector.md) +- [vendor dependencies: `deno vendor`](./tools/vendor.md) + +## Test + +- [test runner: `deno test`](./basics/testing.md) +- [benchmark: `deno bench`](./tools/benchmarker.md) + +## Distribute + +- [compile to a single executable: `deno compile`](./tools/compiler.md) +- [installer: `deno install`](./tools/script_installer.md) diff --git a/tools/benchmarker.md b/tools/benchmarker.md index 7be56aef..80443742 100644 --- a/tools/benchmarker.md +++ b/tools/benchmarker.md @@ -84,6 +84,42 @@ Deno.bench("async hello world", async () => { }); ``` +### Critical sections + +Sometimes the benchmark case needs to include setup and teardown code that would +taint the benchmark results. For example, if you want to measure how long it +takes to read a small file, you need to open the file, read it, and then close +it. If the file is small enough the time it takes to open and close the file +might outweigh the time it takes to read the file itself. + +To help with such situations you can `Deno.BenchContext.start` and +`Deno.BenchContext.end` to tell the benchmarking tool about the critical section +you want to measure. Everything outside of the section between these two calls +will be excluded from the measurement. + +```ts, ignore +import { readAll } from "https://deno.land/std@$STD_VERSION/streams/mod.ts"; + +Deno.bench("foo", async (b) => { + // Open a file that we will act upon. + const file = await Deno.open("a_big_data_file.txt"); + + // Tell the benchmarking tool that this is the only section you want + // to measure. + b.start(); + + // Now let's measure how long it takes to read all of the data from the file. + await readAll(file); + + // End measurement here. + b.end(); + + // Now we can perform some potentially time-consuming teardown that will not + // taint out benchmark results. + file.close(); +}); +``` + ## Grouping and baselines When registering a bench case, it can be assigned to a group, using diff --git a/tools/bundler.md b/tools/bundler.md index 42e29021..56f36c29 100644 --- a/tools/bundler.md +++ b/tools/bundler.md @@ -6,10 +6,10 @@ Deno, which includes all dependencies of the specified input. For example: ```bash -deno bundle https://deno.land/std@$STD_VERSION/examples/colors.ts colors.bundle.js -Bundle https://deno.land/std@$STD_VERSION/examples/colors.ts -Download https://deno.land/std@$STD_VERSION/examples/colors.ts -Download https://deno.land/std@$STD_VERSION/fmt/colors.ts +deno bundle https://deno.land/std@0.198.0/examples/colors.ts colors.bundle.js +Bundle https://deno.land/std@0.198.0/examples/colors.ts +Download https://deno.land/std@0.198.0/examples/colors.ts +Download https://deno.land/std@0.198.0/fmt/colors.ts Emit "colors.bundle.js" (9.83KB) ``` diff --git a/tools/compiler.md b/tools/compiler.md index 3acc23cb..20acace4 100644 --- a/tools/compiler.md +++ b/tools/compiler.md @@ -4,7 +4,7 @@ self-contained executable. ``` -> deno compile https://deno.land/std/examples/welcome.ts +> deno compile https://examples.deno.land/hello-world.ts ``` If you omit the `OUT` parameter, the name of the executable file will be @@ -28,6 +28,41 @@ can be partially embedded. > ./file_server --help ``` +## Dynamic Imports + +By default, statically analyzable dynamic imports (imports that have the string +literal within the `import("...")` call expression) will be included in the +output. + +```ts, ignore +// calculator.ts and its dependencies will be included in the binary +const calculator = await import("./calculator.ts"); +``` + +But non-statically analyzable dynamic imports won't: + +```ts, ignore +const specifier = condition ? "./calc.ts" : "./better_calc.ts"; +const calculator = await import(specifier); +``` + +To include non-statically analyzable dynamic imports, specify an +`--include ` flag. + +```shell +deno compile --include calc.ts --include better_calc.ts main.ts +``` + +## Workers + +Similarly to non-statically analyzable dynamic imports, code for +[workers](../runtime/workers.md) is not included in the compiled executable by +default. You must use the `--include ` flag to include the worker code. + +```shell +deno compile --include worker.ts main.ts +``` + ## Cross Compilation You can compile binaries for other platforms by adding the `--target` CLI flag. diff --git a/tools/repl.md b/tools/repl.md index dc5187da..0004d603 100644 --- a/tools/repl.md +++ b/tools/repl.md @@ -50,14 +50,14 @@ into the REPL. This is useful for importing some code you commonly use in the REPL, or modifying the runtime in some way: ``` -$ deno repl --allow-net --eval 'import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"' -Deno 1.31.0 -exit using ctrl+d or close() +$ deno repl --allow-net --eval 'import { assert } from "https://deno.land/std@$STD_VERSION/assert/mod.ts"' +Deno 1.36.0 +exit using ctrl+d, ctrl+c, or close() > assert(true) undefined > assert(false) Uncaught AssertionError - at assert (https://deno.land/std@0.178.0/testing/asserts.ts:141:11) + at assert (https://deno.land/std@0.197.0/assert/assert.ts:7:11) at :2:1 ``` diff --git a/typos.toml b/typos.toml new file mode 100644 index 00000000..4244c0fc --- /dev/null +++ b/typos.toml @@ -0,0 +1,2 @@ +[default.extend-words] +Linke = "Linke" # LinkeDOM \ No newline at end of file