( filePath: string, actions: SessionAction[], session?: SessionState, )
| 448 | } |
| 449 | |
| 450 | export function writeReplayScript( |
| 451 | filePath: string, |
| 452 | actions: SessionAction[], |
| 453 | session?: SessionState, |
| 454 | ) { |
| 455 | const lines: string[] = []; |
| 456 | // Session can be missing if the replay session is closed/deleted between execution and update write. |
| 457 | // In that case we still persist healed actions and omit only the context header. |
| 458 | if (session) { |
| 459 | const kind = session.device.kind ? ` kind=${session.device.kind}` : ''; |
| 460 | const target = session.device.target ? ` target=${session.device.target}` : ''; |
| 461 | // approach (b): heal-write the PUBLIC leaf platform (ios/macos), never the |
| 462 | // internal `apple` — keeps healed `.ad` scripts byte-compatible with checked-in |
| 463 | // fixtures and machine consumers. |
| 464 | lines.push( |
| 465 | `context platform=${publicPlatformString(session.device)}${target} device=${formatScriptStringLiteral(session.device.name)}${kind} theme=unknown`, |
| 466 | ); |
| 467 | } |
| 468 | for (const action of actions) { |
| 469 | lines.push(formatReplayActionLine(action)); |
| 470 | } |
| 471 | const serialized = `${lines.join('\n')}\n`; |
| 472 | const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now()}`; |
| 473 | fs.writeFileSync(tmpPath, serialized); |
| 474 | fs.renameSync(tmpPath, filePath); |
| 475 | } |
| 476 | |
| 477 | function formatReplayActionLine(action: SessionAction): string { |
| 478 | return formatPortableActionLine(action, { runtimeIncludeAllPositionals: true }); |
no test coverage detected