mirror of
https://github.com/penpot/penpot.git
synced 2026-08-19 19:28:36 +00:00
✨ Add the file-level graph columns and tighten the svg ones
Split out of "🐛 Declare the shape attributes stored files carry", which is now #11125 and carries only its `common/` half. This commit is the graph's own side of that change, and it stays on this branch. `app.graph.schema.contract` pins `svg_viewbox` to `DOUBLE[4]` and `svg_transform` to `DOUBLE[6]`. The shape schema types both `:map` on purpose, because legacy files hold them as plain maps rather than as `::grc/rect` and `::gmt/matrix` records, and a tighter *schema* would reject those files. A tighter *column* costs nothing, since `app.graph.schema.values/coerce` reads either form. `app.graph.schema.nodes` declares four file-level attributes as projection `:extra` rather than in `ctf/schema:file`: `:options`, `:backend`, `:comment-thread-seqn`, and `:ignore-sync-until`. Declaring them in the file schema breaks saving, measured at 185 failures, because `app.binfile.common/update-file!` derives its UPDATE column list from a file map's keys and the `file` table has no `backend` column, that value being synthesized on read. An `:extra` is local to the graph and cannot reach a write. `app.graph.project.document` lifts `:options` out of `:data` before the blob is dropped, so a consumer reads file-level configuration without opening the blob. AI-assisted-by: mixed models
This commit is contained in:
parent
1479c1a2ca
commit
02c91e521d
@ -29,9 +29,14 @@
|
|||||||
uuid/zero)
|
uuid/zero)
|
||||||
|
|
||||||
(defn- document-attrs
|
(defn- document-attrs
|
||||||
|
"The Document node's attrs: the file row, minus its data blob.
|
||||||
|
|
||||||
|
`:options` is lifted out of the blob before it goes: it is file-level
|
||||||
|
configuration a consumer wants without opening `:data`."
|
||||||
[file data]
|
[file data]
|
||||||
(-> file
|
(-> file
|
||||||
(assoc :id (or (:id data) (:id file)))
|
(assoc :id (or (:id data) (:id file)))
|
||||||
|
(cond-> (:options data) (assoc :options (:options data)))
|
||||||
(dissoc :data)))
|
(dissoc :data)))
|
||||||
|
|
||||||
(defn- page-attrs
|
(defn- page-attrs
|
||||||
|
|||||||
@ -107,7 +107,14 @@
|
|||||||
;; derivable from `x`/`y`/`width`/`height`, and a fixed-size array is a
|
;; derivable from `x`/`y`/`width`/`height`, and a fixed-size array is a
|
||||||
;; tensor row a consumer reads without parsing.
|
;; tensor row a consumer reads without parsing.
|
||||||
"selrect" "DOUBLE[4]"
|
"selrect" "DOUBLE[4]"
|
||||||
"svg_viewbox" "DOUBLE[4]"
|
|
||||||
|
;; The SVG provenance attributes are typed `:map` in the shape schema on
|
||||||
|
;; purpose — legacy files hold them as plain maps rather than as `::grc/rect`
|
||||||
|
;; and `::gmt/matrix` records, and a tighter *schema* would reject those files
|
||||||
|
;; (`app.common.types.shape/schema:shape-generic-attrs`). A tighter *column*
|
||||||
|
;; is free: `app.graph.schema.values/coerce` reads either form.
|
||||||
|
"svg_viewbox" "DOUBLE[4]"
|
||||||
|
"svg_transform" "DOUBLE[6]"
|
||||||
|
|
||||||
;; `:fills` is an `:or` — the packed `app.common.types.fills` value or a
|
;; `:fills` is an `:or` — the packed `app.common.types.fills` value or a
|
||||||
;; plain vector of fill maps — so the schema alone cannot say it is a
|
;; plain vector of fill maps — so the schema alone cannot say it is a
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
(:require
|
(:require
|
||||||
[app.common.exceptions :as ex]
|
[app.common.exceptions :as ex]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
|
[app.common.time :as ct]
|
||||||
[app.common.types.component :as ctk]
|
[app.common.types.component :as ctk]
|
||||||
[app.common.types.file :as ctf]
|
[app.common.types.file :as ctf]
|
||||||
[app.common.types.page :as ctp]
|
[app.common.types.page :as ctp]
|
||||||
@ -33,7 +34,24 @@
|
|||||||
;; beadpot/graph/schemas.py drop_fields
|
;; beadpot/graph/schemas.py drop_fields
|
||||||
(def ^:private document-projection
|
(def ^:private document-projection
|
||||||
{:source ctf/schema:file
|
{:source ctf/schema:file
|
||||||
:drop [:data]})
|
:drop [:data]
|
||||||
|
;; Attributes a file map carries that `ctf/schema:file` does not declare.
|
||||||
|
;;
|
||||||
|
;; They belong here rather than in that schema, even though the graph wants
|
||||||
|
;; them, because `schema:file` is on the *write* path too:
|
||||||
|
;; `app.binfile.common/update-file!` derives its UPDATE columns from a file
|
||||||
|
;; map's keys, so declaring `:backend` there made it try to write a `backend`
|
||||||
|
;; column, which the `file` table does not have — it is synthesized on read.
|
||||||
|
;; A projection `:extra` is local to the graph and cannot reach a write.
|
||||||
|
;;
|
||||||
|
;; `:options` is lifted out of `:data` before the blob is dropped
|
||||||
|
;; (`app.graph.project.document/document-attrs`); the rest come off the file
|
||||||
|
;; map as `get-file` returns it.
|
||||||
|
:extra [:map
|
||||||
|
[:options {:optional true} [:maybe :map]]
|
||||||
|
[:backend {:optional true} [:maybe :string]]
|
||||||
|
[:comment-thread-seqn {:optional true} [:maybe :int]]
|
||||||
|
[:ignore-sync-until {:optional true} [:maybe ::ct/inst]]]})
|
||||||
|
|
||||||
(def ^:private page-projection
|
(def ^:private page-projection
|
||||||
{:source ctp/schema:page
|
{:source ctp/schema:page
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user