mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2026-01-10 05:04:25 +00:00
Added x-files feature
This commit is contained in:
213
pkg/restheadspec/xfiles_example.md
Normal file
213
pkg/restheadspec/xfiles_example.md
Normal file
@@ -0,0 +1,213 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user