Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
f597c22
chore: migrates to scalar open types
baywet Oct 7, 2025
b7bc26d
draft: package migration for parser
baywet Oct 7, 2025
65b9d64
chore: migrates document import logic to new package
baywet Oct 10, 2025
da0374f
chore: removes old parser references
baywet Oct 10, 2025
72577c6
docs: adds the chronus entry for the dependencies replacement
baywet Oct 10, 2025
14d1870
Merge branch 'main' into chore/parser-migration
baywet Oct 10, 2025
1b344e8
Merge branch 'main' into chore/parser-migration
baywet Oct 16, 2025
56d8671
chore: updates scalar dependencies to latest
baywet Oct 16, 2025
5354e48
Merge branch 'main' into chore/parser-migration
baywet Oct 17, 2025
6693a29
chore: fixes specification loading
baywet Oct 20, 2025
81de872
Merge branch 'main' into chore/parser-migration
baywet Oct 20, 2025
93aa367
chore: linting no deprecated
baywet Oct 20, 2025
9dd13b4
chore: adds magic bundle dependency
baywet Oct 21, 2025
d0d0105
chore: updates from deprecated load method to bundle method
baywet Oct 21, 2025
5a3d285
Merge branch 'main' into chore/parser-migration
baywet Oct 27, 2025
baf11bc
chore: removes dereference to avoid inlining of schemas
baywet Oct 27, 2025
5e95c6b
linting: error message
baywet Oct 27, 2025
bc4e839
feat: adds new discriminator default mapping field
baywet Oct 27, 2025
de036c0
feat: add new OAS version in emitter options
baywet Oct 27, 2025
fd9b79c
docs: adds the chronus entry for OAI 3.2.0 support
baywet Oct 27, 2025
afeff75
feat: adds support for $self property in oai 3.2.0
baywet Oct 27, 2025
3fce7ef
feat: adds support for server name in OAS 3.2.0
baywet Oct 27, 2025
07ff406
feat: adds support for media type components in 3.2
baywet Oct 27, 2025
e8daf36
feat: adds response summary field for OAI 3.2.0
baywet Oct 27, 2025
996c1d4
Merge branch 'main' into feat/oai-3-2-emission
baywet Oct 28, 2025
7bdc156
chore: adds placehold for specs props
baywet Oct 28, 2025
142f6d1
tests: adds helper for OAI 3.2.0
baywet Oct 28, 2025
e8d1ec3
feat: adds support for OAI 3.2.0 security scheme deprecated field
baywet Oct 28, 2025
a8b6fc8
feat: adds support for device auth flow in OAI 3.2.0
baywet Oct 28, 2025
2fd692a
feat: adds support for OAI 3.2.0 example string and data value fields
baywet Oct 28, 2025
ce18be7
feat: adds support for xml new fields in OAI 3.2.0
baywet Oct 28, 2025
ddb8c23
tests: updates assertion to match new type information
baywet Oct 28, 2025
f1a6294
feat: adds support for query and additional operations in OAI 3.2.0
baywet Oct 28, 2025
683ca37
feat: adds support for query string parameter in OAI 3.2.0
baywet Oct 28, 2025
1c23a30
feat: adds new tag fields for OAI 3.2.0
baywet Oct 28, 2025
398e2e7
tests: aligns structure with updated types
baywet Oct 28, 2025
013b151
tests: further typing alignment
baywet Oct 28, 2025
93d3103
feat: adds support for cookie style parameter in OAI 3.2.0
baywet Oct 28, 2025
e92b9a6
fix: schema mapping for parameters import
baywet Oct 28, 2025
319310a
Merge branch 'main' into feat/oai-3-2-emission
baywet Oct 29, 2025
35df978
chore: aligns usage of 3.2.0 media type
baywet Oct 29, 2025
888f97e
chore: validate response and example 3.2 are referenced all the way up
baywet Oct 29, 2025
bb13531
chore: aligns schema references for OAI 3.2.0
baywet Oct 29, 2025
4d7cd09
feat: adds 3_2 types exports
baywet Oct 29, 2025
b274c74
fix: types misalignments
baywet Oct 29, 2025
374d2c4
docs: outdated 3.0 links
baywet Oct 29, 2025
5d28db6
docs: additional outdated links updates
baywet Oct 29, 2025
63377dd
fix: additional types misalignments corrections
baywet Oct 29, 2025
c36ce50
tests: adds unit tests for OAI 3.2.0 import
baywet Oct 29, 2025
9961466
tests: duplicates tests for 3.1.0 to 3.2.0
baywet Oct 29, 2025
154d157
fix: types misalignments
baywet Oct 29, 2025
31a3724
fix: more types misalignments
baywet Oct 29, 2025
6b4d429
Merge branch 'main' into feat/oai-3-2-emission
baywet Oct 30, 2025
217c869
feat: adds version 3.2.0 to the playground
baywet Oct 30, 2025
450f3eb
fix: regression explode true should be default for query parameters
baywet Oct 30, 2025
c24bf48
tests: updates test value with added description
baywet Oct 30, 2025
6760fc4
fix: regression for alias imports
baywet Oct 30, 2025
c27060b
chore: adds missing v2 http method export
baywet Oct 30, 2025
7cdc443
chore: removes http2 methods as requested during review
baywet Oct 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .chronus/changes/feat-oai-3-2-emission-2025-9-27-15-15-29.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
changeKind: feature
packages:
- "@typespec/openapi3"
---

added support for OpenAPI 3.2.0 emission
4 changes: 2 additions & 2 deletions packages/openapi3/src/cli/actions/convert/convert.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AnyObject, dereference } from "@scalar/openapi-parser";
import { formatTypeSpec } from "@typespec/compiler";
import { OpenAPI3Document } from "../../../types.js";
import { SupportedOpenAPIDocuments } from "../../../types.js";
import { generateMain } from "./generators/generate-main.js";
import { transform } from "./transforms/transforms.js";
import { createContext } from "./utils/context.js";
Expand All @@ -17,7 +17,7 @@ export interface ConvertOpenAPI3DocumentOptions {
}

export async function convertOpenAPI3Document(
document: OpenAPI3Document,
document: SupportedOpenAPIDocuments,
{ disableExternalRefs, namespace }: ConvertOpenAPI3DocumentOptions = {},
) {
const dereferenceOptions = disableExternalRefs
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { printIdentifier } from "@typespec/compiler";
import { OpenAPI3Encoding, OpenAPI3Schema, Refable } from "../../../../types.js";
import { OpenAPI3Encoding, Refable, SupportedOpenAPISchema } from "../../../../types.js";
import {
TypeSpecAlias,
TypeSpecDataTypes,
Expand Down Expand Up @@ -96,7 +96,7 @@ function generateUnion(union: TypeSpecUnion, context: Context): string {

const schema = union.schema;

const getVariantName = (member: Refable<OpenAPI3Schema>) => {
const getVariantName = (member: Refable<SupportedOpenAPISchema>) => {
if (union.schema.discriminator === undefined) {
return "";
}
Expand Down Expand Up @@ -159,7 +159,7 @@ function generateUnion(union: TypeSpecUnion, context: Context): string {
}
}

if (schema.nullable) {
if ("nullable" in schema && schema.nullable) {
definitions.push("null,");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,10 +359,10 @@ function convertHeaderToProperty(

return {
name: normalizedName,
decorators: [headerDecorator, ...getDecoratorsForSchema(header.schema)],
doc: props.header.description ?? header.description ?? header.schema.description,
decorators: [headerDecorator, ...(header.schema ? getDecoratorsForSchema(header.schema) : [])],
doc: props.header.description ?? header.description ?? header.schema?.description,
isOptional: !header.required,
schema: header.schema,
schema: header.schema ?? {},
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { printIdentifier } from "@typespec/compiler";
import {
OpenAPI3Encoding,
OpenAPI3Schema,
OpenAPI3SchemaProperty,
OpenAPISchema3_2,
Refable,
SupportedOpenAPISchema,
} from "../../../../types.js";
import { Context } from "../utils/context.js";
import {
Expand All @@ -17,7 +17,7 @@ export class SchemaToExpressionGenerator {
constructor(public rootNamespace: string) {}

public generateTypeFromRefableSchema(
schema: Refable<OpenAPI3Schema>,
schema: Refable<SupportedOpenAPISchema>,
callingScope: string[],
isHttpPart = false,
encoding?: Record<string, OpenAPI3Encoding>,
Expand All @@ -29,7 +29,7 @@ export class SchemaToExpressionGenerator {
: this.getTypeFromSchema(schema, callingScope, isHttpPart, encoding, context);
}

public generateArrayType(schema: OpenAPI3Schema, callingScope: string[]): string {
public generateArrayType(schema: SupportedOpenAPISchema, callingScope: string[]): string {
const items = schema.items;
if (!items) {
return "unknown[]";
Expand Down Expand Up @@ -85,7 +85,7 @@ export class SchemaToExpressionGenerator {
}

private getTypeFromSchema(
schema: OpenAPI3Schema,
schema: SupportedOpenAPISchema,
callingScope: string[],
isHttpPart = false,
encoding?: Record<string, OpenAPI3Encoding>,
Expand All @@ -103,7 +103,7 @@ export class SchemaToExpressionGenerator {
} else {
// Create a schema with a single type to reuse existing type extraction logic
// Remove type array, nullable, and default to avoid double-processing
const singleTypeSchema: OpenAPI3Schema = {
const singleTypeSchema: SupportedOpenAPISchema = {
...schema,
type: t as any,
nullable: undefined,
Expand Down Expand Up @@ -154,7 +154,7 @@ export class SchemaToExpressionGenerator {
type = this.generateArrayType(schema, callingScope);
}

if (schema.nullable) {
if ("nullable" in schema && schema.nullable) {
type += ` | null`;
}

Expand All @@ -170,7 +170,7 @@ export class SchemaToExpressionGenerator {
}

private generateDefaultValue(
schema: OpenAPI3Schema,
schema: SupportedOpenAPISchema,
callingScope: string[],
context?: Context,
): string | undefined {
Expand Down Expand Up @@ -224,9 +224,9 @@ export class SchemaToExpressionGenerator {
return undefined; // Return undefined to indicate no default found
}

private getAllOfType(schema: OpenAPI3Schema, callingScope: string[]): string {
private getAllOfType(schema: SupportedOpenAPISchema, callingScope: string[]): string {
const requiredProps: string[] = schema.required || [];
let properties: Record<string, Refable<OpenAPI3Schema>> = {};
let properties: Record<string, Refable<SupportedOpenAPISchema>> = {};
const baseTypes: string[] = [];

for (const member of schema.allOf || []) {
Expand Down Expand Up @@ -261,7 +261,9 @@ export class SchemaToExpressionGenerator {
}
}

private stripDefaultsFromSchema(schema: Refable<OpenAPI3Schema>): Refable<OpenAPI3Schema> {
private stripDefaultsFromSchema(
schema: Refable<SupportedOpenAPISchema>,
): Refable<SupportedOpenAPISchema> {
if ("$ref" in schema) {
return schema;
}
Expand All @@ -274,24 +276,31 @@ export class SchemaToExpressionGenerator {
strippedSchema.items = this.stripDefaultsFromSchema(strippedSchema.items);
}

// in the next blocks the casts are ugly but safe because the stripped schema is going to be the same as the original one
if (strippedSchema.anyOf) {
strippedSchema.anyOf = strippedSchema.anyOf.map((item) => this.stripDefaultsFromSchema(item));
strippedSchema.anyOf = strippedSchema.anyOf.map((item) =>
this.stripDefaultsFromSchema(item),
) as unknown as OpenAPISchema3_2[];
}

if (strippedSchema.oneOf) {
strippedSchema.oneOf = strippedSchema.oneOf.map((item) => this.stripDefaultsFromSchema(item));
strippedSchema.oneOf = strippedSchema.oneOf.map((item) =>
this.stripDefaultsFromSchema(item),
) as unknown as OpenAPISchema3_2[];
}

if (strippedSchema.allOf) {
strippedSchema.allOf = strippedSchema.allOf.map((item) => this.stripDefaultsFromSchema(item));
strippedSchema.allOf = strippedSchema.allOf.map((item) =>
this.stripDefaultsFromSchema(item),
) as unknown as OpenAPISchema3_2[];
}

if (strippedSchema.properties) {
const strippedProperties: Record<string, Refable<OpenAPI3Schema>> = {};
const strippedProperties: Record<string, Refable<SupportedOpenAPISchema>> = {};
for (const [key, prop] of Object.entries(strippedSchema.properties)) {
strippedProperties[key] = this.stripDefaultsFromSchema(prop);
}
strippedSchema.properties = strippedProperties;
strippedSchema.properties = strippedProperties as unknown as Record<string, OpenAPISchema3_2>;
}

if (
Expand All @@ -306,7 +315,7 @@ export class SchemaToExpressionGenerator {
return strippedSchema;
}

private getAnyOfType(schema: OpenAPI3Schema, callingScope: string[]): string {
private getAnyOfType(schema: SupportedOpenAPISchema, callingScope: string[]): string {
const definitions: string[] = [];

for (const item of schema.anyOf ?? []) {
Expand All @@ -318,7 +327,7 @@ export class SchemaToExpressionGenerator {
return definitions.join(" | ");
}

private getOneOfType(schema: OpenAPI3Schema, callingScope: string[]): string {
private getOneOfType(schema: SupportedOpenAPISchema, callingScope: string[]): string {
const definitions: string[] = [];

for (const item of schema.oneOf ?? []) {
Expand Down Expand Up @@ -408,7 +417,7 @@ export class SchemaToExpressionGenerator {
public static readonly decoratorNamesToExcludeForParts: string[] = ["minValue", "maxValue"];

private getObjectType(
schema: OpenAPI3Schema,
schema: SupportedOpenAPISchema,
callingScope: string[],
isHttpPart = false,
encoding?: Record<string, OpenAPI3Encoding>,
Expand Down Expand Up @@ -466,7 +475,7 @@ export class SchemaToExpressionGenerator {
}

export function isReferencedEnumType(
propSchema: OpenAPI3SchemaProperty,
propSchema: Refable<SupportedOpenAPISchema>,
context: Context,
): boolean {
let isEnumType = false;
Expand All @@ -486,7 +495,7 @@ export function isReferencedEnumType(
}

export function isReferencedUnionType(
propSchema: OpenAPI3SchemaProperty,
propSchema: Refable<SupportedOpenAPISchema>,
context: Context,
): boolean {
let isUnionType = false;
Expand All @@ -509,7 +518,7 @@ export function isReferencedUnionType(
return isUnionType;
}

export function getTypeSpecPrimitiveFromSchema(schema: OpenAPI3Schema): string | undefined {
export function getTypeSpecPrimitiveFromSchema(schema: SupportedOpenAPISchema): string | undefined {
if (schema.type === "boolean") {
return "boolean";
} else if ((schema as any).type === "null") {
Expand All @@ -524,7 +533,7 @@ export function getTypeSpecPrimitiveFromSchema(schema: OpenAPI3Schema): string |
return;
}

function getIntegerType(schema: OpenAPI3Schema): string {
function getIntegerType(schema: SupportedOpenAPISchema): string {
const format = schema.format ?? "";
switch (format) {
case "int8":
Expand All @@ -543,7 +552,7 @@ function getIntegerType(schema: OpenAPI3Schema): string {
}
}

function getNumberType(schema: OpenAPI3Schema): string {
function getNumberType(schema: SupportedOpenAPISchema): string {
const format = schema.format ?? "";
switch (format) {
case "decimal":
Expand All @@ -559,7 +568,7 @@ function getNumberType(schema: OpenAPI3Schema): string {
}
}

function getStringType(schema: OpenAPI3Schema): string {
function getStringType(schema: SupportedOpenAPISchema): string {
const format = schema.format ?? "";
let type = "string";
switch (format) {
Expand Down Expand Up @@ -588,6 +597,6 @@ function getStringType(schema: OpenAPI3Schema): string {
return type;
}

function getEnum(schemaEnum: (string | number | boolean)[]): string {
function getEnum(schemaEnum: (string | number | boolean | null)[]): string {
return schemaEnum.map((e) => JSON.stringify(e)).join(" | ");
}
23 changes: 14 additions & 9 deletions packages/openapi3/src/cli/actions/convert/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { Contact, License } from "@typespec/openapi";
import { OpenAPI3Encoding, OpenAPI3Responses, OpenAPI3Schema, Refable } from "../../../types.js";
import {
OpenAPI3Encoding,
OpenAPI3Responses,
Refable,
SupportedOpenAPISchema,
} from "../../../types.js";

export interface TypeSpecProgram {
serviceInfo: TypeSpecServiceInfo;
Expand Down Expand Up @@ -87,7 +92,7 @@ export interface TypeSpecModel extends TypeSpecDeclaration {
kind: "model";

properties: TypeSpecModelProperty[];
additionalProperties?: Refable<OpenAPI3Schema>;
additionalProperties?: Refable<SupportedOpenAPISchema>;
/**
* Note: Only one of `extends` or `is` should be specified.
*/
Expand All @@ -99,7 +104,7 @@ export interface TypeSpecModel extends TypeSpecDeclaration {
/**
* Defaults to 'object'
*/
type?: OpenAPI3Schema["type"];
type?: SupportedOpenAPISchema["type"];

spread?: string[];

Expand All @@ -120,17 +125,17 @@ export interface TypeSpecAlias extends Pick<TypeSpecDeclaration, "name" | "doc"

export interface TypeSpecEnum extends TypeSpecDeclaration {
kind: "enum";
schema: OpenAPI3Schema;
schema: SupportedOpenAPISchema;
}

export interface TypeSpecUnion extends TypeSpecDeclaration {
kind: "union";
schema: OpenAPI3Schema;
schema: SupportedOpenAPISchema;
}

export interface TypeSpecScalar extends TypeSpecDeclaration {
kind: "scalar";
schema: OpenAPI3Schema;
schema: SupportedOpenAPISchema;
}

export interface TypeSpecModelProperty {
Expand All @@ -143,7 +148,7 @@ export interface TypeSpecModelProperty {
* Example: location decorators for parameters
*/
decorators: TypeSpecDecorator[];
schema: Refable<OpenAPI3Schema>;
schema: Refable<SupportedOpenAPISchema>;
}

export interface TypeSpecOperation extends TypeSpecDeclaration {
Expand All @@ -160,13 +165,13 @@ export interface TypeSpecOperationParameter {
doc?: string;
decorators: TypeSpecDecorator[];
isOptional: boolean;
schema: Refable<OpenAPI3Schema>;
schema: Refable<SupportedOpenAPISchema>;
}

export interface TypeSpecRequestBody {
contentType: string;
doc?: string;
isOptional: boolean;
encoding?: Record<string, OpenAPI3Encoding>;
schema?: Refable<OpenAPI3Schema>;
schema?: Refable<SupportedOpenAPISchema>;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { printIdentifier } from "@typespec/compiler";
import { OpenAPI3Parameter } from "../../../../types.js";
import { OpenAPI3Parameter, OpenAPIParameter3_2 } from "../../../../types.js";
import { TypeSpecDataTypes, TypeSpecModelProperty } from "../interfaces.js";
import { Context } from "../utils/context.js";
import { getParameterDecorators } from "../utils/decorators.js";
Expand All @@ -22,14 +22,15 @@ export function transformComponentParameters(

for (const name of Object.keys(parameters)) {
const parameter = parameters[name];
if ("$ref" in parameter) continue;
transformComponentParameter(dataTypes, name, parameter);
}
}

function transformComponentParameter(
dataTypes: TypeSpecDataTypes[],
key: string,
parameter: OpenAPI3Parameter,
parameter: OpenAPI3Parameter | OpenAPIParameter3_2,
): void {
const { name, scope } = getScopeAndName(key);
// Parameters should live in the root Parameters namespace
Expand All @@ -44,12 +45,15 @@ function transformComponentParameter(
});
}

function getModelPropertyFromParameter(parameter: OpenAPI3Parameter): TypeSpecModelProperty {
function getModelPropertyFromParameter(
parameter: OpenAPI3Parameter | OpenAPIParameter3_2,
): TypeSpecModelProperty {
const parameterSchema = "schema" in parameter ? (parameter.schema ?? {}) : {};
return {
name: printIdentifier(parameter.name),
isOptional: !parameter.required,
doc: parameter.description ?? parameter.schema.description,
doc: parameter.description ?? parameterSchema.description,
decorators: getParameterDecorators(parameter),
schema: parameter.schema,
schema: parameterSchema,
};
}
Loading
Loading