chore: move docs to separate repository
3
docs/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
Documentation is available at: https://deno.land/manual
|
||||
|
||||
Documentation repository is at: https://github.com/denoland/manual
|
|
@ -1,81 +0,0 @@
|
|||
# Contributing
|
||||
|
||||
- Read the [style guide](./contributing/style_guide.md).
|
||||
|
||||
- Please don't make [the benchmarks](https://deno.land/benchmarks) worse.
|
||||
|
||||
- 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
|
||||
_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.
|
||||
|
||||
- Please be professional in the forums. We follow
|
||||
[Rust's code of conduct](https://www.rust-lang.org/policies/code-of-conduct)
|
||||
(CoC). Have a problem? Email ry@tinyclouds.org.
|
||||
|
||||
## Development
|
||||
|
||||
Instructions on how to build from source can be found
|
||||
[here](./contributing/building_from_source.md).
|
||||
|
||||
## Submitting a Pull Request
|
||||
|
||||
Before submitting, please make sure the following is done:
|
||||
|
||||
1. Give the PR a descriptive title.
|
||||
|
||||
Examples of good PR title:
|
||||
|
||||
- fix(std/http): Fix race condition in server
|
||||
- docs(console): Update docstrings
|
||||
- feat(doc): Handle nested re-exports
|
||||
|
||||
Examples of bad PR title:
|
||||
|
||||
- fix #7123
|
||||
- update docs
|
||||
- fix bugs
|
||||
|
||||
2. Ensure there is a related issue and it is referenced in the PR text.
|
||||
3. Ensure there are tests that cover the changes.
|
||||
4. Ensure `cargo test` passes.
|
||||
5. Ensure `./tools/format.js` passes without changing files.
|
||||
6. Ensure `./tools/lint.js` passes.
|
||||
|
||||
## Adding Ops (aka bindings)
|
||||
|
||||
We are very concerned about making mistakes when adding new APIs. When adding an
|
||||
Op to Deno, the counterpart interfaces on other platforms should be researched.
|
||||
Please list how this functionality is done in Go, Node, Rust, and Python.
|
||||
|
||||
As an example, see how `Deno.rename()` was proposed and added in
|
||||
[PR #671](https://github.com/denoland/deno/pull/671).
|
||||
|
||||
## Releases
|
||||
|
||||
Summary of the changes from previous releases can be found
|
||||
[here](https://github.com/denoland/deno/releases).
|
||||
|
||||
## Documenting APIs
|
||||
|
||||
It is important to document public APIs and we want to do that inline with the
|
||||
code. This helps ensure that code and documentation are tightly coupled
|
||||
together.
|
||||
|
||||
### Utilize JSDoc
|
||||
|
||||
All publicly exposed APIs and types, both via the `deno` module as well as the
|
||||
global/`window` namespace should have JSDoc documentation. This documentation is
|
||||
parsed and available to the TypeScript compiler, and therefore easy to provide
|
||||
further downstream. JSDoc blocks come just prior to the statement they apply to
|
||||
and are denoted by a leading `/**` before terminating with a `*/`. For example:
|
||||
|
||||
```ts
|
||||
/** A simple JSDoc comment */
|
||||
export const FOO = "foo";
|
||||
```
|
||||
|
||||
Find more at: https://jsdoc.app/
|
|
@ -1,64 +0,0 @@
|
|||
## Internal details
|
||||
|
||||
### Deno and Linux analogy
|
||||
|
||||
| **Linux** | **Deno** |
|
||||
| ------------------------------: | :------------------------------------------- |
|
||||
| Processes | Web Workers |
|
||||
| Syscalls | Ops |
|
||||
| File descriptors (fd) | [Resource ids (rid)](architecture#resources) |
|
||||
| Scheduler | Tokio |
|
||||
| Userland: libc++ / glib / boost | https://deno.land/std/ |
|
||||
| /proc/\$\$/stat | [Deno.metrics()](architecture#metrics) |
|
||||
| man pages | deno types |
|
||||
|
||||
#### Resources
|
||||
|
||||
Resources (AKA `rid`) are Deno's version of file descriptors. They are integer
|
||||
values used to refer to open files, sockets, and other concepts. For testing it
|
||||
would be good to be able to query the system for how many open resources there
|
||||
are.
|
||||
|
||||
```ts
|
||||
console.log(Deno.resources());
|
||||
// { 0: "stdin", 1: "stdout", 2: "stderr" }
|
||||
Deno.close(0);
|
||||
console.log(Deno.resources());
|
||||
// { 1: "stdout", 2: "stderr" }
|
||||
```
|
||||
|
||||
#### Metrics
|
||||
|
||||
Metrics is Deno's internal counter for various statistics.
|
||||
|
||||
```shell
|
||||
> console.table(Deno.metrics())
|
||||
┌─────────────────────────┬───────────┐
|
||||
│ (idx) │ Values │
|
||||
├─────────────────────────┼───────────┤
|
||||
│ opsDispatched │ 9 │
|
||||
│ opsDispatchedSync │ 0 │
|
||||
│ opsDispatchedAsync │ 0 │
|
||||
│ opsDispatchedAsyncUnref │ 0 │
|
||||
│ opsCompleted │ 9 │
|
||||
│ opsCompletedSync │ 0 │
|
||||
│ opsCompletedAsync │ 0 │
|
||||
│ opsCompletedAsyncUnref │ 0 │
|
||||
│ bytesSentControl │ 504 │
|
||||
│ bytesSentData │ 0 │
|
||||
│ bytesReceived │ 856 │
|
||||
└─────────────────────────┴───────────┘
|
||||
```
|
||||
|
||||
### Schematic diagram
|
||||
|
||||
![architectural schematic](https://deno.land/images/schematic_v0.2.png)
|
||||
|
||||
### Conference
|
||||
|
||||
- Ryan Dahl. (May 27, 2020).
|
||||
[An interesting case with Deno](https://www.youtube.com/watch?v=1b7FoBwxc7E).
|
||||
Deno Israel.
|
||||
- Bartek Iwańczuk. (Oct 6, 2020).
|
||||
[Deno internals - how modern JS/TS runtime is
|
||||
built](https://www.youtube.com/watch?v=AOvg_GbnsbA&t=35m13s). Paris Deno.
|
|
@ -1,104 +0,0 @@
|
|||
## Building from source
|
||||
|
||||
Below are instructions on how to build Deno from source. If you just want to use
|
||||
Deno you can download a prebuilt executable (more information in the
|
||||
`Getting Started` chapter).
|
||||
|
||||
### Cloning the Repository
|
||||
|
||||
Clone on Linux or Mac:
|
||||
|
||||
```shell
|
||||
git clone --recurse-submodules https://github.com/denoland/deno.git
|
||||
```
|
||||
|
||||
Extra steps for Windows users:
|
||||
|
||||
1. [Enable "Developer Mode"](https://www.google.com/search?q=windows+enable+developer+mode)
|
||||
(otherwise symlinks would require administrator privileges).
|
||||
2. Make sure you are using git version 2.19.2.windows.1 or newer.
|
||||
3. Set `core.symlinks=true` before the checkout:
|
||||
```shell
|
||||
git config --global core.symlinks true
|
||||
git clone --recurse-submodules https://github.com/denoland/deno.git
|
||||
```
|
||||
|
||||
### Prerequisites
|
||||
|
||||
> Deno requires the progressively latest stable release of Rust. Deno does not
|
||||
> support the Rust nightlies.
|
||||
|
||||
[Update or Install Rust](https://www.rust-lang.org/tools/install). Check that
|
||||
Rust installed/updated correctly:
|
||||
|
||||
```
|
||||
rustc -V
|
||||
cargo -V
|
||||
```
|
||||
|
||||
### Building Deno
|
||||
|
||||
The easiest way to build Deno is by using a precompiled version of V8:
|
||||
|
||||
```
|
||||
cargo build -vv
|
||||
```
|
||||
|
||||
However if you want to build Deno and V8 from source code:
|
||||
|
||||
```
|
||||
V8_FROM_SOURCE=1 cargo build -vv
|
||||
```
|
||||
|
||||
When building V8 from source, there are more dependencies:
|
||||
|
||||
[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`.)
|
||||
|
||||
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.)
|
||||
|
||||
For Windows users:
|
||||
|
||||
1. Get [VS Community 2019](https://www.visualstudio.com/downloads/) with
|
||||
"Desktop development with C++" toolkit and make sure to select the following
|
||||
required tools listed below along with all C++ tools.
|
||||
|
||||
- Visual C++ tools for CMake
|
||||
- Windows 10 SDK (10.0.17763.0)
|
||||
- Testing tools core features - Build Tools
|
||||
- Visual C++ ATL for x86 and x64
|
||||
- Visual C++ MFC for x86 and x64
|
||||
- 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.)
|
||||
|
||||
See [rusty_v8's README](https://github.com/denoland/rusty_v8) for more details
|
||||
about the V8 build.
|
||||
|
||||
### Building
|
||||
|
||||
Build with Cargo:
|
||||
|
||||
```shell
|
||||
# Build:
|
||||
cargo build -vv
|
||||
|
||||
# Build errors? Ensure you have latest main and try building again, or if that doesn't work try:
|
||||
cargo clean && cargo build -vv
|
||||
|
||||
# Run:
|
||||
./target/debug/deno run cli/tests/002_hello.ts
|
||||
```
|
|
@ -1,69 +0,0 @@
|
|||
## Testing and Tools
|
||||
|
||||
### Tests
|
||||
|
||||
Test `deno`:
|
||||
|
||||
```shell
|
||||
# Run the whole suite:
|
||||
cargo test
|
||||
|
||||
# Only test cli/tests/unit/:
|
||||
cargo test js_unit_tests
|
||||
```
|
||||
|
||||
Test `std/`:
|
||||
|
||||
```shell
|
||||
cargo test std_tests
|
||||
```
|
||||
|
||||
### Lint and format
|
||||
|
||||
Lint the code:
|
||||
|
||||
```shell
|
||||
deno run -A --unstable ./tools/lint.js
|
||||
```
|
||||
|
||||
Format the code:
|
||||
|
||||
```shell
|
||||
deno run -A --unstable ./tools/format.js
|
||||
```
|
||||
|
||||
### Continuous Benchmarks
|
||||
|
||||
See our benchmarks [over here](https://deno.land/benchmarks)
|
||||
|
||||
The benchmark chart supposes
|
||||
https://github.com/denoland/benchmark_data/blob/gh-pages/data.json has the type
|
||||
`BenchmarkData[]` where `BenchmarkData` is defined like the below:
|
||||
|
||||
```ts
|
||||
interface ExecTimeData {
|
||||
mean: number;
|
||||
stddev: number;
|
||||
user: number;
|
||||
system: number;
|
||||
min: number;
|
||||
max: number;
|
||||
}
|
||||
|
||||
interface BenchmarkData {
|
||||
created_at: string;
|
||||
sha1: string;
|
||||
benchmark: {
|
||||
[key: string]: ExecTimeData;
|
||||
};
|
||||
binarySizeData: {
|
||||
[key: string]: number;
|
||||
};
|
||||
threadCountData: {
|
||||
[key: string]: number;
|
||||
};
|
||||
syscallCountData: {
|
||||
[key: string]: number;
|
||||
};
|
||||
}
|
||||
```
|
|
@ -1,35 +0,0 @@
|
|||
## Release Schedule
|
||||
|
||||
A new minor release for the `deno` cli is released every 6 weeks. After 1.9.0 we
|
||||
will be switching to a 4 week release cycle. A new patch version is released
|
||||
weekly, as necessary.
|
||||
|
||||
The release dates for the upcoming minor releases are:
|
||||
|
||||
- 1.11.0: June 8, 2021
|
||||
- 1.12.0: July 13, 2021
|
||||
- 1.13.0: August 10, 2021
|
||||
- 1.14.0: September 14, 2021
|
||||
|
||||
Stable releases can be found on the
|
||||
[GitHub releases page](https://github.com/denoland/deno/releases).
|
||||
|
||||
### Canary channel
|
||||
|
||||
In addition to the stable channel described above, canaries are released
|
||||
multiple times daily (for each commit on main). You can upgrade to the latest
|
||||
canary release by running:
|
||||
|
||||
```
|
||||
deno upgrade --canary
|
||||
```
|
||||
|
||||
To update to a specific canary, pass the commit hash in the `--version` option:
|
||||
|
||||
```
|
||||
deno upgrade --canary --version=973af61d8bb03c1709f61e456581d58386ed4952
|
||||
```
|
||||
|
||||
To switch back to the stable channel, run `deno upgrade`.
|
||||
|
||||
Canaries can be downloaded from https://dl.deno.land.
|
|
@ -1,360 +0,0 @@
|
|||
# Deno Style Guide
|
||||
|
||||
## Copyright Headers
|
||||
|
||||
Most modules in the repository should have the following copyright header:
|
||||
|
||||
```ts
|
||||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||
```
|
||||
|
||||
If the code originates elsewhere, ensure that the file has the proper copyright
|
||||
headers. We only allow MIT, BSD, and Apache licensed code.
|
||||
|
||||
## Use underscores, not dashes in filenames.
|
||||
|
||||
Example: Use `file_server.ts` instead of `file-server.ts`.
|
||||
|
||||
## Add tests for new features.
|
||||
|
||||
Each module should contain or be accompanied by tests for its public
|
||||
functionality.
|
||||
|
||||
## TODO Comments
|
||||
|
||||
TODO comments should usually include an issue or the author's github username in
|
||||
parentheses. Example:
|
||||
|
||||
```ts
|
||||
// TODO(ry): Add tests.
|
||||
// TODO(#123): Support Windows.
|
||||
// FIXME(#349): Sometimes panics.
|
||||
```
|
||||
|
||||
## Meta-programming is discouraged. Including the use of Proxy.
|
||||
|
||||
Be explicit even when it means more code.
|
||||
|
||||
There are some situations where it may make sense to use such techniques, but in
|
||||
the vast majority of cases it does not.
|
||||
|
||||
## Inclusive code
|
||||
|
||||
Please follow the guidelines for inclusive code outlined at
|
||||
https://chromium.googlesource.com/chromium/src/+/master/styleguide/inclusive_code.md.
|
||||
|
||||
## Rust
|
||||
|
||||
Follow Rust conventions and be consistent with existing code.
|
||||
|
||||
## TypeScript
|
||||
|
||||
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
|
||||
filenames, it suggests that they can be left out of the module specifier when
|
||||
they cannot. This is confusing.
|
||||
|
||||
If a directory of code needs a default entry point, use the filename `mod.ts`.
|
||||
The filename `mod.ts` follows Rust’s convention, is shorter than `index.ts`, and
|
||||
doesn’t come with any preconceived notions about how it might work.
|
||||
|
||||
### Exported functions: max 2 args, put the rest into an options object.
|
||||
|
||||
When designing function interfaces, stick to the following rules.
|
||||
|
||||
1. A function that is part of the public API takes 0-2 required arguments, plus
|
||||
(if necessary) an options object (so max 3 total).
|
||||
|
||||
2. Optional parameters should generally go into the options object.
|
||||
|
||||
An optional parameter that's not in an options object might be acceptable if
|
||||
there is only one, and it seems inconceivable that we would add more optional
|
||||
parameters in the future.
|
||||
|
||||
3. The 'options' argument is the only argument that is a regular 'Object'.
|
||||
|
||||
Other arguments can be objects, but they must be distinguishable from a
|
||||
'plain' Object runtime, by having either:
|
||||
|
||||
- a distinguishing prototype (e.g. `Array`, `Map`, `Date`, `class MyThing`).
|
||||
- a well-known symbol property (e.g. an iterable with `Symbol.iterator`).
|
||||
|
||||
This allows the API to evolve in a backwards compatible way, even when the
|
||||
position of the options object changes.
|
||||
|
||||
```ts
|
||||
// BAD: optional parameters not part of options object. (#2)
|
||||
export function resolve(
|
||||
hostname: string,
|
||||
family?: "ipv4" | "ipv6",
|
||||
timeout?: number,
|
||||
): IPAddress[] {}
|
||||
|
||||
// GOOD.
|
||||
export interface ResolveOptions {
|
||||
family?: "ipv4" | "ipv6";
|
||||
timeout?: number;
|
||||
}
|
||||
export function resolve(
|
||||
hostname: string,
|
||||
options: ResolveOptions = {},
|
||||
): IPAddress[] {}
|
||||
```
|
||||
|
||||
```ts
|
||||
export interface Environment {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
// BAD: `env` could be a regular Object and is therefore indistinguishable
|
||||
// from an options object. (#3)
|
||||
export function runShellWithEnv(cmdline: string, env: Environment): string {}
|
||||
|
||||
// GOOD.
|
||||
export interface RunShellOptions {
|
||||
env: Environment;
|
||||
}
|
||||
export function runShellWithEnv(
|
||||
cmdline: string,
|
||||
options: RunShellOptions,
|
||||
): string {}
|
||||
```
|
||||
|
||||
```ts
|
||||
// BAD: more than 3 arguments (#1), multiple optional parameters (#2).
|
||||
export function renameSync(
|
||||
oldname: string,
|
||||
newname: string,
|
||||
replaceExisting?: boolean,
|
||||
followLinks?: boolean,
|
||||
) {}
|
||||
|
||||
// GOOD.
|
||||
interface RenameOptions {
|
||||
replaceExisting?: boolean;
|
||||
followLinks?: boolean;
|
||||
}
|
||||
export function renameSync(
|
||||
oldname: string,
|
||||
newname: string,
|
||||
options: RenameOptions = {},
|
||||
) {}
|
||||
```
|
||||
|
||||
```ts
|
||||
// BAD: too many arguments. (#1)
|
||||
export function pwrite(
|
||||
fd: number,
|
||||
buffer: TypedArray,
|
||||
offset: number,
|
||||
length: number,
|
||||
position: number,
|
||||
) {}
|
||||
|
||||
// BETTER.
|
||||
export interface PWrite {
|
||||
fd: number;
|
||||
buffer: TypedArray;
|
||||
offset: number;
|
||||
length: number;
|
||||
position: number;
|
||||
}
|
||||
export function pwrite(options: PWrite) {}
|
||||
```
|
||||
|
||||
### Export all interfaces that are used as parameters to an exported member
|
||||
|
||||
Whenever you are using interfaces that are included in the arguments of an
|
||||
exported member, you should export the interface that is used. Here is an
|
||||
example:
|
||||
|
||||
```ts
|
||||
// my_file.ts
|
||||
export interface Person {
|
||||
name: string;
|
||||
age: number;
|
||||
}
|
||||
|
||||
export function createPerson(name: string, age: number): Person {
|
||||
return { name, age };
|
||||
}
|
||||
|
||||
// mod.ts
|
||||
export { createPerson } from "./my_file.ts";
|
||||
export type { Person } from "./my_file.ts";
|
||||
```
|
||||
|
||||
### Minimize dependencies; do not make circular imports.
|
||||
|
||||
Although `std` has no external dependencies, we must still be careful to keep
|
||||
internal dependencies simple and manageable. In particular, be careful not to
|
||||
introduce circular imports.
|
||||
|
||||
### If a filename starts with an underscore: `_foo.ts`, do not link to it.
|
||||
|
||||
Sometimes there may be situations where an internal module is necessary but its
|
||||
API is not meant to be stable or linked to. In this case prefix it with an
|
||||
underscore. By convention, only files in its own directory should import it.
|
||||
|
||||
### Use JSDoc for exported symbols.
|
||||
|
||||
We strive for complete documentation. Every exported symbol ideally should have
|
||||
a documentation line.
|
||||
|
||||
If possible, use a single line for the JSDoc. Example:
|
||||
|
||||
```ts
|
||||
/** foo does bar. */
|
||||
export function foo() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
It is important that documentation is easily human readable, but there is also a
|
||||
need to provide additional styling information to ensure generated documentation
|
||||
is more rich text. Therefore JSDoc should generally follow markdown markup to
|
||||
enrich the text.
|
||||
|
||||
While markdown supports HTML tags, it is forbidden in JSDoc blocks.
|
||||
|
||||
Code string literals should be braced with the back-tick (\`) instead of quotes.
|
||||
For example:
|
||||
|
||||
```ts
|
||||
/** Import something from the `deno` module. */
|
||||
```
|
||||
|
||||
Do not document function arguments unless they are non-obvious of their intent
|
||||
(though if they are non-obvious intent, the API should be considered anyways).
|
||||
Therefore `@param` should generally not be used. If `@param` is used, it should
|
||||
not include the `type` as TypeScript is already strongly typed.
|
||||
|
||||
```ts
|
||||
/**
|
||||
* Function with non obvious param.
|
||||
* @param foo Description of non obvious parameter.
|
||||
*/
|
||||
```
|
||||
|
||||
Vertical spacing should be minimized whenever possible. Therefore single line
|
||||
comments should be written as:
|
||||
|
||||
```ts
|
||||
/** This is a good single line JSDoc. */
|
||||
```
|
||||
|
||||
And not:
|
||||
|
||||
```ts
|
||||
/**
|
||||
* This is a bad single line JSDoc.
|
||||
*/
|
||||
```
|
||||
|
||||
Code examples should utilize markdown format, like so:
|
||||
|
||||
````ts
|
||||
/** A straight forward comment and an example:
|
||||
* ```ts
|
||||
* import { foo } from "deno";
|
||||
* foo("bar");
|
||||
* ```
|
||||
*/
|
||||
````
|
||||
|
||||
Code examples should not contain additional comments and must not be indented.
|
||||
It is already inside a comment. If it needs further comments it is not a good
|
||||
example.
|
||||
|
||||
### Resolve linting problems using directives
|
||||
|
||||
Currently, the building process uses `dlint` to validate linting problems in the
|
||||
code. If the task requires code that is non-conformant to linter use
|
||||
`deno-lint-ignore <code>` directive to suppress the warning.
|
||||
|
||||
```typescript
|
||||
// deno-lint-ignore no-explicit-any
|
||||
let x: any;
|
||||
```
|
||||
|
||||
This ensures the continuous integration process doesn't fail due to linting
|
||||
problems, but it should be used scarcely.
|
||||
|
||||
### Each module should come with a test module.
|
||||
|
||||
Every module with public functionality `foo.ts` should come with a test module
|
||||
`foo_test.ts`. A test for a `std` module should go in `std/tests` due to their
|
||||
different contexts, otherwise it should just be a sibling to the tested module.
|
||||
|
||||
### Unit Tests should be explicit.
|
||||
|
||||
For a better understanding of the tests, function should be correctly named as
|
||||
its prompted throughout the test command. Like:
|
||||
|
||||
```
|
||||
test myTestFunction ... ok
|
||||
```
|
||||
|
||||
Example of test:
|
||||
|
||||
```ts
|
||||
import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
import { foo } from "./mod.ts";
|
||||
|
||||
Deno.test("myTestFunction", function () {
|
||||
assertEquals(foo(), { bar: "bar" });
|
||||
});
|
||||
```
|
||||
|
||||
### Top level functions should not use arrow syntax.
|
||||
|
||||
Top level functions should use the `function` keyword. Arrow syntax should be
|
||||
limited to closures.
|
||||
|
||||
Bad:
|
||||
|
||||
```ts
|
||||
export const foo = (): string => {
|
||||
return "bar";
|
||||
};
|
||||
```
|
||||
|
||||
Good:
|
||||
|
||||
```ts
|
||||
export function foo(): string {
|
||||
return "bar";
|
||||
}
|
||||
```
|
||||
|
||||
### `std`
|
||||
|
||||
#### Do not depend on external code.
|
||||
|
||||
`https://deno.land/std/` is intended to be baseline functionality that all Deno
|
||||
programs can rely on. We want to guarantee to users that this code does not
|
||||
include potentially unreviewed third party code.
|
||||
|
||||
#### Document and maintain browser compatibility.
|
||||
|
||||
If a module is browser compatible, include the following in the JSDoc at the top
|
||||
of the module:
|
||||
|
||||
```ts
|
||||
// This module is browser compatible.
|
||||
```
|
||||
|
||||
Maintain browser compatibility for such a module by either not using the global
|
||||
`Deno` namespace or feature-testing for it. Make sure any new dependencies are
|
||||
also browser compatible.
|
|
@ -1,133 +0,0 @@
|
|||
## Web Platform Test
|
||||
|
||||
Deno uses a custom test runner for Web Platform Tests. It can be found at
|
||||
`./tools/wpt.ts`.
|
||||
|
||||
### Running tests
|
||||
|
||||
> If you are on Windows, or your system does not support shebangs, prefix all
|
||||
> `./tools/wpt.ts` commands with
|
||||
> `deno run --unstable --allow-write --allow-read --allow-net --allow-env --allow-run`.
|
||||
|
||||
Before attempting to run WPT tests for the first time, please run the WPT setup.
|
||||
You must also run this command every time the `./test_util/wpt` submodule is
|
||||
updated:
|
||||
|
||||
```shell
|
||||
./tools/wpt.ts setup
|
||||
```
|
||||
|
||||
To run all available web platform tests, run the following command:
|
||||
|
||||
```shell
|
||||
./tools/wpt.ts run
|
||||
|
||||
# You can also filter which test files to run by specifying filters:
|
||||
./tools/wpt.ts run -- streams/piping/general hr-time
|
||||
```
|
||||
|
||||
The test runner will run each web platform test and record its status (failed or
|
||||
ok). It will then compare this output to the expected output of each test as
|
||||
specified in the `./tools/wpt/expectation.json` file. This file is a nested JSON
|
||||
structure that mirrors the `./test_utils/wpt` directory. It describes for each
|
||||
test file, if it should pass as a whole (all tests pass, `true`), if it should
|
||||
fail as a whole (test runner encounters an exception outside of a test or all
|
||||
tests fail, `false`), or which tests it expects to fail (a string array of test
|
||||
case names).
|
||||
|
||||
### Updating enabled tests or expectations
|
||||
|
||||
You can update the `./tools/wpt/expectation.json` file manually by changing the
|
||||
value of each of the test file entries in the JSON structure. The alternative
|
||||
and preferred option is to have the WPT runner run all, or a filtered subset of
|
||||
tests, and then automatically update the `expectation.json` file to match the
|
||||
current reality. You can do this with the `./wpt.ts update` command. Example:
|
||||
|
||||
```shell
|
||||
./tools/wpt.ts update -- hr-time
|
||||
```
|
||||
|
||||
After running this command the `expectation.json` file will match the current
|
||||
output of all the tests that were run. This means that running `wpt.ts run`
|
||||
right after a `wpt.ts update` should always pass.
|
||||
|
||||
### Subcommands
|
||||
|
||||
#### `setup`
|
||||
|
||||
Validate that your environment is configured correctly, or help you configure
|
||||
it.
|
||||
|
||||
This will check that the python3 (or `python.exe` on Windows) is actually
|
||||
Python 3.
|
||||
|
||||
You can specify the following flags to customize behaviour:
|
||||
|
||||
```
|
||||
--rebuild
|
||||
Rebuild the manifest instead of downloading. This can take up to 3 minutes.
|
||||
|
||||
--auto-config
|
||||
Automatically configure /etc/hosts if it is not configured (no prompt will be shown).
|
||||
```
|
||||
|
||||
#### `run`
|
||||
|
||||
Run all tests like specified in `expectation.json`.
|
||||
|
||||
You can specify the following flags to customize behaviour:
|
||||
|
||||
```
|
||||
--release
|
||||
Use the ./target/release/deno binary instead of ./target/debug/deno
|
||||
|
||||
--quiet
|
||||
Disable printing of `ok` test cases.
|
||||
|
||||
--json=<file>
|
||||
Output the test results as JSON to the file specified.
|
||||
```
|
||||
|
||||
You can also specify exactly which tests to run by specifying one of more
|
||||
filters after a `--`:
|
||||
|
||||
```
|
||||
./tools/wpt.ts run -- hr-time streams/piping/general
|
||||
```
|
||||
|
||||
### `update`
|
||||
|
||||
Update the `expectation.json` to match the current reality.
|
||||
|
||||
You can specify the following flags to customize behaviour:
|
||||
|
||||
```
|
||||
--release
|
||||
Use the ./target/release/deno binary instead of ./target/debug/deno
|
||||
|
||||
--quiet
|
||||
Disable printing of `ok` test cases.
|
||||
|
||||
--json=<file>
|
||||
Output the test results as JSON to the file specified.
|
||||
```
|
||||
|
||||
You can also specify exactly which tests to run by specifying one of more
|
||||
filters after a `--`:
|
||||
|
||||
```
|
||||
./tools/wpt.ts update -- hr-time streams/piping/general
|
||||
```
|
||||
|
||||
### FAQ
|
||||
|
||||
#### Upgrading the wpt submodule:
|
||||
|
||||
```shell
|
||||
cd test_util/wpt/
|
||||
# Rebase to retain our modifications
|
||||
git rebase origin/master
|
||||
git push denoland
|
||||
```
|
||||
|
||||
All contributors will need to rerun `./tools/wpt.ts setup` after this.
|
|
@ -1,11 +0,0 @@
|
|||
# Embedding Deno
|
||||
|
||||
Deno consists of multiple parts, one of which is `deno_core`. This is a rust
|
||||
crate that can be used to embed a JavaScript runtime into your rust application.
|
||||
Deno is built on top of `deno_core`.
|
||||
|
||||
The Deno crate is hosted on [crates.io](https://crates.io/crates/deno_core).
|
||||
|
||||
You can view the API on [docs.rs](https://docs.rs/deno_core).
|
||||
|
||||
<!-- TODO(lucacasonato): better docs -->
|
|
@ -1,23 +0,0 @@
|
|||
# Examples
|
||||
|
||||
In this chapter you can find some example programs that you can use to learn
|
||||
more about the runtime.
|
||||
|
||||
## Basic
|
||||
|
||||
- [Hello world](./examples/hello_world.md)
|
||||
- [Import and export modules](./examples/import_export.md)
|
||||
- [Manage dependencies](./examples/manage_dependencies.md)
|
||||
- [Fetch data](./examples/fetch_data.md)
|
||||
- [Read and write files](./examples/read_write_files.md)
|
||||
|
||||
## Advanced
|
||||
|
||||
- [Unix cat program](./examples/unix_cat.md)
|
||||
- [HTTP web server](./examples/http_server.md)
|
||||
- [File server](./examples/file_server.md)
|
||||
- [TCP echo server](./examples/tcp_echo.md)
|
||||
- [Creating a subprocess](./examples/subprocess.md)
|
||||
- [OS signals](./examples/os_signals.md)
|
||||
- [File system events](./examples/file_system_events.md)
|
||||
- [Module metadata](./examples/module_metadata.md)
|
|
@ -1,58 +0,0 @@
|
|||
# Fetch data
|
||||
|
||||
## Concepts
|
||||
|
||||
- Like browsers, Deno implements web standard APIs such as
|
||||
[fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API).
|
||||
- Deno is secure by default, meaning explicit permission must be granted to
|
||||
access the network.
|
||||
- See also: Deno's [permissions](../getting_started/permissions.md) model.
|
||||
|
||||
## Overview
|
||||
|
||||
When building any sort of web application developers will usually need to
|
||||
retrieve data from somewhere else on the web. This works no differently in Deno
|
||||
than in any other JavaScript application, just call the `fetch()` method. For
|
||||
more information on fetch read the
|
||||
[MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API).
|
||||
|
||||
The exception with Deno occurs when running a script which makes a call over the
|
||||
web. Deno is secure by default which means access to IO (Input / Output) is
|
||||
prohibited. To make a call over the web Deno must be explicitly told it is ok to
|
||||
do so. This is achieved by adding the `--allow-net` flag to the `deno run`
|
||||
command.
|
||||
|
||||
## Example
|
||||
|
||||
**Command:** `deno run --allow-net fetch.ts`
|
||||
|
||||
```js
|
||||
/**
|
||||
* Output: JSON Data
|
||||
*/
|
||||
const json = fetch("https://api.github.com/users/denoland");
|
||||
|
||||
json.then((response) => {
|
||||
return response.json();
|
||||
}).then((jsonData) => {
|
||||
console.log(jsonData);
|
||||
});
|
||||
|
||||
/**
|
||||
* Output: HTML Data
|
||||
*/
|
||||
const text = fetch("https://deno.land/");
|
||||
|
||||
text.then((response) => {
|
||||
return response.text();
|
||||
}).then((textData) => {
|
||||
console.log(textData);
|
||||
});
|
||||
|
||||
/**
|
||||
* Output: Error Message
|
||||
*/
|
||||
const error = fetch("https://does.not.exist/");
|
||||
|
||||
error.catch((error) => console.log(error.message));
|
||||
```
|
|
@ -1,63 +0,0 @@
|
|||
# File server
|
||||
|
||||
## Concepts
|
||||
|
||||
- Use the Deno standard library
|
||||
[file_server.ts](https://deno.land/std@$STD_VERSION/http/file_server.ts) to
|
||||
run your own file server and access your files from your web browser.
|
||||
- Run [Deno install](../tools/script_installer.md) to install the file server
|
||||
locally.
|
||||
|
||||
## Example
|
||||
|
||||
Serve a local directory via HTTP. First install the remote script to your local
|
||||
file system. This will install the script to the Deno installation root's bin
|
||||
directory, e.g. `/home/alice/.deno/bin/file_server`.
|
||||
|
||||
```shell
|
||||
deno install --allow-net --allow-read https://deno.land/std@$STD_VERSION/http/file_server.ts
|
||||
```
|
||||
|
||||
You can now run the script with the simplified script name. Run it:
|
||||
|
||||
```shell
|
||||
$ file_server .
|
||||
Downloading https://deno.land/std@$STD_VERSION/http/file_server.ts...
|
||||
[...]
|
||||
HTTP server listening on http://0.0.0.0:4507/
|
||||
```
|
||||
|
||||
Now go to [http://0.0.0.0:4507/](http://0.0.0.0:4507/) in your web browser to
|
||||
see your local directory contents.
|
||||
|
||||
## Help
|
||||
|
||||
Help and a complete list of options are available via:
|
||||
|
||||
```shell
|
||||
file_server --help
|
||||
```
|
||||
|
||||
Example output:
|
||||
|
||||
```
|
||||
Deno File Server
|
||||
Serves a local directory in HTTP.
|
||||
|
||||
INSTALL:
|
||||
deno install --allow-net --allow-read https://deno.land/std/http/file_server.ts
|
||||
|
||||
USAGE:
|
||||
file_server [path] [options]
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Prints help information
|
||||
-p, --port <PORT> Set port
|
||||
--cors Enable CORS via the "Access-Control-Allow-Origin" header
|
||||
--host <HOST> Hostname (default is 0.0.0.0)
|
||||
-c, --cert <FILE> TLS certificate file (enables TLS)
|
||||
-k, --key <FILE> TLS key file (enables TLS)
|
||||
--no-dir-listing Disable directory listing
|
||||
|
||||
All TLS options are required when one is provided.
|
||||
```
|
|
@ -1,40 +0,0 @@
|
|||
# File system events
|
||||
|
||||
## Concepts
|
||||
|
||||
- Use [Deno.watchFs](https://doc.deno.land/builtin/stable#Deno.watchFs) to watch
|
||||
for file system events.
|
||||
- Results may vary between operating systems.
|
||||
|
||||
## Example
|
||||
|
||||
To poll for file system events in the current directory:
|
||||
|
||||
```ts
|
||||
/**
|
||||
* watcher.ts
|
||||
*/
|
||||
const watcher = Deno.watchFs(".");
|
||||
for await (const event of watcher) {
|
||||
console.log(">>>> event", event);
|
||||
// Example event: { kind: "create", paths: [ "/home/alice/deno/foo.txt" ] }
|
||||
}
|
||||
```
|
||||
|
||||
Run with:
|
||||
|
||||
```shell
|
||||
deno run --allow-read watcher.ts
|
||||
```
|
||||
|
||||
Now try adding, removing and modifying files in the same directory as
|
||||
`watcher.ts`.
|
||||
|
||||
Note that the exact ordering of the events can vary between operating systems.
|
||||
This feature uses different syscalls depending on the platform:
|
||||
|
||||
- Linux: [inotify](https://man7.org/linux/man-pages/man7/inotify.7.html)
|
||||
- macOS:
|
||||
[FSEvents](https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/FSEvents_ProgGuide/Introduction/Introduction.html)
|
||||
- Windows:
|
||||
[ReadDirectoryChangesW](https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-readdirectorychangesw)
|
|
@ -1,79 +0,0 @@
|
|||
# Hello world
|
||||
|
||||
## Concepts
|
||||
|
||||
- Deno can run JavaScript or TypeScript out of the box with no additional tools
|
||||
or config required.
|
||||
|
||||
## Overview
|
||||
|
||||
Deno is a secure runtime for both JavaScript and TypeScript. As the hello world
|
||||
examples below highlight the same functionality can be created in JavaScript or
|
||||
TypeScript, and Deno will execute both.
|
||||
|
||||
## JavaScript
|
||||
|
||||
In this JavaScript example the message `Hello [name]` is printed to the console
|
||||
and the code ensures the name provided is capitalized.
|
||||
|
||||
**Command:** `deno run hello-world.js`
|
||||
|
||||
```js
|
||||
/**
|
||||
* hello-world.js
|
||||
*/
|
||||
function capitalize(word) {
|
||||
return word.charAt(0).toUpperCase() + word.slice(1);
|
||||
}
|
||||
|
||||
function hello(name) {
|
||||
return "Hello " + capitalize(name);
|
||||
}
|
||||
|
||||
console.log(hello("john"));
|
||||
console.log(hello("Sarah"));
|
||||
console.log(hello("kai"));
|
||||
|
||||
/**
|
||||
* Output:
|
||||
*
|
||||
* Hello John
|
||||
* Hello Sarah
|
||||
* Hello Kai
|
||||
**/
|
||||
```
|
||||
|
||||
## TypeScript
|
||||
|
||||
This TypeScript example is exactly the same as the JavaScript example above, the
|
||||
code just has the additional type information which TypeScript supports.
|
||||
|
||||
The `deno run` command is exactly the same, it just references a `*.ts` file
|
||||
rather than a `*.js` file.
|
||||
|
||||
**Command:** `deno run hello-world.ts`
|
||||
|
||||
```ts
|
||||
/**
|
||||
* hello-world.ts
|
||||
*/
|
||||
function capitalize(word: string): string {
|
||||
return word.charAt(0).toUpperCase() + word.slice(1);
|
||||
}
|
||||
|
||||
function hello(name: string): string {
|
||||
return "Hello " + capitalize(name);
|
||||
}
|
||||
|
||||
console.log(hello("john"));
|
||||
console.log(hello("Sarah"));
|
||||
console.log(hello("kai"));
|
||||
|
||||
/**
|
||||
* Output:
|
||||
*
|
||||
* Hello John
|
||||
* Hello Sarah
|
||||
* Hello Kai
|
||||
**/
|
||||
```
|
|
@ -1,88 +0,0 @@
|
|||
# Simple HTTP web server
|
||||
|
||||
## Concepts
|
||||
|
||||
- Use Deno's integrated HTTP server to run your own web server.
|
||||
|
||||
## Overview
|
||||
|
||||
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.
|
||||
|
||||
> ℹ️ The _native_ HTTP server is currently unstable, meaning the API is not
|
||||
> finalized and may change in breaking ways in future version of Deno. To have
|
||||
> the APIs discussed here available, you must run Deno with the `--unstable`
|
||||
> flag.
|
||||
|
||||
## Sample web server
|
||||
|
||||
In this example, the user-agent of the client is returned to the client:
|
||||
|
||||
**webserver.ts**:
|
||||
|
||||
```ts
|
||||
// Start listening on port 8080 of localhost.
|
||||
const server = Deno.listen({ port: 8080 });
|
||||
console.log(`HTTP webserver running. Access it at: http://localhost:8080/`);
|
||||
|
||||
// Connections to the server will be yielded up as an async iterable.
|
||||
for await (const conn of server) {
|
||||
// In order to not be blocking, we need to handle each connection individually
|
||||
// in its own async function.
|
||||
(async () => {
|
||||
// This "upgrades" a network connection into an HTTP connection.
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
// Each request sent over the HTTP connection will be yielded as an async
|
||||
// iterator from the HTTP connection.
|
||||
for await (const requestEvent of httpConn) {
|
||||
// The native HTTP server uses the web standard `Request` and `Response`
|
||||
// objects.
|
||||
const body = `Your user-agent is:\n\n${requestEvent.request.headers.get(
|
||||
"user-agent",
|
||||
) ?? "Unknown"}`;
|
||||
// The requestEvent's `.respondWith()` method is how we send the response
|
||||
// back to the client.
|
||||
requestEvent.respondWith(
|
||||
new Response(body, {
|
||||
status: 200,
|
||||
}),
|
||||
);
|
||||
}
|
||||
})();
|
||||
}
|
||||
```
|
||||
|
||||
Then run this with:
|
||||
|
||||
```shell
|
||||
deno run --allow-net --unstable webserver.ts
|
||||
```
|
||||
|
||||
Then navigate to `http://localhost:8080/` in a browser.
|
||||
|
||||
### Using the `std/http` library
|
||||
|
||||
If you do not want to use the unstable APIs, you can still use the standard
|
||||
library's HTTP server:
|
||||
|
||||
**webserver.ts**:
|
||||
|
||||
```ts
|
||||
import { serve } from "https://deno.land/std@$STD_VERSION/http/server.ts";
|
||||
|
||||
const server = serve({ port: 8080 });
|
||||
console.log(`HTTP webserver running. Access it at: http://localhost:8080/`);
|
||||
|
||||
for await (const request of server) {
|
||||
let bodyContent = "Your user-agent is:\n\n";
|
||||
bodyContent += request.headers.get("user-agent") || "Unknown";
|
||||
|
||||
request.respond({ status: 200, body: bodyContent });
|
||||
}
|
||||
```
|
||||
|
||||
Then run this with:
|
||||
|
||||
```shell
|
||||
deno run --allow-net webserver.ts
|
||||
```
|
|
@ -1,120 +0,0 @@
|
|||
# Import and export modules
|
||||
|
||||
## Concepts
|
||||
|
||||
- [import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)
|
||||
allows you to include and use modules held elsewhere, on your local file
|
||||
system or remotely.
|
||||
- Imports are URLs or file system paths.
|
||||
- [export](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export)
|
||||
allows you to specify which parts of your module are accessible to users who
|
||||
import your module.
|
||||
|
||||
## Overview
|
||||
|
||||
Deno by default standardizes the way modules are imported in both JavaScript and
|
||||
TypeScript using the ECMAScript 6 `import/export` standard.
|
||||
|
||||
It adopts browser-like module resolution, meaning that file names must be
|
||||
specified in full. You may not omit the file extension and there is no special
|
||||
handling of `index.js`.
|
||||
|
||||
```js
|
||||
import { add, multiply } from "./arithmetic.ts";
|
||||
```
|
||||
|
||||
Dependencies are also imported directly, there is no package management
|
||||
overhead. Local modules are imported in exactly the same way as remote modules.
|
||||
As the examples show below, the same functionality can be produced in the same
|
||||
way with local or remote modules.
|
||||
|
||||
## Local Import
|
||||
|
||||
In this example the `add` and `multiply` functions are imported from a local
|
||||
`arithmetic.ts` module.
|
||||
|
||||
**Command:** `deno run local.ts`
|
||||
|
||||
```ts
|
||||
/**
|
||||
* local.ts
|
||||
*/
|
||||
import { add, multiply } from "./arithmetic.ts";
|
||||
|
||||
function totalCost(outbound: number, inbound: number, tax: number): number {
|
||||
return multiply(add(outbound, inbound), tax);
|
||||
}
|
||||
|
||||
console.log(totalCost(19, 31, 1.2));
|
||||
console.log(totalCost(45, 27, 1.15));
|
||||
|
||||
/**
|
||||
* Output
|
||||
*
|
||||
* 60
|
||||
* 82.8
|
||||
*/
|
||||
```
|
||||
|
||||
## Remote Import
|
||||
|
||||
In the local import example above an `add` and `multiply` method are imported
|
||||
from a locally stored arithmetic module. The same functionality can be created
|
||||
by importing `add` and `multiply` methods from a remote module too.
|
||||
|
||||
In this case the Ramda module is referenced, including the version number. Also
|
||||
note a JavaScript module is imported directly into a TypeScript module, Deno has
|
||||
no problem handling this.
|
||||
|
||||
**Command:** `deno run ./remote.ts`
|
||||
|
||||
```ts
|
||||
/**
|
||||
* remote.ts
|
||||
*/
|
||||
import {
|
||||
add,
|
||||
multiply,
|
||||
} from "https://x.nest.land/ramda@0.27.0/source/index.js";
|
||||
|
||||
function totalCost(outbound: number, inbound: number, tax: number): number {
|
||||
return multiply(add(outbound, inbound), tax);
|
||||
}
|
||||
|
||||
console.log(totalCost(19, 31, 1.2));
|
||||
console.log(totalCost(45, 27, 1.15));
|
||||
|
||||
/**
|
||||
* Output
|
||||
*
|
||||
* 60
|
||||
* 82.8
|
||||
*/
|
||||
```
|
||||
|
||||
## Export
|
||||
|
||||
In the local import example above the `add` and `multiply` functions are
|
||||
imported from a locally stored arithmetic module. To make this possible the
|
||||
functions stored in the arithmetic module must be exported.
|
||||
|
||||
To do this just add the keyword `export` to the beginning of the function
|
||||
signature as is shown below.
|
||||
|
||||
```ts
|
||||
/**
|
||||
* arithmetic.ts
|
||||
*/
|
||||
export function add(a: number, b: number): number {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
export function multiply(a: number, b: number): number {
|
||||
return a * b;
|
||||
}
|
||||
```
|
||||
|
||||
All functions, classes, constants and variables which need to be accessible
|
||||
inside external modules must be exported. Either by prepending them with the
|
||||
`export` keyword or including them in an export statement at the bottom of the
|
||||
file.
|
|
@ -1,73 +0,0 @@
|
|||
# Managing dependencies
|
||||
|
||||
## Concepts
|
||||
|
||||
- Deno uses URLs for dependency management.
|
||||
- One convention places all these dependent URLs into a local `deps.ts` file.
|
||||
Functionality is then exported out of `deps.ts` for use by local modules.
|
||||
- Continuing this convention, dev only dependencies can be kept in a
|
||||
`dev_deps.ts` file.
|
||||
- See also [Linking to external code](../linking_to_external_code.md)
|
||||
|
||||
## Overview
|
||||
|
||||
In Deno there is no concept of a package manager as external modules are
|
||||
imported directly into local modules. This raises the question of how to manage
|
||||
remote dependencies without a package manager. In big projects with many
|
||||
dependencies it will become cumbersome and time consuming to update modules if
|
||||
they are all imported individually into individual modules.
|
||||
|
||||
The standard practice for solving this problem in Deno is to create a `deps.ts`
|
||||
file. All required remote dependencies are referenced in this file and the
|
||||
required methods and classes are re-exported. The dependent local modules then
|
||||
reference the `deps.ts` rather than the remote dependencies. If now for example
|
||||
one remote dependency is used in several files, upgrading to a new version of
|
||||
this remote dependency is much simpler as this can be done just within
|
||||
`deps.ts`.
|
||||
|
||||
With all dependencies centralized in `deps.ts`, managing these becomes easier.
|
||||
Dev dependencies can also be managed in a separate `dev_deps.ts` file, allowing
|
||||
clean separation between dev only and production dependencies.
|
||||
|
||||
## Example
|
||||
|
||||
```ts
|
||||
/**
|
||||
* deps.ts
|
||||
*
|
||||
* This module re-exports the required methods from the dependant remote Ramda module.
|
||||
**/
|
||||
export {
|
||||
add,
|
||||
multiply,
|
||||
} from "https://x.nest.land/ramda@0.27.0/source/index.js";
|
||||
```
|
||||
|
||||
In this example the same functionality is created as is the case in the
|
||||
[local and remote import examples](./import_export.md). But in this case instead
|
||||
of the Ramda module being referenced directly it is referenced by proxy using a
|
||||
local `deps.ts` module.
|
||||
|
||||
**Command:** `deno run example.ts`
|
||||
|
||||
```ts
|
||||
/**
|
||||
* example.ts
|
||||
*/
|
||||
|
||||
import { add, multiply } from "./deps.ts";
|
||||
|
||||
function totalCost(outbound: number, inbound: number, tax: number): number {
|
||||
return multiply(add(outbound, inbound), tax);
|
||||
}
|
||||
|
||||
console.log(totalCost(19, 31, 1.2));
|
||||
console.log(totalCost(45, 27, 1.15));
|
||||
|
||||
/**
|
||||
* Output
|
||||
*
|
||||
* 60
|
||||
* 82.8
|
||||
*/
|
||||
```
|
|
@ -1,68 +0,0 @@
|
|||
# Module metadata
|
||||
|
||||
## Concepts
|
||||
|
||||
- [import.meta](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import.meta)
|
||||
can provide information on the context of the module.
|
||||
- The boolean
|
||||
[import.meta.main](https://doc.deno.land/builtin/stable#ImportMeta) will let
|
||||
you know if the current module is the program entry point.
|
||||
- The string [import.meta.url](https://doc.deno.land/builtin/stable#ImportMeta)
|
||||
will give you the URL of the current module.
|
||||
- The string
|
||||
[Deno.mainModule](https://doc.deno.land/builtin/stable#Deno.mainModule) will
|
||||
give you the URL of the main module entry point, i.e. the module invoked by
|
||||
the deno runtime.
|
||||
|
||||
## Example
|
||||
|
||||
The example below uses two modules to show the difference between
|
||||
`import.meta.url`, `import.meta.main` and `Deno.mainModule`. In this example,
|
||||
`module_a.ts` is the main module entry point:
|
||||
|
||||
```ts
|
||||
/**
|
||||
* module_b.ts
|
||||
*/
|
||||
export function outputB() {
|
||||
console.log("Module B's import.meta.url", import.meta.url);
|
||||
console.log("Module B's mainModule url", Deno.mainModule);
|
||||
console.log(
|
||||
"Is module B the main module via import.meta.main?",
|
||||
import.meta.main,
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
/**
|
||||
* module_a.ts
|
||||
*/
|
||||
import { outputB } from "./module_b.ts";
|
||||
|
||||
function outputA() {
|
||||
console.log("Module A's import.meta.url", import.meta.url);
|
||||
console.log("Module A's mainModule url", Deno.mainModule);
|
||||
console.log(
|
||||
"Is module A the main module via import.meta.main?",
|
||||
import.meta.main,
|
||||
);
|
||||
}
|
||||
|
||||
outputA();
|
||||
console.log("");
|
||||
outputB();
|
||||
```
|
||||
|
||||
If `module_a.ts` is located in `/home/alice/deno` then the output of
|
||||
`deno run --allow-read module_a.ts` is:
|
||||
|
||||
```
|
||||
Module A's import.meta.url file:///home/alice/deno/module_a.ts
|
||||
Module A's mainModule url file:///home/alice/deno/module_a.ts
|
||||
Is module A the main module via import.meta.main? true
|
||||
|
||||
Module B's import.meta.url file:///home/alice/deno/module_b.ts
|
||||
Module B's mainModule url file:///home/alice/deno/module_a.ts
|
||||
Is module B the main module via import.meta.main? false
|
||||
```
|
|
@ -1,83 +0,0 @@
|
|||
# Handle OS Signals
|
||||
|
||||
> This program makes use of an unstable Deno feature. Learn more about
|
||||
> [unstable features](../runtime/stability.md).
|
||||
|
||||
## Concepts
|
||||
|
||||
- Use the `--unstable` flag to access new or unstable features in Deno.
|
||||
- [Deno.signal](https://doc.deno.land/builtin/unstable#Deno.signal) can be used
|
||||
to capture and monitor OS signals.
|
||||
- Use the `dispose()` function of the Deno.signal
|
||||
[SignalStream](https://doc.deno.land/builtin/unstable#Deno.SignalStream) to
|
||||
stop watching the signal.
|
||||
|
||||
## Async iterator example
|
||||
|
||||
You can use `Deno.signal()` function for handling OS signals:
|
||||
|
||||
```ts
|
||||
/**
|
||||
* async-iterator-signal.ts
|
||||
*/
|
||||
console.log("Press Ctrl-C to trigger a SIGINT signal");
|
||||
for await (const _ of Deno.signal(Deno.Signal.SIGINT)) {
|
||||
console.log("interrupted!");
|
||||
Deno.exit();
|
||||
}
|
||||
```
|
||||
|
||||
Run with:
|
||||
|
||||
```shell
|
||||
deno run --unstable async-iterator-signal.ts
|
||||
```
|
||||
|
||||
## Promise based example
|
||||
|
||||
`Deno.signal()` also works as a promise:
|
||||
|
||||
```ts
|
||||
/**
|
||||
* promise-signal.ts
|
||||
*/
|
||||
console.log("Press Ctrl-C to trigger a SIGINT signal");
|
||||
await Deno.signal(Deno.Signal.SIGINT);
|
||||
console.log("interrupted!");
|
||||
Deno.exit();
|
||||
```
|
||||
|
||||
Run with:
|
||||
|
||||
```shell
|
||||
deno run --unstable promise-signal.ts
|
||||
```
|
||||
|
||||
## Stop watching signals
|
||||
|
||||
If you want to stop watching the signal, you can use `dispose()` method of the
|
||||
signal object:
|
||||
|
||||
```ts
|
||||
/**
|
||||
* dispose-signal.ts
|
||||
*/
|
||||
const sig = Deno.signal(Deno.Signal.SIGINT);
|
||||
setTimeout(() => {
|
||||
sig.dispose();
|
||||
console.log("No longer watching SIGINT signal");
|
||||
}, 5000);
|
||||
|
||||
console.log("Watching SIGINT signals");
|
||||
for await (const _ of sig) {
|
||||
console.log("interrupted");
|
||||
}
|
||||
```
|
||||
|
||||
Run with:
|
||||
|
||||
```shell
|
||||
deno run --unstable dispose-signal.ts
|
||||
```
|
||||
|
||||
The above for-await loop exits after 5 seconds when `sig.dispose()` is called.
|
|
@ -1,108 +0,0 @@
|
|||
# Read and write files
|
||||
|
||||
## Concepts
|
||||
|
||||
- Deno's runtime API provides the
|
||||
[Deno.readTextFile](https://doc.deno.land/builtin/stable#Deno.readTextFile)
|
||||
and
|
||||
[Deno.writeTextFile](https://doc.deno.land/builtin/stable#Deno.writeTextFile)
|
||||
asynchronous functions for reading and writing entire text files.
|
||||
- Like many of Deno's APIs, synchronous alternatives are also available. See
|
||||
[Deno.readTextFileSync](https://doc.deno.land/builtin/stable#Deno.readTextFileSync)
|
||||
and
|
||||
[Deno.writeTextFileSync](https://doc.deno.land/builtin/stable#Deno.writeTextFileSync).
|
||||
- Use `--allow-read` and `--allow-write` permissions to gain access to the file
|
||||
system.
|
||||
|
||||
## Overview
|
||||
|
||||
Interacting with the filesystem to read and write files is a common requirement.
|
||||
Deno provides a number of ways to do this via the
|
||||
[standard library](https://deno.land/std) and the
|
||||
[Deno runtime API](https://doc.deno.land/builtin/stable).
|
||||
|
||||
As highlighted in the [Fetch Data example](./fetch_data) Deno restricts access
|
||||
to Input / Output by default for security reasons. Therefore when interacting
|
||||
with the filesystem the `--allow-read` and `--allow-write` flags must be used
|
||||
with the `deno run` command.
|
||||
|
||||
## Reading a text file
|
||||
|
||||
The Deno runtime API makes it possible to read text files via the
|
||||
`Deno.readTextFile()` method, it just requires a path string or URL object. The
|
||||
method returns a promise which provides access to the file's text data.
|
||||
|
||||
**Command:** `deno run --allow-read read.ts`
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* read.ts
|
||||
*/
|
||||
const text = Deno.readTextFile("./people.json");
|
||||
|
||||
text.then((response) => console.log(response));
|
||||
|
||||
/**
|
||||
* Output:
|
||||
*
|
||||
* [
|
||||
* {"id": 1, "name": "John", "age": 23},
|
||||
* {"id": 2, "name": "Sandra", "age": 51},
|
||||
* {"id": 5, "name": "Devika", "age": 11}
|
||||
* ]
|
||||
*/
|
||||
```
|
||||
|
||||
## Writing a text file
|
||||
|
||||
The Deno runtime API allows developers to write text to files via the
|
||||
`Deno.writeTextFile()` method. It just requires a file path and text string. The
|
||||
method returns a promise which resolves when the file was successfully written.
|
||||
|
||||
To run the command the `--allow-write` flag must be supplied to the `deno run`
|
||||
command.
|
||||
|
||||
**Command:** `deno run --allow-write write.ts`
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* write.ts
|
||||
*/
|
||||
const write = Deno.writeTextFile("./hello.txt", "Hello World!");
|
||||
|
||||
write.then(() => console.log("File written to ./hello.txt"));
|
||||
|
||||
/**
|
||||
* Output: File written to ./hello.txt
|
||||
*/
|
||||
```
|
||||
|
||||
By combining `Deno.writeTextFile` and `JSON.stringify` you can easily write
|
||||
serialized JSON objects to a file. This example uses synchronous
|
||||
`Deno.writeTextFileSync`, but this can also be done asynchronously using
|
||||
`await Deno.writeTextFile`.
|
||||
|
||||
To execute the code the `deno run` command needs the write flag.
|
||||
|
||||
**Command:** `deno run --allow-write write.ts`
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* write.ts
|
||||
*/
|
||||
function writeJson(path: string, data: object): string {
|
||||
try {
|
||||
Deno.writeTextFileSync(path, JSON.stringify(data));
|
||||
|
||||
return "Written to " + path;
|
||||
} catch (e) {
|
||||
return e.message;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(writeJson("./data.json", { hello: "World" }));
|
||||
|
||||
/**
|
||||
* Output: Written to ./data.json
|
||||
*/
|
||||
```
|
|
@ -1,99 +0,0 @@
|
|||
# Creating a subprocess
|
||||
|
||||
## Concepts
|
||||
|
||||
- Deno is capable of spawning a subprocess via
|
||||
[Deno.run](https://doc.deno.land/builtin/stable#Deno.run).
|
||||
- `--allow-run` permission is required to spawn a subprocess.
|
||||
- Spawned subprocesses do not run in a security sandbox.
|
||||
- Communicate with the subprocess via the
|
||||
[stdin](https://doc.deno.land/builtin/stable#Deno.stdin),
|
||||
[stdout](https://doc.deno.land/builtin/stable#Deno.stdout) and
|
||||
[stderr](https://doc.deno.land/builtin/stable#Deno.stderr) streams.
|
||||
- Use a specific shell by providing its path/name and its string input switch,
|
||||
e.g. `Deno.run({cmd: ["bash", "-c", '"ls -la"']});`
|
||||
|
||||
## Simple example
|
||||
|
||||
This example is the equivalent of running `'echo hello'` from the command line.
|
||||
|
||||
```ts
|
||||
/**
|
||||
* subprocess_simple.ts
|
||||
*/
|
||||
|
||||
// create subprocess
|
||||
const p = Deno.run({
|
||||
cmd: ["echo", "hello"],
|
||||
});
|
||||
|
||||
// await its completion
|
||||
await p.status();
|
||||
```
|
||||
|
||||
Run it:
|
||||
|
||||
```shell
|
||||
$ deno run --allow-run ./subprocess_simple.ts
|
||||
hello
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
The `--allow-run` permission is required for creation of a subprocess. Be aware
|
||||
that subprocesses are not run in a Deno sandbox and therefore have the same
|
||||
permissions as if you were to run the command from the command line yourself.
|
||||
|
||||
## Communicating with subprocesses
|
||||
|
||||
By default when you use `Deno.run()` the subprocess inherits `stdin`, `stdout`
|
||||
and `stderr` of the parent process. If you want to communicate with started
|
||||
subprocess you can use `"piped"` option.
|
||||
|
||||
```ts
|
||||
/**
|
||||
* subprocess.ts
|
||||
*/
|
||||
const fileNames = Deno.args;
|
||||
|
||||
const p = Deno.run({
|
||||
cmd: [
|
||||
"deno",
|
||||
"run",
|
||||
"--allow-read",
|
||||
"https://deno.land/std@$STD_VERSION/examples/cat.ts",
|
||||
...fileNames,
|
||||
],
|
||||
stdout: "piped",
|
||||
stderr: "piped",
|
||||
});
|
||||
|
||||
const { code } = await p.status();
|
||||
|
||||
// Reading the outputs closes their pipes
|
||||
const rawOutput = await p.output();
|
||||
const rawError = await p.stderrOutput();
|
||||
|
||||
if (code === 0) {
|
||||
await Deno.stdout.write(rawOutput);
|
||||
} else {
|
||||
const errorString = new TextDecoder().decode(rawError);
|
||||
console.log(errorString);
|
||||
}
|
||||
|
||||
Deno.exit(code);
|
||||
```
|
||||
|
||||
When you run it:
|
||||
|
||||
```shell
|
||||
$ deno run --allow-run ./subprocess.ts <somefile>
|
||||
[file content]
|
||||
|
||||
$ deno run --allow-run ./subprocess.ts non_existent_file.md
|
||||
|
||||
Uncaught NotFound: No such file or directory (os error 2)
|
||||
at DenoError (deno/js/errors.ts:22:5)
|
||||
at maybeError (deno/js/errors.ts:41:12)
|
||||
at handleAsyncMsgFromRust (deno/js/dispatch.ts:27:17)
|
||||
```
|
|
@ -1,47 +0,0 @@
|
|||
# TCP echo server
|
||||
|
||||
## Concepts
|
||||
|
||||
- Listening for TCP port connections with
|
||||
[Deno.listen](https://doc.deno.land/builtin/stable#Deno.listen).
|
||||
- Use
|
||||
[copy](https://doc.deno.land/https/deno.land/std@$STD_VERSION/io/util.ts#copy)
|
||||
to take inbound data and redirect it to be outbound data.
|
||||
|
||||
## Example
|
||||
|
||||
This is an example of a server which accepts connections on port 8080, and
|
||||
returns to the client anything it sends.
|
||||
|
||||
```ts
|
||||
/**
|
||||
* echo_server.ts
|
||||
*/
|
||||
import { copy } from "https://deno.land/std@$STD_VERSION/io/util.ts";
|
||||
const listener = Deno.listen({ port: 8080 });
|
||||
console.log("listening on 0.0.0.0:8080");
|
||||
for await (const conn of listener) {
|
||||
copy(conn, conn).finally(() => conn.close());
|
||||
}
|
||||
```
|
||||
|
||||
Run with:
|
||||
|
||||
```shell
|
||||
deno run --allow-net echo_server.ts
|
||||
```
|
||||
|
||||
To test it, try sending data to it with
|
||||
[netcat](https://en.wikipedia.org/wiki/Netcat) (Linux/MacOS only). Below
|
||||
`'hello world'` is sent over the connection, which is then echoed back to the
|
||||
user:
|
||||
|
||||
```shell
|
||||
$ nc localhost 8080
|
||||
hello world
|
||||
hello world
|
||||
```
|
||||
|
||||
Like the [cat.ts example](./unix_cat.md), the `copy()` function here also does
|
||||
not make unnecessary memory copies. It receives a packet from the kernel and
|
||||
sends back, without further complexity.
|
|
@ -1,36 +0,0 @@
|
|||
# An implementation of the unix "cat" program
|
||||
|
||||
## Concepts
|
||||
|
||||
- Use the Deno runtime API to output the contents of a file to the console.
|
||||
- [Deno.args](https://doc.deno.land/builtin/stable#Deno.args) accesses the
|
||||
command line arguments.
|
||||
- [Deno.open](https://doc.deno.land/builtin/stable#Deno.open) is used to get a
|
||||
handle to a file.
|
||||
- [copy](https://doc.deno.land/https/deno.land/std@$STD_VERSION/io/util.ts#copy)
|
||||
is used to transfer data from the file to the output stream.
|
||||
- Files should be closed when you are finished with them
|
||||
- Modules can be run directly from remote URLs.
|
||||
|
||||
## Example
|
||||
|
||||
In this program each command-line argument is assumed to be a filename, the file
|
||||
is opened, and printed to stdout (e.g. the console).
|
||||
|
||||
```ts
|
||||
/**
|
||||
* cat.ts
|
||||
*/
|
||||
import { copy } from "https://deno.land/std@$STD_VERSION/io/util.ts";
|
||||
for (const filename of Deno.args) {
|
||||
const file = await Deno.open(filename);
|
||||
await copy(file, Deno.stdout);
|
||||
file.close();
|
||||
}
|
||||
```
|
||||
|
||||
To run the program:
|
||||
|
||||
```shell
|
||||
deno run --allow-read https://deno.land/std@$STD_VERSION/examples/cat.ts /etc/passwd
|
||||
```
|
|
@ -1,12 +0,0 @@
|
|||
# Getting Started
|
||||
|
||||
In this chapter we'll discuss:
|
||||
|
||||
- [Installing Deno](./getting_started/installation.md)
|
||||
- [Setting up your environment](./getting_started/setup_your_environment.md)
|
||||
- [Running a `Hello World` script](./getting_started/first_steps.md)
|
||||
- [Writing our own script](./getting_started/first_steps.md)
|
||||
- [Command line interface](./getting_started/command_line_interface.md)
|
||||
- [Understanding permissions](./getting_started/permissions.md)
|
||||
- [Using WebAssembly](./getting_started/webassembly.md)
|
||||
- [Debugging your code](./getting_started/debugging_your_code.md)
|
|
@ -1,145 +0,0 @@
|
|||
## Command line interface
|
||||
|
||||
Deno is a command line program. You should be familiar with some simple commands
|
||||
having followed the examples thus far and already understand the basics of shell
|
||||
usage.
|
||||
|
||||
There are multiple ways of viewing the main help text:
|
||||
|
||||
```shell
|
||||
# Using the subcommand.
|
||||
deno help
|
||||
|
||||
# Using the short flag -- outputs the same as above.
|
||||
deno -h
|
||||
|
||||
# Using the long flag -- outputs more detailed help text where available.
|
||||
deno --help
|
||||
```
|
||||
|
||||
Deno's CLI is subcommand-based. The above commands should show you a list of
|
||||
those supported, such as `deno bundle`. To see subcommand-specific help for
|
||||
`bundle`, you can similarly run one of:
|
||||
|
||||
```shell
|
||||
deno help bundle
|
||||
deno bundle -h
|
||||
deno bundle --help
|
||||
```
|
||||
|
||||
Detailed guides to each subcommand can be found [here](../tools.md).
|
||||
|
||||
### Script source
|
||||
|
||||
Deno can grab the scripts from multiple sources, a filename, a url, and '-' to
|
||||
read the file from stdin. The last is useful for integration with other
|
||||
applications.
|
||||
|
||||
```shell
|
||||
deno run main.ts
|
||||
deno run https://mydomain.com/main.ts
|
||||
cat main.ts | deno run -
|
||||
```
|
||||
|
||||
### Script arguments
|
||||
|
||||
Separately from the Deno runtime flags, you can pass user-space arguments to the
|
||||
script you are running by specifying them after the script name:
|
||||
|
||||
```shell
|
||||
deno run main.ts a b -c --quiet
|
||||
```
|
||||
|
||||
```ts
|
||||
// main.ts
|
||||
console.log(Deno.args); // [ "a", "b", "-c", "--quiet" ]
|
||||
```
|
||||
|
||||
**Note that anything passed after the script name will be passed as a script
|
||||
argument and not consumed as a Deno runtime flag.** This leads to the following
|
||||
pitfall:
|
||||
|
||||
```shell
|
||||
# Good. We grant net permission to net_client.ts.
|
||||
deno run --allow-net net_client.ts
|
||||
|
||||
# Bad! --allow-net was passed to Deno.args, throws a net permission error.
|
||||
deno run net_client.ts --allow-net
|
||||
```
|
||||
|
||||
Some see it as unconventional that:
|
||||
|
||||
> a non-positional flag is parsed differently depending on its position.
|
||||
|
||||
However:
|
||||
|
||||
1. This is the most logical and ergonomic way of distinguishing between runtime
|
||||
flags and script arguments.
|
||||
2. This is, in fact, the same behaviour as that of any other popular runtime.
|
||||
- Try `node -c index.js` and `node index.js -c`. The first will only do a
|
||||
syntax check on `index.js` as per Node's `-c` flag. The second will
|
||||
_execute_ `index.js` with `-c` passed to `require("process").argv`.
|
||||
|
||||
---
|
||||
|
||||
There exist logical groups of flags that are shared between related subcommands.
|
||||
We discuss these below.
|
||||
|
||||
### Watch mode
|
||||
|
||||
You can supply the `--watch` flag to `deno run` to enable the built in file
|
||||
watcher. When Deno starts up with this flag it watches the entrypoint, and all
|
||||
local files the entrypoint statically imports. Whenever one of these files is
|
||||
changed on disk, the program will automatically be restarted.
|
||||
|
||||
```
|
||||
deno run --watch main.ts
|
||||
```
|
||||
|
||||
### Integrity flags
|
||||
|
||||
Affect commands which can download resources to the cache: `deno cache`,
|
||||
`deno run` and `deno test`.
|
||||
|
||||
```
|
||||
--lock <FILE> Check the specified lock file
|
||||
--lock-write Write lock file. Use with --lock.
|
||||
```
|
||||
|
||||
Find out more about these
|
||||
[here](../linking_to_external_code/integrity_checking.md).
|
||||
|
||||
### Cache and compilation flags
|
||||
|
||||
Affect commands which can populate the cache: `deno cache`, `deno run` and
|
||||
`deno test`. As well as the flags above this includes those which affect module
|
||||
resolution, compilation configuration etc.
|
||||
|
||||
```
|
||||
--config <FILE> Load tsconfig.json configuration file
|
||||
--import-map <FILE> UNSTABLE: Load import map file
|
||||
--no-remote Do not resolve remote modules
|
||||
--reload=<CACHE_BLOCKLIST> Reload source code cache (recompile TypeScript)
|
||||
--unstable Enable unstable APIs
|
||||
```
|
||||
|
||||
### Runtime flags
|
||||
|
||||
Affect commands which execute user code: `deno run` and `deno test`. These
|
||||
include all of the above as well as the following.
|
||||
|
||||
#### Permission flags
|
||||
|
||||
These are listed [here](./permissions.md#permissions-list).
|
||||
|
||||
#### Other runtime flags
|
||||
|
||||
More flags which affect the execution environment.
|
||||
|
||||
```
|
||||
--cached-only Require that remote dependencies are already cached
|
||||
--inspect=<HOST:PORT> activate inspector on host:port ...
|
||||
--inspect-brk=<HOST:PORT> activate inspector on host:port and break at ...
|
||||
--seed <NUMBER> Seed Math.random()
|
||||
--v8-flags=<v8-flags> Set V8 command line options. For help: ...
|
||||
```
|
|
@ -1,145 +0,0 @@
|
|||
## Debugging your code
|
||||
|
||||
Deno supports the [V8 Inspector Protocol](https://v8.dev/docs/inspector).
|
||||
|
||||
It's possible to debug Deno programs using Chrome Devtools or other clients that
|
||||
support the protocol (eg. VSCode).
|
||||
|
||||
To activate debugging capabilities run Deno with the `--inspect` or
|
||||
`--inspect-brk` flags.
|
||||
|
||||
The `--inspect` flag allows attaching the debugger at any point in time, while
|
||||
`--inspect-brk` will wait for the debugger to attach and will pause execution on
|
||||
the first line of code.
|
||||
|
||||
### Chrome Devtools
|
||||
|
||||
Let's try debugging a program using Chrome Devtools. For this, we'll use
|
||||
[file_server.ts](https://deno.land/std@$STD_VERSION/http/file_server.ts) from
|
||||
`std`, a static file server.
|
||||
|
||||
Use the `--inspect-brk` flag to break execution on the first line:
|
||||
|
||||
```shell
|
||||
$ deno run --inspect-brk --allow-read --allow-net https://deno.land/std@$STD_VERSION/http/file_server.ts
|
||||
Debugger listening on ws://127.0.0.1:9229/ws/1e82c406-85a9-44ab-86b6-7341583480b1
|
||||
Download https://deno.land/std@$STD_VERSION/http/file_server.ts
|
||||
Compile https://deno.land/std@$STD_VERSION/http/file_server.ts
|
||||
...
|
||||
```
|
||||
|
||||
Open `chrome://inspect` and click `Inspect` next to target:
|
||||
|
||||
![chrome://inspect](../images/debugger1.jpg)
|
||||
|
||||
It might take a few seconds after opening the Devtools to load all modules.
|
||||
|
||||
![Devtools opened](../images/debugger2.jpg)
|
||||
|
||||
You might notice that Devtools paused execution on the first line of
|
||||
`_constants.ts` instead of `file_server.ts`. This is expected behavior and is
|
||||
caused by the way ES modules are evaluated by V8 (`_constants.ts` is left-most,
|
||||
bottom-most dependency of `file_server.ts` so it is evaluated first).
|
||||
|
||||
At this point all source code is available in the Devtools, so let's open up
|
||||
`file_server.ts` and add a breakpoint there; go to "Sources" pane and expand the
|
||||
tree:
|
||||
|
||||
![Open file_server.ts](../images/debugger3.jpg)
|
||||
|
||||
_Looking closely you'll find duplicate entries for each file; one written
|
||||
regularly and one in italics. The former is compiled source file (so in the case
|
||||
of `.ts` files it will be emitted JavaScript source), while the latter is a
|
||||
source map for the file._
|
||||
|
||||
Next, add a breakpoint in the `listenAndServe` method:
|
||||
|
||||
![Break in file_server.ts](../images/debugger4.jpg)
|
||||
|
||||
As soon as we've added the breakpoint Devtools automatically opened up the
|
||||
source map file, which allows us step through the actual source code that
|
||||
includes types.
|
||||
|
||||
Now that we have our breakpoints set, we can resume the execution of our script
|
||||
so that we might inspect an incoming request. Hit the Resume script execution
|
||||
button to do so. You might even need to hit it twice!
|
||||
|
||||
Once our script is running again, let's send a request and inspect it in
|
||||
Devtools:
|
||||
|
||||
```
|
||||
$ curl http://0.0.0.0:4507/
|
||||
```
|
||||
|
||||
![Break in request handling](../images/debugger5.jpg)
|
||||
|
||||
At this point we can introspect the contents of the request and go step-by-step
|
||||
to debug the code.
|
||||
|
||||
### VSCode
|
||||
|
||||
Deno can be debugged using VSCode.
|
||||
|
||||
Official support via the plugin is being worked on -
|
||||
https://github.com/denoland/vscode_deno/issues/12
|
||||
|
||||
We can still attach the debugger by manually providing a
|
||||
[`launch.json`](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations)
|
||||
config:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Deno",
|
||||
"type": "pwa-node",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"runtimeExecutable": "deno",
|
||||
"runtimeArgs": ["run", "--inspect-brk", "-A", "${file}"],
|
||||
"attachSimplePort": 9229
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**NOTE**: This uses the file you have open as the entry point; replace `${file}`
|
||||
with a script name if you want a fixed entry point.
|
||||
|
||||
Let's try out debugging a local source file. Create `server.ts`:
|
||||
|
||||
```ts
|
||||
import { serve } from "https://deno.land/std@$STD_VERSION/http/server.ts";
|
||||
const server = serve({ port: 8000 });
|
||||
console.log("http://localhost:8000/");
|
||||
|
||||
for await (const req of server) {
|
||||
req.respond({ body: "Hello World\n" });
|
||||
}
|
||||
```
|
||||
|
||||
Then we can set a breakpoint, and run the created configuration:
|
||||
|
||||
![VSCode debugger](../images/debugger7.jpg)
|
||||
|
||||
### JetBrains IDEs
|
||||
|
||||
You can debug Deno using your JetBrains IDE by right-clicking the file you want
|
||||
to debug and selecting the `Debug 'Deno: <file name>'` option. This will create
|
||||
a run/debug configuration with no permission flags set. To configure these flags
|
||||
edit the run/debug configuration and modify the `Arguments` field with the
|
||||
required flags.
|
||||
|
||||
### Other
|
||||
|
||||
Any client that implements the Devtools protocol should be able to connect to a
|
||||
Deno process.
|
||||
|
||||
### Limitations
|
||||
|
||||
Devtools support is still immature. There is some functionality that is known to
|
||||
be missing or buggy:
|
||||
|
||||
- autocomplete in Devtools' console causes the Deno process to exit.
|
||||
- profiling and memory dumps might not work correctly.
|
|
@ -1,146 +0,0 @@
|
|||
## First steps
|
||||
|
||||
This page contains some examples to teach you about the fundamentals of Deno.
|
||||
|
||||
This document assumes that you have some prior knowledge of JavaScript,
|
||||
especially about `async`/`await`. If you have no prior knowledge of JavaScript,
|
||||
you might want to follow a guide
|
||||
[on the basics of JavaScript](https://developer.mozilla.org/en-US/docs/Learn/JavaScript)
|
||||
before attempting to start with Deno.
|
||||
|
||||
### Hello World
|
||||
|
||||
Deno is a runtime for JavaScript/TypeScript which tries to be web compatible and
|
||||
use modern features wherever possible.
|
||||
|
||||
Browser compatibility means a `Hello World` program in Deno is the same as the
|
||||
one you can run in the browser:
|
||||
|
||||
```ts
|
||||
console.log("Welcome to Deno!");
|
||||
```
|
||||
|
||||
Try the program:
|
||||
|
||||
```shell
|
||||
deno run https://deno.land/std@$STD_VERSION/examples/welcome.ts
|
||||
```
|
||||
|
||||
### Making an HTTP request
|
||||
|
||||
Many programs use HTTP requests to fetch data from a webserver. Let's write a
|
||||
small program that fetches a file and prints its contents out to the terminal.
|
||||
|
||||
Just like in the browser you can use the web standard
|
||||
[`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) API to
|
||||
make HTTP calls:
|
||||
|
||||
```ts
|
||||
const url = Deno.args[0];
|
||||
const res = await fetch(url);
|
||||
|
||||
const body = new Uint8Array(await res.arrayBuffer());
|
||||
await Deno.stdout.write(body);
|
||||
```
|
||||
|
||||
Let's walk through what this application does:
|
||||
|
||||
1. We get the first argument passed to the application, and store it in the
|
||||
`url` constant.
|
||||
2. We make a request to the url specified, await the response, and store it in
|
||||
the `res` constant.
|
||||
3. We parse the response body as an
|
||||
[`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer),
|
||||
await the response, and convert it into a
|
||||
[`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array)
|
||||
to store in the `body` constant.
|
||||
4. We write the contents of the `body` constant to `stdout`.
|
||||
|
||||
Try it out:
|
||||
|
||||
```shell
|
||||
deno run https://deno.land/std@$STD_VERSION/examples/curl.ts https://example.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
|
||||
which is secure by default. This means you need to explicitly give programs the
|
||||
permission to do certain 'privileged' actions, such as access the network.
|
||||
|
||||
Try it out again with the correct permission flag:
|
||||
|
||||
```shell
|
||||
deno run --allow-net=example.com https://deno.land/std@$STD_VERSION/examples/curl.ts https://example.com
|
||||
```
|
||||
|
||||
### Reading a file
|
||||
|
||||
Deno also provides APIs which do not come from the web. These are all contained
|
||||
in the `Deno` global. You can find documentation for these APIs on
|
||||
[doc.deno.land](https://doc.deno.land/builtin/stable#Deno).
|
||||
|
||||
Filesystem APIs for example do not have a web standard form, so Deno provides
|
||||
its own API.
|
||||
|
||||
In this program each command-line argument is assumed to be a filename, the file
|
||||
is opened, and printed to stdout.
|
||||
|
||||
```ts
|
||||
import { copy } from "https://deno.land/std@$STD_VERSION/io/util.ts";
|
||||
const filenames = Deno.args;
|
||||
for (const filename of filenames) {
|
||||
const file = await Deno.open(filename);
|
||||
await copy(file, Deno.stdout);
|
||||
file.close();
|
||||
}
|
||||
```
|
||||
|
||||
The `copy()` function here actually makes no more than the necessary
|
||||
kernel→userspace→kernel copies. That is, the same memory from which data is read
|
||||
from the file, is written to stdout. This illustrates a general design goal for
|
||||
I/O streams in Deno.
|
||||
|
||||
Try the program:
|
||||
|
||||
```shell
|
||||
deno run --allow-read https://deno.land/std@$STD_VERSION/examples/cat.ts /etc/passwd
|
||||
```
|
||||
|
||||
### TCP server
|
||||
|
||||
This is an example of a server which accepts connections on port 8080, and
|
||||
returns to the client anything it sends.
|
||||
|
||||
```ts
|
||||
import { copy } from "https://deno.land/std@$STD_VERSION/io/util.ts";
|
||||
const hostname = "0.0.0.0";
|
||||
const port = 8080;
|
||||
const listener = Deno.listen({ hostname, port });
|
||||
console.log(`Listening on ${hostname}:${port}`);
|
||||
for await (const conn of listener) {
|
||||
copy(conn, conn);
|
||||
}
|
||||
```
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
To test it, try sending data to it with netcat:
|
||||
|
||||
```shell
|
||||
$ nc localhost 8080
|
||||
hello world
|
||||
hello world
|
||||
```
|
||||
|
||||
Like the `cat.ts` example, the `copy()` function here also does not make
|
||||
unnecessary memory copies. It receives a packet from the kernel and sends it
|
||||
back, without further complexity.
|
||||
|
||||
### More examples
|
||||
|
||||
You can find more examples, like an HTTP file server, in the `Examples` chapter.
|
|
@ -1,92 +0,0 @@
|
|||
## Installation
|
||||
|
||||
Deno works on macOS, Linux, and Windows. Deno is a single binary executable. It
|
||||
has no external dependencies.
|
||||
|
||||
### Download and install
|
||||
|
||||
[deno_install](https://github.com/denoland/deno_install) provides convenience
|
||||
scripts to download and install the binary.
|
||||
|
||||
Using Shell (macOS and Linux):
|
||||
|
||||
```shell
|
||||
curl -fsSL https://deno.land/x/install/install.sh | sh
|
||||
```
|
||||
|
||||
Using PowerShell (Windows):
|
||||
|
||||
```shell
|
||||
iwr https://deno.land/x/install/install.ps1 -useb | iex
|
||||
```
|
||||
|
||||
Using [Scoop](https://scoop.sh/) (Windows):
|
||||
|
||||
```shell
|
||||
scoop install deno
|
||||
```
|
||||
|
||||
Using [Chocolatey](https://chocolatey.org/packages/deno) (Windows):
|
||||
|
||||
```shell
|
||||
choco install deno
|
||||
```
|
||||
|
||||
Using [Homebrew](https://formulae.brew.sh/formula/deno) (macOS):
|
||||
|
||||
```shell
|
||||
brew install deno
|
||||
```
|
||||
|
||||
Using [Nix](https://nixos.org/download.html) (macOS and Linux):
|
||||
|
||||
```shell
|
||||
nix-shell -p deno
|
||||
```
|
||||
|
||||
Build and install from source using [Cargo](https://crates.io/crates/deno):
|
||||
|
||||
```shell
|
||||
cargo install deno --locked
|
||||
```
|
||||
|
||||
Deno binaries can also be installed manually, by downloading a zip file at
|
||||
[github.com/denoland/deno/releases](https://github.com/denoland/deno/releases).
|
||||
These packages contain just a single executable file. You will have to set the
|
||||
executable bit on macOS and Linux.
|
||||
|
||||
### Docker
|
||||
|
||||
For more information and instructions on the official Docker images:
|
||||
[https://github.com/denoland/deno_docker](https://github.com/denoland/deno_docker)
|
||||
|
||||
### Testing your installation
|
||||
|
||||
To test your installation, run `deno --version`. If this prints the Deno version
|
||||
to the console the installation was successful.
|
||||
|
||||
Use `deno help` to see help text documenting Deno's flags and usage. Get a
|
||||
detailed guide on the CLI [here](./command_line_interface.md).
|
||||
|
||||
### Updating
|
||||
|
||||
To update a previously installed version of Deno, you can run:
|
||||
|
||||
```shell
|
||||
deno upgrade
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
You can also use this utility to install a specific version of Deno:
|
||||
|
||||
```shell
|
||||
deno upgrade --version 1.0.1
|
||||
```
|
||||
|
||||
### Building from source
|
||||
|
||||
Information about how to build from source can be found in the `Contributing`
|
||||
chapter.
|
|
@ -1,96 +0,0 @@
|
|||
## Permissions
|
||||
|
||||
Deno is secure by default. Therefore, unless you specifically enable it, a deno
|
||||
module has no file, network, or environment access for example. Access to
|
||||
security-sensitive areas or functions requires the use of permissions to be
|
||||
granted to a deno process on the command line.
|
||||
|
||||
For the following example, `mod.ts` has been granted read-only access to the
|
||||
file system. It cannot write to it, or perform any other security-sensitive
|
||||
functions.
|
||||
|
||||
```shell
|
||||
deno run --allow-read mod.ts
|
||||
```
|
||||
|
||||
### Permissions list
|
||||
|
||||
The following permissions are available:
|
||||
|
||||
- **-A, --allow-all** Allow all permissions. This disables all security.
|
||||
- **--allow-env=\<allow-env\>** Allow environment access for things like getting
|
||||
and setting of environment variables. Since Deno 1.9, you can specify a
|
||||
optional, comma-separated list of environment variables to provide an
|
||||
allow-list of allowed environment variables.
|
||||
- **--allow-hrtime** Allow high-resolution time measurement. High-resolution
|
||||
time can be used in timing attacks and fingerprinting.
|
||||
- **--allow-net=\<allow-net\>** Allow network access. You can specify an
|
||||
optional, comma-separated list of domains to provide an allow-list of allowed
|
||||
domains.
|
||||
- **--allow-plugin** Allow loading plugins. Please note that --allow-plugin is
|
||||
an unstable feature.
|
||||
- **--allow-read=\<allow-read\>** Allow file system read access. You can specify
|
||||
an optional, comma-separated list of directories or files to provide an
|
||||
allow-list of allowed file system access.
|
||||
- **--allow-run=\<allow-run\>** Allow running subprocesses. Since Deno 1.9, You
|
||||
can specify an options, comma-separated list of subprocesses to provide an
|
||||
allow-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.
|
||||
- **--allow-write=\<allow-write\>** Allow file system write access. You can
|
||||
specify an optional, comma-separated list of directories or files to provide
|
||||
an allow-list of allowed file system access.
|
||||
|
||||
### Permissions allow-list
|
||||
|
||||
Deno also allows you to control the granularity of some permissions with
|
||||
allow-lists.
|
||||
|
||||
This example restricts file system access by allow-listing only the `/usr`
|
||||
directory, however the execution fails as the process was attempting to access a
|
||||
file in the `/etc` directory:
|
||||
|
||||
```shell
|
||||
$ deno run --allow-read=/usr https://deno.land/std@$STD_VERSION/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)
|
||||
...
|
||||
```
|
||||
|
||||
Try it out again with the correct permissions by allow-listing `/etc` instead:
|
||||
|
||||
```shell
|
||||
deno run --allow-read=/etc https://deno.land/std@$STD_VERSION/examples/cat.ts /etc/passwd
|
||||
```
|
||||
|
||||
`--allow-write` works the same as `--allow-read`.
|
||||
|
||||
### Network access:
|
||||
|
||||
_fetch.ts_:
|
||||
|
||||
```ts
|
||||
const result = await fetch("https://deno.land/");
|
||||
```
|
||||
|
||||
This is an example of how to allow-list hosts/urls:
|
||||
|
||||
```shell
|
||||
deno run --allow-net=github.com,deno.land fetch.ts
|
||||
```
|
||||
|
||||
If `fetch.ts` tries to establish network connections to any other domain, the
|
||||
process will fail.
|
||||
|
||||
Allow net calls to any host/url:
|
||||
|
||||
```shell
|
||||
deno run --allow-net fetch.ts
|
||||
```
|
||||
|
||||
### Conference
|
||||
|
||||
Ryan Dahl. (September 25, 2020).
|
||||
[The Deno security model](https://www.youtube.com/watch?v=r5F6dekUmdE#t=34m57).
|
||||
Speakeasy JS.
|
|
@ -1,329 +0,0 @@
|
|||
## Set up your environment
|
||||
|
||||
To productively get going with Deno you should set up your environment. This
|
||||
means setting up shell autocomplete, environmental variables and your editor or
|
||||
IDE of choice.
|
||||
|
||||
### Environmental variables
|
||||
|
||||
There are several env vars that control how Deno behaves:
|
||||
|
||||
`DENO_DIR` defaults to `$HOME/.cache/deno` but can be set to any path to control
|
||||
where generated and cached source code is written and read to.
|
||||
|
||||
`NO_COLOR` will turn off color output if set. See https://no-color.org/. User
|
||||
code can test if `NO_COLOR` was set without having `--allow-env` by using the
|
||||
boolean constant `Deno.noColor`.
|
||||
|
||||
### Shell autocomplete
|
||||
|
||||
You can generate completion script for your shell using the
|
||||
`deno completions <shell>` command. The command outputs to stdout so you should
|
||||
redirect it to an appropriate file.
|
||||
|
||||
The supported shells are:
|
||||
|
||||
- zsh
|
||||
- bash
|
||||
- fish
|
||||
- powershell
|
||||
- elvish
|
||||
|
||||
Example (bash):
|
||||
|
||||
```shell
|
||||
deno completions bash > /usr/local/etc/bash_completion.d/deno.bash
|
||||
source /usr/local/etc/bash_completion.d/deno.bash
|
||||
```
|
||||
|
||||
Example (zsh without framework):
|
||||
|
||||
```shell
|
||||
mkdir ~/.zsh # create a folder to save your completions. it can be anywhere
|
||||
deno completions zsh > ~/.zsh/_deno
|
||||
```
|
||||
|
||||
then add this to your `.zshrc`
|
||||
|
||||
```shell
|
||||
fpath=(~/.zsh $fpath)
|
||||
autoload -Uz compinit
|
||||
compinit -u
|
||||
```
|
||||
|
||||
and restart your terminal. note that if completions are still not loading, you
|
||||
may need to run `rm ~/.zcompdump/` to remove previously generated completions
|
||||
and then `compinit` to generate them again.
|
||||
|
||||
Example (zsh + oh-my-zsh) [recommended for zsh users] :
|
||||
|
||||
```shell
|
||||
mkdir ~/.oh-my-zsh/custom/plugins/deno
|
||||
deno completions zsh > ~/.oh-my-zsh/custom/plugins/deno/_deno
|
||||
```
|
||||
|
||||
After this add deno plugin under plugins tag in `~/.zshrc` file. for tools like
|
||||
`antigen` path will be `~/.antigen/bundles/robbyrussell/oh-my-zsh/plugins` and
|
||||
command will be `antigen bundle deno` and so on.
|
||||
|
||||
Example (Powershell):
|
||||
|
||||
```shell
|
||||
deno completions powershell >> $profile
|
||||
.$profile
|
||||
```
|
||||
|
||||
This will be create a Powershell profile at
|
||||
`$HOME\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1` by default,
|
||||
and it will be run whenever you launch the PowerShell.
|
||||
|
||||
### Editors and IDEs
|
||||
|
||||
Because Deno requires the use of file extensions for module imports and allows
|
||||
http imports, and most editors and language servers do not natively support this
|
||||
at the moment, many editors will throw errors about being unable to find files
|
||||
or imports having unnecessary file extensions.
|
||||
|
||||
The community has developed extensions for some editors to solve these issues:
|
||||
|
||||
#### VS Code
|
||||
|
||||
The beta version of [vscode_deno](https://github.com/denoland/vscode_deno) is
|
||||
published on the
|
||||
[Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno).
|
||||
Please report any issues.
|
||||
|
||||
#### JetBrains IDEs
|
||||
|
||||
Support for JetBrains IDEs is available through
|
||||
[the Deno plugin](https://plugins.jetbrains.com/plugin/14382-deno).
|
||||
|
||||
Once installed, replace the content of
|
||||
`External Libraries > Deno Library > lib > lib.deno.d.ts` with the output of
|
||||
`deno types`. This will ensure the typings for the extension match the current
|
||||
version. You will have to do this every time you update the version of Deno. For
|
||||
more information on how to set-up your JetBrains IDE for Deno, read
|
||||
[this comment](https://youtrack.jetbrains.com/issue/WEB-41607#focus=streamItem-27-4160152.0-0)
|
||||
on YouTrack.
|
||||
|
||||
#### Vim and NeoVim
|
||||
|
||||
Vim works fairly well for Deno/TypeScript if you install
|
||||
[CoC](https://github.com/neoclide/coc.nvim) (intellisense engine and language
|
||||
server protocol) or [ALE](https://github.com/dense-analysis/ale) (syntax checker
|
||||
and language server protocol client).
|
||||
|
||||
##### CoC
|
||||
|
||||
After CoC is installed, from inside Vim, run`:CocInstall coc-tsserver` and
|
||||
`:CocInstall coc-deno`. Run `:CocCommand deno.initializeWorkspace` in your
|
||||
project to initialize workspace configurations. From now on, things like `gd`
|
||||
(go to definition) and `gr` (goto/find references) should work.
|
||||
|
||||
##### ALE
|
||||
|
||||
ALE integrates with Deno's LSP out of the box and should not require any extra
|
||||
configuration. However, if your Deno executable is not located in `$PATH`, has a
|
||||
different name than `deno` or you want to use unstable features/APIs, you need
|
||||
to override ALE's default values. See
|
||||
[`:help ale-typescript`](https://github.com/dense-analysis/ale/blob/master/doc/ale-typescript.txt).
|
||||
|
||||
ALE provides support for autocompletion, refactoring, going to definition,
|
||||
finding references and more, however, key bindings need to be configured
|
||||
manually. Copy the snippet below into your `vimrc`/`init.vim` for basic
|
||||
configuration or consult the
|
||||
[official documentation](https://github.com/dense-analysis/ale#table-of-contents)
|
||||
for a more in-depth look at how to configure ALE.
|
||||
|
||||
ALE can fix linter issues by running `deno fmt`. To instruct ALE to use the Deno
|
||||
formatter the `ale_linter` setting needs to be set either on a per buffer basis
|
||||
(`let b:ale_linter = ['deno']`) or globally for all TypeScript files
|
||||
(`let g:ale_fixers={'typescript': ['deno']}`)
|
||||
|
||||
```vim
|
||||
" Use ALE autocompletion with Vim's 'omnifunc' setting (press <C-x><C-o> in insert mode)
|
||||
autocmd FileType typescript set omnifunc=ale#completion#OmniFunc
|
||||
|
||||
" Make sure to use map instead of noremap when using a <Plug>(...) expression as the {rhs}
|
||||
nmap gr <Plug>(ale_rename)
|
||||
nmap gR <Plug>(ale_find_reference)
|
||||
nmap gd <Plug>(ale_go_to_definition)
|
||||
nmap gD <Plug>(ale_go_to_type_definition)
|
||||
|
||||
let g:ale_fixers = {'typescript': ['deno']}
|
||||
let g:ale_fix_on_save = 1 " run deno fmt when saving a buffer
|
||||
```
|
||||
|
||||
#### Emacs
|
||||
|
||||
Emacs works pretty well for a TypeScript project targeted to Deno by using a
|
||||
combination of [tide](https://github.com/ananthakumaran/tide) which is the
|
||||
canonical way of using TypeScript within Emacs and
|
||||
[typescript-deno-plugin](https://github.com/justjavac/typescript-deno-plugin)
|
||||
which is what is used by the
|
||||
[official VSCode extension for Deno](https://github.com/denoland/vscode_deno).
|
||||
|
||||
To use it, first make sure that `tide` is setup for your instance of Emacs.
|
||||
Next, as instructed on the
|
||||
[typescript-deno-plugin](https://github.com/justjavac/typescript-deno-plugin)
|
||||
page, first `npm install --save-dev typescript-deno-plugin typescript` in your
|
||||
project (`npm init -y` as necessary), then add the following block to your
|
||||
`tsconfig.json` and you are off to the races!
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"compilerOptions": {
|
||||
"plugins": [
|
||||
{
|
||||
"name": "typescript-deno-plugin",
|
||||
"enable": true, // default is `true`
|
||||
"importmap": "import_map.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can also use built-in Deno language server by using
|
||||
[`eglot`](https://github.com/joaotavora/eglot).
|
||||
|
||||
Example configuration:
|
||||
|
||||
```elisp
|
||||
(add-to-list 'eglot-server-programs '((js-mode typescript-mode) . (eglot-deno "deno" "lsp")))
|
||||
|
||||
(defclass eglot-deno (eglot-lsp-server) ()
|
||||
:documentation "A custom class for deno lsp.")
|
||||
|
||||
(cl-defmethod eglot-initialization-options ((server eglot-deno))
|
||||
"Passes through required deno initialization options"
|
||||
(list :enable t
|
||||
:lint t))
|
||||
```
|
||||
|
||||
#### Atom
|
||||
|
||||
Install [atom-ide-base](https://atom.io/packages/atom-ide-base) package and
|
||||
[atom-ide-deno](https://atom.io/packages/atom-ide-deno) package on Atom.
|
||||
|
||||
#### LSP clients
|
||||
|
||||
Deno has builtin support for the
|
||||
[Language server protocol](https://langserver.org) as of version 1.6.0 or later.
|
||||
|
||||
If your editor supports the LSP, you can use Deno as a language server for
|
||||
TypeScript and JavaScript.
|
||||
|
||||
The editor can start the server with `deno lsp`.
|
||||
|
||||
##### Example for Kakoune
|
||||
|
||||
After installing the [`kak-lsp`](https://github.com/kak-lsp/kak-lsp) LSP client
|
||||
you can add the Deno language server by adding the following to your
|
||||
`kak-lsp.toml`
|
||||
|
||||
```toml
|
||||
[language.deno]
|
||||
filetypes = ["typescript", "javascript"]
|
||||
roots = [".git"]
|
||||
command = "deno"
|
||||
args = ["lsp"]
|
||||
|
||||
[language.deno.initialization_options]
|
||||
enable = true
|
||||
lint = true
|
||||
```
|
||||
|
||||
##### Example for Vim/Neovim
|
||||
|
||||
After installing the [`vim-lsp`](https://github.com/prabirshrestha/vim-lsp) LSP
|
||||
client you can add the Deno language server by adding the following to your
|
||||
`vimrc`/`init.vim`:
|
||||
|
||||
```vim
|
||||
if executable("deno")
|
||||
augroup LspTypeScript
|
||||
autocmd!
|
||||
autocmd User lsp_setup call lsp#register_server({
|
||||
\ "name": "deno lsp",
|
||||
\ "cmd": {server_info -> ["deno", "lsp"]},
|
||||
\ "root_uri": {server_info->lsp#utils#path_to_uri(lsp#utils#find_nearest_parent_file_directory(lsp#utils#get_buffer_path(), "tsconfig.json"))},
|
||||
\ "allowlist": ["typescript", "typescript.tsx"],
|
||||
\ "initialization_options": {
|
||||
\ "enable": v:true,
|
||||
\ "lint": v:true,
|
||||
\ "unstable": v:true,
|
||||
\ },
|
||||
\ })
|
||||
augroup END
|
||||
endif
|
||||
```
|
||||
|
||||
##### Example for Sublime Text
|
||||
|
||||
- Install the [Sublime LSP package](https://packagecontrol.io/packages/LSP)
|
||||
- Install the
|
||||
[TypeScript package](https://packagecontrol.io/packages/TypeScript) to get
|
||||
syntax highlighting
|
||||
- Add the following `.sublime-project` file to your project folder
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"settings": {
|
||||
"LSP": {
|
||||
"deno": {
|
||||
"command": [
|
||||
"deno",
|
||||
"lsp"
|
||||
],
|
||||
"initializationOptions": {
|
||||
// "config": "", // Sets the path for the config file in your project
|
||||
"enable": true,
|
||||
// "importMap": "", // Sets the path for the import-map in your project
|
||||
"lint": true,
|
||||
"unstable": false
|
||||
},
|
||||
"enabled": true,
|
||||
"languages": [
|
||||
{
|
||||
"languageId": "javascript",
|
||||
"scopes": ["source.js"],
|
||||
"syntaxes": [
|
||||
"Packages/Babel/JavaScript (Babel).sublime-syntax",
|
||||
"Packages/JavaScript/JavaScript.sublime-syntax"
|
||||
]
|
||||
},
|
||||
{
|
||||
"languageId": "javascriptreact",
|
||||
"scopes": ["source.jsx"],
|
||||
"syntaxes": [
|
||||
"Packages/Babel/JavaScript (Babel).sublime-syntax",
|
||||
"Packages/JavaScript/JavaScript.sublime-syntax"
|
||||
]
|
||||
},
|
||||
{
|
||||
"languageId": "typescript",
|
||||
"scopes": ["source.ts"],
|
||||
"syntaxes": [
|
||||
"Packages/TypeScript-TmLanguage/TypeScript.tmLanguage",
|
||||
"Packages/TypeScript Syntax/TypeScript.tmLanguage"
|
||||
]
|
||||
},
|
||||
{
|
||||
"languageId": "typescriptreact",
|
||||
"scopes": ["source.tsx"],
|
||||
"syntaxes": [
|
||||
"Packages/TypeScript-TmLanguage/TypeScriptReact.tmLanguage",
|
||||
"Packages/TypeScript Syntax/TypeScriptReact.tmLanguage"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If you don't see your favorite IDE on this list, maybe you can develop an
|
||||
extension. Our [community Discord group](https://discord.gg/deno) can give you
|
||||
some pointers on where to get started.
|
|
@ -1,4 +0,0 @@
|
|||
## Using TypeScript
|
||||
|
||||
> ℹ️ This section has been moved to
|
||||
> [Using TypeScript Chapter](../typescript.md).
|
|
@ -1,43 +0,0 @@
|
|||
## WebAssembly support
|
||||
|
||||
Deno can execute [WebAssembly](https://webassembly.org/) modules with the same
|
||||
interfaces that
|
||||
[browsers provide](https://developer.mozilla.org/en-US/docs/WebAssembly).
|
||||
|
||||
<!-- deno-fmt-ignore -->
|
||||
|
||||
```ts
|
||||
const wasmCode = new Uint8Array([
|
||||
0, 97, 115, 109, 1, 0, 0, 0, 1, 133, 128, 128, 128, 0, 1, 96, 0, 1, 127,
|
||||
3, 130, 128, 128, 128, 0, 1, 0, 4, 132, 128, 128, 128, 0, 1, 112, 0, 0,
|
||||
5, 131, 128, 128, 128, 0, 1, 0, 1, 6, 129, 128, 128, 128, 0, 0, 7, 145,
|
||||
128, 128, 128, 0, 2, 6, 109, 101, 109, 111, 114, 121, 2, 0, 4, 109, 97,
|
||||
105, 110, 0, 0, 10, 138, 128, 128, 128, 0, 1, 132, 128, 128, 128, 0, 0,
|
||||
65, 42, 11
|
||||
]);
|
||||
const wasmModule = new WebAssembly.Module(wasmCode);
|
||||
const wasmInstance = new WebAssembly.Instance(wasmModule);
|
||||
const main = wasmInstance.exports.main as CallableFunction
|
||||
console.log(main().toString());
|
||||
```
|
||||
|
||||
For files:
|
||||
|
||||
```ts
|
||||
const wasmCode = await Deno.readFile("main.wasm");
|
||||
const wasmModule = new WebAssembly.Module(wasmCode);
|
||||
const wasmInstance = new WebAssembly.Instance(wasmModule);
|
||||
const main = wasmInstance.exports.main as CallableFunction;
|
||||
console.log(main().toString());
|
||||
```
|
||||
|
||||
And for loading WebAssembly modules over the network (note that the file must be
|
||||
served with `application/wasm` MIME type):
|
||||
|
||||
```ts
|
||||
const { instance, module } = await WebAssembly.instantiateStreaming(
|
||||
fetch("https://wpt.live/wasm/incrementer.wasm"),
|
||||
);
|
||||
const increment = instance.exports.increment as (input: number) => number;
|
||||
console.log(increment(41));
|
||||
```
|
18
docs/help.md
|
@ -1,18 +0,0 @@
|
|||
# Where To Get Help
|
||||
|
||||
Stuck? Lost? Get Help from the Community.
|
||||
|
||||
### [Stack Overflow](https://stackoverflow.com/questions/tagged/deno)
|
||||
|
||||
Stack Overflow is a popular forum to ask code-level questions or if you’re stuck
|
||||
with a specific error.
|
||||
[ask your own!](https://stackoverflow.com/questions/ask?tags=deno)
|
||||
|
||||
### [Community Discord](https://discord.gg/deno)
|
||||
|
||||
Ask questions and chat with community members in real-time.
|
||||
|
||||
### [DEV's Deno Community](https://dev.to/t/deno)
|
||||
|
||||
A great place to find interesting articles about best practices, application
|
||||
architecture and new learnings. Post your articles with the tag `deno`.
|
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 106 KiB |
Before Width: | Height: | Size: 112 KiB |
Before Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 111 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 11 KiB |
|
@ -1,73 +0,0 @@
|
|||
# Introduction
|
||||
|
||||
Deno is a JavaScript/TypeScript runtime with secure defaults and a great
|
||||
developer experience.
|
||||
|
||||
It's built on V8, Rust, and Tokio.
|
||||
|
||||
## Feature highlights
|
||||
|
||||
- Secure by default. No file, network, or environment access (unless explicitly
|
||||
enabled).
|
||||
- Supports TypeScript out of the box.
|
||||
- Ships a single executable (`deno`).
|
||||
- Has built-in utilities like a dependency inspector (`deno info`) and a code
|
||||
formatter (`deno fmt`).
|
||||
- Has
|
||||
[a set of reviewed (audited) standard
|
||||
modules](https://github.com/denoland/deno_std) that are guaranteed to work
|
||||
with Deno.
|
||||
- Can bundle scripts into a single JavaScript file.
|
||||
|
||||
## Philosophy
|
||||
|
||||
Deno aims to be a productive and secure scripting environment for the modern
|
||||
programmer.
|
||||
|
||||
Deno will always be distributed as a single executable. Given a URL to a Deno
|
||||
program, it is runnable with nothing more than
|
||||
[the ~25 megabyte zipped executable](https://github.com/denoland/deno/releases).
|
||||
Deno explicitly takes on the role of both runtime and package manager. It uses a
|
||||
standard browser-compatible protocol for loading modules: URLs.
|
||||
|
||||
Among other things, Deno is a great replacement for utility scripts that may
|
||||
have been historically written with Bash or Python.
|
||||
|
||||
## Goals
|
||||
|
||||
- Ship as just a single executable (`deno`).
|
||||
- Provide secure defaults.
|
||||
- Unless specifically allowed, scripts can't access files, the environment, or
|
||||
the network.
|
||||
- Be browser-compatible.
|
||||
- The subset of Deno programs which are written completely in JavaScript and
|
||||
do not use the global `Deno` namespace (or feature test for it), ought to
|
||||
also be able to be run in a modern web browser without change.
|
||||
- Provide built-in tooling to improve developer experience.
|
||||
- E.g. unit testing, code formatting, and linting.
|
||||
- Keep V8 concepts out of user land.
|
||||
- Serve HTTP efficiently.
|
||||
|
||||
## Comparison to Node.js
|
||||
|
||||
- Deno does not use `npm`.
|
||||
- It uses modules referenced as URLs or file paths.
|
||||
- Deno does not use `package.json` in its module resolution algorithm.
|
||||
- All async actions in Deno return a promise. Thus Deno provides different APIs
|
||||
than Node.
|
||||
- Deno requires explicit permissions for file, network, and environment access.
|
||||
- Deno always dies on uncaught errors.
|
||||
- Deno uses "ES Modules" and does not support `require()`. Third party modules
|
||||
are imported via URLs:
|
||||
|
||||
```javascript
|
||||
import * as log from "https://deno.land/std@$STD_VERSION/log/mod.ts";
|
||||
```
|
||||
|
||||
## Other key behaviors
|
||||
|
||||
- Fetch and cache remote code upon first execution, and never update it until
|
||||
the code is run with the `--reload` flag. (So, this will still work on an
|
||||
airplane.)
|
||||
- Modules/files loaded from remote URLs are intended to be immutable and
|
||||
cacheable.
|
|
@ -1,110 +0,0 @@
|
|||
# Linking to third party code
|
||||
|
||||
In the [Getting Started](./getting_started.md) section, we saw Deno could
|
||||
execute scripts from URLs. Like browser JavaScript, Deno can import libraries
|
||||
directly from URLs. This example uses a URL to import an assertion library:
|
||||
|
||||
**test.ts**
|
||||
|
||||
```ts
|
||||
import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
|
||||
assertEquals("hello", "hello");
|
||||
assertEquals("world", "world");
|
||||
|
||||
console.log("Asserted! ✓");
|
||||
```
|
||||
|
||||
Try running this:
|
||||
|
||||
```shell
|
||||
$ deno run test.ts
|
||||
Compile file:///mnt/f9/Projects/github.com/denoland/deno/docs/test.ts
|
||||
Download https://deno.land/std@$STD_VERSION/testing/asserts.ts
|
||||
Download https://deno.land/std@$STD_VERSION/fmt/colors.ts
|
||||
Download https://deno.land/std@$STD_VERSION/testing/diff.ts
|
||||
Asserted! ✓
|
||||
```
|
||||
|
||||
Note that we did not have to provide the `--allow-net` flag for this program,
|
||||
and yet it accessed the network. The runtime has special access to download
|
||||
imports and cache them to disk.
|
||||
|
||||
Deno caches remote imports in a special directory specified by the `DENO_DIR`
|
||||
environment variable. It defaults to the system's cache directory if `DENO_DIR`
|
||||
is not specified. The next time you run the program, no downloads will be made.
|
||||
If the program hasn't changed, it won't be recompiled either. The default
|
||||
directory is:
|
||||
|
||||
- On Linux/Redox: `$XDG_CACHE_HOME/deno` or `$HOME/.cache/deno`
|
||||
- On Windows: `%LOCALAPPDATA%/deno` (`%LOCALAPPDATA%` = `FOLDERID_LocalAppData`)
|
||||
- On macOS: `$HOME/Library/Caches/deno`
|
||||
- If something fails, it falls back to `$HOME/.deno`
|
||||
|
||||
## FAQ
|
||||
|
||||
### How do I import a specific version of a module?
|
||||
|
||||
Specify the version in the URL. For example, this URL fully specifies the code
|
||||
being run: `https://unpkg.com/liltest@0.0.5/dist/liltest.js`.
|
||||
|
||||
### It seems unwieldy to import URLs everywhere.
|
||||
|
||||
> What if one of the URLs links to a subtly different version of a library?
|
||||
|
||||
> Isn't it error prone to maintain URLs everywhere in a large project?
|
||||
|
||||
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
|
||||
create a `deps.ts` file that exports the third-party code:
|
||||
|
||||
**deps.ts**
|
||||
|
||||
```ts
|
||||
export {
|
||||
assert,
|
||||
assertEquals,
|
||||
assertStrContains,
|
||||
} from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
```
|
||||
|
||||
And throughout the same project, you can import from the `deps.ts` and avoid
|
||||
having many references to the same URL:
|
||||
|
||||
```ts
|
||||
import { assertEquals, runTests, test } from "./deps.ts";
|
||||
```
|
||||
|
||||
This design circumvents a plethora of complexity spawned by package management
|
||||
software, centralized code repositories, and superfluous file formats.
|
||||
|
||||
### How can I trust a URL that may change?
|
||||
|
||||
By using a lock file (with the `--lock` command line flag), you can ensure that
|
||||
the code pulled from a URL is the same as it was during initial development. You
|
||||
can learn more about this
|
||||
[here](./linking_to_external_code/integrity_checking.md).
|
||||
|
||||
### But what if the host of the URL goes down? The source won't be available.
|
||||
|
||||
This, like the above, is a problem faced by _any_ remote dependency system.
|
||||
Relying on external servers is convenient for development but brittle in
|
||||
production. Production software should always vendor its dependencies. In Node
|
||||
this is done by checking `node_modules` into source control. In Deno this is
|
||||
done by pointing `$DENO_DIR` to some project-local directory at runtime, and
|
||||
similarly checking that into source control:
|
||||
|
||||
```shell
|
||||
# Download the dependencies.
|
||||
DENO_DIR=./deno_dir deno cache src/deps.ts
|
||||
|
||||
# Make sure the variable is set for any command which invokes the cache.
|
||||
DENO_DIR=./deno_dir deno test src
|
||||
|
||||
# Check the directory into source control.
|
||||
git add -u deno_dir
|
||||
git commit
|
||||
```
|
|
@ -1,53 +0,0 @@
|
|||
## Import maps
|
||||
|
||||
Deno supports [import maps](https://github.com/WICG/import-maps).
|
||||
|
||||
You can use import maps with the `--import-map=<FILE>` CLI flag.
|
||||
|
||||
Example:
|
||||
|
||||
**import_map.json**
|
||||
|
||||
```js
|
||||
{
|
||||
"imports": {
|
||||
"fmt/": "https://deno.land/std@$STD_VERSION/fmt/"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**color.ts**
|
||||
|
||||
```ts
|
||||
import { red } from "fmt/colors.ts";
|
||||
|
||||
console.log(red("hello world"));
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
```shell
|
||||
$ deno run --import-map=import_map.json color.ts
|
||||
```
|
||||
|
||||
To use your project root for absolute imports:
|
||||
|
||||
**import_map.json**
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"imports": {
|
||||
"/": "./",
|
||||
"./": "./"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**main.ts**
|
||||
|
||||
```ts
|
||||
import { MyUtil } from "/util.ts";
|
||||
```
|
||||
|
||||
This causes import specifiers starting with `/` to be resolved relative to the
|
||||
import map's URL or file path.
|
|
@ -1,85 +0,0 @@
|
|||
## Integrity checking & lock files
|
||||
|
||||
### Introduction
|
||||
|
||||
Let's say your module depends on remote module `https://some.url/a.ts`. When you
|
||||
compile your module for the first time `a.ts` is retrieved, compiled and cached.
|
||||
It will remain this way until you run your module on a new machine (say in
|
||||
production) or reload the cache (through `deno cache --reload` for example). But
|
||||
what happens if the content in the remote url `https://some.url/a.ts` is
|
||||
changed? This could lead to your production module running with different
|
||||
dependency code than your local module. Deno's solution to avoid this is to use
|
||||
integrity checking and lock files.
|
||||
|
||||
### Caching and lock files
|
||||
|
||||
Deno can store and check subresource integrity for modules using a small JSON
|
||||
file. Use the `--lock=lock.json` to enable and specify lock file checking. To
|
||||
update or create a lock use `--lock=lock.json --lock-write`. The
|
||||
`--lock=lock.json` tells Deno what the lock file to use is, while the
|
||||
`--lock-write` is used to output dependency hashes to the lock file
|
||||
(`--lock-write` must be used in conjunction with `--lock`).
|
||||
|
||||
A `lock.json` might look like this, storing a hash of the file against the
|
||||
dependency:
|
||||
|
||||
```json
|
||||
{
|
||||
"https://deno.land/std@$STD_VERSION/textproto/mod.ts": "3118d7a42c03c242c5a49c2ad91c8396110e14acca1324e7aaefd31a999b71a4",
|
||||
"https://deno.land/std@$STD_VERSION/io/util.ts": "ae133d310a0fdcf298cea7bc09a599c49acb616d34e148e263bcb02976f80dee",
|
||||
"https://deno.land/std@$STD_VERSION/async/delay.ts": "35957d585a6e3dd87706858fb1d6b551cb278271b03f52c5a2cb70e65e00c26a",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
A typical workflow will look like this:
|
||||
|
||||
**src/deps.ts**
|
||||
|
||||
```ts
|
||||
// Add a new dependency to "src/deps.ts", used somewhere else.
|
||||
export { xyz } from "https://unpkg.com/xyz-lib@v0.9.0/lib.ts";
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
```shell
|
||||
# Create/update the lock file "lock.json".
|
||||
deno cache --lock=lock.json --lock-write src/deps.ts
|
||||
|
||||
# Include it when committing to source control.
|
||||
git add -u lock.json
|
||||
git commit -m "feat: Add support for xyz using xyz-lib"
|
||||
git push
|
||||
```
|
||||
|
||||
Collaborator on another machine -- in a freshly cloned project tree:
|
||||
|
||||
```shell
|
||||
# Download the project's dependencies into the machine's cache, integrity
|
||||
# checking each resource.
|
||||
deno cache --reload --lock=lock.json src/deps.ts
|
||||
|
||||
# Done! You can proceed safely.
|
||||
deno test --allow-read src
|
||||
```
|
||||
|
||||
### Runtime verification
|
||||
|
||||
Like caching above, you can also use the `--lock=lock.json` option during use of
|
||||
the `deno run` sub command, validating the integrity of any locked modules
|
||||
during the run. Remember that this only validates against dependencies
|
||||
previously added to the `lock.json` file. New dependencies will be cached but
|
||||
not validated.
|
||||
|
||||
You can take this a step further as well by using the `--cached-only` flag to
|
||||
require that remote dependencies are already cached.
|
||||
|
||||
```shell
|
||||
deno run --lock=lock.json --cached-only mod.ts
|
||||
```
|
||||
|
||||
This will fail if there are any dependencies in the dependency tree for mod.ts
|
||||
which are not yet cached.
|
||||
|
||||
<!-- TODO - Add detail on dynamic imports -->
|
|
@ -1,75 +0,0 @@
|
|||
## Private modules and repositories
|
||||
|
||||
There maybe 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,
|
||||
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 in the
|
||||
format of `{token}@{hostname[:port]}`.
|
||||
|
||||
For example a single token for would look something like this:
|
||||
|
||||
```sh
|
||||
DENO_AUTH_TOKENS=a1b2c3d4e5f6@deno.land
|
||||
```
|
||||
|
||||
And multiple tokens would look like this:
|
||||
|
||||
```sh
|
||||
DENO_AUTH_TOKENS=a1b2c3d4e5f6@deno.land;f1e2d3c4b5a6@example.com:8080
|
||||
```
|
||||
|
||||
When Deno goes to fetch a remote module, where the hostname matches the hostname
|
||||
of the remote module, Deno will set the `Authorization` header of the request to
|
||||
the value of `Bearer {token}`. This allows the remote server to recognize that
|
||||
the request is an authorized request tied to a specific authenticated user, and
|
||||
provide access to the appropriate resources and 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_:
|
||||
|
||||
![Personal access tokens settings on GitHub](../images/private-pat.png)
|
||||
|
||||
You would then choose to _Generate new token_ and give your token a description
|
||||
and appropriate access:
|
||||
|
||||
![Creating a new personal access token on GitHub](../images/private-github-new-token.png)
|
||||
|
||||
And once created GitHub will display the new token a single time, the value of
|
||||
which you would want to use in the environment variable:
|
||||
|
||||
![Display of newly created token on GitHub](../images/private-github-token-display.png)
|
||||
|
||||
In order to access modules that are contained in a private repository on GitHub,
|
||||
you would want to use the generated token in the `DENO_AUTH_TOKENS` environment
|
||||
variable scoped to the `raw.githubusercontent.com` hostname. For example:
|
||||
|
||||
```sh
|
||||
DENO_AUTH_TOKENS=a1b2c3d4e5f6@raw.githubusercontent.com
|
||||
```
|
||||
|
||||
This should allow Deno to access any modules that the user who the token was
|
||||
issued for has access to.
|
||||
|
||||
When the token is incorrect, or the user does not have access to the module,
|
||||
GitHub will issue a `404 Not Found` status, instead of an unauthorized status.
|
||||
So if you are getting errors that the modules you are trying to access are not
|
||||
found on the command line, check the environment variable settings and the
|
||||
personal access token settings.
|
||||
|
||||
In addition, `deno run -L debug` should print out a debug message about the
|
||||
number of tokens that are parsed out of the environment variable. It will print
|
||||
an error message if it feels any of the tokens are malformed. It won't print any
|
||||
details about the tokens for security purposes.
|
|
@ -1,9 +0,0 @@
|
|||
## Proxies
|
||||
|
||||
Deno supports proxies for module downloads and the Web standard `fetch` API.
|
||||
|
||||
Proxy configuration is read from environmental variables: `HTTP_PROXY`,
|
||||
`HTTPS_PROXY` and `NO_PROXY`.
|
||||
|
||||
In case of Windows, if environment variables are not found Deno falls back to
|
||||
reading proxies from registry.
|
|
@ -1,33 +0,0 @@
|
|||
## Reloading modules
|
||||
|
||||
By default, a module in the cache will be reused without fetching or
|
||||
re-compiling it. Sometimes this is not desirable and you can force deno to
|
||||
refetch and recompile modules into the cache. You can invalidate your local
|
||||
`DENO_DIR` cache using the `--reload` flag of the `deno cache` subcommand. It's
|
||||
usage is described below:
|
||||
|
||||
### To reload everything
|
||||
|
||||
```bash
|
||||
deno cache --reload my_module.ts
|
||||
```
|
||||
|
||||
### To reload specific modules
|
||||
|
||||
Sometimes we want to upgrade only some modules. You can control it by passing an
|
||||
argument to a `--reload` flag.
|
||||
|
||||
To reload all \$STD_VERSION standard modules:
|
||||
|
||||
```bash
|
||||
deno cache --reload=https://deno.land/std@$STD_VERSION my_module.ts
|
||||
```
|
||||
|
||||
To reload specific modules (in this example - colors and file system copy) use a
|
||||
comma to separate URLs.
|
||||
|
||||
```bash
|
||||
deno cache --reload=https://deno.land/std@$STD_VERSION/fs/copy.ts,https://deno.land/std@$STD_VERSION/fmt/colors.ts my_module.ts
|
||||
```
|
||||
|
||||
<!-- Should this be part of examples? -->
|
|
@ -1,59 +0,0 @@
|
|||
# Using npm/Node.js code
|
||||
|
||||
While Deno is pretty powerful itself, there is a large eco-system of code in the
|
||||
[npm](https://npmjs.com/) registry, and many people will want to re-leverage
|
||||
tools, code and libraries that are built for [Node.js](https://nodejs.org/). In
|
||||
this chapter we will explore how to use it.
|
||||
|
||||
The good news, is that in many cases, it _just works_.
|
||||
|
||||
There are some foundational things to understand about differences between
|
||||
Node.js and Deno that can help in understanding what challenges might be faced:
|
||||
|
||||
- Current Node.js supports both CommonJS and ES Modules, while Deno only
|
||||
supports ES Modules. The addition of stabilized ES Modules in Node.js is
|
||||
relatively recent and most code written for Node.js is in the CommonJS format.
|
||||
- Node.js has quite a few built-in modules that can be imported and they are a
|
||||
fairly expansive set of APIs. On the other hand, Deno focuses on implementing
|
||||
web standards and where functionality goes beyond the browser, we locate APIs
|
||||
in a single global `Deno` variable/namespace. Lots of code written for Node.js
|
||||
expects/depends upon these built-in APIs to be available.
|
||||
- Node.js has a non-standards based module resolution algorithm, where you can
|
||||
import bare-specifiers (e.g. `react` or `lodash`) and Node.js will look in
|
||||
your local and global `node_modules` for a path, introspect the `package.json`
|
||||
and try to see if there is a module named the right way. Deno resolves modules
|
||||
the same way a browser does. For local files, Deno expects a full module name,
|
||||
including the extension. When dealing with remote imports, Deno expects the
|
||||
web server to do any "resolving" and provide back the media type of the code
|
||||
(see the
|
||||
[Determining the type of file](../typescript/overview.md#determining-the-type-of-file)
|
||||
for more information).
|
||||
- Node.js effectively doesn't work without a `package.json` file. Deno doesn't
|
||||
require an external meta-data file to function or resolve modules.
|
||||
- Node.js doesn't support remote HTTP imports. It expects all 3rd party code to
|
||||
be installed locally on your machine using a package manager like `npm` into
|
||||
the local or global `node_modules` folder. Deno supports remote HTTP imports
|
||||
(as well as `data` and `blob` URLs) and will go ahead and fetch the remote
|
||||
code and cache it locally, similar to the way a browser works.
|
||||
|
||||
In order to help mitigate these differences, we will further explore in this
|
||||
chapter:
|
||||
|
||||
- Using the [`std/node`](./npm_nodejs/std_node.md) modules of the Deno standard
|
||||
library to "polyfill" the built-in modules of Node.js
|
||||
- Using [CDNs](./npm_nodejs/cdns.md) to access the vast majority of npm packages
|
||||
in ways that work under Deno.
|
||||
- How [import maps](./npm_nodejs/import_maps.md) can be used to provide "bare
|
||||
specifier" imports like Node.js under Deno, without needing to use a package
|
||||
manager to install packages locally.
|
||||
- And finally, a general section of
|
||||
[frequently asked questions](./npm_nodejs/faqs.md)
|
||||
|
||||
That being said, there are some differences that cannot be overcome:
|
||||
|
||||
- Node.js has a plugin system that is incompatible with Deno, and Deno will
|
||||
never support Node.js plugins. If the Node.js code you want to use requires a
|
||||
"native" Node.js plugin, it won't work under Deno.
|
||||
- Node.js has some built in modules (e.g. like `vm`) that are effectively
|
||||
incompatible with the scope of Deno and therefore there aren't easy ways to
|
||||
provide a _polyfill_ of the functionality in Deno.
|
|
@ -1,186 +0,0 @@
|
|||
## Packages from CDNs
|
||||
|
||||
Because Deno supports remote HTTP modules, and content delivery networks (CDNs)
|
||||
can be powerful tools to transform code, the combination allows an easy way to
|
||||
access code in the npm registry via Deno, usually in a way that works with Deno
|
||||
without any further actions, and often enriched with TypeScript types. In this
|
||||
section we will explore that in detail.
|
||||
|
||||
### What about `deno.land/x/`?
|
||||
|
||||
The [`deno.land/x/`](https://deno.land/x/) is a public registry for code,
|
||||
hopefully code written specifically for Deno. It is a public registry though and
|
||||
all it does is "redirect" Deno to the location where the code exists. It doesn't
|
||||
transform the code in any way. There is a lot of great code on the registry, but
|
||||
at the same time, there is some code that just isn't well maintained (or doesn't
|
||||
work at all). If you are familiar with the npm registry, you know that as well,
|
||||
there are varying degrees of quality.
|
||||
|
||||
Because it simply serves up the original published source code, it doesn't
|
||||
really help when trying to use code that didn't specifically consider Deno when
|
||||
authored.
|
||||
|
||||
### Deno "friendly" CDNs
|
||||
|
||||
Deno friendly content delivery networks (CDNs) not only host packages from npm,
|
||||
they provide them in a way that maximizes their integration to Deno. They
|
||||
directly address some of the challenges in consuming code written for Node.js:
|
||||
|
||||
- The provide packages and modules in the ES Module format, irrespective of how
|
||||
they are published on npm.
|
||||
- They resolve all the dependencies as the modules are served, meaning that all
|
||||
the Node.js specific module resolution logic is handled by the CDN.
|
||||
- Often, they inform Deno of type definitions for a package, meaning that Deno
|
||||
can use them to type check your code and provide a better development
|
||||
experience.
|
||||
- The CDNs also "polyfill" the built-in Node.js modules, making a lot of code
|
||||
that leverages the built-in Node.js modules _just work_.
|
||||
- The CDNs deal with all the semver matching for packages that a package manager
|
||||
like `npm` would be required for a Node.js application, meaning you as a
|
||||
developer can express your 3rd party dependency versioning as part of the URL
|
||||
you use to import the package.
|
||||
|
||||
#### esm.sh
|
||||
|
||||
[esm.sh](https://esm.sh/) is a CDN that was specifically designed for Deno,
|
||||
though addressing the concerns for Deno also makes it a general purpose CDN for
|
||||
accessing npm packages as ES Module bundles. esm.sh uses
|
||||
[esbuild](https://esbuild.github.io/) to take an arbitrary npm package and
|
||||
ensure that it is consumable as an ES Module. In many cases you can just import
|
||||
the npm package into your Deno application:
|
||||
|
||||
```ts
|
||||
import React from "https://esm.sh/react";
|
||||
|
||||
export default class A extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div></div>
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
esm.sh supports the use of both specific versions of packages, as well as
|
||||
[semver](https://semver.npmjs.com/) versions of packages, so you can express
|
||||
your dependency in a similar way you would in a `package.json` file when you
|
||||
import it. For example, to get a specific version of a package:
|
||||
|
||||
```ts
|
||||
import React from "https://esm.sh/react@17.0.2";
|
||||
```
|
||||
|
||||
Or to get the latest patch release of a minor release:
|
||||
|
||||
```ts
|
||||
import React from "https://esm.sh/react@~16.13.0";
|
||||
```
|
||||
|
||||
esm.sh uses the `std/node` polyfills to replace the built-in modules in Node.js,
|
||||
meaning that code that uses those built-in modules will have the same
|
||||
limitations and caveats as those modules in `std/node`.
|
||||
|
||||
esm.sh also automatically sets a header which Deno recognizes that allows Deno
|
||||
to be able to retrieve type definitions for the package/module. See
|
||||
[Using `X-TypeScript-Types` header](../typescript/types.md#using-x-typescript-types-header)
|
||||
in this manual for more details on how this works.
|
||||
|
||||
The CDN is also a good choice for people who develop in mainland China, as the
|
||||
hosting of the CDN is specifically designed to work with "the great firewall of
|
||||
China", as well as esm.sh provides information on self hosting the CDN as well.
|
||||
|
||||
Check out the [esm.sh homepage](https://esm.sh/) for more detailed information
|
||||
on how the CDN can be used and what features it has.
|
||||
|
||||
#### Skypack
|
||||
|
||||
[Skypack.dev](https://www.skypack.dev/) is designed to make development overall
|
||||
easier by not requiring packages to be installed locally, even for Node.js
|
||||
development, and to make it easy to create web and Deno applications that
|
||||
leverage code from the npm registry.
|
||||
|
||||
Skypack has a great way of discovering packages in the npm registry, by
|
||||
providing a lot of contextual information about the package, as well as a
|
||||
"scoring" system to try to help determine if the package follows best-practices.
|
||||
|
||||
Skypack detects Deno's user agent when requests for modules are received and
|
||||
ensures the code served up is tailored to meet the needs of Deno. The easiest
|
||||
way to load a package is to use the
|
||||
[lookup URL](https://docs.skypack.dev/skypack-cdn/api-reference/lookup-urls) for
|
||||
the package:
|
||||
|
||||
```ts
|
||||
import React from "https://cdn.skypack.dev/react";
|
||||
|
||||
export default class A extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div></div>
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Lookup URLs can also contain the [semver](https://semver.npmjs.com/) version in
|
||||
the URL:
|
||||
|
||||
```ts
|
||||
import React from "https://cdn.skypack.dev/react@~16.13.0";
|
||||
```
|
||||
|
||||
By default, Skypack does not set the types header on packages. In order to have
|
||||
the types header set, which is automatically recognized by Deno, you have to
|
||||
append `?dts` to the URL for that package:
|
||||
|
||||
```ts
|
||||
import { pathToRegexp } from "https://cdn.skypack.dev/path-to-regexp?dts";
|
||||
|
||||
const re = pathToRegexp("/path/:id");
|
||||
```
|
||||
|
||||
See
|
||||
[Using `X-TypeScript-Types` header](../typescript/types.md#using-x-typescript-types-header)
|
||||
in this manual for more details on how this works.
|
||||
|
||||
Skypack docs have a
|
||||
[specific page on usage with Deno](https://docs.skypack.dev/skypack-cdn/code/deno)
|
||||
for more information.
|
||||
|
||||
### Other CDNs
|
||||
|
||||
There are a couple of other CDNs worth mentioning.
|
||||
|
||||
#### UNPKG
|
||||
|
||||
[UNPKG](https://unpkg.com/) is the most well known CDN for npm packages. For
|
||||
packages that include an ES Module distribution for things like the browsers,
|
||||
many of them can be used directly off of UNPKG. That being said, everything
|
||||
available on UNPKG is available on more Deno friendly CDNs.
|
||||
|
||||
#### JSPM
|
||||
|
||||
The [jspm.io](https://jspm.io) CDN is specifically designed to provide npm and
|
||||
other registry packages as ES Modules in a way that works well with import maps.
|
||||
While it doesn't currently cater to Deno, the fact that Deno can utilize import
|
||||
maps, allows you to use the [JSPM.io generator](https://generator.jspm.io/) to
|
||||
generate an import-map of all the packages you want to use and have them served
|
||||
up from the CDN.
|
||||
|
||||
### Considerations
|
||||
|
||||
While CDNs can make it easy to allow Deno to consume packages and modules from
|
||||
the npm registry, there can still be some things to consider:
|
||||
|
||||
- Deno does not (and will not) support Node.js plugins. If the package requires
|
||||
a native plugin, it won't work under Deno.
|
||||
- Dependency management can always be a bit of a challenge and a CDN can make it
|
||||
a bit more obfuscated what dependencies are there. You can always use
|
||||
`deno info` with the module or URL to get a full breakdown of how Deno
|
||||
resolves all the code.
|
||||
- While the Deno friendly CDNs try their best to serve up types with the code
|
||||
for consumption with Deno, lots of types for packages conflict with other
|
||||
packages and/or don't consider Deno, which means you can often get strange
|
||||
diagnostic message when type checking code imported from these CDNs, though
|
||||
skipping type checking will result in the code working perfectly fine. This is
|
||||
a fairly complex topic and is covered in the
|
||||
[Types and type declarations](../typescript/types.md) section of the manual.
|
|
@ -1,55 +0,0 @@
|
|||
## Frequently asked questions
|
||||
|
||||
### Getting errors when type checking like `cannot find namespace NodeJS`
|
||||
|
||||
One of the modules you are using has type definitions that depend upon the
|
||||
NodeJS global namespace, but those types don't include the NodeJS global
|
||||
namespace in their types.
|
||||
|
||||
The quickest fix is to skip type checking. You can do this by using the
|
||||
`--no-check` flag.
|
||||
|
||||
Skipping type checking might not be acceptable though. You could try to load the
|
||||
Node.js types yourself. For example from UNPKG it would look something like
|
||||
this:
|
||||
|
||||
```ts
|
||||
import type {} from "https://unpkg.com/@types/node/index.d.ts";
|
||||
```
|
||||
|
||||
Or from esm.sh:
|
||||
|
||||
```ts
|
||||
import type {} from "https://esm.sh/@types/node/index.d.ts";
|
||||
```
|
||||
|
||||
Or from Skypack:
|
||||
|
||||
```ts
|
||||
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
|
||||
declare global {
|
||||
namespace NodeJS {
|
||||
type ProcessEnv = Record<string, string>;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Getting type errors like cannot find `document` or `HTMLElement`
|
||||
|
||||
The library you are using has dependencies on the DOM. This is common for
|
||||
packages that are designed to run in a browser as well as server-side. By
|
||||
default, Deno only includes the libraries that are directly supported. Assuming
|
||||
the package properly identifies what environment it is running in at runtime it
|
||||
is "safe" to use the DOM libraries to type check the code. For more information
|
||||
on this, check out the
|
||||
[Targeting Deno and the Browser](../typescript/configuration.md#targeting-deno-and-the-browser)
|
||||
section of the manual.
|
|
@ -1,112 +0,0 @@
|
|||
## Using import maps
|
||||
|
||||
Deno supports [import maps](../linking_to_external_code/import_maps.md) which
|
||||
allow you to supply Deno with information about how to resolve modules that
|
||||
overrides the default behavior. Import maps are a web platform standard that is
|
||||
increasingly being included natively in browsers. They are specifically useful
|
||||
with adapting Node.js code to work well with Deno, as you can use import maps to
|
||||
map "bare" specifiers to a specific module.
|
||||
|
||||
When coupled with Deno friendly [CDNs](./cdns.md) import maps can be a powerful
|
||||
tool in managing code and dependencies without need of a package management
|
||||
tool.
|
||||
|
||||
### Bare and extension-less specifiers
|
||||
|
||||
Deno will only load a fully qualified module, including the extension. The
|
||||
import specifier needs to either be relative or absolute. Specifiers that are
|
||||
neither relative or absolute are often called "bare" specifiers. For example
|
||||
`"./lodash/index.js"` is a relative specifier and
|
||||
`https://cdn.skypack.dev/lodash` is an absolute specifier. Where is `"lodash"`
|
||||
would be a bare specifier.
|
||||
|
||||
Also Deno requires that for local modules, the module to load is fully
|
||||
resolve-able. When an extension is not present, Deno would have to "guess" what
|
||||
the author intended to be loaded. For example does `"./lodash"` mean
|
||||
`./lodash.js`, `./lodash.ts`, `./lodash.tsx`, `./lodash.jsx`,
|
||||
`./lodash/index.js`, `./lodash/index.ts`, `./lodash/index.jsx`, or
|
||||
`./lodash/index.tsx`?
|
||||
|
||||
When dealing with remote modules, Deno allows the CDN/web server define whatever
|
||||
semantics around resolution the server wants to define. It just treats a URL,
|
||||
including its query string, as a "unique" module that can be loaded. It expects
|
||||
the CDN/web server to provide it with a valid media/content type to instruct
|
||||
Deno how to handle the file. More information on how media types impact how Deno
|
||||
handles modules can be found in the
|
||||
[Determining the type of file](../typescript/overview.md#determining-the-type-of-file)
|
||||
section of the manual.
|
||||
|
||||
Node.js does have defined semantics for resolving specifiers, but they are
|
||||
complex, assume unfettered access to the local file system to query it. Deno has
|
||||
chosen not to go down that path.
|
||||
|
||||
But, import maps can be used to provide some of the ease of the developer
|
||||
experience if you wish to use bare specifiers. For example, if we want to do the
|
||||
following in our code:
|
||||
|
||||
```ts
|
||||
import lodash from "lodash";
|
||||
```
|
||||
|
||||
We can accomplish this using an import map, and we don't even have to install
|
||||
the `lodash` package locally. We would want to create a JSON file (for example
|
||||
**import_map.json**) with the following:
|
||||
|
||||
```json
|
||||
{
|
||||
"imports": {
|
||||
"lodash": "https://cdn.skypack.dev/lodash"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And we would run our program like:
|
||||
|
||||
```
|
||||
> deno run --import-map ./import_map.json example.ts
|
||||
```
|
||||
|
||||
If you wanted to manage the versions in the import map, you could do this as
|
||||
well. For example if you were using Skypack CDN, you can used a
|
||||
[pinned URL](https://docs.skypack.dev/skypack-cdn/api-reference/pinned-urls-optimized)
|
||||
for the dependency in your import map. For example, to pin to lodash version
|
||||
4.17.21 (and minified production ready version), you would do this:
|
||||
|
||||
```json
|
||||
{
|
||||
"imports": {
|
||||
"lodash": "https://cdn.skypack.dev/pin/lodash@v4.17.21-K6GEbP02mWFnLA45zAmi/mode=imports,min/optimized/lodash.js"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Overriding imports
|
||||
|
||||
The other situation where import maps can be very useful is the situation where
|
||||
you have tried your best to make something work, but have failed. For example
|
||||
you are using an npm package which has a dependency on some code that just
|
||||
doesn't work under Deno, and you want to substitute another module that
|
||||
"polyfills" the incompatible APIs.
|
||||
|
||||
For example, let's say we have a package that is using a version of the built in
|
||||
`"fs"` module that we have a local module we want to replace it with when it
|
||||
tries to import it, but we want other code we are loading to use the standard
|
||||
library replacement module for `"fs"`. We would want to create an import map
|
||||
that looked something like this:
|
||||
|
||||
```ts
|
||||
{
|
||||
"imports": {
|
||||
"fs": "https://deno.land/std@$STD_VERSION/node/fs.ts"
|
||||
},
|
||||
"scopes": {
|
||||
"https://deno.land/x/example": {
|
||||
"fs": "./patched/fs.ts"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Import maps can be very powerful, check out the official
|
||||
[standards README](https://github.com/WICG/import-maps#the-import-map) for more
|
||||
information.
|
|
@ -1,100 +0,0 @@
|
|||
## The `std/node` library
|
||||
|
||||
The `std/node` part of the Deno standard library is a Node.js compatibility
|
||||
layer. It's primary focus is providing "polyfills" for Node.js's
|
||||
[built-in modules](https://github.com/denoland/deno_std/tree/main/node#supported-builtins).
|
||||
It also provides a mechanism for loading CommonJS modules into Deno.
|
||||
|
||||
The library is most useful when trying to use your own or private code that was
|
||||
written for Node.js. If you are trying to consume public npm packages, you are
|
||||
likely to get a better result using a [CDN](./cdns.md).
|
||||
|
||||
### Node.js built-in modules
|
||||
|
||||
The standard library provides several "replacement" modules for Node.js built-in
|
||||
modules. These either replicate the functionality of the built-in or they call
|
||||
the Deno native APIs, returning an interface that is compatible with Node.js.
|
||||
|
||||
The standard library provides modules for the the following built-ins:
|
||||
|
||||
- [`assert`](https://doc.deno.land/https/deno.land/std/node/assert.ts)
|
||||
(_partly_)
|
||||
- [`buffer`](https://doc.deno.land/https/deno.land/std/node/buffer.ts)
|
||||
- [`child_process`](https://doc.deno.land/https/deno.land/std/node/child_process.ts)
|
||||
(_partly_)
|
||||
- [`console`](https://doc.deno.land/https/deno.land/std/node/console.ts)
|
||||
(_partly_)
|
||||
- [`constants`](https://doc.deno.land/https/deno.land/std/node/constants.ts)
|
||||
(_partly_)
|
||||
- [`crypto`](https://doc.deno.land/https/deno.land/std/node/crypto.ts)
|
||||
(_partly_)
|
||||
- [`events`](https://doc.deno.land/https/deno.land/std/node/events.ts)
|
||||
- [`fs`](https://doc.deno.land/https/deno.land/std/node/fs.ts) (_partly_)
|
||||
- [`module`](https://doc.deno.land/https/deno.land/std/node/module.ts)
|
||||
- [`os`](https://doc.deno.land/https/deno.land/std/node/os.ts) (_partly_)
|
||||
- [`path`](https://doc.deno.land/https/deno.land/std/node/path.ts)
|
||||
- [`process`](https://doc.deno.land/https/deno.land/std/node/process.ts)
|
||||
(_partly_)
|
||||
- [`querystring`](https://doc.deno.land/https/deno.land/std/node/querystring.ts)
|
||||
- [`stream`](https://doc.deno.land/https/deno.land/std/node/stream.ts)
|
||||
- [`string_decoder`](https://doc.deno.land/https/deno.land/std/node/string_decoder.ts)
|
||||
- [`timers`](https://doc.deno.land/https/deno.land/std/node/timers.ts)
|
||||
- [`tty`](https://doc.deno.land/https/deno.land/std/node/tty.ts) (_partly_)
|
||||
- [`url`](https://doc.deno.land/https/deno.land/std/node/url.ts)
|
||||
- [`util`](https://doc.deno.land/https/deno.land/std/node/util.ts) (_partly_)
|
||||
|
||||
In addition, there is the
|
||||
[`std/node/global.ts`](https://doc.deno.land/https/deno.land/std/node/global.ts)
|
||||
module which provides some of the Node.js globals like `global`, `process`, and
|
||||
`Buffer`.
|
||||
|
||||
If you want documentation for any of the modules, you can simply type `deno doc`
|
||||
and the URL of the module in your terminal:
|
||||
|
||||
```
|
||||
> deno doc https://deno.land/std/assert.ts
|
||||
```
|
||||
|
||||
### Loading CommonJS modules
|
||||
|
||||
Deno only supports natively loading ES Modules, but a lot of Node.js code is
|
||||
still written in the CommonJS format. As mentioned above, for public npm
|
||||
packages, it is often better to use a CDN to transpile CommonJS modules to ES
|
||||
Modules for consumption by Deno. Not only do you get reliable conversion plus
|
||||
all the dependency resolution and management without requiring a package manager
|
||||
to install the packages on your local machine, you get the advantages of being
|
||||
able to share your code easier without requiring other users to setup some of
|
||||
the Node.js infrastructure to consume your code with Node.js.
|
||||
|
||||
That being said, the built-in Node.js module `"module"` provides a function
|
||||
named `createRequire()` which allows you to create a Node.js compatible
|
||||
`require()` function which can be used to load CommonJS modules, as well as use
|
||||
the same resolution logic that Node.js uses when trying to load a module.
|
||||
`createRequire()` will also install the Node.js globals for you.
|
||||
|
||||
Example usage would look like this:
|
||||
|
||||
```ts
|
||||
import { createRequire } from "https://deno.land/std@$STD_VERSION/node/module.ts";
|
||||
|
||||
// import.meta.url will be the location of "this" module (like `__filename` in
|
||||
// Node.js), and then serve as the root for your "package", where the
|
||||
// `package.json` is expected to be, and where the `node_modules` will be used
|
||||
// for resolution of packages.
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
// Loads the built-in module Deno "replacement":
|
||||
const path = require("path");
|
||||
|
||||
// Loads a CommonJS module (without specifying the extension):
|
||||
const cjsModule = require("./my_mod");
|
||||
|
||||
// Uses Node.js resolution in `node_modules` to load the package/module. The
|
||||
// package would need to be installed locally via a package management tool
|
||||
// like npm:
|
||||
const leftPad = require("left-pad");
|
||||
```
|
||||
|
||||
When modules are loaded via the created `require()`, they are executed in a
|
||||
context which is similar to a Node.js context, which means that a lot of code
|
||||
written targeting Node.js will work.
|
|
@ -1,25 +0,0 @@
|
|||
# Runtime
|
||||
|
||||
Documentation for all runtime functions (Web APIs + `Deno` global) can be found
|
||||
on [`doc.deno.land`](https://doc.deno.land/builtin/stable).
|
||||
|
||||
## Web Platform APIs
|
||||
|
||||
For APIs where a web standard already exists, like `fetch` for HTTP requests,
|
||||
Deno uses these rather than inventing a new proprietary API.
|
||||
|
||||
For more details, view the chapter on
|
||||
[Web Platform APIs](./runtime/web_platform_apis.md).
|
||||
|
||||
## `Deno` global
|
||||
|
||||
All APIs that are not web standard are contained in the global `Deno` namespace.
|
||||
It has the APIs for reading from files, opening TCP sockets, serving HTTP, and
|
||||
executing subprocesses, etc.
|
||||
|
||||
The TypeScript definitions for the Deno namespaces can be found in the
|
||||
[`lib.deno.ns.d.ts`](https://github.com/denoland/deno/blob/$CLI_VERSION/cli/dts/lib.deno.ns.d.ts)
|
||||
file.
|
||||
|
||||
The documentation for all of the Deno specific APIs can be found on
|
||||
[doc.deno.land](https://doc.deno.land/https/raw.githubusercontent.com/denoland/deno/main/cli/dts/lib.deno.ns.d.ts).
|
|
@ -1,4 +0,0 @@
|
|||
## Compiler APIs
|
||||
|
||||
> ℹ️ This section has been moved to
|
||||
> [TypeScript Runtime APIs](../typescript/runtime.md).
|
|
@ -1,258 +0,0 @@
|
|||
## HTTP Server APIs
|
||||
|
||||
As of Deno 1.9 and later, _native_ HTTP server APIs were introduced which allow
|
||||
users to create robust and performant web servers in Deno.
|
||||
|
||||
The API tries to leverage as much of the web standards as is possible as well as
|
||||
tries to be simple and straight forward.
|
||||
|
||||
> ℹ️ The APIs are currently unstable, meaning they can change in the future in
|
||||
> breaking ways and should be carefully considered before using in production
|
||||
> code. They require the `--unstable` flag to make them available.
|
||||
|
||||
### Listening for a connection
|
||||
|
||||
In order to accept requests, first you need to listen for a connection on a
|
||||
network port. To do this in Deno, you use `Deno.listen()`:
|
||||
|
||||
```ts
|
||||
const server = Deno.listen({ port: 8080 });
|
||||
```
|
||||
|
||||
> ℹ️ When supplying a port, Deno assumes you are going to listen on a TCP socket
|
||||
> as well as bind to the localhost. You can specify `transport: "tcp"` to be
|
||||
> more explicit as well as provide an IP address or hostname in the `hostname`
|
||||
> property as well.
|
||||
|
||||
If there is an issue with opening the network port, `Deno.listen()` will throw,
|
||||
so often in a server sense, you will want to wrap it in the `try ... catch`
|
||||
block in order to handle exceptions, like the port already being in use.
|
||||
|
||||
You can also listen for a TLS connection (e.g. HTTPS) using `Deno.listenTls()`:
|
||||
|
||||
```ts
|
||||
const server = Deno.listenTls({
|
||||
port: 8443,
|
||||
certFile: "localhost.crt",
|
||||
keyFile: "localhost.key",
|
||||
alpnProtocols: ["h2", "http/1.1"],
|
||||
});
|
||||
```
|
||||
|
||||
The `certFile` and `keyFile` options are required and point to the appropriate
|
||||
certificate and key files for the server. They are relative to the CWD for Deno.
|
||||
The `alpnProtocols` property is optional, but if you want to be able to support
|
||||
HTTP/2 on the server, you add the protocols here, as the protocol negotiation
|
||||
happens during the TLS negotiation with the client and server.
|
||||
|
||||
> ℹ️ Generating SSL certificates is outside of the scope of this documentation.
|
||||
> There are many resources on the web which address this.
|
||||
|
||||
### Handling connections
|
||||
|
||||
Once we are listening for a connection, we need to handle the connection. The
|
||||
return value of `Deno.listen()` or `Deno.listenTls()` is a `Deno.Listener` which
|
||||
is an async iterable which yields up `Deno.Conn` connections as well as provide
|
||||
a couple methods for handling connections.
|
||||
|
||||
To use it as an async iterable we would do something like this:
|
||||
|
||||
```ts
|
||||
const server = Deno.listen({ port: 8080 });
|
||||
|
||||
for await (const conn of server) {
|
||||
// ...handle the connection...
|
||||
}
|
||||
```
|
||||
|
||||
Every connection made would yielded up a `Deno.Conn` assigned to `conn`. Then
|
||||
further processing can be applied to the connection.
|
||||
|
||||
There is also the `.accept()` method on the listener which can be used:
|
||||
|
||||
```ts
|
||||
const server = Deno.listen({ port: 8080 });
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
const conn = await server.accept();
|
||||
// ... handle the connection ...
|
||||
} catch (err) {
|
||||
// The listener has closed
|
||||
break;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Whether using the async iterator or the `.accept()` method, exceptions can be
|
||||
thrown and robust production code should handle these using `try ... catch`
|
||||
blocks. Especially when it comes to accepting TLS connections, there can be many
|
||||
conditions, like invalid or unknown certificates which can be surfaced on the
|
||||
listener and might need handling in the user code.
|
||||
|
||||
A listener also has a `.close()` method which can be used to close the listener.
|
||||
|
||||
### Serving HTTP
|
||||
|
||||
Once a connection is accepted, you can use `Deno.serveHttp()` to handle HTTP
|
||||
requests and responses on the connection. `Deno.serveHttp()` returns a
|
||||
`Deno.HttpConn`. A `Deno.HttpConn` is like a `Deno.Listener` in that requests
|
||||
the connection receives from the client are asynchronously yielded up as a
|
||||
`Deno.RequestEvent`.
|
||||
|
||||
To deal with HTTP requests as async iterable it would look something like this:
|
||||
|
||||
```ts
|
||||
const server = Deno.listen({ port: 8080 });
|
||||
|
||||
for await (const conn of server) {
|
||||
(async () => {
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
for await (const requestEvent of httpConn) {
|
||||
// ... handle requestEvent ...
|
||||
}
|
||||
})();
|
||||
}
|
||||
```
|
||||
|
||||
The `Deno.HttpConn` also has the method `.nextRequest()` which can be used to
|
||||
await the next request. It would look something like this:
|
||||
|
||||
```ts
|
||||
const server = Deno.listen({ port: 8080 });
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
const conn = await server.accept();
|
||||
(async () => {
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
while (true) {
|
||||
try {
|
||||
const requestEvent = await httpConn.nextRequest();
|
||||
// ... handle requestEvent ...
|
||||
} catch (err) {
|
||||
// the connection has finished
|
||||
break;
|
||||
}
|
||||
}
|
||||
})();
|
||||
} catch (err) {
|
||||
// The listener has closed
|
||||
break;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note that in both cases we are using an IIFE to create an inner function to deal
|
||||
with each connection. If we awaited the HTTP requests in the same function scope
|
||||
as the one we were receiving the connections, we would be blocking accepting
|
||||
additional connections, which would make it seem that our server was "frozen".
|
||||
In practice, it might make more sense to have a separate function all together:
|
||||
|
||||
```ts
|
||||
async function handle(conn: Deno.Conn) {
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
for await (const requestEvent of httpConn) {
|
||||
// ... handle requestEvent
|
||||
}
|
||||
}
|
||||
|
||||
const server = Deno.listen({ port: 8080 });
|
||||
|
||||
for await (const conn of server) {
|
||||
handle(conn);
|
||||
}
|
||||
```
|
||||
|
||||
In the examples from this point on, we will focus on what would occur within an
|
||||
example `handle()` function and remove the listening and connection
|
||||
"boilerplate".
|
||||
|
||||
### HTTP Requests and Responses
|
||||
|
||||
HTTP requests and responses in Deno are essentially the inverse of web standard
|
||||
[Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). The
|
||||
Deno HTTP Server API and the Fetch API leverage the
|
||||
[`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) and
|
||||
[`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) object
|
||||
classes. So if you are familiar with the Fetch API you just need to flip them
|
||||
around in your mind and now it is a server API.
|
||||
|
||||
As mentioned above, a `Deno.HttpConn` asynchronously yields up
|
||||
`Deno.RequestEvent`s. These request events contain a `.request` property and a
|
||||
`.respondWith()` method.
|
||||
|
||||
The `.request` property is an instance of the `Request` class with the
|
||||
information about the request. For example, if we wanted to know what URL path
|
||||
was being requested, we would do something like this:
|
||||
|
||||
```ts
|
||||
async function handle(conn: Deno.Conn) {
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
for await (const requestEvent of httpConn) {
|
||||
const url = new URL(requestEvent.request.url);
|
||||
console.log(`path: ${url.path}`);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `.respondWith()` method is how we complete a request. The method takes
|
||||
either a `Response` object or a `Promise` which resolves with a `Response`
|
||||
object. Responding with a basic "hello world" would look like this:
|
||||
|
||||
```ts
|
||||
async function handle(conn: Deno.Conn) {
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
for await (const requestEvent of httpConn) {
|
||||
await requestEvent.respondWith(
|
||||
new Response("hello world", {
|
||||
status: 200,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note that we awaited the `.respondWith()` method. It isn't required, but in
|
||||
practice any errors in processing the response will cause the promise returned
|
||||
from the method to be rejected, like if the client disconnected before all the
|
||||
response could be sent. While there may not be anything your application needs
|
||||
to do, not handling the rejection will cause an "unhandled rejection" to occur
|
||||
which will terminate the Deno process, which isn't so good for a server. In
|
||||
addition, you might want to await the promise returned in order to determine
|
||||
when to do any cleanup from for the request/response cycle.
|
||||
|
||||
The web standard `Response` object is pretty powerful, allowing easy creation of
|
||||
complex and rich responses to a client, and Deno strives to provide a `Response`
|
||||
object that as closely matches the web standard as possible, so if you are
|
||||
wondering how to send a particular response, checkout out the documentation for
|
||||
the web standard
|
||||
[`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response).
|
||||
|
||||
### HTTP/2 Support
|
||||
|
||||
HTTP/2 support is effectively transparent within the Deno runtime. Typically
|
||||
HTTP/2 is negotiated between a client and a server during the TLS connection
|
||||
setup via
|
||||
[ALPN](https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation). To
|
||||
enable this, you need to provide the protocols you want to support when you
|
||||
start listening via the `alpnProtocols` property. This will enable the
|
||||
negotiation to occur when the connection is made. For example:
|
||||
|
||||
```ts
|
||||
const server = Deno.listenTls({
|
||||
port: 8443,
|
||||
certFile: "localhost.crt",
|
||||
keyFile: "localhost.key",
|
||||
alpnProtocols: ["h2", "http/1.1"],
|
||||
});
|
||||
```
|
||||
|
||||
The protocols are provided in order of preference. In practice, the only two
|
||||
protocols that are supported currently are HTTP/2 and HTTP/1.1 which are
|
||||
expressed as `h2` and `http/1.1`.
|
||||
|
||||
Currently Deno does not support upgrading a plain-text HTTP/1.1 connection to an
|
||||
HTTP/2 cleartext connection via the `Upgrade` header (see:
|
||||
[#10275](https://github.com/denoland/deno/issues/10275)), so therefore HTTP/2
|
||||
support is only available via a TLS/HTTPS connection.
|
|
@ -1,76 +0,0 @@
|
|||
## Location API
|
||||
|
||||
Deno supports the
|
||||
[`location`](https://developer.mozilla.org/en-US/docs/Web/API/Window/location)
|
||||
global from the web. Please read on.
|
||||
|
||||
### Location flag
|
||||
|
||||
There is no "web page" whose URL we can use for a location in a Deno process. We
|
||||
instead allow users to emulate a document location by specifying one on the CLI
|
||||
using the `--location` flag. It can be a `http` or `https` URL.
|
||||
|
||||
```ts
|
||||
// deno run --location https://example.com/path main.ts
|
||||
|
||||
console.log(location.href);
|
||||
// "https://example.com/path"
|
||||
```
|
||||
|
||||
You must pass `--location <href>` for this to work. If you don't, any access to
|
||||
the `location` global will throw an error.
|
||||
|
||||
```ts
|
||||
// deno run main.ts
|
||||
|
||||
console.log(location.href);
|
||||
// error: Uncaught ReferenceError: Access to "location", run again with --location <href>.
|
||||
```
|
||||
|
||||
Setting `location` or any of its fields will normally cause navigation in
|
||||
browsers. This is not applicable in Deno, so it will throw in this situation.
|
||||
|
||||
```ts
|
||||
// deno run --location https://example.com/path main.ts
|
||||
|
||||
location.pathname = "./foo";
|
||||
// error: Uncaught NotSupportedError: Cannot set "location.pathname".
|
||||
```
|
||||
|
||||
### Extended usage
|
||||
|
||||
On the web, resource resolution (excluding modules) typically uses the value of
|
||||
`location.href` as the root on which to base any relative URLs. This affects
|
||||
some web APIs adopted by Deno.
|
||||
|
||||
#### Fetch API
|
||||
|
||||
```ts
|
||||
// deno run --location https://api.github.com/ --allow-net main.ts
|
||||
|
||||
const response = await fetch("./orgs/denoland");
|
||||
// Fetches "https://api.github.com/orgs/denoland".
|
||||
```
|
||||
|
||||
The `fetch()` call above would throw if the `--location` flag was not passed,
|
||||
since there is no web-analogous location to base it onto.
|
||||
|
||||
#### Worker modules
|
||||
|
||||
```ts
|
||||
// deno run --location https://example.com/index.html --allow-net main.ts
|
||||
|
||||
const worker = new Worker("./workers/hello.ts", { type: "module" });
|
||||
// Fetches worker module at "https://example.com/workers/hello.ts".
|
||||
```
|
||||
|
||||
### Only use if necessary
|
||||
|
||||
For the above use cases, it is preferable to pass URLs in full rather than
|
||||
relying on `--location`. You can manually base a relative URL using the `URL`
|
||||
constructor if needed.
|
||||
|
||||
The `--location` flag is intended for those who have some specific purpose in
|
||||
mind for emulating a document location and are aware that this will only work at
|
||||
application-level. However, you may also use it to silence errors from a
|
||||
dependency which is frivolously accessing the `location` global.
|
|
@ -1,186 +0,0 @@
|
|||
## Permission APIs
|
||||
|
||||
Permissions are granted from the CLI when running the `deno` command. User code
|
||||
will often assume its own set of required permissions, but there is no guarantee
|
||||
during execution that the set of _granted_ permissions will align with this.
|
||||
|
||||
In some cases, ensuring a fault-tolerant program requires a way to interact with
|
||||
the permission system at runtime.
|
||||
|
||||
### Permission descriptors
|
||||
|
||||
On the CLI, read permission for `/foo/bar` is represented as
|
||||
`--allow-read=/foo/bar`. In runtime JS, it is represented as the following:
|
||||
|
||||
```ts
|
||||
const desc = { name: "read", path: "/foo/bar" } as const;
|
||||
```
|
||||
|
||||
Other examples:
|
||||
|
||||
```ts
|
||||
// Global write permission.
|
||||
const desc1 = { name: "write" } as const;
|
||||
|
||||
// Write permission to `$PWD/foo/bar`.
|
||||
const desc2 = { name: "write", path: "foo/bar" } as const;
|
||||
|
||||
// Global net permission.
|
||||
const desc3 = { name: "net" } as const;
|
||||
|
||||
// Net permission to 127.0.0.1:8000.
|
||||
const desc4 = { name: "net", host: "127.0.0.1:8000" } as const;
|
||||
|
||||
// High-resolution time permission.
|
||||
const desc5 = { name: "hrtime" } as const;
|
||||
```
|
||||
|
||||
### Query permissions
|
||||
|
||||
Check, by descriptor, if a permission is granted or not.
|
||||
|
||||
```ts
|
||||
// deno run --allow-read=/foo main.ts
|
||||
|
||||
const desc1 = { name: "read", path: "/foo" } as const;
|
||||
console.log(await Deno.permissions.query(desc1));
|
||||
// PermissionStatus { state: "granted" }
|
||||
|
||||
const desc2 = { name: "read", path: "/foo/bar" } as const;
|
||||
console.log(await Deno.permissions.query(desc2));
|
||||
// PermissionStatus { state: "granted" }
|
||||
|
||||
const desc3 = { name: "read", path: "/bar" } as const;
|
||||
console.log(await Deno.permissions.query(desc3));
|
||||
// PermissionStatus { state: "prompt" }
|
||||
```
|
||||
|
||||
### Permission states
|
||||
|
||||
A permission state can be either "granted", "prompt" or "denied". Permissions
|
||||
which have been granted from the CLI will query to `{ state: "granted" }`. Those
|
||||
which have not been granted query to `{ state: "prompt" }` by default, while
|
||||
`{ state: "denied" }` reserved for those which have been explicitly refused.
|
||||
This will come up in [Request permissions](#request-permissions).
|
||||
|
||||
### Permission strength
|
||||
|
||||
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.
|
||||
|
||||
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`.
|
||||
|
||||
More examples:
|
||||
|
||||
```ts
|
||||
const desc1 = { name: "write" } as const;
|
||||
// is stronger than
|
||||
const desc2 = { name: "write", path: "/foo" } as const;
|
||||
|
||||
const desc3 = { name: "net", host: "127.0.0.1" } as const;
|
||||
// is stronger than
|
||||
const desc4 = { name: "net", host: "127.0.0.1:8000" } as const;
|
||||
```
|
||||
|
||||
### Request permissions
|
||||
|
||||
Request an ungranted permission from the user via CLI prompt.
|
||||
|
||||
```ts
|
||||
// deno run main.ts
|
||||
|
||||
const desc1 = { name: "read", path: "/foo" } as const;
|
||||
const status1 = await Deno.permissions.request(desc1);
|
||||
// ⚠️ Deno requests read access to "/foo". Grant? [g/d (g = grant, d = deny)] g
|
||||
console.log(status1);
|
||||
// PermissionStatus { state: "granted" }
|
||||
|
||||
const desc2 = { name: "read", path: "/bar" } as const;
|
||||
const status2 = await Deno.permissions.request(desc2);
|
||||
// ⚠️ Deno requests read access to "/bar". Grant? [g/d (g = grant, d = deny)] d
|
||||
console.log(status2);
|
||||
// PermissionStatus { state: "denied" }
|
||||
```
|
||||
|
||||
If the current permission state is "prompt", a prompt will appear on the user's
|
||||
terminal asking them if they would like to grant the request. The request for
|
||||
`desc1` was granted so its new status is returned and execution will continue as
|
||||
if `--allow-read=/foo` was specified on the CLI. The request for `desc2` was
|
||||
denied so its permission state is downgraded from "prompt" to "denied".
|
||||
|
||||
If the current permission state is already either "granted" or "denied", the
|
||||
request will behave like a query and just return the current status. This
|
||||
prevents prompts both for already granted permissions and previously denied
|
||||
requests.
|
||||
|
||||
### Revoke permissions
|
||||
|
||||
Downgrade a permission from "granted" to "prompt".
|
||||
|
||||
```ts
|
||||
// deno run --allow-read=/foo main.ts
|
||||
|
||||
const desc = { name: "read", path: "/foo" } as const;
|
||||
console.log(await Deno.permissions.revoke(desc));
|
||||
// PermissionStatus { state: "prompt" }
|
||||
```
|
||||
|
||||
However, what happens when you try to revoke a permission which is _partial_ to
|
||||
one granted on the CLI?
|
||||
|
||||
```ts
|
||||
// deno run --allow-read=/foo main.ts
|
||||
|
||||
const desc = { name: "read", path: "/foo/bar" } as const;
|
||||
console.log(await Deno.permissions.revoke(desc));
|
||||
// PermissionStatus { state: "granted" }
|
||||
```
|
||||
|
||||
It was not revoked.
|
||||
|
||||
To understand this behaviour, imagine that Deno stores an internal set of
|
||||
_explicitly granted permission descriptors_. Specifying `--allow-read=/foo,/bar`
|
||||
on the CLI initializes this set to:
|
||||
|
||||
```ts
|
||||
[
|
||||
{ name: "read", path: "/foo" },
|
||||
{ name: "read", path: "/bar" },
|
||||
];
|
||||
```
|
||||
|
||||
Granting a runtime request for `{ name: "write", path: "/foo" }` updates the set
|
||||
to:
|
||||
|
||||
```ts
|
||||
[
|
||||
{ name: "read", path: "/foo" },
|
||||
{ name: "read", path: "/bar" },
|
||||
{ name: "write", path: "/foo" },
|
||||
];
|
||||
```
|
||||
|
||||
Deno's permission revocation algorithm works by removing every element from this
|
||||
set which the argument permission descriptor is _stronger than_. So to ensure
|
||||
`desc` is not longer granted, pass an argument descriptor _stronger than_
|
||||
whichever _explicitly granted permission descriptor_ is _stronger than_ `desc`.
|
||||
|
||||
```ts
|
||||
// deno run --allow-read=/foo main.ts
|
||||
|
||||
const desc = { name: "read", path: "/foo/bar" } as const;
|
||||
console.log(await Deno.permissions.revoke(desc)); // Insufficient.
|
||||
// PermissionStatus { state: "granted" }
|
||||
|
||||
const strongDesc = { name: "read", path: "/foo" } as const;
|
||||
await Deno.permissions.revoke(strongDesc); // Good.
|
||||
|
||||
console.log(await Deno.permissions.query(desc));
|
||||
// PermissionStatus { state: "prompt" }
|
||||
```
|
|
@ -1,79 +0,0 @@
|
|||
## Program lifecycle
|
||||
|
||||
Deno supports browser compatible lifecycle events: `load` and `unload`. You can
|
||||
use these events to provide setup and cleanup code in your program.
|
||||
|
||||
Listeners for `load` events can be asynchronous and will be awaited. Listeners
|
||||
for `unload` events need to be synchronous. Both events cannot be cancelled.
|
||||
|
||||
Example:
|
||||
|
||||
**main.ts**
|
||||
|
||||
```ts
|
||||
import "./imported.ts";
|
||||
|
||||
const handler = (e: Event): void => {
|
||||
console.log(`got ${e.type} event in event handler (main)`);
|
||||
};
|
||||
|
||||
window.addEventListener("load", handler);
|
||||
|
||||
window.addEventListener("unload", handler);
|
||||
|
||||
window.onload = (e: Event): void => {
|
||||
console.log(`got ${e.type} event in onload function (main)`);
|
||||
};
|
||||
|
||||
window.onunload = (e: Event): void => {
|
||||
console.log(`got ${e.type} event in onunload function (main)`);
|
||||
};
|
||||
|
||||
console.log("log from main script");
|
||||
```
|
||||
|
||||
**imported.ts**
|
||||
|
||||
```ts
|
||||
const handler = (e: Event): void => {
|
||||
console.log(`got ${e.type} event in event handler (imported)`);
|
||||
};
|
||||
|
||||
window.addEventListener("load", handler);
|
||||
window.addEventListener("unload", handler);
|
||||
|
||||
window.onload = (e: Event): void => {
|
||||
console.log(`got ${e.type} event in onload function (imported)`);
|
||||
};
|
||||
|
||||
window.onunload = (e: Event): void => {
|
||||
console.log(`got ${e.type} event in onunload function (imported)`);
|
||||
};
|
||||
|
||||
console.log("log from imported script");
|
||||
```
|
||||
|
||||
Note that you can use both `window.addEventListener` and
|
||||
`window.onload`/`window.onunload` to define handlers for events. There is a
|
||||
major difference between them, let's run the example:
|
||||
|
||||
```shell
|
||||
$ deno run main.ts
|
||||
log from imported script
|
||||
log from main script
|
||||
got load event in event handler (imported)
|
||||
got load event in event handler (main)
|
||||
got load event in onload function (main)
|
||||
got unload event in event handler (imported)
|
||||
got unload event in event handler (main)
|
||||
got unload event in onunload function (main)
|
||||
```
|
||||
|
||||
All listeners added using `window.addEventListener` were run, but
|
||||
`window.onload` and `window.onunload` defined in `main.ts` overrode handlers
|
||||
defined in `imported.ts`.
|
||||
|
||||
In other words, you can register multiple `window.addEventListener` `"load"` or
|
||||
`"unload"` events, but only the last loaded `window.onload` or `window.onunload`
|
||||
event handlers will be executed. It is preferable to use `addEventListener` when
|
||||
possible for this reason.
|
|
@ -1,32 +0,0 @@
|
|||
## Stability
|
||||
|
||||
As of Deno 1.0.0, the `Deno` namespace APIs are stable. That means we will
|
||||
strive to make code working under 1.0.0 continue to work in future versions.
|
||||
|
||||
However, not all of Deno's features are ready for production yet. Features which
|
||||
are not ready, because they are still in draft phase, are locked behind the
|
||||
`--unstable` command line flag.
|
||||
|
||||
```shell
|
||||
deno run --unstable mod_which_uses_unstable_stuff.ts
|
||||
```
|
||||
|
||||
Passing this flag does a few things:
|
||||
|
||||
- It enables the use of unstable APIs during runtime.
|
||||
- It adds the
|
||||
[`lib.deno.unstable.d.ts`](https://doc.deno.land/https/raw.githubusercontent.com/denoland/deno/main/cli/dts/lib.deno.unstable.d.ts)
|
||||
file to the list of TypeScript definitions that are used for type checking.
|
||||
This includes the output of `deno types`.
|
||||
|
||||
You should be aware that many unstable APIs have **not undergone a security
|
||||
review**, are likely to have **breaking API changes** in the future, and are
|
||||
**not ready for production**.
|
||||
|
||||
### Standard modules
|
||||
|
||||
Deno's standard modules (https://deno.land/std/) are not yet stable. We
|
||||
currently version the standard modules differently from the CLI to reflect this.
|
||||
Note that unlike the `Deno` namespace, the use of the standard modules do not
|
||||
require the `--unstable` flag (unless the standard module itself makes use of an
|
||||
unstable Deno feature).
|
|
@ -1,97 +0,0 @@
|
|||
# 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.
|
||||
|
||||
Here is a list of web platform APIs Deno implements:
|
||||
|
||||
## `fetch` API
|
||||
|
||||
### Overview
|
||||
|
||||
The `fetch` API can be used to make HTTP requests. It is implemented as
|
||||
specified in the [WHATWG `fetch` spec](https://fetch.spec.whatwg.org/).
|
||||
|
||||
You can find documentation about this API on
|
||||
[MDN](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API).
|
||||
|
||||
### Spec deviations
|
||||
|
||||
- The Deno user agent does not have a cookie jar. As such, the `set-cookie`
|
||||
header on a response is not processed, or filtered from the visible response
|
||||
headers.
|
||||
- Deno does not follow the same-origin policy, because the Deno user agent
|
||||
currently does not have the concept of origins, and it does not have a cookie
|
||||
jar. This means Deno does not need to protect against leaking authenticated
|
||||
data cross origin. Because of this Deno does not implement the following
|
||||
sections of the WHATWG `fetch` specification:
|
||||
- Section `3.1. 'Origin' header`.
|
||||
- Section `3.2. CORS protocol`.
|
||||
- Section `3.5. CORB`.
|
||||
- Section `3.6. 'Cross-Origin-Resource-Policy' header`.
|
||||
- `Atomic HTTP redirect handling`.
|
||||
- The `opaqueredirect` response type.
|
||||
- A `fetch` with a `redirect` mode of `manual` will return a `basic` response
|
||||
rather than an `opaqueredirect` response.
|
||||
|
||||
## `CustomEvent`, `EventTarget` and `EventListener`
|
||||
|
||||
### Overview
|
||||
|
||||
The DOM Event API can be used to dispatch and listen to events happening in an
|
||||
application. It is implemented as specified in the
|
||||
[WHATWG DOM spec](https://dom.spec.whatwg.org/#events).
|
||||
|
||||
You can find documentation about this API on
|
||||
[MDN](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget).
|
||||
|
||||
### Spec deviations
|
||||
|
||||
- Events do not bubble, because Deno does not have a DOM hierarchy, so there is
|
||||
no tree for Events to bubble/capture through.
|
||||
|
||||
## Web Worker API
|
||||
|
||||
### Overview
|
||||
|
||||
The WebWorker API can be used to executing code in a separate thread. It is
|
||||
implemented as specified in the
|
||||
[WHATWG HTML spec](https://html.spec.whatwg.org/multipage/workers.html#workers).
|
||||
|
||||
You can find documentation about this API on
|
||||
[MDN](https://developer.mozilla.org/en-US/docs/Web/API/Worker).
|
||||
|
||||
### Spec deviations
|
||||
|
||||
- Currently creating workers from blob URLs is not supported.
|
||||
- Currently posted data is serialized to JSON instead of structured cloning.
|
||||
- Currently object ownership cannot be transferred between workers.
|
||||
|
||||
## Other APIs
|
||||
|
||||
- [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
|
||||
- [Console](https://developer.mozilla.org/en-US/docs/Web/API/Console)
|
||||
- [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData)
|
||||
- [Performance](https://developer.mozilla.org/en-US/docs/Web/API/Performance)
|
||||
- [setTimeout, setInterval, clearInterval](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout)
|
||||
- [Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API)
|
||||
- [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL)
|
||||
- [URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)
|
||||
- [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
|
||||
|
||||
---
|
||||
|
||||
## Typings
|
||||
|
||||
The TypeScript definitions for the implemented web APIs can be found in the
|
||||
[`lib.deno.shared_globals.d.ts`](https://github.com/denoland/deno/blob/$CLI_VERSION/cli/dts/lib.deno.shared_globals.d.ts)
|
||||
and
|
||||
[`lib.deno.window.d.ts`](https://github.com/denoland/deno/blob/$CLI_VERSION/cli/dts/lib.deno.window.d.ts)
|
||||
files.
|
||||
|
||||
Definitions that are specific to workers can be found in the
|
||||
[`lib.deno.worker.d.ts`](https://github.com/denoland/deno/blob/$CLI_VERSION/cli/dts/lib.deno.worker.d.ts)
|
||||
file.
|
|
@ -1,39 +0,0 @@
|
|||
## Web Storage API
|
||||
|
||||
As of Deno 1.10, the Web Storage API (`localStorage` & `sessionStorage`) was
|
||||
introduced, which through `localStorage` allows persistent storage, whereas
|
||||
`sessionStorage` is a non-persistent memory-based storage.
|
||||
|
||||
To use persistent storage, you need to pass the `--location` flag. The location
|
||||
for persistent storage is listed in `deno info`, and additionally passing the
|
||||
`--location` will give you the path for the specified origin.
|
||||
|
||||
To learn more about the Web Storage APIs, visit the
|
||||
[MDN page on Web Storage](https://developer.mozilla.org/en-US/docs/Web/API/Storage).
|
||||
|
||||
### Example
|
||||
|
||||
The following snippet accesses the local storage bucket for the current origin
|
||||
and adds a data item to it using `setItem()`.
|
||||
|
||||
```ts
|
||||
localStorage.setItem("myDemo", "Deno App");
|
||||
```
|
||||
|
||||
The syntax for reading the localStorage item is as follows:
|
||||
|
||||
```ts
|
||||
const cat = localStorage.getItem("myDemo");
|
||||
```
|
||||
|
||||
The syntax for removing the localStorage item is as follows:
|
||||
|
||||
```ts
|
||||
localStorage.removeItem("myDemo");
|
||||
```
|
||||
|
||||
The syntax for removing all the localStorage items is as follows:
|
||||
|
||||
```ts
|
||||
localStorage.clear();
|
||||
```
|
|
@ -1,251 +0,0 @@
|
|||
## Workers
|
||||
|
||||
Deno supports
|
||||
[`Web Worker API`](https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker).
|
||||
|
||||
Workers can be used to run code on multiple threads. Each instance of `Worker`
|
||||
is run on a separate thread, dedicated only to that worker.
|
||||
|
||||
Currently Deno supports only `module` type workers; thus it's essential to pass
|
||||
the `type: "module"` option when creating a new worker.
|
||||
|
||||
Use of relative module specifiers in the main worker are only supported with
|
||||
`--location <href>` passed on the CLI. This is not recommended for portability.
|
||||
You can instead use the `URL` constructor and `import.meta.url` to easily create
|
||||
a specifier for some nearby script. Dedicated workers, however, have a location
|
||||
and this capability by default.
|
||||
|
||||
```ts
|
||||
// Good
|
||||
new Worker(new URL("./worker.js", import.meta.url).href, { type: "module" });
|
||||
|
||||
// Bad
|
||||
new Worker(new URL("./worker.js", import.meta.url).href);
|
||||
new Worker(new URL("./worker.js", import.meta.url).href, { type: "classic" });
|
||||
new Worker("./worker.js", { type: "module" });
|
||||
```
|
||||
|
||||
### Instantiation permissions
|
||||
|
||||
Creating a new `Worker` instance is similar to a dynamic import; therefore Deno
|
||||
requires appropriate permission for this action.
|
||||
|
||||
For workers using local modules; `--allow-read` permission is required:
|
||||
|
||||
**main.ts**
|
||||
|
||||
```ts
|
||||
new Worker(new URL("./worker.ts", import.meta.url).href, { type: "module" });
|
||||
```
|
||||
|
||||
**worker.ts**
|
||||
|
||||
```ts
|
||||
console.log("hello world");
|
||||
self.close();
|
||||
```
|
||||
|
||||
```shell
|
||||
$ deno run main.ts
|
||||
error: Uncaught PermissionDenied: read access to "./worker.ts", run again with the --allow-read flag
|
||||
|
||||
$ deno run --allow-read main.ts
|
||||
hello world
|
||||
```
|
||||
|
||||
For workers using remote modules; `--allow-net` permission is required:
|
||||
|
||||
**main.ts**
|
||||
|
||||
```ts
|
||||
new Worker("https://example.com/worker.ts", { type: "module" });
|
||||
```
|
||||
|
||||
**worker.ts** (at https[]()://example.com/worker.ts)
|
||||
|
||||
```ts
|
||||
console.log("hello world");
|
||||
self.close();
|
||||
```
|
||||
|
||||
```shell
|
||||
$ deno run main.ts
|
||||
error: Uncaught PermissionDenied: net access to "https://example.com/worker.ts", run again with the --allow-net flag
|
||||
|
||||
$ deno run --allow-net main.ts
|
||||
hello world
|
||||
```
|
||||
|
||||
### Using Deno in worker
|
||||
|
||||
> This is an unstable Deno feature. Learn more about
|
||||
> [unstable features](./stability.md).
|
||||
|
||||
By default the `Deno` namespace is not available in worker scope.
|
||||
|
||||
To enable the `Deno` namespace pass `deno.namespace = true` option when creating
|
||||
new worker:
|
||||
|
||||
**main.js**
|
||||
|
||||
```ts
|
||||
const worker = new Worker(new URL("./worker.js", import.meta.url).href, {
|
||||
type: "module",
|
||||
deno: {
|
||||
namespace: true,
|
||||
},
|
||||
});
|
||||
worker.postMessage({ filename: "./log.txt" });
|
||||
```
|
||||
|
||||
**worker.js**
|
||||
|
||||
```ts
|
||||
self.onmessage = async (e) => {
|
||||
const { filename } = e.data;
|
||||
const text = await Deno.readTextFile(filename);
|
||||
console.log(text);
|
||||
self.close();
|
||||
};
|
||||
```
|
||||
|
||||
**log.txt**
|
||||
|
||||
```
|
||||
hello world
|
||||
```
|
||||
|
||||
```shell
|
||||
$ deno run --allow-read --unstable main.js
|
||||
hello world
|
||||
```
|
||||
|
||||
### Specifying worker permissions
|
||||
|
||||
> This is an unstable Deno feature. Learn more about
|
||||
> [unstable features](./stability.md).
|
||||
|
||||
The permissions available for the worker are analogous to the CLI permission
|
||||
flags, meaning every permission enabled there can be disabled at the level of
|
||||
the Worker API. You can find a more detailed description of each of the
|
||||
permission options [here](../getting_started/permissions.md).
|
||||
|
||||
By default a worker will inherit permissions from the thread it was created in,
|
||||
however in order to allow users to limit the access of this worker we provide
|
||||
the `deno.permissions` option in the worker API.
|
||||
|
||||
- For permissions that support granular access you can pass in a list of the
|
||||
desired resources the worker will have access to, and for those who only have
|
||||
the on/off option you can pass true/false respectively.
|
||||
|
||||
```ts
|
||||
const worker = new Worker(new URL("./worker.js", import.meta.url).href, {
|
||||
type: "module",
|
||||
deno: {
|
||||
namespace: true,
|
||||
permissions: {
|
||||
net: [
|
||||
"https://deno.land/",
|
||||
],
|
||||
read: [
|
||||
new URL("./file_1.txt", import.meta.url),
|
||||
new URL("./file_2.txt", import.meta.url),
|
||||
],
|
||||
write: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
- Granular access permissions receive both absolute and relative routes as
|
||||
arguments, however take into account that relative routes will be resolved
|
||||
relative to the file the worker is instantiated in, not the path the worker
|
||||
file is currently in
|
||||
|
||||
```ts
|
||||
const worker = new Worker(
|
||||
new URL("./worker/worker.js", import.meta.url).href,
|
||||
{
|
||||
type: "module",
|
||||
deno: {
|
||||
namespace: true,
|
||||
permissions: {
|
||||
read: [
|
||||
"/home/user/Documents/deno/worker/file_1.txt",
|
||||
"./worker/file_2.txt",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
- Both `deno.permissions` and its children support the option `"inherit"`, which
|
||||
implies it will borrow its parent permissions.
|
||||
|
||||
```ts
|
||||
// This worker will inherit its parent permissions
|
||||
const worker = new Worker(new URL("./worker.js", import.meta.url).href, {
|
||||
type: "module",
|
||||
deno: {
|
||||
namespace: true,
|
||||
permissions: "inherit",
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```ts
|
||||
// This worker will inherit only the net permissions of its parent
|
||||
const worker = new Worker(new URL("./worker.js", import.meta.url).href, {
|
||||
type: "module",
|
||||
deno: {
|
||||
namespace: true,
|
||||
permissions: {
|
||||
env: false,
|
||||
hrtime: false,
|
||||
net: "inherit",
|
||||
plugin: false,
|
||||
read: false,
|
||||
run: false,
|
||||
write: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
- Not specifying the `deno.permissions` option or one of its children will cause
|
||||
the worker to inherit by default.
|
||||
|
||||
```ts
|
||||
// This worker will inherit its parent permissions
|
||||
const worker = new Worker(new URL("./worker.js", import.meta.url).href, {
|
||||
type: "module",
|
||||
});
|
||||
```
|
||||
|
||||
```ts
|
||||
// This worker will inherit all the permissions of its parent BUT net
|
||||
const worker = new Worker(new URL("./worker.js", import.meta.url).href, {
|
||||
type: "module",
|
||||
deno: {
|
||||
namespace: true,
|
||||
permissions: {
|
||||
net: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
- You can disable the permissions of the worker all together by passing `"none"`
|
||||
to the `deno.permissions` option.
|
||||
|
||||
```ts
|
||||
// This worker will not have any permissions enabled
|
||||
const worker = new Worker(new URL("./worker.js", import.meta.url).href, {
|
||||
type: "module",
|
||||
deno: {
|
||||
namespace: true,
|
||||
permissions: "none",
|
||||
},
|
||||
});
|
||||
```
|
|
@ -1,116 +0,0 @@
|
|||
{
|
||||
"$id": "https://deno.land/schemas/module-graph.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema",
|
||||
"description": "A JSON representation of a Deno module dependency graph.",
|
||||
"required": [
|
||||
"root",
|
||||
"modules",
|
||||
"size"
|
||||
],
|
||||
"title": "Deno Dependency Graph Schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"root": {
|
||||
"default": "",
|
||||
"description": "The root specifier for the graph.",
|
||||
"examples": [
|
||||
"https://deno.land/x/mod.ts"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"modules": {
|
||||
"default": [],
|
||||
"description": "The modules that are part of the graph.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/module"
|
||||
}
|
||||
},
|
||||
"size": {
|
||||
"type": "integer",
|
||||
"description": "The total size of all the unique dependencies in the graph in bytes.",
|
||||
"default": 0
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"module": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"specifier"
|
||||
],
|
||||
"properties": {
|
||||
"specifier": {
|
||||
"type": "string",
|
||||
"description": "The fully qualified module specifier (URL) for the module."
|
||||
},
|
||||
"dependencies": {
|
||||
"type": "array",
|
||||
"description": "An array of dependencies of the module.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/dependency"
|
||||
}
|
||||
},
|
||||
"size": {
|
||||
"type": "integer",
|
||||
"description": "The size of the module on disk in bytes."
|
||||
},
|
||||
"mediaType": {
|
||||
"type": "string",
|
||||
"description": "How the file is treated within Deno. All the possible media types that Deno considers are listed here, but in practice, several of them would never appear in a module graph.",
|
||||
"enum": [
|
||||
"JavaScript",
|
||||
"TypeScript",
|
||||
"JSX",
|
||||
"TSX",
|
||||
"Dts",
|
||||
"Json",
|
||||
"Wasm",
|
||||
"TsBuildInfo",
|
||||
"SourceMap",
|
||||
"Unknown"
|
||||
]
|
||||
},
|
||||
"local": {
|
||||
"type": "string",
|
||||
"description": "The path to the local file. For local modules this will be the local file path, for remote modules and data URLs, this would be the path to the file in the Deno cache."
|
||||
},
|
||||
"checksum": {
|
||||
"type": "string",
|
||||
"description": "The checksum of the local source file. This can be used to validate if the current on disk version matches the version described here."
|
||||
},
|
||||
"emit": {
|
||||
"type": "string",
|
||||
"description": "The path to an emitted version of the module, if the module requires transpilation to be loaded into the Deno runtime."
|
||||
},
|
||||
"map": {
|
||||
"type": "string",
|
||||
"description": "The path to an optionally emitted source map between the original and emitted version of the file."
|
||||
},
|
||||
"error": {
|
||||
"type": "string",
|
||||
"description": "If when resolving the module, Deno encountered an error and the module is unavailable, the text of that error will be indicated here."
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependency": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"specifier"
|
||||
],
|
||||
"properties": {
|
||||
"specifier": {
|
||||
"type": "string",
|
||||
"description": "The specifier provided from within the module."
|
||||
},
|
||||
"code": {
|
||||
"type": "string",
|
||||
"description": "The fully qualified module specifier (URL) for the code dependency."
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "The fully qualified module specifier (URL) for the type only dependency."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
# Standard library
|
||||
|
||||
Deno provides a set of standard modules that are audited by the core team and
|
||||
are guaranteed to work with Deno.
|
||||
|
||||
Standard library is available at: https://deno.land/std/
|
||||
|
||||
## Versioning and stability
|
||||
|
||||
Standard library is not yet stable and therefore it is versioned differently
|
||||
than Deno. For latest release consult https://deno.land/std/ or
|
||||
https://deno.land/std/version.ts. The standard library is released each time
|
||||
Deno is released.
|
||||
|
||||
We strongly suggest to always use imports with pinned version of standard
|
||||
library to avoid unintended changes. For example, rather than linking to the
|
||||
default branch of code, which may change at any time, potentially causing
|
||||
compilation errors or unexpected behavior:
|
||||
|
||||
```typescript
|
||||
// import the latest release, this should be avoided
|
||||
import { copy } from "https://deno.land/std/fs/copy.ts";
|
||||
```
|
||||
|
||||
instead, used a version of the std library which is immutable and will not
|
||||
change:
|
||||
|
||||
```typescript
|
||||
// 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/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.
|
169
docs/testing.md
|
@ -1,169 +0,0 @@
|
|||
# Testing
|
||||
|
||||
Deno has a built-in test runner that you can use for testing JavaScript or
|
||||
TypeScript code.
|
||||
|
||||
`deno test` will search in `./*` and `./**/*` recursively, for test files:
|
||||
|
||||
- named `test.{ts, tsx, js, mjs, jsx}`,
|
||||
- or ending with `.test.{ts, tsx, js, mjs, jsx}`,
|
||||
- or ending with `_test.{ts, tsx, js, mjs, jsx}`
|
||||
|
||||
## Writing tests
|
||||
|
||||
To define a test you need to register it with a call to `Deno.test` with a name
|
||||
and function to be tested. There are two styles you can use.
|
||||
|
||||
```ts
|
||||
import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
|
||||
// Simple name and function, compact form, but not configurable
|
||||
Deno.test("hello world #1", () => {
|
||||
const x = 1 + 2;
|
||||
assertEquals(x, 3);
|
||||
});
|
||||
|
||||
// Fully fledged test definition, longer form, but configurable (see below)
|
||||
Deno.test({
|
||||
name: "hello world #2",
|
||||
fn: () => {
|
||||
const x = 1 + 2;
|
||||
assertEquals(x, 3);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Async functions
|
||||
|
||||
You can also test asynchronous code by passing a test function that returns a
|
||||
promise. For this you can use the `async` keyword when defining a function:
|
||||
|
||||
```ts
|
||||
import { delay } from "https://deno.land/std@$STD_VERSION/async/delay.ts";
|
||||
|
||||
Deno.test("async hello world", async () => {
|
||||
const x = 1 + 2;
|
||||
|
||||
// await some async task
|
||||
await delay(100);
|
||||
|
||||
if (x !== 3) {
|
||||
throw Error("x should be equal to 3");
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Running tests
|
||||
|
||||
To run the test, call `deno test` with the file that contains your test
|
||||
function. You can also omit the file name, in which case all tests in the
|
||||
current directory (recursively) that match the glob
|
||||
`{*_,*.,}test.{js,mjs,ts,jsx,tsx}` will be run. If you pass a directory, all
|
||||
files in the directory that match this glob will be run.
|
||||
|
||||
```shell
|
||||
# Run all tests in the current directory and all sub-directories
|
||||
deno test
|
||||
|
||||
# Run all tests in the util directory
|
||||
deno test util/
|
||||
|
||||
# Run just my_test.ts
|
||||
deno test my_test.ts
|
||||
```
|
||||
|
||||
`deno test` uses the same permission model as `deno run` and therefore will
|
||||
require, for example, `--allow-write` to write to the file system during
|
||||
testing.
|
||||
|
||||
To see all runtime options with `deno test`, you can reference the command line
|
||||
help:
|
||||
|
||||
```shell
|
||||
deno help test
|
||||
```
|
||||
|
||||
## Filtering
|
||||
|
||||
There are a number of options to filter the tests you are running.
|
||||
|
||||
### Command line filtering
|
||||
|
||||
Tests can be run individually or in groups using the command line `--filter`
|
||||
option.
|
||||
|
||||
The filter flags accept a string or a pattern as value.
|
||||
|
||||
Assuming the following tests:
|
||||
|
||||
```ts
|
||||
Deno.test({ name: "my-test", fn: myTest });
|
||||
Deno.test({ name: "test-1", fn: test1 });
|
||||
Deno.test({ name: "test2", fn: test2 });
|
||||
```
|
||||
|
||||
This command will run all of these tests because they all contain the word
|
||||
"test".
|
||||
|
||||
```shell
|
||||
deno test --filter "test" tests/
|
||||
```
|
||||
|
||||
On the flip side, the following command uses a pattern and will run the second
|
||||
and third tests.
|
||||
|
||||
```shell
|
||||
deno test --filter "/test-*\d/" tests/
|
||||
```
|
||||
|
||||
_To let Deno know that you want to use a pattern, wrap your filter with
|
||||
forward-slashes like the JavaScript syntactic sugar for a REGEX._
|
||||
|
||||
### Test definition filtering
|
||||
|
||||
Within the tests themselves, you have two options for filtering.
|
||||
|
||||
#### Filtering out (Ignoring these tests)
|
||||
|
||||
Sometimes you want to ignore tests based on some sort of condition (for example
|
||||
you only want a test to run on Windows). For this you can use the `ignore`
|
||||
boolean in the test definition. If it is set to true the test will be skipped.
|
||||
|
||||
```ts
|
||||
Deno.test({
|
||||
name: "do macOS feature",
|
||||
ignore: Deno.build.os !== "darwin",
|
||||
fn() {
|
||||
doMacOSFeature();
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
#### Filtering in (Only run these tests)
|
||||
|
||||
Sometimes you may be in the middle of a problem within a large test class and
|
||||
you would like to focus on just that test and ignore the rest for now. For this
|
||||
you can use the `only` option to tell the test framework to only run tests with
|
||||
this set to true. Multiple tests can set this option. While the test run will
|
||||
report on the success or failure of each test, the overall test run will always
|
||||
fail if any test is flagged with `only`, as this is a temporary measure only
|
||||
which disables nearly all of your tests.
|
||||
|
||||
```ts
|
||||
Deno.test({
|
||||
name: "Focus on this test only",
|
||||
only: true,
|
||||
fn() {
|
||||
testComplicatedStuff();
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## Failing fast
|
||||
|
||||
If you have a long running test suite and wish for it to stop on the first
|
||||
failure, you can specify the `--fail-fast` flag when running the suite.
|
||||
|
||||
```shell
|
||||
deno test --fail-fast
|
||||
```
|
|
@ -1,263 +0,0 @@
|
|||
## 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`.
|
||||
|
||||
```js
|
||||
import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
|
||||
Deno.test("Hello Test", () => {
|
||||
assert("Hello");
|
||||
});
|
||||
```
|
||||
|
||||
The assertions module provides 10 assertions:
|
||||
|
||||
- `assert(expr: unknown, msg = ""): asserts expr`
|
||||
- `assertEquals(actual: unknown, expected: unknown, msg?: string): void`
|
||||
- `assertExists(actual: unknown,msg?: string): void`
|
||||
- `assertNotEquals(actual: unknown, expected: unknown, msg?: string): void`
|
||||
- `assertStrictEquals(actual: unknown, expected: unknown, msg?: string): void`
|
||||
- `assertStringIncludes(actual: string, expected: string, msg?: string): void`
|
||||
- `assertArrayIncludes(actual: unknown[], expected: unknown[], msg?: string): void`
|
||||
- `assertMatch(actual: string, expected: RegExp, msg?: string): void`
|
||||
- `assertNotMatch(actual: string, expected: RegExp, msg?: string): void`
|
||||
- `assertObjectMatch( actual: Record<PropertyKey, unknown>, expected: Record<PropertyKey, unknown>): void`
|
||||
- `assertThrows(fn: () => void, ErrorClass?: Constructor, msgIncludes = "", msg?: string): Error`
|
||||
- `assertThrowsAsync(fn: () => Promise<void>, ErrorClass?: Constructor, msgIncludes = "", msg?: string): Promise<Error>`
|
||||
|
||||
### Assert
|
||||
|
||||
The assert method is a simple 'truthy' assertion and can be used to assert any
|
||||
value which can be inferred as true.
|
||||
|
||||
```js
|
||||
Deno.test("Test Assert", () => {
|
||||
assert(1);
|
||||
assert("Hello");
|
||||
assert(true);
|
||||
});
|
||||
```
|
||||
|
||||
### Exists
|
||||
|
||||
The `assertExists` can be used to check if a value is not `null` or `undefined`.
|
||||
|
||||
```js
|
||||
assertExists("Denosaurus");
|
||||
Deno.test("Test Assert Exists", () => {
|
||||
assertExists("Denosaurus");
|
||||
assertExists(false);
|
||||
assertExists(0);
|
||||
});
|
||||
```
|
||||
|
||||
### Equality
|
||||
|
||||
There are three equality assertions available, `assertEquals()`,
|
||||
`assertNotEquals()` and `assertStrictEquals()`.
|
||||
|
||||
The `assertEquals()` and `assertNotEquals()` methods provide a general equality
|
||||
check and are capable of asserting equality between primitive types and objects.
|
||||
|
||||
```js
|
||||
Deno.test("Test Assert Equals", () => {
|
||||
assertEquals(1, 1);
|
||||
assertEquals("Hello", "Hello");
|
||||
assertEquals(true, true);
|
||||
assertEquals(undefined, undefined);
|
||||
assertEquals(null, null);
|
||||
assertEquals(new Date(), new Date());
|
||||
assertEquals(new RegExp("abc"), new RegExp("abc"));
|
||||
|
||||
class Foo {}
|
||||
const foo1 = new Foo();
|
||||
const foo2 = new Foo();
|
||||
|
||||
assertEquals(foo1, foo2);
|
||||
});
|
||||
|
||||
Deno.test("Test Assert Not Equals", () => {
|
||||
assertNotEquals(1, 2);
|
||||
assertNotEquals("Hello", "World");
|
||||
assertNotEquals(true, false);
|
||||
assertNotEquals(undefined, "");
|
||||
assertNotEquals(new Date(), Date.now());
|
||||
assertNotEquals(new RegExp("abc"), new RegExp("def"));
|
||||
});
|
||||
```
|
||||
|
||||
By contrast `assertStrictEquals()` provides a simpler, stricter equality check
|
||||
based on the `===` operator. As a result it will not assert two instances of
|
||||
identical objects as they won't be referentially the same.
|
||||
|
||||
```js
|
||||
Deno.test("Test Assert Strict Equals", () => {
|
||||
assertStrictEquals(1, 1);
|
||||
assertStrictEquals("Hello", "Hello");
|
||||
assertStrictEquals(true, true);
|
||||
assertStrictEquals(undefined, undefined);
|
||||
});
|
||||
```
|
||||
|
||||
The `assertStrictEquals()` assertion is best used when you wish to make a
|
||||
precise check against two primitive types.
|
||||
|
||||
### Contains
|
||||
|
||||
There are two methods available to assert a value contains a value,
|
||||
`assertStringIncludes()` and `assertArrayIncludes()`.
|
||||
|
||||
The `assertStringIncludes()` assertion does a simple includes check on a string
|
||||
to see if it contains the expected string.
|
||||
|
||||
```js
|
||||
Deno.test("Test Assert String Contains", () => {
|
||||
assertStringIncludes("Hello World", "Hello");
|
||||
});
|
||||
```
|
||||
|
||||
The `assertArrayIncludes()` assertion is slightly more advanced and can find
|
||||
both a value within an array and an array of values within an array.
|
||||
|
||||
```js
|
||||
Deno.test("Test Assert Array Contains", () => {
|
||||
assertArrayIncludes([1, 2, 3], [1]);
|
||||
assertArrayIncludes([1, 2, 3], [1, 2]);
|
||||
assertArrayIncludes(Array.from("Hello World"), Array.from("Hello"));
|
||||
});
|
||||
```
|
||||
|
||||
### Regex
|
||||
|
||||
You can assert regular expressions via `assertMatch()` and `assertNotMatch()`
|
||||
assertions.
|
||||
|
||||
```js
|
||||
Deno.test("Test Assert Match", () => {
|
||||
assertMatch("abcdefghi", new RegExp("def"));
|
||||
|
||||
const basicUrl = new RegExp("^https?://[a-z.]+.com$");
|
||||
assertMatch("https://www.google.com", basicUrl);
|
||||
assertMatch("http://facebook.com", basicUrl);
|
||||
});
|
||||
|
||||
Deno.test("Test Assert Not Match", () => {
|
||||
assertNotMatch("abcdefghi", new RegExp("jkl"));
|
||||
|
||||
const basicUrl = new RegExp("^https?://[a-z.]+.com$");
|
||||
assertNotMatch("https://deno.land/", basicUrl);
|
||||
});
|
||||
```
|
||||
|
||||
### Object
|
||||
|
||||
Use `assertObjectMatch` to check that a JavaScript object matches a subset of
|
||||
the properties of an object.
|
||||
|
||||
```js
|
||||
// Simple subset
|
||||
assertObjectMatch(
|
||||
{ foo: true, bar: false },
|
||||
{
|
||||
foo: true,
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
### Throws
|
||||
|
||||
There are two ways to assert whether something throws an error in Deno,
|
||||
`assertThrows()` and `assertThrowsAsync()`. Both assertions allow you to check
|
||||
an
|
||||
[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
|
||||
has been thrown, the type of error thrown and what the message was.
|
||||
|
||||
The difference between the two assertions is `assertThrows()` accepts a standard
|
||||
function and `assertThrowsAsync()` accepts a function which returns a
|
||||
[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
|
||||
|
||||
The `assertThrows()` assertion will check an error has been thrown, and
|
||||
optionally will check the thrown error is of the correct type, and assert the
|
||||
error message is as expected.
|
||||
|
||||
```js
|
||||
Deno.test("Test Assert Throws", () => {
|
||||
assertThrows(
|
||||
() => {
|
||||
throw new Error("Panic!");
|
||||
},
|
||||
Error,
|
||||
"Panic!",
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
The `assertThrowsAsync()` assertion is a little more complicated, mainly because
|
||||
it deals with Promises. But basically it will catch thrown errors or rejections
|
||||
in Promises. You can also optionally check for the error type and error message.
|
||||
|
||||
```js
|
||||
Deno.test("Test Assert Throws Async", () => {
|
||||
assertThrowsAsync(
|
||||
() => {
|
||||
return new Promise(() => {
|
||||
throw new Error("Panic! Threw Error");
|
||||
});
|
||||
},
|
||||
Error,
|
||||
"Panic! Threw Error",
|
||||
);
|
||||
|
||||
assertThrowsAsync(
|
||||
() => {
|
||||
return Promise.reject(new Error("Panic! Reject Error"));
|
||||
},
|
||||
Error,
|
||||
"Panic! Reject Error",
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
### Custom Messages
|
||||
|
||||
Each of Deno's built in assertions allow you to overwrite the standard CLI error
|
||||
message if you wish. For instance this example will output "Values Don't Match!"
|
||||
rather than the standard CLI error message.
|
||||
|
||||
```js
|
||||
Deno.test("Test Assert Equal Fail Custom Message", () => {
|
||||
assertEquals(1, 2, "Values Don't Match!");
|
||||
});
|
||||
```
|
||||
|
||||
### 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
|
||||
`custom assertion function` can improve readability and reduce the amount of
|
||||
code.
|
||||
|
||||
```js
|
||||
function assertPowerOf(actual: number, expected: number, msg?: string): void {
|
||||
let received = actual;
|
||||
while (received % expected === 0) received = received / expected;
|
||||
if (received !== 1) {
|
||||
if (!msg) {
|
||||
msg = `actual: "${actual}" expected to be a power of : "${expected}"`;
|
||||
}
|
||||
throw new AssertionError(msg);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Use this matcher in your code like this:
|
||||
|
||||
```js
|
||||
Deno.test("Test Assert PowerOf", () => {
|
||||
assertPowerOf(8, 2);
|
||||
assertPowerOf(11, 4);
|
||||
});
|
||||
```
|
|
@ -1,36 +0,0 @@
|
|||
# Test coverage
|
||||
|
||||
Deno will collect test coverage into a directory for your code if you specify
|
||||
the `--coverage` flag when starting `deno test`.
|
||||
|
||||
This coverage information is acquired directly from the JavaScript engine (V8)
|
||||
which is very accurate.
|
||||
|
||||
This can then be further processed from the internal format into well known
|
||||
formats by the `deno coverage` tool.
|
||||
|
||||
```bash
|
||||
# Go into your project's working directory
|
||||
git clone https://github.com/oakserver/oak && cd oak
|
||||
|
||||
# Collect your coverage profile with deno test --coverage=<output_directory>
|
||||
deno test --coverage=cov_profile
|
||||
|
||||
# From this you can get a pretty printed diff of uncovered lines
|
||||
deno coverage cov_profile
|
||||
|
||||
# Or generate an lcov report
|
||||
deno coverage cov_profile --lcov > cov_profile.lcov
|
||||
|
||||
# Which can then be further processed by tools like genhtml
|
||||
genhtml -o cov_profile/html cov_profile.lcov
|
||||
```
|
||||
|
||||
By default, `deno coverage` will exclude any files matching the regular
|
||||
expression `test\.(js|mjs|ts|jsx|tsx)` and only consider including specifiers
|
||||
matching the regular expression `^file:` - ie. remote files will be excluded
|
||||
from coverage report.
|
||||
|
||||
These filters can be overridden using the `--exclude` and `--include` flags. A
|
||||
module specifier must _match_ the include_regular expression and _not match_ the
|
||||
exclude_ expression for it to be a part of the report.
|
|
@ -1,39 +0,0 @@
|
|||
# Documentation tests
|
||||
|
||||
Deno supports type-checking your documentation examples.
|
||||
|
||||
This makes sure that examples within your documentation are up to date and
|
||||
working.
|
||||
|
||||
The basic idea is this:
|
||||
|
||||
````ts
|
||||
/**
|
||||
* # Examples
|
||||
*
|
||||
* ```ts
|
||||
* const x = 42;
|
||||
* ```
|
||||
*/
|
||||
````
|
||||
|
||||
The triple backticks mark the start and end of code blocks.
|
||||
|
||||
If this example was in a file named foo.ts, running `deno test --doc foo.ts`
|
||||
will extract this example, and then type-check it as a standalone module living
|
||||
in the same directory as the module being documented.
|
||||
|
||||
To document your exports, import the module using a relative path specifier:
|
||||
|
||||
````ts
|
||||
/**
|
||||
* # Examples
|
||||
*
|
||||
* ```ts
|
||||
* import { foo } from "./foo.ts";
|
||||
* ```
|
||||
*/
|
||||
export function foo(): string {
|
||||
return "foo";
|
||||
}
|
||||
````
|
|
@ -1,69 +0,0 @@
|
|||
# Test Sanitizers
|
||||
|
||||
The test runner offers several sanitizers to ensure that the test behaves in a
|
||||
reasonable and expected way.
|
||||
|
||||
### Resource sanitizer
|
||||
|
||||
Certain actions in Deno create resources in the resource table
|
||||
([learn more here](./contributing/architecture.md)).
|
||||
|
||||
These resources should be closed after you are done using them.
|
||||
|
||||
For each test definition, the test runner checks that all resources created in
|
||||
this test have been closed. This is to prevent resource 'leaks'. This is enabled
|
||||
by default for all tests, but can be disabled by setting the `sanitizeResources`
|
||||
boolean to false in the test definition.
|
||||
|
||||
```ts
|
||||
Deno.test({
|
||||
name: "leaky resource test",
|
||||
async fn() {
|
||||
await Deno.open("hello.txt");
|
||||
},
|
||||
sanitizeResources: false,
|
||||
});
|
||||
```
|
||||
|
||||
### Op sanitizer
|
||||
|
||||
The same is true for async operation like interacting with the filesystem. The
|
||||
test runner checks that each operation you start in the test is completed before
|
||||
the end of the test. This is enabled by default for all tests, but can be
|
||||
disabled by setting the `sanitizeOps` boolean to false in the test definition.
|
||||
|
||||
```ts
|
||||
Deno.test({
|
||||
name: "leaky operation test",
|
||||
fn() {
|
||||
setTimeout(function () {}, 1000);
|
||||
},
|
||||
sanitizeOps: false,
|
||||
});
|
||||
```
|
||||
|
||||
### Exit sanitizer
|
||||
|
||||
There's also the exit sanitizer which ensures that tested code doesn't call
|
||||
`Deno.exit()` signaling a false test success.
|
||||
|
||||
This is enabled by default for all tests, but can be disabled by setting the
|
||||
`sanitizeExit` boolean to false in the test definition.
|
||||
|
||||
```ts
|
||||
Deno.test({
|
||||
name: "false success",
|
||||
fn() {
|
||||
Deno.exit(0);
|
||||
},
|
||||
sanitizeExit: false,
|
||||
});
|
||||
|
||||
// This test never runs, because the process exits during "false success" test
|
||||
Deno.test({
|
||||
name: "failing test",
|
||||
fn() {
|
||||
throw new Error("this test fails");
|
||||
},
|
||||
});
|
||||
```
|
120
docs/toc.json
|
@ -1,120 +0,0 @@
|
|||
{
|
||||
"introduction": {
|
||||
"name": "Introduction"
|
||||
},
|
||||
"getting_started": {
|
||||
"name": "Getting Started",
|
||||
"children": {
|
||||
"installation": "Installation",
|
||||
"setup_your_environment": "Setup your environment",
|
||||
"first_steps": "First steps",
|
||||
"command_line_interface": "Command line interface",
|
||||
"permissions": "Permissions",
|
||||
"webassembly": "Using WebAssembly",
|
||||
"debugging_your_code": "Debugging your code"
|
||||
}
|
||||
},
|
||||
"runtime": {
|
||||
"name": "The Runtime",
|
||||
"children": {
|
||||
"stability": "Stability",
|
||||
"program_lifecycle": "Program lifecycle",
|
||||
"permission_apis": "Permission APIs",
|
||||
"web_platform_apis": "Web Platform APIs",
|
||||
"http_server_apis": "HTTP Server APIs",
|
||||
"location_api": "Location API",
|
||||
"web_storage_api": "Web Storage API",
|
||||
"workers": "Workers"
|
||||
}
|
||||
},
|
||||
"linking_to_external_code": {
|
||||
"name": "Linking to external code",
|
||||
"children": {
|
||||
"reloading_modules": "Reloading modules",
|
||||
"integrity_checking": "Integrity checking",
|
||||
"proxies": "Proxies",
|
||||
"private": "Private modules",
|
||||
"import_maps": "Import maps"
|
||||
}
|
||||
},
|
||||
"npm_nodejs": {
|
||||
"name": "Using npm/Node.js code",
|
||||
"children": {
|
||||
"std_node": "The std/node library",
|
||||
"cdns": "Packages from CDNs",
|
||||
"import_maps": "Using import maps",
|
||||
"faqs": "Frequently asked questions"
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"name": "Using TypeScript",
|
||||
"children": {
|
||||
"overview": "Overview",
|
||||
"configuration": "Configuration",
|
||||
"types": "Types and type declarations",
|
||||
"migration": "Migrating to/from JavaScript",
|
||||
"runtime": "Runtime compiler APIs",
|
||||
"faqs": "Frequently asked questions"
|
||||
}
|
||||
},
|
||||
"standard_library": {
|
||||
"name": "Standard library"
|
||||
},
|
||||
"examples": {
|
||||
"name": "Examples",
|
||||
"children": {
|
||||
"hello_world": "Hello world",
|
||||
"import_export": "Import and export modules",
|
||||
"manage_dependencies": "Manage dependencies",
|
||||
"fetch_data": "Fetch data",
|
||||
"read_write_files": "Read and write files",
|
||||
"unix_cat": "Unix cat program",
|
||||
"http_server": "HTTP web server",
|
||||
"file_server": "File server",
|
||||
"tcp_echo": "TCP echo server",
|
||||
"subprocess": "Creating a subprocess",
|
||||
"os_signals": "OS signals",
|
||||
"file_system_events": "File system events",
|
||||
"module_metadata": "Module metadata"
|
||||
}
|
||||
},
|
||||
"testing": {
|
||||
"name": "Testing",
|
||||
"children": {
|
||||
"assertions": "Assertions",
|
||||
"coverage": "Coverage",
|
||||
"documentation": "Documentation",
|
||||
"sanitizers": "Sanitizers"
|
||||
}
|
||||
},
|
||||
"tools": {
|
||||
"name": "Tools",
|
||||
"children": {
|
||||
"script_installer": "Script installer",
|
||||
"formatter": "Formatter",
|
||||
"repl": "Read-eval-print-loop",
|
||||
"bundler": "Bundler",
|
||||
"compiler": "Compiling executables",
|
||||
"documentation_generator": "Documentation generator",
|
||||
"dependency_inspector": "Dependency inspector",
|
||||
"linter": "Linter"
|
||||
}
|
||||
},
|
||||
"embedding_deno": {
|
||||
"name": "Embedding Deno"
|
||||
},
|
||||
"help": {
|
||||
"name": "Help"
|
||||
},
|
||||
"contributing": {
|
||||
"name": "Contributing",
|
||||
"children": {
|
||||
"building_from_source": "Building from source",
|
||||
"development_tools": "Development tools",
|
||||
"web_platform_tests": "Web platform tests",
|
||||
"style_guide": "Style guide",
|
||||
"architecture": "Architecture",
|
||||
"release_schedule": "Release schedule"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
# Built-in tooling
|
||||
|
||||
Deno provides some built in tooling that is useful when working with JavaScript
|
||||
and TypeScript:
|
||||
|
||||
- [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)
|
||||
- [repl (`deno repl`)](./tools/repl.md)
|
||||
- [test runner (`deno test`)](./testing.md)
|
||||
- [linter (`deno lint`)](./tools/linter.md)
|
|
@ -1,51 +0,0 @@
|
|||
## Bundling
|
||||
|
||||
`deno bundle [URL]` will output a single JavaScript file, 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
|
||||
Emit "colors.bundle.js" (9.83KB)
|
||||
```
|
||||
|
||||
If you omit the out file, the bundle will be sent to `stdout`.
|
||||
|
||||
The bundle can just be run as any other module in Deno would:
|
||||
|
||||
```bash
|
||||
deno run colors.bundle.js
|
||||
```
|
||||
|
||||
The output is a self contained ES Module, where any exports from the main module
|
||||
supplied on the command line will be available. For example, if the main module
|
||||
looked something like this:
|
||||
|
||||
```ts
|
||||
export { foo } from "./foo.js";
|
||||
|
||||
export const bar = "bar";
|
||||
```
|
||||
|
||||
It could be imported like this:
|
||||
|
||||
```ts
|
||||
import { bar, foo } from "./lib.bundle.js";
|
||||
```
|
||||
|
||||
Bundles can also be loaded in the web browser. The bundle is a self-contained ES
|
||||
module, and so the attribute of `type` must be set to `"module"`. For example:
|
||||
|
||||
```html
|
||||
<script type="module" src="website.bundle.js"></script>
|
||||
```
|
||||
|
||||
Or you could import it into another ES module to consume:
|
||||
|
||||
```html
|
||||
<script type="module">
|
||||
import * as website from "website.bundle.js";
|
||||
</script>
|
||||
```
|
|
@ -1,36 +0,0 @@
|
|||
## Compiling Executables
|
||||
|
||||
`deno compile [--output <OUT>] <SRC>` will compile the script into a
|
||||
self-contained executable.
|
||||
|
||||
```
|
||||
> deno compile https://deno.land/std/examples/welcome.ts
|
||||
```
|
||||
|
||||
If you omit the `OUT` parameter, the name of the executable file will be
|
||||
inferred.
|
||||
|
||||
### Flags
|
||||
|
||||
As with [`deno install`](./script_installer.md), the runtime flags used to
|
||||
execute the script must be specified at compilation time. This includes
|
||||
permission flags.
|
||||
|
||||
```
|
||||
> deno compile --allow-read --allow-net https://deno.land/std/http/file_server.ts
|
||||
```
|
||||
|
||||
[Script arguments](../getting_started/command_line_interface.md#script-arguments)
|
||||
can be partially embedded.
|
||||
|
||||
```
|
||||
> deno compile --allow-read --allow-net https://deno.land/std/http/file_server.ts -p 8080
|
||||
> ./file_server --help
|
||||
```
|
||||
|
||||
### Cross Compilation
|
||||
|
||||
You can compile binaries for other platforms by adding the `--target` CLI flag.
|
||||
Deno currently supports compiling to Windows x64, macOS x64, macOS ARM and Linux
|
||||
x64. Use `deno compile --help` to list the full values for each compilation
|
||||
target.
|
|
@ -1,74 +0,0 @@
|
|||
## Dependency Inspector
|
||||
|
||||
`deno info [URL]` will inspect ES module and all of its dependencies.
|
||||
|
||||
```shell
|
||||
deno info https://deno.land/std@0.67.0/http/file_server.ts
|
||||
Download https://deno.land/std@0.67.0/http/file_server.ts
|
||||
...
|
||||
local: /home/deno/.cache/deno/deps/https/deno.land/f57792e36f2dbf28b14a75e2372a479c6392780d4712d76698d5031f943c0020
|
||||
type: TypeScript
|
||||
compiled: /home/deno/.cache/deno/gen/https/deno.land/f57792e36f2dbf28b14a75e2372a479c6392780d4712d76698d5031f943c0020.js
|
||||
deps: 23 unique (total 139.89KB)
|
||||
https://deno.land/std@0.67.0/http/file_server.ts (10.49KB)
|
||||
├─┬ https://deno.land/std@0.67.0/path/mod.ts (717B)
|
||||
│ ├── https://deno.land/std@0.67.0/path/_constants.ts (2.35KB)
|
||||
│ ├─┬ https://deno.land/std@0.67.0/path/win32.ts (27.36KB)
|
||||
│ │ ├── https://deno.land/std@0.67.0/path/_interface.ts (657B)
|
||||
│ │ ├── https://deno.land/std@0.67.0/path/_constants.ts *
|
||||
│ │ ├─┬ https://deno.land/std@0.67.0/path/_util.ts (3.3KB)
|
||||
│ │ │ ├── https://deno.land/std@0.67.0/path/_interface.ts *
|
||||
│ │ │ └── https://deno.land/std@0.67.0/path/_constants.ts *
|
||||
│ │ └── https://deno.land/std@0.67.0/_util/assert.ts (405B)
|
||||
│ ├─┬ https://deno.land/std@0.67.0/path/posix.ts (12.67KB)
|
||||
│ │ ├── https://deno.land/std@0.67.0/path/_interface.ts *
|
||||
│ │ ├── https://deno.land/std@0.67.0/path/_constants.ts *
|
||||
│ │ └── https://deno.land/std@0.67.0/path/_util.ts *
|
||||
│ ├─┬ https://deno.land/std@0.67.0/path/common.ts (1.14KB)
|
||||
│ │ └─┬ https://deno.land/std@0.67.0/path/separator.ts (264B)
|
||||
│ │ └── https://deno.land/std@0.67.0/path/_constants.ts *
|
||||
│ ├── https://deno.land/std@0.67.0/path/separator.ts *
|
||||
│ ├── https://deno.land/std@0.67.0/path/_interface.ts *
|
||||
│ └─┬ https://deno.land/std@0.67.0/path/glob.ts (8.12KB)
|
||||
│ ├── https://deno.land/std@0.67.0/path/_constants.ts *
|
||||
│ ├── https://deno.land/std@0.67.0/path/mod.ts *
|
||||
│ └── https://deno.land/std@0.67.0/path/separator.ts *
|
||||
├─┬ https://deno.land/std@0.67.0/http/server.ts (10.23KB)
|
||||
│ ├── https://deno.land/std@0.67.0/encoding/utf8.ts (433B)
|
||||
│ ├─┬ https://deno.land/std@0.67.0/io/bufio.ts (21.15KB)
|
||||
│ │ ├── https://deno.land/std@0.67.0/bytes/mod.ts (4.34KB)
|
||||
│ │ └── https://deno.land/std@0.67.0/_util/assert.ts *
|
||||
│ ├── https://deno.land/std@0.67.0/_util/assert.ts *
|
||||
│ ├─┬ https://deno.land/std@0.67.0/async/mod.ts (202B)
|
||||
│ │ ├── https://deno.land/std@0.67.0/async/deferred.ts (1.03KB)
|
||||
│ │ ├── https://deno.land/std@0.67.0/async/delay.ts (279B)
|
||||
│ │ ├─┬ https://deno.land/std@0.67.0/async/mux_async_iterator.ts (1.98KB)
|
||||
│ │ │ └── https://deno.land/std@0.67.0/async/deferred.ts *
|
||||
│ │ └── https://deno.land/std@0.67.0/async/pool.ts (1.58KB)
|
||||
│ └─┬ https://deno.land/std@0.67.0/http/_io.ts (11.25KB)
|
||||
│ ├── https://deno.land/std@0.67.0/io/bufio.ts *
|
||||
│ ├─┬ https://deno.land/std@0.67.0/textproto/mod.ts (4.52KB)
|
||||
│ │ ├── https://deno.land/std@0.67.0/io/bufio.ts *
|
||||
│ │ ├── https://deno.land/std@0.67.0/bytes/mod.ts *
|
||||
│ │ └── https://deno.land/std@0.67.0/encoding/utf8.ts *
|
||||
│ ├── https://deno.land/std@0.67.0/_util/assert.ts *
|
||||
│ ├── https://deno.land/std@0.67.0/encoding/utf8.ts *
|
||||
│ ├── https://deno.land/std@0.67.0/http/server.ts *
|
||||
│ └── https://deno.land/std@0.67.0/http/http_status.ts (5.93KB)
|
||||
├─┬ https://deno.land/std@0.67.0/flags/mod.ts (9.54KB)
|
||||
│ └── https://deno.land/std@0.67.0/_util/assert.ts *
|
||||
└── https://deno.land/std@0.67.0/_util/assert.ts *
|
||||
```
|
||||
|
||||
Dependency inspector works with any local or remote ES modules.
|
||||
|
||||
## Cache location
|
||||
|
||||
`deno info` can be used to display information about cache location:
|
||||
|
||||
```shell
|
||||
deno info
|
||||
DENO_DIR location: "/Users/deno/Library/Caches/deno"
|
||||
Remote modules cache: "/Users/deno/Library/Caches/deno/deps"
|
||||
TypeScript compiler cache: "/Users/deno/Library/Caches/deno/gen"
|
||||
```
|
|
@ -1,31 +0,0 @@
|
|||
## Documentation Generator
|
||||
|
||||
`deno doc` followed by a list of one or more source files will print the JSDoc
|
||||
documentation for each of the module's **exported** members.
|
||||
|
||||
For example, given a file `add.ts` with the contents:
|
||||
|
||||
```ts
|
||||
/**
|
||||
* Adds x and y.
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
* @returns {number} Sum of x and y
|
||||
*/
|
||||
export function add(x: number, y: number): number {
|
||||
return x + y;
|
||||
}
|
||||
```
|
||||
|
||||
Running the Deno `doc` command, prints the function's JSDoc comment to `stdout`:
|
||||
|
||||
```shell
|
||||
deno doc add.ts
|
||||
function add(x: number, y: number): number
|
||||
Adds x and y. @param {number} x @param {number} y @returns {number} Sum of x and y
|
||||
```
|
||||
|
||||
Use the `--json` flag to output the documentation in JSON format. This JSON
|
||||
format is consumed by the
|
||||
[deno doc website](https://github.com/denoland/doc_website) and is used to
|
||||
generate module documentation.
|
|
@ -1,29 +0,0 @@
|
|||
## Code formatter
|
||||
|
||||
Deno ships with a built in code formatter that auto-formats TypeScript and
|
||||
JavaScript code.
|
||||
|
||||
```shell
|
||||
# format all JS/TS files in the current directory and subdirectories
|
||||
deno fmt
|
||||
# format specific files
|
||||
deno fmt myfile1.ts myfile2.ts
|
||||
# check if all the JS/TS files in the current directory and subdirectories are formatted
|
||||
deno fmt --check
|
||||
# format stdin and write to stdout
|
||||
cat file.ts | deno fmt -
|
||||
```
|
||||
|
||||
Ignore formatting code by preceding it with a `// deno-fmt-ignore` comment:
|
||||
|
||||
```ts
|
||||
// deno-fmt-ignore
|
||||
export const identity = [
|
||||
1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1,
|
||||
];
|
||||
```
|
||||
|
||||
Or ignore an entire file by adding a `// deno-fmt-ignore-file` comment at the
|
||||
top of the file.
|
|
@ -1,150 +0,0 @@
|
|||
## Linter
|
||||
|
||||
Deno ships with a built in code linter for JavaScript and TypeScript.
|
||||
|
||||
```shell
|
||||
# lint all JS/TS files in the current directory and subdirectories
|
||||
deno lint
|
||||
# lint specific files
|
||||
deno lint myfile1.ts myfile2.ts
|
||||
# print result as JSON
|
||||
deno lint --json
|
||||
# read from stdin
|
||||
cat file.ts | deno lint -
|
||||
```
|
||||
|
||||
For more detail, run `deno lint --help`.
|
||||
|
||||
### Available rules
|
||||
|
||||
- `adjacent-overload-signatures`
|
||||
- `ban-ts-comment`
|
||||
- `ban-types`
|
||||
- `ban-untagged-ignore`
|
||||
- `camelcase`
|
||||
- `constructor-super`
|
||||
- `for-direction`
|
||||
- `getter-return`
|
||||
- `no-array-constructor`
|
||||
- `no-async-promise-executor`
|
||||
- `no-case-declarations`
|
||||
- `no-class-assign`
|
||||
- `no-compare-neg-zero`
|
||||
- `no-cond-assign`
|
||||
- `no-constant-condition`
|
||||
- `no-control-regex`
|
||||
- `no-debugger`
|
||||
- `no-delete-var`
|
||||
- `no-deprecated-deno-api`
|
||||
- `no-dupe-args`
|
||||
- `no-dupe-class-members`
|
||||
- `no-dupe-else-if`
|
||||
- `no-dupe-keys`
|
||||
- `no-duplicate-case`
|
||||
- `no-empty`
|
||||
- `no-empty-character-class`
|
||||
- `no-empty-interface`
|
||||
- `no-empty-pattern`
|
||||
- `no-ex-assign`
|
||||
- `no-explicit-any`
|
||||
- `no-extra-boolean-cast`
|
||||
- `no-extra-non-null-assertion`
|
||||
- `no-extra-semi`
|
||||
- `no-fallthrough`
|
||||
- `no-func-assign`
|
||||
- `no-global-assign`
|
||||
- `no-import-assign`
|
||||
- `no-inferrable-types`
|
||||
- `no-inner-declarations`
|
||||
- `no-invalid-regexp`
|
||||
- `no-irregular-whitespace`
|
||||
- `no-misused-new`
|
||||
- `no-mixed-spaces-and-tabs`
|
||||
- `no-namespace`
|
||||
- `no-new-symbol`
|
||||
- `no-obj-calls`
|
||||
- `no-octal`
|
||||
- `no-prototype-builtins`
|
||||
- `no-redeclare`
|
||||
- `no-regex-spaces`
|
||||
- `no-self-assign`
|
||||
- `no-setter-return`
|
||||
- `no-shadow-restricted-names`
|
||||
- `no-this-alias`
|
||||
- `no-this-before-super`
|
||||
- `no-unreachable`
|
||||
- `no-unsafe-finally`
|
||||
- `no-unsafe-negation`
|
||||
- `no-unused-labels`
|
||||
- `no-unused-vars`
|
||||
- `no-with`
|
||||
- `prefer-as-const`
|
||||
- `prefer-const`
|
||||
- `prefer-namespace-keyword`
|
||||
- `require-await`
|
||||
- `require-yield`
|
||||
- `use-isnan`
|
||||
- `valid-typeof`
|
||||
|
||||
For more detail about each rule, visit
|
||||
[the deno_lint rule documentation](https://lint.deno.land).
|
||||
|
||||
### Ignore directives
|
||||
|
||||
#### Files
|
||||
|
||||
To ignore whole file `// deno-lint-ignore-file` directive should placed at the
|
||||
top of the file:
|
||||
|
||||
```ts
|
||||
// deno-lint-ignore-file
|
||||
|
||||
function foo(): any {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Ignore directive must be placed before first statement or declaration:
|
||||
|
||||
```ts
|
||||
// Copyright 2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
/**
|
||||
* Some JS doc
|
||||
**/
|
||||
|
||||
// deno-lint-ignore-file
|
||||
|
||||
import { bar } from "./bar.js";
|
||||
|
||||
function foo(): any {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
You can also ignore certain diagnostics in the whole file
|
||||
|
||||
```ts
|
||||
// deno-lint-ignore-file no-explicit-any no-empty
|
||||
|
||||
function foo(): any {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### Diagnostics
|
||||
|
||||
To ignore certain diagnostic `// deno-lint-ignore <codes...>` directive should
|
||||
be placed before offending line. Specifying ignored rule name is required:
|
||||
|
||||
```ts
|
||||
// deno-lint-ignore no-explicit-any
|
||||
function foo(): any {
|
||||
// ...
|
||||
}
|
||||
|
||||
// deno-lint-ignore no-explicit-any explicit-function-return-type
|
||||
function bar(a: any) {
|
||||
// ...
|
||||
}
|
||||
```
|
|
@ -1,52 +0,0 @@
|
|||
# Read-eval-print-loop
|
||||
|
||||
`deno repl` starts an read-eval-print-loop, which lets you interactively build
|
||||
up program state in the global context.
|
||||
|
||||
## Keyboard shortcuts
|
||||
|
||||
| Keystroke | Action |
|
||||
| --------------------- | ------------------------------------------------------------------------------------------------ |
|
||||
| Ctrl-A, Home | Move cursor to the beginning of line |
|
||||
| Ctrl-B, Left | Move cursor one character left |
|
||||
| Ctrl-C | Interrupt and cancel the current edit |
|
||||
| Ctrl-D | If if line _is_ empty, signal end of line |
|
||||
| Ctrl-D, Del | If line is _not_ empty, delete character under cursor |
|
||||
| Ctrl-E, End | Move cursor to end of line |
|
||||
| Ctrl-F, Right | Move cursor one character right |
|
||||
| Ctrl-H, Backspace | Delete character before cursor |
|
||||
| Ctrl-I, Tab | Next completion |
|
||||
| Ctrl-J, Ctrl-M, Enter | Finish the line entry |
|
||||
| Ctrl-K | Delete from cursor to end of line |
|
||||
| Ctrl-L | Clear screen |
|
||||
| Ctrl-N, Down | Next match from history |
|
||||
| Ctrl-P, Up | Previous match from history |
|
||||
| Ctrl-R | Reverse Search history (Ctrl-S forward, Ctrl-G cancel) |
|
||||
| Ctrl-T | Transpose previous character with current character |
|
||||
| Ctrl-U | Delete from start of line to cursor |
|
||||
| Ctrl-V | Insert any special character without performing its associated action |
|
||||
| Ctrl-W | Delete word leading up to cursor (using white space as a word boundary) |
|
||||
| Ctrl-X Ctrl-U | Undo |
|
||||
| Ctrl-Y | Paste from Yank buffer |
|
||||
| Ctrl-Y | Paste from Yank buffer (Meta-Y to paste next yank instead) |
|
||||
| Ctrl-Z | Suspend (Unix only) |
|
||||
| Ctrl-_ | Undo |
|
||||
| Meta-0, 1, ..., - | Specify the digit to the argument. `–` starts a negative argument. |
|
||||
| Meta-< | Move to first entry in history |
|
||||
| Meta-> | Move to last entry in history |
|
||||
| Meta-B, Alt-Left | Move cursor to previous word |
|
||||
| Meta-Backspace | Kill from the start of the current word, or, if between words, to the start of the previous word |
|
||||
| Meta-C | Capitalize the current word |
|
||||
| Meta-D | Delete forwards one word |
|
||||
| Meta-F, Alt-Right | Move cursor to next word |
|
||||
| Meta-L | Lower-case the next word |
|
||||
| Meta-T | Transpose words |
|
||||
| Meta-U | Upper-case the next word |
|
||||
| Meta-Y | See Ctrl-Y |
|
||||
|
||||
## Special variables
|
||||
|
||||
| Identifier | Description |
|
||||
| ---------- | ------------------------------------ |
|
||||
| _ | Yields the last evaluated expression |
|
||||
| _error | Yields the last thrown error |
|
|
@ -1,90 +0,0 @@
|
|||
## Script installer
|
||||
|
||||
Deno provides `deno install` to easily install and distribute executable code.
|
||||
|
||||
`deno install [OPTIONS...] [URL] [SCRIPT_ARGS...]` will install the script
|
||||
available at `URL` under the name `EXE_NAME`.
|
||||
|
||||
This command creates a thin, executable shell script which invokes `deno` using
|
||||
the specified CLI flags and main module. It is placed in the installation root's
|
||||
`bin` directory.
|
||||
|
||||
Example:
|
||||
|
||||
```shell
|
||||
$ deno install --allow-net --allow-read https://deno.land/std@$STD_VERSION/http/file_server.ts
|
||||
[1/1] Compiling https://deno.land/std@$STD_VERSION/http/file_server.ts
|
||||
|
||||
✅ Successfully installed file_server.
|
||||
/Users/deno/.deno/bin/file_server
|
||||
```
|
||||
|
||||
To change the executable name, use `-n`/`--name`:
|
||||
|
||||
```shell
|
||||
deno install --allow-net --allow-read -n serve https://deno.land/std@$STD_VERSION/http/file_server.ts
|
||||
```
|
||||
|
||||
The executable name is inferred by default:
|
||||
|
||||
- Attempt to take the file stem of the URL path. The above example would become
|
||||
'file_server'.
|
||||
- If the file stem is something generic like 'main', 'mod', 'index' or 'cli',
|
||||
and the path has no parent, take the file name of the parent path. Otherwise
|
||||
settle with the generic name.
|
||||
- If the resulting name has an '@...' suffix, strip it.
|
||||
|
||||
To change the installation root, use `--root`:
|
||||
|
||||
```shell
|
||||
deno install --allow-net --allow-read --root /usr/local https://deno.land/std@$STD_VERSION/http/file_server.ts
|
||||
```
|
||||
|
||||
The installation root is determined, in order of precedence:
|
||||
|
||||
- `--root` option
|
||||
- `DENO_INSTALL_ROOT` environment variable
|
||||
- `$HOME/.deno`
|
||||
|
||||
These must be added to the path manually if required.
|
||||
|
||||
```shell
|
||||
echo 'export PATH="$HOME/.deno/bin:$PATH"' >> ~/.bashrc
|
||||
```
|
||||
|
||||
You must specify permissions that will be used to run the script at installation
|
||||
time.
|
||||
|
||||
```shell
|
||||
deno install --allow-net --allow-read https://deno.land/std@$STD_VERSION/http/file_server.ts -p 8080
|
||||
```
|
||||
|
||||
The above command creates an executable called `file_server` that runs with
|
||||
network and read permissions and binds to port 8080.
|
||||
|
||||
For good practice, use the [`import.meta.main`](../examples/module_metadata.md)
|
||||
idiom to specify the entry point in an executable script.
|
||||
|
||||
Example:
|
||||
|
||||
<!-- deno-fmt-ignore -->
|
||||
|
||||
```ts
|
||||
// https://example.com/awesome/cli.ts
|
||||
async function myAwesomeCli(): Promise<void> {
|
||||
-- snip --
|
||||
}
|
||||
|
||||
if (import.meta.main) {
|
||||
myAwesomeCli();
|
||||
}
|
||||
```
|
||||
|
||||
When you create an executable script make sure to let users know by adding an
|
||||
example installation command to your repository:
|
||||
|
||||
```shell
|
||||
# Install using deno install
|
||||
|
||||
$ deno install -n awesome_cli https://example.com/awesome/cli.ts
|
||||
```
|
|
@ -1,10 +0,0 @@
|
|||
# Using TypeScript
|
||||
|
||||
In this chapter we will discuss:
|
||||
|
||||
- [Overview of TypeScript in Deno](./typescript/overview.md)
|
||||
- [Configuring TypeScript in Deno](./typescript/configuration.md)
|
||||
- [Types and Type Declarations](./typescript/types.md)
|
||||
- [Migrating to/from JavaScript](./typescript/migration.md)
|
||||
- [Runtime compiler APIs](./typescript/runtime.md)
|
||||
- [FAQs about TypeScript in Deno](./typescript/faqs.md)
|
|
@ -1,206 +0,0 @@
|
|||
## Configuring TypeScript in Deno
|
||||
|
||||
TypeScript comes with a load of different options that can be configured, but
|
||||
Deno strives to make it easy to use TypeScript with Deno. Lots of different
|
||||
options frustrates that goal. To make things easier, Deno configures TypeScript
|
||||
to "just work" and shouldn't require additional configuration.
|
||||
|
||||
That being said, Deno does support using a TypeScript configuration file, though
|
||||
like the rest of Deno, the detection and use of a configuration file is not
|
||||
automatic. To use a TypeScript configuration file with Deno, you have to provide
|
||||
a path on the command line. For example:
|
||||
|
||||
```
|
||||
> deno run --config ./tsconfig.json main.ts
|
||||
```
|
||||
|
||||
> ⚠️ Do consider though that if you are creating libraries that require a
|
||||
> configuration file, all of the consumers of your modules will require that
|
||||
> configuration file too if you distribute your modules as TypeScript. In
|
||||
> addition, there could be settings you do in the configuration file that make
|
||||
> other TypeScript modules incompatible. Honestly it is best to use the Deno
|
||||
> defaults and to think long and hard about using a configuration file.
|
||||
|
||||
### How Deno uses a configuration file
|
||||
|
||||
Deno does not process a TypeScript configuration file like `tsc` does, as there
|
||||
are lots of parts of a TypeScript configuration file that are meaningless in a
|
||||
Deno context or would cause Deno to not function properly if they were applied.
|
||||
|
||||
Deno only looks at the `compilerOptions` section of a configuration file, and
|
||||
even then it only considers certain compiler options, with the rest being
|
||||
ignored.
|
||||
|
||||
Here is a table of compiler options that can be changed, their default in Deno
|
||||
and any other notes about that option:
|
||||
|
||||
| Option | Default | Notes |
|
||||
| -------------------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `allowJs` | `true` | This almost never needs to be changed |
|
||||
| `allowUnreachableCode` | `false` | |
|
||||
| `allowUnusedLabels` | `false` | |
|
||||
| `checkJs` | `false` | If `true` causes TypeScript to type check JavaScript |
|
||||
| `experimentalDecorators` | `true` | We enable these by default as they are already opt-in in the code and when we skip type checking, the Rust based emitter has them on by default. We strongly discourage the use of legacy decorators, as they are incompatible with the future decorators standard in JavaScript |
|
||||
| `jsx` | `"react"` | |
|
||||
| `jsxFactory` | `"React.createElement"` | |
|
||||
| `jsxFragmentFactory` | `"React.Fragment"` | |
|
||||
| `keyofStringsOnly` | `false` | |
|
||||
| `lib` | `[ "deno.window" ]` | The default for this varies based on other settings in Deno. If it is supplied, it overrides the default. See below for more information. |
|
||||
| `noFallthroughCasesInSwitch` | `false` | |
|
||||
| `noImplicitAny` | `true` | |
|
||||
| `noImplicitReturns` | `false` | |
|
||||
| `noImplicitThis` | `true` | |
|
||||
| `noImplicitUseStrict` | `true` | |
|
||||
| `noStrictGenericChecks` | `false` | |
|
||||
| `noUnusedLocals` | `false` | |
|
||||
| `noUnusedParameters` | `false` | |
|
||||
| `noUncheckedIndexedAccess` | `false` | |
|
||||
| `reactNamespace` | `React` | |
|
||||
| `strict` | `true` | |
|
||||
| `strictBindCallApply` | `true` | |
|
||||
| `strictFunctionTypes` | `true` | |
|
||||
| `strictPropertyInitialization` | `true` | |
|
||||
| `strictNullChecks` | `true` | |
|
||||
| `suppressExcessPropertyErrors` | `false` | |
|
||||
| `suppressImplicitAnyIndexErrors` | `false` | |
|
||||
|
||||
For a full list of compiler options and how they affect TypeScript, please refer
|
||||
to the
|
||||
[TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/compiler-options.html)
|
||||
|
||||
### What an implied tsconfig.json looks like
|
||||
|
||||
It is impossible to get `tsc` to behave like Deno. It is also difficult to get
|
||||
the TypeScript language service to behave like Deno. This is why we have built a
|
||||
language service directly into Deno. That being said, it can be useful to
|
||||
understand what is implied.
|
||||
|
||||
If you were to write a `tsconfig.json` for Deno, it would look something like
|
||||
this:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"esModuleInterop": true,
|
||||
"experimentalDecorators": true,
|
||||
"inlineSourceMap": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "react",
|
||||
"lib": ["deno.window"],
|
||||
"module": "esnext",
|
||||
"strict": true,
|
||||
"target": "esnext",
|
||||
"useDefineForClassFields": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can't copy paste this into a `tsconfig.json` and get it to work,
|
||||
specifically because of the built in type libraries that are custom to Deno
|
||||
which are provided to the TypeScript compiler. This can somewhat be mocked by
|
||||
running `deno types` on the command line and piping the output to a file and
|
||||
including that in the files as part of the program, removing the `"lib"` option,
|
||||
and setting the `"noLib"` option to `true`.
|
||||
|
||||
If you use the `--unstable` flag, Deno will change the `"lib"` option to
|
||||
`[ "deno.window", "deno.unstable" ]`. If you are trying to load a worker, that
|
||||
is type checked with `"deno.worker"` instead of `"deno.window"`. See
|
||||
[Type Checking Web Workers](./types#type-checking-web-workers) for more
|
||||
information on this.
|
||||
|
||||
### Using the "lib" property
|
||||
|
||||
Deno has several libraries built into it that are not present in other
|
||||
platforms, like `tsc`. This is what enables Deno to properly check code written
|
||||
for Deno. In some situations though, this automatic behavior can cause
|
||||
challenges, for example like writing code that is intended to also run in a
|
||||
browser. In these situations the `"lib"` property of a `tsconfig.json` can be
|
||||
used to modify the behavior of Deno when type checking code.
|
||||
|
||||
The built-in libraries that are of interest to users:
|
||||
|
||||
- `"deno.ns"` - This includes all the custom `Deno` global namespace APIs plus
|
||||
the Deno additions to `import.meta`. This should generally not conflict with
|
||||
other libraries or global types.
|
||||
- `"deno.unstable"` - This includes the addition unstable `Deno` global
|
||||
namespace APIs.
|
||||
- `"deno.window"` - This is the "default" library used when checking Deno main
|
||||
runtime scripts. It includes the `"deno.ns"` as well as other type libraries
|
||||
for the extensions that are built into Deno. This library will conflict with
|
||||
libraries like `"dom"` and `"dom.iterable"` that are standard TypeScript
|
||||
libraries.
|
||||
- `"deno.worker"` - This is the library used when checking a Deno web worker
|
||||
script. For more information about web workers, check out
|
||||
[Type Checking Web Workers](./types#type-checking-web-workers).
|
||||
- `"dom.asynciterable"` - TypeScript currently does not include the DOM async
|
||||
iterables that Deno implements (plus several browsers), so we have implemented
|
||||
it ourselves until it becomes available in TypeScript.
|
||||
|
||||
These are common libraries that Deno doesn't use, but are useful when writing
|
||||
code that is intended to also work in another runtime:
|
||||
|
||||
- `"dom"` - The main browser global library that ships with TypeScript. The type
|
||||
definitions conflict in many ways with `"deno.window"` and so if `"dom"` is
|
||||
used, then consider using just `"deno.ns"` to expose the Deno specific APIs.
|
||||
- `"dom.iterable"` - The iterable extensions to the browser global library.
|
||||
- `"scripthost"` - The library for the Microsoft Windows Script Host.
|
||||
- `"webworker"` - The main library for web workers in the browser. Like `"dom"`
|
||||
this will conflict with `"deno.window"` or `"deno.worker"`, so consider using
|
||||
just `"deno.ns"` to expose the Deno specific APIs.
|
||||
- `"webworker.importscripts"` - The library that exposes the `importScripts()`
|
||||
API in the web worker.
|
||||
- `"webworker.iterable"` - The library that adds iterables to objects within a
|
||||
web worker. Modern browsers support this.
|
||||
|
||||
#### Targeting Deno and the Browser
|
||||
|
||||
A common use case is writing code that works in Deno and the browser, and have
|
||||
the code "sniff" to determine if it is running in the browser or in Deno. If
|
||||
that is the case a common configuration of a `tsconfig.json` would look like
|
||||
this:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"lib": ["dom", "dom.iterable", "dom.asynciterable", "deno.ns"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This should allow most code to be type checked properly by Deno.
|
||||
|
||||
If you expect to run the code in Deno with the `--unstable` flag, then you will
|
||||
want to add that library to the mix as well:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"dom.asynciterable",
|
||||
"deno.ns",
|
||||
"deno.unstable"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Typically when you use the `"lib"` option in TypeScript, you need to include an
|
||||
"es" library as well. In the case of `"deno.ns"` and `"deno.unstable"`, they
|
||||
automatically include `"esnext"` when you bring them in.
|
||||
|
||||
The biggest "danger" when doing something like this, is that the type checking
|
||||
is significantly looser, and there is no way to validate that you are doing
|
||||
sufficient and effective feature detection in your code, which may lead to what
|
||||
could be trivial errors becoming runtime errors.
|
||||
|
||||
### Using the "types" property
|
||||
|
||||
The `"types"` property in `"compilerOptions"` can be used to specify arbitrary
|
||||
type definitions to include when type checking a programme. For more information
|
||||
on this see
|
||||
[Using ambient or global types](./types#using-ambient-or-global-types).
|
|
@ -1,136 +0,0 @@
|
|||
## FAQs about TypeScript in Deno
|
||||
|
||||
### Can I use TypeScript not written for Deno?
|
||||
|
||||
Maybe. That is the best answer, we are afraid. For lots of reasons, Deno has
|
||||
chosen to have fully qualified module specifiers. In part this is because it
|
||||
treats TypeScript as a first class language. Also, Deno uses explicit module
|
||||
resolution, with no _magic_. This is effectively the same way browsers
|
||||
themselves work, though they don't obviously support TypeScript directly. If the
|
||||
TypeScript modules use imports that don't have these design decisions in mind,
|
||||
they may not work under Deno.
|
||||
|
||||
Also, in recent versions of Deno (starting with 1.5), we have started to use a
|
||||
Rust library to do transformations of TypeScript to JavaScript in certain
|
||||
scenarios. Because of this, there are certain situations in TypeScript where
|
||||
type information is required, and therefore those are not supported under Deno.
|
||||
If you are using `tsc` as stand-alone, the setting to use is `"isolatedModules"`
|
||||
and setting it to `true` to help ensure that your code can be properly handled
|
||||
by Deno.
|
||||
|
||||
One of the ways to deal with the extension and the lack of Node.js non-standard
|
||||
resolution logic is to use
|
||||
[import maps](../linking_to_external_code/import_maps.md) which would allow you
|
||||
to specify "packages" of bare specifiers which then Deno could resolve and load.
|
||||
|
||||
### What version(s) of TypeScript does Deno support?
|
||||
|
||||
Deno is built with a specific version of TypeScript. To find out what this is,
|
||||
type the following on the command line:
|
||||
|
||||
```shell
|
||||
> deno --version
|
||||
```
|
||||
|
||||
The TypeScript version (along with the version of Deno and v8) will be printed.
|
||||
Deno tries to keep up to date with general releases of TypeScript, providing
|
||||
them in the next patch or minor release of Deno.
|
||||
|
||||
### There was a breaking change in the version of TypeScript that Deno uses, why did you break my program?
|
||||
|
||||
We do not consider changes in behavior or breaking changes in TypeScript
|
||||
releases as breaking changes for Deno. TypeScript is a generally mature language
|
||||
and breaking changes in TypeScript are almost always "good things" making code
|
||||
more sound, and it is best that we all keep our code sound. If there is a
|
||||
blocking change in the version of TypeScript and it isn't suitable to use an
|
||||
older release of Deno until the problem can be resolved, then you should be able
|
||||
to use `--no-check` to skip type checking all together.
|
||||
|
||||
In addition you can utilize `@ts-ignore` to _ignore_ a specific error in code
|
||||
that you control. You can also replace whole dependencies, using
|
||||
[import maps](../linking_to_external_code/import_maps), for situations where a
|
||||
dependency of a dependency isn't being maintained or has some sort of breaking
|
||||
change you want to bypass while waiting for it to be updated.
|
||||
|
||||
### How do I write code that works in Deno and a browser, but still type checks?
|
||||
|
||||
You can do this by using a `tsconfig.json` file with the `--config` option on
|
||||
the command line and adjusting the `"lib"` option in the `"compilerOptions"` in
|
||||
the file. For more information see
|
||||
[Targeting Deno and the Browser](./configuration#targeting-deno-and-the-browser).
|
||||
|
||||
### Why are you forcing me to use isolated modules, why can't I use const enums with Deno, why do I need to do export type?
|
||||
|
||||
As of Deno 1.5 we defaulted to _isolatedModules_ to `true` and in Deno 1.6 we
|
||||
removed the options to set it back to `false` via a configuration file. The
|
||||
_isolatedModules_ option forces the TypeScript compiler to check and emit
|
||||
TypeScript as if each module would stand on its own. TypeScript has a few _type
|
||||
directed emits_ in the language at the moment. While not allowing type directed
|
||||
emits into the language was a design goal for TypeScript, it has happened
|
||||
anyways. This means that the TypeScript compiler needs to understand the
|
||||
erasable types in the code to determine what to emit, which when you are trying
|
||||
to make a fully erasable type system on top of JavaScript, that becomes a
|
||||
problem.
|
||||
|
||||
When people started transpiling TypeScript without `tsc`, these type directed
|
||||
emits became a problem, since the likes of Babel simply try to erase the types
|
||||
without needing to understand the types to direct the emit. In the internals of
|
||||
Deno we have started to use a Rust based emitter which allows us to optionally
|
||||
skip type checking and generates the bundles for things like `deno bundle`. Like
|
||||
all transpilers, it doesn't care about the types, it just tries to erase them.
|
||||
This means in certain situations we cannot support those type directed emits.
|
||||
|
||||
So instead of trying to get every user to understand when and how we could
|
||||
support the type directed emits, we made the decision to disable the use of them
|
||||
by forcing the _isolatedModules_ option to `true`. This means that even when we
|
||||
are using the TypeScript compiler to emit the code, it will follow the same
|
||||
"rules" that the Rust based emitter follows.
|
||||
|
||||
This means that certain language features are not supportable. Those features
|
||||
are:
|
||||
|
||||
- Re-exporting of types is ambiguous and requires knowing if the source module
|
||||
is exporting runtime code or just type information. Therefore, it is
|
||||
recommended that you use `import type` and `export type` for type only imports
|
||||
and exports. This will help ensure that when the code is emitted, that all the
|
||||
types are erased.
|
||||
- `const enum` is not supported. `const enum`s require type information to
|
||||
direct the emit, as `const enum`s get written out as hard coded values.
|
||||
Especially when `const enum`s get exported, they are a type system only
|
||||
construct.
|
||||
- `export =` and `import =` are legacy TypeScript syntax which we do not
|
||||
support.
|
||||
- Only `declare namespace` is support. Runtime `namespace` is legacy TypeScript
|
||||
syntax that is not supported.
|
||||
|
||||
### Why don't you support language service plugins or transformer plugins?
|
||||
|
||||
While `tsc` supports language service plugins, Deno does not. Deno does not
|
||||
always use the built in TypeScript compiler to do what it does, and the
|
||||
complexity of adding support for a language service plugin is not feasible.
|
||||
TypeScript does not support emitter plugins, but there are a few community
|
||||
projects which _hack_ emitter plugins into TypeScript. First, we wouldn't want
|
||||
to support something that TypeScript doesn't support, plus we do not always use
|
||||
the TypeScript compiler for the emit, which would mean we would need to ensure
|
||||
we supported it in all modes, and the other emitter is written in Rust, meaning
|
||||
that any emitter plugin for TypeScript wouldn't be available for the Rust
|
||||
emitter.
|
||||
|
||||
The TypeScript in Deno isn't intended to be a fully flexible TypeScript
|
||||
compiler. Its main purpose is to ensure that TypeScript and JavaScript can run
|
||||
under Deno. The secondary ability to do TypeScript and JavaScript emitting via
|
||||
the runtime API `Deno.emit()` is intended to be simple and straight forward and
|
||||
support a certain set of use cases.
|
||||
|
||||
### How do I combine Deno code with non-Deno code in my IDE?
|
||||
|
||||
The Deno language server supports the ability to have a "per-resource"
|
||||
configuration of enabling Deno or not. This also requires a client IDE to
|
||||
support this ability. For Visual Studio Code the official
|
||||
[Deno extension](https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno)
|
||||
supports the vscode concept of
|
||||
[multi-root workspace](https://code.visualstudio.com/docs/editor/multi-root-workspaces).
|
||||
This means you just need to add folders to the workspace and set the
|
||||
`deno.enable` setting as required on each folder.
|
||||
|
||||
For other IDEs, the client extensions needs to support the similar IDE concepts.
|
|
@ -1,71 +0,0 @@
|
|||
## Migrating to and from JavaScript
|
||||
|
||||
One of the advantages of Deno is that it treats TypeScript and JavaScript pretty
|
||||
equally. This might mean that transitioning from JavaScript to TypeScript or
|
||||
even from TypeScript to JavaScript is something you want to accomplish. There
|
||||
are several features of Deno that can help with this.
|
||||
|
||||
### Type checking JavaScript
|
||||
|
||||
You might have some JavaScript that you would like to ensure is more type sound
|
||||
but you don't want to go through a process of adding type annotations
|
||||
everywhere.
|
||||
|
||||
Deno supports using the TypeScript type checker to type check JavaScript. You
|
||||
can mark any individual file by adding the check JavaScript pragma to the file:
|
||||
|
||||
```js
|
||||
// @ts-check
|
||||
```
|
||||
|
||||
This will cause the type checker to infer type information about the JavaScript
|
||||
code and raise any issues as diagnostic issues.
|
||||
|
||||
These can be turned on for all JavaScript files in a program by providing a
|
||||
configuration file with the check JS option enabled:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"checkJs": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And setting the `--config` option on the command line.
|
||||
|
||||
### Using JSDoc in JavaScript
|
||||
|
||||
If you are type checking JavaScript, or even importing JavaScript into
|
||||
TypeScript you can use JSDoc in JavaScript to express more types information
|
||||
than can just be inferred from the code itself. Deno supports this without any
|
||||
additional configuration, you simply need to annotate the code in line with the
|
||||
supported
|
||||
[TypeScript JSDoc](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html).
|
||||
For example to set the type of an array:
|
||||
|
||||
```js
|
||||
/** @type {string[]} */
|
||||
const a = [];
|
||||
```
|
||||
|
||||
### Skipping type checking
|
||||
|
||||
You might have TypeScript code that you are experimenting with, where the syntax
|
||||
is valid but not fully type safe. You can always bypass type checking for a
|
||||
whole program by passing the `--no-check`.
|
||||
|
||||
You can also skip whole files being type checked, including JavaScript if you
|
||||
have check JS enabled, by using the no-check pragma:
|
||||
|
||||
```js
|
||||
// @ts-nocheck
|
||||
```
|
||||
|
||||
### Just renaming JS files to TS files
|
||||
|
||||
While this might work in some cases, it has some severe limits in Deno. This is
|
||||
because Deno, by default, runs type checking in what is called _strict mode_.
|
||||
This means a lot of unclear or ambiguous situations where are not caught in
|
||||
non-strict mode will result in diagnostics being generated, and JavaScript is
|
||||
nothing but unclear and ambiguous when it comes to types.
|
|
@ -1,159 +0,0 @@
|
|||
## Overview of TypeScript in Deno
|
||||
|
||||
One of the benefits of Deno is that it treats TypeScript as a first class
|
||||
language, just like JavaScript or Web Assembly, when running code in Deno. What
|
||||
that means is you can run or import TypeScript without installing anything more
|
||||
than the Deno CLI.
|
||||
|
||||
_But wait a minute, does Deno really run TypeScript?_ you might be asking
|
||||
yourself. Well, depends on what you mean by run. One could argue that in a
|
||||
browser you don't actually _run_ JavaScript either. The JavaScript engine in the
|
||||
browser translates the JavaScript to a series of operation codes, which it then
|
||||
executes in a sandbox. So it translates JavaScript to something close to
|
||||
assembly. Even Web Assembly goes through a similar translation, in that Web
|
||||
Assembly is architecture agnostic while it needs to be translated into the
|
||||
machine specific operation codes needed for the particular platform architecture
|
||||
it is running on. So when we say TypeScript is a first class language in Deno,
|
||||
we mean that we try to make the user experience in authoring and running
|
||||
TypeScript as easy and straightforward as JavaScript and Web Assembly.
|
||||
|
||||
Behind the scenes, we use a combination of technologies, in Rust and JavaScript,
|
||||
to provide that experience.
|
||||
|
||||
### How does it work?
|
||||
|
||||
At a high level, Deno converts TypeScript (as well as TSX and JSX) into
|
||||
JavaScript. It does this via a combination of the
|
||||
[TypeScript compiler](https://github.com/microsoft/TypeScript), which we build
|
||||
into Deno, and a Rust library called [swc](https://swc.rs/). When the code has
|
||||
been type checked and transformed, it is stored in a cache, ready for the next
|
||||
run without the need to convert it from its source to JavaScript again.
|
||||
|
||||
You can see this cache location by running `deno info`:
|
||||
|
||||
```shell
|
||||
> deno info
|
||||
DENO_DIR location: "/path/to/cache/deno"
|
||||
Remote modules cache: "/path/to/cache/deno/deps"
|
||||
TypeScript compiler cache: "/path/to/cache/deno/gen"
|
||||
```
|
||||
|
||||
If you were to look in that cache, you would see a directory structure that
|
||||
mimics that source directory structure and individual `.js` and `.meta` files
|
||||
(also potentially `.map` files). The `.js` file is the transformed source file
|
||||
while the `.meta` file contains meta data we want to cache about the file, which
|
||||
at the moment contains a _hash_ of the source module that helps us manage cache
|
||||
invalidation. You might also see a `.buildinfo` file as well, which is a
|
||||
TypeScript compiler incremental build information file, which we cache to help
|
||||
speed up type checking.
|
||||
|
||||
### Type Checking
|
||||
|
||||
One of the main advantages of TypeScript is that you can make code more type
|
||||
safe, so that what would be syntactically valid JavaScript becomes TypeScript
|
||||
with warnings about being "unsafe".
|
||||
|
||||
In Deno we handle TypeScript in two major ways. We can type check TypeScript,
|
||||
the default, or you can opt into skipping that checking using the `--no-check`
|
||||
flag. For example if you had a program you wanted to run, normally you would do
|
||||
something like this:
|
||||
|
||||
```
|
||||
deno run --allow-net my_server.ts
|
||||
```
|
||||
|
||||
But if you wanted to skip the type checking, you would do something like this:
|
||||
|
||||
```
|
||||
deno run --allow-net --no-check my_server.ts
|
||||
```
|
||||
|
||||
Type checking can take a significant amount of time, especially if you are
|
||||
working on a code base where you are making a lot of changes. We have tried to
|
||||
optimise the type checking, but it still comes at a cost. If you just want to
|
||||
hack at some code, or if you are working in an IDE which is type checking your
|
||||
code as you author it, using `--no-check` can certainly speed up the process of
|
||||
running TypeScript in Deno.
|
||||
|
||||
### Determining the type of file
|
||||
|
||||
Since Deno supports JavaScript, TypeScript, JSX, TSX modules, Deno has to make a
|
||||
decision about how to treat each of these kinds of files. For local modules,
|
||||
Deno makes this determination based fully on the extension. When the extension
|
||||
is absent in a local file, it is assumed to be JavaScript.
|
||||
|
||||
For remote modules, the media type (mime-type) is used to determine the type of
|
||||
the module, where the path of the module is used to help influence the file
|
||||
type, when it is ambiguous what type of file it is.
|
||||
|
||||
For example, a `.d.ts` file and a `.ts` file have different semantics in
|
||||
TypeScript as well as have different ways they need to be handled in Deno. While
|
||||
we expect to convert a `.ts` file into JavaScript, a `.d.ts` file contains no
|
||||
"runnable" code, and is simply describing types (often of "plain" JavaScript).
|
||||
So when we fetch a remote module, the media type for a `.ts.` and `.d.ts` file
|
||||
looks the same. So we look at the path, and if we see something that has a path
|
||||
that ends with `.d.ts` we treat it as a type definition only file instead of
|
||||
"runnable" TypeScript.
|
||||
|
||||
#### Supported media types
|
||||
|
||||
The following table provides a list of media types which Deno supports when
|
||||
identifying the type of file of a remote module:
|
||||
|
||||
| Media Type | How File is Handled |
|
||||
| -------------------------- | ----------------------------------------------------------- |
|
||||
| `application/typescript` | TypeScript (with path extension influence) |
|
||||
| `text/typescript` | TypeScript (with path extension influence) |
|
||||
| `video/vnd.dlna.mpeg-tts` | TypeScript (with path extension influence) |
|
||||
| `video/mp2t` | TypeScript (with path extension influence) |
|
||||
| `application/x-typescript` | TypeScript (with path extension influence) |
|
||||
| `application/javascript` | JavaScript (with path extensions influence) |
|
||||
| `text/javascript` | JavaScript (with path extensions influence) |
|
||||
| `application/ecmascript` | JavaScript (with path extensions influence) |
|
||||
| `text/ecmascript` | JavaScript (with path extensions influence) |
|
||||
| `application/x-javascript` | JavaScript (with path extensions influence) |
|
||||
| `application/node` | JavaScript (with path extensions influence) |
|
||||
| `text/jsx` | JSX |
|
||||
| `text/tsx` | TSX |
|
||||
| `text/plain` | Attempt to determine that path extension, otherwise unknown |
|
||||
| `application/octet-stream` | Attempt to determine that path extension, otherwise unknown |
|
||||
|
||||
### Strict by default
|
||||
|
||||
Deno type checks TypeScript in _strict_ mode by default, and the TypeScript core
|
||||
team recommends _strict_ mode as a sensible default. This mode generally enables
|
||||
features of TypeScript that probably should have been there from the start, but
|
||||
as TypeScript continued to evolve, would be breaking changes for existing code.
|
||||
|
||||
### Mixing JavaScript and TypeScript
|
||||
|
||||
By default, Deno does not type check JavaScript. This can be changed, and is
|
||||
discussed further in [Configuring TypeScript in Deno](./configuration.md). Deno
|
||||
does support JavaScript importing TypeScript and TypeScript importing
|
||||
JavaScript, in complex scenarios.
|
||||
|
||||
An important note though is that when type checking TypeScript, by default Deno
|
||||
will "read" all the JavaScript in order to be able to evaluate how it might have
|
||||
an impact on the TypeScript types. The type checker will do the best it can to
|
||||
figure out what the types are of the JavaScript you import into TypeScript,
|
||||
including reading any JSDoc comments. Details of this are discussed in detail in
|
||||
the [Types and type declarations](./types.md) section.
|
||||
|
||||
### Diagnostics are terminal
|
||||
|
||||
While `tsc` by default will still emit JavaScript when run while encountering
|
||||
diagnostic (type checking) issues, Deno currently treats them as terminal. It
|
||||
will halt on these warnings, not cache any of the emitted files, and exit the
|
||||
process.
|
||||
|
||||
In order to avoid this, you will either need to resolve the issue, utilise the
|
||||
`// @ts-ignore` or `// @ts-expect-error` pragmas, or utilise `--no-check` to
|
||||
bypass type checking all together.
|
||||
|
||||
### Type resolution
|
||||
|
||||
One of the core design principles of Deno is to avoid non-standard module
|
||||
resolution, and this applies to type resolution as well. If you want to utilise
|
||||
JavaScript that has type definitions (e.g. a `.d.ts` file), you have to
|
||||
explicitly tell Deno about this. The details of how this is accomplished are
|
||||
covered in the [Types and type declarations](./types.md) section.
|
|
@ -1,270 +0,0 @@
|
|||
## Runtime compiler APIs
|
||||
|
||||
> ⚠️ The runtime compiler API is unstable (and requires the `--unstable` flag to
|
||||
> be used to enable it).
|
||||
|
||||
The runtime compiler API allows access to the internals of Deno to be able to
|
||||
type check, transpile and bundle JavaScript and TypeScript. As of Deno 1.7,
|
||||
several disparate APIs we consolidated into a single API, `Deno.emit()`.
|
||||
|
||||
### Deno.emit()
|
||||
|
||||
The API is defined in the `Deno` namespace as:
|
||||
|
||||
```ts
|
||||
function emit(
|
||||
rootSpecifier: string | URL,
|
||||
options?: EmitOptions,
|
||||
): Promise<EmitResult>;
|
||||
```
|
||||
|
||||
The emit options are defined in the `Deno` namespace as:
|
||||
|
||||
```ts
|
||||
interface EmitOptions {
|
||||
/** Indicate that the source code should be emitted to a single file
|
||||
* JavaScript bundle that is a single ES module (`"module"`) or a single
|
||||
* file self contained script we executes in an immediately invoked function
|
||||
* when loaded (`"classic"`). */
|
||||
bundle?: "module" | "classic";
|
||||
/** If `true` then the sources will be typed checked, returning any
|
||||
* diagnostic errors in the result. If `false` type checking will be
|
||||
* skipped. Defaults to `true`.
|
||||
*
|
||||
* *Note* by default, only TypeScript will be type checked, just like on
|
||||
* the command line. Use the `compilerOptions` options of `checkJs` to
|
||||
* enable type checking of JavaScript. */
|
||||
check?: boolean;
|
||||
/** A set of options that are aligned to TypeScript compiler options that
|
||||
* are supported by Deno. */
|
||||
compilerOptions?: CompilerOptions;
|
||||
/** An [import-map](https://deno.land/manual/linking_to_external_code/import_maps#import-maps)
|
||||
* which will be applied to the imports. */
|
||||
importMap?: ImportMap;
|
||||
/** An absolute path to an [import-map](https://deno.land/manual/linking_to_external_code/import_maps#import-maps).
|
||||
* Required to be specified if an `importMap` is specified to be able to
|
||||
* determine resolution of relative paths. If a `importMap` is not
|
||||
* specified, then it will assumed the file path points to an import map on
|
||||
* disk and will be attempted to be loaded based on current runtime
|
||||
* permissions.
|
||||
*/
|
||||
importMapPath?: string;
|
||||
/** A record of sources to use when doing the emit. If provided, Deno will
|
||||
* use these sources instead of trying to resolve the modules externally. */
|
||||
sources?: Record<string, string>;
|
||||
}
|
||||
```
|
||||
|
||||
The emit result is defined in the `Deno` namespace as:
|
||||
|
||||
```ts
|
||||
interface EmitResult {
|
||||
/** Diagnostic messages returned from the type checker (`tsc`). */
|
||||
diagnostics: Diagnostic[];
|
||||
/** Any emitted files. If bundled, then the JavaScript will have the
|
||||
* key of `deno:///bundle.js` with an optional map (based on
|
||||
* `compilerOptions`) in `deno:///bundle.js.map`. */
|
||||
files: Record<string, string>;
|
||||
/** An optional array of any compiler options that were ignored by Deno. */
|
||||
ignoredOptions?: string[];
|
||||
/** An array of internal statistics related to the emit, for diagnostic
|
||||
* purposes. */
|
||||
stats: Array<[string, number]>;
|
||||
}
|
||||
```
|
||||
|
||||
The API is designed to support several use cases, which are described in the
|
||||
sections below.
|
||||
|
||||
### Using external sources
|
||||
|
||||
Using external sources, both local and remote, `Deno.emit()` can behave like
|
||||
`deno cache` does on the command line, resolving those external dependencies,
|
||||
type checking those dependencies, and providing an emitted output.
|
||||
|
||||
By default, `Deno.emit()` will utilise external resources. The _rootSpecifier_
|
||||
supplied as the first argument will determine what module will be used as the
|
||||
root. The root module is similar to what you would provide on the command line.
|
||||
|
||||
For example if you did:
|
||||
|
||||
```
|
||||
> deno run mod.ts
|
||||
```
|
||||
|
||||
You could do something similar with `Deno.emit()`:
|
||||
|
||||
```ts
|
||||
try {
|
||||
const { files } = await Deno.emit("mod.ts");
|
||||
for (const [fileName, text] of Object.entries(files)) {
|
||||
console.log(`emitted ${fileName} with a length of ${text.length}`);
|
||||
}
|
||||
} catch (e) {
|
||||
// something went wrong, inspect `e` to determine
|
||||
}
|
||||
```
|
||||
|
||||
`Deno.emit()` will use the same on disk cache for remote modules that the
|
||||
standard CLI does, and it inherits the permissions and cache options of the
|
||||
process that executes it.
|
||||
|
||||
If the _rootSpecifier_ is a relative path, then the current working directory of
|
||||
the Deno process will be used to resolve the specifier. (Not relative to the
|
||||
current module!)
|
||||
|
||||
The _rootSpecifier_ can be a string file path, a string URL, or a URL.
|
||||
`Deno.emit()` supports the same protocols for URLs that Deno supports, which are
|
||||
currently `file`, `http`, `https`, and `data`.
|
||||
|
||||
### Providing sources
|
||||
|
||||
Instead of resolving modules externally, you can provide `Deno.emit()` with the
|
||||
sources directly. This is especially useful for a server to be able to provide
|
||||
_on demand_ compiling of code supplied by a user, where the Deno process has
|
||||
collected all the code it wants to emit.
|
||||
|
||||
The sources are passed in the _sources_ property of the `Deno.emit()` _options_
|
||||
argument:
|
||||
|
||||
```ts
|
||||
const { files } = await Deno.emit("/mod.ts", {
|
||||
sources: {
|
||||
"/mod.ts": `import * as a from "./a.ts";\nconsole.log(a);\n`,
|
||||
"/a.ts": `export const a: Record<string, string> = {};\n`,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
When sources are provided, Deno will no longer look externally and will try to
|
||||
resolve all modules from within the map of sources provided, though the module
|
||||
resolution follow the same rules as if the modules were external. For example
|
||||
all module specifiers need their full filename. Also, because there are no media
|
||||
types, if you are providing remote URLs in the sources, the path should end with
|
||||
the appropriate extension, so that Deno can determine how to handle the file.
|
||||
|
||||
### Type checking and emitting
|
||||
|
||||
By default, `Deno.emit()` will type check any TypeScript (and TSX) it
|
||||
encounters, just like on the command line. It will also attempt to transpile
|
||||
JSX, but will leave JavaScript "alone". This behavior can be changed by changing
|
||||
the compiler options. For example if you wanted Deno to type check your
|
||||
JavaScript as well, you could set the _checkJs_ option to `true` in the compiler
|
||||
options:
|
||||
|
||||
```ts
|
||||
const { files, diagnostics } = await Deno.emit("./mod.js", {
|
||||
compilerOptions: {
|
||||
checkJs: true,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The `Deno.emit()` result provides any diagnostic messages about the code
|
||||
supplied. On the command line, any diagnostic messages get logged to stderr and
|
||||
the Deno process terminates, but with `Deno.emit()` they are returned to the
|
||||
caller.
|
||||
|
||||
Typically you will want to check if there are any diagnostics and handle them
|
||||
appropriately. You can introspect the diagnostics individually, but there is a
|
||||
handy formatting function available to make it easier to potentially log the
|
||||
diagnostics to the console for the user called `Deno.formatDiagnostics()`:
|
||||
|
||||
```ts
|
||||
const { files, diagnostics } = await Deno.emit("./mod.ts");
|
||||
if (diagnostics.length) {
|
||||
// there is something that impacted the emit
|
||||
console.warn(Deno.formatDiagnostics(diagnostics));
|
||||
}
|
||||
```
|
||||
|
||||
### Bundling
|
||||
|
||||
`Deno.emit()` is also capable of providing output similar to `deno bundle` on
|
||||
the command line. This is enabled by setting the _bundle_ option to `"module"`
|
||||
or `"classic"`. Currently Deno supports bundling as a single file ES module
|
||||
(`"module"`) or a single file self contained legacy script (`"classic"`).
|
||||
|
||||
```ts
|
||||
const { files, diagnostics } = await Deno.emit("./mod.ts", {
|
||||
bundle: "module",
|
||||
});
|
||||
```
|
||||
|
||||
The _files_ of the result will contain a single key named `deno:///bundle.js` of
|
||||
which the value with be the resulting bundle.
|
||||
|
||||
> ⚠️ Just like with `deno bundle`, the bundle will not include things like
|
||||
> dynamic imports or worker scripts, and those would be expected to be resolved
|
||||
> and available when the code is run.
|
||||
|
||||
### Import maps
|
||||
|
||||
`Deno.emit()` supports import maps as well, just like on the command line. This
|
||||
is a really powerful feature that can be used even more effectively to emit and
|
||||
bundle code.
|
||||
|
||||
Because of the way import maps work, when using with `Deno.emit()` you also have
|
||||
to supply an absolute URL for the import map. This allows Deno to resolve any
|
||||
relative URLs specified in the import map. This needs to be supplied even if the
|
||||
import map doesn't contain any relative URLs. The URL does not need to really
|
||||
exist, it is just feed to the API.
|
||||
|
||||
An example might be that I want to use a bare specifier to load a special
|
||||
version of _lodash_ I am using with my project. I could do the following:
|
||||
|
||||
```ts
|
||||
const { files } = await Deno.emit("mod.ts", {
|
||||
bundle: "module",
|
||||
importMap: {
|
||||
imports: {
|
||||
"lodash": "https://deno.land/x/lodash",
|
||||
},
|
||||
},
|
||||
importMapPath: "file:///import-map.json",
|
||||
});
|
||||
```
|
||||
|
||||
> ⚠️ If you are not bundling your code, the emitted code specifiers do not get
|
||||
> rewritten, that means that whatever process will consume the code, Deno or a
|
||||
> browser for example, would need to support import maps and have that map
|
||||
> available at runtime.
|
||||
|
||||
### Skip type checking/transpiling only
|
||||
|
||||
`Deno.emit()` supports skipping type checking similar to the `--no-check` flag
|
||||
on the command line. This is accomplished by setting the _check_ property to
|
||||
`false`:
|
||||
|
||||
```ts
|
||||
const { files } = await Deno.emit("./mod.ts", {
|
||||
check: false,
|
||||
});
|
||||
```
|
||||
|
||||
Setting _check_ to `false` will instruct Deno to not utilise the TypeScript
|
||||
compiler to type check the code and emit it, instead only transpiling the code
|
||||
from within Deno. This can be significantly quicker than doing the full type
|
||||
checking.
|
||||
|
||||
### Compiler options
|
||||
|
||||
`Deno.emit()` supports quite a few compiler options that can impact how code is
|
||||
type checked and emitted. They are similar to the options supported by a
|
||||
`tsconfig.json` in the `compilerOptions` section, but there are several options
|
||||
that are not supported. This is because they are either meaningless in Deno or
|
||||
would cause Deno to not be able to work properly. The defaults for `Deno.emit()`
|
||||
are the same defaults that are on the command line. The options are
|
||||
[documented here](https://doc.deno.land/builtin/unstable#Deno.CompilerOptions)
|
||||
along with their default values and are built into the Deno types.
|
||||
|
||||
If you are type checking your code, the compiler options will be type checked
|
||||
for you, but if for some reason you are either dynamically providing the
|
||||
compiler options or are not type checking, then the result of `Deno.emit()` will
|
||||
provide you with an array of _ignoredOptions_ if there are any.
|
||||
|
||||
> ⚠️ we have only tried to disable/remove options that we know won't work, that
|
||||
> does not mean we extensively test all options in all configurations under
|
||||
> `Deno.emit()`. You may find that some behaviors do not match what you can get
|
||||
> from `tsc` or are otherwise incompatible. If you do find something that
|
||||
> doesn't work, please do feel free to raise an issue.
|
|
@ -1,290 +0,0 @@
|
|||
## Types and Type Declarations
|
||||
|
||||
One of the design principles of Deno is no non-standard module resolution. When
|
||||
TypeScript is type checking a file, it only cares about the types for the file,
|
||||
and the `tsc` compiler has a lot of logic to try to resolve those types. By
|
||||
default, it expects _ambiguous_ module specifiers with an extension, and will
|
||||
attempt to look for the file under the `.ts` specifier, then `.d.ts`, and
|
||||
finally `.js` (plus a whole other set of logic when the module resolution is set
|
||||
to `"node"`). Deno deals with explicit specifiers.
|
||||
|
||||
This can cause a couple problems though. For example, let's say I want to
|
||||
consume a TypeScript file that has already been transpiled to JavaScript along
|
||||
with a type definition file. So I have `mod.js` and `mod.d.ts`. If I try to
|
||||
import `mod.js` into Deno, it will only do what I ask it to do, and import
|
||||
`mod.js`, but that means my code won't be as well type checked as if TypeScript
|
||||
was considering the `mod.d.ts` file in place of the `mod.js` file.
|
||||
|
||||
In order to support this in Deno, Deno has two solutions, of which there is a
|
||||
variation of a solution to enhance support. The two main situations you come
|
||||
across would be:
|
||||
|
||||
- As the importer of a JavaScript module, I know what types should be applied to
|
||||
the module.
|
||||
- As the supplier of the JavaScript module, I know what types should be applied
|
||||
to the module.
|
||||
|
||||
The latter case is the better case, meaning you as the provider or host of the
|
||||
module, everyone can consume it without having to figure out how to resolve the
|
||||
types for the JavaScript module, but when consuming modules that you may not
|
||||
have direct control over, the ability to do the former is also required.
|
||||
|
||||
### Providing types when importing
|
||||
|
||||
If you are consuming a JavaScript module and you have either created types (a
|
||||
`.d.ts` file) or have otherwise obtained the types, you want to use, you can
|
||||
instruct Deno to use that file when type checking instead of the JavaScript file
|
||||
using the `@deno-types` compiler hint. `@deno-types` needs to be a single line
|
||||
double slash comment, where when used impacts the next import or re-export
|
||||
statement.
|
||||
|
||||
For example if I have a JavaScript modules `coolLib.js` and I had a separate
|
||||
`coolLib.d.ts` file that I wanted to use, I would import it like this:
|
||||
|
||||
```ts
|
||||
// @deno-types="./coolLib.d.ts"
|
||||
import * as coolLib from "./coolLib.js";
|
||||
```
|
||||
|
||||
When type checking `coolLib` and your usage of it in the file, the
|
||||
`coolLib.d.ts` types will be used instead of looking at the JavaScript file.
|
||||
|
||||
The pattern matching for the compiler hint is somewhat forgiving and will accept
|
||||
quoted and non-question values for the specifier as well as it accepts
|
||||
whitespace before and after the equals sign.
|
||||
|
||||
### Providing types when hosting
|
||||
|
||||
If you are in control of the source code of the module, or you are in control of
|
||||
how the file is hosted on a web server, there are two ways to inform Deno of the
|
||||
types for a given module, without requiring the importer to do anything special.
|
||||
|
||||
#### Using the triple-slash reference directive
|
||||
|
||||
Deno supports using the triple-slash reference `types` directive, which adopts
|
||||
the reference comment used by TypeScript in TypeScript files to _include_ other
|
||||
files and applies it only to JavaScript files.
|
||||
|
||||
For example, if I had created `coolLib.js` and along side of it I had created my
|
||||
type definitions for my library in `coolLib.d.ts` I could do the following in
|
||||
the `coolLib.js` file:
|
||||
|
||||
```js
|
||||
/// <reference types="./coolLib.d.ts" />
|
||||
|
||||
// ... the rest of the JavaScript ...
|
||||
```
|
||||
|
||||
When Deno encounters this directive, it would resolve the `./coolLib.d.ts` file
|
||||
and use that instead of the JavaScript file when TypeScript was type checking
|
||||
the file, but still load the JavaScript file when running the program.
|
||||
|
||||
> ℹ️ _Note_ this is a repurposed directive for TypeScript that only applies to
|
||||
> JavaScript files. Using the triple-slash reference directive of `types` in a
|
||||
> TypeScript file works under Deno as well, but has essentially the same
|
||||
> behavior as the `path` directive.
|
||||
|
||||
#### Using X-TypeScript-Types header
|
||||
|
||||
Similar to the triple-slash directive, Deno supports a header for remote modules
|
||||
that instructs Deno where to locate the types for a given module. For example, a
|
||||
response for `https://example.com/coolLib.js` might look something like this:
|
||||
|
||||
```
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/javascript; charset=UTF-8
|
||||
Content-Length: 648
|
||||
X-TypeScript-Types: ./coolLib.d.ts
|
||||
```
|
||||
|
||||
When seeing this header, Deno would attempt to retrieve
|
||||
`https://example.com/coolLib.d.ts` and use that when type checking the original
|
||||
module.
|
||||
|
||||
### Using ambient or global types
|
||||
|
||||
Overall it is better to use module/UMD type definitions with Deno, where a
|
||||
module expressly imports the types it depends upon. Modular type definitions can
|
||||
express
|
||||
[augmentation of the global scope](https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html)
|
||||
via the `declare global` in the type definition. For example:
|
||||
|
||||
```ts
|
||||
declare global {
|
||||
var AGlobalString: string;
|
||||
}
|
||||
```
|
||||
|
||||
This would make `AGlobalString` available in the global namespace when importing
|
||||
the type definition.
|
||||
|
||||
In some cases though, when leveraging other existing type libraries, it may not
|
||||
be possible to leverage modular type definitions. Therefore there are ways to
|
||||
include arbitrary type definitions when type checking programmes.
|
||||
|
||||
#### Using a triple-slash directive
|
||||
|
||||
This option couples the type definitions to the code itself. By adding a
|
||||
triple-slash `types` directive near the type of a module, type checking the file
|
||||
will include the type definition. For example:
|
||||
|
||||
```ts
|
||||
/// <reference types="./types.d.ts" />
|
||||
```
|
||||
|
||||
The specifier provided is resolved just like any other specifier in Deno, which
|
||||
means it requires an extension, and is relative to the module referencing it. It
|
||||
can be a fully qualified URL as well:
|
||||
|
||||
```ts
|
||||
/// <reference types="https://deno.land/x/pkg@1.0.0/types.d.ts" />
|
||||
```
|
||||
|
||||
#### Using a `tsconfig.json` file
|
||||
|
||||
Another option is to use a `tsconfig.json` file that is configured to include
|
||||
the type definitions, by supplying a `"types"` value to the `"compilerOptions"`.
|
||||
For example:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"types": [
|
||||
"./types.d.ts",
|
||||
"https://deno.land/x/pkg@1.0.0/types.d.ts",
|
||||
"/Users/me/pkg/types.d.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Like the triple-slash reference above, the specifier supplied in the `"types"`
|
||||
array will be resolved like other specifiers in Deno. In the case of relative
|
||||
specifiers, it will be resolved relative to the path to the `tsconfig.json`.
|
||||
|
||||
### Type Checking Web Workers
|
||||
|
||||
When Deno loads a TypeScript module in a web worker, it will automatically type
|
||||
check the module and its dependencies against the Deno web worker library. This
|
||||
can present a challenge in other contexts like `deno cache`, `deno bundle`, or
|
||||
in editors. There are a couple of ways to instruct Deno to use the worker
|
||||
libraries instead of the standard Deno libraries.
|
||||
|
||||
#### Using triple-slash directives
|
||||
|
||||
This option couples the library settings with the code itself. By adding the
|
||||
following triple-slash directives near the top of the entry point file for the
|
||||
worker script, Deno will now type check it as a Deno worker script, irrespective
|
||||
of how the module is analyzed:
|
||||
|
||||
```ts
|
||||
/// <reference no-default-lib="true" />
|
||||
/// <reference lib="deno.worker" />
|
||||
```
|
||||
|
||||
The first directive ensures that no other default libraries are used. If this is
|
||||
omitted, you will get some conflicting type definitions, because Deno will try
|
||||
to apply the standard Deno library as well. The second instructs Deno to apply
|
||||
the built in Deno worker type definitions plus dependent libraries (like
|
||||
`"esnext"`).
|
||||
|
||||
When you run a `deno cache` or `deno bundle` command or use an IDE which uses
|
||||
the Deno language server, Deno should automatically detect these directives and
|
||||
apply the correct libraries when type checking.
|
||||
|
||||
The one disadvantage of this, is that it makes the code less portable to other
|
||||
non-Deno platforms like `tsc`, as it is only Deno which has the `"deno.worker"`
|
||||
library built into it.
|
||||
|
||||
#### Using a `tsconfig.json` file
|
||||
|
||||
Another option is to use a `tsconfig.json` file that is configured to apply the
|
||||
library files. A minimal file that would work would look something like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"lib": ["deno.worker"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then when running a command on the command line, you would need to pass the
|
||||
`--config tsconfig.json` argument, or if you are using an IDE which leverages
|
||||
the Deno language server, set the `deno.config` setting.
|
||||
|
||||
If you also have non-worker scripts, you will either need to omit the `--config`
|
||||
argument, or have one that is configured to meet the needs of your non-worker
|
||||
scripts.
|
||||
|
||||
### Important points
|
||||
|
||||
#### Type declaration semantics
|
||||
|
||||
Type declaration files (`.d.ts` files) follow the same semantics as other files
|
||||
in Deno. This means that declaration files are assumed to be module declarations
|
||||
(_UMD declarations_) and not ambient/global declarations. It is unpredictable
|
||||
how Deno will handle ambient/global declarations.
|
||||
|
||||
In addition, if a type declaration imports something else, like another `.d.ts`
|
||||
file, its resolution follow the normal import rules of Deno. For a lot of the
|
||||
`.d.ts` files that are generated and available on the web, they may not be
|
||||
compatible with Deno.
|
||||
|
||||
To overcome this problem, some solution providers, like the
|
||||
[Skypack CDN](https://www.skypack.dev/), will automatically bundle type
|
||||
declarations just like they provide bundles of JavaScript as ESM.
|
||||
|
||||
#### Deno Friendly CDNs
|
||||
|
||||
There are CDNs which host JavaScript modules that integrate well with Deno.
|
||||
|
||||
- [Skypack.dev](https://docs.skypack.dev/skypack-cdn/code/deno) is a CDN which
|
||||
provides type declarations (via the `X-TypeScript-Types` header) when you
|
||||
append `?dts` as a query string to your remote module import statements. For
|
||||
example:
|
||||
|
||||
```ts
|
||||
import React from "https://cdn.skypack.dev/react?dts";
|
||||
```
|
||||
|
||||
### Behavior of JavaScript when type checking
|
||||
|
||||
If you import JavaScript into TypeScript in Deno and there are no types, even if
|
||||
you have `checkJs` set to `false` (the default for Deno), the TypeScript
|
||||
compiler will still access the JavaScript module and attempt to do some static
|
||||
analysis on it, to at least try to determine the shape of the exports of that
|
||||
module to validate the import in the TypeScript file.
|
||||
|
||||
This is usually never a problem when trying to import a "regular" ES module, but
|
||||
in some cases if the module has special packaging, or is a global _UMD_ module,
|
||||
TypeScript's analysis of the module can fail and cause misleading errors. The
|
||||
best thing to do in this situation is provide some form of types using one of
|
||||
the methods mention above.
|
||||
|
||||
#### Internals
|
||||
|
||||
While it isn't required to understand how Deno works internally to be able to
|
||||
leverage TypeScript with Deno well, it can help to understand how it works.
|
||||
|
||||
Before any code is executed or compiled, Deno generates a module graph by
|
||||
parsing the root module, and then detecting all of its dependencies, and then
|
||||
retrieving and parsing those modules, recursively, until all the dependencies
|
||||
are retrieved.
|
||||
|
||||
For each dependency, there are two potential "slots" that are used. There is the
|
||||
code slot and the type slot. As the module graph is filled out, if the module is
|
||||
something that is or can be emitted to JavaScript, it fills the code slot, and
|
||||
type only dependencies, like `.d.ts` files fill the type slot.
|
||||
|
||||
When the module graph is built, and there is a need to type check the graph,
|
||||
Deno starts up the TypeScript compiler and feeds it the names of the modules
|
||||
that need to be potentially emitted as JavaScript. During that process, the
|
||||
TypeScript compiler will request additional modules, and Deno will look at the
|
||||
slots for the dependency, offering it the type slot if it is filled before
|
||||
offering it the code slot.
|
||||
|
||||
This means when you import a `.d.ts` module, or you use one of the solutions
|
||||
above to provide alternative type modules for JavaScript code, that is what is
|
||||
provided to TypeScript instead when resolving the module.
|