@lotics/app-sdk 0.79.1 → 0.79.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/data_fetching.md +12 -1
- package/docs/queries.md +8 -0
- package/package.json +1 -1
package/docs/data_fetching.md
CHANGED
|
@@ -89,6 +89,17 @@ server validates system conditions by `type` and never reads `field_key` on them
|
|
|
89
89
|
- **`error`** is a `string | null`. A failed query surfaces immediately — there is **no automatic
|
|
90
90
|
retry** (no retry loop that masks the error). The last successful rows for the same key stay
|
|
91
91
|
rendered. The next focus revalidation or an explicit `refetch()` re-runs it.
|
|
92
|
+
- **Never derive a FIGURE from `rows` without gating on `error`.** On a failure `rows` is `[]`,
|
|
93
|
+
and `[]` is indistinguishable from a genuinely empty result — so `rows.reduce(…)` returns `0`,
|
|
94
|
+
`rows.length` returns `0`, and a screen states a confident number that no query answered. This
|
|
95
|
+
is the one place the empty-vs-broken distinction is load-bearing: a list that renders nothing
|
|
96
|
+
looks obviously wrong, whereas a total that reads `0` looks *fine*. It cost a sales register
|
|
97
|
+
nine days of showing every rep `0 ₫` of commission, because one query's runtime filter named a
|
|
98
|
+
column it did not project and nothing read `error`. A count, a sum, a "N of M", a progress
|
|
99
|
+
meter, a badge — anything a reader would act on — renders a dash and the failure, never a
|
|
100
|
+
number, while `error !== null`. Note a key CHANGE resets this: a new `params`/`filter`/`sort`
|
|
101
|
+
is a fresh key with no prior rows, so the "last successful rows stay rendered" behaviour above
|
|
102
|
+
does not save you.
|
|
92
103
|
- **`refetch()`** re-runs the query. Call it after a known mutation point — a successful
|
|
93
104
|
`useWorkflow` call — to pull the latest state (see [./mutations.md](./mutations.md)).
|
|
94
105
|
`usePaginatedQuery.refetch()` refreshes the page, and the count when the hook owns it
|
|
@@ -110,7 +121,7 @@ server validates system conditions by `type` and never reads `field_key` on them
|
|
|
110
121
|
| `query timed out after 15s — narrow the filter or simplify the query` | The query hit the per-query statement timeout (15 s). Usually an unindexed predicate scanning a large table — filter *shape* drives latency; see the performance contract in [./queries.md](./queries.md). | Narrow with an indexed filter or `search`, reduce the work per request. |
|
|
111
122
|
| `The app is handling too many requests right now. Please retry in a moment.` | The server's bounded-concurrency gate shed the query under load (a 503). Distinct from a query error — nothing is wrong with the query itself. | Retry (e.g. surface a retry button wired to `refetch()`); the hook does not auto-retry. |
|
|
112
123
|
| `query execution failed` | The query failed at the database. Deliberately generic — database internals are never sent to the client. | The app author diagnoses from the platform's server logs; the app surfaces the message. |
|
|
113
|
-
| A specific validation message | e.g. an un-projected `field_key` in runtime `sort`/`filter`, invalid params, an unknown alias. | Fix the call site — these are contract violations, not transient. |
|
|
124
|
+
| A specific validation message | e.g. an un-projected `field_key` in runtime `sort`/`filter`, invalid params, an unknown alias. An unknown column names every column the query DOES project, so the valid set is in the message. | Fix the call site — these are contract violations, not transient. |
|
|
114
125
|
|
|
115
126
|
## Pagination — two models
|
|
116
127
|
|
package/docs/queries.md
CHANGED
|
@@ -116,6 +116,14 @@ source_table_id?, source_field_key? }` per column. Rows are plain objects keyed
|
|
|
116
116
|
column name; decode cells with the SDK readers (`row.*`, `readSelect`, `readMembers`,
|
|
117
117
|
`readLinks`, `readFiles` — see [data_fetching.md](./data_fetching.md)).
|
|
118
118
|
|
|
119
|
+
**`source_fields_by_table_id` is always `{}`** — the key is part of the shape, the map is not
|
|
120
|
+
filled. The server reads the source tables' field definitions to resolve option and member
|
|
121
|
+
cells and then keeps them: sending them beside every page was 94% of a real register
|
|
122
|
+
response's compressed bytes, for a map no reader wanted there. **The complete option sets —
|
|
123
|
+
every option including those no loaded row holds, with colors — are `useFieldOptions`**
|
|
124
|
+
(`/field-options`, which derives them from the same definitions); a cell's own `{ key, label }`
|
|
125
|
+
comes down on the cell. See [members_and_options.md](./members_and_options.md).
|
|
126
|
+
|
|
119
127
|
Delivery-layer enrichment (applied to the response, per request):
|
|
120
128
|
|
|
121
129
|
- **`files` cells** — each entry gains a presigned `url` + `thumbnail_url` (24 h TTL) and
|