{"version":3,"file":"build-formatted-query.mjs","names":["queryObject","constants"],"sources":["../../../../src/libs/http/utils/build-formatted-query.ts"],"sourcesContent":["import z, { type ZodType } from \"zod\";\nimport constants from \"../../../constants/constants.js\";\nimport type { LucidHonoContext } from \"../../../types/hono.js\";\nimport type {\n\tFilterOperator,\n\tFilterValue,\n\tQueryParamFilterGroups,\n\tQueryParamFilters,\n} from \"../../../types/query-params.js\";\nimport { LucidAPIError } from \"../../../utils/errors/index.js\";\nimport { copy } from \"../../i18n/index.js\";\n\nconst buildSort = (query: unknown) => {\n\tconst queryObject = query as Record<string, string>;\n\tconst sort = queryObject.sort;\n\tif (!sort) return undefined;\n\treturn sort.split(\",\").map((sort) => {\n\t\tif (sort.startsWith(\"-\")) {\n\t\t\treturn {\n\t\t\t\tkey: sort.slice(1),\n\t\t\t\tdirection: \"desc\",\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tkey: sort,\n\t\t\tdirection: \"asc\",\n\t\t};\n\t});\n};\n\n/** Splits set values while preserving commas in semantic text filters. */\nconst parseFilterValue = (value: string, operator?: string): FilterValue => {\n\tif (operator === \"in\" || operator === \"not-in\") return value.split(\",\");\n\tif (operator !== undefined && operator !== \"\") return value;\n\treturn value.includes(\",\") ? value.split(\",\") : value;\n};\n\nconst buildFilter = (query: unknown, nullableFields?: string[]) => {\n\treturn Object.entries(\n\t\tquery as Record<string, string>,\n\t).reduce<QueryParamFilters>((acc, [key, value]) => {\n\t\tif (key.includes(\"filter[\")) {\n\t\t\tconst match = key.match(/^filter\\[([^\\]:]+):?([^\\]]*)\\]$/);\n\t\t\tif (!match) return acc;\n\t\t\tconst [, name, operator] = match;\n\t\t\tif (!name) return acc;\n\n\t\t\tlet processedValue = parseFilterValue(value, operator);\n\n\t\t\tif (nullableFields?.includes(name) && processedValue === \"\") {\n\t\t\t\tprocessedValue = null;\n\t\t\t}\n\n\t\t\tacc[name] = {\n\t\t\t\tvalue: processedValue,\n\t\t\t\toperator:\n\t\t\t\t\toperator === \"\" || operator === undefined\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: (operator as FilterOperator),\n\t\t\t};\n\t\t}\n\t\treturn acc;\n\t}, {});\n};\n\n/** Parses grouped OR params while preserving numeric group order. */\nconst buildFilterOr = (query: unknown, nullableFields?: string[]) => {\n\tconst groups = new Map<number, QueryParamFilterGroups[number]>();\n\n\tfor (const [key, value] of Object.entries(query as Record<string, string>)) {\n\t\tconst match = key.match(/^filter\\[or\\]\\[(\\d+)\\]\\[([^\\]:]+):?([^\\]]*)\\]$/);\n\t\tif (!match) continue;\n\n\t\tconst [, groupIndexRaw, name, operator] = match;\n\t\tif (!groupIndexRaw || !name) continue;\n\n\t\tconst groupIndex = Number.parseInt(groupIndexRaw, 10);\n\t\tif (Number.isNaN(groupIndex)) continue;\n\n\t\tlet processedValue = parseFilterValue(value, operator);\n\n\t\tif (nullableFields?.includes(name) && processedValue === \"\") {\n\t\t\tprocessedValue = null;\n\t\t}\n\n\t\tconst group = groups.get(groupIndex) ?? [];\n\t\tgroup.push({\n\t\t\tkey: name,\n\t\t\tvalue: processedValue,\n\t\t\toperator:\n\t\t\t\toperator === \"\" || operator === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: (operator as FilterOperator),\n\t\t});\n\t\tgroups.set(groupIndex, group);\n\t}\n\n\tconst filterGroups = Array.from(groups.entries())\n\t\t.sort(([left], [right]) => left - right)\n\t\t.map(([, group]) => group)\n\t\t.filter((group) => group.length > 0);\n\n\treturn filterGroups.length > 0 ? filterGroups : undefined;\n};\n\nconst buildPage = (query: unknown) => {\n\tconst queryObject = query as Record<string, string>;\n\tconst page = queryObject.page;\n\tif (!page) return constants.query.page;\n\treturn Number.parseInt(page, 10);\n};\n\nconst buildPerPage = (query: unknown) => {\n\tconst queryObject = query as Record<string, string>;\n\tconst perPage = queryObject.perPage;\n\tif (!perPage) return constants.query.perPage;\n\treturn Number.parseInt(perPage, 10);\n};\n\nconst buildInclude = (query: unknown) => {\n\tconst queryObject = query as Record<string, string>;\n\tconst include = queryObject.include;\n\tif (!include) return undefined;\n\treturn include.split(\",\");\n};\n\nconst buildExclude = (query: unknown) => {\n\tconst queryObject = query as Record<string, string>;\n\tconst exclude = queryObject.exclude;\n\tif (!exclude) return undefined;\n\treturn exclude.split(\",\");\n};\n\nconst addRemainingQuery = (query: unknown) => {\n\tconst queryObject = query as Record<string, string>;\n\tconst remainingQuery = Object.fromEntries(\n\t\tObject.entries(queryObject).filter(\n\t\t\t([key]) =>\n\t\t\t\t![\"include\", \"exclude\", \"filter\", \"sort\", \"page\", \"perPage\"].includes(\n\t\t\t\t\tkey,\n\t\t\t\t),\n\t\t),\n\t);\n\treturn remainingQuery;\n};\n\nconst buildFormattedQuery = async <T extends ZodType>(\n\tc: LucidHonoContext,\n\tschema: T,\n\toptions?: {\n\t\tnullableFields?: string[];\n\t},\n): Promise<z.infer<T>> => {\n\tconst querySchema = schema ?? z.object({});\n\n\tconst queryParams = c.req.query();\n\n\tconst formattedQueryObject = {\n\t\tsort: buildSort(queryParams),\n\t\tfilter: buildFilter(queryParams, options?.nullableFields),\n\t\tfilterOr: buildFilterOr(queryParams, options?.nullableFields),\n\t\tinclude: buildInclude(queryParams),\n\t\texclude: buildExclude(queryParams),\n\t\tpage: buildPage(queryParams),\n\t\tperPage: buildPerPage(queryParams),\n\t\t...addRemainingQuery(queryParams),\n\t};\n\n\tconst validateResult = await querySchema.safeParseAsync(formattedQueryObject);\n\n\tif (!validateResult.success) {\n\t\tthrow new LucidAPIError({\n\t\t\ttype: \"validation\",\n\t\t\tmessage: copy(\"server:core.requests.query.validation.message\"),\n\t\t\tzod: validateResult.error,\n\t\t});\n\t}\n\n\tconst parsedQuery = validateResult.data as Record<string, unknown>;\n\n\treturn {\n\t\t...parsedQuery,\n\t\t...(formattedQueryObject.filterOr !== undefined\n\t\t\t? { filterOr: formattedQueryObject.filterOr }\n\t\t\t: {}),\n\t} as z.infer<T>;\n};\n\nexport default buildFormattedQuery;\n"],"mappings":"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"}