From 84ee8d70e2edcc1719ad74623cd534624d5aa985 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Thu, 26 Oct 2023 23:36:42 +0200 Subject: [PATCH 1/2] doc: add Customization section and subsections to related sub systems --- doc/api/customization.md | 52 ++++++++++++++++++++++++++++++++++++++++ doc/api/module.md | 40 +++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 doc/api/customization.md diff --git a/doc/api/customization.md b/doc/api/customization.md new file mode 100644 index 000000000000..a522c88da924 --- /dev/null +++ b/doc/api/customization.md @@ -0,0 +1,52 @@ +# Customization + +> Stability: 1.0 - Early development + +Node.js has multiple APIs for customizing behaviour and can easily be invoked +via [`--import`][]: A `"nodejs-customization"` [entry point][`"exports"`] for a +package loaded via [`--import`][] is automatically run at startup. The +package.json of such a plugin would look something like this: + +```json +{ + "name": "example-nodejs-plugin", + "keywords": [ + "nodejs-plugin" + ], + "exports": { + "nodejs-customization": "./registration.mjs" + } +} +``` + +Setting the keyword `nodejs-plugin` is important for users to find the package +(which may be automated). It should also contain the official name(s) for the +support it provides; for a plugin extending support for typescript would contain +`typescript` in its keywords; avoid red-herrings such as `typescript` as a +keyword when the library does not extend support for typescript but is merely +itself written in typescript. Failing to avoid these red-herrings will cause +your package to be listed for things it does not do, aggravating users. + +These steps configure Node.js with a customization plugin: + +1. Install the plugin via your preferred package manager. For finding the + plugin, package managers provide often a CLI utility, such as [`npm + search`][], as well as a website. +2. Once installed, in order to get Node.js to automatically use it, create a + [`.env`][`--env-file`] file containing an [`--import`][] for your chosen + plugin, like `NODE_OPTIONS="--import=example-nodejs-plugin"`. +3. Include the env file flag on subsequent runs, like + `node --env-file=.env main.mjs`. + +## APIs + +Customizable systems each expose a `register` function, whereby the +customization plugin is registered into Node.js. + +* [`node:module`][module.register] + +[`"exports"`]: packages.md#exports +[`--env-file`]: cli.md#--env-file +[`--import`]: cli.md#--import +[`npm search`]: https://docs.npmjs.com/cli/v10/commands/npm-search +[module.register]: module.md#moduleregisterspecifier-parenturl-options diff --git a/doc/api/module.md b/doc/api/module.md index f4338028abe3..47898e7811e4 100644 --- a/doc/api/module.md +++ b/doc/api/module.md @@ -683,6 +683,44 @@ export async function load(url, context, nextLoad) { In a more advanced scenario, this can also be used to transform an unsupported source to a supported one (see [Examples](#examples) below). +### External formats + +Node.js natively understands a handful of formats (see the table in [`load` +hook][load hook]). Non-native or external formats require transpilation to +something Node.js understands, and many packages exist to handle this. A simple +example of such a package would look something like this: + +```json +{ + "name": "example-nodejs-plugin", + "keywords": [ + "nodejs-plugin", + "typescript" + ], + "exports": { + "nodejs-customization": "./registration.mjs", + "typescript": "./hooks/typescript.mjs" + } +} +``` + +```mjs +import { register } from 'node:module'; + +register('example-nodejs-plugin/typescript'); +``` + +`typescript.mjs` would contain [customization hooks][hooks]: + +* A [`resolve` hook][resolve hook] that sets `format` for applicable modules to + the format it handles, such as `'typescript'`. +* A [`load` hook][load hook] that transpiles the external format (as signalled + by its `resolve` hook) to something Node.js understands. +* Optionally, an [`initialize` hook][`initialize`]. + +See [Node.js Customization][Customization] for information about registering and +persisting these plugins. + ### Examples The various module customization hooks can be used together to accomplish @@ -1027,6 +1065,7 @@ returned object contains the following keys: [CommonJS]: modules.md [Conditional exports]: packages.md#conditional-exports +[Customization]: customization.md [Customization hooks]: #customization-hooks [ES Modules]: esm.md [HTTPS and HTTP imports]: esm.md#https-and-http-imports @@ -1048,5 +1087,6 @@ returned object contains the following keys: [load hook]: #loadurl-context-nextload [module wrapper]: modules.md#the-module-wrapper [realm]: https://tc39.es/ecma262/#realm +[resolve hook]: #resolvespecifier-context-nextresolve [source map include directives]: https://sourcemaps.info/spec.html#h.lmz475t4mvbx [transferrable objects]: worker_threads.md#portpostmessagevalue-transferlist From a1013a0f6787a5adac26a7128236a181ec8c2f28 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Sun, 29 Oct 2023 17:04:21 +0100 Subject: [PATCH 2/2] update orthography to American, and set entry-point name to `register` --- doc/api/customization.md | 42 ++++++++++++++++++++++++---------------- doc/api/module.md | 9 ++++++--- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/doc/api/customization.md b/doc/api/customization.md index a522c88da924..a636d164507e 100644 --- a/doc/api/customization.md +++ b/doc/api/customization.md @@ -2,10 +2,9 @@ > Stability: 1.0 - Early development -Node.js has multiple APIs for customizing behaviour and can easily be invoked -via [`--import`][]: A `"nodejs-customization"` [entry point][`"exports"`] for a -package loaded via [`--import`][] is automatically run at startup. The -package.json of such a plugin would look something like this: +Node.js has multiple APIs for customizing behavior and can easily be invoked via +[`--import`][]. The package.json of such a plugin would look something like +this: ```json { @@ -14,29 +13,38 @@ package.json of such a plugin would look something like this: "nodejs-plugin" ], "exports": { - "nodejs-customization": "./registration.mjs" + "register": "./registration.mjs" } } ``` -Setting the keyword `nodejs-plugin` is important for users to find the package -(which may be automated). It should also contain the official name(s) for the -support it provides; for a plugin extending support for typescript would contain -`typescript` in its keywords; avoid red-herrings such as `typescript` as a -keyword when the library does not extend support for typescript but is merely -itself written in typescript. Failing to avoid these red-herrings will cause -your package to be listed for things it does not do, aggravating users. +Setting the keyword `nodejs-plugin` is important for users to find the +package (which may be automated). It should also contain the official name(s) +for the support it provides; a plugin extending Node.js support for TypeScript +should contain `typescript` in its keywords; a customization package that does +not extend Node.js support for TypeScript should not contain `typescript` (such +as when the library is itself merely written in TypeScript). Incorrect keywords +will cause a package to be listed for things it does not do, aggravating users. + +## Setting up a plugin These steps configure Node.js with a customization plugin: 1. Install the plugin via your preferred package manager. For finding the plugin, package managers provide often a CLI utility, such as [`npm search`][], as well as a website. -2. Once installed, in order to get Node.js to automatically use it, create a - [`.env`][`--env-file`] file containing an [`--import`][] for your chosen - plugin, like `NODE_OPTIONS="--import=example-nodejs-plugin"`. -3. Include the env file flag on subsequent runs, like - `node --env-file=.env main.mjs`. +2. Once installed, in order to get Node.js to use it, you have 2 options: + * Pass the `--import` directly in the shell command: + `node --import=example-nodejs-plugin/register" main.mjs`. This option works + well when the command is simple, but it can + quickly become unwieldy as the list of flags grows, and it requires you to + remember everything you need to pass. + * Create a [`.env`][`--env-file`] file containing an [`--import`][] for your + chosen plugin, like `NODE_OPTIONS="--import=example-nodejs-plugin/register"`. + This option avoids the command becoming unwieldly, and it's easier to + remember (a single, unchanging `--env-file` flag). + * Include the `.env` file flag on subsequent runs, like + `node --env-file=.env main.mjs`. ## APIs diff --git a/doc/api/module.md b/doc/api/module.md index 47898e7811e4..a07e18cd4754 100644 --- a/doc/api/module.md +++ b/doc/api/module.md @@ -698,12 +698,15 @@ example of such a package would look something like this: "typescript" ], "exports": { - "nodejs-customization": "./registration.mjs", + "register": "./registration.mjs", "typescript": "./hooks/typescript.mjs" } } ``` +> **Note**: The `"typescript"` entry point is not required but it makes the next +> step (and possibly others) simpler. + ```mjs import { register } from 'node:module'; @@ -714,8 +717,8 @@ register('example-nodejs-plugin/typescript'); * A [`resolve` hook][resolve hook] that sets `format` for applicable modules to the format it handles, such as `'typescript'`. -* A [`load` hook][load hook] that transpiles the external format (as signalled - by its `resolve` hook) to something Node.js understands. +* A [`load` hook][load hook] that transpiles the external format (as signaled by + its `resolve` hook) to something Node.js understands. * Optionally, an [`initialize` hook][`initialize`]. See [Node.js Customization][Customization] for information about registering and