From 26460ea04ef4e3439c86196a2f5c3910bdd6619b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 12:28:38 +0000 Subject: [PATCH 1/2] fix(deps): update uppy monorepo --- packages/web-app-files/package.json | 2 +- packages/web-pkg/package.json | 10 +++++----- packages/web-runtime/package.json | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/web-app-files/package.json b/packages/web-app-files/package.json index ffd449aae9c..f1b86fddd37 100644 --- a/packages/web-app-files/package.json +++ b/packages/web-app-files/package.json @@ -11,7 +11,7 @@ "@ownclouders/design-system": "workspace:^", "@ownclouders/web-client": "workspace:*", "@ownclouders/web-pkg": "workspace:*", - "@uppy/core": "^3.3.0", + "@uppy/core": "^3.3.0 || ^4.0.0", "@vueuse/core": "^11.0.0 || ^12.0.0", "axios": "1.7.9", "email-validator": "^2.0.4", diff --git a/packages/web-pkg/package.json b/packages/web-pkg/package.json index d1901f0e547..85016977a8f 100644 --- a/packages/web-pkg/package.json +++ b/packages/web-pkg/package.json @@ -42,11 +42,11 @@ "@sentry/vue": "^8.33.1", "@toast-ui/editor-plugin-code-syntax-highlight": "^3.1.0", "@toast-ui/editor": "^3.2.2", - "@uppy/core": "^3.3.0", - "@uppy/drop-target": "^2.0.0", - "@uppy/tus": "^3.1.0", - "@uppy/utils": "^5.3.0", - "@uppy/xhr-upload": "^3.0.1", + "@uppy/core": "^4.0.0", + "@uppy/drop-target": "^3.0.0", + "@uppy/tus": "^4.0.0", + "@uppy/utils": "^6.0.0", + "@uppy/xhr-upload": "^4.0.0", "@vue/shared": "^3.5.11", "@vueuse/core": "^12.0.0", "axios": "^1.7.7", diff --git a/packages/web-runtime/package.json b/packages/web-runtime/package.json index a19586cb13b..9ae19e91eef 100644 --- a/packages/web-runtime/package.json +++ b/packages/web-runtime/package.json @@ -12,11 +12,11 @@ "@ownclouders/web-client": "workspace:*", "@ownclouders/web-pkg": "workspace:*", "@sentry/vue": "8.42.0", - "@uppy/core": "3.3.0", - "@uppy/drop-target": "2.0.0", - "@uppy/tus": "3.1.0", - "@uppy/utils": "5.3.0", - "@uppy/xhr-upload": "3.0.1", + "@uppy/core": "4.3.1", + "@uppy/drop-target": "3.0.2", + "@uppy/tus": "4.1.5", + "@uppy/utils": "6.0.6", + "@uppy/xhr-upload": "4.2.3", "@vueuse/core": "12.0.0", "@vueuse/head": "2.0.0", "axios": "1.7.9", From e1828e7f70c7b30c300e713b5be16aa17cb4b9f6 Mon Sep 17 00:00:00 2001 From: Dominik Schmidt Date: Fri, 20 Dec 2024 15:19:00 +0100 Subject: [PATCH 2/2] refactor: switch back to upstream uppy --- package.json | 17 -- packages/web-app-files/package.json | 2 +- packages/web-app-files/src/HandleUpload.ts | 64 +++--- .../src/components/AppBar/CreateAndUpload.vue | 2 +- .../src/helpers/resource/actions/upload.ts | 8 +- .../tests/unit/HandleUpload.spec.ts | 54 ++--- .../components/AppBar/CreateAndUpload.spec.ts | 9 +- .../helpers/resource/actions/upload.spec.ts | 40 ++-- packages/web-pkg/package.json | 10 +- .../src/composables/upload/useUpload.ts | 29 ++- packages/web-pkg/src/services/uppy/index.ts | 1 - packages/web-pkg/src/services/uppy/types.ts | 40 ---- .../web-pkg/src/services/uppy/uppyService.ts | 117 ++++++---- .../web-runtime/src/components/UploadInfo.vue | 46 ++-- .../tests/unit/components/UploadInfo.spec.ts | 17 +- pnpm-lock.yaml | 208 +++++++++--------- 16 files changed, 331 insertions(+), 333 deletions(-) delete mode 100644 packages/web-pkg/src/services/uppy/types.ts diff --git a/package.json b/package.json index 6ee7e7a2c98..bed97b12c4e 100644 --- a/package.json +++ b/package.json @@ -96,23 +96,6 @@ "node": "22.12.0" }, "pnpm": { - "overrides": { - "@uppy/companion-client": "https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-companion-client.tgz", - "@uppy/core": "https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz", - "@uppy/dashboard": "https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-dashboard.tgz", - "@uppy/drop-target": "https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-drop-target.tgz", - "@uppy/google-drive": "https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-google-drive.tgz", - "@uppy/informer": "https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-informer.tgz", - "@uppy/onedrive": "https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-onedrive.tgz", - "@uppy/provider-views": "https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-provider-views.tgz", - "@uppy/status-bar": "https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-status-bar.tgz", - "@uppy/store-default": "https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-store-default.tgz", - "@uppy/thumbnail-generator": "https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-thumbnail-generator.tgz", - "@uppy/tus": "https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-tus.tgz", - "@uppy/utils": "https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-utils.tgz", - "@uppy/webdav": "https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-webdav.tgz", - "@uppy/xhr-upload": "https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-xhr-upload.tgz" - }, "packageExtensions": { "@toast-ui/editor": { "dependencies": { diff --git a/packages/web-app-files/package.json b/packages/web-app-files/package.json index f1b86fddd37..05122e21424 100644 --- a/packages/web-app-files/package.json +++ b/packages/web-app-files/package.json @@ -11,7 +11,7 @@ "@ownclouders/design-system": "workspace:^", "@ownclouders/web-client": "workspace:*", "@ownclouders/web-pkg": "workspace:*", - "@uppy/core": "^3.3.0 || ^4.0.0", + "@uppy/core": "4.3.1", "@vueuse/core": "^11.0.0 || ^12.0.0", "axios": "1.7.9", "email-validator": "^2.0.4", diff --git a/packages/web-app-files/src/HandleUpload.ts b/packages/web-app-files/src/HandleUpload.ts index 2a7524aea2c..775c5771a8e 100644 --- a/packages/web-app-files/src/HandleUpload.ts +++ b/packages/web-app-files/src/HandleUpload.ts @@ -1,4 +1,4 @@ -import Uppy, { BasePlugin, UppyFile } from '@uppy/core' +import Uppy, { BasePlugin } from '@uppy/core' import { basename, dirname, join } from 'path' import { v4 as uuidV4 } from 'uuid' import { Language } from 'vue3-gettext' @@ -13,11 +13,15 @@ import { SpacesStore, UserStore, locationPublicLink, - formatFileSize + formatFileSize, + OcUppyFile, + OcUppyMeta, + OcUppyBody } from '@ownclouders/web-pkg' -import { locationSpacesGeneric, UppyService, UppyResource } from '@ownclouders/web-pkg' +import { locationSpacesGeneric, UppyService } from '@ownclouders/web-pkg' import { isPersonalSpaceResource, isShareSpaceResource } from '@ownclouders/web-client' import { ClientService, queryItemAsString } from '@ownclouders/web-pkg' +import { PluginOpts } from '@uppy/core/lib/BasePlugin' export interface HandleUploadOptions { clientService: ClientService @@ -44,7 +48,7 @@ export interface HandleUploadOptions { * 4. create directory tree if needed * 5. start upload */ -export class HandleUpload extends BasePlugin { +export class HandleUpload extends BasePlugin { clientService: ClientService language: Language route: Ref @@ -58,7 +62,7 @@ export class HandleUpload extends BasePlugin { directoryTreeCreateEnabled: boolean conflictHandlingEnabled: boolean - constructor(uppy: Uppy, opts: HandleUploadOptions) { + constructor(uppy: Uppy, opts: HandleUploadOptions) { super(uppy, opts) this.id = opts.id || 'HandleUpload' this.type = 'modifier' @@ -81,7 +85,7 @@ export class HandleUpload extends BasePlugin { this.handleUpload = this.handleUpload.bind(this) } - removeFilesFromUpload(filesToUpload: UppyResource[]) { + removeFilesFromUpload(filesToUpload: OcUppyFile[]) { for (const file of filesToUpload) { this.uppy.removeFile(file.id) } @@ -104,8 +108,8 @@ export class HandleUpload extends BasePlugin { /** * Converts the input files type UppyResources and updates the uppy upload queue */ - prepareFiles(files: UppyFile[], uploadFolder: Resource): UppyResource[] { - const filesToUpload: Record = {} + prepareFiles(files: OcUppyFile[], uploadFolder: Resource): OcUppyFile[] { + const filesToUpload: Record = {} if (!this.resourcesStore.currentFolder && unref(this.route)?.params?.token) { // public file drop @@ -127,7 +131,7 @@ export class HandleUpload extends BasePlugin { uploadId: uuidV4() } - filesToUpload[file.id] = file as unknown as UppyResource + filesToUpload[file.id] = file } this.uppy.setState({ files: { ...this.uppy.getState().files, ...filesToUpload } }) return Object.values(filesToUpload) @@ -138,7 +142,7 @@ export class HandleUpload extends BasePlugin { const topLevelFolderIds: Record = {} for (const file of files) { - const relativeFilePath = (file.meta.relativePath || file.meta.webkitRelativePath) as string + const relativeFilePath = file.meta.relativePath // Directory without filename const directory = !relativeFilePath || dirname(relativeFilePath) === '.' ? '' : dirname(relativeFilePath) @@ -166,7 +170,7 @@ export class HandleUpload extends BasePlugin { ...file.meta, // file data name: file.name, - mtime: file.data.lastModified / 1000, + mtime: (file.data as File).lastModified / 1000, // current path & space spaceId: unref(this.space).id, spaceName: unref(this.space).name, @@ -186,27 +190,25 @@ export class HandleUpload extends BasePlugin { routeShareId: queryItemAsString(query?.shareId) || '' } - filesToUpload[file.id] = file as unknown as UppyResource + filesToUpload[file.id] = file } this.uppy.setState({ files: { ...this.uppy.getState().files, ...filesToUpload } }) return Object.values(filesToUpload) } - checkQuotaExceeded(filesToUpload: UppyResource[]): boolean { + checkQuotaExceeded(filesToUpload: OcUppyFile[]): boolean { let quotaExceeded = false - const uploadSizeSpaceMapping = filesToUpload.reduce((acc, uppyResource) => { + const uploadSizeSpaceMapping = filesToUpload.reduce((acc, uppyFile) => { let targetUploadSpace: SpaceResource - if (uppyResource.meta.routeName === locationPublicLink.name) { + if (uppyFile.meta.routeName === locationPublicLink.name) { return acc } - if (uppyResource.meta.routeName === locationSpacesGeneric.name) { - targetUploadSpace = this.spacesStore.spaces.find( - ({ id }) => id === uppyResource.meta.spaceId - ) + if (uppyFile.meta.routeName === locationSpacesGeneric.name) { + targetUploadSpace = this.spacesStore.spaces.find(({ id }) => id === uppyFile.meta.spaceId) } if ( @@ -219,7 +221,7 @@ export class HandleUpload extends BasePlugin { } const existingFile = this.resourcesStore.resources.find( - (c) => !uppyResource.meta.relativeFolder && c.name === uppyResource.name + (c) => !uppyFile.meta.relativeFolder && c.name === uppyFile.name ) const existingFileSize = existingFile ? Number(existingFile.size) : 0 @@ -230,12 +232,12 @@ export class HandleUpload extends BasePlugin { if (!matchingMappingRecord) { acc.push({ space: targetUploadSpace, - uploadSize: uppyResource.data.size - existingFileSize + uploadSize: uppyFile.data.size - existingFileSize }) return acc } - matchingMappingRecord.uploadSize = uppyResource.data.size - existingFileSize + matchingMappingRecord.uploadSize = uppyFile.data.size - existingFileSize return acc }, []) @@ -274,9 +276,9 @@ export class HandleUpload extends BasePlugin { * Creates the directory tree and removes files of failed directories from the upload queue. */ async createDirectoryTree( - filesToUpload: UppyResource[], + filesToUpload: OcUppyFile[], uploadFolder: Resource - ): Promise { + ): Promise { const { webdav } = this.clientService const space = unref(this.space) const { id: currentFolderId, path: currentFolderPath } = uploadFolder @@ -307,7 +309,7 @@ export class HandleUpload extends BasePlugin { const uploadId = !isRoot ? uuidV4() : topLevelIds[path] const relativeFolder = dirname(path) === '/' ? '' : dirname(path) - const uppyResource = { + const uppyFile = { id: uuidV4(), name: basename(path), isFolder: true, @@ -332,7 +334,7 @@ export class HandleUpload extends BasePlugin { return } - this.uppyService.publish('addedForUpload', [uppyResource]) + this.uppyService.publish('addedForUpload', [uppyFile]) try { const folder = await webdav.createFolder(space, { @@ -340,14 +342,14 @@ export class HandleUpload extends BasePlugin { fetchFolder: isRoot }) this.uppyService.publish('uploadSuccess', { - ...uppyResource, - meta: { ...uppyResource.meta, fileId: folder?.fileId } + ...uppyFile, + meta: { ...uppyFile.meta, fileId: folder?.fileId } }) } catch (error) { if (error.statusCode !== 405) { console.error(error) failedFolders.push(path) - this.uppyService.publish('uploadError', { file: uppyResource, error }) + this.uppyService.publish('uploadError', { file: uppyFile, error }) } } } @@ -380,7 +382,7 @@ export class HandleUpload extends BasePlugin { * The handler that prepares all files to be uploaded and goes through all necessary steps. * Eventually triggers to upload in Uppy. */ - async handleUpload(files: UppyFile[]) { + async handleUpload(files: OcUppyFile[]) { if (!files.length) { return } @@ -415,7 +417,7 @@ export class HandleUpload extends BasePlugin { } filesToUpload = result - const conflictMap = result.reduce>((acc, file) => { + const conflictMap = result.reduce>((acc, file) => { acc[file.id] = file return acc }, {}) diff --git a/packages/web-app-files/src/components/AppBar/CreateAndUpload.vue b/packages/web-app-files/src/components/AppBar/CreateAndUpload.vue index 8d1ab2678ee..27446d024bc 100644 --- a/packages/web-app-files/src/components/AppBar/CreateAndUpload.vue +++ b/packages/web-app-files/src/components/AppBar/CreateAndUpload.vue @@ -191,6 +191,7 @@ import { useFileActionsCreateNewShortcut, useMessages, useResourcesStore, + useRoute, useSharesStore, useSpacesStore, useUserStore @@ -225,7 +226,6 @@ import { } from '@ownclouders/web-client' import { useService, useUpload, UppyService, UploadResult } from '@ownclouders/web-pkg' import { HandleUpload } from '../../HandleUpload' -import { useRoute } from 'vue-router' import { useGettext } from 'vue3-gettext' import { useExtensionRegistry } from '@ownclouders/web-pkg' import { Action, ResourceIcon } from '@ownclouders/web-pkg' diff --git a/packages/web-app-files/src/helpers/resource/actions/upload.ts b/packages/web-app-files/src/helpers/resource/actions/upload.ts index 1407fcb21a7..9baedb7177c 100644 --- a/packages/web-app-files/src/helpers/resource/actions/upload.ts +++ b/packages/web-app-files/src/helpers/resource/actions/upload.ts @@ -3,12 +3,12 @@ import { Resource } from '@ownclouders/web-client' import { extractExtensionFromFile } from '@ownclouders/web-client' import { ConflictDialog, + OcUppyFile, ResolveConflict, resolveFileNameDuplicate, ResolveStrategy, ResourceConflictModal, ResourcesStore, - UppyResource, useModals } from '@ownclouders/web-pkg' @@ -59,7 +59,7 @@ export class UploadResourceConflict extends ConflictDialog { }) } - getConflicts(files: UppyResource[]): ConflictedResource[] { + getConflicts(files: OcUppyFile[]): ConflictedResource[] { const conflicts: ConflictedResource[] = [] for (const file of files) { const relativeFilePath = file.meta.relativePath @@ -87,9 +87,9 @@ export class UploadResourceConflict extends ConflictDialog { } async displayOverwriteDialog( - files: UppyResource[], + files: OcUppyFile[], conflicts: ConflictedResource[] - ): Promise { + ): Promise { let fileCount = 0 let folderCount = 0 const resolvedFileConflicts: { name: string; strategy: ResolveStrategy }[] = [] diff --git a/packages/web-app-files/tests/unit/HandleUpload.spec.ts b/packages/web-app-files/tests/unit/HandleUpload.spec.ts index c994a914143..9453b11e053 100644 --- a/packages/web-app-files/tests/unit/HandleUpload.spec.ts +++ b/packages/web-app-files/tests/unit/HandleUpload.spec.ts @@ -1,4 +1,4 @@ -import Uppy, { UppyFile, State, UIPlugin } from '@uppy/core' +import Uppy, { State, UnknownPlugin } from '@uppy/core' import { HandleUpload } from '../../src/HandleUpload' import { mock, mockDeep } from 'vitest-mock-extended' import { Resource, SpaceResource } from '@ownclouders/web-client' @@ -7,12 +7,14 @@ import { ref, unref } from 'vue' import { ClientService, UppyService, - UppyResource, locationSpacesGeneric, useUserStore, useMessages, useSpacesStore, - useResourcesStore + useResourcesStore, + OcUppyFile, + OcUppyMeta, + OcUppyBody } from '@ownclouders/web-pkg' import { Language } from 'vue3-gettext' import { UploadResourceConflict } from '../../src/helpers/resource/actions' @@ -20,6 +22,8 @@ import { createTestingPinia } from '@ownclouders/web-test-helpers' vi.mock('../../src/helpers/resource/actions') +type UppyPlugin = UnknownPlugin> + describe('HandleUpload', () => { it('installs the handleUpload callback when files are being added', () => { const { instance, mocks } = getWrapper() @@ -33,14 +37,14 @@ describe('HandleUpload', () => { }) it('removes files from the uppy upload queue', () => { const { instance, mocks } = getWrapper() - const fileToRemove = mock() + const fileToRemove = mock() instance.removeFilesFromUpload([fileToRemove]) expect(mocks.uppy.removeFile).toHaveBeenCalledWith(fileToRemove.id) }) it('correctly prepares all files that need to be uploaded', () => { const { instance, mocks } = getWrapper() - mocks.uppy.getPlugin.mockReturnValue(mock()) - const fileToUpload = mock({ name: 'name' }) + mocks.uppy.getPlugin.mockReturnValue(mock()) + const fileToUpload = mock({ name: 'name' }) const uploadFolder = mock({ id: '1', path: '/' }) const processedFiles = instance.prepareFiles([fileToUpload], uploadFolder) @@ -63,9 +67,9 @@ describe('HandleUpload', () => { describe('method createDirectoryTree', () => { it('creates a directory for a single file with a relative folder given', async () => { const { instance, mocks } = getWrapper() - mocks.uppy.getPlugin.mockReturnValue(mock()) + mocks.uppy.getPlugin.mockReturnValue(mock()) const relativeFolder = '/relativeFolder' - const fileToUpload = mock({ name: 'name', meta: { relativeFolder } }) + const fileToUpload = mock({ name: 'name', meta: { relativeFolder } }) const createdFolder = mock() mocks.opts.clientService.webdav.createFolder.mockResolvedValue(createdFolder) @@ -107,9 +111,9 @@ describe('HandleUpload', () => { vi.spyOn(console, 'error').mockImplementation(() => undefined) const { instance, mocks } = getWrapper() - mocks.uppy.getPlugin.mockReturnValue(mock()) + mocks.uppy.getPlugin.mockReturnValue(mock()) const relativeFolder = '/relativeFolder' - const fileToUpload = mock({ name: 'name', meta: { relativeFolder } }) + const fileToUpload = mock({ name: 'name', meta: { relativeFolder } }) mocks.opts.clientService.webdav.createFolder.mockRejectedValue({}) const result = await instance.createDirectoryTree([fileToUpload], mock()) @@ -123,7 +127,7 @@ describe('HandleUpload', () => { it('prepares files and eventually triggers the upload in uppy', async () => { const { instance, mocks } = getWrapper() const prepareFilesSpy = vi.spyOn(instance, 'prepareFiles') - await instance.handleUpload([mock({ name: 'name' })]) + await instance.handleUpload([mock({ name: 'name' })]) expect(prepareFilesSpy).toHaveBeenCalledTimes(1) expect(mocks.opts.uppyService.publish).toHaveBeenCalledWith( 'addedForUpload', @@ -135,13 +139,13 @@ describe('HandleUpload', () => { it('checks quota if check enabled', async () => { const { instance } = getWrapper() const checkQuotaExceededSpy = vi.spyOn(instance, 'checkQuotaExceeded') - await instance.handleUpload([mock({ name: 'name' })]) + await instance.handleUpload([mock({ name: 'name' })]) expect(checkQuotaExceededSpy).toHaveBeenCalled() }) it('does not check quota if check disabled', async () => { const { instance } = getWrapper({ quotaCheckEnabled: false }) const checkQuotaExceededSpy = vi.spyOn(instance, 'checkQuotaExceeded') - await instance.handleUpload([mock({ name: 'name' })]) + await instance.handleUpload([mock({ name: 'name' })]) expect(checkQuotaExceededSpy).not.toHaveBeenCalled() }) it.each([ @@ -160,7 +164,7 @@ describe('HandleUpload', () => { }) const { instance } = getWrapper({ spaces: [space] }) const result = await instance.checkQuotaExceeded([ - mock({ + mock({ name: 'name', meta: { spaceId: '1', routeName: locationSpacesGeneric.name as string }, data: { size } as Blob @@ -179,7 +183,7 @@ describe('HandleUpload', () => { }) const { instance } = getWrapper({ spaces: [space] }) const result = await instance.checkQuotaExceeded([ - mock({ + mock({ name: 'name', meta: { spaceId: '1', routeName: locationSpacesGeneric.name as string }, data: { size } as Blob @@ -198,7 +202,7 @@ describe('HandleUpload', () => { }) const { instance } = getWrapper({ spaces: [space] }) const result = await instance.checkQuotaExceeded([ - mock({ + mock({ name: 'name', meta: { spaceId: '1', routeName: locationSpacesGeneric.name as string }, data: { size } as Blob @@ -210,27 +214,27 @@ describe('HandleUpload', () => { describe('conflict handling check', () => { it('checks for conflicts if check enabled', async () => { const { instance, mocks } = getWrapper() - await instance.handleUpload([mock({ name: 'name' })]) + await instance.handleUpload([mock({ name: 'name' })]) expect(mocks.resourceConflict.getConflicts).toHaveBeenCalled() }) it('does not check for conflicts if check disabled', async () => { const { instance, mocks } = getWrapper({ conflictHandlingEnabled: false }) - await instance.handleUpload([mock({ name: 'name' })]) + await instance.handleUpload([mock({ name: 'name' })]) expect(mocks.resourceConflict.getConflicts).not.toHaveBeenCalled() }) it('does not start upload if all files were skipped in conflict handling', async () => { const { instance, mocks } = getWrapper({ conflicts: [{}], conflictHandlerResult: [] }) const removeFilesFromUploadSpy = vi.spyOn(instance, 'removeFilesFromUpload') - await instance.handleUpload([mock({ name: 'name' })]) + await instance.handleUpload([mock({ name: 'name' })]) expect(mocks.opts.uppyService.uploadFiles).not.toHaveBeenCalled() expect(mocks.opts.uppyService.clearInputs).toHaveBeenCalled() expect(removeFilesFromUploadSpy).toHaveBeenCalled() }) it('sets the result of the conflict handler as uppy file state', async () => { - const conflictHandlerResult = [mock({ id: '1' })] + const conflictHandlerResult = [mock({ id: '1' })] const { instance, mocks } = getWrapper({ conflicts: [{}], conflictHandlerResult }) - await instance.handleUpload([mock(), mock()]) + await instance.handleUpload([mock(), mock()]) expect(mocks.uppy.setState).toHaveBeenCalledWith({ files: { [conflictHandlerResult[0].id]: conflictHandlerResult[0] } @@ -241,13 +245,13 @@ describe('HandleUpload', () => { it('creates the directly tree if enabled', async () => { const { instance } = getWrapper() const createDirectoryTreeSpy = vi.spyOn(instance, 'createDirectoryTree') - await instance.handleUpload([mock({ name: 'name' })]) + await instance.handleUpload([mock({ name: 'name' })]) expect(createDirectoryTreeSpy).toHaveBeenCalled() }) it('does not create the directly tree if disabled', async () => { const { instance } = getWrapper({ directoryTreeCreateEnabled: false }) const createDirectoryTreeSpy = vi.spyOn(instance, 'createDirectoryTree') - await instance.handleUpload([mock({ name: 'name' })]) + await instance.handleUpload([mock({ name: 'name' })]) expect(createDirectoryTreeSpy).not.toHaveBeenCalled() }) }) @@ -271,8 +275,8 @@ const getWrapper = ({ route.params.driveAliasAndItem = '1' route.query.shareId = '1' - const uppy = mockDeep() - uppy.getState.mockReturnValue(mock({ files: {} })) + const uppy = mockDeep>() + uppy.getState.mockReturnValue(mock>({ files: {} })) createTestingPinia({ initialState: { diff --git a/packages/web-app-files/tests/unit/components/AppBar/CreateAndUpload.spec.ts b/packages/web-app-files/tests/unit/components/AppBar/CreateAndUpload.spec.ts index 19a1c46cb5e..188fad30caf 100644 --- a/packages/web-app-files/tests/unit/components/AppBar/CreateAndUpload.spec.ts +++ b/packages/web-app-files/tests/unit/components/AppBar/CreateAndUpload.spec.ts @@ -9,9 +9,10 @@ import { CapabilityStore, useClipboardStore, useFileActionsPaste, - useExtensionRegistry + useExtensionRegistry, + OcUppyFile } from '@ownclouders/web-pkg' -import { eventBus, UppyResource } from '@ownclouders/web-pkg' +import { eventBus } from '@ownclouders/web-pkg' import { defaultPlugins, shallowMount, defaultComponentMocks } from '@ownclouders/web-test-helpers' import { RouteLocation } from 'vue-router' import { computed, ref } from 'vue' @@ -140,7 +141,7 @@ describe('CreateAndUpload component', () => { { driveType: 'share', updated: 0 }, { driveType: 'public', updated: 0 } ])('updates the space quota for supported drive types: %s', async ({ driveType, updated }) => { - const file = mock({ meta: { driveType, spaceId: '1' } }) + const file = mock({ meta: { driveType, spaceId: '1' } }) const spaces = [ mock({ id: file.meta.spaceId, isOwner: () => driveType === 'personal' }) ] @@ -156,7 +157,7 @@ describe('CreateAndUpload component', () => { const itemId = 'itemId' const space = mock({ id: '1' }) const { wrapper, mocks } = getWrapper({ itemId, space }) - const file = mock({ + const file = mock({ meta: { driveType: 'project', spaceId: space.id, currentFolderId: itemId } }) const graphMock = mocks.$clientService.graphAuthenticated diff --git a/packages/web-app-files/tests/unit/helpers/resource/actions/upload.spec.ts b/packages/web-app-files/tests/unit/helpers/resource/actions/upload.spec.ts index ae88cfeb1b3..4fcd6089fc4 100644 --- a/packages/web-app-files/tests/unit/helpers/resource/actions/upload.spec.ts +++ b/packages/web-app-files/tests/unit/helpers/resource/actions/upload.spec.ts @@ -1,7 +1,7 @@ import { mock, mockDeep } from 'vitest-mock-extended' import { Language } from 'vue3-gettext' import { UploadResourceConflict } from '../../../../../src/helpers/resource' -import { ResolveStrategy, UppyResource, useResourcesStore } from '@ownclouders/web-pkg' +import { ResolveStrategy, OcUppyFile, useResourcesStore } from '@ownclouders/web-pkg' import { Resource } from '@ownclouders/web-client' import { createTestingPinia } from '@ownclouders/web-test-helpers' @@ -25,8 +25,8 @@ describe('upload helper', () => { mockDeep({ name: folderName }) ] const filesToUpload = [ - mockDeep({ name: fileName, meta: { relativePath: '', relativeFolder: '' } }), - mockDeep({ + mockDeep({ name: fileName, meta: { relativePath: '', relativeFolder: '' } }), + mockDeep({ name: 'anotherFile', meta: { relativePath: `/${folderName}/anotherFile` } }) @@ -43,14 +43,14 @@ describe('upload helper', () => { it.each([ResolveStrategy.REPLACE, ResolveStrategy.KEEP_BOTH])( 'should return all files if user chooses replace or keep both for all', async (strategy) => { - const uppyResource = mockDeep({ + const OcUppyFile = mockDeep({ name: 'test', meta: { relativeFolder: '' } }) const conflict = { - name: uppyResource.name, + name: OcUppyFile.name, type: 'file' } @@ -60,14 +60,14 @@ describe('upload helper', () => { ) instance.resolveFileExists = resolveFileConflictMethod - const result = await instance.displayOverwriteDialog([uppyResource], [conflict]) + const result = await instance.displayOverwriteDialog([OcUppyFile], [conflict]) expect(result.length).toBe(1) - expect(result).toEqual([uppyResource]) + expect(result).toEqual([OcUppyFile]) } ) it('should return no files if user chooses skip for all', async () => { - const uppyResource = mockDeep({ name: 'test' }) - const conflict = { name: uppyResource.name, type: 'file' } + const OcUppyFile = mockDeep({ name: 'test' }) + const conflict = { name: OcUppyFile.name, type: 'file' } const instance = getResourceConflictInstance() @@ -76,14 +76,14 @@ describe('upload helper', () => { ) instance.resolveFileExists = resolveFileConflictMethod - const result = await instance.displayOverwriteDialog([uppyResource], [conflict]) + const result = await instance.displayOverwriteDialog([OcUppyFile], [conflict]) expect(result.length).toBe(0) }) it('should show dialog once if do for all conflicts is ticked', async () => { - const uppyResourceOne = mockDeep({ name: 'test' }) - const uppyResourceTwo = mockDeep({ name: 'test2' }) - const conflictOne = { name: uppyResourceOne.name, type: 'file' } - const conflictTwo = { name: uppyResourceTwo.name, type: 'file' } + const OcUppyFileOne = mockDeep({ name: 'test' }) + const OcUppyFileTwo = mockDeep({ name: 'test2' }) + const conflictOne = { name: OcUppyFileOne.name, type: 'file' } + const conflictTwo = { name: OcUppyFileTwo.name, type: 'file' } const instance = getResourceConflictInstance() const resolveFileConflictMethod = vi.fn(() => @@ -92,21 +92,21 @@ describe('upload helper', () => { instance.resolveFileExists = resolveFileConflictMethod await instance.displayOverwriteDialog( - [uppyResourceOne, uppyResourceTwo], + [OcUppyFileOne, OcUppyFileTwo], [conflictOne, conflictTwo] ) expect(resolveFileConflictMethod).toHaveBeenCalledTimes(1) }) it('should show dialog twice if do for all conflicts is ticked and folders and files are uploaded', async () => { - const uppyResourceOne = mockDeep({ name: 'test' }) - const uppyResourceTwo = mockDeep({ name: 'folder' }) + const OcUppyFileOne = mockDeep({ name: 'test' }) + const OcUppyFileTwo = mockDeep({ name: 'folder' }) const conflictOne = { - name: uppyResourceOne.name, + name: OcUppyFileOne.name, type: 'file', meta: { relativeFolder: '/' } } - const conflictTwo = { name: uppyResourceTwo.name, type: 'folder' } + const conflictTwo = { name: OcUppyFileTwo.name, type: 'folder' } const instance = getResourceConflictInstance() instance.resolveFileExists = vi.fn(() => @@ -114,7 +114,7 @@ describe('upload helper', () => { ) await instance.displayOverwriteDialog( - [uppyResourceOne, uppyResourceTwo], + [OcUppyFileOne, OcUppyFileTwo], [conflictOne, conflictTwo] ) diff --git a/packages/web-pkg/package.json b/packages/web-pkg/package.json index 85016977a8f..32dd9a4f632 100644 --- a/packages/web-pkg/package.json +++ b/packages/web-pkg/package.json @@ -42,11 +42,11 @@ "@sentry/vue": "^8.33.1", "@toast-ui/editor-plugin-code-syntax-highlight": "^3.1.0", "@toast-ui/editor": "^3.2.2", - "@uppy/core": "^4.0.0", - "@uppy/drop-target": "^3.0.0", - "@uppy/tus": "^4.0.0", - "@uppy/utils": "^6.0.0", - "@uppy/xhr-upload": "^4.0.0", + "@uppy/core": "4.3.1", + "@uppy/drop-target": "3.0.2", + "@uppy/tus": "4.1.5", + "@uppy/utils": "6.0.6", + "@uppy/xhr-upload": "4.2.3", "@vue/shared": "^3.5.11", "@vueuse/core": "^12.0.0", "axios": "^1.7.7", diff --git a/packages/web-pkg/src/composables/upload/useUpload.ts b/packages/web-pkg/src/composables/upload/useUpload.ts index f9d69fcaf1f..f46657a03cd 100644 --- a/packages/web-pkg/src/composables/upload/useUpload.ts +++ b/packages/web-pkg/src/composables/upload/useUpload.ts @@ -1,10 +1,14 @@ import { computed, unref, watch } from 'vue' import { v4 as uuidV4 } from 'uuid' -import { UppyService } from '../../services/uppy/uppyService' +import { + OcTusOptions, + OcUppyBody, + OcUppyFile, + OcUppyMeta, + UppyService +} from '../../services/uppy/uppyService' import { useAuthStore, useCapabilityStore } from '../piniaStores' -import { TusOptions } from '@uppy/tus' import { XHRUploadOptions } from '@uppy/xhr-upload' -import { UppyFile } from '@uppy/core' import { useClientService } from '../clientService' import { useGettext } from 'vue3-gettext' @@ -37,17 +41,17 @@ export function useUpload(options: UploadOptions) { return headers } - const tusOptions = computed(() => { - const options: TusOptions = { + const tusOptions = computed(() => { + const options: OcTusOptions = { onBeforeRequest: (req, file) => - new Promise((resolve) => { + new Promise((resolve) => { const headers = getHeaders() req.setHeader('Authorization', headers.Authorization) req.setHeader('X-Request-ID', headers['X-Request-ID']) req.setHeader('Accept-Language', headers['Accept-Language']) req.setHeader('Initiator-ID', headers['Initiator-ID']) if (file?.isRemote) { - req.setHeader('x-oc-mtime', (file?.data?.lastModified / 1000).toString()) + req.setHeader('x-oc-mtime', ((file?.data as File)?.lastModified / 1000).toFixed(0)) } resolve() }), @@ -57,21 +61,24 @@ export function useUpload(options: UploadOptions) { } // FIXME: remove if cloud upload still works without this - ;(options as any)['headers'] = (file: UppyFile) => { + ;(options as any)['headers'] = (file: OcUppyFile) => { if (!!file.xhrUpload || file?.isRemote) { - return { 'x-oc-mtime': file?.data?.lastModified / 1000, ...getHeaders() } + return { + 'x-oc-mtime': ((file?.data as File)?.lastModified / 1000).toFixed(0), + ...getHeaders() + } } } return options }) - const xhrOptions = computed(() => { + const xhrOptions = computed>(() => { return { timeout: 60000, endpoint: '', headers: (file) => ({ - 'x-oc-mtime': file?.data?.lastModified / 1000, + 'x-oc-mtime': ((file?.data as File)?.lastModified / 1000).toFixed(0), ...getHeaders() }) } diff --git a/packages/web-pkg/src/services/uppy/index.ts b/packages/web-pkg/src/services/uppy/index.ts index 0d7e1bb7e3b..cbc67cad329 100644 --- a/packages/web-pkg/src/services/uppy/index.ts +++ b/packages/web-pkg/src/services/uppy/index.ts @@ -1,2 +1 @@ -export * from './types' export * from './uppyService' diff --git a/packages/web-pkg/src/services/uppy/types.ts b/packages/web-pkg/src/services/uppy/types.ts deleted file mode 100644 index a9c5f41f441..00000000000 --- a/packages/web-pkg/src/services/uppy/types.ts +++ /dev/null @@ -1,40 +0,0 @@ -export interface UppyResource { - id?: string - source: string - name: string - isFolder: boolean - type: string - size: number - data: Blob - isRemote: boolean - meta: { - // IMPORTANT: must only contain primitive types, complex types won't be serialized properly! - name?: string - mtime?: number - // current space & folder - spaceId: string - spaceName: string - driveAlias: string - driveType: string - currentFolder: string // current folder path during upload initiation - currentFolderId?: string - fileId?: string - // upload data - uppyId?: string - relativeFolder: string - relativePath: string - tusEndpoint: string - uploadId: string - topLevelFolderId?: string - // route data - routeName?: string - routeDriveAliasAndItem?: string - routeShareId?: string - } - tus?: { - endpoint: string - } - xhrUpload?: { - endpoint: string - } -} diff --git a/packages/web-pkg/src/services/uppy/uppyService.ts b/packages/web-pkg/src/services/uppy/uppyService.ts index 768fe0b8e0c..393d1589a88 100644 --- a/packages/web-pkg/src/services/uppy/uppyService.ts +++ b/packages/web-pkg/src/services/uppy/uppyService.ts @@ -1,4 +1,4 @@ -import Uppy, { BasePlugin, UppyFile, UIPlugin } from '@uppy/core' +import Uppy, { BasePlugin, UnknownPlugin, UppyFile } from '@uppy/core' import Tus from '@uppy/tus' import { TusOptions } from '@uppy/tus' import XHRUpload, { XHRUploadOptions } from '@uppy/xhr-upload' @@ -6,13 +6,10 @@ import { Language } from 'vue3-gettext' import { eventBus } from '../eventBus' import DropTarget from '@uppy/drop-target' import { Resource, urlJoin } from '@ownclouders/web-client' -import { UppyResource } from './types' - -// @ts-ignore -import getFileType from '@uppy/utils/lib/getFileType' // @ts-ignore import generateFileID from '@uppy/utils/lib/generateFileID' +import { Body, MinimalRequiredUppyFile } from '@uppy/utils/lib/UppyFile' type UppyServiceTopics = | 'uploadStarted' @@ -33,8 +30,8 @@ export type uppyHeaders = { } export type UploadResult = { - successful: UppyResource[] - failed: UppyResource[] + successful: OcUppyFile[] + failed: OcUppyFile[] uploadID?: string } @@ -42,17 +39,59 @@ interface UppyServiceOptions { language: Language } +type FileWithPath = File & { + readonly path?: string + readonly relativePath?: string +} + // FIXME: tus error types seem to be wrong in Uppy, we need the type of the tus client lib type TusClientError = Error & { originalResponse: any } +// IMPORTANT: must only contain primitive types, complex types won't be serialized properly! +export type OcUppyMeta = { + retry?: boolean + name?: string + mtime?: number + // current space & folder + spaceId: string + spaceName: string + driveAlias: string + driveType: string + currentFolder: string // current folder path during upload initiation + currentFolderId?: string + fileId?: string + // upload data + uppyId?: string + relativeFolder: string + relativePath: string + tusEndpoint: string + uploadId: string + topLevelFolderId?: string + // route data + routeName?: string + routeDriveAliasAndItem?: string + routeShareId?: string + + isFolder: boolean +} +export type OcUppyBody = Body +export type OcUppyFile = UppyFile +type OcUppyPlugin = typeof BasePlugin +export type OcMinimalUppyFile = MinimalRequiredUppyFile + +export type OcTusOptions = TusOptions + +/** `OmitFirstArg` is the type of the returned value of `someArray.slice(1)`. */ +type OmitFirstArg = T extends [any, ...infer U] ? U : never + export class UppyService { - uppy: Uppy + uppy: Uppy uploadInputs: HTMLInputElement[] = [] uploadFolderMap: Record = {} constructor({ language }: UppyServiceOptions) { const { $gettext } = language - this.uppy = new Uppy({ + this.uppy = new Uppy({ autoProceed: false, onBeforeFileAdded: (file, files) => { if (file.id in files) { @@ -60,12 +99,17 @@ export class UppyService { } file.meta.relativePath = this.getRelativeFilePath(file) // id needs to be generated after the relative path has been set. - file.id = generateFileID(file) + file.id = generateFileID(file, this.uppy.getID()) return file - }, + } + }) + + // FIXME: move to importer plugin, as strings are only visible in the dashboard anyhow + this.uppy.setOptions({ locale: { strings: { addedNumFiles: $gettext('Added %{numFiles} file(s)'), // for some reason this string is required and missing in uppy + authenticate: $gettext('Connect'), authenticateWith: $gettext('Connect to %{pluginName}'), authenticateWithTitle: $gettext('Please authenticate with %{pluginName} to select files'), cancel: $gettext('Cancel'), @@ -73,10 +117,7 @@ export class UppyService { loadedXFiles: $gettext('Loaded %{numFiles} files'), loading: $gettext('Loading...'), logOut: $gettext('Log out'), - publicLinkURLLabel: $gettext('Public Link URL'), - publicLinkURLDescription: $gettext( - 'Please provide a URL to a public link without password protection.' - ), + pluginWebdavInputLabel: $gettext('Public link without password protection'), selectX: { 0: $gettext('Select %{smart_count}'), 1: $gettext('Select %{smart_count}') @@ -89,24 +130,28 @@ export class UppyService { this.setUpEvents() } - getRelativeFilePath = (file: UppyFile): string | undefined => { + getRelativeFilePath = (file: OcUppyFile): string | undefined => { const relativePath = - file.webkitRelativePath || - file.relativePath || - file.data.relativePath || - file.data.webkitRelativePath + (file.data as FileWithPath).relativePath || (file.data as File).webkitRelativePath return relativePath ? urlJoin(relativePath) : undefined } - addPlugin(plugin: any, opts: any) { - this.uppy.use(plugin, opts) + addPlugin( + Plugin: T, + // We want to let the plugin decide whether `opts` is optional or not + // so we spread the argument rather than defining `opts:` ourselves. + ...args: OmitFirstArg> + ) { + this.uppy.use(Plugin, ...args) } - removePlugin(plugin: UIPlugin | BasePlugin) { + removePlugin(plugin: UnknownPlugin) { this.uppy.removePlugin(plugin) } - getPlugin(name: string): UIPlugin | BasePlugin { + getPlugin< + T extends UnknownPlugin = UnknownPlugin + >(name: string): T | undefined { return this.uppy.getPlugin(name) } @@ -116,8 +161,8 @@ export class UppyService { uploadDataDuringCreation, onBeforeRequest, headers - }: TusOptions) { - const tusPluginOptions: TusOptions = { + }: TusOptions) { + const tusPluginOptions: TusOptions = { chunkSize, removeFingerprintOnSuccess: true, overridePatchMethod, @@ -152,8 +197,8 @@ export class UppyService { this.uppy.use(Tus, tusPluginOptions) } - useXhr({ headers, timeout, endpoint }: XHRUploadOptions) { - const xhrPluginOptions: XHRUploadOptions = { + useXhr({ headers, timeout, endpoint }: XHRUploadOptions) { + const xhrPluginOptions: XHRUploadOptions = { endpoint, method: 'put', headers, @@ -251,7 +296,7 @@ export class UppyService { el.setAttribute('listener', 'true') el.addEventListener('change', (event) => { const target = event.target as HTMLInputElement - const files = Array.from(target.files) as unknown as UppyFile[] + const files = Array.from(target.files) this.addFiles(files) }) this.uploadInputs.push(el) @@ -262,17 +307,13 @@ export class UppyService { this.uploadInputs = this.uploadInputs.filter((input) => input !== el) } - generateUploadId(file: File): string { - return generateFileID({ - name: file.name, - size: file.size, - type: getFileType(file as unknown as UppyFile), - data: file - } as unknown as UppyFile) + generateUploadId(uppyFile: OcUppyFile): string { + return generateFileID(uppyFile, this.uppy.getID()) } - addFiles(files: UppyFile[]) { - this.uppy.addFiles(files) + addFiles(files: OcMinimalUppyFile[] | File[]) { + // uppy types say they do not accept File[] but they are wrong + this.uppy.addFiles(files as OcMinimalUppyFile[]) } uploadFiles() { diff --git a/packages/web-runtime/src/components/UploadInfo.vue b/packages/web-runtime/src/components/UploadInfo.vue index 4d6e2c89d55..601fdd733fc 100644 --- a/packages/web-runtime/src/components/UploadInfo.vue +++ b/packages/web-runtime/src/components/UploadInfo.vue @@ -162,20 +162,13 @@ import { isUndefined } from 'lodash-es' import getSpeed from '@uppy/utils/lib/getSpeed' import { HttpError, Resource, urlJoin } from '@ownclouders/web-client' -import { queryItemAsString, useConfigStore } from '@ownclouders/web-pkg' -import { - formatFileSize, - UppyResource, - ResourceListItem, - ResourceIcon, - ResourceName -} from '@ownclouders/web-pkg' +import { OcUppyFile, queryItemAsString, useConfigStore } from '@ownclouders/web-pkg' +import { formatFileSize, ResourceListItem, ResourceIcon, ResourceName } from '@ownclouders/web-pkg' import { extractParentFolderName } from '@ownclouders/web-client' import { storeToRefs } from 'pinia' import { RouteLocationNamedRaw } from 'vue-router' -interface UploadResult extends UppyResource { - extension?: string +interface UploadResult extends OcUppyFile { path?: string targetRoute?: RouteLocationNamedRaw status?: string @@ -338,8 +331,8 @@ export default defineComponent({ this.runningUploads += 1 this.inFinalization = false }) - this.$uppyService.subscribe('addedForUpload', (files: UppyResource[]) => { - this.filesInProgressCount += files.filter((f) => !f.isFolder).length + this.$uppyService.subscribe('addedForUpload', (files: OcUppyFile[]) => { + this.filesInProgressCount += files.filter((f) => !f.meta.isFolder).length for (const file of files) { if (!this.disableActions && file.isRemote) { @@ -356,7 +349,7 @@ export default defineComponent({ if (isTopLevelItem) { this.uploads[uploadId] = file // top level folders get initialized with file counts about their files inside - if (file.isFolder && this.uploads[uploadId].filesCount === undefined) { + if (file.meta.isFolder && this.uploads[uploadId].filesCount === undefined) { this.uploads[uploadId].filesCount = 0 this.uploads[uploadId].errorCount = 0 this.uploads[uploadId].successCount = 0 @@ -364,7 +357,7 @@ export default defineComponent({ } // count all files inside top level folders to mark them as successful or failed later - if (!file.isFolder && !isTopLevelItem && this.uploads[topLevelFolderId]) { + if (!file.meta.isFolder && !isTopLevelItem && this.uploads[topLevelFolderId]) { this.uploads[topLevelFolderId].filesCount += 1 } } @@ -381,7 +374,7 @@ export default defineComponent({ }) this.$uppyService.subscribe( 'upload-progress', - ({ file, progress }: { file: UppyResource; progress: { bytesUploaded: number } }) => { + ({ file, progress }: { file: OcUppyFile; progress: { bytesUploaded: number } }) => { if (!this.timeStarted) { this.timeStarted = new Date() this.inPreparation = false @@ -399,7 +392,8 @@ export default defineComponent({ this.uploadSpeed = getSpeed({ bytesUploaded: this.bytesUploaded, - uploadStarted: this.timeStarted + uploadStarted: this.timeStarted.getTime(), + bytesTotal: this.bytesTotal }) const progressPercent = (100 * this.bytesUploaded) / this.bytesTotal @@ -417,7 +411,7 @@ export default defineComponent({ ) this.$uppyService.subscribe( 'uploadError', - ({ file, error }: { file: UppyResource; error: Error }) => { + ({ file, error }: { file: OcUppyFile; error: Error }) => { if (this.errors[file.meta.uploadId]) { return } @@ -443,10 +437,10 @@ export default defineComponent({ } } ) - this.$uppyService.subscribe('uploadSuccess', (file: UppyResource) => { + this.$uppyService.subscribe('uploadSuccess', (file: OcUppyFile) => { // item inside folder if (!this.uploads[file.meta.uploadId]) { - if (!file.isFolder) { + if (!file.meta.isFolder) { this.successful.push(file.meta.uploadId) this.filesInProgressCount -= 1 @@ -460,7 +454,7 @@ export default defineComponent({ // file inside folder that succeeded via retry can now be removed again from this.uploads if (file.meta.relativeFolder) { - if (!file.isFolder) { + if (!file.meta.isFolder) { this.successful.push(file.meta.uploadId) this.filesInProgressCount -= 1 if (file.meta.topLevelFolderId) { @@ -476,7 +470,7 @@ export default defineComponent({ this.uploads[file.meta.uploadId].path = urlJoin(file.meta.currentFolder, file.name) this.uploads[file.meta.uploadId].targetRoute = this.buildRouteFromUppyResource(file) - if (!file.isFolder) { + if (!file.meta.isFolder) { this.uploads[file.meta.uploadId].status = 'success' this.successful.push(file.meta.uploadId) this.filesInProgressCount -= 1 @@ -507,7 +501,7 @@ export default defineComponent({ return this.$gettext('Few seconds left') }, - handleTopLevelFolderUpdate(file: UppyResource, status: string) { + handleTopLevelFolderUpdate(file: OcUppyFile, status: string) { const topLevelFolder = this.uploads[file.meta.topLevelFolderId] if (status === 'success') { topLevelFolder.successCount += 1 @@ -549,10 +543,10 @@ export default defineComponent({ return !!file.targetRoute }, isResourceClickable(file: UploadResult) { - return file.isFolder === true + return file.meta.isFolder === true }, resourceLink(file: UploadResult) { - if (!file.isFolder) { + if (!file.meta.isFolder) { return {} } return { @@ -584,7 +578,7 @@ export default defineComponent({ } } }, - buildRouteFromUppyResource(resource: UppyResource): RouteLocationNamedRaw { + buildRouteFromUppyResource(resource: OcUppyFile): RouteLocationNamedRaw { if (!resource.meta.routeName) { return null } @@ -656,7 +650,7 @@ export default defineComponent({ (u) => u.status !== 'success' && u.status !== 'error' ) - for (const item of runningUploads as UppyResource[]) { + for (const item of runningUploads) { this.uploads[item.meta.uploadId].status = 'cancelled' } }, diff --git a/packages/web-runtime/tests/unit/components/UploadInfo.spec.ts b/packages/web-runtime/tests/unit/components/UploadInfo.spec.ts index 626d82a8e30..51cbb16c5a8 100644 --- a/packages/web-runtime/tests/unit/components/UploadInfo.spec.ts +++ b/packages/web-runtime/tests/unit/components/UploadInfo.spec.ts @@ -1,6 +1,6 @@ import UploadInfo from '../../../src/components/UploadInfo.vue' import { defaultPlugins, shallowMount, defaultComponentMocks } from '@ownclouders/web-test-helpers' -import { ResourceListItem, UppyResource } from '@ownclouders/web-pkg' +import { ResourceListItem, OcUppyFile } from '@ownclouders/web-pkg' import { nextTick } from 'vue' import { HttpError } from '@ownclouders/web-client' @@ -142,13 +142,13 @@ describe('UploadInfo component', () => { path: '/', type: 'file', meta: { uploadId: '1' } - } as unknown as UppyResource, + } as unknown as OcUppyFile, '2': { name: 'file2', path: '/', type: 'file', meta: { uploadId: '2' } - } as unknown as UppyResource + } as unknown as OcUppyFile } await nextTick() @@ -169,19 +169,19 @@ describe('UploadInfo component', () => { path: '/', type: 'file', meta: { uploadId: '1' } - } as unknown as UppyResource, + } as unknown as OcUppyFile, '2': { name: 'file2', path: '/', type: 'file', meta: { uploadId: '2' } - } as unknown as UppyResource, + } as unknown as OcUppyFile, '3': { name: 'file3', path: '/', type: 'file', meta: { uploadId: '3' } - } as unknown as UppyResource + } as unknown as OcUppyFile }), (wrapper.vm.errors = { 1: new HttpError('', undefined), @@ -205,11 +205,10 @@ describe('UploadInfo component', () => { '1': { name: 'file', type: 'folder', - isFolder: true, targetRoute: { params: { driveAliasAndItem: 'some/drive/alias' } }, path: '', - meta: { uploadId: '1' } - } as unknown as UppyResource + meta: { uploadId: '1', isFolder: true } + } as unknown as OcUppyFile } await nextTick() diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c9d3a2eb230..d2ffb4a1070 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,23 +4,6 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -overrides: - '@uppy/companion-client': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-companion-client.tgz - '@uppy/core': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz - '@uppy/dashboard': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-dashboard.tgz - '@uppy/drop-target': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-drop-target.tgz - '@uppy/google-drive': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-google-drive.tgz - '@uppy/informer': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-informer.tgz - '@uppy/onedrive': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-onedrive.tgz - '@uppy/provider-views': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-provider-views.tgz - '@uppy/status-bar': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-status-bar.tgz - '@uppy/store-default': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-store-default.tgz - '@uppy/thumbnail-generator': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-thumbnail-generator.tgz - '@uppy/tus': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-tus.tgz - '@uppy/utils': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-utils.tgz - '@uppy/webdav': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-webdav.tgz - '@uppy/xhr-upload': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-xhr-upload.tgz - packageExtensionsChecksum: 3ef0ab2b0f9b90185dab73258f7cc8d5 patchedDependencies: @@ -705,8 +688,8 @@ importers: specifier: workspace:* version: link:../web-pkg '@uppy/core': - specifier: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz - version: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz + specifier: 4.3.1 + version: 4.3.1 '@vueuse/core': specifier: ^11.0.0 || ^12.0.0 version: 12.0.0(typescript@5.6.3) @@ -980,20 +963,20 @@ importers: specifier: ^3.1.0 version: 3.1.0 '@uppy/core': - specifier: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz - version: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz + specifier: 4.3.1 + version: 4.3.1 '@uppy/drop-target': - specifier: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-drop-target.tgz - version: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-drop-target.tgz(@uppy/core@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz) + specifier: 3.0.2 + version: 3.0.2(@uppy/core@4.3.1) '@uppy/tus': - specifier: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-tus.tgz - version: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-tus.tgz(@uppy/core@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz) + specifier: 4.1.5 + version: 4.1.5(@uppy/core@4.3.1) '@uppy/utils': - specifier: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-utils.tgz - version: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-utils.tgz + specifier: 6.0.6 + version: 6.0.6 '@uppy/xhr-upload': - specifier: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-xhr-upload.tgz - version: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-xhr-upload.tgz(@uppy/core@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz) + specifier: 4.2.3 + version: 4.2.3(@uppy/core@4.3.1) '@vue/shared': specifier: ^3.5.11 version: 3.5.13 @@ -1114,20 +1097,20 @@ importers: specifier: 8.42.0 version: 8.42.0(pinia@2.3.0(typescript@5.6.3)(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3)) '@uppy/core': - specifier: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz - version: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz + specifier: 4.3.1 + version: 4.3.1 '@uppy/drop-target': - specifier: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-drop-target.tgz - version: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-drop-target.tgz(@uppy/core@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz) + specifier: 3.0.2 + version: 3.0.2(@uppy/core@4.3.1) '@uppy/tus': - specifier: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-tus.tgz - version: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-tus.tgz(@uppy/core@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz) + specifier: 4.1.5 + version: 4.1.5(@uppy/core@4.3.1) '@uppy/utils': - specifier: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-utils.tgz - version: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-utils.tgz + specifier: 6.0.6 + version: 6.0.6 '@uppy/xhr-upload': - specifier: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-xhr-upload.tgz - version: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-xhr-upload.tgz(@uppy/core@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz) + specifier: 4.2.3 + version: 4.2.3(@uppy/core@4.3.1) '@vueuse/core': specifier: 12.0.0 version: 12.0.0(typescript@5.6.3) @@ -2616,8 +2599,8 @@ packages: '@toast-ui/editor@3.2.2': resolution: {integrity: sha512-ASX7LFjN2ZYQJrwmkUajPs7DRr9FsM1+RQ82CfTO0Y5ZXorBk1VZS4C2Dpxinx9kl55V4F8/A2h2QF4QMDtRbA==} - '@transloadit/prettier-bytes@0.0.9': - resolution: {integrity: sha512-pCvdmea/F3Tn4hAtHqNXmjcixSaroJJ+L3STXlYJdir1g1m2mRQpWbN8a4SvgQtaw2930Ckhdx8qXdXBFMKbAA==} + '@transloadit/prettier-bytes@0.3.5': + resolution: {integrity: sha512-xF4A3d/ZyX2LJWeQZREZQw+qFX4TGQ8bGVP97OLRt6sPO6T0TNHBFTuRHOJh7RNmYOBmQ9MHxpolD9bXihpuVA==} '@trysound/sax@0.2.0': resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} @@ -2696,6 +2679,9 @@ packages: '@types/parse5@5.0.3': resolution: {integrity: sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==} + '@types/retry@0.12.2': + resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} + '@types/semver@7.5.8': resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} @@ -2811,39 +2797,34 @@ packages: peerDependencies: vue: '>=2.7 || >=3' - '@uppy/companion-client@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-companion-client.tgz': - resolution: {tarball: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-companion-client.tgz} - version: 3.2.0 + '@uppy/companion-client@4.3.0': + resolution: {integrity: sha512-S8Fs7KgLE8CEf225S/j28yZTMqVaqvmesX5mrd/I1H0dHzIoruLYC/3q3QnihGbQRxyobUpnBmo67o24+mAc7g==} + peerDependencies: + '@uppy/core': ^4.3.1 - '@uppy/core@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz': - resolution: {tarball: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz} - version: 3.3.0 + '@uppy/core@4.3.1': + resolution: {integrity: sha512-vov6agqmZrbmkG6E5LpSGNOeVXP4u0pe3UXCqVBZvU+WPInA264d4+X7NUnD6cF/BHPfckbfKh+60Tm1A40VEg==} - '@uppy/drop-target@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-drop-target.tgz': - resolution: {tarball: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-drop-target.tgz} - version: 2.0.1 + '@uppy/drop-target@3.0.2': + resolution: {integrity: sha512-NXUsl7Ohf4iaYwyY5Goic0TPTl1V7qVZ0EQDrbNHRgFR6Lda54Gqh7sFoMeaP9sUutEOwXXvPSLE/VWa2mv1Mg==} peerDependencies: - '@uppy/core': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz + '@uppy/core': ^4.3.0 - '@uppy/store-default@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-store-default.tgz': - resolution: {tarball: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-store-default.tgz} - version: 3.0.3 + '@uppy/store-default@4.1.2': + resolution: {integrity: sha512-1Zi4S9rZiiEzDw/7TDNtwCWP8Y/6aBtWzKwP6EWH7NHBKX8yGFlQMRDwAXCKaxDxb46L0RNK8nWjOzHM+0Farg==} - '@uppy/tus@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-tus.tgz': - resolution: {tarball: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-tus.tgz} - version: 3.1.2 + '@uppy/tus@4.1.5': + resolution: {integrity: sha512-vVfFuDkBbCSFpB5M2oh0yDkY8aR5UXCsNa0v71CtyBKZfCiSHzJ/jL5AVMKr9gaEpYitIDhTKS+YItwZpV6Dng==} peerDependencies: - '@uppy/core': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz + '@uppy/core': ^4.3.0 - '@uppy/utils@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-utils.tgz': - resolution: {tarball: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-utils.tgz} - version: 5.4.0 + '@uppy/utils@6.0.6': + resolution: {integrity: sha512-7/4jrJTSEth7DKCOZiOEY3JWGTUlwV9Gnrtlp25yJvJ7HbOVQ0ToJUuDz9wCZJ3V2++zfj30JbvBynbOH40WxA==} - '@uppy/xhr-upload@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-xhr-upload.tgz': - resolution: {tarball: https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-xhr-upload.tgz} - version: 3.3.1 + '@uppy/xhr-upload@4.2.3': + resolution: {integrity: sha512-XoqrfNCSADvPXcKHeilyEVNOtoWCI6OFaJA2tRp0EL+L9iF4FRr++SvkgJb7xFv04TCTT1h5CDKxGLmnf0e4yg==} peerDependencies: - '@uppy/core': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz + '@uppy/core': ^4.3.0 '@vitejs/plugin-vue@5.2.0': resolution: {integrity: sha512-7n7KdUEtx/7Yl7I/WVAMZ1bEb0eVvXF3ummWTeLcs/9gvo9pJhuLdouSXGjdZ/MKD1acf1I272+X0RMua4/R3g==} @@ -5439,6 +5420,10 @@ packages: resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} engines: {node: '>= 0.4'} + is-network-error@1.1.0: + resolution: {integrity: sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==} + engines: {node: '>=16'} + is-number@3.0.0: resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} engines: {node: '>=0.10.0'} @@ -6250,9 +6235,9 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - nanoid@4.0.0: - resolution: {integrity: sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg==} - engines: {node: ^14 || ^16 || >=18} + nanoid@5.0.9: + resolution: {integrity: sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==} + engines: {node: ^18 || >=20} hasBin: true nanomatch@1.2.13: @@ -6596,6 +6581,10 @@ packages: resolution: {integrity: sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==} engines: {node: '>=6'} + p-retry@6.2.1: + resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} + engines: {node: '>=16.17'} + p-timeout@6.1.2: resolution: {integrity: sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==} engines: {node: '>=14.16'} @@ -7626,6 +7615,10 @@ packages: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -8464,8 +8457,9 @@ packages: tty-browserify@0.0.1: resolution: {integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==} - tus-js-client@3.0.0: - resolution: {integrity: sha512-PHWI/K8YrCzpc83MqkLhqm89EGG+pPrkBaJ/0NQH0xQoqxfs7HKqAqfXrjmcw2CHZeGYaqxI6oVcolXThzYOSA==} + tus-js-client@4.2.3: + resolution: {integrity: sha512-UkQUCeDWKh5AwArcasIJWcL5EP66XPypKQtsdPu82wNnTea8eAUHdpDx3DcfZgDERAiCII895zMYkXri4M1wzw==} + engines: {node: '>=18'} type-check@0.3.2: resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} @@ -10157,7 +10151,7 @@ snapshots: '@cucumber/ci-environment': 10.0.1 '@cucumber/cucumber-expressions': 17.1.0 '@cucumber/gherkin': 28.0.0 - '@cucumber/gherkin-streams': 5.0.1(@cucumber/gherkin@28.0.0)(@cucumber/message-streams@4.0.1(@cucumber/messages@27.0.2))(@cucumber/messages@24.1.0) + '@cucumber/gherkin-streams': 5.0.1(@cucumber/gherkin@28.0.0)(@cucumber/message-streams@4.0.1(@cucumber/messages@24.1.0))(@cucumber/messages@24.1.0) '@cucumber/gherkin-utils': 9.0.0 '@cucumber/html-formatter': 21.6.0(@cucumber/messages@24.1.0) '@cucumber/junit-xml-formatter': 0.6.0(@cucumber/messages@24.1.0) @@ -10201,7 +10195,7 @@ snapshots: '@cucumber/ci-environment': 9.1.0 '@cucumber/cucumber-expressions': 16.1.1 '@cucumber/gherkin': 26.0.3 - '@cucumber/gherkin-streams': 5.0.1(@cucumber/gherkin@26.0.3)(@cucumber/message-streams@4.0.1(@cucumber/messages@21.0.1))(@cucumber/messages@21.0.1) + '@cucumber/gherkin-streams': 5.0.1(@cucumber/gherkin@26.0.3)(@cucumber/message-streams@4.0.1(@cucumber/messages@27.0.2))(@cucumber/messages@21.0.1) '@cucumber/gherkin-utils': 8.0.2 '@cucumber/html-formatter': 20.2.1(@cucumber/messages@21.0.1) '@cucumber/message-streams': 4.0.1(@cucumber/messages@21.0.1) @@ -10239,7 +10233,7 @@ snapshots: yaml: 2.6.0 yup: 0.32.11 - '@cucumber/gherkin-streams@5.0.1(@cucumber/gherkin@26.0.3)(@cucumber/message-streams@4.0.1(@cucumber/messages@21.0.1))(@cucumber/messages@21.0.1)': + '@cucumber/gherkin-streams@5.0.1(@cucumber/gherkin@26.0.3)(@cucumber/message-streams@4.0.1(@cucumber/messages@27.0.2))(@cucumber/messages@21.0.1)': dependencies: '@cucumber/gherkin': 26.0.3 '@cucumber/message-streams': 4.0.1(@cucumber/messages@21.0.1) @@ -10247,10 +10241,10 @@ snapshots: commander: 9.1.0 source-map-support: 0.5.21 - '@cucumber/gherkin-streams@5.0.1(@cucumber/gherkin@28.0.0)(@cucumber/message-streams@4.0.1(@cucumber/messages@27.0.2))(@cucumber/messages@24.1.0)': + '@cucumber/gherkin-streams@5.0.1(@cucumber/gherkin@28.0.0)(@cucumber/message-streams@4.0.1(@cucumber/messages@24.1.0))(@cucumber/messages@24.1.0)': dependencies: '@cucumber/gherkin': 28.0.0 - '@cucumber/message-streams': 4.0.1(@cucumber/messages@21.0.1) + '@cucumber/message-streams': 4.0.1(@cucumber/messages@24.1.0) '@cucumber/messages': 24.1.0 commander: 9.1.0 source-map-support: 0.5.21 @@ -10894,7 +10888,7 @@ snapshots: prosemirror-transform: 1.8.0 prosemirror-view: 1.32.7 - '@transloadit/prettier-bytes@0.0.9': {} + '@transloadit/prettier-bytes@0.3.5': {} '@trysound/sax@0.2.0': {} @@ -10969,6 +10963,8 @@ snapshots: '@types/parse5@5.0.3': {} + '@types/retry@0.12.2': {} + '@types/semver@7.5.8': {} '@types/sizzle@2.3.8': {} @@ -11128,46 +11124,48 @@ snapshots: unhead: 1.8.4 vue: 3.5.13(typescript@5.6.3) - '@uppy/companion-client@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-companion-client.tgz': + '@uppy/companion-client@4.3.0(@uppy/core@4.3.1)': dependencies: - '@uppy/utils': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-utils.tgz + '@uppy/core': 4.3.1 + '@uppy/utils': 6.0.6 namespace-emitter: 2.0.1 + p-retry: 6.2.1 - '@uppy/core@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz': + '@uppy/core@4.3.1': dependencies: - '@transloadit/prettier-bytes': 0.0.9 - '@uppy/store-default': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-store-default.tgz - '@uppy/utils': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-utils.tgz + '@transloadit/prettier-bytes': 0.3.5 + '@uppy/store-default': 4.1.2 + '@uppy/utils': 6.0.6 lodash: 4.17.21 mime-match: 1.0.2 namespace-emitter: 2.0.1 - nanoid: 4.0.0 + nanoid: 5.0.9 preact: 10.7.1 - '@uppy/drop-target@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-drop-target.tgz(@uppy/core@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz)': + '@uppy/drop-target@3.0.2(@uppy/core@4.3.1)': dependencies: - '@uppy/core': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz - '@uppy/utils': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-utils.tgz + '@uppy/core': 4.3.1 + '@uppy/utils': 6.0.6 - '@uppy/store-default@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-store-default.tgz': {} + '@uppy/store-default@4.1.2': {} - '@uppy/tus@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-tus.tgz(@uppy/core@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz)': + '@uppy/tus@4.1.5(@uppy/core@4.3.1)': dependencies: - '@uppy/companion-client': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-companion-client.tgz - '@uppy/core': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz - '@uppy/utils': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-utils.tgz - tus-js-client: 3.0.0 + '@uppy/companion-client': 4.3.0(@uppy/core@4.3.1) + '@uppy/core': 4.3.1 + '@uppy/utils': 6.0.6 + tus-js-client: 4.2.3 - '@uppy/utils@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-utils.tgz': + '@uppy/utils@6.0.6': dependencies: lodash: 4.17.21 + preact: 10.7.1 - '@uppy/xhr-upload@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-xhr-upload.tgz(@uppy/core@https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz)': + '@uppy/xhr-upload@4.2.3(@uppy/core@4.3.1)': dependencies: - '@uppy/companion-client': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-companion-client.tgz - '@uppy/core': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-core.tgz - '@uppy/utils': https://github.com/owncloud/uppy/releases/download/v3.12.13-owncloud/uppy-utils.tgz - nanoid: 4.0.0 + '@uppy/companion-client': 4.3.0(@uppy/core@4.3.1) + '@uppy/core': 4.3.1 + '@uppy/utils': 6.0.6 '@vitejs/plugin-vue@5.2.0(vite@6.0.1(@types/node@22.9.0)(jiti@1.21.0)(sass@1.81.0)(terser@5.36.0)(yaml@2.6.0))(vue@3.5.13(typescript@5.6.3))': dependencies: @@ -14166,6 +14164,8 @@ snapshots: call-bind: 1.0.7 define-properties: 1.2.1 + is-network-error@1.1.0: {} + is-number@3.0.0: dependencies: kind-of: 3.2.2 @@ -14966,7 +14966,7 @@ snapshots: nanoid@3.3.7: {} - nanoid@4.0.0: {} + nanoid@5.0.9: {} nanomatch@1.2.13(supports-color@6.1.0): dependencies: @@ -15287,6 +15287,12 @@ snapshots: dependencies: retry: 0.12.0 + p-retry@6.2.1: + dependencies: + '@types/retry': 0.12.2 + is-network-error: 1.1.0 + retry: 0.13.1 + p-timeout@6.1.2: {} p-try@2.2.0: {} @@ -16447,6 +16453,8 @@ snapshots: retry@0.12.0: {} + retry@0.13.1: {} + reusify@1.0.4: {} rev-hash@3.0.0: {} @@ -17399,7 +17407,7 @@ snapshots: tty-browserify@0.0.1: {} - tus-js-client@3.0.0: + tus-js-client@4.2.3: dependencies: buffer-from: 1.1.2 combine-errors: 3.0.3