Skip to content

Commit 4f515ab

Browse files
feat: register() & tsImport() via esm/api (#12)
1 parent 8eb1674 commit 4f515ab

17 files changed

+600
-354
lines changed

docs/node.md

+73-25
Original file line numberDiff line numberDiff line change
@@ -54,20 +54,27 @@ node --import tsx/esm ./file.ts
5454
node --loader tsx/esm ./file.ts
5555
```
5656

57-
### Hooks API
58-
> Previously known as _Loaders_ ([renamed in Node.js v21](https://github.com/nodejs/loaders/issues/95))
57+
### Registration & Unregistration
58+
```js
59+
import { register } from 'tsx/esm/api'
5960

60-
You can use the [Hooks API](https://nodejs.org/api/module.html#customization-hooks) to load TypeScript files with `tsx/esm`:
61+
// register tsx enhancement
62+
const unregister = register()
6163

62-
```js
63-
import { register } from 'node:module'
64+
// Unregister when needed
65+
unregister()
66+
```
6467

65-
register('tsx/esm', {
66-
parentURL: import.meta.url,
67-
data: true
68-
})
68+
#### Tracking loaded files
69+
Detect files that get loaded with the `onImport` hook:
6970

70-
const loaded = await import('./hello.ts')
71+
```ts
72+
register({
73+
onImport: (file: string) => {
74+
console.log(file)
75+
// file:///foo.ts
76+
}
77+
})
7178
```
7279

7380
## Only CommonJS enhancement
@@ -82,21 +89,15 @@ Pass _tsx_ into the `--require` flag:
8289
node --require tsx/cjs ./file.ts
8390
```
8491

85-
### Node.js API
86-
87-
#### Globally patching `require`
88-
89-
##### Enabling TSX Enhancement
90-
91-
Add the following line at the top of your entry file:
92+
This is the equivalent of adding the following at the top of your entry file, which you can also do:
9293

9394
```js
9495
require('tsx/cjs')
9596
```
9697

97-
##### Manual Registration & Unregistration
98+
### Registration & Unregistration
9899

99-
To manually register and unregister the TypeScript enhancement:
100+
To manually register and unregister the tsx enhancement:
100101

101102
```js
102103
const tsx = require('tsx/cjs/api')
@@ -108,13 +109,60 @@ const unregister = tsx.register()
108109
unregister()
109110
```
110111

111-
## `tsx.require()`
112+
## Enhanced `import()` & `require()`
113+
114+
tsx exports enhanced `import()` or `require()` functions, allowing you to load TypeScript/ESM files without affecting the runtime environment.
115+
116+
### `tsImport()`
117+
118+
The `import()` function enhanced to support TypeScript. Because it's the native `import()`, it supports [top-level await](https://v8.dev/features/top-level-await).
119+
120+
::: warning Caveat
121+
`require()` calls in the loaded files are not enhanced.
122+
:::
123+
124+
#### ESM usage
125+
126+
Note, the current file path must be passed in as the second argument to resolve the import context.
127+
128+
```js
129+
import { tsImport } from 'tsx/esm/api'
130+
131+
const loaded = await tsImport('./file.ts', import.meta.url)
132+
```
133+
134+
#### CommonJS usage
135+
136+
```js
137+
const { tsImport } = require('tsx/esm/api')
138+
139+
const loaded = await tsImport('./file.ts', __filename)
140+
```
141+
142+
#### Tracking loaded files
143+
Detect files that get loaded with the `onImport` hook:
112144
113-
For loading a TypeScript file without affecting the environment, `tsx` exports a custom `require(id, loadFromPath)` function.
145+
```ts
146+
tsImport('./file.ts', {
147+
parentURL: import.meta.url,
148+
onImport: (file: string) => {
149+
console.log(file)
150+
// file:///foo.ts
151+
}
152+
})
153+
```
154+
155+
### `tsx.require()`
156+
157+
The `require()` function enhanced to support TypeScript and ESM.
158+
159+
::: warning Caveat
160+
`import()` & asynchronous `require()` calls in the loaded files are not enhanced.
161+
:::
114162
115-
Note, the current file path must be passed in as the second argument so it knows how to resolve relative paths.
163+
#### CommonJS usage
116164
117-
### CommonJS usage
165+
Note, the current file path must be passed in as the second argument to resolve the import context.
118166
119167
```js
120168
const tsx = require('tsx/cjs/api')
@@ -123,7 +171,7 @@ const loaded = tsx.require('./file.ts', __filename)
123171
const filepath = tsx.require.resolve('./file.ts', __filename)
124172
```
125173
126-
### ESM usage
174+
#### ESM usage
127175
128176
```js
129177
import { require } from 'tsx/cjs/api'
@@ -132,7 +180,7 @@ const loaded = require('./file.ts', import.meta.url)
132180
const filepath = require.resolve('./file.ts', import.meta.url)
133181
```
134182
135-
### Module graph inspection
183+
#### Tracking loaded files
136184
137185
Because the CommonJS API tracks loaded modules in `require.cache`, you can use it to identify loaded files for dependency tracking. This can be useful when implementing a watcher.
138186

package.json

+12-2
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,24 @@
3131
"default": "./dist/cjs/api/index.cjs"
3232
},
3333
"./esm": "./dist/esm/index.mjs",
34+
"./esm/api": {
35+
"import": {
36+
"types": "./dist/esm/api/index.d.mts",
37+
"default": "./dist/esm/api/index.mjs"
38+
},
39+
"require": {
40+
"types": "./dist/esm/api/index.d.cts",
41+
"default": "./dist/esm/api/index.cjs"
42+
}
43+
},
3444
"./cli": "./dist/cli.mjs",
3545
"./suppress-warnings": "./dist/suppress-warnings.cjs",
3646
"./preflight": "./dist/preflight.cjs",
3747
"./repl": "./dist/repl.mjs"
3848
},
3949
"scripts": {
4050
"prepare": "pnpm simple-git-hooks",
41-
"build": "pkgroll --target=node12.19 --minify",
51+
"build": "pkgroll --minify",
4252
"lint": "lintroll --node --cache .",
4353
"type-check": "tsc --noEmit",
4454
"test": "pnpm build && node ./dist/cli.mjs tests/index.ts",
@@ -80,7 +90,7 @@
8090
"get-node": "^15.0.0",
8191
"kolorist": "^1.8.0",
8292
"lint-staged": "^15.2.2",
83-
"lintroll": "^1.5.0",
93+
"lintroll": "^1.5.1",
8494
"magic-string": "^0.30.10",
8595
"manten": "^1.3.0",
8696
"memfs": "^4.9.1",

0 commit comments

Comments
 (0)