@strapi/upload 5.50.0 → 5.50.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.js +1 -1
  2. package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.js.map +1 -1
  3. package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.mjs +1 -1
  4. package/dist/admin/components/MediaLibraryInput/MediaLibraryInput.mjs.map +1 -1
  5. package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromComputerForm.js.map +1 -1
  6. package/dist/admin/components/UploadAssetDialog/AddAssetStep/FromComputerForm.mjs.map +1 -1
  7. package/dist/admin/future/pages/Assets/AssetsPage.js +125 -122
  8. package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -1
  9. package/dist/admin/future/pages/Assets/AssetsPage.mjs +125 -122
  10. package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -1
  11. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js +700 -0
  12. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.js.map +1 -0
  13. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs +678 -0
  14. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetCropEditor.mjs.map +1 -0
  15. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +132 -15
  16. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
  17. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +135 -18
  18. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
  19. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetPreview.js +23 -1
  20. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetPreview.js.map +1 -1
  21. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetPreview.mjs +23 -1
  22. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetPreview.mjs.map +1 -1
  23. package/dist/admin/future/pages/Assets/components/AssetDetails/useCropImg.js +211 -0
  24. package/dist/admin/future/pages/Assets/components/AssetDetails/useCropImg.js.map +1 -0
  25. package/dist/admin/future/pages/Assets/components/AssetDetails/useCropImg.mjs +188 -0
  26. package/dist/admin/future/pages/Assets/components/AssetDetails/useCropImg.mjs.map +1 -0
  27. package/dist/admin/future/pages/Assets/components/AssetsGrid.js +48 -3
  28. package/dist/admin/future/pages/Assets/components/AssetsGrid.js.map +1 -1
  29. package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs +49 -4
  30. package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs.map +1 -1
  31. package/dist/admin/future/pages/Assets/components/AssetsTable.js +43 -4
  32. package/dist/admin/future/pages/Assets/components/AssetsTable.js.map +1 -1
  33. package/dist/admin/future/pages/Assets/components/AssetsTable.mjs +44 -5
  34. package/dist/admin/future/pages/Assets/components/AssetsTable.mjs.map +1 -1
  35. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js +195 -0
  36. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.js.map +1 -0
  37. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs +192 -0
  38. package/dist/admin/future/pages/Assets/components/Dnd/AssetsDndProvider.mjs.map +1 -0
  39. package/dist/admin/future/pages/Assets/components/Dnd/DragOverlayChip.js +37 -0
  40. package/dist/admin/future/pages/Assets/components/Dnd/DragOverlayChip.js.map +1 -0
  41. package/dist/admin/future/pages/Assets/components/Dnd/DragOverlayChip.mjs +35 -0
  42. package/dist/admin/future/pages/Assets/components/Dnd/DragOverlayChip.mjs.map +1 -0
  43. package/dist/admin/future/pages/Assets/components/Dnd/dndIds.js +18 -0
  44. package/dist/admin/future/pages/Assets/components/Dnd/dndIds.js.map +1 -0
  45. package/dist/admin/future/pages/Assets/components/Dnd/dndIds.mjs +13 -0
  46. package/dist/admin/future/pages/Assets/components/Dnd/dndIds.mjs.map +1 -0
  47. package/dist/admin/future/pages/Assets/components/Dnd/useAssetDnd.js +97 -0
  48. package/dist/admin/future/pages/Assets/components/Dnd/useAssetDnd.js.map +1 -0
  49. package/dist/admin/future/pages/Assets/components/Dnd/useAssetDnd.mjs +94 -0
  50. package/dist/admin/future/pages/Assets/components/Dnd/useAssetDnd.mjs.map +1 -0
  51. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZone.js +13 -4
  52. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZone.js.map +1 -1
  53. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZone.mjs +13 -4
  54. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZone.mjs.map +1 -1
  55. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.js +6 -3
  56. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.js.map +1 -1
  57. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.mjs +6 -3
  58. package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.mjs.map +1 -1
  59. package/dist/admin/future/services/api.js +37 -1
  60. package/dist/admin/future/services/api.js.map +1 -1
  61. package/dist/admin/future/services/api.mjs +37 -2
  62. package/dist/admin/future/services/api.mjs.map +1 -1
  63. package/dist/admin/future/services/folders.js +36 -5
  64. package/dist/admin/future/services/folders.js.map +1 -1
  65. package/dist/admin/future/services/folders.mjs +36 -6
  66. package/dist/admin/future/services/folders.mjs.map +1 -1
  67. package/dist/admin/future/utils/buildBulkMovePayload.js +20 -0
  68. package/dist/admin/future/utils/buildBulkMovePayload.js.map +1 -0
  69. package/dist/admin/future/utils/buildBulkMovePayload.mjs +18 -0
  70. package/dist/admin/future/utils/buildBulkMovePayload.mjs.map +1 -0
  71. package/dist/admin/future/utils/canDropItemOnFolder.js +64 -0
  72. package/dist/admin/future/utils/canDropItemOnFolder.js.map +1 -0
  73. package/dist/admin/future/utils/canDropItemOnFolder.mjs +61 -0
  74. package/dist/admin/future/utils/canDropItemOnFolder.mjs.map +1 -0
  75. package/dist/admin/future/utils/getBulkMoveErrorMessage.js +23 -0
  76. package/dist/admin/future/utils/getBulkMoveErrorMessage.js.map +1 -0
  77. package/dist/admin/future/utils/getBulkMoveErrorMessage.mjs +21 -0
  78. package/dist/admin/future/utils/getBulkMoveErrorMessage.mjs.map +1 -0
  79. package/dist/admin/hooks/useAIMetadataJob.js.map +1 -1
  80. package/dist/admin/hooks/useAIMetadataJob.mjs.map +1 -1
  81. package/dist/admin/hooks/useAssets.js.map +1 -1
  82. package/dist/admin/hooks/useAssets.mjs.map +1 -1
  83. package/dist/admin/hooks/useBulkEdit.js.map +1 -1
  84. package/dist/admin/hooks/useBulkEdit.mjs.map +1 -1
  85. package/dist/admin/hooks/useBulkMove.js.map +1 -1
  86. package/dist/admin/hooks/useBulkMove.mjs.map +1 -1
  87. package/dist/admin/hooks/useBulkRemove.js.map +1 -1
  88. package/dist/admin/hooks/useBulkRemove.mjs.map +1 -1
  89. package/dist/admin/hooks/useEditAsset.js.map +1 -1
  90. package/dist/admin/hooks/useEditAsset.mjs.map +1 -1
  91. package/dist/admin/hooks/useEditFolder.js +4 -3
  92. package/dist/admin/hooks/useEditFolder.js.map +1 -1
  93. package/dist/admin/hooks/useEditFolder.mjs +4 -3
  94. package/dist/admin/hooks/useEditFolder.mjs.map +1 -1
  95. package/dist/admin/hooks/useFolder.js.map +1 -1
  96. package/dist/admin/hooks/useFolder.mjs.map +1 -1
  97. package/dist/admin/hooks/useUpload.js.map +1 -1
  98. package/dist/admin/hooks/useUpload.mjs.map +1 -1
  99. package/dist/admin/pages/SettingsPage/SettingsPage.js +1 -1
  100. package/dist/admin/pages/SettingsPage/SettingsPage.js.map +1 -1
  101. package/dist/admin/pages/SettingsPage/SettingsPage.mjs +1 -1
  102. package/dist/admin/pages/SettingsPage/SettingsPage.mjs.map +1 -1
  103. package/dist/admin/src/future/pages/Assets/components/AssetDetails/AssetCropEditor.d.ts +10 -0
  104. package/dist/admin/src/future/pages/Assets/components/AssetDetails/useCropImg.d.ts +48 -0
  105. package/dist/admin/src/future/pages/Assets/components/Dnd/AssetsDndProvider.d.ts +12 -0
  106. package/dist/admin/src/future/pages/Assets/components/Dnd/DragOverlayChip.d.ts +6 -0
  107. package/dist/admin/src/future/pages/Assets/components/Dnd/dndIds.d.ts +4 -0
  108. package/dist/admin/src/future/pages/Assets/components/Dnd/useAssetDnd.d.ts +51 -0
  109. package/dist/admin/src/future/services/api.d.ts +24 -6
  110. package/dist/admin/src/future/services/assets.d.ts +1 -1
  111. package/dist/admin/src/future/services/folders.d.ts +12 -2
  112. package/dist/admin/src/future/services/settings.d.ts +1 -1
  113. package/dist/admin/src/future/types/dnd.d.ts +22 -0
  114. package/dist/admin/src/future/utils/buildBulkMovePayload.d.ts +2 -0
  115. package/dist/admin/src/future/utils/canDropItemOnFolder.d.ts +9 -0
  116. package/dist/admin/src/future/utils/getBulkMoveErrorMessage.d.ts +1 -0
  117. package/dist/admin/src/hooks/useAIMetadataJob.d.ts +1 -1
  118. package/dist/admin/src/hooks/useBulkEdit.d.ts +14 -14
  119. package/dist/admin/src/hooks/useBulkMove.d.ts +146 -15
  120. package/dist/admin/src/hooks/useBulkRemove.d.ts +186 -15
  121. package/dist/admin/src/hooks/useEditFolder.d.ts +3 -2
  122. package/dist/admin/translations/en.json.js +28 -0
  123. package/dist/admin/translations/en.json.js.map +1 -1
  124. package/dist/admin/translations/en.json.mjs +28 -0
  125. package/dist/admin/translations/en.json.mjs.map +1 -1
  126. package/dist/admin/translations/pl.json.js +54 -29
  127. package/dist/admin/translations/pl.json.js.map +1 -1
  128. package/dist/admin/translations/pl.json.mjs +54 -29
  129. package/dist/admin/translations/pl.json.mjs.map +1 -1
  130. package/dist/server/controllers/admin-upload.js +3 -2
  131. package/dist/server/controllers/admin-upload.js.map +1 -1
  132. package/dist/server/controllers/admin-upload.mjs +3 -2
  133. package/dist/server/controllers/admin-upload.mjs.map +1 -1
  134. package/dist/server/controllers/content-api.js +6 -5
  135. package/dist/server/controllers/content-api.js.map +1 -1
  136. package/dist/server/controllers/content-api.mjs +6 -5
  137. package/dist/server/controllers/content-api.mjs.map +1 -1
  138. package/dist/server/src/controllers/admin-upload.d.ts.map +1 -1
  139. package/dist/server/src/controllers/content-api.d.ts.map +1 -1
  140. package/package.json +8 -7
@@ -8,7 +8,6 @@ var pl = {
8
8
  "asset-details.videoNotSupported": "Twoja przeglądarka nie obsługuje tagu video.",
9
9
  "asset-details.size": "Rozmiar",
10
10
  "asset-details.dimensions": "Wymiary",
11
- "asset-details.duration": "Czas trwania",
12
11
  "asset-details.creationDate": "Data utworzenia",
13
12
  "asset-details.lastUpdated": "Ostatnia aktualizacja",
14
13
  "asset-details.createdBy": "Utworzone przez",
@@ -17,6 +16,32 @@ var pl = {
17
16
  "asset-details.fileName": "Nazwa pliku",
18
17
  "asset-details.caption": "Podpis",
19
18
  "asset-details.alternativeText": "Tekst alternatywny",
19
+ "asset-details.location": "Lokalizacja",
20
+ "asset-details.save": "Zapisz zmiany",
21
+ "asset-details.update.success": "Plik zaktualizowany",
22
+ "asset-details.update.error": "Nie udało się zaktualizować pliku.",
23
+ "asset-details.field.empty": "{label} jest obecnie puste.",
24
+ "asset-details.location.root": "Biblioteka mediów",
25
+ "asset-details.saveChanges": "Zapisz zmiany",
26
+ "asset-details.delete.trigger": "Usuń ten plik",
27
+ "asset-details.delete.title": "Usunąć ten plik multimedialny?",
28
+ "asset-details.delete.description": "Ten plik nie może zostać odzyskany po usunięciu. Jeśli jest obecnie używany, powiązana treść zostanie uszkodzona, a kontenery obrazów będą puste.",
29
+ "asset-details.delete.success": "1 element został usunięty z {folderName}",
30
+ "asset-details.delete.error": "Nie udało się usunąć pliku.",
31
+ "asset-details.delete.loading": "Usuwanie pliku…",
32
+ "asset-details.replace.trigger": "Zamień ten plik",
33
+ "asset-details.replace.title": "Zamienić ten plik multimedialny?",
34
+ "asset-details.replace.description": "Obecna zawartość zostanie trwale zastąpiona.",
35
+ "asset-details.replace.description.ai": "AI wygeneruje nowe metadane po przesłaniu.",
36
+ "asset-details.replace.continue": "Kontynuuj",
37
+ "asset-details.replace.success": "Plik zamieniony.",
38
+ "asset-details.replace.error": "Nie udało się zamienić pliku.",
39
+ "asset-details.replace.loading": "Zastępowanie pliku…",
40
+ "asset-details.copy-link.trigger": "Kopiuj link",
41
+ "asset-details.copy-link.success": "Link skopiowany.",
42
+ "asset-details.copy-link.error": "Nie udało się skopiować linku.",
43
+ "asset-details.download.trigger": "Pobierz",
44
+ "asset-details.download.error": "Nie udało się pobrać pliku.",
20
45
  "asset-details.noPreview": "Brak podglądu",
21
46
  "upload.generic-error": "Wystąpił błąd podczas przesyłania pliku.",
22
47
  "upload.progress": "Postęp przesyłania",
@@ -47,7 +72,7 @@ var pl = {
47
72
  "button.next": "Dalej",
48
73
  "new": "Nowy",
49
74
  "checkControl.crop-duplicate": "Duplikuj i przytnij",
50
- "checkControl.crop-original": "Przytnij",
75
+ "checkControl.crop-original": "Przytnij oryginalny zasób",
51
76
  "content.isLoading": "Ładowanie listy.",
52
77
  "control-card.add": "Dodaj",
53
78
  "control-card.cancel": "Anuluj",
@@ -60,7 +85,7 @@ var pl = {
60
85
  "control-card.download": "Pobierz",
61
86
  "control-card.edit": "Edytuj",
62
87
  "control-card.remove-selection": "Usuń z zaznaczenia",
63
- "control-card.replace-media": "Zamień",
88
+ "control-card.replace-media": "Zamień media",
64
89
  "control-card.save": "Zapisz",
65
90
  "control-card.stop-crop": "Zatrzymaj przycinanie",
66
91
  "dropzone.upload.message": "Upuść tutaj, aby przesłać do",
@@ -94,38 +119,38 @@ var pl = {
94
119
  "input.label-bold": "Przeciągnij & upuść",
95
120
  "input.label-normal": "do przesłania lub",
96
121
  "input.placeholder": "Kliknij aby wybrać lub przeciągnij i upuść plik tutaj",
97
- "input.placeholder.icon": "Upuść tutaj",
122
+ "input.placeholder.icon": "Upuść zasób w tej strefie",
98
123
  "input.url.description": "Oddziel swoje linki URL umieszczając je w nowych liniach.",
99
- "input.url.label": "URL",
100
- "input.url.placeholder": "Brak",
124
+ "input.url.label": "URL(e)",
125
+ "input.url.placeholder": "Pusty",
101
126
  "input.notification.not-supported": "Nie możesz przesłać pliku tego typu, akceptowane są tylko następujące typy – {fileTypes}",
102
127
  "list.assets.title": "Pliki ({count})",
103
- "list.asset.at.finished": "Załadowano.",
128
+ "list.asset.at.finished": "Zasoby zakończyły ładowanie.",
104
129
  "list.assets-empty.search": "Brak wyników wyszukiwania",
105
130
  "list.assets-empty.subtitle": "Dodaj jeden do listy.",
106
131
  "list.assets-empty.title": "Nie ma jeszcze żadnych plików",
107
132
  "list.assets-empty.title-withSearch": "Brak plików pasujących do wybranych filtrów",
108
133
  "list.assets.empty": "Biblioteka Mediów jest pusta",
109
134
  "list.assets.empty-upload": "Prześlij pierwszy plik...",
110
- "list.assets.empty.no-permissions": "Lista jest pusta.",
135
+ "list.assets.empty.no-permissions": "Brak uprawnień do wyświetlania",
111
136
  "list.assets.error": "Wystąpił błąd podczas pobierania zasobów.",
112
137
  "list.assets.loading-more": "Ładowanie kolejnych zasobów...",
113
138
  "list.assets.loading-asset": "Ładowanie podglądu dla: {path}",
114
139
  "list.assets.not-supported-content": "Podgląd nie jest dostępny",
115
- "list.assets.preview-asset": "Podgląd dla video: {path}",
116
- "list.assets.selected": "{number, plural, =0 {Brak plików} other {# zaznaczono}}",
140
+ "list.assets.preview-asset": "Podgląd wideo: {path}",
141
+ "list.assets.selected": "{numberFolders, plural, one {1 folder} other {# folderów}} - {numberAssets, plural, one {1 plik} other {# plików}}",
117
142
  "list-assets-select": "Wybierz plik {name}",
118
143
  "list.assets.type-not-allowed": "Ten typ pliku jest niedozwolony.",
119
144
  "list.assets.to-upload": "{number, plural, =0 {Brak plików} one {1 plik gotowy} other {# plików gotowych}} do przesłania",
120
145
  "list.folder.edit": "Edytuj folder",
121
146
  "list.folder.select": "Wybierz folder {name}",
122
- "list.folder.subtitle": "{folderCount, plural, =0 {# folderów} one {# folder} other {# foldery}}, {filesCount, plural, =0 {# plików} one {# plik} other {# plików}}",
147
+ "list.folder.subtitle": "{folderCount, plural, one {# folder} other {# foldery}}, {filesCount, plural, one {# plik} other {# plików}}",
123
148
  "list.folders.title": "Foldery ({count})",
124
149
  "list.folders.link-label": "Przejdź do folderu",
125
- "mediaLibraryInput.actions.nextSlide": "Następny",
126
- "mediaLibraryInput.actions.previousSlide": "Poprzedni",
127
- "mediaLibraryInput.placeholder": "Kliknij by dodać plik lub przeciągnij i upuść plik w to miejsce",
128
- "mediaLibraryInput.slideCount": "{n} z {m}",
150
+ "mediaLibraryInput.actions.nextSlide": "Następny slajd",
151
+ "mediaLibraryInput.actions.previousSlide": "Poprzedni slajd",
152
+ "mediaLibraryInput.placeholder": "Kliknij, aby dodać plik lub przeciągnij i upuść plik w to miejsce",
153
+ "mediaLibraryInput.slideCount": "{n} z {m} slajdów",
129
154
  "modal.file-details.date": "Data",
130
155
  "modal.file-details.dimensions": "Wymiary",
131
156
  "modal.file-details.extension": "Rozszerzenia",
@@ -146,35 +171,35 @@ var pl = {
146
171
  "modal.remove.success-label": "Elementy zostały pomyślnie usunięte.",
147
172
  "modal.move.success-label": "Elementy zostały pomyślnie przeniesione",
148
173
  "modal.selected-list.sub-header-subtitle": "Przeciągnij i upuść, aby zmienić kolejność plików w polu",
149
- "modal.upload-list.footer.button": "Prześlij pliki do biblioteki",
150
- "modal.upload-list.sub-header-subtitle": "Zarządzaj plikami przed dodaniem ich do Biblioteki Multimediów",
151
- "modal.upload-list.sub-header.button": "Dodaj więcej",
174
+ "modal.upload-list.footer.button": "Prześlij {number, plural, one {# plik} other {# plików}} do biblioteki",
175
+ "modal.upload-list.sub-header-subtitle": "Zarządzaj plikami przed dodaniem ich do biblioteki multimediów",
176
+ "modal.upload-list.sub-header.button": "Dodaj więcej plików",
152
177
  "modal.upload.cancelled": "Przesyłanie przerwane.",
153
- "page.title": "Ustawienia - Biblioteka Multimediów",
178
+ "page.title": "Ustawienia - Biblioteka multimediów",
154
179
  "permissions.not-allowed.update": "Brak dostępu do edycji pliku.",
155
180
  "plugin.description.long": "Zarządzanie plikami multimedialnymi.",
156
181
  "plugin.description.short": "Zarządzanie plikami multimedialnymi.",
157
- "plugin.name": "Bilbioteka Multimediów",
182
+ "plugin.name": "Biblioteka multimediów",
158
183
  "plugin.home": "Strona główna",
159
- "search.clear.label": "Wyczyść",
160
- "search.label": "Szukaj",
161
- "search.placeholder": "Szukaj...",
184
+ "search.clear.label": "Wyczyść wyszukiwanie",
185
+ "search.label": "Szukaj pliku",
186
+ "search.placeholder": "np. pierwszy pies na księżycu",
162
187
  "settings.blockTitle": "Zarządzanie plikami",
163
188
  "settings.form.aiMetadata.label": "Automatycznie generuj podpisy i teksty alternatywne za pomocą sztucznej inteligencji podczas przesyłania!",
164
189
  "settings.form.aiMetadata.description": "Włącz tę funkcję, aby zaoszczędzić czas, zoptymalizować SEO i zwiększyć dostępność, pozwalając naszej sztucznej inteligencji generować za Ciebie podpisy i teksty alternatywne.",
165
190
  "settings.form.aiMetadata.allAssetsHaveMetadata": "Wszystkie zasoby mają podpisy i teksty alternatywne",
166
- "settings.form.aiMetadata.imagesWithoutMetadata": "{count, plural, jeden {# obraz nie ma podpisu lub tekstu alternatywnego} other {# obrazy nie mają podpisów lub tekstów alternatywnych}}",
191
+ "settings.form.aiMetadata.imagesWithoutMetadata": "{count, plural, one {# obraz nie ma podpisu lub tekstu alternatywnego} other {# obrazów nie ma podpisów lub tekstów alternatywnych}}",
167
192
  "settings.form.aiMetadata.generatingMetadata": "AI generuje Twoje metadane",
168
193
  "settings.form.aiMetadata.metadataGenerated": "Twoje metadane zostały wygenerowane",
169
194
  "settings.form.aiMetadata.generateButton": "Generuj metadane",
170
195
  "settings.form.aiMetadata.confirmDialog.title": "Generuj metadane AI",
171
196
  "settings.form.aiMetadata.confirmDialog.message": "Spowoduje to uruchomienie procesu w tle w celu wygenerowania podpisów i tekstu alternatywnego dla {count, plural, one {# obrazu} other {# obrazów}}. Sztuczna inteligencja może popełniać błędy, pamiętaj, aby sprawdzić wygenerowaną treść.",
172
197
  "settings.form.autoOrientation.description": "Automatycznie obróć obraz zgodnie ze znacznikiem orientacji EXIF",
173
- "settings.form.autoOrientation.label": "Włącz automatyczną orientację",
198
+ "settings.form.autoOrientation.label": "Automatyczna orientacja",
174
199
  "settings.form.responsiveDimensions.description": "Automatycznie generuje wiele formatów (duży, średni, mały) przesłanego pliku",
175
- "settings.form.responsiveDimensions.label": "Włącz przesyłanie przyjazne responsywności",
200
+ "settings.form.responsiveDimensions.label": "Przesyłanie przyjazne responsywności",
176
201
  "settings.form.sizeOptimization.description": "Włączenie tej opcji zmniejszy rozmiar obrazka i delikatnie zmniejszy jego jakość.",
177
- "settings.form.sizeOptimization.label": "Włącz optymalizację rozmiaru (bez utraty jakości)",
202
+ "settings.form.sizeOptimization.label": "Optymalizacja rozmiaru",
178
203
  "settings.form.videoPreview.description": "Wygeneruje sześciosekundowy podgląd wideo (GIF)",
179
204
  "settings.form.videoPreview.label": "Podgląd",
180
205
  "settings.header.label": "Biblioteka Multimediów",
@@ -213,9 +238,9 @@ var pl = {
213
238
  "config.popUpWarning.warning.updateAllSettings": "Spowoduje to modyfikację wszystkich Twoich ustawień",
214
239
  "view-switch.list": "Widok listy",
215
240
  "view-switch.grid": "Widok siatki",
216
- "view.switch.label": "View options",
241
+ "view.switch.label": "Opcje widoku",
217
242
  "view.table": "Widok tabeli",
218
- "view.grid": "Widokl siatki",
243
+ "view.grid": "Widok siatki",
219
244
  "ai.modal.uploading.title": "Przesyłanie i przetwarzanie przez AI...",
220
245
  "ai.modal.title": "{count, plural, one {# przesłany zasób} other {# przesłanych zasobów}}, sprawdź metadane wygenerowane przez AI",
221
246
  "ai.modal.error": "Nie udało się wygenerować metadanych dla przesłanych plików przez AI."
@@ -1 +1 @@
1
- {"version":3,"file":"pl.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"pl.json.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -54,15 +54,16 @@ var adminUpload = {
54
54
  });
55
55
  },
56
56
  async replaceFile (ctx) {
57
- const { state: { userAbility, user }, query: { id }, request: { body, files: { files } = {} } } = ctx;
57
+ const { state: { userAbility, user }, query: { id }, request: { body, files: { files: filesInput } = {} } } = ctx;
58
58
  if (typeof id !== 'string') {
59
59
  throw new utils.errors.ValidationError('File id is required');
60
60
  }
61
61
  const uploadService = index.getService('upload');
62
62
  const { pm } = await findEntityAndCheckPermissions.findEntityAndCheckPermissions(userAbility, constants.ACTIONS.update, constants.FILE_MODEL_UID, id);
63
- if (Array.isArray(files)) {
63
+ if (Array.isArray(filesInput) && filesInput.length > 1) {
64
64
  throw new utils.errors.ApplicationError('Cannot replace a file with multiple ones');
65
65
  }
66
+ const files = Array.isArray(filesInput) ? filesInput[0] : filesInput;
66
67
  const { validFiles, filteredBody, errors: validationErrors } = await mimeValidation.prepareUploadRequest(files, body, strapi);
67
68
  if (validFiles.length === 0) {
68
69
  throw new utils.errors.ValidationError(validationErrors[0].message);
@@ -1 +1 @@
1
- {"version":3,"file":"admin-upload.js","sources":["../../../server/src/controllers/admin-upload.ts"],"sourcesContent":["import os from 'os';\nimport path from 'path';\nimport fse from 'fs-extra';\nimport _ from 'lodash';\nimport { errors, async } from '@strapi/utils';\n\nimport type { Context } from 'koa';\n\nimport { getService } from '../utils';\nimport { ACTIONS, FILE_MODEL_UID } from '../constants';\nimport { validateBulkUpdateBody, validateUploadBody } from './validation/admin/upload';\nimport { findEntityAndCheckPermissions } from './utils/find-entity-and-check-permissions';\nimport { Config, FileInfo } from '../types';\nimport { prepareUploadRequest, type FileUploadError } from '../utils/mime-validation';\nimport type { UploadFileInfo } from '../../../shared/contracts/files';\n\nexport default {\n async bulkUpdateFileInfo(ctx: Context) {\n const {\n state: { userAbility, user },\n request: { body },\n } = ctx;\n\n const { updates } = await validateBulkUpdateBody(body);\n const uploadService = getService('upload');\n\n const results = await async.map(\n updates,\n async ({ id, fileInfo }: { id: number; fileInfo: FileInfo }) => {\n const { pm } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.update,\n FILE_MODEL_UID,\n id\n );\n\n const updated = await uploadService.updateFileInfo(id, fileInfo as any, { user });\n\n // Sign file urls for private providers\n const signedFile = await getService('file').signFileUrls(updated);\n\n return pm.sanitizeOutput(signedFile, { action: ACTIONS.read });\n }\n );\n\n ctx.body = results;\n },\n\n async updateFileInfo(ctx: Context) {\n const {\n state: { userAbility, user },\n query: { id },\n request: { body },\n } = ctx;\n\n if (typeof id !== 'string') {\n throw new errors.ValidationError('File id is required');\n }\n\n const uploadService = getService('upload');\n const { pm } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.update,\n FILE_MODEL_UID,\n id\n );\n\n const data = await validateUploadBody(body);\n\n const file = await uploadService.updateFileInfo(id, data.fileInfo as any, { user });\n\n // Sign file urls for private providers\n const signedFile = await getService('file').signFileUrls(file);\n\n ctx.body = await pm.sanitizeOutput(signedFile, { action: ACTIONS.read });\n },\n\n async replaceFile(ctx: Context) {\n const {\n state: { userAbility, user },\n query: { id },\n request: { body, files: { files } = {} },\n } = ctx;\n\n if (typeof id !== 'string') {\n throw new errors.ValidationError('File id is required');\n }\n\n const uploadService = getService('upload');\n const { pm } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.update,\n FILE_MODEL_UID,\n id\n );\n\n if (Array.isArray(files)) {\n throw new errors.ApplicationError('Cannot replace a file with multiple ones');\n }\n\n const {\n validFiles,\n filteredBody,\n errors: validationErrors,\n } = await prepareUploadRequest(files, body, strapi);\n if (validFiles.length === 0) {\n throw new errors.ValidationError(validationErrors[0].message);\n }\n\n const data = (await validateUploadBody(filteredBody)) as { fileInfo: FileInfo };\n const replacedFile = await uploadService.replace(id, { data, file: validFiles[0] }, { user });\n\n // Regenerate AI metadata for image replacements so the alt text / caption\n // reflect the new file content. Mirrors the post-upload hook in\n // `uploadFiles`; failure is logged and swallowed to keep the replace flow\n // resilient when the AI provider is unavailable.\n const aiMetadataService = getService('aiMetadata');\n if (replacedFile?.mime?.startsWith('image/') && (await aiMetadataService.isEnabled())) {\n try {\n const metadataResults = await aiMetadataService.processFiles([replacedFile]);\n await aiMetadataService.updateFilesWithAIMetadata([replacedFile], metadataResults, user);\n } catch (error) {\n strapi.log.warn('AI metadata generation failed on replace, proceeding without it', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n // Sign file urls for private providers\n const signedFile = await getService('file').signFileUrls(replacedFile);\n\n ctx.body = await pm.sanitizeOutput(signedFile, { action: ACTIONS.read });\n },\n\n async uploadFiles(ctx: Context) {\n const {\n state: { userAbility, user },\n request: { body, files: { files } = {} },\n } = ctx;\n\n const uploadService = getService('upload');\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.create,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n const {\n validFiles,\n filteredBody,\n errors: validationErrors,\n } = await prepareUploadRequest(files, body, strapi);\n if (validFiles.length === 0) {\n throw new errors.ValidationError(validationErrors[0].message);\n }\n\n const isMultipleFiles = validFiles.length > 1;\n const data = await validateUploadBody(filteredBody, isMultipleFiles);\n\n let filesArray = validFiles;\n\n if (\n data.fileInfo &&\n Array.isArray(data.fileInfo) &&\n filesArray.length === data.fileInfo.length\n ) {\n // Reorder filesArray to match data.fileInfo order\n const alignedFilesArray = data.fileInfo\n .map((info) => {\n return filesArray.find((file) => file.originalFilename === info.name);\n })\n .filter(Boolean) as any[];\n\n filesArray = alignedFilesArray;\n }\n\n // Upload files first to get thumbnails\n const uploadedFiles = await uploadService.upload({ data, files: filesArray }, { user });\n if (uploadedFiles.some((file) => file.mime?.startsWith('image/'))) {\n await getService('metrics').trackUsage('didUploadImage');\n }\n\n const aiMetadataService = getService('aiMetadata');\n\n // AFTER upload - generate AI metadata for images\n if (await aiMetadataService.isEnabled()) {\n try {\n const metadataResults = await aiMetadataService.processFiles(uploadedFiles);\n // Update the uploaded files with AI metadata\n await aiMetadataService.updateFilesWithAIMetadata(uploadedFiles, metadataResults, user);\n } catch (error) {\n strapi.log.warn('AI metadata generation failed, proceeding without AI enhancements', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n // Sign file urls for private providers\n const signedFiles = await async.map(uploadedFiles, getService('file').signFileUrls);\n\n ctx.body = await pm.sanitizeOutput(signedFiles, { action: ACTIONS.read });\n ctx.status = 201;\n },\n\n /**\n * @experimental\n * Upload a single file and return the created File.\n *\n * Accepts one file per request (multipart `files` + `fileInfo`) and returns a\n * single `File` object. Unlike `uploadFiles`, it does **not** run AI metadata\n * generation inline — that responsibility is decoupled and will be handled by a\n * background job. Auth and permission checks mirror `POST /upload`.\n */\n async unstable_uploadFile(ctx: Context) {\n const {\n state: { userAbility, user },\n request: { body, files: { files } = {} },\n } = ctx;\n\n const uploadService = getService('upload');\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.create,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n if (_.isEmpty(files) || (!Array.isArray(files) && files.size === 0)) {\n throw new errors.ApplicationError('Files are empty');\n }\n\n // Accept a single file per request; ignore any extras defensively.\n const file = Array.isArray(files) ? files[0] : files;\n const fileName = file.originalFilename || 'unknown';\n\n // Parse the single fileInfo object from the multipart body.\n let fileInfo: UploadFileInfo = {\n name: fileName,\n caption: null,\n alternativeText: null,\n folder: null,\n };\n if (body?.fileInfo) {\n const raw = body.fileInfo;\n if (typeof raw === 'string') {\n fileInfo = JSON.parse(raw);\n } else if (Array.isArray(raw)) {\n fileInfo = (typeof raw[0] === 'string' ? JSON.parse(raw[0]) : raw[0]) as UploadFileInfo;\n } else {\n fileInfo = raw as UploadFileInfo;\n }\n }\n\n // Validate this single file using security checks.\n const { validFiles, errors: validationErrors } = await prepareUploadRequest(\n file,\n { fileInfo: JSON.stringify(fileInfo) },\n strapi\n );\n\n if (validFiles.length === 0) {\n throw new errors.ValidationError(validationErrors[0]?.message || 'Validation failed');\n }\n\n const data = await validateUploadBody({ fileInfo }, false);\n const [uploadedFile] = await uploadService.upload({ data, files: [validFiles[0]] }, { user });\n\n if (uploadedFile.mime?.startsWith('image/')) {\n await getService('metrics').trackUsage('didUploadImage');\n }\n\n // No inline AI metadata generation — intentionally decoupled for the async job.\n\n // Sign file url for private providers.\n const signedFile = await getService('file').signFileUrls(uploadedFile);\n\n ctx.body = await pm.sanitizeOutput(signedFile, { action: ACTIONS.read });\n ctx.status = 201;\n },\n\n /**\n * @experimental\n * Upload files from URLs with SSE streaming for per-file progress\n *\n * Accepts JSON body with URLs and fetches them server-side.\n * Streams Server-Sent Events as each URL is fetched and uploaded:\n * - file:fetching — when starting to fetch a URL\n * - file:uploading — when upload starts for a fetched file\n * - file:complete — when a file is successfully uploaded\n * - file:error — when a URL fetch or upload fails\n * - stream:complete — final summary with all results\n */\n async unstable_uploadFromUrls(ctx: Context) {\n const {\n state: { userAbility, user },\n request: { body },\n } = ctx;\n\n const uploadService = getService('upload');\n const fileService = getService('file');\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.create,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n // Parse and validate request body\n const { urls, folderId } = body as { urls?: string[]; folderId?: number | null };\n\n if (!urls || !Array.isArray(urls) || urls.length === 0) {\n throw new errors.ApplicationError('URLs are required');\n }\n\n if (urls.length > 20) {\n throw new errors.ApplicationError('Maximum 20 URLs allowed per request');\n }\n\n // Take manual control of the response for SSE streaming\n ctx.respond = false;\n const res = ctx.res;\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n Connection: 'keep-alive',\n });\n\n const writeSSE = (event: string, data: Record<string, unknown>) => {\n res.write(`event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`);\n };\n\n const total = urls.length;\n const uploadErrors: FileUploadError[] = [];\n const successfulFiles: any[] = [];\n\n // Create temp directory for fetched files\n const tmpWorkingDirectory = await fse.mkdtemp(path.join(os.tmpdir(), 'strapi-url-upload-'));\n const { sizeLimit } = strapi.config.get<Config>('plugin::upload');\n\n try {\n // Process each URL sequentially\n for (let i = 0; i < urls.length; i += 1) {\n const url = urls[i];\n\n writeSSE('file:fetching', { url, index: i, total });\n\n try {\n // Fetch URL to temp file\n const { file } = await fileService.fetchUrlToInputFile(\n url,\n tmpWorkingDirectory,\n sizeLimit\n );\n const fileName = file.originalFilename;\n\n writeSSE('file:uploading', {\n name: fileName,\n index: i,\n total,\n size: file.size,\n });\n\n // Validate using security checks\n const fileInfo: UploadFileInfo = {\n name: fileName,\n caption: null,\n alternativeText: null,\n folder: folderId ?? null,\n };\n\n const { validFiles, errors: validationErrors } = await prepareUploadRequest(\n file,\n { fileInfo: JSON.stringify(fileInfo) },\n strapi\n );\n\n if (validFiles.length === 0) {\n const errorMessage = validationErrors[0]?.message || 'Validation failed';\n uploadErrors.push({ name: fileName, message: errorMessage });\n writeSSE('file:error', { name: fileName, url, index: i, message: errorMessage });\n } else {\n // Upload the file\n const data = await validateUploadBody({ fileInfo }, false);\n const [uploadedFile] = await uploadService.upload(\n { data, files: [validFiles[0]] },\n { user }\n );\n\n // Sign file url\n const signedFile = await fileService.signFileUrls(uploadedFile);\n successfulFiles.push(signedFile);\n\n writeSSE('file:complete', { name: fileName, index: i, file: signedFile });\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n uploadErrors.push({ name: url, message: errorMessage });\n writeSSE('file:error', { url, index: i, message: errorMessage });\n }\n }\n\n // Track image upload metric once if any images were uploaded\n if (successfulFiles.some((file) => file.mime?.startsWith('image/'))) {\n await getService('metrics').trackUsage('didUploadImage');\n }\n\n // Send final stream summary\n writeSSE('stream:complete', {\n data: await pm.sanitizeOutput(successfulFiles, { action: ACTIONS.read }),\n errors: uploadErrors,\n });\n } finally {\n // Clean up temp directory\n await fse.remove(tmpWorkingDirectory);\n }\n\n res.end();\n },\n\n // TODO: split into multiple endpoints\n async upload(ctx: Context) {\n const {\n query: { id },\n request: { files: { files } = {} },\n } = ctx;\n\n if (_.isEmpty(files) || (!Array.isArray(files) && files.size === 0)) {\n if (id) {\n return this.updateFileInfo(ctx);\n }\n\n throw new errors.ApplicationError('Files are empty');\n }\n\n await (id ? this.replaceFile : this.uploadFiles)(ctx);\n },\n};\n"],"names":["bulkUpdateFileInfo","ctx","state","userAbility","user","request","body","updates","validateBulkUpdateBody","uploadService","getService","results","async","map","id","fileInfo","pm","findEntityAndCheckPermissions","ACTIONS","update","FILE_MODEL_UID","updated","updateFileInfo","signedFile","signFileUrls","sanitizeOutput","action","read","query","errors","ValidationError","data","validateUploadBody","file","replaceFile","files","Array","isArray","ApplicationError","validFiles","filteredBody","validationErrors","prepareUploadRequest","strapi","length","message","replacedFile","replace","aiMetadataService","mime","startsWith","isEnabled","metadataResults","processFiles","updateFilesWithAIMetadata","error","log","warn","Error","String","uploadFiles","service","createPermissionsManager","ability","create","model","isAllowed","forbidden","isMultipleFiles","filesArray","alignedFilesArray","info","find","originalFilename","name","filter","Boolean","uploadedFiles","upload","some","trackUsage","signedFiles","status","unstable_uploadFile","_","isEmpty","size","fileName","caption","alternativeText","folder","raw","JSON","parse","stringify","uploadedFile","unstable_uploadFromUrls","fileService","urls","folderId","respond","res","writeHead","Connection","writeSSE","event","write","total","uploadErrors","successfulFiles","tmpWorkingDirectory","fse","mkdtemp","path","join","os","tmpdir","sizeLimit","config","get","i","url","index","fetchUrlToInputFile","errorMessage","push","remove","end"],"mappings":"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"}
1
+ {"version":3,"file":"admin-upload.js","sources":["../../../server/src/controllers/admin-upload.ts"],"sourcesContent":["import os from 'os';\nimport path from 'path';\nimport fse from 'fs-extra';\nimport _ from 'lodash';\nimport { errors, async } from '@strapi/utils';\n\nimport type { Context } from 'koa';\n\nimport { getService } from '../utils';\nimport { ACTIONS, FILE_MODEL_UID } from '../constants';\nimport { validateBulkUpdateBody, validateUploadBody } from './validation/admin/upload';\nimport { findEntityAndCheckPermissions } from './utils/find-entity-and-check-permissions';\nimport { Config, FileInfo } from '../types';\nimport { prepareUploadRequest, type FileUploadError } from '../utils/mime-validation';\nimport type { UploadFileInfo } from '../../../shared/contracts/files';\n\nexport default {\n async bulkUpdateFileInfo(ctx: Context) {\n const {\n state: { userAbility, user },\n request: { body },\n } = ctx;\n\n const { updates } = await validateBulkUpdateBody(body);\n const uploadService = getService('upload');\n\n const results = await async.map(\n updates,\n async ({ id, fileInfo }: { id: number; fileInfo: FileInfo }) => {\n const { pm } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.update,\n FILE_MODEL_UID,\n id\n );\n\n const updated = await uploadService.updateFileInfo(id, fileInfo as any, { user });\n\n // Sign file urls for private providers\n const signedFile = await getService('file').signFileUrls(updated);\n\n return pm.sanitizeOutput(signedFile, { action: ACTIONS.read });\n }\n );\n\n ctx.body = results;\n },\n\n async updateFileInfo(ctx: Context) {\n const {\n state: { userAbility, user },\n query: { id },\n request: { body },\n } = ctx;\n\n if (typeof id !== 'string') {\n throw new errors.ValidationError('File id is required');\n }\n\n const uploadService = getService('upload');\n const { pm } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.update,\n FILE_MODEL_UID,\n id\n );\n\n const data = await validateUploadBody(body);\n\n const file = await uploadService.updateFileInfo(id, data.fileInfo as any, { user });\n\n // Sign file urls for private providers\n const signedFile = await getService('file').signFileUrls(file);\n\n ctx.body = await pm.sanitizeOutput(signedFile, { action: ACTIONS.read });\n },\n\n async replaceFile(ctx: Context) {\n const {\n state: { userAbility, user },\n query: { id },\n request: { body, files: { files: filesInput } = {} },\n } = ctx;\n\n if (typeof id !== 'string') {\n throw new errors.ValidationError('File id is required');\n }\n\n const uploadService = getService('upload');\n const { pm } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.update,\n FILE_MODEL_UID,\n id\n );\n\n if (Array.isArray(filesInput) && filesInput.length > 1) {\n throw new errors.ApplicationError('Cannot replace a file with multiple ones');\n }\n\n const files = Array.isArray(filesInput) ? filesInput[0] : filesInput;\n\n const {\n validFiles,\n filteredBody,\n errors: validationErrors,\n } = await prepareUploadRequest(files, body, strapi);\n if (validFiles.length === 0) {\n throw new errors.ValidationError(validationErrors[0].message);\n }\n\n const data = (await validateUploadBody(filteredBody)) as { fileInfo: FileInfo };\n const replacedFile = await uploadService.replace(id, { data, file: validFiles[0] }, { user });\n\n // Regenerate AI metadata for image replacements so the alt text / caption\n // reflect the new file content. Mirrors the post-upload hook in\n // `uploadFiles`; failure is logged and swallowed to keep the replace flow\n // resilient when the AI provider is unavailable.\n const aiMetadataService = getService('aiMetadata');\n if (replacedFile?.mime?.startsWith('image/') && (await aiMetadataService.isEnabled())) {\n try {\n const metadataResults = await aiMetadataService.processFiles([replacedFile]);\n await aiMetadataService.updateFilesWithAIMetadata([replacedFile], metadataResults, user);\n } catch (error) {\n strapi.log.warn('AI metadata generation failed on replace, proceeding without it', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n // Sign file urls for private providers\n const signedFile = await getService('file').signFileUrls(replacedFile);\n\n ctx.body = await pm.sanitizeOutput(signedFile, { action: ACTIONS.read });\n },\n\n async uploadFiles(ctx: Context) {\n const {\n state: { userAbility, user },\n request: { body, files: { files } = {} },\n } = ctx;\n\n const uploadService = getService('upload');\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.create,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n const {\n validFiles,\n filteredBody,\n errors: validationErrors,\n } = await prepareUploadRequest(files, body, strapi);\n if (validFiles.length === 0) {\n throw new errors.ValidationError(validationErrors[0].message);\n }\n\n const isMultipleFiles = validFiles.length > 1;\n const data = await validateUploadBody(filteredBody, isMultipleFiles);\n\n let filesArray = validFiles;\n\n if (\n data.fileInfo &&\n Array.isArray(data.fileInfo) &&\n filesArray.length === data.fileInfo.length\n ) {\n // Reorder filesArray to match data.fileInfo order\n const alignedFilesArray = data.fileInfo\n .map((info) => {\n return filesArray.find((file) => file.originalFilename === info.name);\n })\n .filter(Boolean) as any[];\n\n filesArray = alignedFilesArray;\n }\n\n // Upload files first to get thumbnails\n const uploadedFiles = await uploadService.upload({ data, files: filesArray }, { user });\n if (uploadedFiles.some((file) => file.mime?.startsWith('image/'))) {\n await getService('metrics').trackUsage('didUploadImage');\n }\n\n const aiMetadataService = getService('aiMetadata');\n\n // AFTER upload - generate AI metadata for images\n if (await aiMetadataService.isEnabled()) {\n try {\n const metadataResults = await aiMetadataService.processFiles(uploadedFiles);\n // Update the uploaded files with AI metadata\n await aiMetadataService.updateFilesWithAIMetadata(uploadedFiles, metadataResults, user);\n } catch (error) {\n strapi.log.warn('AI metadata generation failed, proceeding without AI enhancements', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n // Sign file urls for private providers\n const signedFiles = await async.map(uploadedFiles, getService('file').signFileUrls);\n\n ctx.body = await pm.sanitizeOutput(signedFiles, { action: ACTIONS.read });\n ctx.status = 201;\n },\n\n /**\n * @experimental\n * Upload a single file and return the created File.\n *\n * Accepts one file per request (multipart `files` + `fileInfo`) and returns a\n * single `File` object. Unlike `uploadFiles`, it does **not** run AI metadata\n * generation inline — that responsibility is decoupled and will be handled by a\n * background job. Auth and permission checks mirror `POST /upload`.\n */\n async unstable_uploadFile(ctx: Context) {\n const {\n state: { userAbility, user },\n request: { body, files: { files } = {} },\n } = ctx;\n\n const uploadService = getService('upload');\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.create,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n if (_.isEmpty(files) || (!Array.isArray(files) && files.size === 0)) {\n throw new errors.ApplicationError('Files are empty');\n }\n\n // Accept a single file per request; ignore any extras defensively.\n const file = Array.isArray(files) ? files[0] : files;\n const fileName = file.originalFilename || 'unknown';\n\n // Parse the single fileInfo object from the multipart body.\n let fileInfo: UploadFileInfo = {\n name: fileName,\n caption: null,\n alternativeText: null,\n folder: null,\n };\n if (body?.fileInfo) {\n const raw = body.fileInfo;\n if (typeof raw === 'string') {\n fileInfo = JSON.parse(raw);\n } else if (Array.isArray(raw)) {\n fileInfo = (typeof raw[0] === 'string' ? JSON.parse(raw[0]) : raw[0]) as UploadFileInfo;\n } else {\n fileInfo = raw as UploadFileInfo;\n }\n }\n\n // Validate this single file using security checks.\n const { validFiles, errors: validationErrors } = await prepareUploadRequest(\n file,\n { fileInfo: JSON.stringify(fileInfo) },\n strapi\n );\n\n if (validFiles.length === 0) {\n throw new errors.ValidationError(validationErrors[0]?.message || 'Validation failed');\n }\n\n const data = await validateUploadBody({ fileInfo }, false);\n const [uploadedFile] = await uploadService.upload({ data, files: [validFiles[0]] }, { user });\n\n if (uploadedFile.mime?.startsWith('image/')) {\n await getService('metrics').trackUsage('didUploadImage');\n }\n\n // No inline AI metadata generation — intentionally decoupled for the async job.\n\n // Sign file url for private providers.\n const signedFile = await getService('file').signFileUrls(uploadedFile);\n\n ctx.body = await pm.sanitizeOutput(signedFile, { action: ACTIONS.read });\n ctx.status = 201;\n },\n\n /**\n * @experimental\n * Upload files from URLs with SSE streaming for per-file progress\n *\n * Accepts JSON body with URLs and fetches them server-side.\n * Streams Server-Sent Events as each URL is fetched and uploaded:\n * - file:fetching — when starting to fetch a URL\n * - file:uploading — when upload starts for a fetched file\n * - file:complete — when a file is successfully uploaded\n * - file:error — when a URL fetch or upload fails\n * - stream:complete — final summary with all results\n */\n async unstable_uploadFromUrls(ctx: Context) {\n const {\n state: { userAbility, user },\n request: { body },\n } = ctx;\n\n const uploadService = getService('upload');\n const fileService = getService('file');\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.create,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n // Parse and validate request body\n const { urls, folderId } = body as { urls?: string[]; folderId?: number | null };\n\n if (!urls || !Array.isArray(urls) || urls.length === 0) {\n throw new errors.ApplicationError('URLs are required');\n }\n\n if (urls.length > 20) {\n throw new errors.ApplicationError('Maximum 20 URLs allowed per request');\n }\n\n // Take manual control of the response for SSE streaming\n ctx.respond = false;\n const res = ctx.res;\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n Connection: 'keep-alive',\n });\n\n const writeSSE = (event: string, data: Record<string, unknown>) => {\n res.write(`event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`);\n };\n\n const total = urls.length;\n const uploadErrors: FileUploadError[] = [];\n const successfulFiles: any[] = [];\n\n // Create temp directory for fetched files\n const tmpWorkingDirectory = await fse.mkdtemp(path.join(os.tmpdir(), 'strapi-url-upload-'));\n const { sizeLimit } = strapi.config.get<Config>('plugin::upload');\n\n try {\n // Process each URL sequentially\n for (let i = 0; i < urls.length; i += 1) {\n const url = urls[i];\n\n writeSSE('file:fetching', { url, index: i, total });\n\n try {\n // Fetch URL to temp file\n const { file } = await fileService.fetchUrlToInputFile(\n url,\n tmpWorkingDirectory,\n sizeLimit\n );\n const fileName = file.originalFilename;\n\n writeSSE('file:uploading', {\n name: fileName,\n index: i,\n total,\n size: file.size,\n });\n\n // Validate using security checks\n const fileInfo: UploadFileInfo = {\n name: fileName,\n caption: null,\n alternativeText: null,\n folder: folderId ?? null,\n };\n\n const { validFiles, errors: validationErrors } = await prepareUploadRequest(\n file,\n { fileInfo: JSON.stringify(fileInfo) },\n strapi\n );\n\n if (validFiles.length === 0) {\n const errorMessage = validationErrors[0]?.message || 'Validation failed';\n uploadErrors.push({ name: fileName, message: errorMessage });\n writeSSE('file:error', { name: fileName, url, index: i, message: errorMessage });\n } else {\n // Upload the file\n const data = await validateUploadBody({ fileInfo }, false);\n const [uploadedFile] = await uploadService.upload(\n { data, files: [validFiles[0]] },\n { user }\n );\n\n // Sign file url\n const signedFile = await fileService.signFileUrls(uploadedFile);\n successfulFiles.push(signedFile);\n\n writeSSE('file:complete', { name: fileName, index: i, file: signedFile });\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n uploadErrors.push({ name: url, message: errorMessage });\n writeSSE('file:error', { url, index: i, message: errorMessage });\n }\n }\n\n // Track image upload metric once if any images were uploaded\n if (successfulFiles.some((file) => file.mime?.startsWith('image/'))) {\n await getService('metrics').trackUsage('didUploadImage');\n }\n\n // Send final stream summary\n writeSSE('stream:complete', {\n data: await pm.sanitizeOutput(successfulFiles, { action: ACTIONS.read }),\n errors: uploadErrors,\n });\n } finally {\n // Clean up temp directory\n await fse.remove(tmpWorkingDirectory);\n }\n\n res.end();\n },\n\n // TODO: split into multiple endpoints\n async upload(ctx: Context) {\n const {\n query: { id },\n request: { files: { files } = {} },\n } = ctx;\n\n if (_.isEmpty(files) || (!Array.isArray(files) && files.size === 0)) {\n if (id) {\n return this.updateFileInfo(ctx);\n }\n\n throw new errors.ApplicationError('Files are empty');\n }\n\n await (id ? this.replaceFile : this.uploadFiles)(ctx);\n },\n};\n"],"names":["bulkUpdateFileInfo","ctx","state","userAbility","user","request","body","updates","validateBulkUpdateBody","uploadService","getService","results","async","map","id","fileInfo","pm","findEntityAndCheckPermissions","ACTIONS","update","FILE_MODEL_UID","updated","updateFileInfo","signedFile","signFileUrls","sanitizeOutput","action","read","query","errors","ValidationError","data","validateUploadBody","file","replaceFile","files","filesInput","Array","isArray","length","ApplicationError","validFiles","filteredBody","validationErrors","prepareUploadRequest","strapi","message","replacedFile","replace","aiMetadataService","mime","startsWith","isEnabled","metadataResults","processFiles","updateFilesWithAIMetadata","error","log","warn","Error","String","uploadFiles","service","createPermissionsManager","ability","create","model","isAllowed","forbidden","isMultipleFiles","filesArray","alignedFilesArray","info","find","originalFilename","name","filter","Boolean","uploadedFiles","upload","some","trackUsage","signedFiles","status","unstable_uploadFile","_","isEmpty","size","fileName","caption","alternativeText","folder","raw","JSON","parse","stringify","uploadedFile","unstable_uploadFromUrls","fileService","urls","folderId","respond","res","writeHead","Connection","writeSSE","event","write","total","uploadErrors","successfulFiles","tmpWorkingDirectory","fse","mkdtemp","path","join","os","tmpdir","sizeLimit","config","get","i","url","index","fetchUrlToInputFile","errorMessage","push","remove","end"],"mappings":"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"}
@@ -45,15 +45,16 @@ var adminUpload = {
45
45
  });
46
46
  },
47
47
  async replaceFile (ctx) {
48
- const { state: { userAbility, user }, query: { id }, request: { body, files: { files } = {} } } = ctx;
48
+ const { state: { userAbility, user }, query: { id }, request: { body, files: { files: filesInput } = {} } } = ctx;
49
49
  if (typeof id !== 'string') {
50
50
  throw new errors.ValidationError('File id is required');
51
51
  }
52
52
  const uploadService = getService('upload');
53
53
  const { pm } = await findEntityAndCheckPermissions(userAbility, ACTIONS.update, FILE_MODEL_UID, id);
54
- if (Array.isArray(files)) {
54
+ if (Array.isArray(filesInput) && filesInput.length > 1) {
55
55
  throw new errors.ApplicationError('Cannot replace a file with multiple ones');
56
56
  }
57
+ const files = Array.isArray(filesInput) ? filesInput[0] : filesInput;
57
58
  const { validFiles, filteredBody, errors: validationErrors } = await prepareUploadRequest(files, body, strapi);
58
59
  if (validFiles.length === 0) {
59
60
  throw new errors.ValidationError(validationErrors[0].message);
@@ -1 +1 @@
1
- {"version":3,"file":"admin-upload.mjs","sources":["../../../server/src/controllers/admin-upload.ts"],"sourcesContent":["import os from 'os';\nimport path from 'path';\nimport fse from 'fs-extra';\nimport _ from 'lodash';\nimport { errors, async } from '@strapi/utils';\n\nimport type { Context } from 'koa';\n\nimport { getService } from '../utils';\nimport { ACTIONS, FILE_MODEL_UID } from '../constants';\nimport { validateBulkUpdateBody, validateUploadBody } from './validation/admin/upload';\nimport { findEntityAndCheckPermissions } from './utils/find-entity-and-check-permissions';\nimport { Config, FileInfo } from '../types';\nimport { prepareUploadRequest, type FileUploadError } from '../utils/mime-validation';\nimport type { UploadFileInfo } from '../../../shared/contracts/files';\n\nexport default {\n async bulkUpdateFileInfo(ctx: Context) {\n const {\n state: { userAbility, user },\n request: { body },\n } = ctx;\n\n const { updates } = await validateBulkUpdateBody(body);\n const uploadService = getService('upload');\n\n const results = await async.map(\n updates,\n async ({ id, fileInfo }: { id: number; fileInfo: FileInfo }) => {\n const { pm } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.update,\n FILE_MODEL_UID,\n id\n );\n\n const updated = await uploadService.updateFileInfo(id, fileInfo as any, { user });\n\n // Sign file urls for private providers\n const signedFile = await getService('file').signFileUrls(updated);\n\n return pm.sanitizeOutput(signedFile, { action: ACTIONS.read });\n }\n );\n\n ctx.body = results;\n },\n\n async updateFileInfo(ctx: Context) {\n const {\n state: { userAbility, user },\n query: { id },\n request: { body },\n } = ctx;\n\n if (typeof id !== 'string') {\n throw new errors.ValidationError('File id is required');\n }\n\n const uploadService = getService('upload');\n const { pm } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.update,\n FILE_MODEL_UID,\n id\n );\n\n const data = await validateUploadBody(body);\n\n const file = await uploadService.updateFileInfo(id, data.fileInfo as any, { user });\n\n // Sign file urls for private providers\n const signedFile = await getService('file').signFileUrls(file);\n\n ctx.body = await pm.sanitizeOutput(signedFile, { action: ACTIONS.read });\n },\n\n async replaceFile(ctx: Context) {\n const {\n state: { userAbility, user },\n query: { id },\n request: { body, files: { files } = {} },\n } = ctx;\n\n if (typeof id !== 'string') {\n throw new errors.ValidationError('File id is required');\n }\n\n const uploadService = getService('upload');\n const { pm } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.update,\n FILE_MODEL_UID,\n id\n );\n\n if (Array.isArray(files)) {\n throw new errors.ApplicationError('Cannot replace a file with multiple ones');\n }\n\n const {\n validFiles,\n filteredBody,\n errors: validationErrors,\n } = await prepareUploadRequest(files, body, strapi);\n if (validFiles.length === 0) {\n throw new errors.ValidationError(validationErrors[0].message);\n }\n\n const data = (await validateUploadBody(filteredBody)) as { fileInfo: FileInfo };\n const replacedFile = await uploadService.replace(id, { data, file: validFiles[0] }, { user });\n\n // Regenerate AI metadata for image replacements so the alt text / caption\n // reflect the new file content. Mirrors the post-upload hook in\n // `uploadFiles`; failure is logged and swallowed to keep the replace flow\n // resilient when the AI provider is unavailable.\n const aiMetadataService = getService('aiMetadata');\n if (replacedFile?.mime?.startsWith('image/') && (await aiMetadataService.isEnabled())) {\n try {\n const metadataResults = await aiMetadataService.processFiles([replacedFile]);\n await aiMetadataService.updateFilesWithAIMetadata([replacedFile], metadataResults, user);\n } catch (error) {\n strapi.log.warn('AI metadata generation failed on replace, proceeding without it', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n // Sign file urls for private providers\n const signedFile = await getService('file').signFileUrls(replacedFile);\n\n ctx.body = await pm.sanitizeOutput(signedFile, { action: ACTIONS.read });\n },\n\n async uploadFiles(ctx: Context) {\n const {\n state: { userAbility, user },\n request: { body, files: { files } = {} },\n } = ctx;\n\n const uploadService = getService('upload');\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.create,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n const {\n validFiles,\n filteredBody,\n errors: validationErrors,\n } = await prepareUploadRequest(files, body, strapi);\n if (validFiles.length === 0) {\n throw new errors.ValidationError(validationErrors[0].message);\n }\n\n const isMultipleFiles = validFiles.length > 1;\n const data = await validateUploadBody(filteredBody, isMultipleFiles);\n\n let filesArray = validFiles;\n\n if (\n data.fileInfo &&\n Array.isArray(data.fileInfo) &&\n filesArray.length === data.fileInfo.length\n ) {\n // Reorder filesArray to match data.fileInfo order\n const alignedFilesArray = data.fileInfo\n .map((info) => {\n return filesArray.find((file) => file.originalFilename === info.name);\n })\n .filter(Boolean) as any[];\n\n filesArray = alignedFilesArray;\n }\n\n // Upload files first to get thumbnails\n const uploadedFiles = await uploadService.upload({ data, files: filesArray }, { user });\n if (uploadedFiles.some((file) => file.mime?.startsWith('image/'))) {\n await getService('metrics').trackUsage('didUploadImage');\n }\n\n const aiMetadataService = getService('aiMetadata');\n\n // AFTER upload - generate AI metadata for images\n if (await aiMetadataService.isEnabled()) {\n try {\n const metadataResults = await aiMetadataService.processFiles(uploadedFiles);\n // Update the uploaded files with AI metadata\n await aiMetadataService.updateFilesWithAIMetadata(uploadedFiles, metadataResults, user);\n } catch (error) {\n strapi.log.warn('AI metadata generation failed, proceeding without AI enhancements', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n // Sign file urls for private providers\n const signedFiles = await async.map(uploadedFiles, getService('file').signFileUrls);\n\n ctx.body = await pm.sanitizeOutput(signedFiles, { action: ACTIONS.read });\n ctx.status = 201;\n },\n\n /**\n * @experimental\n * Upload a single file and return the created File.\n *\n * Accepts one file per request (multipart `files` + `fileInfo`) and returns a\n * single `File` object. Unlike `uploadFiles`, it does **not** run AI metadata\n * generation inline — that responsibility is decoupled and will be handled by a\n * background job. Auth and permission checks mirror `POST /upload`.\n */\n async unstable_uploadFile(ctx: Context) {\n const {\n state: { userAbility, user },\n request: { body, files: { files } = {} },\n } = ctx;\n\n const uploadService = getService('upload');\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.create,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n if (_.isEmpty(files) || (!Array.isArray(files) && files.size === 0)) {\n throw new errors.ApplicationError('Files are empty');\n }\n\n // Accept a single file per request; ignore any extras defensively.\n const file = Array.isArray(files) ? files[0] : files;\n const fileName = file.originalFilename || 'unknown';\n\n // Parse the single fileInfo object from the multipart body.\n let fileInfo: UploadFileInfo = {\n name: fileName,\n caption: null,\n alternativeText: null,\n folder: null,\n };\n if (body?.fileInfo) {\n const raw = body.fileInfo;\n if (typeof raw === 'string') {\n fileInfo = JSON.parse(raw);\n } else if (Array.isArray(raw)) {\n fileInfo = (typeof raw[0] === 'string' ? JSON.parse(raw[0]) : raw[0]) as UploadFileInfo;\n } else {\n fileInfo = raw as UploadFileInfo;\n }\n }\n\n // Validate this single file using security checks.\n const { validFiles, errors: validationErrors } = await prepareUploadRequest(\n file,\n { fileInfo: JSON.stringify(fileInfo) },\n strapi\n );\n\n if (validFiles.length === 0) {\n throw new errors.ValidationError(validationErrors[0]?.message || 'Validation failed');\n }\n\n const data = await validateUploadBody({ fileInfo }, false);\n const [uploadedFile] = await uploadService.upload({ data, files: [validFiles[0]] }, { user });\n\n if (uploadedFile.mime?.startsWith('image/')) {\n await getService('metrics').trackUsage('didUploadImage');\n }\n\n // No inline AI metadata generation — intentionally decoupled for the async job.\n\n // Sign file url for private providers.\n const signedFile = await getService('file').signFileUrls(uploadedFile);\n\n ctx.body = await pm.sanitizeOutput(signedFile, { action: ACTIONS.read });\n ctx.status = 201;\n },\n\n /**\n * @experimental\n * Upload files from URLs with SSE streaming for per-file progress\n *\n * Accepts JSON body with URLs and fetches them server-side.\n * Streams Server-Sent Events as each URL is fetched and uploaded:\n * - file:fetching — when starting to fetch a URL\n * - file:uploading — when upload starts for a fetched file\n * - file:complete — when a file is successfully uploaded\n * - file:error — when a URL fetch or upload fails\n * - stream:complete — final summary with all results\n */\n async unstable_uploadFromUrls(ctx: Context) {\n const {\n state: { userAbility, user },\n request: { body },\n } = ctx;\n\n const uploadService = getService('upload');\n const fileService = getService('file');\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.create,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n // Parse and validate request body\n const { urls, folderId } = body as { urls?: string[]; folderId?: number | null };\n\n if (!urls || !Array.isArray(urls) || urls.length === 0) {\n throw new errors.ApplicationError('URLs are required');\n }\n\n if (urls.length > 20) {\n throw new errors.ApplicationError('Maximum 20 URLs allowed per request');\n }\n\n // Take manual control of the response for SSE streaming\n ctx.respond = false;\n const res = ctx.res;\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n Connection: 'keep-alive',\n });\n\n const writeSSE = (event: string, data: Record<string, unknown>) => {\n res.write(`event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`);\n };\n\n const total = urls.length;\n const uploadErrors: FileUploadError[] = [];\n const successfulFiles: any[] = [];\n\n // Create temp directory for fetched files\n const tmpWorkingDirectory = await fse.mkdtemp(path.join(os.tmpdir(), 'strapi-url-upload-'));\n const { sizeLimit } = strapi.config.get<Config>('plugin::upload');\n\n try {\n // Process each URL sequentially\n for (let i = 0; i < urls.length; i += 1) {\n const url = urls[i];\n\n writeSSE('file:fetching', { url, index: i, total });\n\n try {\n // Fetch URL to temp file\n const { file } = await fileService.fetchUrlToInputFile(\n url,\n tmpWorkingDirectory,\n sizeLimit\n );\n const fileName = file.originalFilename;\n\n writeSSE('file:uploading', {\n name: fileName,\n index: i,\n total,\n size: file.size,\n });\n\n // Validate using security checks\n const fileInfo: UploadFileInfo = {\n name: fileName,\n caption: null,\n alternativeText: null,\n folder: folderId ?? null,\n };\n\n const { validFiles, errors: validationErrors } = await prepareUploadRequest(\n file,\n { fileInfo: JSON.stringify(fileInfo) },\n strapi\n );\n\n if (validFiles.length === 0) {\n const errorMessage = validationErrors[0]?.message || 'Validation failed';\n uploadErrors.push({ name: fileName, message: errorMessage });\n writeSSE('file:error', { name: fileName, url, index: i, message: errorMessage });\n } else {\n // Upload the file\n const data = await validateUploadBody({ fileInfo }, false);\n const [uploadedFile] = await uploadService.upload(\n { data, files: [validFiles[0]] },\n { user }\n );\n\n // Sign file url\n const signedFile = await fileService.signFileUrls(uploadedFile);\n successfulFiles.push(signedFile);\n\n writeSSE('file:complete', { name: fileName, index: i, file: signedFile });\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n uploadErrors.push({ name: url, message: errorMessage });\n writeSSE('file:error', { url, index: i, message: errorMessage });\n }\n }\n\n // Track image upload metric once if any images were uploaded\n if (successfulFiles.some((file) => file.mime?.startsWith('image/'))) {\n await getService('metrics').trackUsage('didUploadImage');\n }\n\n // Send final stream summary\n writeSSE('stream:complete', {\n data: await pm.sanitizeOutput(successfulFiles, { action: ACTIONS.read }),\n errors: uploadErrors,\n });\n } finally {\n // Clean up temp directory\n await fse.remove(tmpWorkingDirectory);\n }\n\n res.end();\n },\n\n // TODO: split into multiple endpoints\n async upload(ctx: Context) {\n const {\n query: { id },\n request: { files: { files } = {} },\n } = ctx;\n\n if (_.isEmpty(files) || (!Array.isArray(files) && files.size === 0)) {\n if (id) {\n return this.updateFileInfo(ctx);\n }\n\n throw new errors.ApplicationError('Files are empty');\n }\n\n await (id ? this.replaceFile : this.uploadFiles)(ctx);\n },\n};\n"],"names":["bulkUpdateFileInfo","ctx","state","userAbility","user","request","body","updates","validateBulkUpdateBody","uploadService","getService","results","async","map","id","fileInfo","pm","findEntityAndCheckPermissions","ACTIONS","update","FILE_MODEL_UID","updated","updateFileInfo","signedFile","signFileUrls","sanitizeOutput","action","read","query","errors","ValidationError","data","validateUploadBody","file","replaceFile","files","Array","isArray","ApplicationError","validFiles","filteredBody","validationErrors","prepareUploadRequest","strapi","length","message","replacedFile","replace","aiMetadataService","mime","startsWith","isEnabled","metadataResults","processFiles","updateFilesWithAIMetadata","error","log","warn","Error","String","uploadFiles","service","createPermissionsManager","ability","create","model","isAllowed","forbidden","isMultipleFiles","filesArray","alignedFilesArray","info","find","originalFilename","name","filter","Boolean","uploadedFiles","upload","some","trackUsage","signedFiles","status","unstable_uploadFile","_","isEmpty","size","fileName","caption","alternativeText","folder","raw","JSON","parse","stringify","uploadedFile","unstable_uploadFromUrls","fileService","urls","folderId","respond","res","writeHead","Connection","writeSSE","event","write","total","uploadErrors","successfulFiles","tmpWorkingDirectory","fse","mkdtemp","path","join","os","tmpdir","sizeLimit","config","get","i","url","index","fetchUrlToInputFile","errorMessage","push","remove","end"],"mappings":"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"}
1
+ {"version":3,"file":"admin-upload.mjs","sources":["../../../server/src/controllers/admin-upload.ts"],"sourcesContent":["import os from 'os';\nimport path from 'path';\nimport fse from 'fs-extra';\nimport _ from 'lodash';\nimport { errors, async } from '@strapi/utils';\n\nimport type { Context } from 'koa';\n\nimport { getService } from '../utils';\nimport { ACTIONS, FILE_MODEL_UID } from '../constants';\nimport { validateBulkUpdateBody, validateUploadBody } from './validation/admin/upload';\nimport { findEntityAndCheckPermissions } from './utils/find-entity-and-check-permissions';\nimport { Config, FileInfo } from '../types';\nimport { prepareUploadRequest, type FileUploadError } from '../utils/mime-validation';\nimport type { UploadFileInfo } from '../../../shared/contracts/files';\n\nexport default {\n async bulkUpdateFileInfo(ctx: Context) {\n const {\n state: { userAbility, user },\n request: { body },\n } = ctx;\n\n const { updates } = await validateBulkUpdateBody(body);\n const uploadService = getService('upload');\n\n const results = await async.map(\n updates,\n async ({ id, fileInfo }: { id: number; fileInfo: FileInfo }) => {\n const { pm } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.update,\n FILE_MODEL_UID,\n id\n );\n\n const updated = await uploadService.updateFileInfo(id, fileInfo as any, { user });\n\n // Sign file urls for private providers\n const signedFile = await getService('file').signFileUrls(updated);\n\n return pm.sanitizeOutput(signedFile, { action: ACTIONS.read });\n }\n );\n\n ctx.body = results;\n },\n\n async updateFileInfo(ctx: Context) {\n const {\n state: { userAbility, user },\n query: { id },\n request: { body },\n } = ctx;\n\n if (typeof id !== 'string') {\n throw new errors.ValidationError('File id is required');\n }\n\n const uploadService = getService('upload');\n const { pm } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.update,\n FILE_MODEL_UID,\n id\n );\n\n const data = await validateUploadBody(body);\n\n const file = await uploadService.updateFileInfo(id, data.fileInfo as any, { user });\n\n // Sign file urls for private providers\n const signedFile = await getService('file').signFileUrls(file);\n\n ctx.body = await pm.sanitizeOutput(signedFile, { action: ACTIONS.read });\n },\n\n async replaceFile(ctx: Context) {\n const {\n state: { userAbility, user },\n query: { id },\n request: { body, files: { files: filesInput } = {} },\n } = ctx;\n\n if (typeof id !== 'string') {\n throw new errors.ValidationError('File id is required');\n }\n\n const uploadService = getService('upload');\n const { pm } = await findEntityAndCheckPermissions(\n userAbility,\n ACTIONS.update,\n FILE_MODEL_UID,\n id\n );\n\n if (Array.isArray(filesInput) && filesInput.length > 1) {\n throw new errors.ApplicationError('Cannot replace a file with multiple ones');\n }\n\n const files = Array.isArray(filesInput) ? filesInput[0] : filesInput;\n\n const {\n validFiles,\n filteredBody,\n errors: validationErrors,\n } = await prepareUploadRequest(files, body, strapi);\n if (validFiles.length === 0) {\n throw new errors.ValidationError(validationErrors[0].message);\n }\n\n const data = (await validateUploadBody(filteredBody)) as { fileInfo: FileInfo };\n const replacedFile = await uploadService.replace(id, { data, file: validFiles[0] }, { user });\n\n // Regenerate AI metadata for image replacements so the alt text / caption\n // reflect the new file content. Mirrors the post-upload hook in\n // `uploadFiles`; failure is logged and swallowed to keep the replace flow\n // resilient when the AI provider is unavailable.\n const aiMetadataService = getService('aiMetadata');\n if (replacedFile?.mime?.startsWith('image/') && (await aiMetadataService.isEnabled())) {\n try {\n const metadataResults = await aiMetadataService.processFiles([replacedFile]);\n await aiMetadataService.updateFilesWithAIMetadata([replacedFile], metadataResults, user);\n } catch (error) {\n strapi.log.warn('AI metadata generation failed on replace, proceeding without it', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n // Sign file urls for private providers\n const signedFile = await getService('file').signFileUrls(replacedFile);\n\n ctx.body = await pm.sanitizeOutput(signedFile, { action: ACTIONS.read });\n },\n\n async uploadFiles(ctx: Context) {\n const {\n state: { userAbility, user },\n request: { body, files: { files } = {} },\n } = ctx;\n\n const uploadService = getService('upload');\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.create,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n const {\n validFiles,\n filteredBody,\n errors: validationErrors,\n } = await prepareUploadRequest(files, body, strapi);\n if (validFiles.length === 0) {\n throw new errors.ValidationError(validationErrors[0].message);\n }\n\n const isMultipleFiles = validFiles.length > 1;\n const data = await validateUploadBody(filteredBody, isMultipleFiles);\n\n let filesArray = validFiles;\n\n if (\n data.fileInfo &&\n Array.isArray(data.fileInfo) &&\n filesArray.length === data.fileInfo.length\n ) {\n // Reorder filesArray to match data.fileInfo order\n const alignedFilesArray = data.fileInfo\n .map((info) => {\n return filesArray.find((file) => file.originalFilename === info.name);\n })\n .filter(Boolean) as any[];\n\n filesArray = alignedFilesArray;\n }\n\n // Upload files first to get thumbnails\n const uploadedFiles = await uploadService.upload({ data, files: filesArray }, { user });\n if (uploadedFiles.some((file) => file.mime?.startsWith('image/'))) {\n await getService('metrics').trackUsage('didUploadImage');\n }\n\n const aiMetadataService = getService('aiMetadata');\n\n // AFTER upload - generate AI metadata for images\n if (await aiMetadataService.isEnabled()) {\n try {\n const metadataResults = await aiMetadataService.processFiles(uploadedFiles);\n // Update the uploaded files with AI metadata\n await aiMetadataService.updateFilesWithAIMetadata(uploadedFiles, metadataResults, user);\n } catch (error) {\n strapi.log.warn('AI metadata generation failed, proceeding without AI enhancements', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n // Sign file urls for private providers\n const signedFiles = await async.map(uploadedFiles, getService('file').signFileUrls);\n\n ctx.body = await pm.sanitizeOutput(signedFiles, { action: ACTIONS.read });\n ctx.status = 201;\n },\n\n /**\n * @experimental\n * Upload a single file and return the created File.\n *\n * Accepts one file per request (multipart `files` + `fileInfo`) and returns a\n * single `File` object. Unlike `uploadFiles`, it does **not** run AI metadata\n * generation inline — that responsibility is decoupled and will be handled by a\n * background job. Auth and permission checks mirror `POST /upload`.\n */\n async unstable_uploadFile(ctx: Context) {\n const {\n state: { userAbility, user },\n request: { body, files: { files } = {} },\n } = ctx;\n\n const uploadService = getService('upload');\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.create,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n if (_.isEmpty(files) || (!Array.isArray(files) && files.size === 0)) {\n throw new errors.ApplicationError('Files are empty');\n }\n\n // Accept a single file per request; ignore any extras defensively.\n const file = Array.isArray(files) ? files[0] : files;\n const fileName = file.originalFilename || 'unknown';\n\n // Parse the single fileInfo object from the multipart body.\n let fileInfo: UploadFileInfo = {\n name: fileName,\n caption: null,\n alternativeText: null,\n folder: null,\n };\n if (body?.fileInfo) {\n const raw = body.fileInfo;\n if (typeof raw === 'string') {\n fileInfo = JSON.parse(raw);\n } else if (Array.isArray(raw)) {\n fileInfo = (typeof raw[0] === 'string' ? JSON.parse(raw[0]) : raw[0]) as UploadFileInfo;\n } else {\n fileInfo = raw as UploadFileInfo;\n }\n }\n\n // Validate this single file using security checks.\n const { validFiles, errors: validationErrors } = await prepareUploadRequest(\n file,\n { fileInfo: JSON.stringify(fileInfo) },\n strapi\n );\n\n if (validFiles.length === 0) {\n throw new errors.ValidationError(validationErrors[0]?.message || 'Validation failed');\n }\n\n const data = await validateUploadBody({ fileInfo }, false);\n const [uploadedFile] = await uploadService.upload({ data, files: [validFiles[0]] }, { user });\n\n if (uploadedFile.mime?.startsWith('image/')) {\n await getService('metrics').trackUsage('didUploadImage');\n }\n\n // No inline AI metadata generation — intentionally decoupled for the async job.\n\n // Sign file url for private providers.\n const signedFile = await getService('file').signFileUrls(uploadedFile);\n\n ctx.body = await pm.sanitizeOutput(signedFile, { action: ACTIONS.read });\n ctx.status = 201;\n },\n\n /**\n * @experimental\n * Upload files from URLs with SSE streaming for per-file progress\n *\n * Accepts JSON body with URLs and fetches them server-side.\n * Streams Server-Sent Events as each URL is fetched and uploaded:\n * - file:fetching — when starting to fetch a URL\n * - file:uploading — when upload starts for a fetched file\n * - file:complete — when a file is successfully uploaded\n * - file:error — when a URL fetch or upload fails\n * - stream:complete — final summary with all results\n */\n async unstable_uploadFromUrls(ctx: Context) {\n const {\n state: { userAbility, user },\n request: { body },\n } = ctx;\n\n const uploadService = getService('upload');\n const fileService = getService('file');\n const pm = strapi.service('admin::permission').createPermissionsManager({\n ability: userAbility,\n action: ACTIONS.create,\n model: FILE_MODEL_UID,\n });\n\n if (!pm.isAllowed) {\n return ctx.forbidden();\n }\n\n // Parse and validate request body\n const { urls, folderId } = body as { urls?: string[]; folderId?: number | null };\n\n if (!urls || !Array.isArray(urls) || urls.length === 0) {\n throw new errors.ApplicationError('URLs are required');\n }\n\n if (urls.length > 20) {\n throw new errors.ApplicationError('Maximum 20 URLs allowed per request');\n }\n\n // Take manual control of the response for SSE streaming\n ctx.respond = false;\n const res = ctx.res;\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n Connection: 'keep-alive',\n });\n\n const writeSSE = (event: string, data: Record<string, unknown>) => {\n res.write(`event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`);\n };\n\n const total = urls.length;\n const uploadErrors: FileUploadError[] = [];\n const successfulFiles: any[] = [];\n\n // Create temp directory for fetched files\n const tmpWorkingDirectory = await fse.mkdtemp(path.join(os.tmpdir(), 'strapi-url-upload-'));\n const { sizeLimit } = strapi.config.get<Config>('plugin::upload');\n\n try {\n // Process each URL sequentially\n for (let i = 0; i < urls.length; i += 1) {\n const url = urls[i];\n\n writeSSE('file:fetching', { url, index: i, total });\n\n try {\n // Fetch URL to temp file\n const { file } = await fileService.fetchUrlToInputFile(\n url,\n tmpWorkingDirectory,\n sizeLimit\n );\n const fileName = file.originalFilename;\n\n writeSSE('file:uploading', {\n name: fileName,\n index: i,\n total,\n size: file.size,\n });\n\n // Validate using security checks\n const fileInfo: UploadFileInfo = {\n name: fileName,\n caption: null,\n alternativeText: null,\n folder: folderId ?? null,\n };\n\n const { validFiles, errors: validationErrors } = await prepareUploadRequest(\n file,\n { fileInfo: JSON.stringify(fileInfo) },\n strapi\n );\n\n if (validFiles.length === 0) {\n const errorMessage = validationErrors[0]?.message || 'Validation failed';\n uploadErrors.push({ name: fileName, message: errorMessage });\n writeSSE('file:error', { name: fileName, url, index: i, message: errorMessage });\n } else {\n // Upload the file\n const data = await validateUploadBody({ fileInfo }, false);\n const [uploadedFile] = await uploadService.upload(\n { data, files: [validFiles[0]] },\n { user }\n );\n\n // Sign file url\n const signedFile = await fileService.signFileUrls(uploadedFile);\n successfulFiles.push(signedFile);\n\n writeSSE('file:complete', { name: fileName, index: i, file: signedFile });\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n uploadErrors.push({ name: url, message: errorMessage });\n writeSSE('file:error', { url, index: i, message: errorMessage });\n }\n }\n\n // Track image upload metric once if any images were uploaded\n if (successfulFiles.some((file) => file.mime?.startsWith('image/'))) {\n await getService('metrics').trackUsage('didUploadImage');\n }\n\n // Send final stream summary\n writeSSE('stream:complete', {\n data: await pm.sanitizeOutput(successfulFiles, { action: ACTIONS.read }),\n errors: uploadErrors,\n });\n } finally {\n // Clean up temp directory\n await fse.remove(tmpWorkingDirectory);\n }\n\n res.end();\n },\n\n // TODO: split into multiple endpoints\n async upload(ctx: Context) {\n const {\n query: { id },\n request: { files: { files } = {} },\n } = ctx;\n\n if (_.isEmpty(files) || (!Array.isArray(files) && files.size === 0)) {\n if (id) {\n return this.updateFileInfo(ctx);\n }\n\n throw new errors.ApplicationError('Files are empty');\n }\n\n await (id ? this.replaceFile : this.uploadFiles)(ctx);\n },\n};\n"],"names":["bulkUpdateFileInfo","ctx","state","userAbility","user","request","body","updates","validateBulkUpdateBody","uploadService","getService","results","async","map","id","fileInfo","pm","findEntityAndCheckPermissions","ACTIONS","update","FILE_MODEL_UID","updated","updateFileInfo","signedFile","signFileUrls","sanitizeOutput","action","read","query","errors","ValidationError","data","validateUploadBody","file","replaceFile","files","filesInput","Array","isArray","length","ApplicationError","validFiles","filteredBody","validationErrors","prepareUploadRequest","strapi","message","replacedFile","replace","aiMetadataService","mime","startsWith","isEnabled","metadataResults","processFiles","updateFilesWithAIMetadata","error","log","warn","Error","String","uploadFiles","service","createPermissionsManager","ability","create","model","isAllowed","forbidden","isMultipleFiles","filesArray","alignedFilesArray","info","find","originalFilename","name","filter","Boolean","uploadedFiles","upload","some","trackUsage","signedFiles","status","unstable_uploadFile","_","isEmpty","size","fileName","caption","alternativeText","folder","raw","JSON","parse","stringify","uploadedFile","unstable_uploadFromUrls","fileService","urls","folderId","respond","res","writeHead","Connection","writeSSE","event","write","total","uploadErrors","successfulFiles","tmpWorkingDirectory","fse","mkdtemp","path","join","os","tmpdir","sizeLimit","config","get","i","url","index","fetchUrlToInputFile","errorMessage","push","remove","end"],"mappings":"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"}
@@ -90,14 +90,15 @@ var contentApi = (({ strapi })=>{
90
90
  },
91
91
  async replaceFile (ctx) {
92
92
  const { query: { id }, request: { body, files: { files: filesInput } = {} } } = ctx;
93
- const { validFiles, filteredBody, errors: validationErrors } = await mimeValidation.prepareUploadRequest(filesInput, body, strapi);
94
- if (validFiles.length === 0) {
95
- throw new utils.errors.ValidationError(validationErrors[0].message);
96
- }
97
93
  // cannot replace with more than one file
98
- if (Array.isArray(filesInput)) {
94
+ if (Array.isArray(filesInput) && filesInput.length > 1) {
99
95
  throw new ValidationError('Cannot replace a file with multiple ones');
100
96
  }
97
+ const files = Array.isArray(filesInput) ? filesInput[0] : filesInput;
98
+ const { validFiles, filteredBody, errors: validationErrors } = await mimeValidation.prepareUploadRequest(files, body, strapi);
99
+ if (validFiles.length === 0) {
100
+ throw new utils.errors.ValidationError(validationErrors[0].message);
101
+ }
101
102
  if (!id || typeof id !== 'string' && typeof id !== 'number') {
102
103
  throw new ValidationError('File id is required and must be a single value');
103
104
  }