import fs from 'fs'; import { join, dirname } from 'path'; import debug from 'debug'; const LWC_CONFIG_FILE = 'lwc.config.json'; /** * @returns all modules reachable from the lwc config in packageDir */ export function resolveModules(packageDir: string): any { // TODO: add option to return only exposed modules? (we need all for labels though) const lwcConfig = readConfig(packageDir); debug('b2c-lite:resolver')(`resolving modules from config in ${packageDir}`); return lwcConfig ? resolveModulesFromList(packageDir, lwcConfig.modules) : []; } function resolveOldLwcConfig(packageDir: string, record: string): any { // assumes record is a String, try first dir, else npm package const dir = join(packageDir, record); return fs.existsSync(dir) ? resolveModulesFromDir(dir) : resolveModulesFromNpm(record); } function resolveModulesFromList(packageDir: string, moduleRecords: any): any { const resolvedModules = []; for (const record of moduleRecords) { if (record.dir) { resolvedModules.push(...resolveModulesFromDir(join(packageDir, record.dir))); } else if (record.npm) { resolvedModules.push(...resolveModulesFromNpm(record.npm)); } else if (record.name) { // skipping alias records } else { resolvedModules.push(...resolveOldLwcConfig(packageDir, record)); } } return resolvedModules; } function resolveModulesFromDir(modulesDir: string): any { const namespaces = fs.readdirSync(modulesDir); const resolvedModules = []; for (const ns of namespaces) { if (ns[0] !== '.' && fs.lstatSync(join(modulesDir, ns)).isDirectory()) { const namespacedModuleDir = join(modulesDir, ns); const modules = fs.readdirSync(namespacedModuleDir); for (const moduleName of modules) { const moduleDir = join(namespacedModuleDir, moduleName); const entry = getModuleEntry(moduleDir, moduleName); if (entry) { const specifier = `${ns}/${moduleName}`; resolvedModules.push({ entry, specifier }); } } } } return resolvedModules; } function resolveModulesFromNpm(packageName: string): any { const pkgJsonPath = require.resolve(`${packageName}/package.json`); const packageDir = dirname(pkgJsonPath); return resolveModules(packageDir); } function getEntry(moduleDir: string, moduleName: string, ext: string): string { return join(moduleDir, `${moduleName}.${ext}`); } function getModuleEntry(moduleDir: string, moduleName: string): any { const entryJS = getEntry(moduleDir, moduleName, 'js'); // Order is important if (fs.existsSync(entryJS)) { return entryJS; } const entryTS = getEntry(moduleDir, moduleName, 'ts'); if (fs.existsSync(entryTS)) { return entryTS; } const entryHTML = getEntry(moduleDir, moduleName, 'html'); if (fs.existsSync(entryHTML)) { return entryHTML; } const entryCSS = getEntry(moduleDir, moduleName, 'css'); if (fs.existsSync(entryCSS)) { return entryCSS; } return null; } function readConfig(packageDir: string): any { const configFile = join(packageDir, LWC_CONFIG_FILE); if (fs.existsSync(configFile)) { return JSON.parse(fs.readFileSync(configFile, 'utf8')); } const packageJson = JSON.parse(fs.readFileSync(join(packageDir, 'package.json'), 'utf8')); return packageJson.lwc; }