@knpkv/jira-clockify 0.2.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 (92) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +121 -0
  3. package/dist/package.json +47 -0
  4. package/dist/src/bin.js +28 -0
  5. package/dist/src/bin.js.map +1 -0
  6. package/dist/src/cli/auth.js +169 -0
  7. package/dist/src/cli/auth.js.map +1 -0
  8. package/dist/src/cli/config.js +107 -0
  9. package/dist/src/cli/config.js.map +1 -0
  10. package/dist/src/cli/fuzzySelect.js +149 -0
  11. package/dist/src/cli/fuzzySelect.js.map +1 -0
  12. package/dist/src/cli/layers.js +59 -0
  13. package/dist/src/cli/layers.js.map +1 -0
  14. package/dist/src/cli/list.js +27 -0
  15. package/dist/src/cli/list.js.map +1 -0
  16. package/dist/src/cli/setup.js +134 -0
  17. package/dist/src/cli/setup.js.map +1 -0
  18. package/dist/src/cli/timer/discard.js +33 -0
  19. package/dist/src/cli/timer/discard.js.map +1 -0
  20. package/dist/src/cli/timer/edit.js +139 -0
  21. package/dist/src/cli/timer/edit.js.map +1 -0
  22. package/dist/src/cli/timer/index.js +12 -0
  23. package/dist/src/cli/timer/index.js.map +1 -0
  24. package/dist/src/cli/timer/log.js +96 -0
  25. package/dist/src/cli/timer/log.js.map +1 -0
  26. package/dist/src/cli/timer/start.js +156 -0
  27. package/dist/src/cli/timer/start.js.map +1 -0
  28. package/dist/src/cli/timer/status.js +80 -0
  29. package/dist/src/cli/timer/status.js.map +1 -0
  30. package/dist/src/cli/timer/stop.js +96 -0
  31. package/dist/src/cli/timer/stop.js.map +1 -0
  32. package/dist/src/cli/timer.js +7 -0
  33. package/dist/src/cli/timer.js.map +1 -0
  34. package/dist/src/main.js +24 -0
  35. package/dist/src/main.js.map +1 -0
  36. package/dist/src/services/ClockifyAuth.js +77 -0
  37. package/dist/src/services/ClockifyAuth.js.map +1 -0
  38. package/dist/src/services/ConfigService.js +66 -0
  39. package/dist/src/services/ConfigService.js.map +1 -0
  40. package/dist/src/services/StateWriter.js +69 -0
  41. package/dist/src/services/StateWriter.js.map +1 -0
  42. package/dist/src/services/TicketService.js +106 -0
  43. package/dist/src/services/TicketService.js.map +1 -0
  44. package/dist/src/services/TimerService.js +271 -0
  45. package/dist/src/services/TimerService.js.map +1 -0
  46. package/dist/src/tui/App.js +204 -0
  47. package/dist/src/tui/App.js.map +1 -0
  48. package/dist/src/tui/atoms/runtime.js +9 -0
  49. package/dist/src/tui/atoms/runtime.js.map +1 -0
  50. package/dist/src/tui/atoms/tickets.js +17 -0
  51. package/dist/src/tui/atoms/tickets.js.map +1 -0
  52. package/dist/src/tui/atoms/timer.js +31 -0
  53. package/dist/src/tui/atoms/timer.js.map +1 -0
  54. package/dist/src/tui/atoms/ui.js +10 -0
  55. package/dist/src/tui/atoms/ui.js.map +1 -0
  56. package/dist/src/tui/components/BigTimer.js +60 -0
  57. package/dist/src/tui/components/BigTimer.js.map +1 -0
  58. package/dist/src/tui/components/Footer.js +16 -0
  59. package/dist/src/tui/components/Footer.js.map +1 -0
  60. package/dist/src/tui/components/Header.js +16 -0
  61. package/dist/src/tui/components/Header.js.map +1 -0
  62. package/dist/src/tui/components/PopupInput.js +30 -0
  63. package/dist/src/tui/components/PopupInput.js.map +1 -0
  64. package/dist/src/tui/components/PopupMessage.js +47 -0
  65. package/dist/src/tui/components/PopupMessage.js.map +1 -0
  66. package/dist/src/tui/components/TicketList.js +40 -0
  67. package/dist/src/tui/components/TicketList.js.map +1 -0
  68. package/dist/src/tui/components/TicketRow.js +48 -0
  69. package/dist/src/tui/components/TicketRow.js.map +1 -0
  70. package/dist/src/tui/components/TimerDisplay.js +30 -0
  71. package/dist/src/tui/components/TimerDisplay.js.map +1 -0
  72. package/dist/src/tui/components/index.js +12 -0
  73. package/dist/src/tui/components/index.js.map +1 -0
  74. package/dist/src/tui/context/theme.js +15 -0
  75. package/dist/src/tui/context/theme.js.map +1 -0
  76. package/dist/src/tui/hooks/useElapsedTimer.js +35 -0
  77. package/dist/src/tui/hooks/useElapsedTimer.js.map +1 -0
  78. package/dist/src/tui/hooks/useTerminalSize.js +32 -0
  79. package/dist/src/tui/hooks/useTerminalSize.js.map +1 -0
  80. package/dist/src/utils/time.js +23 -0
  81. package/dist/src/utils/time.js.map +1 -0
  82. package/dist/test/TimerService.test.js +355 -0
  83. package/dist/test/TimerService.test.js.map +1 -0
  84. package/dist/tsconfig.tsbuildinfo +1 -0
  85. package/nvim/lua/jcf/branch.lua +26 -0
  86. package/nvim/lua/jcf/float.lua +87 -0
  87. package/nvim/lua/jcf/init.lua +70 -0
  88. package/nvim/lua/jcf/state.lua +56 -0
  89. package/nvim/lua/jcf/statusline.lua +31 -0
  90. package/nvim/lua/jcf/telescope.lua +50 -0
  91. package/nvim/plugin/jcf.vim +2 -0
  92. package/package.json +47 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 knpkv
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # @knpkv/jira-clockify
2
+
3
+ TUI time tracker bridging Jira and Clockify. Start/stop timers on Jira tickets, auto-log worklogs to both services. Includes Neovim integration.
4
+
5
+ Built with Effect-TS and [@opentui/react](https://github.com/anomalyco/opentui).
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pnpm add @knpkv/jira-clockify
11
+ ```
12
+
13
+ Or link globally:
14
+
15
+ ```bash
16
+ cd packages/jira-clockify && pnpm link --global
17
+ ```
18
+
19
+ ## Setup
20
+
21
+ ### 1. Jira OAuth
22
+
23
+ ```bash
24
+ jcf auth jira create # Opens Atlassian console — create OAuth 2.0 app
25
+ jcf auth jira configure # Set client ID and secret
26
+ jcf auth jira login # Authenticate via browser
27
+ ```
28
+
29
+ ### 2. Clockify API Key
30
+
31
+ ```bash
32
+ jcf auth clockify setup # Enter API key from https://app.clockify.me/manage-api-keys
33
+ ```
34
+
35
+ ### 3. Configure Defaults
36
+
37
+ ```bash
38
+ jcf config set project # Select default Clockify project
39
+ jcf config set billable # Set default billable flag
40
+ jcf config set jql <jql> # Set default JQL filter
41
+ jcf config show # Show current config
42
+ jcf config reset # Reset to defaults
43
+ ```
44
+
45
+ ## CLI Commands
46
+
47
+ ```bash
48
+ jcf # Launch TUI (or guided setup if not configured)
49
+ jcf tui # Launch TUI explicitly
50
+ jcf start [ISSUE-KEY] # Start timer on a Jira ticket
51
+ jcf stop # Stop timer, log to Clockify + Jira
52
+ jcf discard # Discard timer (delete Clockify entry, no Jira worklog)
53
+ jcf log # Log past work manually
54
+ jcf edit # Edit running timer
55
+ jcf status # Show current timer status
56
+ jcf list [--json] # List Jira tickets from configured JQL
57
+ jcf auth status # Show auth status for both services
58
+ ```
59
+
60
+ ## TUI Keybindings
61
+
62
+ | Key | Action |
63
+ | ------------- | -------------------------------- |
64
+ | `j` / `k` | Navigate ticket list |
65
+ | `s` / `Enter` | Start timer on selected ticket |
66
+ | `x` | Stop timer (with comment prompt) |
67
+ | `d` | Discard timer |
68
+ | `l` / `Tab` | Toggle between timer and tickets |
69
+ | `/` / `f` | Filter tickets |
70
+ | `r` | Refresh ticket list |
71
+ | `q` | Quit |
72
+ | `Ctrl+C` | Force quit |
73
+
74
+ ## Neovim Plugin
75
+
76
+ Ships with a Lua plugin in `nvim/lua/jcf/`. Auto-detects Jira issue keys from branch names.
77
+
78
+ ### lazy.nvim
79
+
80
+ ```lua
81
+ {
82
+ dir = "path/to/packages/jira-clockify",
83
+ config = function()
84
+ require("jcf").setup({
85
+ binary = "jcf", -- path to jcf binary
86
+ auto_detect_branch = true, -- detect issue key from git branch
87
+ float = { width = 0.8, height = 0.8 },
88
+ poll_interval = 30000, -- ms, poll Clockify for external changes
89
+ })
90
+ end,
91
+ }
92
+ ```
93
+
94
+ ### Neovim Commands
95
+
96
+ | Command | Description |
97
+ | ------------- | --------------------------------------------------- |
98
+ | `:JcfToggle` | Toggle jcf floating terminal |
99
+ | `:JcfStart` | Start timer (auto-detects branch or opens selector) |
100
+ | `:JcfStop` | Stop timer (opens float for comment) |
101
+ | `:JcfDiscard` | Discard timer |
102
+ | `:JcfLog` | Log past work |
103
+ | `:JcfEdit` | Edit running timer |
104
+ | `:JcfStatus` | Show timer status |
105
+
106
+ ## Config
107
+
108
+ Stored in `~/.jcf/`:
109
+
110
+ ```
111
+ ~/.jcf/
112
+ ├── config.json # JQL, project, billable defaults
113
+ ├── clockify.json # Clockify API key, workspace, user
114
+ └── state.json # Current timer state
115
+ ```
116
+
117
+ Jira OAuth credentials stored via `@knpkv/atlassian-common` in `~/.config/atlassian/`.
118
+
119
+ ## License
120
+
121
+ MIT
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@knpkv/jira-clockify",
3
+ "version": "0.2.0",
4
+ "description": "TUI for Jira-Clockify time tracking, attachable to neovim",
5
+ "license": "MIT",
6
+ "author": "knpkv",
7
+ "type": "module",
8
+ "bin": {
9
+ "jcf": "dist/src/bin.js"
10
+ },
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "nvim"
17
+ ],
18
+ "scripts": {
19
+ "start": "tsx src/bin.ts",
20
+ "build": "tsc -b && chmod +x dist/src/bin.js",
21
+ "check": "tsc -b tsconfig.json",
22
+ "test": "vitest",
23
+ "lint": "eslint \"{src,test}/**/*.{ts,tsx}\""
24
+ },
25
+ "dependencies": {
26
+ "@effect-atom/atom": "latest",
27
+ "@effect-atom/atom-react": "latest",
28
+ "@effect/cli": "latest",
29
+ "@effect/platform": "latest",
30
+ "@effect/platform-node": "latest",
31
+ "@knpkv/atlassian-common": "workspace:^",
32
+ "@knpkv/clockify-api-client": "workspace:^",
33
+ "@knpkv/jira-api-client": "workspace:^",
34
+ "@knpkv/jira-cli": "workspace:^",
35
+ "@opentui/core": "https://pkg.pr.new/anomalyco/opentui/@opentui/core@367a94087821b3b5feedd35bbb57df43b10a286e",
36
+ "@opentui/react": "https://pkg.pr.new/anomalyco/opentui/@opentui/react@367a94087821b3b5feedd35bbb57df43b10a286e",
37
+ "effect": "latest",
38
+ "react": "^19.1.0"
39
+ },
40
+ "devDependencies": {
41
+ "@effect/vitest": "latest",
42
+ "@types/node": "latest",
43
+ "@types/react": "^19.1.8",
44
+ "tsx": "^4.19.4",
45
+ "vitest": "latest"
46
+ }
47
+ }
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI entry point for jcf — assembles root command and runs via `NodeRuntime.runMain`.
4
+ *
5
+ * @module
6
+ */
7
+ import { Command } from "@effect/cli";
8
+ import { NodeRuntime } from "@effect/platform-node";
9
+ import { Effect, Logger, LogLevel } from "effect";
10
+ import nodeProcess from "node:process";
11
+ import { auth } from "./cli/auth.js";
12
+ import { config } from "./cli/config.js";
13
+ import { HeadlessLayer } from "./cli/layers.js";
14
+ import { list } from "./cli/list.js";
15
+ import { launchTuiOrSetup } from "./cli/setup.js";
16
+ import { discard, edit, log, start, statusCmd, stop } from "./cli/timer.js";
17
+ // Capture argv once at the edge — only Node process usage in the codebase
18
+ const argv = nodeProcess.argv;
19
+ const tui = Command.make("tui", {}, () => launchTuiOrSetup(argv));
20
+ const root = Command.make("jcf", {}, () => launchTuiOrSetup(argv)).pipe(Command.withSubcommands([tui, auth, start, stop, discard, log, statusCmd, list, config, edit]));
21
+ const cli = Command.run(root, {
22
+ name: "jcf",
23
+ version: "0.1.0"
24
+ });
25
+ // @effect/cli provides --log-level built-in (none, debug, info, warning, error)
26
+ // Default to suppressing logs; use --log-level debug for verbose output
27
+ Effect.suspend(() => cli(argv)).pipe(Logger.withMinimumLogLevel(LogLevel.Warning), Effect.provide(HeadlessLayer), NodeRuntime.runMain);
28
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../../src/bin.ts"],"names":[],"mappings":";AACA;;;;GAIG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AACjD,OAAO,WAAW,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAE3E,0EAA0E;AAC1E,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAA;AAE7B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAA;AAEjE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CACrE,OAAO,CAAC,eAAe,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAC/F,CAAA;AAED,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE;IAC5B,IAAI,EAAE,KAAK;IACX,OAAO,EAAE,OAAO;CACjB,CAAC,CAAA;AAEF,gFAAgF;AAChF,wEAAwE;AACxE,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAClC,MAAM,CAAC,mBAAmB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAC5C,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAC7B,WAAW,CAAC,OAAO,CACpB,CAAA"}
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Auth commands: jira (create/configure/login/logout/status), clockify (setup/status), combined status.
3
+ *
4
+ * @module
5
+ */
6
+ import { Command, Options, Prompt } from "@effect/cli";
7
+ import * as PlatformCommand from "@effect/platform/Command";
8
+ import * as CommandExecutor from "@effect/platform/CommandExecutor";
9
+ import { makeOpenApiFetchClient, toEffect } from "@knpkv/clockify-api-client";
10
+ import { JiraAuth } from "@knpkv/jira-cli/JiraAuth";
11
+ import { Console, Effect, Layer, Option } from "effect";
12
+ import { ClockifyAuth } from "../services/ClockifyAuth.js";
13
+ // ---------------------------------------------------------------------------
14
+ // Jira OAuth
15
+ // ---------------------------------------------------------------------------
16
+ const jiraCreate = Command.make("create", {}, () => Effect.gen(function* () {
17
+ yield* Console.log(`
18
+ Create OAuth app in Atlassian Developer Console:
19
+
20
+ 1. Browser will open to create a new OAuth 2.0 (3LO) app
21
+ 2. Enter app name (e.g., "jcf")
22
+ 3. Go to "Permissions" → add Jira API:
23
+ - read:jira-work
24
+ - write:jira-work
25
+ - read:jira-user
26
+ And User Identity API:
27
+ - read:me
28
+ 4. Go to "Authorization" → callback URL: http://localhost:8585/callback
29
+ 5. Go to "Settings" → copy Client ID and Secret
30
+ 6. Run: jcf auth jira configure
31
+ `);
32
+ const url = "https://developer.atlassian.com/console/myapps/create-3lo-app/";
33
+ const executor = yield* CommandExecutor.CommandExecutor;
34
+ yield* PlatformCommand.make("open", url).pipe(PlatformCommand.exitCode, Effect.catchAll(() => PlatformCommand.make("xdg-open", url).pipe(PlatformCommand.exitCode)), Effect.catchAll(() => PlatformCommand.make("cmd", "/c", "start", "", url).pipe(PlatformCommand.exitCode)), Effect.provide(Layer.succeed(CommandExecutor.CommandExecutor, executor)), Effect.asVoid, Effect.catchAll(() => Effect.void));
35
+ }));
36
+ const jiraConfigure = Command.make("configure", {
37
+ clientId: Options.text("client-id").pipe(Options.withDescription("OAuth client ID"), Options.optional),
38
+ clientSecret: Options.text("client-secret").pipe(Options.withDescription("OAuth client secret"), Options.optional)
39
+ }, ({ clientId, clientSecret }) => Effect.gen(function* () {
40
+ const auth = yield* JiraAuth;
41
+ const id = Option.isSome(clientId)
42
+ ? clientId.value
43
+ : yield* Prompt.text({ message: "Enter OAuth client ID:" });
44
+ const secret = Option.isSome(clientSecret)
45
+ ? clientSecret.value
46
+ : yield* Prompt.text({ message: "Enter OAuth client secret:" });
47
+ yield* auth.configure({ clientId: id, clientSecret: secret });
48
+ yield* Console.log("OAuth configured. Run: jcf auth jira login");
49
+ }));
50
+ const jiraLogin = Command.make("login", { site: Options.text("site").pipe(Options.withDescription("Jira site URL"), Options.optional) }, ({ site }) => Effect.gen(function* () {
51
+ const auth = yield* JiraAuth;
52
+ const result = yield* auth.login(Option.isSome(site) ? { siteUrl: site.value } : undefined);
53
+ if (Array.isArray(result) && result.length > 0) {
54
+ yield* Console.log("\nRe-run with --site <url> to select a specific site.");
55
+ }
56
+ }).pipe(Effect.catchAll((e) => Console.log(`Error: ${"message" in e ? e.message : String(e)}`))));
57
+ const jiraLogout = Command.make("logout", {}, () => Effect.gen(function* () {
58
+ const auth = yield* JiraAuth;
59
+ yield* auth.logout();
60
+ yield* Console.log("Logged out from Jira");
61
+ }).pipe(Effect.catchAll((e) => Console.log(`Error: ${"message" in e ? e.message : String(e)}`))));
62
+ const jiraStatus = Command.make("status", {}, () => Effect.gen(function* () {
63
+ const auth = yield* JiraAuth;
64
+ const user = yield* auth.getCurrentUser();
65
+ if (user) {
66
+ yield* Console.log(`Jira: ✓ logged in as ${user.name} (${user.email})`);
67
+ }
68
+ else {
69
+ yield* Console.log("Jira: ✗ not logged in");
70
+ yield* Console.log(" Run: jcf auth jira create → configure → login");
71
+ }
72
+ }).pipe(Effect.catchAll(() => Console.log("Jira: ✗ not configured"))));
73
+ const authJira = Command.make("jira", {}, () => Console.log("Jira auth: create, configure, login, logout, status"))
74
+ .pipe(Command.withSubcommands([jiraCreate, jiraConfigure, jiraLogin, jiraLogout, jiraStatus]));
75
+ // ---------------------------------------------------------------------------
76
+ // Clockify API key
77
+ // ---------------------------------------------------------------------------
78
+ export const clockifySetup = Command.make("setup", {}, () => Effect.gen(function* () {
79
+ const auth = yield* ClockifyAuth;
80
+ yield* Console.log("Clockify API Key Setup");
81
+ yield* Console.log("Get your API key from: https://app.clockify.me/manage-api-keys");
82
+ yield* Console.log("");
83
+ const apiKey = yield* Prompt.text({ message: "Enter API key:" });
84
+ if (!apiKey) {
85
+ yield* Console.log("No API key provided, aborting.");
86
+ return;
87
+ }
88
+ yield* Console.log("Validating...");
89
+ // Create a temporary openapi-fetch client with the entered key
90
+ const { client } = makeOpenApiFetchClient("https://api.clockify.me/api", {
91
+ "X-Api-Key": apiKey,
92
+ "Content-Type": "application/json"
93
+ });
94
+ const user = yield* toEffect(client.GET("/v1/user")).pipe(Effect.catchAll(() => Effect.fail(new Error("Invalid API key — check the value and try again"))));
95
+ yield* Console.log(`Authenticated as: ${user.name} (${user.email})`);
96
+ const workspaces = yield* toEffect(client.GET("/v1/workspaces")).pipe(Effect.catchAll(() => Effect.succeed([])));
97
+ if (workspaces.length === 0) {
98
+ yield* Console.log("No workspaces found.");
99
+ return;
100
+ }
101
+ yield* Console.log("");
102
+ yield* Console.log("Workspaces:");
103
+ for (let i = 0; i < workspaces.length; i++) {
104
+ yield* Console.log(` ${i + 1}. ${workspaces[i].name}`);
105
+ }
106
+ let selectedIdx = 0;
107
+ if (workspaces.length > 1) {
108
+ const choice = yield* Prompt.text({ message: `Select workspace (1-${workspaces.length}):` });
109
+ selectedIdx = Math.max(0, Math.min(workspaces.length - 1, parseInt(choice, 10) - 1));
110
+ }
111
+ const workspace = workspaces[selectedIdx];
112
+ yield* Console.log(`Selected: ${workspace.name}`);
113
+ yield* auth.save({
114
+ apiKey,
115
+ workspaceId: workspace.id,
116
+ userId: user.id,
117
+ baseUrl: "https://api.clockify.me/api"
118
+ });
119
+ yield* Console.log("");
120
+ yield* Console.log("Clockify configured! Saved to ~/.jcf/clockify.json");
121
+ }).pipe(Effect.catchAll((e) => Console.log(`Error: ${"message" in e ? e.message : String(e)}`))));
122
+ const clockifyStatus = Command.make("status", {}, () => Effect.gen(function* () {
123
+ const auth = yield* ClockifyAuth;
124
+ const configured = yield* auth.isConfigured;
125
+ if (!configured) {
126
+ yield* Console.log("Clockify: ✗ not configured");
127
+ yield* Console.log(" Run: jcf auth clockify setup");
128
+ return;
129
+ }
130
+ const config = yield* auth.getConfig.pipe(Effect.catchAll((e) => Console.log(`Clockify: error — ${e.message}`).pipe(Effect.flatMap(() => Effect.fail(e)))));
131
+ yield* Console.log("Clockify: ✓ authenticated");
132
+ yield* Console.log(` Workspace: ${config.workspaceId}`);
133
+ yield* Console.log(` User: ${config.userId}`);
134
+ }).pipe(Effect.catchAll(() => Effect.void)));
135
+ const authClockify = Command.make("clockify", {}, () => Console.log("Clockify auth: setup, status")).pipe(Command.withSubcommands([clockifySetup, clockifyStatus]));
136
+ // ---------------------------------------------------------------------------
137
+ // Combined status
138
+ // ---------------------------------------------------------------------------
139
+ const authStatus = Command.make("status", {}, () => Effect.gen(function* () {
140
+ yield* Console.log("=== Auth Status ===");
141
+ yield* Console.log("");
142
+ // Jira
143
+ const jira = yield* JiraAuth;
144
+ const jiraUser = yield* jira.getCurrentUser().pipe(Effect.catchAll(() => Effect.succeed(null)));
145
+ if (jiraUser) {
146
+ yield* Console.log(`Jira: ✓ ${jiraUser.name} (${jiraUser.email})`);
147
+ }
148
+ else {
149
+ yield* Console.log("Jira: ✗ not logged in");
150
+ }
151
+ // Clockify
152
+ const clockifyAuth = yield* ClockifyAuth;
153
+ const clockifyOk = yield* clockifyAuth.isConfigured;
154
+ if (clockifyOk) {
155
+ const cfg = yield* clockifyAuth.getConfig.pipe(Effect.catchAll(() => Effect.succeed(null)));
156
+ if (cfg) {
157
+ yield* Console.log(`Clockify: ✓ workspace ${cfg.workspaceId}`);
158
+ }
159
+ else {
160
+ yield* Console.log("Clockify: ✗ config corrupt");
161
+ }
162
+ }
163
+ else {
164
+ yield* Console.log("Clockify: ✗ not configured");
165
+ }
166
+ }));
167
+ /** Top-level `auth` command with jira/clockify/status subcommands. */
168
+ export const auth = Command.make("auth", {}, () => Console.log("Auth: jira, clockify, status")).pipe(Command.withSubcommands([authJira, authClockify, authStatus]));
169
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/cli/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Config commands: show, set (project/billable/jql), reset.
3
+ *
4
+ * @module
5
+ */
6
+ import { Args, Command, Prompt } from "@effect/cli";
7
+ import { ClockifyApiClient } from "@knpkv/clockify-api-client";
8
+ import { Console, Effect } from "effect";
9
+ import { ClockifyAuth } from "../services/ClockifyAuth.js";
10
+ import { ConfigService } from "../services/ConfigService.js";
11
+ // ---------------------------------------------------------------------------
12
+ // show
13
+ // ---------------------------------------------------------------------------
14
+ const configShow = Command.make("show", {}, () => Effect.gen(function* () {
15
+ const cfg = yield* ConfigService;
16
+ const config = yield* cfg.get;
17
+ yield* Console.log("~/.jcf/config.json:");
18
+ yield* Console.log("");
19
+ yield* Console.log(` Default JQL: ${config.defaultJql}`);
20
+ yield* Console.log(` Refresh (sec): ${config.refreshInterval}`);
21
+ yield* Console.log(` Default project: ${config.defaultProjectName ?? config.defaultProjectId ?? "(none)"}`);
22
+ yield* Console.log(` Default billable:${config.defaultBillable ? " yes" : " no"}`);
23
+ yield* Console.log(` Project map: ${JSON.stringify(config.projectMap)}`);
24
+ }));
25
+ // ---------------------------------------------------------------------------
26
+ // set subcommands
27
+ // ---------------------------------------------------------------------------
28
+ const configSetProject = Command.make("project", {}, () => Effect.gen(function* () {
29
+ const cfg = yield* ConfigService;
30
+ const clockifyAuth = yield* ClockifyAuth;
31
+ const clockifyClient = yield* ClockifyApiClient;
32
+ const auth = yield* clockifyAuth.getConfig.pipe(Effect.catchAll(() => Effect.succeed(null)));
33
+ if (!auth) {
34
+ yield* Console.log("Clockify not configured. Run: jcf auth clockify setup");
35
+ return;
36
+ }
37
+ const projects = yield* clockifyClient.getProjects(auth.workspaceId).pipe(Effect.catchAll(() => Effect.succeed([])));
38
+ if (projects.length === 0) {
39
+ yield* Console.log("No projects found in Clockify workspace.");
40
+ return;
41
+ }
42
+ const selected = yield* Prompt.select({
43
+ message: "Default project:",
44
+ choices: [
45
+ ...projects.map((p) => ({ title: p.name, value: p.id })),
46
+ { title: "(none)", value: "" }
47
+ ]
48
+ });
49
+ if (selected) {
50
+ const name = projects.find((p) => p.id === selected)?.name ?? null;
51
+ yield* cfg.set({ defaultProjectId: selected, defaultProjectName: name });
52
+ yield* Console.log(`Default project: ${name ?? selected}`);
53
+ }
54
+ else {
55
+ yield* cfg.set({ defaultProjectId: null, defaultProjectName: null });
56
+ yield* Console.log("Default project cleared.");
57
+ }
58
+ }));
59
+ const configSetBillable = Command.make("billable", {}, () => Effect.gen(function* () {
60
+ const cfg = yield* ConfigService;
61
+ const val = yield* Prompt.select({
62
+ message: "Default billable:",
63
+ choices: [
64
+ { title: "Yes", value: true },
65
+ { title: "No", value: false }
66
+ ]
67
+ });
68
+ yield* cfg.set({ defaultBillable: val });
69
+ yield* Console.log(`Default billable: ${val ? "yes" : "no"}`);
70
+ }));
71
+ const configSetJql = Command.make("jql", { jql: Args.text({ name: "jql" }) }, ({ jql }) => Effect.gen(function* () {
72
+ const cfg = yield* ConfigService;
73
+ yield* cfg.set({ defaultJql: jql });
74
+ yield* Console.log(`Default JQL: ${jql}`);
75
+ }));
76
+ // ---------------------------------------------------------------------------
77
+ // reset
78
+ // ---------------------------------------------------------------------------
79
+ const configReset = Command.make("reset", {}, () => Effect.gen(function* () {
80
+ const cfg = yield* ConfigService;
81
+ yield* cfg.set({
82
+ defaultProjectId: null,
83
+ defaultProjectName: null,
84
+ defaultBillable: true,
85
+ defaultJql: "assignee = currentUser() AND status != Done ORDER BY updated DESC",
86
+ refreshInterval: 30,
87
+ projectMap: {}
88
+ });
89
+ yield* Console.log("Config reset to defaults.");
90
+ }));
91
+ const configSet = Command.make("set", {}, () => Console.log("Config set: project, billable, jql")).pipe(Command.withSubcommands([configSetProject, configSetBillable, configSetJql]));
92
+ // ---------------------------------------------------------------------------
93
+ // Top-level config command
94
+ // ---------------------------------------------------------------------------
95
+ /** Top-level `config` command with show/set/reset subcommands. */
96
+ export const config = Command.make("config", {}, () => Effect.gen(function* () {
97
+ const cfg = yield* ConfigService;
98
+ const c = yield* cfg.get;
99
+ yield* Console.log("~/.jcf/config.json:");
100
+ yield* Console.log("");
101
+ yield* Console.log(` Default JQL: ${c.defaultJql}`);
102
+ yield* Console.log(` Refresh (sec): ${c.refreshInterval}`);
103
+ yield* Console.log(` Default project: ${c.defaultProjectName ?? c.defaultProjectId ?? "(none)"}`);
104
+ yield* Console.log(` Default billable:${c.defaultBillable ? " yes" : " no"}`);
105
+ yield* Console.log(` Project map: ${JSON.stringify(c.projectMap)}`);
106
+ })).pipe(Command.withSubcommands([configShow, configSet, configReset]));
107
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/cli/config.ts"],"names":[],"mappings":"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"}