Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 68 additions & 49 deletions frontend-integration/01-totaljs-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ DELETE /posts/abc123 → delete post

**Total.js API Routing:**
```
POST /api/ { "schema": "posts_list" }
POST /api/ { "schema": "posts_read/abc123" }
POST /api/ { "schema": "posts_create", "data": { ... } }
POST /api/ { "schema": "posts_update/abc123", "data": { ... } }
POST /api/ { "schema": "posts_remove/abc123" }
POST /api/ { "schema": "Posts|list" }
POST /api/ { "schema": "Posts|read", "data": { "id": "abc123" } }
POST /api/ { "schema": "Posts|create", "data": { ... } }
POST /api/ { "schema": "Posts|update", "data": { "id": "abc123", ... } }
POST /api/ { "schema": "Posts|remove", "data": { "id": "abc123" } }
```

| Concern | REST | Total.js API Routing |
|---------|------|----------------------|
| HTTP endpoint count | One per resource | **One for everything** |
| HTTP verbs | GET, POST, PUT, DELETE | **Always POST** |
| Resource identity | In the URL path | In the `schema` string |
| Resource identity | In the URL path | In the `data` object |
| Action | In the HTTP verb | In the `schema` string |
| Query params | On the URL | Appended to the `schema` string |
| Request body | Payload only | `{ schema, data }` envelope |
Expand All @@ -56,11 +56,23 @@ x-token: <session_token> ← omitted for public schemas

This is the only URL your client calls for **JSON API work**. File upload/download, health checks, and WebSockets are ordinary HTTP/WS routes and are documented separately. Do not invent a REST surface for CRUD.

The path is project-defined. Many backends use `/api/`. Some register API routing on the root path:
The path is project-defined. Many backends use `/api/`. An action can register API routing on the root path:

```javascript
ROUTE('API / +account_login --> Auth/login');
ROUTE('+API / -account_logout --> Auth/logout');
NEWACTION('Account|login', {
input: '*email,*password',
route: 'API /',
action: function($, model) {
// Public login action
}
});

NEWACTION('Account|logout', {
route: '+API /',
action: function($) {
// Protected logout action
}
});
```

The client then calls `POST https://api.example.com/` with the same `{ schema, data }` envelope. Make the API path configurable instead of hard-coding `/api/`.
Expand All @@ -69,62 +81,69 @@ The client then calls `POST https://api.example.com/` with the same `{ schema, d

## The schema string

The schema string is the complete address of an operation. It has up to three parts:
The schema string identifies a stable backend action. Input values such as IDs belong in `data`:

```
<resource>_<action>
<resource>_<action>/<id>
<resource>_<action>/<id>?key=value&key=value
<Namespace>|<action>
<Namespace>|<action>?key=value&key=value
```

### Part 1 — Resource

The domain entity being acted upon: `account`, `posts`, `users`, `orders`, `messages`, etc. This mirrors your backend schema definition name.
The action namespace being addressed: `Posts`, `Users`, `Orders`, `Messages`, etc.

### Part 2 — Action

A verb describing what to do. Common conventions:

| Action suffix | Meaning |
| Action name | Meaning |
|---------------|---------|
| `_list` | Return all records (optionally filtered) |
| `_read` | Return one record by ID |
| `_create` | Create a new record |
| `_insert` | Alias for create (used interchangeably) |
| `_update` | Update an existing record |
| `_remove` | Delete a record |
| `_toggle_<field>` | Toggle a boolean field |
| `_search` | Free-text or semantic search |
| `_export` | Export data |
| `_import` | Import data |
| `\|list` | Return all records (optionally filtered) |
| `\|read` | Return one record by ID |
| `\|create` | Create a new record |
| `\|insert` | Alias for create (used interchangeably) |
| `\|update` | Update an existing record |
| `\|remove` | Delete a record |
| `\|toggle_<field>` | Toggle a boolean field |
| `\|search` | Free-text or semantic search |
| `\|export` | Export data |
| `\|import` | Import data |

Custom actions beyond CRUD are common and encouraged — they make intent explicit:

```
account_logout
account_password ← change password
account_verify ← verify email
session_refresh
notifications_mark_read
Account|logout
Account|password ← change password
Account|verify ← verify email
Session|refresh
Notifications|mark_read
```

### Part 3 — Dynamic segment (optional)
### Input parameters

A resource ID or other path parameter appended after a `/`:
Declare required action input on the backend and send it in `data`:

```javascript
NEWACTION('Posts|read', {
input: '*id',
route: '+API /api/',
action: function($, model) {
// model.id
}
});
```
posts_read/abc123
posts_update/abc123
users_remove/usr_9f4k2

```json
{ "schema": "Posts|read", "data": { "id": "abc123" } }
```

### Query parameters (optional)

Appended directly to the schema string — **not** to the HTTP URL:

```json
{ "schema": "posts_list?page=2&limit=20&status=published" }
{ "schema": "posts_search?limit=10&mode=semantic", "data": { "query": "..." } }
{ "schema": "Posts|list?page=2&limit=20&status=published" }
{ "schema": "Posts|search?limit=10&mode=semantic", "data": { "query": "..." } }
```

---
Expand All @@ -149,7 +168,7 @@ You do not need to explore or version an endpoint tree. The backend developer te

**5. Actions are self-documenting.**

`orders_cancel/ord_123` is unambiguous. `DELETE /orders/ord_123` requires knowledge that DELETE means "cancel" in this context and not "archive" or "refund".
`Orders|cancel` with `{ "id": "ord_123" }` in `data` is unambiguous. `DELETE /orders/ord_123` requires knowledge that DELETE means "cancel" in this context and not "archive" or "refund".

---

Expand All @@ -175,19 +194,19 @@ Frontend auth behavior should be documented separately by the backend team or ve
## Schema naming conventions summary

```
account_login public auth
account_logout protected auth
account get current user profile (protected)
account_update update profile (protected)
Account|login public auth
Account|logout protected auth
Account|read get current user profile (protected)
Account|update update profile (protected)

