69 lines
1.6 KiB
TypeScript
69 lines
1.6 KiB
TypeScript
import * as fs from 'node:fs';
|
|
|
|
/**
|
|
* Pause state interface
|
|
*/
|
|
export interface IPauseState {
|
|
/** Timestamp when pause was activated */
|
|
pausedAt: number;
|
|
/** Who initiated the pause (e.g., 'cli', 'api') */
|
|
pausedBy: string;
|
|
/** Optional reason for pausing */
|
|
reason?: string;
|
|
/** When to auto-resume (null = indefinite, timestamp in ms) */
|
|
resumeAt?: number | null;
|
|
}
|
|
|
|
export type TPauseTransition = 'unchanged' | 'paused' | 'resumed' | 'autoResumed';
|
|
|
|
export interface IPauseSnapshot {
|
|
isPaused: boolean;
|
|
pauseState: IPauseState | null;
|
|
transition: TPauseTransition;
|
|
}
|
|
|
|
export function loadPauseSnapshot(
|
|
filePath: string,
|
|
wasPaused: boolean,
|
|
now: number = Date.now(),
|
|
): IPauseSnapshot {
|
|
try {
|
|
if (!fs.existsSync(filePath)) {
|
|
return {
|
|
isPaused: false,
|
|
pauseState: null,
|
|
transition: wasPaused ? 'resumed' : 'unchanged',
|
|
};
|
|
}
|
|
|
|
const data = fs.readFileSync(filePath, 'utf8');
|
|
const pauseState = JSON.parse(data) as IPauseState;
|
|
|
|
if (pauseState.resumeAt && now >= pauseState.resumeAt) {
|
|
try {
|
|
fs.unlinkSync(filePath);
|
|
} catch (_error) {
|
|
// Ignore deletion errors and still treat the pause as expired.
|
|
}
|
|
|
|
return {
|
|
isPaused: false,
|
|
pauseState: null,
|
|
transition: wasPaused ? 'autoResumed' : 'unchanged',
|
|
};
|
|
}
|
|
|
|
return {
|
|
isPaused: true,
|
|
pauseState,
|
|
transition: wasPaused ? 'unchanged' : 'paused',
|
|
};
|
|
} catch (_error) {
|
|
return {
|
|
isPaused: false,
|
|
pauseState: null,
|
|
transition: 'unchanged',
|
|
};
|
|
}
|
|
}
|