Fix array docs not showing up in openapi emitter (#2004)
This commit is contained in:
Родитель
afd531aa2b
Коммит
d53a6f2b2a
|
@ -7,7 +7,7 @@
|
|||
},
|
||||
{
|
||||
"packageName": "@typespec/compiler",
|
||||
"comment": "**DEPRECATION** `object` is deprecated. Alternative is to use `{}` for an empty model, `Record<unknown>` for a record with unknown propertie types, `unknown[]` for an array.",
|
||||
"comment": "**DEPRECATION** `object` is deprecated. Alternative is to use `{}` for an empty model, `Record<unknown>` for a record with unknown property types, `unknown[]` for an array.",
|
||||
"type": "none"
|
||||
}
|
||||
],
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@typespec/compiler",
|
||||
"comment": "Mark `Array` and `Record` doc comment as for dev only",
|
||||
"type": "none"
|
||||
}
|
||||
],
|
||||
"packageName": "@typespec/compiler"
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@typespec/openapi3",
|
||||
"comment": "Fix: Documentation on `model is x[]` was not included in schema description",
|
||||
"type": "none"
|
||||
}
|
||||
],
|
||||
"packageName": "@typespec/openapi3"
|
||||
}
|
|
@ -5307,7 +5307,8 @@ function extractMainDoc(type: Type): string | undefined {
|
|||
for (const doc of type.node.docs) {
|
||||
mainDoc += getDocContent(doc.content);
|
||||
}
|
||||
return mainDoc;
|
||||
const trimmed = mainDoc.trim();
|
||||
return trimmed === "" ? undefined : trimmed;
|
||||
}
|
||||
|
||||
function extractParamDoc(node: OperationStatementNode, paramName: string): string | undefined {
|
||||
|
|
|
@ -124,18 +124,18 @@ scalar boolean;
|
|||
* Represent a model
|
||||
*/
|
||||
// Deprecated June 2023 sprint
|
||||
@deprecated("object is deprecated. Please use {} for an empty model, `Record<unknown>` for a record with unknown propertie types, `unknown[]` for an array.")
|
||||
@deprecated("object is deprecated. Please use {} for an empty model, `Record<unknown>` for a record with unknown property types, `unknown[]` for an array.")
|
||||
model object {}
|
||||
|
||||
/**
|
||||
* Array model type, equivalent to `T[]`
|
||||
* @dev Array model type, equivalent to `T[]`
|
||||
* @template T The type of the array elements
|
||||
*/
|
||||
@indexer(integer, T)
|
||||
model Array<T> {}
|
||||
|
||||
/**
|
||||
* Model with string properties where all the properties have type `T`
|
||||
* @dev Model with string properties where all the properties have type `T`
|
||||
* @template T The type of the properties
|
||||
*/
|
||||
@indexer(string, T)
|
||||
|
|
|
@ -887,7 +887,7 @@ function createOAPIEmitter(program: Program, options: ResolvedOpenAPI3EmitterOpt
|
|||
|
||||
if (type.kind === "String" || type.kind === "Number" || type.kind === "Boolean") {
|
||||
// For literal types, we just want to emit them directly as well.
|
||||
return mapTypeSpecTypeToOpenAPI(type, visibility);
|
||||
return getSchemaForLiterals(type);
|
||||
}
|
||||
|
||||
if (type.kind === "Intrinsic" && type.name === "unknown") {
|
||||
|
@ -1251,7 +1251,7 @@ function createOAPIEmitter(program: Program, options: ResolvedOpenAPI3EmitterOpt
|
|||
}
|
||||
|
||||
function getSchemaForType(type: Type, visibility: Visibility): OpenAPI3Schema | undefined {
|
||||
const builtinType = mapTypeSpecTypeToOpenAPI(type, visibility);
|
||||
const builtinType = getSchemaForLiterals(type);
|
||||
if (builtinType !== undefined) return builtinType;
|
||||
|
||||
switch (type.kind) {
|
||||
|
@ -1364,7 +1364,7 @@ function createOAPIEmitter(program: Program, options: ResolvedOpenAPI3EmitterOpt
|
|||
|
||||
if (isLiteralType(variant.type)) {
|
||||
if (!literalVariantEnumByType[variant.type.kind]) {
|
||||
const enumSchema = mapTypeSpecTypeToOpenAPI(variant.type, visibility);
|
||||
const enumSchema = getSchemaForLiterals(variant.type);
|
||||
literalVariantEnumByType[variant.type.kind] = enumSchema;
|
||||
schemaMembers.push({ schema: enumSchema, type: null });
|
||||
} else {
|
||||
|
@ -1502,6 +1502,13 @@ function createOAPIEmitter(program: Program, options: ResolvedOpenAPI3EmitterOpt
|
|||
}
|
||||
|
||||
function getSchemaForModel(model: Model, visibility: Visibility) {
|
||||
const arrayOrRecord = mapTypeSpecIntrinsicModelToOpenAPI(model, visibility);
|
||||
if (arrayOrRecord) {
|
||||
const arrayDoc = getDoc(program, model);
|
||||
arrayOrRecord.description = arrayDoc;
|
||||
return arrayOrRecord;
|
||||
}
|
||||
|
||||
let modelSchema: OpenAPI3Schema & Required<Pick<OpenAPI3Schema, "properties">> = {
|
||||
type: "object",
|
||||
properties: {},
|
||||
|
@ -1772,7 +1779,11 @@ function createOAPIEmitter(program: Program, options: ResolvedOpenAPI3EmitterOpt
|
|||
|
||||
// Map an TypeSpec type to an OA schema. Returns undefined when the resulting
|
||||
// OA schema is just a regular object schema.
|
||||
function mapTypeSpecTypeToOpenAPI(typespecType: Type, visibility: Visibility): any {
|
||||
function getSchemaForLiterals(
|
||||
typespecType: NumericLiteral | StringLiteral | BooleanLiteral
|
||||
): OpenAPI3Schema;
|
||||
function getSchemaForLiterals(typespecType: Type): OpenAPI3Schema | undefined;
|
||||
function getSchemaForLiterals(typespecType: Type): OpenAPI3Schema | undefined {
|
||||
switch (typespecType.kind) {
|
||||
case "Number":
|
||||
return { type: "number", enum: [typespecType.value] };
|
||||
|
@ -1780,8 +1791,8 @@ function createOAPIEmitter(program: Program, options: ResolvedOpenAPI3EmitterOpt
|
|||
return { type: "string", enum: [typespecType.value] };
|
||||
case "Boolean":
|
||||
return { type: "boolean", enum: [typespecType.value] };
|
||||
case "Model":
|
||||
return mapTypeSpecIntrinsicModelToOpenAPI(typespecType, visibility);
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1836,7 +1847,7 @@ function createOAPIEmitter(program: Program, options: ResolvedOpenAPI3EmitterOpt
|
|||
function mapTypeSpecIntrinsicModelToOpenAPI(
|
||||
typespecType: Model,
|
||||
visibility: Visibility
|
||||
): any | undefined {
|
||||
): OpenAPI3Schema | undefined {
|
||||
if (typespecType.indexer) {
|
||||
if (isNeverType(typespecType.indexer.key)) {
|
||||
} else {
|
||||
|
@ -1854,6 +1865,7 @@ function createOAPIEmitter(program: Program, options: ResolvedOpenAPI3EmitterOpt
|
|||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getSchemaForScalar(scalar: Scalar): OpenAPI3Schema {
|
||||
|
|
|
@ -431,7 +431,7 @@ export type OpenAPI3Schema = Extensions & {
|
|||
*
|
||||
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.23
|
||||
*/
|
||||
enum?: string[];
|
||||
enum?: (string | number | boolean)[];
|
||||
|
||||
/** the JSON type for the schema */
|
||||
type?: JsonType;
|
||||
|
|
|
@ -37,6 +37,18 @@ describe("openapi3: Array", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("named array applies doc", async () => {
|
||||
const res = await oapiForModel(
|
||||
"Pet",
|
||||
`
|
||||
@doc("This is a doc for PetNames")
|
||||
model PetNames is string[] {}
|
||||
model Pet { names: PetNames };
|
||||
`
|
||||
);
|
||||
deepStrictEqual(res.schemas.PetNames.description, "This is a doc for PetNames");
|
||||
});
|
||||
|
||||
it("can specify minItems using @minItems decorator", async () => {
|
||||
const res = await oapiForModel(
|
||||
"Pet",
|
||||
|
|
|
@ -355,8 +355,8 @@ components:
|
|||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Book'
|
||||
x-typespec-name: Book[]
|
||||
description: The list of books.
|
||||
x-typespec-name: Book[]
|
||||
next_page_token:
|
||||
type: string
|
||||
description: >-
|
||||
|
@ -396,8 +396,8 @@ components:
|
|||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Shelf'
|
||||
x-typespec-name: Shelf[]
|
||||
description: The list of shelves.
|
||||
x-typespec-name: Shelf[]
|
||||
next_page_token:
|
||||
type: string
|
||||
description: >-
|
||||
|
|
|
@ -603,8 +603,8 @@ components:
|
|||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Checkup'
|
||||
x-typespec-name: Checkup[]
|
||||
description: The items on this page
|
||||
x-typespec-name: Checkup[]
|
||||
nextLink:
|
||||
type: string
|
||||
format: uri
|
||||
|
@ -670,8 +670,8 @@ components:
|
|||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Owner'
|
||||
x-typespec-name: Owner[]
|
||||
description: The items on this page
|
||||
x-typespec-name: Owner[]
|
||||
nextLink:
|
||||
type: string
|
||||
format: uri
|
||||
|
@ -731,8 +731,8 @@ components:
|
|||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Pet'
|
||||
x-typespec-name: Pet[]
|
||||
description: The items on this page
|
||||
x-typespec-name: Pet[]
|
||||
nextLink:
|
||||
type: string
|
||||
format: uri
|
||||
|
@ -810,8 +810,8 @@ components:
|
|||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Toy'
|
||||
x-typespec-name: Toy[]
|
||||
description: The items on this page
|
||||
x-typespec-name: Toy[]
|
||||
nextLink:
|
||||
type: string
|
||||
format: uri
|
||||
|
|
Загрузка…
Ссылка в новой задаче