I hereby claim:
- I am aabbccsmith on github.
- I am aabbccsmith (https://keybase.io/aabbccsmith) on keybase.
- I have a public key ASAjdhw9WSY3MWPwMArg_1ctDRGffZppjkLhWZSfdSUBIgo
To claim this, I am signing this object:
I hereby claim:
To claim this, I am signing this object:
What is this all about? | |
// Please don't fork this! | |
// One |
import { Permer } from "permer"; | |
const permer = new Permer(["web", "email"]); | |
type NotificationSettings = { | |
user_id: number; | |
review_comment: number; | |
user_likes_review: number; | |
user_comment_review: number; | |
user_like_list: number; |
async function wrapRedis<T>(key: string, fn: () => Promise<T>, seconds = 60): Promise<T> { | |
const cached = await redis.get(key); | |
if (cached) return JSON.parse(cached); | |
const recent = await fn(); | |
if (recent) { | |
await redis.set(key, JSON.stringify(recent), 'ex', seconds); | |
} |
/** | |
* Handle clicks outside of an element. | |
* This is useful for closing a modal by clicking outside of the modal. | |
* @param callback - The callback function to run when clicking outside of an element | |
*/ | |
export function useOutsideClick<E extends HTMLElement = HTMLElement>(callback: () => unknown) { | |
const container = useRef<E | null>(null); | |
useEffect(() => { | |
const handler = (event: MouseEvent) => { |
export function useThrottle<T>(value: T, limit = 1000) { | |
const [throttledValue, setThrottledValue] = useState(value); | |
const lastRan = useRef(Date.now()); | |
useEffect(() => { | |
const handler = setTimeout(() => { | |
if (Date.now() - lastRan.current >= limit) { | |
setThrottledValue(value); | |
lastRan.current = Date.now(); | |
} |
/** | |
* TypeScript currently lacks a way of typing a record of keys only but not values. | |
* we need this because we want an object of typed keys but we want to leave the values inferred. | |
* thankfully, we can do this with generics. This function allows the second generic's values to be inferred | |
* so that our object is fully type safe for hugely complex types, but we can guarantee that all the keys we need exist. | |
* It's not perfect, but it gets the job done for the time being | |
*/ | |
export function ensureKeys<T>() { | |
/** | |
* Function that returns the value that gets put in, values are type-safely inferred |
/** | |
* Pick a subset of keys from an object in a type-safe fashion | |
* @param obj | |
* @param keys | |
*/ | |
export function pick<T, K extends Array<keyof T>>( | |
obj: T, | |
keys: K | |
): Pick<T, K[number]> { | |
return Object.fromEntries( |
// Was having some fun with TypeScript and built a signature for some theoretical | |
// object that could cast any type to any other type. This uses template literal types, | |
// generics, infer and mapped types. | |
import {Except} from 'type-fest'; | |
type TypeofsTypes = { | |
string: string; | |
number: number; | |
bigint: BigInt; |
/** | |
* Joins a string array together with a given spacer. Ridiculously unecessarily type-safe! | |
* @param t The tuple/array of string items to join together | |
* @param s The spacer to go between each character | |
* @returns A joint string joined together | |
*/ | |
export function join<V extends string, Tuple extends Readonly<[V, ...V[]]>, Spacer extends string>( | |
t: Tuple, | |
s: Spacer | |
) { |