2025-09-05 14:59:21 +08:00

78 lines
2.7 KiB
JavaScript

import { getQuery, createError } from "h3";
import { jsonParse, jsonStringify } from "./json.js";
const parseJSONQueryParams = (body) => {
try {
return jsonParse(body);
} catch {
throw createError({ statusCode: 400, message: "Invalid _params query" });
}
};
export const encodeQueryParams = (params) => {
let encoded = jsonStringify(params);
encoded = typeof Buffer !== "undefined" ? Buffer.from(encoded).toString("base64") : btoa(encoded);
encoded = encoded.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
const chunks = encoded.match(/.{1,100}/g) || [];
return chunks.join("/");
};
export const decodeQueryParams = (encoded) => {
encoded = encoded.replace(/\//g, "");
encoded = encoded.replace(/-/g, "+").replace(/_/g, "/");
encoded = encoded.padEnd(encoded.length + (4 - encoded.length % 4) % 4, "=");
return parseJSONQueryParams(typeof Buffer !== "undefined" ? Buffer.from(encoded, "base64").toString() : atob(encoded));
};
const memory = {};
export const getContentQuery = (event) => {
const { params } = event.context.params || {};
if (params) {
return decodeQueryParams(params.replace(/.json$/, ""));
}
const qid = event.context.params?.qid?.replace(/.json$/, "");
const query = getQuery(event) || {};
if (qid && query._params) {
memory[qid] = parseJSONQueryParams(decodeURIComponent(query._params));
if (memory[qid]?.where && !Array.isArray(memory[qid]?.where)) {
memory[qid].where = [memory[qid].where];
}
return memory[qid];
}
if (qid && memory[qid]) {
return memory[qid];
}
if (query._params) {
return parseJSONQueryParams(decodeURIComponent(query._params));
}
if (typeof query.only === "string" && query.only.includes(",")) {
query.only = query.only.split(",").map((s) => s.trim());
}
if (typeof query.without === "string" && query.without.includes(",")) {
query.without = query.without.split(",").map((s) => s.trim());
}
const where = query.where || {};
for (const key of ["draft", "partial", "empty"]) {
if (query[key] && ["true", "false"].includes(query[key])) {
where[key] = query[key] === "true";
delete query[key];
}
}
if (query.sort) {
query.sort = String(query.sort).split(",").map((s) => {
const [key, order] = s.split(":");
return [key, Number.parseInt(order || "0", 10)];
});
}
const reservedKeys = ["partial", "draft", "only", "without", "where", "sort", "limit", "skip"];
for (const key of Object.keys(query)) {
if (reservedKeys.includes(key)) {
continue;
}
query.where = query.where || {};
query.where[key] = query[key];
}
if (Object.keys(where).length > 0) {
query.where = [where];
} else {
delete query.where;
}
return query;
};