Skip to content

Commit

Permalink
chore(napi): align *Fields in UserResolveOptions with enhanced-resolve
Browse files Browse the repository at this point in the history
  • Loading branch information
xc2 committed Dec 17, 2023
1 parent c4432a5 commit 4539ede
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 14 deletions.
8 changes: 4 additions & 4 deletions napi/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export interface NapiResolveOptions {
*
* Default `[]`
*/
aliasFields?: Array<Array<string>>
aliasFields?: (string | string[])[]
/**
* Condition names for exports field which defines entry points of a package.
* The key order in the exports field is significant. During condition matching, earlier entries have higher priority and take precedence over later entries.
Expand Down Expand Up @@ -65,7 +65,7 @@ export interface NapiResolveOptions {
*
* Default `[["exports"]]`.
*/
exportsFields?: Array<Array<string>>
exportsFields?: (string | string[])[]
/**
* An object which maps extension to extension aliases.
*
Expand Down Expand Up @@ -99,7 +99,7 @@ export interface NapiResolveOptions {
*
* Default `["main"]`.
*/
mainFields?: Array<string>
mainFields?: string | string[]
/**
* The filename to be used while resolving directories.
*
Expand All @@ -111,7 +111,7 @@ export interface NapiResolveOptions {
*
* Default `["node_modules"]`
*/
modules?: Array<string>
modules?: string | string[]
/**
* Resolve to a context instead of a file.
*
Expand Down
2 changes: 1 addition & 1 deletion napi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"scripts": {
"build": "napi build --platform --release",
"build:debug": "napi build --platform ",
"test": "node test.mjs"
"test": "node --test"
},
"devDependencies": {
"@napi-rs/cli": "^2.15.2"
Expand Down
19 changes: 14 additions & 5 deletions napi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};
use napi_derive::napi;
use oxc_resolver::{ResolveOptions, Resolver};

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

mod options;

Expand Down Expand Up @@ -48,14 +48,20 @@ impl ResolverFactory {
.collect::<Vec<_>>()
})
.unwrap_or(default_options.alias),
alias_fields: op.alias_fields.unwrap_or(default_options.alias_fields),
alias_fields: op
.alias_fields
.map(|o| o.into_iter().map(|x| StrOrStrList(x).into()).collect::<Vec<_>>())
.unwrap_or(default_options.alias_fields),
condition_names: op.condition_names.unwrap_or(default_options.condition_names),
description_files: op.description_files.unwrap_or(default_options.description_files),
enforce_extension: op
.enforce_extension
.map(|enforce_extension| enforce_extension.into())
.unwrap_or(default_options.enforce_extension),
exports_fields: op.exports_fields.unwrap_or(default_options.exports_fields),
exports_fields: op
.exports_fields
.map(|o| o.into_iter().map(|x| StrOrStrList(x).into()).collect::<Vec<_>>())
.unwrap_or(default_options.exports_fields),
extension_alias: op
.extension_alias
.map(|extension_alias| extension_alias.into_iter().collect::<Vec<_>>())
Expand All @@ -80,9 +86,12 @@ impl ResolverFactory {
})
.unwrap_or(default_options.fallback),
fully_specified: op.fully_specified.unwrap_or(default_options.fully_specified),
main_fields: op.main_fields.unwrap_or(default_options.main_fields),
main_fields: op
.main_fields
.map(|o| StrOrStrList(o).into())
.unwrap_or(default_options.main_fields),
main_files: op.main_files.unwrap_or(default_options.main_files),
modules: op.modules.unwrap_or(default_options.modules),
modules: op.modules.map(|o| StrOrStrList(o).into()).unwrap_or(default_options.modules),
resolve_to_context: op.resolve_to_context.unwrap_or(default_options.resolve_to_context),
prefer_relative: op.prefer_relative.unwrap_or(default_options.prefer_relative),
prefer_absolute: op.prefer_absolute.unwrap_or(default_options.prefer_absolute),
Expand Down
27 changes: 23 additions & 4 deletions napi/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ pub struct NapiResolveOptions {
/// Create aliases to import or require certain modules more easily.
/// A trailing $ can also be added to the given object's keys to signify an exact match.
///
// FIXME can be array
pub alias: Option<HashMap<String, Vec<Option<String>>>>,

/// A list of alias fields in description files.
/// Specify a field, such as `browser`, to be parsed according to [this specification](https://github.com/defunctzombie/package-browser-field-spec).
/// Can be a path to json object such as `["path", "to", "exports"]`.
///
/// Default `[]`
pub alias_fields: Option<Vec<Vec<String>>>,
#[napi(ts_type = "(string | string[])[]")]
pub alias_fields: Option<Vec<StrOrStrListType>>,

/// Condition names for exports field which defines entry points of a package.
/// The key order in the exports field is significant. During condition matching, earlier entries have higher priority and take precedence over later entries.
Expand Down Expand Up @@ -58,7 +60,8 @@ pub struct NapiResolveOptions {
/// Can be a path to json object such as `["path", "to", "exports"]`.
///
/// Default `[["exports"]]`.
pub exports_fields: Option<Vec<Vec<String>>>,
#[napi(ts_type = "(string | string[])[]")]
pub exports_fields: Option<Vec<StrOrStrListType>>,

/// An object which maps extension to extension aliases.
///
Expand All @@ -75,6 +78,7 @@ pub struct NapiResolveOptions {
/// Redirect module requests when normal resolving fails.
///
/// Default `[]`
// FIXME can be array - same as alias
pub fallback: Option<HashMap<String, Vec<Option<String>>>>,

/// Request passed to resolve is already fully specified and extensions or main files are not resolved for it (they are still resolved for internal requests).
Expand All @@ -87,7 +91,9 @@ pub struct NapiResolveOptions {
/// A list of main fields in description files
///
/// Default `["main"]`.
pub main_fields: Option<Vec<String>>,
// FIXME (string | string[] | { name: string | string[]; forceRelative: boolean })[]
#[napi(ts_type = "string | string[]")]
pub main_fields: Option<StrOrStrListType>,

/// The filename to be used while resolving directories.
///
Expand All @@ -97,7 +103,8 @@ pub struct NapiResolveOptions {
/// A list of directories to resolve modules from, can be absolute path or folder name.
///
/// Default `["node_modules"]`
pub modules: Option<Vec<String>>,
#[napi(ts_type = "string | string[]")]
pub modules: Option<StrOrStrListType>,

/// Resolve to a context instead of a file.
///
Expand Down Expand Up @@ -234,3 +241,15 @@ impl Into<oxc_resolver::TsconfigOptions> for TsconfigOptions {
}
}
}

type StrOrStrListType = Either<String, Vec<String>>;
pub struct StrOrStrList(pub StrOrStrListType);

impl Into<Vec<String>> for StrOrStrList {
fn into(self) -> Vec<String> {
match self {
StrOrStrList(Either::A(s)) => Vec::from([s]),
StrOrStrList(Either::B(a)) => a,
}
}
}
59 changes: 59 additions & 0 deletions napi/tests/options.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { describe, it } from "node:test";
import { ResolverFactory } from "../index.js";
import * as assert from "node:assert";
import * as path from "node:path";

const fixtureDir = new URL(
"../../fixtures/enhanced_resolve/test/fixtures",
import.meta.url
).pathname;

describe("option", () => {
describe("aliasFields", () => {
it("should allow field string ", () => {
const resolver = new ResolverFactory({ aliasFields: ["browser"] });
assert.match(
resolver.sync(fixtureDir, "./browser-module/lib/replaced.js").path,
/browser-module\/lib\/browser\.js$/
);
});
it("should allow json path array", () => {
const resolver = new ResolverFactory({
aliasFields: [["innerBrowser1", "field", "browser"]],
});

assert.match(
resolver.sync(fixtureDir, "./browser-module/lib/main1.js").path,
/browser-module\/lib\/main\.js$/
);
});
});

describe("exportsFields", () => {
const createTest = (exportsFields) => {
const resolver = new ResolverFactory({ exportsFields });
assert.match(
resolver.sync(
path.resolve(fixtureDir, "./exports-field3"),
"exports-field"
).path,
/\/exports-field\/src\/index\.js$/
);
};
it("should allow string as field item", createTest(["broken"]));
it("should allow json path array as field item", createTest([["broken"]]));
});

describe("mainFields", () => {
const createTest = (mainFields) => {
const resolver = new ResolverFactory({ mainFields });
assert.match(
resolver.sync(fixtureDir, "../..").path,
/\/lib\/index\.js$/
);
};
it("should use `'main'` as default", createTest(undefined));
it("should allow field string", createTest("main"));
it("should allow field array", createTest(["main"]));
});
});

0 comments on commit 4539ede

Please sign in to comment.