workday-daemon 0.1.0

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.
Files changed (56) hide show
  1. package/README.md +95 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +710 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/collectors/git-client.d.ts +16 -0
  6. package/dist/collectors/git-client.js +58 -0
  7. package/dist/collectors/git-client.js.map +1 -0
  8. package/dist/collectors/git-tracker.d.ts +43 -0
  9. package/dist/collectors/git-tracker.js +168 -0
  10. package/dist/collectors/git-tracker.js.map +1 -0
  11. package/dist/collectors/reflog-parser.d.ts +30 -0
  12. package/dist/collectors/reflog-parser.js +71 -0
  13. package/dist/collectors/reflog-parser.js.map +1 -0
  14. package/dist/collectors/snapshot-parser.d.ts +34 -0
  15. package/dist/collectors/snapshot-parser.js +79 -0
  16. package/dist/collectors/snapshot-parser.js.map +1 -0
  17. package/dist/core/activity-evaluator.d.ts +33 -0
  18. package/dist/core/activity-evaluator.js +94 -0
  19. package/dist/core/activity-evaluator.js.map +1 -0
  20. package/dist/core/config.d.ts +18 -0
  21. package/dist/core/config.js +174 -0
  22. package/dist/core/config.js.map +1 -0
  23. package/dist/core/constants.d.ts +39 -0
  24. package/dist/core/constants.js +51 -0
  25. package/dist/core/constants.js.map +1 -0
  26. package/dist/core/daily-log.d.ts +56 -0
  27. package/dist/core/daily-log.js +366 -0
  28. package/dist/core/daily-log.js.map +1 -0
  29. package/dist/core/session-tracker.d.ts +110 -0
  30. package/dist/core/session-tracker.js +460 -0
  31. package/dist/core/session-tracker.js.map +1 -0
  32. package/dist/core/status-renderer.d.ts +20 -0
  33. package/dist/core/status-renderer.js +178 -0
  34. package/dist/core/status-renderer.js.map +1 -0
  35. package/dist/core/types.d.ts +320 -0
  36. package/dist/core/types.js +52 -0
  37. package/dist/core/types.js.map +1 -0
  38. package/dist/daemon.d.ts +31 -0
  39. package/dist/daemon.js +266 -0
  40. package/dist/daemon.js.map +1 -0
  41. package/dist/http-server.d.ts +30 -0
  42. package/dist/http-server.js +342 -0
  43. package/dist/http-server.js.map +1 -0
  44. package/dist/push/jira-client.d.ts +5 -0
  45. package/dist/push/jira-client.js +84 -0
  46. package/dist/push/jira-client.js.map +1 -0
  47. package/dist/push/report-builder.d.ts +9 -0
  48. package/dist/push/report-builder.js +77 -0
  49. package/dist/push/report-builder.js.map +1 -0
  50. package/dist/push/tempo-client.d.ts +27 -0
  51. package/dist/push/tempo-client.js +92 -0
  52. package/dist/push/tempo-client.js.map +1 -0
  53. package/dist/push/tempo-pusher.d.ts +17 -0
  54. package/dist/push/tempo-pusher.js +317 -0
  55. package/dist/push/tempo-pusher.js.map +1 -0
  56. package/package.json +35 -0
