mili
Version:
Scaffolding with continuous control over the development of the project.
193 lines (192 loc) • 7.22 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import AJV from 'ajv8';
import ajvFormats from 'ajv-formats';
import * as fs from 'fs-extra';
import * as path from 'path';
import * as JSON5 from 'json5';
import * as YAML from 'js-yaml';
import * as configSchema from './schema/config.json';
import * as hooksSchema from './schema/hooks.json';
import * as questionsSchema from './schema/questions.json';
import * as templatesSchema from './schema/templates.json';
import * as R from 'ramda';
const ajv = new AJV();
ajvFormats(ajv);
function validate(schema, data, dataVar) {
const validator = ajv.compile(schema);
const valid = validator(data);
if (!valid)
throw new Error(ajv.errorsText(validator.errors, { dataVar }));
return true;
}
function exist(filepath) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield fs.access(filepath);
return true;
}
catch (error) {
return false;
}
});
}
function readJson(filepath) {
return __awaiter(this, void 0, void 0, function* () {
const content = yield fs.readFile(filepath, { encoding: 'utf8' });
return JSON5.parse(content);
});
}
function readYaml(filepath) {
return __awaiter(this, void 0, void 0, function* () {
const content = yield fs.readFile(filepath, { encoding: 'utf8' });
return YAML.load(content);
});
}
function readConfig(filepath) {
return __awaiter(this, void 0, void 0, function* () {
const ymlFilepath = `${filepath}.yml`;
const jsonFilepath = `${filepath}.json`;
if (yield exist(ymlFilepath)) {
return readYaml(ymlFilepath);
}
else if (yield exist(jsonFilepath)) {
return readJson(jsonFilepath);
}
});
}
const buildInLoaders = fs.readdirSync(path.join(__dirname, '../loader'));
const buildInHanlders = fs.readdirSync(path.join(__dirname, '../handler'));
export function loadMiliConfig(dir) {
return __awaiter(this, void 0, void 0, function* () {
const config = yield readConfig(path.join(dir, 'mili'));
validate(configSchema, config, 'config');
if (!config.version) {
const packageJson = yield readJson(path.join(dir, 'package.json'));
config.version = packageJson.version;
}
if (!config.extends)
config.extends = [];
if (!config.loaders)
config.loaders = [];
config.loaders = config.loaders.map(loader => {
if (typeof loader === 'string') {
return {
name: loader,
options: {},
};
}
return loader;
});
config.loaders = config.loaders.map(loader => {
if (buildInLoaders.includes(`${loader.name}.js`) || buildInLoaders.includes(loader.name)) {
return {
name: path.join(__dirname, '../loader', loader.name),
options: loader.options,
};
}
else {
return {
name: path.join(dir, 'node_modules', loader.name),
options: loader.options,
};
}
});
config.extends = config.extends.map(ext => {
if (typeof ext === 'string') {
return {
template: ext,
version: 'latest',
};
}
return ext;
});
return config;
});
}
export function loadHooksConfig(dir) {
return __awaiter(this, void 0, void 0, function* () {
const config = yield readConfig(path.join(dir, 'hooks'));
if (!config)
return [];
validate(hooksSchema, config, 'hooks');
const pair = Object.entries(config);
return pair.map(([name, exec]) => ({ name, exec }));
});
}
export function loadQuestionsConfig(dir) {
return __awaiter(this, void 0, void 0, function* () {
const config = yield readConfig(path.join(dir, 'questions'));
if (!config)
return [];
validate(questionsSchema, config, 'questions');
return config;
});
}
export function loadTemplateConfig(dir) {
return __awaiter(this, void 0, void 0, function* () {
const config = yield readConfig(path.join(dir, 'templates'));
validate(templatesSchema, config, 'templates');
config.push({
path: '**',
encoding: 'utf8',
handlers: ['overwrite'],
});
return R.unnest(config.map(item => {
if (!item.encoding)
item.encoding = 'utf8';
if (!item.handlers || !item.handlers.length)
item.handlers = ['overwrite'];
item.handlers = item.handlers.map(handler => {
if (typeof handler === 'string') {
return {
name: handler,
options: {},
};
}
return handler;
});
if (item.handlers[item.handlers.length - 1].name !== 'overwrite') {
item.handlers.push({
name: 'overwrite',
options: {},
});
}
item.handlers = item.handlers.map(handler => {
if (buildInHanlders.includes(`${handler.name}.js`) || buildInHanlders.includes(handler.name)) {
return {
name: path.join(__dirname, '../handler', handler.name),
options: handler.options,
};
}
else {
return {
name: path.join(dir, 'node_modules', handler.name),
options: handler.options,
};
}
});
if (Array.isArray(item.path)) {
return item.path.map(subpath => {
const handler = R.clone(item);
handler.path = subpath;
return handler;
});
}
return item;
}));
});
}
export function loadConfig(dir) {
return __awaiter(this, void 0, void 0, function* () {
const config = yield loadMiliConfig(dir);
return Object.assign(Object.assign({}, config), { hooks: yield loadHooksConfig(dir), questions: yield loadQuestionsConfig(dir), templates: yield loadTemplateConfig(dir) });
});
}