From ef3143dcb82a11aca3b95fdf07e52ee9c09d8167 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 30 Mar 2026 12:35:39 +0200 Subject: [PATCH 01/16] :paperclip: Update changelog --- CHANGES.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index d5f46c6c3b..d774392169 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,28 @@ # CHANGELOG +## 2.14.1 + +### :sparkles: New features & Enhancements + +- Add automatic retry with backoff for idempotent RPC requests on network failures [Github #8792](https://github.com/penpot/penpot/pull/8792) +- Add scroll and zoom throttling to one state update per animation frame [Github #8812](https://github.com/penpot/penpot/pull/8812) +- Improve error handling and exception formatting [Github #8757](https://github.com/penpot/penpot/pull/8757) + +### :bug: Bugs fixed + +- Fix crash in apply-text-modifier with nil selrect or modifier [Github #8762](https://github.com/penpot/penpot/pull/8762) +- Fix incorrect attrs references on generate-sync-shape [Github #8776](https://github.com/penpot/penpot/pull/8776) +- Fix regression on subpath support [Github #8793](https://github.com/penpot/penpot/pull/8793) +- Improve error reporting on request parsing failures [Github #8805](https://github.com/penpot/penpot/pull/8805) +- Fix fetch abort errors escaping the unhandled exception handler [Github #8801](https://github.com/penpot/penpot/pull/8801) +- Fix nil deref on missing bounds in layout modifier propagation [Github #8735](https://github.com/penpot/penpot/pull/8735) +- Fix TypeError when token error map lacks :error/fn key [Github #8767](https://github.com/penpot/penpot/pull/8767) +- Fix dissoc error when detaching stroke color from library [Github #8738](https://github.com/penpot/penpot/pull/8738) +- Fix crash when pasting image into text editor +- Fix null text crash on paste in text editor +- Ensure path content is always PathData when saving +- Fix error when get-parent-with-data encounters non-Element nodes + ## 2.14.0 ### :boom: Breaking changes & Deprecations From c1044ac52299074216a168113d7722ffdcef66b1 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 17 Mar 2026 15:04:06 +0100 Subject: [PATCH 02/16] :sparkles: Add protection for stale cache of js assets loading issues (#8638) * :sparkles: Use update-when for update dashboard state This make updates more consistent and reduces possible eventual consistency issues in out of order events execution. * :bug: Detect stale JS modules at boot and force reload When the browser serves cached JS files from a previous deployment alongside a fresh index.html, code-split modules reference keyword constants that do not exist in the stale shared.js, causing TypeError crashes. This adds a compile-time version tag (via goog-define / closure-defines) that is baked into the JS bundle. At boot, it is compared against the runtime version tag from index.html (which is always fresh due to no-cache headers). If they differ, the app forces a hard page reload before initializing, ensuring all JS modules come from the same build. * :paperclip: Ensure consistent version across builds on github e2e test workflow --------- Signed-off-by: Andrey Antukh --- .github/workflows/tests.yml | 2 +- frontend/shadow-cljs.edn | 3 +- frontend/src/app/config.cljs | 55 +++++++++++++++++++- frontend/src/app/main.cljs | 24 ++++++--- frontend/src/app/main/data/dashboard.cljs | 8 +-- frontend/src/app/main/errors.cljs | 47 ++++++++++++++--- frontend/src/app/main/ui/error_boundary.cljs | 21 +++++--- frontend/src/app/util/storage.cljs | 23 +++++--- 8 files changed, 149 insertions(+), 34 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4ba57dde95..6cce286ced 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -252,7 +252,7 @@ jobs: - name: Build Bundle working-directory: ./frontend run: | - ./scripts/build 0.0.0 + ./scripts/build - name: Store Bundle Cache uses: actions/cache@v4 diff --git a/frontend/shadow-cljs.edn b/frontend/shadow-cljs.edn index bd09d46e6d..fadcb4131f 100644 --- a/frontend/shadow-cljs.edn +++ b/frontend/shadow-cljs.edn @@ -70,7 +70,8 @@ :release {:closure-defines {goog.DEBUG false - goog.debug.LOGGING_ENABLED true} + goog.debug.LOGGING_ENABLED true + app.config/compiled-version-tag #shadow/env ["VERSION_TAG" :default "develop"]} :compiler-options {:fn-invoke-direct true :optimizations #shadow/env ["PENPOT_BUILD_OPTIMIZATIONS" :as :keyword :default :advanced] diff --git a/frontend/src/app/config.cljs b/frontend/src/app/config.cljs index a0c5680204..f1c1e2b8bf 100644 --- a/frontend/src/app/config.cljs +++ b/frontend/src/app/config.cljs @@ -6,8 +6,11 @@ (ns app.config (:require + [app.common.data :as d] [app.common.data.macros :as dm] [app.common.flags :as flags] + [app.common.logging :as log] + [app.common.time :as ct] [app.common.uri :as u] [app.common.version :as v] [app.util.avatars :as avatars] @@ -15,6 +18,8 @@ [app.util.globals :refer [global location]] [app.util.navigator :as nav] [app.util.object :as obj] + [app.util.storage :as sto] + [app.util.timers :as ts] [cuerdas.core :as str])) (set! *assert* js/goog.DEBUG) @@ -81,6 +86,16 @@ "unknown" date))) +;; --- Compile-time version tag +;; +;; This value is baked into the compiled JS at build time via closure-defines, +;; so it travels with the JS bundle. In contrast, `version-tag` (below) is read +;; at runtime from globalThis.penpotVersionTag which is set by the always-fresh +;; index.html. Comparing the two lets us detect when the browser has loaded +;; stale cached JS files. + +(goog-define compiled-version-tag "develop") + ;; --- Global Config Vars (def default-theme "default") @@ -90,12 +105,50 @@ (def build-date (parse-build-date global)) (def flags (parse-flags global)) -(def version (parse-version global)) (def target (parse-target global)) (def browser (parse-browser)) (def platform (parse-platform)) +(def version (parse-version global)) (def version-tag (obj/get global "penpotVersionTag")) + +(defn stale-build? + "Returns true when the compiled JS was built with a different version + tag than the one present in the current index.html. This indicates + the browser has cached JS from a previous deployment." + ^boolean + [] + (not= compiled-version-tag version-tag)) + +;; --- Throttled reload +;; +;; A generic reload mechanism with loop protection via sessionStorage. +;; Used by both the boot-time stale-build check and the runtime +;; stale-asset error handler. + +(def ^:private reload-storage-key "penpot-last-reload-timestamp") +(def ^:private reload-cooldown-ms 30000) + +(defn throttled-reload + "Force a hard page reload unless one was already triggered within the + last 30 seconds (tracked in sessionStorage). Returns true when a + reload is initiated, false when suppressed." + [& {:keys [reason]}] + (let [now (ct/now) + prev-ts (-> (sto/get-item sto/session-storage reload-storage-key) + (d/parse-integer))] + (if (and (some? prev-ts) + (< (- now prev-ts) reload-cooldown-ms)) + (do + (log/wrn :hint "reload suppressed (cooldown active)" + :reason reason) + false) + (do + (log/wrn :hint "forcing page reload" :reason reason) + (sto/set-item sto/session-storage reload-storage-key (str now)) + (ts/asap #(.reload ^js location true)) + true)))) + (def terms-of-service-uri (obj/get global "penpotTermsOfServiceURI")) (def privacy-policy-uri (obj/get global "penpotPrivacyPolicyURI")) (def flex-help-uri (obj/get global "penpotGridHelpURI" "https://help.penpot.app/user-guide/flexible-layouts/")) diff --git a/frontend/src/app/main.cljs b/frontend/src/app/main.cljs index 9994856f60..870f8a82bb 100644 --- a/frontend/src/app/main.cljs +++ b/frontend/src/app/main.cljs @@ -100,16 +100,24 @@ (defn ^:export init [options] - (some-> (unchecked-get options "defaultTranslations") - (i18n/set-default-translations)) + ;; Before initializing anything, check if the browser has loaded + ;; stale JS from a previous deployment. If so, do a hard reload so + ;; the browser fetches fresh assets matching the current index.html. + (if (cf/stale-build?) + (cf/throttled-reload + :reason (dm/str "stale JS: compiled=" cf/compiled-version-tag + " expected=" cf/version-tag)) + (do + (some-> (unchecked-get options "defaultTranslations") + (i18n/set-default-translations)) - (mw/init!) - (i18n/init) - (cur/init-styles) + (mw/init!) + (i18n/init) + (cur/init-styles) - (init-ui) - (st/emit! (plugins/initialize) - (initialize))) + (init-ui) + (st/emit! (plugins/initialize) + (initialize))))) (defn ^:export reinit ([] diff --git a/frontend/src/app/main/data/dashboard.cljs b/frontend/src/app/main/data/dashboard.cljs index f4f6ead4be..a5ce2cd2c3 100644 --- a/frontend/src/app/main/data/dashboard.cljs +++ b/frontend/src/app/main/data/dashboard.cljs @@ -362,7 +362,7 @@ (ptk/reify ::toggle-project-pin ptk/UpdateEvent (update [_ state] - (assoc-in state [:projects id :is-pinned] (not is-pinned))) + (d/update-in-when state [:projects id] assoc :is-pinned (not is-pinned))) ptk/WatchEvent (watch [_ state _] @@ -379,7 +379,7 @@ ptk/UpdateEvent (update [_ state] (-> state - (update-in [:projects id :name] (constantly name)) + (d/update-in-when [:projects id] assoc :name name) (update :dashboard-local dissoc :project-for-edit))) ptk/WatchEvent @@ -409,7 +409,7 @@ (ptk/reify ::file-deleted ptk/UpdateEvent (update [_ state] - (update-in state [:projects project-id :count] dec)))) + (d/update-in-when state [:projects project-id :count] dec)))) (defn delete-file [{:keys [id project-id] :as params}] @@ -514,7 +514,7 @@ (-> state (assoc-in [:files id] file) (assoc-in [:recent-files id] file) - (update-in [:projects project-id :count] inc)))))) + (d/update-in-when [:projects project-id :count] inc)))))) (defn create-file [{:keys [project-id name] :as params}] diff --git a/frontend/src/app/main/errors.cljs b/frontend/src/app/main/errors.cljs index a4037b1f63..7671316589 100644 --- a/frontend/src/app/main/errors.cljs +++ b/frontend/src/app/main/errors.cljs @@ -33,6 +33,27 @@ ;; Will contain last uncaught exception (def last-exception nil) +;; --- Stale-asset error detection and auto-reload +;; +;; When the browser loads JS modules from different builds (e.g. shared.js from +;; build A and main-dashboard.js from build B because you loaded it in the +;; middle of a deploy per example), keyword constants referenced across modules +;; will be undefined. This manifests as TypeError messages containing +;; "$cljs$cst$" and "is undefined" or "is null". + +(defn stale-asset-error? + "Returns true if the error matches the signature of a cross-build + module mismatch: accessing a ClojureScript keyword constant that + doesn't exist on the shared $APP object." + [cause] + (when (some? cause) + (let [message (ex-message cause)] + (and (string? message) + (str/includes? message "$cljs$cst$") + (or (str/includes? message "is undefined") + (str/includes? message "is null") + (str/includes? message "is not a function")))))) + (defn exception->error-data [cause] (let [data (ex-data cause)] @@ -375,17 +396,31 @@ (.preventDefault ^js event) (when-let [cause (unchecked-get event "error")] (when-not (is-ignorable-exception? cause) - (set! last-exception cause) - (ex/print-throwable cause :prefix "Uncaught Exception") - (ts/schedule #(flash :cause cause :type :unhandled))))) + (if (stale-asset-error? cause) + (cf/throttled-reload :reason (ex-message cause)) + (let [data (ex-data cause) + type (get data :type)] + (set! last-exception cause) + (if (= :wasm-error type) + (on-error cause) + (do + (ex/print-throwable cause :prefix "Uncaught Exception") + (ts/asap #(flash :cause cause :type :unhandled))))))))) (on-unhandled-rejection [event] (.preventDefault ^js event) (when-let [cause (unchecked-get event "reason")] (when-not (is-ignorable-exception? cause) - (set! last-exception cause) - (ex/print-throwable cause :prefix "Uncaught Rejection") - (ts/schedule #(flash :cause cause :type :unhandled)))))] + (if (stale-asset-error? cause) + (cf/throttled-reload :reason (ex-message cause)) + (let [data (ex-data cause) + type (get data :type)] + (set! last-exception cause) + (if (= :wasm-error type) + (on-error cause) + (do + (ex/print-throwable cause :prefix "Uncaught Rejection") + (ts/asap #(flash :cause cause :type :unhandled)))))))))] (.addEventListener g/window "error" on-unhandled-error) (.addEventListener g/window "unhandledrejection" on-unhandled-rejection) diff --git a/frontend/src/app/main/ui/error_boundary.cljs b/frontend/src/app/main/ui/error_boundary.cljs index c3e9ec18b6..9d3f304489 100644 --- a/frontend/src/app/main/ui/error_boundary.cljs +++ b/frontend/src/app/main/ui/error_boundary.cljs @@ -9,6 +9,7 @@ (:require ["react-error-boundary" :as reb] [app.common.exceptions :as ex] + [app.config :as cf] [app.main.errors :as errors] [app.main.refs :as refs] [goog.functions :as gfn] @@ -35,13 +36,19 @@ ;; very small amount of time, so we debounce for 100ms for ;; avoid duplicate and redundant reports (gfn/debounce (fn [error info] - (set! errors/last-exception error) - (ex/print-throwable error) - (js/console.error - "Component trace: \n" - (unchecked-get info "componentStack") - "\n" - error)) + ;; If the error is a stale-asset error (cross-build + ;; module mismatch), force a hard page reload instead + ;; of showing the error page to the user. + (if (errors/stale-asset-error? error) + (cf/throttled-reload :reason (ex-message error)) + (do + (set! errors/last-exception error) + (ex/print-throwable error) + (js/console.error + "Component trace: \n" + (unchecked-get info "componentStack") + "\n" + error)))) 100))] [:> reb/ErrorBoundary diff --git a/frontend/src/app/util/storage.cljs b/frontend/src/app/util/storage.cljs index b67c805d25..dd97d7ea35 100644 --- a/frontend/src/app/util/storage.cljs +++ b/frontend/src/app/util/storage.cljs @@ -17,10 +17,10 @@ ;; Using ex/ignoring because can receive a DOMException like this when ;; importing the code as a library: Failed to read the 'localStorage' ;; property from 'Window': Storage is disabled inside 'data:' URLs. -(defonce ^:private local-storage-backend +(defonce local-storage (ex/ignoring (unchecked-get g/global "localStorage"))) -(defonce ^:private session-storage-backend +(defonce session-storage (ex/ignoring (unchecked-get g/global "sessionStorage"))) (def ^:dynamic *sync* @@ -69,6 +69,17 @@ (persistent! result)))) {})) +(defn set-item + [storage key val] + (when (and (some? storage) + (string? key)) + (.setItem ^js storage key val))) + +(defn get-item + [storage key] + (when (some? storage) + (.getItem storage key))) + (defn create-storage [backend prefix] (let [initial (load-data backend prefix) @@ -154,10 +165,10 @@ (-remove-watch [_ key] (.delete watches key))))) -(defonce global (create-storage local-storage-backend "penpot-global")) -(defonce user (create-storage local-storage-backend "penpot-user")) -(defonce storage (create-storage local-storage-backend "penpot")) -(defonce session (create-storage session-storage-backend "penpot")) +(defonce global (create-storage local-storage "penpot-global")) +(defonce user (create-storage local-storage "penpot-user")) +(defonce storage (create-storage local-storage "penpot")) +(defonce session (create-storage session-storage "penpot")) (defonce before-unload (letfn [(on-before-unload [_] From 905f4fa5ddabe0cfbf32a009ebc7d0b76396a665 Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Fri, 27 Mar 2026 14:57:17 +0100 Subject: [PATCH 03/16] :sparkles: Provide root package version as PENPOT_MCP_VERSION in plugin Update current root package version using set-version script --- mcp/package.json | 2 +- mcp/packages/plugin/src/vite-env.d.ts | 1 + mcp/packages/plugin/vite.config.ts | 9 ++++++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/mcp/package.json b/mcp/package.json index 31764661b9..6324fe3898 100644 --- a/mcp/package.json +++ b/mcp/package.json @@ -1,6 +1,6 @@ { "name": "@penpot/mcp", - "version": "1.0.0", + "version": "2.15.0-rc.1.153", "description": "MCP server for Penpot integration", "bin": { "penpot-mcp": "./bin/mcp-local.js" diff --git a/mcp/packages/plugin/src/vite-env.d.ts b/mcp/packages/plugin/src/vite-env.d.ts index ddbf746e04..252ff654af 100644 --- a/mcp/packages/plugin/src/vite-env.d.ts +++ b/mcp/packages/plugin/src/vite-env.d.ts @@ -2,3 +2,4 @@ declare const IS_MULTI_USER_MODE: boolean; declare const PENPOT_MCP_WEBSOCKET_URL: string; +declare const PENPOT_MCP_VERSION: string; diff --git a/mcp/packages/plugin/vite.config.ts b/mcp/packages/plugin/vite.config.ts index 75c7266b7e..9e79ca7f73 100644 --- a/mcp/packages/plugin/vite.config.ts +++ b/mcp/packages/plugin/vite.config.ts @@ -1,10 +1,16 @@ import { defineConfig } from "vite"; import livePreview from "vite-live-preview"; +import { createRequire } from "module"; + +const require = createRequire(import.meta.url); +const rootPkg = require("../../package.json"); let WS_URI = process.env.WS_URI || "http://localhost:4402"; let SERVER_HOST = process.env.PENPOT_MCP_PLUGIN_SERVER_HOST ?? "localhost"; +let MCP_VERSION = JSON.stringify(rootPkg.version); -console.log("Will define PENPOT_MCP_WEBSOCKET_URL as:", JSON.stringify(WS_URI)); +console.log("PENPOT_MCP_WEBSOCKET_URL:", JSON.stringify(WS_URI)); +console.log("PENPOT_MCP_VERSION:", MCP_VERSION); export default defineConfig({ base: "./", @@ -37,5 +43,6 @@ export default defineConfig({ }, define: { PENPOT_MCP_WEBSOCKET_URL: JSON.stringify(WS_URI), + PENPOT_MCP_VERSION: MCP_VERSION, }, }); From f3cc6d0d7267a0d8f111dc1cf72a9e1535dd3bf3 Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Fri, 27 Mar 2026 18:17:27 +0100 Subject: [PATCH 04/16] :tada: Add MCP version mismatch detection If the MCP version (as given in mcp/package.json) does not match the Penpot version (as given by penpot.version), display a warning message in the plugin UI. This is important for users running the local MCP server, as it is a common failure mode to combine the MCP server with an incompatible Penpot version. --- mcp/README.md | 4 +++ mcp/packages/plugin/index.html | 4 +++ mcp/packages/plugin/src/index.d.ts | 9 +++++++ mcp/packages/plugin/src/main.ts | 11 ++++++++ mcp/packages/plugin/src/plugin.ts | 42 ++++++++++++++++++++++++------ mcp/packages/plugin/src/style.css | 12 +++++++++ 6 files changed, 74 insertions(+), 8 deletions(-) diff --git a/mcp/README.md b/mcp/README.md index 539266ee15..f74a89b6ae 100644 --- a/mcp/README.md +++ b/mcp/README.md @@ -302,5 +302,9 @@ you may set the following environment variables to configure the two servers * The [contribution guidelines for Penpot](../CONTRIBUTING.md) apply * Auto-formatting: Use `pnpm run fmt` * Generating API type data: See [types-generator/README.md](types-generator/README.md) +* Versioning: Use `bash scripts/set-version` to set the version for the MCP package (in `package.json`). + - Ensure that at least the major, minor and patch components of the version are always up-to-date. + - The MCP plugin assumes that a mismatch between the MCP version and the Penpot version (as returned by the API) + indicates incompatibility, resulting in the display of a warning message in the plugin UI. * Packaging and publishing: - Create npm package: `bash scripts/pack` (sets version and then calls `npm pack`) diff --git a/mcp/packages/plugin/index.html b/mcp/packages/plugin/index.html index fa573c1d0e..de2ff5853c 100644 --- a/mcp/packages/plugin/index.html +++ b/mcp/packages/plugin/index.html @@ -7,6 +7,10 @@
+ +
Not connected diff --git a/mcp/packages/plugin/src/index.d.ts b/mcp/packages/plugin/src/index.d.ts index a0eda651e1..42587c8304 100644 --- a/mcp/packages/plugin/src/index.d.ts +++ b/mcp/packages/plugin/src/index.d.ts @@ -1,3 +1,12 @@ +import "@penpot/plugin-types"; + +declare module "@penpot/plugin-types" { + interface Penpot { + /** The Penpot application version string. */ + version: string; + } +} + interface McpOptions { getToken(): string; getServerUrl(): string; diff --git a/mcp/packages/plugin/src/main.ts b/mcp/packages/plugin/src/main.ts index e721689563..40b5bd7ba8 100644 --- a/mcp/packages/plugin/src/main.ts +++ b/mcp/packages/plugin/src/main.ts @@ -14,6 +14,8 @@ const executedCodeEl = document.getElementById("executed-code") as HTMLTextAreaE const copyCodeBtn = document.getElementById("copy-code-btn") as HTMLButtonElement; const connectBtn = document.getElementById("connect-btn") as HTMLButtonElement; const disconnectBtn = document.getElementById("disconnect-btn") as HTMLButtonElement; +const versionWarningEl = document.getElementById("version-warning") as HTMLElement; +const versionWarningTextEl = document.getElementById("version-warning-text") as HTMLElement; /** * Updates the status pill and button visibility based on connection state. @@ -177,6 +179,15 @@ window.addEventListener("message", (event) => { if (event.data.type === "start-server") { connectToMcpServer(event.data.url, event.data.token); } + if (event.data.type === "version-mismatch") { + if (versionWarningEl && versionWarningTextEl) { + versionWarningTextEl.innerHTML = + `Version mismatch detected: This version of the MCP server is intended for Penpot ` + + `${event.data.mcpVersion} while the current version is ${event.data.penpotVersion}. ` + + `Executions may not work or produce suboptimal results.`; + versionWarningEl.hidden = false; + } + } if (event.data.type === "stop-server") { ws?.close(); } else if (event.data.source === "penpot") { diff --git a/mcp/packages/plugin/src/plugin.ts b/mcp/packages/plugin/src/plugin.ts index e2b5bee38e..3827db70eb 100644 --- a/mcp/packages/plugin/src/plugin.ts +++ b/mcp/packages/plugin/src/plugin.ts @@ -1,6 +1,17 @@ import { ExecuteCodeTaskHandler } from "./task-handlers/ExecuteCodeTaskHandler"; import { Task, TaskHandler } from "./TaskHandler"; +/** + * Extracts the major.minor.patch prefix from a version string. + * + * @param version - a version string starting with major.minor.patch + * @returns the major.minor.patch prefix, or the original string if it does not match + */ +function extractVersionPrefix(version: string): string { + const match = version.match(/^(\d+\.\d+\.\d+)/); + return match ? match[1] : version; +} + mcp?.setMcpStatus("connecting"); /** @@ -15,18 +26,33 @@ penpot.ui.open("Penpot MCP Plugin", `?theme=${penpot.theme}`, { hidden: !!mcp, } as any); -// Handle messages +// Register message handlers penpot.ui.onMessage((message) => { - // Handle plugin task requests - if (mcp && typeof message === "object" && message.type === "ui-initialized") { - penpot.ui.sendMessage({ - type: "start-server", - url: mcp?.getServerUrl(), - token: mcp?.getToken(), - }); + if (typeof message === "object" && message.type === "ui-initialized") { + // Check Penpot version compatibility + const penpotVersionPrefix = penpot.version ? extractVersionPrefix(penpot.version) : "<2.15"; // pre-2.15 versions don't have version info + const mcpVersionPrefix = extractVersionPrefix(PENPOT_MCP_VERSION); + console.log(`Penpot version: ${penpotVersionPrefix}, MCP version: ${mcpVersionPrefix}`); + const isLocalPenpotVersion = penpotVersionPrefix == "0.0.0"; + if (penpotVersionPrefix !== mcpVersionPrefix && !isLocalPenpotVersion) { + penpot.ui.sendMessage({ + type: "version-mismatch", + mcpVersion: mcpVersionPrefix, + penpotVersion: penpotVersionPrefix, + }); + } + // Initiate connection to remote MCP server (if enabled) + if (mcp) { + penpot.ui.sendMessage({ + type: "start-server", + url: mcp?.getServerUrl(), + token: mcp?.getToken(), + }); + } } else if (typeof message === "object" && message.type === "update-connection-status") { mcp?.setMcpStatus(message.status || "unknown"); } else if (typeof message === "object" && message.task && message.id) { + // Handle plugin tasks submitted by the MCP server handlePluginTaskRequest(message).catch((error) => { console.error("Error in handlePluginTaskRequest:", error); }); diff --git a/mcp/packages/plugin/src/style.css b/mcp/packages/plugin/src/style.css index 7061657b33..53e0a9da3d 100644 --- a/mcp/packages/plugin/src/style.css +++ b/mcp/packages/plugin/src/style.css @@ -169,6 +169,18 @@ details[open] > .collapsible-header .collapsible-arrow { border-color: var(--accent-primary); } +/* ── Version warning ─────────────────────────────────────────────── */ + +.version-warning { + align-items: flex-start; + padding: var(--spacing-8) var(--spacing-12); + border-radius: var(--spacing-8); + border: 1px solid var(--warning-500, #f59e0b); + color: var(--warning-500, #f59e0b); + width: 100%; + box-sizing: border-box; +} + /* ── Action buttons ──────────────────────────────────────────────── */ #connect-btn, From 8ce860cf0c1e12cbc18a85ce79eb6e33c7920369 Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Mon, 30 Mar 2026 03:00:57 +0200 Subject: [PATCH 05/16] :books: Update MCP git branch information --- mcp/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mcp/README.md b/mcp/README.md index f74a89b6ae..a9a623b1e0 100644 --- a/mcp/README.md +++ b/mcp/README.md @@ -85,16 +85,16 @@ On Windows, use the Git Bash terminal to ensure compatibility with the provided Clone the Penpot repository, using the proper branch depending on the version of Penpot you want to use the MCP server with. - * For the current Penpot release 2.14, use the `mcp-prod-2.14.0` branch: + * For the current Penpot release 2.14, use the `mcp-prod-2.14.1` branch: ```shell - git clone https://github.com/penpot/penpot.git --branch mcp-prod-2.14.0 --depth 1 + git clone https://github.com/penpot/penpot.git --branch mcp-prod-2.14.1 --depth 1 ``` - * For the latest development version of Penpot (including the MCP beta-test), use the `develop` branch: + * For the MCP beta-test, use the `staging` branch: ```shell - git clone https://github.com/penpot/penpot.git --branch develop --depth 1 + git clone https://github.com/penpot/penpot.git --branch staging --depth 1 ``` Then change into the `mcp` directory: From d6dc0fe1a75203f249965154485651bebc8a44b4 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 31 Mar 2026 14:36:43 +0200 Subject: [PATCH 06/16] :bug: Fix raw file data download on dbg pannel (#8847) --- backend/src/app/http/debug.clj | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/backend/src/app/http/debug.clj b/backend/src/app/http/debug.clj index 35650f9a10..6fb8419ac8 100644 --- a/backend/src/app/http/debug.clj +++ b/backend/src/app/http/debug.clj @@ -31,7 +31,6 @@ [app.srepl.main :as srepl] [app.storage :as-alias sto] [app.storage.tmp :as tmp] - [app.util.blob :as blob] [app.util.template :as tmpl] [cuerdas.core :as str] [datoteka.io :as io] @@ -71,8 +70,7 @@ (defn- get-resolved-file [cfg file-id] - (some-> (bfc/get-file cfg file-id :migrate? false) - (update :data blob/encode))) + (bfc/get-file cfg file-id :migrate? false :decode? false)) (defn prepare-download [file filename] From 9d703439bd082d8f4f3dade6972080c27eebee87 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 31 Mar 2026 15:03:27 +0200 Subject: [PATCH 07/16] :sparkles: Add helper for define clock in millis precision --- common/src/app/common/time.cljc | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/common/src/app/common/time.cljc b/common/src/app/common/time.cljc index 3784cba8a5..d73225008c 100644 --- a/common/src/app/common/time.cljc +++ b/common/src/app/common/time.cljc @@ -90,13 +90,22 @@ (Clock/fixed ^Instant (inst instant) ^ZoneId (ZoneId/of "Z")))) - - (defn now [] #?(:clj (Instant/now *clock*) :cljs (new js/Date))) +#?(:clj + (defn tick-millis-clock + "Alternate clock with a resolution of milliseconds instead of the default nanoseconds of the Java clock. + This may be useful if the instant is going to be serialized to DB with fressian (that does not have + resolution enough to store all precission) and need to compare the deserialized value for equality. + + You can replace the global clock (for example in unit tests) with + (alter-var-root #'ct/*clock* (constantly (ct/tick-millis-clock)))" + [] + (Clock/tickMillis (ZoneId/of "Z")))) + ;; --- DURATION (defn- resolve-temporal-unit From 667a995e66b6a184ed568fd0de5ea8c78212bf46 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 31 Mar 2026 15:03:59 +0200 Subject: [PATCH 08/16] :sparkles: Make update-token- noop if token is not modified --- common/src/app/common/types/tokens_lib.cljc | 24 +++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/common/src/app/common/types/tokens_lib.cljc b/common/src/app/common/types/tokens_lib.cljc index 63cd87e393..6430a05a7b 100644 --- a/common/src/app/common/types/tokens_lib.cljc +++ b/common/src/app/common/types/tokens_lib.cljc @@ -242,17 +242,19 @@ (update-token- [this token-id f] (assert (uuid? token-id) "expected uuid for `token-id`") (if-let [token (get-token- this token-id)] - (let [token' (-> (make-token (f token)) - (assoc :modified-at (ct/now)))] - (TokenSet. id - name - description - (ct/now) - (if (= (:name token) (:name token')) - (assoc tokens (:name token') token') - (-> tokens - (d/oassoc-before (:name token) (:name token') token') - (dissoc (:name token)))))) + (let [token' (f token)] + (if (not= token token') + (let [token' (assoc token' :modified-at (ct/now))] + (TokenSet. id + name + description + (ct/now) + (if (= (:name token) (:name token')) + (assoc tokens (:name token') token') + (-> tokens + (d/oassoc-before (:name token) (:name token') token') + (dissoc (:name token)))))) + this)) this)) (delete-token- [this token-id] From e6ab57f71953d1a88d5bed001d925681b73abfa0 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 31 Mar 2026 15:05:54 +0200 Subject: [PATCH 09/16] :paperclip: Add minor cosmetic reoriganization on tokens-lib --- common/src/app/common/types/tokens_lib.cljc | 59 ++++++++++--------- .../test/common_tests/types/token_test.cljc | 14 +++-- 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/common/src/app/common/types/tokens_lib.cljc b/common/src/app/common/types/tokens_lib.cljc index 6430a05a7b..e4b0e5ae43 100644 --- a/common/src/app/common/types/tokens_lib.cljc +++ b/common/src/app/common/types/tokens_lib.cljc @@ -305,6 +305,35 @@ (-clj->js [this] (clj->js (datafy this))))) +(def ^:private set-prefix "S-") + +(def ^:private set-group-prefix "G-") + +(def ^:private set-separator "/") + +(defn get-set-path + [token-set] + (cpn/split-path (get-name token-set) :separator set-separator)) + +(defn split-set-name + [name] + (cpn/split-path name :separator set-separator)) + +(defn join-set-path [path] + (cpn/join-path path :separator set-separator :with-spaces? false)) + +(defn normalize-set-name + "Normalize a set name (ensure that there are no extra spaces, like ' group / set' -> 'group/set'). + + If `relative-to` is provided, the normalized name will preserve the same group prefix as reference name." + ([name] + (-> (split-set-name name) + (cpn/join-path :separator set-separator :with-spaces? false))) + ([name relative-to] + (-> (concat (butlast (split-set-name relative-to)) + (split-set-name name)) + (cpn/join-path :separator set-separator :with-spaces? false)))) + (defn token-set? [o] (instance? TokenSet o)) @@ -359,6 +388,7 @@ (def check-token-set (sm/check-fn schema:token-set :hint "expected valid token set")) + (defn map->token-set [& {:as attrs}] (TokenSet. (:id attrs) @@ -377,35 +407,6 @@ (check-token-set-attrs) (map->token-set))) -(def ^:private set-prefix "S-") - -(def ^:private set-group-prefix "G-") - -(def ^:private set-separator "/") - -(defn get-set-path - [token-set] - (cpn/split-path (get-name token-set) :separator set-separator)) - -(defn split-set-name - [name] - (cpn/split-path name :separator set-separator)) - -(defn join-set-path [path] - (cpn/join-path path :separator set-separator :with-spaces? false)) - -(defn normalize-set-name - "Normalize a set name (ensure that there are no extra spaces, like ' group / set' -> 'group/set'). - - If `relative-to` is provided, the normalized name will preserve the same group prefix as reference name." - ([name] - (-> (split-set-name name) - (cpn/join-path :separator set-separator :with-spaces? false))) - ([name relative-to] - (-> (concat (butlast (split-set-name relative-to)) - (split-set-name name)) - (cpn/join-path :separator set-separator :with-spaces? false)))) - (defn normalized-set-name? "Check if a set name is normalized (no extra spaces)." [name] diff --git a/common/test/common_tests/types/token_test.cljc b/common/test/common_tests/types/token_test.cljc index 96e642690c..b44bc87eaf 100644 --- a/common/test/common_tests/types/token_test.cljc +++ b/common/test/common_tests/types/token_test.cljc @@ -10,20 +10,26 @@ [app.common.types.token :as cto] [clojure.test :as t])) -(t/deftest test-valid-token-name-schema +(t/deftest test-valid-token-name ;; Allow regular namespace token names (t/is (true? (sm/validate cto/schema:token-name "Foo"))) (t/is (true? (sm/validate cto/schema:token-name "foo"))) (t/is (true? (sm/validate cto/schema:token-name "FOO"))) (t/is (true? (sm/validate cto/schema:token-name "Foo.Bar.Baz"))) - ;; Disallow trailing tokens + ;; Allow $ inside or at the end of the name, but not at the beginning + (t/is (true? (sm/validate cto/schema:token-name "Foo$Bar$Baz"))) + (t/is (true? (sm/validate cto/schema:token-name "Foo$Bar$Baz$"))) + (t/is (false? (sm/validate cto/schema:token-name "$Foo$Bar$Baz"))) + ;; Disallow starting and trailing dots + (t/is (false? (sm/validate cto/schema:token-name "....Foo.Bar.Baz"))) (t/is (false? (sm/validate cto/schema:token-name "Foo.Bar.Baz...."))) ;; Disallow multiple separator dots (t/is (false? (sm/validate cto/schema:token-name "Foo..Bar.Baz"))) ;; Disallow any special characters (t/is (false? (sm/validate cto/schema:token-name "Hey Foo.Bar"))) - (t/is (false? (sm/validate cto/schema:token-name "Hey😈Foo.Bar"))) - (t/is (false? (sm/validate cto/schema:token-name "Hey%Foo.Bar")))) + (t/is (false? (sm/validate cto/schema:token-name "HeyÅFoo.Bar"))) + (t/is (false? (sm/validate cto/schema:token-name "Hey%Foo.Bar"))) + (t/is (false? (sm/validate cto/schema:token-name "Hey / Foo/Bar")))) (t/deftest token-value-with-refs From 084ca401fd5b66cab1fba3b57e904e0e7ea22cf8 Mon Sep 17 00:00:00 2001 From: Yamila Moreno Date: Tue, 31 Mar 2026 15:11:58 +0200 Subject: [PATCH 10/16] :books: Improve recommended settings for self-host (#8846) --- docs/technical-guide/configuration.md | 14 ++++++++++++++ .../getting-started/recommended-settings.md | 13 +++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/docs/technical-guide/configuration.md b/docs/technical-guide/configuration.md index f48117b071..ad4579fcde 100644 --- a/docs/technical-guide/configuration.md +++ b/docs/technical-guide/configuration.md @@ -401,6 +401,20 @@ PENPOT_FLAGS: [...] enable-air-gapped-conf When Penpot starts, it will leave out the Nginx configuration related to external requests. This means that, with this flag enabled, the Penpot configuration will disable as well the libraries and templates dashboard and the use of Google fonts. +## High availability + +The mechanisms for installing Penpot in HA depend largely on how each infrastructure is managed. +In this section, we mention the key factors to consider when replicating a Penpot installation: + +The components that can be replicated are the `frontend`, the `backend`, and the `exporter`. +Replication management depends on the infrastructure, whether it's a load balancer or a Kubernetes deployment with HPA. + +In a high-availability (HA) scenario, managing the state outside of replicas is crucial. This affects the following components: + +- Database: Penpot typically operates with a single database instance. This database can also have a replica in case the primary instance fails. +- Valkey: Penpot only needs one Valkey instance to function correctly. Due to the nature of the data it manages, replication isn't even essential. +- User media storage: This should not be configured with local storage but rather with centralized storage, such as Kubernetes PVC or S3. + ## Backend This section enumerates the backend only configuration variables. diff --git a/docs/technical-guide/getting-started/recommended-settings.md b/docs/technical-guide/getting-started/recommended-settings.md index 4a36935b75..e0550ad430 100644 --- a/docs/technical-guide/getting-started/recommended-settings.md +++ b/docs/technical-guide/getting-started/recommended-settings.md @@ -3,9 +3,18 @@ title: 1.1 Recommended settings desc: Learn recommended self-hosting settings, Docker & Kubernetes installs, configuration, and troubleshooting tips in Penpot's technical guide. --- -# Recommended storage +# Recommended settings -Disk requirements depend on your usage, with the primary factors being database storage and user-uploaded files. +

+ These recommended settings do not cover specific high-availability setups, which will depend on your particular best practices. + Also, for air-gapped environments, please make sure to read this section of the guide. +

+ +Regarding **hardware requirements**, these will largely depend on the purpose of the installation. It's important to know that Penpot makes extensive use of the browser, so you need to ensure you have powerful end-user computers. To get the most out of Penpot, we recommend using the latest stable version of Chrome. + +Regarding the **server**, 4 CPUs and 16GB of RAM are sufficient to support thousands of users. So you can also be conservative when allocating resources to the instance. + +**Disk requirements** depend on your usage, with the primary factors being database storage and user-uploaded files. As a rule of thumb, start with a **minimum** database size of **50GB** to **100GB** with elastic sizing capability — this configuration should adequately support up to 10 editors. For environments with **more than 10 users**, we recommend adding approximately **5GB** of capacity per additional editor. From 94215447c9a52767f6d9e3933a3f818622fe2bef Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Tue, 31 Mar 2026 13:13:18 +0200 Subject: [PATCH 11/16] :fire: Remove redundant lock file in server package Lock file in mcp/ base package should be single source of truth. --- mcp/packages/server/.gitignore | 1 + mcp/packages/server/pnpm-lock.yaml | 2840 ---------------------------- 2 files changed, 1 insertion(+), 2840 deletions(-) delete mode 100644 mcp/packages/server/pnpm-lock.yaml diff --git a/mcp/packages/server/.gitignore b/mcp/packages/server/.gitignore index e69de29bb2..54e8e7dc16 100644 --- a/mcp/packages/server/.gitignore +++ b/mcp/packages/server/.gitignore @@ -0,0 +1 @@ +/pnpm-lock.yaml diff --git a/mcp/packages/server/pnpm-lock.yaml b/mcp/packages/server/pnpm-lock.yaml deleted file mode 100644 index b8229de386..0000000000 --- a/mcp/packages/server/pnpm-lock.yaml +++ /dev/null @@ -1,2840 +0,0 @@ -lockfileVersion: "9.0" - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - .: - dependencies: - "@modelcontextprotocol/sdk": - specifier: ^1.24.0 - version: 1.25.3(hono@4.11.7)(zod@4.3.6) - "@penpot-mcp/common": - specifier: file:../common - version: file:../common - class-transformer: - specifier: ^0.5.1 - version: 0.5.1 - class-validator: - specifier: ^0.14.3 - version: 0.14.3 - express: - specifier: ^5.1.0 - version: 5.2.1 - js-yaml: - specifier: ^4.1.1 - version: 4.1.1 - penpot-mcp: - specifier: file:.. - version: file:.. - pino: - specifier: ^9.10.0 - version: 9.14.0 - pino-pretty: - specifier: ^13.1.1 - version: 13.1.3 - reflect-metadata: - specifier: ^0.1.13 - version: 0.1.14 - sharp: - specifier: ^0.34.5 - version: 0.34.5 - ws: - specifier: ^8.18.0 - version: 8.19.0 - devDependencies: - "@types/express": - specifier: ^4.17.0 - version: 4.17.25 - "@types/js-yaml": - specifier: ^4.0.9 - version: 4.0.9 - "@types/node": - specifier: ^20.0.0 - version: 20.19.30 - "@types/ws": - specifier: ^8.5.10 - version: 8.18.1 - esbuild: - specifier: ^0.25.0 - version: 0.25.12 - ts-node: - specifier: ^10.9.0 - version: 10.9.2(@types/node@20.19.30)(typescript@5.9.3) - typescript: - specifier: ^5.0.0 - version: 5.9.3 - -packages: - "@babel/runtime@7.28.6": - resolution: - { - integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==, - } - engines: { node: ">=6.9.0" } - - "@cspotcode/source-map-support@0.8.1": - resolution: - { - integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==, - } - engines: { node: ">=12" } - - "@emnapi/runtime@1.8.1": - resolution: - { - integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==, - } - - "@esbuild/aix-ppc64@0.25.12": - resolution: - { - integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==, - } - engines: { node: ">=18" } - cpu: [ppc64] - os: [aix] - - "@esbuild/android-arm64@0.25.12": - resolution: - { - integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [android] - - "@esbuild/android-arm@0.25.12": - resolution: - { - integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==, - } - engines: { node: ">=18" } - cpu: [arm] - os: [android] - - "@esbuild/android-x64@0.25.12": - resolution: - { - integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [android] - - "@esbuild/darwin-arm64@0.25.12": - resolution: - { - integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [darwin] - - "@esbuild/darwin-x64@0.25.12": - resolution: - { - integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [darwin] - - "@esbuild/freebsd-arm64@0.25.12": - resolution: - { - integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [freebsd] - - "@esbuild/freebsd-x64@0.25.12": - resolution: - { - integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [freebsd] - - "@esbuild/linux-arm64@0.25.12": - resolution: - { - integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [linux] - - "@esbuild/linux-arm@0.25.12": - resolution: - { - integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==, - } - engines: { node: ">=18" } - cpu: [arm] - os: [linux] - - "@esbuild/linux-ia32@0.25.12": - resolution: - { - integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==, - } - engines: { node: ">=18" } - cpu: [ia32] - os: [linux] - - "@esbuild/linux-loong64@0.25.12": - resolution: - { - integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==, - } - engines: { node: ">=18" } - cpu: [loong64] - os: [linux] - - "@esbuild/linux-mips64el@0.25.12": - resolution: - { - integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==, - } - engines: { node: ">=18" } - cpu: [mips64el] - os: [linux] - - "@esbuild/linux-ppc64@0.25.12": - resolution: - { - integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==, - } - engines: { node: ">=18" } - cpu: [ppc64] - os: [linux] - - "@esbuild/linux-riscv64@0.25.12": - resolution: - { - integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==, - } - engines: { node: ">=18" } - cpu: [riscv64] - os: [linux] - - "@esbuild/linux-s390x@0.25.12": - resolution: - { - integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==, - } - engines: { node: ">=18" } - cpu: [s390x] - os: [linux] - - "@esbuild/linux-x64@0.25.12": - resolution: - { - integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [linux] - - "@esbuild/netbsd-arm64@0.25.12": - resolution: - { - integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [netbsd] - - "@esbuild/netbsd-x64@0.25.12": - resolution: - { - integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [netbsd] - - "@esbuild/openbsd-arm64@0.25.12": - resolution: - { - integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [openbsd] - - "@esbuild/openbsd-x64@0.25.12": - resolution: - { - integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [openbsd] - - "@esbuild/openharmony-arm64@0.25.12": - resolution: - { - integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [openharmony] - - "@esbuild/sunos-x64@0.25.12": - resolution: - { - integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [sunos] - - "@esbuild/win32-arm64@0.25.12": - resolution: - { - integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==, - } - engines: { node: ">=18" } - cpu: [arm64] - os: [win32] - - "@esbuild/win32-ia32@0.25.12": - resolution: - { - integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==, - } - engines: { node: ">=18" } - cpu: [ia32] - os: [win32] - - "@esbuild/win32-x64@0.25.12": - resolution: - { - integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==, - } - engines: { node: ">=18" } - cpu: [x64] - os: [win32] - - "@hono/node-server@1.19.9": - resolution: - { - integrity: sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==, - } - engines: { node: ">=18.14.1" } - peerDependencies: - hono: ^4 - - "@img/colour@1.0.0": - resolution: - { - integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==, - } - engines: { node: ">=18" } - - "@img/sharp-darwin-arm64@0.34.5": - resolution: - { - integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [arm64] - os: [darwin] - - "@img/sharp-darwin-x64@0.34.5": - resolution: - { - integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [x64] - os: [darwin] - - "@img/sharp-libvips-darwin-arm64@1.2.4": - resolution: - { - integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==, - } - cpu: [arm64] - os: [darwin] - - "@img/sharp-libvips-darwin-x64@1.2.4": - resolution: - { - integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==, - } - cpu: [x64] - os: [darwin] - - "@img/sharp-libvips-linux-arm64@1.2.4": - resolution: - { - integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==, - } - cpu: [arm64] - os: [linux] - - "@img/sharp-libvips-linux-arm@1.2.4": - resolution: - { - integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==, - } - cpu: [arm] - os: [linux] - - "@img/sharp-libvips-linux-ppc64@1.2.4": - resolution: - { - integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==, - } - cpu: [ppc64] - os: [linux] - - "@img/sharp-libvips-linux-riscv64@1.2.4": - resolution: - { - integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==, - } - cpu: [riscv64] - os: [linux] - - "@img/sharp-libvips-linux-s390x@1.2.4": - resolution: - { - integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==, - } - cpu: [s390x] - os: [linux] - - "@img/sharp-libvips-linux-x64@1.2.4": - resolution: - { - integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==, - } - cpu: [x64] - os: [linux] - - "@img/sharp-libvips-linuxmusl-arm64@1.2.4": - resolution: - { - integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==, - } - cpu: [arm64] - os: [linux] - - "@img/sharp-libvips-linuxmusl-x64@1.2.4": - resolution: - { - integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==, - } - cpu: [x64] - os: [linux] - - "@img/sharp-linux-arm64@0.34.5": - resolution: - { - integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [arm64] - os: [linux] - - "@img/sharp-linux-arm@0.34.5": - resolution: - { - integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [arm] - os: [linux] - - "@img/sharp-linux-ppc64@0.34.5": - resolution: - { - integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [ppc64] - os: [linux] - - "@img/sharp-linux-riscv64@0.34.5": - resolution: - { - integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [riscv64] - os: [linux] - - "@img/sharp-linux-s390x@0.34.5": - resolution: - { - integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [s390x] - os: [linux] - - "@img/sharp-linux-x64@0.34.5": - resolution: - { - integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [x64] - os: [linux] - - "@img/sharp-linuxmusl-arm64@0.34.5": - resolution: - { - integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [arm64] - os: [linux] - - "@img/sharp-linuxmusl-x64@0.34.5": - resolution: - { - integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [x64] - os: [linux] - - "@img/sharp-wasm32@0.34.5": - resolution: - { - integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [wasm32] - - "@img/sharp-win32-arm64@0.34.5": - resolution: - { - integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [arm64] - os: [win32] - - "@img/sharp-win32-ia32@0.34.5": - resolution: - { - integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [ia32] - os: [win32] - - "@img/sharp-win32-x64@0.34.5": - resolution: - { - integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - cpu: [x64] - os: [win32] - - "@jridgewell/resolve-uri@3.1.2": - resolution: - { - integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==, - } - engines: { node: ">=6.0.0" } - - "@jridgewell/sourcemap-codec@1.5.5": - resolution: - { - integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==, - } - - "@jridgewell/trace-mapping@0.3.9": - resolution: - { - integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==, - } - - "@modelcontextprotocol/sdk@1.25.3": - resolution: - { - integrity: sha512-vsAMBMERybvYgKbg/l4L1rhS7VXV1c0CtyJg72vwxONVX0l4ZfKVAnZEWTQixJGTzKnELjQ59e4NbdFDALRiAQ==, - } - engines: { node: ">=18" } - peerDependencies: - "@cfworker/json-schema": ^4.1.1 - zod: ^3.25 || ^4.0 - peerDependenciesMeta: - "@cfworker/json-schema": - optional: true - - "@penpot-mcp/common@file:../common": - resolution: { directory: ../common, type: directory } - - "@pinojs/redact@0.4.0": - resolution: - { - integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==, - } - - "@tsconfig/node10@1.0.12": - resolution: - { - integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==, - } - - "@tsconfig/node12@1.0.11": - resolution: - { - integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==, - } - - "@tsconfig/node14@1.0.3": - resolution: - { - integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==, - } - - "@tsconfig/node16@1.0.4": - resolution: - { - integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==, - } - - "@types/body-parser@1.19.6": - resolution: - { - integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==, - } - - "@types/connect@3.4.38": - resolution: - { - integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==, - } - - "@types/express-serve-static-core@4.19.8": - resolution: - { - integrity: sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==, - } - - "@types/express@4.17.25": - resolution: - { - integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==, - } - - "@types/http-errors@2.0.5": - resolution: - { - integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==, - } - - "@types/js-yaml@4.0.9": - resolution: - { - integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==, - } - - "@types/mime@1.3.5": - resolution: - { - integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==, - } - - "@types/node@20.19.30": - resolution: - { - integrity: sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==, - } - - "@types/qs@6.14.0": - resolution: - { - integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==, - } - - "@types/range-parser@1.2.7": - resolution: - { - integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==, - } - - "@types/send@0.17.6": - resolution: - { - integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==, - } - - "@types/send@1.2.1": - resolution: - { - integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==, - } - - "@types/serve-static@1.15.10": - resolution: - { - integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==, - } - - "@types/validator@13.15.10": - resolution: - { - integrity: sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==, - } - - "@types/ws@8.18.1": - resolution: - { - integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==, - } - - accepts@2.0.0: - resolution: - { - integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==, - } - engines: { node: ">= 0.6" } - - acorn-walk@8.3.4: - resolution: - { - integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==, - } - engines: { node: ">=0.4.0" } - - acorn@8.15.0: - resolution: - { - integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==, - } - engines: { node: ">=0.4.0" } - hasBin: true - - ajv-formats@3.0.1: - resolution: - { - integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==, - } - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - - ajv@8.17.1: - resolution: - { - integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==, - } - - ansi-regex@5.0.1: - resolution: - { - integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, - } - engines: { node: ">=8" } - - ansi-styles@4.3.0: - resolution: - { - integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, - } - engines: { node: ">=8" } - - arg@4.1.3: - resolution: - { - integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==, - } - - argparse@2.0.1: - resolution: - { - integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==, - } - - atomic-sleep@1.0.0: - resolution: - { - integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==, - } - engines: { node: ">=8.0.0" } - - body-parser@2.2.2: - resolution: - { - integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==, - } - engines: { node: ">=18" } - - bytes@3.1.2: - resolution: - { - integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==, - } - engines: { node: ">= 0.8" } - - call-bind-apply-helpers@1.0.2: - resolution: - { - integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==, - } - engines: { node: ">= 0.4" } - - call-bound@1.0.4: - resolution: - { - integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==, - } - engines: { node: ">= 0.4" } - - chalk@4.1.2: - resolution: - { - integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==, - } - engines: { node: ">=10" } - - class-transformer@0.5.1: - resolution: - { - integrity: sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==, - } - - class-validator@0.14.3: - resolution: - { - integrity: sha512-rXXekcjofVN1LTOSw+u4u9WXVEUvNBVjORW154q/IdmYWy1nMbOU9aNtZB0t8m+FJQ9q91jlr2f9CwwUFdFMRA==, - } - - cliui@8.0.1: - resolution: - { - integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==, - } - engines: { node: ">=12" } - - color-convert@2.0.1: - resolution: - { - integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, - } - engines: { node: ">=7.0.0" } - - color-name@1.1.4: - resolution: - { - integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, - } - - colorette@2.0.20: - resolution: - { - integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==, - } - - concurrently@8.2.2: - resolution: - { - integrity: sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==, - } - engines: { node: ^14.13.0 || >=16.0.0 } - hasBin: true - - content-disposition@1.0.1: - resolution: - { - integrity: sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==, - } - engines: { node: ">=18" } - - content-type@1.0.5: - resolution: - { - integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==, - } - engines: { node: ">= 0.6" } - - cookie-signature@1.2.2: - resolution: - { - integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==, - } - engines: { node: ">=6.6.0" } - - cookie@0.7.2: - resolution: - { - integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==, - } - engines: { node: ">= 0.6" } - - cors@2.8.6: - resolution: - { - integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==, - } - engines: { node: ">= 0.10" } - - create-require@1.1.1: - resolution: - { - integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==, - } - - cross-spawn@7.0.6: - resolution: - { - integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==, - } - engines: { node: ">= 8" } - - date-fns@2.30.0: - resolution: - { - integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==, - } - engines: { node: ">=0.11" } - - dateformat@4.6.3: - resolution: - { - integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==, - } - - debug@4.4.3: - resolution: - { - integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==, - } - engines: { node: ">=6.0" } - peerDependencies: - supports-color: "*" - peerDependenciesMeta: - supports-color: - optional: true - - depd@2.0.0: - resolution: - { - integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==, - } - engines: { node: ">= 0.8" } - - detect-libc@2.1.2: - resolution: - { - integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==, - } - engines: { node: ">=8" } - - diff@4.0.4: - resolution: - { - integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==, - } - engines: { node: ">=0.3.1" } - - dunder-proto@1.0.1: - resolution: - { - integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==, - } - engines: { node: ">= 0.4" } - - ee-first@1.1.1: - resolution: - { - integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==, - } - - emoji-regex@8.0.0: - resolution: - { - integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, - } - - encodeurl@2.0.0: - resolution: - { - integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==, - } - engines: { node: ">= 0.8" } - - end-of-stream@1.4.5: - resolution: - { - integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==, - } - - es-define-property@1.0.1: - resolution: - { - integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==, - } - engines: { node: ">= 0.4" } - - es-errors@1.3.0: - resolution: - { - integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==, - } - engines: { node: ">= 0.4" } - - es-object-atoms@1.1.1: - resolution: - { - integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==, - } - engines: { node: ">= 0.4" } - - esbuild@0.25.12: - resolution: - { - integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==, - } - engines: { node: ">=18" } - hasBin: true - - escalade@3.2.0: - resolution: - { - integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==, - } - engines: { node: ">=6" } - - escape-html@1.0.3: - resolution: - { - integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==, - } - - etag@1.8.1: - resolution: - { - integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==, - } - engines: { node: ">= 0.6" } - - eventsource-parser@3.0.6: - resolution: - { - integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==, - } - engines: { node: ">=18.0.0" } - - eventsource@3.0.7: - resolution: - { - integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==, - } - engines: { node: ">=18.0.0" } - - express-rate-limit@7.5.1: - resolution: - { - integrity: sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==, - } - engines: { node: ">= 16" } - peerDependencies: - express: ">= 4.11" - - express@5.2.1: - resolution: - { - integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==, - } - engines: { node: ">= 18" } - - fast-copy@4.0.2: - resolution: - { - integrity: sha512-ybA6PDXIXOXivLJK/z9e+Otk7ve13I4ckBvGO5I2RRmBU1gMHLVDJYEuJYhGwez7YNlYji2M2DvVU+a9mSFDlw==, - } - - fast-deep-equal@3.1.3: - resolution: - { - integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, - } - - fast-safe-stringify@2.1.1: - resolution: - { - integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==, - } - - fast-uri@3.1.0: - resolution: - { - integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==, - } - - finalhandler@2.1.1: - resolution: - { - integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==, - } - engines: { node: ">= 18.0.0" } - - forwarded@0.2.0: - resolution: - { - integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==, - } - engines: { node: ">= 0.6" } - - fresh@2.0.0: - resolution: - { - integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==, - } - engines: { node: ">= 0.8" } - - function-bind@1.1.2: - resolution: - { - integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==, - } - - get-caller-file@2.0.5: - resolution: - { - integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==, - } - engines: { node: 6.* || 8.* || >= 10.* } - - get-intrinsic@1.3.0: - resolution: - { - integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==, - } - engines: { node: ">= 0.4" } - - get-proto@1.0.1: - resolution: - { - integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==, - } - engines: { node: ">= 0.4" } - - get-them-args@1.3.2: - resolution: - { - integrity: sha512-LRn8Jlk+DwZE4GTlDbT3Hikd1wSHgLMme/+7ddlqKd7ldwR6LjJgTVWzBnR01wnYGe4KgrXjg287RaI22UHmAw==, - } - - gopd@1.2.0: - resolution: - { - integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==, - } - engines: { node: ">= 0.4" } - - has-flag@4.0.0: - resolution: - { - integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==, - } - engines: { node: ">=8" } - - has-symbols@1.1.0: - resolution: - { - integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==, - } - engines: { node: ">= 0.4" } - - hasown@2.0.2: - resolution: - { - integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==, - } - engines: { node: ">= 0.4" } - - help-me@5.0.0: - resolution: - { - integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==, - } - - hono@4.11.7: - resolution: - { - integrity: sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==, - } - engines: { node: ">=16.9.0" } - - http-errors@2.0.1: - resolution: - { - integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==, - } - engines: { node: ">= 0.8" } - - iconv-lite@0.7.2: - resolution: - { - integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==, - } - engines: { node: ">=0.10.0" } - - inherits@2.0.4: - resolution: - { - integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, - } - - ipaddr.js@1.9.1: - resolution: - { - integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==, - } - engines: { node: ">= 0.10" } - - is-fullwidth-code-point@3.0.0: - resolution: - { - integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, - } - engines: { node: ">=8" } - - is-promise@4.0.0: - resolution: - { - integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==, - } - - isexe@2.0.0: - resolution: - { - integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, - } - - jose@6.1.3: - resolution: - { - integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==, - } - - joycon@3.1.1: - resolution: - { - integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==, - } - engines: { node: ">=10" } - - js-yaml@4.1.1: - resolution: - { - integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==, - } - hasBin: true - - json-schema-traverse@1.0.0: - resolution: - { - integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==, - } - - json-schema-typed@8.0.2: - resolution: - { - integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==, - } - - kill-port@2.0.1: - resolution: - { - integrity: sha512-e0SVOV5jFo0mx8r7bS29maVWp17qGqLBZ5ricNSajON6//kmb7qqqNnml4twNE8Dtj97UQD+gNFOaipS/q1zzQ==, - } - hasBin: true - - libphonenumber-js@1.12.35: - resolution: - { - integrity: sha512-T/Cz6iLcsZdb5jDncDcUNhSAJ0VlSC9TnsqtBNdpkaAmy24/R1RhErtNWVWBrcUZKs9hSgaVsBkc7HxYnazIfw==, - } - - lodash@4.17.23: - resolution: - { - integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==, - } - - make-error@1.3.6: - resolution: - { - integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==, - } - - math-intrinsics@1.1.0: - resolution: - { - integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==, - } - engines: { node: ">= 0.4" } - - media-typer@1.1.0: - resolution: - { - integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==, - } - engines: { node: ">= 0.8" } - - merge-descriptors@2.0.0: - resolution: - { - integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==, - } - engines: { node: ">=18" } - - mime-db@1.54.0: - resolution: - { - integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==, - } - engines: { node: ">= 0.6" } - - mime-types@3.0.2: - resolution: - { - integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==, - } - engines: { node: ">=18" } - - minimist@1.2.8: - resolution: - { - integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==, - } - - ms@2.1.3: - resolution: - { - integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, - } - - negotiator@1.0.0: - resolution: - { - integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==, - } - engines: { node: ">= 0.6" } - - object-assign@4.1.1: - resolution: - { - integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==, - } - engines: { node: ">=0.10.0" } - - object-inspect@1.13.4: - resolution: - { - integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==, - } - engines: { node: ">= 0.4" } - - on-exit-leak-free@2.1.2: - resolution: - { - integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==, - } - engines: { node: ">=14.0.0" } - - on-finished@2.4.1: - resolution: - { - integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==, - } - engines: { node: ">= 0.8" } - - once@1.4.0: - resolution: - { - integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, - } - - parseurl@1.3.3: - resolution: - { - integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==, - } - engines: { node: ">= 0.8" } - - path-key@3.1.1: - resolution: - { - integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, - } - engines: { node: ">=8" } - - path-to-regexp@8.3.0: - resolution: - { - integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==, - } - - penpot-mcp@file:..: - resolution: { directory: .., type: directory } - - pino-abstract-transport@2.0.0: - resolution: - { - integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==, - } - - pino-abstract-transport@3.0.0: - resolution: - { - integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==, - } - - pino-pretty@13.1.3: - resolution: - { - integrity: sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==, - } - hasBin: true - - pino-std-serializers@7.1.0: - resolution: - { - integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==, - } - - pino@9.14.0: - resolution: - { - integrity: sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==, - } - hasBin: true - - pkce-challenge@5.0.1: - resolution: - { - integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==, - } - engines: { node: ">=16.20.0" } - - process-warning@5.0.0: - resolution: - { - integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==, - } - - proxy-addr@2.0.7: - resolution: - { - integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==, - } - engines: { node: ">= 0.10" } - - pump@3.0.3: - resolution: - { - integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==, - } - - qs@6.14.1: - resolution: - { - integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==, - } - engines: { node: ">=0.6" } - - quick-format-unescaped@4.0.4: - resolution: - { - integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==, - } - - range-parser@1.2.1: - resolution: - { - integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==, - } - engines: { node: ">= 0.6" } - - raw-body@3.0.2: - resolution: - { - integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==, - } - engines: { node: ">= 0.10" } - - real-require@0.2.0: - resolution: - { - integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==, - } - engines: { node: ">= 12.13.0" } - - reflect-metadata@0.1.14: - resolution: - { - integrity: sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==, - } - - require-directory@2.1.1: - resolution: - { - integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==, - } - engines: { node: ">=0.10.0" } - - require-from-string@2.0.2: - resolution: - { - integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==, - } - engines: { node: ">=0.10.0" } - - router@2.2.0: - resolution: - { - integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==, - } - engines: { node: ">= 18" } - - rxjs@7.8.2: - resolution: - { - integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==, - } - - safe-stable-stringify@2.5.0: - resolution: - { - integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==, - } - engines: { node: ">=10" } - - safer-buffer@2.1.2: - resolution: - { - integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==, - } - - secure-json-parse@4.1.0: - resolution: - { - integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==, - } - - semver@7.7.3: - resolution: - { - integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==, - } - engines: { node: ">=10" } - hasBin: true - - send@1.2.1: - resolution: - { - integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==, - } - engines: { node: ">= 18" } - - serve-static@2.2.1: - resolution: - { - integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==, - } - engines: { node: ">= 18" } - - setprototypeof@1.2.0: - resolution: - { - integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==, - } - - sharp@0.34.5: - resolution: - { - integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==, - } - engines: { node: ^18.17.0 || ^20.3.0 || >=21.0.0 } - - shebang-command@2.0.0: - resolution: - { - integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, - } - engines: { node: ">=8" } - - shebang-regex@3.0.0: - resolution: - { - integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, - } - engines: { node: ">=8" } - - shell-exec@1.0.2: - resolution: - { - integrity: sha512-jyVd+kU2X+mWKMmGhx4fpWbPsjvD53k9ivqetutVW/BQ+WIZoDoP4d8vUMGezV6saZsiNoW2f9GIhg9Dondohg==, - } - - shell-quote@1.8.3: - resolution: - { - integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==, - } - engines: { node: ">= 0.4" } - - side-channel-list@1.0.0: - resolution: - { - integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==, - } - engines: { node: ">= 0.4" } - - side-channel-map@1.0.1: - resolution: - { - integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==, - } - engines: { node: ">= 0.4" } - - side-channel-weakmap@1.0.2: - resolution: - { - integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==, - } - engines: { node: ">= 0.4" } - - side-channel@1.1.0: - resolution: - { - integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==, - } - engines: { node: ">= 0.4" } - - sonic-boom@4.2.0: - resolution: - { - integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==, - } - - spawn-command@0.0.2: - resolution: - { - integrity: sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==, - } - - split2@4.2.0: - resolution: - { - integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==, - } - engines: { node: ">= 10.x" } - - statuses@2.0.2: - resolution: - { - integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==, - } - engines: { node: ">= 0.8" } - - string-width@4.2.3: - resolution: - { - integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, - } - engines: { node: ">=8" } - - strip-ansi@6.0.1: - resolution: - { - integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, - } - engines: { node: ">=8" } - - strip-json-comments@5.0.3: - resolution: - { - integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==, - } - engines: { node: ">=14.16" } - - supports-color@7.2.0: - resolution: - { - integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==, - } - engines: { node: ">=8" } - - supports-color@8.1.1: - resolution: - { - integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==, - } - engines: { node: ">=10" } - - thread-stream@3.1.0: - resolution: - { - integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==, - } - - toidentifier@1.0.1: - resolution: - { - integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==, - } - engines: { node: ">=0.6" } - - tree-kill@1.2.2: - resolution: - { - integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==, - } - hasBin: true - - ts-node@10.9.2: - resolution: - { - integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==, - } - hasBin: true - peerDependencies: - "@swc/core": ">=1.2.50" - "@swc/wasm": ">=1.2.50" - "@types/node": "*" - typescript: ">=2.7" - peerDependenciesMeta: - "@swc/core": - optional: true - "@swc/wasm": - optional: true - - tslib@2.8.1: - resolution: - { - integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==, - } - - type-is@2.0.1: - resolution: - { - integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==, - } - engines: { node: ">= 0.6" } - - typescript@5.9.3: - resolution: - { - integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==, - } - engines: { node: ">=14.17" } - hasBin: true - - undici-types@6.21.0: - resolution: - { - integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==, - } - - unpipe@1.0.0: - resolution: - { - integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==, - } - engines: { node: ">= 0.8" } - - v8-compile-cache-lib@3.0.1: - resolution: - { - integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==, - } - - validator@13.15.26: - resolution: - { - integrity: sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==, - } - engines: { node: ">= 0.10" } - - vary@1.1.2: - resolution: - { - integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==, - } - engines: { node: ">= 0.8" } - - which@2.0.2: - resolution: - { - integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, - } - engines: { node: ">= 8" } - hasBin: true - - wrap-ansi@7.0.0: - resolution: - { - integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==, - } - engines: { node: ">=10" } - - wrappy@1.0.2: - resolution: - { - integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, - } - - ws@8.19.0: - resolution: - { - integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==, - } - engines: { node: ">=10.0.0" } - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - y18n@5.0.8: - resolution: - { - integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==, - } - engines: { node: ">=10" } - - yargs-parser@21.1.1: - resolution: - { - integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==, - } - engines: { node: ">=12" } - - yargs@17.7.2: - resolution: - { - integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==, - } - engines: { node: ">=12" } - - yn@3.1.1: - resolution: - { - integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==, - } - engines: { node: ">=6" } - - zod-to-json-schema@3.25.1: - resolution: - { - integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==, - } - peerDependencies: - zod: ^3.25 || ^4 - - zod@4.3.6: - resolution: - { - integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==, - } - -snapshots: - "@babel/runtime@7.28.6": {} - - "@cspotcode/source-map-support@0.8.1": - dependencies: - "@jridgewell/trace-mapping": 0.3.9 - - "@emnapi/runtime@1.8.1": - dependencies: - tslib: 2.8.1 - optional: true - - "@esbuild/aix-ppc64@0.25.12": - optional: true - - "@esbuild/android-arm64@0.25.12": - optional: true - - "@esbuild/android-arm@0.25.12": - optional: true - - "@esbuild/android-x64@0.25.12": - optional: true - - "@esbuild/darwin-arm64@0.25.12": - optional: true - - "@esbuild/darwin-x64@0.25.12": - optional: true - - "@esbuild/freebsd-arm64@0.25.12": - optional: true - - "@esbuild/freebsd-x64@0.25.12": - optional: true - - "@esbuild/linux-arm64@0.25.12": - optional: true - - "@esbuild/linux-arm@0.25.12": - optional: true - - "@esbuild/linux-ia32@0.25.12": - optional: true - - "@esbuild/linux-loong64@0.25.12": - optional: true - - "@esbuild/linux-mips64el@0.25.12": - optional: true - - "@esbuild/linux-ppc64@0.25.12": - optional: true - - "@esbuild/linux-riscv64@0.25.12": - optional: true - - "@esbuild/linux-s390x@0.25.12": - optional: true - - "@esbuild/linux-x64@0.25.12": - optional: true - - "@esbuild/netbsd-arm64@0.25.12": - optional: true - - "@esbuild/netbsd-x64@0.25.12": - optional: true - - "@esbuild/openbsd-arm64@0.25.12": - optional: true - - "@esbuild/openbsd-x64@0.25.12": - optional: true - - "@esbuild/openharmony-arm64@0.25.12": - optional: true - - "@esbuild/sunos-x64@0.25.12": - optional: true - - "@esbuild/win32-arm64@0.25.12": - optional: true - - "@esbuild/win32-ia32@0.25.12": - optional: true - - "@esbuild/win32-x64@0.25.12": - optional: true - - "@hono/node-server@1.19.9(hono@4.11.7)": - dependencies: - hono: 4.11.7 - - "@img/colour@1.0.0": {} - - "@img/sharp-darwin-arm64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-darwin-arm64": 1.2.4 - optional: true - - "@img/sharp-darwin-x64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-darwin-x64": 1.2.4 - optional: true - - "@img/sharp-libvips-darwin-arm64@1.2.4": - optional: true - - "@img/sharp-libvips-darwin-x64@1.2.4": - optional: true - - "@img/sharp-libvips-linux-arm64@1.2.4": - optional: true - - "@img/sharp-libvips-linux-arm@1.2.4": - optional: true - - "@img/sharp-libvips-linux-ppc64@1.2.4": - optional: true - - "@img/sharp-libvips-linux-riscv64@1.2.4": - optional: true - - "@img/sharp-libvips-linux-s390x@1.2.4": - optional: true - - "@img/sharp-libvips-linux-x64@1.2.4": - optional: true - - "@img/sharp-libvips-linuxmusl-arm64@1.2.4": - optional: true - - "@img/sharp-libvips-linuxmusl-x64@1.2.4": - optional: true - - "@img/sharp-linux-arm64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-arm64": 1.2.4 - optional: true - - "@img/sharp-linux-arm@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-arm": 1.2.4 - optional: true - - "@img/sharp-linux-ppc64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-ppc64": 1.2.4 - optional: true - - "@img/sharp-linux-riscv64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-riscv64": 1.2.4 - optional: true - - "@img/sharp-linux-s390x@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-s390x": 1.2.4 - optional: true - - "@img/sharp-linux-x64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linux-x64": 1.2.4 - optional: true - - "@img/sharp-linuxmusl-arm64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linuxmusl-arm64": 1.2.4 - optional: true - - "@img/sharp-linuxmusl-x64@0.34.5": - optionalDependencies: - "@img/sharp-libvips-linuxmusl-x64": 1.2.4 - optional: true - - "@img/sharp-wasm32@0.34.5": - dependencies: - "@emnapi/runtime": 1.8.1 - optional: true - - "@img/sharp-win32-arm64@0.34.5": - optional: true - - "@img/sharp-win32-ia32@0.34.5": - optional: true - - "@img/sharp-win32-x64@0.34.5": - optional: true - - "@jridgewell/resolve-uri@3.1.2": {} - - "@jridgewell/sourcemap-codec@1.5.5": {} - - "@jridgewell/trace-mapping@0.3.9": - dependencies: - "@jridgewell/resolve-uri": 3.1.2 - "@jridgewell/sourcemap-codec": 1.5.5 - - "@modelcontextprotocol/sdk@1.25.3(hono@4.11.7)(zod@4.3.6)": - dependencies: - "@hono/node-server": 1.19.9(hono@4.11.7) - ajv: 8.17.1 - ajv-formats: 3.0.1(ajv@8.17.1) - content-type: 1.0.5 - cors: 2.8.6 - cross-spawn: 7.0.6 - eventsource: 3.0.7 - eventsource-parser: 3.0.6 - express: 5.2.1 - express-rate-limit: 7.5.1(express@5.2.1) - jose: 6.1.3 - json-schema-typed: 8.0.2 - pkce-challenge: 5.0.1 - raw-body: 3.0.2 - zod: 4.3.6 - zod-to-json-schema: 3.25.1(zod@4.3.6) - transitivePeerDependencies: - - hono - - supports-color - - "@penpot-mcp/common@file:../common": - dependencies: - penpot-mcp: file:.. - - "@pinojs/redact@0.4.0": {} - - "@tsconfig/node10@1.0.12": {} - - "@tsconfig/node12@1.0.11": {} - - "@tsconfig/node14@1.0.3": {} - - "@tsconfig/node16@1.0.4": {} - - "@types/body-parser@1.19.6": - dependencies: - "@types/connect": 3.4.38 - "@types/node": 20.19.30 - - "@types/connect@3.4.38": - dependencies: - "@types/node": 20.19.30 - - "@types/express-serve-static-core@4.19.8": - dependencies: - "@types/node": 20.19.30 - "@types/qs": 6.14.0 - "@types/range-parser": 1.2.7 - "@types/send": 1.2.1 - - "@types/express@4.17.25": - dependencies: - "@types/body-parser": 1.19.6 - "@types/express-serve-static-core": 4.19.8 - "@types/qs": 6.14.0 - "@types/serve-static": 1.15.10 - - "@types/http-errors@2.0.5": {} - - "@types/js-yaml@4.0.9": {} - - "@types/mime@1.3.5": {} - - "@types/node@20.19.30": - dependencies: - undici-types: 6.21.0 - - "@types/qs@6.14.0": {} - - "@types/range-parser@1.2.7": {} - - "@types/send@0.17.6": - dependencies: - "@types/mime": 1.3.5 - "@types/node": 20.19.30 - - "@types/send@1.2.1": - dependencies: - "@types/node": 20.19.30 - - "@types/serve-static@1.15.10": - dependencies: - "@types/http-errors": 2.0.5 - "@types/node": 20.19.30 - "@types/send": 0.17.6 - - "@types/validator@13.15.10": {} - - "@types/ws@8.18.1": - dependencies: - "@types/node": 20.19.30 - - accepts@2.0.0: - dependencies: - mime-types: 3.0.2 - negotiator: 1.0.0 - - acorn-walk@8.3.4: - dependencies: - acorn: 8.15.0 - - acorn@8.15.0: {} - - ajv-formats@3.0.1(ajv@8.17.1): - optionalDependencies: - ajv: 8.17.1 - - ajv@8.17.1: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - - ansi-regex@5.0.1: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - arg@4.1.3: {} - - argparse@2.0.1: {} - - atomic-sleep@1.0.0: {} - - body-parser@2.2.2: - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 4.4.3 - http-errors: 2.0.1 - iconv-lite: 0.7.2 - on-finished: 2.4.1 - qs: 6.14.1 - raw-body: 3.0.2 - type-is: 2.0.1 - transitivePeerDependencies: - - supports-color - - bytes@3.1.2: {} - - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - call-bound@1.0.4: - dependencies: - call-bind-apply-helpers: 1.0.2 - get-intrinsic: 1.3.0 - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - class-transformer@0.5.1: {} - - class-validator@0.14.3: - dependencies: - "@types/validator": 13.15.10 - libphonenumber-js: 1.12.35 - validator: 13.15.26 - - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - colorette@2.0.20: {} - - concurrently@8.2.2: - dependencies: - chalk: 4.1.2 - date-fns: 2.30.0 - lodash: 4.17.23 - rxjs: 7.8.2 - shell-quote: 1.8.3 - spawn-command: 0.0.2 - supports-color: 8.1.1 - tree-kill: 1.2.2 - yargs: 17.7.2 - - content-disposition@1.0.1: {} - - content-type@1.0.5: {} - - cookie-signature@1.2.2: {} - - cookie@0.7.2: {} - - cors@2.8.6: - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - - create-require@1.1.1: {} - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - date-fns@2.30.0: - dependencies: - "@babel/runtime": 7.28.6 - - dateformat@4.6.3: {} - - debug@4.4.3: - dependencies: - ms: 2.1.3 - - depd@2.0.0: {} - - detect-libc@2.1.2: {} - - diff@4.0.4: {} - - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-errors: 1.3.0 - gopd: 1.2.0 - - ee-first@1.1.1: {} - - emoji-regex@8.0.0: {} - - encodeurl@2.0.0: {} - - end-of-stream@1.4.5: - dependencies: - once: 1.4.0 - - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - - es-object-atoms@1.1.1: - dependencies: - es-errors: 1.3.0 - - esbuild@0.25.12: - optionalDependencies: - "@esbuild/aix-ppc64": 0.25.12 - "@esbuild/android-arm": 0.25.12 - "@esbuild/android-arm64": 0.25.12 - "@esbuild/android-x64": 0.25.12 - "@esbuild/darwin-arm64": 0.25.12 - "@esbuild/darwin-x64": 0.25.12 - "@esbuild/freebsd-arm64": 0.25.12 - "@esbuild/freebsd-x64": 0.25.12 - "@esbuild/linux-arm": 0.25.12 - "@esbuild/linux-arm64": 0.25.12 - "@esbuild/linux-ia32": 0.25.12 - "@esbuild/linux-loong64": 0.25.12 - "@esbuild/linux-mips64el": 0.25.12 - "@esbuild/linux-ppc64": 0.25.12 - "@esbuild/linux-riscv64": 0.25.12 - "@esbuild/linux-s390x": 0.25.12 - "@esbuild/linux-x64": 0.25.12 - "@esbuild/netbsd-arm64": 0.25.12 - "@esbuild/netbsd-x64": 0.25.12 - "@esbuild/openbsd-arm64": 0.25.12 - "@esbuild/openbsd-x64": 0.25.12 - "@esbuild/openharmony-arm64": 0.25.12 - "@esbuild/sunos-x64": 0.25.12 - "@esbuild/win32-arm64": 0.25.12 - "@esbuild/win32-ia32": 0.25.12 - "@esbuild/win32-x64": 0.25.12 - - escalade@3.2.0: {} - - escape-html@1.0.3: {} - - etag@1.8.1: {} - - eventsource-parser@3.0.6: {} - - eventsource@3.0.7: - dependencies: - eventsource-parser: 3.0.6 - - express-rate-limit@7.5.1(express@5.2.1): - dependencies: - express: 5.2.1 - - express@5.2.1: - dependencies: - accepts: 2.0.0 - body-parser: 2.2.2 - content-disposition: 1.0.1 - content-type: 1.0.5 - cookie: 0.7.2 - cookie-signature: 1.2.2 - debug: 4.4.3 - depd: 2.0.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 2.1.1 - fresh: 2.0.0 - http-errors: 2.0.1 - merge-descriptors: 2.0.0 - mime-types: 3.0.2 - on-finished: 2.4.1 - once: 1.4.0 - parseurl: 1.3.3 - proxy-addr: 2.0.7 - qs: 6.14.1 - range-parser: 1.2.1 - router: 2.2.0 - send: 1.2.1 - serve-static: 2.2.1 - statuses: 2.0.2 - type-is: 2.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - - fast-copy@4.0.2: {} - - fast-deep-equal@3.1.3: {} - - fast-safe-stringify@2.1.1: {} - - fast-uri@3.1.0: {} - - finalhandler@2.1.1: - dependencies: - debug: 4.4.3 - encodeurl: 2.0.0 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.2 - transitivePeerDependencies: - - supports-color - - forwarded@0.2.0: {} - - fresh@2.0.0: {} - - function-bind@1.1.2: {} - - get-caller-file@2.0.5: {} - - get-intrinsic@1.3.0: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - - get-them-args@1.3.2: {} - - gopd@1.2.0: {} - - has-flag@4.0.0: {} - - has-symbols@1.1.0: {} - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - help-me@5.0.0: {} - - hono@4.11.7: {} - - http-errors@2.0.1: - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.2 - toidentifier: 1.0.1 - - iconv-lite@0.7.2: - dependencies: - safer-buffer: 2.1.2 - - inherits@2.0.4: {} - - ipaddr.js@1.9.1: {} - - is-fullwidth-code-point@3.0.0: {} - - is-promise@4.0.0: {} - - isexe@2.0.0: {} - - jose@6.1.3: {} - - joycon@3.1.1: {} - - js-yaml@4.1.1: - dependencies: - argparse: 2.0.1 - - json-schema-traverse@1.0.0: {} - - json-schema-typed@8.0.2: {} - - kill-port@2.0.1: - dependencies: - get-them-args: 1.3.2 - shell-exec: 1.0.2 - - libphonenumber-js@1.12.35: {} - - lodash@4.17.23: {} - - make-error@1.3.6: {} - - math-intrinsics@1.1.0: {} - - media-typer@1.1.0: {} - - merge-descriptors@2.0.0: {} - - mime-db@1.54.0: {} - - mime-types@3.0.2: - dependencies: - mime-db: 1.54.0 - - minimist@1.2.8: {} - - ms@2.1.3: {} - - negotiator@1.0.0: {} - - object-assign@4.1.1: {} - - object-inspect@1.13.4: {} - - on-exit-leak-free@2.1.2: {} - - on-finished@2.4.1: - dependencies: - ee-first: 1.1.1 - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - parseurl@1.3.3: {} - - path-key@3.1.1: {} - - path-to-regexp@8.3.0: {} - - penpot-mcp@file:..: - dependencies: - concurrently: 8.2.2 - kill-port: 2.0.1 - - pino-abstract-transport@2.0.0: - dependencies: - split2: 4.2.0 - - pino-abstract-transport@3.0.0: - dependencies: - split2: 4.2.0 - - pino-pretty@13.1.3: - dependencies: - colorette: 2.0.20 - dateformat: 4.6.3 - fast-copy: 4.0.2 - fast-safe-stringify: 2.1.1 - help-me: 5.0.0 - joycon: 3.1.1 - minimist: 1.2.8 - on-exit-leak-free: 2.1.2 - pino-abstract-transport: 3.0.0 - pump: 3.0.3 - secure-json-parse: 4.1.0 - sonic-boom: 4.2.0 - strip-json-comments: 5.0.3 - - pino-std-serializers@7.1.0: {} - - pino@9.14.0: - dependencies: - "@pinojs/redact": 0.4.0 - atomic-sleep: 1.0.0 - on-exit-leak-free: 2.1.2 - pino-abstract-transport: 2.0.0 - pino-std-serializers: 7.1.0 - process-warning: 5.0.0 - quick-format-unescaped: 4.0.4 - real-require: 0.2.0 - safe-stable-stringify: 2.5.0 - sonic-boom: 4.2.0 - thread-stream: 3.1.0 - - pkce-challenge@5.0.1: {} - - process-warning@5.0.0: {} - - proxy-addr@2.0.7: - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - - pump@3.0.3: - dependencies: - end-of-stream: 1.4.5 - once: 1.4.0 - - qs@6.14.1: - dependencies: - side-channel: 1.1.0 - - quick-format-unescaped@4.0.4: {} - - range-parser@1.2.1: {} - - raw-body@3.0.2: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.1 - iconv-lite: 0.7.2 - unpipe: 1.0.0 - - real-require@0.2.0: {} - - reflect-metadata@0.1.14: {} - - require-directory@2.1.1: {} - - require-from-string@2.0.2: {} - - router@2.2.0: - dependencies: - debug: 4.4.3 - depd: 2.0.0 - is-promise: 4.0.0 - parseurl: 1.3.3 - path-to-regexp: 8.3.0 - transitivePeerDependencies: - - supports-color - - rxjs@7.8.2: - dependencies: - tslib: 2.8.1 - - safe-stable-stringify@2.5.0: {} - - safer-buffer@2.1.2: {} - - secure-json-parse@4.1.0: {} - - semver@7.7.3: {} - - send@1.2.1: - dependencies: - debug: 4.4.3 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 2.0.0 - http-errors: 2.0.1 - mime-types: 3.0.2 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.2 - transitivePeerDependencies: - - supports-color - - serve-static@2.2.1: - dependencies: - encodeurl: 2.0.0 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 1.2.1 - transitivePeerDependencies: - - supports-color - - setprototypeof@1.2.0: {} - - sharp@0.34.5: - dependencies: - "@img/colour": 1.0.0 - detect-libc: 2.1.2 - semver: 7.7.3 - optionalDependencies: - "@img/sharp-darwin-arm64": 0.34.5 - "@img/sharp-darwin-x64": 0.34.5 - "@img/sharp-libvips-darwin-arm64": 1.2.4 - "@img/sharp-libvips-darwin-x64": 1.2.4 - "@img/sharp-libvips-linux-arm": 1.2.4 - "@img/sharp-libvips-linux-arm64": 1.2.4 - "@img/sharp-libvips-linux-ppc64": 1.2.4 - "@img/sharp-libvips-linux-riscv64": 1.2.4 - "@img/sharp-libvips-linux-s390x": 1.2.4 - "@img/sharp-libvips-linux-x64": 1.2.4 - "@img/sharp-libvips-linuxmusl-arm64": 1.2.4 - "@img/sharp-libvips-linuxmusl-x64": 1.2.4 - "@img/sharp-linux-arm": 0.34.5 - "@img/sharp-linux-arm64": 0.34.5 - "@img/sharp-linux-ppc64": 0.34.5 - "@img/sharp-linux-riscv64": 0.34.5 - "@img/sharp-linux-s390x": 0.34.5 - "@img/sharp-linux-x64": 0.34.5 - "@img/sharp-linuxmusl-arm64": 0.34.5 - "@img/sharp-linuxmusl-x64": 0.34.5 - "@img/sharp-wasm32": 0.34.5 - "@img/sharp-win32-arm64": 0.34.5 - "@img/sharp-win32-ia32": 0.34.5 - "@img/sharp-win32-x64": 0.34.5 - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - shell-exec@1.0.2: {} - - shell-quote@1.8.3: {} - - side-channel-list@1.0.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - - side-channel-map@1.0.1: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - - side-channel-weakmap@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - side-channel-map: 1.0.1 - - side-channel@1.1.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - side-channel-list: 1.0.0 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - - sonic-boom@4.2.0: - dependencies: - atomic-sleep: 1.0.0 - - spawn-command@0.0.2: {} - - split2@4.2.0: {} - - statuses@2.0.2: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-json-comments@5.0.3: {} - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-color@8.1.1: - dependencies: - has-flag: 4.0.0 - - thread-stream@3.1.0: - dependencies: - real-require: 0.2.0 - - toidentifier@1.0.1: {} - - tree-kill@1.2.2: {} - - ts-node@10.9.2(@types/node@20.19.30)(typescript@5.9.3): - dependencies: - "@cspotcode/source-map-support": 0.8.1 - "@tsconfig/node10": 1.0.12 - "@tsconfig/node12": 1.0.11 - "@tsconfig/node14": 1.0.3 - "@tsconfig/node16": 1.0.4 - "@types/node": 20.19.30 - acorn: 8.15.0 - acorn-walk: 8.3.4 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.4 - make-error: 1.3.6 - typescript: 5.9.3 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - - tslib@2.8.1: {} - - type-is@2.0.1: - dependencies: - content-type: 1.0.5 - media-typer: 1.1.0 - mime-types: 3.0.2 - - typescript@5.9.3: {} - - undici-types@6.21.0: {} - - unpipe@1.0.0: {} - - v8-compile-cache-lib@3.0.1: {} - - validator@13.15.26: {} - - vary@1.1.2: {} - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrappy@1.0.2: {} - - ws@8.19.0: {} - - y18n@5.0.8: {} - - yargs-parser@21.1.1: {} - - yargs@17.7.2: - dependencies: - cliui: 8.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - - yn@3.1.1: {} - - zod-to-json-schema@3.25.1(zod@4.3.6): - dependencies: - zod: 4.3.6 - - zod@4.3.6: {} From 2e24f1e2deadd78810d9569dc400b32eaf1a1244 Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Tue, 31 Mar 2026 13:20:58 +0200 Subject: [PATCH 12/16] :bug: Fix lock file not being included in npm package The root lock file not being present causes issues, because the sub-project dependencies are managed by it. The lack of inclusion of pnpm-lock.yaml was the root cause of #8829. A dependency was updated incompatibly, breaking the release. Since npm pack has a hard exclusion rule for pnpm-lock.yaml, we include it under a different name and restore it at runtime. --- mcp/README.md | 6 ++++-- mcp/bin/mcp-local.js | 9 +++++++++ mcp/scripts/pack | 9 ++++----- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/mcp/README.md b/mcp/README.md index a9a623b1e0..bd9d9b6447 100644 --- a/mcp/README.md +++ b/mcp/README.md @@ -306,5 +306,7 @@ you may set the following environment variables to configure the two servers - Ensure that at least the major, minor and patch components of the version are always up-to-date. - The MCP plugin assumes that a mismatch between the MCP version and the Penpot version (as returned by the API) indicates incompatibility, resulting in the display of a warning message in the plugin UI. -* Packaging and publishing: - - Create npm package: `bash scripts/pack` (sets version and then calls `npm pack`) +* Packaging and publishing: + 1. Ensure release version is set correctly in package.json (call `bash scripts/set-version` to update it automatically) + 2. Create npm package: `bash scripts/pack` (creates `penpot-mcp-.tgz` for publishing) + 3. Publish to npm: `npm publish penpot-mcp-.tgz --access public` diff --git a/mcp/bin/mcp-local.js b/mcp/bin/mcp-local.js index 517762b4f9..65a2b0f763 100644 --- a/mcp/bin/mcp-local.js +++ b/mcp/bin/mcp-local.js @@ -1,6 +1,7 @@ #!/usr/bin/env node const { execSync } = require("child_process"); +const fs = require("fs"); const path = require("path"); const root = path.resolve(__dirname, ".."); @@ -9,6 +10,14 @@ function run(command) { execSync(command, { cwd: root, stdio: "inherit" }); } +// pnpm-lock.yaml is hard-excluded by npm pack; it is shipped as pnpm-lock.dist.yaml +// and restored here before bootstrap runs. +const distLock = path.join(root, "pnpm-lock.dist.yaml"); +const lock = path.join(root, "pnpm-lock.yaml"); +if (fs.existsSync(distLock)) { + fs.copyFileSync(distLock, lock); +} + try { run("corepack pnpm run bootstrap"); } catch (error) { diff --git a/mcp/scripts/pack b/mcp/scripts/pack index 06826b2143..16a869cf00 100644 --- a/mcp/scripts/pack +++ b/mcp/scripts/pack @@ -1,12 +1,11 @@ #!/usr/bin/env bash -# -# Sets the version from Git tags, then produces the npm tarball. -# Must be invoked directly (not via npm/pnpm) so that the version -# is written to package.json before npm reads it. set -euo pipefail cd "$(dirname "$0")/.." -bash ./scripts/set-version +# pnpm-lock.yaml is hard-excluded by npm, but we need it; ship it under a neutral name +cp pnpm-lock.yaml pnpm-lock.dist.yaml +trap 'rm -f pnpm-lock.dist.yaml' EXIT + npm pack From ad1e598efe6ca9e152132c6237fd3953a983e107 Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Mon, 30 Mar 2026 12:20:57 +0200 Subject: [PATCH 13/16] :sparkles: Add wait time in exportImage to account for async updates #8836 This is a temporary workaround for penpot/penpot-mcp#27. It adds a wait time before exports via the export_shape tool to account for asynchronous updates in Penpot, increasing the likelihood of exporting the fully updated state. --- mcp/packages/plugin/src/PenpotUtils.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mcp/packages/plugin/src/PenpotUtils.ts b/mcp/packages/plugin/src/PenpotUtils.ts index ab5be791e1..2c2cc3e4e5 100644 --- a/mcp/packages/plugin/src/PenpotUtils.ts +++ b/mcp/packages/plugin/src/PenpotUtils.ts @@ -420,6 +420,11 @@ export class PenpotUtils { * - For mode="fill", it will be whatever format the fill image is stored in. */ public static async exportImage(shape: Shape, mode: "shape" | "fill", asSVG: boolean): Promise { + // Updates are asynchronous in Penpot, so wait a tick to ensure any pending updates are applied before export. + // The constant wait time is a temporary workardound until a better solution for penpot/penpot-mcp#27 + // is implemented. + await new Promise((resolve) => setTimeout(resolve, 200)); + // Perform export switch (mode) { case "shape": return shape.export({ type: asSVG ? "svg" : "png" }); From 04f98d7acd005d57e5e838ef792f5a790cc68d36 Mon Sep 17 00:00:00 2001 From: Alonso Torres Date: Tue, 31 Mar 2026 17:24:02 +0200 Subject: [PATCH 14/16] :sparkles: Change caddy config (#8849) --- docker/devenv/files/Caddyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/devenv/files/Caddyfile b/docker/devenv/files/Caddyfile index eda140d5e9..a4e81434b0 100644 --- a/docker/devenv/files/Caddyfile +++ b/docker/devenv/files/Caddyfile @@ -8,7 +8,7 @@ localhost:3449 { header -Strict-Transport-Security } -http://localhost:3450 { +:3450 { # For subpath test # handle_path /penpot/* { # reverse_proxy localhost:4449 From c200dc4040b38e858a5c0b43cddcf3bed77dbca6 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 31 Mar 2026 15:07:20 +0200 Subject: [PATCH 15/16] :bug: Normalize token set name on creating token-set instance --- common/src/app/common/types/tokens_lib.cljc | 5 ++-- .../common_tests/types/tokens_lib_test.cljc | 29 ++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/common/src/app/common/types/tokens_lib.cljc b/common/src/app/common/types/tokens_lib.cljc index e4b0e5ae43..af7fd6c9fd 100644 --- a/common/src/app/common/types/tokens_lib.cljc +++ b/common/src/app/common/types/tokens_lib.cljc @@ -327,11 +327,11 @@ If `relative-to` is provided, the normalized name will preserve the same group prefix as reference name." ([name] - (-> (split-set-name name) + (-> (split-set-name (str name)) (cpn/join-path :separator set-separator :with-spaces? false))) ([name relative-to] (-> (concat (butlast (split-set-name relative-to)) - (split-set-name name)) + (split-set-name (str name))) (cpn/join-path :separator set-separator :with-spaces? false)))) (defn token-set? @@ -404,6 +404,7 @@ (update :modified-at #(or % (ct/now))) (update :tokens #(into (d/ordered-map) %)) (update :description d/nilv "") + (update :name normalize-set-name) (check-token-set-attrs) (map->token-set))) diff --git a/common/test/common_tests/types/tokens_lib_test.cljc b/common/test/common_tests/types/tokens_lib_test.cljc index 23bed42897..dfef086b1b 100644 --- a/common/test/common_tests/types/tokens_lib_test.cljc +++ b/common/test/common_tests/types/tokens_lib_test.cljc @@ -11,7 +11,6 @@ #?(:clj [app.common.test-helpers.tokens :as tht]) #?(:clj [clojure.datafy :refer [datafy]]) [app.common.data :as d] - [app.common.path-names :as cpn] [app.common.test-helpers.ids-map :as thi] [app.common.time :as ct] [app.common.transit :as tr] @@ -2034,3 +2033,31 @@ (t/is (true? (ctob/token-name-path-exists? "border-radius.sm.x" {"border-radius" {:name "sm"}}))) (t/is (false? (ctob/token-name-path-exists? "other" {"border-radius" {:name "sm"}}))) (t/is (false? (ctob/token-name-path-exists? "dark.border-radius.md" {"dark" {"border-radius" {"sm" {:name "sm"}}}})))) + +#?(:clj + (t/deftest token-set-encode-decode-roundtrip-with-invalid-set-name + (binding [ct/*clock* (ct/tick-millis-clock)] + (let [tokens-lib + (-> (ctob/make-tokens-lib) + (ctob/add-set + (ctob/map->token-set + {:id (thi/new-id! :test-token-set) + :name "foo / bar" + :modified-at (ct/now) + :description ""})) + (ctob/add-token + (thi/id :test-token-set) + (ctob/make-token :name "test-token-1" + :type :boolean + :value true))) + + encoded-tokens-lib + (fres/encode tokens-lib) + + decoded-tokens-lib + (fres/decode encoded-tokens-lib)] + + (let [tset-a (ctob/get-set tokens-lib (thi/id :test-token-set)) + tset-b (ctob/get-set decoded-tokens-lib (thi/id :test-token-set))] + (t/is (= (ctob/get-name tset-a) "foo / bar")) + (t/is (= (ctob/get-name tset-b) "foo/bar"))))))) From 0ad5baa5d95c51639564f6ed0ca1aa4a483bf081 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 31 Mar 2026 19:59:32 +0200 Subject: [PATCH 16/16] :bug: Fix mcp build script --- mcp/scripts/build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mcp/scripts/build b/mcp/scripts/build index 84181f2d84..09523164fe 100755 --- a/mcp/scripts/build +++ b/mcp/scripts/build @@ -30,7 +30,7 @@ pnpm -r --filter "mcp-server" run build; rsync -avr packages/server/dist/ ./dist/; cp packages/server/package.json ./dist/; -cp packages/server/pnpm-lock.yaml ./dist/; +cp pnpm-lock.yaml ./dist/; touch ./dist/pnpm-workspace.yaml;