From ee77bcc026feffac5ada53bea0fb5e06da60e99c Mon Sep 17 00:00:00 2001 From: Rob Hogan Date: Wed, 13 Jul 2022 19:19:32 +0100 Subject: [PATCH] types(jest-haste-map): Define/restrict public interfaces --- packages/jest-core/src/cli/index.ts | 4 +- packages/jest-core/src/lib/createContext.ts | 4 +- packages/jest-core/src/watch.ts | 50 ++++++++----------- packages/jest-haste-map/src/HasteFS.ts | 4 +- packages/jest-haste-map/src/ModuleMap.ts | 2 +- packages/jest-haste-map/src/index.ts | 20 +++++--- packages/jest-haste-map/src/types.ts | 18 +++++++ .../jest-resolve-dependencies/src/index.ts | 6 +-- .../src/__tests__/resolve.test.ts | 7 +-- packages/jest-runtime/src/index.ts | 4 +- packages/jest-snapshot/src/index.ts | 6 +-- packages/jest-test-result/src/types.ts | 6 +-- 12 files changed, 76 insertions(+), 55 deletions(-) diff --git a/packages/jest-core/src/cli/index.ts b/packages/jest-core/src/cli/index.ts index 29487d5aff3c..78cc335d376f 100644 --- a/packages/jest-core/src/cli/index.ts +++ b/packages/jest-core/src/cli/index.ts @@ -13,7 +13,7 @@ import type {AggregatedResult, TestContext} from '@jest/test-result'; import type {Config} from '@jest/types'; import type {ChangedFilesPromise} from 'jest-changed-files'; import {readConfigs} from 'jest-config'; -import type HasteMap from 'jest-haste-map'; +import type {IHasteMap} from 'jest-haste-map'; import Runtime from 'jest-runtime'; import {createDirectory, preRunMessage} from 'jest-util'; import {TestWatcher} from 'jest-watcher'; @@ -233,7 +233,7 @@ const runWatch = async ( hasDeprecationWarnings: boolean, globalConfig: Config.GlobalConfig, outputStream: NodeJS.WriteStream, - hasteMapInstances: Array, + hasteMapInstances: Array, filter?: Filter, ) => { if (hasDeprecationWarnings) { diff --git a/packages/jest-core/src/lib/createContext.ts b/packages/jest-core/src/lib/createContext.ts index be1a75061dd9..721f5c5471e9 100644 --- a/packages/jest-core/src/lib/createContext.ts +++ b/packages/jest-core/src/lib/createContext.ts @@ -7,12 +7,12 @@ import type {TestContext} from '@jest/test-result'; import type {Config} from '@jest/types'; -import type {HasteMapObject} from 'jest-haste-map'; +import type {IHasteFS, IModuleMap} from 'jest-haste-map'; import Runtime from 'jest-runtime'; export default function createContext( config: Config.ProjectConfig, - {hasteFS, moduleMap}: HasteMapObject, + {hasteFS, moduleMap}: {hasteFS: IHasteFS; moduleMap: IModuleMap}, ): TestContext { return { config, diff --git a/packages/jest-core/src/watch.ts b/packages/jest-core/src/watch.ts index ca0a6a421f26..055d527a00b0 100644 --- a/packages/jest-core/src/watch.ts +++ b/packages/jest-core/src/watch.ts @@ -12,10 +12,7 @@ import exit = require('exit'); import slash = require('slash'); import type {TestContext} from '@jest/test-result'; import type {Config} from '@jest/types'; -import type { - ChangeEvent as HasteChangeEvent, - default as HasteMap, -} from 'jest-haste-map'; +import type {IHasteMap as HasteMap} from 'jest-haste-map'; import {formatExecError} from 'jest-message-util'; import { isInteractive, @@ -243,31 +240,28 @@ export default async function watch( emitFileChange(); hasteMapInstances.forEach((hasteMapInstance, index) => { - hasteMapInstance.on( - 'change', - ({eventsQueue, hasteFS, moduleMap}: HasteChangeEvent) => { - const validPaths = eventsQueue.filter(({filePath}) => - isValidPath(globalConfig, filePath), - ); + hasteMapInstance.on('change', ({eventsQueue, hasteFS, moduleMap}) => { + const validPaths = eventsQueue.filter(({filePath}) => + isValidPath(globalConfig, filePath), + ); - if (validPaths.length) { - const context = (contexts[index] = createContext( - contexts[index].config, - {hasteFS, moduleMap}, - )); - - activePlugin = null; - - searchSources = searchSources.slice(); - searchSources[index] = { - context, - searchSource: new SearchSource(context), - }; - emitFileChange(); - startRun(globalConfig); - } - }, - ); + if (validPaths.length) { + const context = (contexts[index] = createContext( + contexts[index].config, + {hasteFS, moduleMap}, + )); + + activePlugin = null; + + searchSources = searchSources.slice(); + searchSources[index] = { + context, + searchSource: new SearchSource(context), + }; + emitFileChange(); + startRun(globalConfig); + } + }); }); if (!hasExitListener) { diff --git a/packages/jest-haste-map/src/HasteFS.ts b/packages/jest-haste-map/src/HasteFS.ts index 56fd2792067c..3fc1144c976c 100644 --- a/packages/jest-haste-map/src/HasteFS.ts +++ b/packages/jest-haste-map/src/HasteFS.ts @@ -8,9 +8,9 @@ import {globsToMatcher, replacePathSepForGlob} from 'jest-util'; import H from './constants'; import * as fastPath from './lib/fast_path'; -import type {FileData} from './types'; +import type {FileData, IHasteFS} from './types'; -export default class HasteFS { +export default class HasteFS implements IHasteFS { private readonly _rootDir: string; private readonly _files: FileData; diff --git a/packages/jest-haste-map/src/ModuleMap.ts b/packages/jest-haste-map/src/ModuleMap.ts index fea276a6f325..59fd7760115b 100644 --- a/packages/jest-haste-map/src/ModuleMap.ts +++ b/packages/jest-haste-map/src/ModuleMap.ts @@ -19,7 +19,7 @@ import type { const EMPTY_OBJ: Record = {}; const EMPTY_MAP = new Map(); -export default class ModuleMap implements IModuleMap { +export default class ModuleMap implements IModuleMap { static DuplicateHasteCandidatesError: typeof DuplicateHasteCandidatesError; private readonly _raw: RawModuleMap; private json: SerializableModuleMap | undefined; diff --git a/packages/jest-haste-map/src/index.ts b/packages/jest-haste-map/src/index.ts index b3585c29d52e..8e55869780fc 100644 --- a/packages/jest-haste-map/src/index.ts +++ b/packages/jest-haste-map/src/index.ts @@ -34,6 +34,8 @@ import type { FileMetaData, HasteMapStatic, HasteRegExp, + IHasteMap, + IModuleMap, InternalHasteMap, HasteMap as InternalHasteMapObject, MockData, @@ -109,11 +111,12 @@ type Watcher = { type HasteWorker = typeof import('./worker'); -export type {default as FS} from './HasteFS'; -export {default as ModuleMap} from './ModuleMap'; +export const ModuleMap = HasteModuleMap as { + create: (rootPath: string) => IModuleMap; +}; export type { - ChangeEvent, - HasteMap as HasteMapObject, + IHasteFS, + IHasteMap, IModuleMap, SerializableModuleMap, } from './types'; @@ -210,7 +213,7 @@ function invariant(condition: unknown, message?: string): asserts condition { * Worker processes can directly access the cache through `HasteMap.read()`. * */ -export default class HasteMap extends EventEmitter { +class HasteMap extends EventEmitter implements IHasteMap { private _buildPromise: Promise | null = null; private _cachePath = ''; private _changeInterval?: ReturnType; @@ -227,7 +230,7 @@ export default class HasteMap extends EventEmitter { return HasteMap; } - static async create(options: Options): Promise { + static async create(options: Options): Promise { if (options.hasteMapModulePath) { const CustomHasteMap = require(options.hasteMapModulePath); return new CustomHasteMap(options); @@ -1144,3 +1147,8 @@ function copy>(object: T): T { function copyMap(input: Map): Map { return new Map(input); } + +export default HasteMap as HasteMapStatic & { + create(options: Options): Promise; + getStatic(config: Config.ProjectConfig): HasteMapStatic; +}; diff --git a/packages/jest-haste-map/src/types.ts b/packages/jest-haste-map/src/types.ts index 934526d218b2..c56c950534c1 100644 --- a/packages/jest-haste-map/src/types.ts +++ b/packages/jest-haste-map/src/types.ts @@ -39,6 +39,24 @@ export interface IModuleMap { toJSON(): S; } +export interface IHasteFS { + exists(path: string): boolean; + getAbsoluteFileIterator(): Iterable; + getAllFiles(): Array; + getDependencies(file: string): Array | null; + getSize(path: string): number | null; + matchFiles(pattern: RegExp | string): Array; + matchFilesWithGlob( + globs: ReadonlyArray, + root: string | null, + ): Set; +} + +export interface IHasteMap { + on(eventType: 'change', handler: (event: ChangeEvent) => void): void; + build(): Promise<{hasteFS: IHasteFS; moduleMap: IModuleMap}>; +} + export type HasteMapStatic = { getCacheFilePath( tmpdir: string, diff --git a/packages/jest-resolve-dependencies/src/index.ts b/packages/jest-resolve-dependencies/src/index.ts index 21ba04ac3115..58ea8b26481b 100644 --- a/packages/jest-resolve-dependencies/src/index.ts +++ b/packages/jest-resolve-dependencies/src/index.ts @@ -6,7 +6,7 @@ */ import * as path from 'path'; -import type {FS as HasteFS} from 'jest-haste-map'; +import type {IHasteFS} from 'jest-haste-map'; import type {ResolveModuleConfig, default as Resolver} from 'jest-resolve'; import {SnapshotResolver, isSnapshotPath} from 'jest-snapshot'; @@ -20,13 +20,13 @@ export type ResolvedModule = { * to retrieve a list of all transitive inverse dependencies. */ export class DependencyResolver { - private _hasteFS: HasteFS; + private _hasteFS: IHasteFS; private _resolver: Resolver; private _snapshotResolver: SnapshotResolver; constructor( resolver: Resolver, - hasteFS: HasteFS, + hasteFS: IHasteFS, snapshotResolver: SnapshotResolver, ) { this._resolver = resolver; diff --git a/packages/jest-resolve/src/__tests__/resolve.test.ts b/packages/jest-resolve/src/__tests__/resolve.test.ts index 3143c9c45e6c..4179ba1ee0a7 100644 --- a/packages/jest-resolve/src/__tests__/resolve.test.ts +++ b/packages/jest-resolve/src/__tests__/resolve.test.ts @@ -10,6 +10,7 @@ import * as path from 'path'; import * as fs from 'graceful-fs'; import {sync as resolveSync} from 'resolve'; import {ModuleMap} from 'jest-haste-map'; +import type {IModuleMap} from 'jest-haste-map'; import userResolver from '../__mocks__/userResolver'; import userResolverAsync from '../__mocks__/userResolverAsync'; import defaultResolver from '../defaultResolver'; @@ -356,7 +357,7 @@ describe('findNodeModuleAsync', () => { }); describe('resolveModule', () => { - let moduleMap: ModuleMap; + let moduleMap: IModuleMap; beforeEach(() => { moduleMap = ModuleMap.create('/'); }); @@ -461,7 +462,7 @@ describe('resolveModule', () => { }); describe('resolveModuleAsync', () => { - let moduleMap: ModuleMap; + let moduleMap: IModuleMap; beforeEach(() => { moduleMap = ModuleMap.create('/'); }); @@ -622,7 +623,7 @@ describe('nodeModulesPaths', () => { describe('Resolver.getModulePaths() -> nodeModulesPaths()', () => { const _path = path; - let moduleMap: ModuleMap; + let moduleMap: IModuleMap; beforeEach(() => { jest.resetModules(); diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 5b9f869bc55a..2bc7cf300167 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -49,7 +49,7 @@ import { shouldInstrument, } from '@jest/transform'; import type {Config, Global} from '@jest/types'; -import type {IModuleMap} from 'jest-haste-map'; +import type {IHasteMap, IModuleMap} from 'jest-haste-map'; import HasteMap from 'jest-haste-map'; import {formatStackTrace, separateMessageFromStack} from 'jest-message-util'; import type {MockFunctionMetadata, ModuleMocker} from 'jest-mock'; @@ -358,7 +358,7 @@ export default class Runtime { static createHasteMap( config: Config.ProjectConfig, options?: HasteMapOptions, - ): Promise { + ): Promise { const ignorePatternParts = [ ...config.modulePathIgnorePatterns, ...(options && options.watch ? config.watchPathIgnorePatterns : []), diff --git a/packages/jest-snapshot/src/index.ts b/packages/jest-snapshot/src/index.ts index 1991a8d49406..5dbbd783899a 100644 --- a/packages/jest-snapshot/src/index.ts +++ b/packages/jest-snapshot/src/index.ts @@ -8,7 +8,7 @@ import * as fs from 'graceful-fs'; import type {Config} from '@jest/types'; import type {MatcherFunctionWithState} from 'expect'; -import type {FS as HasteFS} from 'jest-haste-map'; +import type {IHasteFS} from 'jest-haste-map'; import { BOLD_WEIGHT, EXPECTED_COLOR, @@ -110,11 +110,11 @@ function stripAddedIndentation(inlineSnapshot: string) { return inlineSnapshot; } -const fileExists = (filePath: string, hasteFS: HasteFS): boolean => +const fileExists = (filePath: string, hasteFS: IHasteFS): boolean => hasteFS.exists(filePath) || fs.existsSync(filePath); export const cleanup = ( - hasteFS: HasteFS, + hasteFS: IHasteFS, update: Config.SnapshotUpdateState, snapshotResolver: SnapshotResolver, testPathIgnorePatterns?: Config.ProjectConfig['testPathIgnorePatterns'], diff --git a/packages/jest-test-result/src/types.ts b/packages/jest-test-result/src/types.ts index 2494a47f7c65..a8b2b7cc1799 100644 --- a/packages/jest-test-result/src/types.ts +++ b/packages/jest-test-result/src/types.ts @@ -9,7 +9,7 @@ import type {V8Coverage} from 'collect-v8-coverage'; import type {CoverageMap, CoverageMapData} from 'istanbul-lib-coverage'; import type {ConsoleBuffer} from '@jest/console'; import type {Config, TestResult, TransformTypes} from '@jest/types'; -import type {FS as HasteFS, ModuleMap} from 'jest-haste-map'; +import type {IHasteFS, IModuleMap} from 'jest-haste-map'; import type Resolver from 'jest-resolve'; export interface RuntimeTransformResult extends TransformTypes.TransformResult { @@ -190,8 +190,8 @@ export type Test = { export type TestContext = { config: Config.ProjectConfig; - hasteFS: HasteFS; - moduleMap: ModuleMap; + hasteFS: IHasteFS; + moduleMap: IModuleMap; resolver: Resolver; };