{"version":3,"sources":["../src/index.ts","../src/Middleware.ts","../src/Request.ts","../src/Response.ts","../src/Contracts/HttpContract.ts","../src/Middleware/LogRequests.ts","../src/Providers/HttpServiceProvider.ts","../src/Resources/JsonResource.ts","../src/Resources/ApiResource.ts"],"sourcesContent":["/**\n * @file Automatically generated by barrelsby.\n */\n\nexport * from './Middleware';\nexport * from './Request';\nexport * from './Response';\nexport * from './Contracts/HttpContract';\nexport * from './Middleware/LogRequests';\nexport * from './Providers/HttpServiceProvider';\nexport * from './Resources/ApiResource';\nexport * from './Resources/JsonResource';\n","import { HttpContext } from './Contracts/HttpContract'\nimport { IMiddleware } from '@h3ravel/shared'\n\nexport abstract class Middleware implements IMiddleware {\n    abstract handle (context: HttpContext, next: () => Promise<unknown>): Promise<unknown>\n}\n","import { getQuery, getRouterParams, readBody, type H3Event } from 'h3'\nimport { DotNestedKeys, DotNestedValue, safeDot } from '@h3ravel/support'\nimport type { ResponseHeaderMap, TypedHeaders } from 'fetchdts'\nimport { IRequest } from '@h3ravel/shared'\nimport { Application } from '@h3ravel/core'\n\nexport class Request implements IRequest {\n    /**\n     * Gets route parameters.\n     * @returns An object containing route parameters.\n     */\n    readonly params: NonNullable<H3Event[\"context\"][\"params\"]>\n\n    /**\n     * Gets query parameters.\n     * @returns An object containing query parameters.\n     */\n    readonly query: Record<string, string>;\n\n    /**\n     * Gets the request headers.\n     * @returns An object containing request headers.\n     */\n    readonly headers: TypedHeaders<Record<keyof ResponseHeaderMap, string>>\n\n    /**\n     * The current H3 H3Event instance\n     */\n    private readonly event: H3Event\n\n    constructor(\n        event: H3Event,\n        /**\n         * The current app instance\n         */\n        public app: Application\n    ) {\n        this.event = event\n        this.query = getQuery(this.event)\n        this.params = getRouterParams(this.event)\n        this.headers = this.event.req.headers\n    }\n\n    /**\n     * Get all input data (query + body).\n     */\n    async all<T = Record<string, unknown>> (): Promise<T> {\n        let data = {\n            ...getRouterParams(this.event),\n            ...getQuery(this.event),\n        } as T\n\n        if (this.event.req.method === 'POST') {\n            data = Object.assign({}, data, Object.fromEntries((await this.event.req.formData()).entries()))\n        } else if (this.event.req.method === 'PUT') {\n            data = <never>Object.fromEntries(Object.entries(<never>await readBody(this.event)))\n        }\n\n        return data\n    }\n\n    /**\n     * Get a single input field from query or body.\n     */\n    async input<T = unknown> (key: string, defaultValue?: T): Promise<T> {\n        const data = await this.all<Record<string, T>>()\n        return (data[key] ?? defaultValue) as T\n    }\n\n    /**\n     * Get the base event\n     */\n    getEvent (): H3Event\n    getEvent<K extends DotNestedKeys<H3Event>> (key: K): DotNestedValue<H3Event, K>\n    getEvent<K extends DotNestedKeys<H3Event>> (key?: K): any {\n        return safeDot(this.event, key)\n    }\n}\n","import { DotNestedKeys, DotNestedValue, safeDot } from '@h3ravel/support'\nimport { html, redirect, } from 'h3'\n\nimport { Application } from '@h3ravel/core'\nimport type { H3Event } from 'h3'\nimport { IResponse } from '@h3ravel/shared'\n\nexport class Response implements IResponse {\n    /**\n     * The current H3 H3Event instance\n     */\n    private readonly event: H3Event\n\n    private statusCode: number = 200\n    private headers: Record<string, string> = {}\n\n    constructor(\n        event: H3Event,\n        /**\n         * The current app instance\n         */\n        public app: Application\n    ) {\n        this.event = event\n    }\n\n    /**\n     * Set HTTP status code.\n     */\n    setStatusCode (code: number): this {\n        this.statusCode = code\n        this.event.res.status = code\n        return this\n    }\n\n    /**\n     * Set a header.\n     */\n    setHeader (name: string, value: string): this {\n        this.headers[name] = value\n        return this\n    }\n\n    html (content: string): string {\n        this.applyHeaders()\n        return html(this.event, content)\n    }\n\n    /**\n     * Send a JSON response.\n     */\n    json<T = unknown> (data: T): T {\n        this.setHeader('content-type', 'application/json; charset=utf-8')\n        this.applyHeaders()\n        return data\n    }\n\n    /**\n     * Send plain text.\n     */\n    text (data: string): string {\n        this.setHeader('content-type', 'text/plain; charset=utf-8')\n        this.applyHeaders()\n        return data\n    }\n\n    /**\n     * Redirect to another URL.\n     */\n    redirect (url: string, status = 302): string {\n        this.setStatusCode(status)\n        return redirect(this.event, url, this.statusCode)\n    }\n\n    /**\n     * Apply headers before sending response.\n     */\n    private applyHeaders (): void {\n        Object.entries(this.headers).forEach(([key, value]) => {\n            this.event.res.headers.set(key, value)\n        })\n    }\n\n    /**\n     * Get the base event\n     */\n    getEvent (): H3Event\n    getEvent<K extends DotNestedKeys<H3Event>> (key: K): DotNestedValue<H3Event, K>\n    getEvent<K extends DotNestedKeys<H3Event>> (key?: K): any {\n        return safeDot(this.event, key)\n    }\n}\n","export { HttpContext } from '@h3ravel/shared'\n","import { HttpContext } from '@h3ravel/shared'\nimport { Middleware } from '../Middleware'\n\nexport class LogRequests extends Middleware {\n    async handle ({ request }: HttpContext, next: () => Promise<unknown>): Promise<unknown> {\n        const url = request.getEvent('url')\n        console.log(`[${request.getEvent('method')}] ${url.pathname + url.search}`)\n        return next()\n    }\n}\n","import { H3, serve } from 'h3'\n\nimport { ServiceProvider } from '@h3ravel/core'\n\n/**\n * Sets up HTTP kernel and request lifecycle.\n * \n * Register Request, Response, and Middleware classes.\n * Configure global middleware stack.\n * Boot HTTP kernel.\n * \n * Auto-Registered\n */\nexport class HttpServiceProvider extends ServiceProvider {\n    public static priority = 998;\n\n    register () {\n        this.app.singleton('http.app', () => {\n            return new H3()\n        })\n\n        this.app.singleton('http.serve', () => serve)\n    }\n}\n","import { EventHandlerRequest, H3Event } from 'h3'\n\nexport interface Resource {\n    [key: string]: any;\n    pagination?: {\n        from?: number | undefined;\n        to?: number | undefined;\n        perPage?: number | undefined;\n        total?: number | undefined;\n    } | undefined;\n}\n\ntype BodyResource = Resource & {\n    data: Omit<Resource, 'pagination'>,\n    meta?: {\n        pagination?: Resource['pagination']\n    } | undefined;\n}\n\n/**\n * Class to render API resource\n */\nexport class JsonResource<R extends Resource = any> {\n    /**\n     * The request instance\n     */\n    request: H3Event<EventHandlerRequest>['req']\n    /**\n     * The response instance\n     */\n    response: H3Event['res']\n    /**\n     * The data to send to the client\n     */\n    resource: R\n    /**\n     * The final response data object\n     */\n    body: BodyResource = {\n        data: {},\n    }\n    /**\n     * Flag to track if response should be sent automatically\n     */\n    private shouldSend: boolean = false\n    /**\n     * Flag to track if response has been sent\n     */\n\n    private responseSent: boolean = false;\n\n    /**\n     * Declare that this includes R's properties\n     */\n    [key: string]: any;\n\n    /**\n     * @param req The request instance\n     * @param res The response instance\n     * @param rsc The data to send to the client\n     */\n    constructor(protected event: H3Event, rsc: R) {\n        this.request = event.req\n        this.response = event.res\n        this.resource = rsc\n\n        // Copy all properties from rsc to this, avoiding conflicts\n        for (const key of Object.keys(rsc)) {\n            if (!(key in this)) {\n                Object.defineProperty(this, key, {\n                    enumerable: true,\n                    configurable: true,\n                    get: () => this.resource[key],\n                    set: (value) => {\n                        (<any>this.resource)[key] = value\n                    },\n                })\n            }\n        }\n    }\n\n    /**\n     * Return the data in the expected format\n     * \n     * @returns \n     */\n    data (): Resource {\n        return this.resource\n    }\n\n    /**\n     * Build the response object\n     * @returns this\n     */\n    json () {\n        // Indicate response should be sent automatically\n        this.shouldSend = true\n\n        // Set default status code\n        this.response.status = 200\n\n        // Prepare body\n        const resource = this.data()\n        let data: Resource = Array.isArray(resource) ? [...resource] : { ...resource }\n\n        if (typeof data.data !== 'undefined') {\n            data = data.data\n        }\n\n        if (!Array.isArray(resource)) {\n            delete data.pagination\n        }\n\n        this.body = {\n            data,\n        }\n\n        // Set the pagination from the data() resource, if available\n        if (!Array.isArray(resource) && resource.pagination) {\n            const meta: BodyResource['meta'] = this.body.meta ?? {}\n            meta.pagination = resource.pagination\n            this.body.meta = meta\n        }\n\n        // If pagination is not available on the resource, then check and set it\n        // if it's available on the base resource.\n        if (this.resource.pagination && !this.body.meta?.pagination) {\n            const meta: BodyResource['meta'] = this.body.meta ?? {}\n            meta.pagination = this.resource.pagination\n            this.body.meta = meta\n        }\n\n        return this\n    }\n\n    /**\n     * Add context data to the response object\n     * @param data Context data\n     * @returns this\n     */\n    additional<X extends { [key: string]: any }> (data: X) {\n\n        // Allow automatic send after additional\n        this.shouldSend = true\n\n        // Merge data with body\n        delete data.data\n        delete data.pagination\n\n        this.body = {\n            ...this.body,\n            ...data,\n        }\n\n        return this\n    }\n\n    /**\n     * Send the output to the client\n     * @returns this\n     */\n    send () {\n        this.shouldSend = false // Prevent automatic send\n        if (!this.responseSent) {\n            this.#send()\n        }\n        return this\n    }\n\n    /**\n     * Set the status code for this response\n     * @param code Status code\n     * @returns this\n     */\n    status (code: number) {\n        this.response.status = code\n        return this\n    }\n\n    /**\n     * Private method to send the response\n     */\n    #send () {\n        if (!this.responseSent) {\n            this.event.context.\n                this.response.json(this.body)\n\n            // Mark response as sent\n            this.responseSent = true\n        }\n    }\n\n    /**\n     * Check if send should be triggered automatically\n     */\n    private checkSend () {\n        if (this.shouldSend && !this.responseSent) {\n            this.#send()\n        }\n    }\n}\n","import { JsonResource, Resource } from './JsonResource'\n\nimport { H3Event } from 'h3'\n\nexport function ApiResource (\n    instance: JsonResource\n) {\n    return new Proxy(instance, {\n        get (target, prop, receiver) {\n            const value = Reflect.get(target, prop, receiver)\n            if (typeof value === 'function') {\n                // Intercept json, additional, and send methods\n                if (prop === 'json' || prop === 'additional') {\n                    return (...args: any[]) => {\n                        const result = value.apply(target, args)\n                        // Schedule checkSend after json or additional\n                        setImmediate(() => target['checkSend']())\n                        return result\n                    }\n                } else if (prop === 'send') {\n                    return (...args: any[]) => {\n                        // Prevent checkSend from firing\n                        target['shouldSend'] = false\n\n                        return value.apply(target, args)\n                    }\n                }\n            }\n            return value\n        },\n    })\n}\n\nexport default function BaseResource<R extends Resource> (\n    evt: H3Event,\n    rsc: R\n) {\n    return ApiResource(new JsonResource<R>(evt, rsc))\n}\n"],"mappings":"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","names":["Middleware","Request","params","query","headers","event","app","getQuery","getRouterParams","req","all","data","method","Object","assign","fromEntries","formData","entries","readBody","input","key","defaultValue","getEvent","safeDot","import_support","import_h3","Response","event","statusCode","headers","app","setStatusCode","code","res","status","setHeader","name","value","html","content","applyHeaders","json","data","text","redirect","url","Object","entries","forEach","key","set","getEvent","safeDot","LogRequests","Middleware","handle","request","next","url","getEvent","console","log","pathname","search","import_h3","HttpServiceProvider","ServiceProvider","priority","register","app","singleton","H3","serve","JsonResource","request","response","resource","body","data","shouldSend","responseSent","event","rsc","req","res","key","Object","keys","defineProperty","enumerable","configurable","get","set","value","json","status","Array","isArray","pagination","meta","additional","send","code","context","this","checkSend","ApiResource","instance","Proxy","get","target","prop","receiver","value","Reflect","args","result","apply","setImmediate"]}