@superblocksteam/vite-plugin-file-sync 2.0.37-next.5 → 2.0.37-next.51

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.
Files changed (112) hide show
  1. package/dist/ai-service/agent/apis-system-prompt.d.ts +1 -1
  2. package/dist/ai-service/agent/apis-system-prompt.d.ts.map +1 -1
  3. package/dist/ai-service/agent/apis-system-prompt.js +214 -2
  4. package/dist/ai-service/agent/apis-system-prompt.js.map +1 -1
  5. package/dist/ai-service/agent/apis.d.ts.map +1 -1
  6. package/dist/ai-service/agent/apis.js +71 -6
  7. package/dist/ai-service/agent/apis.js.map +1 -1
  8. package/dist/ai-service/agent/tool-message-utils.js +14 -14
  9. package/dist/ai-service/agent/tool-message-utils.js.map +1 -1
  10. package/dist/ai-service/agent/tools/build-finalize.d.ts.map +1 -1
  11. package/dist/ai-service/agent/tools/build-finalize.js +2 -6
  12. package/dist/ai-service/agent/tools/build-finalize.js.map +1 -1
  13. package/dist/ai-service/agent/tools/build-list-available-components.d.ts.map +1 -1
  14. package/dist/ai-service/agent/tools/build-list-available-components.js +5 -31
  15. package/dist/ai-service/agent/tools/build-list-available-components.js.map +1 -1
  16. package/dist/ai-service/agent/utils.d.ts +6 -0
  17. package/dist/ai-service/agent/utils.d.ts.map +1 -1
  18. package/dist/ai-service/agent/utils.js +46 -4
  19. package/dist/ai-service/agent/utils.js.map +1 -1
  20. package/dist/ai-service/clark-provider/clark-language-model.d.ts.map +1 -1
  21. package/dist/ai-service/clark-provider/clark-language-model.js +23 -10
  22. package/dist/ai-service/clark-provider/clark-language-model.js.map +1 -1
  23. package/dist/ai-service/const.d.ts +0 -12
  24. package/dist/ai-service/const.d.ts.map +1 -1
  25. package/dist/ai-service/const.js +0 -5
  26. package/dist/ai-service/const.js.map +1 -1
  27. package/dist/ai-service/context/app-context.d.ts +5 -0
  28. package/dist/ai-service/context/app-context.d.ts.map +1 -1
  29. package/dist/ai-service/context/app-context.js +18 -1
  30. package/dist/ai-service/context/app-context.js.map +1 -1
  31. package/dist/ai-service/index.d.ts +3 -1
  32. package/dist/ai-service/index.d.ts.map +1 -1
  33. package/dist/ai-service/index.js +25 -2
  34. package/dist/ai-service/index.js.map +1 -1
  35. package/dist/ai-service/integrations/metadata/database.d.ts.map +1 -1
  36. package/dist/ai-service/integrations/metadata/database.js +34 -5
  37. package/dist/ai-service/integrations/metadata/database.js.map +1 -1
  38. package/dist/ai-service/prompt-builder-service/static-fragments/library-components/ButtonPropsDocs.js +1 -1
  39. package/dist/ai-service/prompt-builder-service/static-fragments/library-components/CheckboxPropsDocs.js +1 -1
  40. package/dist/ai-service/prompt-builder-service/static-fragments/library-components/ColumnPropsDocs.js +1 -1
  41. package/dist/ai-service/prompt-builder-service/static-fragments/library-components/ContainerPropsDocs.js +1 -1
  42. package/dist/ai-service/prompt-builder-service/static-fragments/library-components/DatePickerPropsDocs.js +1 -1
  43. package/dist/ai-service/prompt-builder-service/static-fragments/library-components/DropdownPropsDocs.js +1 -1
  44. package/dist/ai-service/prompt-builder-service/static-fragments/library-components/IconPropsDocs.js +1 -1
  45. package/dist/ai-service/prompt-builder-service/static-fragments/library-components/ImagePropsDocs.js +1 -1
  46. package/dist/ai-service/prompt-builder-service/static-fragments/library-components/InputPropsDocs.js +1 -1
  47. package/dist/ai-service/prompt-builder-service/static-fragments/library-components/ModalPropsDocs.js +1 -1
  48. package/dist/ai-service/prompt-builder-service/static-fragments/library-components/PagePropsDocs.js +1 -1
  49. package/dist/ai-service/prompt-builder-service/static-fragments/library-components/SectionPropsDocs.js +1 -1
  50. package/dist/ai-service/prompt-builder-service/static-fragments/library-components/SlideoutPropsDocs.js +1 -1
  51. package/dist/ai-service/prompt-builder-service/static-fragments/library-components/SwitchPropsDocs.js +1 -1
  52. package/dist/ai-service/prompt-builder-service/static-fragments/library-components/TablePropsDocs.js +1 -1
  53. package/dist/ai-service/prompt-builder-service/static-fragments/library-components/TextPropsDocs.js +1 -1
  54. package/dist/ai-service/prompt-builder-service/static-fragments/library-typedefs/Dim.js +1 -1
  55. package/dist/ai-service/prompt-builder-service/static-fragments/library-typedefs/EventFlow.js +1 -1
  56. package/dist/ai-service/prompt-builder-service/static-fragments/library-typedefs/TextStyleWithVariant.js +1 -1
  57. package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/full-examples.js +1 -1
  58. package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-api.js +1 -1
  59. package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-components-rules.js +1 -1
  60. package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-custom-components.js +1 -1
  61. package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-data-filtering.js +1 -1
  62. package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-event-flow.js +1 -1
  63. package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-forms.js +1 -1
  64. package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-layouts.js +1 -1
  65. package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-page.js +1 -1
  66. package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-rbac.js +1 -1
  67. package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-routes.js +1 -1
  68. package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-state.js +1 -1
  69. package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-theming-chakra-new.js +1 -1
  70. package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/system-base.js +1 -1
  71. package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/system-incremental.js +1 -1
  72. package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/system-specific-edit.js +1 -1
  73. package/dist/ai-service/state-machine/clark-fsm.d.ts +3 -1
  74. package/dist/ai-service/state-machine/clark-fsm.d.ts.map +1 -1
  75. package/dist/ai-service/state-machine/clark-fsm.js.map +1 -1
  76. package/dist/ai-service/state-machine/handlers/agent-planning.d.ts.map +1 -1
  77. package/dist/ai-service/state-machine/handlers/agent-planning.js +2 -1
  78. package/dist/ai-service/state-machine/handlers/agent-planning.js.map +1 -1
  79. package/dist/ai-service/state-machine/handlers/llm-generating.d.ts.map +1 -1
  80. package/dist/ai-service/state-machine/handlers/llm-generating.js +33 -5
  81. package/dist/ai-service/state-machine/handlers/llm-generating.js.map +1 -1
  82. package/dist/ai-service/state-machine/handlers/simple-prompt-builder.d.ts.map +1 -1
  83. package/dist/ai-service/state-machine/handlers/simple-prompt-builder.js +180 -80
  84. package/dist/ai-service/state-machine/handlers/simple-prompt-builder.js.map +1 -1
  85. package/dist/ai-service/state-machine/helpers/cache-breakpoint.d.ts +29 -0
  86. package/dist/ai-service/state-machine/helpers/cache-breakpoint.d.ts.map +1 -0
  87. package/dist/ai-service/state-machine/helpers/cache-breakpoint.js +58 -0
  88. package/dist/ai-service/state-machine/helpers/cache-breakpoint.js.map +1 -0
  89. package/dist/file-sync-vite-plugin.d.ts.map +1 -1
  90. package/dist/file-sync-vite-plugin.js +24 -68
  91. package/dist/file-sync-vite-plugin.js.map +1 -1
  92. package/dist/file-system-manager.d.ts +7 -2
  93. package/dist/file-system-manager.d.ts.map +1 -1
  94. package/dist/file-system-manager.js +139 -151
  95. package/dist/file-system-manager.js.map +1 -1
  96. package/dist/socket-manager.d.ts +2 -1
  97. package/dist/socket-manager.d.ts.map +1 -1
  98. package/dist/socket-manager.js +3 -4
  99. package/dist/socket-manager.js.map +1 -1
  100. package/dist/source-tracker.d.ts +1 -9
  101. package/dist/source-tracker.d.ts.map +1 -1
  102. package/dist/source-tracker.js +0 -16
  103. package/dist/source-tracker.js.map +1 -1
  104. package/package.json +7 -7
  105. package/dist/custom-components.d.ts +0 -6
  106. package/dist/custom-components.d.ts.map +0 -1
  107. package/dist/custom-components.js +0 -51
  108. package/dist/custom-components.js.map +0 -1
  109. package/dist/parsing/theme.d.ts +0 -3
  110. package/dist/parsing/theme.d.ts.map +0 -1
  111. package/dist/parsing/theme.js +0 -87
  112. package/dist/parsing/theme.js.map +0 -1
