anatine / zod-plugins

Plugins and utilities for Zod
661 stars 93 forks source link

[zod-mock] Provide hints to better determine Faker type #134

Open ispringle opened 1 year ago

ispringle commented 1 year ago

I'm interested in using zod-mock to generate mock data. We use JSDocs at work for typing and are looking to document the JSON our apps consume with Zod and then infer the JSDoc typing for those endpoints. Ideally I'd like to define the API in Zod and then automatically get Faker data for mocking (currently our mock data is generated with the standard facker-js API directly).

The problem with using zod-mock currently is that it the zod -> faker is not robust enough. If my object keys do not match the names decided by faker-js than I do not get the rich data I'm looking for.

The ts-to-zod package (which also has support for jsdoc to zod) allows you to provide some hinting in the TS/JSDoc definition to ensure you end up with the proper Zod type. For example you can use @format email on a string type to ensure that Zod treats that string as an email string. I'm wondering if it'd be at all possible to do something similar so that for zod-mock, such that I can annotate my zod schemas with JSDoc tags to provide hinting. For example if I my API is sending a phone property on an object I could do:

const Contact = z.object({
  /**
   * @faker phone.number
   */
  phone: z.string(),

Normally I'd need to use transform to rename that phone property to something that zod-mock understands (phoneNumber). But if there was a way to provide hints similar to JSDoc annotation then I could let me object keys remain whatever I or the API devs desire and then just specify to zod-mock how to treat it.

Brian-McBride commented 1 year ago

I'm totally open to an idea or PR to make it easier.

I have noticed the changes in Faker have also made it harder to map. That is partly why there is a string map option in there.

const mockData = generateMock(schema, {
  stringMap: {
    locked: () => `this return set to the locked value`,
    email: () => `not a email anymore`,
    primaryColor: () => faker.internet.color(),
  },
});

It isn't nearly as nice. But if your company has common keys and expected values, you could create yourself a common map that you share across projects. It isn't as ideal as finding the best match.

ispringle commented 1 year ago

I've been playing with the jsdocs syntax a little and have been able to define a set of non-standard annotations. I'll see about actually fetching and iterating over that, but if/when I get that figured out I think it might be pretty trivial to take those hints and generate the stringMap programmatically. I'll keep you posted.