UNPKG

@vtex/fsp-cli

Version:

A VTEX CLI

132 lines (106 loc) 3.38 kB
import { readFileSync } from 'node:fs' import path from 'node:path' import type { Command } from '@oclif/core' import { type ModuleConfig, loadConfig } from '@vtex/fsp-config' import type { PackageJson } from 'type-fest' /** * Maps the module name to the correct npm package */ export const moduleCliMap: Record<string, string> = { checkout: '@vtex/checkout', discovery: '@faststore/cli', 'sales-app': '@vtex/sales-app', } const moduleCLIPathMap: Record<string, string> = { '@vtex/checkout': '@vtex/checkout/cli', '@faststore/cli': '@faststore/cli', '@vtex/sales-app': '@vtex/sales-app/cli', } export const availableModules = Object.keys(moduleCliMap) /** * Load modules from the config file of a given account * @param account Account of the config to load the modules * @param moduleFilterFn Filter modules to be loaded. It loads all modules by default */ export async function loadModules( account: string, moduleFilterFn: (module: string) => boolean = () => true ) { const { stores } = await loadConfig() const accountConfigs = stores[account] if (!accountConfigs) { const availableAccounts = Object.keys(stores).join(', ') throw new Error( `Could not find account "${account}". Found accounts: ${availableAccounts}` ) } const modules = Object.keys(accountConfigs) .filter(moduleFilterFn) .map((module) => { const moduleConfig = accountConfigs[module] const cli = moduleConfig?.cli ?? moduleCliMap[module] if (!cli) { throw new Error('CLI not found! Provide a valid module or a CLI') } return { ...accountConfigs[module], cli, } }) return await Promise.all(modules.map((module) => loadModule(module))) } async function loadModule(module: Module): Promise<LoadedModule> { const foundDirectory = path.join(process.cwd(), module.path) if (!foundDirectory) { throw new Error('Module not found') } const loadedCli = await load(module) return { ...module, loadedCli } } export async function load(module: Module): Promise<ModulePackageExports> { let rootPackageJson: PackageJson = {} try { rootPackageJson = JSON.parse( readFileSync(path.join(process.cwd(), 'package.json')).toString() ) } catch { throw new Error('Could not find package.json') } if (!rootPackageJson.devDependencies?.[module.cli]) { throw new Error( `You must add ${module.cli} to your devDependencies and install it` ) } try { const importedModule = await import(moduleCLIPathMap[module.cli]) const isEsm = !!importedModule.__esModule return isEsm ? importedModule.default : importedModule } catch { throw new Error(`Could not import module ${module.cli}`) } } export interface CommandList { build: Command.Class dev: Command.Class create: Command.Class serve: Command.Class [key: string]: Command.Class | undefined } interface HookList { preDev?: () => Promise<void> postDev?: () => Promise<void> preBuild?: () => Promise<void> postBuild?: () => Promise<void> preServe?: () => Promise<void> postServe?: () => Promise<void> } export interface LoadedModule extends Module { loadedCli: ModulePackageExports } export interface ModulePackageExports { commands: CommandList hooks?: HookList } export interface Module extends ModuleConfig { cli: string }