Domain configuration
Operations
Input dispositions

InputDispositions

Since some of the configuration is dynamic, a client might not know from the API documentation what an operation mutation would expect an operation input to be valid. For this a client can request the InputDispositions from an operation mutation to get the actual state of any attribute validation. In other words ActiveQL sends the client exactly the information it uses to validate the current input data. A client could use this e.g. to build or enhance a UI application. Without requesting a result in the operation request a client can make a "dry-run" with any data input from a user to see if it is valid and also rendering a UI allowing a user to only enter data that would be sufficient for an actual operation call.

InputDispositions are always evaluated, whether the client adds it to requested fields or not.

PropertyTypeDynamicRelevant forDescription
typestringNoinput & attributethe type of the input or attribute
listbooleanNoinput & attributewhether the input or attribute is a list
requiredbooleanYesinput & attributewhether the input or attribute is required in the operation input
uniquestring | boolean | string[]Noentity string attributewhether the attribute value must be unique
defaultValueanyYesattributethe value this attribute would get when no value was in the input
patternstringYesstring attributea pattern this _attribute _ must match
validationobjectYesattribute
rangeOperationRangeYeslist input & attribute
allowedunknown[]Yes
omitbooleanYes
descriptionstringNoinput & attribute
customanyYes
valueanyYesattribute

Given a most simple operation configuration

operation:
  RentCar:
    input: 
      Rental:
        attributes:
          carId: String
          driverId: String

When API client would send a request without any data in the input

mutation { RentCar { inputDispositions } }

we would get these dispositions and since none of the configuration options are dynamic the information in the attribute dispositions would be the same a client would get from the API documentation.

{
  Rental: {
    type: 'RentCarInputRental',
    list: false,
    required: false
  },
  'Rental.carId': {
    type: 'String',
    list: false,
    required: false,
    omit: false
  },
  'Rental.driverId': {
    type: 'String',
    list: false,
    required: false,
    omit: false
  }
}

But let's see if we use dynamic configuration. Take a look at the firstname attribute required configuration. We use a FEEL expression to state that if the Rental is for "Porsche" we do require the this value. We also validate the age range based on the carBrand value: if a Rental is for either a "Porsche" or "BMW" we only allow an age value of greater or equal to 21 or 18 otherwise.

enum:
  Brand:
    - Mercedes
    - BMW
    - Porsche
 
operation:
  RentCar:
    input: 
      Rental:
        attributes:
          brand: 
            type: Brand!
          firstname: 
            type: String
            required:
              expression: eq( @brand, 'Porsche')
          lastname: String!
          age:
            type: Int!            
            range: 
              expression: if includes( ['Porsche', 'BMW'], @brand ) then [21,null] else [18,null]

The dispositions are now dependent on the actual input. Let's see the evaluated values when calling this operation the brand "Mercedes".

mutation { RentCar( Rental: { brand: Mercedes lastname: "Coleman" age: 19 } ) { inputDispositions } }
{
  "Rental.firstname": {
    type: "String",
    list: false,
    required: false,
    omit: false,
  },
  "Rental.age": {
    type: "Int",
    list: false,
    required: true,
    omit: false,
    range: {
      min: 18, 
      max: null
    }
  }
}

As expected we see the firstname attribute is not required and the age range says min 18. Let's now send a request for a "Porsche".

mutation { RentCar( Rental: { brand: Porsche lastname: "Coleman" age: 19 } ) { inputDispositions } }
{
  "Rental.firstname": {
    type: "String",
    list: false,
    required: true,
    omit: false,
  },
  "Rental.age": {
    type: "Int",
    list: false,
    required: true,
    omit: false,
    range: {
      min: 21, 
      max: null
    }
  }
}

Notice how the firstname attribute is now required and the range starts at 21.

List values in dispositions

When a ConfigSource can use the position in a list to evaluate it's value. Let's say a Rental has many Driver but only the first firstname attribute is required, we could express it like so: