mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2025-12-06 14:26:22 +00:00
214 lines
5.7 KiB
Markdown
214 lines
5.7 KiB
Markdown
# X-Files Header Usage
|
|
|
|
The `x-files` header allows you to configure complex query options using a single JSON object. The XFiles configuration is parsed and populates the `ExtendedRequestOptions` fields, which means it integrates seamlessly with the existing query building system.
|
|
|
|
## Architecture
|
|
|
|
When an `x-files` header is received:
|
|
1. It's parsed into an `XFiles` struct
|
|
2. The `XFiles` fields populate the `ExtendedRequestOptions` (columns, filters, sort, preload, etc.)
|
|
3. The normal query building process applies these options to the SQL query
|
|
4. This allows x-files to work alongside individual headers if needed
|
|
|
|
## Basic Example
|
|
|
|
```http
|
|
GET /public/users
|
|
X-Files: {"tablename":"users","columns":["id","name","email"],"limit":"10","offset":"0"}
|
|
```
|
|
|
|
## Complete Example
|
|
|
|
```http
|
|
GET /public/users
|
|
X-Files: {
|
|
"tablename": "users",
|
|
"schema": "public",
|
|
"columns": ["id", "name", "email", "created_at"],
|
|
"omit_columns": [],
|
|
"sort": ["-created_at", "name"],
|
|
"limit": "50",
|
|
"offset": "0",
|
|
"filter_fields": [
|
|
{
|
|
"field": "status",
|
|
"operator": "eq",
|
|
"value": "active"
|
|
},
|
|
{
|
|
"field": "age",
|
|
"operator": "gt",
|
|
"value": "18"
|
|
}
|
|
],
|
|
"sql_and": ["deleted_at IS NULL"],
|
|
"sql_or": [],
|
|
"cql_columns": ["UPPER(name)"],
|
|
"skipcount": false,
|
|
"distinct": false
|
|
}
|
|
```
|
|
|
|
## Supported Filter Operators
|
|
|
|
- `eq` - equals
|
|
- `neq` - not equals
|
|
- `gt` - greater than
|
|
- `gte` - greater than or equals
|
|
- `lt` - less than
|
|
- `lte` - less than or equals
|
|
- `like` - SQL LIKE
|
|
- `ilike` - case-insensitive LIKE
|
|
- `in` - IN clause
|
|
- `between` - between (exclusive)
|
|
- `between_inclusive` - between (inclusive)
|
|
- `is_null` - is NULL
|
|
- `is_not_null` - is NOT NULL
|
|
|
|
## Sorting
|
|
|
|
Sort fields can be prefixed with:
|
|
- `+` for ascending (default)
|
|
- `-` for descending
|
|
|
|
Examples:
|
|
- `"sort": ["name"]` - ascending by name
|
|
- `"sort": ["-created_at"]` - descending by created_at
|
|
- `"sort": ["-created_at", "name"]` - multiple sorts
|
|
|
|
## Computed Columns (CQL)
|
|
|
|
Use `cql_columns` to add computed SQL expressions:
|
|
|
|
```json
|
|
{
|
|
"cql_columns": [
|
|
"UPPER(name)",
|
|
"CONCAT(first_name, ' ', last_name)"
|
|
]
|
|
}
|
|
```
|
|
|
|
These will be available as `cql1`, `cql2`, etc. in the response.
|
|
|
|
## Cursor Pagination
|
|
|
|
```json
|
|
{
|
|
"cursor_forward": "eyJpZCI6MTAwfQ==",
|
|
"cursor_backward": ""
|
|
}
|
|
```
|
|
|
|
## Base64 Encoding
|
|
|
|
For complex JSON, you can base64-encode the value and prefix it with `ZIP_` or `__`:
|
|
|
|
```http
|
|
GET /public/users
|
|
X-Files: ZIP_eyJ0YWJsZW5hbWUiOiJ1c2VycyIsImxpbWl0IjoiMTAifQ==
|
|
```
|
|
|
|
## XFiles Struct Reference
|
|
|
|
```go
|
|
type XFiles struct {
|
|
TableName string `json:"tablename"`
|
|
Schema string `json:"schema"`
|
|
PrimaryKey string `json:"primarykey"`
|
|
ForeignKey string `json:"foreignkey"`
|
|
RelatedKey string `json:"relatedkey"`
|
|
Sort []string `json:"sort"`
|
|
Prefix string `json:"prefix"`
|
|
Editable bool `json:"editable"`
|
|
Recursive bool `json:"recursive"`
|
|
Expand bool `json:"expand"`
|
|
Rownumber bool `json:"rownumber"`
|
|
Skipcount bool `json:"skipcount"`
|
|
Offset json.Number `json:"offset"`
|
|
Limit json.Number `json:"limit"`
|
|
Columns []string `json:"columns"`
|
|
OmitColumns []string `json:"omit_columns"`
|
|
CQLColumns []string `json:"cql_columns"`
|
|
SqlJoins []string `json:"sql_joins"`
|
|
SqlOr []string `json:"sql_or"`
|
|
SqlAnd []string `json:"sql_and"`
|
|
FilterFields []struct {
|
|
Field string `json:"field"`
|
|
Value string `json:"value"`
|
|
Operator string `json:"operator"`
|
|
} `json:"filter_fields"`
|
|
CursorForward string `json:"cursor_forward"`
|
|
CursorBackward string `json:"cursor_backward"`
|
|
}
|
|
```
|
|
|
|
## Recursive Preloading with ParentTables and ChildTables
|
|
|
|
XFiles now supports recursive preloading of related entities:
|
|
|
|
```json
|
|
{
|
|
"tablename": "users",
|
|
"columns": ["id", "name"],
|
|
"limit": "10",
|
|
"parenttables": [
|
|
{
|
|
"tablename": "Company",
|
|
"columns": ["id", "name", "industry"],
|
|
"sort": ["-created_at"]
|
|
}
|
|
],
|
|
"childtables": [
|
|
{
|
|
"tablename": "Orders",
|
|
"columns": ["id", "total", "status"],
|
|
"limit": "5",
|
|
"sort": ["-order_date"],
|
|
"filter_fields": [
|
|
{"field": "status", "operator": "eq", "value": "completed"}
|
|
],
|
|
"childtables": [
|
|
{
|
|
"tablename": "OrderItems",
|
|
"columns": ["id", "product_name", "quantity"],
|
|
"recursive": true
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### How Recursive Preloading Works
|
|
|
|
- **ParentTables**: Preloads parent relationships (e.g., User -> Company)
|
|
- **ChildTables**: Preloads child relationships (e.g., User -> Orders -> OrderItems)
|
|
- **Recursive**: When `true`, continues preloading the same relation recursively
|
|
- Each nested table can have its own:
|
|
- Column selection (`columns`, `omit_columns`)
|
|
- Filtering (`filter_fields`, `sql_and`)
|
|
- Sorting (`sort`)
|
|
- Pagination (`limit`)
|
|
- Further nesting (`parenttables`, `childtables`)
|
|
|
|
### Relation Path Building
|
|
|
|
Relations are built as dot-separated paths:
|
|
- `Company` (direct parent)
|
|
- `Orders` (direct child)
|
|
- `Orders.OrderItems` (nested child)
|
|
- `Orders.OrderItems.Product` (deeply nested)
|
|
|
|
## Notes
|
|
|
|
- Individual headers (like `x-select-fields`, `x-sort`, etc.) can still be used alongside `x-files`
|
|
- X-Files populates `ExtendedRequestOptions` which is then processed by the normal query building logic
|
|
- ParentTables and ChildTables are converted to `PreloadOption` entries with full support for:
|
|
- Column selection
|
|
- Filtering
|
|
- Sorting
|
|
- Limit
|
|
- Recursive nesting
|
|
- The relation name in ParentTables/ChildTables should match the GORM/Bun relation field name on the model
|