@strapi/upload 5.35.0 → 5.36.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/future/App.js +8 -20
- package/dist/admin/future/App.js.map +1 -1
- package/dist/admin/future/App.mjs +8 -20
- package/dist/admin/future/App.mjs.map +1 -1
- package/dist/admin/future/components/UploadProgressDialog.js +494 -0
- package/dist/admin/future/components/UploadProgressDialog.js.map +1 -0
- package/dist/admin/future/components/UploadProgressDialog.mjs +473 -0
- package/dist/admin/future/components/UploadProgressDialog.mjs.map +1 -0
- package/dist/admin/future/enums.js +12 -0
- package/dist/admin/future/enums.js.map +1 -0
- package/dist/admin/future/enums.mjs +10 -0
- package/dist/admin/future/enums.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/AssetsPage.js +311 -0
- package/dist/admin/future/pages/Assets/AssetsPage.js.map +1 -0
- package/dist/admin/future/pages/Assets/AssetsPage.mjs +290 -0
- package/dist/admin/future/pages/Assets/AssetsPage.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/AssetsGrid.js +164 -0
- package/dist/admin/future/pages/Assets/components/AssetsGrid.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs +162 -0
- package/dist/admin/future/pages/Assets/components/AssetsGrid.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/AssetsTable.js +198 -0
- package/dist/admin/future/pages/Assets/components/AssetsTable.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/AssetsTable.mjs +196 -0
- package/dist/admin/future/pages/Assets/components/AssetsTable.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZone.js +127 -0
- package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZone.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZone.mjs +105 -0
- package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZone.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.js +107 -0
- package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.js.map +1 -0
- package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.mjs +104 -0
- package/dist/admin/future/pages/Assets/components/DropZone/UploadDropZoneContext.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/constants.js +54 -0
- package/dist/admin/future/pages/Assets/constants.js.map +1 -0
- package/dist/admin/future/pages/Assets/constants.mjs +50 -0
- package/dist/admin/future/pages/Assets/constants.mjs.map +1 -0
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js +77 -0
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.js.map +1 -0
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs +74 -0
- package/dist/admin/future/pages/Assets/hooks/useInfiniteAssets.mjs.map +1 -0
- package/dist/admin/future/services/api.js +419 -9
- package/dist/admin/future/services/api.js.map +1 -1
- package/dist/admin/future/services/api.mjs +417 -9
- package/dist/admin/future/services/api.mjs.map +1 -1
- package/dist/admin/future/services/assets.js +37 -0
- package/dist/admin/future/services/assets.js.map +1 -0
- package/dist/admin/future/services/assets.mjs +35 -0
- package/dist/admin/future/services/assets.mjs.map +1 -0
- package/dist/admin/future/store/hooks.js +10 -0
- package/dist/admin/future/store/hooks.js.map +1 -0
- package/dist/admin/future/store/hooks.mjs +7 -0
- package/dist/admin/future/store/hooks.mjs.map +1 -0
- package/dist/admin/future/store/uploadProgress.js +156 -0
- package/dist/admin/future/store/uploadProgress.js.map +1 -0
- package/dist/admin/future/store/uploadProgress.mjs +143 -0
- package/dist/admin/future/store/uploadProgress.mjs.map +1 -0
- package/dist/admin/future/utils/files.js +23 -0
- package/dist/admin/future/utils/files.js.map +1 -0
- package/dist/admin/future/utils/files.mjs +19 -0
- package/dist/admin/future/utils/files.mjs.map +1 -0
- package/dist/admin/future/utils/getAssetIcon.js +28 -0
- package/dist/admin/future/utils/getAssetIcon.js.map +1 -0
- package/dist/admin/future/utils/getAssetIcon.mjs +26 -0
- package/dist/admin/future/utils/getAssetIcon.mjs.map +1 -0
- package/dist/admin/index.js +11 -0
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +11 -0
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/package.json.js +11 -9
- package/dist/admin/package.json.js.map +1 -1
- package/dist/admin/package.json.mjs +11 -9
- package/dist/admin/package.json.mjs.map +1 -1
- package/dist/admin/src/future/components/UploadProgressDialog.d.ts +1 -0
- package/dist/admin/src/future/enums.d.ts +6 -0
- package/dist/admin/src/future/pages/Assets/AssetsPage.d.ts +1 -0
- package/dist/admin/src/future/pages/Assets/components/AssetsGrid.d.ts +6 -0
- package/dist/admin/src/future/pages/Assets/components/AssetsTable.d.ts +6 -0
- package/dist/admin/src/future/pages/Assets/components/DropZone/UploadDropZone.d.ts +9 -0
- package/dist/admin/src/future/pages/Assets/components/DropZone/UploadDropZoneContext.d.ts +11 -0
- package/dist/admin/src/future/pages/Assets/constants.d.ts +17 -0
- package/dist/admin/src/future/pages/Assets/hooks/useInfiniteAssets.d.ts +17 -0
- package/dist/admin/src/future/services/api.d.ts +21 -3
- package/dist/admin/src/future/services/assets.d.ts +13 -0
- package/dist/admin/src/future/store/hooks.d.ts +6 -0
- package/dist/admin/src/future/store/uploadProgress.d.ts +46 -0
- package/dist/admin/src/future/utils/files.d.ts +3 -0
- package/dist/admin/src/future/utils/getAssetIcon.d.ts +12 -0
- package/dist/admin/translations/en.json.js +25 -0
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +25 -0
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/server/controllers/admin-upload.js +151 -2
- package/dist/server/controllers/admin-upload.js.map +1 -1
- package/dist/server/controllers/admin-upload.mjs +151 -2
- package/dist/server/controllers/admin-upload.mjs.map +1 -1
- package/dist/server/controllers/content-api.js +8 -2
- package/dist/server/controllers/content-api.js.map +1 -1
- package/dist/server/controllers/content-api.mjs +9 -3
- package/dist/server/controllers/content-api.mjs.map +1 -1
- package/dist/server/routes/admin.js +10 -0
- package/dist/server/routes/admin.js.map +1 -1
- package/dist/server/routes/admin.mjs +10 -0
- package/dist/server/routes/admin.mjs.map +1 -1
- package/dist/server/src/controllers/admin-upload.d.ts +12 -0
- package/dist/server/src/controllers/admin-upload.d.ts.map +1 -1
- package/dist/server/src/controllers/content-api.d.ts.map +1 -1
- package/dist/server/src/controllers/index.d.ts +1 -0
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +1 -0
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/routes/admin.d.ts.map +1 -1
- package/dist/server/src/utils/mime-validation.d.ts +5 -0
- package/dist/server/src/utils/mime-validation.d.ts.map +1 -1
- package/dist/server/utils/mime-validation.js +7 -4
- package/dist/server/utils/mime-validation.js.map +1 -1
- package/dist/server/utils/mime-validation.mjs +7 -4
- package/dist/server/utils/mime-validation.mjs.map +1 -1
- package/dist/shared/contracts/files.d.ts +52 -0
- package/dist/shared/contracts/files.d.ts.map +1 -0
- package/package.json +11 -9
- package/dist/admin/future/pages/AIGenerationPage.js +0 -24
- package/dist/admin/future/pages/AIGenerationPage.js.map +0 -1
- package/dist/admin/future/pages/AIGenerationPage.mjs +0 -22
- package/dist/admin/future/pages/AIGenerationPage.mjs.map +0 -1
- package/dist/admin/future/pages/MediaLibraryPage.js +0 -119
- package/dist/admin/future/pages/MediaLibraryPage.js.map +0 -1
- package/dist/admin/future/pages/MediaLibraryPage.mjs +0 -98
- package/dist/admin/future/pages/MediaLibraryPage.mjs.map +0 -1
- package/dist/admin/src/future/pages/AIGenerationPage.d.ts +0 -1
- package/dist/admin/src/future/pages/MediaLibraryPage.d.ts +0 -1
|
@@ -47,6 +47,16 @@ const routes = {
|
|
|
47
47
|
]
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
|
+
{
|
|
51
|
+
method: 'POST',
|
|
52
|
+
path: '/unstable/stream',
|
|
53
|
+
handler: 'admin-upload.unstable_uploadFilesStream',
|
|
54
|
+
config: {
|
|
55
|
+
policies: [
|
|
56
|
+
'admin::isAuthenticatedAdmin'
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
},
|
|
50
60
|
{
|
|
51
61
|
method: 'GET',
|
|
52
62
|
path: '/files',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.mjs","sources":["../../../server/src/routes/admin.ts"],"sourcesContent":["export const routes = {\n type: 'admin',\n routes: [\n {\n method: 'GET',\n path: '/settings',\n handler: 'admin-settings.getSettings',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.settings.read'],\n },\n },\n ],\n },\n },\n {\n method: 'PUT',\n path: '/settings',\n handler: 'admin-settings.updateSettings',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.settings.read'],\n },\n },\n ],\n },\n },\n {\n method: 'POST',\n path: '/',\n handler: 'admin-upload.upload',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n {\n method: 'GET',\n path: '/files',\n handler: 'admin-file.find',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.read'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/files/:id',\n handler: 'admin-file.findOne',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.read'],\n },\n },\n ],\n },\n },\n {\n method: 'DELETE',\n path: '/files/:id',\n handler: 'admin-file.destroy',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.assets.update'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/folders/:id',\n handler: 'admin-folder.findOne',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.read'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/folders',\n handler: 'admin-folder.find',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.read'],\n },\n },\n ],\n },\n },\n {\n method: 'POST',\n path: '/folders',\n handler: 'admin-folder.create',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.assets.create'],\n },\n },\n ],\n },\n },\n {\n method: 'PUT',\n path: '/folders/:id',\n handler: 'admin-folder.update',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.assets.update'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/folder-structure',\n handler: 'admin-folder.getStructure',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.read'],\n },\n },\n ],\n },\n },\n {\n method: 'POST',\n path: '/actions/bulk-delete',\n handler: 'admin-folder-file.deleteMany',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.assets.update'],\n },\n },\n ],\n },\n },\n {\n method: 'POST',\n path: '/actions/bulk-move',\n handler: 'admin-folder-file.moveMany',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.assets.update'],\n },\n },\n ],\n },\n },\n {\n method: 'POST',\n path: '/actions/bulk-update',\n handler: 'admin-upload.bulkUpdateFileInfo',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.assets.update'],\n },\n },\n ],\n },\n },\n {\n method: 'POST',\n path: '/actions/generate-ai-metadata',\n handler: 'admin-file.generateAIMetadata',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.assets.update'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/actions/generate-ai-metadata/count',\n handler: 'admin-file.getAIMetadataCount',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.read'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/actions/generate-ai-metadata/latest',\n handler: 'admin-file.getLatestAIMetadataJob',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n ],\n};\n"],"names":["routes","type","method","path","handler","config","policies","name","actions"],"mappings":"MAAaA,MAAS,GAAA;IACpBC,IAAM,EAAA,OAAA;IACND,MAAQ,EAAA;AACN,QAAA;YACEE,MAAQ,EAAA,KAAA;YACRC,IAAM,EAAA,WAAA;YACNC,OAAS,EAAA,4BAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AACR,oBAAA,6BAAA;AACA,oBAAA;wBACEC,IAAM,EAAA,uBAAA;wBACNF,MAAQ,EAAA;4BACNG,OAAS,EAAA;AAAC,gCAAA;AAA+B;AAC3C;AACF;AACD;AACH;AACF,SAAA;AACA,QAAA;YACEN,MAAQ,EAAA,KAAA;YACRC,IAAM,EAAA,WAAA;YACNC,OAAS,EAAA,+BAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AACR,oBAAA,6BAAA;AACA,oBAAA;wBACEC,IAAM,EAAA,uBAAA;wBACNF,MAAQ,EAAA;4BACNG,OAAS,EAAA;AAAC,gCAAA;AAA+B;AAC3C;AACF;AACD;AACH;AACF,SAAA;AACA,QAAA;YACEN,MAAQ,EAAA,MAAA;YACRC,IAAM,EAAA,GAAA;YACNC,OAAS,EAAA,qBAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AAAC,oBAAA;AAA8B;AAC3C;AACF,SAAA;AACA,QAAA;YACEJ,MAAQ,EAAA,KAAA;YACRC,IAAM,EAAA,QAAA;YACNC,OAAS,EAAA,iBAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AACR,oBAAA,6BAAA;AACA,oBAAA;wBACEC,IAAM,EAAA,uBAAA;wBACNF,MAAQ,EAAA;4BACNG,OAAS,EAAA;AAAC,gCAAA;AAAsB;AAClC;AACF;AACD;AACH;AACF,SAAA;AACA,QAAA;YACEN,MAAQ,EAAA,KAAA;YACRC,IAAM,EAAA,YAAA;YACNC,OAAS,EAAA,oBAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AACR,oBAAA,6BAAA;AACA,oBAAA;wBACEC,IAAM,EAAA,uBAAA;wBACNF,MAAQ,EAAA;4BACNG,OAAS,EAAA;AAAC,gCAAA;AAAsB;AAClC;AACF;AACD;AACH;AACF,SAAA;AACA,QAAA;YACEN,MAAQ,EAAA,QAAA;YACRC,IAAM,EAAA,YAAA;YACNC,OAAS,EAAA,oBAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AACR,oBAAA,6BAAA;AACA,oBAAA;wBACEC,IAAM,EAAA,uBAAA;wBACNF,MAAQ,EAAA;4BACNG,OAAS,EAAA;AAAC,gCAAA;AAA+B;AAC3C;AACF;AACD;AACH;AACF,SAAA;AACA,QAAA;YACEN,MAAQ,EAAA,KAAA;YACRC,IAAM,EAAA,cAAA;YACNC,OAAS,EAAA,sBAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AACR,oBAAA,6BAAA;AACA,oBAAA;wBACEC,IAAM,EAAA,uBAAA;wBACNF,MAAQ,EAAA;4BACNG,OAAS,EAAA;AAAC,gCAAA;AAAsB;AAClC;AACF;AACD;AACH;AACF,SAAA;AACA,QAAA;YACEN,MAAQ,EAAA,KAAA;YACRC,IAAM,EAAA,UAAA;YACNC,OAAS,EAAA,mBAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AACR,oBAAA,6BAAA;AACA,oBAAA;wBACEC,IAAM,EAAA,uBAAA;wBACNF,MAAQ,EAAA;4BACNG,OAAS,EAAA;AAAC,gCAAA;AAAsB;AAClC;AACF;AACD;AACH;AACF,SAAA;AACA,QAAA;YACEN,MAAQ,EAAA,MAAA;YACRC,IAAM,EAAA,UAAA;YACNC,OAAS,EAAA,qBAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AACR,oBAAA,6BAAA;AACA,oBAAA;wBACEC,IAAM,EAAA,uBAAA;wBACNF,MAAQ,EAAA;4BACNG,OAAS,EAAA;AAAC,gCAAA;AAA+B;AAC3C;AACF;AACD;AACH;AACF,SAAA;AACA,QAAA;YACEN,MAAQ,EAAA,KAAA;YACRC,IAAM,EAAA,cAAA;YACNC,OAAS,EAAA,qBAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AACR,oBAAA,6BAAA;AACA,oBAAA;wBACEC,IAAM,EAAA,uBAAA;wBACNF,MAAQ,EAAA;4BACNG,OAAS,EAAA;AAAC,gCAAA;AAA+B;AAC3C;AACF;AACD;AACH;AACF,SAAA;AACA,QAAA;YACEN,MAAQ,EAAA,KAAA;YACRC,IAAM,EAAA,mBAAA;YACNC,OAAS,EAAA,2BAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AACR,oBAAA,6BAAA;AACA,oBAAA;wBACEC,IAAM,EAAA,uBAAA;wBACNF,MAAQ,EAAA;4BACNG,OAAS,EAAA;AAAC,gCAAA;AAAsB;AAClC;AACF;AACD;AACH;AACF,SAAA;AACA,QAAA;YACEN,MAAQ,EAAA,MAAA;YACRC,IAAM,EAAA,sBAAA;YACNC,OAAS,EAAA,8BAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AACR,oBAAA,6BAAA;AACA,oBAAA;wBACEC,IAAM,EAAA,uBAAA;wBACNF,MAAQ,EAAA;4BACNG,OAAS,EAAA;AAAC,gCAAA;AAA+B;AAC3C;AACF;AACD;AACH;AACF,SAAA;AACA,QAAA;YACEN,MAAQ,EAAA,MAAA;YACRC,IAAM,EAAA,oBAAA;YACNC,OAAS,EAAA,4BAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AACR,oBAAA,6BAAA;AACA,oBAAA;wBACEC,IAAM,EAAA,uBAAA;wBACNF,MAAQ,EAAA;4BACNG,OAAS,EAAA;AAAC,gCAAA;AAA+B;AAC3C;AACF;AACD;AACH;AACF,SAAA;AACA,QAAA;YACEN,MAAQ,EAAA,MAAA;YACRC,IAAM,EAAA,sBAAA;YACNC,OAAS,EAAA,iCAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AACR,oBAAA,6BAAA;AACA,oBAAA;wBACEC,IAAM,EAAA,uBAAA;wBACNF,MAAQ,EAAA;4BACNG,OAAS,EAAA;AAAC,gCAAA;AAA+B;AAC3C;AACF;AACD;AACH;AACF,SAAA;AACA,QAAA;YACEN,MAAQ,EAAA,MAAA;YACRC,IAAM,EAAA,+BAAA;YACNC,OAAS,EAAA,+BAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AACR,oBAAA,6BAAA;AACA,oBAAA;wBACEC,IAAM,EAAA,uBAAA;wBACNF,MAAQ,EAAA;4BACNG,OAAS,EAAA;AAAC,gCAAA;AAA+B;AAC3C;AACF;AACD;AACH;AACF,SAAA;AACA,QAAA;YACEN,MAAQ,EAAA,KAAA;YACRC,IAAM,EAAA,qCAAA;YACNC,OAAS,EAAA,+BAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AACR,oBAAA,6BAAA;AACA,oBAAA;wBACEC,IAAM,EAAA,uBAAA;wBACNF,MAAQ,EAAA;4BACNG,OAAS,EAAA;AAAC,gCAAA;AAAsB;AAClC;AACF;AACD;AACH;AACF,SAAA;AACA,QAAA;YACEN,MAAQ,EAAA,KAAA;YACRC,IAAM,EAAA,sCAAA;YACNC,OAAS,EAAA,mCAAA;YACTC,MAAQ,EAAA;gBACNC,QAAU,EAAA;AAAC,oBAAA;AAA8B;AAC3C;AACF;AACD;AACH;;;;"}
|
|
1
|
+
{"version":3,"file":"admin.mjs","sources":["../../../server/src/routes/admin.ts"],"sourcesContent":["export const routes = {\n type: 'admin',\n routes: [\n {\n method: 'GET',\n path: '/settings',\n handler: 'admin-settings.getSettings',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.settings.read'],\n },\n },\n ],\n },\n },\n {\n method: 'PUT',\n path: '/settings',\n handler: 'admin-settings.updateSettings',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.settings.read'],\n },\n },\n ],\n },\n },\n {\n method: 'POST',\n path: '/',\n handler: 'admin-upload.upload',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n {\n method: 'POST',\n path: '/unstable/stream',\n handler: 'admin-upload.unstable_uploadFilesStream',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n {\n method: 'GET',\n path: '/files',\n handler: 'admin-file.find',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.read'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/files/:id',\n handler: 'admin-file.findOne',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.read'],\n },\n },\n ],\n },\n },\n {\n method: 'DELETE',\n path: '/files/:id',\n handler: 'admin-file.destroy',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.assets.update'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/folders/:id',\n handler: 'admin-folder.findOne',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.read'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/folders',\n handler: 'admin-folder.find',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.read'],\n },\n },\n ],\n },\n },\n {\n method: 'POST',\n path: '/folders',\n handler: 'admin-folder.create',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.assets.create'],\n },\n },\n ],\n },\n },\n {\n method: 'PUT',\n path: '/folders/:id',\n handler: 'admin-folder.update',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.assets.update'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/folder-structure',\n handler: 'admin-folder.getStructure',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.read'],\n },\n },\n ],\n },\n },\n {\n method: 'POST',\n path: '/actions/bulk-delete',\n handler: 'admin-folder-file.deleteMany',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.assets.update'],\n },\n },\n ],\n },\n },\n {\n method: 'POST',\n path: '/actions/bulk-move',\n handler: 'admin-folder-file.moveMany',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.assets.update'],\n },\n },\n ],\n },\n },\n {\n method: 'POST',\n path: '/actions/bulk-update',\n handler: 'admin-upload.bulkUpdateFileInfo',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.assets.update'],\n },\n },\n ],\n },\n },\n {\n method: 'POST',\n path: '/actions/generate-ai-metadata',\n handler: 'admin-file.generateAIMetadata',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.assets.update'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/actions/generate-ai-metadata/count',\n handler: 'admin-file.getAIMetadataCount',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'admin::hasPermissions',\n config: {\n actions: ['plugin::upload.read'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/actions/generate-ai-metadata/latest',\n handler: 'admin-file.getLatestAIMetadataJob',\n config: {\n policies: ['admin::isAuthenticatedAdmin'],\n },\n },\n ],\n};\n"],"names":["routes","type","method","path","handler","config","policies","name","actions"],"mappings":"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"}
|
|
@@ -4,6 +4,18 @@ declare const _default: {
|
|
|
4
4
|
updateFileInfo(ctx: Context): Promise<void>;
|
|
5
5
|
replaceFile(ctx: Context): Promise<void>;
|
|
6
6
|
uploadFiles(ctx: Context): Promise<Context | undefined>;
|
|
7
|
+
/**
|
|
8
|
+
* @experimental
|
|
9
|
+
* Stream upload files with SSE streaming for per-file progress
|
|
10
|
+
*
|
|
11
|
+
* Streams Server-Sent Events as each file is validated and uploaded:
|
|
12
|
+
* - file:uploading — when processing starts for a file
|
|
13
|
+
* - file:complete — when a file is successfully uploaded
|
|
14
|
+
* - file:error — when a file fails validation or upload
|
|
15
|
+
* - stream:complete — final summary with all results
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
unstable_uploadFilesStream(ctx: Context): Promise<Context | undefined>;
|
|
7
19
|
upload(ctx: Context): Promise<void>;
|
|
8
20
|
};
|
|
9
21
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-upload.d.ts","sourceRoot":"","sources":["../../../../server/src/controllers/admin-upload.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;;
|
|
1
|
+
{"version":3,"file":"admin-upload.d.ts","sourceRoot":"","sources":["../../../../server/src/controllers/admin-upload.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;;4BAWH,OAAO;wBA2BX,OAAO;qBA0BV,OAAO;qBAyCP,OAAO;IA0E9B;;;;;;;;;;OAUG;oCACmC,OAAO;gBA0H3B,OAAO;;AA9S3B,wBA8TE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-api.d.ts","sourceRoot":"","sources":["../../../../server/src/controllers/content-api.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACnC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;qCAUd;IAAE,MAAM,EAAE,KAAK,MAAM,CAAA;CAAE;cAuB/B,OAAO;iBASJ,OAAO;iBAiBP,OAAO;wBAgBA,OAAO;qBAgBV,OAAO;
|
|
1
|
+
{"version":3,"file":"content-api.d.ts","sourceRoot":"","sources":["../../../../server/src/controllers/content-api.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACnC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;qCAUd;IAAE,MAAM,EAAE,KAAK,MAAM,CAAA;CAAE;cAuB/B,OAAO;iBASJ,OAAO;iBAiBP,OAAO;wBAgBA,OAAO;qBAgBV,OAAO;qBA+BP,OAAO;gBAyCZ,OAAO;;AAzJ7B,wBA0KE"}
|
|
@@ -36,6 +36,7 @@ export declare const controllers: {
|
|
|
36
36
|
updateFileInfo(ctx: import("koa").Context): Promise<void>;
|
|
37
37
|
replaceFile(ctx: import("koa").Context): Promise<void>;
|
|
38
38
|
uploadFiles(ctx: import("koa").Context): Promise<import("koa").Context | undefined>;
|
|
39
|
+
unstable_uploadFilesStream(ctx: import("koa").Context): Promise<import("koa").Context | undefined>;
|
|
39
40
|
upload(ctx: import("koa").Context): Promise<void>;
|
|
40
41
|
};
|
|
41
42
|
'content-api': ({ strapi }: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/src/controllers/index.ts"],"names":[],"mappings":";AAQA,eAAO,MAAM,WAAW
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/src/controllers/index.ts"],"names":[],"mappings":";AAQA,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAQvB,CAAC"}
|
|
@@ -88,6 +88,7 @@ declare const _default: () => {
|
|
|
88
88
|
updateFileInfo(ctx: import("koa").Context): Promise<void>;
|
|
89
89
|
replaceFile(ctx: import("koa").Context): Promise<void>;
|
|
90
90
|
uploadFiles(ctx: import("koa").Context): Promise<import("koa").Context | undefined>;
|
|
91
|
+
unstable_uploadFilesStream(ctx: import("koa").Context): Promise<import("koa").Context | undefined>;
|
|
91
92
|
upload(ctx: import("koa").Context): Promise<void>;
|
|
92
93
|
};
|
|
93
94
|
'content-api': ({ strapi }: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../server/src/index.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../server/src/index.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOxC,wBAQG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../../../server/src/routes/admin.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../../../server/src/routes/admin.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;CA4QlB,CAAC"}
|
|
@@ -30,9 +30,14 @@ export declare function enforceUploadSecurity(files: any, strapi: Core.Strapi):
|
|
|
30
30
|
validFileNames: string[];
|
|
31
31
|
errors: Array<ErrorDetail>;
|
|
32
32
|
}>;
|
|
33
|
+
export type FileUploadError = {
|
|
34
|
+
name: string;
|
|
35
|
+
message: string;
|
|
36
|
+
};
|
|
33
37
|
export type PrepareUploadResult = {
|
|
34
38
|
validFiles: any[];
|
|
35
39
|
filteredBody: any;
|
|
40
|
+
errors: FileUploadError[];
|
|
36
41
|
};
|
|
37
42
|
/**
|
|
38
43
|
* Prepare files and body for upload by enforcing security and parsing fileInfo
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mime-validation.d.ts","sourceRoot":"","sources":["../../../../server/src/utils/mime-validation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAG1C,MAAM,MAAM,cAAc,GAAG;IAC3B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AACF,KAAK,qBAAqB,GAAG;IAC3B,IAAI,EAAE,uBAAuB,GAAG,kBAAkB,GAAG,eAAe,CAAC;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,qBAAqB,CAAC;CAC/B,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,GAAG,CAAC;IACV,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,qBAAqB,CAAC;CAC9B,CAAC;AAOF,wBAAsB,cAAc,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAmC3E;AAsBD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAcnF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,GAAG;;;EAMxC;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,GAAG,EACT,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,IAAI,CAAC,MAAM,GAClB,OAAO,CAAC,gBAAgB,CAAC,CAoE3B;AAED,wBAAsB,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA6DhG;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,IAAI,CAAC,MAAM,GAClB,OAAO,CAAC;IACT,UAAU,EAAE,GAAG,EAAE,CAAC;IAClB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;CAC5B,CAAC,CAqCD;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,UAAU,EAAE,GAAG,EAAE,CAAC;IAClB,YAAY,EAAE,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"mime-validation.d.ts","sourceRoot":"","sources":["../../../../server/src/utils/mime-validation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAG1C,MAAM,MAAM,cAAc,GAAG;IAC3B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AACF,KAAK,qBAAqB,GAAG;IAC3B,IAAI,EAAE,uBAAuB,GAAG,kBAAkB,GAAG,eAAe,CAAC;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,qBAAqB,CAAC;CAC/B,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,GAAG,CAAC;IACV,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,qBAAqB,CAAC;CAC9B,CAAC;AAOF,wBAAsB,cAAc,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAmC3E;AAsBD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAcnF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,GAAG;;;EAMxC;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,GAAG,EACT,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,IAAI,CAAC,MAAM,GAClB,OAAO,CAAC,gBAAgB,CAAC,CAoE3B;AAED,wBAAsB,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA6DhG;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,IAAI,CAAC,MAAM,GAClB,OAAO,CAAC;IACT,UAAU,EAAE,GAAG,EAAE,CAAC;IAClB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;CAC5B,CAAC,CAqCD;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,UAAU,EAAE,GAAG,EAAE,CAAC;IAClB,YAAY,EAAE,GAAG,CAAC;IAClB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B,CAAC;AAEF;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,GAAG,EACf,IAAI,EAAE,GAAG,EACT,MAAM,EAAE,IAAI,CAAC,MAAM,GAClB,OAAO,CAAC,mBAAmB,CAAC,CAoD9B"}
|
|
@@ -216,9 +216,6 @@ async function enforceUploadSecurity(files, strapi) {
|
|
|
216
216
|
* Prepare files and body for upload by enforcing security and parsing fileInfo
|
|
217
217
|
*/ async function prepareUploadRequest(filesInput, body, strapi) {
|
|
218
218
|
const securityResults = await enforceUploadSecurity(filesInput, strapi);
|
|
219
|
-
if (securityResults.validFiles.length === 0) {
|
|
220
|
-
throw new utils.errors.ValidationError(securityResults.errors[0].error.message, securityResults.errors[0].error.details);
|
|
221
|
-
}
|
|
222
219
|
let filteredBody = body;
|
|
223
220
|
if (body?.fileInfo) {
|
|
224
221
|
// Parse JSON strings in fileInfo
|
|
@@ -250,9 +247,15 @@ async function enforceUploadSecurity(files, strapi) {
|
|
|
250
247
|
};
|
|
251
248
|
}
|
|
252
249
|
}
|
|
250
|
+
// Map errors to simplified format
|
|
251
|
+
const uploadErrors = securityResults.errors.map((e)=>({
|
|
252
|
+
name: e.file?.originalFilename || e.file?.name || 'unknown',
|
|
253
|
+
message: e.error.message
|
|
254
|
+
}));
|
|
253
255
|
return {
|
|
254
256
|
validFiles: securityResults.validFiles,
|
|
255
|
-
filteredBody
|
|
257
|
+
filteredBody,
|
|
258
|
+
errors: uploadErrors
|
|
256
259
|
};
|
|
257
260
|
}
|
|
258
261
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mime-validation.js","sources":["../../../server/src/utils/mime-validation.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport type { Core } from '@strapi/types';\nimport { errors } from '@strapi/utils';\n\nexport type SecurityConfig = {\n allowedTypes?: string[];\n deniedTypes?: string[];\n};\ntype UploadValidationError = {\n code: 'MIME_TYPE_NOT_ALLOWED' | 'VALIDATION_ERROR' | 'UNKNOWN_ERROR';\n message: string;\n details: Record<string, any>;\n};\n\ntype ValidationResult = {\n isValid: boolean;\n error?: UploadValidationError;\n};\n\ntype ErrorDetail = {\n file: any;\n originalIndex: number;\n error: UploadValidationError;\n};\n\nasync function readFileChunk(filePath: string, chunkSize: number = 4100): Promise<Buffer> {\n const buffer = await readFile(filePath);\n return buffer.length > chunkSize ? buffer.subarray(0, chunkSize) : buffer;\n}\n\nexport async function detectMimeType(file: any): Promise<string | undefined> {\n let buffer: Buffer;\n\n const filePath = file.path || file.filepath || file.tempFilePath;\n\n if (filePath) {\n try {\n buffer = await readFileChunk(filePath, 4100);\n } catch (error) {\n throw new Error(\n `Failed to read file: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n } else if (file.buffer) {\n buffer = file.buffer.length > 4100 ? file.buffer.subarray(0, 4100) : file.buffer;\n } else {\n // No file data available\n return undefined;\n }\n\n try {\n /**\n * Use dynamic import to support file-type which is ESM-only\n * Static imports fail during CommonJS build since bundler can't transform ESM-only packages\n * @see https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c\n */\n const { fileTypeFromBuffer } = await import('file-type');\n\n const result = await fileTypeFromBuffer(new Uint8Array(buffer));\n return result?.mime;\n } catch (error) {\n throw new Error(\n `Failed to detect MIME type: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\nfunction matchesMimePattern(mimeType: string, patterns: string[]): boolean {\n if (!patterns?.length) return false;\n\n return patterns.some((pattern) => {\n const normalizedPattern = pattern.toLowerCase();\n const normalizedMimeType = mimeType.toLowerCase();\n\n if (normalizedPattern.includes('*')) {\n const regexPattern = normalizedPattern.replace(/\\*/g, '.*');\n\n const regex = new RegExp(`^${regexPattern}$`);\n const matches = regex.test(normalizedMimeType);\n return matches;\n }\n\n const exactMatch = normalizedPattern === normalizedMimeType;\n return exactMatch;\n });\n}\n\nexport function isMimeTypeAllowed(mimeType: string, config: SecurityConfig): boolean {\n const { allowedTypes, deniedTypes } = config;\n\n if (!mimeType) return false;\n\n if (deniedTypes?.length && matchesMimePattern(mimeType, deniedTypes)) {\n return false;\n }\n\n if (allowedTypes?.length) {\n return matchesMimePattern(mimeType, allowedTypes);\n }\n\n return true;\n}\n\nexport function extractFileInfo(file: any) {\n const fileName =\n file.originalFilename || file.name || file.filename || file.newFilename || 'unknown';\n const declaredMimeType = file.mimetype || file.type || file.mimeType || file.mime || '';\n\n return { fileName, declaredMimeType };\n}\n\nexport async function validateFile(\n file: any,\n config: SecurityConfig,\n strapi: Core.Strapi\n): Promise<ValidationResult> {\n const { allowedTypes, deniedTypes } = config;\n\n if (!allowedTypes && !deniedTypes) {\n return { isValid: true };\n }\n\n const { fileName, declaredMimeType } = extractFileInfo(file);\n\n let detectedMime: string | undefined;\n let mimeDetectionFailed = false;\n\n try {\n detectedMime = await detectMimeType(file);\n } catch (error) {\n mimeDetectionFailed = true;\n strapi.log.warn('Failed to detect MIME type from file', {\n fileName,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n\n const mimeToValidate = detectedMime || declaredMimeType;\n\n if (\n !detectedMime &&\n (declaredMimeType === 'application/octet-stream' || !declaredMimeType || mimeDetectionFailed)\n ) {\n if (allowedTypes?.length || deniedTypes?.length) {\n return {\n isValid: false,\n error: {\n code: 'MIME_TYPE_NOT_ALLOWED',\n message: `Cannot verify file type for security reasons`,\n details: {\n fileName,\n reason: 'Unable to detect MIME type from file content',\n declaredType: declaredMimeType,\n mimeDetectionFailed,\n },\n },\n };\n }\n }\n\n if (\n mimeToValidate &&\n (allowedTypes || deniedTypes) &&\n !isMimeTypeAllowed(mimeToValidate, config)\n ) {\n return {\n isValid: false,\n error: {\n code: 'MIME_TYPE_NOT_ALLOWED',\n message: `File type '${mimeToValidate}' is not allowed`,\n details: {\n fileName,\n detectedType: detectedMime,\n declaredType: declaredMimeType,\n finalType: mimeToValidate,\n allowedTypes,\n deniedTypes,\n },\n },\n };\n }\n\n return { isValid: true };\n}\n\nexport async function validateFiles(files: any, strapi: Core.Strapi): Promise<ValidationResult[]> {\n const filesArray = Array.isArray(files) ? files : [files];\n\n if (!filesArray.length) {\n return [];\n }\n\n const config: SecurityConfig = strapi.config.get('plugin::upload.security', {});\n if (\n config.allowedTypes &&\n (!Array.isArray(config.allowedTypes) ||\n !config.allowedTypes.every((item) => typeof item === 'string'))\n ) {\n throw new errors.ApplicationError(\n 'Invalid configuration: allowedTypes must be an array of strings.'\n );\n }\n\n if (\n config.deniedTypes &&\n (!Array.isArray(config.deniedTypes) ||\n !config.deniedTypes.every((item) => typeof item === 'string'))\n ) {\n throw new errors.ApplicationError(\n 'Invalid configuration: deniedTypes must be an array of strings.'\n );\n }\n\n if (!config.allowedTypes && !config.deniedTypes) {\n strapi.log.warn(\n 'No upload security configuration found. Consider configuring plugin.upload.security for enhanced file validation.'\n );\n return filesArray.map(() => ({ isValid: true }));\n }\n\n const validationPromises = filesArray.map(async (file, index) => {\n try {\n return await validateFile(file, config, strapi);\n } catch (error) {\n strapi.log.error('Unexpected error during file validation', {\n fileIndex: index,\n fileName: file?.name || file?.originalname,\n error: error instanceof Error ? error.message : String(error),\n });\n\n return {\n isValid: false,\n error: {\n code: 'VALIDATION_ERROR' as const,\n message: `Validation failed for file at index ${index}`,\n details: {\n index,\n fileName: file?.name || file?.originalname,\n originalError: error instanceof Error ? error.message : String(error),\n },\n },\n };\n }\n });\n\n return Promise.all(validationPromises);\n}\n\nexport async function enforceUploadSecurity(\n files: any,\n strapi: Core.Strapi\n): Promise<{\n validFiles: any[];\n validFileNames: string[];\n errors: Array<ErrorDetail>;\n}> {\n const validationResults = await validateFiles(files, strapi);\n const filesArray = Array.isArray(files) ? files : [files];\n\n const validFiles: any[] = [];\n const validFileNames: string[] = [];\n const errors: Array<ErrorDetail> = [];\n\n for (const [index, result] of validationResults.entries()) {\n if (result.isValid) {\n const file = filesArray[index];\n validFiles.push(file);\n validFileNames.push(file.originalFilename || file.name);\n } else if (result.error) {\n errors.push({\n file: filesArray[index],\n originalIndex: index,\n error: result.error,\n });\n } else {\n // Handle case where validation failed but no error details are provided\n errors.push({\n file: filesArray[index],\n originalIndex: index,\n error: {\n code: 'UNKNOWN_ERROR' as const,\n message: 'File validation failed for unknown reason',\n details: {\n index,\n fileName: filesArray[index]?.name || filesArray[index]?.originalname,\n },\n },\n });\n }\n }\n\n return { validFiles, validFileNames, errors };\n}\n\nexport type PrepareUploadResult = {\n validFiles: any[];\n filteredBody: any;\n};\n\n/**\n * Prepare files and body for upload by enforcing security and parsing fileInfo\n */\nexport async function prepareUploadRequest(\n filesInput: any,\n body: any,\n strapi: Core.Strapi\n): Promise<PrepareUploadResult> {\n const securityResults = await enforceUploadSecurity(filesInput, strapi);\n\n if (securityResults.validFiles.length === 0) {\n throw new errors.ValidationError(\n securityResults.errors[0].error.message,\n securityResults.errors[0].error.details\n );\n }\n\n let filteredBody = body;\n if (body?.fileInfo) {\n // Parse JSON strings in fileInfo\n let parsedFileInfo = body.fileInfo;\n if (Array.isArray(body.fileInfo)) {\n parsedFileInfo = body.fileInfo.map((fi: any) =>\n typeof fi === 'string' ? JSON.parse(fi) : fi\n );\n } else if (typeof body.fileInfo === 'string') {\n parsedFileInfo = JSON.parse(body.fileInfo);\n }\n\n // Filter fileInfo by index - only keep entries for files that passed validation\n if (Array.isArray(parsedFileInfo)) {\n const invalidIndices = new Set(securityResults.errors.map((e) => e.originalIndex));\n const filteredFileInfo = parsedFileInfo.filter(\n (_: any, index: number) => !invalidIndices.has(index)\n );\n\n if (filteredFileInfo.length === 1) {\n filteredBody = {\n ...body,\n fileInfo: filteredFileInfo[0],\n };\n } else {\n filteredBody = {\n ...body,\n fileInfo: filteredFileInfo,\n };\n }\n } else {\n filteredBody = {\n ...body,\n fileInfo: parsedFileInfo,\n };\n }\n }\n\n return {\n validFiles: securityResults.validFiles,\n filteredBody,\n };\n}\n"],"names":["readFileChunk","filePath","chunkSize","buffer","readFile","length","subarray","detectMimeType","file","path","filepath","tempFilePath","error","Error","message","String","undefined","fileTypeFromBuffer","result","Uint8Array","mime","matchesMimePattern","mimeType","patterns","some","pattern","normalizedPattern","toLowerCase","normalizedMimeType","includes","regexPattern","replace","regex","RegExp","matches","test","exactMatch","isMimeTypeAllowed","config","allowedTypes","deniedTypes","extractFileInfo","fileName","originalFilename","name","filename","newFilename","declaredMimeType","mimetype","type","validateFile","strapi","isValid","detectedMime","mimeDetectionFailed","log","warn","mimeToValidate","code","details","reason","declaredType","detectedType","finalType","validateFiles","files","filesArray","Array","isArray","get","every","item","errors","ApplicationError","map","validationPromises","index","fileIndex","originalname","originalError","Promise","all","enforceUploadSecurity","validationResults","validFiles","validFileNames","entries","push","originalIndex","prepareUploadRequest","filesInput","body","securityResults","ValidationError","filteredBody","fileInfo","parsedFileInfo","fi","JSON","parse","invalidIndices","Set","e","filteredFileInfo","filter","_","has"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mime-validation.js","sources":["../../../server/src/utils/mime-validation.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport type { Core } from '@strapi/types';\nimport { errors } from '@strapi/utils';\n\nexport type SecurityConfig = {\n allowedTypes?: string[];\n deniedTypes?: string[];\n};\ntype UploadValidationError = {\n code: 'MIME_TYPE_NOT_ALLOWED' | 'VALIDATION_ERROR' | 'UNKNOWN_ERROR';\n message: string;\n details: Record<string, any>;\n};\n\ntype ValidationResult = {\n isValid: boolean;\n error?: UploadValidationError;\n};\n\ntype ErrorDetail = {\n file: any;\n originalIndex: number;\n error: UploadValidationError;\n};\n\nasync function readFileChunk(filePath: string, chunkSize: number = 4100): Promise<Buffer> {\n const buffer = await readFile(filePath);\n return buffer.length > chunkSize ? buffer.subarray(0, chunkSize) : buffer;\n}\n\nexport async function detectMimeType(file: any): Promise<string | undefined> {\n let buffer: Buffer;\n\n const filePath = file.path || file.filepath || file.tempFilePath;\n\n if (filePath) {\n try {\n buffer = await readFileChunk(filePath, 4100);\n } catch (error) {\n throw new Error(\n `Failed to read file: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n } else if (file.buffer) {\n buffer = file.buffer.length > 4100 ? file.buffer.subarray(0, 4100) : file.buffer;\n } else {\n // No file data available\n return undefined;\n }\n\n try {\n /**\n * Use dynamic import to support file-type which is ESM-only\n * Static imports fail during CommonJS build since bundler can't transform ESM-only packages\n * @see https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c\n */\n const { fileTypeFromBuffer } = await import('file-type');\n\n const result = await fileTypeFromBuffer(new Uint8Array(buffer));\n return result?.mime;\n } catch (error) {\n throw new Error(\n `Failed to detect MIME type: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\nfunction matchesMimePattern(mimeType: string, patterns: string[]): boolean {\n if (!patterns?.length) return false;\n\n return patterns.some((pattern) => {\n const normalizedPattern = pattern.toLowerCase();\n const normalizedMimeType = mimeType.toLowerCase();\n\n if (normalizedPattern.includes('*')) {\n const regexPattern = normalizedPattern.replace(/\\*/g, '.*');\n\n const regex = new RegExp(`^${regexPattern}$`);\n const matches = regex.test(normalizedMimeType);\n return matches;\n }\n\n const exactMatch = normalizedPattern === normalizedMimeType;\n return exactMatch;\n });\n}\n\nexport function isMimeTypeAllowed(mimeType: string, config: SecurityConfig): boolean {\n const { allowedTypes, deniedTypes } = config;\n\n if (!mimeType) return false;\n\n if (deniedTypes?.length && matchesMimePattern(mimeType, deniedTypes)) {\n return false;\n }\n\n if (allowedTypes?.length) {\n return matchesMimePattern(mimeType, allowedTypes);\n }\n\n return true;\n}\n\nexport function extractFileInfo(file: any) {\n const fileName =\n file.originalFilename || file.name || file.filename || file.newFilename || 'unknown';\n const declaredMimeType = file.mimetype || file.type || file.mimeType || file.mime || '';\n\n return { fileName, declaredMimeType };\n}\n\nexport async function validateFile(\n file: any,\n config: SecurityConfig,\n strapi: Core.Strapi\n): Promise<ValidationResult> {\n const { allowedTypes, deniedTypes } = config;\n\n if (!allowedTypes && !deniedTypes) {\n return { isValid: true };\n }\n\n const { fileName, declaredMimeType } = extractFileInfo(file);\n\n let detectedMime: string | undefined;\n let mimeDetectionFailed = false;\n\n try {\n detectedMime = await detectMimeType(file);\n } catch (error) {\n mimeDetectionFailed = true;\n strapi.log.warn('Failed to detect MIME type from file', {\n fileName,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n\n const mimeToValidate = detectedMime || declaredMimeType;\n\n if (\n !detectedMime &&\n (declaredMimeType === 'application/octet-stream' || !declaredMimeType || mimeDetectionFailed)\n ) {\n if (allowedTypes?.length || deniedTypes?.length) {\n return {\n isValid: false,\n error: {\n code: 'MIME_TYPE_NOT_ALLOWED',\n message: `Cannot verify file type for security reasons`,\n details: {\n fileName,\n reason: 'Unable to detect MIME type from file content',\n declaredType: declaredMimeType,\n mimeDetectionFailed,\n },\n },\n };\n }\n }\n\n if (\n mimeToValidate &&\n (allowedTypes || deniedTypes) &&\n !isMimeTypeAllowed(mimeToValidate, config)\n ) {\n return {\n isValid: false,\n error: {\n code: 'MIME_TYPE_NOT_ALLOWED',\n message: `File type '${mimeToValidate}' is not allowed`,\n details: {\n fileName,\n detectedType: detectedMime,\n declaredType: declaredMimeType,\n finalType: mimeToValidate,\n allowedTypes,\n deniedTypes,\n },\n },\n };\n }\n\n return { isValid: true };\n}\n\nexport async function validateFiles(files: any, strapi: Core.Strapi): Promise<ValidationResult[]> {\n const filesArray = Array.isArray(files) ? files : [files];\n\n if (!filesArray.length) {\n return [];\n }\n\n const config: SecurityConfig = strapi.config.get('plugin::upload.security', {});\n if (\n config.allowedTypes &&\n (!Array.isArray(config.allowedTypes) ||\n !config.allowedTypes.every((item) => typeof item === 'string'))\n ) {\n throw new errors.ApplicationError(\n 'Invalid configuration: allowedTypes must be an array of strings.'\n );\n }\n\n if (\n config.deniedTypes &&\n (!Array.isArray(config.deniedTypes) ||\n !config.deniedTypes.every((item) => typeof item === 'string'))\n ) {\n throw new errors.ApplicationError(\n 'Invalid configuration: deniedTypes must be an array of strings.'\n );\n }\n\n if (!config.allowedTypes && !config.deniedTypes) {\n strapi.log.warn(\n 'No upload security configuration found. Consider configuring plugin.upload.security for enhanced file validation.'\n );\n return filesArray.map(() => ({ isValid: true }));\n }\n\n const validationPromises = filesArray.map(async (file, index) => {\n try {\n return await validateFile(file, config, strapi);\n } catch (error) {\n strapi.log.error('Unexpected error during file validation', {\n fileIndex: index,\n fileName: file?.name || file?.originalname,\n error: error instanceof Error ? error.message : String(error),\n });\n\n return {\n isValid: false,\n error: {\n code: 'VALIDATION_ERROR' as const,\n message: `Validation failed for file at index ${index}`,\n details: {\n index,\n fileName: file?.name || file?.originalname,\n originalError: error instanceof Error ? error.message : String(error),\n },\n },\n };\n }\n });\n\n return Promise.all(validationPromises);\n}\n\nexport async function enforceUploadSecurity(\n files: any,\n strapi: Core.Strapi\n): Promise<{\n validFiles: any[];\n validFileNames: string[];\n errors: Array<ErrorDetail>;\n}> {\n const validationResults = await validateFiles(files, strapi);\n const filesArray = Array.isArray(files) ? files : [files];\n\n const validFiles: any[] = [];\n const validFileNames: string[] = [];\n const errors: Array<ErrorDetail> = [];\n\n for (const [index, result] of validationResults.entries()) {\n if (result.isValid) {\n const file = filesArray[index];\n validFiles.push(file);\n validFileNames.push(file.originalFilename || file.name);\n } else if (result.error) {\n errors.push({\n file: filesArray[index],\n originalIndex: index,\n error: result.error,\n });\n } else {\n // Handle case where validation failed but no error details are provided\n errors.push({\n file: filesArray[index],\n originalIndex: index,\n error: {\n code: 'UNKNOWN_ERROR' as const,\n message: 'File validation failed for unknown reason',\n details: {\n index,\n fileName: filesArray[index]?.name || filesArray[index]?.originalname,\n },\n },\n });\n }\n }\n\n return { validFiles, validFileNames, errors };\n}\n\nexport type FileUploadError = {\n name: string;\n message: string;\n};\n\nexport type PrepareUploadResult = {\n validFiles: any[];\n filteredBody: any;\n errors: FileUploadError[];\n};\n\n/**\n * Prepare files and body for upload by enforcing security and parsing fileInfo\n */\nexport async function prepareUploadRequest(\n filesInput: any,\n body: any,\n strapi: Core.Strapi\n): Promise<PrepareUploadResult> {\n const securityResults = await enforceUploadSecurity(filesInput, strapi);\n\n let filteredBody = body;\n if (body?.fileInfo) {\n // Parse JSON strings in fileInfo\n let parsedFileInfo = body.fileInfo;\n if (Array.isArray(body.fileInfo)) {\n parsedFileInfo = body.fileInfo.map((fi: any) =>\n typeof fi === 'string' ? JSON.parse(fi) : fi\n );\n } else if (typeof body.fileInfo === 'string') {\n parsedFileInfo = JSON.parse(body.fileInfo);\n }\n\n // Filter fileInfo by index - only keep entries for files that passed validation\n if (Array.isArray(parsedFileInfo)) {\n const invalidIndices = new Set(securityResults.errors.map((e) => e.originalIndex));\n const filteredFileInfo = parsedFileInfo.filter(\n (_: any, index: number) => !invalidIndices.has(index)\n );\n\n if (filteredFileInfo.length === 1) {\n filteredBody = {\n ...body,\n fileInfo: filteredFileInfo[0],\n };\n } else {\n filteredBody = {\n ...body,\n fileInfo: filteredFileInfo,\n };\n }\n } else {\n filteredBody = {\n ...body,\n fileInfo: parsedFileInfo,\n };\n }\n }\n\n // Map errors to simplified format\n const uploadErrors: FileUploadError[] = securityResults.errors.map((e) => ({\n name: e.file?.originalFilename || e.file?.name || 'unknown',\n message: e.error.message,\n }));\n\n return {\n validFiles: securityResults.validFiles,\n filteredBody,\n errors: uploadErrors,\n };\n}\n"],"names":["readFileChunk","filePath","chunkSize","buffer","readFile","length","subarray","detectMimeType","file","path","filepath","tempFilePath","error","Error","message","String","undefined","fileTypeFromBuffer","result","Uint8Array","mime","matchesMimePattern","mimeType","patterns","some","pattern","normalizedPattern","toLowerCase","normalizedMimeType","includes","regexPattern","replace","regex","RegExp","matches","test","exactMatch","isMimeTypeAllowed","config","allowedTypes","deniedTypes","extractFileInfo","fileName","originalFilename","name","filename","newFilename","declaredMimeType","mimetype","type","validateFile","strapi","isValid","detectedMime","mimeDetectionFailed","log","warn","mimeToValidate","code","details","reason","declaredType","detectedType","finalType","validateFiles","files","filesArray","Array","isArray","get","every","item","errors","ApplicationError","map","validationPromises","index","fileIndex","originalname","originalError","Promise","all","enforceUploadSecurity","validationResults","validFiles","validFileNames","entries","push","originalIndex","prepareUploadRequest","filesInput","body","securityResults","filteredBody","fileInfo","parsedFileInfo","fi","JSON","parse","invalidIndices","Set","e","filteredFileInfo","filter","_","has","uploadErrors"],"mappings":"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"}
|
|
@@ -214,9 +214,6 @@ async function enforceUploadSecurity(files, strapi) {
|
|
|
214
214
|
* Prepare files and body for upload by enforcing security and parsing fileInfo
|
|
215
215
|
*/ async function prepareUploadRequest(filesInput, body, strapi) {
|
|
216
216
|
const securityResults = await enforceUploadSecurity(filesInput, strapi);
|
|
217
|
-
if (securityResults.validFiles.length === 0) {
|
|
218
|
-
throw new errors.ValidationError(securityResults.errors[0].error.message, securityResults.errors[0].error.details);
|
|
219
|
-
}
|
|
220
217
|
let filteredBody = body;
|
|
221
218
|
if (body?.fileInfo) {
|
|
222
219
|
// Parse JSON strings in fileInfo
|
|
@@ -248,9 +245,15 @@ async function enforceUploadSecurity(files, strapi) {
|
|
|
248
245
|
};
|
|
249
246
|
}
|
|
250
247
|
}
|
|
248
|
+
// Map errors to simplified format
|
|
249
|
+
const uploadErrors = securityResults.errors.map((e)=>({
|
|
250
|
+
name: e.file?.originalFilename || e.file?.name || 'unknown',
|
|
251
|
+
message: e.error.message
|
|
252
|
+
}));
|
|
251
253
|
return {
|
|
252
254
|
validFiles: securityResults.validFiles,
|
|
253
|
-
filteredBody
|
|
255
|
+
filteredBody,
|
|
256
|
+
errors: uploadErrors
|
|
254
257
|
};
|
|
255
258
|
}
|
|
256
259
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mime-validation.mjs","sources":["../../../server/src/utils/mime-validation.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport type { Core } from '@strapi/types';\nimport { errors } from '@strapi/utils';\n\nexport type SecurityConfig = {\n allowedTypes?: string[];\n deniedTypes?: string[];\n};\ntype UploadValidationError = {\n code: 'MIME_TYPE_NOT_ALLOWED' | 'VALIDATION_ERROR' | 'UNKNOWN_ERROR';\n message: string;\n details: Record<string, any>;\n};\n\ntype ValidationResult = {\n isValid: boolean;\n error?: UploadValidationError;\n};\n\ntype ErrorDetail = {\n file: any;\n originalIndex: number;\n error: UploadValidationError;\n};\n\nasync function readFileChunk(filePath: string, chunkSize: number = 4100): Promise<Buffer> {\n const buffer = await readFile(filePath);\n return buffer.length > chunkSize ? buffer.subarray(0, chunkSize) : buffer;\n}\n\nexport async function detectMimeType(file: any): Promise<string | undefined> {\n let buffer: Buffer;\n\n const filePath = file.path || file.filepath || file.tempFilePath;\n\n if (filePath) {\n try {\n buffer = await readFileChunk(filePath, 4100);\n } catch (error) {\n throw new Error(\n `Failed to read file: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n } else if (file.buffer) {\n buffer = file.buffer.length > 4100 ? file.buffer.subarray(0, 4100) : file.buffer;\n } else {\n // No file data available\n return undefined;\n }\n\n try {\n /**\n * Use dynamic import to support file-type which is ESM-only\n * Static imports fail during CommonJS build since bundler can't transform ESM-only packages\n * @see https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c\n */\n const { fileTypeFromBuffer } = await import('file-type');\n\n const result = await fileTypeFromBuffer(new Uint8Array(buffer));\n return result?.mime;\n } catch (error) {\n throw new Error(\n `Failed to detect MIME type: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\nfunction matchesMimePattern(mimeType: string, patterns: string[]): boolean {\n if (!patterns?.length) return false;\n\n return patterns.some((pattern) => {\n const normalizedPattern = pattern.toLowerCase();\n const normalizedMimeType = mimeType.toLowerCase();\n\n if (normalizedPattern.includes('*')) {\n const regexPattern = normalizedPattern.replace(/\\*/g, '.*');\n\n const regex = new RegExp(`^${regexPattern}$`);\n const matches = regex.test(normalizedMimeType);\n return matches;\n }\n\n const exactMatch = normalizedPattern === normalizedMimeType;\n return exactMatch;\n });\n}\n\nexport function isMimeTypeAllowed(mimeType: string, config: SecurityConfig): boolean {\n const { allowedTypes, deniedTypes } = config;\n\n if (!mimeType) return false;\n\n if (deniedTypes?.length && matchesMimePattern(mimeType, deniedTypes)) {\n return false;\n }\n\n if (allowedTypes?.length) {\n return matchesMimePattern(mimeType, allowedTypes);\n }\n\n return true;\n}\n\nexport function extractFileInfo(file: any) {\n const fileName =\n file.originalFilename || file.name || file.filename || file.newFilename || 'unknown';\n const declaredMimeType = file.mimetype || file.type || file.mimeType || file.mime || '';\n\n return { fileName, declaredMimeType };\n}\n\nexport async function validateFile(\n file: any,\n config: SecurityConfig,\n strapi: Core.Strapi\n): Promise<ValidationResult> {\n const { allowedTypes, deniedTypes } = config;\n\n if (!allowedTypes && !deniedTypes) {\n return { isValid: true };\n }\n\n const { fileName, declaredMimeType } = extractFileInfo(file);\n\n let detectedMime: string | undefined;\n let mimeDetectionFailed = false;\n\n try {\n detectedMime = await detectMimeType(file);\n } catch (error) {\n mimeDetectionFailed = true;\n strapi.log.warn('Failed to detect MIME type from file', {\n fileName,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n\n const mimeToValidate = detectedMime || declaredMimeType;\n\n if (\n !detectedMime &&\n (declaredMimeType === 'application/octet-stream' || !declaredMimeType || mimeDetectionFailed)\n ) {\n if (allowedTypes?.length || deniedTypes?.length) {\n return {\n isValid: false,\n error: {\n code: 'MIME_TYPE_NOT_ALLOWED',\n message: `Cannot verify file type for security reasons`,\n details: {\n fileName,\n reason: 'Unable to detect MIME type from file content',\n declaredType: declaredMimeType,\n mimeDetectionFailed,\n },\n },\n };\n }\n }\n\n if (\n mimeToValidate &&\n (allowedTypes || deniedTypes) &&\n !isMimeTypeAllowed(mimeToValidate, config)\n ) {\n return {\n isValid: false,\n error: {\n code: 'MIME_TYPE_NOT_ALLOWED',\n message: `File type '${mimeToValidate}' is not allowed`,\n details: {\n fileName,\n detectedType: detectedMime,\n declaredType: declaredMimeType,\n finalType: mimeToValidate,\n allowedTypes,\n deniedTypes,\n },\n },\n };\n }\n\n return { isValid: true };\n}\n\nexport async function validateFiles(files: any, strapi: Core.Strapi): Promise<ValidationResult[]> {\n const filesArray = Array.isArray(files) ? files : [files];\n\n if (!filesArray.length) {\n return [];\n }\n\n const config: SecurityConfig = strapi.config.get('plugin::upload.security', {});\n if (\n config.allowedTypes &&\n (!Array.isArray(config.allowedTypes) ||\n !config.allowedTypes.every((item) => typeof item === 'string'))\n ) {\n throw new errors.ApplicationError(\n 'Invalid configuration: allowedTypes must be an array of strings.'\n );\n }\n\n if (\n config.deniedTypes &&\n (!Array.isArray(config.deniedTypes) ||\n !config.deniedTypes.every((item) => typeof item === 'string'))\n ) {\n throw new errors.ApplicationError(\n 'Invalid configuration: deniedTypes must be an array of strings.'\n );\n }\n\n if (!config.allowedTypes && !config.deniedTypes) {\n strapi.log.warn(\n 'No upload security configuration found. Consider configuring plugin.upload.security for enhanced file validation.'\n );\n return filesArray.map(() => ({ isValid: true }));\n }\n\n const validationPromises = filesArray.map(async (file, index) => {\n try {\n return await validateFile(file, config, strapi);\n } catch (error) {\n strapi.log.error('Unexpected error during file validation', {\n fileIndex: index,\n fileName: file?.name || file?.originalname,\n error: error instanceof Error ? error.message : String(error),\n });\n\n return {\n isValid: false,\n error: {\n code: 'VALIDATION_ERROR' as const,\n message: `Validation failed for file at index ${index}`,\n details: {\n index,\n fileName: file?.name || file?.originalname,\n originalError: error instanceof Error ? error.message : String(error),\n },\n },\n };\n }\n });\n\n return Promise.all(validationPromises);\n}\n\nexport async function enforceUploadSecurity(\n files: any,\n strapi: Core.Strapi\n): Promise<{\n validFiles: any[];\n validFileNames: string[];\n errors: Array<ErrorDetail>;\n}> {\n const validationResults = await validateFiles(files, strapi);\n const filesArray = Array.isArray(files) ? files : [files];\n\n const validFiles: any[] = [];\n const validFileNames: string[] = [];\n const errors: Array<ErrorDetail> = [];\n\n for (const [index, result] of validationResults.entries()) {\n if (result.isValid) {\n const file = filesArray[index];\n validFiles.push(file);\n validFileNames.push(file.originalFilename || file.name);\n } else if (result.error) {\n errors.push({\n file: filesArray[index],\n originalIndex: index,\n error: result.error,\n });\n } else {\n // Handle case where validation failed but no error details are provided\n errors.push({\n file: filesArray[index],\n originalIndex: index,\n error: {\n code: 'UNKNOWN_ERROR' as const,\n message: 'File validation failed for unknown reason',\n details: {\n index,\n fileName: filesArray[index]?.name || filesArray[index]?.originalname,\n },\n },\n });\n }\n }\n\n return { validFiles, validFileNames, errors };\n}\n\nexport type PrepareUploadResult = {\n validFiles: any[];\n filteredBody: any;\n};\n\n/**\n * Prepare files and body for upload by enforcing security and parsing fileInfo\n */\nexport async function prepareUploadRequest(\n filesInput: any,\n body: any,\n strapi: Core.Strapi\n): Promise<PrepareUploadResult> {\n const securityResults = await enforceUploadSecurity(filesInput, strapi);\n\n if (securityResults.validFiles.length === 0) {\n throw new errors.ValidationError(\n securityResults.errors[0].error.message,\n securityResults.errors[0].error.details\n );\n }\n\n let filteredBody = body;\n if (body?.fileInfo) {\n // Parse JSON strings in fileInfo\n let parsedFileInfo = body.fileInfo;\n if (Array.isArray(body.fileInfo)) {\n parsedFileInfo = body.fileInfo.map((fi: any) =>\n typeof fi === 'string' ? JSON.parse(fi) : fi\n );\n } else if (typeof body.fileInfo === 'string') {\n parsedFileInfo = JSON.parse(body.fileInfo);\n }\n\n // Filter fileInfo by index - only keep entries for files that passed validation\n if (Array.isArray(parsedFileInfo)) {\n const invalidIndices = new Set(securityResults.errors.map((e) => e.originalIndex));\n const filteredFileInfo = parsedFileInfo.filter(\n (_: any, index: number) => !invalidIndices.has(index)\n );\n\n if (filteredFileInfo.length === 1) {\n filteredBody = {\n ...body,\n fileInfo: filteredFileInfo[0],\n };\n } else {\n filteredBody = {\n ...body,\n fileInfo: filteredFileInfo,\n };\n }\n } else {\n filteredBody = {\n ...body,\n fileInfo: parsedFileInfo,\n };\n }\n }\n\n return {\n validFiles: securityResults.validFiles,\n filteredBody,\n };\n}\n"],"names":["readFileChunk","filePath","chunkSize","buffer","readFile","length","subarray","detectMimeType","file","path","filepath","tempFilePath","error","Error","message","String","undefined","fileTypeFromBuffer","result","Uint8Array","mime","matchesMimePattern","mimeType","patterns","some","pattern","normalizedPattern","toLowerCase","normalizedMimeType","includes","regexPattern","replace","regex","RegExp","matches","test","exactMatch","isMimeTypeAllowed","config","allowedTypes","deniedTypes","extractFileInfo","fileName","originalFilename","name","filename","newFilename","declaredMimeType","mimetype","type","validateFile","strapi","isValid","detectedMime","mimeDetectionFailed","log","warn","mimeToValidate","code","details","reason","declaredType","detectedType","finalType","validateFiles","files","filesArray","Array","isArray","get","every","item","errors","ApplicationError","map","validationPromises","index","fileIndex","originalname","originalError","Promise","all","enforceUploadSecurity","validationResults","validFiles","validFileNames","entries","push","originalIndex","prepareUploadRequest","filesInput","body","securityResults","ValidationError","filteredBody","fileInfo","parsedFileInfo","fi","JSON","parse","invalidIndices","Set","e","filteredFileInfo","filter","_","has"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mime-validation.mjs","sources":["../../../server/src/utils/mime-validation.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport type { Core } from '@strapi/types';\nimport { errors } from '@strapi/utils';\n\nexport type SecurityConfig = {\n allowedTypes?: string[];\n deniedTypes?: string[];\n};\ntype UploadValidationError = {\n code: 'MIME_TYPE_NOT_ALLOWED' | 'VALIDATION_ERROR' | 'UNKNOWN_ERROR';\n message: string;\n details: Record<string, any>;\n};\n\ntype ValidationResult = {\n isValid: boolean;\n error?: UploadValidationError;\n};\n\ntype ErrorDetail = {\n file: any;\n originalIndex: number;\n error: UploadValidationError;\n};\n\nasync function readFileChunk(filePath: string, chunkSize: number = 4100): Promise<Buffer> {\n const buffer = await readFile(filePath);\n return buffer.length > chunkSize ? buffer.subarray(0, chunkSize) : buffer;\n}\n\nexport async function detectMimeType(file: any): Promise<string | undefined> {\n let buffer: Buffer;\n\n const filePath = file.path || file.filepath || file.tempFilePath;\n\n if (filePath) {\n try {\n buffer = await readFileChunk(filePath, 4100);\n } catch (error) {\n throw new Error(\n `Failed to read file: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n } else if (file.buffer) {\n buffer = file.buffer.length > 4100 ? file.buffer.subarray(0, 4100) : file.buffer;\n } else {\n // No file data available\n return undefined;\n }\n\n try {\n /**\n * Use dynamic import to support file-type which is ESM-only\n * Static imports fail during CommonJS build since bundler can't transform ESM-only packages\n * @see https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c\n */\n const { fileTypeFromBuffer } = await import('file-type');\n\n const result = await fileTypeFromBuffer(new Uint8Array(buffer));\n return result?.mime;\n } catch (error) {\n throw new Error(\n `Failed to detect MIME type: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\nfunction matchesMimePattern(mimeType: string, patterns: string[]): boolean {\n if (!patterns?.length) return false;\n\n return patterns.some((pattern) => {\n const normalizedPattern = pattern.toLowerCase();\n const normalizedMimeType = mimeType.toLowerCase();\n\n if (normalizedPattern.includes('*')) {\n const regexPattern = normalizedPattern.replace(/\\*/g, '.*');\n\n const regex = new RegExp(`^${regexPattern}$`);\n const matches = regex.test(normalizedMimeType);\n return matches;\n }\n\n const exactMatch = normalizedPattern === normalizedMimeType;\n return exactMatch;\n });\n}\n\nexport function isMimeTypeAllowed(mimeType: string, config: SecurityConfig): boolean {\n const { allowedTypes, deniedTypes } = config;\n\n if (!mimeType) return false;\n\n if (deniedTypes?.length && matchesMimePattern(mimeType, deniedTypes)) {\n return false;\n }\n\n if (allowedTypes?.length) {\n return matchesMimePattern(mimeType, allowedTypes);\n }\n\n return true;\n}\n\nexport function extractFileInfo(file: any) {\n const fileName =\n file.originalFilename || file.name || file.filename || file.newFilename || 'unknown';\n const declaredMimeType = file.mimetype || file.type || file.mimeType || file.mime || '';\n\n return { fileName, declaredMimeType };\n}\n\nexport async function validateFile(\n file: any,\n config: SecurityConfig,\n strapi: Core.Strapi\n): Promise<ValidationResult> {\n const { allowedTypes, deniedTypes } = config;\n\n if (!allowedTypes && !deniedTypes) {\n return { isValid: true };\n }\n\n const { fileName, declaredMimeType } = extractFileInfo(file);\n\n let detectedMime: string | undefined;\n let mimeDetectionFailed = false;\n\n try {\n detectedMime = await detectMimeType(file);\n } catch (error) {\n mimeDetectionFailed = true;\n strapi.log.warn('Failed to detect MIME type from file', {\n fileName,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n\n const mimeToValidate = detectedMime || declaredMimeType;\n\n if (\n !detectedMime &&\n (declaredMimeType === 'application/octet-stream' || !declaredMimeType || mimeDetectionFailed)\n ) {\n if (allowedTypes?.length || deniedTypes?.length) {\n return {\n isValid: false,\n error: {\n code: 'MIME_TYPE_NOT_ALLOWED',\n message: `Cannot verify file type for security reasons`,\n details: {\n fileName,\n reason: 'Unable to detect MIME type from file content',\n declaredType: declaredMimeType,\n mimeDetectionFailed,\n },\n },\n };\n }\n }\n\n if (\n mimeToValidate &&\n (allowedTypes || deniedTypes) &&\n !isMimeTypeAllowed(mimeToValidate, config)\n ) {\n return {\n isValid: false,\n error: {\n code: 'MIME_TYPE_NOT_ALLOWED',\n message: `File type '${mimeToValidate}' is not allowed`,\n details: {\n fileName,\n detectedType: detectedMime,\n declaredType: declaredMimeType,\n finalType: mimeToValidate,\n allowedTypes,\n deniedTypes,\n },\n },\n };\n }\n\n return { isValid: true };\n}\n\nexport async function validateFiles(files: any, strapi: Core.Strapi): Promise<ValidationResult[]> {\n const filesArray = Array.isArray(files) ? files : [files];\n\n if (!filesArray.length) {\n return [];\n }\n\n const config: SecurityConfig = strapi.config.get('plugin::upload.security', {});\n if (\n config.allowedTypes &&\n (!Array.isArray(config.allowedTypes) ||\n !config.allowedTypes.every((item) => typeof item === 'string'))\n ) {\n throw new errors.ApplicationError(\n 'Invalid configuration: allowedTypes must be an array of strings.'\n );\n }\n\n if (\n config.deniedTypes &&\n (!Array.isArray(config.deniedTypes) ||\n !config.deniedTypes.every((item) => typeof item === 'string'))\n ) {\n throw new errors.ApplicationError(\n 'Invalid configuration: deniedTypes must be an array of strings.'\n );\n }\n\n if (!config.allowedTypes && !config.deniedTypes) {\n strapi.log.warn(\n 'No upload security configuration found. Consider configuring plugin.upload.security for enhanced file validation.'\n );\n return filesArray.map(() => ({ isValid: true }));\n }\n\n const validationPromises = filesArray.map(async (file, index) => {\n try {\n return await validateFile(file, config, strapi);\n } catch (error) {\n strapi.log.error('Unexpected error during file validation', {\n fileIndex: index,\n fileName: file?.name || file?.originalname,\n error: error instanceof Error ? error.message : String(error),\n });\n\n return {\n isValid: false,\n error: {\n code: 'VALIDATION_ERROR' as const,\n message: `Validation failed for file at index ${index}`,\n details: {\n index,\n fileName: file?.name || file?.originalname,\n originalError: error instanceof Error ? error.message : String(error),\n },\n },\n };\n }\n });\n\n return Promise.all(validationPromises);\n}\n\nexport async function enforceUploadSecurity(\n files: any,\n strapi: Core.Strapi\n): Promise<{\n validFiles: any[];\n validFileNames: string[];\n errors: Array<ErrorDetail>;\n}> {\n const validationResults = await validateFiles(files, strapi);\n const filesArray = Array.isArray(files) ? files : [files];\n\n const validFiles: any[] = [];\n const validFileNames: string[] = [];\n const errors: Array<ErrorDetail> = [];\n\n for (const [index, result] of validationResults.entries()) {\n if (result.isValid) {\n const file = filesArray[index];\n validFiles.push(file);\n validFileNames.push(file.originalFilename || file.name);\n } else if (result.error) {\n errors.push({\n file: filesArray[index],\n originalIndex: index,\n error: result.error,\n });\n } else {\n // Handle case where validation failed but no error details are provided\n errors.push({\n file: filesArray[index],\n originalIndex: index,\n error: {\n code: 'UNKNOWN_ERROR' as const,\n message: 'File validation failed for unknown reason',\n details: {\n index,\n fileName: filesArray[index]?.name || filesArray[index]?.originalname,\n },\n },\n });\n }\n }\n\n return { validFiles, validFileNames, errors };\n}\n\nexport type FileUploadError = {\n name: string;\n message: string;\n};\n\nexport type PrepareUploadResult = {\n validFiles: any[];\n filteredBody: any;\n errors: FileUploadError[];\n};\n\n/**\n * Prepare files and body for upload by enforcing security and parsing fileInfo\n */\nexport async function prepareUploadRequest(\n filesInput: any,\n body: any,\n strapi: Core.Strapi\n): Promise<PrepareUploadResult> {\n const securityResults = await enforceUploadSecurity(filesInput, strapi);\n\n let filteredBody = body;\n if (body?.fileInfo) {\n // Parse JSON strings in fileInfo\n let parsedFileInfo = body.fileInfo;\n if (Array.isArray(body.fileInfo)) {\n parsedFileInfo = body.fileInfo.map((fi: any) =>\n typeof fi === 'string' ? JSON.parse(fi) : fi\n );\n } else if (typeof body.fileInfo === 'string') {\n parsedFileInfo = JSON.parse(body.fileInfo);\n }\n\n // Filter fileInfo by index - only keep entries for files that passed validation\n if (Array.isArray(parsedFileInfo)) {\n const invalidIndices = new Set(securityResults.errors.map((e) => e.originalIndex));\n const filteredFileInfo = parsedFileInfo.filter(\n (_: any, index: number) => !invalidIndices.has(index)\n );\n\n if (filteredFileInfo.length === 1) {\n filteredBody = {\n ...body,\n fileInfo: filteredFileInfo[0],\n };\n } else {\n filteredBody = {\n ...body,\n fileInfo: filteredFileInfo,\n };\n }\n } else {\n filteredBody = {\n ...body,\n fileInfo: parsedFileInfo,\n };\n }\n }\n\n // Map errors to simplified format\n const uploadErrors: FileUploadError[] = securityResults.errors.map((e) => ({\n name: e.file?.originalFilename || e.file?.name || 'unknown',\n message: e.error.message,\n }));\n\n return {\n validFiles: securityResults.validFiles,\n filteredBody,\n errors: uploadErrors,\n };\n}\n"],"names":["readFileChunk","filePath","chunkSize","buffer","readFile","length","subarray","detectMimeType","file","path","filepath","tempFilePath","error","Error","message","String","undefined","fileTypeFromBuffer","result","Uint8Array","mime","matchesMimePattern","mimeType","patterns","some","pattern","normalizedPattern","toLowerCase","normalizedMimeType","includes","regexPattern","replace","regex","RegExp","matches","test","exactMatch","isMimeTypeAllowed","config","allowedTypes","deniedTypes","extractFileInfo","fileName","originalFilename","name","filename","newFilename","declaredMimeType","mimetype","type","validateFile","strapi","isValid","detectedMime","mimeDetectionFailed","log","warn","mimeToValidate","code","details","reason","declaredType","detectedType","finalType","validateFiles","files","filesArray","Array","isArray","get","every","item","errors","ApplicationError","map","validationPromises","index","fileIndex","originalname","originalError","Promise","all","enforceUploadSecurity","validationResults","validFiles","validFileNames","entries","push","originalIndex","prepareUploadRequest","filesInput","body","securityResults","filteredBody","fileInfo","parsedFileInfo","fi","JSON","parse","invalidIndices","Set","e","filteredFileInfo","filter","_","has","uploadErrors"],"mappings":";;;AAyBA,eAAeA,aAAcC,CAAAA,QAAgB,EAAEC,SAAAA,GAAoB,IAAI,EAAA;IACrE,MAAMC,MAAAA,GAAS,MAAMC,QAASH,CAAAA,QAAAA,CAAAA;IAC9B,OAAOE,MAAAA,CAAOE,MAAM,GAAGH,SAAAA,GAAYC,OAAOG,QAAQ,CAAC,GAAGJ,SAAaC,CAAAA,GAAAA,MAAAA;AACrE;AAEO,eAAeI,eAAeC,IAAS,EAAA;IAC5C,IAAIL,MAAAA;IAEJ,MAAMF,QAAAA,GAAWO,KAAKC,IAAI,IAAID,KAAKE,QAAQ,IAAIF,KAAKG,YAAY;AAEhE,IAAA,IAAIV,QAAU,EAAA;QACZ,IAAI;YACFE,MAAS,GAAA,MAAMH,cAAcC,QAAU,EAAA,IAAA,CAAA;AACzC,SAAA,CAAE,OAAOW,KAAO,EAAA;YACd,MAAM,IAAIC,KACR,CAAA,CAAC,qBAAqB,EAAED,KAAiBC,YAAAA,KAAAA,GAAQD,KAAME,CAAAA,OAAO,GAAGC,MAAAA,CAAOH,KAAQ,CAAA,CAAA,CAAA,CAAA;AAEpF;KACK,MAAA,IAAIJ,IAAKL,CAAAA,MAAM,EAAE;AACtBA,QAAAA,MAAAA,GAASK,IAAKL,CAAAA,MAAM,CAACE,MAAM,GAAG,IAAOG,GAAAA,IAAAA,CAAKL,MAAM,CAACG,QAAQ,CAAC,CAAG,EAAA,IAAA,CAAA,GAAQE,KAAKL,MAAM;KAC3E,MAAA;;QAEL,OAAOa,SAAAA;AACT;IAEA,IAAI;AACF;;;;AAIC,QACD,MAAM,EAAEC,kBAAkB,EAAE,GAAG,MAAM,OAAO,WAAA,CAAA;AAE5C,QAAA,MAAMC,MAAS,GAAA,MAAMD,kBAAmB,CAAA,IAAIE,UAAWhB,CAAAA,MAAAA,CAAAA,CAAAA;AACvD,QAAA,OAAOe,MAAQE,EAAAA,IAAAA;AACjB,KAAA,CAAE,OAAOR,KAAO,EAAA;QACd,MAAM,IAAIC,KACR,CAAA,CAAC,4BAA4B,EAAED,KAAiBC,YAAAA,KAAAA,GAAQD,KAAME,CAAAA,OAAO,GAAGC,MAAAA,CAAOH,KAAQ,CAAA,CAAA,CAAA,CAAA;AAE3F;AACF;AAEA,SAASS,kBAAAA,CAAmBC,QAAgB,EAAEC,QAAkB,EAAA;IAC9D,IAAI,CAACA,QAAUlB,EAAAA,MAAAA,EAAQ,OAAO,KAAA;IAE9B,OAAOkB,QAAAA,CAASC,IAAI,CAAC,CAACC,OAAAA,GAAAA;QACpB,MAAMC,iBAAAA,GAAoBD,QAAQE,WAAW,EAAA;QAC7C,MAAMC,kBAAAA,GAAqBN,SAASK,WAAW,EAAA;QAE/C,IAAID,iBAAAA,CAAkBG,QAAQ,CAAC,GAAM,CAAA,EAAA;AACnC,YAAA,MAAMC,YAAeJ,GAAAA,iBAAAA,CAAkBK,OAAO,CAAC,KAAO,EAAA,IAAA,CAAA;YAEtD,MAAMC,KAAAA,GAAQ,IAAIC,MAAO,CAAA,CAAC,CAAC,EAAEH,YAAAA,CAAa,CAAC,CAAC,CAAA;YAC5C,MAAMI,OAAAA,GAAUF,KAAMG,CAAAA,IAAI,CAACP,kBAAAA,CAAAA;YAC3B,OAAOM,OAAAA;AACT;AAEA,QAAA,MAAME,aAAaV,iBAAsBE,KAAAA,kBAAAA;QACzC,OAAOQ,UAAAA;AACT,KAAA,CAAA;AACF;AAEO,SAASC,iBAAAA,CAAkBf,QAAgB,EAAEgB,MAAsB,EAAA;AACxE,IAAA,MAAM,EAAEC,YAAY,EAAEC,WAAW,EAAE,GAAGF,MAAAA;IAEtC,IAAI,CAAChB,UAAU,OAAO,KAAA;AAEtB,IAAA,IAAIkB,WAAanC,EAAAA,MAAAA,IAAUgB,kBAAmBC,CAAAA,QAAAA,EAAUkB,WAAc,CAAA,EAAA;QACpE,OAAO,KAAA;AACT;AAEA,IAAA,IAAID,cAAclC,MAAQ,EAAA;AACxB,QAAA,OAAOgB,mBAAmBC,QAAUiB,EAAAA,YAAAA,CAAAA;AACtC;IAEA,OAAO,IAAA;AACT;AAEO,SAASE,gBAAgBjC,IAAS,EAAA;AACvC,IAAA,MAAMkC,QACJlC,GAAAA,IAAAA,CAAKmC,gBAAgB,IAAInC,IAAKoC,CAAAA,IAAI,IAAIpC,IAAAA,CAAKqC,QAAQ,IAAIrC,IAAKsC,CAAAA,WAAW,IAAI,SAAA;AAC7E,IAAA,MAAMC,gBAAmBvC,GAAAA,IAAAA,CAAKwC,QAAQ,IAAIxC,IAAKyC,CAAAA,IAAI,IAAIzC,IAAAA,CAAKc,QAAQ,IAAId,IAAKY,CAAAA,IAAI,IAAI,EAAA;IAErF,OAAO;AAAEsB,QAAAA,QAAAA;AAAUK,QAAAA;AAAiB,KAAA;AACtC;AAEO,eAAeG,YACpB1C,CAAAA,IAAS,EACT8B,MAAsB,EACtBa,MAAmB,EAAA;AAEnB,IAAA,MAAM,EAAEZ,YAAY,EAAEC,WAAW,EAAE,GAAGF,MAAAA;IAEtC,IAAI,CAACC,YAAgB,IAAA,CAACC,WAAa,EAAA;QACjC,OAAO;YAAEY,OAAS,EAAA;AAAK,SAAA;AACzB;AAEA,IAAA,MAAM,EAAEV,QAAQ,EAAEK,gBAAgB,EAAE,GAAGN,eAAgBjC,CAAAA,IAAAA,CAAAA;IAEvD,IAAI6C,YAAAA;AACJ,IAAA,IAAIC,mBAAsB,GAAA,KAAA;IAE1B,IAAI;AACFD,QAAAA,YAAAA,GAAe,MAAM9C,cAAeC,CAAAA,IAAAA,CAAAA;AACtC,KAAA,CAAE,OAAOI,KAAO,EAAA;QACd0C,mBAAsB,GAAA,IAAA;AACtBH,QAAAA,MAAAA,CAAOI,GAAG,CAACC,IAAI,CAAC,sCAAwC,EAAA;AACtDd,YAAAA,QAAAA;AACA9B,YAAAA,KAAAA,EAAOA,KAAiBC,YAAAA,KAAAA,GAAQD,KAAME,CAAAA,OAAO,GAAGC,MAAOH,CAAAA,KAAAA;AACzD,SAAA,CAAA;AACF;AAEA,IAAA,MAAM6C,iBAAiBJ,YAAgBN,IAAAA,gBAAAA;IAEvC,IACE,CAACM,iBACAN,gBAAAA,KAAqB,8BAA8B,CAACA,gBAAAA,IAAoBO,mBAAkB,CAC3F,EAAA;QACA,IAAIf,YAAAA,EAAclC,MAAUmC,IAAAA,WAAAA,EAAanC,MAAQ,EAAA;YAC/C,OAAO;gBACL+C,OAAS,EAAA,KAAA;gBACTxC,KAAO,EAAA;oBACL8C,IAAM,EAAA,uBAAA;oBACN5C,OAAS,EAAA,CAAC,4CAA4C,CAAC;oBACvD6C,OAAS,EAAA;AACPjB,wBAAAA,QAAAA;wBACAkB,MAAQ,EAAA,8CAAA;wBACRC,YAAcd,EAAAA,gBAAAA;AACdO,wBAAAA;AACF;AACF;AACF,aAAA;AACF;AACF;IAEA,IACEG,cAAAA,KACClB,YAAgBC,IAAAA,WAAU,KAC3B,CAACH,iBAAAA,CAAkBoB,gBAAgBnB,MACnC,CAAA,EAAA;QACA,OAAO;YACLc,OAAS,EAAA,KAAA;YACTxC,KAAO,EAAA;gBACL8C,IAAM,EAAA,uBAAA;AACN5C,gBAAAA,OAAAA,EAAS,CAAC,WAAW,EAAE2C,cAAAA,CAAe,gBAAgB,CAAC;gBACvDE,OAAS,EAAA;AACPjB,oBAAAA,QAAAA;oBACAoB,YAAcT,EAAAA,YAAAA;oBACdQ,YAAcd,EAAAA,gBAAAA;oBACdgB,SAAWN,EAAAA,cAAAA;AACXlB,oBAAAA,YAAAA;AACAC,oBAAAA;AACF;AACF;AACF,SAAA;AACF;IAEA,OAAO;QAAEY,OAAS,EAAA;AAAK,KAAA;AACzB;AAEO,eAAeY,aAAAA,CAAcC,KAAU,EAAEd,MAAmB,EAAA;AACjE,IAAA,MAAMe,UAAaC,GAAAA,KAAAA,CAAMC,OAAO,CAACH,SAASA,KAAQ,GAAA;AAACA,QAAAA;AAAM,KAAA;IAEzD,IAAI,CAACC,UAAW7D,CAAAA,MAAM,EAAE;AACtB,QAAA,OAAO,EAAE;AACX;AAEA,IAAA,MAAMiC,SAAyBa,MAAOb,CAAAA,MAAM,CAAC+B,GAAG,CAAC,2BAA2B,EAAC,CAAA;IAC7E,IACE/B,MAAAA,CAAOC,YAAY,KAClB,CAAC4B,KAAMC,CAAAA,OAAO,CAAC9B,MAAAA,CAAOC,YAAY,CAAA,IACjC,CAACD,MAAOC,CAAAA,YAAY,CAAC+B,KAAK,CAAC,CAACC,IAAS,GAAA,OAAOA,IAAS,KAAA,QAAA,CAAQ,CAC/D,EAAA;QACA,MAAM,IAAIC,MAAOC,CAAAA,gBAAgB,CAC/B,kEAAA,CAAA;AAEJ;IAEA,IACEnC,MAAAA,CAAOE,WAAW,KACjB,CAAC2B,KAAMC,CAAAA,OAAO,CAAC9B,MAAAA,CAAOE,WAAW,CAAA,IAChC,CAACF,MAAOE,CAAAA,WAAW,CAAC8B,KAAK,CAAC,CAACC,IAAS,GAAA,OAAOA,IAAS,KAAA,QAAA,CAAQ,CAC9D,EAAA;QACA,MAAM,IAAIC,MAAOC,CAAAA,gBAAgB,CAC/B,iEAAA,CAAA;AAEJ;AAEA,IAAA,IAAI,CAACnC,MAAOC,CAAAA,YAAY,IAAI,CAACD,MAAAA,CAAOE,WAAW,EAAE;QAC/CW,MAAOI,CAAAA,GAAG,CAACC,IAAI,CACb,mHAAA,CAAA;AAEF,QAAA,OAAOU,UAAWQ,CAAAA,GAAG,CAAC,KAAO;gBAAEtB,OAAS,EAAA;aAAK,CAAA,CAAA;AAC/C;AAEA,IAAA,MAAMuB,kBAAqBT,GAAAA,UAAAA,CAAWQ,GAAG,CAAC,OAAOlE,IAAMoE,EAAAA,KAAAA,GAAAA;QACrD,IAAI;YACF,OAAO,MAAM1B,YAAa1C,CAAAA,IAAAA,EAAM8B,MAAQa,EAAAA,MAAAA,CAAAA;AAC1C,SAAA,CAAE,OAAOvC,KAAO,EAAA;AACduC,YAAAA,MAAAA,CAAOI,GAAG,CAAC3C,KAAK,CAAC,yCAA2C,EAAA;gBAC1DiE,SAAWD,EAAAA,KAAAA;gBACXlC,QAAUlC,EAAAA,IAAAA,EAAMoC,QAAQpC,IAAMsE,EAAAA,YAAAA;AAC9BlE,gBAAAA,KAAAA,EAAOA,KAAiBC,YAAAA,KAAAA,GAAQD,KAAME,CAAAA,OAAO,GAAGC,MAAOH,CAAAA,KAAAA;AACzD,aAAA,CAAA;YAEA,OAAO;gBACLwC,OAAS,EAAA,KAAA;gBACTxC,KAAO,EAAA;oBACL8C,IAAM,EAAA,kBAAA;oBACN5C,OAAS,EAAA,CAAC,oCAAoC,EAAE8D,KAAO,CAAA,CAAA;oBACvDjB,OAAS,EAAA;AACPiB,wBAAAA,KAAAA;wBACAlC,QAAUlC,EAAAA,IAAAA,EAAMoC,QAAQpC,IAAMsE,EAAAA,YAAAA;AAC9BC,wBAAAA,aAAAA,EAAenE,KAAiBC,YAAAA,KAAAA,GAAQD,KAAME,CAAAA,OAAO,GAAGC,MAAOH,CAAAA,KAAAA;AACjE;AACF;AACF,aAAA;AACF;AACF,KAAA,CAAA;IAEA,OAAOoE,OAAAA,CAAQC,GAAG,CAACN,kBAAAA,CAAAA;AACrB;AAEO,eAAeO,qBAAAA,CACpBjB,KAAU,EACVd,MAAmB,EAAA;IAMnB,MAAMgC,iBAAAA,GAAoB,MAAMnB,aAAAA,CAAcC,KAAOd,EAAAA,MAAAA,CAAAA;AACrD,IAAA,MAAMe,UAAaC,GAAAA,KAAAA,CAAMC,OAAO,CAACH,SAASA,KAAQ,GAAA;AAACA,QAAAA;AAAM,KAAA;AAEzD,IAAA,MAAMmB,aAAoB,EAAE;AAC5B,IAAA,MAAMC,iBAA2B,EAAE;AACnC,IAAA,MAAMb,SAA6B,EAAE;AAErC,IAAA,KAAK,MAAM,CAACI,KAAAA,EAAO1D,OAAO,IAAIiE,iBAAAA,CAAkBG,OAAO,EAAI,CAAA;QACzD,IAAIpE,MAAAA,CAAOkC,OAAO,EAAE;YAClB,MAAM5C,IAAAA,GAAO0D,UAAU,CAACU,KAAM,CAAA;AAC9BQ,YAAAA,UAAAA,CAAWG,IAAI,CAAC/E,IAAAA,CAAAA;AAChB6E,YAAAA,cAAAA,CAAeE,IAAI,CAAC/E,IAAAA,CAAKmC,gBAAgB,IAAInC,KAAKoC,IAAI,CAAA;SACjD,MAAA,IAAI1B,MAAON,CAAAA,KAAK,EAAE;AACvB4D,YAAAA,MAAAA,CAAOe,IAAI,CAAC;gBACV/E,IAAM0D,EAAAA,UAAU,CAACU,KAAM,CAAA;gBACvBY,aAAeZ,EAAAA,KAAAA;AACfhE,gBAAAA,KAAAA,EAAOM,OAAON;AAChB,aAAA,CAAA;SACK,MAAA;;AAEL4D,YAAAA,MAAAA,CAAOe,IAAI,CAAC;gBACV/E,IAAM0D,EAAAA,UAAU,CAACU,KAAM,CAAA;gBACvBY,aAAeZ,EAAAA,KAAAA;gBACfhE,KAAO,EAAA;oBACL8C,IAAM,EAAA,eAAA;oBACN5C,OAAS,EAAA,2CAAA;oBACT6C,OAAS,EAAA;AACPiB,wBAAAA,KAAAA;wBACAlC,QAAUwB,EAAAA,UAAU,CAACU,KAAM,CAAA,EAAEhC,QAAQsB,UAAU,CAACU,MAAM,EAAEE;AAC1D;AACF;AACF,aAAA,CAAA;AACF;AACF;IAEA,OAAO;AAAEM,QAAAA,UAAAA;AAAYC,QAAAA,cAAAA;AAAgBb,QAAAA;AAAO,KAAA;AAC9C;AAaA;;AAEC,IACM,eAAeiB,oBAAAA,CACpBC,UAAe,EACfC,IAAS,EACTxC,MAAmB,EAAA;IAEnB,MAAMyC,eAAAA,GAAkB,MAAMV,qBAAAA,CAAsBQ,UAAYvC,EAAAA,MAAAA,CAAAA;AAEhE,IAAA,IAAI0C,YAAeF,GAAAA,IAAAA;AACnB,IAAA,IAAIA,MAAMG,QAAU,EAAA;;QAElB,IAAIC,cAAAA,GAAiBJ,KAAKG,QAAQ;AAClC,QAAA,IAAI3B,KAAMC,CAAAA,OAAO,CAACuB,IAAAA,CAAKG,QAAQ,CAAG,EAAA;AAChCC,YAAAA,cAAAA,GAAiBJ,IAAKG,CAAAA,QAAQ,CAACpB,GAAG,CAAC,CAACsB,EAClC,GAAA,OAAOA,EAAO,KAAA,QAAA,GAAWC,IAAKC,CAAAA,KAAK,CAACF,EAAMA,CAAAA,GAAAA,EAAAA,CAAAA;AAE9C,SAAA,MAAO,IAAI,OAAOL,IAAKG,CAAAA,QAAQ,KAAK,QAAU,EAAA;AAC5CC,YAAAA,cAAAA,GAAiBE,IAAKC,CAAAA,KAAK,CAACP,IAAAA,CAAKG,QAAQ,CAAA;AAC3C;;QAGA,IAAI3B,KAAAA,CAAMC,OAAO,CAAC2B,cAAiB,CAAA,EAAA;YACjC,MAAMI,cAAAA,GAAiB,IAAIC,GAAAA,CAAIR,eAAgBpB,CAAAA,MAAM,CAACE,GAAG,CAAC,CAAC2B,CAAMA,GAAAA,CAAAA,CAAEb,aAAa,CAAA,CAAA;YAChF,MAAMc,gBAAAA,GAAmBP,cAAeQ,CAAAA,MAAM,CAC5C,CAACC,GAAQ5B,KAAkB,GAAA,CAACuB,cAAeM,CAAAA,GAAG,CAAC7B,KAAAA,CAAAA,CAAAA;YAGjD,IAAI0B,gBAAAA,CAAiBjG,MAAM,KAAK,CAAG,EAAA;gBACjCwF,YAAe,GAAA;AACb,oBAAA,GAAGF,IAAI;oBACPG,QAAUQ,EAAAA,gBAAgB,CAAC,CAAE;AAC/B,iBAAA;aACK,MAAA;gBACLT,YAAe,GAAA;AACb,oBAAA,GAAGF,IAAI;oBACPG,QAAUQ,EAAAA;AACZ,iBAAA;AACF;SACK,MAAA;YACLT,YAAe,GAAA;AACb,gBAAA,GAAGF,IAAI;gBACPG,QAAUC,EAAAA;AACZ,aAAA;AACF;AACF;;IAGA,MAAMW,YAAAA,GAAkCd,gBAAgBpB,MAAM,CAACE,GAAG,CAAC,CAAC2B,KAAO;AACzEzD,YAAAA,IAAAA,EAAMyD,EAAE7F,IAAI,EAAEmC,oBAAoB0D,CAAE7F,CAAAA,IAAI,EAAEoC,IAAQ,IAAA,SAAA;YAClD9B,OAASuF,EAAAA,CAAAA,CAAEzF,KAAK,CAACE;SACnB,CAAA,CAAA;IAEA,OAAO;AACLsE,QAAAA,UAAAA,EAAYQ,gBAAgBR,UAAU;AACtCS,QAAAA,YAAAA;QACArB,MAAQkC,EAAAA;AACV,KAAA;AACF;;;;"}
|
|
@@ -83,6 +83,7 @@ export interface File {
|
|
|
83
83
|
updatedBy?: number;
|
|
84
84
|
isLocal?: boolean;
|
|
85
85
|
}
|
|
86
|
+
export type UploadFileInfo = Pick<File, 'name' | 'alternativeText' | 'caption' | 'focalPoint' | 'folder'>;
|
|
86
87
|
export interface RawFile extends Blob {
|
|
87
88
|
size: number;
|
|
88
89
|
lastModified: number;
|
|
@@ -187,6 +188,7 @@ export declare namespace DeleteFile {
|
|
|
187
188
|
}
|
|
188
189
|
/**
|
|
189
190
|
* POST /upload - Create a file
|
|
191
|
+
* @deprecated Use CreateFilesStream instead
|
|
190
192
|
*/
|
|
191
193
|
export declare namespace CreateFile {
|
|
192
194
|
interface Request {
|
|
@@ -198,6 +200,56 @@ export declare namespace CreateFile {
|
|
|
198
200
|
error?: errors.ApplicationError | errors.ValidationError;
|
|
199
201
|
}
|
|
200
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* POST /upload/unstable/stream - Stream upload files with partial success support
|
|
205
|
+
*/
|
|
206
|
+
export declare namespace CreateFilesStream {
|
|
207
|
+
interface FileUploadError {
|
|
208
|
+
name: string;
|
|
209
|
+
message: string;
|
|
210
|
+
}
|
|
211
|
+
interface Request {
|
|
212
|
+
body: FormData;
|
|
213
|
+
}
|
|
214
|
+
interface Response {
|
|
215
|
+
data: File[];
|
|
216
|
+
errors?: FileUploadError[];
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* POST /upload/unstable/stream - SSE streaming event types
|
|
221
|
+
*
|
|
222
|
+
* The endpoint streams Server-Sent Events as each file is processed.
|
|
223
|
+
* The final `stream:complete` event carries the same shape as CreateFilesStream.Response.
|
|
224
|
+
*/
|
|
225
|
+
export declare namespace CreateFilesStreamEvents {
|
|
226
|
+
interface FileUploadingEvent {
|
|
227
|
+
name: string;
|
|
228
|
+
index: number;
|
|
229
|
+
total: number;
|
|
230
|
+
size: number;
|
|
231
|
+
}
|
|
232
|
+
interface FileCompleteEvent {
|
|
233
|
+
name: string;
|
|
234
|
+
index: number;
|
|
235
|
+
file: File;
|
|
236
|
+
}
|
|
237
|
+
interface FileErrorEvent {
|
|
238
|
+
name: string;
|
|
239
|
+
index: number;
|
|
240
|
+
message: string;
|
|
241
|
+
}
|
|
242
|
+
interface StreamCompleteEvent {
|
|
243
|
+
data: File[];
|
|
244
|
+
errors: CreateFilesStream.FileUploadError[];
|
|
245
|
+
}
|
|
246
|
+
type SSEEventMap = {
|
|
247
|
+
'file:uploading': FileUploadingEvent;
|
|
248
|
+
'file:complete': FileCompleteEvent;
|
|
249
|
+
'file:error': FileErrorEvent;
|
|
250
|
+
'stream:complete': StreamCompleteEvent;
|
|
251
|
+
};
|
|
252
|
+
}
|
|
201
253
|
/**
|
|
202
254
|
* POST /upload?id=:id - Update asset
|
|
203
255
|
*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../../shared/contracts/files.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@strapi/upload",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.36.1",
|
|
4
4
|
"description": "Makes it easy to upload images and files to your Strapi Application.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"author": {
|
|
@@ -61,12 +61,14 @@
|
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"@mux/mux-player-react": "3.1.0",
|
|
64
|
+
"@radix-ui/react-dialog": "1.1.15",
|
|
65
|
+
"@radix-ui/react-toggle-group": "1.1.11",
|
|
64
66
|
"@reduxjs/toolkit": "1.9.7",
|
|
65
|
-
"@strapi/database": "5.
|
|
67
|
+
"@strapi/database": "5.36.1",
|
|
66
68
|
"@strapi/design-system": "2.1.2",
|
|
67
69
|
"@strapi/icons": "2.1.2",
|
|
68
|
-
"@strapi/provider-upload-local": "5.
|
|
69
|
-
"@strapi/utils": "5.
|
|
70
|
+
"@strapi/provider-upload-local": "5.36.1",
|
|
71
|
+
"@strapi/utils": "5.36.1",
|
|
70
72
|
"byte-size": "8.1.1",
|
|
71
73
|
"cropperjs": "1.6.1",
|
|
72
74
|
"date-fns": "2.30.0",
|
|
@@ -79,7 +81,7 @@
|
|
|
79
81
|
"lodash": "4.17.21",
|
|
80
82
|
"mime-types": "2.1.35",
|
|
81
83
|
"prop-types": "^15.8.1",
|
|
82
|
-
"qs": "6.14.
|
|
84
|
+
"qs": "6.14.2",
|
|
83
85
|
"react-dnd": "16.0.1",
|
|
84
86
|
"react-intl": "6.6.2",
|
|
85
87
|
"react-query": "3.39.3",
|
|
@@ -90,8 +92,8 @@
|
|
|
90
92
|
"zod": "3.25.67"
|
|
91
93
|
},
|
|
92
94
|
"devDependencies": {
|
|
93
|
-
"@strapi/admin": "5.
|
|
94
|
-
"@strapi/types": "5.
|
|
95
|
+
"@strapi/admin": "5.36.1",
|
|
96
|
+
"@strapi/types": "5.36.1",
|
|
95
97
|
"@testing-library/dom": "10.4.1",
|
|
96
98
|
"@testing-library/react": "16.3.0",
|
|
97
99
|
"@testing-library/user-event": "14.6.1",
|
|
@@ -106,14 +108,14 @@
|
|
|
106
108
|
"msw": "1.3.0",
|
|
107
109
|
"react": "18.3.1",
|
|
108
110
|
"react-dom": "18.3.1",
|
|
109
|
-
"react-router-dom": "6.
|
|
111
|
+
"react-router-dom": "6.30.3",
|
|
110
112
|
"styled-components": "6.1.8"
|
|
111
113
|
},
|
|
112
114
|
"peerDependencies": {
|
|
113
115
|
"@strapi/admin": "^5.0.0",
|
|
114
116
|
"react": "^17.0.0 || ^18.0.0",
|
|
115
117
|
"react-dom": "^17.0.0 || ^18.0.0",
|
|
116
|
-
"react-router-dom": "^6.
|
|
118
|
+
"react-router-dom": "^6.30.3",
|
|
117
119
|
"styled-components": "^6.0.0"
|
|
118
120
|
},
|
|
119
121
|
"engines": {
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
-
var strapiAdmin = require('@strapi/admin/strapi-admin');
|
|
5
|
-
var designSystem = require('@strapi/design-system');
|
|
6
|
-
|
|
7
|
-
const AIGenerationPage = ()=>{
|
|
8
|
-
return /*#__PURE__*/ jsxRuntime.jsxs(strapiAdmin.Layouts.Root, {
|
|
9
|
-
children: [
|
|
10
|
-
/*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Layouts.Header, {
|
|
11
|
-
title: "AI Generation",
|
|
12
|
-
primaryAction: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
|
|
13
|
-
children: "TODO: Generate"
|
|
14
|
-
})
|
|
15
|
-
}),
|
|
16
|
-
/*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Layouts.Content, {
|
|
17
|
-
children: "TODO: AI ListView"
|
|
18
|
-
})
|
|
19
|
-
]
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
exports.AIGenerationPage = AIGenerationPage;
|
|
24
|
-
//# sourceMappingURL=AIGenerationPage.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AIGenerationPage.js","sources":["../../../../admin/src/future/pages/AIGenerationPage.tsx"],"sourcesContent":["import { Layouts } from '@strapi/admin/strapi-admin';\nimport { Button } from '@strapi/design-system';\n\nexport const AIGenerationPage = () => {\n return (\n <Layouts.Root>\n <Layouts.Header title=\"AI Generation\" primaryAction={<Button>TODO: Generate</Button>} />\n\n <Layouts.Content>TODO: AI ListView</Layouts.Content>\n </Layouts.Root>\n );\n};\n"],"names":["AIGenerationPage","_jsxs","Layouts","Root","_jsx","Header","title","primaryAction","Button","Content"],"mappings":";;;;;;MAGaA,gBAAmB,GAAA,IAAA;IAC9B,qBACEC,eAAA,CAACC,oBAAQC,IAAI,EAAA;;AACX,0BAAAC,cAAA,CAACF,oBAAQG,MAAM,EAAA;gBAACC,KAAM,EAAA,eAAA;AAAgBC,gBAAAA,aAAAA,gBAAeH,cAACI,CAAAA,mBAAAA,EAAAA;AAAO,oBAAA,QAAA,EAAA;;;AAE7D,0BAAAJ,cAAA,CAACF,oBAAQO,OAAO,EAAA;AAAC,gBAAA,QAAA,EAAA;;;;AAGvB;;;;"}
|