{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://www.rubyschema.org/blazer.json",
  "title": "Blazer Configuration",
  "markdownDescription": "Configuration for Blazer, a business intelligence tool for Rails that lets you explore data with SQL, build dashboards and run checks. Located at `config/blazer.yml` and generated by `rails generate blazer:install`. The file is processed with ERB before being parsed.\n\n[Blazer Documentation](https://github.com/ankane/blazer)",
  "type": "object",
  "definitions": {
    "adapter": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "athena",
            "bigquery",
            "cassandra",
            "clickhouse",
            "drill",
            "druid",
            "elasticsearch",
            "hive",
            "ignite",
            "influxdb",
            "neo4j",
            "opensearch",
            "presto",
            "salesforce",
            "snowflake",
            "snowflake2",
            "soda",
            "spark",
            "sql",
            "trino"
          ],
          "markdownEnumDescriptions": [
            "Amazon Athena. Requires the `aws-sdk-athena` and `aws-sdk-glue` gems.",
            "Google BigQuery. Requires the `google-cloud-bigquery` gem.",
            "Cassandra. Requires the `cassandra-driver` and `sorted_set` gems. Detected automatically from a `cassandra://` URL.",
            "ClickHouse.",
            "Apache Drill. Requires the `drill-sergeant` gem.",
            "Druid, using its SQL API.",
            "Elasticsearch. Requires the `elasticsearch` gem.",
            "Apache Hive. Requires the `hexspace` gem.",
            "Apache Ignite. Requires the `ignite-client` gem. Detected automatically from an `ignite://` URL.",
            "InfluxDB. Requires the `influxdb` gem.",
            "Neo4j. Requires the `neo4j-ruby-driver` gem.",
            "OpenSearch. Requires the `opensearch-ruby` gem.",
            "Presto. Requires the `presto-client` gem. Detected automatically from a `presto://` URL.",
            "Salesforce, using SOQL. Requires the `restforce` gem and the `SALESFORCE_*` environment variables.",
            "Snowflake over ODBC (legacy). Prefer `snowflake2`.",
            "Snowflake, using the SQL API.",
            "Socrata Open Data API (SODA).",
            "Apache Spark. Requires the `hexspace` gem.",
            "Any database supported by Active Record (PostgreSQL, MySQL, SQLite, Redshift, SQL Server, Oracle and more). The default for URLs without a more specific scheme.",
            "Trino. Requires the `trino-client` gem. Detected automatically from a `trino://` URL."
          ]
        },
        {
          "type": "string",
          "markdownDescription": "A custom adapter registered with `Blazer.register_adapter`."
        }
      ]
    },
    "data_source": {
      "type": "object",
      "properties": {
        "url": {
          "type": "string",
          "markdownDescription": "Connection URL for the data source. Use ERB to read it from an environment variable. Required outside development and test, except for the `athena`, `bigquery`, `snowflake` and `salesforce` adapters.\n\nWhen `adapter` is not set, it is detected from the URL scheme: `presto`, `trino`, `cassandra` and `ignite` use their own adapters and everything else uses `sql`.\n\n**Example:**\n```yaml\nurl: <%= ENV[\"BLAZER_DATABASE_URL\"] %>\n```",
          "examples": [
            "<%= ENV[\"BLAZER_DATABASE_URL\"] %>",
            "postgres://user:password@hostname:5432/database",
            "mysql2://user:password@hostname:3306/database",
            "sqlite3:path/to/database.sqlite3"
          ]
        },
        "adapter": {
          "$ref": "#/definitions/adapter",
          "markdownDescription": "Adapter used to connect to the data source.\n\n**Default:** detected from the `url` scheme, falling back to `sql`"
        },
        "name": {
          "type": "string",
          "markdownDescription": "Display name for the data source.\n\n**Default:** the data source key"
        },
        "timeout": {
          "type": "number",
          "markdownDescription": "Statement timeout, in seconds. Supported by PostgreSQL, Redshift, MySQL and MariaDB.\n\n**Default:** no timeout",
          "examples": [15]
        },
        "cache": {
          "markdownDescription": "Cache query results. Either a number of minutes to cache every query for, or a hash of cache settings.\n\n**Default:** caching is off\n\n**Example:**\n```yaml\ncache:\n  mode: slow\n  expires_in: 60 # min\n  slow_threshold: 15 # sec\n```",
          "anyOf": [
            {
              "type": "number",
              "markdownDescription": "Cache every query for this many minutes."
            },
            {
              "type": "object",
              "properties": {
                "mode": {
                  "type": "string",
                  "enum": ["slow", "all"],
                  "markdownEnumDescriptions": [
                    "Cache queries that take at least `slow_threshold` seconds.",
                    "Cache every query."
                  ],
                  "markdownDescription": "Which queries to cache."
                },
                "expires_in": {
                  "type": "number",
                  "markdownDescription": "How long to keep cached results, in minutes.\n\n**Default:** `60`",
                  "default": 60
                },
                "slow_threshold": {
                  "type": "number",
                  "markdownDescription": "Minimum query duration, in seconds, for a result to be cached in `slow` mode.\n\n**Default:** `15`",
                  "default": 15
                }
              },
              "additionalProperties": false
            }
          ]
        },
        "use_transaction": {
          "type": "boolean",
          "markdownDescription": "Wrap queries in a transaction that is rolled back, for safety. Not necessary when connecting as a read-only user. Only used by the `sql` adapter.\n\n**Default:** `true`",
          "default": true
        },
        "smart_variables": {
          "type": ["object", "null"],
          "markdownDescription": "Let users pick a variable's value from a list instead of typing it. Each key is a variable name. The value is a SQL query whose first column is the value and second column is the label, an array of values, or a hash of values to labels.\n\n**Example:**\n```yaml\nsmart_variables:\n  zone_id: \"SELECT id, name FROM zones ORDER BY name ASC\"\n  period: [\"day\", \"week\", \"month\"]\n  status: {0: \"Active\", 1: \"Archived\"}\n```",
          "additionalProperties": {
            "anyOf": [
              { "type": "string" },
              { "type": "array" },
              { "type": "object" }
            ]
          }
        },
        "linked_columns": {
          "type": ["object", "null"],
          "markdownDescription": "Link result columns to other pages. Each key is a column name and the value is a URL, where `{value}` is replaced with the cell's value.\n\n**Example:**\n```yaml\nlinked_columns:\n  user_id: \"/admin/users/{value}\"\n```",
          "additionalProperties": {
            "type": "string"
          }
        },
        "smart_columns": {
          "type": ["object", "null"],
          "markdownDescription": "Replace ids in result columns with readable values. Each key is a column name. The value is a SQL query, where `{value}` is replaced with the list of ids, or a hash of values to labels.\n\n**Example:**\n```yaml\nsmart_columns:\n  city_id: \"SELECT id, name FROM cities WHERE id IN {value}\"\n  status: {0: \"Active\", 1: \"Archived\"}\n```",
          "additionalProperties": {
            "anyOf": [{ "type": "string" }, { "type": "object" }]
          }
        },
        "variable_defaults": {
          "type": ["object", "null"],
          "markdownDescription": "Default values for query variables. Each key is a variable name.\n\n**Example:**\n```yaml\nvariable_defaults:\n  period: day\n```",
          "additionalProperties": {
            "type": ["string", "number", "boolean"]
          }
        },
        "inherit_smart_settings": {
          "markdownDescription": "Data source keys to fall back to when a smart variable or smart column is not defined on this data source.\n\n**Example:**\n```yaml\ninherit_smart_settings: [main]\n```",
          "anyOf": [
            { "type": "string" },
            { "type": "array", "items": { "type": "string" } }
          ]
        },
        "local_time_suffix": {
          "markdownDescription": "Column name suffixes for timestamps already stored in local time. Matching columns are not converted to Blazer's `time_zone`.\n\n**Example:**\n```yaml\nlocal_time_suffix: [_local]\n```",
          "anyOf": [
            { "type": "string" },
            { "type": "array", "items": { "type": "string" } }
          ]
        },
        "schemas": {
          "type": "array",
          "items": { "type": "string" },
          "markdownDescription": "Database schemas to show in the schema browser. Only used by the `sql` adapter.\n\n**Default:** every schema except system schemas (the current database on MySQL)",
          "examples": [["public"]]
        },
        "database": {
          "type": "string",
          "markdownDescription": "Database to query. Used by the `athena`, `clickhouse` and `snowflake2` adapters.\n\n**Default:** `default` for `athena` and `clickhouse`"
        },
        "catalog": {
          "type": "string",
          "markdownDescription": "Data catalog to query. Only used by the `athena` adapter.",
          "examples": ["s3tablescatalog/some-bucket"]
        },
        "output_location": {
          "type": "string",
          "markdownDescription": "S3 location for query results. Only used by the `athena` adapter.",
          "examples": ["s3://some-bucket/"]
        },
        "workgroup": {
          "type": "string",
          "markdownDescription": "Athena workgroup to run queries in. Only used by the `athena` adapter.",
          "examples": ["primary"]
        },
        "engine_version": {
          "type": ["integer", "string"],
          "markdownDescription": "Athena engine version. Only used by the `athena` adapter.\n\n**Default:** `1`",
          "default": 1
        },
        "access_key_id": {
          "type": "string",
          "markdownDescription": "AWS access key ID. Only used by the `athena` adapter.\n\n**Default:** the AWS SDK's default credentials"
        },
        "secret_access_key": {
          "type": "string",
          "markdownDescription": "AWS secret access key. Only used by the `athena` adapter.\n\n**Default:** the AWS SDK's default credentials"
        },
        "region": {
          "type": "string",
          "markdownDescription": "AWS region. Only used by the `athena` adapter.\n\n**Default:** the AWS SDK's default region",
          "examples": ["us-east-1"]
        },
        "project": {
          "type": "string",
          "markdownDescription": "Google Cloud project ID. Only used by the `bigquery` adapter."
        },
        "keyfile": {
          "type": "string",
          "markdownDescription": "Path to a Google Cloud service account key file. Only used by the `bigquery` adapter.",
          "examples": ["path/to/keyfile.json"]
        },
        "account_id": {
          "type": "string",
          "markdownDescription": "Snowflake account identifier. Required by the `snowflake2` adapter."
        },
        "access_token": {
          "type": "string",
          "markdownDescription": "Snowflake access token. Required by the `snowflake2` adapter."
        },
        "schema": {
          "type": "string",
          "markdownDescription": "Snowflake schema to query. Only used by the `snowflake2` adapter.",
          "examples": ["PUBLIC"]
        },
        "warehouse": {
          "type": "string",
          "markdownDescription": "Snowflake warehouse to run queries in. Only used by the `snowflake2` adapter."
        },
        "role": {
          "type": "string",
          "markdownDescription": "Snowflake role to run queries as. Only used by the `snowflake2` adapter."
        },
        "dsn": {
          "type": "string",
          "markdownDescription": "ODBC data source name. Only used by the legacy `snowflake` adapter."
        },
        "conn_str": {
          "type": "string",
          "markdownDescription": "ODBC connection string. Only used by the legacy `snowflake` adapter."
        },
        "app_token": {
          "type": "string",
          "markdownDescription": "Socrata app token. Only used by the `soda` adapter."
        }
      },
      "if": {
        "required": ["adapter"],
        "properties": {
          "adapter": {
            "not": {
              "enum": [
                "athena",
                "bigquery",
                "cassandra",
                "clickhouse",
                "drill",
                "druid",
                "elasticsearch",
                "hive",
                "ignite",
                "influxdb",
                "neo4j",
                "opensearch",
                "presto",
                "salesforce",
                "snowflake",
                "snowflake2",
                "soda",
                "spark",
                "sql",
                "trino"
              ]
            }
          }
        }
      },
      "else": {
        "propertyNames": {
          "enum": [
            "url",
            "adapter",
            "name",
            "timeout",
            "cache",
            "use_transaction",
            "smart_variables",
            "linked_columns",
            "smart_columns",
            "variable_defaults",
            "inherit_smart_settings",
            "local_time_suffix",
            "schemas",
            "database",
            "catalog",
            "output_location",
            "workgroup",
            "engine_version",
            "access_key_id",
            "secret_access_key",
            "region",
            "project",
            "keyfile",
            "account_id",
            "access_token",
            "schema",
            "warehouse",
            "role",
            "dsn",
            "conn_str",
            "app_token"
          ]
        }
      }
    },
    "detector": {
      "anyOf": [
        {
          "type": "string",
          "enum": ["prophet", "trend", "anomaly_detection"]
        },
        {
          "type": "string",
          "markdownDescription": "A custom method registered with Blazer."
        },
        {
          "const": false
        }
      ]
    }
  },
  "properties": {
    "data_sources": {
      "type": "object",
      "markdownDescription": "Data sources users can query. Each key is a data source identifier.\n\n**Example:**\n```yaml\ndata_sources:\n  main:\n    url: <%= ENV[\"BLAZER_DATABASE_URL\"] %>\n  catalog:\n    url: <%= ENV[\"CATALOG_DATABASE_URL\"] %>\n```",
      "additionalProperties": {
        "$ref": "#/definitions/data_source"
      }
    },
    "audit": {
      "type": "boolean",
      "markdownDescription": "Record an audit entry each time a query runs. Required for `rake blazer:archive_queries`.\n\n**Default:** `true`",
      "default": true
    },
    "time_zone": {
      "type": "string",
      "markdownDescription": "Time zone used to display timestamps. Accepts any Active Support time zone name.\n\n**Default:** the app's `Time.zone`",
      "examples": ["Pacific Time (US & Canada)", "UTC"]
    },
    "user_class": {
      "markdownDescription": "Class name of the user model, used to record who created queries, dashboards and checks. Set to `null` to turn this off.\n\n**Default:** `User`, when it exists",
      "anyOf": [{ "type": "string" }, { "type": "null" }, { "const": false }],
      "examples": ["User", "Admin"]
    },
    "user_method": {
      "type": "string",
      "markdownDescription": "Controller method that returns the current user.\n\n**Default:** `current_` followed by the singular, lowercase `user_class` (e.g. `current_user`)",
      "examples": ["current_user"]
    },
    "user_name": {
      "type": "string",
      "markdownDescription": "Method on the user model that returns a display name.\n\n**Default:** `name`",
      "default": "name"
    },
    "before_action_method": {
      "type": "string",
      "markdownDescription": "Controller method to run before every Blazer action, for authentication. Define it in your `ApplicationController` and render or redirect when the user is not allowed.\n\n**Example:**\n```yaml\nbefore_action_method: require_admin\n```"
    },
    "before_action": {
      "type": "string",
      "markdownDescription": "Renamed to `before_action_method`. Blazer raises an error at boot while this key is present.",
      "deprecationMessage": "Use `before_action_method` instead. Blazer raises an error while `before_action` is set."
    },
    "from_email": {
      "type": "string",
      "markdownDescription": "Address check emails are sent from.",
      "examples": ["blazer@example.org"]
    },
    "slack_webhook_url": {
      "type": "string",
      "markdownDescription": "Slack incoming webhook URL for check notifications.\n\n**Default:** `ENV[\"BLAZER_SLACK_WEBHOOK_URL\"]`",
      "examples": ["<%= ENV[\"BLAZER_SLACK_WEBHOOK_URL\"] %>"]
    },
    "slack_oauth_token": {
      "type": "string",
      "markdownDescription": "Slack OAuth token for check notifications, as an alternative to a webhook.\n\n**Default:** `ENV[\"BLAZER_SLACK_OAUTH_TOKEN\"]`"
    },
    "check_schedules": {
      "type": "array",
      "items": { "type": "string" },
      "markdownDescription": "Schedules users can pick for checks. Each one needs a matching job that runs `Blazer.run_checks(schedule: \"...\")`.\n\n**Default:** `[\"5 minutes\", \"1 hour\", \"1 day\"]`",
      "default": ["5 minutes", "1 hour", "1 day"]
    },
    "anomaly_checks": {
      "$ref": "#/definitions/detector",
      "markdownDescription": "Enable anomaly detection checks with the given method.\n\n- `prophet` requires the `prophet-rb` gem\n- `trend` requires the `trend` gem and `Trend.url`\n- `anomaly_detection` requires the `anomaly_detection` gem\n\n**Default:** `false`"
    },
    "forecasting": {
      "$ref": "#/definitions/detector",
      "markdownDescription": "Enable forecasting with the given method, for queries that return a timestamp and a numeric column.\n\n- `prophet` requires the `prophet-rb` gem\n- `trend` requires the `trend` gem and `Trend.url`\n\n**Default:** `false`"
    },
    "async": {
      "type": "boolean",
      "markdownDescription": "Run queries in the background instead of holding up a request. Requires caching, and a shared cache store such as Memcached or Redis when you run more than one web process.\n\n**Default:** `false`",
      "default": false
    },
    "images": {
      "type": "boolean",
      "markdownDescription": "Show image URLs in results as images. Applies to columns whose name includes `image` and to values ending in an image extension.\n\n**Default:** `false`",
      "default": false
    },
    "override_csp": {
      "type": "boolean",
      "markdownDescription": "Replace your app's Content Security Policy with a permissive one for Blazer's pages. Use this if views are stuck on `Loading...`.\n\n**Default:** `false`",
      "default": false
    },
    "mapbox_access_token": {
      "type": "string",
      "markdownDescription": "Mapbox public access token (starting with `pk.`), used to show results with coordinates or GeoJSON on a map.\n\n**Default:** `ENV[\"MAPBOX_ACCESS_TOKEN\"]`",
      "examples": ["<%= ENV[\"MAPBOX_ACCESS_TOKEN\"] %>"]
    },
    "uploads": {
      "type": "object",
      "markdownDescription": "Let users create database tables from CSV files. Requires PostgreSQL and `rails generate blazer:uploads`.\n\n**Example:**\n```yaml\nuploads:\n  url: <%= ENV[\"BLAZER_UPLOADS_URL\"] %>\n  schema: uploads\n  data_source: main\n```",
      "properties": {
        "url": {
          "type": "string",
          "markdownDescription": "Connection URL for the database uploads are written to.",
          "examples": ["<%= ENV[\"BLAZER_UPLOADS_URL\"] %>"]
        },
        "schema": {
          "type": "string",
          "markdownDescription": "Database schema uploaded tables are created in. Create a schema just for uploads.\n\n**Default:** `uploads`",
          "default": "uploads"
        },
        "data_source": {
          "type": "string",
          "markdownDescription": "Data source key that queries on uploaded tables use.",
          "examples": ["main"]
        }
      },
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}
