109 lines
2.9 KiB
TypeScript
109 lines
2.9 KiB
TypeScript
|
// BAA stands for Before Around After
|
||
|
|
||
|
import { getQuery, type H3Event } from "h3";
|
||
|
import { type QueryObject } from "ufo";
|
||
|
|
||
|
import { isString } from "./isString";
|
||
|
|
||
|
import { createError } from "#imports";
|
||
|
|
||
|
type queryType<none extends boolean = boolean> = none extends false ? {
|
||
|
type: "before" | "after" | "around",
|
||
|
id: bigint
|
||
|
} : {
|
||
|
type: null
|
||
|
};
|
||
|
|
||
|
export type pageData<none extends boolean = boolean> = queryType<none> & { count: number }
|
||
|
|
||
|
/**
|
||
|
* Gets queryType for a given query with a value
|
||
|
* @param query the query to parse
|
||
|
* @throws if query malformed (multiple before/after/around)
|
||
|
*/
|
||
|
function getLocationParameterType(query: QueryObject): queryType {
|
||
|
const before = query.before;
|
||
|
const after = query.after;
|
||
|
const around = query.around;
|
||
|
|
||
|
let setLocationParametersCount = 0;
|
||
|
let rvalue: queryType = { type: null };
|
||
|
|
||
|
if (isString(before)) {
|
||
|
setLocationParametersCount++;
|
||
|
rvalue = { type: "before", id: BigInt(before) };
|
||
|
}
|
||
|
|
||
|
if (isString(after)) {
|
||
|
setLocationParametersCount++;
|
||
|
rvalue = { type: "after", id: BigInt(after) };
|
||
|
}
|
||
|
|
||
|
if (isString(around)) {
|
||
|
setLocationParametersCount++;
|
||
|
rvalue = { type: "around", id: BigInt(around) };
|
||
|
}
|
||
|
|
||
|
if (setLocationParametersCount > 1) {
|
||
|
throw createError({
|
||
|
statusCode: 400,
|
||
|
message: "multiple location parameters not allowed",
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return rvalue;
|
||
|
}
|
||
|
|
||
|
/** Gets the count parameter from the query object.
|
||
|
* @param query the query to check.
|
||
|
* @param defaultCount the default count if the query doesn't have count parameter. (default 50)
|
||
|
* @param countLimit the maximum count of the parameter before throwing. (default 200)
|
||
|
* @returns the value of count parameter.
|
||
|
* @throws if the parameter in query exceeds provided countLimit.
|
||
|
*/
|
||
|
function getRequestedCount(
|
||
|
query: QueryObject,
|
||
|
defaultCount = 50,
|
||
|
countLimit = 200,
|
||
|
) {
|
||
|
let count = defaultCount;
|
||
|
if (query.limit) count = Number(query.limit);
|
||
|
|
||
|
if (count > countLimit) {
|
||
|
throw createError({
|
||
|
statusCode: 400,
|
||
|
message: `Cannot retrieve more than ${countLimit} records`,
|
||
|
});
|
||
|
}
|
||
|
if (count <= 0) {
|
||
|
throw createError({
|
||
|
statusCode: 400,
|
||
|
message: "Tried to retireve 0 or less records",
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
/** Gets the baa page parameters from the H3event,
|
||
|
* @param e the H3event to fetch parameters.
|
||
|
* @param defaultCount the default count to use if there is no count parameter. (default 50)
|
||
|
* @param countLimit the maximum value of the count parameter before throwing an error. (default 200)
|
||
|
* @returns the page data found in the query.
|
||
|
* @throws if event has a count parameter in the query that exceed provided countLimit.
|
||
|
*/
|
||
|
export default function getPaginatedParameters(
|
||
|
e: H3Event,
|
||
|
defaultCount = 50,
|
||
|
countLimit = 200,
|
||
|
): pageData {
|
||
|
const query = getQuery(e);
|
||
|
const queryParameters = getLocationParameterType(query);
|
||
|
const queryCount = getRequestedCount(query, defaultCount, countLimit);
|
||
|
|
||
|
return {
|
||
|
...queryParameters,
|
||
|
count: queryCount,
|
||
|
};
|
||
|
}
|