UNPKG

@noony-serverless/core

Version:

A Middy base framework compatible with Firebase and GCP Cloud Functions with TypeScript

160 lines 5.91 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.queryParametersMiddleware = exports.QueryParametersMiddleware = void 0; const core_1 = require("../core"); const validateQueryParameters = (requiredParams, query) => { for (const param of requiredParams) { if (!query[param]) { throw new core_1.ValidationError(`Missing required query parameter: ${param}`); } } }; const convertQueryToRecord = (query) => { const result = {}; for (const key in query) { if (query[key] !== undefined) { result[key] = Array.isArray(query[key]) ? query[key].map(String) : String(query[key]); } } return result; }; /** * Middleware class that validates and processes query parameters from the request URL. * Extracts query parameters and validates that required parameters are present. * * @template TBody - The type of the request body payload (preserves type chain) * @template TUser - The type of the authenticated user (preserves type chain) * @implements {BaseMiddleware} * * @example * Basic query parameter validation: * ```typescript * import { Handler, QueryParametersMiddleware } from '@noony-serverless/core'; * * const searchHandler = new Handler() * .use(new QueryParametersMiddleware(['q', 'type'])) * .handle(async (context) => { * const { q, type } = context.req.query; * const results = await search(q, type); * return { success: true, results, query: q, type }; * }); * ``` * * @example * Pagination with required parameters: * ```typescript * const listHandler = new Handler() * .use(new QueryParametersMiddleware(['page', 'limit'])) * .handle(async (context) => { * const { page, limit, sort } = context.req.query; * const items = await getItems(parseInt(page), parseInt(limit), sort); * return { success: true, items, pagination: { page, limit } }; * }); * ``` * * @example * Optional parameters (empty required array): * ```typescript * const flexibleHandler = new Handler() * .use(new QueryParametersMiddleware([])) // No required parameters * .handle(async (context) => { * const { filter, sort, category } = context.req.query || {}; * const data = await getData({ filter, sort, category }); * return { success: true, data }; * }); * ``` */ class QueryParametersMiddleware { requiredParams; constructor(requiredParams = []) { this.requiredParams = requiredParams; } async before(context) { const host = (Array.isArray(context.req.headers.host) ? context.req.headers.host[0] : context.req.headers.host) || 'localhost'; const url = new URL(context.req.url, `http://${host}`); context.req.query = Object.fromEntries(url.searchParams); const query = convertQueryToRecord(context.req.query); validateQueryParameters(this.requiredParams, query); } } exports.QueryParametersMiddleware = QueryParametersMiddleware; /** * Factory function that creates a query parameter processing middleware. * Extracts and validates query parameters from the request URL. * * @template TBody - The type of the request body payload (preserves type chain) * @template TUser - The type of the authenticated user (preserves type chain) * @param requiredParams - Array of parameter names that must be present (default: empty array) * @returns BaseMiddleware object with query parameter processing logic * * @example * API endpoint with required search parameters: * ```typescript * import { Handler, queryParametersMiddleware } from '@noony-serverless/core'; * * const searchApiHandler = new Handler() * .use(queryParametersMiddleware(['q'])) // 'q' parameter is required * .handle(async (context) => { * const { q, category, sort } = context.req.query; * const searchResults = await performSearch(q, { category, sort }); * return { success: true, results: searchResults }; * }); * ``` * * @example * E-commerce product listing with filters: * ```typescript * const productListHandler = new Handler() * .use(queryParametersMiddleware(['category'])) // Category is required * .handle(async (context) => { * const { category, price_min, price_max, brand, sort } = context.req.query; * const products = await getProducts({ * category, * priceRange: { min: price_min, max: price_max }, * brand, * sortBy: sort || 'name' * }); * return { success: true, products, filters: { category, brand, sort } }; * }); * ``` * * @example * Flexible API with optional parameters: * ```typescript * const dataHandler = new Handler() * .use(queryParametersMiddleware()) // No required parameters * .handle(async (context) => { * const queryParams = context.req.query || {}; * const { * page = '1', * limit = '10', * sort = 'created_at', * order = 'desc' * } = queryParams; * * const data = await fetchData({ * pagination: { page: parseInt(page), limit: parseInt(limit) }, * sorting: { field: sort, order } * }); * * return { success: true, data, meta: { page, limit, sort, order } }; * }); * ``` */ const queryParametersMiddleware = (requiredParams = []) => ({ async before(context) { const host = (Array.isArray(context.req.headers.host) ? context.req.headers.host[0] : context.req.headers.host) || 'localhost'; const url = new URL(context.req.url, `http://${host}`); context.req.query = Object.fromEntries(url.searchParams); const query = convertQueryToRecord(context.req.query); validateQueryParameters(requiredParams, query); }, }); exports.queryParametersMiddleware = queryParametersMiddleware; //# sourceMappingURL=queryParametersMiddleware.js.map