@strapi/upload 5.47.0 → 5.48.0

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 (126) hide show
  1. package/dist/admin/components/EditAssetDialog/EditAssetContent.js +12 -2
  2. package/dist/admin/components/EditAssetDialog/EditAssetContent.js.map +1 -1
  3. package/dist/admin/components/EditAssetDialog/EditAssetContent.mjs +12 -2
  4. package/dist/admin/components/EditAssetDialog/EditAssetContent.mjs.map +1 -1
  5. package/dist/admin/components/UploadAssetDialog/UploadAssetDialog.js +1 -0
  6. package/dist/admin/components/UploadAssetDialog/UploadAssetDialog.js.map +1 -1
  7. package/dist/admin/components/UploadAssetDialog/UploadAssetDialog.mjs +1 -0
  8. package/dist/admin/components/UploadAssetDialog/UploadAssetDialog.mjs.map +1 -1
  9. package/dist/admin/future/components/Drawer.js +7 -2
  10. package/dist/admin/future/components/Drawer.js.map +1 -1
  11. package/dist/admin/future/components/Drawer.mjs +7 -2
  12. package/dist/admin/future/components/Drawer.mjs.map +1 -1
  13. package/dist/admin/future/components/UploadProgressDialog.js +33 -29
  14. package/dist/admin/future/components/UploadProgressDialog.js.map +1 -1
  15. package/dist/admin/future/components/UploadProgressDialog.mjs +36 -32
  16. package/dist/admin/future/components/UploadProgressDialog.mjs.map +1 -1
  17. package/dist/admin/future/pages/Assets/AssetsPage.js +2 -2
  18. package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -1
  19. package/dist/admin/future/pages/Assets/AssetsPage.mjs +3 -3
  20. package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -1
  21. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js +733 -148
  22. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.js.map +1 -1
  23. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs +737 -155
  24. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.mjs.map +1 -1
  25. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetPreview.js +25 -5
  26. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetPreview.js.map +1 -1
  27. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetPreview.mjs +25 -5
  28. package/dist/admin/future/pages/Assets/components/AssetDetails/AssetPreview.mjs.map +1 -1
  29. package/dist/admin/future/services/api.js +124 -200
  30. package/dist/admin/future/services/api.js.map +1 -1
  31. package/dist/admin/future/services/api.mjs +124 -200
  32. package/dist/admin/future/services/api.mjs.map +1 -1
  33. package/dist/admin/future/services/assets.js +88 -1
  34. package/dist/admin/future/services/assets.js.map +1 -1
  35. package/dist/admin/future/services/assets.mjs +86 -2
  36. package/dist/admin/future/services/assets.mjs.map +1 -1
  37. package/dist/admin/future/services/folders.js +33 -1
  38. package/dist/admin/future/services/folders.js.map +1 -1
  39. package/dist/admin/future/services/folders.mjs +33 -2
  40. package/dist/admin/future/services/folders.mjs.map +1 -1
  41. package/dist/admin/future/services/settings.js +18 -0
  42. package/dist/admin/future/services/settings.js.map +1 -0
  43. package/dist/admin/future/services/settings.mjs +16 -0
  44. package/dist/admin/future/services/settings.mjs.map +1 -0
  45. package/dist/admin/future/services/uploadFileViaXHR.js +92 -0
  46. package/dist/admin/future/services/uploadFileViaXHR.js.map +1 -0
  47. package/dist/admin/future/services/uploadFileViaXHR.mjs +88 -0
  48. package/dist/admin/future/services/uploadFileViaXHR.mjs.map +1 -0
  49. package/dist/admin/future/store/uploadProgress.js +32 -26
  50. package/dist/admin/future/store/uploadProgress.js.map +1 -1
  51. package/dist/admin/future/store/uploadProgress.mjs +32 -27
  52. package/dist/admin/future/store/uploadProgress.mjs.map +1 -1
  53. package/dist/admin/future/utils/createRafBatcher.js +42 -0
  54. package/dist/admin/future/utils/createRafBatcher.js.map +1 -0
  55. package/dist/admin/future/utils/createRafBatcher.mjs +40 -0
  56. package/dist/admin/future/utils/createRafBatcher.mjs.map +1 -0
  57. package/dist/admin/future/utils/downloadFile.js +19 -0
  58. package/dist/admin/future/utils/downloadFile.js.map +1 -0
  59. package/dist/admin/future/utils/downloadFile.mjs +17 -0
  60. package/dist/admin/future/utils/downloadFile.mjs.map +1 -0
  61. package/dist/admin/hooks/useAssets.js +5 -3
  62. package/dist/admin/hooks/useAssets.js.map +1 -1
  63. package/dist/admin/hooks/useAssets.mjs +5 -3
  64. package/dist/admin/hooks/useAssets.mjs.map +1 -1
  65. package/dist/admin/index.js +1 -1
  66. package/dist/admin/index.mjs +1 -1
  67. package/dist/admin/src/components/EditAssetDialog/EditAssetContent.d.ts +2 -1
  68. package/dist/admin/src/future/pages/Assets/components/AssetDetails/AssetDetailsDrawer.d.ts +22 -0
  69. package/dist/admin/src/future/pages/Assets/components/AssetDetails/AssetPreview.d.ts +4 -1
  70. package/dist/admin/src/future/services/api.d.ts +9 -8
  71. package/dist/admin/src/future/services/assets.d.ts +11 -2
  72. package/dist/admin/src/future/services/folders.d.ts +1 -1
  73. package/dist/admin/src/future/services/uploadFileViaXHR.d.ts +34 -0
  74. package/dist/admin/src/future/store/uploadProgress.d.ts +17 -4
  75. package/dist/admin/src/future/utils/createRafBatcher.d.ts +23 -0
  76. package/dist/admin/src/future/utils/downloadFile.d.ts +6 -0
  77. package/dist/admin/translations/{dk.json.js → da.json.js} +3 -3
  78. package/dist/admin/translations/{dk.json.js.map → da.json.js.map} +1 -1
  79. package/dist/admin/translations/{dk.json.mjs → da.json.mjs} +3 -3
  80. package/dist/admin/translations/{dk.json.mjs.map → da.json.mjs.map} +1 -1
  81. package/dist/admin/translations/en.json.js +26 -1
  82. package/dist/admin/translations/en.json.js.map +1 -1
  83. package/dist/admin/translations/en.json.mjs +26 -1
  84. package/dist/admin/translations/en.json.mjs.map +1 -1
  85. package/dist/server/bootstrap.js +0 -3
  86. package/dist/server/bootstrap.js.map +1 -1
  87. package/dist/server/bootstrap.mjs +0 -3
  88. package/dist/server/bootstrap.mjs.map +1 -1
  89. package/dist/server/controllers/admin-upload.js +69 -118
  90. package/dist/server/controllers/admin-upload.js.map +1 -1
  91. package/dist/server/controllers/admin-upload.mjs +69 -118
  92. package/dist/server/controllers/admin-upload.mjs.map +1 -1
  93. package/dist/server/routes/admin.js +2 -2
  94. package/dist/server/routes/admin.js.map +1 -1
  95. package/dist/server/routes/admin.mjs +2 -2
  96. package/dist/server/routes/admin.mjs.map +1 -1
  97. package/dist/server/services/ai-metadata-jobs.js +0 -23
  98. package/dist/server/services/ai-metadata-jobs.js.map +1 -1
  99. package/dist/server/services/ai-metadata-jobs.mjs +0 -23
  100. package/dist/server/services/ai-metadata-jobs.mjs.map +1 -1
  101. package/dist/server/services/image-manipulation.js +16 -8
  102. package/dist/server/services/image-manipulation.js.map +1 -1
  103. package/dist/server/services/image-manipulation.mjs +16 -8
  104. package/dist/server/services/image-manipulation.mjs.map +1 -1
  105. package/dist/server/services/upload.js +1 -1
  106. package/dist/server/services/upload.js.map +1 -1
  107. package/dist/server/services/upload.mjs +1 -1
  108. package/dist/server/services/upload.mjs.map +1 -1
  109. package/dist/server/src/bootstrap.d.ts.map +1 -1
  110. package/dist/server/src/controllers/admin-upload.d.ts +6 -8
  111. package/dist/server/src/controllers/admin-upload.d.ts.map +1 -1
  112. package/dist/server/src/controllers/index.d.ts +1 -1
  113. package/dist/server/src/index.d.ts +1 -2
  114. package/dist/server/src/index.d.ts.map +1 -1
  115. package/dist/server/src/services/ai-metadata-jobs.d.ts +0 -1
  116. package/dist/server/src/services/ai-metadata-jobs.d.ts.map +1 -1
  117. package/dist/server/src/services/image-manipulation.d.ts +5 -0
  118. package/dist/server/src/services/image-manipulation.d.ts.map +1 -1
  119. package/dist/server/src/services/index.d.ts +0 -1
  120. package/dist/server/src/services/index.d.ts.map +1 -1
  121. package/dist/server/src/services/upload.d.ts.map +1 -1
  122. package/dist/server/src/types.d.ts +2 -2
  123. package/dist/server/src/types.d.ts.map +1 -1
  124. package/dist/shared/contracts/files.d.ts +19 -2
  125. package/dist/shared/contracts/files.d.ts.map +1 -1
  126. package/package.json +8 -8
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.js","sources":["../../server/src/bootstrap.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\nimport { getService } from './utils';\nimport { ALLOWED_SORT_STRINGS, ALLOWED_WEBHOOK_EVENTS } from './constants';\n\nexport async function bootstrap({ strapi }: { strapi: Core.Strapi }) {\n const defaultConfig = {\n settings: {\n sizeOptimization: true,\n responsiveDimensions: true,\n autoOrientation: false,\n aiMetadata: true,\n },\n view_configuration: {\n pageSize: 10,\n sort: ALLOWED_SORT_STRINGS[0],\n },\n };\n\n for (const [key, defaultValue] of Object.entries(defaultConfig)) {\n // set plugin store\n const configurator = strapi.store!({ type: 'plugin', name: 'upload', key });\n\n const config = await configurator.get({});\n if (\n config &&\n Object.keys(defaultValue).every((key) => Object.prototype.hasOwnProperty.call(config, key))\n ) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n // if the config does not exist or does not have all the required keys\n // set from the defaultValue ensuring all required settings are present\n await configurator.set({\n value: Object.assign(defaultValue, config || {}),\n });\n }\n\n await registerPermissionActions();\n await registerWebhookEvents();\n\n await getService('weeklyMetrics').registerCron();\n if (strapi.ai.admin.isEnabled() === true) {\n await getService('aiMetadataJobs').registerCron();\n }\n\n getService('metrics').sendUploadPluginMetrics();\n\n getService('extensions').signFileUrlsOnDocumentService();\n}\n\nconst registerWebhookEvents = async () =>\n Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {\n strapi.get('webhookStore').addAllowedEvent(key, value);\n });\n\nconst registerPermissionActions = async () => {\n const actions = [\n {\n section: 'plugins',\n displayName: 'Access the Media Library',\n uid: 'read',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Create (upload)',\n uid: 'assets.create',\n subCategory: 'assets',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Update (crop, details, replace) + delete',\n uid: 'assets.update',\n subCategory: 'assets',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Download',\n uid: 'assets.download',\n subCategory: 'assets',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Copy link',\n uid: 'assets.copy-link',\n subCategory: 'assets',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Configure view',\n uid: 'configure-view',\n pluginName: 'upload',\n },\n {\n section: 'settings',\n displayName: 'Access the Media Library settings page',\n uid: 'settings.read',\n category: 'media library',\n pluginName: 'upload',\n },\n ];\n\n await strapi.service('admin::permission').actionProvider.registerMany(actions);\n};\n"],"names":["bootstrap","strapi","defaultConfig","settings","sizeOptimization","responsiveDimensions","autoOrientation","aiMetadata","view_configuration","pageSize","sort","ALLOWED_SORT_STRINGS","key","defaultValue","Object","entries","configurator","store","type","name","config","get","keys","every","prototype","hasOwnProperty","call","set","value","assign","registerPermissionActions","registerWebhookEvents","getService","registerCron","ai","admin","isEnabled","sendUploadPluginMetrics","signFileUrlsOnDocumentService","ALLOWED_WEBHOOK_EVENTS","forEach","addAllowedEvent","actions","section","displayName","uid","pluginName","subCategory","category","service","actionProvider","registerMany"],"mappings":"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"}
1
+ {"version":3,"file":"bootstrap.js","sources":["../../server/src/bootstrap.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\nimport { getService } from './utils';\nimport { ALLOWED_SORT_STRINGS, ALLOWED_WEBHOOK_EVENTS } from './constants';\n\nexport async function bootstrap({ strapi }: { strapi: Core.Strapi }) {\n const defaultConfig = {\n settings: {\n sizeOptimization: true,\n responsiveDimensions: true,\n autoOrientation: false,\n aiMetadata: true,\n },\n view_configuration: {\n pageSize: 10,\n sort: ALLOWED_SORT_STRINGS[0],\n },\n };\n\n for (const [key, defaultValue] of Object.entries(defaultConfig)) {\n // set plugin store\n const configurator = strapi.store!({ type: 'plugin', name: 'upload', key });\n\n const config = await configurator.get({});\n if (\n config &&\n Object.keys(defaultValue).every((key) => Object.prototype.hasOwnProperty.call(config, key))\n ) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n // if the config does not exist or does not have all the required keys\n // set from the defaultValue ensuring all required settings are present\n await configurator.set({\n value: Object.assign(defaultValue, config || {}),\n });\n }\n\n await registerPermissionActions();\n await registerWebhookEvents();\n\n await getService('weeklyMetrics').registerCron();\n\n getService('metrics').sendUploadPluginMetrics();\n\n getService('extensions').signFileUrlsOnDocumentService();\n}\n\nconst registerWebhookEvents = async () =>\n Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {\n strapi.get('webhookStore').addAllowedEvent(key, value);\n });\n\nconst registerPermissionActions = async () => {\n const actions = [\n {\n section: 'plugins',\n displayName: 'Access the Media Library',\n uid: 'read',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Create (upload)',\n uid: 'assets.create',\n subCategory: 'assets',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Update (crop, details, replace) + delete',\n uid: 'assets.update',\n subCategory: 'assets',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Download',\n uid: 'assets.download',\n subCategory: 'assets',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Copy link',\n uid: 'assets.copy-link',\n subCategory: 'assets',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Configure view',\n uid: 'configure-view',\n pluginName: 'upload',\n },\n {\n section: 'settings',\n displayName: 'Access the Media Library settings page',\n uid: 'settings.read',\n category: 'media library',\n pluginName: 'upload',\n },\n ];\n\n await strapi.service('admin::permission').actionProvider.registerMany(actions);\n};\n"],"names":["bootstrap","strapi","defaultConfig","settings","sizeOptimization","responsiveDimensions","autoOrientation","aiMetadata","view_configuration","pageSize","sort","ALLOWED_SORT_STRINGS","key","defaultValue","Object","entries","configurator","store","type","name","config","get","keys","every","prototype","hasOwnProperty","call","set","value","assign","registerPermissionActions","registerWebhookEvents","getService","registerCron","sendUploadPluginMetrics","signFileUrlsOnDocumentService","ALLOWED_WEBHOOK_EVENTS","forEach","addAllowedEvent","actions","section","displayName","uid","pluginName","subCategory","category","service","actionProvider","registerMany"],"mappings":";;;;;AAKO,eAAeA,SAAAA,CAAU,EAAEC,MAAAA,EAAAA,OAAM,EAA2B,EAAA;AACjE,IAAA,MAAMC,aAAAA,GAAgB;QACpBC,QAAAA,EAAU;YACRC,gBAAAA,EAAkB,IAAA;YAClBC,oBAAAA,EAAsB,IAAA;YACtBC,eAAAA,EAAiB,KAAA;YACjBC,UAAAA,EAAY;AACd,SAAA;QACAC,kBAAAA,EAAoB;YAClBC,QAAAA,EAAU,EAAA;YACVC,IAAAA,EAAMC,8BAAoB,CAAC,CAAA;AAC7B;AACF,KAAA;IAEA,KAAK,MAAM,CAACC,GAAAA,EAAKC,YAAAA,CAAa,IAAIC,MAAAA,CAAOC,OAAO,CAACb,aAAAA,CAAAA,CAAgB;;QAE/D,MAAMc,YAAAA,GAAef,OAAAA,CAAOgB,KAAK,CAAE;YAAEC,IAAAA,EAAM,QAAA;YAAUC,IAAAA,EAAM,QAAA;AAAUP,YAAAA;AAAI,SAAA,CAAA;AAEzE,QAAA,MAAMQ,MAAAA,GAAS,MAAMJ,YAAAA,CAAaK,GAAG,CAAC,EAAC,CAAA;AACvC,QAAA,IACED,UACAN,MAAAA,CAAOQ,IAAI,CAACT,YAAAA,CAAAA,CAAcU,KAAK,CAAC,CAACX,GAAAA,GAAQE,MAAAA,CAAOU,SAAS,CAACC,cAAc,CAACC,IAAI,CAACN,QAAQR,GAAAA,CAAAA,CAAAA,EACtF;AAEA,YAAA;AACF,QAAA;;;QAIA,MAAMI,YAAAA,CAAaW,GAAG,CAAC;AACrBC,YAAAA,KAAAA,EAAOd,MAAAA,CAAOe,MAAM,CAAChB,YAAAA,EAAcO,UAAU,EAAC;AAChD,SAAA,CAAA;AACF,IAAA;IAEA,MAAMU,yBAAAA,EAAAA;IACN,MAAMC,qBAAAA,EAAAA;IAEN,MAAMC,gBAAAA,CAAW,iBAAiBC,YAAY,EAAA;AAE9CD,IAAAA,gBAAAA,CAAW,WAAWE,uBAAuB,EAAA;AAE7CF,IAAAA,gBAAAA,CAAW,cAAcG,6BAA6B,EAAA;AACxD;AAEA,MAAMJ,qBAAAA,GAAwB,UAC5BjB,MAAAA,CAAOC,OAAO,CAACqB,gCAAAA,CAAAA,CAAwBC,OAAO,CAAC,CAAC,CAACzB,GAAAA,EAAKgB,KAAAA,CAAM,GAAA;AAC1D3B,QAAAA,MAAAA,CAAOoB,GAAG,CAAC,cAAA,CAAA,CAAgBiB,eAAe,CAAC1B,GAAAA,EAAKgB,KAAAA,CAAAA;AAClD,IAAA,CAAA,CAAA;AAEF,MAAME,yBAAAA,GAA4B,UAAA;AAChC,IAAA,MAAMS,OAAAA,GAAU;AACd,QAAA;YACEC,OAAAA,EAAS,SAAA;YACTC,WAAAA,EAAa,0BAAA;YACbC,GAAAA,EAAK,MAAA;YACLC,UAAAA,EAAY;AACd,SAAA;AACA,QAAA;YACEH,OAAAA,EAAS,SAAA;YACTC,WAAAA,EAAa,iBAAA;YACbC,GAAAA,EAAK,eAAA;YACLE,WAAAA,EAAa,QAAA;YACbD,UAAAA,EAAY;AACd,SAAA;AACA,QAAA;YACEH,OAAAA,EAAS,SAAA;YACTC,WAAAA,EAAa,0CAAA;YACbC,GAAAA,EAAK,eAAA;YACLE,WAAAA,EAAa,QAAA;YACbD,UAAAA,EAAY;AACd,SAAA;AACA,QAAA;YACEH,OAAAA,EAAS,SAAA;YACTC,WAAAA,EAAa,UAAA;YACbC,GAAAA,EAAK,iBAAA;YACLE,WAAAA,EAAa,QAAA;YACbD,UAAAA,EAAY;AACd,SAAA;AACA,QAAA;YACEH,OAAAA,EAAS,SAAA;YACTC,WAAAA,EAAa,WAAA;YACbC,GAAAA,EAAK,kBAAA;YACLE,WAAAA,EAAa,QAAA;YACbD,UAAAA,EAAY;AACd,SAAA;AACA,QAAA;YACEH,OAAAA,EAAS,SAAA;YACTC,WAAAA,EAAa,gBAAA;YACbC,GAAAA,EAAK,gBAAA;YACLC,UAAAA,EAAY;AACd,SAAA;AACA,QAAA;YACEH,OAAAA,EAAS,UAAA;YACTC,WAAAA,EAAa,wCAAA;YACbC,GAAAA,EAAK,eAAA;YACLG,QAAAA,EAAU,eAAA;YACVF,UAAAA,EAAY;AACd;AACD,KAAA;AAED,IAAA,MAAM1C,OAAO6C,OAAO,CAAC,qBAAqBC,cAAc,CAACC,YAAY,CAACT,OAAAA,CAAAA;AACxE,CAAA;;;;"}
@@ -34,9 +34,6 @@ async function bootstrap({ strapi: strapi1 }) {
34
34
  await registerPermissionActions();
35
35
  await registerWebhookEvents();
36
36
  await getService('weeklyMetrics').registerCron();
37
- if (strapi1.ai.admin.isEnabled() === true) {
38
- await getService('aiMetadataJobs').registerCron();
39
- }
40
37
  getService('metrics').sendUploadPluginMetrics();
41
38
  getService('extensions').signFileUrlsOnDocumentService();
42
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.mjs","sources":["../../server/src/bootstrap.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\nimport { getService } from './utils';\nimport { ALLOWED_SORT_STRINGS, ALLOWED_WEBHOOK_EVENTS } from './constants';\n\nexport async function bootstrap({ strapi }: { strapi: Core.Strapi }) {\n const defaultConfig = {\n settings: {\n sizeOptimization: true,\n responsiveDimensions: true,\n autoOrientation: false,\n aiMetadata: true,\n },\n view_configuration: {\n pageSize: 10,\n sort: ALLOWED_SORT_STRINGS[0],\n },\n };\n\n for (const [key, defaultValue] of Object.entries(defaultConfig)) {\n // set plugin store\n const configurator = strapi.store!({ type: 'plugin', name: 'upload', key });\n\n const config = await configurator.get({});\n if (\n config &&\n Object.keys(defaultValue).every((key) => Object.prototype.hasOwnProperty.call(config, key))\n ) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n // if the config does not exist or does not have all the required keys\n // set from the defaultValue ensuring all required settings are present\n await configurator.set({\n value: Object.assign(defaultValue, config || {}),\n });\n }\n\n await registerPermissionActions();\n await registerWebhookEvents();\n\n await getService('weeklyMetrics').registerCron();\n if (strapi.ai.admin.isEnabled() === true) {\n await getService('aiMetadataJobs').registerCron();\n }\n\n getService('metrics').sendUploadPluginMetrics();\n\n getService('extensions').signFileUrlsOnDocumentService();\n}\n\nconst registerWebhookEvents = async () =>\n Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {\n strapi.get('webhookStore').addAllowedEvent(key, value);\n });\n\nconst registerPermissionActions = async () => {\n const actions = [\n {\n section: 'plugins',\n displayName: 'Access the Media Library',\n uid: 'read',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Create (upload)',\n uid: 'assets.create',\n subCategory: 'assets',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Update (crop, details, replace) + delete',\n uid: 'assets.update',\n subCategory: 'assets',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Download',\n uid: 'assets.download',\n subCategory: 'assets',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Copy link',\n uid: 'assets.copy-link',\n subCategory: 'assets',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Configure view',\n uid: 'configure-view',\n pluginName: 'upload',\n },\n {\n section: 'settings',\n displayName: 'Access the Media Library settings page',\n uid: 'settings.read',\n category: 'media library',\n pluginName: 'upload',\n },\n ];\n\n await strapi.service('admin::permission').actionProvider.registerMany(actions);\n};\n"],"names":["bootstrap","strapi","defaultConfig","settings","sizeOptimization","responsiveDimensions","autoOrientation","aiMetadata","view_configuration","pageSize","sort","ALLOWED_SORT_STRINGS","key","defaultValue","Object","entries","configurator","store","type","name","config","get","keys","every","prototype","hasOwnProperty","call","set","value","assign","registerPermissionActions","registerWebhookEvents","getService","registerCron","ai","admin","isEnabled","sendUploadPluginMetrics","signFileUrlsOnDocumentService","ALLOWED_WEBHOOK_EVENTS","forEach","addAllowedEvent","actions","section","displayName","uid","pluginName","subCategory","category","service","actionProvider","registerMany"],"mappings":"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"}
1
+ {"version":3,"file":"bootstrap.mjs","sources":["../../server/src/bootstrap.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\n\nimport { getService } from './utils';\nimport { ALLOWED_SORT_STRINGS, ALLOWED_WEBHOOK_EVENTS } from './constants';\n\nexport async function bootstrap({ strapi }: { strapi: Core.Strapi }) {\n const defaultConfig = {\n settings: {\n sizeOptimization: true,\n responsiveDimensions: true,\n autoOrientation: false,\n aiMetadata: true,\n },\n view_configuration: {\n pageSize: 10,\n sort: ALLOWED_SORT_STRINGS[0],\n },\n };\n\n for (const [key, defaultValue] of Object.entries(defaultConfig)) {\n // set plugin store\n const configurator = strapi.store!({ type: 'plugin', name: 'upload', key });\n\n const config = await configurator.get({});\n if (\n config &&\n Object.keys(defaultValue).every((key) => Object.prototype.hasOwnProperty.call(config, key))\n ) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n // if the config does not exist or does not have all the required keys\n // set from the defaultValue ensuring all required settings are present\n await configurator.set({\n value: Object.assign(defaultValue, config || {}),\n });\n }\n\n await registerPermissionActions();\n await registerWebhookEvents();\n\n await getService('weeklyMetrics').registerCron();\n\n getService('metrics').sendUploadPluginMetrics();\n\n getService('extensions').signFileUrlsOnDocumentService();\n}\n\nconst registerWebhookEvents = async () =>\n Object.entries(ALLOWED_WEBHOOK_EVENTS).forEach(([key, value]) => {\n strapi.get('webhookStore').addAllowedEvent(key, value);\n });\n\nconst registerPermissionActions = async () => {\n const actions = [\n {\n section: 'plugins',\n displayName: 'Access the Media Library',\n uid: 'read',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Create (upload)',\n uid: 'assets.create',\n subCategory: 'assets',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Update (crop, details, replace) + delete',\n uid: 'assets.update',\n subCategory: 'assets',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Download',\n uid: 'assets.download',\n subCategory: 'assets',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Copy link',\n uid: 'assets.copy-link',\n subCategory: 'assets',\n pluginName: 'upload',\n },\n {\n section: 'plugins',\n displayName: 'Configure view',\n uid: 'configure-view',\n pluginName: 'upload',\n },\n {\n section: 'settings',\n displayName: 'Access the Media Library settings page',\n uid: 'settings.read',\n category: 'media library',\n pluginName: 'upload',\n },\n ];\n\n await strapi.service('admin::permission').actionProvider.registerMany(actions);\n};\n"],"names":["bootstrap","strapi","defaultConfig","settings","sizeOptimization","responsiveDimensions","autoOrientation","aiMetadata","view_configuration","pageSize","sort","ALLOWED_SORT_STRINGS","key","defaultValue","Object","entries","configurator","store","type","name","config","get","keys","every","prototype","hasOwnProperty","call","set","value","assign","registerPermissionActions","registerWebhookEvents","getService","registerCron","sendUploadPluginMetrics","signFileUrlsOnDocumentService","ALLOWED_WEBHOOK_EVENTS","forEach","addAllowedEvent","actions","section","displayName","uid","pluginName","subCategory","category","service","actionProvider","registerMany"],"mappings":"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"}
@@ -21,7 +21,9 @@ var adminUpload = {
21
21
  const updated = await uploadService.updateFileInfo(id, fileInfo, {
22
22
  user
23
23
  });
24
- return pm.sanitizeOutput(updated, {
24
+ // Sign file urls for private providers
25
+ const signedFile = await index.getService('file').signFileUrls(updated);
26
+ return pm.sanitizeOutput(signedFile, {
25
27
  action: constants.ACTIONS.read
26
28
  });
27
29
  });
@@ -38,7 +40,9 @@ var adminUpload = {
38
40
  const file = await uploadService.updateFileInfo(id, data.fileInfo, {
39
41
  user
40
42
  });
41
- ctx.body = await pm.sanitizeOutput(file, {
43
+ // Sign file urls for private providers
44
+ const signedFile = await index.getService('file').signFileUrls(file);
45
+ ctx.body = await pm.sanitizeOutput(signedFile, {
42
46
  action: constants.ACTIONS.read
43
47
  });
44
48
  },
@@ -63,6 +67,25 @@ var adminUpload = {
63
67
  }, {
64
68
  user
65
69
  });
70
+ // Regenerate AI metadata for image replacements so the alt text / caption
71
+ // reflect the new file content. Mirrors the post-upload hook in
72
+ // `uploadFiles`; failure is logged and swallowed to keep the replace flow
73
+ // resilient when the AI provider is unavailable.
74
+ const aiMetadataService = index.getService('aiMetadata');
75
+ if (replacedFile?.mime?.startsWith('image/') && await aiMetadataService.isEnabled()) {
76
+ try {
77
+ const metadataResults = await aiMetadataService.processFiles([
78
+ replacedFile
79
+ ]);
80
+ await aiMetadataService.updateFilesWithAIMetadata([
81
+ replacedFile
82
+ ], metadataResults, user);
83
+ } catch (error) {
84
+ strapi.log.warn('AI metadata generation failed on replace, proceeding without it', {
85
+ error: error instanceof Error ? error.message : String(error)
86
+ });
87
+ }
88
+ }
66
89
  // Sign file urls for private providers
67
90
  const signedFile = await index.getService('file').signFileUrls(replacedFile);
68
91
  ctx.body = await pm.sanitizeOutput(signedFile, {
@@ -126,15 +149,13 @@ var adminUpload = {
126
149
  },
127
150
  /**
128
151
  * @experimental
129
- * Stream upload files with SSE streaming for per-file progress
152
+ * Upload a single file and return the created File.
130
153
  *
131
- * Streams Server-Sent Events as each file is validated and uploaded:
132
- * - file:uploading when processing starts for a file
133
- * - file:complete when a file is successfully uploaded
134
- * - file:error — when a file fails validation or upload
135
- * - stream:complete final summary with all results
136
- *
137
- */ async unstable_uploadFilesStream (ctx) {
154
+ * Accepts one file per request (multipart `files` + `fileInfo`) and returns a
155
+ * single `File` object. Unlike `uploadFiles`, it does **not** run AI metadata
156
+ * generation inline that responsibility is decoupled and will be handled by a
157
+ * background job. Auth and permission checks mirror `POST /upload`.
158
+ */ async unstable_uploadFile (ctx) {
138
159
  const { state: { userAbility, user }, request: { body, files: { files } = {} } } = ctx;
139
160
  const uploadService = index.getService('upload');
140
161
  const pm = strapi.service('admin::permission').createPermissionsManager({
@@ -148,124 +169,54 @@ var adminUpload = {
148
169
  if (_.isEmpty(files) || !Array.isArray(files) && files.size === 0) {
149
170
  throw new utils.errors.ApplicationError('Files are empty');
150
171
  }
151
- // Take manual control of the response for SSE streaming
152
- ctx.respond = false;
153
- const res = ctx.res;
154
- res.writeHead(200, {
155
- 'Content-Type': 'text/event-stream',
156
- 'Cache-Control': 'no-cache',
157
- Connection: 'keep-alive'
158
- });
159
- const writeSSE = (event, data)=>{
160
- res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
172
+ // Accept a single file per request; ignore any extras defensively.
173
+ const file = Array.isArray(files) ? files[0] : files;
174
+ const fileName = file.originalFilename || 'unknown';
175
+ // Parse the single fileInfo object from the multipart body.
176
+ let fileInfo = {
177
+ name: fileName,
178
+ caption: null,
179
+ alternativeText: null,
180
+ folder: null
161
181
  };
162
- // Normalize files to an array
163
- const filesArray = Array.isArray(files) ? files : [
164
- files
165
- ];
166
- const total = filesArray.length;
167
- // Parse fileInfo from body
168
- // Multipart forms send fileInfo as either:
169
- // - An array of JSON strings (one per file)
170
- // - A single JSON string (one file, or a JSON-encoded array)
171
- let parsedFileInfo = [];
172
182
  if (body?.fileInfo) {
173
183
  const raw = body.fileInfo;
174
- if (Array.isArray(raw)) {
175
- parsedFileInfo = raw.map((fi)=>typeof fi === 'string' ? JSON.parse(fi) : fi);
176
- } else if (typeof raw === 'string') {
177
- const parsed = JSON.parse(raw);
178
- // Handle case where a single string contains a JSON array
179
- parsedFileInfo = Array.isArray(parsed) ? parsed : [
180
- parsed
181
- ];
184
+ if (typeof raw === 'string') {
185
+ fileInfo = JSON.parse(raw);
186
+ } else if (Array.isArray(raw)) {
187
+ fileInfo = typeof raw[0] === 'string' ? JSON.parse(raw[0]) : raw[0];
182
188
  } else {
183
- parsedFileInfo = [
184
- raw
185
- ];
189
+ fileInfo = raw;
186
190
  }
187
191
  }
188
- const uploadErrors = [];
189
- const successfulFiles = [];
190
- // Process each file sequentially with inline validation
191
- for(let i = 0; i < filesArray.length; i += 1){
192
- const file = filesArray[i];
193
- const fileName = file.originalFilename || 'unknown';
194
- const fileInfo = parsedFileInfo[i] || {
195
- name: fileName,
196
- caption: null,
197
- alternativeText: null,
198
- folder: null
199
- };
200
- writeSSE('file:uploading', {
201
- name: fileName,
202
- index: i,
203
- total,
204
- size: file.size || 0
205
- });
206
- try {
207
- // Validate this single file using security checks
208
- const { validFiles, errors: validationErrors } = await mimeValidation.prepareUploadRequest(file, {
209
- fileInfo: JSON.stringify(fileInfo)
210
- }, strapi);
211
- if (validFiles.length === 0) {
212
- const errorMessage = validationErrors[0]?.message || 'Validation failed';
213
- uploadErrors.push({
214
- name: fileName,
215
- message: errorMessage
216
- });
217
- writeSSE('file:error', {
218
- name: fileName,
219
- index: i,
220
- message: errorMessage
221
- });
222
- } else {
223
- // Validate using the already-parsed single fileInfo object directly
224
- const data = await upload.validateUploadBody({
225
- fileInfo
226
- }, false);
227
- const [uploadedFile] = await uploadService.upload({
228
- data,
229
- files: [
230
- validFiles[0]
231
- ]
232
- }, {
233
- user
234
- });
235
- // Sign file url
236
- const signedFile = await index.getService('file').signFileUrls(uploadedFile);
237
- successfulFiles.push(signedFile);
238
- writeSSE('file:complete', {
239
- name: fileName,
240
- index: i,
241
- file: signedFile
242
- });
243
- }
244
- } catch (error) {
245
- const errorMessage = error instanceof Error ? error.message : String(error);
246
- uploadErrors.push({
247
- name: fileName,
248
- message: errorMessage
249
- });
250
- writeSSE('file:error', {
251
- name: fileName,
252
- index: i,
253
- message: errorMessage
254
- });
255
- }
192
+ // Validate this single file using security checks.
193
+ const { validFiles, errors: validationErrors } = await mimeValidation.prepareUploadRequest(file, {
194
+ fileInfo: JSON.stringify(fileInfo)
195
+ }, strapi);
196
+ if (validFiles.length === 0) {
197
+ throw new utils.errors.ValidationError(validationErrors[0]?.message || 'Validation failed');
256
198
  }
257
- // Track image upload metric once if any images were uploaded
258
- if (successfulFiles.some((file)=>file.mime?.startsWith('image/'))) {
199
+ const data = await upload.validateUploadBody({
200
+ fileInfo
201
+ }, false);
202
+ const [uploadedFile] = await uploadService.upload({
203
+ data,
204
+ files: [
205
+ validFiles[0]
206
+ ]
207
+ }, {
208
+ user
209
+ });
210
+ if (uploadedFile.mime?.startsWith('image/')) {
259
211
  await index.getService('metrics').trackUsage('didUploadImage');
260
212
  }
261
- // Send final stream summary
262
- writeSSE('stream:complete', {
263
- data: await pm.sanitizeOutput(successfulFiles, {
264
- action: constants.ACTIONS.read
265
- }),
266
- errors: uploadErrors
213
+ // No inline AI metadata generation — intentionally decoupled for the async job.
214
+ // Sign file url for private providers.
215
+ const signedFile = await index.getService('file').signFileUrls(uploadedFile);
216
+ ctx.body = await pm.sanitizeOutput(signedFile, {
217
+ action: constants.ACTIONS.read
267
218
  });
268
- res.end();
219
+ ctx.status = 201;
269
220
  },
270
221
  /**
271
222
  * @experimental
@@ -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 return pm.sanitizeOutput(updated, { 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 ctx.body = await pm.sanitizeOutput(file, { 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 // 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 * Stream upload files with SSE streaming for per-file progress\n *\n * Streams Server-Sent Events as each file is validated and uploaded:\n * - file:uploading — when processing starts for a file\n * - file:complete — when a file is successfully uploaded\n * - file:error — when a file fails validation or upload\n * - stream:complete — final summary with all results\n *\n */\n async unstable_uploadFilesStream(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 // 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 // Normalize files to an array\n const filesArray = Array.isArray(files) ? files : [files];\n const total = filesArray.length;\n\n // Parse fileInfo from body\n // Multipart forms send fileInfo as either:\n // - An array of JSON strings (one per file)\n // - A single JSON string (one file, or a JSON-encoded array)\n let parsedFileInfo: UploadFileInfo[] = [];\n if (body?.fileInfo) {\n const raw = body.fileInfo;\n if (Array.isArray(raw)) {\n parsedFileInfo = raw.map((fi: unknown) =>\n typeof fi === 'string' ? JSON.parse(fi) : fi\n ) as UploadFileInfo[];\n } else if (typeof raw === 'string') {\n const parsed = JSON.parse(raw);\n // Handle case where a single string contains a JSON array\n parsedFileInfo = (Array.isArray(parsed) ? parsed : [parsed]) as UploadFileInfo[];\n } else {\n parsedFileInfo = [raw as UploadFileInfo];\n }\n }\n\n const uploadErrors: FileUploadError[] = [];\n const successfulFiles: any[] = [];\n\n // Process each file sequentially with inline validation\n for (let i = 0; i < filesArray.length; i += 1) {\n const file = filesArray[i];\n const fileName = file.originalFilename || 'unknown';\n const fileInfo: UploadFileInfo = parsedFileInfo[i] || {\n name: fileName,\n caption: null,\n alternativeText: null,\n folder: null,\n };\n\n writeSSE('file:uploading', { name: fileName, index: i, total, size: file.size || 0 });\n\n try {\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 const errorMessage = validationErrors[0]?.message || 'Validation failed';\n uploadErrors.push({ name: fileName, message: errorMessage });\n writeSSE('file:error', { name: fileName, index: i, message: errorMessage });\n } else {\n // Validate using the already-parsed single fileInfo object directly\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 getService('file').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: fileName, message: errorMessage });\n writeSSE('file:error', { name: fileName, 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\n res.end();\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","sanitizeOutput","action","read","query","errors","ValidationError","data","validateUploadBody","file","replaceFile","files","Array","isArray","ApplicationError","validFiles","filteredBody","validationErrors","prepareUploadRequest","strapi","length","message","replacedFile","replace","signedFile","signFileUrls","uploadFiles","service","createPermissionsManager","ability","create","model","isAllowed","forbidden","isMultipleFiles","filesArray","alignedFilesArray","info","find","originalFilename","name","filter","Boolean","uploadedFiles","upload","some","mime","startsWith","trackUsage","aiMetadataService","isEnabled","metadataResults","processFiles","updateFilesWithAIMetadata","error","log","warn","Error","String","signedFiles","status","unstable_uploadFilesStream","_","isEmpty","size","respond","res","writeHead","Connection","writeSSE","event","write","JSON","stringify","total","parsedFileInfo","raw","fi","parse","parsed","uploadErrors","successfulFiles","i","fileName","caption","alternativeText","folder","index","errorMessage","push","uploadedFile","end","unstable_uploadFromUrls","fileService","urls","folderId","tmpWorkingDirectory","fse","mkdtemp","path","join","os","tmpdir","sizeLimit","config","get","url","fetchUrlToInputFile","remove"],"mappings":";;;;;;;;;;;;;AAgBA,kBAAe;AACb,IAAA,MAAMA,oBAAmBC,GAAY,EAAA;AACnC,QAAA,MAAM,EACJC,KAAAA,EAAO,EAAEC,WAAW,EAAEC,IAAI,EAAE,EAC5BC,OAAAA,EAAS,EAAEC,IAAI,EAAE,EAClB,GAAGL,GAAAA;AAEJ,QAAA,MAAM,EAAEM,OAAO,EAAE,GAAG,MAAMC,6BAAAA,CAAuBF,IAAAA,CAAAA;AACjD,QAAA,MAAMG,gBAAgBC,gBAAAA,CAAW,QAAA,CAAA;QAEjC,MAAMC,OAAAA,GAAU,MAAMC,WAAAA,CAAMC,GAAG,CAC7BN,OAAAA,EACA,OAAO,EAAEO,EAAE,EAAEC,QAAQ,EAAsC,GAAA;YACzD,MAAM,EAAEC,EAAE,EAAE,GAAG,MAAMC,4DACnBd,WAAAA,EACAe,iBAAAA,CAAQC,MAAM,EACdC,wBAAAA,EACAN,EAAAA,CAAAA;AAGF,YAAA,MAAMO,UAAU,MAAMZ,aAAAA,CAAca,cAAc,CAACR,IAAIC,QAAAA,EAAiB;AAAEX,gBAAAA;AAAK,aAAA,CAAA;YAC/E,OAAOY,EAAAA,CAAGO,cAAc,CAACF,OAAAA,EAAS;AAAEG,gBAAAA,MAAAA,EAAQN,kBAAQO;AAAK,aAAA,CAAA;AAC3D,QAAA,CAAA,CAAA;AAGFxB,QAAAA,GAAAA,CAAIK,IAAI,GAAGK,OAAAA;AACb,IAAA,CAAA;AAEA,IAAA,MAAMW,gBAAerB,GAAY,EAAA;AAC/B,QAAA,MAAM,EACJC,KAAAA,EAAO,EAAEC,WAAW,EAAEC,IAAI,EAAE,EAC5BsB,KAAAA,EAAO,EAAEZ,EAAE,EAAE,EACbT,OAAAA,EAAS,EAAEC,IAAI,EAAE,EAClB,GAAGL,GAAAA;QAEJ,IAAI,OAAOa,OAAO,QAAA,EAAU;YAC1B,MAAM,IAAIa,YAAAA,CAAOC,eAAe,CAAC,qBAAA,CAAA;AACnC,QAAA;AAEA,QAAA,MAAMnB,gBAAgBC,gBAAAA,CAAW,QAAA,CAAA;QACjC,MAAM,EAAEM,EAAE,EAAE,GAAG,MAAMC,4DACnBd,WAAAA,EACAe,iBAAAA,CAAQC,MAAM,EACdC,wBAAAA,EACAN,EAAAA,CAAAA;QAGF,MAAMe,IAAAA,GAAO,MAAMC,yBAAAA,CAAmBxB,IAAAA,CAAAA;QAEtC,MAAMyB,IAAAA,GAAO,MAAMtB,aAAAA,CAAca,cAAc,CAACR,EAAAA,EAAIe,IAAAA,CAAKd,QAAQ,EAAS;AAAEX,YAAAA;AAAK,SAAA,CAAA;AAEjFH,QAAAA,GAAAA,CAAIK,IAAI,GAAG,MAAMU,EAAAA,CAAGO,cAAc,CAACQ,IAAAA,EAAM;AAAEP,YAAAA,MAAAA,EAAQN,kBAAQO;AAAK,SAAA,CAAA;AAClE,IAAA,CAAA;AAEA,IAAA,MAAMO,aAAY/B,GAAY,EAAA;QAC5B,MAAM,EACJC,KAAAA,EAAO,EAAEC,WAAW,EAAEC,IAAI,EAAE,EAC5BsB,KAAAA,EAAO,EAAEZ,EAAE,EAAE,EACbT,SAAS,EAAEC,IAAI,EAAE2B,KAAAA,EAAO,EAAEA,KAAK,EAAE,GAAG,EAAE,EAAE,EACzC,GAAGhC,GAAAA;QAEJ,IAAI,OAAOa,OAAO,QAAA,EAAU;YAC1B,MAAM,IAAIa,YAAAA,CAAOC,eAAe,CAAC,qBAAA,CAAA;AACnC,QAAA;AAEA,QAAA,MAAMnB,gBAAgBC,gBAAAA,CAAW,QAAA,CAAA;QACjC,MAAM,EAAEM,EAAE,EAAE,GAAG,MAAMC,4DACnBd,WAAAA,EACAe,iBAAAA,CAAQC,MAAM,EACdC,wBAAAA,EACAN,EAAAA,CAAAA;QAGF,IAAIoB,KAAAA,CAAMC,OAAO,CAACF,KAAAA,CAAAA,EAAQ;YACxB,MAAM,IAAIN,YAAAA,CAAOS,gBAAgB,CAAC,0CAAA,CAAA;AACpC,QAAA;AAEA,QAAA,MAAM,EACJC,UAAU,EACVC,YAAY,EACZX,MAAAA,EAAQY,gBAAgB,EACzB,GAAG,MAAMC,mCAAAA,CAAqBP,KAAAA,EAAO3B,IAAAA,EAAMmC,MAAAA,CAAAA;QAC5C,IAAIJ,UAAAA,CAAWK,MAAM,KAAK,CAAA,EAAG;YAC3B,MAAM,IAAIf,aAAOC,eAAe,CAACW,gBAAgB,CAAC,CAAA,CAAE,CAACI,OAAO,CAAA;AAC9D,QAAA;QAEA,MAAMd,IAAAA,GAAQ,MAAMC,yBAAAA,CAAmBQ,YAAAA,CAAAA;AACvC,QAAA,MAAMM,YAAAA,GAAe,MAAMnC,aAAAA,CAAcoC,OAAO,CAAC/B,EAAAA,EAAI;AAAEe,YAAAA,IAAAA;YAAME,IAAAA,EAAMM,UAAU,CAAC,CAAA;SAAG,EAAG;AAAEjC,YAAAA;AAAK,SAAA,CAAA;;AAG3F,QAAA,MAAM0C,UAAAA,GAAa,MAAMpC,gBAAAA,CAAW,MAAA,CAAA,CAAQqC,YAAY,CAACH,YAAAA,CAAAA;AAEzD3C,QAAAA,GAAAA,CAAIK,IAAI,GAAG,MAAMU,EAAAA,CAAGO,cAAc,CAACuB,UAAAA,EAAY;AAAEtB,YAAAA,MAAAA,EAAQN,kBAAQO;AAAK,SAAA,CAAA;AACxE,IAAA,CAAA;AAEA,IAAA,MAAMuB,aAAY/C,GAAY,EAAA;QAC5B,MAAM,EACJC,OAAO,EAAEC,WAAW,EAAEC,IAAI,EAAE,EAC5BC,OAAAA,EAAS,EAAEC,IAAI,EAAE2B,KAAAA,EAAO,EAAEA,KAAK,EAAE,GAAG,EAAE,EAAE,EACzC,GAAGhC,GAAAA;AAEJ,QAAA,MAAMQ,gBAAgBC,gBAAAA,CAAW,QAAA,CAAA;AACjC,QAAA,MAAMM,KAAKyB,MAAAA,CAAOQ,OAAO,CAAC,mBAAA,CAAA,CAAqBC,wBAAwB,CAAC;YACtEC,OAAAA,EAAShD,WAAAA;AACTqB,YAAAA,MAAAA,EAAQN,kBAAQkC,MAAM;YACtBC,KAAAA,EAAOjC;AACT,SAAA,CAAA;QAEA,IAAI,CAACJ,EAAAA,CAAGsC,SAAS,EAAE;AACjB,YAAA,OAAOrD,IAAIsD,SAAS,EAAA;AACtB,QAAA;AAEA,QAAA,MAAM,EACJlB,UAAU,EACVC,YAAY,EACZX,MAAAA,EAAQY,gBAAgB,EACzB,GAAG,MAAMC,mCAAAA,CAAqBP,KAAAA,EAAO3B,IAAAA,EAAMmC,MAAAA,CAAAA;QAC5C,IAAIJ,UAAAA,CAAWK,MAAM,KAAK,CAAA,EAAG;YAC3B,MAAM,IAAIf,aAAOC,eAAe,CAACW,gBAAgB,CAAC,CAAA,CAAE,CAACI,OAAO,CAAA;AAC9D,QAAA;QAEA,MAAMa,eAAAA,GAAkBnB,UAAAA,CAAWK,MAAM,GAAG,CAAA;QAC5C,MAAMb,IAAAA,GAAO,MAAMC,yBAAAA,CAAmBQ,YAAAA,EAAckB,eAAAA,CAAAA;AAEpD,QAAA,IAAIC,UAAAA,GAAapB,UAAAA;AAEjB,QAAA,IACER,KAAKd,QAAQ,IACbmB,KAAAA,CAAMC,OAAO,CAACN,IAAAA,CAAKd,QAAQ,CAAA,IAC3B0C,UAAAA,CAAWf,MAAM,KAAKb,IAAAA,CAAKd,QAAQ,CAAC2B,MAAM,EAC1C;;AAEA,YAAA,MAAMgB,oBAAoB7B,IAAAA,CAAKd,QAAQ,CACpCF,GAAG,CAAC,CAAC8C,IAAAA,GAAAA;gBACJ,OAAOF,UAAAA,CAAWG,IAAI,CAAC,CAAC7B,OAASA,IAAAA,CAAK8B,gBAAgB,KAAKF,IAAAA,CAAKG,IAAI,CAAA;AACtE,YAAA,CAAA,CAAA,CACCC,MAAM,CAACC,OAAAA,CAAAA;YAEVP,UAAAA,GAAaC,iBAAAA;AACf,QAAA;;AAGA,QAAA,MAAMO,aAAAA,GAAgB,MAAMxD,aAAAA,CAAcyD,MAAM,CAAC;AAAErC,YAAAA,IAAAA;YAAMI,KAAAA,EAAOwB;SAAW,EAAG;AAAErD,YAAAA;AAAK,SAAA,CAAA;QACrF,IAAI6D,aAAAA,CAAcE,IAAI,CAAC,CAACpC,OAASA,IAAAA,CAAKqC,IAAI,EAAEC,UAAAA,CAAW,QAAA,CAAA,CAAA,EAAY;YACjE,MAAM3D,gBAAAA,CAAW,SAAA,CAAA,CAAW4D,UAAU,CAAC,gBAAA,CAAA;AACzC,QAAA;AAEA,QAAA,MAAMC,oBAAoB7D,gBAAAA,CAAW,YAAA,CAAA;;QAGrC,IAAI,MAAM6D,iBAAAA,CAAkBC,SAAS,EAAA,EAAI;YACvC,IAAI;AACF,gBAAA,MAAMC,eAAAA,GAAkB,MAAMF,iBAAAA,CAAkBG,YAAY,CAACT,aAAAA,CAAAA;;AAE7D,gBAAA,MAAMM,iBAAAA,CAAkBI,yBAAyB,CAACV,aAAAA,EAAeQ,eAAAA,EAAiBrE,IAAAA,CAAAA;AACpF,YAAA,CAAA,CAAE,OAAOwE,KAAAA,EAAO;AACdnC,gBAAAA,MAAAA,CAAOoC,GAAG,CAACC,IAAI,CAAC,mEAAA,EAAqE;AACnFF,oBAAAA,KAAAA,EAAOA,KAAAA,YAAiBG,KAAAA,GAAQH,KAAAA,CAAMjC,OAAO,GAAGqC,MAAAA,CAAOJ,KAAAA;AACzD,iBAAA,CAAA;AACF,YAAA;AACF,QAAA;;QAGA,MAAMK,WAAAA,GAAc,MAAMrE,WAAAA,CAAMC,GAAG,CAACoD,aAAAA,EAAevD,gBAAAA,CAAW,QAAQqC,YAAY,CAAA;AAElF9C,QAAAA,GAAAA,CAAIK,IAAI,GAAG,MAAMU,EAAAA,CAAGO,cAAc,CAAC0D,WAAAA,EAAa;AAAEzD,YAAAA,MAAAA,EAAQN,kBAAQO;AAAK,SAAA,CAAA;AACvExB,QAAAA,GAAAA,CAAIiF,MAAM,GAAG,GAAA;AACf,IAAA,CAAA;AAEA;;;;;;;;;;MAWA,MAAMC,4BAA2BlF,GAAY,EAAA;QAC3C,MAAM,EACJC,OAAO,EAAEC,WAAW,EAAEC,IAAI,EAAE,EAC5BC,OAAAA,EAAS,EAAEC,IAAI,EAAE2B,KAAAA,EAAO,EAAEA,KAAK,EAAE,GAAG,EAAE,EAAE,EACzC,GAAGhC,GAAAA;AAEJ,QAAA,MAAMQ,gBAAgBC,gBAAAA,CAAW,QAAA,CAAA;AACjC,QAAA,MAAMM,KAAKyB,MAAAA,CAAOQ,OAAO,CAAC,mBAAA,CAAA,CAAqBC,wBAAwB,CAAC;YACtEC,OAAAA,EAAShD,WAAAA;AACTqB,YAAAA,MAAAA,EAAQN,kBAAQkC,MAAM;YACtBC,KAAAA,EAAOjC;AACT,SAAA,CAAA;QAEA,IAAI,CAACJ,EAAAA,CAAGsC,SAAS,EAAE;AACjB,YAAA,OAAOrD,IAAIsD,SAAS,EAAA;AACtB,QAAA;AAEA,QAAA,IAAI6B,CAAAA,CAAEC,OAAO,CAACpD,KAAAA,CAAAA,IAAW,CAACC,KAAAA,CAAMC,OAAO,CAACF,KAAAA,CAAAA,IAAUA,KAAAA,CAAMqD,IAAI,KAAK,CAAA,EAAI;YACnE,MAAM,IAAI3D,YAAAA,CAAOS,gBAAgB,CAAC,iBAAA,CAAA;AACpC,QAAA;;AAGAnC,QAAAA,GAAAA,CAAIsF,OAAO,GAAG,KAAA;QACd,MAAMC,GAAAA,GAAMvF,IAAIuF,GAAG;QACnBA,GAAAA,CAAIC,SAAS,CAAC,GAAA,EAAK;YACjB,cAAA,EAAgB,mBAAA;YAChB,eAAA,EAAiB,UAAA;YACjBC,UAAAA,EAAY;AACd,SAAA,CAAA;QAEA,MAAMC,QAAAA,GAAW,CAACC,KAAAA,EAAe/D,IAAAA,GAAAA;AAC/B2D,YAAAA,GAAAA,CAAIK,KAAK,CAAC,CAAC,OAAO,EAAED,KAAAA,CAAM,QAAQ,EAAEE,IAAAA,CAAKC,SAAS,CAAClE,IAAAA,CAAAA,CAAM,IAAI,CAAC,CAAA;AAChE,QAAA,CAAA;;AAGA,QAAA,MAAM4B,UAAAA,GAAavB,KAAAA,CAAMC,OAAO,CAACF,SAASA,KAAAA,GAAQ;AAACA,YAAAA;AAAM,SAAA;QACzD,MAAM+D,KAAAA,GAAQvC,WAAWf,MAAM;;;;;AAM/B,QAAA,IAAIuD,iBAAmC,EAAE;AACzC,QAAA,IAAI3F,MAAMS,QAAAA,EAAU;YAClB,MAAMmF,GAAAA,GAAM5F,KAAKS,QAAQ;YACzB,IAAImB,KAAAA,CAAMC,OAAO,CAAC+D,GAAAA,CAAAA,EAAM;gBACtBD,cAAAA,GAAiBC,GAAAA,CAAIrF,GAAG,CAAC,CAACsF,EAAAA,GACxB,OAAOA,EAAAA,KAAO,QAAA,GAAWL,IAAAA,CAAKM,KAAK,CAACD,EAAAA,CAAAA,GAAMA,EAAAA,CAAAA;YAE9C,CAAA,MAAO,IAAI,OAAOD,GAAAA,KAAQ,QAAA,EAAU;gBAClC,MAAMG,MAAAA,GAASP,IAAAA,CAAKM,KAAK,CAACF,GAAAA,CAAAA;;AAE1BD,gBAAAA,cAAAA,GAAkB/D,KAAAA,CAAMC,OAAO,CAACkE,MAAAA,CAAAA,GAAUA,MAAAA,GAAS;AAACA,oBAAAA;AAAO,iBAAA;YAC7D,CAAA,MAAO;gBACLJ,cAAAA,GAAiB;AAACC,oBAAAA;AAAsB,iBAAA;AAC1C,YAAA;AACF,QAAA;AAEA,QAAA,MAAMI,eAAkC,EAAE;AAC1C,QAAA,MAAMC,kBAAyB,EAAE;;QAGjC,IAAK,IAAIC,IAAI,CAAA,EAAGA,CAAAA,GAAI/C,WAAWf,MAAM,EAAE8D,KAAK,CAAA,CAAG;YAC7C,MAAMzE,IAAAA,GAAO0B,UAAU,CAAC+C,CAAAA,CAAE;YAC1B,MAAMC,QAAAA,GAAW1E,IAAAA,CAAK8B,gBAAgB,IAAI,SAAA;AAC1C,YAAA,MAAM9C,QAAAA,GAA2BkF,cAAc,CAACO,CAAAA,CAAE,IAAI;gBACpD1C,IAAAA,EAAM2C,QAAAA;gBACNC,OAAAA,EAAS,IAAA;gBACTC,eAAAA,EAAiB,IAAA;gBACjBC,MAAAA,EAAQ;AACV,aAAA;AAEAjB,YAAAA,QAAAA,CAAS,gBAAA,EAAkB;gBAAE7B,IAAAA,EAAM2C,QAAAA;gBAAUI,KAAAA,EAAOL,CAAAA;AAAGR,gBAAAA,KAAAA;gBAAOV,IAAAA,EAAMvD,IAAAA,CAAKuD,IAAI,IAAI;AAAE,aAAA,CAAA;YAEnF,IAAI;;gBAEF,MAAM,EAAEjD,UAAU,EAAEV,MAAAA,EAAQY,gBAAgB,EAAE,GAAG,MAAMC,mCAAAA,CACrDT,IAAAA,EACA;oBAAEhB,QAAAA,EAAU+E,IAAAA,CAAKC,SAAS,CAAChF,QAAAA;iBAAU,EACrC0B,MAAAA,CAAAA;gBAGF,IAAIJ,UAAAA,CAAWK,MAAM,KAAK,CAAA,EAAG;AAC3B,oBAAA,MAAMoE,YAAAA,GAAevE,gBAAgB,CAAC,CAAA,CAAE,EAAEI,OAAAA,IAAW,mBAAA;AACrD2D,oBAAAA,YAAAA,CAAaS,IAAI,CAAC;wBAAEjD,IAAAA,EAAM2C,QAAAA;wBAAU9D,OAAAA,EAASmE;AAAa,qBAAA,CAAA;AAC1DnB,oBAAAA,QAAAA,CAAS,YAAA,EAAc;wBAAE7B,IAAAA,EAAM2C,QAAAA;wBAAUI,KAAAA,EAAOL,CAAAA;wBAAG7D,OAAAA,EAASmE;AAAa,qBAAA,CAAA;gBAC3E,CAAA,MAAO;;oBAEL,MAAMjF,IAAAA,GAAO,MAAMC,yBAAAA,CAAmB;AAAEf,wBAAAA;qBAAS,EAAG,KAAA,CAAA;AACpD,oBAAA,MAAM,CAACiG,YAAAA,CAAa,GAAG,MAAMvG,aAAAA,CAAcyD,MAAM,CAC/C;AAAErC,wBAAAA,IAAAA;wBAAMI,KAAAA,EAAO;AAACI,4BAAAA,UAAU,CAAC,CAAA;AAAG;qBAAC,EAC/B;AAAEjC,wBAAAA;AAAK,qBAAA,CAAA;;AAIT,oBAAA,MAAM0C,UAAAA,GAAa,MAAMpC,gBAAAA,CAAW,MAAA,CAAA,CAAQqC,YAAY,CAACiE,YAAAA,CAAAA;AACzDT,oBAAAA,eAAAA,CAAgBQ,IAAI,CAACjE,UAAAA,CAAAA;AAErB6C,oBAAAA,QAAAA,CAAS,eAAA,EAAiB;wBAAE7B,IAAAA,EAAM2C,QAAAA;wBAAUI,KAAAA,EAAOL,CAAAA;wBAAGzE,IAAAA,EAAMe;AAAW,qBAAA,CAAA;AACzE,gBAAA;AACF,YAAA,CAAA,CAAE,OAAO8B,KAAAA,EAAO;AACd,gBAAA,MAAMkC,eAAelC,KAAAA,YAAiBG,KAAAA,GAAQH,KAAAA,CAAMjC,OAAO,GAAGqC,MAAAA,CAAOJ,KAAAA,CAAAA;AACrE0B,gBAAAA,YAAAA,CAAaS,IAAI,CAAC;oBAAEjD,IAAAA,EAAM2C,QAAAA;oBAAU9D,OAAAA,EAASmE;AAAa,iBAAA,CAAA;AAC1DnB,gBAAAA,QAAAA,CAAS,YAAA,EAAc;oBAAE7B,IAAAA,EAAM2C,QAAAA;oBAAUI,KAAAA,EAAOL,CAAAA;oBAAG7D,OAAAA,EAASmE;AAAa,iBAAA,CAAA;AAC3E,YAAA;AACF,QAAA;;QAGA,IAAIP,eAAAA,CAAgBpC,IAAI,CAAC,CAACpC,OAASA,IAAAA,CAAKqC,IAAI,EAAEC,UAAAA,CAAW,QAAA,CAAA,CAAA,EAAY;YACnE,MAAM3D,gBAAAA,CAAW,SAAA,CAAA,CAAW4D,UAAU,CAAC,gBAAA,CAAA;AACzC,QAAA;;AAGAqB,QAAAA,QAAAA,CAAS,iBAAA,EAAmB;AAC1B9D,YAAAA,IAAAA,EAAM,MAAMb,EAAAA,CAAGO,cAAc,CAACgF,eAAAA,EAAiB;AAAE/E,gBAAAA,MAAAA,EAAQN,kBAAQO;AAAK,aAAA,CAAA;YACtEE,MAAAA,EAAQ2E;AACV,SAAA,CAAA;AAEAd,QAAAA,GAAAA,CAAIyB,GAAG,EAAA;AACT,IAAA,CAAA;AAEA;;;;;;;;;;;MAYA,MAAMC,yBAAwBjH,GAAY,EAAA;AACxC,QAAA,MAAM,EACJC,KAAAA,EAAO,EAAEC,WAAW,EAAEC,IAAI,EAAE,EAC5BC,OAAAA,EAAS,EAAEC,IAAI,EAAE,EAClB,GAAGL,GAAAA;AAEJ,QAAA,MAAMQ,gBAAgBC,gBAAAA,CAAW,QAAA,CAAA;AACjC,QAAA,MAAMyG,cAAczG,gBAAAA,CAAW,MAAA,CAAA;AAC/B,QAAA,MAAMM,KAAKyB,MAAAA,CAAOQ,OAAO,CAAC,mBAAA,CAAA,CAAqBC,wBAAwB,CAAC;YACtEC,OAAAA,EAAShD,WAAAA;AACTqB,YAAAA,MAAAA,EAAQN,kBAAQkC,MAAM;YACtBC,KAAAA,EAAOjC;AACT,SAAA,CAAA;QAEA,IAAI,CAACJ,EAAAA,CAAGsC,SAAS,EAAE;AACjB,YAAA,OAAOrD,IAAIsD,SAAS,EAAA;AACtB,QAAA;;AAGA,QAAA,MAAM,EAAE6D,IAAI,EAAEC,QAAQ,EAAE,GAAG/G,IAAAA;QAE3B,IAAI,CAAC8G,IAAAA,IAAQ,CAAClF,KAAAA,CAAMC,OAAO,CAACiF,IAAAA,CAAAA,IAASA,IAAAA,CAAK1E,MAAM,KAAK,CAAA,EAAG;YACtD,MAAM,IAAIf,YAAAA,CAAOS,gBAAgB,CAAC,mBAAA,CAAA;AACpC,QAAA;QAEA,IAAIgF,IAAAA,CAAK1E,MAAM,GAAG,EAAA,EAAI;YACpB,MAAM,IAAIf,YAAAA,CAAOS,gBAAgB,CAAC,qCAAA,CAAA;AACpC,QAAA;;AAGAnC,QAAAA,GAAAA,CAAIsF,OAAO,GAAG,KAAA;QACd,MAAMC,GAAAA,GAAMvF,IAAIuF,GAAG;QACnBA,GAAAA,CAAIC,SAAS,CAAC,GAAA,EAAK;YACjB,cAAA,EAAgB,mBAAA;YAChB,eAAA,EAAiB,UAAA;YACjBC,UAAAA,EAAY;AACd,SAAA,CAAA;QAEA,MAAMC,QAAAA,GAAW,CAACC,KAAAA,EAAe/D,IAAAA,GAAAA;AAC/B2D,YAAAA,GAAAA,CAAIK,KAAK,CAAC,CAAC,OAAO,EAAED,KAAAA,CAAM,QAAQ,EAAEE,IAAAA,CAAKC,SAAS,CAAClE,IAAAA,CAAAA,CAAM,IAAI,CAAC,CAAA;AAChE,QAAA,CAAA;QAEA,MAAMmE,KAAAA,GAAQoB,KAAK1E,MAAM;AACzB,QAAA,MAAM4D,eAAkC,EAAE;AAC1C,QAAA,MAAMC,kBAAyB,EAAE;;QAGjC,MAAMe,mBAAAA,GAAsB,MAAMC,GAAAA,CAAIC,OAAO,CAACC,KAAKC,IAAI,CAACC,EAAAA,CAAGC,MAAM,EAAA,EAAI,oBAAA,CAAA,CAAA;QACrE,MAAM,EAAEC,SAAS,EAAE,GAAGpF,OAAOqF,MAAM,CAACC,GAAG,CAAS,gBAAA,CAAA;QAEhD,IAAI;;YAEF,IAAK,IAAIvB,IAAI,CAAA,EAAGA,CAAAA,GAAIY,KAAK1E,MAAM,EAAE8D,KAAK,CAAA,CAAG;gBACvC,MAAMwB,GAAAA,GAAMZ,IAAI,CAACZ,CAAAA,CAAE;AAEnBb,gBAAAA,QAAAA,CAAS,eAAA,EAAiB;AAAEqC,oBAAAA,GAAAA;oBAAKnB,KAAAA,EAAOL,CAAAA;AAAGR,oBAAAA;AAAM,iBAAA,CAAA;gBAEjD,IAAI;;oBAEF,MAAM,EAAEjE,IAAI,EAAE,GAAG,MAAMoF,WAAAA,CAAYc,mBAAmB,CACpDD,GAAAA,EACAV,mBAAAA,EACAO,SAAAA,CAAAA;oBAEF,MAAMpB,QAAAA,GAAW1E,KAAK8B,gBAAgB;AAEtC8B,oBAAAA,QAAAA,CAAS,gBAAA,EAAkB;wBACzB7B,IAAAA,EAAM2C,QAAAA;wBACNI,KAAAA,EAAOL,CAAAA;AACPR,wBAAAA,KAAAA;AACAV,wBAAAA,IAAAA,EAAMvD,KAAKuD;AACb,qBAAA,CAAA;;AAGA,oBAAA,MAAMvE,QAAAA,GAA2B;wBAC/B+C,IAAAA,EAAM2C,QAAAA;wBACNC,OAAAA,EAAS,IAAA;wBACTC,eAAAA,EAAiB,IAAA;AACjBC,wBAAAA,MAAAA,EAAQS,QAAAA,IAAY;AACtB,qBAAA;oBAEA,MAAM,EAAEhF,UAAU,EAAEV,MAAAA,EAAQY,gBAAgB,EAAE,GAAG,MAAMC,mCAAAA,CACrDT,IAAAA,EACA;wBAAEhB,QAAAA,EAAU+E,IAAAA,CAAKC,SAAS,CAAChF,QAAAA;qBAAU,EACrC0B,MAAAA,CAAAA;oBAGF,IAAIJ,UAAAA,CAAWK,MAAM,KAAK,CAAA,EAAG;AAC3B,wBAAA,MAAMoE,YAAAA,GAAevE,gBAAgB,CAAC,CAAA,CAAE,EAAEI,OAAAA,IAAW,mBAAA;AACrD2D,wBAAAA,YAAAA,CAAaS,IAAI,CAAC;4BAAEjD,IAAAA,EAAM2C,QAAAA;4BAAU9D,OAAAA,EAASmE;AAAa,yBAAA,CAAA;AAC1DnB,wBAAAA,QAAAA,CAAS,YAAA,EAAc;4BAAE7B,IAAAA,EAAM2C,QAAAA;AAAUuB,4BAAAA,GAAAA;4BAAKnB,KAAAA,EAAOL,CAAAA;4BAAG7D,OAAAA,EAASmE;AAAa,yBAAA,CAAA;oBAChF,CAAA,MAAO;;wBAEL,MAAMjF,IAAAA,GAAO,MAAMC,yBAAAA,CAAmB;AAAEf,4BAAAA;yBAAS,EAAG,KAAA,CAAA;AACpD,wBAAA,MAAM,CAACiG,YAAAA,CAAa,GAAG,MAAMvG,aAAAA,CAAcyD,MAAM,CAC/C;AAAErC,4BAAAA,IAAAA;4BAAMI,KAAAA,EAAO;AAACI,gCAAAA,UAAU,CAAC,CAAA;AAAG;yBAAC,EAC/B;AAAEjC,4BAAAA;AAAK,yBAAA,CAAA;;AAIT,wBAAA,MAAM0C,UAAAA,GAAa,MAAMqE,WAAAA,CAAYpE,YAAY,CAACiE,YAAAA,CAAAA;AAClDT,wBAAAA,eAAAA,CAAgBQ,IAAI,CAACjE,UAAAA,CAAAA;AAErB6C,wBAAAA,QAAAA,CAAS,eAAA,EAAiB;4BAAE7B,IAAAA,EAAM2C,QAAAA;4BAAUI,KAAAA,EAAOL,CAAAA;4BAAGzE,IAAAA,EAAMe;AAAW,yBAAA,CAAA;AACzE,oBAAA;AACF,gBAAA,CAAA,CAAE,OAAO8B,KAAAA,EAAO;AACd,oBAAA,MAAMkC,eAAelC,KAAAA,YAAiBG,KAAAA,GAAQH,KAAAA,CAAMjC,OAAO,GAAGqC,MAAAA,CAAOJ,KAAAA,CAAAA;AACrE0B,oBAAAA,YAAAA,CAAaS,IAAI,CAAC;wBAAEjD,IAAAA,EAAMkE,GAAAA;wBAAKrF,OAAAA,EAASmE;AAAa,qBAAA,CAAA;AACrDnB,oBAAAA,QAAAA,CAAS,YAAA,EAAc;AAAEqC,wBAAAA,GAAAA;wBAAKnB,KAAAA,EAAOL,CAAAA;wBAAG7D,OAAAA,EAASmE;AAAa,qBAAA,CAAA;AAChE,gBAAA;AACF,YAAA;;YAGA,IAAIP,eAAAA,CAAgBpC,IAAI,CAAC,CAACpC,OAASA,IAAAA,CAAKqC,IAAI,EAAEC,UAAAA,CAAW,QAAA,CAAA,CAAA,EAAY;gBACnE,MAAM3D,gBAAAA,CAAW,SAAA,CAAA,CAAW4D,UAAU,CAAC,gBAAA,CAAA;AACzC,YAAA;;AAGAqB,YAAAA,QAAAA,CAAS,iBAAA,EAAmB;AAC1B9D,gBAAAA,IAAAA,EAAM,MAAMb,EAAAA,CAAGO,cAAc,CAACgF,eAAAA,EAAiB;AAAE/E,oBAAAA,MAAAA,EAAQN,kBAAQO;AAAK,iBAAA,CAAA;gBACtEE,MAAAA,EAAQ2E;AACV,aAAA,CAAA;QACF,CAAA,QAAU;;YAER,MAAMiB,GAAAA,CAAIW,MAAM,CAACZ,mBAAAA,CAAAA;AACnB,QAAA;AAEA9B,QAAAA,GAAAA,CAAIyB,GAAG,EAAA;AACT,IAAA,CAAA;;AAGA,IAAA,MAAM/C,QAAOjE,GAAY,EAAA;AACvB,QAAA,MAAM,EACJyB,KAAAA,EAAO,EAAEZ,EAAE,EAAE,EACbT,OAAAA,EAAS,EAAE4B,KAAAA,EAAO,EAAEA,KAAK,EAAE,GAAG,EAAE,EAAE,EACnC,GAAGhC,GAAAA;AAEJ,QAAA,IAAImF,CAAAA,CAAEC,OAAO,CAACpD,KAAAA,CAAAA,IAAW,CAACC,KAAAA,CAAMC,OAAO,CAACF,KAAAA,CAAAA,IAAUA,KAAAA,CAAMqD,IAAI,KAAK,CAAA,EAAI;AACnE,YAAA,IAAIxE,EAAAA,EAAI;gBACN,OAAO,IAAI,CAACQ,cAAc,CAACrB,GAAAA,CAAAA;AAC7B,YAAA;YAEA,MAAM,IAAI0B,YAAAA,CAAOS,gBAAgB,CAAC,iBAAA,CAAA;AACpC,QAAA;QAEA,MAAOtB,CAAAA,EAAAA,GAAK,IAAI,CAACkB,WAAW,GAAG,IAAI,CAACgB,WAAU,EAAG/C,GAAAA,CAAAA;AACnD,IAAA;AACF,CAAA;;;;"}
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":";;;;;;;;;;;;;AAgBA,kBAAe;AACb,IAAA,MAAMA,oBAAmBC,GAAY,EAAA;AACnC,QAAA,MAAM,EACJC,KAAAA,EAAO,EAAEC,WAAW,EAAEC,IAAI,EAAE,EAC5BC,OAAAA,EAAS,EAAEC,IAAI,EAAE,EAClB,GAAGL,GAAAA;AAEJ,QAAA,MAAM,EAAEM,OAAO,EAAE,GAAG,MAAMC,6BAAAA,CAAuBF,IAAAA,CAAAA;AACjD,QAAA,MAAMG,gBAAgBC,gBAAAA,CAAW,QAAA,CAAA;QAEjC,MAAMC,OAAAA,GAAU,MAAMC,WAAAA,CAAMC,GAAG,CAC7BN,OAAAA,EACA,OAAO,EAAEO,EAAE,EAAEC,QAAQ,EAAsC,GAAA;YACzD,MAAM,EAAEC,EAAE,EAAE,GAAG,MAAMC,4DACnBd,WAAAA,EACAe,iBAAAA,CAAQC,MAAM,EACdC,wBAAAA,EACAN,EAAAA,CAAAA;AAGF,YAAA,MAAMO,UAAU,MAAMZ,aAAAA,CAAca,cAAc,CAACR,IAAIC,QAAAA,EAAiB;AAAEX,gBAAAA;AAAK,aAAA,CAAA;;AAG/E,YAAA,MAAMmB,UAAAA,GAAa,MAAMb,gBAAAA,CAAW,MAAA,CAAA,CAAQc,YAAY,CAACH,OAAAA,CAAAA;YAEzD,OAAOL,EAAAA,CAAGS,cAAc,CAACF,UAAAA,EAAY;AAAEG,gBAAAA,MAAAA,EAAQR,kBAAQS;AAAK,aAAA,CAAA;AAC9D,QAAA,CAAA,CAAA;AAGF1B,QAAAA,GAAAA,CAAIK,IAAI,GAAGK,OAAAA;AACb,IAAA,CAAA;AAEA,IAAA,MAAMW,gBAAerB,GAAY,EAAA;AAC/B,QAAA,MAAM,EACJC,KAAAA,EAAO,EAAEC,WAAW,EAAEC,IAAI,EAAE,EAC5BwB,KAAAA,EAAO,EAAEd,EAAE,EAAE,EACbT,OAAAA,EAAS,EAAEC,IAAI,EAAE,EAClB,GAAGL,GAAAA;QAEJ,IAAI,OAAOa,OAAO,QAAA,EAAU;YAC1B,MAAM,IAAIe,YAAAA,CAAOC,eAAe,CAAC,qBAAA,CAAA;AACnC,QAAA;AAEA,QAAA,MAAMrB,gBAAgBC,gBAAAA,CAAW,QAAA,CAAA;QACjC,MAAM,EAAEM,EAAE,EAAE,GAAG,MAAMC,4DACnBd,WAAAA,EACAe,iBAAAA,CAAQC,MAAM,EACdC,wBAAAA,EACAN,EAAAA,CAAAA;QAGF,MAAMiB,IAAAA,GAAO,MAAMC,yBAAAA,CAAmB1B,IAAAA,CAAAA;QAEtC,MAAM2B,IAAAA,GAAO,MAAMxB,aAAAA,CAAca,cAAc,CAACR,EAAAA,EAAIiB,IAAAA,CAAKhB,QAAQ,EAAS;AAAEX,YAAAA;AAAK,SAAA,CAAA;;AAGjF,QAAA,MAAMmB,UAAAA,GAAa,MAAMb,gBAAAA,CAAW,MAAA,CAAA,CAAQc,YAAY,CAACS,IAAAA,CAAAA;AAEzDhC,QAAAA,GAAAA,CAAIK,IAAI,GAAG,MAAMU,EAAAA,CAAGS,cAAc,CAACF,UAAAA,EAAY;AAAEG,YAAAA,MAAAA,EAAQR,kBAAQS;AAAK,SAAA,CAAA;AACxE,IAAA,CAAA;AAEA,IAAA,MAAMO,aAAYjC,GAAY,EAAA;QAC5B,MAAM,EACJC,KAAAA,EAAO,EAAEC,WAAW,EAAEC,IAAI,EAAE,EAC5BwB,KAAAA,EAAO,EAAEd,EAAE,EAAE,EACbT,SAAS,EAAEC,IAAI,EAAE6B,KAAAA,EAAO,EAAEA,KAAK,EAAE,GAAG,EAAE,EAAE,EACzC,GAAGlC,GAAAA;QAEJ,IAAI,OAAOa,OAAO,QAAA,EAAU;YAC1B,MAAM,IAAIe,YAAAA,CAAOC,eAAe,CAAC,qBAAA,CAAA;AACnC,QAAA;AAEA,QAAA,MAAMrB,gBAAgBC,gBAAAA,CAAW,QAAA,CAAA;QACjC,MAAM,EAAEM,EAAE,EAAE,GAAG,MAAMC,4DACnBd,WAAAA,EACAe,iBAAAA,CAAQC,MAAM,EACdC,wBAAAA,EACAN,EAAAA,CAAAA;QAGF,IAAIsB,KAAAA,CAAMC,OAAO,CAACF,KAAAA,CAAAA,EAAQ;YACxB,MAAM,IAAIN,YAAAA,CAAOS,gBAAgB,CAAC,0CAAA,CAAA;AACpC,QAAA;AAEA,QAAA,MAAM,EACJC,UAAU,EACVC,YAAY,EACZX,MAAAA,EAAQY,gBAAgB,EACzB,GAAG,MAAMC,mCAAAA,CAAqBP,KAAAA,EAAO7B,IAAAA,EAAMqC,MAAAA,CAAAA;QAC5C,IAAIJ,UAAAA,CAAWK,MAAM,KAAK,CAAA,EAAG;YAC3B,MAAM,IAAIf,aAAOC,eAAe,CAACW,gBAAgB,CAAC,CAAA,CAAE,CAACI,OAAO,CAAA;AAC9D,QAAA;QAEA,MAAMd,IAAAA,GAAQ,MAAMC,yBAAAA,CAAmBQ,YAAAA,CAAAA;AACvC,QAAA,MAAMM,YAAAA,GAAe,MAAMrC,aAAAA,CAAcsC,OAAO,CAACjC,EAAAA,EAAI;AAAEiB,YAAAA,IAAAA;YAAME,IAAAA,EAAMM,UAAU,CAAC,CAAA;SAAG,EAAG;AAAEnC,YAAAA;AAAK,SAAA,CAAA;;;;;AAM3F,QAAA,MAAM4C,oBAAoBtC,gBAAAA,CAAW,YAAA,CAAA;AACrC,QAAA,IAAIoC,cAAcG,IAAAA,EAAMC,UAAAA,CAAW,aAAc,MAAMF,iBAAAA,CAAkBG,SAAS,EAAA,EAAK;YACrF,IAAI;AACF,gBAAA,MAAMC,eAAAA,GAAkB,MAAMJ,iBAAAA,CAAkBK,YAAY,CAAC;AAACP,oBAAAA;AAAa,iBAAA,CAAA;gBAC3E,MAAME,iBAAAA,CAAkBM,yBAAyB,CAAC;AAACR,oBAAAA;AAAa,iBAAA,EAAEM,eAAAA,EAAiBhD,IAAAA,CAAAA;AACrF,YAAA,CAAA,CAAE,OAAOmD,KAAAA,EAAO;AACdZ,gBAAAA,MAAAA,CAAOa,GAAG,CAACC,IAAI,CAAC,iEAAA,EAAmE;AACjFF,oBAAAA,KAAAA,EAAOA,KAAAA,YAAiBG,KAAAA,GAAQH,KAAAA,CAAMV,OAAO,GAAGc,MAAAA,CAAOJ,KAAAA;AACzD,iBAAA,CAAA;AACF,YAAA;AACF,QAAA;;AAGA,QAAA,MAAMhC,UAAAA,GAAa,MAAMb,gBAAAA,CAAW,MAAA,CAAA,CAAQc,YAAY,CAACsB,YAAAA,CAAAA;AAEzD7C,QAAAA,GAAAA,CAAIK,IAAI,GAAG,MAAMU,EAAAA,CAAGS,cAAc,CAACF,UAAAA,EAAY;AAAEG,YAAAA,MAAAA,EAAQR,kBAAQS;AAAK,SAAA,CAAA;AACxE,IAAA,CAAA;AAEA,IAAA,MAAMiC,aAAY3D,GAAY,EAAA;QAC5B,MAAM,EACJC,OAAO,EAAEC,WAAW,EAAEC,IAAI,EAAE,EAC5BC,OAAAA,EAAS,EAAEC,IAAI,EAAE6B,KAAAA,EAAO,EAAEA,KAAK,EAAE,GAAG,EAAE,EAAE,EACzC,GAAGlC,GAAAA;AAEJ,QAAA,MAAMQ,gBAAgBC,gBAAAA,CAAW,QAAA,CAAA;AACjC,QAAA,MAAMM,KAAK2B,MAAAA,CAAOkB,OAAO,CAAC,mBAAA,CAAA,CAAqBC,wBAAwB,CAAC;YACtEC,OAAAA,EAAS5D,WAAAA;AACTuB,YAAAA,MAAAA,EAAQR,kBAAQ8C,MAAM;YACtBC,KAAAA,EAAO7C;AACT,SAAA,CAAA;QAEA,IAAI,CAACJ,EAAAA,CAAGkD,SAAS,EAAE;AACjB,YAAA,OAAOjE,IAAIkE,SAAS,EAAA;AACtB,QAAA;AAEA,QAAA,MAAM,EACJ5B,UAAU,EACVC,YAAY,EACZX,MAAAA,EAAQY,gBAAgB,EACzB,GAAG,MAAMC,mCAAAA,CAAqBP,KAAAA,EAAO7B,IAAAA,EAAMqC,MAAAA,CAAAA;QAC5C,IAAIJ,UAAAA,CAAWK,MAAM,KAAK,CAAA,EAAG;YAC3B,MAAM,IAAIf,aAAOC,eAAe,CAACW,gBAAgB,CAAC,CAAA,CAAE,CAACI,OAAO,CAAA;AAC9D,QAAA;QAEA,MAAMuB,eAAAA,GAAkB7B,UAAAA,CAAWK,MAAM,GAAG,CAAA;QAC5C,MAAMb,IAAAA,GAAO,MAAMC,yBAAAA,CAAmBQ,YAAAA,EAAc4B,eAAAA,CAAAA;AAEpD,QAAA,IAAIC,UAAAA,GAAa9B,UAAAA;AAEjB,QAAA,IACER,KAAKhB,QAAQ,IACbqB,KAAAA,CAAMC,OAAO,CAACN,IAAAA,CAAKhB,QAAQ,CAAA,IAC3BsD,UAAAA,CAAWzB,MAAM,KAAKb,IAAAA,CAAKhB,QAAQ,CAAC6B,MAAM,EAC1C;;AAEA,YAAA,MAAM0B,oBAAoBvC,IAAAA,CAAKhB,QAAQ,CACpCF,GAAG,CAAC,CAAC0D,IAAAA,GAAAA;gBACJ,OAAOF,UAAAA,CAAWG,IAAI,CAAC,CAACvC,OAASA,IAAAA,CAAKwC,gBAAgB,KAAKF,IAAAA,CAAKG,IAAI,CAAA;AACtE,YAAA,CAAA,CAAA,CACCC,MAAM,CAACC,OAAAA,CAAAA;YAEVP,UAAAA,GAAaC,iBAAAA;AACf,QAAA;;AAGA,QAAA,MAAMO,aAAAA,GAAgB,MAAMpE,aAAAA,CAAcqE,MAAM,CAAC;AAAE/C,YAAAA,IAAAA;YAAMI,KAAAA,EAAOkC;SAAW,EAAG;AAAEjE,YAAAA;AAAK,SAAA,CAAA;QACrF,IAAIyE,aAAAA,CAAcE,IAAI,CAAC,CAAC9C,OAASA,IAAAA,CAAKgB,IAAI,EAAEC,UAAAA,CAAW,QAAA,CAAA,CAAA,EAAY;YACjE,MAAMxC,gBAAAA,CAAW,SAAA,CAAA,CAAWsE,UAAU,CAAC,gBAAA,CAAA;AACzC,QAAA;AAEA,QAAA,MAAMhC,oBAAoBtC,gBAAAA,CAAW,YAAA,CAAA;;QAGrC,IAAI,MAAMsC,iBAAAA,CAAkBG,SAAS,EAAA,EAAI;YACvC,IAAI;AACF,gBAAA,MAAMC,eAAAA,GAAkB,MAAMJ,iBAAAA,CAAkBK,YAAY,CAACwB,aAAAA,CAAAA;;AAE7D,gBAAA,MAAM7B,iBAAAA,CAAkBM,yBAAyB,CAACuB,aAAAA,EAAezB,eAAAA,EAAiBhD,IAAAA,CAAAA;AACpF,YAAA,CAAA,CAAE,OAAOmD,KAAAA,EAAO;AACdZ,gBAAAA,MAAAA,CAAOa,GAAG,CAACC,IAAI,CAAC,mEAAA,EAAqE;AACnFF,oBAAAA,KAAAA,EAAOA,KAAAA,YAAiBG,KAAAA,GAAQH,KAAAA,CAAMV,OAAO,GAAGc,MAAAA,CAAOJ,KAAAA;AACzD,iBAAA,CAAA;AACF,YAAA;AACF,QAAA;;QAGA,MAAM0B,WAAAA,GAAc,MAAMrE,WAAAA,CAAMC,GAAG,CAACgE,aAAAA,EAAenE,gBAAAA,CAAW,QAAQc,YAAY,CAAA;AAElFvB,QAAAA,GAAAA,CAAIK,IAAI,GAAG,MAAMU,EAAAA,CAAGS,cAAc,CAACwD,WAAAA,EAAa;AAAEvD,YAAAA,MAAAA,EAAQR,kBAAQS;AAAK,SAAA,CAAA;AACvE1B,QAAAA,GAAAA,CAAIiF,MAAM,GAAG,GAAA;AACf,IAAA,CAAA;AAEA;;;;;;;;MASA,MAAMC,qBAAoBlF,GAAY,EAAA;QACpC,MAAM,EACJC,OAAO,EAAEC,WAAW,EAAEC,IAAI,EAAE,EAC5BC,OAAAA,EAAS,EAAEC,IAAI,EAAE6B,KAAAA,EAAO,EAAEA,KAAK,EAAE,GAAG,EAAE,EAAE,EACzC,GAAGlC,GAAAA;AAEJ,QAAA,MAAMQ,gBAAgBC,gBAAAA,CAAW,QAAA,CAAA;AACjC,QAAA,MAAMM,KAAK2B,MAAAA,CAAOkB,OAAO,CAAC,mBAAA,CAAA,CAAqBC,wBAAwB,CAAC;YACtEC,OAAAA,EAAS5D,WAAAA;AACTuB,YAAAA,MAAAA,EAAQR,kBAAQ8C,MAAM;YACtBC,KAAAA,EAAO7C;AACT,SAAA,CAAA;QAEA,IAAI,CAACJ,EAAAA,CAAGkD,SAAS,EAAE;AACjB,YAAA,OAAOjE,IAAIkE,SAAS,EAAA;AACtB,QAAA;AAEA,QAAA,IAAIiB,CAAAA,CAAEC,OAAO,CAAClD,KAAAA,CAAAA,IAAW,CAACC,KAAAA,CAAMC,OAAO,CAACF,KAAAA,CAAAA,IAAUA,KAAAA,CAAMmD,IAAI,KAAK,CAAA,EAAI;YACnE,MAAM,IAAIzD,YAAAA,CAAOS,gBAAgB,CAAC,iBAAA,CAAA;AACpC,QAAA;;QAGA,MAAML,IAAAA,GAAOG,MAAMC,OAAO,CAACF,SAASA,KAAK,CAAC,EAAE,GAAGA,KAAAA;QAC/C,MAAMoD,QAAAA,GAAWtD,IAAAA,CAAKwC,gBAAgB,IAAI,SAAA;;AAG1C,QAAA,IAAI1D,QAAAA,GAA2B;YAC7B2D,IAAAA,EAAMa,QAAAA;YACNC,OAAAA,EAAS,IAAA;YACTC,eAAAA,EAAiB,IAAA;YACjBC,MAAAA,EAAQ;AACV,SAAA;AACA,QAAA,IAAIpF,MAAMS,QAAAA,EAAU;YAClB,MAAM4E,GAAAA,GAAMrF,KAAKS,QAAQ;YACzB,IAAI,OAAO4E,QAAQ,QAAA,EAAU;gBAC3B5E,QAAAA,GAAW6E,IAAAA,CAAKC,KAAK,CAACF,GAAAA,CAAAA;AACxB,YAAA,CAAA,MAAO,IAAIvD,KAAAA,CAAMC,OAAO,CAACsD,GAAAA,CAAAA,EAAM;AAC7B5E,gBAAAA,QAAAA,GAAY,OAAO4E,GAAG,CAAC,CAAA,CAAE,KAAK,QAAA,GAAWC,IAAAA,CAAKC,KAAK,CAACF,GAAG,CAAC,CAAA,CAAE,CAAA,GAAIA,GAAG,CAAC,CAAA,CAAE;YACtE,CAAA,MAAO;gBACL5E,QAAAA,GAAW4E,GAAAA;AACb,YAAA;AACF,QAAA;;QAGA,MAAM,EAAEpD,UAAU,EAAEV,MAAAA,EAAQY,gBAAgB,EAAE,GAAG,MAAMC,mCAAAA,CACrDT,IAAAA,EACA;YAAElB,QAAAA,EAAU6E,IAAAA,CAAKE,SAAS,CAAC/E,QAAAA;SAAU,EACrC4B,MAAAA,CAAAA;QAGF,IAAIJ,UAAAA,CAAWK,MAAM,KAAK,CAAA,EAAG;YAC3B,MAAM,IAAIf,aAAOC,eAAe,CAACW,gBAAgB,CAAC,CAAA,CAAE,EAAEI,OAAAA,IAAW,mBAAA,CAAA;AACnE,QAAA;QAEA,MAAMd,IAAAA,GAAO,MAAMC,yBAAAA,CAAmB;AAAEjB,YAAAA;SAAS,EAAG,KAAA,CAAA;AACpD,QAAA,MAAM,CAACgF,YAAAA,CAAa,GAAG,MAAMtF,aAAAA,CAAcqE,MAAM,CAAC;AAAE/C,YAAAA,IAAAA;YAAMI,KAAAA,EAAO;AAACI,gBAAAA,UAAU,CAAC,CAAA;AAAG;SAAC,EAAG;AAAEnC,YAAAA;AAAK,SAAA,CAAA;AAE3F,QAAA,IAAI2F,YAAAA,CAAa9C,IAAI,EAAEC,UAAAA,CAAW,QAAA,CAAA,EAAW;YAC3C,MAAMxC,gBAAAA,CAAW,SAAA,CAAA,CAAWsE,UAAU,CAAC,gBAAA,CAAA;AACzC,QAAA;;;AAKA,QAAA,MAAMzD,UAAAA,GAAa,MAAMb,gBAAAA,CAAW,MAAA,CAAA,CAAQc,YAAY,CAACuE,YAAAA,CAAAA;AAEzD9F,QAAAA,GAAAA,CAAIK,IAAI,GAAG,MAAMU,EAAAA,CAAGS,cAAc,CAACF,UAAAA,EAAY;AAAEG,YAAAA,MAAAA,EAAQR,kBAAQS;AAAK,SAAA,CAAA;AACtE1B,QAAAA,GAAAA,CAAIiF,MAAM,GAAG,GAAA;AACf,IAAA,CAAA;AAEA;;;;;;;;;;;MAYA,MAAMc,yBAAwB/F,GAAY,EAAA;AACxC,QAAA,MAAM,EACJC,KAAAA,EAAO,EAAEC,WAAW,EAAEC,IAAI,EAAE,EAC5BC,OAAAA,EAAS,EAAEC,IAAI,EAAE,EAClB,GAAGL,GAAAA;AAEJ,QAAA,MAAMQ,gBAAgBC,gBAAAA,CAAW,QAAA,CAAA;AACjC,QAAA,MAAMuF,cAAcvF,gBAAAA,CAAW,MAAA,CAAA;AAC/B,QAAA,MAAMM,KAAK2B,MAAAA,CAAOkB,OAAO,CAAC,mBAAA,CAAA,CAAqBC,wBAAwB,CAAC;YACtEC,OAAAA,EAAS5D,WAAAA;AACTuB,YAAAA,MAAAA,EAAQR,kBAAQ8C,MAAM;YACtBC,KAAAA,EAAO7C;AACT,SAAA,CAAA;QAEA,IAAI,CAACJ,EAAAA,CAAGkD,SAAS,EAAE;AACjB,YAAA,OAAOjE,IAAIkE,SAAS,EAAA;AACtB,QAAA;;AAGA,QAAA,MAAM,EAAE+B,IAAI,EAAEC,QAAQ,EAAE,GAAG7F,IAAAA;QAE3B,IAAI,CAAC4F,IAAAA,IAAQ,CAAC9D,KAAAA,CAAMC,OAAO,CAAC6D,IAAAA,CAAAA,IAASA,IAAAA,CAAKtD,MAAM,KAAK,CAAA,EAAG;YACtD,MAAM,IAAIf,YAAAA,CAAOS,gBAAgB,CAAC,mBAAA,CAAA;AACpC,QAAA;QAEA,IAAI4D,IAAAA,CAAKtD,MAAM,GAAG,EAAA,EAAI;YACpB,MAAM,IAAIf,YAAAA,CAAOS,gBAAgB,CAAC,qCAAA,CAAA;AACpC,QAAA;;AAGArC,QAAAA,GAAAA,CAAImG,OAAO,GAAG,KAAA;QACd,MAAMC,GAAAA,GAAMpG,IAAIoG,GAAG;QACnBA,GAAAA,CAAIC,SAAS,CAAC,GAAA,EAAK;YACjB,cAAA,EAAgB,mBAAA;YAChB,eAAA,EAAiB,UAAA;YACjBC,UAAAA,EAAY;AACd,SAAA,CAAA;QAEA,MAAMC,QAAAA,GAAW,CAACC,KAAAA,EAAe1E,IAAAA,GAAAA;AAC/BsE,YAAAA,GAAAA,CAAIK,KAAK,CAAC,CAAC,OAAO,EAAED,KAAAA,CAAM,QAAQ,EAAEb,IAAAA,CAAKE,SAAS,CAAC/D,IAAAA,CAAAA,CAAM,IAAI,CAAC,CAAA;AAChE,QAAA,CAAA;QAEA,MAAM4E,KAAAA,GAAQT,KAAKtD,MAAM;AACzB,QAAA,MAAMgE,eAAkC,EAAE;AAC1C,QAAA,MAAMC,kBAAyB,EAAE;;QAGjC,MAAMC,mBAAAA,GAAsB,MAAMC,GAAAA,CAAIC,OAAO,CAACC,KAAKC,IAAI,CAACC,EAAAA,CAAGC,MAAM,EAAA,EAAI,oBAAA,CAAA,CAAA;QACrE,MAAM,EAAEC,SAAS,EAAE,GAAG1E,OAAO2E,MAAM,CAACC,GAAG,CAAS,gBAAA,CAAA;QAEhD,IAAI;;YAEF,IAAK,IAAIC,IAAI,CAAA,EAAGA,CAAAA,GAAItB,KAAKtD,MAAM,EAAE4E,KAAK,CAAA,CAAG;gBACvC,MAAMC,GAAAA,GAAMvB,IAAI,CAACsB,CAAAA,CAAE;AAEnBhB,gBAAAA,QAAAA,CAAS,eAAA,EAAiB;AAAEiB,oBAAAA,GAAAA;oBAAKC,KAAAA,EAAOF,CAAAA;AAAGb,oBAAAA;AAAM,iBAAA,CAAA;gBAEjD,IAAI;;oBAEF,MAAM,EAAE1E,IAAI,EAAE,GAAG,MAAMgE,WAAAA,CAAY0B,mBAAmB,CACpDF,GAAAA,EACAX,mBAAAA,EACAO,SAAAA,CAAAA;oBAEF,MAAM9B,QAAAA,GAAWtD,KAAKwC,gBAAgB;AAEtC+B,oBAAAA,QAAAA,CAAS,gBAAA,EAAkB;wBACzB9B,IAAAA,EAAMa,QAAAA;wBACNmC,KAAAA,EAAOF,CAAAA;AACPb,wBAAAA,KAAAA;AACArB,wBAAAA,IAAAA,EAAMrD,KAAKqD;AACb,qBAAA,CAAA;;AAGA,oBAAA,MAAMvE,QAAAA,GAA2B;wBAC/B2D,IAAAA,EAAMa,QAAAA;wBACNC,OAAAA,EAAS,IAAA;wBACTC,eAAAA,EAAiB,IAAA;AACjBC,wBAAAA,MAAAA,EAAQS,QAAAA,IAAY;AACtB,qBAAA;oBAEA,MAAM,EAAE5D,UAAU,EAAEV,MAAAA,EAAQY,gBAAgB,EAAE,GAAG,MAAMC,mCAAAA,CACrDT,IAAAA,EACA;wBAAElB,QAAAA,EAAU6E,IAAAA,CAAKE,SAAS,CAAC/E,QAAAA;qBAAU,EACrC4B,MAAAA,CAAAA;oBAGF,IAAIJ,UAAAA,CAAWK,MAAM,KAAK,CAAA,EAAG;AAC3B,wBAAA,MAAMgF,YAAAA,GAAenF,gBAAgB,CAAC,CAAA,CAAE,EAAEI,OAAAA,IAAW,mBAAA;AACrD+D,wBAAAA,YAAAA,CAAaiB,IAAI,CAAC;4BAAEnD,IAAAA,EAAMa,QAAAA;4BAAU1C,OAAAA,EAAS+E;AAAa,yBAAA,CAAA;AAC1DpB,wBAAAA,QAAAA,CAAS,YAAA,EAAc;4BAAE9B,IAAAA,EAAMa,QAAAA;AAAUkC,4BAAAA,GAAAA;4BAAKC,KAAAA,EAAOF,CAAAA;4BAAG3E,OAAAA,EAAS+E;AAAa,yBAAA,CAAA;oBAChF,CAAA,MAAO;;wBAEL,MAAM7F,IAAAA,GAAO,MAAMC,yBAAAA,CAAmB;AAAEjB,4BAAAA;yBAAS,EAAG,KAAA,CAAA;AACpD,wBAAA,MAAM,CAACgF,YAAAA,CAAa,GAAG,MAAMtF,aAAAA,CAAcqE,MAAM,CAC/C;AAAE/C,4BAAAA,IAAAA;4BAAMI,KAAAA,EAAO;AAACI,gCAAAA,UAAU,CAAC,CAAA;AAAG;yBAAC,EAC/B;AAAEnC,4BAAAA;AAAK,yBAAA,CAAA;;AAIT,wBAAA,MAAMmB,UAAAA,GAAa,MAAM0E,WAAAA,CAAYzE,YAAY,CAACuE,YAAAA,CAAAA;AAClDc,wBAAAA,eAAAA,CAAgBgB,IAAI,CAACtG,UAAAA,CAAAA;AAErBiF,wBAAAA,QAAAA,CAAS,eAAA,EAAiB;4BAAE9B,IAAAA,EAAMa,QAAAA;4BAAUmC,KAAAA,EAAOF,CAAAA;4BAAGvF,IAAAA,EAAMV;AAAW,yBAAA,CAAA;AACzE,oBAAA;AACF,gBAAA,CAAA,CAAE,OAAOgC,KAAAA,EAAO;AACd,oBAAA,MAAMqE,eAAerE,KAAAA,YAAiBG,KAAAA,GAAQH,KAAAA,CAAMV,OAAO,GAAGc,MAAAA,CAAOJ,KAAAA,CAAAA;AACrEqD,oBAAAA,YAAAA,CAAaiB,IAAI,CAAC;wBAAEnD,IAAAA,EAAM+C,GAAAA;wBAAK5E,OAAAA,EAAS+E;AAAa,qBAAA,CAAA;AACrDpB,oBAAAA,QAAAA,CAAS,YAAA,EAAc;AAAEiB,wBAAAA,GAAAA;wBAAKC,KAAAA,EAAOF,CAAAA;wBAAG3E,OAAAA,EAAS+E;AAAa,qBAAA,CAAA;AAChE,gBAAA;AACF,YAAA;;YAGA,IAAIf,eAAAA,CAAgB9B,IAAI,CAAC,CAAC9C,OAASA,IAAAA,CAAKgB,IAAI,EAAEC,UAAAA,CAAW,QAAA,CAAA,CAAA,EAAY;gBACnE,MAAMxC,gBAAAA,CAAW,SAAA,CAAA,CAAWsE,UAAU,CAAC,gBAAA,CAAA;AACzC,YAAA;;AAGAwB,YAAAA,QAAAA,CAAS,iBAAA,EAAmB;AAC1BzE,gBAAAA,IAAAA,EAAM,MAAMf,EAAAA,CAAGS,cAAc,CAACoF,eAAAA,EAAiB;AAAEnF,oBAAAA,MAAAA,EAAQR,kBAAQS;AAAK,iBAAA,CAAA;gBACtEE,MAAAA,EAAQ+E;AACV,aAAA,CAAA;QACF,CAAA,QAAU;;YAER,MAAMG,GAAAA,CAAIe,MAAM,CAAChB,mBAAAA,CAAAA;AACnB,QAAA;AAEAT,QAAAA,GAAAA,CAAI0B,GAAG,EAAA;AACT,IAAA,CAAA;;AAGA,IAAA,MAAMjD,QAAO7E,GAAY,EAAA;AACvB,QAAA,MAAM,EACJ2B,KAAAA,EAAO,EAAEd,EAAE,EAAE,EACbT,OAAAA,EAAS,EAAE8B,KAAAA,EAAO,EAAEA,KAAK,EAAE,GAAG,EAAE,EAAE,EACnC,GAAGlC,GAAAA;AAEJ,QAAA,IAAImF,CAAAA,CAAEC,OAAO,CAAClD,KAAAA,CAAAA,IAAW,CAACC,KAAAA,CAAMC,OAAO,CAACF,KAAAA,CAAAA,IAAUA,KAAAA,CAAMmD,IAAI,KAAK,CAAA,EAAI;AACnE,YAAA,IAAIxE,EAAAA,EAAI;gBACN,OAAO,IAAI,CAACQ,cAAc,CAACrB,GAAAA,CAAAA;AAC7B,YAAA;YAEA,MAAM,IAAI4B,YAAAA,CAAOS,gBAAgB,CAAC,iBAAA,CAAA;AACpC,QAAA;QAEA,MAAOxB,CAAAA,EAAAA,GAAK,IAAI,CAACoB,WAAW,GAAG,IAAI,CAAC0B,WAAU,EAAG3D,GAAAA,CAAAA;AACnD,IAAA;AACF,CAAA;;;;"}