@drazenbebic/wdid 0.1.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +134 -21
  2. package/dist/index.js +1110 -32
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,8 +1,21 @@
1
- # wdid
1
+ <div align="center">
2
+ <picture>
3
+ <source
4
+ srcset="./logos/wdid_logo_white_transparent.png"
5
+ media="(prefers-color-scheme: dark)"
6
+ width="820" height="332"
7
+ />
8
+ <img
9
+ src="./logos/wdid_logo_black_transparent.png"
10
+ alt="What did I do Logo"
11
+ width="820" height="332"
12
+ />
13
+ </picture>
14
+ </div>
2
15
 
3
16
  > What did I do? — a small CLI that summarizes your git activity as a tidy table, so you can fill in your timesheet without trying to remember Tuesday.
4
17
 
5
- `wdid` reads `git log` for your author across one or more repos and renders the output as a colorized table with **Date**, **Ticket** (JIRA-style `ABC-123`, parsed from the commit subject), and **Description**.
18
+ `wdid` reads `git log` for your author across one or more repos and renders the output as a colorized table with **Date** (with commit time, shown in your local timezone), **Ticket** (JIRA-style `ABC-123` by default, parsed from the commit subject), and **Description**.
6
19
 
7
20
  ## Install
8
21
 
@@ -28,17 +41,36 @@ By default `wdid` uses `git config user.name` as the author and the current work
28
41
  ### Example output
29
42
 
30
43
  ```
31
- ┌────────────┬──────────────┬──────────────────────────────────────────────────┐
32
- │ Date │ Ticket │ Description │
33
- ├────────────┼──────────────┼──────────────────────────────────────────────────┤
34
- │ 2026-05-27 │ ABC-123 │ feat(ABC-123): add login flow │
35
- │ 2026-05-27 │ — │ chore: bump deps │
36
- │ 2026-05-26 │ ABC-119 │ fix(ABC-119): handle empty payload │
37
- └────────────┴──────────────┴──────────────────────────────────────────────────┘
44
+ ┌──────────────────┬──────────────┬──────────────────────────────────────────────────┐
45
+ │ Date │ Ticket │ Description │
46
+ ├──────────────────┼──────────────┼──────────────────────────────────────────────────┤
47
+ │ 2026-05-27 16:42 │ ABC-123 │ feat(ABC-123): add login flow │
48
+ │ 2026-05-27 11:08 │ — │ chore: bump deps │
49
+ │ 2026-05-26 17:53 │ ABC-119 │ fix(ABC-119): handle empty payload │
50
+ └──────────────────┴──────────────┴──────────────────────────────────────────────────┘
38
51
  ```
39
52
 
