1import * as ts from "./_namespaces/ts"; 2import * as vfs from "./_namespaces/vfs"; 3 4export import sep = ts.directorySeparator; 5export import normalizeSeparators = ts.normalizeSlashes; 6export import isAbsolute = ts.isRootedDiskPath; 7export import isRoot = ts.isDiskPathRoot; 8export import hasTrailingSeparator = ts.hasTrailingDirectorySeparator; 9export import addTrailingSeparator = ts.ensureTrailingDirectorySeparator; 10export import removeTrailingSeparator = ts.removeTrailingDirectorySeparator; 11export import normalize = ts.normalizePath; 12export import combine = ts.combinePaths; 13export import parse = ts.getPathComponents; 14export import reduce = ts.reducePathComponents; 15export import format = ts.getPathFromPathComponents; 16export import resolve = ts.resolvePath; 17export import compare = ts.comparePaths; 18export import compareCaseSensitive = ts.comparePathsCaseSensitive; 19export import compareCaseInsensitive = ts.comparePathsCaseInsensitive; 20export import dirname = ts.getDirectoryPath; 21export import basename = ts.getBaseFileName; 22export import extname = ts.getAnyExtensionFromPath; 23export import relative = ts.getRelativePathFromDirectory; 24export import beneath = ts.containsPath; 25export import changeExtension = ts.changeAnyExtension; 26export import isTypeScript = ts.hasTSFileExtension; 27export import isJavaScript = ts.hasJSFileExtension; 28 29const invalidRootComponentRegExp = /^(?!(\/|\/\/\w+\/|[a-zA-Z]:\/?|)$)/; 30const invalidNavigableComponentRegExp = /[:*?"<>|]/; 31const invalidNavigableComponentWithWildcardsRegExp = /[:"<>|]/; 32const invalidNonNavigableComponentRegExp = /^\.{1,2}$|[:*?"<>|]/; 33const invalidNonNavigableComponentWithWildcardsRegExp = /^\.{1,2}$|[:"<>|]/; 34const extRegExp = /\.\w+$/; 35 36export const enum ValidationFlags { 37 None = 0, 38 39 RequireRoot = 1 << 0, 40 RequireDirname = 1 << 1, 41 RequireBasename = 1 << 2, 42 RequireExtname = 1 << 3, 43 RequireTrailingSeparator = 1 << 4, 44 45 AllowRoot = 1 << 5, 46 AllowDirname = 1 << 6, 47 AllowBasename = 1 << 7, 48 AllowExtname = 1 << 8, 49 AllowTrailingSeparator = 1 << 9, 50 AllowNavigation = 1 << 10, 51 AllowWildcard = 1 << 11, 52 53 /** Path must be a valid directory root */ 54 Root = RequireRoot | AllowRoot | AllowTrailingSeparator, 55 56 /** Path must be a absolute */ 57 Absolute = RequireRoot | AllowRoot | AllowDirname | AllowBasename | AllowExtname | AllowTrailingSeparator | AllowNavigation, 58 59 /** Path may be relative or absolute */ 60 RelativeOrAbsolute = AllowRoot | AllowDirname | AllowBasename | AllowExtname | AllowTrailingSeparator | AllowNavigation, 61 62 /** Path may only be a filename */ 63 Basename = RequireBasename | AllowExtname, 64} 65 66function validateComponents(components: string[], flags: ValidationFlags, hasTrailingSeparator: boolean) { 67 const hasRoot = !!components[0]; 68 const hasDirname = components.length > 2; 69 const hasBasename = components.length > 1; 70 const hasExtname = hasBasename && extRegExp.test(components[components.length - 1]); 71 const invalidComponentRegExp = flags & ValidationFlags.AllowNavigation 72 ? flags & ValidationFlags.AllowWildcard ? invalidNavigableComponentWithWildcardsRegExp : invalidNavigableComponentRegExp 73 : flags & ValidationFlags.AllowWildcard ? invalidNonNavigableComponentWithWildcardsRegExp : invalidNonNavigableComponentRegExp; 74 75 // Validate required components 76 if (flags & ValidationFlags.RequireRoot && !hasRoot) return false; 77 if (flags & ValidationFlags.RequireDirname && !hasDirname) return false; 78 if (flags & ValidationFlags.RequireBasename && !hasBasename) return false; 79 if (flags & ValidationFlags.RequireExtname && !hasExtname) return false; 80 if (flags & ValidationFlags.RequireTrailingSeparator && !hasTrailingSeparator) return false; 81 82 // Required components indicate allowed components 83 if (flags & ValidationFlags.RequireRoot) flags |= ValidationFlags.AllowRoot; 84 if (flags & ValidationFlags.RequireDirname) flags |= ValidationFlags.AllowDirname; 85 if (flags & ValidationFlags.RequireBasename) flags |= ValidationFlags.AllowBasename; 86 if (flags & ValidationFlags.RequireExtname) flags |= ValidationFlags.AllowExtname; 87 if (flags & ValidationFlags.RequireTrailingSeparator) flags |= ValidationFlags.AllowTrailingSeparator; 88 89 // Validate disallowed components 90 if (~flags & ValidationFlags.AllowRoot && hasRoot) return false; 91 if (~flags & ValidationFlags.AllowDirname && hasDirname) return false; 92 if (~flags & ValidationFlags.AllowBasename && hasBasename) return false; 93 if (~flags & ValidationFlags.AllowExtname && hasExtname) return false; 94 if (~flags & ValidationFlags.AllowTrailingSeparator && hasTrailingSeparator) return false; 95 96 // Validate component strings 97 if (invalidRootComponentRegExp.test(components[0])) return false; 98 for (let i = 1; i < components.length; i++) { 99 if (invalidComponentRegExp.test(components[i])) return false; 100 } 101 102 return true; 103} 104 105export function validate(path: string, flags: ValidationFlags = ValidationFlags.RelativeOrAbsolute) { 106 const components = parse(path); 107 const trailing = hasTrailingSeparator(path); 108 if (!validateComponents(components, flags, trailing)) throw vfs.createIOError("ENOENT"); 109 return components.length > 1 && trailing ? format(reduce(components)) + sep : format(reduce(components)); 110} 111 112export function isDeclaration(path: string) { 113 return ts.isDeclarationFileName(path); 114} 115 116export function isSourceMap(path: string) { 117 return extname(path, ".map", /*ignoreCase*/ false).length > 0; 118} 119 120const javaScriptSourceMapExtensions: readonly string[] = [".js.map", ".jsx.map"]; 121 122export function isJavaScriptSourceMap(path: string) { 123 return extname(path, javaScriptSourceMapExtensions, /*ignoreCase*/ false).length > 0; 124} 125 126export function isJson(path: string) { 127 return extname(path, ".json", /*ignoreCase*/ false).length > 0 || extname(path, ".json5", /*ignoreCase*/ false).length > 0; 128} 129 130export function isDefaultLibrary(path: string) { 131 return isDeclaration(path) 132 && basename(path).startsWith("lib."); 133} 134 135export function isTsConfigFile(path: string): boolean { 136 return path.indexOf("tsconfig") !== -1 && path.indexOf("json") !== -1; 137} 138