Saving recommended updates by the Svelte Gemini agent.
This commit is contained in:
31
documentation/Aether_API_CRUD_V3_beta_recommendations.md
Normal file
31
documentation/Aether_API_CRUD_V3_beta_recommendations.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Aether API CRUD V3 Beta Recommendations
|
||||
|
||||
Following the initial migration of the Journals module to the V3 CRUD endpoints, the following architectural recommendations are proposed for the FastAPI backend to improve developer experience and frontend efficiency.
|
||||
|
||||
---
|
||||
|
||||
## 1. "View" Selection (`use_alt_tbl` Replacement)
|
||||
In V2, the `use_alt_tbl` flag was frequently used to fetch "rich" objects (e.g., including joined data like `person_name`).
|
||||
- **Recommendation:** Implement a `response_view` (or `view`) query parameter for both GET list and POST search endpoints.
|
||||
- **Example:** `GET /v3/crud/journal/?view=enriched`
|
||||
- **Goal:** Allow the client to request a heavier model with joined fields only when necessary, keeping the default response lightweight.
|
||||
|
||||
## 2. Hybrid Filtering for Search
|
||||
Currently, the `/search` endpoint requires a full JSON body even for simple standard filters like `enabled` or `hidden`.
|
||||
- **Recommendation:** Update the `POST .../search` endpoint to accept standard query parameters that automatically append `AND` conditions to the logic defined in the body.
|
||||
- **Example:** `POST /v3/crud/journal/search?enabled=true`
|
||||
- **Goal:** Simplifies frontend code for common toggles while still allowing complex logic in the POST body.
|
||||
|
||||
## 3. Standardized Full-Text Search Field
|
||||
The current migration uses a field named `default_qry_str` with a `match` operator for text search.
|
||||
- **Recommendation:** Implement a reserved top-level property in the Search Pydantic model (e.g., `_search_` or `query_string`) specifically for global text search.
|
||||
- **Goal:** Decouples the frontend from knowing specific database column names used for full-text indexing. The backend can then decide which columns (name, description, tags, etc.) to include in the search.
|
||||
|
||||
## 4. Explicit "Parent" Filtering in Search
|
||||
Filtering by parent (e.g., Account or Site) is a primary use case but currently requires manual injection into the `and` array.
|
||||
- **Recommendation:** Expose `for_obj_type` and `for_obj_id` as top-level arguments in the Search API.
|
||||
- **Goal:** Standardizes how parent context is passed, allowing the backend to more easily perform ownership and permission validation before executing the search.
|
||||
|
||||
---
|
||||
**Date:** 2026-01-02
|
||||
**Status:** Beta Feedback
|
||||
@@ -9,86 +9,48 @@ This guide explains how to update or create frontend functions to interact with
|
||||
| Feature | CRUD V2 (Legacy) | CRUD V3 (Modern) |
|
||||
| --- | --- | --- |
|
||||
| **Base Prefix** | `/v2/crud` | `/v3/crud` |
|
||||
| **List Suffix** | Uses `/list` (e.g., `/v2/crud/journal/list`) | **No suffix** (e.g., `/v3/crud/journal/`) |
|
||||
| **Nested Path** | Not supported in URL path | **Supported** (e.g., `/v3/crud/journal/{id}/journal_entry/`) |
|
||||
| **Order By** | Passed in **Headers** (`order_by_li`) | Passed as **Query Parameter** (`order_by_li`) |
|
||||
| **Complex Search**| Limited to GET `jp` (~2KB limit) | **POST `/search`** (Unlimited size) |
|
||||
| **Latency Simulation**| Not standardized | `X-Delay-ms` (Header) or `delay_ms` (Query) |
|
||||
| **List Suffix** | Uses `/list` | **No suffix** (e.g., `/v3/crud/journal/`) |
|
||||
| **Nested Path** | Not supported in URL | **Supported** (e.g., `/v3/crud/journal/{id}/journal_entry/`) |
|
||||
| **View Selection**| `tbl_alt`, `mdl_alt` | **`view` parameter** (e.g., `?view=enriched`) |
|
||||
| **Complex Search**| Limited to GET `jp` | **POST `/search`** (Unlimited size + Hybrid params) |
|
||||
| **Full-Text Search**| Manual column names | **Reserved `q` property** in SearchQuery |
|
||||
|
||||
---
|
||||
|
||||
## 2. Implementing V3 CRUD Functions
|
||||
|
||||
### A. List Top-Level Objects (GET)
|
||||
Use this for simple lists or filtering by a parent via query parameters.
|
||||
### A. List & Single Object (GET)
|
||||
Support for view selection allows fetching richer data models when needed.
|
||||
|
||||
```ts
|
||||
export async function get_ae_obj_li_v3({
|
||||
api_cfg,
|
||||
obj_type,
|
||||
for_obj_type,
|
||||
for_obj_id,
|
||||
enabled = 'enabled',
|
||||
hidden = 'not_hidden',
|
||||
limit = 100,
|
||||
offset = 0,
|
||||
order_by_li = null, // e.g., {"created_on": "DESC"}
|
||||
delay_ms = 0
|
||||
}) {
|
||||
// 1. Build V3 Endpoint (Note: No /list suffix)
|
||||
const endpoint = `/v3/crud/${obj_type}/`;
|
||||
|
||||
// 2. Build Query Params
|
||||
const params: any = {
|
||||
enabled,
|
||||
hidden,
|
||||
limit,
|
||||
offset
|
||||
};
|
||||
|
||||
if (for_obj_type) params.for_obj_type = for_obj_type;
|
||||
if (for_obj_id) params.for_obj_id = for_obj_id;
|
||||
if (order_by_li) params.order_by_li = JSON.stringify(order_by_li);
|
||||
if (delay_ms) params.delay_ms = delay_ms;
|
||||
|
||||
return await get_object({ api_cfg, endpoint, params });
|
||||
// Example: Get enriched journal details
|
||||
// GET /v3/crud/journal/{id}?view=enriched
|
||||
export async function get_ae_obj_v3({ api_cfg, obj_type, obj_id, view = 'default' }) {
|
||||
const endpoint = `/v3/crud/${obj_type}/${obj_id}`;
|
||||
return await get_object({ api_cfg, endpoint, params: { view } });
|
||||
}
|
||||
```
|
||||
|
||||
### B. Access Nested Objects (GET)
|
||||
V3 allows you to enforce parent-child relationships directly in the URL.
|
||||
|
||||
```ts
|
||||
// Example: Get all entries for a specific journal
|
||||
// GET /v3/crud/journal/{journal_id}/journal_entry/
|
||||
export async function get_nested_obj_li_v3({
|
||||
api_cfg,
|
||||
parent_type,
|
||||
parent_id,
|
||||
child_type,
|
||||
limit = 100
|
||||
}) {
|
||||
const endpoint = `/v3/crud/${parent_type}/${parent_id}/${child_type}/`;
|
||||
return await get_object({ api_cfg, endpoint, params: { limit } });
|
||||
}
|
||||
```
|
||||
|
||||
### C. Advanced Search (POST)
|
||||
Use the new `/search` endpoint for complex logic (AND/OR, LIKE, IN) that would exceed URL length limits.
|
||||
### B. Advanced & Hybrid Search (POST)
|
||||
The `/search` endpoint combines the power of complex logical bodies with the simplicity of query parameters.
|
||||
|
||||
```ts
|
||||
export async function search_ae_obj_v3({
|
||||
api_cfg,
|
||||
obj_type,
|
||||
search_query, // Complex SearchQuery object
|
||||
order_by_li = null
|
||||
search_query, // { q: "search term", and: [...] }
|
||||
enabled = 'enabled',
|
||||
view = 'default',
|
||||
for_obj_type,
|
||||
for_obj_id
|
||||
}) {
|
||||
const endpoint = `/v3/crud/${obj_type}/search`;
|
||||
|
||||
const params: any = {};
|
||||
if (order_by_li) params.order_by_li = JSON.stringify(order_by_li);
|
||||
// Standard filters can be passed as query params
|
||||
const params: any = { enabled, view };
|
||||
if (for_obj_type) params.for_obj_type = for_obj_type;
|
||||
if (for_obj_id) params.for_obj_id = for_obj_id;
|
||||
|
||||
// Note: search_query is sent in the BODY via POST
|
||||
return await post_object({
|
||||
api_cfg,
|
||||
endpoint,
|
||||
@@ -96,36 +58,26 @@ export async function search_ae_obj_v3({
|
||||
data: search_query
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
/**
|
||||
* Example search_query usage:
|
||||
* {
|
||||
* "and": [
|
||||
* { "field": "enable", "op": "eq", "value": true },
|
||||
* {
|
||||
* "or": [
|
||||
* { "field": "name", "op": "like", "value": "%Meeting%" },
|
||||
* { "field": "priority", "op": "gt", "value": 5 }
|
||||
* ]
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
*/
|
||||
### C. Standardized Global Search
|
||||
Use the `q` property in your search body for a general keyword search across indexed columns.
|
||||
|
||||
```json
|
||||
// POST /v3/crud/journal/search
|
||||
{
|
||||
"q": "Annual Meeting",
|
||||
"and": [
|
||||
{ "field": "enable", "op": "eq", "value": true }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Best Practices for V3
|
||||
|
||||
1. **Stop using Headers for Sorting**: In V2, we used `headers['order_by_li']`. In V3, always use `params['order_by_li']`.
|
||||
2. **Prefer `/search` for Filters**: If your query involves more than a simple `for_obj_id`, use the `POST .../search` endpoint. It is safer, more readable, and bypasses the 2083-character URL limit.
|
||||
3. **Non-Blocking UI**: Use the `delay_ms` parameter during development to test how your Svelte components handle loading states and skeleton screens.
|
||||
4. **Singular Nouns**: Always use singular names for `obj_type` (e.g., `journal`, not `journals`), following the backend's `obj_type_kv_li` registry.
|
||||
|
||||
---
|
||||
|
||||
## 4. Special Case: Account Context
|
||||
V3 strictly enforces account context. Ensure your `api_cfg` logic correctly sets the `X-Account-ID` header.
|
||||
|
||||
* If a request doesn't need an account (e.g., public site data), set the `X-No-Account-ID: bypass` header.
|
||||
* If using a temporary token, use the `x_no_account_id_token` query parameter.
|
||||
1. **Use `view` for Rich Data**: Instead of manually joining data in separate calls, use `?view=enriched` or `?view=detail` if defined in the backend.
|
||||
2. **Hybrid Search**: Use query parameters for simple toggles (enabled/hidden) and the POST body for complex logic.
|
||||
3. **Global Search**: Always prefer the `q` property for text search instead of manually targeting `default_qry_str`.
|
||||
4. **Singular Nouns**: Always use singular names for `obj_type` (e.g., `journal`).
|
||||
Reference in New Issue
Block a user