Skip to content

Commit

Permalink
OpenAPI3: emit all properties for unreferenced schemas (#2620)
Browse files Browse the repository at this point in the history
Fix #2571.

**BREAKING CHANGE**: Since the previous behavior was to emit
unreferenced schemas with Read visibility, this change can produce a
breaking change in Swagger if unreferenced schemas were previously
emitted that had write visibility properties stripped.
  • Loading branch information
tjprescott authored Nov 30, 2023
1 parent 9e167ad commit 52d0a8b
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@typespec/openapi3",
"comment": "Emitter will now emit all properties on unreferenced schemas.",
"type": "none"
}
],
"packageName": "@typespec/openapi3"
}
2 changes: 1 addition & 1 deletion packages/openapi3/src/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1295,7 +1295,7 @@ function createOAPIEmitter(
!paramModels.has(type) &&
!shouldInline(program, type)
) {
callSchemaEmitter(type, Visibility.Read);
callSchemaEmitter(type, Visibility.All);
}
};
const skipSubNamespaces = isGlobalNamespace(program, serviceNamespace);
Expand Down
3 changes: 2 additions & 1 deletion packages/openapi3/src/visibility-usage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ export function resolveVisibilityUsage(
const reachableTypes = new Set<Type>(usages.keys());

if (!omitUnreachableTypes) {
// Evaluate all unreferenced types and the types they reference with Visibility.All
const trackType = (type: Type) => {
if (!usages.has(type)) {
navigateReferencedTypes(type, Visibility.Read, (type, vis) =>
navigateReferencedTypes(type, Visibility.All, (type, vis) =>
trackUsageExact(usages, type, vis)
);
}
Expand Down
88 changes: 88 additions & 0 deletions packages/openapi3/test/metadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,94 @@ import { deepStrictEqual } from "assert";
import { openApiFor } from "./test-host.js";

describe("openapi3: metadata", () => {
it("will expose all properties on unreferenced models but filter properties on referenced models", async () => {
const res = await openApiFor(`
model M {
@visibility("read") r: string;
@visibility("create", "update") uc?: string;
@visibility("read", "create") rc?: string;
@visibility("read", "update", "create") ruc?: string;
}
`);

deepStrictEqual(res.components.schemas, {
M: {
type: "object",
properties: {
r: { type: "string", readOnly: true },
uc: { type: "string" },
rc: { type: "string" },
ruc: { type: "string" },
},
required: ["r"],
},
});
});

it("prioritizes read visibility when referenced and unreferenced models share schemas", async () => {
const res = await openApiFor(`
model Shared {
@visibility("create", "update") password: string;
prop: string;
}
model Unreferenced {
@visibility("read") r: string;
@visibility("create") c: string;
shared: Shared;
}
model Referenced {
@visibility("read") r: string;
@visibility("create") c: string;
shared: Shared;
}
@get op get(): Referenced;
`);

deepStrictEqual(res.components.schemas, {
Referenced: {
type: "object",
properties: {
r: { type: "string", readOnly: true },
shared: { $ref: "#/components/schemas/Shared" },
},
required: ["r", "shared"],
},
Shared: {
type: "object",
required: ["prop"],
properties: {
prop: {
type: "string",
},
},
},
SharedReadOrCreateOrUpdateOrDeleteOrQuery: {
type: "object",
required: ["password", "prop"],
properties: {
password: {
type: "string",
},
prop: {
type: "string",
},
},
},
Unreferenced: {
type: "object",
properties: {
c: { type: "string" },
r: { type: "string", readOnly: true },
shared: { $ref: "#/components/schemas/SharedReadOrCreateOrUpdateOrDeleteOrQuery" },
},
required: ["r", "c", "shared"],
},
});
});

it("will expose create visibility properties on PATCH model using @requestVisibility", async () => {
const res = await openApiFor(`
model M {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ components:
id:
type: string
readOnly: true
secret:
type: string
name:
type: string
test:
Expand All @@ -112,7 +114,7 @@ components:
relatives:
type: array
items:
$ref: '#/components/schemas/PersonRelative'
$ref: '#/components/schemas/PersonRelativeReadOrCreateOrUpdateOrDeleteOrQueryItem'
Person:
type: object
required:
Expand Down Expand Up @@ -174,6 +176,31 @@ components:
type: array
items:
$ref: '#/components/schemas/PersonRelativeCreateOrUpdateItem'
PersonReadOrCreateOrUpdateOrDeleteOrQueryItem:
type: object
required:
- id
- secret
- name
- test
- other
- relatives
properties:
id:
type: string
readOnly: true
secret:
type: string
name:
type: string
test:
type: string
other:
type: string
relatives:
type: array
items:
$ref: '#/components/schemas/PersonRelativeReadOrCreateOrUpdateOrDeleteOrQueryItem'
PersonRelative:
type: object
required:
Expand Down Expand Up @@ -204,6 +231,16 @@ components:
$ref: '#/components/schemas/PersonCreateOrUpdateItem'
relationship:
type: string
PersonRelativeReadOrCreateOrUpdateOrDeleteOrQueryItem:
type: object
required:
- person
- relationship
properties:
person:
$ref: '#/components/schemas/PersonReadOrCreateOrUpdateOrDeleteOrQueryItem'
relationship:
type: string
PersonRelativeUpdateItem:
type: object
required:
Expand Down

0 comments on commit 52d0a8b

Please sign in to comment.