@@ -10,7 +10,6 @@ import { isEqual } from "lodash-es";
10
10
  import yaml from "yaml";
11
11
  import { generateJSXAttribute } from "./codegen.js";
12
12
  import { ComponentsManager } from "./components-manager.js";
13
- import { addLegacyCustomComponentVariables, modifyLegacyCustomComponentElements, modifyLegacyCustomComponentImports, } from "./custom-components.js";
14
13
  import { applyErrorHandling, } from "./errors/error-handler.js";
15
14
  import { getApiFilePath, getPageFolder, isPageFilePath, PAGES_DIRECTORY, ROUTES_FILE, SCOPE_FILE, } from "./file-system-helpers.js";
16
15
  import { generate } from "./generate.js";
@@ -20,7 +19,7 @@ import { getSbElementId } from "./parsing/ids.js";
20
19
  import { makeJSXAttribute } from "./parsing/jsx.js";
21
20
  import { getRootNodes } from "./parsing/page.js";
22
21
  import { getScope } from "./parsing/scope.js";
23
- import { getLegacyComponentsFolder, isCustomBuildEnabled, } from "./plugin-options.js";
22
+ import { getLegacyComponentsFolder } from "./plugin-options.js";
24
23
  import { RenameManager } from "./rename-manager.js";
25
24
  import { getFullImportPath } from "./resolver.js";
