Skip to content
Merged
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
1 change: 1 addition & 0 deletions content/docs/(reference)/api-reference/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ The reference groups operations by what they act on. The groups and the operatio
| Event stream | Changes to items and edges, streamed as they happen | [Stream change events](/api-reference/event-stream/streamEvents) |
| Webhooks | Changes sent to a URL you choose, and each delivery's record | [Create a webhook](/api-reference/webhooks/createWebhook) |
| Folders | A folder's settings, held as a `system.folder` item | [Create a folder](/api-reference/folders/createFolder) |
| Views | Saved lists of items and how each app shows them, held as `system.view` items | [Create a view](/api-reference/views/createView) |
| Connectors | Processes outside the server that read and write on your behalf, with their heartbeats and runs | [Register a connector](/api-reference/connectors/registerConnector) |
| Connector state | What the instance keeps for a connector's source: its hold, its state and its agreements | [Take a connector hold](/api-reference/connector-state/takeConnectorHold) |
| Inbound webhooks | Addresses where a service sends requests to a connector, and the deliveries Marfa stores for it | [Create an inbound endpoint](/api-reference/inbound-webhooks/createInboundEndpoint) |
Expand Down
3 changes: 2 additions & 1 deletion content/docs/catalog/(system)/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"defaultOpen": false,
"pages": [
"connection",
"folder"
"folder",
"view"
]
}
9 changes: 9 additions & 0 deletions content/docs/catalog/(system)/view.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
title: View
description: "A saved list of items, held here and shared by every app: which items, and how each layout shows them. Written only through /views: created, changed at a version, and deleted, which removes it at once with no trash. Lifecycle bounded to active | revoked. Has no tier."
identifier: system.view
---

[Save a list as a view](/guides/list-filter-search#save-a-list-as-a-view) uses the view operations that write these settings. No item operation writes a view: each one refuses a `system.*` type with `403 type_not_permitted` ([`items/system-types`](https://github.com/withmarfa/marfa/blob/main/conformance/spec/items.md#itemssystem-types)).

<include cwd>src/generated/catalog/system.view.md</include>
44 changes: 44 additions & 0 deletions content/docs/guides/list-filter-search.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,50 @@ Each entry has a `starts_at`, an `ends_at` where the event has one, and the `ite

The whole window comes in one page, in order of `starts_at`. A window spans at most **400 days**, and Marfa refuses one with too many occurrences rather than trim it, so narrow the window. If the answer carries `expansion_incomplete: true`, **the calendar is missing something**: `series_errors` names the series that couldn't be unfolded.

## Save a list as a view

A [view](/catalog/view) saves a listing so every app shows the same one: its `query` says which items it lists, and its `layouts` say how each one shows them. [Create a view](/api-reference/views/createView) with a `title`, a `query` of `types`, `tier`, `state`, `filter` and `beneath` that says which items it lists, and at least one layout, each with an `id` and a `kind` (`list`, `table`, `board`, `gallery`, `calendar`, `timeline`, `chart` or `map`):

```bash tab="CLI" tab-group="client"
marfa views create --title "Open tasks" \
--query '{"types":["core.task"],"filter":"properties.status neq \"completed\""}' \
--layouts '[{"id":"main","kind":"board","group":{"by":"properties.priority"}}]'
```

```http tab="HTTP"
POST /views
Authorization: Bearer <key>
Content-Type: application/json

{
"title": "Open tasks",
"query": { "types": ["core.task"], "filter": "properties.status neq \"completed\"" },
"layouts": [
{ "id": "main", "kind": "board", "group": { "by": "properties.priority" } }
]
}
```

```ts tab="TypeScript"
const { data } = await marfa.POST("/views", {
body: {
title: "Open tasks",
query: { types: ["core.task"], filter: 'properties.status neq "completed"' },
layouts: [
{ id: "main", kind: "board", group: { by: "properties.priority" } },
],
},
});
```

The answer is the view as a `system.view` item at `version` 1. A view never answers the items it lists: an app runs the `query` itself and shows them as the layout says. A layout only arranges, so it takes no filter of its own.

- **To change a view,** [update it](/api-reference/views/updateView) with the `version` you read and the settings you change. Each one you name is replaced whole, `layouts` included, and a change based on an older version still applies when nobody changed the same setting since.
- **To delete a view,** [delete it](/api-reference/views/deleteView). It's gone at once, with no trash.
- **To read a view,** [get it](/api-reference/items/getItem) by its `id`, or list the type `system.view`, like any other item.

Writing a view needs write on `system.view`, and reading one needs read; a `content:*` scope reaches neither. Marfa refuses a malformed setting before it writes anything, and names it in `details.errors[0].path`, such as `layouts.0.group.bucket`. The rules are in the [views](https://github.com/withmarfa/marfa/blob/main/conformance/spec/views.md) chapter of the contract.

## When a query is refused

Marfa refuses a query it can't answer exactly, rather than answer a different one:
Expand Down
Loading
Loading