Skip to content

Commit 60409c5

Browse files
authored
fix: handle absolute path destinations in dev correctly (#166)
1 parent 337f976 commit 60409c5

File tree

6 files changed

+37
-5
lines changed

6 files changed

+37
-5
lines changed

.changeset/funny-results-win.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'vite-plugin-static-copy': patch
3+
---
4+
5+
fix absolute destination paths in copy targets incorrectly returning contents in dev

src/options.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ export type Target = {
3636
*/
3737
src: string | string[]
3838
/**
39-
* destination
39+
* destination path
40+
*
41+
* If a relative path is passed, it will be resolved from `build.outDir`.
4042
*/
4143
dest: string
4244
/**

src/serve.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
import { debounce } from 'throttle-debounce'
1111
import chokidar from 'chokidar'
1212
import pc from 'picocolors'
13+
import path from 'node:path'
1314

1415
type FileMapValue = {
1516
src: string
@@ -30,14 +31,15 @@ export const servePlugin = ({
3031
const fileMap: FileMap = new Map()
3132

3233
const collectFileMap = async () => {
34+
const absoluteBuildOutDir = path.resolve(config.root, config.build.outDir)
3335
try {
3436
const copyTargets = await collectCopyTargets(
3537
config.root,
3638
targets,
3739
structured,
3840
silent
3941
)
40-
updateFileMapFromTargets(copyTargets, fileMap)
42+
updateFileMapFromTargets(copyTargets, fileMap, absoluteBuildOutDir)
4143
} catch (e) {
4244
if (!silent) {
4345
config.logger.error(formatConsole(pc.red((e as Error).toString())))

src/utils.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -279,12 +279,22 @@ export const copyAll = async (
279279

280280
export const updateFileMapFromTargets = (
281281
targets: SimpleTarget[],
282-
fileMap: FileMap
282+
fileMap: FileMap,
283+
absoluteBuildOutDir: string
283284
) => {
284285
fileMap.clear()
285286
for (const target of [...targets].reverse()) {
286-
let dest = target.dest.replace(/\\/g, '/')
287-
if (!dest.startsWith('/')) {
287+
let dest = path.isAbsolute(target.dest)
288+
? path.relative(absoluteBuildOutDir, target.dest)
289+
: target.dest
290+
dest = dest.replace(/\\/g, '/')
291+
if (path.isAbsolute(dest) || dest.startsWith('../')) {
292+
// outside buildOutDir
293+
continue
294+
}
295+
if (dest.startsWith('./')) {
296+
dest = dest.slice(1)
297+
} else if (!dest.startsWith('/')) {
288298
dest = `/${dest}`
289299
}
290300

test/fixtures/vite.config.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
import path from 'node:path'
2+
import { fileURLToPath } from 'node:url'
13
import { defineConfig } from 'vite'
24
import { viteStaticCopy } from 'vite-plugin-static-copy'
35

6+
const _dirname = path.dirname(fileURLToPath(import.meta.url))
7+
48
const wait = (delay: number) =>
59
new Promise(resolve => {
610
setTimeout(resolve, delay)
@@ -136,6 +140,10 @@ export default defineConfig({
136140
return `${filename}.foo`
137141
}
138142
},
143+
{
144+
src: 'foo.txt',
145+
dest: path.resolve(_dirname, 'dist/fixture13')
146+
},
139147
{ src: 'eexist/*', dest: 'eexist' },
140148
{ src: 'eexist/*', dest: 'Eexist' }
141149
]

test/testcases.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ export const testcases: Record<string, Testcase[]> = {
136136
dest: '/fixture12/foo.foo',
137137
contentType: ''
138138
},
139+
{
140+
name: 'absolute path dest',
141+
src: './foo.txt',
142+
dest: '/fixture13/foo.txt'
143+
},
139144
{
140145
name: 'parallel copy to same dir (1)',
141146
src: './eexist/a/1.txt',

0 commit comments

Comments
 (0)