Skip to Content

view line

view 將 saved view 納入同一套 ref/state 管理。它描述可重建的 filter、sort、column set,以及可選的 list/matrix/timeline layout;建立者是 server-owned audit identity,不屬於可攜的 IaC spec。

JSONL Line

{"kind":"view","table":"orders","ref":"open_orders","spec":{"name":"Open orders","is_shared":true,"config":{"filters":{"status":"open"},"sort_by":"order_no","sort_order":"asc","columns":["order_no","status"]}}}

欄位契約

頂層對應 IacViewLine:必填 kind: "view"、table、ref;可選 state(預設 present)與 renamed_from;present 必須提供 object spec,只有純 rename 可省略;absent 禁止 spec。

IaC model 將 spec 保留為 dict。Apply 不會執行 REST 的 CustomTableSavedViewPayload model:它只讀取 name、config 與 is_shared,並依驗證錯誤所述檢查 config:

欄位必填精確契約
name是string;保存的名稱最多 64 字元。IaC 寫入前不會檢查,請保持非空且不超過這個長度
config否object,預設空 config
is_shared否boolean。Create 時省略會建立私人 view;update 時省略則保留 live 值。IaC 分享 view 不需要 moderator 權限

其他頂層 key 既不會被拒絕,也不會被套用。Plan 每次都拿它和 live view 比較,所以像 created_by 這樣的雜 key 會讓該行永遠規劃 update。

config 可選欄位是 filters(預設 {})、stored_filters(最多 20)、computed_filters(最多 3)、any_of(1–10 個 OR 群組,每組 1–10 條 predicate;空清單會被拒絕)、q(最多 200 字元)、sort_by、sort_order(asc/desc,預設 asc)、sort(多欄排序,最多 3 個 key,與 sort_by 互斥)、columns(最多 200,預設 [])、kind(list/matrix/timeline,預設 list),以及對應 kind 的 matrix 或 timeline 物件。不要提供 created_by、view ID、timestamps 或 response-only is_owner。

Layout kinds

Matrix line 的巢狀設定可全程使用 authored column refs:

{"kind":"view","table":"orders","ref":"weekly_matrix","spec":{"name":"Weekly order matrix","is_shared":true,"config":{"kind":"matrix","matrix":{"row_column":"owner","bucket_column":"due_at","column_bucket":"week","cell_column":"order_no"},"columns":["order_no","owner","due_at"]}}}
Kind必要子設定精確契約
list無禁止 matrix 與 timeline
matrixmatrix必填 row_column、bucket_column、cell_column。bucket_column 必須是 date、datetime 或 select。column_bucket 可為 day、week、month(預設 day);select 必須使用 day。
timelinetimeline必填 lane_column、start_column、end_column。Start/end 必須同為 date 或同為 datetime。label_column 可省略;slot_minutes 為 5–1440,預設 30。

只有選到對應 kind 時,該子設定才是必填;其他 kind 一律禁止它。例如:

{"kind":"view","table":"orders","ref":"delivery_timeline","spec":{"name":"Delivery timeline","config":{"kind":"timeline","timeline":{"lane_column":"owner","start_column":"starts_at","end_column":"ends_at","label_column":"order_no","slot_minutes":30}}}}

Plan/apply 會 fail closed 地解析每個 layout column ref、持久化為內部鍵,並驗證與 REST 相同的 bucket/range type gates。後端保存的是 presentation config,apply 時仍執行一般 saved record query;matrix 與 timeline 完全由前端渲染。

Ref 與身分規則

Qualified identity 是 orders.open_orders,與同 table 的 column、rule、trigger、public_read refs 以及固定的 client_access identity 共用 namespace。IaC 中 filters object keys、predicate column、sort_by、columns entries,以及所有 matrix/timeline column fields 都使用 authored column refs;plan fail closed 地解析為 CRUD 所需的 internal/display representation。

View 名稱不是 identity。改 name 產生 update;改 IaC ref 應使用 renamed_from 產生 move。Export 不會把 server-owned created_by 放進 spec,而且只輸出共享 view,所以 IaC 建立的私人 view 不會出現在 export 裡。

生命週期與規劃

Present line可規劃 create、adopt、move、update 或 noop;state: "absent" 規劃刪除 saved view。Adoption 比對該表中恰好一個名為 spec.name 的共享 view,但目前不會收斂:apply 會以 view '{table}.{ref}': adopt with no resolvable state row 讓該行失敗,下一次 plan 仍規劃 adopt;請先透過 REST 移除 live 的那一份,讓該行規劃 create(見 adoption)。

Apply 直接寫入 view,以執行 apply 的使用者為建立者。它只對照資料表 schema 驗證 config,不套用 caller ACL——IaC route 本身已要求 scope 管理者權限——所以 view 可以指名部分讀者看不到的欄位;讀者執行該 view 時,仍受自己的欄位與列權限限制。

省略 view line 不會刪除 live view。若要撤除,保留同一 table/ref 並明確宣告 absent。

View 可以是 public_read token 的發佈對象,而這個綁定會限制它的生命週期。Token 的 view_id 外鍵是 ON DELETE CASCADE,因此在仍有 present token 指向它時把 view 宣告為 absent,會得到硬性的 validate 錯誤,而不是連帶刪除——請先撤銷 token 行。public_read 行的 view 宣告在後面是可以的;executor 會把它延到第二輪處理。

驗證錯誤

state=absent lines carry no spec (table lines are the sole adopt-then-delete exception) state=present lines require a spec (unless a pure rename via renamed_from) unknown table ref 'orders' duplicate ref 'orders.open_orders' (already declared in this document) unknown column ref 'orders.status'

最後一種 detail 可由 filters key、predicate column、sort_by、columns entry 或 matrix/timeline column field 觸發。兩則 lifecycle 訊息來自丟出一般 ValueError 的 validator:伺服器在 plan 與 apply 都以 parse 階段的 400 回應,detail 是 loc 為 ["view"] 的 typed value_error issue(見 Validator 訊息類別),工作台顯示相同的 detail。精確本機字串來源:components/iac/parse.ts。

Apply 接著以和 REST 儲存相同的方式,對照資料表 schema 檢查翻譯後的 config,並只讓該行在 200 內失敗:

view '{table}.{ref}': Column '{name}' does not exist in table schema view '{table}.{ref}': Op '{op}' cannot be saved in a view — display-name filters are request-scoped; resolve the person to a raw id and store eq/in instead view '{table}.{ref}': {matrix or timeline column type message} view '{table}.{ref}': table no longer resolves live view '{table}.{ref}' no longer resolves live

最後一則對應 plan 之後 live view 已被刪除的 update。

自 2026-07-28 版起,apply 在任何 view CRUD 之前,會先對翻譯後的 spec.config key 做 fail-closed 驗證——config 在 parse 階段是自由 dict,工作台攔不到雜 key。未知 key 只讓那一行出錯:200 的 apply body 裡出現 view '{table}.{ref}': invalid configuration (N field error(s));其他行照常執行,失敗那行不落任何東西。成功時保存的是翻譯後的原始 dict(不是 model 正規化輸出),所以套用過的 view replan 仍是零差異。讀取側是寬鬆的另一半:已經帶著雜 key 的存量 view 永遠讀得到——未知 key 在讀取時被剝除,絕不會 500。

動手試試

在 IaC 工作台建立 orders.status 與範例 view,把 sort_by 改成未知 ref,修正後執行 server plan。確認 is_shared 與 column visibility 符合預期使用者 ACL。

Last updated on