Skip to content

Commit 8ca8ff8

Browse files
authored
feat(napi): add ResolveResult::builtin information (#575)
closes #565
1 parent 77ea974 commit 8ca8ff8

File tree

3 files changed

+65
-9
lines changed

3 files changed

+65
-9
lines changed

napi/index.d.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,22 @@ export declare class ResolverFactory {
1313
async(directory: string, request: string): Promise<ResolveResult>
1414
}
1515

16+
/** Node.js builtin module when `Options::builtin_modules` is enabled. */
17+
export interface Builtin {
18+
/**
19+
* Resolved module.
20+
*
21+
* Always prefixed with "node:" in compliance with the ESM specification.
22+
*/
23+
resolved: string
24+
/**
25+
* Whether the request was prefixed with `node:` or not.
26+
* `fs` -> `false`.
27+
* `node:fs` returns `true`.
28+
*/
29+
isRuntimeModule: boolean
30+
}
31+
1632
export declare const enum EnforceExtension {
1733
Auto = 0,
1834
Enabled = 1,
@@ -207,6 +223,7 @@ export interface NapiResolveOptions {
207223
export interface ResolveResult {
208224
path?: string
209225
error?: string
226+
builtin?: Builtin
210227
/**
211228
* Module type for this path.
212229
*

napi/src/lib.rs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::{
1212

1313
use napi::{Task, bindgen_prelude::AsyncTask};
1414
use napi_derive::napi;
15-
use oxc_resolver::{PackageJson, ResolveOptions, Resolver};
15+
use oxc_resolver::{PackageJson, ResolveError, ResolveOptions, Resolver};
1616

1717
use self::options::{NapiResolveOptions, StrOrStrList};
1818

@@ -24,6 +24,7 @@ mod tracing;
2424
pub struct ResolveResult {
2525
pub path: Option<String>,
2626
pub error: Option<String>,
27+
pub builtin: Option<Builtin>,
2728
/// Module type for this path.
2829
///
2930
/// Enable with `ResolveOptions#moduleType`.
@@ -37,23 +38,47 @@ pub struct ResolveResult {
3738
pub package_json_path: Option<String>,
3839
}
3940

41+
/// Node.js builtin module when `Options::builtin_modules` is enabled.
42+
#[napi(object)]
43+
pub struct Builtin {
44+
/// Resolved module.
45+
///
46+
/// Always prefixed with "node:" in compliance with the ESM specification.
47+
pub resolved: String,
48+
49+
/// Whether the request was prefixed with `node:` or not.
50+
/// `fs` -> `false`.
51+
/// `node:fs` returns `true`.
52+
pub is_runtime_module: bool,
53+
}
54+
4055
fn resolve(resolver: &Resolver, path: &Path, request: &str) -> ResolveResult {
4156
match resolver.resolve(path, request) {
4257
Ok(resolution) => ResolveResult {
4358
path: Some(resolution.full_path().to_string_lossy().to_string()),
4459
error: None,
60+
builtin: None,
4561
module_type: resolution.module_type().map(ModuleType::from),
4662
package_json_path: resolution
4763
.package_json()
4864
.and_then(|p| p.path().to_str())
4965
.map(|p| p.to_string()),
5066
},
51-
Err(err) => ResolveResult {
52-
path: None,
53-
module_type: None,
54-
error: Some(err.to_string()),
55-
package_json_path: None,
56-
},
67+
Err(err) => {
68+
let error = err.to_string();
69+
ResolveResult {
70+
path: None,
71+
builtin: match err {
72+
ResolveError::Builtin { resolved, is_runtime_module } => {
73+
Some(Builtin { resolved, is_runtime_module })
74+
}
75+
_ => None,
76+
},
77+
module_type: None,
78+
error: Some(error),
79+
package_json_path: None,
80+
}
81+
}
5782
}
5883
}
5984

@@ -250,11 +275,11 @@ impl ResolverFactory {
250275
symlinks: op.symlinks.unwrap_or(default.symlinks),
251276
builtin_modules: op.builtin_modules.unwrap_or(default.builtin_modules),
252277
module_type: op.module_type.unwrap_or(default.module_type),
253-
#[cfg(feature = "yarn_pnp")]
254-
pnp_manifest: default.pnp_manifest,
255278
allow_package_exports_in_directory_resolve: op
256279
.allow_package_exports_in_directory_resolve
257280
.unwrap_or(default.allow_package_exports_in_directory_resolve),
281+
#[cfg(feature = "yarn_pnp")]
282+
pnp_manifest: default.pnp_manifest,
258283
}
259284
}
260285
}

napi/tests/simple.test.mjs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,17 @@ test('module_type', () => {
4141

4242
assert.equal(cjsResolver.sync(dir, 'minimatch').moduleType, ModuleType.CommonJs);
4343
});
44+
45+
test('builtin', () => {
46+
const resolver = new ResolverFactory({
47+
builtinModules: true,
48+
});
49+
assert.deepEqual(resolver.sync('/', 'fs').builtin, {
50+
resolved: 'node:fs',
51+
isRuntimeModule: false,
52+
});
53+
assert.deepEqual(resolver.sync('/', 'node:fs').builtin, {
54+
resolved: 'node:fs',
55+
isRuntimeModule: true,
56+
});
57+
});

0 commit comments

Comments
 (0)