Skip to content

Commit 2b3a6ec

Browse files
feat: support native type stripping for Node >= v23 (#442)
* feat: support native type stripping for Node >= v23 * fix: remove unnecessary callback wraping * docs: inform about native type stripping support for Node >= 23 * revert: log condition * fix: forgot && to run jest test * docs: update related doc * revert: style changes * refactor: simplify condition * fix: nit
1 parent 69d42a5 commit 2b3a6ec

File tree

15 files changed

+143
-15
lines changed

15 files changed

+143
-15
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ provider, such as `ts-node`. Otherwise, widening the acceptance extension here w
319319
```
320320
321321
## Override TypeScript detection using an environment variable
322+
This plugin uses [native type stripping](https://nodejs.org/docs/latest-v23.x/api/typescript.html#modules-typescript) with Node 23 and later.
322323
323324
It is possible to override the automatic detection of a TypeScript-capable runtime using the `FASTIFY_AUTOLOAD_TYPESCRIPT` environment variable. If set to a truthy value Autoload will load `.ts` files, expecting that node has a TypeScript-capable loader.
324325

lib/find-plugins.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,16 @@ function accumulatePlugin ({ file, type, opts, pluginTree, prefix }) {
144144
}
145145

146146
function handleTypeScriptSupport (file, language, isHook = false) {
147-
if (language === 'typescript' && !runtime.supportTypeScript) {
148-
throw new Error(`@fastify/autoload cannot import ${isHook ? 'hooks ' : ''}plugin at '${file}'. To fix this error compile TypeScript to JavaScript or use 'ts-node' to run your app.`)
149-
}
147+
if (
148+
language === 'typescript' &&
149+
/* c8 ignore start - This cannot be reached from Node 23 native type-stripping */
150+
!runtime.supportTypeScript
151+
) {
152+
throw new Error(
153+
`@fastify/autoload cannot import ${isHook ? 'hooks ' : ''}plugin at '${file}'. To fix this error compile TypeScript to JavaScript or use 'ts-node' to run your app.`
154+
)
155+
}
156+
/* c8 ignore end */
150157
}
151158

152159
function filterPath (path, filter) {

lib/runtime.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ Object.defineProperties(runtime, {
116116
runtime.tsm ||
117117
runtime.tsx ||
118118
runtime.esbuild ||
119-
runtime.tsimp
119+
runtime.tsimp ||
120+
runtime.nodeVersion >= 23
120121
)
121122
return cache.supportTypeScript
122123
}
@@ -130,7 +131,13 @@ Object.defineProperties(runtime, {
130131
)
131132
return cache.forceESM
132133
}
133-
}
134+
},
135+
nodeVersion: {
136+
get () {
137+
cache.nodeVersion ??= Number(process.version.split('.')[0].slice(1))
138+
return cache.nodeVersion
139+
},
140+
},
134141
})
135142

136143
module.exports = runtime

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"scripts": {
99
"lint": "eslint",
1010
"lint:fix": "eslint --fix",
11-
"test": "npm run typescript && npm run typescript:jest && npm run typescript:swc-node-register && npm run typescript:tsm && npm run typescript:tsx && npm run typescript:vitest && npm run typescript:esbuild && npm run unit",
11+
"test": "npm run typescript && npm run typescript:native && npm run typescript:jest && npm run typescript:swc-node-register && npm run typescript:tsm && npm run typescript:tsx && npm run typescript:vitest && npm run typescript:esbuild && npm run unit",
1212
"typescript": "tsd",
1313
"typescript:jest": "jest",
1414
"typescript:esm": "node scripts/unit-typescript-esm.js",
@@ -17,6 +17,7 @@
1717
"typescript:tsx": "node scripts/unit-typescript-tsx.js",
1818
"typescript:tsimp": "node scripts/unit-typescript-tsimp.js",
1919
"typescript:esbuild": "node scripts/unit-typescript-esbuild.js",
20+
"typescript:native": "node scripts/unit-typescript-native-type-stripping.js",
2021
"typescript:vitest": "vitest run",
2122
"typescript:vitest:dev": "vitest",
2223
"unit": "node scripts/unit.js",
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'use strict'
2+
3+
const { exec } = require('node:child_process')
4+
const runtime = require('../lib/runtime')
5+
6+
function common () {
7+
const args = ['node', 'test/typescript-common/index.ts']
8+
const child = exec(args.join(' '), {
9+
shell: true,
10+
})
11+
child.stdout.pipe(process.stdout)
12+
child.stderr.pipe(process.stderr)
13+
child.once('close', esm)
14+
}
15+
16+
function esm () {
17+
const args = ['node', 'test/typescript-esm/forceESM.ts']
18+
19+
const child = exec(args.join(' '), {
20+
shell: true,
21+
})
22+
23+
child.stdout.pipe(process.stdout)
24+
child.stderr.pipe(process.stderr)
25+
child.once('close', process.exit)
26+
}
27+
28+
if (runtime.nodeVersion >= 23) {
29+
common()
30+
}

scripts/unit-typescript-tsx.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
'use strict'
22

33
const { exec } = require('node:child_process')
4-
5-
const version = Number(process.version.split('.')[0].slice(1))
4+
const runtime = require('../lib/runtime')
65

76
const args = [
87
'npx',
9-
version >= 18 ? '--node-options=--import=tsx' : '',
8+
runtime.nodeVersion >= 18 ? '--node-options=--import=tsx' : '',
109
'tsnd',
1110
'test/typescript/basic.ts'
1211
]

test/commonjs/error.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
const t = require('tap')
44
const fastify = require('fastify')
5+
const runtime = require('../../lib/runtime')
6+
7+
const typeStrippingEnabled = runtime.nodeVersion >= 23
58

69
t.test('independent of module support', function (t) {
7-
t.plan(8)
10+
t.plan(typeStrippingEnabled ? 7 : 8)
811
const app = fastify()
912

1013
app.register(require('./syntax-error/app'))
@@ -28,8 +31,12 @@ t.test('independent of module support', function (t) {
2831
app3.register(require('./ts-error/app'))
2932

3033
app3.ready(function (err) {
31-
t.type(err, Error)
32-
t.match(err.message, /cannot import plugin.*typescript/i)
34+
if (typeStrippingEnabled) {
35+
t.error(err)
36+
} else {
37+
t.type(err, Error)
38+
t.match(err.message, /cannot import plugin.*typescript/i)
39+
}
3340
})
3441

3542
const app4 = fastify()

test/issues/369/test.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const { test } = require('tap')
44
const Fastify = require('fastify')
55
const path = require('node:path')
66
const autoload = require('../../..')
7+
const runtime = require('../../../lib/runtime')
78

89
test('Should throw an error when trying to load invalid hooks', async (t) => {
910
const app = Fastify()
@@ -22,7 +23,11 @@ test('Should throw an error when trying to import hooks plugin using index.ts if
2223
autoHooks: true
2324
})
2425

25-
await t.rejects(app.ready(), new Error(`@fastify/autoload cannot import hooks plugin at '${path.join(__dirname, 'invalid-index-type/index.ts')}'`))
26+
if (runtime.nodeVersion >= 23) {
27+
t.doesNotThrow(() => app.ready())
28+
} else {
29+
await t.rejects(app.ready(), new Error(`@fastify/autoload cannot import hooks plugin at '${path.join(__dirname, 'invalid-index-type/index.ts')}'`))
30+
}
2631
})
2732

2833
test('Should not accumulate plugin if doesn\'t comply to matchFilter', async (t) => {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { FastifyInstance } from 'fastify'
2+
3+
const { join } = require('node:path')
4+
const fastifyAutoLoad = require('../../../index.js')
5+
6+
module.exports = function (fastify: FastifyInstance, _opts: any, next: any) {
7+
fastify.register(fastifyAutoLoad, {
8+
dir: join(__dirname, 'foo'),
9+
})
10+
11+
next()
12+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict'
2+
3+
module.exports = function (fastify, _opts, next) {
4+
fastify.get('/javascript', (_request, reply) => {
5+
reply.send({ script: 'java' })
6+
})
7+
8+
next()
9+
}

0 commit comments

Comments
 (0)