UNPKG

@swell/cli

Version:

Swell's command line interface/utility

167 lines (166 loc) 4.95 kB
/** * App configuration for local development of Swell Apps. */ import Conf from 'conf'; import * as fs from 'node:fs'; import * as path from 'node:path'; const schema = { compatibilities: { type: 'object' }, description: { type: 'string' }, extensions: { type: 'array' }, id: { type: 'string' }, integrations: { type: 'array' }, name: { type: 'string' }, permissions: { type: 'array' }, storefront: { type: 'object' }, theme: { type: 'object' }, type: { type: 'string' }, version: { type: 'string' }, }; const APP_FILE_NAME = 'swell'; const APP_FILE_EXT = 'json'; /** * Builds the path to the app config file. If no directory is provided, the * current working directory is used. * * @param dir - the directory to use for the config file path * @returns string */ function swellConfigFile(dir = '') { if (!dir) { dir = process.cwd(); } return path.join(dir, [APP_FILE_NAME, '.', APP_FILE_EXT].join('')); } /** * Checks if the swell config file exists at the given path, default to cwd. * * @param configFilePath - the path to the app config file * @returns boolean * @throws Error */ function swellConfigFileExists(configFilePath = '') { // if the config file path is not provided, try to find it as the default if (!configFilePath) { configFilePath = swellConfigFile(); } try { // eslint-disable-next-line no-bitwise fs.accessSync(configFilePath, fs.constants.R_OK | fs.constants.W_OK); return true; } catch (error) { if (error.code !== 'ENOENT') { throw error; } return false; } } /** * Finds the app config file in the current directory or a parent directory. * If the file is not found, an error is thrown. * * @param dir - the directory to start searching from * @returns string * @throws Error */ function swellConfigFilePath(dir = '') { const configFilePath = swellConfigFile(dir); if (swellConfigFileExists(configFilePath)) { return configFilePath; } // if the file doesn't exist, try to find it in the parent directory // until we reach the root directory if (dir && dir === path.parse(dir).root) { return ''; } return swellConfigFilePath(path.resolve(dir, '..')); } async function writeRcFile(path, data) { let dataToWrite = '# This file is automatically generated by the Swell CLI\n'; for (const [key, value] of Object.entries(data)) { dataToWrite += `${key}=${value}\n`; } fs.writeFileSync(path, dataToWrite); } function readRcFile(path) { const data = {}; const dataFromFile = fs.readFileSync(path, 'utf8'); const lines = dataFromFile.split('\n'); for (const line of lines) { const cleanLine = line.trim(); if (cleanLine.startsWith('#')) { // Ignore comments continue; } const [key, value] = cleanLine.trim().split('='); const cleanValue = value && value.trim(); if (key && cleanValue) { data[key] = cleanValue; } } return data; } /** * Returns a new configuration instance in the current working directory or * a parent directory. * * @param configDir - the path to the app config directory. If not provided, * the config file will be searched for in the current working directory or * a parent directory. * * @returns Conf */ function config(configDir = '') { const dirPath = configDir || path.dirname(swellConfigFilePath()); let config; try { config = new Conf({ clearInvalidConfig: true, configName: APP_FILE_NAME, cwd: dirPath, schema, }); } catch (error) { throw new Error(`Error parsing swell.json: ${error.toString()}`); } // for convenience, we add custom properties to the Conf object // we prefix them with "sw" to avoid conflicts with Conf's properties config.swDirPath = dirPath; return config; } /** * Returns a new configuration instance in the current working directory only. * * @param path Path of the current working directory * @returns Conf */ function newConfig(path) { return new Conf({ clearInvalidConfig: true, configName: APP_FILE_NAME, cwd: `${process.cwd()}${path ? `/${path}` : ''}`, schema, serialize, }); } /** * Returns a new configuration instance at the specified path. * * @param appPath Path of the current working directory * @returns Conf */ function newConfigAtPath(appPath) { const dirPath = appPath || path.dirname(swellConfigFilePath()); return new Conf({ configName: APP_FILE_NAME, cwd: dirPath, schema, serialize, }); } function serialize(value) { return JSON.stringify(value, null, 2); } export { config as default, newConfig, newConfigAtPath, readRcFile, swellConfigFileExists, writeRcFile, };