UNPKG

@stylework/loopback-query-parser

Version:

LoopBack 4/8 middleware to parse and coerce query parameters

68 lines (67 loc) 1.98 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.queryParserMiddleware = void 0; const qs_1 = __importDefault(require("qs")); // --- Coercion Helpers --- function coerce(value) { if (value === "true") return true; if (value === "false") return false; if (typeof value === "string" && value.trim() !== "" && !isNaN(Number(value))) { return Number(value); } return value; } function deepCoerce(obj) { if (Array.isArray(obj)) return obj.map(deepCoerce); if (obj && typeof obj === "object") { const coerced = {}; for (const key of Object.keys(obj)) { coerced[key] = deepCoerce(obj[key]); } return coerced; } return coerce(obj); } // --- Only-Whitelist Coercion Wrapper --- const whitelistedKeys = new Set([ "filter", "where", "fields", "include", "order", "limit", "skip", "offset", "page", "count", ]); function selectivelyCoerceTopLevel(parsed) { if (!parsed || typeof parsed !== "object") return parsed; const out = {}; for (const key of Object.keys(parsed)) { out[key] = whitelistedKeys.has(key) ? deepCoerce(parsed[key]) : parsed[key]; } return out; } // --- Middleware --- const queryParserMiddleware = async (ctx, next) => { const req = ctx.request; if (req.url.includes("?")) { const [, query] = req.url.split("?"); const parsed = qs_1.default.parse(query, { allowDots: false }); // CHANGE: Only coerce whitelisted LoopBack fields; others remain unchanged req.query = selectivelyCoerceTopLevel(parsed); console.log("[queryParserMiddleware] Parsed query:", req.query); } await next(); }; exports.queryParserMiddleware = queryParserMiddleware;