{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://acuminous.github.io/filby/lib/schema.json",
  "title": "JSON Schema for Filby",
  "type": "array",
  "minItems": 1,
  "items": {
    "allOf": [
      {
        "type": "object",
        "properties": {
          "operation": {
            "type": "string",
            "enum": [
              "ADD_ENUM",
              "ADD_ENTITY",
              "ADD_PROJECTION",
              "ADD_HOOK",
              "ADD_CHANGE_SET",
              "ALTER_ENUM",
              "DROP_ENUM",
              "DROP_ENTITY",
              "DROP_PROJECTION",
              "DROP_HOOK"
            ]
          }
        },
        "required": [
          "operation"
        ]
      },
      {
        "anyOf": [
          {
            "allOf": [
              {
                "type": "object",
                "properties": {
                  "operation": {
                    "$ref": "#/definitions/AddEnumOperationType"
                  }
                }
              },
              {
                "$ref": "#/definitions/AddEnumType"
              }
            ]
          },
          {
            "allOf": [
              {
                "type": "object",
                "properties": {
                  "operation": {
                    "$ref": "#/definitions/AddEntityOperationType"
                  }
                }
              },
              {
                "$ref": "#/definitions/AddEntityType"
              }
            ]
          },
          {
            "allOf": [
              {
                "type": "object",
                "properties": {
                  "operation": {
                    "$ref": "#/definitions/AddProjectionOperationType"
                  }
                }
              },
              {
                "$ref": "#/definitions/AddProjectionType"
              }
            ]
          },
          {
            "allOf": [
              {
                "type": "object",
                "properties": {
                  "operation": {
                    "$ref": "#/definitions/AddHookOperationType"
                  }
                }
              },
              {
                "$ref": "#/definitions/AddHookType"
              }
            ]
          },
          {
            "allOf": [
              {
                "type": "object",
                "properties": {
                  "operation": {
                    "$ref": "#/definitions/AddChangeSetOperationType"
                  }
                }
              },
              {
                "$ref": "#/definitions/AddChangeSetType"
              }
            ]
          },
          {
            "allOf": [
              {
                "type": "object",
                "properties": {
                  "operation": {
                    "$ref": "#/definitions/AlterEnumOperationType"
                  }
                }
              },
              {
                "$ref": "#/definitions/AlterEnumType"
              }
            ]
          },
          {
            "allOf": [
              {
                "type": "object",
                "properties": {
                  "operation": {
                    "$ref": "#/definitions/DropEnumOperationType"
                  }
                }
              },
              {
                "$ref": "#/definitions/DropEnumType"
              }
            ]
          },
          {
            "allOf": [
              {
                "type": "object",
                "properties": {
                  "operation": {
                    "$ref": "#/definitions/DropEntityOperationType"
                  }
                }
              },
              {
                "$ref": "#/definitions/DropEntityType"
              }
            ]
          },
          {
            "allOf": [
              {
                "type": "object",
                "properties": {
                  "operation": {
                    "$ref": "#/definitions/DropProjectionOperationType"
                  }
                }
              },
              {
                "$ref": "#/definitions/DropProjectionType"
              }
            ]
          },
          {
            "allOf": [
              {
                "type": "object",
                "properties": {
                  "operation": {
                    "$ref": "#/definitions/DropHookOperationType"
                  }
                }
              },
              {
                "$ref": "#/definitions/DropHookType"
              }
            ]
          }
        ]
      }
    ]
  },
  "definitions": {
    "AddEnumType": {
      "type": "object",
      "properties": {
        "operation": {
          "$ref": "#/definitions/AddEnumOperationType"
        },
        "description": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "values": {
          "$ref": "#/definitions/StringListType"
        }
      },
      "additionalProperties": false,
      "required": [
        "operation",
        "name",
        "values"
      ]
    },
    "AddEntityType": {
      "type": "object",
      "properties": {
        "operation": {
          "$ref": "#/definitions/AddEntityOperationType"
        },
        "description": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "version": {
          "type": "integer"
        },
        "fields": {
          "if": {
            "type": "object"
          },
          "then": {
            "type": "object",
            "minProperties": 1,
            "additionalProperties": {
              "type": [
                "string",
                "object"
              ],
              "properties": {
                "type": {
                  "type": "string"
                },
                "nullable": {
                  "type": "boolean"
                }
              },
              "additionalProperties": false,
              "required": [
                "type"
              ]
            }
          },
          "else": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "type": {
                  "type": "string"
                },
                "nullable": {
                  "type": "boolean"
                }
              },
              "additionalProperties": false,
              "required": [
                "name",
                "type"
              ]
            }
          }
        },
        "key": {
          "$ref": "#/definitions/StringListType"
        },
        "identified_by": {
          "$ref": "#/definitions/StringListType"
        },
        "checks": {
          "type": "object",
          "minProperties": 1,
          "patternProperties": {
            ".+": {
              "type": "string"
            }
          }
        }
      },
      "additionalProperties": false,
      "required": [
        "operation",
        "name",
        "fields"
      ],
      "if": {
        "required": [
          "key"
        ]
      },
      "else": {
        "required": [
          "identified_by"
        ]
      }
    },
    "AddProjectionType": {
      "type": "object",
      "properties": {
        "operation": {
          "$ref": "#/definitions/AddProjectionOperationType"
        },
        "description": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "version": {
          "type": "integer"
        },
        "root": {
          "type": "string",
          "pattern": "@[0-9]+$"
        },
        "fields": {
          "$ref": "#/definitions/StringListType"
        },
        "dependencies": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "properties": {
              "entity": {
                "type": "string"
              },
              "version": {
                "type": "integer"
              }
            },
            "additionalProperties": false,
            "required": [
              "entity"
            ],
            "if": {
              "$ref": "#/definitions/VersionedEntityReferenceType"
            },
            "else": {
              "required": [
                "version"
              ]
            }
          }
        },
        "parameters": {
          "type": "object",
          "minProperties": 1,
          "additionalProperties": {
            "type": "object",
            "properties": {
              "field": {
                "type": "string"
              },
              "match": {
                "type": "string",
                "enum": [
                  "equals",
                  "prefix",
                  "in",
                  "range",
                  "gt",
                  "gte",
                  "lt",
                  "lte"
                ]
              }
            },
            "additionalProperties": false,
            "required": [
              "field"
            ]
          }
        },
        "order": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/definitions/OrderItemType"
          }
        },
        "paging": {
          "type": "object",
          "properties": {
            "page_size": {
              "type": "integer",
              "minimum": 1
            },
            "page_max": {
              "type": "integer",
              "minimum": 1
            }
          },
          "additionalProperties": false,
          "required": [
            "page_size",
            "page_max"
          ]
        },
        "nest": {
          "$ref": "#/definitions/NestType"
        },
        "lookup": {
          "$ref": "#/definitions/LookupType"
        }
      },
      "additionalProperties": false,
      "required": [
        "operation",
        "name"
      ],
      "if": {
        "required": [
          "root"
        ]
      },
      "else": {
        "required": [
          "dependencies"
        ]
      }
    },
    "AddHookType": {
      "type": "object",
      "properties": {
        "operation": {
          "$ref": "#/definitions/AddHookOperationType"
        },
        "description": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "event": {
          "$ref": "#/definitions/EventType"
        },
        "projection": {
          "type": "string"
        },
        "version": {
          "type": "integer"
        }
      },
      "additionalProperties": false,
      "if": {
        "anyOf": [
          {
            "required": [
              "projection"
            ]
          },
          {
            "required": [
              "version"
            ]
          }
        ]
      },
      "then": {
        "properties": {
          "event": {
            "type": "string",
            "enum": [
              "ADD_CHANGE_SET",
              "COMMENCE_CHANGE_SET"
            ]
          }
        },
        "required": [
          "operation",
          "name",
          "event",
          "projection"
        ],
        "if": {
          "properties": {
            "projection": {
              "type": "string",
              "pattern": "@[0-9]+$"
            }
          },
          "required": [
            "projection"
          ]
        },
        "else": {
          "required": [
            "version"
          ]
        }
      },
      "else": {
        "required": [
          "operation",
          "name",
          "event"
        ]
      }
    },
    "AddChangeSetType": {
      "type": "object",
      "properties": {
        "operation": {
          "$ref": "#/definitions/AddChangeSetOperationType"
        },
        "description": {
          "type": "string"
        },
        "effective": {
          "type": "string",
          "anyOf": [
            {
              "format": "date-time"
            },
            {
              "format": "date"
            }
          ]
        },
        "timezone": {
          "type": "string"
        },
        "changes": {
          "$ref": "#/definitions/FrameListType"
        },
        "frames": {
          "$ref": "#/definitions/FrameListType"
        }
      },
      "additionalProperties": false,
      "required": [
        "operation",
        "description",
        "effective"
      ],
      "if": {
        "required": [
          "changes"
        ]
      },
      "else": {
        "required": [
          "frames"
        ]
      }
    },
    "FrameListType": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string"
          },
          "entity": {
            "type": "string"
          },
          "version": {
            "type": "integer"
          },
          "action": {
            "type": "string",
            "enum": [
              "SET",
              "POST",
              "DELETE"
            ]
          },
          "data": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object"
            }
          }
        },
        "additionalProperties": false,
        "required": [
          "entity"
        ],
        "oneOf": [
          {
            "required": [
              "source"
            ]
          },
          {
            "required": [
              "action",
              "data"
            ]
          }
        ],
        "if": {
          "$ref": "#/definitions/VersionedEntityReferenceType"
        },
        "else": {
          "required": [
            "version"
          ]
        }
      }
    },
    "VersionedEntityReferenceType": {
      "type": "object",
      "properties": {
        "entity": {
          "type": "string",
          "pattern": "@[0-9]+$"
        }
      },
      "required": [
        "entity"
      ]
    },
    "AlterEnumType": {
      "type": "object",
      "properties": {
        "operation": {
          "$ref": "#/definitions/AlterEnumOperationType"
        },
        "description": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "add": {
          "$ref": "#/definitions/StringListType"
        }
      },
      "additionalProperties": false,
      "required": [
        "operation",
        "name",
        "add"
      ]
    },
    "DropEnumType": {
      "type": "object",
      "properties": {
        "operation": {
          "$ref": "#/definitions/DropEnumOperationType"
        },
        "description": {
          "type": "string"
        },
        "name": {
          "type": "string"
        }
      },
      "additionalProperties": false,
      "required": [
        "operation",
        "name"
      ]
    },
    "DropEntityType": {
      "type": "object",
      "properties": {
        "operation": {
          "$ref": "#/definitions/DropEntityOperationType"
        },
        "description": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "version": {
          "type": "integer"
        }
      },
      "additionalProperties": false,
      "required": [
        "operation",
        "name",
        "version"
      ]
    },
    "DropProjectionType": {
      "type": "object",
      "properties": {
        "operation": {
          "$ref": "#/definitions/DropProjectionOperationType"
        },
        "description": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "version": {
          "type": "integer"
        }
      },
      "additionalProperties": false,
      "required": [
        "operation",
        "name",
        "version"
      ]
    },
    "DropHookType": {
      "type": "object",
      "properties": {
        "operation": {
          "$ref": "#/definitions/DropHookOperationType"
        },
        "description": {
          "type": "string"
        },
        "name": {
          "type": "string"
        }
      },
      "additionalProperties": false,
      "required": [
        "operation",
        "name"
      ]
    },
    "AddEnumOperationType": {
      "const": "ADD_ENUM"
    },
    "AddEntityOperationType": {
      "const": "ADD_ENTITY"
    },
    "AddProjectionOperationType": {
      "const": "ADD_PROJECTION"
    },
    "AddHookOperationType": {
      "const": "ADD_HOOK"
    },
    "AddChangeSetOperationType": {
      "const": "ADD_CHANGE_SET"
    },
    "AlterEnumOperationType": {
      "const": "ALTER_ENUM"
    },
    "DropEnumOperationType": {
      "const": "DROP_ENUM"
    },
    "DropEntityOperationType": {
      "const": "DROP_ENTITY"
    },
    "DropProjectionOperationType": {
      "const": "DROP_PROJECTION"
    },
    "DropHookOperationType": {
      "const": "DROP_HOOK"
    },
    "EventType": {
      "type": "string",
      "enum": [
        "ADD_PROJECTION",
        "DROP_PROJECTION",
        "ADD_CHANGE_SET",
        "COMMENCE_CHANGE_SET"
      ]
    },
    "NestType": {
      "type": "object",
      "minProperties": 1,
      "additionalProperties": {
        "type": "object",
        "properties": {
          "entity": {
            "type": "string",
            "pattern": "@[0-9]+$"
          },
          "on": {
            "type": "object",
            "minProperties": 1,
            "additionalProperties": {
              "type": "string"
            }
          },
          "fields": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "order": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/definitions/OrderItemType"
            }
          },
          "nest": {
            "$ref": "#/definitions/NestType"
          },
          "lookup": {
            "$ref": "#/definitions/LookupType"
          }
        },
        "additionalProperties": false,
        "required": [
          "entity",
          "on"
        ]
      }
    },
    "LookupType": {
      "type": "object",
      "minProperties": 1,
      "additionalProperties": {
        "type": "object",
        "properties": {
          "entity": {
            "type": "string",
            "pattern": "@[0-9]+$"
          },
          "on": {
            "type": "object",
            "minProperties": 1,
            "additionalProperties": {
              "type": "string"
            }
          },
          "fields": {
            "$ref": "#/definitions/StringListType"
          }
        },
        "additionalProperties": false,
        "required": [
          "entity",
          "on"
        ]
      }
    },
    "OrderItemType": {
      "type": "object",
      "properties": {
        "field": {
          "type": "string"
        },
        "direction": {
          "type": "string",
          "enum": [
            "ASC",
            "DESC"
          ]
        },
        "nulls": {
          "type": "string",
          "enum": [
            "FIRST",
            "LAST"
          ]
        }
      },
      "additionalProperties": false,
      "required": [
        "field"
      ]
    },
    "StringListType": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "string"
      }
    }
  }
}