Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(jest-resolve): expose PackageFilter, PathFilter and PackageJSON types #12712

Merged
merged 2 commits into from Apr 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Expand Up @@ -46,7 +46,7 @@
- `[jest-resolve, jest-runtime]` Add support for `data:` URI import and mock ([#12392](https://github.com/facebook/jest/pull/12392))
- `[jest-resolve, jest-runtime]` Add support for async resolver ([#11540](https://github.com/facebook/jest/pull/11540))
- `[jest-resolve]` [**BREAKING**] Remove `browser?: boolean` from resolver options, `conditions: ['browser']` should be used instead ([#12707](https://github.com/facebook/jest/pull/12707))
- `[jest-resolve]` Expose `JestResolver`, `AsyncResolver` and `SyncResolver` types ([#12707](https://github.com/facebook/jest/pull/12707))
- `[jest-resolve]` Expose `JestResolver`, `AsyncResolver`, `SyncResolver`, `PackageFilter`, `PathFilter` and `PackageJSON` types ([#12707](https://github.com/facebook/jest/pull/12707), ([#12712](https://github.com/facebook/jest/pull/12712))
- `[jest-runner]` Allow `setupFiles` module to export an async function ([#12042](https://github.com/facebook/jest/pull/12042))
- `[jest-runner]` Allow passing `testEnvironmentOptions` via docblocks ([#12470](https://github.com/facebook/jest/pull/12470))
- `[jest-runner]` Exposing `CallbackTestRunner`, `EmittingTestRunner` abstract classes to help typing third party runners ([#12646](https://github.com/facebook/jest/pull/12646))
Expand Down
6 changes: 2 additions & 4 deletions docs/Configuration.md
Expand Up @@ -927,8 +927,6 @@ This option allows the use of a custom resolver. This resolver must be a module
The options object provided to resolvers has the shape:

```ts
type PackageJson = Record<string, unknown>;

type ResolverOptions = {
/** Directory to begin resolving from. */
basedir: string;
Expand All @@ -943,9 +941,9 @@ type ResolverOptions = {
/** List of `require.paths` to use if nothing is found in `node_modules`. */
paths?: Array<string>;
/** Allows transforming parsed `package.json` contents. */
packageFilter?: (pkg: PackageJson, file: string, dir: string) => PackageJson;
packageFilter?: (pkg: PackageJSON, file: string, dir: string) => PackageJSON;
/** Allows transforms a path within a package. */
pathFilter?: (pkg: PackageJson, path: string, relativePath: string) => string;
pathFilter?: (pkg: PackageJSON, path: string, relativePath: string) => string;
/** Current root directory. */
rootDir?: string;
};
Expand Down
48 changes: 35 additions & 13 deletions packages/jest-resolve/__typetests__/resolver.test.ts
Expand Up @@ -6,19 +6,41 @@
*/

import {expectAssignable, expectError, expectType} from 'tsd-lite';
import type {AsyncResolver, JestResolver, SyncResolver} from 'jest-resolve';

type PackageJson = Record<string, unknown>;
type PackageFilter = (
pkg: PackageJson,
file: string,
dir: string,
) => PackageJson;
type PathFilter = (
pkg: PackageJson,
path: string,
relativePath: string,
) => string;
import type {
AsyncResolver,
JestResolver,
PackageFilter,
PackageJSON,
PathFilter,
SyncResolver,
} from 'jest-resolve';

// PackageJSON

expectAssignable<PackageJSON>({
caption: 'test',
count: 100,
isTest: true,
location: {name: 'test', start: [1, 2], valid: false, x: 10, y: 20},
values: [0, 10, 20, {x: 1, y: 2}, true, 'test', ['a', 'b']],
});

expectError<PackageJSON>({
filter: () => {},
});

// PackageFilter

const packageFilter = (pkg: PackageJSON, file: string, dir: string) => pkg;

expectAssignable<PackageFilter>(packageFilter);

// PathFilter

const pathFilter = (pkg: PackageJSON, path: string, relativePath: string) =>
relativePath;

expectAssignable<PathFilter>(pathFilter);

// AsyncResolver

Expand Down
2 changes: 1 addition & 1 deletion packages/jest-resolve/package.json
Expand Up @@ -30,7 +30,7 @@
"devDependencies": {
"@tsd/typescript": "~4.6.2",
"@types/graceful-fs": "^4.1.3",
"@types/resolve": "^1.20.0",
"@types/resolve": "^1.20.2",
"tsd-lite": "^0.5.1"
},
"engines": {
Expand Down
39 changes: 34 additions & 5 deletions packages/jest-resolve/src/defaultResolver.ts
Expand Up @@ -13,13 +13,43 @@ import {
resolve as resolveExports,
} from 'resolve.exports';
import {
PackageJson,
findClosestPackageJson,
isDirectory,
isFile,
readPackageCached,
realpathSync,
} from './fileWalkers';
import type {PackageJSON} from './types';

/**
* Allows transforming parsed `package.json` contents.
*
* @param pkg - Parsed `package.json` contents.
* @param file - Path to `package.json` file.
* @param dir - Directory that contains the `package.json`.
*
* @returns Transformed `package.json` contents.
*/
export type PackageFilter = (
pkg: PackageJSON,
file: string,
dir: string,
) => PackageJSON;

/**
* Allows transforms a path within a package.
*
* @param pkg - Parsed `package.json` contents.
* @param path - Path being resolved.
* @param relativePath - Path relative from the `package.json` location.
*
* @returns Relative path that will be joined from the `package.json` location.
*/
export type PathFilter = (
pkg: PackageJSON,
path: string,
relativePath: string,
) => string;

type ResolverOptions = {
/** Directory to begin resolving from. */
Expand All @@ -45,9 +75,9 @@ type ResolverOptions = {
*/
paths?: Array<string>;
/** Allows transforming parsed `package.json` contents. */
packageFilter?: (pkg: PackageJson, file: string, dir: string) => PackageJson;
packageFilter?: PackageFilter;
/** Allows transforms a path within a package. */
pathFilter?: (pkg: PackageJson, path: string, relativePath: string) => string;
pathFilter?: PathFilter;
/** Current root directory. */
rootDir?: string;
};
Expand Down Expand Up @@ -79,7 +109,6 @@ const defaultResolver: SyncResolver = (path, options) => {
return pnpResolver(path, options);
}

// @ts-expect-error: TODO remove after merging https://github.com/DefinitelyTyped/DefinitelyTyped/pull/59990
const resolveOptions: UpstreamResolveOptionsWithConditions = {
...options,
isDirectory,
Expand Down Expand Up @@ -108,7 +137,7 @@ export default defaultResolver;
* helper functions
*/

function readPackageSync(_: unknown, file: string): PackageJson {
function readPackageSync(_: unknown, file: string): PackageJSON {
return readPackageCached(file);
}

Expand Down
9 changes: 4 additions & 5 deletions packages/jest-resolve/src/fileWalkers.ts
Expand Up @@ -8,6 +8,7 @@
import {dirname, resolve} from 'path';
import * as fs from 'graceful-fs';
import {tryRealpath} from 'jest-util';
import type {PackageJSON} from './types';

export function clearFsCache(): void {
checkedPaths.clear();
Expand Down Expand Up @@ -71,17 +72,15 @@ function realpathCached(path: string): string {
return result;
}

export type PackageJson = Record<string, unknown>;

const packageContents = new Map<string, PackageJson>();
export function readPackageCached(path: string): PackageJson {
const packageContents = new Map<string, PackageJSON>();
export function readPackageCached(path: string): PackageJSON {
let result = packageContents.get(path);

if (result != null) {
return result;
}

result = JSON.parse(fs.readFileSync(path, 'utf8')) as PackageJson;
result = JSON.parse(fs.readFileSync(path, 'utf8')) as PackageJSON;

packageContents.set(path, result);

Expand Down
8 changes: 7 additions & 1 deletion packages/jest-resolve/src/index.ts
Expand Up @@ -7,12 +7,18 @@

import Resolver from './resolver';

export type {AsyncResolver, SyncResolver} from './defaultResolver';
export type {
AsyncResolver,
SyncResolver,
PackageFilter,
PathFilter,
} from './defaultResolver';
export type {
FindNodeModuleConfig,
ResolveModuleConfig,
ResolverObject as JestResolver,
} from './resolver';
export type {PackageJSON} from './types';
export * from './utils';

export default Resolver;
8 changes: 8 additions & 0 deletions packages/jest-resolve/src/types.ts
Expand Up @@ -21,3 +21,11 @@ type ModuleNameMapperConfig = {
regex: RegExp;
moduleName: string | Array<string>;
};

// https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540
type JSONValue = string | number | boolean | JSONObject | Array<JSONValue>;
interface JSONObject {
[key: string]: JSONValue;
}

export type PackageJSON = JSONObject;
10 changes: 5 additions & 5 deletions yarn.lock
Expand Up @@ -5373,10 +5373,10 @@ __metadata:
languageName: node
linkType: hard

"@types/resolve@npm:^1.20.0":
version: 1.20.1
resolution: "@types/resolve@npm:1.20.1"
checksum: d035d5aaadbd455027fa9457a4a263563d49647f088876aebd2b0388d4c35400b85c0382fdc2ec5253c35442abfc2d25431c989345b97fefe26a367811214343
"@types/resolve@npm:^1.20.2":
version: 1.20.2
resolution: "@types/resolve@npm:1.20.2"
checksum: 61c2cad2499ffc8eab36e3b773945d337d848d3ac6b7b0a87c805ba814bc838ef2f262fc0f109bfd8d2e0898ff8bd80ad1025f9ff64f1f71d3d4294c9f14e5f6
languageName: node
linkType: hard

Expand Down Expand Up @@ -13446,7 +13446,7 @@ __metadata:
dependencies:
"@tsd/typescript": ~4.6.2
"@types/graceful-fs": ^4.1.3
"@types/resolve": ^1.20.0
"@types/resolve": ^1.20.2
chalk: ^4.0.0
graceful-fs: ^4.2.9
jest-haste-map: ^28.0.0-alpha.11
Expand Down