m1212e / prismabox

typebox schema generator for prisma
MIT License
34 stars 6 forks source link

Add support for Transform types #25

Open anotheri opened 4 hours ago

anotheri commented 4 hours ago

First of all thanks for maintaining this lib!

I have a feature request. The Typebox supports types transformations now:

https://github.com/sinclairzx81/typebox?tab=readme-ov-file#transform-types

It seems an alternative approach for what useJsonTypes flag allows to have. There is an idea on how that can be done. So for example in scope of Dates, it can be something like this:

// Define custom type with transformation, this assumes format date-time has been registered
const IsoDate = (options?: StringOptions) =>
  Type.Transform(Type.String({ format: 'date-time', ...options }))
    .Decode(value => new Date(value))
    .Encode(value => value.toISOString())

// Generated schema consuming the type helper
MySchema = Type.Object({
  createdAt: IsoDate()
});

So it can be realized the next way: 1) add config option with path to file with custom types (this module(s) should be imported into generated schema files if one of custom types are used in schema); 2) maybe add some predefined custom types, e.g. this IsoDate which is quite generic and useful; 3) add a new annotation which would apply custom type to the particular field in generated schema, e.g.:

/// @prismabox.type{ custom: 'IsoDate' }

So in case when generated schemas are used as DTO (i guess this is one of the main reasons to generate Typebox schemas from Prisma models), the application codebase most probably should rely on StaticDecode<typeof T> — kind of "internal" type, and both original Static<typeof T> and StaticEncode<typeof T> supposed to be equal and represent "external" JSON schema valid type, which can easily be used for example with Fastify, Open API documentation, etc.

On side note, if you prefer to have a couple hardcoded custom types in combination with useJsonTypes flag, here is an "inverted" helper respectively:

const IsoString = (options?: DateOptions) =>
  Type.Transform(Type.Date({ ...options }))
    .Decode((value) => value.toISOString())
    .Encode((value) => new Date(value));

Please let me know what do you think.

m1212e commented 2 hours ago

Didn't know about this feature yet but this seems like a good way to flawlessly support pure JSON schema while maintaining prisma compatibility which expects native date objects. Sounds like a good idea. Currently I'm sick and pretty busy but I'll have a look throughout the next weeks. Feel free to open a PR or ask any questions if you'd like to tackle this yourself! Thanks for the notice!