Source: index.js

const { Component } = require("./class/Component")
const { ComponentStore } = require("./class/ComponentStore")
const { OrigamiMounter } = require("./class/Mounter")
const { OrigamiServer } = require("./class/OrigamiServer")
const { Route } = require("./class/Route")
const { RouteStore } = require("./class/RouteStore")
const { RequestError } = require("./class/RequestError")
const { Loader } = require("./class/Loader")

/**
 * An Origami app.
 * @constructor
 * @param {number} port - The port the app should bind to
 * @param {object} settings - The settings to intialize the app with
 */
class Origami {
    constructor(port = 3000, settings = {}) {
        this.port = port
        this.settings = settings

        this.server = new OrigamiServer(this.port, this)

        this.mounter = new OrigamiMounter(this)
        this.loader = new Loader()

        this.routes = new RouteStore()
        this.components = new ComponentStore()
    }

    /**
     * Create an Origami server. Goes live on the port specified on instantiation.
     * 
     * @param {Function} cback - Callback to run after server goes live
     * @returns {Origami}
     */
    listen = function(cback = () => {}) {
        this.server.listen(this.port)

        cback(this)

        return this
    }

    /**
     * Mount a directory to the application. Routes and components are imported automatically.
     * 
     * @param {string} directory - The directory from which to import
     * @param {string} basePath - The path to bind imported routes under
     * @param {Function} cback - The callback to run after importing is finished
     * @returns {Origami}
     */
    use = async function(directory, basePath, cback = () => {}) {
        let thingsToMount = await this.loader.use(directory, basePath)

        for(let k in thingsToMount) {
            this.mounter.mount(thingsToMount[k])
        }

        await cback(this)

        return this
    }

    /**
     * Mount something onto the app.
     * 
     * @param {Route|Component} thing - The thing to try to mount.
     * @returns {Origami}
     */
    Mount = function(thing) {
        return this.mounter.mount(thing)
    }

    /**
     * @callback routeResolver
     * 
     * @param {RequestContext} ctx - The context of the incoming request
     * @param {RequestResponse} res - The response object of the incoming request
     */

    /**
     * Shorthand for creating a route and mounting it to the app.
     * 
     * @param {string} method - The method of the route. One of: GET, POST, PUT, DELETE, PATCH
     * @param {string} path - The path of the route
     * @param {routeResolver} resolver - The resolver function of the route
     * @returns {Route}
     */
    Route = function(method, path, resolver) {
        return this.Mount(
            new Route(method, path, resolver)
        )
    }

    /**
     * Shorthand for creating a component and mounting it to the app.
     * 
     * @param {string} name - The name of the component
     * @param {class} recipe - The recipe class of the component
     * @returns {Component}
     */
    Component = function(name, recipe) {
        return this.Mount(
            new Component(name, recipe)
        )
    }
}

module.exports.Origami = Origami
module.exports.Component = Component
module.exports.Route = Route
module.exports.RequestError = RequestError