posts_list list (protected or public depending on backend)
posts_read/{id} read one
posts_create create
posts_update/{id} update
posts_remove/{id} delete
Posts|list list (protected or public depending on backend)
Posts|read read one; send id in data
Posts|create create
Posts|update update; send id in data
Posts|remove delete; send id in data

posts_list?page=2 pagination via query param in schema
posts_search?limit=5 search with filter params
Posts|list?page=2 pagination via query param in schema
Posts|search?limit=5 search with filter params
```

Conventions may vary slightly per project. The backend developer defines the schema names — this guide describes the patterns used in a standard Total.js API Routing setup.
46 changes: 23 additions & 23 deletions frontend-integration/02-request-response.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ POST https://totaljsbackend.com/api/
Always use one API endpoint. The path is project-specific:

- Generic examples often use `POST /api/`
- Projects with `ROUTE('API / ...')` use `POST /`
- Actions declared with a root `route: 'API /'` use `POST /`

Keep the path configurable, for example with `EXPO_PUBLIC_API_PATH`.

Expand All @@ -37,30 +37,30 @@ Do not attach tokens to known public schemas if the app can avoid it. Keep a cli

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `schema` | string | Always | The operation address. May include `/{id}` and `?query=params`. |
| `data` | object | When the operation needs input | Omit entirely for operations that take no parameters (e.g. list, read). |
| `schema` | string | Always | The stable action name. May include `?query=params`. |
| `data` | object | When the operation needs input | Contains declared inputs such as `id`; omit only when the action needs no input. |

### Examples

**List — no data:**
```json
{ "schema": "posts_list" }
{ "schema": "Posts|list" }
```

**List with pagination — params in schema string:**
```json
{ "schema": "posts_list?page=2&limit=20&status=published" }
{ "schema": "Posts|list?page=2&limit=20&status=published" }
```

**Read one — ID in schema string:**
**Read one — ID in data:**
```json
{ "schema": "posts_read/abc123" }
{ "schema": "Posts|read", "data": { "id": "abc123" } }
```

**Create — payload in data:**
```json
{
"schema": "posts_create",
"schema": "Posts|create",
"data": {
"title": "Hello World",
"body": "Content here",
Expand All @@ -69,23 +69,23 @@ Do not attach tokens to known public schemas if the app can avoid it. Keep a cli
}
```

**Update — ID in schema, fields in data:**
**Update — ID and fields in data:**
```json
{
"schema": "posts_update/abc123",
"data": { "title": "Updated Title", "status": "published" }
"schema": "Posts|update",
"data": { "id": "abc123", "title": "Updated Title", "status": "published" }
}
```

**Delete — no data:**
**Delete — ID in data:**
```json
{ "schema": "posts_remove/abc123" }
{ "schema": "Posts|remove", "data": { "id": "abc123" } }
```

**Search — params in schema, query in data:**
```json
{
"schema": "posts_search?limit=10&mode=semantic",
"schema": "Posts|search?limit=10&mode=semantic",
"data": { "query": "how to get started" }
}
```
Expand All @@ -95,7 +95,7 @@ Do not attach tokens to known public schemas if the app can avoid it. Keep a cli
Some Total.js projects support `GET /?schema=<schema_string>` for read-only helper calls. Treat this as project-specific convenience. The durable contract remains the JSON envelope:

```text
GET /?schema=posts_list%3Flimit%3D20
GET /?schema=Posts%7Clist%3Flimit%3D20
```

---
Expand Down Expand Up @@ -155,13 +155,13 @@ Production clients should centralize this normalization:

| Operation | `value` |
|-----------|---------|
| `*_list` | Array of records |
| `*_read/{id}` | Single record object |
| `*_create` / `*_insert` | Created record or its ID |
| `*_update/{id}` | Updated record |
| `*_remove/{id}` | `true` or `null` |
| `account_login` | Session token string (or nested in response root as `token`) |
| `account` (profile) | Current user object |
| `*\|list` | Array of records |
| `*\|read` | Single record object |
| `*\|create` / `*\|insert` | Created record or its ID |
| `*\|update` | Updated record |
| `*\|remove` | `true` or `null` |
| `Account\|login` | Session token string (or nested in response root as `token`) |
| `Account\|read` (profile) | Current user object |

### Paginated response

Expand Down Expand Up @@ -252,7 +252,7 @@ Step 1 — Upload file:

Step 2 — Register in the app:
POST https://totaljsbackend.com/api/
{ "schema": "documents_create", "data": { id, url, name, size, type } }
{ "schema": "Documents|create", "data": { id, url, name, size, type } }
```

### Upload response shape
Expand Down
Loading