Skip to content

Instantly share code, notes, and snippets.

@probablykasper
Last active July 10, 2025 22:21
Show Gist options
  • Select an option

  • Save probablykasper/f5e23ba782a61af3da8f8e106a569c6f to your computer and use it in GitHub Desktop.

Select an option

Save probablykasper/f5e23ba782a61af3da8f8e106a569c6f to your computer and use it in GitHub Desktop.
type LiteralString<T> = string extends T ? never : T
export type Kaction = {
name: string
schema: ZodType
actions: Record<string, Action>
action_name: string
_types: {
input: unknown
output: Record<string, unknown>
}
}
export function kaction<
N extends string,
I,
O,
R extends string | null,
P extends Partial<Record<string, string>> = Partial<Record<string, string>>,
>(options: {
/** This has to be specified as a constant, for example `'login' as const` */
name: LiteralString<N>
schema: ZodType<I>
handler: (event: RequestEvent<P, R> & { input: I }, input: I) => O | Promise<O>
}): Record<
N,
((event: RequestEvent<P, R>) => Promise<O>) & {
action_name: LiteralString<N>
_types: { input: I; output: Awaited<O> }
}
> {
const action_fn = async function (event: RequestEvent<P, R>) {
const json = await event.request.json()
const result = options.schema.safeParse(json)
if (!result.success) sk_error(400, prettifyError(result.error))
const action_event = Object.assign(event, {
input: result.data,
})
return options.handler(action_event, result.data)
}
const action = Object.assign(action_fn, {
action_name: options.name,
_types: {
input: undefined as unknown as I,
output: undefined as unknown as Awaited<O>,
},
})
const actions = {} as Record<N, typeof action>
actions[options.name] = action
return actions
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment