106 Commits

Author SHA1 Message Date
Andrey Antukh
c5de4c27b0 Merge remote-tracking branch 'origin/main' into staging 2026-06-01 12:57:39 +02:00
Yamila Moreno
ddba2ffa75
📎 Update Kaleidos Copyright (#9929) 2026-05-29 11:24:58 +02:00
Full Stack Developer
25e6b939ba
Show detailed messages on file import errors (#9004)
*  Show detailed messages on file import errors

Signed-off-by: jsdevninja <topit89807@gmail.com>

*  Fix test

*  Fix build error

---------

Signed-off-by: jsdevninja <topit89807@gmail.com>
2026-04-24 09:13:46 +02:00
Andrey Antukh
e5f9c1e863 🎉 Add chunked upload API for large media and binary files
Introduce a purpose-agnostic three-step session-based upload API that
allows uploading large binary blobs (media files and .penpot imports)
without hitting multipart size limits.

Backend:
- Migration 0147: new `upload_session` table (profile_id, total_chunks,
  created_at) with indexes on profile_id and created_at.
- Three new RPC commands in media.clj:
    * `create-upload-session`  – allocates a session row; enforces
      `upload-sessions-per-profile` and `upload-chunks-per-session`
      quota limits (configurable in config.clj, defaults 5 / 20).
    * `upload-chunk`           – stores each slice as a storage object;
      validates chunk index bounds and profile ownership.
    * `assemble-file-media-object` – reassembles chunks via the shared
      `assemble-chunks!` helper and creates the final media object.
- `assemble-chunks!` is a public helper in media.clj shared by both
  `assemble-file-media-object` and `import-binfile`.
- `import-binfile` (binfile.clj): accepts an optional `upload-id` param;
  when provided, materialises the temp file from chunks instead of
  expecting an inline multipart body, removing the 200 MiB body limit
  on .penpot imports.  Schema updated with an `:and` validator requiring
  either `:file` or `:upload-id`.
- quotes.clj: new `upload-sessions-per-profile` quota check.
- Background GC task (`tasks/upload_session_gc.clj`): deletes stalled
  (never-completed) sessions older than 1 hour; scheduled daily at
  midnight via the cron system in main.clj.
- backend/AGENTS.md: document the background-task wiring pattern.

Frontend:
- New `app.main.data.uploads` namespace: generic `upload-blob-chunked`
  helper drives steps 1–2 (create session + upload all chunks with a
  concurrency cap of 2) and emits `{:session-id uuid}` for callers.
- `config.cljs`: expose `upload-chunk-size` (default 25 MiB, overridable
  via `penpotUploadChunkSize` global).
- `workspace/media.cljs`: blobs ≥ chunk-size go through the chunked path
  (`upload-blob-chunked` → `assemble-file-media-object`); smaller blobs
  use the existing direct `upload-file-media-object` path.
  `handle-media-error` simplified; `on-error` callback removed.
- `worker/import.cljs`: new `import-blob-via-upload` helper replaces the
  inline multipart approach for both binfile-v1 and binfile-v3 imports.
- `repo.cljs`: `:upload-chunk` derived as a `::multipart-upload`;
  `form-data?` removed from `import-binfile` (JSON params only).

Tests:
- Backend (rpc_media_test.clj): happy path, idempotency, permission
  isolation, invalid media type, missing chunks, session-not-found,
  chunk-index out-of-range, and quota-limit scenarios.
- Frontend (uploads_test.cljs): session creation and chunk-count
  correctness for `upload-blob-chunked`.
- Frontend (workspace_media_test.cljs): direct-upload path for small
  blobs, chunked path for large blobs, and chunk-count correctness for
  `process-blobs`.
- `helpers/http.cljs`: shared fetch-mock helpers (`install-fetch-mock!`,
  `make-json-response`, `make-transit-response`, `url->cmd`).

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-21 18:51:10 +00:00
Andrey Antukh
6fa440cf92 🎉 Add chunked upload API for large media and binary files
Introduce a purpose-agnostic three-step session-based upload API that
allows uploading large binary blobs (media files and .penpot imports)
without hitting multipart size limits.

Backend:
- Migration 0147: new `upload_session` table (profile_id, total_chunks,
  created_at) with indexes on profile_id and created_at.
- Three new RPC commands in media.clj:
    * `create-upload-session`  – allocates a session row; enforces
      `upload-sessions-per-profile` and `upload-chunks-per-session`
      quota limits (configurable in config.clj, defaults 5 / 20).
    * `upload-chunk`           – stores each slice as a storage object;
      validates chunk index bounds and profile ownership.
    * `assemble-file-media-object` – reassembles chunks via the shared
      `assemble-chunks!` helper and creates the final media object.
- `assemble-chunks!` is a public helper in media.clj shared by both
  `assemble-file-media-object` and `import-binfile`.
- `import-binfile` (binfile.clj): accepts an optional `upload-id` param;
  when provided, materialises the temp file from chunks instead of
  expecting an inline multipart body, removing the 200 MiB body limit
  on .penpot imports.  Schema updated with an `:and` validator requiring
  either `:file` or `:upload-id`.
- quotes.clj: new `upload-sessions-per-profile` quota check.
- Background GC task (`tasks/upload_session_gc.clj`): deletes stalled
  (never-completed) sessions older than 1 hour; scheduled daily at
  midnight via the cron system in main.clj.
- backend/AGENTS.md: document the background-task wiring pattern.

Frontend:
- New `app.main.data.uploads` namespace: generic `upload-blob-chunked`
  helper drives steps 1–2 (create session + upload all chunks with a
  concurrency cap of 2) and emits `{:session-id uuid}` for callers.
- `config.cljs`: expose `upload-chunk-size` (default 25 MiB, overridable
  via `penpotUploadChunkSize` global).
- `workspace/media.cljs`: blobs ≥ chunk-size go through the chunked path
  (`upload-blob-chunked` → `assemble-file-media-object`); smaller blobs
  use the existing direct `upload-file-media-object` path.
  `handle-media-error` simplified; `on-error` callback removed.
- `worker/import.cljs`: new `import-blob-via-upload` helper replaces the
  inline multipart approach for both binfile-v1 and binfile-v3 imports.
- `repo.cljs`: `:upload-chunk` derived as a `::multipart-upload`;
  `form-data?` removed from `import-binfile` (JSON params only).

Tests:
- Backend (rpc_media_test.clj): happy path, idempotency, permission
  isolation, invalid media type, missing chunks, session-not-found,
  chunk-index out-of-range, and quota-limit scenarios.
- Frontend (uploads_test.cljs): session creation and chunk-count
  correctness for `upload-blob-chunked`.
- Frontend (workspace_media_test.cljs): direct-upload path for small
  blobs, chunked path for large blobs, and chunk-count correctness for
  `process-blobs`.
- `helpers/http.cljs`: shared fetch-mock helpers (`install-fetch-mock!`,
  `make-json-response`, `make-transit-response`, `url->cmd`).

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-04-16 19:43:57 +02:00
Andrey Antukh
11b75408fe
🐛 Fix regression on importing binfile-v1 files (#7359) 2025-09-23 11:38:33 +02:00
Andrey Antukh
22db773b2e 🔥 Remove unused code from worker import ns 2025-06-04 12:46:49 +02:00
Andrey Antukh
36b162b4fa ♻️ Replace jszip usage with zip.js library 2025-05-20 13:05:52 +02:00
Andrey Antukh
dc7e53881a 🔥 Remove legacy-zip exportation support 2025-05-20 13:05:52 +02:00
Andrey Antukh
99e325acaf 🔥 Remove support from legacy-zip format 2025-05-07 12:14:52 +02:00
Andrey Antukh
1fc0203c38 🎉 Add full integration with path data type feature 2025-05-06 13:39:10 +02:00
Andrey Antukh
422a9db07b Sanitize uuid parsing on legacy zip import code 2025-04-14 09:13:35 +02:00
Andrey Antukh
0870910dcc
🐛 Fix nodejs incompatibility with common tests prepend script (#5730)
* 🐛 Fix nodejs incompatibility with common tests prepend script

* 📎 Fix linter issues

Related to the upcoming update of clj-kondo
2025-01-30 14:32:43 +01:00
Andrey Antukh
577b731b22 🐛 Fix import format detection and error handling 2024-11-25 12:29:59 +01:00
Andrey Antukh
8618cb950f 🎉 Add binfile-v3 export/import file format 2024-10-18 17:19:29 +02:00
Andrey Antukh
d46274abf2 Add better error reporting on zip file importation 2024-10-10 16:04:15 +02:00
Andrey Antukh
534659cdc6 🐛 Fix flows import and export on zip format 2024-10-10 16:04:15 +02:00
Andrey Antukh
4ad4057878 ♻️ Refactor page options data structure 2024-09-18 12:15:12 +02:00
Andrey Antukh
2643dae0a7 🐛 Fix json encoding on zip encoding decoding 2024-08-27 15:43:31 +02:00
Alejandro Alonso
40b43c6c5b 🐛 Fix lost image colors in library when export/import using zip format 2024-06-27 09:54:02 +02:00
Alejandro Alonso
58466e6488 🐛 Color library loses association with shapes when exporting/importing the document 2024-06-26 10:40:30 +02:00
Andrés Moya
798970a923 🐛 Rework svg import of deleted components 2024-06-25 15:23:52 +02:00
Alejandro Alonso
46764a1e6e 🐛 Fix export boards loses opacity 2024-06-11 10:54:11 +02:00
alonso.torres
b1e226cdc6 🐛 Fix problem with import zip files 2024-04-04 16:09:11 +02:00
alonso.torres
86b4a95875 Fix problem when importing zip files 2024-02-15 09:27:51 +01:00
Andrey Antukh
cdf312fdd9 Add better progress reporting
For components migration and for binfile import process
2024-01-30 16:27:16 +01:00
alonso.torres
c8593b1c18 🐛 Fix get name from file when importing 2024-01-26 09:26:32 +01:00
alonso.torres
19e40175be 🐛 Disable import to v1 from v2 2024-01-15 10:10:13 +01:00
alonso.torres
28981e5d46 🐛 Fix import of zip files from v2 to v2 2024-01-15 10:10:13 +01:00
Andrey Antukh
e0a1cd6e77 📎 Move import parser from util to worker directory 2024-01-09 23:11:42 +01:00
Andrey Antukh
b6c257bfc5 🐛 Fix incorrect svg-attrs handlng on .zip import process 2024-01-09 23:11:42 +01:00
Andrey Antukh
833871df65 💄 Format frontend code 2024-01-08 09:32:50 +01:00
Andrey Antukh
cfe7ba34f7 🐛 Fix validation of validation error on file validate ns 2024-01-05 18:29:16 +01:00
Andrey Antukh
96f5a33f5f ⬆️ Upgrade to beicon2 (part1) 2023-12-26 14:14:20 +01:00
Andrey Antukh
15f81e557c 🐛 Fix unexpected exception on importing some binary files 2023-12-15 17:54:26 +01:00
Andrey Antukh
03518a8da1 Add the ability to stream events on rpc methods 2023-12-13 14:20:07 +01:00
Alejandro Alonso
1913395c47 🎉 Support for images as fills 2023-11-14 12:39:53 +01:00
Andrey Antukh
d5e34df364 🐛 Fix incorrect frontend error handling on import code 2023-11-14 10:55:55 +01:00
Andrey Antukh
fbdba39be9 🐛 Fix importation of zip files 2023-11-08 17:11:42 +01:00
Andrey Antukh
fb1bdd4ce7 🐛 Fix frontend cljs linter issues 2023-08-31 09:31:53 +02:00
Andrey Antukh
405aa66357 🎉 Add new shape & rect data structures
Also optimizes some functions for faster shape and rect props
access (there is still a lot of work ahead optimizing the rest of
the functions)

Also normalizes shape creation and validation for ensuring
correct setup of all the mandatory properties.
2023-07-11 17:27:35 +02:00
alonso.torres
b3b984d339 Add import/export svg for grid 2023-07-10 14:49:24 +02:00
Aitor
48834f96d3 ♻️ Refactor thumbnail rendering on workspace 2023-05-22 10:56:46 +02:00
Alejandro Alonso
da517f2d35 Merge remote-tracking branch 'origin/staging' into develop 2023-01-20 13:58:08 +01:00
Andrés Moya
2b978777d7 🐛 Fix import/export components with boards inside 2023-01-20 12:04:47 +01:00
Andrey Antukh
3dd65db651 Use commands instead of mutations for assets upload
And properly deprecate media rpc mutations
2023-01-18 11:20:36 +01:00
Andrey Antukh
2c558a6a02
Merge pull request #2625 from penpot/hiru-detect-version-import
 Include features info in exported zipfiles
2022-12-02 09:19:28 +01:00
Andrés Moya
148f6cb3c2 🐛 Fix adding an extra blank page on import 2022-12-01 17:15:20 +01:00
Andrés Moya
94cdd4a481 Include features info in exported zipfiles 2022-12-01 15:33:13 +01:00
Andrey Antukh
1b9dea01e2 🔥 Remove unused d/update-vals function
Already available as clojure.core/update-vals
2022-11-22 14:06:14 +01:00