mirror of
https://github.com/filebrowser/filebrowser.git
synced 2026-07-17 16:36:49 +00:00
fix: double slash in TUS upload path when readEntries returns multiple batches (#5848)
This commit is contained in:
parent
ae72f93667
commit
432f3e60ff
5 changed files with 336 additions and 3 deletions
18
.github/workflows/ci.yaml
vendored
18
.github/workflows/ci.yaml
vendored
|
|
@ -27,6 +27,24 @@ jobs:
|
|||
pnpm install --frozen-lockfile
|
||||
pnpm run lint
|
||||
|
||||
test-frontend:
|
||||
name: Test Frontend
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
package_json_file: "frontend/package.json"
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: "24.x"
|
||||
cache: "pnpm"
|
||||
cache-dependency-path: "frontend/pnpm-lock.yaml"
|
||||
- working-directory: frontend
|
||||
run: |
|
||||
pnpm install --frozen-lockfile
|
||||
pnpm run test
|
||||
|
||||
lint-backend:
|
||||
name: Lint Backend
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@
|
|||
"typecheck": "vue-tsc -p ./tsconfig.app.json --noEmit",
|
||||
"lint": "eslint src/",
|
||||
"lint:fix": "eslint --fix src/",
|
||||
"format": "prettier --write ."
|
||||
"format": "prettier --write .",
|
||||
"test": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@chenfengyuan/vue-number-input": "^2.0.1",
|
||||
|
|
@ -70,6 +71,7 @@
|
|||
"typescript": "^5.9.3",
|
||||
"vite": "^8.0.0",
|
||||
"vite-plugin-compression2": "^2.3.1",
|
||||
"vitest": "^4.1.0",
|
||||
"vue-tsc": "^3.1.3"
|
||||
},
|
||||
"packageManager": "pnpm@10.32.1+sha512.a706938f0e89ac1456b6563eab4edf1d1faf3368d1191fc5c59790e96dc918e4456ab2e67d613de1043d2e8c81f87303e6b40d4ffeca9df15ef1ad567348f2be"
|
||||
|
|
|
|||
230
frontend/pnpm-lock.yaml
generated
230
frontend/pnpm-lock.yaml
generated
|
|
@ -162,6 +162,9 @@ importers:
|
|||
vite-plugin-compression2:
|
||||
specifier: ^2.3.1
|
||||
version: 2.5.1(rollup@4.57.1)
|
||||
vitest:
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.0(@types/node@24.12.0)(vite@8.0.0(@types/node@24.12.0)(esbuild@0.27.3)(terser@5.46.0)(yaml@2.8.2))
|
||||
vue-tsc:
|
||||
specifier: ^3.1.3
|
||||
version: 3.2.5(typescript@5.9.3)
|
||||
|
|
@ -1400,12 +1403,21 @@ packages:
|
|||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@standard-schema/spec@1.1.0':
|
||||
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
|
||||
|
||||
'@tsconfig/node24@24.0.4':
|
||||
resolution: {integrity: sha512-2A933l5P5oCbv6qSxHs7ckKwobs8BDAe9SJ/Xr2Hy+nDlwmLE1GhFh/g/vXGRZWgxBg9nX/5piDtHR9Dkw/XuA==}
|
||||
|
||||
'@tybys/wasm-util@0.10.1':
|
||||
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
|
||||
|
||||
'@types/chai@5.2.3':
|
||||
resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
|
||||
|
||||
'@types/deep-eql@4.0.2':
|
||||
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
|
||||
|
||||
'@types/esrecurse@4.3.1':
|
||||
resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==}
|
||||
|
||||
|
|
@ -1572,6 +1584,35 @@ packages:
|
|||
vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
vue: ^3.2.25
|
||||
|
||||
'@vitest/expect@4.1.0':
|
||||
resolution: {integrity: sha512-EIxG7k4wlWweuCLG9Y5InKFwpMEOyrMb6ZJ1ihYu02LVj/bzUwn2VMU+13PinsjRW75XnITeFrQBMH5+dLvCDA==}
|
||||
|
||||
'@vitest/mocker@4.1.0':
|
||||
resolution: {integrity: sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw==}
|
||||
peerDependencies:
|
||||
msw: ^2.4.9
|
||||
vite: ^6.0.0 || ^7.0.0 || ^8.0.0-0
|
||||
peerDependenciesMeta:
|
||||
msw:
|
||||
optional: true
|
||||
vite:
|
||||
optional: true
|
||||
|
||||
'@vitest/pretty-format@4.1.0':
|
||||
resolution: {integrity: sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A==}
|
||||
|
||||
'@vitest/runner@4.1.0':
|
||||
resolution: {integrity: sha512-Duvx2OzQ7d6OjchL+trw+aSrb9idh7pnNfxrklo14p3zmNL4qPCDeIJAK+eBKYjkIwG96Bc6vYuxhqDXQOWpoQ==}
|
||||
|
||||
'@vitest/snapshot@4.1.0':
|
||||
resolution: {integrity: sha512-0Vy9euT1kgsnj1CHttwi9i9o+4rRLEaPRSOJ5gyv579GJkNpgJK+B4HSv/rAWixx2wdAFci1X4CEPjiu2bXIMg==}
|
||||
|
||||
'@vitest/spy@4.1.0':
|
||||
resolution: {integrity: sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw==}
|
||||
|
||||
'@vitest/utils@4.1.0':
|
||||
resolution: {integrity: sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw==}
|
||||
|
||||
'@volar/language-core@2.4.28':
|
||||
resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==}
|
||||
|
||||
|
|
@ -1777,6 +1818,10 @@ packages:
|
|||
alien-signals@3.1.2:
|
||||
resolution: {integrity: sha512-d9dYqZTS90WLiU0I5c6DHj/HcKkF8ZyGN3G5x8wSbslulz70KOxaqCT0hQCo9KOyhVqzqGojvNdJXoTumZOtcw==}
|
||||
|
||||
assertion-error@2.0.1:
|
||||
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
ast-kit@2.2.0:
|
||||
resolution: {integrity: sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==}
|
||||
engines: {node: '>=20.19.0'}
|
||||
|
|
@ -1853,6 +1898,10 @@ packages:
|
|||
caniuse-lite@1.0.30001774:
|
||||
resolution: {integrity: sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA==}
|
||||
|
||||
chai@6.2.2:
|
||||
resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
chokidar@5.0.0:
|
||||
resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
|
||||
engines: {node: '>= 20.19.0'}
|
||||
|
|
@ -1946,6 +1995,9 @@ packages:
|
|||
epubjs@0.3.93:
|
||||
resolution: {integrity: sha512-c06pNSdBxcXv3dZSbXAVLE1/pmleRhOT6mXNZo6INKmvuKpYB65MwU/lO7830czCtjIiK9i+KR+3S+p0wtljrw==}
|
||||
|
||||
es-module-lexer@2.0.0:
|
||||
resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==}
|
||||
|
||||
es5-ext@0.10.64:
|
||||
resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
|
@ -2068,6 +2120,9 @@ packages:
|
|||
estree-walker@2.0.2:
|
||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||
|
||||
estree-walker@3.0.3:
|
||||
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
|
||||
|
||||
esutils@2.0.3:
|
||||
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
|
@ -2075,6 +2130,10 @@ packages:
|
|||
event-emitter@0.3.5:
|
||||
resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==}
|
||||
|
||||
expect-type@1.3.0:
|
||||
resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
exsolve@1.0.8:
|
||||
resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
|
||||
|
||||
|
|
@ -2487,6 +2546,9 @@ packages:
|
|||
nth-check@2.1.1:
|
||||
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
||||
|
||||
obug@2.1.1:
|
||||
resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==}
|
||||
|
||||
optionator@0.9.4:
|
||||
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
|
@ -2700,6 +2762,9 @@ packages:
|
|||
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
siginfo@2.0.0:
|
||||
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
|
||||
|
||||
signal-exit@3.0.7:
|
||||
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
||||
|
||||
|
|
@ -2718,6 +2783,12 @@ packages:
|
|||
resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
stackback@0.0.2:
|
||||
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
|
||||
|
||||
std-env@4.0.0:
|
||||
resolution: {integrity: sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==}
|
||||
|
||||
string_decoder@1.1.1:
|
||||
resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
|
||||
|
||||
|
|
@ -2747,10 +2818,21 @@ packages:
|
|||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
tinybench@2.9.0:
|
||||
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
|
||||
|
||||
tinyexec@1.0.4:
|
||||
resolution: {integrity: sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
tinyglobby@0.2.15:
|
||||
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
tinyrainbow@3.1.0:
|
||||
resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
to-regex-range@5.0.1:
|
||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||
engines: {node: '>=8.0'}
|
||||
|
|
@ -2909,6 +2991,41 @@ packages:
|
|||
yaml:
|
||||
optional: true
|
||||
|
||||
vitest@4.1.0:
|
||||
resolution: {integrity: sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw==}
|
||||
engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@edge-runtime/vm': '*'
|
||||
'@opentelemetry/api': ^1.9.0
|
||||
'@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0
|
||||
'@vitest/browser-playwright': 4.1.0
|
||||
'@vitest/browser-preview': 4.1.0
|
||||
'@vitest/browser-webdriverio': 4.1.0
|
||||
'@vitest/ui': 4.1.0
|
||||
happy-dom: '*'
|
||||
jsdom: '*'
|
||||
vite: ^6.0.0 || ^7.0.0 || ^8.0.0-0
|
||||
peerDependenciesMeta:
|
||||
'@edge-runtime/vm':
|
||||
optional: true
|
||||
'@opentelemetry/api':
|
||||
optional: true
|
||||
'@types/node':
|
||||
optional: true
|
||||
'@vitest/browser-playwright':
|
||||
optional: true
|
||||
'@vitest/browser-preview':
|
||||
optional: true
|
||||
'@vitest/browser-webdriverio':
|
||||
optional: true
|
||||
'@vitest/ui':
|
||||
optional: true
|
||||
happy-dom:
|
||||
optional: true
|
||||
jsdom:
|
||||
optional: true
|
||||
|
||||
vscode-uri@3.1.0:
|
||||
resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}
|
||||
|
||||
|
|
@ -2972,6 +3089,11 @@ packages:
|
|||
engines: {node: '>= 8'}
|
||||
hasBin: true
|
||||
|
||||
why-is-node-running@2.3.0:
|
||||
resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
|
||||
engines: {node: '>=8'}
|
||||
hasBin: true
|
||||
|
||||
word-wrap@1.2.5:
|
||||
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
|
@ -4135,6 +4257,8 @@ snapshots:
|
|||
'@rollup/rollup-win32-x64-msvc@4.57.1':
|
||||
optional: true
|
||||
|
||||
'@standard-schema/spec@1.1.0': {}
|
||||
|
||||
'@tsconfig/node24@24.0.4': {}
|
||||
|
||||
'@tybys/wasm-util@0.10.1':
|
||||
|
|
@ -4142,6 +4266,13 @@ snapshots:
|
|||
tslib: 2.8.1
|
||||
optional: true
|
||||
|
||||
'@types/chai@5.2.3':
|
||||
dependencies:
|
||||
'@types/deep-eql': 4.0.2
|
||||
assertion-error: 2.0.1
|
||||
|
||||
'@types/deep-eql@4.0.2': {}
|
||||
|
||||
'@types/esrecurse@4.3.1': {}
|
||||
|
||||
'@types/estree@1.0.8': {}
|
||||
|
|
@ -4384,6 +4515,47 @@ snapshots:
|
|||
vite: 8.0.0(@types/node@24.12.0)(esbuild@0.27.3)(terser@5.46.0)(yaml@2.8.2)
|
||||
vue: 3.5.30(typescript@5.9.3)
|
||||
|
||||
'@vitest/expect@4.1.0':
|
||||
dependencies:
|
||||
'@standard-schema/spec': 1.1.0
|
||||
'@types/chai': 5.2.3
|
||||
'@vitest/spy': 4.1.0
|
||||
'@vitest/utils': 4.1.0
|
||||
chai: 6.2.2
|
||||
tinyrainbow: 3.1.0
|
||||
|
||||
'@vitest/mocker@4.1.0(vite@8.0.0(@types/node@24.12.0)(esbuild@0.27.3)(terser@5.46.0)(yaml@2.8.2))':
|
||||
dependencies:
|
||||
'@vitest/spy': 4.1.0
|
||||
estree-walker: 3.0.3
|
||||
magic-string: 0.30.21
|
||||
optionalDependencies:
|
||||
vite: 8.0.0(@types/node@24.12.0)(esbuild@0.27.3)(terser@5.46.0)(yaml@2.8.2)
|
||||
|
||||
'@vitest/pretty-format@4.1.0':
|
||||
dependencies:
|
||||
tinyrainbow: 3.1.0
|
||||
|
||||
'@vitest/runner@4.1.0':
|
||||
dependencies:
|
||||
'@vitest/utils': 4.1.0
|
||||
pathe: 2.0.3
|
||||
|
||||
'@vitest/snapshot@4.1.0':
|
||||
dependencies:
|
||||
'@vitest/pretty-format': 4.1.0
|
||||
'@vitest/utils': 4.1.0
|
||||
magic-string: 0.30.21
|
||||
pathe: 2.0.3
|
||||
|
||||
'@vitest/spy@4.1.0': {}
|
||||
|
||||
'@vitest/utils@4.1.0':
|
||||
dependencies:
|
||||
'@vitest/pretty-format': 4.1.0
|
||||
convert-source-map: 2.0.0
|
||||
tinyrainbow: 3.1.0
|
||||
|
||||
'@volar/language-core@2.4.28':
|
||||
dependencies:
|
||||
'@volar/source-map': 2.4.28
|
||||
|
|
@ -4619,6 +4791,8 @@ snapshots:
|
|||
|
||||
alien-signals@3.1.2: {}
|
||||
|
||||
assertion-error@2.0.1: {}
|
||||
|
||||
ast-kit@2.2.0:
|
||||
dependencies:
|
||||
'@babel/parser': 7.29.0
|
||||
|
|
@ -4701,6 +4875,8 @@ snapshots:
|
|||
|
||||
caniuse-lite@1.0.30001774: {}
|
||||
|
||||
chai@6.2.2: {}
|
||||
|
||||
chokidar@5.0.0:
|
||||
dependencies:
|
||||
readdirp: 5.0.0
|
||||
|
|
@ -4783,6 +4959,8 @@ snapshots:
|
|||
marks-pane: 1.0.9
|
||||
path-webpack: 0.0.3
|
||||
|
||||
es-module-lexer@2.0.0: {}
|
||||
|
||||
es5-ext@0.10.64:
|
||||
dependencies:
|
||||
es6-iterator: 2.0.3
|
||||
|
|
@ -4977,6 +5155,10 @@ snapshots:
|
|||
|
||||
estree-walker@2.0.2: {}
|
||||
|
||||
estree-walker@3.0.3:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
|
||||
esutils@2.0.3: {}
|
||||
|
||||
event-emitter@0.3.5:
|
||||
|
|
@ -4984,6 +5166,8 @@ snapshots:
|
|||
d: 1.0.2
|
||||
es5-ext: 0.10.64
|
||||
|
||||
expect-type@1.3.0: {}
|
||||
|
||||
exsolve@1.0.8: {}
|
||||
|
||||
ext@1.7.0:
|
||||
|
|
@ -5338,6 +5522,8 @@ snapshots:
|
|||
dependencies:
|
||||
boolbase: 1.0.0
|
||||
|
||||
obug@2.1.1: {}
|
||||
|
||||
optionator@0.9.4:
|
||||
dependencies:
|
||||
deep-is: 0.1.4
|
||||
|
|
@ -5569,6 +5755,8 @@ snapshots:
|
|||
|
||||
shebang-regex@3.0.0: {}
|
||||
|
||||
siginfo@2.0.0: {}
|
||||
|
||||
signal-exit@3.0.7: {}
|
||||
|
||||
source-map-js@1.2.1: {}
|
||||
|
|
@ -5582,6 +5770,10 @@ snapshots:
|
|||
|
||||
speakingurl@14.0.1: {}
|
||||
|
||||
stackback@0.0.2: {}
|
||||
|
||||
std-env@4.0.0: {}
|
||||
|
||||
string_decoder@1.1.1:
|
||||
dependencies:
|
||||
safe-buffer: 5.1.2
|
||||
|
|
@ -5610,11 +5802,17 @@ snapshots:
|
|||
commander: 2.20.3
|
||||
source-map-support: 0.5.21
|
||||
|
||||
tinybench@2.9.0: {}
|
||||
|
||||
tinyexec@1.0.4: {}
|
||||
|
||||
tinyglobby@0.2.15:
|
||||
dependencies:
|
||||
fdir: 6.5.0(picomatch@4.0.3)
|
||||
picomatch: 4.0.3
|
||||
|
||||
tinyrainbow@3.1.0: {}
|
||||
|
||||
to-regex-range@5.0.1:
|
||||
dependencies:
|
||||
is-number: 7.0.0
|
||||
|
|
@ -5764,6 +5962,33 @@ snapshots:
|
|||
terser: 5.46.0
|
||||
yaml: 2.8.2
|
||||
|
||||
vitest@4.1.0(@types/node@24.12.0)(vite@8.0.0(@types/node@24.12.0)(esbuild@0.27.3)(terser@5.46.0)(yaml@2.8.2)):
|
||||
dependencies:
|
||||
'@vitest/expect': 4.1.0
|
||||
'@vitest/mocker': 4.1.0(vite@8.0.0(@types/node@24.12.0)(esbuild@0.27.3)(terser@5.46.0)(yaml@2.8.2))
|
||||
'@vitest/pretty-format': 4.1.0
|
||||
'@vitest/runner': 4.1.0
|
||||
'@vitest/snapshot': 4.1.0
|
||||
'@vitest/spy': 4.1.0
|
||||
'@vitest/utils': 4.1.0
|
||||
es-module-lexer: 2.0.0
|
||||
expect-type: 1.3.0
|
||||
magic-string: 0.30.21
|
||||
obug: 2.1.1
|
||||
pathe: 2.0.3
|
||||
picomatch: 4.0.3
|
||||
std-env: 4.0.0
|
||||
tinybench: 2.9.0
|
||||
tinyexec: 1.0.4
|
||||
tinyglobby: 0.2.15
|
||||
tinyrainbow: 3.1.0
|
||||
vite: 8.0.0(@types/node@24.12.0)(esbuild@0.27.3)(terser@5.46.0)(yaml@2.8.2)
|
||||
why-is-node-running: 2.3.0
|
||||
optionalDependencies:
|
||||
'@types/node': 24.12.0
|
||||
transitivePeerDependencies:
|
||||
- msw
|
||||
|
||||
vscode-uri@3.1.0: {}
|
||||
|
||||
vue-eslint-parser@10.4.0(eslint@10.0.3):
|
||||
|
|
@ -5842,6 +6067,11 @@ snapshots:
|
|||
dependencies:
|
||||
isexe: 2.0.0
|
||||
|
||||
why-is-node-running@2.3.0:
|
||||
dependencies:
|
||||
siginfo: 2.0.0
|
||||
stackback: 0.0.2
|
||||
|
||||
word-wrap@1.2.5: {}
|
||||
|
||||
xml-name-validator@4.0.0: {}
|
||||
|
|
|
|||
80
frontend/src/utils/__tests__/upload.test.ts
Normal file
80
frontend/src/utils/__tests__/upload.test.ts
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
import { describe, it, expect } from "vitest";
|
||||
|
||||
/**
|
||||
* Reproduces the path-building logic from scanFiles() in upload.ts (lines 118-138).
|
||||
*
|
||||
* readReaderContent() is called when traversing a dropped folder. The browser's
|
||||
* FileSystemDirectoryReader.readEntries() returns entries in batches — you must
|
||||
* call it repeatedly until it returns an empty array. Each recursive call in the
|
||||
* current code appends "/" to the directory, so the second batch and beyond get
|
||||
* double (or triple, etc.) slashes in the constructed fullPath.
|
||||
*/
|
||||
|
||||
type Entry = { name: string; isFile: boolean; isDirectory: boolean };
|
||||
|
||||
function simulateScanFiles(
|
||||
dirName: string,
|
||||
entryBatches: Entry[][]
|
||||
): string[] {
|
||||
const paths: string[] = [];
|
||||
let batchIndex = 0;
|
||||
|
||||
// Mirrors readEntry() for files — records fullPath as `${directory}${file.name}`
|
||||
function readEntry(entry: Entry, directory = ""): void {
|
||||
if (entry.isFile) {
|
||||
paths.push(`${directory}${entry.name}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Mirrors readReaderContent() from upload.ts lines 118-138
|
||||
function readReaderContent(directory: string): void {
|
||||
const entries = batchIndex < entryBatches.length ? entryBatches[batchIndex] : [];
|
||||
batchIndex++;
|
||||
|
||||
if (entries.length > 0) {
|
||||
const dirWithSlash = directory.endsWith("/")
|
||||
? directory
|
||||
: `${directory}/`;
|
||||
for (const entry of entries) {
|
||||
readEntry(entry, dirWithSlash);
|
||||
}
|
||||
readReaderContent(dirWithSlash);
|
||||
}
|
||||
}
|
||||
|
||||
// Initial call mirrors readEntry() for a directory — upload.ts line 111-114
|
||||
readReaderContent(dirName);
|
||||
return paths;
|
||||
}
|
||||
|
||||
describe("scanFiles path construction", () => {
|
||||
it("should not produce double slashes when readEntries returns multiple batches", () => {
|
||||
// Two batches: simulates a large directory where the browser splits
|
||||
// readEntries() results across multiple calls
|
||||
const paths = simulateScanFiles("TestFolder", [
|
||||
[
|
||||
{ name: "file1.xlsx", isFile: true, isDirectory: false },
|
||||
{ name: "file2.xlsx", isFile: true, isDirectory: false },
|
||||
],
|
||||
[
|
||||
{ name: "file3.xlsx", isFile: true, isDirectory: false },
|
||||
],
|
||||
]);
|
||||
|
||||
expect(paths).toHaveLength(3);
|
||||
|
||||
for (const p of paths) {
|
||||
expect(p, `path "${p}" contains double slash`).not.toContain("//");
|
||||
}
|
||||
});
|
||||
|
||||
it("single batch should work fine (no regression)", () => {
|
||||
const paths = simulateScanFiles("TestFolder", [
|
||||
[
|
||||
{ name: "file1.xlsx", isFile: true, isDirectory: false },
|
||||
],
|
||||
]);
|
||||
|
||||
expect(paths).toEqual(["TestFolder/file1.xlsx"]);
|
||||
});
|
||||
});
|
||||
|
|
@ -124,11 +124,14 @@ export function scanFiles(dt: DataTransfer): Promise<UploadList | FileList> {
|
|||
reader.readEntries((entries) => {
|
||||
reading--;
|
||||
if (entries.length > 0) {
|
||||
const dirWithSlash = directory.endsWith("/")
|
||||
? directory
|
||||
: `${directory}/`;
|
||||
for (const entry of entries) {
|
||||
readEntry(entry, `${directory}/`);
|
||||
readEntry(entry, dirWithSlash);
|
||||
}
|
||||
|
||||
readReaderContent(reader, `${directory}/`);
|
||||
readReaderContent(reader, dirWithSlash);
|
||||
}
|
||||
|
||||
if (reading === 0) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue