//#region src/errors.ts
var InvalidCursorError = class extends Error {
	name = "InvalidCursorError";
	constructor() {
		super("INVALID_CURSOR");
	}
};
//#endregion
//#region src/cursor.ts
const DEFAULT_LIMIT = 50;
const MAX_LIMIT = 200;
const PLUS = /\+/g;
const SLASH = /\//g;
const TRAILING_EQ = /=+$/;
const DASH = /-/g;
const UNDERSCORE = /_/g;
function toBase64Url(value) {
	return btoa(value).replace(PLUS, "-").replace(SLASH, "_").replace(TRAILING_EQ, "");
}
function fromBase64Url(value) {
	let base64 = value.replace(DASH, "+").replace(UNDERSCORE, "/");
	const pad = base64.length % 4;
	if (pad) base64 += "=".repeat(4 - pad);
	return atob(base64);
}
function isKeyset(value) {
	return typeof value === "object" && value !== null && "c" in value && "s" in value && typeof value.c === "number" && typeof value.s === "number" && Number.isFinite(value.c) && Number.isFinite(value.s);
}
function encodeCursor(key) {
	const payload = {
		c: key.createdAtMs,
		s: key.seq
	};
	return toBase64Url(JSON.stringify(payload));
}
function decodeCursor(cursor) {
	try {
		const json = fromBase64Url(cursor);
		const parsed = JSON.parse(json);
		if (!isKeyset(parsed)) throw new InvalidCursorError();
		return {
			createdAtMs: parsed.c,
			seq: parsed.s
		};
	} catch (error) {
		if (error instanceof InvalidCursorError) throw error;
		throw new InvalidCursorError();
	}
}
/** Clamp untrusted `limit`: non-finite/undefined/<=0 → default; huge → max. Never throws. */
function clampLimit(value, opts) {
	const defaultLimit = opts?.defaultLimit ?? DEFAULT_LIMIT;
	const maxLimit = opts?.maxLimit ?? MAX_LIMIT;
	if (value === void 0 || !Number.isFinite(value) || value <= 0) return defaultLimit;
	const truncated = Math.trunc(value);
	if (truncated <= 0) return defaultLimit;
	return Math.min(truncated, maxLimit);
}
//#endregion
//#region src/derive.ts
function deriveStored(value, now, makeId) {
	const createdAtMs = Date.parse(now());
	if (Number.isNaN(createdAtMs)) throw new RangeError("deriveStored: injected now() returned an unparseable timestamp");
	return {
		id: makeId(),
		createdAtMs,
		createdAt: new Date(createdAtMs).toISOString(),
		record: JSON.parse(JSON.stringify(value))
	};
}
//#endregion
export { InvalidCursorError as a, encodeCursor as i, clampLimit as n, decodeCursor as r, deriveStored as t };
