Skip to content

Commit 51f0b2e

Browse files
doc: Extending support
1 parent 5a5c189 commit 51f0b2e

File tree

3 files changed

+65
-79
lines changed

3 files changed

+65
-79
lines changed

doc/api/external_formats.md

-78
This file was deleted.

doc/api/module.md

+64
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,67 @@ console.log('some module!');
881881
Running `node --import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register(pathToFileURL("./import-map-hooks.js"));' main.js`
882882
should print `some module!`.
883883
884+
### Extending support
885+
886+
> Stability: 1.0 - Early development
887+
888+
A `"register"` [entry point][`"exports"`] for a package loaded via [`--import`][] is automatically
889+
run at startup. A package extending Node.js support for typescript would look something like this:
890+
891+
```json
892+
{
893+
"name": "example-nodejs-extension",
894+
"keywords": [
895+
"nodejs-extension",
896+
"typescript"
897+
],
898+
"exports": {
899+
"register": "./registration.mjs",
900+
"typescript": "./hooks/typescript.mjs"
901+
}
902+
}
903+
```
904+
905+
Setting the keyword `nodejs-extension` is important for users to find the package (which may be
906+
automated). It should also contain the official name(s) for the support it provides, such as
907+
`typescript`; it should avoid red-herrings such as including `typescript` when the library does not
908+
extend support for typescript but is merely itself written in typescript.
909+
910+
```mjs
911+
import { register } from 'node:module';
912+
913+
register('example-nodejs-extension/typescript');
914+
```
915+
916+
`typescript.mjs` would contain [customization hooks][hooks]:
917+
918+
* A [`resolve` hook][resolve hook] that sets `format` for applicable modules to the format it
919+
handles, such as `'typescript'`.
920+
* A [`load` hook][load hook] that transpiles the external format (as signalled by its resolve hook)
921+
to something Node.js understands.
922+
* Optionally, an [`initialize` hook][`initialize`].
923+
924+
#### External formats
925+
926+
> Stability: 1.0 - Early development
927+
928+
Node.js natively understands a handful of formats (see the table in [load hook][]).
929+
Non-native or external formats require transpilation to something Node.js understands. When
930+
attempting to run a module with an external format, such as `node main.ts`, Node.js will look at the
931+
file extension to attempt to identify the type. If the type is recognized, Node.js will print a
932+
message with instructions (that lead here).
933+
934+
##### Setting up an extension
935+
936+
These steps configure Node.js to support a format it doesn't understand:
937+
938+
1. Find and install an extension via your preferred package manager. Some package managers provide a
939+
CLI utility, such as `npm search nodejs-extension typescript`, as well as a website.
940+
1. Once installed, in order to get Node.js to automatically use it, create a [`.env`][`--env-file`]
941+
file containing an [`--import`][] for your chosen extension, like
942+
`NODE_OPTIONS="--import=example-nodejs-extension"`.
943+
1. Include the env file flag on subsequent runs, like `node --env-file=.env main.ts`.
944+
884945
## Source map v3 support
885946
886947
<!-- YAML
@@ -1033,6 +1094,8 @@ returned object contains the following keys:
10331094
[Source map v3 format]: https://sourcemaps.info/spec.html#h.mofvlxcwqzej
10341095
[`"exports"`]: packages.md#exports
10351096
[`--enable-source-maps`]: cli.md#--enable-source-maps
1097+
[`--env-file`]: cli.md#--env-file
1098+
[`--import`]: cli.md#--import
10361099
[`ArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
10371100
[`NODE_V8_COVERAGE=dir`]: cli.md#node_v8_coveragedir
10381101
[`SharedArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
@@ -1048,5 +1111,6 @@ returned object contains the following keys:
10481111
[load hook]: #loadurl-context-nextload
10491112
[module wrapper]: modules.md#the-module-wrapper
10501113
[realm]: https://tc39.es/ecma262/#realm
1114+
[resolve hook]: #resolvespecifier-context-nextresolve
10511115
[source map include directives]: https://sourcemaps.info/spec.html#h.lmz475t4mvbx
10521116
[transferrable objects]: worker_threads.md#portpostmessagevalue-transferlist

lib/internal/errors.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1810,7 +1810,7 @@ E('ERR_UNSUPPORTED_ESM_URL_SCHEME', (url, supported) => {
18101810
}, Error);
18111811
E('ERR_UNSUPPORTED_MODULE_FORMAT',
18121812
'Module format "%s" for URL %s has no installed translator. Install one and re-run. ' +
1813-
'See https://nodejs.org/api/external_formats.html for more information.',
1813+
'See https://nodejs.org/api/module.html#extending-support for more information.',
18141814
TypeError);
18151815
E('ERR_USE_AFTER_CLOSE', '%s was closed', Error);
18161816

0 commit comments

Comments
 (0)