Saving recommended updates by the Svelte Gemini agent.

This commit is contained in:
Scott Idem
2026-01-02 18:57:37 -05:00
parent 8c0be931c0
commit bf16f988c5
6 changed files with 160 additions and 178 deletions

View 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

View File

@@ -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`).