hackhours 0.1.0 → 0.1.2
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/README.md +2 -1
- package/dist/cli.js +65 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,6 +28,7 @@ hackhours init
|
|
|
28
28
|
```bash
|
|
29
29
|
hackhours start
|
|
30
30
|
hackhours stop
|
|
31
|
+
hackhours status
|
|
31
32
|
```
|
|
32
33
|
|
|
33
34
|
## Reports
|
|
@@ -70,4 +71,4 @@ npm test
|
|
|
70
71
|
|
|
71
72
|
## Notes
|
|
72
73
|
- `hackhours start` spawns a detached background process.
|
|
73
|
-
- Use `hackhours stop` to end tracking cleanly.
|
|
74
|
+
- Use `hackhours stop` to end tracking cleanly.
|
package/dist/cli.js
CHANGED
|
@@ -58,6 +58,15 @@ const printBreakdown = (title, map, total) => {
|
|
|
58
58
|
}
|
|
59
59
|
console.log(table.toString());
|
|
60
60
|
};
|
|
61
|
+
const topEntry = (map) => {
|
|
62
|
+
let best = null;
|
|
63
|
+
for (const entry of map.entries()) {
|
|
64
|
+
if (!best || entry[1] > best[1]) {
|
|
65
|
+
best = entry;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return best;
|
|
69
|
+
};
|
|
61
70
|
const parseRange = (from, to) => {
|
|
62
71
|
if (!from || !to) {
|
|
63
72
|
throw new Error("Both --from and --to are required.");
|
|
@@ -122,6 +131,62 @@ program
|
|
|
122
131
|
console.log(chalk.yellow("HackHours was not running."));
|
|
123
132
|
}
|
|
124
133
|
});
|
|
134
|
+
program
|
|
135
|
+
.command("status")
|
|
136
|
+
.description("Show tracker status and recent activity")
|
|
137
|
+
.action(async () => {
|
|
138
|
+
const state = readState();
|
|
139
|
+
let running = false;
|
|
140
|
+
if (state) {
|
|
141
|
+
try {
|
|
142
|
+
process.kill(state.pid, 0);
|
|
143
|
+
running = true;
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
clearState();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const config = loadConfig();
|
|
150
|
+
const { collections } = await openChrono(config.dataDir);
|
|
151
|
+
const now = new Date();
|
|
152
|
+
const todayFrom = startOfDay(now).getTime();
|
|
153
|
+
const todayTo = endOfDay(now).getTime();
|
|
154
|
+
const weekFromDate = new Date(now);
|
|
155
|
+
weekFromDate.setDate(weekFromDate.getDate() - 6);
|
|
156
|
+
const weekFrom = startOfDay(weekFromDate).getTime();
|
|
157
|
+
const weekTo = endOfDay(now).getTime();
|
|
158
|
+
const [todaySummary, weekSummary] = await Promise.all([
|
|
159
|
+
buildSummary(collections, todayFrom, todayTo, config.idleMinutes),
|
|
160
|
+
buildSummary(collections, weekFrom, weekTo, config.idleMinutes),
|
|
161
|
+
]);
|
|
162
|
+
console.log(chalk.bold("\nHackHours Status"));
|
|
163
|
+
console.log(`${chalk.cyan("Running:")} ${running ? chalk.green("Yes") : chalk.red("No")}`);
|
|
164
|
+
if (running && state) {
|
|
165
|
+
const startedAt = new Date(state.startedAt);
|
|
166
|
+
const uptime = Math.max(0, Date.now() - state.startedAt);
|
|
167
|
+
console.log(`${chalk.cyan("PID:")} ${state.pid}`);
|
|
168
|
+
console.log(`${chalk.cyan("Started:")} ${startedAt.toLocaleString()}`);
|
|
169
|
+
console.log(`${chalk.cyan("Uptime:")} ${formatDuration(uptime)}`);
|
|
170
|
+
}
|
|
171
|
+
console.log(`\n${chalk.cyan("Today:")} ${formatDuration(todaySummary.totalTimeMs)}`);
|
|
172
|
+
const todayTopProject = topEntry(todaySummary.projects);
|
|
173
|
+
if (todayTopProject) {
|
|
174
|
+
console.log(`${chalk.cyan("Top project (today):")} ${todayTopProject[0]} (${formatDuration(todayTopProject[1])})`);
|
|
175
|
+
}
|
|
176
|
+
const todayTopLang = topEntry(todaySummary.languages);
|
|
177
|
+
if (todayTopLang) {
|
|
178
|
+
console.log(`${chalk.cyan("Top language (today):")} ${todayTopLang[0]} (${formatDuration(todayTopLang[1])})`);
|
|
179
|
+
}
|
|
180
|
+
console.log(`\n${chalk.cyan("Last 7 days:")} ${formatDuration(weekSummary.totalTimeMs)}`);
|
|
181
|
+
const weekTopProject = topEntry(weekSummary.projects);
|
|
182
|
+
if (weekTopProject) {
|
|
183
|
+
console.log(`${chalk.cyan("Top project (7 days):")} ${weekTopProject[0]} (${formatDuration(weekTopProject[1])})`);
|
|
184
|
+
}
|
|
185
|
+
const weekTopLang = topEntry(weekSummary.languages);
|
|
186
|
+
if (weekTopLang) {
|
|
187
|
+
console.log(`${chalk.cyan("Top language (7 days):")} ${weekTopLang[0]} (${formatDuration(weekTopLang[1])})`);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
125
190
|
program
|
|
126
191
|
.command("daemon")
|
|
127
192
|
.description("Run watcher in foreground (internal)")
|