Skip to content

Parameter

JonathanMontane edited this page May 4, 2016 · 4 revisions

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.

Import

/* if in src/ */
import { Parameter } from './models/Core'

Interface

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()
})

Fields

Parameter.key
  • Parameter.key expects a string and is required. it describes the key of the key-value pair the Parameter represents. For instance, if talking about the header parameter Content-Type: application/json, Parameter.key would be 'Content-Type'.
Parameter.value
  • Parameter.name expects either null or a value that respects the type defined in Parameter.type and follows the format defined in Parameter.format, if provided. Parameter.value represents the default value of the Parameter.
Parameter.type
  • 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 support object type yet, and only provides partial support for the array and date type. It introduces the same date and file as the RAML specification, but also adds two other types schema and multi.
If Parameter.type equals schema:
  • Parameter.value must be a Schema component
If Parameter.type equals multi:
  • The Parameter acts as a container for other Parameters. Therefore Parameter.value must be an Immutable.List of Parameters.
Parameter.format
  • Parameter.format expects either null or a string that describes the parameter.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.
Special Formats
  • 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
  • Parameter.name is the display name of the Parameter. It is different from Parameter.key, and should not be used for anything else than informational purposes. For instance, a Parameter with key: 'api_key' might have name: 'API Key'.
Parameter.description
  • Parameter.description contains a description of what the parameter is and does.
Parameter.example
  • Parameter.example contains one or more examples of what the value of the Parameter should be. It is different from Parameter.value, as Parameter.value can be used during data generation, while Parameter.example will not.
Parameter.interals
  • Parameter.internals expects an Immutable.List of Constraints. It defines the Constraints under which the value must be generated. A value is valid if and only if it is validated by all the constraints defined in internals. For more information on how to use internals, read the section Internals and Externals manipulation.
Parameter.externals
  • Parameter.externals expects an Immutable.List of Parameters. It defines the environments/contexts in which the Parameter 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.

Methods

In addition to these fields, Parameter also provides a function that can help manipulate its data:

generate
  • Parameter.generate(useDefault) generates a value based on the value, type, format and internals of a Parameter. If useDefault is set to true, then the Parameter will use its value field if it is defined; otherwise, it will use internals to define the set of constraints under which it should generate the data
validate
  • Parameter.validate(value) compares a value against the constraints defined in internals. it returns true if and only if all the constraints are validated.
validate with type: multi

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.

isValid
  • Parameter.isValid(_parameter_) validates each external of Parameter.externals using external.validate(_parameter_). It returns true if any external 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 the Content-Type was either 'application/json' or 'application/xml', then comparing it against a Parameter with key: Content-Type and value: 'application/json' would yield true.

Example

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])