Skip to content

Commit 15df9b1

Browse files
authored
feat(napi): expose cloneWithOptions and clearCache methods (#40)
* feat(napi): expose `cloneWithOptions` and `clearCache` methods
1 parent 06fbeae commit 15df9b1

File tree

6 files changed

+87
-63
lines changed

6 files changed

+87
-63
lines changed

napi/Cargo.lock

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

napi/index.d.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ export interface NapiResolveOptions {
1919
tsconfig?: TsconfigOptions
2020
/**
2121
* Alias for [ResolveOptions::alias] and [ResolveOptions::fallback].
22+
*
2223
* For the second value of the tuple, `None -> AliasValue::Ignore`, Some(String) ->
2324
* AliasValue::Path(String)`
2425
* Create aliases to import or require certain modules more easily.
2526
* A trailing $ can also be added to the given object's keys to signify an exact match.
26-
*
2727
*/
2828
alias?: Record<string, Array<string | undefined | null>>
2929
/**
@@ -199,7 +199,11 @@ export interface ResolveResult {
199199
}
200200
export function sync(path: string, request: string): ResolveResult
201201
export class ResolverFactory {
202-
constructor(op: NapiResolveOptions)
202+
constructor(options: NapiResolveOptions)
203203
static default(): ResolverFactory
204+
/** Clone the resolver using the same underlying cache. */
205+
cloneWithOptions(options: NapiResolveOptions): ResolverFactory
206+
/** Clear the underlying cache. */
207+
clearCache(): void
204208
sync(path: string, request: string): ResolveResult
205209
}

napi/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,8 @@ if (!nativeBinding) {
252252
throw new Error(`Failed to load native binding`)
253253
}
254254

255-
const { EnforceExtension, ResolverFactory, sync } = nativeBinding
255+
const { EnforceExtension, sync, ResolverFactory } = nativeBinding
256256

257257
module.exports.EnforceExtension = EnforceExtension
258-
module.exports.ResolverFactory = ResolverFactory
259258
module.exports.sync = sync
259+
module.exports.ResolverFactory = ResolverFactory

napi/src/lib.rs

Lines changed: 70 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,24 @@ pub struct ResolveResult {
1717
pub error: Option<String>,
1818
}
1919

20+
fn resolve(resolver: &Resolver, path: &Path, request: &str) -> ResolveResult {
21+
match resolver.resolve(path, request) {
22+
Ok(resolution) => ResolveResult {
23+
path: Some(resolution.full_path().to_string_lossy().to_string()),
24+
error: None,
25+
},
26+
Err(err) => ResolveResult { path: None, error: Some(err.to_string()) },
27+
}
28+
}
29+
30+
#[allow(clippy::needless_pass_by_value)]
31+
#[napi]
32+
pub fn sync(path: String, request: String) -> ResolveResult {
33+
let path = PathBuf::from(path);
34+
let resolver = Resolver::new(ResolveOptions::default());
35+
resolve(&resolver, &path, &request)
36+
}
37+
2038
#[napi]
2139
pub struct ResolverFactory {
2240
resolver: Resolver,
@@ -25,10 +43,39 @@ pub struct ResolverFactory {
2543
#[napi]
2644
impl ResolverFactory {
2745
#[napi(constructor)]
28-
pub fn new(op: NapiResolveOptions) -> Self {
46+
pub fn new(options: NapiResolveOptions) -> Self {
47+
Self { resolver: Resolver::new(Self::normalize_options(options)) }
48+
}
49+
50+
#[napi]
51+
pub fn default() -> Self {
2952
let default_options = ResolveOptions::default();
53+
Self { resolver: Resolver::new(default_options) }
54+
}
55+
56+
/// Clone the resolver using the same underlying cache.
57+
#[napi]
58+
pub fn clone_with_options(&self, options: NapiResolveOptions) -> Self {
59+
Self { resolver: self.resolver.clone_with_options(Self::normalize_options(options)) }
60+
}
61+
62+
/// Clear the underlying cache.
63+
#[napi]
64+
pub fn clear_cache(&self) {
65+
self.resolver.clear_cache();
66+
}
67+
68+
#[allow(clippy::needless_pass_by_value)]
69+
#[napi]
70+
pub fn sync(&self, path: String, request: String) -> ResolveResult {
71+
let path = PathBuf::from(path);
72+
resolve(&self.resolver, &path, &request)
73+
}
74+
75+
fn normalize_options(op: NapiResolveOptions) -> ResolveOptions {
76+
let default = ResolveOptions::default();
3077
// merging options
31-
let finalize_options = ResolveOptions {
78+
ResolveOptions {
3279
tsconfig: op.tsconfig.map(|tsconfig| tsconfig.into()),
3380
alias: op
3481
.alias
@@ -47,26 +94,26 @@ impl ResolverFactory {
4794
})
4895
.collect::<Vec<_>>()
4996
})
50-
.unwrap_or(default_options.alias),
97+
.unwrap_or(default.alias),
5198
alias_fields: op
5299
.alias_fields
53100
.map(|o| o.into_iter().map(|x| StrOrStrList(x).into()).collect::<Vec<_>>())
54-
.unwrap_or(default_options.alias_fields),
55-
condition_names: op.condition_names.unwrap_or(default_options.condition_names),
56-
description_files: op.description_files.unwrap_or(default_options.description_files),
101+
.unwrap_or(default.alias_fields),
102+
condition_names: op.condition_names.unwrap_or(default.condition_names),
103+
description_files: op.description_files.unwrap_or(default.description_files),
57104
enforce_extension: op
58105
.enforce_extension
59106
.map(|enforce_extension| enforce_extension.into())
60-
.unwrap_or(default_options.enforce_extension),
107+
.unwrap_or(default.enforce_extension),
61108
exports_fields: op
62109
.exports_fields
63110
.map(|o| o.into_iter().map(|x| StrOrStrList(x).into()).collect::<Vec<_>>())
64-
.unwrap_or(default_options.exports_fields),
111+
.unwrap_or(default.exports_fields),
65112
extension_alias: op
66113
.extension_alias
67114
.map(|extension_alias| extension_alias.into_iter().collect::<Vec<_>>())
68-
.unwrap_or(default_options.extension_alias),
69-
extensions: op.extensions.unwrap_or(default_options.extensions),
115+
.unwrap_or(default.extension_alias),
116+
extensions: op.extensions.unwrap_or(default.extensions),
70117
fallback: op
71118
.fallback
72119
.map(|fallback| {
@@ -84,17 +131,17 @@ impl ResolverFactory {
84131
})
85132
.collect::<Vec<_>>()
86133
})
87-
.unwrap_or(default_options.fallback),
88-
fully_specified: op.fully_specified.unwrap_or(default_options.fully_specified),
134+
.unwrap_or(default.fallback),
135+
fully_specified: op.fully_specified.unwrap_or(default.fully_specified),
89136
main_fields: op
90137
.main_fields
91138
.map(|o| StrOrStrList(o).into())
92-
.unwrap_or(default_options.main_fields),
93-
main_files: op.main_files.unwrap_or(default_options.main_files),
94-
modules: op.modules.map(|o| StrOrStrList(o).into()).unwrap_or(default_options.modules),
95-
resolve_to_context: op.resolve_to_context.unwrap_or(default_options.resolve_to_context),
96-
prefer_relative: op.prefer_relative.unwrap_or(default_options.prefer_relative),
97-
prefer_absolute: op.prefer_absolute.unwrap_or(default_options.prefer_absolute),
139+
.unwrap_or(default.main_fields),
140+
main_files: op.main_files.unwrap_or(default.main_files),
141+
modules: op.modules.map(|o| StrOrStrList(o).into()).unwrap_or(default.modules),
142+
resolve_to_context: op.resolve_to_context.unwrap_or(default.resolve_to_context),
143+
prefer_relative: op.prefer_relative.unwrap_or(default.prefer_relative),
144+
prefer_absolute: op.prefer_absolute.unwrap_or(default.prefer_absolute),
98145
restrictions: op
99146
.restrictions
100147
.map(|restrictions| {
@@ -103,44 +150,13 @@ impl ResolverFactory {
103150
.map(|restriction| restriction.into())
104151
.collect::<Vec<_>>()
105152
})
106-
.unwrap_or(default_options.restrictions),
153+
.unwrap_or(default.restrictions),
107154
roots: op
108155
.roots
109156
.map(|roots| roots.into_iter().map(PathBuf::from).collect::<Vec<_>>())
110-
.unwrap_or(default_options.roots),
111-
symlinks: op.symlinks.unwrap_or(default_options.symlinks),
112-
builtin_modules: op.builtin_modules.unwrap_or(default_options.builtin_modules),
113-
};
114-
Self { resolver: Resolver::new(finalize_options) }
115-
}
116-
#[napi]
117-
pub fn default() -> Self {
118-
let default_options = ResolveOptions::default();
119-
Self { resolver: Resolver::new(default_options) }
120-
}
121-
122-
#[allow(clippy::needless_pass_by_value)]
123-
#[napi]
124-
pub fn sync(&self, path: String, request: String) -> ResolveResult {
125-
let path = PathBuf::from(path);
126-
resolve(&self.resolver, &path, &request)
127-
}
128-
}
129-
130-
fn resolve(resolver: &Resolver, path: &Path, request: &str) -> ResolveResult {
131-
match resolver.resolve(path, request) {
132-
Ok(resolution) => ResolveResult {
133-
path: Some(resolution.full_path().to_string_lossy().to_string()),
134-
error: None,
135-
},
136-
Err(err) => ResolveResult { path: None, error: Some(err.to_string()) },
157+
.unwrap_or(default.roots),
158+
symlinks: op.symlinks.unwrap_or(default.symlinks),
159+
builtin_modules: op.builtin_modules.unwrap_or(default.builtin_modules),
160+
}
137161
}
138162
}
139-
140-
#[allow(clippy::needless_pass_by_value)]
141-
#[napi]
142-
pub fn sync(path: String, request: String) -> ResolveResult {
143-
let path = PathBuf::from(path);
144-
let resolver = Resolver::new(ResolveOptions::default());
145-
resolve(&resolver, &path, &request)
146-
}

napi/test.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ assert.deepStrictEqual(resolver.sync(cwd, "./index.js").path, path.join(cwd, 'in
1515

1616
assert.strict(resolver.sync(cwd, "./ts").error.length > 0);
1717

18+
const newResolver = resolver.cloneWithOptions({});
19+
newResolver.clearCache();
20+
1821

1922
// custom constructor
2023
const resolver2 = new ResolverFactory(

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ impl<Fs: FileSystem + Default> ResolverGeneric<Fs> {
147147
Self { cache: Arc::new(Cache::new(file_system)), ..Self::new(options) }
148148
}
149149

150+
/// Clone the resolver using the same underlying cache.
150151
#[must_use]
151152
pub fn clone_with_options(&self, options: ResolveOptions) -> Self {
152153
Self { options: options.sanitize(), cache: Arc::clone(&self.cache) }

0 commit comments

Comments
 (0)