diff --git a/apps/space/helpers/file.helper.ts b/apps/space/helpers/file.helper.ts index f693940ab..0d396bbd2 100644 --- a/apps/space/helpers/file.helper.ts +++ b/apps/space/helpers/file.helper.ts @@ -1,18 +1,5 @@ +// plane imports import { API_BASE_URL } from "@plane/constants"; -import { TFileMetaDataLite, TFileSignedURLResponse } from "@plane/types"; - -/** - * @description from the provided signed URL response, generate a payload to be used to upload the file - * @param {TFileSignedURLResponse} signedURLResponse - * @param {File} file - * @returns {FormData} file upload request payload - */ -export const generateFileUploadPayload = (signedURLResponse: TFileSignedURLResponse, file: File): FormData => { - const formData = new FormData(); - Object.entries(signedURLResponse.upload_data.fields).forEach(([key, value]) => formData.append(key, value)); - formData.append("file", file); - return formData; -}; /** * @description combine the file path with the base URL @@ -26,17 +13,6 @@ export const getFileURL = (path: string): string | undefined => { return `${API_BASE_URL}${path}`; }; -/** - * @description returns the necessary file meta data to upload a file - * @param {File} file - * @returns {TFileMetaDataLite} payload with file info - */ -export const getFileMetaDataForUpload = (file: File): TFileMetaDataLite => ({ - name: file.name, - size: file.size, - type: file.type, -}); - /** * @description this function returns the assetId from the asset source * @param {string} src diff --git a/apps/web/core/services/file.service.ts b/apps/web/core/services/file.service.ts index c18960cdb..47a531fc3 100644 --- a/apps/web/core/services/file.service.ts +++ b/apps/web/core/services/file.service.ts @@ -1,9 +1,10 @@ import { AxiosRequestConfig } from "axios"; // plane types import { API_BASE_URL } from "@plane/constants"; +import { getFileMetaDataForUpload, generateFileUploadPayload } from "@plane/services"; import { TFileEntityInfo, TFileSignedURLResponse } from "@plane/types"; +import { getAssetIdFromUrl } from "@plane/utils"; // helpers -import { generateFileUploadPayload, getAssetIdFromUrl, getFileMetaDataForUpload } from "@plane/utils"; // services import { APIService } from "@/services/api.service"; import { FileUploadService } from "@/services/file-upload.service"; @@ -68,7 +69,7 @@ export class FileService extends APIService { file: File, uploadProgressHandler?: AxiosRequestConfig["onUploadProgress"] ): Promise { - const fileMetaData = getFileMetaDataForUpload(file); + const fileMetaData = await getFileMetaDataForUpload(file); return this.post(`/api/assets/v2/workspaces/${workspaceSlug}/`, { ...data, ...fileMetaData, @@ -145,7 +146,7 @@ export class FileService extends APIService { file: File, uploadProgressHandler?: AxiosRequestConfig["onUploadProgress"] ): Promise { - const fileMetaData = getFileMetaDataForUpload(file); + const fileMetaData = await getFileMetaDataForUpload(file); return this.post(`/api/assets/v2/workspaces/${workspaceSlug}/projects/${projectId}/`, { ...data, ...fileMetaData, @@ -175,7 +176,7 @@ export class FileService extends APIService { } async uploadUserAsset(data: TFileEntityInfo, file: File): Promise { - const fileMetaData = getFileMetaDataForUpload(file); + const fileMetaData = await getFileMetaDataForUpload(file); return this.post(`/api/assets/v2/user-assets/`, { ...data, ...fileMetaData, diff --git a/apps/web/core/services/issue/issue_attachment.service.ts b/apps/web/core/services/issue/issue_attachment.service.ts index 740843791..5d512606a 100644 --- a/apps/web/core/services/issue/issue_attachment.service.ts +++ b/apps/web/core/services/issue/issue_attachment.service.ts @@ -1,9 +1,8 @@ import { AxiosRequestConfig } from "axios"; import { API_BASE_URL } from "@plane/constants"; // plane types +import { getFileMetaDataForUpload, generateFileUploadPayload } from "@plane/services"; import { EIssueServiceType, TIssueAttachment, TIssueAttachmentUploadResponse, TIssueServiceType } from "@plane/types"; -// helpers -import { generateFileUploadPayload, getFileMetaDataForUpload } from "@plane/utils"; // services import { APIService } from "@/services/api.service"; import { FileUploadService } from "@/services/file-upload.service"; @@ -41,7 +40,7 @@ export class IssueAttachmentService extends APIService { file: File, uploadProgressHandler?: AxiosRequestConfig["onUploadProgress"] ): Promise { - const fileMetaData = getFileMetaDataForUpload(file); + const fileMetaData = await getFileMetaDataForUpload(file); return this.post( `/api/assets/v2/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/attachments/`, fileMetaData diff --git a/packages/services/package.json b/packages/services/package.json index 3f7fca38f..eea823d9c 100644 --- a/packages/services/package.json +++ b/packages/services/package.json @@ -23,7 +23,8 @@ "dependencies": { "@plane/constants": "workspace:*", "@plane/types": "workspace:*", - "axios": "catalog:" + "axios": "catalog:", + "file-type": "^21.0.0" }, "devDependencies": { "@plane/eslint-config": "workspace:*", diff --git a/packages/services/src/file/helper.ts b/packages/services/src/file/helper.ts index 4b812cfde..49f47c2af 100644 --- a/packages/services/src/file/helper.ts +++ b/packages/services/src/file/helper.ts @@ -1,3 +1,6 @@ +// external imports +import { fileTypeFromBuffer } from "file-type"; +// plane imports import { TFileMetaDataLite, TFileSignedURLResponse } from "@plane/types"; /** @@ -13,16 +16,63 @@ export const generateFileUploadPayload = (signedURLResponse: TFileSignedURLRespo return formData; }; +/** + * @description Detect MIME type from file signature using file-type library + * @param {File} file + * @returns {Promise} detected MIME type or empty string if unknown + */ +const detectMimeTypeFromSignature = async (file: File): Promise => { + try { + // Read first 4KB which is usually sufficient for most file type detection + const chunk = file.slice(0, 4096); + const buffer = await chunk.arrayBuffer(); + const uint8Array = new Uint8Array(buffer); + + const fileType = await fileTypeFromBuffer(uint8Array); + return fileType?.mime || ""; + } catch (_error) { + return ""; + } +}; + +/** + * @description Determine the MIME type of a file using multiple detection methods + * @param {File} file + * @returns {Promise} detected MIME type + */ +const detectFileType = async (file: File): Promise => { + // check if the file has a MIME type + if (file.type && file.type.trim() !== "") { + return file.type; + } + + // detect from file signature using file-type library + try { + const signatureType = await detectMimeTypeFromSignature(file); + if (signatureType) { + return signatureType; + } + } catch (_error) { + console.error("Error detecting file type from signature:", _error); + } + + // fallback for unknown files + return "application/octet-stream"; +}; + /** * @description returns the necessary file meta data to upload a file * @param {File} file - * @returns {TFileMetaDataLite} payload with file info + * @returns {Promise} payload with file info */ -export const getFileMetaDataForUpload = (file: File): TFileMetaDataLite => ({ - name: file.name, - size: file.size, - type: file.type, -}); +export const getFileMetaDataForUpload = async (file: File): Promise => { + const fileType = await detectFileType(file); + return { + name: file.name, + size: file.size, + type: fileType, + }; +}; /** * @description this function returns the assetId from the asset source diff --git a/packages/services/src/file/index.ts b/packages/services/src/file/index.ts index 439db5ac7..d3b2a5290 100644 --- a/packages/services/src/file/index.ts +++ b/packages/services/src/file/index.ts @@ -1,3 +1,4 @@ export * from "./file-upload.service"; export * from "./sites-file.service"; export * from "./file.service"; +export * from "./helper"; diff --git a/packages/services/src/file/sites-file.service.ts b/packages/services/src/file/sites-file.service.ts index 2d606a09e..0536c5043 100644 --- a/packages/services/src/file/sites-file.service.ts +++ b/packages/services/src/file/sites-file.service.ts @@ -74,7 +74,7 @@ export class SitesFileService extends FileService { * @throws {Error} If the request fails */ async uploadAsset(anchor: string, data: TFileEntityInfo, file: File): Promise { - const fileMetaData = getFileMetaDataForUpload(file); + const fileMetaData = await getFileMetaDataForUpload(file); return this.post(`/api/public/assets/v2/anchor/${anchor}/`, { ...data, ...fileMetaData, diff --git a/packages/utils/src/file.ts b/packages/utils/src/file.ts index 225c574c1..632be9265 100644 --- a/packages/utils/src/file.ts +++ b/packages/utils/src/file.ts @@ -1,6 +1,5 @@ // plane imports import { API_BASE_URL } from "@plane/constants"; -import { TFileMetaDataLite, TFileSignedURLResponse } from "@plane/types"; /** * @description combine the file path with the base URL @@ -14,30 +13,6 @@ export const getFileURL = (path: string): string | undefined => { return `${API_BASE_URL}${path}`; }; -/** - * @description from the provided signed URL response, generate a payload to be used to upload the file - * @param {TFileSignedURLResponse} signedURLResponse - * @param {File} file - * @returns {FormData} file upload request payload - */ -export const generateFileUploadPayload = (signedURLResponse: TFileSignedURLResponse, file: File): FormData => { - const formData = new FormData(); - Object.entries(signedURLResponse.upload_data.fields).forEach(([key, value]) => formData.append(key, value)); - formData.append("file", file); - return formData; -}; - -/** - * @description returns the necessary file meta data to upload a file - * @param {File} file - * @returns {TFileMetaDataLite} payload with file info - */ -export const getFileMetaDataForUpload = (file: File): TFileMetaDataLite => ({ - name: file.name, - size: file.size, - type: file.type, -}); - /** * @description this function returns the assetId from the asset source * @param {string} src diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8616671c6..798d47b12 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1088,6 +1088,9 @@ importers: axios: specifier: 'catalog:' version: 1.12.0 + file-type: + specifier: ^21.0.0 + version: 21.0.0 devDependencies: '@plane/eslint-config': specifier: workspace:* @@ -1546,6 +1549,9 @@ packages: '@types/react': optional: true + '@borewit/text-codec@0.1.1': + resolution: {integrity: sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA==} + '@bprogress/core@1.3.4': resolution: {integrity: sha512-q/AqpurI/1uJzOrQROuZWixn/+ARekh+uvJGwLCP6HQ/EqAX4SkvNf618tSBxL4NysC0MwqAppb/mRw6Tzi61w==} @@ -2203,8 +2209,8 @@ packages: '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} - '@napi-rs/wasm-runtime@1.0.5': - resolution: {integrity: sha512-TBr9Cf9onSAS2LQ2+QHx6XcC6h9+RIzJgbqG3++9TUZSH204AwEy5jg3BTQ0VATsyoGj4ee49tN/y6rvaOOtcg==} + '@napi-rs/wasm-runtime@1.0.3': + resolution: {integrity: sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q==} '@next/env@14.2.32': resolution: {integrity: sha512-n9mQdigI6iZ/DF6pCTwMKeWgF2e8lg7qgt5M7HXMLtyhZYMnf/u905M18sSpPmHL9MKp9JHo56C6jrD2EvWxng==} @@ -2648,51 +2654,101 @@ packages: rollup: optional: true + '@rollup/rollup-android-arm-eabi@4.50.0': + resolution: {integrity: sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ==} + cpu: [arm] + os: [android] + '@rollup/rollup-android-arm-eabi@4.52.4': resolution: {integrity: sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==} cpu: [arm] os: [android] + '@rollup/rollup-android-arm64@4.50.0': + resolution: {integrity: sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw==} + cpu: [arm64] + os: [android] + '@rollup/rollup-android-arm64@4.52.4': resolution: {integrity: sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==} cpu: [arm64] os: [android] + '@rollup/rollup-darwin-arm64@4.50.0': + resolution: {integrity: sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg==} + cpu: [arm64] + os: [darwin] + '@rollup/rollup-darwin-arm64@4.52.4': resolution: {integrity: sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==} cpu: [arm64] os: [darwin] + '@rollup/rollup-darwin-x64@4.50.0': + resolution: {integrity: sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw==} + cpu: [x64] + os: [darwin] + '@rollup/rollup-darwin-x64@4.52.4': resolution: {integrity: sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==} cpu: [x64] os: [darwin] + '@rollup/rollup-freebsd-arm64@4.50.0': + resolution: {integrity: sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ==} + cpu: [arm64] + os: [freebsd] + '@rollup/rollup-freebsd-arm64@4.52.4': resolution: {integrity: sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==} cpu: [arm64] os: [freebsd] + '@rollup/rollup-freebsd-x64@4.50.0': + resolution: {integrity: sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA==} + cpu: [x64] + os: [freebsd] + '@rollup/rollup-freebsd-x64@4.52.4': resolution: {integrity: sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==} cpu: [x64] os: [freebsd] + '@rollup/rollup-linux-arm-gnueabihf@4.50.0': + resolution: {integrity: sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w==} + cpu: [arm] + os: [linux] + '@rollup/rollup-linux-arm-gnueabihf@4.52.4': resolution: {integrity: sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==} cpu: [arm] os: [linux] + '@rollup/rollup-linux-arm-musleabihf@4.50.0': + resolution: {integrity: sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg==} + cpu: [arm] + os: [linux] + '@rollup/rollup-linux-arm-musleabihf@4.52.4': resolution: {integrity: sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==} cpu: [arm] os: [linux] + '@rollup/rollup-linux-arm64-gnu@4.50.0': + resolution: {integrity: sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g==} + cpu: [arm64] + os: [linux] + '@rollup/rollup-linux-arm64-gnu@4.52.4': resolution: {integrity: sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==} cpu: [arm64] os: [linux] + '@rollup/rollup-linux-arm64-musl@4.50.0': + resolution: {integrity: sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ==} + cpu: [arm64] + os: [linux] + '@rollup/rollup-linux-arm64-musl@4.52.4': resolution: {integrity: sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==} cpu: [arm64] @@ -2703,46 +2759,96 @@ packages: cpu: [loong64] os: [linux] + '@rollup/rollup-linux-loongarch64-gnu@4.50.0': + resolution: {integrity: sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.50.0': + resolution: {integrity: sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg==} + cpu: [ppc64] + os: [linux] + '@rollup/rollup-linux-ppc64-gnu@4.52.4': resolution: {integrity: sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==} cpu: [ppc64] os: [linux] + '@rollup/rollup-linux-riscv64-gnu@4.50.0': + resolution: {integrity: sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA==} + cpu: [riscv64] + os: [linux] + '@rollup/rollup-linux-riscv64-gnu@4.52.4': resolution: {integrity: sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==} cpu: [riscv64] os: [linux] + '@rollup/rollup-linux-riscv64-musl@4.50.0': + resolution: {integrity: sha512-LSXSGumSURzEQLT2e4sFqFOv3LWZsEF8FK7AAv9zHZNDdMnUPYH3t8ZlaeYYZyTXnsob3htwTKeWtBIkPV27iQ==} + cpu: [riscv64] + os: [linux] + '@rollup/rollup-linux-riscv64-musl@4.52.4': resolution: {integrity: sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==} cpu: [riscv64] os: [linux] + '@rollup/rollup-linux-s390x-gnu@4.50.0': + resolution: {integrity: sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ==} + cpu: [s390x] + os: [linux] + '@rollup/rollup-linux-s390x-gnu@4.52.4': resolution: {integrity: sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==} cpu: [s390x] os: [linux] + '@rollup/rollup-linux-x64-gnu@4.50.0': + resolution: {integrity: sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA==} + cpu: [x64] + os: [linux] + '@rollup/rollup-linux-x64-gnu@4.52.4': resolution: {integrity: sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==} cpu: [x64] os: [linux] + '@rollup/rollup-linux-x64-musl@4.50.0': + resolution: {integrity: sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw==} + cpu: [x64] + os: [linux] + '@rollup/rollup-linux-x64-musl@4.52.4': resolution: {integrity: sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==} cpu: [x64] os: [linux] + '@rollup/rollup-openharmony-arm64@4.50.0': + resolution: {integrity: sha512-PZkNLPfvXeIOgJWA804zjSFH7fARBBCpCXxgkGDRjjAhRLOR8o0IGS01ykh5GYfod4c2yiiREuDM8iZ+pVsT+Q==} + cpu: [arm64] + os: [openharmony] + '@rollup/rollup-openharmony-arm64@4.52.4': resolution: {integrity: sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==} cpu: [arm64] os: [openharmony] + '@rollup/rollup-win32-arm64-msvc@4.50.0': + resolution: {integrity: sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg==} + cpu: [arm64] + os: [win32] + '@rollup/rollup-win32-arm64-msvc@4.52.4': resolution: {integrity: sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==} cpu: [arm64] os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.50.0': + resolution: {integrity: sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw==} + cpu: [ia32] + os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.52.4': resolution: {integrity: sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==} cpu: [ia32] @@ -2753,6 +2859,11 @@ packages: cpu: [x64] os: [win32] + '@rollup/rollup-win32-x64-msvc@4.50.0': + resolution: {integrity: sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg==} + cpu: [x64] + os: [win32] + '@rollup/rollup-win32-x64-msvc@4.52.4': resolution: {integrity: sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==} cpu: [x64] @@ -3391,6 +3502,13 @@ packages: y-protocols: ^1.0.1 yjs: ^13.5.38 + '@tokenizer/inflate@0.2.7': + resolution: {integrity: sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==} + engines: {node: '>=18'} + + '@tokenizer/token@0.3.0': + resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + '@tsconfig/node10@1.0.11': resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} @@ -5158,6 +5276,9 @@ packages: fflate@0.4.8: resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -5166,6 +5287,10 @@ packages: resolution: {integrity: sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig==} engines: {node: '>= 12'} + file-type@21.0.0: + resolution: {integrity: sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==} + engines: {node: '>=20'} + filesize@10.1.6: resolution: {integrity: sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==} engines: {node: '>= 10.4.0'} @@ -7145,6 +7270,11 @@ packages: resolution: {integrity: sha512-Wwh7EwalMzzX3Yy3VN58VEajeR2Si8+HDNMf706jPLIqU7CxneRW+dQVfznf5O0TWTnJyu4npelwg2bzTXB1Nw==} hasBin: true + rollup@4.50.0: + resolution: {integrity: sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + rollup@4.52.4: resolution: {integrity: sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -7433,6 +7563,10 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + strtok3@10.3.4: + resolution: {integrity: sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==} + engines: {node: '>=18'} + style-loader@3.3.4: resolution: {integrity: sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==} engines: {node: '>= 12.13.0'} @@ -7614,6 +7748,10 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} + token-types@6.1.1: + resolution: {integrity: sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==} + engines: {node: '>=14.16'} + tough-cookie@5.1.2: resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} engines: {node: '>=16'} @@ -7777,6 +7915,10 @@ packages: uc.micro@2.1.0: resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + uint8array-extras@1.5.0: + resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} + engines: {node: '>=18'} + unbox-primitive@1.1.0: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} @@ -8401,6 +8543,8 @@ snapshots: optionalDependencies: '@types/react': 18.3.11 + '@borewit/text-codec@0.1.1': {} + '@bprogress/core@1.3.4': {} '@bprogress/next@3.2.12(next@14.2.32(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': @@ -9063,7 +9207,7 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true - '@napi-rs/wasm-runtime@1.0.5': + '@napi-rs/wasm-runtime@1.0.3': dependencies: '@emnapi/core': 1.5.0 '@emnapi/runtime': 1.5.0 @@ -9486,7 +9630,7 @@ snapshots: '@rolldown/binding-wasm32-wasi@1.0.0-beta.34': dependencies: - '@napi-rs/wasm-runtime': 1.0.5 + '@napi-rs/wasm-runtime': 1.0.3 optional: true '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.34': @@ -9508,69 +9652,132 @@ snapshots: optionalDependencies: rollup: 4.52.4 + '@rollup/rollup-android-arm-eabi@4.50.0': + optional: true + '@rollup/rollup-android-arm-eabi@4.52.4': optional: true + '@rollup/rollup-android-arm64@4.50.0': + optional: true + '@rollup/rollup-android-arm64@4.52.4': optional: true + '@rollup/rollup-darwin-arm64@4.50.0': + optional: true + '@rollup/rollup-darwin-arm64@4.52.4': optional: true + '@rollup/rollup-darwin-x64@4.50.0': + optional: true + '@rollup/rollup-darwin-x64@4.52.4': optional: true + '@rollup/rollup-freebsd-arm64@4.50.0': + optional: true + '@rollup/rollup-freebsd-arm64@4.52.4': optional: true + '@rollup/rollup-freebsd-x64@4.50.0': + optional: true + '@rollup/rollup-freebsd-x64@4.52.4': optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.50.0': + optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.52.4': optional: true + '@rollup/rollup-linux-arm-musleabihf@4.50.0': + optional: true + '@rollup/rollup-linux-arm-musleabihf@4.52.4': optional: true + '@rollup/rollup-linux-arm64-gnu@4.50.0': + optional: true + '@rollup/rollup-linux-arm64-gnu@4.52.4': optional: true + '@rollup/rollup-linux-arm64-musl@4.50.0': + optional: true + '@rollup/rollup-linux-arm64-musl@4.52.4': optional: true '@rollup/rollup-linux-loong64-gnu@4.52.4': optional: true + '@rollup/rollup-linux-loongarch64-gnu@4.50.0': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.50.0': + optional: true + '@rollup/rollup-linux-ppc64-gnu@4.52.4': optional: true + '@rollup/rollup-linux-riscv64-gnu@4.50.0': + optional: true + '@rollup/rollup-linux-riscv64-gnu@4.52.4': optional: true + '@rollup/rollup-linux-riscv64-musl@4.50.0': + optional: true + '@rollup/rollup-linux-riscv64-musl@4.52.4': optional: true + '@rollup/rollup-linux-s390x-gnu@4.50.0': + optional: true + '@rollup/rollup-linux-s390x-gnu@4.52.4': optional: true + '@rollup/rollup-linux-x64-gnu@4.50.0': + optional: true + '@rollup/rollup-linux-x64-gnu@4.52.4': optional: true + '@rollup/rollup-linux-x64-musl@4.50.0': + optional: true + '@rollup/rollup-linux-x64-musl@4.52.4': optional: true + '@rollup/rollup-openharmony-arm64@4.50.0': + optional: true + '@rollup/rollup-openharmony-arm64@4.52.4': optional: true + '@rollup/rollup-win32-arm64-msvc@4.50.0': + optional: true + '@rollup/rollup-win32-arm64-msvc@4.52.4': optional: true + '@rollup/rollup-win32-ia32-msvc@4.50.0': + optional: true + '@rollup/rollup-win32-ia32-msvc@4.52.4': optional: true '@rollup/rollup-win32-x64-gnu@4.52.4': optional: true + '@rollup/rollup-win32-x64-msvc@4.50.0': + optional: true + '@rollup/rollup-win32-x64-msvc@4.52.4': optional: true @@ -10331,6 +10538,16 @@ snapshots: y-protocols: 1.0.6(yjs@13.6.27) yjs: 13.6.27 + '@tokenizer/inflate@0.2.7': + dependencies: + debug: 4.4.3 + fflate: 0.8.2 + token-types: 6.1.1 + transitivePeerDependencies: + - supports-color + + '@tokenizer/token@0.3.0': {} + '@tsconfig/node10@1.0.11': optional: true @@ -10374,7 +10591,7 @@ snapshots: '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 22.12.0 + '@types/node': 22.17.2 '@types/chai@5.2.2': dependencies: @@ -10383,15 +10600,15 @@ snapshots: '@types/compression@1.8.1': dependencies: '@types/express': 4.17.23 - '@types/node': 22.12.0 + '@types/node': 22.17.2 '@types/connect@3.4.38': dependencies: - '@types/node': 22.12.0 + '@types/node': 22.17.2 '@types/cors@2.8.19': dependencies: - '@types/node': 22.12.0 + '@types/node': 22.17.2 '@types/d3-array@3.2.1': {} @@ -10441,14 +10658,14 @@ snapshots: '@types/express-serve-static-core@4.19.6': dependencies: - '@types/node': 22.12.0 + '@types/node': 22.17.2 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 0.17.5 '@types/express-serve-static-core@5.0.7': dependencies: - '@types/node': 22.12.0 + '@types/node': 22.17.2 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 0.17.5 @@ -10527,7 +10744,6 @@ snapshots: '@types/node@22.17.2': dependencies: undici-types: 6.21.0 - optional: true '@types/nprogress@0.2.3': {} @@ -10547,7 +10763,7 @@ snapshots: '@types/pino@6.3.12': dependencies: - '@types/node': 22.12.0 + '@types/node': 22.17.2 '@types/pino-pretty': 5.0.0 '@types/pino-std-serializers': 4.0.0 sonic-boom: 2.8.0 @@ -10587,12 +10803,12 @@ snapshots: '@types/send@0.17.5': dependencies: '@types/mime': 1.3.5 - '@types/node': 22.12.0 + '@types/node': 22.17.2 '@types/serve-static@1.15.8': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 22.12.0 + '@types/node': 22.17.2 '@types/send': 0.17.5 '@types/triple-beam@1.3.5': {} @@ -10611,7 +10827,7 @@ snapshots: '@types/ws@8.18.1': dependencies: - '@types/node': 22.12.0 + '@types/node': 22.17.2 '@typescript-eslint/eslint-plugin@8.40.0(@typescript-eslint/parser@8.40.0(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1)(typescript@5.8.3)': dependencies: @@ -12352,6 +12568,8 @@ snapshots: fflate@0.4.8: {} + fflate@0.8.2: {} + file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 @@ -12360,6 +12578,15 @@ snapshots: dependencies: tslib: 2.8.1 + file-type@21.0.0: + dependencies: + '@tokenizer/inflate': 0.2.7 + strtok3: 10.3.4 + token-types: 6.1.1 + uint8array-extras: 1.5.0 + transitivePeerDependencies: + - supports-color + filesize@10.1.6: {} fill-range@7.1.1: @@ -12985,7 +13212,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 22.12.0 + '@types/node': 22.17.2 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -14529,6 +14756,33 @@ snapshots: '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.34 '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.34 + rollup@4.50.0: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.50.0 + '@rollup/rollup-android-arm64': 4.50.0 + '@rollup/rollup-darwin-arm64': 4.50.0 + '@rollup/rollup-darwin-x64': 4.50.0 + '@rollup/rollup-freebsd-arm64': 4.50.0 + '@rollup/rollup-freebsd-x64': 4.50.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.50.0 + '@rollup/rollup-linux-arm-musleabihf': 4.50.0 + '@rollup/rollup-linux-arm64-gnu': 4.50.0 + '@rollup/rollup-linux-arm64-musl': 4.50.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.50.0 + '@rollup/rollup-linux-ppc64-gnu': 4.50.0 + '@rollup/rollup-linux-riscv64-gnu': 4.50.0 + '@rollup/rollup-linux-riscv64-musl': 4.50.0 + '@rollup/rollup-linux-s390x-gnu': 4.50.0 + '@rollup/rollup-linux-x64-gnu': 4.50.0 + '@rollup/rollup-linux-x64-musl': 4.50.0 + '@rollup/rollup-openharmony-arm64': 4.50.0 + '@rollup/rollup-win32-arm64-msvc': 4.50.0 + '@rollup/rollup-win32-ia32-msvc': 4.50.0 + '@rollup/rollup-win32-x64-msvc': 4.50.0 + fsevents: 2.3.3 + rollup@4.52.4: dependencies: '@types/estree': 1.0.8 @@ -14556,6 +14810,7 @@ snapshots: '@rollup/rollup-win32-x64-gnu': 4.52.4 '@rollup/rollup-win32-x64-msvc': 4.52.4 fsevents: 2.3.3 + optional: true rope-sequence@1.3.4: {} @@ -14937,6 +15192,10 @@ snapshots: strip-json-comments@3.1.1: {} + strtok3@10.3.4: + dependencies: + '@tokenizer/token': 0.3.0 + style-loader@3.3.4(webpack@5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.0)): dependencies: webpack: 5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.0) @@ -15113,6 +15372,12 @@ snapshots: toidentifier@1.0.1: {} + token-types@6.1.1: + dependencies: + '@borewit/text-codec': 0.1.1 + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + tough-cookie@5.1.2: dependencies: tldts: 6.1.86 @@ -15281,6 +15546,8 @@ snapshots: uc.micro@2.1.0: {} + uint8array-extras@1.5.0: {} + unbox-primitive@1.1.0: dependencies: call-bound: 1.0.4 @@ -15499,7 +15766,7 @@ snapshots: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.52.4 + rollup: 4.50.0 tinyglobby: 0.2.15 optionalDependencies: '@types/node': 22.17.2