Skip to content

Parse frontmatter in Zod descriptions#180

Open
phpnode wants to merge 1 commit into
anatine:mainfrom
seamapi:support-frontmatter-in-zod-descriptions
Open

Parse frontmatter in Zod descriptions#180
phpnode wants to merge 1 commit into
anatine:mainfrom
seamapi:support-frontmatter-in-zod-descriptions

Conversation

@phpnode

@phpnode phpnode commented Dec 27, 2023

Copy link
Copy Markdown

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.

@nx-cloud

nx-cloud Bot commented Dec 27, 2023

Copy link
Copy Markdown

☁️ 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
Copy Markdown
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
Copy Markdown
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

Brian-McBride commented Jan 18, 2024

Copy link
Copy Markdown
Contributor

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