edgedb / edgedb-js

The official TypeScript/JS client library and query builder for EdgeDB
https://edgedb.com
Apache License 2.0
508 stars 65 forks source link

RFC: New generator: Zod #435

Open spigelli opened 2 years ago

spigelli commented 2 years ago

The ability to opt in to zod schema generation would be awesome not sure how $infer works behind the scenes (if it has runtime type understanding)

I'm wanting this for trpc but it has a lot of other benefits (bit more validation than just a type and others I'm sure)

the trpc use-case:

export const t = initTRPC();

/*
type Movie {
  required property id -> uuid;
  required property title -> str;
  required property release_year -> int16;
}
*/

const select = {
  title: true,
  release_year: true
}

const insertMovie = e.params(
  einfer(e.Movie, select), // this would be cool but not really the point of this example
  (params) => {
    return e.insert(e.Movie, params);
  }
);

const zodMovie = zinfer(e.Movie);
const zodSchemaWithJustId = zodMovie.pick({ id: true });
const zodInput = zodMovie.pick({ title: true, release_year: true });

/*
zod move is
z.object({
  id: z.uuid,
  title: z.string,
  release_year: z.number().positive().int().max(65535) // max for unsigned 16 bit int is 65535
});
*/

// trpc v10
const movieProcedure = t.procedure.input(zodSchemaWithJustId);

const appRouter = t.router({
  createMovie: movieProcedure,
    .input(zodInput)
    .mutation(({ input }) => {
      return insertMovie.run(client, input);       
    }),
});
Sikarii commented 2 years ago

I like this idea a lot, I feel like it would play nicely with this RFC: https://github.com/edgedb/edgedb-js/issues/361. In fact Zod is mentioned in the RFC.

hanayashiki commented 1 year ago

This is not just wanted, but actually REQUIRED

scotttrinh commented 1 year ago

One tricky bit here is not depending on Zod itself and having it be a peerDependency and tracking changes to Zod here: changes to Zod's API would have potentially breaking changes to the generator. Definitely doable and I see a lot of value in being able to map EdgeDB types -> Zod. The other way around is pretty lossy, so we'll need to define exactly what the supported use cases and user flows we would want are.

Probably some prior art with similar projects we can lean into and learn from here.

grokwich commented 1 year ago

+1 Hoping to have generated constraints/validations that are consistent with EdgeDB, which can then be used by Zod, Typebox and other tooling.

haikyuu commented 12 months ago

There is a zod schema generator for prisma.

I find it useful for form validation that works both in the client and server. Of course the server will have extra validation.

But there are many open questions:

/// @zod.import(["import Buffer from 'buffer'"])
model MyModel {
  myField String /// @zod.string.min(3, { message: "min error" }).max(10, { message: "max error" }).[...chain more validators]
}

The prisma generator throws when there is an error, which is nice.

Pros

Cons

For edgedb

One possible way is to implement the same things using annotations ... But I'm not really fond of it, as it will have the same cons. What I would like to do is to actually implement form validation at the schema level using edgeql and be able to generate a client side form validator in wasm that I could use in the client (browser, mobile ...). In the server side, I'd lean on EdgeDB to do validation natively.

This is probably NOT possible since some EdgeDB standard functions are defined in SQL. But it should be possible to do with an extension, especially if there is a wasm extension that enables running wasm in edgeql.

I think it's important for the db and the schema to ACTUALLY be the source of truth. And data/form validation are part of that "truth"