track-dev-time
Version:
CLI tool to track your coding sessions with start, pause and stop commands. Outputs session data to a JSON file.
129 lines (111 loc) • 3.46 kB
JavaScript
//@ts-nocheck
import fs from "fs";
import path from "path";
import {
resendLastUnsyncedSessionIfNeeded,
sendSessionToAPI,
} from "../storage/sync-api.js";
import {
ensureSessionStorage,
readDataFromFile,
writeDataToFile,
} from "../utils/file-storage.js";
import { DEFAULT_RESUME_WINDOW_MS, SESSIONS_PATH } from "../utils/constants.js";
import { getConfig } from "../utils/config.js";
import { calculTotalDuration } from "../utils/time.js";
export const saveSession = async (
currentSession,
action,
filePath = SESSIONS_PATH
) => {
ensureSessionStorage(filePath);
const data = readDataFromFile(filePath);
switch (action) {
case "START":
await saveStartSession(data.sessions, currentSession);
break;
case "PAUSE":
savePauseSession(data.sessions, currentSession);
break;
case "END":
saveEndSession(data.sessions, currentSession);
try {
const success = await sendSessionToAPI(data, currentSession);
if (success) {
const index = data.sessions.findIndex(
(s) => s.id === currentSession.id
);
if (index !== -1) {
data.sessions[index].synced = true;
}
} else {
console.warn("⚠️ Session not synced to API on close.");
}
} catch (error) {
console.error("❌ Error syncing session on close:", error);
}
break;
default:
console.log("Unknown action");
break;
}
writeDataToFile(data, filePath);
console.log("Session saved!");
};
const saveStartSession = async (sessions, currentSession) => {
const lastSession = sessions[sessions.length - 1];
const now = new Date();
const config = getConfig();
const resumeWindow =
config.autoResumeSessionWindowMs ?? DEFAULT_RESUME_WINDOW_MS;
if (
lastSession &&
lastSession.end &&
now - new Date(lastSession.end) <= resumeWindow
) {
lastSession.end = null;
lastSession.duration = null;
console.log("Resuming last session instead");
} else {
await closeLastOpenSessionIfNeeded(sessions);
sessions.push(currentSession);
}
};
const closeLastOpenSessionIfNeeded = async (sessions) => {
const lastSession = sessions[sessions.length - 1];
if (lastSession && !lastSession.end) {
lastSession.end = new Date().toISOString();
lastSession.duration =
(new Date(lastSession.end) - new Date(lastSession.start)) / 1000;
if (lastSession.synced !== true) {
await resendLastUnsyncedSessionIfNeeded(lastSession);
}
}
};
const saveEndSession = (sessions, currentSession) => {
const today = new Date().toDateString();
const index = sessions.findIndex(
(session) =>
!session.end && new Date(session.start).toDateString() === today
);
if (index !== -1) {
const session = sessions[index];
const lastPause = session.pauses?.[session.pauses.length - 1];
if (lastPause && lastPause.end === null) {
lastPause.end = currentSession.end;
console.log("Pause ended before session closed");
}
session.end = currentSession.end;
session.duration = calculTotalDuration(session);
console.log("\n");
console.log("Session closed");
}
};
const savePauseSession = (sessions, updatedSession) => {
const index = sessions.findIndex((s) => s.id === updatedSession.id);
if (index !== -1) {
sessions[index] = updatedSession;
} else {
sessions.push(updatedSession);
}
};