( after: string, targetPath: string, originalContent: string, deps: CutoverDeps, options?: CutoverOptions, )
| 93 | // `after` is serialized once by the caller (which also did the no-op check |
| 94 | // against its pre-dispatch snapshot), so this never re-serializes. |
| 95 | export async function persistSdkSerialize( |
| 96 | after: string, |
| 97 | targetPath: string, |
| 98 | originalContent: string, |
| 99 | deps: CutoverDeps, |
| 100 | options?: CutoverOptions, |
| 101 | ): Promise<void> { |
| 102 | deps.domEditSaveTimestampRef.current = Date.now(); |
| 103 | // Tag this write with the exact content (by hash) so the file-change |
| 104 | // reload-suppression can recognize its own echo by IDENTITY, not just a 2 s |
| 105 | // clock — an undo write (different bytes, not registered here) then always |
| 106 | // reloads instead of being swallowed by the time window. |
| 107 | markSelfWrite(targetPath, after); |
| 108 | await deps.writeProjectFile(targetPath, after); |
| 109 | await deps.editHistory.recordEdit({ |
| 110 | label: options?.label ?? "Edit layer", |
| 111 | kind: "manual", |
| 112 | ...(options?.coalesceKey ? { coalesceKey: options.coalesceKey } : {}), |
| 113 | files: { [targetPath]: { before: originalContent, after } }, |
| 114 | }); |
| 115 | if (deps.refresh) deps.refresh(after); |
| 116 | else if (!options?.skipRefresh) deps.reloadPreview(); |
| 117 | } |
| 118 | |
| 119 | export async function sdkCutoverPersist( |
| 120 | selection: DomEditSelection, |
no test coverage detected