UNPKG

liferay-npm-bundler-preset-reactjs

Version:

liferay npm bundler preset react

179 lines (140 loc) 3.98 kB
/** * SPDX-FileCopyrightText: © 2020 Liferay, Inc. <https://liferay.com> * SPDX-License-Identifier: LGPL-3.0-or-later */ import prop from 'dot-prop'; import readJsonSync from 'read-json-sync'; import FilePath from './file-path'; /** Alias configuration as expressed in `package.json` files */ export type AliasConfig = false | string | AliasHash | undefined; /** Value of the right hand side of an alias */ export type AliasToValue = false | string; export enum AliasFromType { EXTERNAL, LOCAL, } export enum AliasToType { IGNORE, EXTERNAL, LOCAL, } /** * Index is the `from` field of the alias (`/` normalized to `./`), value is the * `to` field. */ export interface AliasHash { [index: string]: AliasToValue; } const aliasesCache: {[index: string]: AliasHash} = Object.create(null); /** * Get `resolve.aliasFields` configuration value. * * @remarks * The `resolve.aliasFields` name resembles the value webpack's configuration * uses for the same functionality (see * https://webpack.js.org/configuration/resolve/#resolvealiasfields) */ export function getAliasFields(globalConfig: object, config: object): string[] { let aliasFields: string[]; if (prop.has(config, 'resolve.aliasFields')) { aliasFields = prop.get(config, 'resolve.aliasFields'); } else if (prop.has(globalConfig, 'resolve.aliasFields')) { aliasFields = prop.get(globalConfig, 'resolve.aliasFields'); } else { aliasFields = ['browser']; } return aliasFields; } /** * Get the type of an alias `from` field (left hand side of alias) */ export function getAliasFromType(from: string): AliasFromType { if (from.startsWith('/') || from.startsWith('.') || from.startsWith('..')) { return AliasFromType.LOCAL; } return AliasFromType.EXTERNAL; } /** * Get the type of an alias `to` field (right hand side of alias) */ export function getAliasToType(to: AliasToValue): AliasToType { if (to === false) { return AliasToType.IGNORE; } if (to.startsWith('/')) { throw new Error( `Absolute paths in require() calls are not supported: ${to}` ); } if (to.startsWith('.') || to.startsWith('..')) { return AliasToType.LOCAL; } return AliasToType.EXTERNAL; } /** * Load aliases from a `package.json` file. */ export function loadAliases( pkgJsonFile: FilePath, aliasFields: string[] ): AliasHash { const absPkgJsonFile = pkgJsonFile.resolve(); const cacheKey = `${absPkgJsonFile.asNative}|${aliasFields.join()}`; let aliases: AliasHash = aliasesCache[cacheKey]; // If not yet cached proceed if (aliases === undefined) { const pkgJson = safeReadJsonSync(absPkgJsonFile); aliases = aliasFields.reduce( (aliases: AliasHash, aliasField: string) => { const aliasConfig: AliasConfig = pkgJson[aliasField]; if (aliasConfig === undefined) { return aliases; } if (aliasConfig === false || typeof aliasConfig === 'string') { let main = pkgJson['main'] || './index.js'; if (!main.startsWith('.')) { main = `./${main}`; } aliases[main] = aliasConfig; } else { Object.entries(aliasConfig).forEach(([from, to]) => { aliases[from] = to; }); } return aliases; }, {} ); // Normalize `/` to `./` Object.keys(aliases).forEach((key) => { if (key.startsWith('/')) { aliases[`.${key}`] = aliases[key]; delete aliases[key]; } }); // Normalize local aliases to make them start with `./` Object.keys(aliases).forEach((key) => { if (key.startsWith('.')) { const value = aliases[key]; if (typeof value === 'string' && !value.startsWith('.')) { aliases[key] = `./${value}`; } } }); } // Store in cache aliasesCache[cacheKey] = Object.assign(Object.create(null), aliases); return aliases; } function safeReadJsonSync(pkgJsonFile: FilePath): object { try { return readJsonSync(pkgJsonFile.asNative); } catch (err) { // Always return some sort of JSON if reading the file fails return {}; } }