UNPKG

@sergio9929/pb-query

Version:

A type-safe PocketBase query builder

233 lines (228 loc) 5.88 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // index.ts var index_exports = {}; __export(index_exports, { OPERATORS: () => OPERATORS, filter: () => filter, pbQuery: () => pbQuery }); module.exports = __toCommonJS(index_exports); // src/constants.ts var OPERATORS = { equal: "=", notEqual: "!=", greaterThan: ">", greaterThanOrEqual: ">=", lessThan: "<", lessThanOrEqual: "<=", like: "~", notLike: "!~", anyEqual: "?=", anyNotEqual: "?!=", anyGreaterThan: "?>", anyGreaterThanOrEqual: "?>=", anyLessThan: "?<", anyLessThanOrEqual: "?<=", anyLike: "?~", anyNotLike: "?!~" }; var DATETIME_MACROS = [ "@now", "@second", "@minute", "@hour", "@weekday", "@day", "@month", "@year", "@yesterday", "@tomorrow", "@todayStart", "@todayEnd", "@monthStart", "@monthEnd", "@yearStart", "@yearEnd" ]; // src/utils.ts function filter(raw, params) { if (!params) { return raw; } let sanitizedQuery = raw; for (const key in params) { let val = params[key]; switch (typeof val) { case "boolean": case "number": val = `${val}`; break; case "string": val = `'${val.replace(/'/g, "\\'")}'`; break; default: if (val === null) { val = "null"; } else if (val instanceof Date) { val = `'${val.toISOString().replace("T", " ")}'`; } else { val = `'${JSON.stringify(val).replace(/'/g, "\\'")}'`; } } sanitizedQuery = sanitizedQuery.replaceAll(`{:${key}}`, val); } return sanitizedQuery; } function isDateMacro(value) { if (!isMacro(value)) { return false; } return DATETIME_MACROS.includes(value); } function isMacro(value) { if (typeof value !== "string") { return false; } return value.length > 1 && value.startsWith("@"); } // src/query.ts function pbQuery() { let query = ""; const keyCounter = /* @__PURE__ */ new Map(); const valueMap = /* @__PURE__ */ new Map(); const incrementKeyCounter = (key) => { const count = keyCounter.get(key) || 0; const newCount = count + 1; keyCounter.set(key, newCount); return newCount; }; const saveValue = (key, value) => { const count = incrementKeyCounter(key); const newName = `${String(key)}${count}`; valueMap.set(newName, value); return newName; }; const expression = (key, operator, value) => { if (isDateMacro(value)) { query += `${String(key)}${operator}${value}`; } else { const newName = saveValue(key, value); query += `${String(key)}${operator}{:${newName}}`; } }; const builderFunctions = {}; for (const [name, operator] of Object.entries(OPERATORS)) { const key = name; builderFunctions[key] = (key2, value) => { expression(key2, operator, value); return restrictedQueryBuilder; }; } function build(filter2) { if (typeof filter2 === "function") { return filter2(query, Object.fromEntries(valueMap)); } return { raw: query, values: Object.fromEntries(valueMap) }; } const queryBuilder = { ...builderFunctions, search(keys, value) { query += "("; const cleanedPaths = keys.filter((key) => key); cleanedPaths.forEach((key, index) => { expression(key, "~", value); query += index < cleanedPaths.length - 1 ? " || " : ""; }); query += ")"; return restrictedQueryBuilder; }, in(key, values) { query += "("; values.forEach((value, index) => { expression(key, "=", value); query += index < values.length - 1 ? " || " : ""; }); query += ")"; return restrictedQueryBuilder; }, notIn(key, values) { query += "("; values.forEach((value, index) => { expression(key, "!=", value); query += index < values.length - 1 ? " && " : ""; }); query += ")"; return restrictedQueryBuilder; }, between(key, from, to) { query += "("; expression(key, ">=", from); query += " && "; expression(key, "<=", to); query += ")"; return restrictedQueryBuilder; }, notBetween(key, from, to) { query += "("; expression(key, "<", from); query += " || "; expression(key, ">", to); query += ")"; return restrictedQueryBuilder; }, isNull(key) { query += `${String(key)}=''`; return restrictedQueryBuilder; }, isNotNull(key) { query += `${String(key)}!=''`; return restrictedQueryBuilder; }, custom(raw) { query += raw; return restrictedQueryBuilder; }, group(callback) { query += "("; callback(queryBuilder); query += ")"; return restrictedQueryBuilder; }, build }; const restrictedQueryBuilder = { and() { query += " && "; return queryBuilder; }, or() { query += " || "; return queryBuilder; }, build }; return queryBuilder; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { OPERATORS, filter, pbQuery });