Skip to content

Commit 335d183

Browse files
committed
feat: support compile js files
1 parent 0b354b0 commit 335d183

File tree

8 files changed

+82
-57
lines changed

8 files changed

+82
-57
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
},
8888
"ava": {
8989
"extensions": [
90+
"js",
9091
"ts",
9192
"tsx"
9293
],
@@ -95,7 +96,7 @@
9596
],
9697
"cache": false,
9798
"files": [
98-
"packages/**/*.spec.{ts,tsx}"
99+
"packages/**/*.spec.{js,ts,tsx}"
99100
],
100101
"environmentVariables": {
101102
"SWC_NODE_PROJECT": "./tsconfig.test.json"

packages/integrate-module/src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { supportedExtensions } from 'file-type'
77
import { foo } from './foo.mjs'
88
import { bar } from './subdirectory/bar.mjs'
99
import { baz } from './subdirectory/index.mjs'
10+
import { bar as subBar } from '@subdirectory/bar.mjs'
11+
import './js-module.mjs'
1012

1113
await test('file-type should work', () => {
1214
assert.ok(supportedExtensions.has('jpg'))
@@ -23,3 +25,7 @@ await test('resolve nested file path', () => {
2325
await test('resolve nested entry point', () => {
2426
assert.equal(baz(), 'baz')
2527
})
28+
29+
await test('resolve paths', () => {
30+
assert.equal(subBar(), 'bar')
31+
})
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* eslint import/order: off */
2+
import assert from 'node:assert'
3+
import test from 'node:test'
4+
5+
import { supportedExtensions } from 'file-type'
6+
7+
import { foo } from './foo.mts'
8+
import { bar } from './subdirectory/bar.mts'
9+
import { baz } from './subdirectory/index.mts'
10+
import { bar as subBar } from '@subdirectory/bar.mts'
11+
12+
await test('js:file-type should work', () => {
13+
assert.ok(supportedExtensions.has('jpg'))
14+
})
15+
16+
await test('js:resolve adjacent file path', () => {
17+
assert.equal(foo(), 'foo')
18+
})
19+
20+
await test('js:resolve nested file path', () => {
21+
assert.equal(bar(), 'bar')
22+
})
23+
24+
await test('js:resolve nested entry point', () => {
25+
assert.equal(baz(), 'baz')
26+
})
27+
28+
await test('js:resolve paths', () => {
29+
assert.equal(subBar(), 'bar')
30+
})

packages/integrate-module/tsconfig.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
"target": "ESNext",
55
"module": "ESNext",
66
"composite": true,
7-
"outDir": "dist"
7+
"outDir": "dist",
8+
"baseUrl": "./",
9+
"paths": {
10+
"@subdirectory/*": ["./src/subdirectory/*"],
11+
},
812
},
9-
"include": ["src"]
13+
"include": ["src"],
1014
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { FIXTURE } from '@integrate/fixture'
2+
import test from 'ava'
3+
4+
test('js should transpile paths', (t) => {
5+
t.is(FIXTURE, 'fixture')
6+
})

packages/register/esm.mts

Lines changed: 30 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { LoadHook, ResolveHook } from 'node:module'
12
import { fileURLToPath, pathToFileURL } from 'url'
23

34
import ts from 'typescript'
@@ -7,24 +8,6 @@ import { readDefaultTsConfig } from '../lib/read-default-tsconfig.js'
78
// @ts-expect-error
89
import { compile } from '../lib/register.js'
910

10-
interface ResolveContext {
11-
conditions: string[]
12-
parentURL: string | undefined
13-
}
14-
15-
interface ResolveResult {
16-
format?: string
17-
shortCircuit?: boolean
18-
url: string
19-
}
20-
21-
type ResolveArgs = [
22-
specifier: string,
23-
context?: ResolveContext,
24-
nextResolve?: (...args: ResolveArgs) => Promise<ResolveResult>,
25-
]
26-
type ResolveFn = (...args: Required<ResolveArgs>) => Promise<ResolveResult>
27-
2811
const tsconfig: ts.CompilerOptions = readDefaultTsConfig()
2912
tsconfig.module = ts.ModuleKind.ESNext
3013

@@ -33,22 +16,27 @@ const host: ts.ModuleResolutionHost = {
3316
fileExists: ts.sys.fileExists,
3417
readFile: ts.sys.readFile,
3518
}
36-
const EXTENSIONS: string[] = [ts.Extension.Ts, ts.Extension.Tsx, ts.Extension.Mts]
3719

38-
export const resolve: ResolveFn = async (specifier, context, nextResolve) => {
39-
const isTS = EXTENSIONS.some((ext) => specifier.endsWith(ext))
20+
const AVAILABLE_TS_EXTENSION_PATTERN = new RegExp(
21+
`/(?!.d)(${[ts.Extension.Ts, ts.Extension.Tsx, ts.Extension.Mts, ts.Extension.Cts].join('|')})`,
22+
'i',
23+
)
4024

25+
export const resolve: ResolveHook = async (specifier, context, nextResolve) => {
4126
// entrypoint
4227
if (!context.parentURL) {
4328
return {
44-
format: isTS ? 'ts' : undefined,
29+
importAttributes: {
30+
...context.importAttributes,
31+
swc: 'entrypoint',
32+
},
4533
url: specifier,
4634
shortCircuit: true,
4735
}
4836
}
4937

5038
// import/require from external library
51-
if (context.parentURL.includes('/node_modules/') && !isTS) {
39+
if (context.parentURL.includes('/node_modules/') && AVAILABLE_TS_EXTENSION_PATTERN.test(specifier)) {
5240
return nextResolve(specifier)
5341
}
5442

@@ -60,50 +48,40 @@ export const resolve: ResolveFn = async (specifier, context, nextResolve) => {
6048
moduleResolutionCache,
6149
)
6250

63-
// import from local project to local project TS file
64-
if (
65-
resolvedModule &&
66-
!resolvedModule.resolvedFileName.includes('/node_modules/') &&
67-
EXTENSIONS.includes(resolvedModule.extension)
68-
) {
51+
// local project file
52+
if (resolvedModule && !resolvedModule.resolvedFileName.includes('/node_modules/')) {
6953
return {
70-
format: 'ts',
7154
url: pathToFileURL(resolvedModule.resolvedFileName).href,
7255
shortCircuit: true,
56+
importAttributes: {
57+
...context.importAttributes,
58+
swc: resolvedModule.resolvedFileName,
59+
},
7360
}
7461
}
7562

76-
// import from local project to either:
77-
// - something TS couldn't resolve
78-
// - external library
79-
// - local project non-TS file
63+
// files could not resolved by typescript
8064
return nextResolve(specifier)
8165
}
8266

83-
interface LoadContext {
84-
conditions: string[]
85-
format: string | null | undefined
86-
}
87-
88-
interface LoadResult {
89-
format: string
90-
shortCircuit?: boolean
91-
source: string | ArrayBuffer | SharedArrayBuffer | Uint8Array
92-
}
93-
94-
type LoadArgs = [url: string, context: LoadContext, nextLoad?: (...args: LoadArgs) => Promise<LoadResult>]
95-
type LoadFn = (...args: Required<LoadArgs>) => Promise<LoadResult>
96-
9767
const tsconfigForSWCNode = {
9868
...tsconfig,
9969
paths: undefined,
10070
baseUrl: undefined,
10171
}
10272

103-
export const load: LoadFn = async (url, context, nextLoad) => {
104-
if (context.format === 'ts') {
105-
const { source } = await nextLoad(url, context)
106-
const code = typeof source === 'string' ? source : Buffer.from(source).toString()
73+
export const load: LoadHook = async (url, context, nextLoad) => {
74+
const swcAttribute = context.importAttributes.swc
75+
76+
if (swcAttribute) {
77+
delete context.importAttributes.swc
78+
79+
const { source } = await nextLoad(url, {
80+
...context,
81+
format: 'ts' as any,
82+
})
83+
84+
const code = !source || typeof source === 'string' ? source : Buffer.from(source).toString()
10785
const compiled = await compile(code, fileURLToPath(url), tsconfigForSWCNode, true)
10886
return {
10987
format: 'module',

packages/register/tsconfig.esm.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
"outDir": "esm"
66
},
77
"include": [],
8-
"files": ["./esm.mts", "./esm-register.mts", "register.d.ts", "./read-default-tsconfig.d.ts"]
8+
"files": ["./esm.mts", "./esm-register.mts", "register.ts", "./read-default-tsconfig.ts"]
99
}

packages/register/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
},
1212
],
1313
"include": ["."],
14-
"exclude": ["lib"],
14+
"exclude": ["lib", "__test__"],
1515
}

0 commit comments

Comments
 (0)