From 285b6f44c149a9148d4fdf8149c36a4912ea2bc1 Mon Sep 17 00:00:00 2001 From: Aryaman Dhingra Date: Wed, 12 Jun 2024 16:25:51 -0400 Subject: [PATCH] feat: parse comment into jsdoc comment block and parse all fields DX-478 --- packages/openapi-generator/src/openapi.ts | 60 +++++++++---------- .../openapi-generator/test/openapi.test.ts | 14 +++-- 2 files changed, 35 insertions(+), 39 deletions(-) diff --git a/packages/openapi-generator/src/openapi.ts b/packages/openapi-generator/src/openapi.ts index 2bd0bb67..e061ae4e 100644 --- a/packages/openapi-generator/src/openapi.ts +++ b/packages/openapi-generator/src/openapi.ts @@ -5,6 +5,7 @@ import { parseCommentBlock } from './jsdoc'; import { optimize } from './optimize'; import type { Route } from './route'; import type { Schema } from './ir'; +import { Block } from 'comment-parser'; function schemaToOpenAPI( schema: Schema, @@ -158,33 +159,39 @@ function schemaToOpenAPI( return fieldValue === 'true'; } else if (schema.type === 'null') { return null; + } else if (schema.type === 'string') { + // Remove extraneous double quotes around the fieldValue + return fieldValue?.replace(/^"(.*)"$/, '$1'); } else { return fieldValue; } }; function buildDefaultOpenAPIObject(schema: Schema): OpenAPIV3.SchemaObject { - const defaultValue = getTagName(schema, 'default'); - const example = getTagName(schema, 'example'); - const maxLength = getTagName(schema, 'maxLength'); - const minLength = getTagName(schema, 'minLength'); - const pattern = getTagName(schema, 'pattern'); - const minimum = getTagName(schema, 'minimum'); - const maximum = getTagName(schema, 'maximum'); - const minItems = getTagName(schema, 'minItems'); - const maxItems = getTagName(schema, 'maxItems'); - const minProperties = getTagName(schema, 'minProperties'); - const maxProperties = getTagName(schema, 'maxProperties'); - const exclusiveMinimum = getTagName(schema, 'exclusiveMinimum'); - const exclusiveMaximum = getTagName(schema, 'exclusiveMaximum'); - const multipleOf = getTagName(schema, 'multipleOf'); - const uniqueItems = getTagName(schema, 'uniqueItems'); - const readOnly = getTagName(schema, 'readOnly'); - const writeOnly = getTagName(schema, 'writeOnly'); - const format = getTagName(schema, 'format'); - const title = getTagContent(schema, 'title'); + const emptyBlock: Block = { description: '', tags: [], source: [], problems: [] }; + const jsdoc = parseCommentBlock(schema.comment ?? emptyBlock); - const deprecated = schema.comment?.tags.find((t) => t.tag === 'deprecated'); + const defaultValue = jsdoc?.tags?.default; + const example = jsdoc?.tags?.example; + const maxLength = jsdoc?.tags?.maxLength; + const minLength = jsdoc?.tags?.minLength; + const pattern = jsdoc?.tags?.pattern; + const minimum = jsdoc?.tags?.minimum; + const maximum = jsdoc?.tags?.maximum; + const minItems = jsdoc?.tags?.minItems; + const maxItems = jsdoc?.tags?.maxItems; + const minProperties = jsdoc?.tags?.minProperties; + const maxProperties = jsdoc?.tags?.maxProperties; + const exclusiveMinimum = jsdoc?.tags?.exclusiveMinimum; + const exclusiveMaximum = jsdoc?.tags?.exclusiveMaximum; + const multipleOf = jsdoc?.tags?.multipleOf; + const uniqueItems = jsdoc?.tags?.uniqueItems; + const readOnly = jsdoc?.tags?.readOnly; + const writeOnly = jsdoc?.tags?.writeOnly; + const format = jsdoc?.tags?.format; + const title = jsdoc?.tags?.title; + + const deprecated = Object.keys(jsdoc?.tags || {}).includes('deprecated'); const description = schema.comment?.description; const defaultOpenAPIObject = { @@ -218,19 +225,6 @@ function schemaToOpenAPI( return openAPIObject; } -function getTagName(schema: Schema, tagName: String): string | undefined { - return schema.comment?.tags.find((t) => t.tag === tagName)?.name; -} - -function getTagContent(schema: Schema, tagName: String): string | undefined { - if (schema.comment === undefined) return undefined; - - const tag = schema.comment.tags.find((t) => t.tag === tagName); - if (tag === undefined) return undefined; - - return `${tag.name} ${tag.description}`.trim(); -} - function routeToOpenAPI(route: Route): [string, string, OpenAPIV3.OperationObject] { const jsdoc = route.comment !== undefined ? parseCommentBlock(route.comment) : {}; const operationId = jsdoc.tags?.operationId; diff --git a/packages/openapi-generator/test/openapi.test.ts b/packages/openapi-generator/test/openapi.test.ts index 5d137b6f..2ad41f4c 100644 --- a/packages/openapi-generator/test/openapi.test.ts +++ b/packages/openapi-generator/test/openapi.test.ts @@ -2054,7 +2054,7 @@ export const route = h.httpRoute({ query: { /** * This is a bar param. - * @example "{ 'foo': 'bar' }" + * @example { "foo": "bar" } */ bar: t.record(t.string, t.string), }, @@ -2103,7 +2103,9 @@ testCase('route with descriptions, patterns, and examples', ROUTE_WITH_DESCRIPTI required: true, schema: { type: 'object', - example: "{ 'foo': 'bar' }", + example: { + foo: 'bar' + }, additionalProperties: { type: 'string' } @@ -2204,7 +2206,7 @@ export const route = h.httpRoute({ body: { /** * This is a foo description. - * @example "BitGo Inc" + * @example BitGo Inc */ foo: Foo, bar: Bar, @@ -2349,8 +2351,8 @@ export const route = h.httpRoute({ * This is a foo description. * @minLength 5 * @maxLength 10 - * @example "SomeInc" - * @default "BitgoInc" + * @example SomeInc + * @default BitgoInc */ foo: t.string() }, @@ -2663,7 +2665,7 @@ export const route = h.httpRoute({ query: { /** * This is a foo description. - * @example "abc" + * @example abc * @pattern ^[a-z]+$ */ foo: h.optional(t.array(t.string))