kalvium-worklog 1.3.0 → 1.3.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.
@@ -72,9 +72,28 @@ async function tryCapture(headless) {
72
72
  timeout: 30000,
73
73
  });
74
74
  await page
75
- .waitForLoadState("networkidle", { timeout: 20000 })
75
+ .waitForLoadState("networkidle", { timeout: 10000 })
76
76
  .catch(() => { });
77
- await page.waitForTimeout(8000);
77
+ // Auto-click "Continue with Google" in headless mode too.
78
+ // If the Google session is still valid in the persistent profile,
79
+ // this completes the entire login invisibly — no browser window,
80
+ // no user interaction needed.
81
+ const googleBtn = page.locator("text=Continue with Google").first();
82
+ const isVisible = await googleBtn.isVisible().catch(() => false);
83
+ if (isVisible) {
84
+ await googleBtn.click();
85
+ console.log(" Clicked 'Continue with Google' (headless)...");
86
+ // Wait for token exchange after auto-click
87
+ for (let i = 0; i < 15; i++) {
88
+ if (tokenData.data)
89
+ break;
90
+ await page.waitForTimeout(1000);
91
+ }
92
+ }
93
+ // If still no token, wait a bit more for any redirects
94
+ if (!tokenData.data) {
95
+ await page.waitForTimeout(5000);
96
+ }
78
97
  }
79
98
  catch {
80
99
  // ignore
@@ -82,16 +101,39 @@ async function tryCapture(headless) {
82
101
  }
83
102
  else {
84
103
  console.log("\n ========================================");
85
- console.log(" Browser opened. Please log in now:");
86
- console.log(" 1. Click 'Continue with Google'");
87
- console.log(" 2. Sign in with your Kalvium account");
88
- console.log(" 3. Complete 2FA if prompted");
89
- console.log(" 4. Wait — the script continues automatically");
104
+ console.log(" Browser opened. Auto-clicking 'Continue with Google'...");
105
+ console.log(" Please complete 2FA if prompted.");
90
106
  console.log(" ========================================\n");
91
107
  await page.goto("https://kalvium.community/internships", {
92
108
  waitUntil: "domcontentloaded",
93
109
  timeout: 120000,
94
110
  });
111
+ // Auto-click "Continue with Google" button
112
+ try {
113
+ // Try common selectors for the Google login button
114
+ const googleBtn = await page
115
+ .locator("text=Continue with Google")
116
+ .first();
117
+ const isVisible = await googleBtn
118
+ .isVisible()
119
+ .catch(() => false);
120
+ if (isVisible) {
121
+ await googleBtn.click();
122
+ console.log(" Clicked 'Continue with Google'.");
123
+ }
124
+ else {
125
+ // Fallback: try other patterns
126
+ await page
127
+ .locator("button:has-text('Google'), a:has-text('Google')")
128
+ .first()
129
+ .click({ timeout: 5000 })
130
+ .catch(() => { });
131
+ console.log(" Clicked Google login button.");
132
+ }
133
+ }
134
+ catch {
135
+ console.log(" Could not auto-click. Please click 'Continue with Google' manually.");
136
+ }
95
137
  console.log(" Waiting for login to complete (up to 5 minutes)...");
96
138
  // Poll up to 5 minutes
97
139
  for (let i = 0; i < 300; i++) {
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, backfillSubmit } from "./submit.js";
5
+ import { submitWorklog, checkStatus, dailySubmit, catchUpSubmit } 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,21 +42,21 @@ 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)")
46
45
  .action(async (text, opts) => {
47
- // Skip weekends (unless dry run or backdating)
46
+ // Skip weekends (unless dry run)
48
47
  const day = new Date().getDay();
49
- if ((day === 0 || day === 6) && !opts.dryRun && !opts.date) {
48
+ if ((day === 0 || day === 6) && !opts.dryRun) {
50
49
  console.log("It's a weekend — skipping.");
51
50
  return;
52
51
  }
53
52
  const result = await submitWorklog({
54
53
  text: text ?? "Working on assigned task",
55
54
  dryRun: opts.dryRun,
56
- date: opts.date,
57
55
  });
58
- if (!result.success)
56
+ if (!result.success) {
57
+ console.log(`ERROR: ${result.message}`);
59
58
  process.exit(1);
59
+ }
60
60
  });
61
61
  // ─── status ────────────────────────────────────────────────────────────────
62
62
  program
@@ -83,16 +83,6 @@ program
83
83
  if (!ok)
84
84
  process.exit(1);
85
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
- });
96
86
  // ─── schedule ──────────────────────────────────────────────────────────────
97
87
  program
98
88
  .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, backfillSubmit } from "./submit.js";
3
+ export { submitWorklog, checkStatus, dailySubmit, catchUpSubmit } 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, backfillSubmit } from "./submit.js";
3
+ export { submitWorklog, checkStatus, dailySubmit, catchUpSubmit } 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,7 +1,6 @@
1
1
  export interface SubmitOptions {
2
2
  text?: string;
3
3
  dryRun?: boolean;
4
- date?: string;
5
4
  }
6
5
  export interface SubmitResult {
7
6
  success: boolean;
@@ -29,9 +28,3 @@ export declare function dailySubmit(): Promise<boolean>;
29
28
  * submitted yet, submit it. Used on login/wake to handle missed runs.
30
29
  */
31
30
  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,7 +11,6 @@ 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)
15
14
  const worklogApi = getWorklogApi();
16
15
  if (!worklogApi) {
17
16
  return {
@@ -19,7 +18,7 @@ export async function submitWorklog(options = {}) {
19
18
  message: "No config found. Run `kalvium-worklog discover` first.",
20
19
  };
21
20
  }
22
- const payload = {
21
+ const body = JSON.stringify({
23
22
  title: STATUS_LABEL,
24
23
  description: STATUS_LABEL,
25
24
  category: STATUS_KEY,
@@ -27,15 +26,10 @@ export async function submitWorklog(options = {}) {
27
26
  priorityLevel: "medium",
28
27
  blockers: "",
29
28
  worklogs: JSON.stringify({ content: `<p>${text}</p>` }),
30
- };
31
- // Include worklogDate if backdating
32
- if (date) {
33
- payload.worklogDate = date;
34
- }
35
- const body = JSON.stringify(payload);
29
+ });
36
30
  if (dryRun) {
37
31
  console.log(`[DRY RUN] Would submit to ${worklogApi}`);
38
- console.log(` text='${text}', status=${STATUS_KEY}, date=${date ?? "today"}`);
32
+ console.log(` text='${text}', status=${STATUS_KEY}`);
39
33
  console.log(` Body: ${body}`);
40
34
  return { success: true, message: "Dry run" };
41
35
  }
@@ -276,98 +270,3 @@ export async function catchUpSubmit() {
276
270
  log("[INFO] Today's worklog is missing. Running catch-up submit...");
277
271
  return dailySubmit();
278
272
  }
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
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kalvium-worklog",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Auto-submit your daily Kalvium worklog without opening the website",
5
5
  "keywords": [
6
6
  "kalvium",