diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d6ffb16d57e..913b7572a4d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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)) diff --git a/docs/Configuration.md b/docs/Configuration.md index 1855b0009b68..a8b148154fb1 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -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; - type ResolverOptions = { /** Directory to begin resolving from. */ basedir: string; @@ -943,9 +941,9 @@ type ResolverOptions = { /** List of `require.paths` to use if nothing is found in `node_modules`. */ paths?: Array; /** 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; }; diff --git a/packages/jest-resolve/__typetests__/resolver.test.ts b/packages/jest-resolve/__typetests__/resolver.test.ts index a9cfc7ab3603..b3ee2403e5f3 100644 --- a/packages/jest-resolve/__typetests__/resolver.test.ts +++ b/packages/jest-resolve/__typetests__/resolver.test.ts @@ -6,19 +6,41 @@ */ import {expectAssignable, expectError, expectType} from 'tsd-lite'; -import type {AsyncResolver, JestResolver, SyncResolver} from 'jest-resolve'; - -type PackageJson = Record; -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({ + 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({ + filter: () => {}, +}); + +// PackageFilter + +const packageFilter = (pkg: PackageJSON, file: string, dir: string) => pkg; + +expectAssignable(packageFilter); + +// PathFilter + +const pathFilter = (pkg: PackageJSON, path: string, relativePath: string) => + relativePath; + +expectAssignable(pathFilter); // AsyncResolver diff --git a/packages/jest-resolve/package.json b/packages/jest-resolve/package.json index 9bccf572115d..c723ff659542 100644 --- a/packages/jest-resolve/package.json +++ b/packages/jest-resolve/package.json @@ -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": { diff --git a/packages/jest-resolve/src/defaultResolver.ts b/packages/jest-resolve/src/defaultResolver.ts index de53b3ccd939..16694ad990ed 100644 --- a/packages/jest-resolve/src/defaultResolver.ts +++ b/packages/jest-resolve/src/defaultResolver.ts @@ -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. */ @@ -45,9 +75,9 @@ type ResolverOptions = { */ paths?: Array; /** 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; }; @@ -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, @@ -108,7 +137,7 @@ export default defaultResolver; * helper functions */ -function readPackageSync(_: unknown, file: string): PackageJson { +function readPackageSync(_: unknown, file: string): PackageJSON { return readPackageCached(file); } diff --git a/packages/jest-resolve/src/fileWalkers.ts b/packages/jest-resolve/src/fileWalkers.ts index 1e57f6fc8251..f19e6b4701ae 100644 --- a/packages/jest-resolve/src/fileWalkers.ts +++ b/packages/jest-resolve/src/fileWalkers.ts @@ -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(); @@ -71,17 +72,15 @@ function realpathCached(path: string): string { return result; } -export type PackageJson = Record; - -const packageContents = new Map(); -export function readPackageCached(path: string): PackageJson { +const packageContents = new Map(); +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); diff --git a/packages/jest-resolve/src/index.ts b/packages/jest-resolve/src/index.ts index af1c1f2cb9ff..e32263a3a488 100644 --- a/packages/jest-resolve/src/index.ts +++ b/packages/jest-resolve/src/index.ts @@ -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; diff --git a/packages/jest-resolve/src/types.ts b/packages/jest-resolve/src/types.ts index 8469e2b9dc3d..b7279945463f 100644 --- a/packages/jest-resolve/src/types.ts +++ b/packages/jest-resolve/src/types.ts @@ -21,3 +21,11 @@ type ModuleNameMapperConfig = { regex: RegExp; moduleName: string | Array; }; + +// https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540 +type JSONValue = string | number | boolean | JSONObject | Array; +interface JSONObject { + [key: string]: JSONValue; +} + +export type PackageJSON = JSONObject; diff --git a/yarn.lock b/yarn.lock index 7871974f8337..fd4bcf67edee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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 @@ -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