90 lines
2.6 KiB
TypeScript
90 lines
2.6 KiB
TypeScript
import type { z } from "zod";
|
|
|
|
export function capitalize(input: string, firstOfAllWords?: boolean): string {
|
|
// capitalize first letter of input
|
|
if (!firstOfAllWords) {
|
|
return input.charAt(0).toUpperCase() + input.slice(1);
|
|
}
|
|
let out = "";
|
|
for (const word of input.split(" ")) {
|
|
out += word.charAt(0).toUpperCase() + word.slice(1) + " ";
|
|
}
|
|
return out.slice(0, -1);
|
|
}
|
|
|
|
export function camelToSpacedPascal(input: string): string {
|
|
let result = "";
|
|
let previousChar = "";
|
|
for (const char of input) {
|
|
if (char === char.toUpperCase() && previousChar !== " ") {
|
|
result += " ";
|
|
}
|
|
result += char;
|
|
previousChar = char;
|
|
}
|
|
return result.charAt(0).toUpperCase() + result.slice(1);
|
|
}
|
|
|
|
export function snakeToCamel(input: string): string {
|
|
if (!input) {
|
|
return input;
|
|
}
|
|
// also account for numbers and kebab-case
|
|
const splits = input.split(/[-_]/);
|
|
let result = splits[0];
|
|
for (const split of splits.slice(1)) {
|
|
result += capitalize(split, true);
|
|
}
|
|
return result ?? "";
|
|
}
|
|
|
|
export function snakeToSpacedPascal(input: string): string {
|
|
return camelToSpacedPascal(snakeToCamel(input));
|
|
}
|
|
|
|
export function spacedPascalToSnake(input: string): string {
|
|
return input.split(" ").join("_").toLowerCase();
|
|
}
|
|
|
|
export function convertDashedLowerToTitleCase(input: string): string {
|
|
return input
|
|
.split("-")
|
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
.join(" "); // Join the words with a space
|
|
}
|
|
|
|
export function encodeCursor<T>(cursor: T): string {
|
|
try {
|
|
// Convert the object to a JSON string
|
|
const jsonString = JSON.stringify(cursor);
|
|
// Convert to UTF-8 bytes, then base64
|
|
return btoa(
|
|
encodeURIComponent(jsonString).replace(/%([0-9A-F]{2})/g, (_, p1) =>
|
|
String.fromCharCode(parseInt(p1, 16)),
|
|
),
|
|
);
|
|
} catch (error) {
|
|
console.error("Error encoding cursor:", error);
|
|
throw new Error("Failed to encode cursor");
|
|
}
|
|
}
|
|
|
|
export function decodeCursor<T>(cursor: string, parser: z.AnyZodObject) {
|
|
try {
|
|
// Decode base64 back to UTF-8 string
|
|
const decoded = decodeURIComponent(
|
|
Array.prototype.map
|
|
.call(atob(cursor), (c) => {
|
|
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
|
|
})
|
|
.join(""),
|
|
);
|
|
// Parse back to object
|
|
const parsedData = JSON.parse(decoded);
|
|
return parser.safeParse(parsedData) as z.SafeParseReturnType<any, T>;
|
|
} catch (error) {
|
|
console.error("Error decoding cursor:", error);
|
|
return { error: new Error("Failed to decode cursor"), data: undefined };
|
|
}
|
|
}
|