diff --git a/runtime/manual/basics/modules/module_metadata.md b/runtime/manual/basics/modules/module_metadata.md new file mode 100644 index 000000000..8e5efc9d0 --- /dev/null +++ b/runtime/manual/basics/modules/module_metadata.md @@ -0,0 +1,80 @@ +--- +title: "Module Metadata" +oldUrl: + - /runtime/manual/examples/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://deno.land/api?s=ImportMeta#prop_main) + will let you know if the current module is the program entry point. +- The string [import.meta.url](https://deno.land/api?s=ImportMeta#prop_url) will + give you the URL of the current module. +- The string + [import.meta.filename](https://deno.land/api?s=ImportMeta#prop_filename) will + give you the fully resolved path to the current module. _For local modules + only_. +- The string + [import.meta.dirname](https://deno.land/api?s=ImportMeta#prop_dirname) will + give you the fully resolved path to the directory containing the current + module. _For local modules only_. +- The [import.meta.resolve](https://deno.land/api?s=ImportMeta#prop_resolve) + allows you to resolve specifier relative to the current module. This function + takes into account an import map (if one was provided on startup). +- The string [Deno.mainModule](https://deno.land/api?s=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 title="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 title="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, + ); + console.log( + "Resolved specifier for ./module_b.ts", + import.meta.resolve("./module_b.ts"), + ); +} + +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: + +```console +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 +Resolved specifier for ./module_b.ts file:///home/alice/deno/module_b.ts + +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 +``` diff --git a/runtime/manual/basics/modules/publishing_modules.md b/runtime/manual/basics/modules/publishing_modules.md new file mode 100644 index 000000000..7ab2e931a --- /dev/null +++ b/runtime/manual/basics/modules/publishing_modules.md @@ -0,0 +1,89 @@ +--- +Title: Publishing Modules +--- + +Any Deno program that defines an export can be published as a module. This +allows other developers to import and use your code in their own projects. +Modules can be published to [JSR](https://jsr.io). + +## Configuring your module + +To configure your module for publishing, you need to ensure you have the +following properties defined in a `deno.json` file at the root of your project: + +```json title="deno.json" +{ + "name": "@my-scope/my-module", + "version": "1.0.0", + "exports": "./mod.ts" +} +``` + +In order to publish, you need a +[JSR scope and a new package](https://jsr.io/docs/publishing-packages#creating-a-scope-and-package) +to identify your module. You can create your scope and package at +[jsr.io/new](https://jsr.io/new). + +The `name` property in your `deno.json` file is a concatenation of your scope +and package name, separated by a `/`. The `exports` property should point to the +main entry point of your module. + +## Publishing your module + +Packages can be published to JSR in the CLI with the +[`deno publish` command](https://jsr.io/docs/publishing-packages#publishing-from-your-local-machine). + +To publish your module, run the following command in the root of your project: + +```bash +deno publish +``` + +Before publishing, you can use the `--dry-run` flag locally to test the +publishing process, without actually publishing your module. This will print out +a list of all of the files that will be published and can be used to verify that +your module is set up correctly: + +```bash +deno publish --dry-run +``` + +By default, interactive authentication is used to publish - this means that a +browser window will open to authenticate you with JSR. If you want to publish +without the interactive browser window, you can use the `--token` flag to +provide a JSR auth token: + +```bash +deno publish --token +``` + +You can create a new auth token at +[jsr.io/account/tokens](https://jsr.io/account/tokens). + +If you're configuring a CI pipeline to publish your module, you can use the +`--token` flag to authenticate with JSR but it's important to ensure that your +token is kept secure. + +If you're publishing a package from GitHub Actions it is recommended to link +your repository by following the instructions at +[jsr.io/docs/publishing-packages#publishing-from-github-actions](https://jsr.io/docs/publishing-packages#publishing-from-github-actions). +This will allow you to publish packages without needing to provide an auth token +and instead uses OIDC authentication from GitHub itself. + +## Other publishing methods + +You can publish your modules from the browser at +[jsr.io/new](https://jsr.io/new). + +## Publishing for Node + +Library authors may want to make their Deno modules available to Node.js users. +This is possible by using the [dnt](https://github.com/denoland/dnt) build tool. + +dnt allows you to develop your Deno module mostly as-is and use a single Deno +script to build, type check, and test an npm package in an output directory. +Once built, you only need to `npm publish` the output directory to distribute it +to Node.js users. + +For more details, see +[https://github.com/denoland/dnt](https://github.com/denoland/dnt). diff --git a/runtime/manual/basics/modules/remote_modules.md b/runtime/manual/basics/modules/remote_modules.md new file mode 100644 index 000000000..bf17bd414 --- /dev/null +++ b/runtime/manual/basics/modules/remote_modules.md @@ -0,0 +1,165 @@ +# Using Remote Modules with Deno + +Using remote modules (downloaded from a registry) in Deno uses the same `import` +syntax as your local code. + +The modules that you add to your project are tracked as `imports` in +`deno.json` - we call this the import map. + +```json +{ + "tasks": { + "dev": "deno run --watch main.ts" + }, + "imports": { + "@scopename/mypackage": "jsr:@scopename/mypackage@^16.1.0" + } +} +``` + +You can add modules using the `Deno CLI` subcommand `deno add` + +```bash +$ deno add @scopename/mypackage +Add @scopename/mypackage - jsr:@scopename/mypackage@^16.1.0 +``` + +Deno add will automatically add the latest version of the module you requested +to your project imports. If you're coming from the `node` ecosystem, this is +equivalent to `npm install PACKAGE --save`. + +## Using Imported Packages + +Once a package is added to the import map in `deno.json`, you can import the +module by its name, and Deno will automatically resolve the module. + +```ts title="mod.ts" +import { someFunction } from "@scopename/mypackage"; + +someFunction(); +``` + +## Package Registries + +Deno recommends that you use [JSR](https://jsr.io/), the JavaScript registry, to +publish and manage your modules for the best publishing experience. JSR offers +automatic documentation generation, semver resolution and improved performance +for TypeScript code. Deno also supports +[other platforms](https://jsr.io/docs/other-registries) for publishing modules, +such as npm, and JavaScript CDNs like deno.land/x, esm.h and unpkg.com + +By default when you use the CLI, the package will be resolved from JSR. + +```bash +deno add @scopename/mypackage +``` + +The resulting import map contains the `jsr:` import specifier in the resulting +`deno.json` file. + +```json +{ + "imports": { + "@scopename/mypackage": "jsr:@scopename/mypackage@^16.1.0" + } +} +``` + +## Importing from other package registries + +Using existing packages from registries like `npm` is equivalent to the +experience in `node`. To add a package from `npm` you need to prefix the package +name with the `npm:` specifier: + +```bash +$ deno add npm:uuid +Add uuid - npm:uuid@^10.0.0 +``` + +The resulting `deno.json` will look like this: + +```json +{ + "imports": { + "uuid": "npm:uuid@^10.0.0" + } +} +``` + +You will then be able to use the `npm` module by importing it with the name from +the import map. + +```ts title="mod.ts" +import * as uuid from "uuid"; + +console.log(uuid.v4()); +``` + +### Supported package registries and specifiers + +We support the following registries: + +| Registry | Specifier | +| -------- | --------- | +| JSR | jsr: | +| npm | npm: | + +## Understanding Package Versions + +When using Deno add, you can specify a version range for the package you are +adding. This is done using the `@` symbol followed by a version range specifier, +and follows the [semver](https://semver.org/) versioning scheme. + +```bash +deno add @scopename/mypackage # latest version +deno add @scopename/mypackage@16.1.0 # exact version +deno add @scopename/mypackage@^16.1.0 # latest patch version 16.x +deno add @scopename/mypackage@~16.1.0 # latest version that doesn't increment the first non-zero portion +``` + +## Importing by URL + +Deno also supports import statements that reference URLs, either directly: + +```js +import { Application } from "https://deno.land/x/oak/mod.ts"; +``` + +or part of your `deno.json` import map: + +```json +{ + "imports": { + "oak": "https://deno.land/x/oak/mod.ts" + } +} +``` + +Supporting URL imports enables us to support the following JavaScript CDNs, as +they provide URL access to JavaScript modules: + +- [deno.land/x](https://deno.land/x) +- [esm.h](https://esm.sh) +- [unpkg.com](https://unpkg.com) + +URL imports are useful if you have a small, often single file, Deno project that +doesn't require any other configuration because you can avoid having a +`Deno.json` file at all. It's not advised to use this style of import in larger +applications as you may end up with version conflicts (where different files use +different version specifiers). + +From a security perspective, the contents of files at URLs can change, so we do +not generally recommend this approach for third-party components. + +URL imports remain supported, **but we recommend using a package registry for +the best experience.** + +## 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.