diff --git a/package.json b/package.json index 4f5cc88..d7a7292 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "functional-models", - "version": "3.4.1", + "version": "3.5.1", "description": "Functional models is ooey gooey framework for building and using awesome models EVERYWHERE.", "main": "index.js", "types": "index.d.ts", diff --git a/src/lib.ts b/src/lib.ts index f5e8abe..897dff8 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -270,6 +270,9 @@ const createZodForProperty = } const _getZodForPropertyType = (pt: any) => { + if (myConfig.choices) { + return z.enum(myConfig.choices as any) + } switch (pt) { case 'UniqueId': return z.string() @@ -319,7 +322,20 @@ const createZodForProperty = ? s.default(myConfig.defaultValue) : s, s => (myConfig.required ? s : s.optional()), - s => (myConfig.description ? s.describe(myConfig.description) : s), + // Attach description for Zod consumers and OpenAPI generators. + s => { + if (myConfig.description) { + // zod's describe helps Zod introspection; some zod-openapi versions expect metadata via .meta or .openapi + // Use .describe and also attach .meta with openapi description if available. + if (typeof s.openapi === 'function') { + return s.openapi({ description: myConfig.description }) + } + return s.meta + ? s.meta({ description: myConfig.description }) + : s.describe(myConfig.description) + } + return s + }, ])(schemaFromChoices) return finalSchema as ZodType diff --git a/src/models.ts b/src/models.ts index c53e4f0..2b001c2 100644 --- a/src/models.ts +++ b/src/models.ts @@ -44,14 +44,28 @@ const _convertOptions = ( return r } +const _addDescription = ( + schema: ZodObject, + description?: string +) => { + if (!description) { + return schema + } + // @ts-ignore + if (typeof schema.openapi === 'function') { + // @ts-ignore + return schema.openapi({ description: description }) + } + return schema.meta + ? schema.meta({ description: description }) + : schema.describe(description) +} + const _createZod = ( modelDefinition: MinimalModelDefinition ): ZodObject => { if (modelDefinition.schema) { - if (modelDefinition.description) { - return modelDefinition.schema.describe(modelDefinition.description) - } - return modelDefinition.schema + return _addDescription(modelDefinition.schema, modelDefinition.description) } const properties = Object.entries(modelDefinition.properties).reduce( (acc, [key, property]) => { @@ -62,7 +76,8 @@ const _createZod = ( }, {} as Record ) - return z.object(properties) as ZodObject + const obj = z.object(properties) as ZodObject + return _addDescription(obj, modelDefinition.description) } const _toModelDefinition = ( diff --git a/test/src/lib.test.ts b/test/src/lib.test.ts index 13183ff..61bb9e7 100644 --- a/test/src/lib.test.ts +++ b/test/src/lib.test.ts @@ -6,7 +6,7 @@ import { createZodForProperty, } from '../../src/lib' import { ApiInfo, ApiMethod } from '../../src/index' -import z from 'zod' +import { z } from 'zod' describe('/src/lib.ts', () => { describe('#populateApiInformation', () => {