fix: preserve external output path spelling (#7) (thanks @jesse-merhi)
This commit is contained in:
parent
a6c7e86dc2
commit
d144817e7c
@ -4,6 +4,7 @@
|
||||
|
||||
### Fixes
|
||||
|
||||
- Add `writeExternalFileWithinRoot()` for libraries that require an output path while preserving caller-provided destination names. (#7; thanks @jesse-merhi)
|
||||
- Reject `fileStore()` and `fileStoreSync()` writes through symlinked parent directories so store commits cannot escape the configured root.
|
||||
- Harden Root fallback mutators, archive merges, private store reads/writes, durable queue ids, JSON fallback writes, sibling temp writes, temp filename sanitization, and trash moves against symlink-swap and path traversal edge cases.
|
||||
- Centralize safe path segment validation, directory identity guards, and guarded mutation wrappers so future filesystem helpers reuse the same race-resistant checks.
|
||||
|
||||
@ -65,8 +65,8 @@ export async function writeExternalFileWithinRoot<T = void>(
|
||||
options: ExternalFileWriteOptions<T>,
|
||||
): Promise<ExternalFileWriteResult<T>> {
|
||||
const targetRoot = await root(options.rootDir);
|
||||
const requestedTargetPath = options.path.trim();
|
||||
if (!requestedTargetPath) {
|
||||
const requestedTargetPath = options.path;
|
||||
if (requestedTargetPath.length === 0) {
|
||||
throw new FsSafeError("invalid-path", "target path is required");
|
||||
}
|
||||
const targetPath = toRootPathInput({
|
||||
|
||||
@ -42,6 +42,26 @@ describe("writeExternalFileWithinRoot", () => {
|
||||
await expect(fs.stat(tempPath)).rejects.toMatchObject({ code: "ENOENT" });
|
||||
});
|
||||
|
||||
it("preserves caller-provided destination filename spacing", async () => {
|
||||
const rootDir = await tempRoot("fs-safe-output-spaces-");
|
||||
const fileName = " report .txt ";
|
||||
|
||||
const result = await writeExternalFileWithinRoot({
|
||||
rootDir,
|
||||
path: fileName,
|
||||
write: async (candidate) => {
|
||||
await fs.writeFile(candidate, "spaced", "utf8");
|
||||
},
|
||||
});
|
||||
|
||||
const finalPath = path.join(rootDir, fileName);
|
||||
expect(result.path).toBe(path.join(await fs.realpath(rootDir), fileName));
|
||||
await expect(fs.readFile(finalPath, "utf8")).resolves.toBe("spaced");
|
||||
await expect(fs.stat(path.join(rootDir, fileName.trim()))).rejects.toMatchObject({
|
||||
code: "ENOENT",
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects empty target paths before invoking the external writer", async () => {
|
||||
const rootDir = await tempRoot("fs-safe-output-default-");
|
||||
let called = false;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user