farmon 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +163 -0
- package/dist/bin/farmon.js +12 -0
- package/dist/bin/farmon.js.map +1 -0
- package/dist/execute/agents/index.js +19 -0
- package/dist/execute/agents/index.js.map +1 -0
- package/dist/execute/agents/instruction-classifier-agent.js +16 -0
- package/dist/execute/agents/instruction-classifier-agent.js.map +1 -0
- package/dist/execute/agents/mutation-agent.js +272 -0
- package/dist/execute/agents/mutation-agent.js.map +1 -0
- package/dist/execute/agents/query-agent.js +118 -0
- package/dist/execute/agents/query-agent.js.map +1 -0
- package/dist/execute/helpers/analyzers.js +8 -0
- package/dist/execute/helpers/analyzers.js.map +1 -0
- package/dist/execute/helpers/ensurers.js +1053 -0
- package/dist/execute/helpers/ensurers.js.map +1 -0
- package/dist/execute/helpers/finders.js +1454 -0
- package/dist/execute/helpers/finders.js.map +1 -0
- package/dist/execute/helpers/general.js +3736 -0
- package/dist/execute/helpers/general.js.map +1 -0
- package/dist/execute/helpers/import-helpers.js +183 -0
- package/dist/execute/helpers/import-helpers.js.map +1 -0
- package/dist/execute/helpers/parsers.js +840 -0
- package/dist/execute/helpers/parsers.js.map +1 -0
- package/dist/execute/helpers/prompt-maker.js +1163 -0
- package/dist/execute/helpers/prompt-maker.js.map +1 -0
- package/dist/execute/helpers/validators.js +40 -0
- package/dist/execute/helpers/validators.js.map +1 -0
- package/dist/execute/history/history-manager.js +1030 -0
- package/dist/execute/history/history-manager.js.map +1 -0
- package/dist/execute/history/rollback-handlers.js +2524 -0
- package/dist/execute/history/rollback-handlers.js.map +1 -0
- package/dist/execute/index.js +44 -0
- package/dist/execute/index.js.map +1 -0
- package/dist/execute/llm/call.js +103 -0
- package/dist/execute/llm/call.js.map +1 -0
- package/dist/execute/tasks/ast.js +3819 -0
- package/dist/execute/tasks/ast.js.map +1 -0
- package/dist/execute/tasks/generators.js +96 -0
- package/dist/execute/tasks/generators.js.map +1 -0
- package/dist/execute/tasks/index.js +7 -0
- package/dist/execute/tasks/index.js.map +1 -0
- package/dist/execute/tasks/mutations.js +8139 -0
- package/dist/execute/tasks/mutations.js.map +1 -0
- package/dist/execute/tasks/query.js +248 -0
- package/dist/execute/tasks/query.js.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/index.js +15 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/ollama.js +40 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/openai-compatible.js +52 -0
- package/dist/providers/openai-compatible.js.map +1 -0
- package/dist/runtime/inject.js +250 -0
- package/dist/runtime/inject.js.map +1 -0
- package/dist/schemas/agent/action.schema.js +935 -0
- package/dist/schemas/agent/action.schema.js.map +1 -0
- package/dist/schemas/agent/index.js +4 -0
- package/dist/schemas/agent/index.js.map +1 -0
- package/dist/schemas/agent/llm.schema.js +16 -0
- package/dist/schemas/agent/llm.schema.js.map +1 -0
- package/dist/schemas/agent/planner.schema.js +17 -0
- package/dist/schemas/agent/planner.schema.js.map +1 -0
- package/dist/schemas/index.js +7 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/project/context.schema.js +2 -0
- package/dist/schemas/project/context.schema.js.map +1 -0
- package/dist/schemas/project/index.js +2 -0
- package/dist/schemas/project/index.js.map +1 -0
- package/dist/schemas/runtime/index.js +4 -0
- package/dist/schemas/runtime/index.js.map +1 -0
- package/dist/schemas/runtime/injector.schema.js +11 -0
- package/dist/schemas/runtime/injector.schema.js.map +1 -0
- package/dist/schemas/runtime/runtime.schema.js +73 -0
- package/dist/schemas/runtime/runtime.schema.js.map +1 -0
- package/dist/schemas/runtime/sse.schema.js +15 -0
- package/dist/schemas/runtime/sse.schema.js.map +1 -0
- package/dist/schemas/system/index.js +2 -0
- package/dist/schemas/system/index.js.map +1 -0
- package/dist/schemas/system/logger.schema.js +56 -0
- package/dist/schemas/system/logger.schema.js.map +1 -0
- package/dist/schemas/task/index.js +9 -0
- package/dist/schemas/task/index.js.map +1 -0
- package/dist/server/app-context.js +254 -0
- package/dist/server/app-context.js.map +1 -0
- package/dist/server/config.js +22 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/error.js +22 -0
- package/dist/server/error.js.map +1 -0
- package/dist/server/event-bus.js +60 -0
- package/dist/server/event-bus.js.map +1 -0
- package/dist/server/logger.js +57 -0
- package/dist/server/logger.js.map +1 -0
- package/dist/server/run.js +265 -0
- package/dist/server/run.js.map +1 -0
- package/dist/server/sse.js +143 -0
- package/dist/server/sse.js.map +1 -0
- package/dist/ui/assets/index-C4ydQSAw.css +2 -0
- package/dist/ui/assets/index-Dzo7S5xs.js +85 -0
- package/dist/ui/favicon.svg +1 -0
- package/dist/ui/icons.svg +24 -0
- package/dist/ui/index.html +14 -0
- package/dist/workers/prettier.js +11 -0
- package/dist/workers/prettier.js.map +1 -0
- package/package.json +114 -0
|
@@ -0,0 +1,2524 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { ERROR_CODES, } from "../../schemas/index.js";
|
|
4
|
+
/*
|
|
5
|
+
|
|
6
|
+
Never use planner methods directly in rollback handlers,
|
|
7
|
+
as they may have side effects that can interfere with rollback process.
|
|
8
|
+
Instead, implement rollback logic using direct file system operations
|
|
9
|
+
to ensure reliable and consistent rollbacks.
|
|
10
|
+
|
|
11
|
+
*/
|
|
12
|
+
import mutations from "../../execute/tasks/mutations.js";
|
|
13
|
+
import { LoomaError } from "../../server/error.js";
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* const serializer = operationSerializers[taskName];
|
|
17
|
+
|
|
18
|
+
const operationPayload = serializer(taskResult);
|
|
19
|
+
*
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
const operationSerializers = {
|
|
23
|
+
ensureLibrary: ({ packageJsonPath, beforePackageJson, afterPackageJson, }) => ({
|
|
24
|
+
target: {
|
|
25
|
+
packageJsonPath,
|
|
26
|
+
},
|
|
27
|
+
before: {
|
|
28
|
+
packageJson: beforePackageJson,
|
|
29
|
+
},
|
|
30
|
+
after: {
|
|
31
|
+
packageJson: afterPackageJson,
|
|
32
|
+
},
|
|
33
|
+
}),
|
|
34
|
+
removeLibrary: ({ packageJsonPath, beforePackageJson, afterPackageJson, }) => ({
|
|
35
|
+
target: {
|
|
36
|
+
packageJsonPath,
|
|
37
|
+
},
|
|
38
|
+
before: {
|
|
39
|
+
packageJson: beforePackageJson,
|
|
40
|
+
},
|
|
41
|
+
after: {
|
|
42
|
+
packageJson: afterPackageJson,
|
|
43
|
+
},
|
|
44
|
+
}),
|
|
45
|
+
// ensureImport: ({
|
|
46
|
+
// payload: { code, source, importName, importType, alias },
|
|
47
|
+
// result: { updatedCode },
|
|
48
|
+
// }) => ({
|
|
49
|
+
// target: {
|
|
50
|
+
// code,
|
|
51
|
+
// },
|
|
52
|
+
// before: {
|
|
53
|
+
// code: code,
|
|
54
|
+
// },
|
|
55
|
+
// after: {
|
|
56
|
+
// code: updatedCode,
|
|
57
|
+
// },
|
|
58
|
+
// }),
|
|
59
|
+
removeImport: ({ payload: { code, source, importName, importType }, result: { updatedCode }, }) => ({
|
|
60
|
+
target: {
|
|
61
|
+
code: code,
|
|
62
|
+
source,
|
|
63
|
+
importName,
|
|
64
|
+
importType,
|
|
65
|
+
},
|
|
66
|
+
before: {
|
|
67
|
+
code: code,
|
|
68
|
+
},
|
|
69
|
+
after: {
|
|
70
|
+
code: updatedCode,
|
|
71
|
+
},
|
|
72
|
+
}),
|
|
73
|
+
// optimizeImports: ({ payload, result }) => ({
|
|
74
|
+
// target: {
|
|
75
|
+
// componentPath,
|
|
76
|
+
// },
|
|
77
|
+
// before: {
|
|
78
|
+
// code: beforeCode,
|
|
79
|
+
// },
|
|
80
|
+
// after: {
|
|
81
|
+
// code: afterCode,
|
|
82
|
+
// },
|
|
83
|
+
// }),
|
|
84
|
+
insertVariable: ({ payload: { code, variableName, value, scope, functionName }, result: { updatedCode }, }) => ({
|
|
85
|
+
target: {
|
|
86
|
+
code,
|
|
87
|
+
variableName,
|
|
88
|
+
value,
|
|
89
|
+
scope,
|
|
90
|
+
functionName,
|
|
91
|
+
},
|
|
92
|
+
before: {
|
|
93
|
+
code: code,
|
|
94
|
+
},
|
|
95
|
+
after: {
|
|
96
|
+
code: updatedCode,
|
|
97
|
+
},
|
|
98
|
+
}),
|
|
99
|
+
updateVariable: ({ payload: { code, variableName, newValue, line }, result: { updatedCode }, }) => ({
|
|
100
|
+
target: {
|
|
101
|
+
code,
|
|
102
|
+
variableName,
|
|
103
|
+
newValue,
|
|
104
|
+
},
|
|
105
|
+
before: {
|
|
106
|
+
code: code,
|
|
107
|
+
},
|
|
108
|
+
after: {
|
|
109
|
+
code: updatedCode,
|
|
110
|
+
},
|
|
111
|
+
}),
|
|
112
|
+
deleteVariable: ({ payload: { code, variableName, line }, result: { updatedCode }, }) => ({
|
|
113
|
+
target: {
|
|
114
|
+
code,
|
|
115
|
+
variableName,
|
|
116
|
+
},
|
|
117
|
+
before: {
|
|
118
|
+
code,
|
|
119
|
+
},
|
|
120
|
+
after: {
|
|
121
|
+
deleted: true,
|
|
122
|
+
},
|
|
123
|
+
}),
|
|
124
|
+
// createFunction: ({ payload, result }) => ({
|
|
125
|
+
// target: {
|
|
126
|
+
// componentPath,
|
|
127
|
+
// functionName,
|
|
128
|
+
// },
|
|
129
|
+
// before: {
|
|
130
|
+
// code: beforeCode,
|
|
131
|
+
// },
|
|
132
|
+
// after: {
|
|
133
|
+
// code: afterCode,
|
|
134
|
+
// },
|
|
135
|
+
// }),
|
|
136
|
+
// updateFunction: ({ payload, result }) => ({
|
|
137
|
+
// target: {
|
|
138
|
+
// componentPath,
|
|
139
|
+
// functionName,
|
|
140
|
+
// },
|
|
141
|
+
// before: {
|
|
142
|
+
// functionCode: beforeFunctionCode,
|
|
143
|
+
// },
|
|
144
|
+
// after: {
|
|
145
|
+
// functionCode: afterFunctionCode,
|
|
146
|
+
// },
|
|
147
|
+
// }),
|
|
148
|
+
// deleteFunction: ({ payload, result }) => ({
|
|
149
|
+
// target: {
|
|
150
|
+
// componentPath,
|
|
151
|
+
// functionName,
|
|
152
|
+
// },
|
|
153
|
+
// before: {
|
|
154
|
+
// functionCode: beforeFunctionCode,
|
|
155
|
+
// },
|
|
156
|
+
// after: {
|
|
157
|
+
// deleted: true,
|
|
158
|
+
// },
|
|
159
|
+
// }),
|
|
160
|
+
// insertCode: ({ payload, result }) => ({
|
|
161
|
+
// target: {
|
|
162
|
+
// filePath,
|
|
163
|
+
// },
|
|
164
|
+
// before: {
|
|
165
|
+
// code: beforeCode,
|
|
166
|
+
// },
|
|
167
|
+
// after: {
|
|
168
|
+
// code: beforeCode,
|
|
169
|
+
// },
|
|
170
|
+
// }),
|
|
171
|
+
// insertJSX: ({ payload, result }) => ({
|
|
172
|
+
// target: {
|
|
173
|
+
// componentPath,
|
|
174
|
+
// targetElement,
|
|
175
|
+
// },
|
|
176
|
+
// before: {
|
|
177
|
+
// jsx: beforeJsx,
|
|
178
|
+
// },
|
|
179
|
+
// after: {
|
|
180
|
+
// jsx: afterJsx,
|
|
181
|
+
// },
|
|
182
|
+
// }),
|
|
183
|
+
// replaceJSX: ({ payload, result }) => ({
|
|
184
|
+
// target: {
|
|
185
|
+
// componentPath,
|
|
186
|
+
// targetElement,
|
|
187
|
+
// },
|
|
188
|
+
// before: {
|
|
189
|
+
// jsx: beforeJsx,
|
|
190
|
+
// },
|
|
191
|
+
// after: {
|
|
192
|
+
// jsx: afterJsx,
|
|
193
|
+
// },
|
|
194
|
+
// }),
|
|
195
|
+
// removeJSX: ({ payload, result }) => ({
|
|
196
|
+
// target: {
|
|
197
|
+
// componentPath,
|
|
198
|
+
// targetElement,
|
|
199
|
+
// },
|
|
200
|
+
// before: {
|
|
201
|
+
// jsx: beforeJsx,
|
|
202
|
+
// },
|
|
203
|
+
// after: {
|
|
204
|
+
// removed: true,
|
|
205
|
+
// },
|
|
206
|
+
// }),
|
|
207
|
+
// wrapJSX: ({ payload, result }) => ({
|
|
208
|
+
// target: {
|
|
209
|
+
// componentPath,
|
|
210
|
+
// targetElement,
|
|
211
|
+
// },
|
|
212
|
+
// before: {
|
|
213
|
+
// jsx: beforeJsx,
|
|
214
|
+
// },
|
|
215
|
+
// after: {
|
|
216
|
+
// jsx: afterJsx,
|
|
217
|
+
// },
|
|
218
|
+
// }),
|
|
219
|
+
// moveJSX: ({ payload, result }) => ({
|
|
220
|
+
// target: {
|
|
221
|
+
// componentPath,
|
|
222
|
+
// sourceElement,
|
|
223
|
+
// destinationElement,
|
|
224
|
+
// },
|
|
225
|
+
// before: {
|
|
226
|
+
// sourceJSX: beforeSourceJSX,
|
|
227
|
+
// destinationJSX: beforeDestinationJSX,
|
|
228
|
+
// },
|
|
229
|
+
// after: {
|
|
230
|
+
// sourceJSX: afterSourceJSX,
|
|
231
|
+
// destinationJSX: afterDestinationJSX,
|
|
232
|
+
// },
|
|
233
|
+
// }),
|
|
234
|
+
createFile: ({ payload: { filePath, content = "" }, result }) => ({
|
|
235
|
+
target: {
|
|
236
|
+
filePath,
|
|
237
|
+
},
|
|
238
|
+
before: {
|
|
239
|
+
exists: false,
|
|
240
|
+
},
|
|
241
|
+
after: {
|
|
242
|
+
content,
|
|
243
|
+
},
|
|
244
|
+
}),
|
|
245
|
+
deleteFile: ({ payload: { filePath }, result: { success, filePath: flPath, trashPath }, }) => ({
|
|
246
|
+
target: {
|
|
247
|
+
originalPath: filePath,
|
|
248
|
+
trashPath,
|
|
249
|
+
},
|
|
250
|
+
before: {
|
|
251
|
+
path: filePath,
|
|
252
|
+
},
|
|
253
|
+
after: {
|
|
254
|
+
path: trashPath,
|
|
255
|
+
},
|
|
256
|
+
}),
|
|
257
|
+
renameFile: ({ payload: { oldFilePath, newFilePath }, result: { success, oldFilePath: oldPath, newFilePath: newPath }, }) => ({
|
|
258
|
+
target: {
|
|
259
|
+
oldFilePath,
|
|
260
|
+
newFilePath,
|
|
261
|
+
},
|
|
262
|
+
before: {
|
|
263
|
+
oldFilePath,
|
|
264
|
+
},
|
|
265
|
+
after: {
|
|
266
|
+
newFilePath,
|
|
267
|
+
},
|
|
268
|
+
}),
|
|
269
|
+
moveFile: ({ payload: { sourcePath, destinationPath }, result: { success, sourcePath: srcPath, destinationPath: dstPath }, }) => ({
|
|
270
|
+
target: {
|
|
271
|
+
sourcePath,
|
|
272
|
+
destinationPath,
|
|
273
|
+
},
|
|
274
|
+
before: {
|
|
275
|
+
sourcePath,
|
|
276
|
+
},
|
|
277
|
+
after: {
|
|
278
|
+
destinationPath,
|
|
279
|
+
},
|
|
280
|
+
}),
|
|
281
|
+
createDirectory: ({ payload: { directoryPath } }, context) => {
|
|
282
|
+
const directoryName = path.basename(directoryPath);
|
|
283
|
+
return {
|
|
284
|
+
target: {
|
|
285
|
+
directoryPath,
|
|
286
|
+
trashPath: path.join(context.project.trashDir, `${Date.now()}_${directoryName}`),
|
|
287
|
+
},
|
|
288
|
+
before: {
|
|
289
|
+
exists: false,
|
|
290
|
+
},
|
|
291
|
+
after: {
|
|
292
|
+
exists: true,
|
|
293
|
+
},
|
|
294
|
+
};
|
|
295
|
+
},
|
|
296
|
+
deleteDirectory: ({ payload: { directoryPath }, result: { trashPath } }) => ({
|
|
297
|
+
target: {
|
|
298
|
+
originalPath: directoryPath,
|
|
299
|
+
trashPath,
|
|
300
|
+
},
|
|
301
|
+
before: {
|
|
302
|
+
path: directoryPath,
|
|
303
|
+
},
|
|
304
|
+
after: {
|
|
305
|
+
path: trashPath,
|
|
306
|
+
},
|
|
307
|
+
}),
|
|
308
|
+
renameDirectory: ({ payload: { oldDirectoryPath, newDirectoryPath }, result, }) => ({
|
|
309
|
+
target: {
|
|
310
|
+
oldDirectoryPath,
|
|
311
|
+
newDirectoryPath,
|
|
312
|
+
},
|
|
313
|
+
before: {
|
|
314
|
+
oldDirectoryPath,
|
|
315
|
+
},
|
|
316
|
+
after: {
|
|
317
|
+
newDirectoryPath,
|
|
318
|
+
},
|
|
319
|
+
}),
|
|
320
|
+
moveDirectory: ({ payload: { sourcePath, destinationPath }, result }) => ({
|
|
321
|
+
target: {
|
|
322
|
+
sourcePath,
|
|
323
|
+
destinationPath,
|
|
324
|
+
},
|
|
325
|
+
before: {
|
|
326
|
+
sourcePath,
|
|
327
|
+
},
|
|
328
|
+
after: {
|
|
329
|
+
destinationPath,
|
|
330
|
+
},
|
|
331
|
+
}),
|
|
332
|
+
createComponent: ({ result: { componentDirectoryPath } }) => ({
|
|
333
|
+
target: {
|
|
334
|
+
componentDirectoryPath,
|
|
335
|
+
},
|
|
336
|
+
before: null,
|
|
337
|
+
after: {
|
|
338
|
+
componentDirectoryPath,
|
|
339
|
+
},
|
|
340
|
+
}),
|
|
341
|
+
updateComponent: ({ payload: { componentPath }, result: { oldComponentCode, newComponentCode }, }) => ({
|
|
342
|
+
target: {
|
|
343
|
+
componentPath,
|
|
344
|
+
},
|
|
345
|
+
before: {
|
|
346
|
+
componentCode: oldComponentCode,
|
|
347
|
+
},
|
|
348
|
+
after: {
|
|
349
|
+
componentCode: newComponentCode,
|
|
350
|
+
},
|
|
351
|
+
}),
|
|
352
|
+
deleteComponent: ({ payload: { componentName, parentDirectory }, result: { componentDirectoryPath, trashPath }, }) => ({
|
|
353
|
+
target: {
|
|
354
|
+
componentName,
|
|
355
|
+
parentDirectory,
|
|
356
|
+
componentDirectoryPath,
|
|
357
|
+
},
|
|
358
|
+
before: {
|
|
359
|
+
exists: true,
|
|
360
|
+
},
|
|
361
|
+
after: {
|
|
362
|
+
exists: false,
|
|
363
|
+
trashPath,
|
|
364
|
+
},
|
|
365
|
+
}),
|
|
366
|
+
moveComponent: ({ payload, result }) => ({
|
|
367
|
+
target: {
|
|
368
|
+
sourcePath: payload.sourcePath,
|
|
369
|
+
destinationPath: payload.destinationPath,
|
|
370
|
+
},
|
|
371
|
+
before: {
|
|
372
|
+
existsAt: payload.sourcePath,
|
|
373
|
+
},
|
|
374
|
+
after: {
|
|
375
|
+
existsAt: payload.destinationPath,
|
|
376
|
+
},
|
|
377
|
+
}),
|
|
378
|
+
renameComponent: ({ payload: { componentPath, updateComponentCode }, result: { renamed, oldComponentName, newComponentName, newComponentPath }, }) => ({
|
|
379
|
+
target: {
|
|
380
|
+
oldComponentpath: componentPath,
|
|
381
|
+
newComponentPath,
|
|
382
|
+
oldComponentName,
|
|
383
|
+
newComponentName,
|
|
384
|
+
},
|
|
385
|
+
before: {
|
|
386
|
+
componentName: oldComponentName,
|
|
387
|
+
},
|
|
388
|
+
after: {
|
|
389
|
+
componentName: newComponentName,
|
|
390
|
+
},
|
|
391
|
+
}),
|
|
392
|
+
// extractComponent: ({ payload: {
|
|
393
|
+
// parentComponentPath,
|
|
394
|
+
// newComponentName,
|
|
395
|
+
// targetJSX,
|
|
396
|
+
// componentsDirectory,
|
|
397
|
+
// includeCss}, result: {
|
|
398
|
+
// success,
|
|
399
|
+
// componentPath: newComponentPath,
|
|
400
|
+
// updatedParentPath: absoluteParentPath,
|
|
401
|
+
// } }) => ({
|
|
402
|
+
// target: {
|
|
403
|
+
// parentComponentPath,
|
|
404
|
+
// newComponentPath,
|
|
405
|
+
// },
|
|
406
|
+
// before: {
|
|
407
|
+
// parentComponentCode: beforeParentComponentCode,
|
|
408
|
+
// },
|
|
409
|
+
// after: {
|
|
410
|
+
// parentComponentCode: afterParentComponentCode,
|
|
411
|
+
// extractedComponentCode,
|
|
412
|
+
// },
|
|
413
|
+
// }),
|
|
414
|
+
// ensureComponentStructure: ({ payload, result }) => ({
|
|
415
|
+
// target: {
|
|
416
|
+
// componentDirectory,
|
|
417
|
+
// },
|
|
418
|
+
// before: {
|
|
419
|
+
// directorySnapshot: beforeDirectorySnapshot,
|
|
420
|
+
// },
|
|
421
|
+
// after: {
|
|
422
|
+
// directorySnapshot: afterDirectorySnapshot,
|
|
423
|
+
// },
|
|
424
|
+
// }),
|
|
425
|
+
// updateComponentImports: ({ payload, result }) => ({
|
|
426
|
+
// target: {
|
|
427
|
+
// componentPath,
|
|
428
|
+
// },
|
|
429
|
+
// before: {
|
|
430
|
+
// imports: beforeImports,
|
|
431
|
+
// },
|
|
432
|
+
// after: {
|
|
433
|
+
// imports: afterImports,
|
|
434
|
+
// },
|
|
435
|
+
// }),
|
|
436
|
+
// normalizeComponent: ({ payload, result }) => ({
|
|
437
|
+
// target: {
|
|
438
|
+
// componentPath,
|
|
439
|
+
// },
|
|
440
|
+
// before: {
|
|
441
|
+
// componentCode: beforeComponentCode,
|
|
442
|
+
// cssCode: beforeCssCode,
|
|
443
|
+
// },
|
|
444
|
+
// after: {
|
|
445
|
+
// componentCode: afterComponentCode,
|
|
446
|
+
// cssCode: afterCssCode,
|
|
447
|
+
// },
|
|
448
|
+
// }),
|
|
449
|
+
// ensureStyleFile: ({ payload, result }) => ({
|
|
450
|
+
// target: {
|
|
451
|
+
// cssPath,
|
|
452
|
+
// },
|
|
453
|
+
// before: {
|
|
454
|
+
// exists: false,
|
|
455
|
+
// },
|
|
456
|
+
// after: {
|
|
457
|
+
// cssCode: cssCode,
|
|
458
|
+
// },
|
|
459
|
+
// }),
|
|
460
|
+
insertStyles: ({ payload: { cssPath, styles, addNewLine }, result }) => ({
|
|
461
|
+
target: {
|
|
462
|
+
cssPath,
|
|
463
|
+
},
|
|
464
|
+
before: {
|
|
465
|
+
cssCode: styles,
|
|
466
|
+
},
|
|
467
|
+
after: {
|
|
468
|
+
cssCode: styles,
|
|
469
|
+
},
|
|
470
|
+
}),
|
|
471
|
+
updateStyles: ({ payload: { cssPath, selector, styles, createIfMissing }, result: { success, cssCode, updatedCss }, }) => ({
|
|
472
|
+
target: {
|
|
473
|
+
cssPath,
|
|
474
|
+
selector,
|
|
475
|
+
},
|
|
476
|
+
before: {
|
|
477
|
+
cssCode,
|
|
478
|
+
},
|
|
479
|
+
after: {
|
|
480
|
+
cssCode: updatedCss,
|
|
481
|
+
},
|
|
482
|
+
}),
|
|
483
|
+
removeStyles: ({ payload: { cssPath, target, removeAll }, result: { success, removed, removedCount, cssCode, updatedCss }, }) => ({
|
|
484
|
+
target: {
|
|
485
|
+
cssPath,
|
|
486
|
+
},
|
|
487
|
+
before: {
|
|
488
|
+
cssCode,
|
|
489
|
+
},
|
|
490
|
+
after: {
|
|
491
|
+
updatedCss,
|
|
492
|
+
},
|
|
493
|
+
}),
|
|
494
|
+
renameCssClass: ({ payload: { cssPath, componentJSXPath, oldClassName, newClassName }, result: { cssCode, updatedCssCode, jsxCode, updatedJsxCode }, }) => ({
|
|
495
|
+
target: {
|
|
496
|
+
cssPath,
|
|
497
|
+
componentJSXPath,
|
|
498
|
+
oldClassName,
|
|
499
|
+
newClassName,
|
|
500
|
+
},
|
|
501
|
+
before: {
|
|
502
|
+
cssCode: cssCode,
|
|
503
|
+
componentJsxCode: jsxCode,
|
|
504
|
+
},
|
|
505
|
+
after: {
|
|
506
|
+
cssCode: updatedCssCode,
|
|
507
|
+
componentJsxCode: updatedJsxCode,
|
|
508
|
+
},
|
|
509
|
+
}),
|
|
510
|
+
// syncComponentStyles: ({ payload, result }) => ({
|
|
511
|
+
// target: {
|
|
512
|
+
// componentPath,
|
|
513
|
+
// cssPath,
|
|
514
|
+
// },
|
|
515
|
+
// before: {
|
|
516
|
+
// componentCode: beforeComponentCode,
|
|
517
|
+
// cssCode: beforeCssCode,
|
|
518
|
+
// },
|
|
519
|
+
// after: {
|
|
520
|
+
// componentCode: afterComponentCode,
|
|
521
|
+
// cssCode: afterCssCode,
|
|
522
|
+
// },
|
|
523
|
+
// }),
|
|
524
|
+
// resolveImportConflicts: ({ payload, result }) => ({
|
|
525
|
+
// target: {
|
|
526
|
+
// componentPath,
|
|
527
|
+
// },
|
|
528
|
+
// before: {
|
|
529
|
+
// imports: beforeImports,
|
|
530
|
+
// },
|
|
531
|
+
// after: {
|
|
532
|
+
// imports: afterImports,
|
|
533
|
+
// },
|
|
534
|
+
// }),
|
|
535
|
+
// resolveCssClassConflicts: ({ payload, result }) => ({
|
|
536
|
+
// target: {
|
|
537
|
+
// cssPath,
|
|
538
|
+
// componentPath,
|
|
539
|
+
// },
|
|
540
|
+
// before: {
|
|
541
|
+
// componentCode: beforeComponentCode,
|
|
542
|
+
// cssCode: beforeCssCode,
|
|
543
|
+
// },
|
|
544
|
+
// after: {
|
|
545
|
+
// componentCode: afterComponentCode,
|
|
546
|
+
// cssCode: afterCssCode,
|
|
547
|
+
// },
|
|
548
|
+
// }),
|
|
549
|
+
// resolveStyleDependencies: ({ payload, result }) => ({
|
|
550
|
+
// target: {
|
|
551
|
+
// cssPath,
|
|
552
|
+
// },
|
|
553
|
+
// before: {
|
|
554
|
+
// imports: beforeImports,
|
|
555
|
+
// },
|
|
556
|
+
// after: {
|
|
557
|
+
// imports: afterImports,
|
|
558
|
+
// },
|
|
559
|
+
// }),
|
|
560
|
+
};
|
|
561
|
+
/**
|
|
562
|
+
* Rolls back moveComponent operation.
|
|
563
|
+
*
|
|
564
|
+
* This restores component directory
|
|
565
|
+
* back to its original location.
|
|
566
|
+
*/
|
|
567
|
+
function undoMoveComponent(operation, appContext) {
|
|
568
|
+
// ----------------------------------------------------------
|
|
569
|
+
// STEP 1:
|
|
570
|
+
// Extract paths from operation
|
|
571
|
+
// ----------------------------------------------------------
|
|
572
|
+
const { sourcePath, destinationPath } = operation.target;
|
|
573
|
+
// ----------------------------------------------------------
|
|
574
|
+
// STEP 2:
|
|
575
|
+
// Resolve component name
|
|
576
|
+
// ----------------------------------------------------------
|
|
577
|
+
//
|
|
578
|
+
// Example:
|
|
579
|
+
//
|
|
580
|
+
// ../../src/components/Header
|
|
581
|
+
//
|
|
582
|
+
// -> Header
|
|
583
|
+
//
|
|
584
|
+
// ----------------------------------------------------------
|
|
585
|
+
const componentName = path.basename(sourcePath);
|
|
586
|
+
// ----------------------------------------------------------
|
|
587
|
+
// STEP 3:
|
|
588
|
+
// Build current moved path
|
|
589
|
+
// ----------------------------------------------------------
|
|
590
|
+
//
|
|
591
|
+
// Current location after move:
|
|
592
|
+
//
|
|
593
|
+
// destinationPath/componentName
|
|
594
|
+
//
|
|
595
|
+
// ----------------------------------------------------------
|
|
596
|
+
const movedComponentPath = path.join(destinationPath, componentName);
|
|
597
|
+
// ----------------------------------------------------------
|
|
598
|
+
// STEP 4:
|
|
599
|
+
// Ensure moved component exists
|
|
600
|
+
// ----------------------------------------------------------
|
|
601
|
+
if (!fs.existsSync(movedComponentPath)) {
|
|
602
|
+
throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND, `Moved component not found: ${movedComponentPath}`);
|
|
603
|
+
}
|
|
604
|
+
// ----------------------------------------------------------
|
|
605
|
+
// STEP 5:
|
|
606
|
+
// Ensure original parent directory exists
|
|
607
|
+
// ----------------------------------------------------------
|
|
608
|
+
//
|
|
609
|
+
// Example:
|
|
610
|
+
//
|
|
611
|
+
// ../../src/components/App
|
|
612
|
+
//
|
|
613
|
+
// ----------------------------------------------------------
|
|
614
|
+
const originalParentDirectory = path.dirname(sourcePath);
|
|
615
|
+
fs.mkdirSync(originalParentDirectory, {
|
|
616
|
+
recursive: true,
|
|
617
|
+
});
|
|
618
|
+
// ----------------------------------------------------------
|
|
619
|
+
// STEP 6:
|
|
620
|
+
// Move component back
|
|
621
|
+
// ----------------------------------------------------------
|
|
622
|
+
fs.renameSync(movedComponentPath, sourcePath);
|
|
623
|
+
// ----------------------------------------------------------
|
|
624
|
+
// STEP 7:
|
|
625
|
+
// Return rollback result
|
|
626
|
+
// ----------------------------------------------------------
|
|
627
|
+
return {
|
|
628
|
+
success: true,
|
|
629
|
+
restoredPath: sourcePath,
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Rolls back a renameComponent operation.
|
|
634
|
+
*
|
|
635
|
+
* Params:
|
|
636
|
+
* - operation:
|
|
637
|
+
* Operation log entry created by appendOperation.
|
|
638
|
+
*
|
|
639
|
+
* Returns:
|
|
640
|
+
* - {
|
|
641
|
+
* rolledBack: boolean,
|
|
642
|
+
* componentPath: string
|
|
643
|
+
* }
|
|
644
|
+
*/
|
|
645
|
+
function undoRenameComponent(operation, appContext) {
|
|
646
|
+
// ----------------------------------------------------------
|
|
647
|
+
// STEP 1:
|
|
648
|
+
// Extract information from operation log.
|
|
649
|
+
// ----------------------------------------------------------
|
|
650
|
+
const { newComponentPath: componentPath } = operation.target;
|
|
651
|
+
const { componentName: oldComponentName } = operation.before;
|
|
652
|
+
const { componentName: newComponentName } = operation.after;
|
|
653
|
+
// ----------------------------------------------------------
|
|
654
|
+
// STEP 2:
|
|
655
|
+
// Rename component back to its original name.
|
|
656
|
+
// ----------------------------------------------------------
|
|
657
|
+
const result = mutations.renameComponent({
|
|
658
|
+
componentPath,
|
|
659
|
+
newComponentName: oldComponentName,
|
|
660
|
+
// Preserve the same behavior that was
|
|
661
|
+
// used during the original rename.
|
|
662
|
+
updateComponentCode: true,
|
|
663
|
+
}, appContext);
|
|
664
|
+
// ----------------------------------------------------------
|
|
665
|
+
// STEP 3:
|
|
666
|
+
// Validate rollback.
|
|
667
|
+
// ----------------------------------------------------------
|
|
668
|
+
if (!result?.success) {
|
|
669
|
+
throw new LoomaError(ERROR_CODES.ROLLBACK_ERROR, `Failed to rollback renameComponent: ${newComponentName} -> ${oldComponentName}`);
|
|
670
|
+
}
|
|
671
|
+
// ----------------------------------------------------------
|
|
672
|
+
// STEP 4:
|
|
673
|
+
// Return result.
|
|
674
|
+
// ----------------------------------------------------------
|
|
675
|
+
return {
|
|
676
|
+
success: true,
|
|
677
|
+
componentPath,
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
function undoCreateComponent(operation, appContext) {
|
|
681
|
+
fs.rmSync(path.resolve(appContext.project.root, operation.target.componentDirectoryPath), {
|
|
682
|
+
recursive: true,
|
|
683
|
+
force: true,
|
|
684
|
+
});
|
|
685
|
+
return {
|
|
686
|
+
success: true,
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
function undoDeleteComponent(operation, appContext) {
|
|
690
|
+
// ----------------------------------------------------------
|
|
691
|
+
// Resolve source directory inside trash.
|
|
692
|
+
// ----------------------------------------------------------
|
|
693
|
+
const sourcePath = path.resolve(appContext.project.root, operation.after.trashPath);
|
|
694
|
+
// ----------------------------------------------------------
|
|
695
|
+
// Resolve original component path.
|
|
696
|
+
// Example:
|
|
697
|
+
// src/components/Home
|
|
698
|
+
// ----------------------------------------------------------
|
|
699
|
+
const destinationPath = path.resolve(appContext.project.root, operation.target.componentDirectoryPath);
|
|
700
|
+
// ----------------------------------------------------------
|
|
701
|
+
// Make sure parent directory exists.
|
|
702
|
+
// ----------------------------------------------------------
|
|
703
|
+
const parentDirectory = path.dirname(destinationPath);
|
|
704
|
+
fs.mkdirSync(parentDirectory, {
|
|
705
|
+
recursive: true,
|
|
706
|
+
});
|
|
707
|
+
// ----------------------------------------------------------
|
|
708
|
+
// Restore directory with its original name.
|
|
709
|
+
// ----------------------------------------------------------
|
|
710
|
+
fs.renameSync(sourcePath, destinationPath);
|
|
711
|
+
return {
|
|
712
|
+
success: true,
|
|
713
|
+
sourcePath,
|
|
714
|
+
destinationPath,
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Rolls back insertCode operation.
|
|
719
|
+
*
|
|
720
|
+
* Restores file content back
|
|
721
|
+
* to original state before insertion.
|
|
722
|
+
*/
|
|
723
|
+
// function undoInsertCode(
|
|
724
|
+
// operation
|
|
725
|
+
// ): TaskResponse<any> {
|
|
726
|
+
// // ----------------------------------------------------------
|
|
727
|
+
// // STEP 1:
|
|
728
|
+
// // Extract file path
|
|
729
|
+
// // ----------------------------------------------------------
|
|
730
|
+
// const { filePath } = operation.target;
|
|
731
|
+
// // ----------------------------------------------------------
|
|
732
|
+
// // STEP 2:
|
|
733
|
+
// // Extract original file content
|
|
734
|
+
// // ----------------------------------------------------------
|
|
735
|
+
// const originalCode = operation.before.code;
|
|
736
|
+
// // ----------------------------------------------------------
|
|
737
|
+
// // STEP 3:
|
|
738
|
+
// // Ensure rollback data exists
|
|
739
|
+
// // ----------------------------------------------------------
|
|
740
|
+
// if (typeof originalCode !== "string") {
|
|
741
|
+
// throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND,"Missing original code for rollback.");
|
|
742
|
+
// }
|
|
743
|
+
// // ----------------------------------------------------------
|
|
744
|
+
// // STEP 4:
|
|
745
|
+
// // Restore original file content
|
|
746
|
+
// // ----------------------------------------------------------
|
|
747
|
+
// fs.writeFileSync(filePath, originalCode, "utf8");
|
|
748
|
+
// // ----------------------------------------------------------
|
|
749
|
+
// // STEP 5:
|
|
750
|
+
// // Return rollback result
|
|
751
|
+
// // ----------------------------------------------------------
|
|
752
|
+
// return {
|
|
753
|
+
// success: true,
|
|
754
|
+
// restoredFilePath: filePath,
|
|
755
|
+
// };
|
|
756
|
+
// }
|
|
757
|
+
/**
|
|
758
|
+
* Rolls back extractComponent operation.
|
|
759
|
+
*
|
|
760
|
+
* This:
|
|
761
|
+
* - restores original parent component code
|
|
762
|
+
* - removes extracted component directory
|
|
763
|
+
*/
|
|
764
|
+
function undoExtractComponent(operation, appContext) {
|
|
765
|
+
// ----------------------------------------------------------
|
|
766
|
+
// STEP 1:
|
|
767
|
+
// Extract rollback information
|
|
768
|
+
// ----------------------------------------------------------
|
|
769
|
+
const { parentComponentPath, newComponentPath } = operation.target;
|
|
770
|
+
// ----------------------------------------------------------
|
|
771
|
+
// STEP 2:
|
|
772
|
+
// Extract original parent component code
|
|
773
|
+
// ----------------------------------------------------------
|
|
774
|
+
const originalParentCode = operation.before.parentComponentCode;
|
|
775
|
+
// ----------------------------------------------------------
|
|
776
|
+
// STEP 3:
|
|
777
|
+
// Ensure rollback snapshot exists
|
|
778
|
+
// ----------------------------------------------------------
|
|
779
|
+
if (typeof originalParentCode !== "string") {
|
|
780
|
+
throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND, "Missing parent component snapshot.");
|
|
781
|
+
}
|
|
782
|
+
// ----------------------------------------------------------
|
|
783
|
+
// STEP 4:
|
|
784
|
+
// Restore original parent component
|
|
785
|
+
// ----------------------------------------------------------
|
|
786
|
+
fs.writeFileSync(parentComponentPath, originalParentCode, "utf8");
|
|
787
|
+
// ----------------------------------------------------------
|
|
788
|
+
// STEP 5:
|
|
789
|
+
// Remove extracted component directory
|
|
790
|
+
// ----------------------------------------------------------
|
|
791
|
+
//
|
|
792
|
+
// Example:
|
|
793
|
+
//
|
|
794
|
+
// /src/components/Header
|
|
795
|
+
//
|
|
796
|
+
// ----------------------------------------------------------
|
|
797
|
+
if (fs.existsSync(newComponentPath)) {
|
|
798
|
+
fs.rmSync(newComponentPath, {
|
|
799
|
+
recursive: true,
|
|
800
|
+
force: true,
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
// ----------------------------------------------------------
|
|
804
|
+
// STEP 6:
|
|
805
|
+
// Return rollback result
|
|
806
|
+
// ----------------------------------------------------------
|
|
807
|
+
return {
|
|
808
|
+
success: true,
|
|
809
|
+
restoredParent: parentComponentPath,
|
|
810
|
+
removedComponent: newComponentPath,
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* Rolls back insertJSX operation.
|
|
815
|
+
*
|
|
816
|
+
* Restores component source code
|
|
817
|
+
* back to original state before JSX insertion.
|
|
818
|
+
*/
|
|
819
|
+
// function undoInsertJSX(
|
|
820
|
+
// operation
|
|
821
|
+
// ): TaskResponse<any> {
|
|
822
|
+
// // ----------------------------------------------------------
|
|
823
|
+
// // STEP 1:
|
|
824
|
+
// // Extract component file path
|
|
825
|
+
// // ----------------------------------------------------------
|
|
826
|
+
// const { componentPath } = operation.target;
|
|
827
|
+
// // ----------------------------------------------------------
|
|
828
|
+
// // STEP 2:
|
|
829
|
+
// // Extract original component code
|
|
830
|
+
// // ----------------------------------------------------------
|
|
831
|
+
// const originalCode = operation.before.code;
|
|
832
|
+
// // ----------------------------------------------------------
|
|
833
|
+
// // STEP 3:
|
|
834
|
+
// // Ensure rollback snapshot exists
|
|
835
|
+
// // ----------------------------------------------------------
|
|
836
|
+
// if (typeof originalCode !== "string") {
|
|
837
|
+
// throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND,"Missing original component code for rollback.");
|
|
838
|
+
// }
|
|
839
|
+
// // ----------------------------------------------------------
|
|
840
|
+
// // STEP 4:
|
|
841
|
+
// // Restore original component code
|
|
842
|
+
// // ----------------------------------------------------------
|
|
843
|
+
// fs.writeFileSync(componentPath, originalCode, "utf8");
|
|
844
|
+
// // ----------------------------------------------------------
|
|
845
|
+
// // STEP 5:
|
|
846
|
+
// // Return rollback result
|
|
847
|
+
// // ----------------------------------------------------------
|
|
848
|
+
// return {
|
|
849
|
+
// success: true,
|
|
850
|
+
// restoredComponent: componentPath,
|
|
851
|
+
// };
|
|
852
|
+
// }
|
|
853
|
+
/**
|
|
854
|
+
* Rolls back replaceJSX operation.
|
|
855
|
+
*
|
|
856
|
+
* Restores component source code
|
|
857
|
+
* back to original state before JSX replacement.
|
|
858
|
+
*/
|
|
859
|
+
// function undoReplaceJSX(
|
|
860
|
+
// operation
|
|
861
|
+
// ): TaskResponse<any> {
|
|
862
|
+
// // ----------------------------------------------------------
|
|
863
|
+
// // STEP 1:
|
|
864
|
+
// // Extract component file path
|
|
865
|
+
// // ----------------------------------------------------------
|
|
866
|
+
// const { componentPath } = operation.target;
|
|
867
|
+
// // ----------------------------------------------------------
|
|
868
|
+
// // STEP 2:
|
|
869
|
+
// // Extract original component code
|
|
870
|
+
// // ----------------------------------------------------------
|
|
871
|
+
// const originalCode = operation.before.code;
|
|
872
|
+
// // ----------------------------------------------------------
|
|
873
|
+
// // STEP 3:
|
|
874
|
+
// // Ensure rollback snapshot exists
|
|
875
|
+
// // ----------------------------------------------------------
|
|
876
|
+
// if (typeof originalCode !== "string") {
|
|
877
|
+
// throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND,"Missing original component code for rollback.");
|
|
878
|
+
// }
|
|
879
|
+
// // ----------------------------------------------------------
|
|
880
|
+
// // STEP 4:
|
|
881
|
+
// // Restore original component code
|
|
882
|
+
// // ----------------------------------------------------------
|
|
883
|
+
// fs.writeFileSync(componentPath, originalCode, "utf8");
|
|
884
|
+
// // ----------------------------------------------------------
|
|
885
|
+
// // STEP 5:
|
|
886
|
+
// // Return rollback result
|
|
887
|
+
// // ----------------------------------------------------------
|
|
888
|
+
// return {
|
|
889
|
+
// success: true,
|
|
890
|
+
// restoredComponent: componentPath,
|
|
891
|
+
// };
|
|
892
|
+
// }
|
|
893
|
+
/**
|
|
894
|
+
* Rolls back removeJSX operation.
|
|
895
|
+
*
|
|
896
|
+
* Restores component source code
|
|
897
|
+
* back to original state before JSX removal.
|
|
898
|
+
*/
|
|
899
|
+
// function undoRemoveJSX(
|
|
900
|
+
// operation
|
|
901
|
+
// ): TaskResponse<any> {
|
|
902
|
+
// // ----------------------------------------------------------
|
|
903
|
+
// // STEP 1:
|
|
904
|
+
// // Extract component file path
|
|
905
|
+
// // ----------------------------------------------------------
|
|
906
|
+
// const { componentPath } = operation.target;
|
|
907
|
+
// // ----------------------------------------------------------
|
|
908
|
+
// // STEP 2:
|
|
909
|
+
// // Extract original component code
|
|
910
|
+
// // ----------------------------------------------------------
|
|
911
|
+
// const originalCode = operation.before.code;
|
|
912
|
+
// // ----------------------------------------------------------
|
|
913
|
+
// // STEP 3:
|
|
914
|
+
// // Ensure rollback snapshot exists
|
|
915
|
+
// // ----------------------------------------------------------
|
|
916
|
+
// if (typeof originalCode !== "string") {
|
|
917
|
+
// throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND,"Missing original component code for rollback.");
|
|
918
|
+
// }
|
|
919
|
+
// // ----------------------------------------------------------
|
|
920
|
+
// // STEP 4:
|
|
921
|
+
// // Restore original component code
|
|
922
|
+
// // ----------------------------------------------------------
|
|
923
|
+
// fs.writeFileSync(componentPath, originalCode, "utf8");
|
|
924
|
+
// // ----------------------------------------------------------
|
|
925
|
+
// // STEP 5:
|
|
926
|
+
// // Return rollback result
|
|
927
|
+
// // ----------------------------------------------------------
|
|
928
|
+
// return {
|
|
929
|
+
// success: true,
|
|
930
|
+
// restoredComponent: componentPath,
|
|
931
|
+
// };
|
|
932
|
+
// }
|
|
933
|
+
/**
|
|
934
|
+
* Rolls back moveJSX operation.
|
|
935
|
+
*
|
|
936
|
+
* Restores component source code
|
|
937
|
+
* back to original state before JSX movement.
|
|
938
|
+
*/
|
|
939
|
+
// function undoMoveJSX(
|
|
940
|
+
// operation
|
|
941
|
+
// ): TaskResponse<any> {
|
|
942
|
+
// // ----------------------------------------------------------
|
|
943
|
+
// // STEP 1:
|
|
944
|
+
// // Extract component file path
|
|
945
|
+
// // ----------------------------------------------------------
|
|
946
|
+
// const { componentPath } = operation.target;
|
|
947
|
+
// // ----------------------------------------------------------
|
|
948
|
+
// // STEP 2:
|
|
949
|
+
// // Extract original component code
|
|
950
|
+
// // ----------------------------------------------------------
|
|
951
|
+
// const originalCode = operation.before.code;
|
|
952
|
+
// // ----------------------------------------------------------
|
|
953
|
+
// // STEP 3:
|
|
954
|
+
// // Ensure rollback snapshot exists
|
|
955
|
+
// // ----------------------------------------------------------
|
|
956
|
+
// if (typeof originalCode !== "string") {
|
|
957
|
+
// throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND,"Missing original component code for rollback.");
|
|
958
|
+
// }
|
|
959
|
+
// // ----------------------------------------------------------
|
|
960
|
+
// // STEP 4:
|
|
961
|
+
// // Restore original component code
|
|
962
|
+
// // ----------------------------------------------------------
|
|
963
|
+
// fs.writeFileSync(componentPath, originalCode, "utf8");
|
|
964
|
+
// // ----------------------------------------------------------
|
|
965
|
+
// // STEP 5:
|
|
966
|
+
// // Return rollback result
|
|
967
|
+
// // ----------------------------------------------------------
|
|
968
|
+
// return {
|
|
969
|
+
// success: true,
|
|
970
|
+
// restoredComponent: componentPath,
|
|
971
|
+
// };
|
|
972
|
+
// }
|
|
973
|
+
/**
|
|
974
|
+
* Rolls back wrapJSX operation.
|
|
975
|
+
*
|
|
976
|
+
* Restores component source code
|
|
977
|
+
* back to original state before JSX wrapping.
|
|
978
|
+
*/
|
|
979
|
+
// function undoWrapJSX(
|
|
980
|
+
// operation
|
|
981
|
+
// ): TaskResponse<any> {
|
|
982
|
+
// // ----------------------------------------------------------
|
|
983
|
+
// // STEP 1:
|
|
984
|
+
// // Extract component file path
|
|
985
|
+
// // ----------------------------------------------------------
|
|
986
|
+
// const { componentPath } = operation.target;
|
|
987
|
+
// // ----------------------------------------------------------
|
|
988
|
+
// // STEP 2:
|
|
989
|
+
// // Extract original component code
|
|
990
|
+
// // ----------------------------------------------------------
|
|
991
|
+
// const originalCode = operation.before.code;
|
|
992
|
+
// // ----------------------------------------------------------
|
|
993
|
+
// // STEP 3:
|
|
994
|
+
// // Ensure rollback snapshot exists
|
|
995
|
+
// // ----------------------------------------------------------
|
|
996
|
+
// if (typeof originalCode !== "string") {
|
|
997
|
+
// throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND,"Missing original component code for rollback.");
|
|
998
|
+
// }
|
|
999
|
+
// // ----------------------------------------------------------
|
|
1000
|
+
// // STEP 4:
|
|
1001
|
+
// // Restore original component code
|
|
1002
|
+
// // ----------------------------------------------------------
|
|
1003
|
+
// fs.writeFileSync(componentPath, originalCode, "utf8");
|
|
1004
|
+
// // ----------------------------------------------------------
|
|
1005
|
+
// // STEP 5:
|
|
1006
|
+
// // Return rollback result
|
|
1007
|
+
// // ----------------------------------------------------------
|
|
1008
|
+
// return {
|
|
1009
|
+
// success: true,
|
|
1010
|
+
// restoredComponent: componentPath,
|
|
1011
|
+
// };
|
|
1012
|
+
// }
|
|
1013
|
+
/**
|
|
1014
|
+
* Rolls back createFile operation.
|
|
1015
|
+
*
|
|
1016
|
+
* Removes file that was created
|
|
1017
|
+
* during createFile task execution.
|
|
1018
|
+
*/
|
|
1019
|
+
function undoCreateFile(operation, appContext) {
|
|
1020
|
+
// ----------------------------------------------------------
|
|
1021
|
+
// STEP 1:
|
|
1022
|
+
// Extract file path
|
|
1023
|
+
// ----------------------------------------------------------
|
|
1024
|
+
const { filePath } = operation.target;
|
|
1025
|
+
// ----------------------------------------------------------
|
|
1026
|
+
// STEP 2:
|
|
1027
|
+
// Ensure file exists
|
|
1028
|
+
// ----------------------------------------------------------
|
|
1029
|
+
if (!fs.existsSync(filePath)) {
|
|
1030
|
+
throw new LoomaError(ERROR_CODES.FILE_NOT_FOUND, `File does not exist: ${filePath}`);
|
|
1031
|
+
}
|
|
1032
|
+
// ----------------------------------------------------------
|
|
1033
|
+
// STEP 3:
|
|
1034
|
+
// Remove created file
|
|
1035
|
+
// ----------------------------------------------------------
|
|
1036
|
+
fs.unlinkSync(filePath);
|
|
1037
|
+
// ----------------------------------------------------------
|
|
1038
|
+
// STEP 4:
|
|
1039
|
+
// Return rollback result
|
|
1040
|
+
// ----------------------------------------------------------
|
|
1041
|
+
return {
|
|
1042
|
+
success: true,
|
|
1043
|
+
removedFile: filePath,
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
/**
|
|
1047
|
+
* Rolls back deleteFile operation.
|
|
1048
|
+
*
|
|
1049
|
+
* Restores deleted file
|
|
1050
|
+
* back to original location.
|
|
1051
|
+
*/
|
|
1052
|
+
function undoDeleteFile(operation, appContext) {
|
|
1053
|
+
// ----------------------------------------------------------
|
|
1054
|
+
// STEP 1:
|
|
1055
|
+
// Extract file paths
|
|
1056
|
+
// ----------------------------------------------------------
|
|
1057
|
+
const { originalPath, trashPath } = operation.target;
|
|
1058
|
+
// ----------------------------------------------------------
|
|
1059
|
+
// STEP 2:
|
|
1060
|
+
// Ensure deleted file exists in trash
|
|
1061
|
+
// ----------------------------------------------------------
|
|
1062
|
+
if (!fs.existsSync(trashPath)) {
|
|
1063
|
+
throw new LoomaError(ERROR_CODES.FILE_NOT_FOUND, `Deleted file not found in trash: ${trashPath}`);
|
|
1064
|
+
}
|
|
1065
|
+
// ----------------------------------------------------------
|
|
1066
|
+
// STEP 3:
|
|
1067
|
+
// Ensure original parent directory exists
|
|
1068
|
+
// ----------------------------------------------------------
|
|
1069
|
+
const parentDirectory = path.dirname(originalPath);
|
|
1070
|
+
fs.mkdirSync(parentDirectory, {
|
|
1071
|
+
recursive: true,
|
|
1072
|
+
});
|
|
1073
|
+
// ----------------------------------------------------------
|
|
1074
|
+
// STEP 4:
|
|
1075
|
+
// Restore file back
|
|
1076
|
+
// ----------------------------------------------------------
|
|
1077
|
+
fs.renameSync(trashPath, originalPath);
|
|
1078
|
+
// ----------------------------------------------------------
|
|
1079
|
+
// STEP 5:
|
|
1080
|
+
// Return rollback result
|
|
1081
|
+
// ----------------------------------------------------------
|
|
1082
|
+
return {
|
|
1083
|
+
success: true,
|
|
1084
|
+
restoredFile: originalPath,
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
/**
|
|
1088
|
+
* Rolls back renameFile operation.
|
|
1089
|
+
*
|
|
1090
|
+
* Renames file back
|
|
1091
|
+
* to its original path.
|
|
1092
|
+
*/
|
|
1093
|
+
function undoRenameFile(operation, appContext) {
|
|
1094
|
+
// ----------------------------------------------------------
|
|
1095
|
+
// STEP 1:
|
|
1096
|
+
// Extract file paths
|
|
1097
|
+
// ----------------------------------------------------------
|
|
1098
|
+
const { oldFilePath, newFilePath } = operation.target;
|
|
1099
|
+
// ----------------------------------------------------------
|
|
1100
|
+
// STEP 2:
|
|
1101
|
+
// Ensure renamed file exists
|
|
1102
|
+
// ----------------------------------------------------------
|
|
1103
|
+
if (!fs.existsSync(newFilePath)) {
|
|
1104
|
+
throw new LoomaError(ERROR_CODES.FILE_NOT_FOUND, `Renamed file not found: ${newFilePath}`);
|
|
1105
|
+
}
|
|
1106
|
+
// ----------------------------------------------------------
|
|
1107
|
+
// STEP 3:
|
|
1108
|
+
// Ensure original parent directory exists
|
|
1109
|
+
// ----------------------------------------------------------
|
|
1110
|
+
const parentDirectory = path.dirname(oldFilePath);
|
|
1111
|
+
fs.mkdirSync(parentDirectory, {
|
|
1112
|
+
recursive: true,
|
|
1113
|
+
});
|
|
1114
|
+
// ----------------------------------------------------------
|
|
1115
|
+
// STEP 4:
|
|
1116
|
+
// Rename file back
|
|
1117
|
+
// ----------------------------------------------------------
|
|
1118
|
+
fs.renameSync(newFilePath, oldFilePath);
|
|
1119
|
+
// ----------------------------------------------------------
|
|
1120
|
+
// STEP 5:
|
|
1121
|
+
// Return rollback result
|
|
1122
|
+
// ----------------------------------------------------------
|
|
1123
|
+
return {
|
|
1124
|
+
success: true,
|
|
1125
|
+
restoredFile: oldFilePath,
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Rolls back moveFile operation.
|
|
1130
|
+
*
|
|
1131
|
+
* Moves file back
|
|
1132
|
+
* to its original location.
|
|
1133
|
+
*/
|
|
1134
|
+
function undoMoveFile(operation, appContext) {
|
|
1135
|
+
// ----------------------------------------------------------
|
|
1136
|
+
// STEP 1:
|
|
1137
|
+
// Extract file paths
|
|
1138
|
+
// ----------------------------------------------------------
|
|
1139
|
+
const { sourcePath, destinationPath } = operation.target;
|
|
1140
|
+
// ----------------------------------------------------------
|
|
1141
|
+
// STEP 2:
|
|
1142
|
+
// Resolve moved file path
|
|
1143
|
+
// ----------------------------------------------------------
|
|
1144
|
+
//
|
|
1145
|
+
// Example:
|
|
1146
|
+
//
|
|
1147
|
+
// sourcePath:
|
|
1148
|
+
// /src/tasks/helpers/api.js
|
|
1149
|
+
//
|
|
1150
|
+
// destinationPath:
|
|
1151
|
+
// /src/services
|
|
1152
|
+
//
|
|
1153
|
+
// moved file:
|
|
1154
|
+
// /src/services/api.js
|
|
1155
|
+
//
|
|
1156
|
+
// ----------------------------------------------------------
|
|
1157
|
+
const fileName = path.basename(sourcePath);
|
|
1158
|
+
// const dstFileName = path.basename(destinationPath);
|
|
1159
|
+
const movedFilePath = path.join(destinationPath, fileName);
|
|
1160
|
+
// ----------------------------------------------------------
|
|
1161
|
+
// STEP 3:
|
|
1162
|
+
// Ensure moved file exists
|
|
1163
|
+
// ----------------------------------------------------------
|
|
1164
|
+
if (!fs.existsSync(movedFilePath)) {
|
|
1165
|
+
throw new LoomaError(ERROR_CODES.FILE_NOT_FOUND, `Moved file not found: ${movedFilePath}`);
|
|
1166
|
+
}
|
|
1167
|
+
// ----------------------------------------------------------
|
|
1168
|
+
// STEP 4:
|
|
1169
|
+
// Ensure original parent directory exists
|
|
1170
|
+
// ----------------------------------------------------------
|
|
1171
|
+
const originalParentDirectory = path.dirname(sourcePath);
|
|
1172
|
+
fs.mkdirSync(originalParentDirectory, {
|
|
1173
|
+
recursive: true,
|
|
1174
|
+
});
|
|
1175
|
+
// ----------------------------------------------------------
|
|
1176
|
+
// STEP 5:
|
|
1177
|
+
// Move file back
|
|
1178
|
+
// ----------------------------------------------------------
|
|
1179
|
+
fs.renameSync(movedFilePath, sourcePath);
|
|
1180
|
+
// ----------------------------------------------------------
|
|
1181
|
+
// STEP 6:
|
|
1182
|
+
// Return rollback result
|
|
1183
|
+
// ----------------------------------------------------------
|
|
1184
|
+
return {
|
|
1185
|
+
success: true,
|
|
1186
|
+
restoredFile: sourcePath,
|
|
1187
|
+
};
|
|
1188
|
+
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Rolls back createDirectory operation.
|
|
1191
|
+
*
|
|
1192
|
+
* Removes directory that was created
|
|
1193
|
+
* during createDirectory task execution.
|
|
1194
|
+
*/
|
|
1195
|
+
function undoCreateDirectory(operation, appContext) {
|
|
1196
|
+
// ----------------------------------------------------------
|
|
1197
|
+
// STEP 1:
|
|
1198
|
+
// Extract paths
|
|
1199
|
+
// ----------------------------------------------------------
|
|
1200
|
+
const { directoryPath, trashPath } = operation.target;
|
|
1201
|
+
// ----------------------------------------------------------
|
|
1202
|
+
// STEP 2:
|
|
1203
|
+
// Ensure directory exists
|
|
1204
|
+
// ----------------------------------------------------------
|
|
1205
|
+
if (!fs.existsSync(directoryPath)) {
|
|
1206
|
+
throw new LoomaError(ERROR_CODES.DIRECTORY_NOT_FOUND, `Directory not found: ${directoryPath}`);
|
|
1207
|
+
}
|
|
1208
|
+
// ----------------------------------------------------------
|
|
1209
|
+
// STEP 3:
|
|
1210
|
+
// Ensure trash parent exists
|
|
1211
|
+
// ----------------------------------------------------------
|
|
1212
|
+
fs.mkdirSync(path.dirname(trashPath), {
|
|
1213
|
+
recursive: true,
|
|
1214
|
+
});
|
|
1215
|
+
// ----------------------------------------------------------
|
|
1216
|
+
// STEP 4:
|
|
1217
|
+
// Move directory to trash
|
|
1218
|
+
// ----------------------------------------------------------
|
|
1219
|
+
fs.renameSync(directoryPath, trashPath);
|
|
1220
|
+
// ----------------------------------------------------------
|
|
1221
|
+
// STEP 5:
|
|
1222
|
+
// Return result
|
|
1223
|
+
// ----------------------------------------------------------
|
|
1224
|
+
return {
|
|
1225
|
+
success: true,
|
|
1226
|
+
removedDirectory: directoryPath,
|
|
1227
|
+
};
|
|
1228
|
+
}
|
|
1229
|
+
/**
|
|
1230
|
+
* Rolls back deleteDirectory operation.
|
|
1231
|
+
*
|
|
1232
|
+
* Restores deleted directory
|
|
1233
|
+
* back to original location.
|
|
1234
|
+
*/
|
|
1235
|
+
function undoDeleteDirectory(operation, appContext) {
|
|
1236
|
+
// ----------------------------------------------------------
|
|
1237
|
+
// STEP 1:
|
|
1238
|
+
// Extract directory paths
|
|
1239
|
+
// ----------------------------------------------------------
|
|
1240
|
+
const { originalPath, trashPath } = operation.target;
|
|
1241
|
+
// ----------------------------------------------------------
|
|
1242
|
+
// STEP 2:
|
|
1243
|
+
// Ensure deleted directory exists in trash
|
|
1244
|
+
// ----------------------------------------------------------
|
|
1245
|
+
if (!fs.existsSync(trashPath)) {
|
|
1246
|
+
throw new LoomaError(ERROR_CODES.DIRECTORY_NOT_FOUND, `Deleted directory not found in trash: ${trashPath}`);
|
|
1247
|
+
}
|
|
1248
|
+
// ----------------------------------------------------------
|
|
1249
|
+
// STEP 3:
|
|
1250
|
+
// Ensure original parent directory exists
|
|
1251
|
+
// ----------------------------------------------------------
|
|
1252
|
+
const parentDirectory = path.dirname(originalPath);
|
|
1253
|
+
fs.mkdirSync(parentDirectory, {
|
|
1254
|
+
recursive: true,
|
|
1255
|
+
});
|
|
1256
|
+
// ----------------------------------------------------------
|
|
1257
|
+
// STEP 4:
|
|
1258
|
+
// Restore directory back
|
|
1259
|
+
// ----------------------------------------------------------
|
|
1260
|
+
fs.renameSync(trashPath, originalPath);
|
|
1261
|
+
// ----------------------------------------------------------
|
|
1262
|
+
// STEP 5:
|
|
1263
|
+
// Return rollback result
|
|
1264
|
+
// ----------------------------------------------------------
|
|
1265
|
+
return {
|
|
1266
|
+
success: true,
|
|
1267
|
+
restoredDirectory: originalPath,
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
/**
|
|
1271
|
+
* Rolls back renameDirectory operation.
|
|
1272
|
+
*
|
|
1273
|
+
* Renames directory back
|
|
1274
|
+
* to its original path.
|
|
1275
|
+
*/
|
|
1276
|
+
function undoRenameDirectory(operation, appContext) {
|
|
1277
|
+
// ----------------------------------------------------------
|
|
1278
|
+
// STEP 1:
|
|
1279
|
+
// Extract directory paths
|
|
1280
|
+
// ----------------------------------------------------------
|
|
1281
|
+
const { oldDirectoryPath, newDirectoryPath } = operation.target;
|
|
1282
|
+
// ----------------------------------------------------------
|
|
1283
|
+
// STEP 2:
|
|
1284
|
+
// Ensure renamed directory exists
|
|
1285
|
+
// ----------------------------------------------------------
|
|
1286
|
+
if (!fs.existsSync(newDirectoryPath)) {
|
|
1287
|
+
throw new LoomaError(ERROR_CODES.DIRECTORY_NOT_FOUND, `Renamed directory not found: ${newDirectoryPath}`);
|
|
1288
|
+
}
|
|
1289
|
+
// ----------------------------------------------------------
|
|
1290
|
+
// STEP 3:
|
|
1291
|
+
// Ensure original parent directory exists
|
|
1292
|
+
// ----------------------------------------------------------
|
|
1293
|
+
const parentDirectory = path.dirname(oldDirectoryPath);
|
|
1294
|
+
fs.mkdirSync(parentDirectory, {
|
|
1295
|
+
recursive: true,
|
|
1296
|
+
});
|
|
1297
|
+
// ----------------------------------------------------------
|
|
1298
|
+
// STEP 4:
|
|
1299
|
+
// Rename directory back
|
|
1300
|
+
// ----------------------------------------------------------
|
|
1301
|
+
fs.renameSync(newDirectoryPath, oldDirectoryPath);
|
|
1302
|
+
// ----------------------------------------------------------
|
|
1303
|
+
// STEP 5:
|
|
1304
|
+
// Return rollback result
|
|
1305
|
+
// ----------------------------------------------------------
|
|
1306
|
+
return {
|
|
1307
|
+
success: true,
|
|
1308
|
+
restoredDirectory: oldDirectoryPath,
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
/**
|
|
1312
|
+
* Rolls back moveDirectory operation.
|
|
1313
|
+
*
|
|
1314
|
+
* Moves directory back
|
|
1315
|
+
* to its original location.
|
|
1316
|
+
*/
|
|
1317
|
+
function undoMoveDirectory(operation, appContext) {
|
|
1318
|
+
// ----------------------------------------------------------
|
|
1319
|
+
// STEP 1:
|
|
1320
|
+
// Extract paths
|
|
1321
|
+
// ----------------------------------------------------------
|
|
1322
|
+
const { sourcePath, destinationPath } = operation.target;
|
|
1323
|
+
// ----------------------------------------------------------
|
|
1324
|
+
// STEP 2:
|
|
1325
|
+
// Determine moved directory path
|
|
1326
|
+
// ----------------------------------------------------------
|
|
1327
|
+
const directoryName = path.basename(sourcePath);
|
|
1328
|
+
const movedDirectoryPath = path.join(destinationPath, directoryName);
|
|
1329
|
+
// ----------------------------------------------------------
|
|
1330
|
+
// STEP 3:
|
|
1331
|
+
// Ensure moved directory exists
|
|
1332
|
+
// ----------------------------------------------------------
|
|
1333
|
+
if (!fs.existsSync(movedDirectoryPath)) {
|
|
1334
|
+
throw new LoomaError(ERROR_CODES.DIRECTORY_NOT_FOUND, `Moved directory not found: ${movedDirectoryPath}`);
|
|
1335
|
+
}
|
|
1336
|
+
// ----------------------------------------------------------
|
|
1337
|
+
// STEP 4:
|
|
1338
|
+
// Ensure original parent directory exists
|
|
1339
|
+
// ----------------------------------------------------------
|
|
1340
|
+
const originalParentDirectory = path.dirname(sourcePath);
|
|
1341
|
+
fs.mkdirSync(originalParentDirectory, {
|
|
1342
|
+
recursive: true,
|
|
1343
|
+
});
|
|
1344
|
+
// ----------------------------------------------------------
|
|
1345
|
+
// STEP 5:
|
|
1346
|
+
// Move directory back
|
|
1347
|
+
// ----------------------------------------------------------
|
|
1348
|
+
fs.renameSync(movedDirectoryPath, sourcePath);
|
|
1349
|
+
// ----------------------------------------------------------
|
|
1350
|
+
// STEP 6:
|
|
1351
|
+
// Return rollback result
|
|
1352
|
+
// ----------------------------------------------------------
|
|
1353
|
+
return {
|
|
1354
|
+
success: true,
|
|
1355
|
+
restoredDirectory: sourcePath,
|
|
1356
|
+
};
|
|
1357
|
+
}
|
|
1358
|
+
/**
|
|
1359
|
+
* Rolls back insertStyles operation.
|
|
1360
|
+
*
|
|
1361
|
+
* Restores CSS file content
|
|
1362
|
+
* back to original state before style insertion.
|
|
1363
|
+
*/
|
|
1364
|
+
// function undoInsertStyles(
|
|
1365
|
+
// operation
|
|
1366
|
+
// ): TaskResponse<any> {
|
|
1367
|
+
// // ----------------------------------------------------------
|
|
1368
|
+
// // STEP 1:
|
|
1369
|
+
// // Extract CSS file path
|
|
1370
|
+
// // ----------------------------------------------------------
|
|
1371
|
+
// const { cssPath } = operation.target;
|
|
1372
|
+
// // ----------------------------------------------------------
|
|
1373
|
+
// // STEP 2:
|
|
1374
|
+
// // Extract original CSS content
|
|
1375
|
+
// // ----------------------------------------------------------
|
|
1376
|
+
// const originalCss = operation.before.cssCode;
|
|
1377
|
+
// // ----------------------------------------------------------
|
|
1378
|
+
// // STEP 3:
|
|
1379
|
+
// // Ensure rollback snapshot exists
|
|
1380
|
+
// // ----------------------------------------------------------
|
|
1381
|
+
// if (typeof originalCss !== "string") {
|
|
1382
|
+
// throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND,"Missing original CSS code for rollback.");
|
|
1383
|
+
// }
|
|
1384
|
+
// // ----------------------------------------------------------
|
|
1385
|
+
// // STEP 4:
|
|
1386
|
+
// // Restore original CSS content
|
|
1387
|
+
// // ----------------------------------------------------------
|
|
1388
|
+
// fs.writeFileSync(cssPath, originalCss, "utf8");
|
|
1389
|
+
// // ----------------------------------------------------------
|
|
1390
|
+
// // STEP 5:
|
|
1391
|
+
// // Return rollback result
|
|
1392
|
+
// // ----------------------------------------------------------
|
|
1393
|
+
// return {
|
|
1394
|
+
// success: true,
|
|
1395
|
+
// restoredCssFile: cssPath,
|
|
1396
|
+
// };
|
|
1397
|
+
// }
|
|
1398
|
+
/**
|
|
1399
|
+
* Rolls back updateStyles operation.
|
|
1400
|
+
*
|
|
1401
|
+
* Restores CSS file content
|
|
1402
|
+
* back to original state before style update.
|
|
1403
|
+
*/
|
|
1404
|
+
function undoUpdateStyles(operation, appContext) {
|
|
1405
|
+
// ----------------------------------------------------------
|
|
1406
|
+
// STEP 1:
|
|
1407
|
+
// Extract CSS file path
|
|
1408
|
+
// ----------------------------------------------------------
|
|
1409
|
+
const { cssPath } = operation.target;
|
|
1410
|
+
// ----------------------------------------------------------
|
|
1411
|
+
// STEP 2:
|
|
1412
|
+
// Extract original CSS content
|
|
1413
|
+
// ----------------------------------------------------------
|
|
1414
|
+
const originalCss = operation.before.cssCode;
|
|
1415
|
+
// ----------------------------------------------------------
|
|
1416
|
+
// STEP 3:
|
|
1417
|
+
// Ensure rollback snapshot exists
|
|
1418
|
+
// ----------------------------------------------------------
|
|
1419
|
+
if (typeof originalCss !== "string") {
|
|
1420
|
+
throw new LoomaError(ERROR_CODES.CSS_NOT_FOUND, "Missing original CSS code for rollback.");
|
|
1421
|
+
}
|
|
1422
|
+
// ----------------------------------------------------------
|
|
1423
|
+
// STEP 4:
|
|
1424
|
+
// Restore original CSS content
|
|
1425
|
+
// ----------------------------------------------------------
|
|
1426
|
+
fs.writeFileSync(cssPath, originalCss, "utf8");
|
|
1427
|
+
// ----------------------------------------------------------
|
|
1428
|
+
// STEP 5:
|
|
1429
|
+
// Return rollback result
|
|
1430
|
+
// ----------------------------------------------------------
|
|
1431
|
+
return {
|
|
1432
|
+
success: true,
|
|
1433
|
+
restoredCssFile: cssPath,
|
|
1434
|
+
};
|
|
1435
|
+
}
|
|
1436
|
+
/**
|
|
1437
|
+
* Rolls back removeStyles operation.
|
|
1438
|
+
*
|
|
1439
|
+
* Restores CSS file content
|
|
1440
|
+
* back to original state before style removal.
|
|
1441
|
+
*/
|
|
1442
|
+
function undoRemoveStyles(operation, appContext) {
|
|
1443
|
+
// ----------------------------------------------------------
|
|
1444
|
+
// STEP 1:
|
|
1445
|
+
// Extract CSS file path
|
|
1446
|
+
// ----------------------------------------------------------
|
|
1447
|
+
const { cssPath } = operation.target;
|
|
1448
|
+
// ----------------------------------------------------------
|
|
1449
|
+
// STEP 2:
|
|
1450
|
+
// Extract original CSS content
|
|
1451
|
+
// ----------------------------------------------------------
|
|
1452
|
+
const originalCss = operation.before.cssCode;
|
|
1453
|
+
// ----------------------------------------------------------
|
|
1454
|
+
// STEP 3:
|
|
1455
|
+
// Ensure rollback snapshot exists
|
|
1456
|
+
// ----------------------------------------------------------
|
|
1457
|
+
if (typeof originalCss !== "string") {
|
|
1458
|
+
throw new LoomaError(ERROR_CODES.CSS_NOT_FOUND, "Missing original CSS code for rollback.");
|
|
1459
|
+
}
|
|
1460
|
+
// ----------------------------------------------------------
|
|
1461
|
+
// STEP 4:
|
|
1462
|
+
// Restore original CSS content
|
|
1463
|
+
// ----------------------------------------------------------
|
|
1464
|
+
fs.writeFileSync(cssPath, originalCss, "utf8");
|
|
1465
|
+
// ----------------------------------------------------------
|
|
1466
|
+
// STEP 5:
|
|
1467
|
+
// Return rollback result
|
|
1468
|
+
// ----------------------------------------------------------
|
|
1469
|
+
return {
|
|
1470
|
+
success: true,
|
|
1471
|
+
restoredCssFile: cssPath,
|
|
1472
|
+
};
|
|
1473
|
+
}
|
|
1474
|
+
/**
|
|
1475
|
+
* Restores CSS and JSX files
|
|
1476
|
+
* to state before renameCssClass.
|
|
1477
|
+
*/
|
|
1478
|
+
function undoRenameCssClass(operation, appContext) {
|
|
1479
|
+
// ----------------------------------------------------------
|
|
1480
|
+
// STEP 1:
|
|
1481
|
+
// Extract target files
|
|
1482
|
+
// ----------------------------------------------------------
|
|
1483
|
+
const { cssPath, componentJSXPath } = operation.target;
|
|
1484
|
+
// ----------------------------------------------------------
|
|
1485
|
+
// STEP 2:
|
|
1486
|
+
// Extract original contents
|
|
1487
|
+
// ----------------------------------------------------------
|
|
1488
|
+
const { cssCode, jsxCode } = operation.before;
|
|
1489
|
+
// ----------------------------------------------------------
|
|
1490
|
+
// STEP 3:
|
|
1491
|
+
// Validate snapshots
|
|
1492
|
+
// ----------------------------------------------------------
|
|
1493
|
+
if (typeof cssCode !== "string") {
|
|
1494
|
+
throw new LoomaError(ERROR_CODES.CSS_NOT_FOUND, "Missing cssCode in operation.before");
|
|
1495
|
+
}
|
|
1496
|
+
if (typeof jsxCode !== "string") {
|
|
1497
|
+
throw new LoomaError(ERROR_CODES.JSX_NOT_FOUND, "Missing jsxCode in operation.before");
|
|
1498
|
+
}
|
|
1499
|
+
// ----------------------------------------------------------
|
|
1500
|
+
// STEP 4:
|
|
1501
|
+
// Restore CSS file
|
|
1502
|
+
// ----------------------------------------------------------
|
|
1503
|
+
fs.writeFileSync(cssPath, cssCode, "utf8");
|
|
1504
|
+
// ----------------------------------------------------------
|
|
1505
|
+
// STEP 5:
|
|
1506
|
+
// Restore JSX file
|
|
1507
|
+
// ----------------------------------------------------------
|
|
1508
|
+
fs.writeFileSync(componentJSXPath, jsxCode, "utf8");
|
|
1509
|
+
// ----------------------------------------------------------
|
|
1510
|
+
// STEP 6:
|
|
1511
|
+
// Return result
|
|
1512
|
+
// ----------------------------------------------------------
|
|
1513
|
+
return {
|
|
1514
|
+
success: true,
|
|
1515
|
+
cssPath,
|
|
1516
|
+
componentJSXPath,
|
|
1517
|
+
};
|
|
1518
|
+
}
|
|
1519
|
+
// function undoRemoveImport(
|
|
1520
|
+
// operation
|
|
1521
|
+
// ): TaskResponse<any> {
|
|
1522
|
+
// return {
|
|
1523
|
+
// success: true,
|
|
1524
|
+
// updatedCode: operation.before.code,
|
|
1525
|
+
// };
|
|
1526
|
+
// }
|
|
1527
|
+
// function undoInsertVariable(
|
|
1528
|
+
// operation
|
|
1529
|
+
// ): TaskResponse<any> {
|
|
1530
|
+
// return {
|
|
1531
|
+
// success: true,
|
|
1532
|
+
// updatedCode: operation.before.code,
|
|
1533
|
+
// };
|
|
1534
|
+
// }
|
|
1535
|
+
// function undoUpdateVariable(
|
|
1536
|
+
// operation
|
|
1537
|
+
// ): TaskResponse<any> {
|
|
1538
|
+
// return {
|
|
1539
|
+
// success: true,
|
|
1540
|
+
// updatedCode: operation.before.code,
|
|
1541
|
+
// };
|
|
1542
|
+
// }
|
|
1543
|
+
// function undoDeleteVariable(
|
|
1544
|
+
// operation
|
|
1545
|
+
// ): TaskResponse<any> {
|
|
1546
|
+
// return {
|
|
1547
|
+
// success: true,
|
|
1548
|
+
// updatedCode: operation.before.code,
|
|
1549
|
+
// };
|
|
1550
|
+
// }
|
|
1551
|
+
/**
|
|
1552
|
+
* Restores a directory from .looma-trash to its original location.
|
|
1553
|
+
*
|
|
1554
|
+
* Params:
|
|
1555
|
+
* - trashPath:
|
|
1556
|
+
* Relative path of the directory inside .looma-trash.
|
|
1557
|
+
*
|
|
1558
|
+
* - originalPath:
|
|
1559
|
+
* Original relative path of the directory before deletion.
|
|
1560
|
+
*
|
|
1561
|
+
* Returns:
|
|
1562
|
+
* {
|
|
1563
|
+
* success: boolean,
|
|
1564
|
+
* trashPath: string,
|
|
1565
|
+
* originalPath: string
|
|
1566
|
+
* }
|
|
1567
|
+
*/
|
|
1568
|
+
// function restoreDirectory({ trashPath, originalPath }) {
|
|
1569
|
+
// // ----------------------------------------------------------
|
|
1570
|
+
// // STEP 1:
|
|
1571
|
+
// // Convert relative paths to absolute paths.
|
|
1572
|
+
// // ----------------------------------------------------------
|
|
1573
|
+
// const absoluteTrashPath = path.resolve(process.cwd(), trashPath);
|
|
1574
|
+
// const absoluteOriginalPath = path.resolve(process.cwd(), originalPath);
|
|
1575
|
+
// // ----------------------------------------------------------
|
|
1576
|
+
// // STEP 2:
|
|
1577
|
+
// // Verify that the directory exists in trash.
|
|
1578
|
+
// // ----------------------------------------------------------
|
|
1579
|
+
// if (!fs.existsSync(absoluteTrashPath)) {
|
|
1580
|
+
// return {
|
|
1581
|
+
// success: false,
|
|
1582
|
+
// message: "Directory does not exist in trash",
|
|
1583
|
+
// trashPath,
|
|
1584
|
+
// originalPath,
|
|
1585
|
+
// };
|
|
1586
|
+
// }
|
|
1587
|
+
// // ----------------------------------------------------------
|
|
1588
|
+
// // STEP 3:
|
|
1589
|
+
// // Ensure parent directory exists.
|
|
1590
|
+
// //
|
|
1591
|
+
// // Example:
|
|
1592
|
+
// //
|
|
1593
|
+
// // originalPath:
|
|
1594
|
+
// // src/components/Home
|
|
1595
|
+
// //
|
|
1596
|
+
// // parent directory:
|
|
1597
|
+
// // src/components
|
|
1598
|
+
// // ----------------------------------------------------------
|
|
1599
|
+
// const parentDirectory = path.dirname(absoluteOriginalPath);
|
|
1600
|
+
// fs.mkdirSync(parentDirectory, {
|
|
1601
|
+
// recursive: true,
|
|
1602
|
+
// });
|
|
1603
|
+
// // ----------------------------------------------------------
|
|
1604
|
+
// // STEP 4:
|
|
1605
|
+
// // Move the directory back to its original location.
|
|
1606
|
+
// // This restores both location and name.
|
|
1607
|
+
// // ----------------------------------------------------------
|
|
1608
|
+
// fs.renameSync(absoluteTrashPath, absoluteOriginalPath);
|
|
1609
|
+
// // ----------------------------------------------------------
|
|
1610
|
+
// // STEP 5:
|
|
1611
|
+
// // Return success.
|
|
1612
|
+
// // ----------------------------------------------------------
|
|
1613
|
+
// return {
|
|
1614
|
+
// success: true,
|
|
1615
|
+
// trashPath,
|
|
1616
|
+
// originalPath,
|
|
1617
|
+
// };
|
|
1618
|
+
// }
|
|
1619
|
+
/**
|
|
1620
|
+
* Restores a file from .looma-trash to its original location.
|
|
1621
|
+
*
|
|
1622
|
+
* Params:
|
|
1623
|
+
* - trashPath:
|
|
1624
|
+
* Relative path of the file inside .looma-trash.
|
|
1625
|
+
*
|
|
1626
|
+
* - originalPath:
|
|
1627
|
+
* Original relative path of the file before deletion.
|
|
1628
|
+
*
|
|
1629
|
+
* Returns:
|
|
1630
|
+
* {
|
|
1631
|
+
* success: boolean,
|
|
1632
|
+
* trashPath: string,
|
|
1633
|
+
* originalPath: string
|
|
1634
|
+
* }
|
|
1635
|
+
*/
|
|
1636
|
+
// function restoreFile({ trashPath, originalPath }) {
|
|
1637
|
+
// // ----------------------------------------------------------
|
|
1638
|
+
// // STEP 1:
|
|
1639
|
+
// // Convert relative paths to absolute paths.
|
|
1640
|
+
// // ----------------------------------------------------------
|
|
1641
|
+
// const absoluteTrashPath = path.resolve(process.cwd(), trashPath);
|
|
1642
|
+
// const absoluteOriginalPath = path.resolve(process.cwd(), originalPath);
|
|
1643
|
+
// // ----------------------------------------------------------
|
|
1644
|
+
// // STEP 2:
|
|
1645
|
+
// // Verify that the file exists in trash.
|
|
1646
|
+
// // ----------------------------------------------------------
|
|
1647
|
+
// if (!fs.existsSync(absoluteTrashPath)) {
|
|
1648
|
+
// return {
|
|
1649
|
+
// success: false,
|
|
1650
|
+
// message: "File does not exist in trash",
|
|
1651
|
+
// trashPath,
|
|
1652
|
+
// originalPath,
|
|
1653
|
+
// };
|
|
1654
|
+
// }
|
|
1655
|
+
// // ----------------------------------------------------------
|
|
1656
|
+
// // STEP 3:
|
|
1657
|
+
// // Ensure parent directory exists.
|
|
1658
|
+
// //
|
|
1659
|
+
// // Example:
|
|
1660
|
+
// //
|
|
1661
|
+
// // originalPath:
|
|
1662
|
+
// // src/App/Header.tsx
|
|
1663
|
+
// //
|
|
1664
|
+
// // parent directory:
|
|
1665
|
+
// // src/App
|
|
1666
|
+
// // ----------------------------------------------------------
|
|
1667
|
+
// const parentDirectory = path.dirname(absoluteOriginalPath);
|
|
1668
|
+
// fs.mkdirSync(parentDirectory, {
|
|
1669
|
+
// recursive: true,
|
|
1670
|
+
// });
|
|
1671
|
+
// // ----------------------------------------------------------
|
|
1672
|
+
// // STEP 4:
|
|
1673
|
+
// // Restore the file to its original path.
|
|
1674
|
+
// // ----------------------------------------------------------
|
|
1675
|
+
// fs.renameSync(absoluteTrashPath, absoluteOriginalPath);
|
|
1676
|
+
// // ----------------------------------------------------------
|
|
1677
|
+
// // STEP 5:
|
|
1678
|
+
// // Return success.
|
|
1679
|
+
// // ----------------------------------------------------------
|
|
1680
|
+
// return {
|
|
1681
|
+
// success: true,
|
|
1682
|
+
// trashPath,
|
|
1683
|
+
// originalPath,
|
|
1684
|
+
// };
|
|
1685
|
+
// }
|
|
1686
|
+
function undoUpdateComponent(operation, appContext) {
|
|
1687
|
+
const { componentPath } = operation.target;
|
|
1688
|
+
const { componentCode } = operation.before;
|
|
1689
|
+
fs.writeFileSync(componentPath, componentCode, "utf8");
|
|
1690
|
+
return {
|
|
1691
|
+
success: true,
|
|
1692
|
+
componentPath,
|
|
1693
|
+
};
|
|
1694
|
+
}
|
|
1695
|
+
const undoHandlers = {
|
|
1696
|
+
// removeImport: (operation, appContext) => {
|
|
1697
|
+
// undoRemoveImport(operation, appContext);
|
|
1698
|
+
// },
|
|
1699
|
+
moveComponent: (operation, appContext) => {
|
|
1700
|
+
undoMoveComponent(operation, appContext);
|
|
1701
|
+
},
|
|
1702
|
+
renameComponent: (operation, appContext) => {
|
|
1703
|
+
undoRenameComponent(operation, appContext);
|
|
1704
|
+
},
|
|
1705
|
+
createComponent: (operation, appContext) => {
|
|
1706
|
+
undoCreateComponent(operation, appContext);
|
|
1707
|
+
},
|
|
1708
|
+
deleteComponent: (operation, appContext) => {
|
|
1709
|
+
undoDeleteComponent(operation, appContext);
|
|
1710
|
+
},
|
|
1711
|
+
// insertVariable: (operation, appContext) => {
|
|
1712
|
+
// undoInsertVariable(operation, appContext);
|
|
1713
|
+
// },
|
|
1714
|
+
// updateVariable: (operation, appContext) => {
|
|
1715
|
+
// undoUpdateVariable(operation, appContext);
|
|
1716
|
+
// },
|
|
1717
|
+
// deleteVariable: (operation, appContext) => {
|
|
1718
|
+
// undoDeleteVariable(operation, appContext);
|
|
1719
|
+
// },
|
|
1720
|
+
// insertCode: (operation, appContext) => {
|
|
1721
|
+
// undoInsertCode(operation, appContext);
|
|
1722
|
+
// },
|
|
1723
|
+
extractComponent: (operation, appContext) => {
|
|
1724
|
+
undoExtractComponent(operation, appContext);
|
|
1725
|
+
},
|
|
1726
|
+
// insertJSX: (operation, appContext) => {
|
|
1727
|
+
// undoInsertJSX(operation, appContext);
|
|
1728
|
+
// },
|
|
1729
|
+
// replaceJSX: (operation, appContext) => {
|
|
1730
|
+
// undoReplaceJSX(operation, appContext);
|
|
1731
|
+
// },
|
|
1732
|
+
// removeJSX: (operation, appContext) => {
|
|
1733
|
+
// undoRemoveJSX(operation, appContext);
|
|
1734
|
+
// },
|
|
1735
|
+
// moveJSX: (operation, appContext) => {
|
|
1736
|
+
// undoMoveJSX(operation, appContext);
|
|
1737
|
+
// },
|
|
1738
|
+
// wrapJSX: (operation, appContext) => {
|
|
1739
|
+
// undoWrapJSX(operation, appContext);
|
|
1740
|
+
// },
|
|
1741
|
+
updateComponent: (operation, appContext) => {
|
|
1742
|
+
undoUpdateComponent(operation, appContext);
|
|
1743
|
+
},
|
|
1744
|
+
// normalizeComponent: (operation, appContext) => {
|
|
1745
|
+
// undoNormalizeComponent(operation, appContext);
|
|
1746
|
+
// },
|
|
1747
|
+
createFile: (operation, appContext) => {
|
|
1748
|
+
undoCreateFile(operation, appContext);
|
|
1749
|
+
},
|
|
1750
|
+
deleteFile: (operation, appContext) => {
|
|
1751
|
+
undoDeleteFile(operation, appContext);
|
|
1752
|
+
},
|
|
1753
|
+
renameFile: (operation, appContext) => {
|
|
1754
|
+
undoRenameFile(operation, appContext);
|
|
1755
|
+
},
|
|
1756
|
+
moveFile: (operation, appContext) => {
|
|
1757
|
+
undoMoveFile(operation, appContext);
|
|
1758
|
+
},
|
|
1759
|
+
createDirectory: (operation, appContext) => {
|
|
1760
|
+
undoCreateDirectory(operation, appContext);
|
|
1761
|
+
},
|
|
1762
|
+
deleteDirectory: (operation, appContext) => {
|
|
1763
|
+
undoDeleteDirectory(operation, appContext);
|
|
1764
|
+
},
|
|
1765
|
+
renameDirectory: (operation, appContext) => {
|
|
1766
|
+
undoRenameDirectory(operation, appContext);
|
|
1767
|
+
},
|
|
1768
|
+
moveDirectory: (operation, appContext) => {
|
|
1769
|
+
undoMoveDirectory(operation, appContext);
|
|
1770
|
+
},
|
|
1771
|
+
// insertStyles: (operation, appContext) => {
|
|
1772
|
+
// undoInsertStyles(operation, appContext);
|
|
1773
|
+
// },
|
|
1774
|
+
updateStyles: (operation, appContext) => {
|
|
1775
|
+
undoUpdateStyles(operation, appContext);
|
|
1776
|
+
},
|
|
1777
|
+
removeStyles: (operation, appContext) => {
|
|
1778
|
+
undoRemoveStyles(operation, appContext);
|
|
1779
|
+
},
|
|
1780
|
+
renameCssClass: (operation, appContext) => {
|
|
1781
|
+
undoRenameCssClass(operation, appContext);
|
|
1782
|
+
},
|
|
1783
|
+
// syncComponentStyles: (operation, appContext) => {
|
|
1784
|
+
// undoSyncComponentStyles(operation, appContext);
|
|
1785
|
+
// },
|
|
1786
|
+
// resolveCssClassConflicts: (operation, appContext) => {
|
|
1787
|
+
// undoResolveCssClassConflicts(operation, appContext);
|
|
1788
|
+
// },
|
|
1789
|
+
// resolveStyleDependencies: (operation, appContext) => {
|
|
1790
|
+
// undoResolveStyleDependencies(operation, appContext);
|
|
1791
|
+
// },
|
|
1792
|
+
// optimizeImports: (operation, appContext) => {
|
|
1793
|
+
// undoOptimizeImports(operation, appContext);
|
|
1794
|
+
// },
|
|
1795
|
+
};
|
|
1796
|
+
function redoUpdateComponent(operation, appContext) {
|
|
1797
|
+
const { componentPath } = operation.target;
|
|
1798
|
+
const { componentCode } = operation.after;
|
|
1799
|
+
fs.writeFileSync(componentPath, componentCode, "utf8");
|
|
1800
|
+
return {
|
|
1801
|
+
success: true,
|
|
1802
|
+
componentPath,
|
|
1803
|
+
};
|
|
1804
|
+
}
|
|
1805
|
+
function redoMoveComponent(operation, appContext) {
|
|
1806
|
+
// ----------------------------------------------------------
|
|
1807
|
+
// STEP 1:
|
|
1808
|
+
// Extract paths from operation
|
|
1809
|
+
// ----------------------------------------------------------
|
|
1810
|
+
const { sourcePath, destinationPath } = operation.target;
|
|
1811
|
+
// ----------------------------------------------------------
|
|
1812
|
+
// STEP 2:
|
|
1813
|
+
// Resolve component name
|
|
1814
|
+
// ----------------------------------------------------------
|
|
1815
|
+
//
|
|
1816
|
+
// Example:
|
|
1817
|
+
//
|
|
1818
|
+
// ../../src/components/Header
|
|
1819
|
+
//
|
|
1820
|
+
// -> Header
|
|
1821
|
+
//
|
|
1822
|
+
// ----------------------------------------------------------
|
|
1823
|
+
const componentName = path.basename(sourcePath);
|
|
1824
|
+
// ----------------------------------------------------------
|
|
1825
|
+
// STEP 3:
|
|
1826
|
+
// Ensure component exists at original location
|
|
1827
|
+
// ----------------------------------------------------------
|
|
1828
|
+
if (!fs.existsSync(sourcePath)) {
|
|
1829
|
+
throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND, `Component not found: ${sourcePath}`);
|
|
1830
|
+
}
|
|
1831
|
+
// ----------------------------------------------------------
|
|
1832
|
+
// STEP 4:
|
|
1833
|
+
// Ensure destination directory exists
|
|
1834
|
+
// ----------------------------------------------------------
|
|
1835
|
+
fs.mkdirSync(destinationPath, {
|
|
1836
|
+
recursive: true,
|
|
1837
|
+
});
|
|
1838
|
+
// ----------------------------------------------------------
|
|
1839
|
+
// STEP 5:
|
|
1840
|
+
// Build final moved location
|
|
1841
|
+
// ----------------------------------------------------------
|
|
1842
|
+
//
|
|
1843
|
+
// Example:
|
|
1844
|
+
//
|
|
1845
|
+
// destinationPath/Header
|
|
1846
|
+
//
|
|
1847
|
+
// ----------------------------------------------------------
|
|
1848
|
+
const movedComponentPath = path.join(destinationPath, componentName);
|
|
1849
|
+
// ----------------------------------------------------------
|
|
1850
|
+
// STEP 6:
|
|
1851
|
+
// Move component again
|
|
1852
|
+
// ----------------------------------------------------------
|
|
1853
|
+
fs.renameSync(sourcePath, movedComponentPath);
|
|
1854
|
+
// ----------------------------------------------------------
|
|
1855
|
+
// STEP 7:
|
|
1856
|
+
// Return redo result
|
|
1857
|
+
// ----------------------------------------------------------
|
|
1858
|
+
return {
|
|
1859
|
+
success: true,
|
|
1860
|
+
movedPath: movedComponentPath,
|
|
1861
|
+
};
|
|
1862
|
+
}
|
|
1863
|
+
function redoRenameComponent(operation, appContext) {
|
|
1864
|
+
// ----------------------------------------------------------
|
|
1865
|
+
// STEP 1:
|
|
1866
|
+
// Extract information from operation log.
|
|
1867
|
+
// ----------------------------------------------------------
|
|
1868
|
+
const { newComponentPath: componentPath } = operation.target;
|
|
1869
|
+
const { componentName: oldComponentName } = operation.before;
|
|
1870
|
+
const { componentName: newComponentName } = operation.after;
|
|
1871
|
+
// ----------------------------------------------------------
|
|
1872
|
+
// STEP 2:
|
|
1873
|
+
// Re-apply the original rename.
|
|
1874
|
+
// ----------------------------------------------------------
|
|
1875
|
+
const result = mutations.renameComponent({
|
|
1876
|
+
componentPath,
|
|
1877
|
+
newComponentName,
|
|
1878
|
+
// Preserve the same behavior used
|
|
1879
|
+
// during the original rename.
|
|
1880
|
+
updateComponentCode: true,
|
|
1881
|
+
}, appContext);
|
|
1882
|
+
// ----------------------------------------------------------
|
|
1883
|
+
// STEP 3:
|
|
1884
|
+
// Validate redo.
|
|
1885
|
+
// ----------------------------------------------------------
|
|
1886
|
+
if (!result?.success) {
|
|
1887
|
+
throw new LoomaError(ERROR_CODES.REDO_FAILED, `Failed to redo renameComponent: ${oldComponentName} -> ${newComponentName}`);
|
|
1888
|
+
}
|
|
1889
|
+
// ----------------------------------------------------------
|
|
1890
|
+
// STEP 4:
|
|
1891
|
+
// Return result.
|
|
1892
|
+
// ----------------------------------------------------------
|
|
1893
|
+
return {
|
|
1894
|
+
success: true,
|
|
1895
|
+
componentPath,
|
|
1896
|
+
};
|
|
1897
|
+
}
|
|
1898
|
+
function redoCreateComponent(operation, appContext) {
|
|
1899
|
+
// ----------------------------------------------------------
|
|
1900
|
+
// STEP 1:
|
|
1901
|
+
// Extract information from operation log
|
|
1902
|
+
// ----------------------------------------------------------
|
|
1903
|
+
const { componentName, componentCode, parentDirectory } = operation.after;
|
|
1904
|
+
// ----------------------------------------------------------
|
|
1905
|
+
// STEP 2:
|
|
1906
|
+
// Recreate component
|
|
1907
|
+
// ----------------------------------------------------------
|
|
1908
|
+
const result = mutations.createComponent({
|
|
1909
|
+
componentName,
|
|
1910
|
+
componentCode,
|
|
1911
|
+
parentDirectory,
|
|
1912
|
+
}, appContext);
|
|
1913
|
+
// ----------------------------------------------------------
|
|
1914
|
+
// STEP 3:
|
|
1915
|
+
// Validate redo
|
|
1916
|
+
// ----------------------------------------------------------
|
|
1917
|
+
if (!result?.success) {
|
|
1918
|
+
throw new LoomaError(ERROR_CODES.REDO_FAILED, `Failed to redo createComponent: ${componentName}`);
|
|
1919
|
+
}
|
|
1920
|
+
// ----------------------------------------------------------
|
|
1921
|
+
// STEP 4:
|
|
1922
|
+
// Return result
|
|
1923
|
+
// ----------------------------------------------------------
|
|
1924
|
+
return {
|
|
1925
|
+
success: true,
|
|
1926
|
+
componentDirectoryPath: result.componentDirectoryPath,
|
|
1927
|
+
};
|
|
1928
|
+
}
|
|
1929
|
+
function redoDeleteComponent(operation, appContext) {
|
|
1930
|
+
// ----------------------------------------------------------
|
|
1931
|
+
// STEP 1:
|
|
1932
|
+
// Resolve original component path.
|
|
1933
|
+
//
|
|
1934
|
+
// Example:
|
|
1935
|
+
//
|
|
1936
|
+
// src/components/Home
|
|
1937
|
+
//
|
|
1938
|
+
// ----------------------------------------------------------
|
|
1939
|
+
const sourcePath = path.resolve(appContext.project.root, operation.target.componentDirectoryPath);
|
|
1940
|
+
// ----------------------------------------------------------
|
|
1941
|
+
// STEP 2:
|
|
1942
|
+
// Resolve trash location.
|
|
1943
|
+
//
|
|
1944
|
+
// Example:
|
|
1945
|
+
//
|
|
1946
|
+
// .looma-trash/1780467601246_Home
|
|
1947
|
+
//
|
|
1948
|
+
// ----------------------------------------------------------
|
|
1949
|
+
const destinationPath = path.resolve(appContext.project.root, operation.after.trashPath);
|
|
1950
|
+
// ----------------------------------------------------------
|
|
1951
|
+
// STEP 3:
|
|
1952
|
+
// Ensure trash parent directory exists.
|
|
1953
|
+
// ----------------------------------------------------------
|
|
1954
|
+
const trashParentDirectory = path.dirname(destinationPath);
|
|
1955
|
+
fs.mkdirSync(trashParentDirectory, {
|
|
1956
|
+
recursive: true,
|
|
1957
|
+
});
|
|
1958
|
+
// ----------------------------------------------------------
|
|
1959
|
+
// STEP 4:
|
|
1960
|
+
// Ensure component still exists.
|
|
1961
|
+
// ----------------------------------------------------------
|
|
1962
|
+
if (!fs.existsSync(sourcePath)) {
|
|
1963
|
+
throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND, `Component not found: ${sourcePath}`);
|
|
1964
|
+
}
|
|
1965
|
+
// ----------------------------------------------------------
|
|
1966
|
+
// STEP 5:
|
|
1967
|
+
// Move component back to trash.
|
|
1968
|
+
// ----------------------------------------------------------
|
|
1969
|
+
fs.renameSync(sourcePath, destinationPath);
|
|
1970
|
+
// ----------------------------------------------------------
|
|
1971
|
+
// STEP 6:
|
|
1972
|
+
// Return redo result.
|
|
1973
|
+
// ----------------------------------------------------------
|
|
1974
|
+
return {
|
|
1975
|
+
success: true,
|
|
1976
|
+
sourcePath,
|
|
1977
|
+
destinationPath,
|
|
1978
|
+
};
|
|
1979
|
+
}
|
|
1980
|
+
// function redoInsertVariable(operation, appContext) {}
|
|
1981
|
+
// function redoUpdateVariable(operation, appContext) {}
|
|
1982
|
+
// function redoDeleteVariable(operation, appContext) {}
|
|
1983
|
+
// function redoInsertCode(operation, appContext) {}
|
|
1984
|
+
function redoExtractComponent(operation, appContext) { }
|
|
1985
|
+
// function redoInsertJSX(operation, appContext) {}
|
|
1986
|
+
// function redoReplaceJSX(operation, appContext) {}
|
|
1987
|
+
// function redoRemoveJSX(operation, appContext) {}
|
|
1988
|
+
// function redoMoveJSX(operation, appContext) {}
|
|
1989
|
+
// function redoWrapJSX(operation, appContext) {}
|
|
1990
|
+
function redoCreateFile(operation, appContext) {
|
|
1991
|
+
// ----------------------------------------------------------
|
|
1992
|
+
// STEP 1:
|
|
1993
|
+
// Extract information from operation log
|
|
1994
|
+
// ----------------------------------------------------------
|
|
1995
|
+
const { filePath } = operation.target;
|
|
1996
|
+
const { fileContent } = operation.after;
|
|
1997
|
+
// ----------------------------------------------------------
|
|
1998
|
+
// STEP 2:
|
|
1999
|
+
// Ensure parent directory exists
|
|
2000
|
+
// ----------------------------------------------------------
|
|
2001
|
+
const parentDirectory = path.dirname(filePath);
|
|
2002
|
+
fs.mkdirSync(parentDirectory, {
|
|
2003
|
+
recursive: true,
|
|
2004
|
+
});
|
|
2005
|
+
// ----------------------------------------------------------
|
|
2006
|
+
// STEP 3:
|
|
2007
|
+
// Ensure file does not already exist
|
|
2008
|
+
// ----------------------------------------------------------
|
|
2009
|
+
if (fs.existsSync(filePath)) {
|
|
2010
|
+
throw new LoomaError(ERROR_CODES.FILE_ALREADY_EXISTS, `File already exists: ${filePath}`);
|
|
2011
|
+
}
|
|
2012
|
+
// ----------------------------------------------------------
|
|
2013
|
+
// STEP 4:
|
|
2014
|
+
// Recreate file
|
|
2015
|
+
// ----------------------------------------------------------
|
|
2016
|
+
fs.writeFileSync(filePath, fileContent, "utf8");
|
|
2017
|
+
// ----------------------------------------------------------
|
|
2018
|
+
// STEP 5:
|
|
2019
|
+
// Return redo result
|
|
2020
|
+
// ----------------------------------------------------------
|
|
2021
|
+
return {
|
|
2022
|
+
success: true,
|
|
2023
|
+
createdFile: filePath,
|
|
2024
|
+
};
|
|
2025
|
+
}
|
|
2026
|
+
function redoDeleteFile(operation, appContext) {
|
|
2027
|
+
// ----------------------------------------------------------
|
|
2028
|
+
// STEP 1:
|
|
2029
|
+
// Extract file paths
|
|
2030
|
+
// ----------------------------------------------------------
|
|
2031
|
+
const { originalPath, trashPath } = operation.target;
|
|
2032
|
+
// ----------------------------------------------------------
|
|
2033
|
+
// STEP 2:
|
|
2034
|
+
// Ensure original file exists
|
|
2035
|
+
// ----------------------------------------------------------
|
|
2036
|
+
if (!fs.existsSync(originalPath)) {
|
|
2037
|
+
throw new LoomaError(ERROR_CODES.FILE_NOT_FOUND, `Original file not found: ${originalPath}`);
|
|
2038
|
+
}
|
|
2039
|
+
// ----------------------------------------------------------
|
|
2040
|
+
// STEP 3:
|
|
2041
|
+
// Ensure trash parent directory exists
|
|
2042
|
+
// ----------------------------------------------------------
|
|
2043
|
+
const trashParentDirectory = path.dirname(trashPath);
|
|
2044
|
+
fs.mkdirSync(trashParentDirectory, {
|
|
2045
|
+
recursive: true,
|
|
2046
|
+
});
|
|
2047
|
+
// ----------------------------------------------------------
|
|
2048
|
+
// STEP 4:
|
|
2049
|
+
// Move file back into trash
|
|
2050
|
+
// ----------------------------------------------------------
|
|
2051
|
+
fs.renameSync(originalPath, trashPath);
|
|
2052
|
+
// ----------------------------------------------------------
|
|
2053
|
+
// STEP 5:
|
|
2054
|
+
// Return redo result
|
|
2055
|
+
// ----------------------------------------------------------
|
|
2056
|
+
return {
|
|
2057
|
+
success: true,
|
|
2058
|
+
deletedFile: originalPath,
|
|
2059
|
+
};
|
|
2060
|
+
}
|
|
2061
|
+
function redoRenameFile(operation, appContext) {
|
|
2062
|
+
// ----------------------------------------------------------
|
|
2063
|
+
// STEP 1:
|
|
2064
|
+
// Extract file paths
|
|
2065
|
+
// ----------------------------------------------------------
|
|
2066
|
+
const { oldFilePath, newFilePath } = operation.target;
|
|
2067
|
+
// ----------------------------------------------------------
|
|
2068
|
+
// STEP 2:
|
|
2069
|
+
// Ensure original file exists
|
|
2070
|
+
// ----------------------------------------------------------
|
|
2071
|
+
if (!fs.existsSync(oldFilePath)) {
|
|
2072
|
+
throw new LoomaError(ERROR_CODES.FILE_NOT_FOUND, `Original file not found: ${oldFilePath}`);
|
|
2073
|
+
}
|
|
2074
|
+
// ----------------------------------------------------------
|
|
2075
|
+
// STEP 3:
|
|
2076
|
+
// Ensure new parent directory exists
|
|
2077
|
+
// ----------------------------------------------------------
|
|
2078
|
+
const parentDirectory = path.dirname(newFilePath);
|
|
2079
|
+
fs.mkdirSync(parentDirectory, {
|
|
2080
|
+
recursive: true,
|
|
2081
|
+
});
|
|
2082
|
+
// ----------------------------------------------------------
|
|
2083
|
+
// STEP 4:
|
|
2084
|
+
// Rename file again
|
|
2085
|
+
// ----------------------------------------------------------
|
|
2086
|
+
fs.renameSync(oldFilePath, newFilePath);
|
|
2087
|
+
// ----------------------------------------------------------
|
|
2088
|
+
// STEP 5:
|
|
2089
|
+
// Return redo result
|
|
2090
|
+
// ----------------------------------------------------------
|
|
2091
|
+
return {
|
|
2092
|
+
success: true,
|
|
2093
|
+
renamedFile: newFilePath,
|
|
2094
|
+
};
|
|
2095
|
+
}
|
|
2096
|
+
function redoMoveFile(operation, appContext) {
|
|
2097
|
+
// ----------------------------------------------------------
|
|
2098
|
+
// STEP 1:
|
|
2099
|
+
// Extract file paths
|
|
2100
|
+
// ----------------------------------------------------------
|
|
2101
|
+
const { sourcePath, destinationPath } = operation.target;
|
|
2102
|
+
// ----------------------------------------------------------
|
|
2103
|
+
// STEP 2:
|
|
2104
|
+
// Ensure original file exists
|
|
2105
|
+
// ----------------------------------------------------------
|
|
2106
|
+
if (!fs.existsSync(sourcePath)) {
|
|
2107
|
+
throw new LoomaError(ERROR_CODES.FILE_NOT_FOUND, `Original file not found: ${sourcePath}`);
|
|
2108
|
+
}
|
|
2109
|
+
// ----------------------------------------------------------
|
|
2110
|
+
// STEP 3:
|
|
2111
|
+
// Resolve moved file path
|
|
2112
|
+
// ----------------------------------------------------------
|
|
2113
|
+
//
|
|
2114
|
+
// Example:
|
|
2115
|
+
//
|
|
2116
|
+
// sourcePath:
|
|
2117
|
+
// /src/tasks/helpers/api.js
|
|
2118
|
+
//
|
|
2119
|
+
// destinationPath:
|
|
2120
|
+
// /src/services
|
|
2121
|
+
//
|
|
2122
|
+
// moved file:
|
|
2123
|
+
// /src/services/api.js
|
|
2124
|
+
//
|
|
2125
|
+
// ----------------------------------------------------------
|
|
2126
|
+
const fileName = path.basename(sourcePath);
|
|
2127
|
+
const movedFilePath = path.join(destinationPath, fileName);
|
|
2128
|
+
// ----------------------------------------------------------
|
|
2129
|
+
// STEP 4:
|
|
2130
|
+
// Ensure destination directory exists
|
|
2131
|
+
// ----------------------------------------------------------
|
|
2132
|
+
fs.mkdirSync(destinationPath, {
|
|
2133
|
+
recursive: true,
|
|
2134
|
+
});
|
|
2135
|
+
// ----------------------------------------------------------
|
|
2136
|
+
// STEP 5:
|
|
2137
|
+
// Move file again
|
|
2138
|
+
// ----------------------------------------------------------
|
|
2139
|
+
fs.renameSync(sourcePath, movedFilePath);
|
|
2140
|
+
// ----------------------------------------------------------
|
|
2141
|
+
// STEP 6:
|
|
2142
|
+
// Return redo result
|
|
2143
|
+
// ----------------------------------------------------------
|
|
2144
|
+
return {
|
|
2145
|
+
success: true,
|
|
2146
|
+
movedFile: movedFilePath,
|
|
2147
|
+
};
|
|
2148
|
+
}
|
|
2149
|
+
function redoCreateDirectory(operation, appContext) {
|
|
2150
|
+
// ----------------------------------------------------------
|
|
2151
|
+
// STEP 1:
|
|
2152
|
+
// Extract paths
|
|
2153
|
+
// ----------------------------------------------------------
|
|
2154
|
+
const { directoryPath, trashPath } = operation.target;
|
|
2155
|
+
// ----------------------------------------------------------
|
|
2156
|
+
// STEP 2:
|
|
2157
|
+
// Ensure trashed directory exists
|
|
2158
|
+
// ----------------------------------------------------------
|
|
2159
|
+
if (!fs.existsSync(trashPath)) {
|
|
2160
|
+
throw new LoomaError(ERROR_CODES.DIRECTORY_NOT_FOUND, `Directory not found in trash: ${trashPath}`);
|
|
2161
|
+
}
|
|
2162
|
+
// ----------------------------------------------------------
|
|
2163
|
+
// STEP 3:
|
|
2164
|
+
// Ensure destination parent exists
|
|
2165
|
+
// ----------------------------------------------------------
|
|
2166
|
+
fs.mkdirSync(path.dirname(directoryPath), {
|
|
2167
|
+
recursive: true,
|
|
2168
|
+
});
|
|
2169
|
+
// ----------------------------------------------------------
|
|
2170
|
+
// STEP 4:
|
|
2171
|
+
// Restore directory
|
|
2172
|
+
// ----------------------------------------------------------
|
|
2173
|
+
fs.renameSync(trashPath, directoryPath);
|
|
2174
|
+
// ----------------------------------------------------------
|
|
2175
|
+
// STEP 5:
|
|
2176
|
+
// Return result
|
|
2177
|
+
// ----------------------------------------------------------
|
|
2178
|
+
return {
|
|
2179
|
+
success: true,
|
|
2180
|
+
restoredDirectory: directoryPath,
|
|
2181
|
+
};
|
|
2182
|
+
}
|
|
2183
|
+
function redoDeleteDirectory(operation, appContext) {
|
|
2184
|
+
// ----------------------------------------------------------
|
|
2185
|
+
// STEP 1:
|
|
2186
|
+
// Extract directory paths
|
|
2187
|
+
// ----------------------------------------------------------
|
|
2188
|
+
const { originalPath, trashPath } = operation.target;
|
|
2189
|
+
// ----------------------------------------------------------
|
|
2190
|
+
// STEP 2:
|
|
2191
|
+
// Ensure original directory exists
|
|
2192
|
+
// ----------------------------------------------------------
|
|
2193
|
+
if (!fs.existsSync(originalPath)) {
|
|
2194
|
+
throw new LoomaError(ERROR_CODES.DIRECTORY_NOT_FOUND, `Original directory not found: ${originalPath}`);
|
|
2195
|
+
}
|
|
2196
|
+
// ----------------------------------------------------------
|
|
2197
|
+
// STEP 3:
|
|
2198
|
+
// Ensure trash parent directory exists
|
|
2199
|
+
// ----------------------------------------------------------
|
|
2200
|
+
const trashParentDirectory = path.dirname(trashPath);
|
|
2201
|
+
fs.mkdirSync(trashParentDirectory, {
|
|
2202
|
+
recursive: true,
|
|
2203
|
+
});
|
|
2204
|
+
// ----------------------------------------------------------
|
|
2205
|
+
// STEP 4:
|
|
2206
|
+
// Move directory back to trash
|
|
2207
|
+
// ----------------------------------------------------------
|
|
2208
|
+
fs.renameSync(originalPath, trashPath);
|
|
2209
|
+
// ----------------------------------------------------------
|
|
2210
|
+
// STEP 5:
|
|
2211
|
+
// Return redo result
|
|
2212
|
+
// ----------------------------------------------------------
|
|
2213
|
+
return {
|
|
2214
|
+
success: true,
|
|
2215
|
+
deletedDirectory: originalPath,
|
|
2216
|
+
};
|
|
2217
|
+
}
|
|
2218
|
+
function redoRenameDirectory(operation, appContext) {
|
|
2219
|
+
// ----------------------------------------------------------
|
|
2220
|
+
// STEP 1:
|
|
2221
|
+
// Extract directory paths
|
|
2222
|
+
// ----------------------------------------------------------
|
|
2223
|
+
const { oldDirectoryPath, newDirectoryPath } = operation.target;
|
|
2224
|
+
// ----------------------------------------------------------
|
|
2225
|
+
// STEP 2:
|
|
2226
|
+
// Ensure original directory exists
|
|
2227
|
+
// ----------------------------------------------------------
|
|
2228
|
+
if (!fs.existsSync(oldDirectoryPath)) {
|
|
2229
|
+
throw new LoomaError(ERROR_CODES.DIRECTORY_NOT_FOUND, `Original directory not found: ${oldDirectoryPath}`);
|
|
2230
|
+
}
|
|
2231
|
+
// ----------------------------------------------------------
|
|
2232
|
+
// STEP 3:
|
|
2233
|
+
// Ensure new parent directory exists
|
|
2234
|
+
// ----------------------------------------------------------
|
|
2235
|
+
const parentDirectory = path.dirname(newDirectoryPath);
|
|
2236
|
+
fs.mkdirSync(parentDirectory, {
|
|
2237
|
+
recursive: true,
|
|
2238
|
+
});
|
|
2239
|
+
// ----------------------------------------------------------
|
|
2240
|
+
// STEP 4:
|
|
2241
|
+
// Reapply rename
|
|
2242
|
+
// ----------------------------------------------------------
|
|
2243
|
+
fs.renameSync(oldDirectoryPath, newDirectoryPath);
|
|
2244
|
+
// ----------------------------------------------------------
|
|
2245
|
+
// STEP 5:
|
|
2246
|
+
// Return redo result
|
|
2247
|
+
// ----------------------------------------------------------
|
|
2248
|
+
return {
|
|
2249
|
+
success: true,
|
|
2250
|
+
renamedDirectory: newDirectoryPath,
|
|
2251
|
+
};
|
|
2252
|
+
}
|
|
2253
|
+
function redoMoveDirectory(operation, appContext) {
|
|
2254
|
+
// ----------------------------------------------------------
|
|
2255
|
+
// STEP 1:
|
|
2256
|
+
// Extract paths
|
|
2257
|
+
// ----------------------------------------------------------
|
|
2258
|
+
const { sourcePath, destinationPath } = operation.target;
|
|
2259
|
+
// ----------------------------------------------------------
|
|
2260
|
+
// STEP 2:
|
|
2261
|
+
// Ensure original directory exists
|
|
2262
|
+
// ----------------------------------------------------------
|
|
2263
|
+
if (!fs.existsSync(sourcePath)) {
|
|
2264
|
+
throw new LoomaError(ERROR_CODES.DIRECTORY_NOT_FOUND, `Original directory not found: ${sourcePath}`);
|
|
2265
|
+
}
|
|
2266
|
+
// ----------------------------------------------------------
|
|
2267
|
+
// STEP 3:
|
|
2268
|
+
// Determine moved directory path
|
|
2269
|
+
// ----------------------------------------------------------
|
|
2270
|
+
//
|
|
2271
|
+
// Example:
|
|
2272
|
+
//
|
|
2273
|
+
// sourcePath:
|
|
2274
|
+
// src/components/Header
|
|
2275
|
+
//
|
|
2276
|
+
// destinationPath:
|
|
2277
|
+
// src/layout
|
|
2278
|
+
//
|
|
2279
|
+
// movedDirectoryPath:
|
|
2280
|
+
// src/layout/Header
|
|
2281
|
+
//
|
|
2282
|
+
// ----------------------------------------------------------
|
|
2283
|
+
const directoryName = path.basename(sourcePath);
|
|
2284
|
+
const movedDirectoryPath = path.join(destinationPath, directoryName);
|
|
2285
|
+
// ----------------------------------------------------------
|
|
2286
|
+
// STEP 4:
|
|
2287
|
+
// Ensure destination directory exists
|
|
2288
|
+
// ----------------------------------------------------------
|
|
2289
|
+
fs.mkdirSync(destinationPath, {
|
|
2290
|
+
recursive: true,
|
|
2291
|
+
});
|
|
2292
|
+
// ----------------------------------------------------------
|
|
2293
|
+
// STEP 5:
|
|
2294
|
+
// Move directory again
|
|
2295
|
+
// ----------------------------------------------------------
|
|
2296
|
+
fs.renameSync(sourcePath, movedDirectoryPath);
|
|
2297
|
+
// ----------------------------------------------------------
|
|
2298
|
+
// STEP 6:
|
|
2299
|
+
// Return redo result
|
|
2300
|
+
// ----------------------------------------------------------
|
|
2301
|
+
return {
|
|
2302
|
+
success: true,
|
|
2303
|
+
movedDirectory: movedDirectoryPath,
|
|
2304
|
+
};
|
|
2305
|
+
}
|
|
2306
|
+
function redoUpdateStyles(operation, appContext) {
|
|
2307
|
+
try {
|
|
2308
|
+
// ----------------------------------------------------------
|
|
2309
|
+
// STEP 1:
|
|
2310
|
+
// Extract CSS file path
|
|
2311
|
+
// ----------------------------------------------------------
|
|
2312
|
+
const { cssPath } = operation.target;
|
|
2313
|
+
// ----------------------------------------------------------
|
|
2314
|
+
// STEP 2:
|
|
2315
|
+
// Extract original CSS content
|
|
2316
|
+
// ----------------------------------------------------------
|
|
2317
|
+
const originalCss = operation.before.cssCode;
|
|
2318
|
+
const newCss = operation.after.cssCode;
|
|
2319
|
+
// ----------------------------------------------------------
|
|
2320
|
+
// STEP 3:
|
|
2321
|
+
// Ensure rollback snapshot exists
|
|
2322
|
+
// ----------------------------------------------------------
|
|
2323
|
+
if (typeof newCss !== "string") {
|
|
2324
|
+
throw new LoomaError(ERROR_CODES.CSS_NOT_FOUND, "Missing new CSS code for Redo.");
|
|
2325
|
+
}
|
|
2326
|
+
// ----------------------------------------------------------
|
|
2327
|
+
// STEP 4:
|
|
2328
|
+
// Restore original CSS content
|
|
2329
|
+
// ----------------------------------------------------------
|
|
2330
|
+
fs.writeFileSync(cssPath, newCss, "utf8");
|
|
2331
|
+
// ----------------------------------------------------------
|
|
2332
|
+
// STEP 5:
|
|
2333
|
+
// Return rollback result
|
|
2334
|
+
// ----------------------------------------------------------
|
|
2335
|
+
return {
|
|
2336
|
+
success: true,
|
|
2337
|
+
newCssFile: cssPath,
|
|
2338
|
+
};
|
|
2339
|
+
}
|
|
2340
|
+
catch (error) {
|
|
2341
|
+
return {
|
|
2342
|
+
success: false,
|
|
2343
|
+
error,
|
|
2344
|
+
};
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
function redoRemoveStyles(operation, appContext) {
|
|
2348
|
+
// ----------------------------------------------------------
|
|
2349
|
+
// STEP 1:
|
|
2350
|
+
// Extract CSS file path
|
|
2351
|
+
// ----------------------------------------------------------
|
|
2352
|
+
const { cssPath } = operation.target;
|
|
2353
|
+
// ----------------------------------------------------------
|
|
2354
|
+
// STEP 2:
|
|
2355
|
+
// Extract CSS snapshot after removal
|
|
2356
|
+
// ----------------------------------------------------------
|
|
2357
|
+
const removedCss = operation.after.cssCode;
|
|
2358
|
+
// ----------------------------------------------------------
|
|
2359
|
+
// STEP 3:
|
|
2360
|
+
// Ensure redo snapshot exists
|
|
2361
|
+
// ----------------------------------------------------------
|
|
2362
|
+
if (typeof removedCss !== "string") {
|
|
2363
|
+
throw new LoomaError(ERROR_CODES.CSS_NOT_FOUND, "Missing CSS code for redo.");
|
|
2364
|
+
}
|
|
2365
|
+
// ----------------------------------------------------------
|
|
2366
|
+
// STEP 4:
|
|
2367
|
+
// Reapply removed styles
|
|
2368
|
+
// ----------------------------------------------------------
|
|
2369
|
+
fs.writeFileSync(cssPath, removedCss, "utf8");
|
|
2370
|
+
// ----------------------------------------------------------
|
|
2371
|
+
// STEP 5:
|
|
2372
|
+
// Return redo result
|
|
2373
|
+
// ----------------------------------------------------------
|
|
2374
|
+
return {
|
|
2375
|
+
success: true,
|
|
2376
|
+
updatedCssFile: cssPath,
|
|
2377
|
+
};
|
|
2378
|
+
}
|
|
2379
|
+
function redoRenameCssClass(operation, appContext) {
|
|
2380
|
+
// ----------------------------------------------------------
|
|
2381
|
+
// STEP 1:
|
|
2382
|
+
// Extract target files
|
|
2383
|
+
// ----------------------------------------------------------
|
|
2384
|
+
const { cssPath, componentJSXPath } = operation.target;
|
|
2385
|
+
// ----------------------------------------------------------
|
|
2386
|
+
// STEP 2:
|
|
2387
|
+
// Extract updated contents
|
|
2388
|
+
// ----------------------------------------------------------
|
|
2389
|
+
const { cssCode, jsxCode } = operation.after;
|
|
2390
|
+
// ----------------------------------------------------------
|
|
2391
|
+
// STEP 3:
|
|
2392
|
+
// Validate snapshots
|
|
2393
|
+
// ----------------------------------------------------------
|
|
2394
|
+
if (typeof cssCode !== "string") {
|
|
2395
|
+
throw new LoomaError(ERROR_CODES.CSS_NOT_FOUND, "Missing cssCode in operation.after");
|
|
2396
|
+
}
|
|
2397
|
+
if (typeof jsxCode !== "string") {
|
|
2398
|
+
throw new LoomaError(ERROR_CODES.JSX_NOT_FOUND, "Missing jsxCode in operation.after");
|
|
2399
|
+
}
|
|
2400
|
+
// ----------------------------------------------------------
|
|
2401
|
+
// STEP 4:
|
|
2402
|
+
// Reapply CSS changes
|
|
2403
|
+
// ----------------------------------------------------------
|
|
2404
|
+
fs.writeFileSync(cssPath, cssCode, "utf8");
|
|
2405
|
+
// ----------------------------------------------------------
|
|
2406
|
+
// STEP 5:
|
|
2407
|
+
// Reapply JSX changes
|
|
2408
|
+
// ----------------------------------------------------------
|
|
2409
|
+
fs.writeFileSync(componentJSXPath, jsxCode, "utf8");
|
|
2410
|
+
// ----------------------------------------------------------
|
|
2411
|
+
// STEP 6:
|
|
2412
|
+
// Return result
|
|
2413
|
+
// ----------------------------------------------------------
|
|
2414
|
+
return {
|
|
2415
|
+
success: true,
|
|
2416
|
+
cssPath,
|
|
2417
|
+
componentJSXPath,
|
|
2418
|
+
};
|
|
2419
|
+
}
|
|
2420
|
+
const redoHandlers = {
|
|
2421
|
+
// normalizeComponent: (operation, appContext) => {
|
|
2422
|
+
//redoNormalizeComponent(operation, appContext);
|
|
2423
|
+
// },
|
|
2424
|
+
updateComponent: (operation, appContext) => {
|
|
2425
|
+
redoUpdateComponent(operation, appContext);
|
|
2426
|
+
},
|
|
2427
|
+
moveComponent: (operation, appContext) => {
|
|
2428
|
+
redoMoveComponent(operation, appContext);
|
|
2429
|
+
},
|
|
2430
|
+
renameComponent: (operation, appContext) => {
|
|
2431
|
+
redoRenameComponent(operation, appContext);
|
|
2432
|
+
},
|
|
2433
|
+
createComponent: (operation, appContext) => {
|
|
2434
|
+
redoCreateComponent(operation, appContext);
|
|
2435
|
+
},
|
|
2436
|
+
deleteComponent: (operation, appContext) => {
|
|
2437
|
+
redoDeleteComponent(operation, appContext);
|
|
2438
|
+
},
|
|
2439
|
+
// insertVariable: (operation, appContext) => {
|
|
2440
|
+
// redoInsertVariable(operation, appContext);
|
|
2441
|
+
// },
|
|
2442
|
+
// updateVariable: (operation, appContext) => {
|
|
2443
|
+
// redoUpdateVariable(operation, appContext);
|
|
2444
|
+
// },
|
|
2445
|
+
// deleteVariable: (operation, appContext) => {
|
|
2446
|
+
// redoDeleteVariable(operation, appContext);
|
|
2447
|
+
// },
|
|
2448
|
+
// insertCode: (operation, appContext) => {
|
|
2449
|
+
// redoInsertCode(operation, appContext);
|
|
2450
|
+
// },
|
|
2451
|
+
extractComponent: (operation, appContext) => {
|
|
2452
|
+
redoExtractComponent(operation, appContext);
|
|
2453
|
+
},
|
|
2454
|
+
// insertJSX: (operation, appContext) => {
|
|
2455
|
+
// redoInsertJSX(operation, appContext);
|
|
2456
|
+
// },
|
|
2457
|
+
// replaceJSX: (operation, appContext) => {
|
|
2458
|
+
// redoReplaceJSX(operation, appContext);
|
|
2459
|
+
// },
|
|
2460
|
+
// removeJSX: (operation, appContext) => {
|
|
2461
|
+
// redoRemoveJSX(operation, appContext);
|
|
2462
|
+
// },
|
|
2463
|
+
// moveJSX: (operation, appContext) => {
|
|
2464
|
+
// redoMoveJSX(operation, appContext);
|
|
2465
|
+
// },
|
|
2466
|
+
// wrapJSX: (operation, appContext) => {
|
|
2467
|
+
// redoWrapJSX(operation, appContext);
|
|
2468
|
+
// },
|
|
2469
|
+
createFile: (operation, appContext) => {
|
|
2470
|
+
redoCreateFile(operation, appContext);
|
|
2471
|
+
},
|
|
2472
|
+
deleteFile: (operation, appContext) => {
|
|
2473
|
+
redoDeleteFile(operation, appContext);
|
|
2474
|
+
},
|
|
2475
|
+
renameFile: (operation, appContext) => {
|
|
2476
|
+
redoRenameFile(operation, appContext);
|
|
2477
|
+
},
|
|
2478
|
+
moveFile: (operation, appContext) => {
|
|
2479
|
+
redoMoveFile(operation, appContext);
|
|
2480
|
+
},
|
|
2481
|
+
createDirectory: (operation, appContext) => {
|
|
2482
|
+
redoCreateDirectory(operation, appContext);
|
|
2483
|
+
},
|
|
2484
|
+
deleteDirectory: (operation, appContext) => {
|
|
2485
|
+
redoDeleteDirectory(operation, appContext);
|
|
2486
|
+
},
|
|
2487
|
+
renameDirectory: (operation, appContext) => {
|
|
2488
|
+
redoRenameDirectory(operation, appContext);
|
|
2489
|
+
},
|
|
2490
|
+
moveDirectory: (operation, appContext) => {
|
|
2491
|
+
redoMoveDirectory(operation, appContext);
|
|
2492
|
+
},
|
|
2493
|
+
// insertStyles: (operation, appContext) => {
|
|
2494
|
+
// redoInsertStyles(operation, appContext);
|
|
2495
|
+
// },
|
|
2496
|
+
updateStyles: (operation, appContext) => {
|
|
2497
|
+
redoUpdateStyles(operation, appContext);
|
|
2498
|
+
},
|
|
2499
|
+
removeStyles: (operation, appContext) => {
|
|
2500
|
+
redoRemoveStyles(operation, appContext);
|
|
2501
|
+
},
|
|
2502
|
+
renameCssClass: (operation, appContext) => {
|
|
2503
|
+
redoRenameCssClass(operation, appContext);
|
|
2504
|
+
},
|
|
2505
|
+
// syncComponentStyles: (operation, appContext) => {
|
|
2506
|
+
// rollbackSyncComponentStyles(operation, appContext);
|
|
2507
|
+
// },
|
|
2508
|
+
// resolveCssClassConflicts: (operation, appContext) => {
|
|
2509
|
+
// rollbackResolveCssClassConflicts(operation, appContext);
|
|
2510
|
+
// },
|
|
2511
|
+
// resolveStyleDependencies: (operation, appContext) => {
|
|
2512
|
+
// rollbackResolveStyleDependencies(operation, appContext);
|
|
2513
|
+
// },
|
|
2514
|
+
// optimizeImports: (operation, appContext) => {
|
|
2515
|
+
// rollbackOptimizeImports(operation, appContext);
|
|
2516
|
+
// },
|
|
2517
|
+
};
|
|
2518
|
+
export default {
|
|
2519
|
+
// rollbackHandlers,
|
|
2520
|
+
operationSerializers,
|
|
2521
|
+
undoHandlers,
|
|
2522
|
+
redoHandlers,
|
|
2523
|
+
};
|
|
2524
|
+
//# sourceMappingURL=rollback-handlers.js.map
|