@@ -0,0 +1,317 @@
1
+ import { readFileSync, writeFileSync, existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { getDataDir } from '../core/config.js';
4
+ import { readDailyLog, writeDailyLog } from '../core/daily-log.js';
5
+ import { PUSH_LOG_FILE, TEMPO_TOLERANCE_SECONDS } from '../core/constants.js';
6
+ import { DayStatus } from '../core/types.js';
7
+ import { buildReport } from './report-builder.js';
8
+ import { getAccountId, resolveIssueIds } from './jira-client.js';
9
+ import { TempoClient } from './tempo-client.js';
10
+ // ─── Push log persistence ────────────────────────────────────────────────
11
+ function getPushLogPath() {
12
+ return join(getDataDir(), PUSH_LOG_FILE);
13
+ }
14
+ function loadPushLog() {
15
+ const path = getPushLogPath();
16
+ if (!existsSync(path))
17
+ return {};
18
+ try {
19
+ return JSON.parse(readFileSync(path, 'utf-8'));
20
+ }
21
+ catch {
22
+ return {};
23
+ }
24
+ }
25
+ function savePushLog(log) {
26
+ writeFileSync(getPushLogPath(), JSON.stringify(log, null, 2), 'utf-8');
27
+ }
28
+ function pushLogKey(date, task) {
29
+ return `${date}|${task}`;
30
+ }
31
+ // ─── Push plan ───────────────────────────────────────────────────────────
32
+ /** Build a plan by comparing report entries with push log and existing Tempo worklogs */
33
+ export function buildPushPlan(report, jiraMap, pushLog, tempoWorklogs) {
34
+ const plan = [];
35
+ // Index Tempo worklogs by (date, issueId) for fast lookup
36
+ const tempoByKey = new Map();
37
+ for (const wl of tempoWorklogs) {
38
+ const key = `${wl.startDate}|${wl.issueId}`;
39
+ const list = tempoByKey.get(key) ?? [];
40
+ list.push(wl);
41
+ tempoByKey.set(key, list);
42
+ }
43
+ // Track which Tempo worklogs are accounted for by our report
44
+ const accountedTempoIds = new Set();
45
+ for (const entry of report) {
46
+ const jira = jiraMap.get(entry.task);
47
+ if (!jira) {
48
+ plan.push({
49
+ date: entry.date,
50
+ task: entry.task,
51
+ targetSeconds: entry.totalSeconds,
52
+ action: 'error',
53
+ detail: 'Unresolved in Jira',
54
+ });
55
+ continue;
56
+ }
57
+ const key = pushLogKey(entry.date, entry.task);
58
+ const logEntry = pushLog[key];
59
+ const tempoKey = `${entry.date}|${jira.issueId}`;
60
+ const tempoMatches = tempoByKey.get(tempoKey) ?? [];
61
+ // Verify push-log worklog still exists in Tempo
62
+ const validLogEntry = logEntry && tempoMatches.some(w => w.tempoWorklogId === logEntry.tempoWorklogId)
63
+ ? logEntry
64
+ : null;
65
+ if (validLogEntry) {
66
+ // We pushed this before and worklog still exists — check if it needs update
67
+ accountedTempoIds.add(validLogEntry.tempoWorklogId);
68
+ const diff = Math.abs(validLogEntry.timeSpentSeconds - entry.totalSeconds);
69
+ if (diff <= TEMPO_TOLERANCE_SECONDS) {
70
+ plan.push({
71
+ date: entry.date,
72
+ task: entry.task,
73
+ targetSeconds: entry.totalSeconds,
74
+ action: 'skip',
75
+ detail: `Already pushed (${formatHours(validLogEntry.timeSpentSeconds)})`,
76
+ issueId: jira.issueId,
77
+ existingWorklogId: validLogEntry.tempoWorklogId,
78
+ });
79
+ }
80
+ else {
81
+ plan.push({
82
+ date: entry.date,
83
+ task: entry.task,
84
+ targetSeconds: entry.totalSeconds,
85
+ action: 'update',
86
+ detail: `${formatHours(validLogEntry.timeSpentSeconds)} → ${formatHours(entry.totalSeconds)}`,
87
+ issueId: jira.issueId,
88
+ existingWorklogId: validLogEntry.tempoWorklogId,
89
+ });
90
+ }
91
+ // Mark other Tempo worklogs for same issue+date
92
+ for (const wl of tempoMatches) {
93
+ accountedTempoIds.add(wl.tempoWorklogId);
94
+ }
95
+ }
96
+ else if (tempoMatches.length > 0) {
97
+ // Not in push log but exists in Tempo — could be manual entry
98
+ for (const wl of tempoMatches)
99
+ accountedTempoIds.add(wl.tempoWorklogId);
100
+ const existingTotal = tempoMatches.reduce((s, w) => s + w.timeSpentSeconds, 0);
101
+ const diff = Math.abs(existingTotal - entry.totalSeconds);
102
+ if (diff <= TEMPO_TOLERANCE_SECONDS) {
103
+ plan.push({
104
+ date: entry.date,
105
+ task: entry.task,
106
+ targetSeconds: entry.totalSeconds,
107
+ action: 'skip',
108
+ detail: `Exists in Tempo (${formatHours(existingTotal)})`,
109
+ issueId: jira.issueId,
110
+ extraWorklogIds: tempoMatches.map(w => w.tempoWorklogId),
111
+ });
112
+ }
113
+ else {
114
+ // Create new — Tempo already has something, but we don't own it
115
+ plan.push({
116
+ date: entry.date,
117
+ task: entry.task,
118
+ targetSeconds: entry.totalSeconds,
119
+ action: 'create',
120
+ detail: `Tempo has ${formatHours(existingTotal)}, adding ${formatHours(entry.totalSeconds)}`,
121
+ issueId: jira.issueId,
122
+ extraWorklogIds: tempoMatches.map(w => w.tempoWorklogId),
123
+ });
124
+ }
125
+ }
126
+ else {
127
+ // Not in push log and not in Tempo — create
128
+ plan.push({
129
+ date: entry.date,
130
+ task: entry.task,
131
+ targetSeconds: entry.totalSeconds,
132
+ action: 'create',
133
+ detail: `New (${formatHours(entry.totalSeconds)})`,
134
+ issueId: jira.issueId,
135
+ });
136
+ }
137
+ }
138
+ // Show Tempo-only entries (not in our report)
139
+ for (const wl of tempoWorklogs) {
140
+ if (accountedTempoIds.has(wl.tempoWorklogId))
141
+ continue;
142
+ // Find task key for this issueId from jiraMap
143
+ let taskKey = `issue:${wl.issueId}`;
144
+ for (const [key, jira] of jiraMap) {
145
+ if (jira.issueId === wl.issueId) {
146
+ taskKey = key;
147
+ break;
148
+ }
149
+ }
150
+ plan.push({
151
+ date: wl.startDate,
152
+ task: taskKey,
153
+ targetSeconds: wl.timeSpentSeconds,
154
+ action: 'skip',
155
+ detail: `Tempo only (${formatHours(wl.timeSpentSeconds)})`,
156
+ existingWorklogId: wl.tempoWorklogId,
157
+ });
158
+ }
159
+ // Sort by date, then task
160
+ plan.sort((a, b) => a.date.localeCompare(b.date) || a.task.localeCompare(b.task));
161
+ return plan;
162
+ }
163
+ // ─── Execute plan ────────────────────────────────────────────────────────
164
+ /** Execute mutations from the plan, update push log */
165
+ export async function executePlan(plan, tempoClient, accountId) {
166
+ const pushLog = loadPushLog();
167
+ let posted = 0;
168
+ let updated = 0;
169
+ let deleted = 0;
170
+ let skipped = 0;
171
+ let failed = 0;
172
+ for (const entry of plan) {
173
+ const key = pushLogKey(entry.date, entry.task);
174
+ switch (entry.action) {
175
+ case 'skip':
176
+ skipped++;
177
+ break;
178
+ case 'create': {
179
+ if (!entry.issueId) {
180
+ failed++;
181
+ break;
182
+ }
183
+ try {
184
+ const result = await tempoClient.createWorklog({
185
+ issueId: entry.issueId,
186
+ authorAccountId: accountId,
187
+ timeSpentSeconds: entry.targetSeconds,
188
+ startDate: entry.date,
189
+ });
190
+ pushLog[key] = {
191
+ tempoWorklogId: result.tempoWorklogId,
192
+ timeSpentSeconds: entry.targetSeconds,
193
+ pushedAt: new Date().toISOString(),
194
+ };
195
+ posted++;
196
+ console.log(` POST ${entry.date} ${entry.task} ${formatHours(entry.targetSeconds)}`);
197
+ }
198
+ catch (err) {
199
+ failed++;
200
+ console.error(` FAIL POST ${entry.date} ${entry.task}: ${err instanceof Error ? err.message : String(err)}`);
201
+ }
202
+ break;
203
+ }
204
+ case 'update': {
205
+ if (!entry.issueId || !entry.existingWorklogId) {
206
+ failed++;
207
+ break;
208
+ }
209
+ try {
210
+ const result = await tempoClient.updateWorklog(entry.existingWorklogId, {
211
+ issueId: entry.issueId,
212
+ authorAccountId: accountId,
213
+ timeSpentSeconds: entry.targetSeconds,
214
+ startDate: entry.date,
215
+ });
216
+ pushLog[key] = {
217
+ tempoWorklogId: result.tempoWorklogId,
218
+ timeSpentSeconds: entry.targetSeconds,
219
+ pushedAt: new Date().toISOString(),
220
+ };
221
+ updated++;
222
+ console.log(` PUT ${entry.date} ${entry.task} ${entry.detail}`);
223
+ }
224
+ catch (err) {
225
+ failed++;
226
+ console.error(` FAIL PUT ${entry.date} ${entry.task}: ${err instanceof Error ? err.message : String(err)}`);
227
+ }
228
+ break;
229
+ }
230
+ case 'error':
231
+ failed++;
232
+ break;
233
+ }
234
+ }
235
+ savePushLog(pushLog);
236
+ return { posted, updated, deleted, skipped, failed };
237
+ }
238
+ // ─── Mark daily logs as pushed ───────────────────────────────────────────
239
+ function markDaysPushed(from, to) {
240
+ const current = new Date(from + 'T12:00:00Z');
241
+ const end = new Date(to + 'T12:00:00Z');
242
+ while (current <= end) {
243
+ const y = current.getUTCFullYear();
244
+ const m = String(current.getUTCMonth() + 1).padStart(2, '0');
245
+ const d = String(current.getUTCDate()).padStart(2, '0');
246
+ const date = `${y}-${m}-${d}`;
247
+ const log = readDailyLog(date);
248
+ if (log && log.status !== DayStatus.Pushed) {
249
+ log.status = DayStatus.Pushed;
250
+ log.pushedAt = new Date().toISOString();
251
+ writeDailyLog(log);
252
+ }
253
+ current.setUTCDate(current.getUTCDate() + 1);
254
+ }
255
+ }
256
+ /** Full push pipeline: build report → resolve Jira → fetch Tempo → plan → execute */
257
+ export async function runPush(options) {
258
+ const { from, to, commit, config, secrets, filePath } = options;
259
+ // Step 1: Build or load report
260
+ let report;
261
+ if (filePath) {
262
+ const raw = readFileSync(filePath, 'utf-8');
263
+ const parsed = JSON.parse(raw);
264
+ report = parsed.entries;
265
+ console.log(`Loaded ${report.length} entries from ${filePath}`);
266
+ }
267
+ else {
268
+ report = buildReport(from, to, config);
269
+ console.log(`Built report: ${report.length} entries (${from} → ${to})`);
270
+ }
271
+ if (report.length === 0) {
272
+ return { dryRun: !commit, plan: [], result: { posted: 0, updated: 0, deleted: 0, skipped: 0, failed: 0 } };
273
+ }
274
+ // Step 2: Resolve Jira issue IDs
275
+ const uniqueTasks = [...new Set(report.map(e => e.task))];
276
+ console.log(`Resolving ${uniqueTasks.length} Jira issue(s)...`);
277
+ const jiraMap = await resolveIssueIds(uniqueTasks, secrets);
278
+ // Step 3: Get Jira accountId + existing Tempo worklogs
279
+ let accountId;
280
+ try {
281
+ accountId = await getAccountId(secrets);
282
+ }
283
+ catch (err) {
284
+ throw new Error(`Jira auth failed (check secrets.json): ${err instanceof Error ? err.message : String(err)}`);
285
+ }
286
+ console.log(`Account: ${accountId}`);
287
+ const tempoClient = new TempoClient(secrets.Tempo_Token);
288
+ console.log(`Fetching Tempo worklogs (${from} → ${to})...`);
289
+ const tempoWorklogs = await tempoClient.getUserWorklogs(accountId, from, to);
290
+ console.log(`Found ${tempoWorklogs.length} existing worklog(s)`);
291
+ // Step 4: Build plan
292
+ const pushLog = loadPushLog();
293
+ const plan = buildPushPlan(report, jiraMap, pushLog, tempoWorklogs);
294
+ if (!commit) {
295
+ return { dryRun: true, plan };
296
+ }
297
+ // Step 5: Execute
298
+ const actionable = plan.filter(e => e.action === 'create' || e.action === 'update');
299
+ if (actionable.length === 0) {
300
+ console.log('Nothing to push.');
301
+ return { dryRun: false, plan, result: { posted: 0, updated: 0, deleted: 0, skipped: 0, failed: 0 } };
302
+ }
303
+ console.log(`Executing ${actionable.length} mutation(s)...`);
304
+ const result = await executePlan(plan, tempoClient, accountId);
305
+ // Mark daily logs as pushed
306
+ markDaysPushed(from, to);
307
+ return { dryRun: false, plan, result };
308
+ }
309
+ // ─── Helpers ─────────────────────────────────────────────────────────────
310
+ function formatHours(seconds) {
311
+ const hours = seconds / 3600;
312
+ const rounded1 = parseFloat(hours.toFixed(1));
313
+ if (Math.abs(hours - rounded1) < 0.01)
314
+ return `${hours.toFixed(1)}h`;
315
+ return `${hours.toFixed(2)}h`;
316
+ }
317
+ //# sourceMappingURL=tempo-pusher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tempo-pusher.js","sourceRoot":"","sources":["../../src/push/tempo-pusher.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "workday-daemon",
3
+ "version": "0.1.0",
4
+ "description": "Lightweight activity tracker & timesheet tool",
5
+ "type": "module",
6
+ "bin": {
7
+ "workday": "./dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "engines": {
13
+ "node": ">=20.0.0"
14
+ },
15
+ "scripts": {
16
+ "dev": "tsx src/daemon.ts",
17
+ "build": "tsc",
18
+ "start": "node dist/daemon.js",
19
+ "cli": "tsx src/cli.ts",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "keywords": [
23
+ "timesheet",
24
+ "tempo",
25
+ "worklog",
26
+ "git",
27
+ "activity-tracker"
28
+ ],
29
+ "license": "MIT",
30
+ "devDependencies": {
31
+ "tsx": "^4.19.0",
32
+ "typescript": "^5.7.0",
33
+ "@types/node": "^22.0.0"
34
+ }
35
+ }