StefanTerdell / zod-to-json-schema

Converts Zod schemas to Json schemas
ISC License
857 stars 68 forks source link

Improvement request: support for MongoDB json schema #40

Closed jamauro closed 10 months ago

jamauro commented 1 year ago

Hi,

Thanks for making this package. Looks super useful. I'd like to use it in a Mongo project but they have a slightly different expectation for json schemas. Would you consider adding Mongo support?

I think it would require a few changes. In particular:

  1. They recommend using bsonType instead of type
  2. They use int instead of integer
  3. They use bool instead of boolean
  4. z.date() would map to bsonType: 'date'
StefanTerdell commented 1 year ago

If those are the only differences it should be pretty trivial to add a third target based on how open API is handled. Not personally interested in doing this but PRs are always welcome :)

marcesengel commented 1 year ago

Hi @jamauro, have you started work on this and are willing to share?

I'd be planning to probably pick this up soon, as @StefanTerdell stated he'd be open to adding it 👍

marcesengel commented 1 year ago

After digging around a little bit, it seems that zod-to-json-schema has pretty good typings for draft 7 output schemas. @StefanTerdell is it fine for you if I don't go into this depth for the mongo db "spec"?

jamauro commented 1 year ago

Hey @marcesengel, I haven't really started on it. I looked around a bit and then needed to shift focus to some other work. I'm still interested in having MongoDB support and happy to hear that you'll be picking it up!

marcesengel commented 1 year ago

After looking through the current implementation some more and starting an implementation I realised that there are three options to integrate support into the existing library

  1. Change the individual parsers to return different types based on the refs passed in (which contains the target) Would require a lot of changes and doesn't seem very clean per-se, as it'd mean a lot of checks like const schema = refs.target === 'mongodb' ? { jsonType: 'double' } : { type: 'number' } and would get worse with each new target introduced.
  2. Create a new set of parsers Would barely reuse anything while adding complexity in the option typings.
  3. Make changes in a post-processing step Not really clean (from a type-checking and code perspective) and would mean that new features for the draft 7 support can break the mongo support.

Because of this I've decided to instead create a separate package, as the overlap between draft 7 and the draft 4 support mongo db has really doesn't justify having both in one code-base.

marcesengel commented 1 year ago

@StefanTerdell here's some more information on the support MongoDB has so you can come to your own conclusions or make suggestions for an integration: https://www.mongodb.com/docs/manual/reference/operator/query/jsonSchema/#json-schema

TL;DR: Basically it's draft 4 with custom types (and the type field being called bsonType), and without

StefanTerdell commented 1 year ago

I think its fine to ignore specific typings for now, just like when you're using openAPI target. One solution to the "type" vs "bsonType" situation would be to store the key and typemap in the refs object and set them based on the target before running the parsers. In the parsers it would look something like this:

return {
  [refs.typeKey]: refs.typeMap.number,
}

With refs containing

{
  "target": "mongoDB",
  "typeKey": "bsonType",
  "typeMap": {
    "number": "double",
    "string": "string",
    ...
  },
  ...
}

As for the "dropped features", one could validate the passed options based on the target, so if you use "mongoDB" target with refStrategy "root" it would warn and switch to "none" etc.

But yeah, maybe just forking it into a new package is less of a headache in this case.

stramel commented 1 year ago

This is exactly what I'm looking for. Let me know if there is anything I can help with!

marcesengel commented 1 year ago

@stramel I've created a new package heavily inspired by zod-to-json-schema, see zod-to-mongodb-schema. At this point I just need to add more parsers to https://github.com/marcesengel/zod-to-mongodb-schema/blob/main/src/parseDef.ts#L39 and implement support for modifiers (i.e. optional()) + the test cases for each of those.

I'm aiming to finish this in the next three weeks, as we want to use it for some new features.

StefanTerdell commented 1 year ago

Awesome to see @marcesengel. I'll keep the issue open to direct traffic until this gains some traction, which I'm sure it will. Let me know if I can be of any use