UNPKG

liferay-npm-bundler-preset-reactjs

Version:

liferay npm bundler preset react

145 lines (112 loc) 3.57 kB
/** * SPDX-FileCopyrightText: © 2020 Liferay, Inc. <https://liferay.com> * SPDX-License-Identifier: LGPL-3.0-or-later */ import fs from 'fs'; import path from 'path'; import readJsonSync from 'read-json-sync'; /** A null object pattern for {@link fs.Stats} object */ interface NullFsStats { isDirectory: () => boolean; isFile: () => boolean; } /** * Converts a package name (optionally versioned) to its target folder name * inside bundled node_modules. * @param name a package name * @param version an optional package version * @return the target folder */ export function getPackageTargetDir( name: string, version: string = null ): string { let targetFolder = name.replace('/', '%2F'); if (version) { targetFolder += `@${version}`; } return targetFolder; } /** * Resolves a module name inside a package directory to a file relative (to * package directory) path. * For example, if you pass './lib' as moduleName and there's an 'index.js' file * inside the 'lib' dir, the method returns './lib/index.js'. * It also honors any 'package.json' with a 'main' entry in package subfolders. * @param pkgPath path to package directory * @param moduleName the module name * @return a path relative to pkgDir */ export function resolveModuleFile(pkgPath: string, moduleName: string): string { let fullModulePath = path.resolve( path.join(pkgPath, ...moduleName.split('/')) ); let moduleStats = safeStat(fullModulePath); if (moduleStats.isDirectory()) { // Given module name is a directory const pkgJsonPath = path.join(fullModulePath, 'package.json'); const pkgJsonStats = safeStat(pkgJsonPath); if (pkgJsonStats.isFile()) { // Module directory has package.json file const pkgJson = readJsonSync(pkgJsonPath); const {main} = pkgJson; if (main) { // Module directory has package.json file with main entry: // recursively resolve the main entry's file path fullModulePath = path.join( pkgPath, resolveModuleFile(pkgPath, path.join(moduleName, main)) ); } else { // Module directory has package.json file without main entry: // assume index.js fullModulePath = path.join(fullModulePath, 'index.js'); } } else { // Module directory has not package.json file: assume index.js fullModulePath = path.join(fullModulePath, 'index.js'); } } else if (moduleStats.isFile()) { // Given module name is a file: do nothing } else if (fullModulePath.endsWith('.js')) { // Given module name is not a directory nor a file but ends with '.js' // extension: see if corresponding '.js.js' file exists moduleStats = safeStat(`${fullModulePath}.js`); if (moduleStats.isFile()) { // Given module name has a corresponding '.js.js' file: add '.js' // extension fullModulePath += '.js'; } else { // Given module name has no corresponding '.js.js' file: do nothing // and assume that the '.js' in the module name is just the // extension of the file and doesn't belong to its name. } } else { // Given module name is not a directory nor a file and doesn't end with // '.js' extension: add '.js' extension fullModulePath += '.js'; } return path.relative(pkgPath, fullModulePath); } /** * Do as fs.statSync without throwing errors. * @param path path to check * @return {fs.Stats} a real fs.Stats object or a null object */ function safeStat(path: string): fs.Stats | NullFsStats { try { return fs.statSync(path); } catch (err) { return { isDirectory: () => false, isFile: () => false, }; } }