Skip to content

Commit

Permalink
[Bugfix] Fix complex intersections of allOf/anyOf/properties/required (
Browse files Browse the repository at this point in the history
…fix #381)
  • Loading branch information
bcherny committed Jan 21, 2024
1 parent 6adcad9 commit c80e0ae
Show file tree
Hide file tree
Showing 8 changed files with 1,339 additions and 101 deletions.
14 changes: 14 additions & 0 deletions src/normalizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,20 @@ rules.set('Transform const to singleton enum', schema => {
}
})

// @see https://json-schema.org/understanding-json-schema/reference/combining#factoring-schemas
rules.set('Propagate additionalProperties=false to all factors', schema => {
const parent = schema[Parent]
if (!parent || parent.additionalProperties !== false) {
return
}

if (schema.hasOwnProperty('additionalProperties')) {
return
}

schema.additionalProperties = false
})

export function normalize(
rootSchema: LinkedJSONSchema,
dereferencedPaths: DereferencedPaths,
Expand Down
10 changes: 8 additions & 2 deletions src/typesOfSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,14 @@ const matchers: Record<SchemaType, (schema: JSONSchema) => boolean> = {
}
return 'enum' in schema
},
UNNAMED_SCHEMA() {
return false // Explicitly handled as the default case
UNNAMED_SCHEMA(schema) {
return Boolean(
!('$id' in schema) &&
(schema.patternProperties?.length ||
schema.properties?.length ||
// TODO: fix the typing
(schema.required as string[])?.length),
)
},
UNTYPED_ARRAY(schema) {
return schema.type === 'array' && !('items' in schema)
Expand Down
1,364 changes: 1,266 additions & 98 deletions test/__snapshots__/test/test.ts.md

Large diffs are not rendered by default.

Binary file modified test/__snapshots__/test/test.ts.snap
Binary file not shown.
15 changes: 15 additions & 0 deletions test/e2e/allOf.properties.1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const input = {
type: 'object',
properties: {
a: {type: 'string'},
b: {type: 'string'},
c: {type: 'string'},
},
allOf: [
{required: ['a']},
{
oneOf: [{required: ['b']}, {required: ['c']}],
},
],
additionalProperties: false,
}
14 changes: 14 additions & 0 deletions test/e2e/allOf.properties.2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const input = {
type: 'object',
properties: {
a: {type: 'string'},
b: {type: 'string'},
c: {type: 'string'},
},
allOf: [
{required: ['a']},
{
oneOf: [{required: ['b']}, {required: ['c']}],
},
],
}
21 changes: 21 additions & 0 deletions test/e2e/allOf.properties.3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export const input = {
type: 'object',
properties: {
a: {type: 'string'},
b: {type: 'string'},
c: {type: 'string'},
},
allOf: [
{required: ['a']},
{
oneOf: [
{required: ['b']},
// Non-existent property is invalid, but it's not up to JSTT to validate this
// "An object instance is valid against this keyword if every
// item in the array is the name of a property in the instance."
// @see https://json-schema.org/draft/2020-12/json-schema-validation#name-required
{required: ['d']},
],
},
],
}
2 changes: 1 addition & 1 deletion test/e2e/allOf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const input = {
a: {type: 'string'},
},
additionalProperties: false,
required: ['a', 'b'],
required: ['a'],
},
},
required: ['foo', 'bar'],
Expand Down

0 comments on commit c80e0ae

Please sign in to comment.