diff --git a/README.md b/README.md index 44e7efc..bc77333 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,7 @@ This package is fully typed with [TypeScript][]. - [`FileSystem`](./src/interfaces/file-system.mts) - [`LoadTsconfigOptions`](./src/interfaces/options-load-tsconfig.mts) +- [`ModuleResolutionHost`](./src/interfaces/host-module-resolution.mts) - [`ReadTsconfigOptions`](./src/interfaces/options-read-tsconfig.mts) - [`ResolvePathOptions`](./src/interfaces/options-resolve-path.mts) - [`ResolvedTsconfig`](./src/interfaces/options-resolve-path.mts) diff --git a/src/interfaces/__tests__/host-module-resolution.spec-d.mts b/src/interfaces/__tests__/host-module-resolution.spec-d.mts new file mode 100644 index 0000000..90ca64c --- /dev/null +++ b/src/interfaces/__tests__/host-module-resolution.spec-d.mts @@ -0,0 +1,114 @@ +/** + * @file Type Tests - ModuleResolutionHost + * @module tsconfig-utils/interfaces/tests/unit-d/ModuleResolutionHost + */ + +import type TestSubject from '#interfaces/host-module-resolution' +import type { ModuleId } from '@flex-development/mlly' +import type ts from 'typescript' + +describe('unit-d:interfaces/ModuleResolutionHost', () => { + it('should match ts.ModuleResolutionHost', () => { + expectTypeOf().toMatchTypeOf() + }) + + describe('directoryExists', () => { + type Subject = TestSubject['directoryExists'] + + it('should match [this: void]', () => { + expectTypeOf().thisParameter.toEqualTypeOf() + }) + + describe('parameters', () => { + it('should be callable with [ModuleId]', () => { + expectTypeOf().parameters.toEqualTypeOf<[ModuleId]>() + }) + }) + + describe('returns', () => { + it('should return boolean', () => { + expectTypeOf().returns.toEqualTypeOf() + }) + }) + }) + + describe('fileExists', () => { + type Subject = TestSubject['fileExists'] + + it('should match [this: void]', () => { + expectTypeOf().thisParameter.toEqualTypeOf() + }) + + describe('parameters', () => { + it('should be callable with [ModuleId]', () => { + expectTypeOf().parameters.toEqualTypeOf<[ModuleId]>() + }) + }) + + describe('returns', () => { + it('should return boolean', () => { + expectTypeOf().returns.toEqualTypeOf() + }) + }) + }) + + describe('getDirectories', () => { + type Subject = TestSubject['getDirectories'] + + it('should match [this: void]', () => { + expectTypeOf().thisParameter.toEqualTypeOf() + }) + + describe('parameters', () => { + it('should be callable with [ModuleId]', () => { + expectTypeOf().parameters.toEqualTypeOf<[ModuleId]>() + }) + }) + + describe('returns', () => { + it('should return string[]', () => { + expectTypeOf().returns.toEqualTypeOf() + }) + }) + }) + + describe('readFile', () => { + type Subject = TestSubject['readFile'] + + it('should match [this: void]', () => { + expectTypeOf().thisParameter.toEqualTypeOf() + }) + + describe('parameters', () => { + it('should be callable with [ModuleId]', () => { + expectTypeOf().parameters.toEqualTypeOf<[ModuleId]>() + }) + }) + + describe('returns', () => { + it('should return string | undefined', () => { + expectTypeOf().returns.toEqualTypeOf() + }) + }) + }) + + describe('realpath', () => { + type Subject = TestSubject['realpath'] + + it('should match [this: void]', () => { + expectTypeOf().thisParameter.toEqualTypeOf() + }) + + describe('parameters', () => { + it('should be callable with [ModuleId]', () => { + expectTypeOf().parameters.toEqualTypeOf<[ModuleId]>() + }) + }) + + describe('returns', () => { + it('should return string', () => { + expectTypeOf().returns.toEqualTypeOf() + }) + }) + }) +}) diff --git a/src/interfaces/host-module-resolution.mts b/src/interfaces/host-module-resolution.mts new file mode 100644 index 0000000..8e722ab --- /dev/null +++ b/src/interfaces/host-module-resolution.mts @@ -0,0 +1,101 @@ +/** + * @file Interfaces - ModuleResolutionHost + * @module tsconfig-utils/interfaces/ModuleResolutionHost + */ + +import type { ModuleId } from '@flex-development/mlly' + +/** + * Module resolution host API. + * + * The module resolution host acts a bridge between the TypeScript compiler and + * the file system. + */ +interface ModuleResolutionHost { + /** + * Check if a directory exists at `id`. + * + * @see {@linkcode ModuleId} + * + * @this {void} + * + * @param {ModuleId} id + * The module id to check + * @return {boolean} + * `true` if directory exists at `id`, `false` otherwise + */ + directoryExists(this: void, id: ModuleId): boolean + + /** + * Check if a file exists at `id`. + * + * @see {@linkcode ModuleId} + * + * @this {void} + * + * @param {ModuleId} id + * The module id to check + * @return {boolean} + * `true` if file exists at `id`, `false` otherwise + */ + fileExists(this: void, id: ModuleId): boolean + + /** + * Get the path to current working directory. + * + * @this {void} + * + * @return {string} + * Path to current working directory + */ + getCurrentDirectory(this: void): string + + /** + * Get a list of subdirectories. + * + * @see {@linkcode ModuleId} + * + * @this {void} + * + * @param {ModuleId} id + * The directory path or URL to read + * @return {string[]} + * List of subdirectory names + */ + getDirectories(this: void, id: ModuleId): string[] + + /** + * Get the contents of a file. + * + * @see {@linkcode ModuleId} + * + * @this {void} + * + * @param {ModuleId} id + * Module id of file + * @return {Buffer | string} + * File contents or `undefined` if file does not exist at `id` + */ + readFile(this: void, id: ModuleId): string | undefined + + /** + * Get the resolved pathname for `id`. + * + * @see {@linkcode ModuleId} + * + * @this {void} + * + * @param {ModuleId} id + * The path or `file:` URL to handle + * @return {string} + * Resolved pathname + */ + realpath(this: void, id: ModuleId): string + + /** + * Treat filenames as case-sensitive? + */ + useCaseSensitiveFileNames?: ((this: void) => boolean) | boolean | undefined +} + +export type { ModuleResolutionHost as default } diff --git a/src/interfaces/index.mts b/src/interfaces/index.mts index 4facc38..5e617c9 100644 --- a/src/interfaces/index.mts +++ b/src/interfaces/index.mts @@ -4,6 +4,9 @@ */ export type { default as FileSystem } from '#interfaces/file-system' +export type { + default as ModuleResolutionHost +} from '#interfaces/host-module-resolution' export type { default as LoadTsconfigOptions } from '#interfaces/options-load-tsconfig'