UNPKG

@lipemat/js-boilerplate

Version:

Dependencies and scripts for a no config JavaScript app

118 lines (105 loc) 3.57 kB
import {existsSync} from 'fs'; import {resolve} from 'path'; import {type Configuration as WebpackConfig} from 'webpack'; import type {Configuration as DevServerConfig} from 'webpack-dev-server'; import type {BabelConfig} from '../config/babel.config'; import type {JestConfig} from '../config/jest.config.js'; import {getPackageConfig} from '@lipemat/js-boilerplate-shared/helpers/package-config.js'; import type {EntriesConfig} from '../config/entries.config.js'; import type {CssLoaderConfig} from '../config/css-loader.config.js'; import {ensureJSExtension, getExtensionsConfig, mergeWithLocalConfig} from '@lipemat/js-boilerplate-shared/helpers/config.js'; type Configs = { 'babel.config.js': BabelConfig; 'css-loader.config.js': CssLoaderConfig; 'dev-server.config.js': DevServerConfig; 'entries.config.js': EntriesConfig; 'jest.config.js': JestConfig; 'webpack.dev.js': WebpackConfig; 'webpack.dist.js': WebpackConfig; }; const {workingDirectory, packageDirectory} = getPackageConfig(); /** * Check to see if a local config file exists. * * @param {string} fileName * @param {boolean} inWorkingDirectory - Look in working directory instead of their /config directory * * @return {boolean} */ export async function hasLocalOverride( fileName: string, inWorkingDirectory: boolean = false ): Promise<boolean> { let hasLocal = false; try { if ( inWorkingDirectory ) { await import( resolve( workingDirectory, fileName ) ); hasLocal = true; } else { await import( resolve( packageDirectory + '/config', fileName ) ); hasLocal = true; } } catch ( e ) { if ( e instanceof Error ) { if ( ! ( 'code' in e ) || 'MODULE_NOT_FOUND' !== e.code ) { console.error( e ); } } } return hasLocal; } /** * Get a config from our /config directory merged with any * matching configuration from the project directory. * * For instance, if we have a file named config/babel.config.js in our project, * we will merge the contents with our config/babel.config.js in favor of whatever * is specified with the project's file. * * If the `module.exports` is a function, the existing configuration will be passed * as the only argument. Otherwise, standard `module.exports` are also supported. * * @example ```ts * // standard * module.export = { * externals: {extra: 'Extra'} * } * // function * module.exports = function(config) { * return { * externals: {...config.externals, extra: 'Extra'} * } * } * ``` * * @param {string} fileName * * @return {Object} */ export async function getConfig<T extends keyof Configs>( fileName: T ): Promise<Configs[T]> { const configModule = await import( ensureJSExtension( `../config/${fileName}` ) ); const config = configModule.default; const extensionsConfig = getExtensionsConfig<Configs[T]>( fileName, config ); const mergedConfig: Configs[T] = {...config, ...extensionsConfig}; return mergeWithLocalConfig<Configs[T]>( fileName, mergedConfig ); } /** * Get the path to the "tsconfig.json" file if it exists. * * 1. The working directory. * 2. The package directory. * * The package directory takes priority over the working directory. * * * @return {string} */ export function getTsConfigFile(): string { const possibles = [ // Backward compatible for before @lipemat/eslint-config version 3. resolve( workingDirectory + '/tsconfig.json' ), resolve( packageDirectory + '/tsconfig.json' ), ].filter( existsSync ); let tsConfig = ''; possibles.forEach( filePath => { tsConfig = filePath; } ); return tsConfig; }