History

Add workspace file browser and preview panel (#3087)

Julius Marminge committed 4 months agov0.0.28-nightly.20260615.565

Commit de8bdc11 parent 477795662 files · +2850 −9551Browse files

Showing the changes to apps/server/src/workspace/Layers/WorkspaceFileSystem.test.ts (1 of 62 files). Show all

Unified · Split

apps/server/src/workspace/Layers/WorkspaceFileSystem.test.ts+58−0
@@ -54,6 +54,64 @@ const writeTextFile = Effect.fn("writeTextFile")(function* ( · 53 unmodified lines
5454 });
5555
5656 it.layer(TestLayer)("WorkspaceFileSystemLive", (it) => {
57+ describe("readFile", () => {
58+ it.effect("reads UTF-8 files relative to the workspace root", () =>
59+ Effect.gen(function* () {
60+ const workspaceFileSystem = yield* WorkspaceFileSystem;
61+ const cwd = yield* makeTempDir;
62+ yield* writeTextFile(cwd, "src/index.ts", "export const answer = 42;\n");
63+
64+ const result = yield* workspaceFileSystem.readFile({
65+ cwd,
66+ relativePath: "src/index.ts",
67+ });
68+
69+ expect(result).toEqual({
70+ relativePath: "src/index.ts",
71+ contents: "export const answer = 42;\n",
72+ byteLength: 26,
73+ truncated: false,
74+ });
75+ }),
76+ );
77+
78+ it.effect("rejects reads outside the workspace root", () =>
79+ Effect.gen(function* () {
80+ const workspaceFileSystem = yield* WorkspaceFileSystem;
81+ const cwd = yield* makeTempDir;
82+
83+ const error = yield* workspaceFileSystem
84+ .readFile({ cwd, relativePath: "../escape.md" })
85+ .pipe(Effect.flip);
86+
87+ expect(error.message).toContain(
88+ "Workspace file path must be relative to the project root: ../escape.md",
89+ );
90+ }),
91+ );
92+
93+ it.effect("rejects symlinks that resolve outside the workspace root", () =>
94+ Effect.gen(function* () {
95+ const workspaceFileSystem = yield* WorkspaceFileSystem;
96+ const fileSystem = yield* FileSystem.FileSystem;
97+ const path = yield* Path.Path;
98+ const cwd = yield* makeTempDir;
99+ const outsideDir = yield* makeTempDir;
100+ yield* writeTextFile(outsideDir, "secret.txt", "outside\n");
101+ yield* fileSystem.symlink(
102+ path.join(outsideDir, "secret.txt"),
103+ path.join(cwd, "linked-secret.txt"),
104+ );
105+
106+ const error = yield* workspaceFileSystem
107+ .readFile({ cwd, relativePath: "linked-secret.txt" })
108+ .pipe(Effect.flip);
109+
110+ expect(error.message).toContain("resolves outside the project root");
111+ }),
112+ );
113+ });
114+
57115 describe("writeFile", () => {
58116 it.effect("writes files relative to the workspace root", () =>
59117 Effect.gen(function* () {