Tiny Zod implementation.
Zod is a dense library, and its module structure (or lack thereof) makes it difficult for bundlers to tree-shake unused modules.
Additionally, using Zod in vals requires the await import
syntax which means having to wrap every schema in a Promise and awaiting it. This is extremely annoying.
So this is a lil-tiny-smol Zod meant for use in vals. A noteworthy use-case is using minizod
to generate tyep-safe API calls to run vals outside of Val Town (such as client-side).
We can use minizod
to create type safe HTTP handlers and generate the corresponding code to call them using Val Town's API, all in a type-safe manner.
First, create a schema for a function. The following example defines a schema for a function that takes a { name: string }
parameter and returns a Promise<{ text: string }>
.
const minizodExampleSchema = () =>
@zackoverflow.minizod().chain((z) =>
z
.func()
.args(z.tuple().item(z.object({ name: z.string() })))
.ret(z.promise().return(z.object({ text: z.string() })))
);
With a function schema, you can then create an implementation and export it as a val:
const minizodExample = @me.minizodExampleSchema().impl(async (
{ name },
) => ({ text: `Hello, ${name}!` })).json()
In the above example, we call .impl()
on a function schema and pass in a closure which implements the actual body of the function. Here, we simply return a greeting to the name passed in.
We can call this val, and it will automatically parse and validate the args we give it:
// Errors at compile time and runtime for us!
const response = @me.minizodExample({ name: 420 })
Alternatively, we can use the .json()
function to use it as a JSON HTTP handler:
const minizodExample = @me.minizodExampleSchema().impl(async (
{ name },
) => ({ text: `Hello, ${name}!` })).json() // <-- this part
We can now call minizodExample
through Val Town's API. Since we defined a schema for it, we know exactly the types of its arguments and return, which means we can generate type-safe code to call the API:
let generatedApiCode =
@zackoverflow.minizodFunctionGenerateTypescript(
// put your username here
"zackoverflow",
"minizodExample",
// put your auth token here
"my auth token",
@me.minizodExampleSchema(),
);
This generates the following the code:
export const fetchMinizodExample = async (
...args: [{ name: string }]
): Promise<Awaited<Promise<{ text: string }>>> =>
await fetch(`https://api.val.town/v1/run/zackoverflow.minizodExample`, {
method: "POST",
body: JSON.stringify({
args: [...args],
}),
headers: {
Authorization: "Bearer ksafajslfkjal;kjf;laksjl;fajsdf",
},
}).then((res) => res.json());