@AppKu/StashKu

@AppKu/StashKu

v1.0.46

source

cli/processors/request-processor.js

/* eslint-disable no-console */
///<reference path="../cli.d.js" />
import GetRequest from '../../requests/get-request.js';
import OptionsRequest from '../../requests/options-request.js';
import Filter from '../../filter.js';
import Sort from '../../sort.js';
import ModelUtility from '../../modeling/model-utility.js';
import BaseProcessor from './base-processor.js';
import StashKu from '../../stashku.js';
import OptionsExporter from '../options-exporter.js';
import fairu from '@appku/fairu';
import path from 'path';

const __dirname = (
    process.platform === 'win32' ?
        path.dirname(decodeURI(new URL(import.meta.url).pathname)).substring(1) :
        path.dirname(decodeURI(new URL(import.meta.url).pathname))
);

/**
 * Runs a standard RESTful StashKu GET request using command line options to define the request metadata. Callers can
 * optionally save output to file.
 */
class RequestProcessor extends BaseProcessor {
    // eslint-disable-next-line valid-jsdoc
    /**
     * Runs a standard RESTful StashKu request using command line options to define the request metadata. Callers can
     * optionally save output to file.
     * @param {CLI.GetCommandLineOptions | CLI.OptionsCommandLineOptions} options - The command line options of the request.
     */
    constructor(options) {
        super(options);

        /**
         * @type {CLI.GetCommandLineOptions | CLI.OptionsCommandLineOptions}
         */
        this.options = options;
    }

    /**
     * @inheritdoc
     */
    async start() {
        if (this.options.cli.test || this.options.cli.samples) {
            this.stash = new StashKu({ engine: this.options.cli.engine || 'memory' });
            this.stash.engine.data.set('products', (await fairu.with(path.join(__dirname, '../templates/samples/data-products.json')).format(fairu.Format.json).read())[0].data);
            this.stash.engine.data.set('themes', (await fairu.with(path.join(__dirname, '../templates/samples/data-themes.json')).format(fairu.Format.json).read())[0].data);
        } else {
            this.stash = new StashKu({ engine: this.options.cli.engine });
        }
        let reqFile = null;
        if (this.options.resource != '*') {
            reqFile = await fairu.with(this.options.resource)
                .throw(false)
                .format(fairu.Format.json)
                .read();
        }
        //build the request
        let multiResource = [this.options.resource];
        let req = null;
        if (reqFile && reqFile.length && reqFile[0].readable) {
            if (Array.isArray(reqFile[0].data)) {
                multiResource = reqFile[0].data;
            } else {
                req = StashKu.requestFromObject(reqFile[0].data);
            }
        }
        for (let resource of multiResource) {
            if (this.options.method === 'get') {
                req = this.buildGet(req, resource);
            } else if (this.options.method === 'options') {
                req = this.buildOptions(req, resource);
            } else {
                throw new Error(`No supported method specified for processing ("${this.options.method}" is invalid or unsupported).`);
            }
            console.info(`Running StashKu ${req.method.toUpperCase()} request:`, JSON.stringify(req, null, 4));
            await this.stash.engine;
            //save query to file (do this early to help facilitate troubleshooting).
            if (this.options.save) {
                await fairu.with(this.options.save).stringify(fairu.Format.json).write(req);
            }
            //run the request
            if (!this.options.cli.quiet && this.options.cli.verbose) {
                console.debug(`Running GET request on "${this.stash.engine?.name}" engine for the "${resource}" resource.`);
                console.debug('Request metadata:', JSON.stringify(req.metadata, null, 4));
            }
            let res = await this.stash[this.options.method](req);
            //output response to console
            if (!this.options.cli.quiet) {
                let outputObj = res;
                //handle options requests sending a constructor instead of instance.
                if (this.options.method === 'options') {
                    outputObj = Object.assign({}, res, { data: [] });
                    for (let i = 0; i < res.returned; i++) {
                        outputObj.data.push(ModelUtility.schema(res.data[i]));
                    }
                }
                console.log(fairu.stringify(this.options.cli.format, outputObj));
            }
            //save output to file
            if (this.options.output) {
                await fairu.with(this.options.output).format(this.options.cli.format).write(res);
            }
            //handle options exporting
            if (this.options.method === 'options') {
                let exportMap = await new OptionsExporter().export(res, {
                    dirPath: this.options.export,
                    overwrite: !!this.options.force
                });
                if (!this.options.cli.quiet && this.options.dryRun) {
                    for (let [r, mt] of exportMap) {
                        if (mt) {
                            console.log(`/** ${r} base: **/\n${mt.base}\n\n/**${r} extending: **/\n${mt.extending}`);
                        } else {
                            console.log(`${r}: <null>`);
                        }
                    }
                }
            }
            req = null;
        }
    }

    /**
     * Builds a `GetRequest` from the command-line/processor options.
     * @param {GetRequest} req - An exisiting `GetRequest` to build upon.
     * @param {String} resource - The resource to retrieve.
     * @returns {GetRequest}
     */
    buildGet(req, resource) {
        if (!req) {
            req = new GetRequest();
            req.from(resource);
        } else if ((req instanceof GetRequest) === false) {
            throw new Error('The "req" argument when specified must be a GetRequest instance.');
        }
        if (Array.isArray(this.options.prop) && this.options.prop.length) {
            req.properties(...this.options.prop);
        }
        if (typeof this.options.skip !== 'undefined' && isNaN(this.options.skip) === false) {
            req.skip(this.options.skip);
        }
        if (typeof this.options.take !== 'undefined' && isNaN(this.options.take) === false) {
            req.take(this.options.take);
        }
        if (this.options.distinct) {
            req.distinct();
        }
        if (this.options.count) {
            req.count();
        }
        if (this.options.where) {
            req.where(Filter.parse(this.options.where));
        }
        if (this.options.sortBy) {
            req.sort(Sort.parse(this.options.sortBy));
        }
        return req;
    }

    /**
     * Builds a `OptionsRequest` from the command-line/processor options.
     * @param {OptionsRequest} req - An exisiting `OptionsRequest` to build upon.
     * @returns {OptionsRequest}
     */
    buildOptions(req, resource) {
        if (!req) {
            req = new OptionsRequest();
            req.from(resource);
        } else if ((req instanceof OptionsRequest) === false) {
            throw new Error('The "req" argument when specified must be a OptionsRequest instance.');
        }
        return req;
    }

}

export default RequestProcessor;