53
+ The time is rendered dimmed and shown in your local timezone (parsed from the committer's full ISO timestamp).
54
+
40
55
  If a commit doesn't reference a ticket, the Ticket column is left blank (rendered as `—`).
41
56
 
57
+ With `--group-by-day`, the date moves into a section heading instead of repeating per row, making longer outputs feel more like a journal:
58
+
59
+ ```
60
+ ┌───────┬──────────────┬─────────────────────────────────────┐
61
+ │ Time │ Ticket │ Description │
62
+ ├───────┴──────────────┴─────────────────────────────────────┤
63
+ │ 2026-05-27 │
64
+ ├───────┬──────────────┬─────────────────────────────────────┤
65
+ │ 16:42 │ ABC-123 │ feat(ABC-123): add login flow │
66
+ │ 11:08 │ — │ chore: bump deps │
67
+ ├───────┴──────────────┴─────────────────────────────────────┤
68
+ │ 2026-05-26 │
69
+ ├───────┬──────────────┬─────────────────────────────────────┤
70
+ │ 17:53 │ ABC-119 │ fix(ABC-119): handle empty payload │
71
+ └───────┴──────────────┴─────────────────────────────────────┘
72
+ ```
73
+
42
74
  ## Options
43
75
 
44
76
  | Option | Description |
@@ -50,6 +82,10 @@ If a commit doesn't reference a ticket, the Ticket column is left blank (rendere
50
82
  | `--repo <path...>` | One or more repo paths to query. Defaults to `defaultRepos` in config, then the current dir. |
51
83
  | `--format <preset>` | Ticket format: `jira`, `github`, `conventional`, or `custom`. Defaults to `jira`. |
52
84
  | `--ticket-pattern <regex>` | Custom regex for ticket extraction. Implies `--format custom`; overrides `--format`. |
85
+ | `--no-color` | Disable colored output. Also honored via the `NO_COLOR` env var. |
86
+ | `--limit <N>` | Cap the table to the most recent `N` rows. Positive integer. |
87
+ | `--group-by-day` | Group rows under a bold date heading per day; the row only shows the time. |
88
+ | `--json` | Emit a JSON array of commit entries to stdout instead of the table. Empty result is `[]`. |
53
89
 
54
90
  ## Configuration
55
91
 
@@ -71,21 +107,98 @@ CLI flags always win. The first match in this list is used in full (configs do n
71
107
  }
72
108
  ```
73
109
 
74
- | Field | Type | Description |
75
- | --------------- | -------------------------------------------------- | ---------------------------------------------------------------------------------- |
76
- | `format` | `"jira" \| "github" \| "conventional" \| "custom"` | Ticket extraction preset. Default `jira`. |
77
- | `customPattern` | `string` | Regex used when `format` is `"custom"`. First capture group wins, else full match. |
78
- | `defaultAuthor` | `string` | Used when `--author` is not passed and you want to skip the `git config` lookup. |
79
- | `defaultRepos` | `string[]` | Paths to query when no `--repo` is given. `~` is expanded. |
110
+ | Field | Type | Description |
111
+ | ------------------- | -------------------------------------------------- | ---------------------------------------------------------------------------------- |
112
+ | `format` | `"jira" \| "github" \| "conventional" \| "custom"` | Ticket extraction preset. Default `jira`. |
113
+ | `customPattern` | `string` | Regex used when `format` is `"custom"`. First capture group wins, else full match. |
114
+ | `defaultAuthor` | `string` | Used when `--author` is not passed and you want to skip the `git config` lookup. |
115
+ | `defaultRepos` | `string[]` | Paths to query when no `--repo` is given. `~` is expanded. |
116
+ | `ticketColumnLabel` | `string` | Override the auto-picked column header (see below). |
80
117
 
81
118
  ### Format presets
82
119
 
83
- | Preset | Matches | Example commit → ticket |
84
- | -------------- | ------------------------------------------------ | -------------------------------------- |
85
- | `jira` | `ABC-123` style (uppercase project key + digits) | `feat(ABC-123): add login` → `ABC-123` |
86
- | `github` | `#123` style | `Closes #42` → `42` |
87
- | `conventional` | Conventional Commit `type(scope)!` | `feat(auth)!: ...` → `feat(auth)!` |
88
- | `custom` | Your `customPattern` regex | depends on the regex |
120
+ | Preset | Matches | Example commit → match | Column header |
121
+ | -------------- | ------------------------------------------------ | -------------------------------------- | ------------- |
122
+ | `jira` | `ABC-123` style (uppercase project key + digits) | `feat(ABC-123): add login` → `ABC-123` | `Ticket` |
123
+ | `github` | `#123` style | `Closes #42` → `42` | `Issue` |
124
+ | `conventional` | Conventional Commit `type(scope)!` | `feat(auth)!: ...` → `feat(auth)!` | `Type` |
125
+ | `custom` | Your `customPattern` regex | depends on the regex | `Match` |
126
+
127
+ The column header is picked automatically based on the active format. To override it for a specific preset (e.g. call them "Tasks" instead of "Ticket"), set `ticketColumnLabel` in your config.
128
+
129
+ ## Toggl integration
130
+
131
+ `wdid toggl sync [date]` pushes the day's commits to Toggl as time entries. By default, commits with the same ticket are **collapsed into a single entry** (duration scales with commit count) and commits whose subject matches `\bmerge\b` are skipped. Entries stack from a configurable day-start hour — you adjust the exact times in Toggl yourself. The sync is **idempotent**: each entry's description carries one `(wdid <short-sha>)` marker per included commit, and re-running skips commits already pushed.
132
+
133
+ Descriptions are condensed for Toggl: the conventional-commit prefix (`feat:`, `chore(ABC-123):`, `fix!:`, etc.) is stripped, and the ticket — if any — is prepended once. So `chore(EN-4435): remove requestBody` becomes `EN-4435: remove requestBody`. Aggregated entries look like `EN-4435: subject A; subject B; subject C`.
134
+
135
+ ```sh
136
+ wdid toggl sync # push today
137
+ wdid toggl sync 2026-05-27 # push a specific day
138
+ wdid toggl sync today --dry-run # preview without pushing
139
+ wdid toggl sync --workspace 12345 today # override the configured workspace
140
+ wdid toggl sync --from 2026-05-25 --to 2026-05-27 # push a multi-day range (inclusive)
141
+ ```
142
+
143
+ `--from` and `--to` are inclusive and mutually exclusive with the positional `[date]`. Each day is planned independently (its own 09:00 start, its own dedup fetch). On a per-day failure (Toggl 500, missing project, etc.), the sync continues through the remaining days and exits non-zero with a summary so one bad day doesn't strand the rest. The range is capped at 366 days as a guardrail.
144
+
145
+ ### Toggl config
146
+
147
+ Add these alongside the other config fields:
148
+
149
+ ```json
150
+ {
151
+ "togglApiToken": "your-api-token",
152
+ "togglWorkspaceId": 12345,
153
+ "togglProjects": {
154
+ "ABC-": 67890,
155
+ "DEF-": 67891
156
+ },
157
+ "togglDefaultProjectId": 99999,
158
+ "togglDefaultDurationMinutes": 30,
159
+ "togglDayStartHour": 9,
160
+ "togglOneEntryPerTicket": true,
161
+ "togglIgnoreSubjectPattern": "\\bmerge\\b"
162
+ }
163
+ ```
164
+
165
+ | Field | Type | Description |
166
+ | ----------------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------- |
167
+ | `togglApiToken` | `string` | Toggl API token (find it in Toggl → Profile → API Token). Prefer the `TOGGL_API_TOKEN` env var. |
168
+ | `togglWorkspaceId` | `number` | Numeric Toggl workspace ID. Required to push. |
169
+ | `togglProjects` | `Record<string, number>` | Map of ticket-prefix → project ID. Longest matching prefix wins. |
170
+ | `togglDefaultProjectId` | `number` | Project ID for commits that don't match any prefix (or have no ticket). |
171
+ | `togglDefaultDurationMinutes` | `number` | Per-commit duration. Default `30`. In per-ticket mode, an entry's total duration is `count × this`. |
172
+ | `togglDayStartHour` | `number` (0–23) | Hour to start stacking entries at. Default `9` (09:00). |
173
+ | `togglOneEntryPerTicket` | `boolean` | When `true` (default), commits sharing a ticket collapse into one entry. Commits without a ticket stay 1:1. |
174
+ | `togglIgnoreSubjectPattern` | `string` (regex) | Subjects matching this pattern (case-insensitive) are skipped. Default `\bmerge\b`. Set to `""` to disable. |
175
+
176
+ ### Auth
177
+
178
+ The API token is resolved in this order: `TOGGL_API_TOKEN` env var > `togglApiToken` in config. The env var path is preferred so you don't have to commit (or remember not to commit) the token.
179
+
180
+ ## Managing config
181
+
182
+ `wdid config` provides four subcommands for the **global** config (`~/.config/wdid/config.json` — honors `XDG_CONFIG_HOME`). Repo-level configs are read but not written by these commands; edit them by hand.
183
+
184
+ ```sh
185
+ wdid config set togglApiToken tok_… # set a scalar field
186
+ wdid config set togglWorkspaceId 12345 # numbers are parsed
187
+ wdid config set togglOneEntryPerTicket false # booleans take "true"/"false"
188
+ wdid config set togglProjects.ABC- 67890 # set a nested record entry
189
+ wdid config get togglApiToken # secrets are masked
190
+ wdid config get togglApiToken --show-secrets # …unless --show-secrets
191
+ wdid config list # all set fields, aligned, secrets masked
192
+ wdid config list --show-secrets # reveal secrets
193
+ wdid config path # absolute path to the config file
194
+ ```
195
+
196
+ Notes:
197
+
198
+ - **Validation runs at `set` time** — `wdid config set togglDayStartHour 99` fails immediately with the schema error, the file is never touched.
199
+ - **Secrets are masked** in `list` / `get` output (`tok_…wa9e0d` style) unless `--show-secrets` is set.
200
+ - **`defaultRepos` is not settable from the CLI** (it's an array). Same for any future array-shaped field. Use `vim $(wdid config path)` to edit those.
201
+ - **To remove a key**, edit the file directly — `unset` isn't included in this slice.
89
202
 
90
203
  ## Development
91
204