import { Package } from './Global'; export const FILE_ENCODING = "UTF-8"; const nodePath = require("path"); const rtrim = require("rtrim"); const fs = require('fs'); /** * Helpers to resolve Path alias format and normalization */ export class AliasPathUtil { /** * @param path nodejs request * @param alias to verify * @returns true if an alias is inside nodejs request otherwise false */ static hasAlias(path: string, alias: string) { alias = AliasPathUtil.stripWildcard(alias); if (!path) { return false; } const onlyAlias = path.length === alias.length; const hasSubdirectory = path[alias.length] === "/" || path[alias.length] === "\\"; const containsAlias = path.indexOf(alias) === 0; return containsAlias && (onlyAlias || hasSubdirectory); } /** * Alias is replaced by its value if is defined inside a request * @param request * @param alias * @param aliasPath */ static getAliasedPath( request: string, alias: string, aliasPath: string ): string { if (!AliasPathUtil.hasAlias(request, alias)) { return request; } return AliasPathUtil.buildPath(request, alias, aliasPath); } /** * Alias is replaced by its value if is defined inside a request * * @param request * @param alias * @param aliasPath */ static buildPath(request: string, alias: string, aliasPath: string): string { const rightSide = AliasPathUtil.normalizeRightSide(request, alias); const normalizedAlias = AliasPathUtil.normalizeAlias(aliasPath); const result = nodePath.join(normalizedAlias, rightSide); return nodePath.normalize(result); } /** * Removes alias inside nodejs require request * @param path * @param alias * * @example * require('@foobar/any/mod') => require('/any/mod') */ static normalizeRightSide(path: string, alias: string): string { alias = AliasPathUtil.stripWildcard(alias); return path.substr(alias.length); } /** * Removes the trailing "*" from a string (if any) * @param path * @returns {string} */ static stripWildcard(path: string): string { if (path.endsWith("/*") || path.endsWith("\\*")) { path = path.substr(0, path.length - 2); } return path; } /** * Removes trailing slash * @param aliasPath value of alias: * * @example * aliasPath = { * alias : aliasPath * } */ static normalizeAlias(aliasPath: string): string { aliasPath = AliasPathUtil.stripWildcard(aliasPath); if (aliasPath.endsWith("/") || aliasPath.endsWith("\\")) { aliasPath = aliasPath.substr(0, aliasPath.length - 1); } return aliasPath; } /** * Find any directory using a file name as needle. * * @param startScanFrom base directory to start searching * @param fileToSearchFor the needle to look for * @param maxTry max number of iterations * @return object with indexes: * file: (string) the needle with directory prepended * directory: (string) current directory found * fileExists: (boolen) true if directory is found otherwise false */ static findFileDirectory(startScanFrom: string, fileToSearchFor: string, maxTry = 10) { let file = ""; let directory = startScanFrom; let maxNum = 0; let fileExists = false; do { directory = nodePath.normalize(directory + "/.."); file = nodePath.join(directory, fileToSearchFor); fileExists = fs.existsSync(file); maxNum++; } while (!fileExists && maxNum < maxTry); return { file: file, directory: directory, fileExists: fileExists }; } /** * Extracts a string from a base string. * @param base string which will be looked for * @param stripFrom string to be removed from the base * @param stripStartsWith characters to be stripped out from the resulting string */ static diffString(base: string, stripFrom: string, stripStartsWith: string = null) { const strResult = (base.slice(stripFrom.length, base.length)); if (stripStartsWith) { return strResult.startsWith(stripStartsWith) ? strResult.slice(stripStartsWith.length, strResult.length) : strResult; } return strResult; } /** * Find typescript config path, if your class is invoking * momotThePug's module in a linear directory back slashes. * @param startScanFrom usually __dirname value is passed * @param rootProjectFile file that marks a directory as root * @param tsconfigFile tsconfig file that marks as typescript project */ static findTSConfigToReadFromRoot(startScanFrom: string, rootPath = null, tsconfigFile = "tsconfig.json") { const tsConfigFile = AliasPathUtil.findFileDirectory(startScanFrom, tsconfigFile); const _packageData = Package.projectData(rootPath); if (tsConfigFile.fileExists) { return { diff: AliasPathUtil.diffString(tsConfigFile.directory, _packageData.get("root"), nodePath.sep), ts: tsConfigFile } } throw `Cannot find ${tsconfigFile}: \n tsConfigFile: ${JSON.stringify(tsConfigFile)} `; } }