feat: implement new feature for enhanced user experience

This commit is contained in:
2026-05-17 14:19:45 +00:00
parent db968ab318
commit f332c707b7
214 changed files with 424 additions and 2562 deletions
@@ -344,7 +344,6 @@ Edit `types/global.d.ts`:
```typescript
interface MyCollectionEntry {
id?: string
_id?: string
active?: boolean
name?: string
// ... fields matching your YAML
+51 -1
View File
@@ -292,6 +292,31 @@ const result = await postDBEntry("content", { name: "New Page", active: true })
const { data, count } = await api<MyType[]>("mycollection", { filter: { active: true }, limit: 20 })
```
### `aggregate` for sub-queries
The server supports an `aggregate` parameter to compute reverse aggregates against another collection and store the result under `_aggregate`. This efficiently calculates counts, sums, existence, etc. without embedding the target documents.
```typescript
const res = await api<MyEntry[]>("mycollection", {
filter: { active: true },
params: {
// String syntax: "collection:foreignField:op:valueField:as"
aggregate: "posts:categoryId:count",
// JSON syntax for advanced use cases (custom source field, filtering)
aggregate: JSON.stringify({
collection: "comments",
foreignField: "entryId",
op: "count",
filter: { approved: true },
as: "approvedComments",
}),
},
})
// Result in res.data[0]._aggregate.postsCount and res.data[0]._aggregate.approvedComments
```
Available operations: `count` (default), `exists`, `sum`, `avg`, `min`, `max`.
### Error handling
```typescript
@@ -311,6 +336,31 @@ try {
}
```
### `aggregate` for sub-queries
The server supports an `aggregate` parameter to compute reverse aggregates against another collection and store the result under `_aggregate`. This efficiently calculates counts, sums, existence, etc. without embedding the target documents.
```typescript
const res = await api<MyEntry[]>("mycollection", {
filter: { active: true },
params: {
// String syntax: "collection:foreignField:op:valueField:as"
aggregate: "posts:categoryId:count",
// JSON syntax for advanced use cases (custom source field, filtering)
aggregate: JSON.stringify({
collection: "comments",
foreignField: "entryId",
op: "count",
filter: { approved: true },
as: "approvedComments",
}),
},
})
// Result in res.data[0]._aggregate.postsCount and res.data[0]._aggregate.approvedComments
```
Available operations: `count` (default), `exists`, `sum`, `avg`, `min`, `max`.
### Error handling guidelines
| Scenario | Approach |
@@ -426,7 +476,7 @@ Nicht aufgeführte Felder (z.B. `description`, `specs`) entfallen spart Band
- **Never `spaNavigate()` in SSR** — always guard with `typeof window !== "undefined"`.
- **Store subscriptions in modules** — if subscribing to stores outside components, remember to unsubscribe to prevent memory leaks.
- **API PUT returns only changed fields** — don't expect a full object back from PUT requests.
- **`_id` not `id` for filters** — API filters use MongoDB's `_id`, but response objects may have both `id` and `_id`.
- **`_id` not `id` for filters** — API filters use MongoDB's `_id`, but response objects only have `id` as string via API.
- **`$location` strips trailing slashes** — `/about/` becomes `/about` (except root `/`).
- **Content cache is 1 hour** — `getCachedEntries` caches in memory for 1h. For admin previews, use `getDBEntries` (uncached).
- **`$effect` alone is not SSR** — server-side rendering must trigger the same data path explicitly outside browser-only reactive effects.