@openfairygui/backend 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,15 +1,21 @@
1
1
  import type { Document } from '@openfairygui/core';
2
2
  import { type FileSystem, type ProjectBranchDirectory, type ProjectSourceFile, ProjectWriter } from '@openfairygui/core/project-io';
3
3
  import type { BackendFileSystem } from '../runtime.js';
4
+ import { assertProjectPathContained } from '../path-policy.js';
4
5
 
5
6
  function createWriterFileSystem(
6
7
  fileSystem: BackendFileSystem,
8
+ projectRoot: string,
7
9
  writtenPaths: string[],
8
10
  failedPaths: string[],
9
11
  ): FileSystem {
12
+ const contained = async <T>(targetPath: string, operation: () => Promise<T>): Promise<T> => {
13
+ await assertProjectPathContained(fileSystem, projectRoot, targetPath);
14
+ return operation();
15
+ };
10
16
  async function trackWrite<T>(targetPath: string, write: () => Promise<T>): Promise<T> {
11
17
  try {
12
- const result = await write();
18
+ const result = await contained(targetPath, write);
13
19
  writtenPaths.push(targetPath);
14
20
  return result;
15
21
  } catch (error) {
@@ -19,8 +25,8 @@ function createWriterFileSystem(
19
25
  }
20
26
 
21
27
  return {
22
- readFile: (path) => fileSystem.readFile(path),
23
- readFileRaw: (path) => fileSystem.readFileRaw(path),
28
+ readFile: (path) => contained(path, () => fileSystem.readFile(path)),
29
+ readFileRaw: (path) => contained(path, () => fileSystem.readFileRaw(path)),
24
30
  writeFile: (path, content) =>
25
31
  trackWrite(path, async () => {
26
32
  await fileSystem.mkdir(fileSystem.dirname(path), { recursive: true });
@@ -31,9 +37,10 @@ function createWriterFileSystem(
31
37
  await fileSystem.mkdir(fileSystem.dirname(path), { recursive: true });
32
38
  await fileSystem.writeFileRaw(path, data);
33
39
  }),
34
- mkdir: (path) => fileSystem.mkdir(path, { recursive: true }),
35
- readdir: (path) => fileSystem.readdir(path),
40
+ mkdir: (path) => contained(path, () => fileSystem.mkdir(path, { recursive: true })),
41
+ readdir: (path) => contained(path, () => fileSystem.readdir(path)),
36
42
  async exists(path): Promise<boolean> {
43
+ await assertProjectPathContained(fileSystem, projectRoot, path);
37
44
  try {
38
45
  await fileSystem.stat(path);
39
46
  return true;
@@ -58,12 +65,23 @@ export async function writeSessionProject(input: {
58
65
  writtenPaths: string[];
59
66
  failedPaths: string[];
60
67
  }): Promise<void> {
61
- const writer = new ProjectWriter(
62
- createWriterFileSystem(input.fileSystem, input.writtenPaths, input.failedPaths),
63
- );
64
- await writer.write(input.document, input.fairyPath, {
65
- staleSourceFiles: input.staleSourceFiles,
66
- staleResourceFolders: input.staleResourceFolders,
67
- staleBranchDirectories: input.staleBranchDirectories,
68
- });
68
+ const projectRoot = input.fileSystem.dirname(input.fairyPath);
69
+ const write = async (fileSystem: BackendFileSystem): Promise<void> => {
70
+ const writer = new ProjectWriter(
71
+ createWriterFileSystem(fileSystem, projectRoot, input.writtenPaths, input.failedPaths),
72
+ );
73
+ await writer.write(input.document, input.fairyPath, {
74
+ staleSourceFiles: input.staleSourceFiles,
75
+ staleResourceFolders: input.staleResourceFolders,
76
+ staleBranchDirectories: input.staleBranchDirectories,
77
+ });
78
+ };
79
+
80
+ if (!input.fileSystem.runProjectWriteTransaction) return write(input.fileSystem);
81
+ try {
82
+ await input.fileSystem.runProjectWriteTransaction(projectRoot, write);
83
+ } catch (error) {
84
+ input.writtenPaths.length = 0;
85
+ throw error;
86
+ }
69
87
  }