@knpkv/jira-clockify 0.2.0 → 0.5.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/README.md +4 -1
- package/dist/package.json +12 -13
- package/dist/src/bin.js +30 -13
- package/dist/src/bin.js.map +1 -1
- package/dist/src/cli/auth.js +23 -19
- package/dist/src/cli/auth.js.map +1 -1
- package/dist/src/cli/config.js +4 -4
- package/dist/src/cli/config.js.map +1 -1
- package/dist/src/cli/fetchTicket.js +30 -0
- package/dist/src/cli/fetchTicket.js.map +1 -0
- package/dist/src/cli/fuzzySelect.js +6 -5
- package/dist/src/cli/fuzzySelect.js.map +1 -1
- package/dist/src/cli/layers.js +10 -8
- package/dist/src/cli/layers.js.map +1 -1
- package/dist/src/cli/list.js +1 -1
- package/dist/src/cli/list.js.map +1 -1
- package/dist/src/cli/setup.js +19 -19
- package/dist/src/cli/setup.js.map +1 -1
- package/dist/src/cli/timer/discard.js +2 -2
- package/dist/src/cli/timer/discard.js.map +1 -1
- package/dist/src/cli/timer/edit.js +11 -11
- package/dist/src/cli/timer/edit.js.map +1 -1
- package/dist/src/cli/timer/log.js +56 -79
- package/dist/src/cli/timer/log.js.map +1 -1
- package/dist/src/cli/timer/start.js +56 -40
- package/dist/src/cli/timer/start.js.map +1 -1
- package/dist/src/cli/timer/status.js +7 -7
- package/dist/src/cli/timer/status.js.map +1 -1
- package/dist/src/cli/timer/stop.js +183 -59
- package/dist/src/cli/timer/stop.js.map +1 -1
- package/dist/src/main.js +15 -3
- package/dist/src/main.js.map +1 -1
- package/dist/src/services/ClockifyAuth.js +12 -23
- package/dist/src/services/ClockifyAuth.js.map +1 -1
- package/dist/src/services/ConfigService.js +7 -7
- package/dist/src/services/ConfigService.js.map +1 -1
- package/dist/src/services/HomeDirectory.js +14 -0
- package/dist/src/services/HomeDirectory.js.map +1 -0
- package/dist/src/services/StateWriter.js +8 -8
- package/dist/src/services/StateWriter.js.map +1 -1
- package/dist/src/services/TicketService.js +22 -15
- package/dist/src/services/TicketService.js.map +1 -1
- package/dist/src/services/TimerService.js +126 -60
- package/dist/src/services/TimerService.js.map +1 -1
- package/dist/src/tui/App.js +72 -8
- package/dist/src/tui/App.js.map +1 -1
- package/dist/src/tui/atoms/runtime.js +1 -1
- package/dist/src/tui/atoms/runtime.js.map +1 -1
- package/dist/src/tui/atoms/tickets.js +1 -1
- package/dist/src/tui/atoms/tickets.js.map +1 -1
- package/dist/src/tui/atoms/timer.js +7 -2
- package/dist/src/tui/atoms/timer.js.map +1 -1
- package/dist/src/tui/atoms/ui.js +1 -1
- package/dist/src/tui/atoms/ui.js.map +1 -1
- package/dist/src/tui/components/BigTimer.js +2 -2
- package/dist/src/tui/components/BigTimer.js.map +1 -1
- package/dist/src/tui/components/Footer.js +1 -1
- package/dist/src/tui/components/Footer.js.map +1 -1
- package/dist/src/tui/components/Header.js +3 -2
- package/dist/src/tui/components/Header.js.map +1 -1
- package/dist/src/tui/components/PopupMessage.js +7 -2
- package/dist/src/tui/components/PopupMessage.js.map +1 -1
- package/dist/src/tui/components/TicketList.js +3 -2
- package/dist/src/tui/components/TicketList.js.map +1 -1
- package/dist/src/tui/context/theme.js.map +1 -1
- package/dist/src/tui/hooks/useElapsedTimer.js +3 -2
- package/dist/src/tui/hooks/useElapsedTimer.js.map +1 -1
- package/dist/src/tui/hooks/useTerminalSize.js +1 -21
- package/dist/src/tui/hooks/useTerminalSize.js.map +1 -1
- package/dist/src/utils/time.js +55 -5
- package/dist/src/utils/time.js.map +1 -1
- package/dist/test/TimerService.test.js +224 -31
- package/dist/test/TimerService.test.js.map +1 -1
- package/dist/test/fetchTicket.test.js +89 -0
- package/dist/test/fetchTicket.test.js.map +1 -0
- package/dist/test/stopPrompts.test.js +93 -0
- package/dist/test/stopPrompts.test.js.map +1 -0
- package/dist/test/time.test.js +84 -0
- package/dist/test/time.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +16 -17
- package/skills/jcf/SKILL.md +89 -0
- package/skills/jcf/agents/openai.yaml +4 -0
|
@@ -3,26 +3,55 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
|
-
import { Args, Command, Options, Prompt } from "@effect/cli";
|
|
7
6
|
import { ClockifyApiClient } from "@knpkv/clockify-api-client";
|
|
8
|
-
import { JiraApiClient, toEffect } from "@knpkv/jira-api-client";
|
|
9
7
|
import { Console, Effect, Option, SubscriptionRef } from "effect";
|
|
8
|
+
import { Argument as Args, Command, Flag as Options, Prompt } from "effect/unstable/cli";
|
|
10
9
|
import { ClockifyAuth } from "../../services/ClockifyAuth.js";
|
|
11
10
|
import { ConfigService } from "../../services/ConfigService.js";
|
|
12
11
|
import { TicketService } from "../../services/TicketService.js";
|
|
13
12
|
import { TimerService } from "../../services/TimerService.js";
|
|
13
|
+
import { formatElapsed, parseDuration, parseStartTime } from "../../utils/time.js";
|
|
14
|
+
import { fetchTicketByKey, NOT_LOGGED_IN_HINT } from "../fetchTicket.js";
|
|
14
15
|
import { fuzzySelect } from "../fuzzySelect.js";
|
|
15
16
|
export const start = Command.make("start", {
|
|
16
|
-
key: Args.
|
|
17
|
-
project: Options.
|
|
17
|
+
key: Args.string("key").pipe(Args.optional),
|
|
18
|
+
project: Options.string("project").pipe(Options.withAlias("p"), Options.withDescription("Clockify project ID"), Options.optional),
|
|
18
19
|
billable: Options.boolean("billable").pipe(Options.withAlias("b"), Options.withDescription("Mark as billable"), Options.optional),
|
|
19
|
-
saveDefaults: Options.boolean("save-defaults").pipe(Options.withDescription("Save project/billable as defaults"), Options.withDefault(false))
|
|
20
|
-
|
|
20
|
+
saveDefaults: Options.boolean("save-defaults").pipe(Options.withDescription("Save project/billable as defaults"), Options.withDefault(false)),
|
|
21
|
+
ago: Options.string("ago").pipe(Options.withAlias("a"), Options.withDescription("Backdate the start by a duration (e.g. 15m, 1h30m) — corrects a forgotten start"), Options.optional),
|
|
22
|
+
since: Options.string("since").pipe(Options.withDescription("Backdate the start to a past time today (HH:MM) or an ISO timestamp"), Options.optional)
|
|
23
|
+
}, ({ ago, billable, key, project, saveDefaults, since }) => Effect.gen(function* () {
|
|
21
24
|
const timer = yield* TimerService;
|
|
22
25
|
const ticketService = yield* TicketService;
|
|
23
26
|
const cfg = yield* ConfigService;
|
|
24
27
|
const clockifyAuth = yield* ClockifyAuth;
|
|
25
28
|
const clockifyClient = yield* ClockifyApiClient;
|
|
29
|
+
// Resolve a backdated start, if requested. --ago wins over --since.
|
|
30
|
+
let startedAt;
|
|
31
|
+
if (Option.isSome(ago)) {
|
|
32
|
+
const secs = parseDuration(ago.value);
|
|
33
|
+
if (secs === null) {
|
|
34
|
+
yield* Console.log("Invalid --ago. Use a duration like 15m, 1h, 1h30m.");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (secs <= 0) {
|
|
38
|
+
yield* Console.log("--ago must be greater than zero (e.g. 15m, 1h).");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
startedAt = new Date(Date.now() - secs * 1000);
|
|
42
|
+
}
|
|
43
|
+
else if (Option.isSome(since)) {
|
|
44
|
+
const parsed = parseStartTime(since.value);
|
|
45
|
+
if (!parsed) {
|
|
46
|
+
yield* Console.log("Invalid --since. Use HH:MM (today) or an ISO timestamp.");
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (parsed.getTime() > Date.now()) {
|
|
50
|
+
yield* Console.log("--since is in the future. Pick a time at or before now.");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
startedAt = parsed;
|
|
54
|
+
}
|
|
26
55
|
// Check for running timer
|
|
27
56
|
yield* timer.detectRunning;
|
|
28
57
|
const currentState = yield* SubscriptionRef.get(timer.state);
|
|
@@ -60,7 +89,7 @@ export const start = Command.make("start", {
|
|
|
60
89
|
title: `${t.key.padEnd(12)} ${t.summary.slice(0, 45).padEnd(45)} [${t.status}]`,
|
|
61
90
|
value: t.key
|
|
62
91
|
}))
|
|
63
|
-
}).pipe(Effect.
|
|
92
|
+
}).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
64
93
|
if (!selectedKey)
|
|
65
94
|
return;
|
|
66
95
|
const found = allTickets.find((t) => t.key === selectedKey);
|
|
@@ -70,36 +99,20 @@ export const start = Command.make("start", {
|
|
|
70
99
|
}
|
|
71
100
|
else {
|
|
72
101
|
// Key provided — fetch from Jira to validate and get title
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
})).pipe(Effect.catchAll(() => Effect.succeed(null)));
|
|
80
|
-
if (!issue) {
|
|
102
|
+
const fetched = yield* fetchTicketByKey(key.value);
|
|
103
|
+
if (fetched._tag === "NotLoggedIn") {
|
|
104
|
+
yield* Console.log(NOT_LOGGED_IN_HINT);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (fetched._tag === "NotFound") {
|
|
81
108
|
yield* Console.log(`Ticket ${key.value} not found in Jira.`);
|
|
82
109
|
return;
|
|
83
110
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
ticket = {
|
|
90
|
-
key: issue.key ?? key.value,
|
|
91
|
-
summary: (typeof fields?.["summary"] === "string" ? fields["summary"] : null) ?? key.value,
|
|
92
|
-
status: (typeof nested("status", "name") === "string" ? nested("status", "name") : null) ??
|
|
93
|
-
"Unknown",
|
|
94
|
-
priority: typeof nested("priority", "name") === "string" ? nested("priority", "name") : null,
|
|
95
|
-
assignee: typeof nested("assignee", "displayName") === "string"
|
|
96
|
-
? nested("assignee", "displayName")
|
|
97
|
-
: null,
|
|
98
|
-
type: (typeof nested("issuetype", "name") === "string" ? nested("issuetype", "name") : null) ??
|
|
99
|
-
"Task",
|
|
100
|
-
labels: Array.isArray(fields?.["labels"]) ? fields["labels"] : [],
|
|
101
|
-
updated: (typeof fields?.["updated"] === "string" ? fields["updated"] : null) ?? new Date().toISOString()
|
|
102
|
-
};
|
|
111
|
+
if (fetched._tag === "FetchError") {
|
|
112
|
+
yield* Console.log(`Failed to fetch ticket ${key.value}: ${fetched.message}`);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
ticket = fetched.ticket;
|
|
103
116
|
yield* Console.log(`${ticket.key}: ${ticket.summary} [${ticket.status}]`);
|
|
104
117
|
}
|
|
105
118
|
// Resolve projectId
|
|
@@ -112,9 +125,9 @@ export const start = Command.make("start", {
|
|
|
112
125
|
}
|
|
113
126
|
else {
|
|
114
127
|
// Prompt: list projects
|
|
115
|
-
const auth = yield* clockifyAuth.getConfig.pipe(Effect.
|
|
128
|
+
const auth = yield* clockifyAuth.getConfig.pipe(Effect.catch(() => Effect.succeed(null)));
|
|
116
129
|
if (auth) {
|
|
117
|
-
const projects = yield* clockifyClient.getProjects(auth.workspaceId).pipe(Effect.
|
|
130
|
+
const projects = yield* clockifyClient.getProjects(auth.workspaceId).pipe(Effect.catch(() => Effect.succeed([])));
|
|
118
131
|
if (projects.length > 0) {
|
|
119
132
|
const selected = yield* Prompt.select({
|
|
120
133
|
message: "Select Clockify project:",
|
|
@@ -138,10 +151,10 @@ export const start = Command.make("start", {
|
|
|
138
151
|
}
|
|
139
152
|
// Save defaults if requested
|
|
140
153
|
if (saveDefaults && (projectId || billableVal !== undefined)) {
|
|
141
|
-
const auth = yield* clockifyAuth.getConfig.pipe(Effect.
|
|
154
|
+
const auth = yield* clockifyAuth.getConfig.pipe(Effect.catch(() => Effect.succeed(null)));
|
|
142
155
|
let projectName = null;
|
|
143
156
|
if (projectId && auth) {
|
|
144
|
-
const projects = yield* clockifyClient.getProjects(auth.workspaceId).pipe(Effect.
|
|
157
|
+
const projects = yield* clockifyClient.getProjects(auth.workspaceId).pipe(Effect.catch(() => Effect.succeed([])));
|
|
145
158
|
projectName = projects.find((p) => p.id === projectId)?.name ?? null;
|
|
146
159
|
}
|
|
147
160
|
yield* cfg.set({
|
|
@@ -150,7 +163,10 @@ export const start = Command.make("start", {
|
|
|
150
163
|
});
|
|
151
164
|
yield* Console.log("Defaults saved to ~/.jcf/config.json");
|
|
152
165
|
}
|
|
153
|
-
yield* timer.start(ticket, { projectId, billable: billableVal }).pipe(Effect.
|
|
154
|
-
|
|
166
|
+
yield* timer.start(ticket, { projectId, billable: billableVal, startedAt }).pipe(Effect.catch((e) => Console.log(`Error: ${e.message}`)));
|
|
167
|
+
const startedSuffix = startedAt
|
|
168
|
+
? ` (started ${formatElapsed(Math.floor((Date.now() - startedAt.getTime()) / 1000))} ago)`
|
|
169
|
+
: "";
|
|
170
|
+
yield* Console.log(`Timer started: ${ticket.key} — ${ticket.summary}${startedSuffix}`);
|
|
155
171
|
}));
|
|
156
172
|
//# sourceMappingURL=start.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../../src/cli/timer/start.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../../src/cli/timer/start.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
|
-
import { Command } from "@effect/cli";
|
|
7
6
|
import { ClockifyApiClient } from "@knpkv/clockify-api-client";
|
|
8
7
|
import { Console, Effect } from "effect";
|
|
8
|
+
import { Command } from "effect/unstable/cli";
|
|
9
9
|
import { ClockifyAuth } from "../../services/ClockifyAuth.js";
|
|
10
10
|
import { StateWriter } from "../../services/StateWriter.js";
|
|
11
11
|
export const statusCmd = Command.make("status", {}, () => Effect.gen(function* () {
|
|
@@ -15,12 +15,12 @@ export const statusCmd = Command.make("status", {}, () => Effect.gen(function* (
|
|
|
15
15
|
if (state.active) {
|
|
16
16
|
const clockifyAuth = yield* ClockifyAuth;
|
|
17
17
|
const clockifyClient = yield* ClockifyApiClient;
|
|
18
|
-
const auth = yield* clockifyAuth.getConfig.pipe(Effect.
|
|
18
|
+
const auth = yield* clockifyAuth.getConfig.pipe(Effect.catch(() => Effect.succeed(null)));
|
|
19
19
|
if (auth) {
|
|
20
20
|
let apiReachable = false;
|
|
21
21
|
const running = yield* clockifyClient.getRunningTimer(auth.workspaceId, auth.userId).pipe(Effect.tap(() => Effect.sync(() => {
|
|
22
22
|
apiReachable = true;
|
|
23
|
-
})), Effect.
|
|
23
|
+
})), Effect.catch(() => Effect.succeed(null)));
|
|
24
24
|
// Only clear if API was reachable and confirmed no running timer
|
|
25
25
|
if (apiReachable && !running) {
|
|
26
26
|
yield* stateWriter.clear;
|
|
@@ -52,20 +52,20 @@ export const statusCmd = Command.make("status", {}, () => Effect.gen(function* (
|
|
|
52
52
|
// Show project/billable from Clockify entry
|
|
53
53
|
const clockifyAuth = yield* ClockifyAuth;
|
|
54
54
|
const clockifyClient = yield* ClockifyApiClient;
|
|
55
|
-
const auth = yield* clockifyAuth.getConfig.pipe(Effect.
|
|
55
|
+
const auth = yield* clockifyAuth.getConfig.pipe(Effect.catch(() => Effect.succeed(null)));
|
|
56
56
|
if (auth && state.clockifyEntryId) {
|
|
57
|
-
const entry = yield* clockifyClient.getTimeEntry(auth.workspaceId, state.clockifyEntryId).pipe(Effect.
|
|
57
|
+
const entry = yield* clockifyClient.getTimeEntry(auth.workspaceId, state.clockifyEntryId).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
58
58
|
if (entry) {
|
|
59
59
|
let projectName = "none";
|
|
60
60
|
if (entry.projectId) {
|
|
61
|
-
const projects = yield* clockifyClient.getProjects(auth.workspaceId).pipe(Effect.
|
|
61
|
+
const projects = yield* clockifyClient.getProjects(auth.workspaceId).pipe(Effect.catch(() => Effect.succeed([])));
|
|
62
62
|
projectName = projects.find((p) => p.id === entry.projectId)?.name ?? entry.projectId;
|
|
63
63
|
}
|
|
64
64
|
yield* Console.log(` Project: ${projectName}`);
|
|
65
65
|
yield* Console.log(` Billable: ${entry.billable ? "yes" : "no"}`);
|
|
66
66
|
// Show tags
|
|
67
67
|
if (entry.tagIds && entry.tagIds.length > 0) {
|
|
68
|
-
const allTags = yield* clockifyClient.getTags(auth.workspaceId).pipe(Effect.
|
|
68
|
+
const allTags = yield* clockifyClient.getTags(auth.workspaceId).pipe(Effect.catch(() => Effect.succeed([])));
|
|
69
69
|
const tagNames = entry.tagIds
|
|
70
70
|
.map((id) => allTags.find((t) => t.id === id)?.name ?? id)
|
|
71
71
|
.join(", ");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../../src/cli/timer/status.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../../src/cli/timer/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,86 +3,196 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
|
-
import { Command, Options, Prompt } from "@effect/cli";
|
|
7
6
|
import { ClockifyApiClient } from "@knpkv/clockify-api-client";
|
|
8
7
|
import { Console, Duration, Effect, Option, SubscriptionRef } from "effect";
|
|
8
|
+
import { Command, Flag as Options, Prompt } from "effect/unstable/cli";
|
|
9
9
|
import { ClockifyAuth } from "../../services/ClockifyAuth.js";
|
|
10
10
|
import { ConfigService } from "../../services/ConfigService.js";
|
|
11
11
|
import { TimerService } from "../../services/TimerService.js";
|
|
12
|
+
import { formatDuration, parseDuration, parseStartTime } from "../../utils/time.js";
|
|
13
|
+
import { fetchTicketByKey, NOT_LOGGED_IN_HINT } from "../fetchTicket.js";
|
|
14
|
+
/**
|
|
15
|
+
* Interactively resolve a Clockify project for the stop/correction flows.
|
|
16
|
+
*
|
|
17
|
+
* Returns the project to use, or `undefined` to leave it unset. No prompt is
|
|
18
|
+
* shown when the project is already known (set on the running timer) or supplied
|
|
19
|
+
* via `--project`; in that case the provided value is passed straight through.
|
|
20
|
+
*
|
|
21
|
+
* When prompting, offers a "save as default" follow-up exactly like the normal
|
|
22
|
+
* stop path.
|
|
23
|
+
*/
|
|
24
|
+
export const resolveStopProject = (params) => Effect.gen(function* () {
|
|
25
|
+
if (params.currentProjectId || params.flagProjectId)
|
|
26
|
+
return params.flagProjectId;
|
|
27
|
+
const clockifyAuth = yield* ClockifyAuth;
|
|
28
|
+
const clockifyClient = yield* ClockifyApiClient;
|
|
29
|
+
const auth = yield* clockifyAuth.getConfig.pipe(Effect.catch(() => Effect.succeed(null)));
|
|
30
|
+
if (!auth)
|
|
31
|
+
return undefined;
|
|
32
|
+
const projects = yield* clockifyClient.getProjects(auth.workspaceId).pipe(Effect.catch(() => Effect.succeed([])));
|
|
33
|
+
if (projects.length === 0)
|
|
34
|
+
return undefined;
|
|
35
|
+
const selected = yield* Prompt.select({
|
|
36
|
+
message: "No project set. Select Clockify project:",
|
|
37
|
+
choices: [
|
|
38
|
+
...projects.map((p) => ({ title: p.name, value: p.id })),
|
|
39
|
+
{ title: "(skip)", value: "" }
|
|
40
|
+
]
|
|
41
|
+
});
|
|
42
|
+
if (!selected)
|
|
43
|
+
return undefined;
|
|
44
|
+
const selectedName = projects.find((p) => p.id === selected)?.name ?? selected;
|
|
45
|
+
const saveDefault = yield* Prompt.select({
|
|
46
|
+
message: `Save "${selectedName}" as default project?`,
|
|
47
|
+
choices: [
|
|
48
|
+
{ title: "Yes", value: true },
|
|
49
|
+
{ title: "No", value: false }
|
|
50
|
+
]
|
|
51
|
+
});
|
|
52
|
+
if (saveDefault) {
|
|
53
|
+
const cfg = yield* ConfigService;
|
|
54
|
+
yield* cfg.set({ defaultProjectId: selected, defaultProjectName: selectedName });
|
|
55
|
+
yield* Console.log("Default project saved.");
|
|
56
|
+
}
|
|
57
|
+
return selected;
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* Interactively resolve the billable flag for the stop/correction flows.
|
|
61
|
+
*
|
|
62
|
+
* Returns the billable value to use, or `undefined` to leave it unset. No prompt
|
|
63
|
+
* is shown when billable was already set on the running timer (`currentBillable`
|
|
64
|
+
* is non-null) or supplied via `--billable`; in that case the provided value is
|
|
65
|
+
* passed straight through.
|
|
66
|
+
*
|
|
67
|
+
* When prompting, offers a "save as default" follow-up exactly like the normal
|
|
68
|
+
* stop path.
|
|
69
|
+
*/
|
|
70
|
+
export const resolveStopBillable = (params) => Effect.gen(function* () {
|
|
71
|
+
if (params.currentBillable !== null || params.flagBillable !== undefined)
|
|
72
|
+
return params.flagBillable;
|
|
73
|
+
const stopBillable = yield* Prompt.select({
|
|
74
|
+
message: "Billable?",
|
|
75
|
+
choices: [
|
|
76
|
+
{ title: "Yes", value: true },
|
|
77
|
+
{ title: "No", value: false }
|
|
78
|
+
]
|
|
79
|
+
});
|
|
80
|
+
const saveDefault = yield* Prompt.select({
|
|
81
|
+
message: `Save billable=${stopBillable ? "yes" : "no"} as default?`,
|
|
82
|
+
choices: [
|
|
83
|
+
{ title: "Yes", value: true },
|
|
84
|
+
{ title: "No", value: false }
|
|
85
|
+
]
|
|
86
|
+
});
|
|
87
|
+
if (saveDefault) {
|
|
88
|
+
const cfg = yield* ConfigService;
|
|
89
|
+
yield* cfg.set({ defaultBillable: stopBillable });
|
|
90
|
+
yield* Console.log("Default billable saved.");
|
|
91
|
+
}
|
|
92
|
+
return stopBillable;
|
|
93
|
+
});
|
|
12
94
|
export const stop = Command.make("stop", {
|
|
13
|
-
project: Options.
|
|
95
|
+
project: Options.string("project").pipe(Options.withAlias("p"), Options.withDescription("Clockify project ID"), Options.optional),
|
|
14
96
|
billable: Options.boolean("billable").pipe(Options.withAlias("b"), Options.withDescription("Mark as billable"), Options.optional)
|
|
15
97
|
}, ({ billable, project }) => Effect.gen(function* () {
|
|
16
98
|
const timer = yield* TimerService;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (!current.projectId && !stopProjectId) {
|
|
25
|
-
const clockifyAuth = yield* ClockifyAuth;
|
|
26
|
-
const clockifyClient = yield* ClockifyApiClient;
|
|
27
|
-
const auth = yield* clockifyAuth.getConfig.pipe(Effect.catchAll(() => Effect.succeed(null)));
|
|
28
|
-
if (auth) {
|
|
29
|
-
const projects = yield* clockifyClient.getProjects(auth.workspaceId).pipe(Effect.catchAll(() => Effect.succeed([])));
|
|
30
|
-
if (projects.length > 0) {
|
|
31
|
-
const selected = yield* Prompt.select({
|
|
32
|
-
message: "No project set. Select Clockify project:",
|
|
33
|
-
choices: [
|
|
34
|
-
...projects.map((p) => ({ title: p.name, value: p.id })),
|
|
35
|
-
{ title: "(skip)", value: "" }
|
|
36
|
-
]
|
|
37
|
-
});
|
|
38
|
-
if (selected) {
|
|
39
|
-
stopProjectId = selected;
|
|
40
|
-
const selectedName = projects.find((p) => p.id === selected)?.name ?? selected;
|
|
41
|
-
const saveDefault = yield* Prompt.select({
|
|
42
|
-
message: `Save "${selectedName}" as default project?`,
|
|
43
|
-
choices: [
|
|
44
|
-
{ title: "Yes", value: true },
|
|
45
|
-
{ title: "No", value: false }
|
|
46
|
-
]
|
|
47
|
-
});
|
|
48
|
-
if (saveDefault) {
|
|
49
|
-
const cfg = yield* ConfigService;
|
|
50
|
-
yield* cfg.set({ defaultProjectId: stopProjectId, defaultProjectName: selectedName });
|
|
51
|
-
yield* Console.log("Default project saved.");
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
// Prompt for billable if not set
|
|
58
|
-
if (current.billable === null && stopBillable === undefined) {
|
|
59
|
-
stopBillable = yield* Prompt.select({
|
|
60
|
-
message: "Billable?",
|
|
99
|
+
const flagProjectId = Option.isSome(project) ? project.value : undefined;
|
|
100
|
+
const flagBillable = Option.isSome(billable) ? billable.value : undefined;
|
|
101
|
+
// Correction flow: log a completed interval when no timer was ever started.
|
|
102
|
+
// Reuses the same project/billable prompts as the normal stop path below.
|
|
103
|
+
const runCorrection = Effect.gen(function* () {
|
|
104
|
+
const proceed = yield* Prompt.select({
|
|
105
|
+
message: "No active timer. Add a correction interval instead?",
|
|
61
106
|
choices: [
|
|
62
107
|
{ title: "Yes", value: true },
|
|
63
108
|
{ title: "No", value: false }
|
|
64
109
|
]
|
|
65
110
|
});
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
111
|
+
if (!proceed) {
|
|
112
|
+
yield* Console.log("No active timer.");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const key = (yield* Prompt.text({ message: "Ticket key (e.g. PROJ-123):" })).trim();
|
|
116
|
+
if (!key) {
|
|
117
|
+
yield* Console.log("No ticket key given.");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const fetched = yield* fetchTicketByKey(key);
|
|
121
|
+
if (fetched._tag === "NotLoggedIn") {
|
|
122
|
+
yield* Console.log(NOT_LOGGED_IN_HINT);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (fetched._tag === "NotFound") {
|
|
126
|
+
yield* Console.log(`Ticket ${key} not found in Jira.`);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (fetched._tag === "FetchError") {
|
|
130
|
+
yield* Console.log(`Failed to fetch ticket ${key}: ${fetched.message}`);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const ticket = fetched.ticket;
|
|
134
|
+
const durationStr = yield* Prompt.text({ message: "Duration (e.g. 45m, 1h30m):" });
|
|
135
|
+
const durationSeconds = parseDuration(durationStr);
|
|
136
|
+
if (durationSeconds === null || durationSeconds < 60) {
|
|
137
|
+
yield* Console.log("Invalid duration. Use format: 45m, 1h30m (minimum 1m).");
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const whenStr = (yield* Prompt.text({
|
|
141
|
+
message: "Started at (HH:MM today or ISO, empty = ends now):"
|
|
142
|
+
})).trim();
|
|
143
|
+
let start;
|
|
144
|
+
if (!whenStr) {
|
|
145
|
+
start = new Date(Date.now() - durationSeconds * 1000);
|
|
77
146
|
}
|
|
147
|
+
else {
|
|
148
|
+
const parsed = parseStartTime(whenStr);
|
|
149
|
+
if (!parsed) {
|
|
150
|
+
yield* Console.log("Invalid start time. Use HH:MM (today) or an ISO timestamp.");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
start = parsed;
|
|
154
|
+
}
|
|
155
|
+
// Same interactive project/billable prompts as a normal stop (with
|
|
156
|
+
// save-as-default). No running timer here, so there is nothing prefilled.
|
|
157
|
+
const correctionProjectId = yield* resolveStopProject({ currentProjectId: null, flagProjectId });
|
|
158
|
+
const correctionBillable = yield* resolveStopBillable({ currentBillable: null, flagBillable });
|
|
159
|
+
const correctionComment = (yield* Prompt.text({ message: "Comment (empty to skip):" })).trim();
|
|
160
|
+
yield* Console.log(`Correction: ${ticket.key} — ${ticket.summary}`);
|
|
161
|
+
yield* Console.log(` Duration: ${formatDuration(durationSeconds)}`);
|
|
162
|
+
yield* Console.log(` Started: ${start.toISOString()}`);
|
|
163
|
+
const result = yield* timer.logManual(ticket, {
|
|
164
|
+
start,
|
|
165
|
+
durationSeconds,
|
|
166
|
+
projectId: correctionProjectId,
|
|
167
|
+
billable: correctionBillable,
|
|
168
|
+
comment: correctionComment || undefined
|
|
169
|
+
}).pipe(Effect.catch((e) => Console.log(`Error: ${e.message}`).pipe(Effect.as(null))));
|
|
170
|
+
if (result) {
|
|
171
|
+
yield* Console.log(` Clockify: ${result.clockifyLogged ? "✓" : "✗"}`);
|
|
172
|
+
yield* Console.log(` Jira worklog: ${result.jiraWorklogLogged ? "✓" : "✗"}`);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
yield* timer.detectRunning;
|
|
176
|
+
// No running timer: offer to log a correction interval (forgot to start it).
|
|
177
|
+
const detected = yield* SubscriptionRef.get(timer.state);
|
|
178
|
+
if (!detected.active) {
|
|
179
|
+
yield* runCorrection;
|
|
180
|
+
return;
|
|
78
181
|
}
|
|
182
|
+
// Check if project/billable need to be set
|
|
183
|
+
const currentTimer = yield* SubscriptionRef.get(timer.state);
|
|
184
|
+
const current = { projectId: currentTimer.projectId, billable: currentTimer.billable };
|
|
185
|
+
// Prompt for project if not set on start and not provided via flag.
|
|
186
|
+
const stopProjectId = yield* resolveStopProject({ currentProjectId: current.projectId, flagProjectId });
|
|
187
|
+
// Prompt for billable if not set.
|
|
188
|
+
const stopBillable = yield* resolveStopBillable({ currentBillable: current.billable, flagBillable });
|
|
79
189
|
// Optional comment for Jira worklog
|
|
80
190
|
const comment = yield* Prompt.text({ message: "Comment (empty to skip):" });
|
|
81
191
|
const result = yield* timer.stop({
|
|
82
192
|
projectId: stopProjectId,
|
|
83
193
|
billable: stopBillable,
|
|
84
194
|
comment: comment.trim() || undefined
|
|
85
|
-
}).pipe(Effect.
|
|
195
|
+
}).pipe(Effect.catch((e) => Console.log(`Error: ${e.message}`).pipe(Effect.flatMap(() => Effect.succeed(null)))));
|
|
86
196
|
if (result) {
|
|
87
197
|
const secs = Duration.toSeconds(result.duration);
|
|
88
198
|
const h = Math.floor(secs / 3600);
|
|
@@ -90,7 +200,21 @@ export const stop = Command.make("stop", {
|
|
|
90
200
|
const s = Math.floor(secs % 60);
|
|
91
201
|
yield* Console.log(`Timer stopped: ${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`);
|
|
92
202
|
yield* Console.log(` Clockify: ${result.clockifyLogged ? "✓" : "✗"}`);
|
|
93
|
-
|
|
203
|
+
// Clockify saved but the Jira worklog failed — offer to retry just the worklog.
|
|
204
|
+
// The Clockify entry stays put, so retrying never double-logs time there.
|
|
205
|
+
let jiraLogged = result.jiraWorklogLogged;
|
|
206
|
+
if (!jiraLogged && result.worklog) {
|
|
207
|
+
const worklog = result.worklog;
|
|
208
|
+
let retry = yield* Prompt.confirm({ message: " Jira worklog: ✗ — retry?", initial: true });
|
|
209
|
+
while (retry) {
|
|
210
|
+
jiraLogged = yield* timer.logWorklog(worklog);
|
|
211
|
+
if (jiraLogged)
|
|
212
|
+
break;
|
|
213
|
+
// Default the re-prompt to No: if a retry just failed, don't keep nudging Yes.
|
|
214
|
+
retry = yield* Prompt.confirm({ message: " Jira worklog: ✗ — retry again?", initial: false });
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
yield* Console.log(` Jira worklog: ${jiraLogged ? "✓" : result.worklog ? "✗" : "skipped"}`);
|
|
94
218
|
}
|
|
95
219
|
}));
|
|
96
220
|
//# sourceMappingURL=stop.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stop.js","sourceRoot":"","sources":["../../../../src/cli/timer/stop.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"stop.js","sourceRoot":"","sources":["../../../../src/cli/timer/stop.ts"],"names":[],"mappings":"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"}
|