26
25
  import { SourceTracker } from "./source-tracker.js";
@@ -53,7 +52,6 @@ const SUPPORTED_FILETYPES = [
53
52
  extension: ".json",
54
53
  },
55
54
  ];
56
- const APP_THEME_FILE_NAME = "appTheme.ts";
57
55
  export class FileSystemManager extends TracedEventEmitter {
58
56
  rootDir;
59
57
  tsFiles = {};
@@ -100,7 +98,6 @@ export class FileSystemManager extends TracedEventEmitter {
100
98
  handleAddEntity: { operation: "adding an entity" },
101
99
  handleUpdateEntity: { operation: "updating an entity" },
102
100
  handleDeleteEntity: { operation: "deleting an entity" },
103
- handleUpdateTheme: { operation: "updating the theme" },
104
101
  handleRenameElement: { operation: "renaming an element" },
105
102
  });
106
103
  const methods = [
@@ -118,7 +115,6 @@ export class FileSystemManager extends TracedEventEmitter {
118
115
  "handleAddEntity",
119
116
  "handleUpdateEntity",
120
117
  "handleDeleteEntity",
121
- "handleUpdateTheme",
122
118
  "handleRenameElement",
123
119
  ];
124
120
  addTracingToMethods(this, methods, tracer);
@@ -146,8 +142,6 @@ export class FileSystemManager extends TracedEventEmitter {
146
142
  const tsxFiles = fileNames.filter((f) => f.endsWith(".tsx") && !f.includes(`${getLegacyComponentsFolder()}/`));
147
143
  const yamlFiles = fileNames.filter((f) => f.endsWith(".yaml"));
148
144
  const scopeFiles = fileNames.filter((f) => f.endsWith(SCOPE_FILE));
149
- // For the moment, the theme file is `appTheme.ts`. This may change in the future.
150
- const appThemeFile = path.join(rootPath, APP_THEME_FILE_NAME);
151
145
  logger.info(`scanning ${tsxFiles.length} code files`);
152
146
  logger.info(`scanning ${yamlFiles.length} api files`);
153
147
  logger.info(`scanning app theme file`);
@@ -175,13 +169,6 @@ export class FileSystemManager extends TracedEventEmitter {
175
169
  };
176
170
  }),
