import fs from "fs" ; import { builtinModules } from "module" ; import os from "os" ; import path from "path" ; import ts from "typescript" ; import util from "util" ; import type { ModuleResolutionHostLike } from "./types" ; export const enum ResolverLogMode { Never , Always , OnFailure } export class ResolverLog { private mode : ResolverLogMode ; private buffering : boolean ; private messages : string [ ] ; private logFile : string | undefined ; constructor ( mode , logFile ? ) { this . mode = mode ; this . buffering = false ; this . messages = [ ] ; this . logFile = logFile ; } getMode ( ) { return this . mode ; } begin ( ) { this . buffering = true ; } log ( format , ... args ) { if ( this . mode !== ResolverLogMode . Never && this . buffering ) { this . messages . push ( util . format ( format , ... args ) ) ; } } endSuccess ( ) { if ( this . mode === ResolverLogMode . Always ) { this . flush ( ) ; } this . reset ( ) ; } endFailure ( ) { if ( this . mode === ResolverLogMode . OnFailure || this . mode === ResolverLogMode . Always ) { this . flush ( ) ; } this . reset ( ) ; } reset ( ) { if ( this . mode !== ResolverLogMode . Never ) { this . messages = [ ] ; } this . buffering = false ; } private flush ( ) { if ( this . messages . length > 0 ) { const messages = this . messages . join ( os . EOL ) ; if ( this . logFile ) { fs . writeFileSync ( this . logFile , messages + os . EOL , { encoding : "utf-8" , flag : "a" } ) ; } else { console . log ( messages ) ; } } } } param host param resolverLog export function changeModuleResolutionHostToLogFileSystemReads ( host ) { const originalFileExists = host . fileExists . bind ( host ) ; const originalReadFile = host . readFile . bind ( host ) ; const originalDirectoryExists = host . directoryExists . bind ( host ) ; const originalRealpath = host . realpath ? host . realpath . bind ( host ) : undefined ; const originalGetDirectories = host . getDirectories . bind ( host ) ; host . fileExists = ( fileName ) : boolean => { const result = originalFileExists ( fileName ) ; if ( ! result && host . trace ) { host . trace ( `File '${ fileName }' does not exist.` ) ; } return result ; } ; host . readFile = ( fileName ) : string | undefined => { const result = originalReadFile ( fileName ) ; if ( host . trace ) { if ( result ) { host . trace ( `Read file '${ fileName }'.` ) ; } else { host . trace ( `File '${ fileName }' cannot be read.` ) ; } } return result ; } ; host . directoryExists = ( directoryName ) : boolean => { const result = originalDirectoryExists ( directoryName ) ; if ( ! result && host . trace ) { host . trace ( `Directory '${ directoryName }' does not exist.` ) ; } return result ; } ; if ( originalRealpath ) { host . realpath = ( path ) : string => { const result = originalRealpath ( path ) ; if ( result && host . trace ) { host . trace ( `Real path of '${ path }' is '${ result }'.` ) ; } return result ; } ; } host . getDirectories = ( path ) : string [ ] => { const result = originalGetDirectories ( path ) ; if ( host . trace ) { const len = result ? result . length . toString ( ) : "0" ; const suffix = result && result . length === 1 ? "y" : "ies" ; host . trace ( `Found ${ len } director${ suffix } under '${ path }'.` ) ; } return result ; } ; } param options param moduleName export function shouldLogResolverFailure ( options , moduleName ) { if ( builtinModules . indexOf ( moduleName ) !== - 1 || moduleName === "fs/promises" || moduleName . toLowerCase ( ) . startsWith ( "node:" ) ) { return false ; } if ( ! options . resolveJsonModule ) { if ( path . extname ( moduleName ) . match ( /\.json$/i ) ) { return false ; } } const multimediaExts = /\.(aac|aiff|bmp|caf|gif|html|jpeg|jpg|m4a|m4v|mov|mp3|mp4|mpeg|mpg|obj|otf|pdf|png|psd|svg|ttf|wav|webm|webp)$/i ; if ( path . extname ( moduleName ) . match ( multimediaExts ) ) { return false ; } const codeExts = /\.(css)$/i ; if ( path . extname ( moduleName ) . match ( codeExts ) ) { return false ; } return true ; } param log param moduleName param containingFile export function logModuleBegin ( log , moduleName , containingFile ) { log . begin ( ) ; log . log ( "======== Resolving module '%s' from '%s' ========" , moduleName , containingFile ) ; } param log param options param moduleName param module export function logModuleEnd ( log , options , moduleName , module ) { if ( module ) { log . log ( "File '%s' exists - using it as a module resolution result." , module . resolvedFileName ) ; log . log ( "======== Module name '%s' was successfully resolved to '%s' ========" , moduleName , module . resolvedFileName ) ; log . endSuccess ( ) ; } else { log . log ( "Failed to resolve module %s to a file." , moduleName ) ; log . log ( "======== Module name '%s' failed to resolve to a file ========" , moduleName ) ; if ( log . getMode ( ) !== ResolverLogMode . Never && shouldLogResolverFailure ( options , moduleName ) ) { log . endFailure ( ) ; } else { log . reset ( ) ; } } }