Skip to content

Commit

Permalink
Add support for nested main field selectors
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronadamsCA committed Jul 29, 2022
1 parent f420039 commit 0a2d6f4
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 18 deletions.
6 changes: 3 additions & 3 deletions README.md
Expand Up @@ -146,7 +146,7 @@ The public API consists of these functions:
export interface ExplicitParams {
baseUrl: string;
paths: { [key: string]: Array<string> };
mainFields?: Array<string>;
mainFields?: (string | string[])[];
addMatchAll?: boolean;
cwd?: string;
}
Expand Down Expand Up @@ -209,7 +209,7 @@ export interface MatchPath {
export function createMatchPath(
absoluteBaseUrl: string,
paths: { [key: string]: Array<string> },
mainFields: string[] = ["main"],
mainFields: (string | string[])[] = ["main"],
addMatchAll: boolean = true
): MatchPath {
```
Expand All @@ -235,7 +235,7 @@ export function matchFromAbsolutePaths(
readJson: Filesystem.ReadJsonSync = Filesystem.readJsonFromDiskSync,
fileExists: Filesystem.FileExistsSync = Filesystem.fileExistsSync,
extensions: Array<string> = Object.keys(require.extensions),
mainFields: string[] = ["main"]
mainFields: (string | string[])[] = ["main"]
): string | undefined {
```
Expand Down
13 changes: 12 additions & 1 deletion src/__tests__/data/match-path-data.ts
Expand Up @@ -7,7 +7,7 @@ export interface OneTest {
readonly skip?: boolean;
readonly absoluteBaseUrl: string;
readonly paths: { [key: string]: Array<string> };
readonly mainFields?: string[];
readonly mainFields?: (string | string[])[];
readonly addMatchAll?: boolean;
readonly existingFiles: ReadonlyArray<string>;
readonly requestedModule: string;
Expand Down Expand Up @@ -149,6 +149,17 @@ export const tests: ReadonlyArray<OneTest> = [
extensions: [".ts", ".js"],
expectedPath: join("/root", "location", "mylibjs", "kalle.js"),
},
{
name: "should resolve nested main fields",
absoluteBaseUrl: "/root/",
paths: { "lib/*": ["location/*"] },
mainFields: [["esnext", "main"]],
packageJson: { esnext: { main: "./main.js" } },
existingFiles: [join("/root", "location", "mylibjs", "main.js")],
extensions: [".ts", ".js"],
requestedModule: "lib/mylibjs",
expectedPath: join("/root", "location", "mylibjs", "main.js"),
},
{
name: "should ignore advanced field mappings in package.json",
absoluteBaseUrl: "/root/",
Expand Down
4 changes: 2 additions & 2 deletions src/config-loader.ts
Expand Up @@ -4,7 +4,7 @@ import * as path from "path";
export interface ExplicitParams {
baseUrl: string;
paths: { [key: string]: Array<string> };
mainFields?: Array<string>;
mainFields?: (string | string[])[];
addMatchAll?: boolean;
}

Expand All @@ -24,7 +24,7 @@ export interface ConfigLoaderSuccessResult {
baseUrl?: string;
absoluteBaseUrl: string;
paths: { [key: string]: Array<string> };
mainFields?: Array<string>;
mainFields?: (string | string[])[];
addMatchAll?: boolean;
}

Expand Down
2 changes: 1 addition & 1 deletion src/filesystem.ts
Expand Up @@ -4,7 +4,7 @@ import * as fs from "fs";
* Typing for the fields of package.json we care about
*/
export interface PackageJson {
[key: string]: string;
[key: string]: string | PackageJson;
}

/**
Expand Down
14 changes: 9 additions & 5 deletions src/match-path-async.ts
Expand Up @@ -27,7 +27,7 @@ export interface MatchPathAsyncCallback {
export function createMatchPathAsync(
absoluteBaseUrl: string,
paths: { [key: string]: Array<string> },
mainFields: string[] = ["main"],
mainFields: (string | string[])[] = ["main"],
addMatchAll: boolean = true
): MatchPathAsync {
const absolutePaths = MappingEntry.getAbsoluteMappingEntries(
Expand Down Expand Up @@ -64,7 +64,7 @@ export function matchFromAbsolutePathsAsync(
fileExists: Filesystem.FileExistsAsync = Filesystem.fileExistsAsync,
extensions: ReadonlyArray<string> = Object.keys(require.extensions),
callback: MatchPathAsyncCallback,
mainFields: string[] = ["main"]
mainFields: (string | string[])[] = ["main"]
): void {
const tryPaths = TryPath.getPathsToTry(
extensions,
Expand All @@ -88,7 +88,7 @@ export function matchFromAbsolutePathsAsync(

function findFirstExistingMainFieldMappedFile(
packageJson: Filesystem.PackageJson,
mainFields: string[],
mainFields: (string | string[])[],
packageJsonPath: string,
fileExistsAsync: Filesystem.FileExistsAsync,
doneCallback: (err?: Error, filepath?: string) => void,
Expand All @@ -108,7 +108,11 @@ function findFirstExistingMainFieldMappedFile(
index + 1
);

const mainFieldMapping = packageJson[mainFields[index]];
const mainFieldSelector = mainFields[index];
const mainFieldMapping =
typeof mainFieldSelector === "string"
? packageJson[mainFieldSelector]
: mainFieldSelector.reduce((obj, key) => obj[key], packageJson);
if (typeof mainFieldMapping !== "string") {
// Skip mappings that are not pointers to replacement files
return tryNext();
Expand Down Expand Up @@ -136,7 +140,7 @@ function findFirstExistingPath(
fileExists: Filesystem.FileExistsAsync,
doneCallback: MatchPathAsyncCallback,
index: number = 0,
mainFields: string[] = ["main"]
mainFields: (string | string[])[] = ["main"]
): void {
const tryPath = tryPaths[index];
if (
Expand Down
15 changes: 9 additions & 6 deletions src/match-path-sync.ts
Expand Up @@ -27,7 +27,7 @@ export interface MatchPath {
export function createMatchPath(
absoluteBaseUrl: string,
paths: { [key: string]: Array<string> },
mainFields: string[] = ["main"],
mainFields: (string | string[])[] = ["main"],
addMatchAll: boolean = true
): MatchPath {
const absolutePaths = MappingEntry.getAbsoluteMappingEntries(
Expand Down Expand Up @@ -69,7 +69,7 @@ export function matchFromAbsolutePaths(
readJson: Filesystem.ReadJsonSync = Filesystem.readJsonFromDiskSync,
fileExists: Filesystem.FileExistsSync = Filesystem.fileExistsSync,
extensions: Array<string> = Object.keys(require.extensions),
mainFields: string[] = ["main"]
mainFields: (string | string[])[] = ["main"]
): string | undefined {
const tryPaths = TryPath.getPathsToTry(
extensions,
Expand All @@ -86,13 +86,16 @@ export function matchFromAbsolutePaths(

function findFirstExistingMainFieldMappedFile(
packageJson: Filesystem.PackageJson,
mainFields: string[],
mainFields: (string | string[])[],
packageJsonPath: string,
fileExists: Filesystem.FileExistsSync
): string | undefined {
for (let index = 0; index < mainFields.length; index++) {
const mainFieldName = mainFields[index];
const candidateMapping = packageJson[mainFieldName];
const mainFieldSelector = mainFields[index];
const candidateMapping =
typeof mainFieldSelector === "string"
? packageJson[mainFieldSelector]
: mainFieldSelector.reduce((obj, key) => obj[key], packageJson);
if (candidateMapping && typeof candidateMapping === "string") {
const candidateFilePath = path.join(
path.dirname(packageJsonPath),
Expand All @@ -111,7 +114,7 @@ function findFirstExistingPath(
tryPaths: ReadonlyArray<TryPath.TryPath>,
readJson: Filesystem.ReadJsonSync = Filesystem.readJsonFromDiskSync,
fileExists: Filesystem.FileExistsSync,
mainFields: string[] = ["main"]
mainFields: (string | string[])[] = ["main"]
): string | undefined {
for (const tryPath of tryPaths) {
if (
Expand Down

0 comments on commit 0a2d6f4

Please sign in to comment.