@argdown/node
Version:
Async Argdown application for node.js
291 lines • 12.4 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AsyncArgdownApplication = void 0;
const lodash_defaultsdeep_1 = __importDefault(require("lodash.defaultsdeep"));
const lodash_isfunction_1 = __importDefault(require("lodash.isfunction"));
const lodash_isstring_1 = __importDefault(require("lodash.isstring"));
const lodash_isempty_1 = __importDefault(require("lodash.isempty"));
const lodash_isobject_1 = __importDefault(require("lodash.isobject"));
const lodash_clonedeep_1 = __importDefault(require("lodash.clonedeep"));
const core_1 = require("@argdown/core");
const IAsyncArgdownPlugin_1 = require("./IAsyncArgdownPlugin");
const path_1 = __importDefault(require("path"));
const chokidar_1 = __importDefault(require("chokidar"));
const glob_1 = __importDefault(require("glob"));
const util_1 = require("util");
const import_fresh_1 = __importDefault(require("import-fresh"));
const fs_1 = require("fs");
const readFileAsync = (0, util_1.promisify)(fs_1.readFile);
class AsyncArgdownApplication extends core_1.ArgdownApplication {
constructor() {
super(...arguments);
this.load = async (request) => {
const processObj = request.processes && (0, lodash_isstring_1.default)(request.process)
? request.processes[request.process]
: undefined;
let req = request;
if (processObj) {
req = (0, lodash_defaultsdeep_1.default)({}, processObj, req);
}
let inputGlob = req.inputPath || "./*.argdown";
const ignoreFiles = req.ignore || [
"**/_*",
"**/_*/**"
];
if (req.logger &&
(0, lodash_isfunction_1.default)(req.logger.log) &&
(0, lodash_isfunction_1.default)(req.logger.setLevel)) {
if (!this.defaultLogger) {
this.defaultLogger = this.logger;
}
this.logger = req.logger;
}
else if (this.defaultLogger) {
this.logger = this.defaultLogger;
}
if (!req.rootPath) {
req.rootPath = process.cwd();
}
if (req.logLevel) {
this.logger.setLevel(req.logLevel);
}
if (req.plugins) {
for (let pluginData of req.plugins) {
if ((0, lodash_isobject_1.default)(pluginData.plugin) && (0, lodash_isstring_1.default)(pluginData.processor)) {
this.addPlugin(pluginData.plugin, pluginData.processor);
}
}
}
if (req.input && !req.inputPath) {
await this.runAsync((0, lodash_clonedeep_1.default)(request));
return;
}
const $ = this;
let absoluteInputGlob = path_1.default.resolve(req.rootPath, inputGlob);
const loadOptions = {};
if (ignoreFiles) {
loadOptions.ignore = ignoreFiles;
}
if (req.watch) {
const watcher = chokidar_1.default.watch(absoluteInputGlob, loadOptions);
const watcherRequest = (0, lodash_clonedeep_1.default)(req);
watcherRequest.watch = false;
watcher
.on("add", path => {
this.logger.log("verbose", `File ${path} has been added.`);
watcherRequest.inputPath = path;
$.load(watcherRequest);
})
.on("change", path => {
this.logger.log("verbose", `File ${path} has been changed.`);
watcherRequest.inputPath = path;
$.load(watcherRequest);
})
.on("unlink", path => {
this.logger.log("verbose", `File ${path} has been removed.`);
});
}
else {
let files = await new Promise((resolve, reject) => {
(0, glob_1.default)(absoluteInputGlob, loadOptions, (er, files) => {
if (er) {
reject(er);
}
resolve(files);
});
});
const promises = [];
if (files.length == 0) {
throw new core_1.ArgdownPluginError("AsyncArgdownApplication.load", "no-files-found", `No Argdown files found at: '${absoluteInputGlob}'`);
}
for (let file of files) {
const requestForFile = (0, lodash_clonedeep_1.default)(request);
requestForFile.inputPath = file;
promises.push(this.runAsync(requestForFile));
}
if (req.plugins) {
for (let pluginData of req.plugins) {
this.removePlugin(pluginData.plugin, pluginData.processor);
}
}
return await Promise.all(promises);
}
return;
};
this.loadConfig = async (filePath) => {
let config = {};
filePath = filePath || "argdown.config.json";
filePath = path_1.default.resolve(process.cwd(), filePath);
const extension = path_1.default.extname(filePath);
if (extension === ".json") {
try {
const buffer = await readFileAsync(filePath, "utf8");
config = JSON.parse(buffer);
}
catch (e) {
if (e instanceof Error) {
this.logger.log("verbose", "[AsyncArgdownApplication]: No config found: " + e.toString());
}
}
}
else if (extension === ".js") {
try {
let jsModuleExports = loadJSFile(filePath);
if (jsModuleExports.config) {
config = jsModuleExports.config;
}
else {
config = jsModuleExports;
}
}
catch (e) {
if (e instanceof Error) {
this.logger.log("verbose", "[AsyncArgdownApplication]: No config found: " + e.toString());
}
}
}
return config;
};
}
async runAsync(request, response) {
let processorsToRun = [];
this.logger.setLevel("error");
let resp = response || {};
let req = request;
if (req) {
if (req.logLevel) {
this.logger.setLevel(req.logLevel);
}
if (req.process) {
if (Array.isArray(req.process)) {
processorsToRun = req.process;
}
else if ((0, lodash_isstring_1.default)(req.process) &&
req.processes &&
req.processes[req.process]) {
const processObj = req.processes[req.process];
req = (0, lodash_defaultsdeep_1.default)({}, processObj, req);
if ((0, lodash_isstring_1.default)(req.process)) {
processorsToRun = this.defaultProcesses[req.process];
}
else if (req.process && req.process.constructor === Array) {
processorsToRun = req.process;
}
}
else if ((0, lodash_isstring_1.default)(req.process)) {
processorsToRun = this.defaultProcesses[req.process];
}
}
}
if ((0, lodash_isempty_1.default)(processorsToRun)) {
this.logger.log("error", "[AsyncArgdownApplication]: No processors to run.");
return resp;
}
const exceptions = [];
resp.exceptions = exceptions;
for (let processorId of processorsToRun) {
let cancelProcessor = false;
let processor = this.processors[processorId];
if (!processor) {
this.logger.log("error", "[AsyncArgdownApplication]: Processor not found: " + processorId);
continue;
}
this.logger.log("verbose", "[AsyncArgdownApplication]: Running processor: " + processorId);
for (let plugin of processor.plugins) {
if ((0, lodash_isfunction_1.default)(plugin.prepare)) {
this.logger.log("verbose", "[AsyncArgdownApplication]: Preparing plugin: " + plugin.name);
try {
plugin.prepare(req, resp, this.logger);
}
catch (e) {
if (req.throwExceptions) {
throw e;
}
else if (e instanceof core_1.ArgdownPluginError) {
e.processor = processorId;
exceptions.push(e);
cancelProcessor = true;
this.logger.log("warning", `Processor ${processorId} canceled.`);
break;
}
}
}
}
if (cancelProcessor) {
break;
}
if (resp.ast && processor.walker) {
try {
processor.walker.walk(req, resp, this.logger);
}
catch (e) {
if (req.throwExceptions) {
throw e;
}
else if (e instanceof core_1.ArgdownPluginError) {
e.processor = processorId;
cancelProcessor = true;
exceptions.push(e);
this.logger.log("warning", `[ArgdownApplication]: Processor ${processorId} canceled.`);
break;
}
}
}
if (cancelProcessor) {
break;
}
for (let plugin of processor.plugins) {
this.logger.log("verbose", "[AsyncArgdownApplication]: Running plugin: " + plugin.name);
try {
if ((0, IAsyncArgdownPlugin_1.isAsyncPlugin)(plugin)) {
await plugin.runAsync(req, resp, this.logger);
}
else if ((0, lodash_isfunction_1.default)(plugin.run)) {
plugin.run(req, resp, this.logger);
}
}
catch (e) {
if (req.throwExceptions) {
throw e;
}
else if (e instanceof core_1.ArgdownPluginError) {
e.processor = processorId;
cancelProcessor = true;
this.logger.log("warning", `Processor ${processorId} canceled.`);
exceptions.push(e);
break;
}
}
}
if (cancelProcessor) {
break;
}
}
if (req.logExceptions === undefined || req.logExceptions) {
for (let exception of exceptions) {
let msg = exception.stack || exception.message;
if (exception instanceof core_1.ArgdownPluginError) {
msg = `[${exception.processor}/${exception.plugin}]: ${msg}`;
}
this.logger.log("error", msg);
}
}
return resp;
}
}
exports.AsyncArgdownApplication = AsyncArgdownApplication;
const loadJSFile = (filePath) => {
try {
return (0, import_fresh_1.default)(filePath);
}
catch (e) {
if (e instanceof Error) {
e.message = `Cannot read file: ${filePath}\nError: ${e.message}`;
}
throw e;
}
};
//# sourceMappingURL=AsyncArgdownApplication.js.map