Initial commit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
谢宇宁
2026-11-05 23:07:59 +07:00
co-authored by Claude Opus 5.5
commit f65d10e998
377 changed files with 31301 additions and 0 deletions
+45
View File
@@ -0,0 +1,45 @@
import {cp, copyFile, lstat, mkdir, readdir, realpath, symlink} from 'node:fs/promises';
import {dirname, join, relative, sep} from 'node:path';
export const under=(path,base)=>path===base||path.startsWith(base+sep);
/**
* Copy a release tree for npm or pnpm layouts.
* In-tree symlinks are rewritten as relative links inside `to` so the package is relocatable.
* Symlinks that escape `from` but stay under `root` are materialized; anything else is rejected.
*/
export async function copyReleaseTree(from,to,{root=from,filter=async()=>true}={}) {
from=await realpath(from);
root=await realpath(root);
async function walk(srcDir,destDir) {
await mkdir(destDir,{recursive:true});
for(const entry of await readdir(srcDir,{withFileTypes:true})) {
const srcPath=join(srcDir,entry.name);
if(!await filter(srcPath))continue;
const destPath=join(destDir,entry.name);
if(entry.isSymbolicLink()){
const target=await realpath(srcPath).catch(()=>null);
if(!target||(!under(target,from)&&!under(target,root)))
throw new Error(`Release source contains a symbolic link: ${srcPath}`);
if(under(target,from)){
const mapped=join(to,relative(from,target));
await symlink(relative(dirname(destPath),mapped),destPath);
continue;
}
await cp(target,destPath,{recursive:true,dereference:true,filter});
continue;
}
if(entry.isDirectory()){
await walk(srcPath,destPath);
continue;
}
if(entry.isFile()){
await copyFile(srcPath,destPath);
continue;
}
// Rare non-file entries (sockets/devices) should never ship.
throw new Error(`Release source contains an unsupported file type: ${srcPath}`);
}
}
await walk(from,to);
}