import fs from "fs"; import cloneDeep from "lodash.clonedeep"; import { error, createSchema, validate } from "luban-cli-shared-utils"; import { getRcPath } from "./rcPath"; import { AnyKindOfDictionary, Preset, LocalConfig } from "../types"; export const rcPath = getRcPath(".lubanrc"); const presetSchema = createSchema((joi) => joi.object().keys({ bare: joi.boolean(), useConfigFiles: joi.boolean(), router: joi.boolean(), routerHistoryMode: joi.boolean(), store: joi.boolean(), cssPreprocessor: joi.string().valid("less", "styled-components"), configs: joi.object(), }), ); const schema = createSchema((joi) => joi.object().keys({ latestVersion: joi.string().regex(/^\d+\.\d+\.\d+(-(alpha|beta|rc)\.\d+)?$/), lastChecked: joi.date().timestamp(), packageManager: joi.string().valid("yarn", "npm"), presets: joi.object().pattern(/^/, presetSchema), }), ); export const validatePreset = function(preset: AnyKindOfDictionary): void { validate(preset, presetSchema, {}, (msg) => { error(`invalid preset options: ${msg}`); }); }; export const defaultPreset: Preset = { useConfigFiles: false, cssPreprocessor: undefined, plugins: { "cli-plugin-service": {} }, }; export const defaults: LocalConfig = { lastChecked: undefined, latestVersion: undefined, packageManager: undefined, presets: { default: defaultPreset, }, }; let cachedOptions: LocalConfig; export const loadLocalConfig = function(): LocalConfig { if (cachedOptions) { return cachedOptions; } if (fs.existsSync(rcPath)) { try { cachedOptions = JSON.parse(fs.readFileSync(rcPath, "utf-8")); } catch (e) { error( `Error loading saved preferences: ` + `~/.lubanrc may be corrupted or have syntax errors. ` + `Please fix/delete it and re-run luban-react-cli in manual mode.\n` + `(${e.message})`, ); process.exit(1); } validate(cachedOptions, schema, {}, () => { error(`~/.lubanrc may be outdated. ` + `Please delete it and re-run luban-react-cli in manual mode.`); }); return cachedOptions; } else { return {}; } }; export const saveLocalConfig = function(toSave: LocalConfig): void { const options = Object.assign(cloneDeep(exports.loadLocalConfig()), toSave); for (const key in options) { if (!(key in exports.defaults)) { delete options[key]; } } cachedOptions = options; try { fs.writeFileSync(rcPath, JSON.stringify(options, null, 2)); } catch (e) { error(`Error saving preferences: ` + `make sure you have write access to ${rcPath}.\n` + `(${e.message})`); } }; export const savePreset = function(name: string, preset: Preset): void { const presets = cloneDeep(exports.loadLocalConfig().presets || {}); presets[name] = preset; saveLocalConfig({ presets }); };