-
Notifications
You must be signed in to change notification settings - Fork 24
Parameter
Parameter components represent any variable that can be used in an HTTP request. They contain a few descriptive fields named format, description, and example, but also fields on what they represent, and in which context they are representing the variable.
Parameter uses a Constraint based paradigm. Indeed, through the use of constraints, the Parameter can define the expected behavior of its internal value. There is a variety of constraints possible, and most of them are derived from the JSON Schema Validation RFC, and you can find more about those in the Constraint page. Besides increasing the readers understanding of what the API is expected as its parameters, defining these internal constraints, or internals
for short, also allows API-Flow to generate example values on the fly, even when none are provided, through the use of jsf.
API-Flow does not limit the use of Constraints to the internals of a Parameter, but also make an active use of them to define the external contexts in which the Parameter can be used. We call an external context any set of constraints that would have an impact on the definition of another Parameter. For instance, the existence of a Parameter named xml-schema
could be depending on whether the Parameter named Content-Type
has application/xml
as a value. Additionally, the content of Parameter could also depend on other Parameters, e.g. the content (value
, type
, internals
, etc.) of the Parameter named data
could very well vary depending on the value of a Parameter named source
being either file
, url
, csv
, etc. Since APIs may supercharge their Parameter definitions based on external contexts, or externals
, API-Flow tries to support them to the highest degree possible.
To read more on how internal and external constraints are defined, used and manipulated, read the section Internals and Externals manipulation.
/* if in src/ */
import { Parameter } from './models/Core'
Parameter extends Immutable.Record using the following pattern:
Class Parameter extends Immutable.Record({
key: null,
value: null,
type: null,
format: null,
name: null,
description: null,
example: null,
internals: Immutable.List(),
externals: Immutable.List()
})
-
Parameter.key
expects astring
and is required. it describes the key of the key-value pair the Parameter represents. For instance, if talking about the header parameterContent-Type: application/json
,Parameter.key
would be'Content-Type'
.
-
Parameter.name
expects eithernull
or a value that respects the type defined inParameter.type
and follows the format defined inParameter.format
, if provided.Parameter.value
represents the default value of the Parameter.
-
Parameter.type
expects one of the following types:[ string, number, integer, date, boolean, array, object, file, schema, multi ]
. These types are an extension of the JSON Schema primitive data types. In version 0.1.0, API-Flow does not supportobject
type yet, and only provides partial support for thearray
anddate
type. It introduces the samedate
andfile
as the RAML specification, but also adds two other typesschema
andmulti
.
-
Parameter.value
must be a Schema component
- The Parameter acts as a container for other Parameters. Therefore
Parameter.value
must be an Immutable.List of Parameters.
-
Parameter.format
expects eithernull
or a string that describes theparameter.value
.Parameter.format
is mostly used to help the reader better understand the type of data he is analyzing. Some formats have special interactions with API-Flow data generation.
-
email
- Parameter will generate valid emails -
byte
- Parameter will generate base64 strings -
binary
- Parameter will generate random ascii patterns - and not random binary patterns. -
date-time
- Parameter will generate a recent date. -
password
- Parameter will generate random ascii patterns.
-
Parameter.name
is the display name of the Parameter. It is different fromParameter.key
, and should not be used for anything else than informational purposes. For instance, a Parameter withkey: 'api_key'
might havename: 'API Key'
.
-
Parameter.description
contains a description of what the parameter is and does.
-
Parameter.example
contains one or more examples of what the value of the Parameter should be. It is different fromParameter.value
, asParameter.value
can be used during data generation, whileParameter.example
will not.
-
Parameter.internals
expects an Immutable.List of Constraints. It defines the Constraints under which thevalue
must be generated. A value is valid if and only if it is validated by all the constraints defined ininternals
. For more information on how to useinternals
, read the section Internals and Externals manipulation.
-
Parameter.externals
expects an Immutable.List of Parameters. It defines the environments/contexts in which theParameter
should be used. A more detailed explanation of why Parameters are used instead of Constraints for externals can be found in the section Internals and Externals manipulation.
In addition to these fields, Parameter
also provides a function that can help manipulate its data:
-
Parameter.generate(useDefault)
generates a value based on thevalue
,type
,format
andinternals
of aParameter
. IfuseDefault
is set totrue
, then the Parameter will use itsvalue
field if it is defined; otherwise, it will useinternals
to define the set of constraints under which it should generate the data
-
Parameter.validate(value)
compares avalue
against the constraints defined ininternals
. it returns true if and only if all the constraints are validated.
If Parameter.type
is multi
, Parameter.validate
calls SubParameter.validate
for each SubParameter contained in its Parameter.value
. It returns true
if any SubParameter return true
, and false
if all return false
.
-
Parameter.isValid(_parameter_)
validates eachexternal
ofParameter.externals
usingexternal.validate(_parameter_)
. It returnstrue
if anyexternal
is validated. From a semantic point of view, this means that isValid will return true if there is at least an environment that fits the criterion defined by_parameter_
, since that means that the Parameter is relevant in that environment. For instance, if there was an environment that was valid if theContent-Type
was either'application/json'
or'application/xml'
, then comparing it against a Parameter withkey: Content-Type
andvalue: 'application/json'
would yieldtrue
.
Please note that this example is abstract, and is there purely to represent the different interactions with Parameter
. The data may be non-sensical.
import parameters from './samples/parameters-examples'
import constraints from './samples/constraints-examples'
import Constraint from './models/Constraint'
import { Parameter } from './models/Core'
let parameter = new Parameter({
key: 'token'
value: null,
type: 'string',
format: null,
name: 'Content Type'
description: 'the purpose of this token is ...'
example: [ '0ae50-bc6-f4fe2-295-ee54d-0ca-12ac5-43d' ],
internals: new Immutable.List([
new Constraint.Pattern(/([0-9a-f]{5}-[0-9a-f]{3}-)+[0-9a-f]{5}-[0-9a-f]{3}/),
new Constraint.MinLength(20),
new Constraint.MaxLength(50)
])
externals: new Immutable.List([
new Parameter({
key: 'Content-Type',
internals: new Immutable.List([
new Constraint.Enum([ 'application/json', 'application/xml' ]),
])
})
])
})
parameter = parameter
.set('key', 'context-token')
.set('value', '0ae50-bc6-f4fe2-295-ee54d-0ca-12ac5-43d')
.set('type', 'string')
.set('format', 'x-uuid')
.set('name', 'Context Token')
.set('description', 'this is a better description, right?')
.set('example', [ 'who needs examples?' ])
.set('internals', new Immutable.List([
constraints[0], constraints[1]
]))
.set('externals', new Immutable.List([
parameters[0], parameters[1]
]))
.setIn([ 'internals', 0 ], constraints[2])
.setIn([ 'externals', 1 ], parameters[2])
let value = parameter.generate()
let validation = parameter.validate(value) // true
let useable = parameter.isValid(parameters[1])