@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.
- package/LICENSE +21 -0
- package/README.md +121 -0
- package/dist/package.json +47 -0
- package/dist/src/bin.js +28 -0
- package/dist/src/bin.js.map +1 -0
- package/dist/src/cli/auth.js +169 -0
- package/dist/src/cli/auth.js.map +1 -0
- package/dist/src/cli/config.js +107 -0
- package/dist/src/cli/config.js.map +1 -0
- package/dist/src/cli/fuzzySelect.js +149 -0
- package/dist/src/cli/fuzzySelect.js.map +1 -0
- package/dist/src/cli/layers.js +59 -0
- package/dist/src/cli/layers.js.map +1 -0
- package/dist/src/cli/list.js +27 -0
- package/dist/src/cli/list.js.map +1 -0
- package/dist/src/cli/setup.js +134 -0
- package/dist/src/cli/setup.js.map +1 -0
- package/dist/src/cli/timer/discard.js +33 -0
- package/dist/src/cli/timer/discard.js.map +1 -0
- package/dist/src/cli/timer/edit.js +139 -0
- package/dist/src/cli/timer/edit.js.map +1 -0
- package/dist/src/cli/timer/index.js +12 -0
- package/dist/src/cli/timer/index.js.map +1 -0
- package/dist/src/cli/timer/log.js +96 -0
- package/dist/src/cli/timer/log.js.map +1 -0
- package/dist/src/cli/timer/start.js +156 -0
- package/dist/src/cli/timer/start.js.map +1 -0
- package/dist/src/cli/timer/status.js +80 -0
- package/dist/src/cli/timer/status.js.map +1 -0
- package/dist/src/cli/timer/stop.js +96 -0
- package/dist/src/cli/timer/stop.js.map +1 -0
- package/dist/src/cli/timer.js +7 -0
- package/dist/src/cli/timer.js.map +1 -0
- package/dist/src/main.js +24 -0
- package/dist/src/main.js.map +1 -0
- package/dist/src/services/ClockifyAuth.js +77 -0
- package/dist/src/services/ClockifyAuth.js.map +1 -0
- package/dist/src/services/ConfigService.js +66 -0
- package/dist/src/services/ConfigService.js.map +1 -0
- package/dist/src/services/StateWriter.js +69 -0
- package/dist/src/services/StateWriter.js.map +1 -0
- package/dist/src/services/TicketService.js +106 -0
- package/dist/src/services/TicketService.js.map +1 -0
- package/dist/src/services/TimerService.js +271 -0
- package/dist/src/services/TimerService.js.map +1 -0
- package/dist/src/tui/App.js +204 -0
- package/dist/src/tui/App.js.map +1 -0
- package/dist/src/tui/atoms/runtime.js +9 -0
- package/dist/src/tui/atoms/runtime.js.map +1 -0
- package/dist/src/tui/atoms/tickets.js +17 -0
- package/dist/src/tui/atoms/tickets.js.map +1 -0
- package/dist/src/tui/atoms/timer.js +31 -0
- package/dist/src/tui/atoms/timer.js.map +1 -0
- package/dist/src/tui/atoms/ui.js +10 -0
- package/dist/src/tui/atoms/ui.js.map +1 -0
- package/dist/src/tui/components/BigTimer.js +60 -0
- package/dist/src/tui/components/BigTimer.js.map +1 -0
- package/dist/src/tui/components/Footer.js +16 -0
- package/dist/src/tui/components/Footer.js.map +1 -0
- package/dist/src/tui/components/Header.js +16 -0
- package/dist/src/tui/components/Header.js.map +1 -0
- package/dist/src/tui/components/PopupInput.js +30 -0
- package/dist/src/tui/components/PopupInput.js.map +1 -0
- package/dist/src/tui/components/PopupMessage.js +47 -0
- package/dist/src/tui/components/PopupMessage.js.map +1 -0
- package/dist/src/tui/components/TicketList.js +40 -0
- package/dist/src/tui/components/TicketList.js.map +1 -0
- package/dist/src/tui/components/TicketRow.js +48 -0
- package/dist/src/tui/components/TicketRow.js.map +1 -0
- package/dist/src/tui/components/TimerDisplay.js +30 -0
- package/dist/src/tui/components/TimerDisplay.js.map +1 -0
- package/dist/src/tui/components/index.js +12 -0
- package/dist/src/tui/components/index.js.map +1 -0
- package/dist/src/tui/context/theme.js +15 -0
- package/dist/src/tui/context/theme.js.map +1 -0
- package/dist/src/tui/hooks/useElapsedTimer.js +35 -0
- package/dist/src/tui/hooks/useElapsedTimer.js.map +1 -0
- package/dist/src/tui/hooks/useTerminalSize.js +32 -0
- package/dist/src/tui/hooks/useTerminalSize.js.map +1 -0
- package/dist/src/utils/time.js +23 -0
- package/dist/src/utils/time.js.map +1 -0
- package/dist/test/TimerService.test.js +355 -0
- package/dist/test/TimerService.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/nvim/lua/jcf/branch.lua +26 -0
- package/nvim/lua/jcf/float.lua +87 -0
- package/nvim/lua/jcf/init.lua +70 -0
- package/nvim/lua/jcf/state.lua +56 -0
- package/nvim/lua/jcf/statusline.lua +31 -0
- package/nvim/lua/jcf/telescope.lua +50 -0
- package/nvim/plugin/jcf.vim +2 -0
- 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
|
+
}
|
package/dist/src/bin.js
ADDED
|
@@ -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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"}
|