mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 22:10:34 +00:00
♻️ Rename app.graph.overlay to app.graph.relation-overlay
The holder vocabulary names a graph by scope and a holder by location, scope, and form, so the overlay namespace takes the holder's name: app.graph.relation-overlay, with its console, queries, and sync children. Aliases keep their short forms. schema-version keeps its "penpot-graph-overlay-2" literal: it is a storage version, and renaming it would rekey stored artefacts without a schema change. AI-assisted-by: glm-5.3-flash Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
This commit is contained in:
parent
bf1efeff6e
commit
d9ef6eb789
@ -71,7 +71,7 @@
|
||||
;; Required by Arrow RootAllocator (lbug only pulls arrow-memory-core).
|
||||
org.apache.arrow/arrow-memory-netty {:mvn/version "19.0.0"}
|
||||
|
||||
;; graph-overlay: datascript index over the document, replacing the Cypher
|
||||
;; relation-overlay: datascript index over the document, replacing the Cypher
|
||||
;; projection for per-file queries. See docs.local/graph roadmap.
|
||||
datascript/datascript {:mvn/version "1.8.1"}}
|
||||
|
||||
|
||||
@ -8,9 +8,9 @@
|
||||
"In-memory overlay sessions for the debug graph console.
|
||||
|
||||
A session is a datascript overlay of one file
|
||||
(`app.graph.overlay`), maintained from the msgbus file-change feed by
|
||||
`app.graph.overlay.sync` and queried in Datalog through
|
||||
`app.graph.overlay.console`. The Ladybug engine no longer appears on
|
||||
(`app.graph.relation-overlay`), maintained from the msgbus file-change feed by
|
||||
`app.graph.relation-overlay.sync` and queried in Datalog through
|
||||
`app.graph.relation-overlay.console`. The Ladybug engine no longer appears on
|
||||
this path: it keeps the batch-export tier (`app.graph.ingest`), where
|
||||
columnar output is the point. The overlay is immutable data in an atom,
|
||||
so readers never lock and the sync loop is the only writer."
|
||||
@ -20,10 +20,10 @@
|
||||
[app.common.logging :as l]
|
||||
[app.common.time :as ct]
|
||||
[app.db :as db]
|
||||
[app.graph.overlay :as overlay]
|
||||
[app.graph.overlay.console :as console]
|
||||
[app.graph.overlay.queries :as queries]
|
||||
[app.graph.overlay.sync :as overlay.sync]
|
||||
[app.graph.relation-overlay :as overlay]
|
||||
[app.graph.relation-overlay.console :as console]
|
||||
[app.graph.relation-overlay.queries :as queries]
|
||||
[app.graph.relation-overlay.sync :as overlay.sync]
|
||||
[app.msgbus :as mbus]
|
||||
[app.srepl.helpers :as h]
|
||||
[clojure.string :as str]
|
||||
@ -37,7 +37,7 @@
|
||||
The `filter_*` columns carry node ids for the graph-view result filter;
|
||||
the results table hides them (see `hide-filter-columns` and the
|
||||
template's `renderQueryOutput`). `$` is bound to the overlay and `%` to
|
||||
the shared rule set of `app.graph.overlay.queries`."
|
||||
the shared rule set of `app.graph.relation-overlay.queries`."
|
||||
(str "[:find ?component ?instance ?page\n"
|
||||
" ?filter_src_id ?filter_tgt_id\n"
|
||||
" :in $ %\n"
|
||||
@ -84,7 +84,7 @@
|
||||
(defn- mark-stale
|
||||
"Record a staleness verdict in a session's sync state, once.
|
||||
|
||||
Every verdict `app.graph.overlay.sync/staleness` returns is a permanent
|
||||
Every verdict `app.graph.relation-overlay.sync/staleness` returns is a permanent
|
||||
divergence: the index has folded a state no rebuild produces, and the
|
||||
batches after it fold onto that state. So a later clean batch must not
|
||||
erase the mark, and only `load-session!` clears it, by building fresh
|
||||
@ -162,7 +162,7 @@
|
||||
(if-let [msgbus (:msgbus session)]
|
||||
;; A dropping buffer is the silence this subsystem cannot see: a full
|
||||
;; buffer discards a message with no log line and no revision change.
|
||||
;; `app.graph.overlay.sync/staleness` catches it one message later,
|
||||
;; `app.graph.relation-overlay.sync/staleness` catches it one message later,
|
||||
;; because the next message's revision is then two beyond the
|
||||
;; index's, and the read gates refuse until a reload rebuilds.
|
||||
(let [sync-ch (sp/chan :buf (sp/dropping-buffer 64))]
|
||||
@ -193,7 +193,7 @@
|
||||
(defn sync-status
|
||||
"Return incremental sync status for the active session.
|
||||
|
||||
`:stale` is the verdict `app.graph.overlay.sync/staleness` returned for
|
||||
`:stale` is the verdict `app.graph.relation-overlay.sync/staleness` returned for
|
||||
the batch that broke the index, nil while the index still equals a
|
||||
rebuild, and `:reason` names which of the three cases it was. The two
|
||||
revisions are reported beside it and neither is the gate: `:revn` is
|
||||
@ -268,7 +268,7 @@
|
||||
(defn- check-fresh!
|
||||
"Refuse a read from an index that has fallen behind.
|
||||
|
||||
The mark is `app.graph.overlay.sync/staleness`'s verdict, recorded by
|
||||
The mark is `app.graph.relation-overlay.sync/staleness`'s verdict, recorded by
|
||||
`apply-file-change!`, and a reload clears it by rebuilding
|
||||
(`load-session!`). This refusal is what makes partial change-type
|
||||
coverage a performance property rather than a correctness one: a
|
||||
@ -286,7 +286,7 @@
|
||||
"Run a Datalog `statement` against the overlay for `profile-id`.
|
||||
|
||||
Read-only by construction (`d/q` cannot transact), gated against
|
||||
function smuggling by `app.graph.overlay.console/check-query!`, and
|
||||
function smuggling by `app.graph.relation-overlay.console/check-query!`, and
|
||||
gated against a stale index by `check-fresh!`."
|
||||
[profile-id statement]
|
||||
(when (or (nil? statement) (= "" statement))
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC Sucursal en España SL
|
||||
|
||||
(ns app.graph.overlay
|
||||
(ns app.graph.relation-overlay
|
||||
"Datascript index over a Penpot document: identity, type, and topology.
|
||||
|
||||
The overlay is an index over what Penpot's helpers read, never a
|
||||
@ -40,7 +40,7 @@
|
||||
- **Token applications fold the property into the attribute name**:
|
||||
`{:token/fill \"layerTwo.background\"}` on the shape itself, over the
|
||||
closed vocabulary of `app.common.types.token/all-keys`. The
|
||||
`uses-token` rule in `app.graph.overlay.queries` hides the encoding,
|
||||
`uses-token` rule in `app.graph.relation-overlay.queries` hides the encoding,
|
||||
so the choice stays reversible.
|
||||
|
||||
The namespace is deliberately JVM-free (no imports, no interop): the
|
||||
@ -81,12 +81,12 @@
|
||||
Color references are stored per source (`fill`, `stroke`, text content)
|
||||
rather than as one union, because the sync path receives `:set` ops one
|
||||
attribute at a time and must be able to rebuild each contribution
|
||||
independently. The `uses-color` rule in `app.graph.overlay.queries`
|
||||
independently. The `uses-color` rule in `app.graph.relation-overlay.queries`
|
||||
reunites them. Each source also keeps the raw id it resolved from, as a
|
||||
value rather than a ref: the id joins nothing until
|
||||
`build-asset-maps` finds the asset, and an asset the library does not
|
||||
hold yet leaves the id stored and the reference absent, which is the
|
||||
state `app.graph.overlay.sync/apply-add-asset` repairs. Folded token
|
||||
state `app.graph.relation-overlay.sync/apply-add-asset` repairs. Folded token
|
||||
attributes (`:token/fill`, ...) are plain string values and need no
|
||||
declaration."
|
||||
{;; document
|
||||
@ -128,7 +128,7 @@
|
||||
:shape/uses-typography {:db/valueType :db.type/ref
|
||||
:db/cardinality :db.cardinality/many}
|
||||
;; the raw ids those four resolved from, one attribute per source,
|
||||
;; indexed because `app.graph.overlay.sync/apply-add-asset` reads the
|
||||
;; indexed because `app.graph.relation-overlay.sync/apply-add-asset` reads the
|
||||
;; shapes waiting on an id
|
||||
:shape/fill-color-ref-id {:db/index true
|
||||
:db/cardinality :db.cardinality/many}
|
||||
@ -311,7 +311,7 @@
|
||||
|
||||
The raw id is written whether or not the ctx resolves it. A shape that
|
||||
names an asset the library does not hold keeps the id and carries no
|
||||
reference, which is what `app.graph.overlay.sync/apply-add-asset` reads
|
||||
reference, which is what `app.graph.relation-overlay.sync/apply-add-asset` reads
|
||||
when the asset finally arrives; a reference is written only for an id
|
||||
the ctx resolves."
|
||||
[shape {:keys [colors typographies]}]
|
||||
@ -4,7 +4,7 @@
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC Sucursal en España SL
|
||||
|
||||
(ns app.graph.overlay.console
|
||||
(ns app.graph.relation-overlay.console
|
||||
"Free-form Datalog for the debug graph console: parse, gate, run,
|
||||
format.
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
binder's own courtesy: the error names the symbol."
|
||||
(:require
|
||||
[app.common.exceptions :as ex]
|
||||
[app.graph.overlay.queries :as queries]
|
||||
[app.graph.relation-overlay.queries :as queries]
|
||||
[clojure.edn :as edn]
|
||||
[datascript.built-ins :as bi]
|
||||
[datascript.core :as d]))
|
||||
@ -137,7 +137,7 @@
|
||||
"Parse, gate, and run `text` against overlay `db`.
|
||||
|
||||
`$` is always supplied; `%` (the shared rule set of
|
||||
`app.graph.overlay.queries`) is supplied when the query's :in asks for
|
||||
`app.graph.relation-overlay.queries`) is supplied when the query's :in asks for
|
||||
it. Returns {:columns [...] :rows [...] :truncated? bool :row-count n}
|
||||
in the shape the console template renders."
|
||||
[db text]
|
||||
@ -4,7 +4,7 @@
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC Sucursal en España SL
|
||||
|
||||
(ns app.graph.overlay.queries
|
||||
(ns app.graph.relation-overlay.queries
|
||||
"The relation vocabulary and the standing question set over the overlay.
|
||||
|
||||
**The relation vocabulary is a rule set, not raw clauses**
|
||||
@ -36,7 +36,7 @@
|
||||
stays the oracle and is never reimplemented here."
|
||||
(:require
|
||||
[app.common.uuid :as uuid]
|
||||
[app.graph.overlay :as overlay]
|
||||
[app.graph.relation-overlay :as overlay]
|
||||
[datascript.core :as d]))
|
||||
|
||||
(def rules
|
||||
@ -4,7 +4,7 @@
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC Sucursal en España SL
|
||||
|
||||
(ns app.graph.overlay.sync
|
||||
(ns app.graph.relation-overlay.sync
|
||||
"Incremental overlay updates from Penpot change vectors.
|
||||
|
||||
The invariant this namespace defends: an overlay maintained from change
|
||||
@ -50,8 +50,8 @@
|
||||
[app.common.types.page :as ctp]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.graph.overlay :as overlay]
|
||||
[app.graph.overlay.queries :as queries]
|
||||
[app.graph.relation-overlay :as overlay]
|
||||
[app.graph.relation-overlay.queries :as queries]
|
||||
[datascript.core :as d]))
|
||||
|
||||
(def supported-change-types
|
||||
@ -77,7 +77,7 @@
|
||||
(some-> (first (d/datoms db :avet :document/id)) :e))
|
||||
|
||||
(defn- sync-asset-ctx
|
||||
"The asset half of `app.graph.overlay`'s build-ctx, resolved against the
|
||||
"The asset half of `app.graph.relation-overlay`'s build-ctx, resolved against the
|
||||
live db: values are eids rather than tempids."
|
||||
[db]
|
||||
{:colors (into {} (map (fn [dtm] [(:v dtm) (:e dtm)]))
|
||||
@ -860,7 +860,7 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; library assets: colours and typographies
|
||||
;;
|
||||
;; The entity is the one `app.graph.overlay/build-tx` writes for a member
|
||||
;; The entity is the one `app.graph.relation-overlay/build-tx` writes for a member
|
||||
;; of `:colors` or `:typographies`: identity, the document ref, and the
|
||||
;; name a standing query asks for. The value lives in the document,
|
||||
;; which the holder of the overlay already has.
|
||||
@ -952,7 +952,7 @@
|
||||
of `ctyl/delete-typography`: both dissoc the asset from the library map
|
||||
and leave every referring shape alone. A rebuild therefore loses the
|
||||
asset entity *and* every resolved reference to it, because
|
||||
`app.graph.overlay/build-asset-maps` only maps the ids the library
|
||||
`app.graph.relation-overlay/build-asset-maps` only maps the ids the library
|
||||
still holds.
|
||||
|
||||
One retraction produces exactly that. Datascript's
|
||||
@ -971,7 +971,7 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; design tokens
|
||||
;;
|
||||
;; The entity shape is `app.graph.overlay/tokens-tx`'s: one entity per
|
||||
;; The entity shape is `app.graph.relation-overlay/tokens-tx`'s: one entity per
|
||||
;; token set (identity, name, document ref) and one per token (identity,
|
||||
;; name, type, set ref). Values, themes and resolution stay in the lib,
|
||||
;; which `app.common.types.tokens-lib` already answers.
|
||||
@ -1016,7 +1016,7 @@
|
||||
|
||||
(defn- token-entities
|
||||
"Token entities of one set from a lib-shaped token map, in
|
||||
`app.graph.overlay/tokens-tx`'s shape."
|
||||
`app.graph.relation-overlay/tokens-tx`'s shape."
|
||||
[set-ref tokens]
|
||||
(into []
|
||||
(map (fn [token]
|
||||
@ -1082,7 +1082,7 @@
|
||||
and token entity goes, and the incoming library's sets and tokens are
|
||||
written fresh. Nothing outside the pair points at them, because an
|
||||
applied token is folded onto the shape as a plain name
|
||||
(`app.graph.overlay/token-attrs`), so no shape datom needs repair."
|
||||
(`app.graph.relation-overlay/token-attrs`), so no shape datom needs repair."
|
||||
[db {:keys [tokens-lib]}]
|
||||
(let [old (-> (mapv (fn [dtm] [:db.fn/retractEntity (:e dtm)])
|
||||
(d/datoms db :avet :token-set/id))
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
(ns backend-tests.graph-overlay-console-test
|
||||
"Pure tests over the console's parse-gate-run pipeline
|
||||
(`app.graph.overlay.console/run-query`) and the default query it ships
|
||||
(`app.graph.relation-overlay.console/run-query`) and the default query it ships
|
||||
(`app.graph.debug/default-query`).
|
||||
|
||||
The gate exists so the console cannot run arbitrary Clojure; these
|
||||
@ -21,8 +21,8 @@
|
||||
[app.common.test-helpers.ids-map :as thi]
|
||||
[app.common.test-helpers.shapes :as ths]
|
||||
[app.graph.debug :as debug]
|
||||
[app.graph.overlay :as overlay]
|
||||
[app.graph.overlay.console :as console]
|
||||
[app.graph.relation-overlay :as overlay]
|
||||
[app.graph.relation-overlay.console :as console]
|
||||
[clojure.string :as str]
|
||||
[clojure.test :as t]
|
||||
[datascript.core :as d]))
|
||||
@ -80,7 +80,7 @@
|
||||
|
||||
(t/deftest shared-rule-invocations-pass-the-gate
|
||||
;; The gate's allowlist derives from `queries/rules`
|
||||
;; (`app.graph.overlay.console/check-query!`), so rule renames pass
|
||||
;; (`app.graph.relation-overlay.console/check-query!`), so rule renames pass
|
||||
;; automatically: the default query proves `instance-of`, and these
|
||||
;; hold the door open for `descendant-of` (with rows) and `uses-token`
|
||||
;; (the fixture defines no tokens, so the gate acceptance is the
|
||||
|
||||
@ -8,8 +8,8 @@
|
||||
"Cold build and incremental sync are two implementations of one mapping,
|
||||
and this namespace holds them to it.
|
||||
|
||||
`app.graph.overlay/build` projects a whole file into a fresh overlay.
|
||||
`app.graph.overlay.sync/apply-changes` replays the change vocabulary the
|
||||
`app.graph.relation-overlay/build` projects a whole file into a fresh overlay.
|
||||
`app.graph.relation-overlay.sync/apply-changes` replays the change vocabulary the
|
||||
editor emits onto an overlay that is already open. The overlay the second
|
||||
one maintains must equal the overlay the first one would build from the
|
||||
changed document, or the console shows a graph no rebuild reproduces.
|
||||
@ -31,9 +31,9 @@
|
||||
[app.common.types.typography :as ctt]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.graph.debug :as graph.debug]
|
||||
[app.graph.overlay :as overlay]
|
||||
[app.graph.overlay.queries :as queries]
|
||||
[app.graph.overlay.sync :as sync]
|
||||
[app.graph.relation-overlay :as overlay]
|
||||
[app.graph.relation-overlay.queries :as queries]
|
||||
[app.graph.relation-overlay.sync :as sync]
|
||||
[clojure.set :as set]
|
||||
[clojure.string :as str]
|
||||
[clojure.test :as t]
|
||||
@ -135,7 +135,7 @@
|
||||
an editing session would emit them, and every indexed attribute at least
|
||||
once: topology (add, reparent, reorder, delete a subtree), the
|
||||
`:mod-obj` set ops
|
||||
with their asset refs (`app.graph.overlay.sync/set-attr-tx`), a touched
|
||||
with their asset refs (`app.graph.relation-overlay.sync/set-attr-tx`), a touched
|
||||
swap slot on a shape inside a copy (`ctk/get-swap-slot`), a copy
|
||||
child's `:shape-ref` repointed at another main shape (the resolved
|
||||
`:shape/refers-to` must follow), the whole component lifecycle from add
|
||||
@ -207,7 +207,7 @@
|
||||
;; the frame's children are sorted by the index each named id holds
|
||||
;; here, and rect-id, which the change does not name, keeps the -1 key
|
||||
;; and stays first. The sibling ordinals must follow that sort
|
||||
;; (`app.graph.overlay.sync/apply-reorder-children`).
|
||||
;; (`app.graph.relation-overlay.sync/apply-reorder-children`).
|
||||
{:type :reorder-children :page-id page-id :parent-id frame-id
|
||||
:shapes [circ-id rect2-id]}
|
||||
|
||||
@ -686,11 +686,11 @@
|
||||
;; The third filter, after the change types and the operations: the
|
||||
;; attributes a shape entity carries. They do not have one writer each. An
|
||||
;; operation writes `:shape/name` and its neighbours through
|
||||
;; `app.graph.overlay.sync/set-attr-tx`, a structural pass writes
|
||||
;; `app.graph.relation-overlay.sync/set-attr-tx`, a structural pass writes
|
||||
;; `:shape/refers-to` (`reresolve-refs-tx`) and the sibling ordinal
|
||||
;; (`order-tx`, which is also how the builder draws it), and the builder
|
||||
;; writes the identity and topology edges and `:shape/type`. The comparison
|
||||
;; asks whether every attribute `app.graph.overlay/schema` declares over
|
||||
;; asks whether every attribute `app.graph.relation-overlay/schema` declares over
|
||||
;; shape entities, plus the folded token vocabulary, has a writer, and
|
||||
;; names its kind. An attribute nothing can write fails by name rather than passing
|
||||
;; as derived, which is the failure mode the operation filter had before
|
||||
@ -748,7 +748,7 @@
|
||||
:shape/exit "the fold and the rebuild number the intervals differently; containment is the invariant"})
|
||||
|
||||
(defn- declared-shape-attrs
|
||||
"The attributes `app.graph.overlay/schema` declares over shape entities,
|
||||
"The attributes `app.graph.relation-overlay/schema` declares over shape entities,
|
||||
plus the folded token vocabulary that needs no declaration."
|
||||
[]
|
||||
(into (into #{} (filter (fn [attr] (= "shape" (namespace attr)))) (keys overlay/schema))
|
||||
@ -966,7 +966,7 @@
|
||||
;; The Euler-tour invariants hold on the synced db, not only on the
|
||||
;; built one. The sync path renumbers a container from beyond the
|
||||
;; global maximum with a different DFS order than the builder
|
||||
;; (`app.graph.overlay.sync/renumber-container-tx`), so interval
|
||||
;; (`app.graph.relation-overlay.sync/renumber-container-tx`), so interval
|
||||
;; values are not comparable between the two paths — containment is.
|
||||
;; Here: every shape of every container carries an interval, the
|
||||
;; interval form answers the recursive walk exactly, and intervals are
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
that is the correctness oracle. A backported assertion that disagrees
|
||||
with a helper is a beadpot bug: the helper's answer is asserted and the
|
||||
divergence is noted in the docstring. Beadpot's idempotency tests have
|
||||
no port here: `app.graph.overlay/build` is a pure function of the
|
||||
no port here: `app.graph.relation-overlay/build` is a pure function of the
|
||||
document, so linking twice cannot duplicate an edge by construction.
|
||||
|
||||
The fixture is built exclusively with the common test helpers
|
||||
@ -35,8 +35,8 @@
|
||||
[app.common.types.text :as txt]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.graph.overlay :as overlay]
|
||||
[app.graph.overlay.queries :as queries]
|
||||
[app.graph.relation-overlay :as overlay]
|
||||
[app.graph.relation-overlay.queries :as queries]
|
||||
[clojure.test :as t]
|
||||
[datascript.built-ins :as bi]
|
||||
[datascript.core :as d]))
|
||||
@ -89,7 +89,7 @@
|
||||
(defn- oracle-containers
|
||||
"The builder's resolution containers, one per page plus one per
|
||||
component that carries its own `:objects` snapshot, as [ctn-container
|
||||
container-id] pairs (`app.graph.overlay/ref-resolver`)."
|
||||
container-id] pairs (`app.graph.relation-overlay/ref-resolver`)."
|
||||
[data]
|
||||
(concat (map (fn [[id page]] [(ctn/make-container page :page) id])
|
||||
(:pages-index data))
|
||||
@ -520,7 +520,7 @@
|
||||
;; (1) the interval form answers the recursive form, and both equal
|
||||
;; `cfh/get-children-ids` (the oracle) for every frame of every
|
||||
;; container; (2) one global counter numbers every container
|
||||
;; (`app.graph.overlay/euler-numbering` threads it file-wide), so
|
||||
;; (`app.graph.relation-overlay/euler-numbering` threads it file-wide), so
|
||||
;; [enter exit] intervals across the whole file are pairwise
|
||||
;; disjoint-or-nested — a partial overlap is the signature of the
|
||||
;; per-container-counter bug the 20260820 report guards against.
|
||||
@ -742,7 +742,7 @@
|
||||
|
||||
(def ^:private control-symbols
|
||||
"Clause heads that structure a query rather than call a function, the
|
||||
console gate's own list (`app.graph.overlay.console`)."
|
||||
console gate's own list (`app.graph.relation-overlay.console`)."
|
||||
'#{not not-join or or-join and pull})
|
||||
|
||||
(def ^:private rule-names
|
||||
|
||||
@ -767,7 +767,7 @@
|
||||
destination's chain up `:parent-id`, reading `:component-id` and
|
||||
`:shape-ref` off every shape it meets: a caller holding those four facts
|
||||
per shape can ask this without a document. It is public because
|
||||
`app.graph.overlay.sync` is that caller, and the incremental overlay
|
||||
`app.graph.relation-overlay.sync` is that caller, and the incremental overlay
|
||||
refuses a move the document refuses by asking this predicate rather than
|
||||
by answering the same question a second time."
|
||||
[objects shape-id parent-id {:keys [allow-altering-copies syncing]}]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user