kalvium-worklog 1.2.0 → 1.3.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.
- package/dist/cli.js +15 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/submit.d.ts +7 -0
- package/dist/submit.js +104 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import { captureToken } from "./capture-token.js";
|
|
4
4
|
import { discoverPosition } from "./discover-position.js";
|
|
5
|
-
import { submitWorklog, checkStatus, dailySubmit, catchUpSubmit } from "./submit.js";
|
|
5
|
+
import { submitWorklog, checkStatus, dailySubmit, catchUpSubmit, backfillSubmit } from "./submit.js";
|
|
6
6
|
import { setupScheduler, removeScheduler } from "./scheduler.js";
|
|
7
7
|
import { loadToken, saveConfig, getPositionIdFromToken } from "./config.js";
|
|
8
8
|
import { existsSync } from "fs";
|
|
@@ -42,16 +42,18 @@ program
|
|
|
42
42
|
.command("submit [text]")
|
|
43
43
|
.description("Submit worklog (default text: 'Working on assigned task')")
|
|
44
44
|
.option("--dry-run", "Test without submitting")
|
|
45
|
+
.option("--date <YYYY-MM-DD>", "Submit for a specific date (backdate)")
|
|
45
46
|
.action(async (text, opts) => {
|
|
46
|
-
// Skip weekends (unless dry run)
|
|
47
|
+
// Skip weekends (unless dry run or backdating)
|
|
47
48
|
const day = new Date().getDay();
|
|
48
|
-
if ((day === 0 || day === 6) && !opts.dryRun) {
|
|
49
|
+
if ((day === 0 || day === 6) && !opts.dryRun && !opts.date) {
|
|
49
50
|
console.log("It's a weekend — skipping.");
|
|
50
51
|
return;
|
|
51
52
|
}
|
|
52
53
|
const result = await submitWorklog({
|
|
53
54
|
text: text ?? "Working on assigned task",
|
|
54
55
|
dryRun: opts.dryRun,
|
|
56
|
+
date: opts.date,
|
|
55
57
|
});
|
|
56
58
|
if (!result.success)
|
|
57
59
|
process.exit(1);
|
|
@@ -81,6 +83,16 @@ program
|
|
|
81
83
|
if (!ok)
|
|
82
84
|
process.exit(1);
|
|
83
85
|
});
|
|
86
|
+
// ─── backfill ──────────────────────────────────────────────────────────────
|
|
87
|
+
program
|
|
88
|
+
.command("backfill [date]")
|
|
89
|
+
.description("Backfill missed worklogs. No arg = last 5 weekdays. Pass YYYY-MM-DD for a specific date.")
|
|
90
|
+
.option("--dry-run", "Test without submitting")
|
|
91
|
+
.action(async (date, opts) => {
|
|
92
|
+
const ok = await backfillSubmit(date, opts.dryRun);
|
|
93
|
+
if (!ok)
|
|
94
|
+
process.exit(1);
|
|
95
|
+
});
|
|
84
96
|
// ─── schedule ──────────────────────────────────────────────────────────────
|
|
85
97
|
program
|
|
86
98
|
.command("schedule [time]")
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { captureToken } from "./capture-token.js";
|
|
2
2
|
export { discoverPosition } from "./discover-position.js";
|
|
3
|
-
export { submitWorklog, checkStatus, dailySubmit, catchUpSubmit } from "./submit.js";
|
|
3
|
+
export { submitWorklog, checkStatus, dailySubmit, catchUpSubmit, backfillSubmit } from "./submit.js";
|
|
4
4
|
export type { SubmitOptions, SubmitResult } from "./submit.js";
|
|
5
5
|
export { setupScheduler, removeScheduler } from "./scheduler.js";
|
|
6
6
|
export type { ScheduleOptions } from "./scheduler.js";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { captureToken } from "./capture-token.js";
|
|
2
2
|
export { discoverPosition } from "./discover-position.js";
|
|
3
|
-
export { submitWorklog, checkStatus, dailySubmit, catchUpSubmit } from "./submit.js";
|
|
3
|
+
export { submitWorklog, checkStatus, dailySubmit, catchUpSubmit, backfillSubmit } from "./submit.js";
|
|
4
4
|
export { setupScheduler, removeScheduler } from "./scheduler.js";
|
|
5
5
|
export { refreshToken } from "./refresh.js";
|
|
6
6
|
export { loadToken, saveToken, loadConfig, saveConfig, getWorklogApi, INSTALL_DIR, TOKEN_FILE, CONFIG_FILE, LOG_FILE, } from "./config.js";
|
package/dist/submit.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export interface SubmitOptions {
|
|
2
2
|
text?: string;
|
|
3
3
|
dryRun?: boolean;
|
|
4
|
+
date?: string;
|
|
4
5
|
}
|
|
5
6
|
export interface SubmitResult {
|
|
6
7
|
success: boolean;
|
|
@@ -28,3 +29,9 @@ export declare function dailySubmit(): Promise<boolean>;
|
|
|
28
29
|
* submitted yet, submit it. Used on login/wake to handle missed runs.
|
|
29
30
|
*/
|
|
30
31
|
export declare function catchUpSubmit(): Promise<boolean>;
|
|
32
|
+
/**
|
|
33
|
+
* Backfill: submit worklogs for missed days.
|
|
34
|
+
* Can backfill a specific date (--date YYYY-MM-DD) or the last N weekdays.
|
|
35
|
+
* Skips days that already have a submitted worklog.
|
|
36
|
+
*/
|
|
37
|
+
export declare function backfillSubmit(dateStr?: string, dryRun?: boolean): Promise<boolean>;
|
package/dist/submit.js
CHANGED
|
@@ -11,6 +11,7 @@ const STATUS_LABEL = "Working on-site (Company location)";
|
|
|
11
11
|
export async function submitWorklog(options = {}) {
|
|
12
12
|
const text = options.text ?? "Working on assigned task";
|
|
13
13
|
const dryRun = options.dryRun ?? false;
|
|
14
|
+
const date = options.date; // YYYY-MM-DD or undefined (today)
|
|
14
15
|
const worklogApi = getWorklogApi();
|
|
15
16
|
if (!worklogApi) {
|
|
16
17
|
return {
|
|
@@ -18,7 +19,7 @@ export async function submitWorklog(options = {}) {
|
|
|
18
19
|
message: "No config found. Run `kalvium-worklog discover` first.",
|
|
19
20
|
};
|
|
20
21
|
}
|
|
21
|
-
const
|
|
22
|
+
const payload = {
|
|
22
23
|
title: STATUS_LABEL,
|
|
23
24
|
description: STATUS_LABEL,
|
|
24
25
|
category: STATUS_KEY,
|
|
@@ -26,10 +27,15 @@ export async function submitWorklog(options = {}) {
|
|
|
26
27
|
priorityLevel: "medium",
|
|
27
28
|
blockers: "",
|
|
28
29
|
worklogs: JSON.stringify({ content: `<p>${text}</p>` }),
|
|
29
|
-
}
|
|
30
|
+
};
|
|
31
|
+
// Include worklogDate if backdating
|
|
32
|
+
if (date) {
|
|
33
|
+
payload.worklogDate = date;
|
|
34
|
+
}
|
|
35
|
+
const body = JSON.stringify(payload);
|
|
30
36
|
if (dryRun) {
|
|
31
37
|
console.log(`[DRY RUN] Would submit to ${worklogApi}`);
|
|
32
|
-
console.log(` text='${text}', status=${STATUS_KEY}`);
|
|
38
|
+
console.log(` text='${text}', status=${STATUS_KEY}, date=${date ?? "today"}`);
|
|
33
39
|
console.log(` Body: ${body}`);
|
|
34
40
|
return { success: true, message: "Dry run" };
|
|
35
41
|
}
|
|
@@ -270,3 +276,98 @@ export async function catchUpSubmit() {
|
|
|
270
276
|
log("[INFO] Today's worklog is missing. Running catch-up submit...");
|
|
271
277
|
return dailySubmit();
|
|
272
278
|
}
|
|
279
|
+
/**
|
|
280
|
+
* Backfill: submit worklogs for missed days.
|
|
281
|
+
* Can backfill a specific date (--date YYYY-MM-DD) or the last N weekdays.
|
|
282
|
+
* Skips days that already have a submitted worklog.
|
|
283
|
+
*/
|
|
284
|
+
export async function backfillSubmit(dateStr, dryRun = false) {
|
|
285
|
+
const worklogApi = getWorklogApi();
|
|
286
|
+
if (!worklogApi) {
|
|
287
|
+
console.log("ERROR: No config found. Run `kalvium-worklog discover` first.");
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
// Determine which dates to backfill
|
|
291
|
+
let datesToFill = [];
|
|
292
|
+
if (dateStr) {
|
|
293
|
+
// Single specific date
|
|
294
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
|
|
295
|
+
console.log("ERROR: Date must be in YYYY-MM-DD format.");
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
datesToFill = [dateStr];
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
// Default: backfill last 5 weekdays (excluding today and weekends)
|
|
302
|
+
const dates = [];
|
|
303
|
+
const today = new Date();
|
|
304
|
+
for (let i = 1; i <= 7; i++) {
|
|
305
|
+
const d = new Date(today);
|
|
306
|
+
d.setDate(d.getDate() - i);
|
|
307
|
+
const day = d.getDay();
|
|
308
|
+
if (day === 0 || day === 6)
|
|
309
|
+
continue; // skip weekends
|
|
310
|
+
dates.push(d.toISOString().slice(0, 10));
|
|
311
|
+
if (dates.length >= 5)
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
datesToFill = dates;
|
|
315
|
+
}
|
|
316
|
+
if (datesToFill.length === 0) {
|
|
317
|
+
console.log("No weekdays to backfill.");
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
console.log(`Backfilling ${datesToFill.length} day(s): ${datesToFill.join(", ")}`);
|
|
321
|
+
// Get already-submitted worklogs to skip them
|
|
322
|
+
let submittedDates = new Set();
|
|
323
|
+
const refreshResult = await refreshToken();
|
|
324
|
+
if (refreshResult.success && refreshResult.accessToken) {
|
|
325
|
+
try {
|
|
326
|
+
const res = await fetch(worklogApi, {
|
|
327
|
+
headers: { authorization: `Bearer ${refreshResult.accessToken}` },
|
|
328
|
+
});
|
|
329
|
+
if (res.ok) {
|
|
330
|
+
const worklogs = await res.json();
|
|
331
|
+
if (Array.isArray(worklogs)) {
|
|
332
|
+
for (const w of worklogs) {
|
|
333
|
+
if (w.status === "complete") {
|
|
334
|
+
submittedDates.add((w.worklogDate ?? "").slice(0, 10));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
// ignore — will try to submit all dates
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
let successCount = 0;
|
|
345
|
+
let skipCount = 0;
|
|
346
|
+
let failCount = 0;
|
|
347
|
+
for (const date of datesToFill) {
|
|
348
|
+
if (submittedDates.has(date)) {
|
|
349
|
+
console.log(` ${date}: already submitted, skipping.`);
|
|
350
|
+
skipCount++;
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
if (dryRun) {
|
|
354
|
+
console.log(` ${date}: [DRY RUN] would submit.`);
|
|
355
|
+
successCount++;
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
console.log(` ${date}: submitting...`);
|
|
359
|
+
const result = await submitWorklog({ date });
|
|
360
|
+
if (result.success) {
|
|
361
|
+
console.log(` ${date}: ✓ ${result.message}`);
|
|
362
|
+
successCount++;
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
console.log(` ${date}: ✗ ${result.message}`);
|
|
366
|
+
failCount++;
|
|
367
|
+
}
|
|
368
|
+
// Small delay between submissions to avoid rate limiting
|
|
369
|
+
await sleep(2000);
|
|
370
|
+
}
|
|
371
|
+
console.log(`\nBackfill complete: ${successCount} submitted, ${skipCount} skipped, ${failCount} failed.`);
|
|
372
|
+
return failCount === 0;
|
|
373
|
+
}
|