From 50a6355537b5826f22d2f9ac0ebd9ac2bd30a36d Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 4 Jul 2025 10:14:53 +0200 Subject: [PATCH 1/3] :tada: Add options for creating library build context With the ability to pass referer. --- backend/src/app/binfile/v3.clj | 2 +- library/src/lib/builder.cljs | 14 +++++++++++--- library/src/lib/export.cljs | 19 ++++++++++++------- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/backend/src/app/binfile/v3.clj b/backend/src/app/binfile/v3.clj index 70a9960e69..f90ff08621 100644 --- a/backend/src/app/binfile/v3.clj +++ b/backend/src/app/binfile/v3.clj @@ -54,7 +54,7 @@ [:map {:title "Manifest"} [:version ::sm/int] [:type :string] - + [:referer {:optional true} :string] [:generated-by {:optional true} :string] [:files diff --git a/library/src/lib/builder.cljs b/library/src/lib/builder.cljs index f77f6f8ae5..c7b87d32c3 100644 --- a/library/src/lib/builder.cljs +++ b/library/src/lib/builder.cljs @@ -271,11 +271,19 @@ (fn [] (json/->js @state)))) +(def ^:private schema:context-options + [:map {:title "ContextOptions"} + [:referer {:optional true} ::sm/text]]) + +(def ^:private decode-context-options + (sm/decoder schema:context-options sm/json-transformer)) + (defn create-build-context "Create an empty builder state context." - [] - (let [state (atom {}) - api (create-builder-api state)] + [options] + (let [options (some-> options decode-params decode-context-options) + state (atom {:options options}) + api (create-builder-api state)] (specify! api cljs.core/IDeref diff --git a/library/src/lib/export.cljs b/library/src/lib/export.cljs index 7fee373440..1d5d5cfcb6 100644 --- a/library/src/lib/export.cljs +++ b/library/src/lib/export.cljs @@ -183,17 +183,22 @@ (defn- generate-manifest-procs [state] - (let [files (->> (get state ::fb/files) - (mapv (fn [[file-id file]] - {:id file-id - :name (:name file) - :features (:features file)}))) + (let [opts (get state :options) + files (->> (get state ::fb/files) + (mapv (fn [[file-id file]] + {:id file-id + :name (:name file) + :features (:features file)}))) params {:type "penpot/export-files" :version 1 :generated-by "penpot-library/%version%" + :referer (get opts :referer) :files files - :relations []}] - ["manifest.json" (delay (json/encode params))])) + :relations []} + params (d/without-nils params)] + + ["manifest.json" + (delay (json/encode params))])) (defn- generate-procs [state] From a7e0cfc6093337b71c8b68af262504abf17285c8 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 4 Jul 2025 10:27:05 +0200 Subject: [PATCH 2/3] :tada: Bump 1.0.7 release of the penpot library Includes the ability to pass referer --- library/CHANGES.md | 11 +++++++++++ library/deps.edn | 5 ++--- library/package.json | 5 ++--- library/playground/sample-fill-stroke-and-media.js | 2 +- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/library/CHANGES.md b/library/CHANGES.md index 1e805c23b8..6f6a732e86 100644 --- a/library/CHANGES.md +++ b/library/CHANGES.md @@ -1,5 +1,16 @@ # CHANGELOG +## 1.0.7 + +- Add the ability to provide refereron creating build context + +```js +const context = penpot.createBuildContext({referer:"my-referer"}); +``` + +The referer will be added as an additional field on the manifest.json + + ## 1.0.6 - Fix unexpected issue on library color decoding diff --git a/library/deps.edn b/library/deps.edn index 0c59e66107..0b2473bf81 100644 --- a/library/deps.edn +++ b/library/deps.edn @@ -21,11 +21,10 @@ :dev {:extra-paths ["dev"] :extra-deps - {thheller/shadow-cljs {:mvn/version "3.1.4"} + {thheller/shadow-cljs {:mvn/version "3.1.7"} com.bhauman/rebel-readline {:mvn/version "RELEASE"} org.clojure/tools.namespace {:mvn/version "RELEASE"} - criterium/criterium {:mvn/version "RELEASE"} - cider/cider-nrepl {:mvn/version "0.48.0"}}} + criterium/criterium {:mvn/version "RELEASE"}}} :shadow-cljs {:main-opts ["-m" "shadow.cljs.devtools.cli"] diff --git a/library/package.json b/library/package.json index b58bfff5da..fa14bf7d46 100644 --- a/library/package.json +++ b/library/package.json @@ -1,6 +1,6 @@ { "name": "@penpot/library", - "version": "1.0.6", + "version": "1.0.7", "license": "MPL-2.0", "author": "Kaleidos INC", "packageManager": "yarn@4.9.1+sha512.f95ce356460e05be48d66401c1ae64ef84d163dd689964962c6888a9810865e39097a5e9de748876c2e0bf89b232d583c33982773e9903ae7a76257270986538", @@ -40,8 +40,7 @@ "@zip.js/zip.js": "patch:@zip.js/zip.js@npm%3A2.7.60#~/.yarn/patches/@zip.js-zip.js-npm-2.7.60-b6b814410b.patch", "concurrently": "^9.1.2", "luxon": "^3.6.1", - "nodemon": "^3.1.9", - "shadow-cljs": "3.1.4" + "nodemon": "^3.1.9" }, "dependencies": { "source-map-support": "^0.5.21" diff --git a/library/playground/sample-fill-stroke-and-media.js b/library/playground/sample-fill-stroke-and-media.js index dbc90cdce2..7bd952265d 100644 --- a/library/playground/sample-fill-stroke-and-media.js +++ b/library/playground/sample-fill-stroke-and-media.js @@ -6,7 +6,7 @@ import { Writable } from "stream"; // console.log(penpot); (async function () { - const context = penpot.createBuildContext(); + const context = penpot.createBuildContext({referer:"playground"}); { context.addFile({ name: "Test File 1" }); From 77741b49a79add8b8b8c49f79434e6c20108e878 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 4 Jul 2025 11:01:25 +0200 Subject: [PATCH 3/3] :sparkles: Add tracking for referer on the import-binfile --- backend/src/app/binfile/v3.clj | 43 ++++++++++++------------ backend/src/app/rpc/commands/binfile.clj | 17 +++++++--- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/backend/src/app/binfile/v3.clj b/backend/src/app/binfile/v3.clj index f90ff08621..7208a54f39 100644 --- a/backend/src/app/binfile/v3.clj +++ b/backend/src/app/binfile/v3.clj @@ -12,7 +12,6 @@ [app.binfile.common :as bfc] [app.binfile.migrations :as bfm] [app.common.data :as d] - [app.common.data.macros :as dm] [app.common.exceptions :as ex] [app.common.features :as cfeat] [app.common.files.migrations :as-alias fmg] @@ -373,6 +372,7 @@ params {:type "penpot/export-files" :version 1 :generated-by (str "penpot/" (:full cf/version)) + :refer "penpot" :files (vec (vals files)) :relations rels}] (write-entry! output "manifest.json" params)))) @@ -878,13 +878,8 @@ (defn- import-files [{:keys [::bfc/timestamp ::bfc/input ::bfc/name] :or {timestamp (dt/now)} :as cfg}] - (dm/assert! - "expected zip file" - (instance? ZipFile input)) - - (dm/assert! - "expected valid instant" - (dt/instant? timestamp)) + (assert (instance? ZipFile input) "expected zip file") + (assert (dt/instant? timestamp) "expected valid instant") (let [manifest (-> (read-manifest input) (validate-manifest)) @@ -896,6 +891,7 @@ :hint "unexpected type on manifest" :manifest manifest)) + ;; Check if all files referenced on manifest are present (doseq [{file-id :id features :features} (:files manifest)] (let [path (str "files/" file-id ".json")] @@ -956,14 +952,13 @@ [{:keys [::bfc/ids] :as cfg} output] - (dm/assert! - "expected a set of uuid's for `::bfc/ids` parameter" - (and (set? ids) - (every? uuid? ids))) + (assert + (and (set? ids) (every? uuid? ids)) + "expected a set of uuid's for `::bfc/ids` parameter") - (dm/assert! - "expected instance of jio/IOFactory for `input`" - (satisfies? jio/IOFactory output)) + (assert + (satisfies? jio/IOFactory output) + "expected instance of jio/IOFactory for `input`") (let [id (uuid/next) tp (dt/tpoint) @@ -1002,14 +997,14 @@ (defn import-files! [{:keys [::bfc/input] :as cfg}] - (dm/assert! - "expected valid profile-id and project-id on `cfg`" + (assert (and (uuid? (::bfc/profile-id cfg)) - (uuid? (::bfc/project-id cfg)))) + (uuid? (::bfc/project-id cfg))) + "expected valid profile-id and project-id on `cfg`") - (dm/assert! - "expected instance of jio/IOFactory for `input`" - (io/coercible? input)) + (assert + (io/coercible? input) + "expected instance of jio/IOFactory for `input`") (let [id (uuid/next) tp (dt/tpoint) @@ -1029,3 +1024,9 @@ :id (str id) :elapsed (dt/format-duration (tp)) :error? (some? @cs)))))) + +(defn get-manifest + [path] + (with-open [input (ZipFile. (fs/file path))] + (-> (read-manifest input) + (validate-manifest)))) diff --git a/backend/src/app/rpc/commands/binfile.clj b/backend/src/app/rpc/commands/binfile.clj index 60b524ee38..0dc301c71e 100644 --- a/backend/src/app/rpc/commands/binfile.clj +++ b/backend/src/app/rpc/commands/binfile.clj @@ -134,11 +134,18 @@ ::webhooks/event? true ::sse/stream? true ::sm/params schema:import-binfile} - [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id project-id version] :as params}] + [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id project-id version file] :as params}] (projects/check-edition-permissions! pool profile-id project-id) - (let [params (-> params - (assoc :profile-id profile-id) - (assoc :version (or version 1)))] + (let [version (or version 1) + params (-> params + (assoc :profile-id profile-id) + (assoc :version version)) + manifest (case (int version) + 1 nil + 3 (bf.v3/get-manifest (:path file)))] + (with-meta (sse/response (partial import-binfile cfg params)) - {::audit/props {:file nil}}))) + {::audit/props {:file nil + :generated-by (:generated-by manifest) + :referer (:referer manifest)}})))