@@ -20,7 +20,7 @@ export async function createFile(
2020 * Sanitizes a hash to be safe for use as a filename.
2121 * esbuild's hashes are base64-encoded and may contain `/` and `+` characters.
2222 */
23- function sanitizeHashForFilename ( hash : string ) : string {
23+ export function sanitizeHashForFilename ( hash : string ) : string {
2424 return hash . replace ( / \/ / g, "_" ) . replace ( / \+ / g, "-" ) ;
2525}
2626
@@ -57,14 +57,32 @@ export async function createFileWithStore(
5757 // Check if content already exists in store by hash
5858 if ( fsSync . existsSync ( storePath ) ) {
5959 // Create hardlink from build path to store path
60- await fsModule . link ( storePath , filePath ) ;
60+ // Fall back to copy if hardlink fails (e.g., on Windows or cross-device)
61+ try {
62+ await fsModule . link ( storePath , filePath ) ;
63+ } catch ( linkError ) {
64+ try {
65+ await fsModule . copyFile ( storePath , filePath ) ;
66+ } catch ( copyError ) {
67+ throw linkError ; // Rethrow original error if copy also fails
68+ }
69+ }
6170 return filePath ;
6271 }
6372
6473 // Write to store first (using hash as filename)
6574 await fsModule . writeFile ( storePath , contents ) ;
6675 // Create hardlink in build directory (with original filename)
67- await fsModule . link ( storePath , filePath ) ;
76+ // Fall back to copy if hardlink fails (e.g., on Windows or cross-device)
77+ try {
78+ await fsModule . link ( storePath , filePath ) ;
79+ } catch ( linkError ) {
80+ try {
81+ await fsModule . copyFile ( storePath , filePath ) ;
82+ } catch ( copyError ) {
83+ throw linkError ; // Rethrow original error if copy also fails
84+ }
85+ }
6886
6987 return filePath ;
7088}
0 commit comments