Skip to content

Commit

Permalink
Default values supporting scalar and object (#4423)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlitzelMendez authored Sep 17, 2024
1 parent 448a492 commit 9a28a9c
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
changeKind: feature
packages:
- "@typespec/openapi3"
---

Added support to use Scalar and Object as default types
6 changes: 0 additions & 6 deletions packages/openapi3/src/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,12 +239,6 @@ export const libDef = {
default: "Enums are not supported unless all options are literals of the same type.",
},
},
"invalid-default": {
severity: "error",
messages: {
default: paramMessage`Invalid type '${"type"}' for a default value`,
},
},
"inline-cycle": {
severity: "error",
messages: {
Expand Down
4 changes: 2 additions & 2 deletions packages/openapi3/src/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ function createOAPIEmitter(
}

const variable: OpenAPI3ServerVariable = {
default: prop.defaultValue ? getDefaultValue(program, prop.defaultValue) : "",
default: prop.defaultValue ? getDefaultValue(program, prop.defaultValue, prop) : "",
description: getDoc(program, prop),
};

Expand Down Expand Up @@ -1371,7 +1371,7 @@ function createOAPIEmitter(
options,
);
if (param.defaultValue) {
schema.default = getDefaultValue(program, param.defaultValue);
schema.default = getDefaultValue(program, param.defaultValue, param);
}
// Description is already provided in the parameter itself.
delete schema.description;
Expand Down
29 changes: 7 additions & 22 deletions packages/openapi3/src/schema-emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ export class OpenAPI3SchemaEmitter extends TypeEmitter<
// Apply decorators on the property to the type's schema
const additionalProps: Partial<OpenAPI3Schema> = this.#applyConstraints(prop, {});
if (prop.defaultValue) {
additionalProps.default = getDefaultValue(program, prop.defaultValue);
additionalProps.default = getDefaultValue(program, prop.defaultValue, prop);
}

if (isReadonlyProperty(program, prop)) {
Expand Down Expand Up @@ -922,27 +922,12 @@ const B = {
},
} as const;

export function getDefaultValue(program: Program, defaultType: Value): any {
switch (defaultType.valueKind) {
case "StringValue":
return defaultType.value;
case "NumericValue":
return defaultType.value.asNumber() ?? undefined;
case "BooleanValue":
return defaultType.value;
case "ArrayValue":
return defaultType.values.map((x) => getDefaultValue(program, x));
case "NullValue":
return null;
case "EnumValue":
return defaultType.value.value ?? defaultType.value.name;
default:
reportDiagnostic(program, {
code: "invalid-default",
format: { type: defaultType.valueKind },
target: defaultType,
});
}
export function getDefaultValue(
program: Program,
defaultType: Value,
modelProperty: ModelProperty,
): any {
return serializeValueAsJson(program, defaultType, modelProperty);
}

export function isBytesKeptRaw(program: Program, type: Type) {
Expand Down
35 changes: 35 additions & 0 deletions packages/openapi3/test/models.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,41 @@ describe("openapi3: models", () => {
});
});

it("scalar used as a default value", async () => {
const res = await oapiForModel(
"Pet",
`
scalar shortName { init name(value: string);}
model Pet { name: shortName = shortName.name("Shorty"); }
`,
);

expect(res.schemas.Pet.properties.name.default).toEqual("Shorty");
});

it("encode know scalar as a default value", async () => {
const res = await oapiForModel(
"Test",
`
model Test { @encode("rfc7231") minDate: utcDateTime = utcDateTime.fromISO("2024-01-01T11:32:00Z"); }
`,
);

expect(res.schemas.Test.properties.minDate.default).toEqual("Mon, 01 Jan 2024 11:32:00 GMT");
});

it("object value used as a default value", async () => {
const res = await oapiForModel(
"Test",
`
model Test { Pet: {name: string;} = #{ name: "Dog"}; }
`,
);

expect(res.schemas.Test.properties.Pet.default.name).toEqual("Dog");
});

describe("numeric defaults", () => {
it.each([
["0.01", 0.01],
Expand Down

0 comments on commit 9a28a9c

Please sign in to comment.