177
171
  ].flat();
178
- if (appThemeFile) {
179
- allFiles.push({
180
- type: "ts",
181
- path: appThemeFile,
182
- content: readFile(appThemeFile),
183
- });
184
- }
185
172
  const contents = await Promise.allSettled(allFiles.map((f) => f.content));
186
173
  contents.forEach((result, i) => {
187
174
  if (result.status === "rejected") {
@@ -271,13 +258,9 @@ export class FileSystemManager extends TracedEventEmitter {
271
258
  }
272
259
  const componentsManager = ComponentsManager.getInstance();
273
260
  const processedTransactions = this.getProcessedTransactionsWithNonce();
274
- const customImports = new Set();
275
261
  traverse(clonedAst.ast, {
276
262
  Program: {
277
263
  exit(nodePath) {
278
- if (isCustomBuildEnabled()) {
279
- addLegacyCustomComponentVariables(nodePath, customImports);
280
- }
281
264
  // we want to inject the component name into the file so we can use it for hot reloading purposes
282
265
  const name = componentsManager.getComponentName(filePath);
283
266
  if (name) {
@@ -287,19 +270,6 @@ export class FileSystemManager extends TracedEventEmitter {
287
270
  }
288
271
  },
289
272
  },
290
- ImportDeclaration(path) {
291
- if (isCustomBuildEnabled()) {
292
- // when we see a custom component, we want to track the import and modify it to point
293
- // to the built source
294
- modifyLegacyCustomComponentImports(path, customImports);
295
- }
296
- },
297
- JSXElement(path) {
298
- if (isCustomBuildEnabled()) {
299
- // based on the imports we see, we want to modify the JSXElement that uses the custom component
300
- modifyLegacyCustomComponentElements(path, customImports);
301
- }
302
- },
303
273
  ReturnStatement(path) {
304
274
  const argument = path.get("argument");
305
275
  if (!argument.isJSXElement()) {
@@ -969,19 +939,6 @@ export const ${name} = ${name}Scope.entities;
969
939
  }
970
940
  });
971
941
  };
972
- handleUpdateTheme = async (payload) => {
973
- const { theme } = payload;
974
- if (!this.rootDir) {
975
- throw new Error("Root directory not set");
976
- }
977
- const filePath = path.join(this.rootDir, APP_THEME_FILE_NAME);
978
- this.sourceTracker?.updateTheme({
979
- themeFilePath: filePath,
980
- theme,
981
- });
982
- const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
983
- await this.writeChanges(changes);
984
- };
985
942
  handleAddComponentNameToScope = async (payload) => {
986
943
  const { scopeName, componentName } = payload;
987
944
  this.sourceTracker?.addScopeComponent({
@@ -1041,133 +998,164 @@ export const ${name} = ${name}Scope.entities;
1041
998
  if (!this.rootDir) {
1042
999
  throw new Error("Root directory not set");
1043
1000
  }
1044
- const newPageFolder = getPageFolder(this.rootDir, newName);
1045
- const oldPageFolder = getPageFolder(this.rootDir, oldName);
1046
- const newIndexFilePath = path.join(newPageFolder, "index.tsx");
1047
- const oldIndexFilePath = path.join(oldPageFolder, "index.tsx");
1048
- const doesFileExist = await fs.stat(newIndexFilePath).catch(() => false);
1049
- if (doesFileExist) {
1050
- throw new Error(`Page ${newName} already exists`);
1001
+ try {
1002
+ await this.performRenamePageTransaction(oldName, newName);
1003
+ this.emit("renamePage", newName);
1051
1004
  }
1052
- this.watcher?.unwatch(newPageFolder);
1053
- this.watcher?.unwatch(oldPageFolder);
1054
- let oldScope;
1055
- let newScope;
1056
- const oldScopeFilePath = path.join(oldPageFolder, SCOPE_FILE);
1057
- const newScopeFilePath = path.join(newPageFolder, SCOPE_FILE);
1058
- const existingRoute = Object.keys(this.routes).find((route) => this.routes[route]?.file ===
1059
- this.getRelativeRoutePath(oldIndexFilePath));
1005
+ catch (error) {
1006
+ getLogger().error("Error renaming page", getErrorMeta(error));
1007
+ throw error;
1008
+ }
1009
+ };
1010
+ /**
1011
+ * As much as possible, we want to perform the rename page transaction as an operation we can roll back if it fails.
1012
+ */
1013
+ async performRenamePageTransaction(oldName, newName) {
1014
+ let snapshot;
1015
+ let changes;
1060
1016
  try {
1017
+ if (!this.rootDir) {
1018
+ throw new Error("Root directory not set");
1019
+ }
1020
+ const newPageFolder = getPageFolder(this.rootDir, newName);
1021
+ const oldPageFolder = getPageFolder(this.rootDir, oldName);
1022
+ const newIndexFilePath = path.join(newPageFolder, "index.tsx");
1023
+ const oldIndexFilePath = path.join(oldPageFolder, "index.tsx");
1024
+ const oldScopeFilePath = path.join(oldPageFolder, SCOPE_FILE);
1025
+ const newScopeFilePath = path.join(newPageFolder, SCOPE_FILE);
1026
+ // Early validations
1027
+ const doesFileExist = await fs.stat(newIndexFilePath).catch(() => false);
1028
+ if (doesFileExist) {
1029
+ throw new Error(`Page ${newName} already exists`);
1030
+ }
1031
+ const existingRoute = Object.keys(this.routes).find((route) => this.routes[route]?.file ===
1032
+ this.getRelativeRoutePath(oldIndexFilePath));
1061
1033
  if (!existingRoute) {
1062
1034
  throw new Error(`Route for ${oldName} not found`);
1063
1035
  }
1064
- oldScope = this.sourceTracker?.getScopeDefinitionForPage(oldName);
1036
+ const oldScope = this.sourceTracker?.getScopeDefinitionForPage(oldName);
1065
1037
  if (!oldScope) {
1066
1038
  throw new Error(`Scope definition not found for old page, ${oldName}`);
1067
1039
  }
1068
- // we copy because its a safer operation than a rename, so it lets us
1069
- // recover from errors
1070
- await fs.cp(oldPageFolder, newPageFolder, { recursive: true });
1071
- const newIndexFile = await readFile(newIndexFilePath);
1072
- if (!newIndexFile) {
1073
- throw new Error(`New index file ${newIndexFilePath} not found`);
1074
- }
1075
- const newScopeFile = await readFile(newScopeFilePath);
1076
- if (!newScopeFile) {
1077
- throw new Error(`New scope file ${newScopeFilePath} not found`);
1078
- }
1079
- delete this.tsFiles[oldIndexFilePath];
1080
- delete this.tsFiles[oldScopeFilePath];
1081
- // you have to write the scope first, otherwise the page parsing breaks
1082
- await this.handleNonVisualChangeByDeletingIds(newScopeFilePath, newScopeFile);
1083
- await this.handleNonVisualChangeByDeletingIds(newIndexFilePath, newIndexFile);
1084
- // move all ts file sources first
1085
- Object.entries(this.tsFiles).forEach(([key, value]) => {
1086
- if (key.startsWith(oldPageFolder)) {
1087
- this.tsFiles[key.replace(oldPageFolder, newPageFolder)] = value;
1088
- }
1089
- });
1090
- // once we are tracking scope internally, we can perform all of the refactoring/renaming
1091
- // in the actual code files
1092
- this.sourceTracker?.renamePage({
1093
- oldName,
1094
- newName,
1095
- scopeFilePath: newScopeFilePath,
1096
- pageFilePath: newIndexFilePath,
1097
- });
1098
- newScope = this.sourceTracker?.getScopeDefinitionForPage(newName);
1099
- if (!newScope) {
1100
- throw new Error(`Scope definition not found for new page, ${newName}`);
1101
- }
1102
- // since we have a scope here, we can move APIs now
1103
- Object.entries(this.apiFiles).forEach(([key, value]) => {
1104
- if (key.startsWith(oldPageFolder)) {
1105
- this.apiFiles[key.replace(oldPageFolder, newPageFolder)] = {
1106
- ...value,
1107
- apiPb: {
1108
- ...value.apiPb,
1109
- trigger: {
1110
- ...value.apiPb.trigger,
1111
- pageName: newName,
1112
- pageId: newScope.id,
1113
- },
1114
- },
1115
- scopeId: newScope.id,
1116
- pageName: newName,
1117
- };
1118
- delete this.apiFiles[key];
1119
- }
1120
- });
1040
+ snapshot = {
1041
+ tsFiles: { ...this.tsFiles },
1042
+ apiFiles: { ...this.apiFiles },
1043
+ routes: { ...this.routes },
1044
+ };
1045
+ changes = {
1046
+ newPageFolder,
1047
+ oldPageFolder,
1048
+ newIndexFilePath,
1049
+ oldIndexFilePath,
1050
+ newScopeFilePath,
1051
+ oldScopeFilePath,
1052
+ oldScope,
1053
+ existingRoute,
1054
+ };
1055
+ await this.commitRenamePageChanges(oldName, newName, changes);
1121
1056
  }
1122
1057
  catch (error) {
1123
- // reverse setting the files to the new paths
1124
- Object.entries(this.tsFiles).forEach(([key, value]) => {
1125
- if (key.startsWith(newPageFolder)) {
1126
- this.tsFiles[key.replace(newPageFolder, oldPageFolder)] = value;
1127
- }
1128
- });
1129
- Object.entries(this.apiFiles).forEach(([key, value]) => {
1130
- if (key.startsWith(newPageFolder)) {
1131
- this.apiFiles[key.replace(newPageFolder, oldPageFolder)] = {
1132
- ...value,
1133
- apiPb: {
1134
- ...value.apiPb,
1135
- trigger: {
1136
- ...value.apiPb.trigger,
1137
- pageName: oldName,
1138
- pageId: oldScope.id,
1139
- },
1058
+ if (snapshot && changes) {
1059
+ await this.rollbackRenamePageChanges(snapshot, changes);
1060
+ }
1061
+ throw error;
1062
+ }
1063
+ }
1064
+ async commitRenamePageChanges(oldName, newName, changes) {
1065
+ const { newPageFolder, oldPageFolder, newIndexFilePath, oldIndexFilePath, newScopeFilePath, oldScopeFilePath, existingRoute, } = changes;
1066
+ // we don't want to trigger fs events during the operation
1067
+ this.watcher?.unwatch(newPageFolder);
1068
+ this.watcher?.unwatch(oldPageFolder);
1069
+ await fs.cp(oldPageFolder, newPageFolder, { recursive: true });
1070
+ const newIndexFile = await readFile(newIndexFilePath);
1071
+ if (!newIndexFile) {
1072
+ throw new Error(`New index file ${newIndexFilePath} not found`);
1073
+ }
1074
+ const newScopeFile = await readFile(newScopeFilePath);
1075
+ if (!newScopeFile) {
1076
+ throw new Error(`New scope file ${newScopeFilePath} not found`);
1077
+ }
1078
+ delete this.tsFiles[oldIndexFilePath];
1079
+ delete this.tsFiles[oldScopeFilePath];
1080
+ // lets setup all the ast stuff for the new files
1081
+ await this.handleNonVisualChangeByDeletingIds(newScopeFilePath, newScopeFile);
1082
+ await this.handleNonVisualChangeByDeletingIds(newIndexFilePath, newIndexFile);
1083
+ Object.entries(this.tsFiles).forEach(([key, value]) => {
1084
+ if (key.startsWith(oldPageFolder)) {
1085
+ this.tsFiles[key.replace(oldPageFolder, newPageFolder)] = value;
1086
+ delete this.tsFiles[key];
1087
+ }
1088
+ });
1089
+ // perform the page rename in source tracker now that we have the ast stuff setup
1090
+ this.sourceTracker?.renamePage({
1091
+ oldName,
1092
+ newName,
1093
+ scopeFilePath: newScopeFilePath,
1094
+ pageFilePath: newIndexFilePath,
1095
+ });
1096
+ const newScope = this.sourceTracker?.getScopeDefinitionForPage(newName);
1097
+ if (!newScope) {
1098
+ throw new Error(`Scope definition not found for new page, ${newName}`);
1099
+ }
1100
+ // our apis need the new scope id info, otherwise ui loses track
1101
+ Object.entries(this.apiFiles).forEach(([key, value]) => {
1102
+ if (key.startsWith(oldPageFolder)) {
1103
+ this.apiFiles[key.replace(oldPageFolder, newPageFolder)] = {
1104
+ ...value,
1105
+ apiPb: {
1106
+ ...value.apiPb,
1107
+ trigger: {
1108
+ ...value.apiPb.trigger,
1109
+ pageName: newName,
1110
+ pageId: newScope.id,
1140
1111
  },
1141
- scopeId: oldScope.id,
1142
- pageName: oldName,
1143
- };
1144
- delete this.apiFiles[key];
1145
- }
1146
- });
1112
+ },
1113
+ scopeId: newScope.id,
1114
+ pageName: newName,
1115
+ };
1116
+ delete this.apiFiles[key];
1117
+ }
1118
+ });
1119
+ await this.removeRoute(oldIndexFilePath);
1120
+ await this.addRoute(existingRoute, newIndexFilePath);
1121
+ await this.sourceTracker?.removeFile(oldIndexFilePath);
1122
+ await this.sourceTracker?.removeFile(oldScopeFilePath);
1123
+ // write all changes
1124
+ const sourceChanges = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
1125
+ await this.writeChanges(sourceChanges);
1126
+ this.watcher?.add(newPageFolder);
1127
+ // should be safe to delete the old page folder now
1128
+ await fs.rm(oldPageFolder, { recursive: true });
1129
+ }
1130
+ async rollbackRenamePageChanges(snapshot, changes) {
1131
+ const { newPageFolder, oldPageFolder, oldScopeFilePath, oldIndexFilePath } = changes;
1132
+ try {
1133
+ this.tsFiles = snapshot.tsFiles;
1134
+ this.apiFiles = snapshot.apiFiles;
1135
+ this.routes = snapshot.routes;
1136
+ // clean up the folders that were created
1147
1137
  await fs.rm(newPageFolder, { recursive: true }).catch((error) => {
1148
- getLogger().warn(`Failed to delete new page folder ${newPageFolder}. Error: ${error}`);
1138
+ getLogger().warn(`Failed to delete new page folder ${newPageFolder} during rollback. Error: ${error}`);
1149
1139
  });
1150
- const oldScopeFile = await readFile(oldScopeFilePath);
1140
+ const oldScopeFile = await readFile(oldScopeFilePath).catch(() => null);
1151
1141
  if (oldScopeFile) {
1152
1142
  await this.handleNonVisualChangeByDeletingIds(oldScopeFilePath, oldScopeFile);
1153
1143
  }
1154
- const oldIndexFile = await readFile(oldIndexFilePath);
1144
+ const oldIndexFile = await readFile(oldIndexFilePath).catch(() => null);
1155
1145
  if (oldIndexFile) {
1156
1146
  await this.handleNonVisualChangeByDeletingIds(oldIndexFilePath, oldIndexFile);
1157
1147
  }
1158
- getLogger().error("Error renaming page", getErrorMeta(error));
1159
- throw error;
1148
+ // ensure we have the the correct routes on disk
1149
+ if (this.rootDir) {
1150
+ await this.writeFile(path.join(this.rootDir, ROUTES_FILE), JSON.stringify(snapshot.routes, null, 2));
1151
+ }
1152
+ // resume watching the original folder
1153
+ this.watcher?.add(oldPageFolder);
1160
1154
  }
1161
- await this.removeRoute(oldIndexFilePath);
1162
- await this.addRoute(existingRoute, newIndexFilePath);
1163
- await this.sourceTracker?.removeFile(oldIndexFilePath);
1164
- await this.sourceTracker?.removeFile(oldScopeFilePath);
1165
- const changes = (await this.sourceTracker?.getAndFlushChanges()) ?? [];
1166
- await this.writeChanges(changes);
1167
- this.watcher?.add(newPageFolder);
1168
- await fs.rm(oldPageFolder, { recursive: true });
1169
- this.emit("renamePage", newName);
1170
- };
1155
+ catch (rollbackError) {
1156
+ getLogger().error("Error during transaction rollback", getErrorMeta(rollbackError));
1157
+ }
1158
+ }
1171
1159
  getRelativeRoutePath(filePath) {
1172
1160
  if (!this.rootDir) {
1173
1161
  throw new Error("Root directory not set");