Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse frontmatter in Zod descriptions #180

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

phpnode
Copy link

@phpnode phpnode commented Dec 27, 2023

This PR adds support for parsing front-matter in Zod type descriptions. This allows us to propagate metadata from the description into the generated OpenAPI spec. For example:

const User = z.object({
  name: z.string().optional().describe(`
    ---
    title: Name
    deprecated: use fullName instead
    ---
    # Name
    The name of the thing.
  `),
   fullName: z.string()
})

becomes:

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "# Name\nThe name of the thing.",
      "deprecated": true,
      "x-title": "Name",
      "x-deprecated": "use fullName instead"
    },
    "fullName": {
      "type": "string"
    }
  },
  "required": ["fullName"]
}

Descriptions that don't include front matter are left intact.

Copy link

nx-cloud bot commented Dec 27, 2023

☁️ Nx Cloud Report

CI is running/has finished running commands for commit 6ab25f5. As they complete they will appear below. Click to see the status, the terminal output, and the build insights.

📂 See all runs for this CI Pipeline Execution


✅ Successfully ran 2 targets

Sent with 💌 from NxCloud.

@Brian-McBride
Copy link
Contributor

This is great, but it does add a large dependency on Front Matter.
I wonder if there is a way we can set up a plugin system to support additional parsing like this?
It seems heavy to add for the majority of users who are likely not using FrontMatter.

For example, you could just do:

const User = z.object({
  name: z.string().optional().describe(
    frontMatter(`
      ---
      title: Name
      deprecated: use fullName instead
      ---
      # Name
      The name of the thing.
    `)
  ),
   fullName: z.string()
})

That should give you the same result without adding the dependency to the full library.

@Brian-McBride
Copy link
Contributor

Oh, sorry, I didn't see you were mapping frontmatter results out inside your function.
That is more complicated, but you could probably create helper function to sit inside of the describe.

@Brian-McBride
Copy link
Contributor

Brian-McBride commented Jan 18, 2024

Maybe we can add in an optional parser function option in the generateSchema function?

LIke:

generateSchema(
  zodRef: OpenApiZodAny,
  useOutput?: boolean,
  optionalParsers?: {
    describeParser: (zodRef: OpenApiZodAny) => SchemaObject
  }
): SchemaObject

Then we can mod the base code similar to how you did.

return merge(baseSchema, describeParser?.(zodRef), ...schemas);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants