-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support constraints! #76
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Schema support | ||
|
||
The `Schema` object in [Open API v3 spec][oaschema] describes several properties | ||
that are shared from JSON Schema, deviations from JSON Schema, or in addition | ||
to JSON Schema. The document descibes this project's support for these | ||
properties. | ||
|
||
## Properties | ||
|
||
The following properties are supported, and implemented according to the | ||
[JSON Schema Validation spec][jsschema]: | ||
|
||
- [x] multipleOf | ||
- [x] maximum | ||
- [x] exclusiveMaximum | ||
- [x] minimum | ||
- [x] exclusiveMinimum | ||
- [x] maxLength | ||
- [x] minLength | ||
- [x] pattern | ||
- [x] maxItems | ||
- [x] minItems | ||
- [x] uniqueItems | ||
- [x] maxProperties | ||
- [x] minProperties | ||
- [x] format | ||
- [x] required | ||
- [x] enum | ||
|
||
## Adjusted JSON Schema Properties | ||
|
||
The OpenAPI specification also supports several additional properties from JSON | ||
Schema, with some adjustments. This project attempts to honor these adjustments, | ||
with any exceptions outlined below: | ||
|
||
- [x] type - Value may be an array, multiple types are supported. | ||
- [x] allOf | ||
- [ ] oneOf | ||
- [ ] anyOf | ||
- [ ] not | ||
- [x] items | ||
- [x] properties | ||
- [ ] additionalProperties | ||
- [x] description | ||
- [x] format | ||
- [x] default | ||
|
||
## Fixed Fields | ||
|
||
At this time, the project supports no [fixed fields][ff]. | ||
|
||
[ff]: https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.md#fixed-fields-20 | ||
[jsschema]: http://json-schema.org/latest/json-schema-validation.html#rfc.section.6 | ||
[oaschema]: https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.md#schemaObject |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import React, { PureComponent } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
export default class ArrayProperty extends PureComponent { | ||
render() { | ||
const { constraints } = this.props; | ||
|
||
if (!constraints) { | ||
return null; | ||
} | ||
|
||
const { minItems, maxItems, uniqueItems } = constraints; | ||
const validations = []; | ||
|
||
if (uniqueItems) { | ||
validations.push('items must be unique'); | ||
} | ||
|
||
if (maxItems !== undefined && minItems !== undefined) { | ||
// Be succint if the minItems is the same maxItems | ||
// ie. value can only be of `x` length. | ||
if (maxItems === minItems) { | ||
validations.push(`${minItems} items`); | ||
} else { | ||
validations.push(`${minItems}-${maxItems} items`); | ||
} | ||
} else if (minItems !== undefined) { | ||
validations.push(`at least ${minItems} items`); | ||
} else if (maxItems !== undefined) { | ||
validations.push(`at most ${maxItems} items`); | ||
} | ||
|
||
if (!validations.length) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<span> | ||
{validations.map(constraint => | ||
<span key={constraint} className="array-constraints">{constraint}</span> | ||
)} | ||
</span> | ||
); | ||
} | ||
} | ||
|
||
ArrayProperty.propTypes = { | ||
constraints: PropTypes.shape({ | ||
maxItems: PropTypes.number, | ||
minItems: PropTypes.number, | ||
uniqueItems: PropTypes.bool | ||
}) | ||
}; | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import React, { PureComponent } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
export default class NumericProperty extends PureComponent { | ||
render() { | ||
const { constraints } = this.props; | ||
|
||
if (!constraints) { | ||
return null; | ||
} | ||
|
||
const { exclusiveMinimum, exclusiveMaximum, maximum, minimum, multipleOf } = constraints; | ||
const validations = []; | ||
|
||
if (multipleOf) { | ||
validations.push(`multiple of ${multipleOf}`); | ||
} | ||
|
||
// We're following JSON-Schema Draft 6, which states that exclusive* are | ||
// integers, not boolean values. Also using `undefined` to prevent edge | ||
// cases where the value is 0 or 1. | ||
if (maximum !== undefined && minimum !== undefined) { | ||
validations.push(`${minimum}…${maximum}`); | ||
} else if (exclusiveMaximum !== undefined && exclusiveMinimum !== undefined) { | ||
validations.push(`${exclusiveMinimum}…${exclusiveMaximum}`); | ||
} else if (minimum !== undefined) { | ||
validations.push(`≥ ${minimum}`); | ||
} else if (maximum !== undefined) { | ||
validations.push(`≤ ${maximum}`); | ||
} else if (exclusiveMinimum !== undefined) { | ||
validations.push(`> ${exclusiveMinimum}`); | ||
} else if (exclusiveMaximum !== undefined) { | ||
validations.push(`< ${exclusiveMaximum}`); | ||
} | ||
|
||
if (!validations.length) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<span> | ||
{validations.map(constraint => | ||
<span key={constraint} className="numeric-constraints">{constraint}</span> | ||
)} | ||
</span> | ||
); | ||
} | ||
} | ||
|
||
NumericProperty.propTypes = { | ||
constraints: PropTypes.shape({ | ||
exclusiveMinimum: PropTypes.number, | ||
exclusiveMaximum: PropTypes.number, | ||
maximum: PropTypes.number, | ||
minimum: PropTypes.number, | ||
multipleOf: PropTypes.number | ||
}) | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like the construction of the constraints in those new constraints components could be extracted out, which would make the logic a bit easier to test (and those components could potentially go away??? We can then have a shared There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't agree sorry. I considered having one component be responsible for constraints, but ultimately it would still have switch logic in it to only apply certain constraints to certain components. Having small (tiny even!) components that just focus on all things I'm happy to dumb down the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I totally agreed with you about the approach of having multiple small components. My point was that all those constraints UI components share the same pattern:
So they only differ in the way If we move the validation logic out (as we try to keep the UI components really lean), to seperate functions, then there are no difference between those UI constraint components. React components offer There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah got you, I have an idea, let me come back to you... |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import React, { PureComponent } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
export default class ObjectProperty extends PureComponent { | ||
render() { | ||
const { constraints } = this.props; | ||
|
||
if (!constraints) { | ||
return null; | ||
} | ||
|
||
const { minProperties, maxProperties } = constraints; | ||
const validations = []; | ||
|
||
if (maxProperties !== undefined && minProperties !== undefined) { | ||
// Be succint if the minProperties is the same maxProperties | ||
// ie. value can only be of `x` length. | ||
if (maxProperties === minProperties) { | ||
validations.push(`${minProperties} properties`); | ||
} else { | ||
validations.push(`${minProperties}-${maxProperties} properties`); | ||
} | ||
} else if (minProperties !== undefined) { | ||
validations.push(`at least ${minProperties} properties`); | ||
} else if (maxProperties !== undefined) { | ||
validations.push(`at most ${maxProperties} properties`); | ||
} | ||
|
||
if (!validations.length) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<span> | ||
{validations.map(constraint => | ||
<span key={constraint} className="object-constraints">{constraint}</span> | ||
)} | ||
</span> | ||
); | ||
} | ||
} | ||
|
||
ObjectProperty.propTypes = { | ||
constraints: PropTypes.shape({ | ||
maxProperties: PropTypes.number, | ||
minProperties: PropTypes.number | ||
}) | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class's responsibility is to render the validation constraints for arrays, and thus should be named accordingly.
Need one space in UI (
Carriers > Returns a list of integrations available for registration
)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want all the *Property classes to be renamed to *Constraints (I don't feel strongly either way)?
As for the space, I'd add some CSS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, they should either have
Constraint
in the name, or are all under aConstraints
directory. That makes it easy to follow.