Saving updated notes.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Aether API V3 Frontend Integration Guide (Svelte/TypeScript)
|
||||
|
||||
This guide explains how to update or create frontend functions to interact with the new **Aether API V3 CRUD** endpoints. V3 introduces a nested URL structure, a powerful POST-based search, and improved performance.
|
||||
This guide explains how to update or create frontend functions to interact with the new **Aether API V3 CRUD** and **Action** endpoints. V3 introduces a nested URL structure, a powerful POST-based search, and specialized "Action" routes for binary data.
|
||||
|
||||
---
|
||||
|
||||
@@ -37,33 +37,13 @@ Once the API Key is validated, you must specify the context of your request.
|
||||
3. **Guest / Anonymous Access**: Provide a **Safe Guest JWT**.
|
||||
* **Header:** `x-aether-api-key: <your_app_key>` (No Account Header)
|
||||
* **Query Param:** `?jwt=<guest_token>`
|
||||
* **Benefit:** Allows the backend to track cryptographically signed session state (e.g., site context) without granting full account access.
|
||||
|
||||
### C. Public Read Whitelist (Unauthenticated)
|
||||
The V3 architecture allows unauthenticated (**guest**) access to specific objects, provided a valid API Key is present.
|
||||
|
||||
* **Whitelisted Objects:** `site_domain`, `event`, `event_session`, `event_presentation`, `event_presenter`, `post`, `post_comment`, `archive`, `archive_content`, `hosted_file`.
|
||||
* **Behavior:** Requests to these objects will succeed without a user-level JWT, but are strictly limited to **Read-Only** operations (GET/Search).
|
||||
|
||||
### D. Passcode Authentication (Machine/Kiosk Logins)
|
||||
For guest machines or specialized kiosks, use the dedicated passcode endpoint to receive a scoped JWT.
|
||||
|
||||
* **Endpoint:** `POST /api/authenticate_passcode`
|
||||
* **Payload:** `{ "site_id": "<site_id_random>", "passcode": "<secret>" }`
|
||||
* **Response:** Returns a JWT containing the site's `account_id` and resolved role flags (`super`, `manager`, `administrator`).
|
||||
|
||||
### E. Fail-Fast on Auth Failures (401/403)
|
||||
The frontend implements a **Fail-Fast** policy for 401/403 errors. If the API returns these codes, the frontend **must not retry** automatically. It should stop and redirect the user or display an error.
|
||||
|
||||
---
|
||||
|
||||
## 3. Implementing V3 CRUD Functions
|
||||
|
||||
### A. List & Single Object (GET)
|
||||
Support for view selection allows fetching richer data models when needed.
|
||||
|
||||
```ts
|
||||
// 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}`;
|
||||
@@ -72,135 +52,88 @@ export async function get_ae_obj_v3({ api_cfg, obj_type, obj_id, view = 'default
|
||||
```
|
||||
|
||||
### B. Advanced & Hybrid Search (POST)
|
||||
The `/search` endpoint combines complex logical bodies with simple query parameters.
|
||||
|
||||
```ts
|
||||
export async function search_ae_obj_v3({
|
||||
api_cfg,
|
||||
obj_type,
|
||||
search_query, // { q: "search term", and: [...] }
|
||||
enabled = 'enabled',
|
||||
view = 'default'
|
||||
}) {
|
||||
// POST /v3/crud/{obj_type}/search
|
||||
export async function search_ae_obj_v3({ api_cfg, obj_type, search_query, enabled = 'enabled' }) {
|
||||
const endpoint = `/v3/crud/${obj_type}/search`;
|
||||
const params = { enabled, view };
|
||||
|
||||
return await post_object({ api_cfg, endpoint, params, data: search_query });
|
||||
}
|
||||
```
|
||||
|
||||
### C. Standardized Global Search (`q`)
|
||||
Use the `q` property in your search body for a keyword search.
|
||||
- **Wildcard**: `q: "%"` returns all records (respecting logical filters).
|
||||
- **Fallback**: Performs a `LIKE` search across all searchable fields if no index exists.
|
||||
|
||||
```json
|
||||
{
|
||||
"q": "Annual Meeting",
|
||||
"and": [{ "field": "enable", "op": "eq", "value": true }]
|
||||
return await post_object({ api_cfg, endpoint, params: { enabled }, data: search_query });
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Create, Update, & Delete
|
||||
## 4. Hosted File Management (Modern V3 Actions)
|
||||
|
||||
### A. Create (POST)
|
||||
V3 validates incoming JSON against the `mdl_in` Pydantic model.
|
||||
V3 uses specialized **"Action"** routes for binary operations to separate processing logic from standard metadata CRUD.
|
||||
|
||||
```ts
|
||||
// POST /v3/crud/{obj_type}/
|
||||
export async function create_ae_obj_v3({ api_cfg, obj_type, data }) {
|
||||
const endpoint = `/v3/crud/${obj_type}/`;
|
||||
return await post_object({ api_cfg, endpoint, data });
|
||||
}
|
||||
```
|
||||
### A. Upload Action
|
||||
**Path**: `POST /v3/action/hosted_file/upload`
|
||||
**Format**: `multipart/form-data`
|
||||
|
||||
### B. Update (PATCH)
|
||||
V3 uses `PATCH` for partial updates. Only provided fields are modified.
|
||||
| Field | Type | Required | Description |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `file_list` | File[] | Yes | One or more files to upload. |
|
||||
| `account_id` | String | Yes | Random ID of the owner account. |
|
||||
| `link_to_type`| String | Yes | Object type to link (e.g., `archive_content`). |
|
||||
| `link_to_id` | String | Yes | Random ID of the object to link. |
|
||||
|
||||
```ts
|
||||
// PATCH /v3/crud/{obj_type}/{obj_id}
|
||||
export async function update_ae_obj_v3({ api_cfg, obj_type, obj_id, data }) {
|
||||
const endpoint = `/v3/crud/${obj_type}/${obj_id}`;
|
||||
return await patch_object({ api_cfg, endpoint, data });
|
||||
}
|
||||
```
|
||||
**Query Parameters:**
|
||||
- `allowed_extensions`: Whitelist check (e.g., `?allowed_extensions=png&allowed_extensions=jpg`).
|
||||
- `delay_ms`: Simulate network delay for UI testing.
|
||||
|
||||
### C. Delete (DELETE)
|
||||
Supports soft-delete (`method=hide`) or hard-delete (`method=delete`).
|
||||
**Features:**
|
||||
- **Automatic Deduplication:** API checks SHA256 hashes. If a file exists on the server, it reuses the record and creates a new link instead of a duplicate upload.
|
||||
- **Relational Integrity:** Automatically creates `hosted_file_link` records.
|
||||
|
||||
```ts
|
||||
// DELETE /v3/crud/{obj_type}/{obj_id}?method=hide
|
||||
export async function delete_ae_obj_v3({ api_cfg, obj_type, obj_id, method = 'delete' }) {
|
||||
const endpoint = `/v3/crud/${obj_type}/${obj_id}`;
|
||||
return await delete_object({ api_cfg, endpoint, params: { method } });
|
||||
}
|
||||
```
|
||||
### B. Download & Streaming Action
|
||||
**Path**: `GET /v3/action/hosted_file/{id}/download`
|
||||
|
||||
**Features:**
|
||||
- **Streaming:** Supports standard `Range` headers for large files and video seeking.
|
||||
- **Auth Bypass:** Use `?site_key=<auth_key>` to download without an API Key header or JWT (useful for public kiosks).
|
||||
- **Testing:** Supports `delay_ms` query parameter.
|
||||
|
||||
### C. Deletion & Cleanup Action
|
||||
**Path**: `DELETE /v3/action/hosted_file/{id}`
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `link_to_type`| Query | null | The type of the link to remove. |
|
||||
| `link_to_id` | Query | null | The random ID of the link to remove. |
|
||||
| `rm_orphan` | Query | false | If true, physically delete file if no links remain. |
|
||||
| `method` | Query | `hide` | Cleanup method: `hide`, `disable`, or `delete` (hard). |
|
||||
| `fake_delete` | Query | false | **Testing Mode:** Verifies file/record existence without modification. |
|
||||
|
||||
---
|
||||
|
||||
## 5. Specialized Endpoints
|
||||
## 5. Hosted File Management (Legacy)
|
||||
|
||||
### A. Schema Discovery
|
||||
**Path**: `GET /v3/crud/{obj_type}/schema`
|
||||
Returns DB column definitions and Pydantic field rules for dynamic UI builders.
|
||||
The following endpoints are maintained for backward compatibility but should be migrated to V3 Actions.
|
||||
|
||||
### B. Secure File Downloads (JWT in URL)
|
||||
For browsers downloading files, you can pass the JWT directly in the query string.
|
||||
- `GET /v3/crud/hosted_file/{id}/?jwt={token}`
|
||||
| Method | Endpoint | Description |
|
||||
| :--- | :--- | :--- |
|
||||
| `POST` | `/hosted_file/upload_files` | Legacy multi-upload. |
|
||||
| `GET` | `/hosted_file/{id}/download` | Legacy download. |
|
||||
| `GET` | `/hosted_file/{id}/stream` | Legacy buffered streamer. |
|
||||
| `DELETE` | `/hosted_file/{id}` | Legacy deletion. |
|
||||
|
||||
---
|
||||
|
||||
## 6. The "ID Vision" Standard (2026)
|
||||
|
||||
V3 uses a **String-Only ID Vision**. The frontend and external agents NEVER handle or store internal database integers.
|
||||
V3 uses a **String-Only ID Vision**. The frontend NEVER handles or stores database integers.
|
||||
|
||||
### A. Automatic ID Mapping (Output)
|
||||
Internal `id_random` fields are renamed to clean, short names in the JSON response.
|
||||
- **`id`**: Unique random identifier for the record.
|
||||
- **`account_id`**: Unique random identifier for the parent account.
|
||||
|
||||
### B. Intelligent Mapping (Input/Search)
|
||||
You can send string IDs back to the API using the same clean names.
|
||||
- **Search**: Filter by `account_id` using the random string value.
|
||||
- **Save**: Send `account_id: "nqOzejLCDXM"` in a payload; the API resolves it to an integer.
|
||||
1. **Automatic Mapping:** Internal `id_random` fields are mapped to `id` and `account_id` in JSON responses.
|
||||
2. **Intelligent Resolution:** You can send random string IDs back to the API in any `*_id` field; the API resolves them to integers before database insertion.
|
||||
|
||||
---
|
||||
|
||||
## 7. Standard Patterns & Pitfalls
|
||||
## 7. Structured Error Handling
|
||||
|
||||
### A. Permissive Update Mode (Available)
|
||||
To simplify state management, V3 supports a **Permissive Update Mode** which ignores unknown extra fields in the payload.
|
||||
- **Header:** `x-ae-ignore-extra-fields: true`
|
||||
- **Use when:** Sending back objects that contain read-only technical metadata.
|
||||
|
||||
### B. Structured Error Handling (Rich Bubbling)
|
||||
V3 returns machine-readable error objects in `meta.details` for failures (400/500).
|
||||
|
||||
**Example Error Response:**
|
||||
```json
|
||||
{
|
||||
"meta": {
|
||||
"success": false,
|
||||
"status_code": 400,
|
||||
"details": {
|
||||
"category": "database_schema",
|
||||
"code": 1054,
|
||||
"message": "Unknown column 'notes' in 'SET'",
|
||||
"recoverable": false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
V3 returns machine-readable error objects in `meta.details` for failures.
|
||||
|
||||
**Common Categories:**
|
||||
- **`database_duplicate`**: Non-unique value (Code 1062).
|
||||
- **`database_constraint`**: Foreign key violation (Codes 1451, 1452).
|
||||
- **`database_schema`**: Invalid column name (Codes 1054, 1146).
|
||||
- **`database_connection`**: Temporary DB issues (`recoverable: true`).
|
||||
- **`validation`**: Pydantic validation failed.
|
||||
|
||||
### C. Booleans: 'NULL' vs '0'
|
||||
**Pitfall:** Fields like `hide` can be `NULL` in the DB.
|
||||
**Standard:** Handle `null`, `undefined`, and `0` identically for boolean checks.
|
||||
- `database_duplicate`: Non-unique value (Code 1062).
|
||||
- `database_constraint`: Foreign key violation (Codes 1451, 1452).
|
||||
- `database_schema`: Invalid column name (Codes 1054, 1146).
|
||||
- `validation`: Pydantic validation failed (Check `details` for field-specific errors).
|
||||
Reference in New Issue
Block a user