Effect-TS / effect

An ecosystem of tools to build robust applications in TypeScript
https://effect.website
MIT License
7.41k stars 231 forks source link

Add a drizzle-schema package #3208

Open amosbastian opened 3 months ago

amosbastian commented 3 months ago

What is the problem this feature would solve?

I'm slowly getting into Effect and am coming from a codebase where I use drizzle-zod, which is a plugin for Drizzle ORM that allows you to generate Zod schemas from Drizzle ORM schemas.

For example, you would be able to do something like the following:

import { pgEnum, pgTable, serial, text, timestamp } from 'drizzle-orm/pg-core';
import { createInsertSchema, createSelectSchema } from 'drizzle-schema';

const noteTable = pgTable('note', {
  id: serial('id').primaryKey(),
  content: text('content').notNull(),
});

// Schema for inserting a user - can be used to validate API requests
const insertNoteSchema = createInsertSchema(noteTable);

// Schema for selecting a user - can be used to validate API responses
const selectNoteSchema = createSelectSchema(noteTable);

export const noteApi = pipe(
  Api.make({ title: "Notes API" }),
  Api.addEndpoint(
    pipe(
      Api.post("createNote", "/notes"),
      Api.setRequestBody(insertNoteSchema),
      Api.setResponseBody(selectNoteSchema),
      Api.setResponseStatus(201),
      Api.addResponse(ApiResponse.make(500, NoteApiError)),
    ),
  ),
);

What is the feature you are proposing to solve the problem?

It would be great to have an Effect equivalent (drizzle-schema) as described above.

What alternatives have you considered?

I found this gist in this Discord thread, but it's using an old version of Effect and I'm way too much on an Effect noob to even consider porting this to the latest version.

datner commented 3 months ago

@arkemaz would you be interested in championing this?

arekmaz commented 3 months ago

sure I can try

arekmaz commented 3 months ago

@amosbastian here's initial version without refine (the second argument) which passes insert test for mysql, pg and sqlite

https://github.com/arekmaz/drizzle-orm/blob/effect-schema/drizzle-schema/src/effect-schema.ts

edit: after some hours the insert tests are passing with refine implemented

here's the draft pr to drizzle-orm (I think it belongs there next to drizzle-zod) https://github.com/drizzle-team/drizzle-orm/pull/2613

arekmaz commented 3 months ago

@amosbastian all tests are passing, insert select, with/without refine, for each db, if you want you can copy that file to your project and test it, the only thing left is some package cleanup, and probably some time will pass before they accept the merge request, if they do at all

amosbastian commented 3 months ago

Thanks for your hard work @arekmaz! I've finally got round to using it today, and it's not 100% clear to me how we can use this to do something like

const requestSchema = insertUserSchema.pick({ name: true, email: true });

as we would with drizzle-zod, but that's probably just me being an Effect beginner 😅

arekmaz commented 3 months ago

EDIT: it doesn't work at the moment but in the end you should be able to do this:

const insertUserSchema = createInsertSchema(usersTable);
const requestSchema = insertUserSchema.pick('name', 'email');

as the output schemas will be just Schema.Struct, probably I should mention that somewhere it's documented here

there is also the Schema.pick operator but it doesn't work on structs for me at the moment

I'm a bit too busy to cleanup the package and request the merge at the moment, on weekend I'll probably get around to it

arekmaz commented 3 months ago

I created a new pull request https://github.com/drizzle-team/drizzle-orm/pull/2665 - I'm new to commit signing

let's see if they accept it

arekmaz commented 2 months ago

@datner it looks like the drizzle team did not even look at the pr, what do you think we should do with this?

maybe try to merge it into @effect/sql-drizzle? or create a standalone package? or just wait?

datner commented 2 months ago

deferring to @mikearnaldi 🙏🏻 I am not sure what would be preferable. I default to wait but that does not guarantee a conclusion

mikearnaldi commented 2 months ago

I'd wait a bit longer and eventually evaluate if to merge in sql-drizzle

danielo515 commented 2 months ago

I was just looking for this today. Currently I have to define drizzle schemas, my own domain schemas and then make conversions between the two. It is a bit cumbersome, and I wish this was already available. To me it feels much more natural to look for this kind of things in the schema repository and docs.

datner commented 2 months ago

@danielo515 given 4 parsers: foo, bar, baz, and qux. Knowing that drizzle-orm had drizzle-foo, drizzle-bar, and drizzle-baz in their repo. Where would you expect drizzle-qux to be? How would you expect it to be named? It's no ideal if we would be required to randomly host it on our end :\ But if they are not interested we can't force them

You can ping the PR there if you're interested in pushing it in hehe