Skip to content

Commit

Permalink
JSONSchema: improve internal pruneUndefinedFromPropertySignature to… (
Browse files Browse the repository at this point in the history
  • Loading branch information
gcanti authored Dec 10, 2024
1 parent 8d914e5 commit 8adcd7e
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 18 deletions.
34 changes: 20 additions & 14 deletions packages/effect/src/JSONSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,10 +334,24 @@ const getASTJsonSchemaAnnotations = (ast: AST.AST): JsonSchemaAnnotations => {
const pruneUndefinedFromPropertySignature = (ast: AST.AST): AST.AST | undefined => {
if (Option.isNone(AST.getJSONSchemaAnnotation(ast))) {
switch (ast._tag) {
case "UndefinedKeyword":
return AST.neverKeyword
case "Union": {
const types = ast.types.filter((type) => !AST.isUndefinedKeyword(type))
if (types.length < ast.types.length) {
return AST.Union.make(types, ast.annotations)
const types: Array<AST.AST> = []
let hasUndefined = false
for (const type of ast.types) {
const pruned = pruneUndefinedFromPropertySignature(type)
if (pruned) {
hasUndefined = true
if (!AST.isNeverKeyword(pruned)) {
types.push(pruned)
}
} else {
types.push(type)
}
}
if (hasUndefined) {
return AST.Union.make(types)
}
break
}
Expand Down Expand Up @@ -532,17 +546,9 @@ const go = (
const name = ps.name
if (Predicate.isString(name)) {
const pruned = pruneUndefinedFromPropertySignature(ps.type)
if (pruned) {
output.properties[name] = {
...go(pruned, $defs, true, path.concat(ps.name), options),
...getJsonSchemaAnnotations(ps.type),
...getJsonSchemaAnnotations(ps)
}
} else {
output.properties[name] = {
...go(ps.type, $defs, true, path.concat(ps.name), options),
...getJsonSchemaAnnotations(ps)
}
output.properties[name] = {
...go(pruned ?? ps.type, $defs, true, path.concat(ps.name), options),
...getJsonSchemaAnnotations(ps)
}
// ---------------------------------------------
// handle optional property signatures
Expand Down
65 changes: 61 additions & 4 deletions packages/effect/test/Schema/JSONSchema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,11 +288,11 @@ schema (UndefinedKeyword): undefined`

it("Struct with an unsupported field", () => {
expectError(
Schema.Struct({ a: Schema.Undefined }),
Schema.Struct({ a: Schema.SymbolFromSelf }),
`Missing annotation
at path: ["a"]
details: Generating a JSON Schema for this schema requires a "jsonSchema" annotation
schema (UndefinedKeyword): undefined`
schema (SymbolKeyword): symbol`
)
})

Expand Down Expand Up @@ -2943,6 +2943,63 @@ details: Cannot encode Symbol(effect/Schema/test/a) key to JSON Schema`
})

describe("Pruning `undefined` and make the property optional by default", () => {
it("Undefined", () => {
expectJsonSchemaAnnotations(
Schema.Struct({
a: Schema.Undefined
}),
{
"type": "object",
"required": [],
"properties": {
"a": {
"enum": [],
"title": "never"
}
},
"additionalProperties": false
}
)
})

it.skip("UndefinedOr(Undefined)", () => {
expectJsonSchemaAnnotations(
Schema.Struct({
a: Schema.UndefinedOr(Schema.Undefined)
}),
{
"type": "object",
"required": [],
"properties": {
"a": {
"enum": [],
"title": "never"
}
},
"additionalProperties": false
}
)
})

it("Nested `Undefined`s", () => {
expectJsonSchemaAnnotations(
Schema.Struct({
a: Schema.UndefinedOr(Schema.UndefinedOr(Schema.Undefined))
}),
{
"type": "object",
"required": [],
"properties": {
"a": {
"enum": [],
"title": "never"
}
},
"additionalProperties": false
}
)
})

it("Schema.optional", () => {
expectJsonSchemaAnnotations(
Schema.Struct({
Expand Down Expand Up @@ -3036,7 +3093,7 @@ details: Cannot encode Symbol(effect/Schema/test/a) key to JSON Schema`
)
})

it("UndefinedOr + annotation should override inner annotations", () => {
it("UndefinedOr + annotation should not override inner annotations", () => {
expectJsonSchemaAnnotations(
Schema.Struct({
a: Schema.UndefinedOr(Schema.String.annotations({ description: "inner" })).annotations({
Expand All @@ -3049,7 +3106,7 @@ details: Cannot encode Symbol(effect/Schema/test/a) key to JSON Schema`
"properties": {
"a": {
"type": "string",
"description": "middle"
"description": "inner"
}
},
"additionalProperties": false
Expand Down

0 comments on commit 8adcd7e

Please sign in to comment.