@milldr/crono 0.1.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 +219 -0
- package/dist/commands/diary.d.ts +7 -0
- package/dist/commands/diary.d.ts.map +1 -0
- package/dist/commands/diary.js +79 -0
- package/dist/commands/diary.js.map +1 -0
- package/dist/commands/login.d.ts +19 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +160 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/quick-add.d.ts +8 -0
- package/dist/commands/quick-add.d.ts.map +1 -0
- package/dist/commands/quick-add.js +49 -0
- package/dist/commands/quick-add.js.map +1 -0
- package/dist/commands/weight.d.ts +7 -0
- package/dist/commands/weight.d.ts.map +1 -0
- package/dist/commands/weight.js +78 -0
- package/dist/commands/weight.js.map +1 -0
- package/dist/config.d.ts +17 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +43 -0
- package/dist/config.js.map +1 -0
- package/dist/credentials.d.ts +27 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +178 -0
- package/dist/credentials.js.map +1 -0
- package/dist/debug-nav.d.ts +2 -0
- package/dist/debug-nav.d.ts.map +1 -0
- package/dist/debug-nav.js +99 -0
- package/dist/debug-nav.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel/client.d.ts +40 -0
- package/dist/kernel/client.d.ts.map +1 -0
- package/dist/kernel/client.js +205 -0
- package/dist/kernel/client.js.map +1 -0
- package/dist/kernel/diary.d.ts +22 -0
- package/dist/kernel/diary.d.ts.map +1 -0
- package/dist/kernel/diary.js +156 -0
- package/dist/kernel/diary.js.map +1 -0
- package/dist/kernel/login.d.ts +24 -0
- package/dist/kernel/login.d.ts.map +1 -0
- package/dist/kernel/login.js +125 -0
- package/dist/kernel/login.js.map +1 -0
- package/dist/kernel/quick-add.d.ts +22 -0
- package/dist/kernel/quick-add.d.ts.map +1 -0
- package/dist/kernel/quick-add.js +260 -0
- package/dist/kernel/quick-add.js.map +1 -0
- package/dist/kernel/weight.d.ts +20 -0
- package/dist/kernel/weight.d.ts.map +1 -0
- package/dist/kernel/weight.js +160 -0
- package/dist/kernel/weight.js.map +1 -0
- package/dist/utils/date.d.ts +31 -0
- package/dist/utils/date.d.ts.map +1 -0
- package/dist/utils/date.js +82 -0
- package/dist/utils/date.js.map +1 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Daniel Miller
|
|
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,219 @@
|
|
|
1
|
+
# 🍎 crono
|
|
2
|
+
|
|
3
|
+
CLI for Cronometer automation via [Kernel.sh](https://kernel.sh).
|
|
4
|
+
|
|
5
|
+
Cronometer has no public API, so crono automates the web UI through Kernel.sh browser automation. Log macros from your terminal in seconds.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## Quickstart
|
|
10
|
+
|
|
11
|
+
### 1. Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g @milldr/crono
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### 2. Log in
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
crono login
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
You'll be prompted for three things:
|
|
24
|
+
|
|
25
|
+
- **Kernel API key** — get one at [kernel.sh](https://kernel.sh)
|
|
26
|
+
- **Cronometer email** — your Cronometer account email
|
|
27
|
+
- **Cronometer password** — stored securely in your system keychain
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
┌ crono login
|
|
31
|
+
│
|
|
32
|
+
◇ Kernel API key
|
|
33
|
+
│ sk-abc...
|
|
34
|
+
│
|
|
35
|
+
◒ Validating API key...
|
|
36
|
+
◇ API key valid.
|
|
37
|
+
│
|
|
38
|
+
◇ Cronometer email
|
|
39
|
+
│ you@example.com
|
|
40
|
+
│
|
|
41
|
+
◇ Cronometer password
|
|
42
|
+
│ ****
|
|
43
|
+
│
|
|
44
|
+
└ Credentials saved.
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 3. Log a meal
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
crono quick-add -p 30 -c 100 -f 20 -m Dinner
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
┌ crono quick-add
|
|
55
|
+
│
|
|
56
|
+
◒ Logging into Cronometer...
|
|
57
|
+
◇ Done.
|
|
58
|
+
│
|
|
59
|
+
└ Added: 30g protein, 100g carbs, 20g fat → Dinner
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Commands
|
|
63
|
+
|
|
64
|
+
### `crono login`
|
|
65
|
+
|
|
66
|
+
Set up or update your Kernel API key and Cronometer credentials. If credentials already exist, pressing Enter keeps the current value.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
crono login
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### `crono quick-add`
|
|
73
|
+
|
|
74
|
+
Add a quick macro entry to your Cronometer diary.
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
crono quick-add [options]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Options:**
|
|
81
|
+
|
|
82
|
+
| Flag | Long | Description |
|
|
83
|
+
| ---- | --------------- | ------------------------------------------------ |
|
|
84
|
+
| `-p` | `--protein <g>` | Grams of protein |
|
|
85
|
+
| `-c` | `--carbs <g>` | Grams of carbohydrates |
|
|
86
|
+
| `-f` | `--fat <g>` | Grams of fat |
|
|
87
|
+
| `-m` | `--meal <name>` | Meal category (Breakfast, Lunch, Dinner, Snacks) |
|
|
88
|
+
|
|
89
|
+
At least one macro flag (`-p`, `-c`, or `-f`) is required.
|
|
90
|
+
|
|
91
|
+
**Examples:**
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# Log 30g protein
|
|
95
|
+
crono quick-add -p 30
|
|
96
|
+
|
|
97
|
+
# Log full meal macros
|
|
98
|
+
crono quick-add -p 30 -c 100 -f 20
|
|
99
|
+
|
|
100
|
+
# Log to Dinner category
|
|
101
|
+
crono quick-add -p 30 -c 50 -f 15 --meal Dinner
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### `crono weight`
|
|
105
|
+
|
|
106
|
+
Check your weight from Cronometer. Defaults to today if no date or range is specified.
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
crono weight [options]
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Options:**
|
|
113
|
+
|
|
114
|
+
| Flag | Long | Description |
|
|
115
|
+
| ---- | ----------------- | ----------------------------------------- |
|
|
116
|
+
| `-d` | `--date <date>` | Date (YYYY-MM-DD) |
|
|
117
|
+
| `-r` | `--range <range>` | Range (7d, 30d, or YYYY-MM-DD:YYYY-MM-DD) |
|
|
118
|
+
| | `--json` | Output as JSON |
|
|
119
|
+
|
|
120
|
+
`-d` and `-r` are mutually exclusive.
|
|
121
|
+
|
|
122
|
+
**Examples:**
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# Today's weight
|
|
126
|
+
crono weight
|
|
127
|
+
# → 212.5 lbs
|
|
128
|
+
|
|
129
|
+
# Specific date
|
|
130
|
+
crono weight -d 2026-02-05
|
|
131
|
+
|
|
132
|
+
# Last 7 days
|
|
133
|
+
crono weight -r 7d
|
|
134
|
+
# → 2026-02-11: 212.5
|
|
135
|
+
# → 2026-02-10: 212.7
|
|
136
|
+
# → 2026-02-09: 215.5
|
|
137
|
+
# → ...
|
|
138
|
+
|
|
139
|
+
# JSON output for scripting
|
|
140
|
+
crono weight --json
|
|
141
|
+
# → {"date":"2026-02-11","weight":212.5,"unit":"lbs"}
|
|
142
|
+
|
|
143
|
+
# Range as JSON
|
|
144
|
+
crono weight -r 7d --json
|
|
145
|
+
# → [{"date":"2026-02-11","weight":212.5,"unit":"lbs"}, ...]
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### `crono diary`
|
|
149
|
+
|
|
150
|
+
View daily nutrition totals (calories, protein, carbs, fat) from Cronometer. Defaults to today if no date or range is specified.
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
crono diary [options]
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Options:**
|
|
157
|
+
|
|
158
|
+
| Flag | Long | Description |
|
|
159
|
+
| ---- | ----------------- | ----------------------------------------- |
|
|
160
|
+
| `-d` | `--date <date>` | Date (YYYY-MM-DD) |
|
|
161
|
+
| `-r` | `--range <range>` | Range (7d, 30d, or YYYY-MM-DD:YYYY-MM-DD) |
|
|
162
|
+
| | `--json` | Output as JSON |
|
|
163
|
+
|
|
164
|
+
`-d` and `-r` are mutually exclusive.
|
|
165
|
+
|
|
166
|
+
**Examples:**
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
# Today's nutrition
|
|
170
|
+
crono diary
|
|
171
|
+
# → 1847 kcal | P: 168g | C: 142g | F: 58g
|
|
172
|
+
|
|
173
|
+
# Specific date
|
|
174
|
+
crono diary -d 2026-02-05
|
|
175
|
+
|
|
176
|
+
# Last 7 days
|
|
177
|
+
crono diary -r 7d
|
|
178
|
+
# → 2026-02-11: 1847 kcal | P: 168g | C: 142g | F: 58g
|
|
179
|
+
# → 2026-02-10: 2103 kcal | P: 155g | C: 200g | F: 72g
|
|
180
|
+
# → ...
|
|
181
|
+
|
|
182
|
+
# JSON output for scripting
|
|
183
|
+
crono diary --json
|
|
184
|
+
# → {"date":"2026-02-11","calories":1847,"protein":168,"carbs":142,"fat":58}
|
|
185
|
+
|
|
186
|
+
# Range as JSON
|
|
187
|
+
crono diary -r 7d --json
|
|
188
|
+
# → [{"date":"2026-02-11","calories":1847,"protein":168,"carbs":142,"fat":58}, ...]
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Requirements
|
|
192
|
+
|
|
193
|
+
- Node.js 18+
|
|
194
|
+
- [Kernel.sh](https://kernel.sh) account (for browser automation)
|
|
195
|
+
- [Cronometer](https://cronometer.com) account
|
|
196
|
+
|
|
197
|
+
## Development
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
git clone https://github.com/milldr/crono.git
|
|
201
|
+
cd crono
|
|
202
|
+
npm install
|
|
203
|
+
|
|
204
|
+
# Run in dev mode
|
|
205
|
+
npm run dev -- login
|
|
206
|
+
npm run dev -- quick-add -p 30
|
|
207
|
+
npm run dev -- weight -r 7d
|
|
208
|
+
npm run dev -- diary
|
|
209
|
+
|
|
210
|
+
# Run tests
|
|
211
|
+
npm test
|
|
212
|
+
|
|
213
|
+
# Build
|
|
214
|
+
npm run build
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## License
|
|
218
|
+
|
|
219
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diary.d.ts","sourceRoot":"","sources":["../../src/commands/diary.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAiEhE"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import { getKernelClient } from "../kernel/client.js";
|
|
3
|
+
import { parseDate, parseRange, dateRange, todayStr } from "../utils/date.js";
|
|
4
|
+
export async function diary(options) {
|
|
5
|
+
// Validate mutual exclusivity
|
|
6
|
+
if (options.date && options.range) {
|
|
7
|
+
p.log.error("-d and -r are mutually exclusive");
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
// Resolve dates to fetch
|
|
11
|
+
let dates;
|
|
12
|
+
let isRange = false;
|
|
13
|
+
try {
|
|
14
|
+
if (options.range) {
|
|
15
|
+
isRange = true;
|
|
16
|
+
const { start, end } = parseRange(options.range);
|
|
17
|
+
dates = dateRange(start, end);
|
|
18
|
+
}
|
|
19
|
+
else if (options.date) {
|
|
20
|
+
dates = [parseDate(options.date)];
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
dates = [todayStr()];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
p.log.error(String(error instanceof Error ? error.message : error));
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
if (!options.json) {
|
|
31
|
+
p.intro("🍎 crono diary");
|
|
32
|
+
}
|
|
33
|
+
const s = options.json ? null : p.spinner();
|
|
34
|
+
s?.start("Connecting...");
|
|
35
|
+
try {
|
|
36
|
+
const kernel = await getKernelClient();
|
|
37
|
+
const entries = await kernel.getDiary(dates, (msg) => s?.message(msg));
|
|
38
|
+
s?.stop("Done.");
|
|
39
|
+
if (options.json) {
|
|
40
|
+
if (isRange) {
|
|
41
|
+
console.log(JSON.stringify(entries, null, 2));
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
console.log(JSON.stringify(entries[0] ?? {
|
|
45
|
+
date: dates[0],
|
|
46
|
+
calories: 0,
|
|
47
|
+
protein: 0,
|
|
48
|
+
carbs: 0,
|
|
49
|
+
fat: 0,
|
|
50
|
+
}, null, 2));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
formatPlainText(entries, isRange);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
s?.stop("Failed.");
|
|
59
|
+
p.log.error(`Failed to read diary: ${error}`);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function formatPlainText(entries, isRange) {
|
|
64
|
+
if (!isRange) {
|
|
65
|
+
const entry = entries[0];
|
|
66
|
+
if (!entry) {
|
|
67
|
+
p.outro("No diary data found");
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
p.outro(`${entry.calories} kcal | P: ${entry.protein}g | C: ${entry.carbs}g | F: ${entry.fat}g`);
|
|
71
|
+
}
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// Range output
|
|
75
|
+
for (const entry of entries) {
|
|
76
|
+
p.log.info(`${entry.date}: ${entry.calories} kcal | P: ${entry.protein}g | C: ${entry.carbs}g | F: ${entry.fat}g`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=diary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diary.js","sourceRoot":"","sources":["../../src/commands/diary.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Login command — prompts for Kernel API key and Cronometer credentials,
|
|
3
|
+
* validates them, and stores them securely.
|
|
4
|
+
*
|
|
5
|
+
* Uses @clack/prompts for styled terminal UI with cancellation handling.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Validate a Kernel API key by attempting to list profiles.
|
|
9
|
+
* Throws if the key is invalid.
|
|
10
|
+
*/
|
|
11
|
+
export declare function validateKernelApiKey(apiKey: string): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Interactive login flow.
|
|
14
|
+
*
|
|
15
|
+
* Each field shows the existing value (masked) if present.
|
|
16
|
+
* Pressing Enter without typing keeps the existing value.
|
|
17
|
+
*/
|
|
18
|
+
export declare function login(): Promise<void>;
|
|
19
|
+
//# sourceMappingURL=login.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAaxE;AAWD;;;;;GAKG;AACH,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAmI3C"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Login command — prompts for Kernel API key and Cronometer credentials,
|
|
3
|
+
* validates them, and stores them securely.
|
|
4
|
+
*
|
|
5
|
+
* Uses @clack/prompts for styled terminal UI with cancellation handling.
|
|
6
|
+
*/
|
|
7
|
+
import * as p from "@clack/prompts";
|
|
8
|
+
import Kernel from "@onkernel/sdk";
|
|
9
|
+
import { getCredential, setCredential } from "../credentials.js";
|
|
10
|
+
/**
|
|
11
|
+
* Validate a Kernel API key by attempting to list profiles.
|
|
12
|
+
* Throws if the key is invalid.
|
|
13
|
+
*/
|
|
14
|
+
export async function validateKernelApiKey(apiKey) {
|
|
15
|
+
const prevKey = process.env["KERNEL_API_KEY"];
|
|
16
|
+
try {
|
|
17
|
+
process.env["KERNEL_API_KEY"] = apiKey;
|
|
18
|
+
const kernel = new Kernel();
|
|
19
|
+
await kernel.profiles.list();
|
|
20
|
+
}
|
|
21
|
+
finally {
|
|
22
|
+
if (prevKey === undefined) {
|
|
23
|
+
delete process.env["KERNEL_API_KEY"];
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
process.env["KERNEL_API_KEY"] = prevKey;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Mask a string for display: show first 4 chars then stars.
|
|
32
|
+
* For short strings (<=4), show all stars.
|
|
33
|
+
*/
|
|
34
|
+
function mask(value) {
|
|
35
|
+
if (value.length <= 4)
|
|
36
|
+
return "*".repeat(value.length);
|
|
37
|
+
return value.slice(0, 4) + "*".repeat(value.length - 4);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Interactive login flow.
|
|
41
|
+
*
|
|
42
|
+
* Each field shows the existing value (masked) if present.
|
|
43
|
+
* Pressing Enter without typing keeps the existing value.
|
|
44
|
+
*/
|
|
45
|
+
export async function login() {
|
|
46
|
+
const existingKey = getCredential("kernel-api-key");
|
|
47
|
+
const existingEmail = getCredential("cronometer-username");
|
|
48
|
+
const existingPassword = getCredential("cronometer-password");
|
|
49
|
+
p.intro("🍎 crono login");
|
|
50
|
+
if (existingKey || existingEmail || existingPassword) {
|
|
51
|
+
p.log.info(`Credentials already configured${existingEmail ? ` for ${existingEmail}` : ""}. Press Enter to keep existing values.`);
|
|
52
|
+
}
|
|
53
|
+
// 1. Kernel API key
|
|
54
|
+
const apiKeyInput = await p.text({
|
|
55
|
+
message: "Kernel API key",
|
|
56
|
+
placeholder: existingKey ? mask(existingKey) : "sk-...",
|
|
57
|
+
defaultValue: existingKey ?? undefined,
|
|
58
|
+
});
|
|
59
|
+
if (p.isCancel(apiKeyInput)) {
|
|
60
|
+
p.cancel("Login cancelled.");
|
|
61
|
+
process.exit(0);
|
|
62
|
+
}
|
|
63
|
+
const apiKey = apiKeyInput || existingKey;
|
|
64
|
+
if (!apiKey) {
|
|
65
|
+
p.cancel("API key cannot be empty.");
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
// Only validate if the key changed
|
|
69
|
+
if (apiKeyInput && apiKeyInput !== existingKey) {
|
|
70
|
+
const s = p.spinner();
|
|
71
|
+
s.start("Validating API key...");
|
|
72
|
+
try {
|
|
73
|
+
await validateKernelApiKey(apiKey);
|
|
74
|
+
s.stop("API key valid.");
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
s.stop("API key invalid.");
|
|
78
|
+
p.cancel("Invalid API key. Check your key at https://kernel.sh");
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// 2. Cronometer email
|
|
83
|
+
const emailInput = await p.text({
|
|
84
|
+
message: "Cronometer email",
|
|
85
|
+
defaultValue: existingEmail ?? undefined,
|
|
86
|
+
placeholder: existingEmail ?? "you@example.com",
|
|
87
|
+
validate: (v) => {
|
|
88
|
+
if (v && !v.includes("@"))
|
|
89
|
+
return "Must be a valid email";
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
if (p.isCancel(emailInput)) {
|
|
93
|
+
p.cancel("Login cancelled.");
|
|
94
|
+
process.exit(0);
|
|
95
|
+
}
|
|
96
|
+
const email = emailInput || existingEmail;
|
|
97
|
+
if (!email || !email.includes("@")) {
|
|
98
|
+
p.cancel("Please enter a valid email address.");
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
// 3. Cronometer password
|
|
102
|
+
let password;
|
|
103
|
+
if (existingPassword) {
|
|
104
|
+
const changePassword = await p.confirm({
|
|
105
|
+
message: "Change Cronometer password?",
|
|
106
|
+
initialValue: false,
|
|
107
|
+
});
|
|
108
|
+
if (p.isCancel(changePassword)) {
|
|
109
|
+
p.cancel("Login cancelled.");
|
|
110
|
+
process.exit(0);
|
|
111
|
+
}
|
|
112
|
+
if (changePassword) {
|
|
113
|
+
const passwordInput = await p.password({
|
|
114
|
+
message: "Cronometer password",
|
|
115
|
+
mask: "*",
|
|
116
|
+
});
|
|
117
|
+
if (p.isCancel(passwordInput)) {
|
|
118
|
+
p.cancel("Login cancelled.");
|
|
119
|
+
process.exit(0);
|
|
120
|
+
}
|
|
121
|
+
password = passwordInput || existingPassword;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
password = existingPassword;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
const passwordInput = await p.password({
|
|
129
|
+
message: "Cronometer password",
|
|
130
|
+
mask: "*",
|
|
131
|
+
});
|
|
132
|
+
if (p.isCancel(passwordInput)) {
|
|
133
|
+
p.cancel("Login cancelled.");
|
|
134
|
+
process.exit(0);
|
|
135
|
+
}
|
|
136
|
+
password = passwordInput;
|
|
137
|
+
}
|
|
138
|
+
if (!password) {
|
|
139
|
+
p.cancel("Password cannot be empty.");
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
// Store credentials
|
|
143
|
+
setCredential("kernel-api-key", apiKey);
|
|
144
|
+
setCredential("cronometer-username", email);
|
|
145
|
+
setCredential("cronometer-password", password);
|
|
146
|
+
const changed = [];
|
|
147
|
+
if (apiKeyInput && apiKeyInput !== existingKey)
|
|
148
|
+
changed.push("API key");
|
|
149
|
+
if (emailInput && emailInput !== existingEmail)
|
|
150
|
+
changed.push("email");
|
|
151
|
+
if (password !== existingPassword)
|
|
152
|
+
changed.push("password");
|
|
153
|
+
if (changed.length > 0) {
|
|
154
|
+
p.outro(`Updated ${changed.join(", ")}.`);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
p.outro("No changes made.");
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quick-add.d.ts","sourceRoot":"","sources":["../../src/commands/quick-add.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAID,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAoDtE"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import { getKernelClient } from "../kernel/client.js";
|
|
3
|
+
const VALID_MEALS = ["breakfast", "lunch", "dinner", "snacks"];
|
|
4
|
+
export async function quickAdd(options) {
|
|
5
|
+
// Validate at least one macro is provided
|
|
6
|
+
if (!options.protein && !options.carbs && !options.fat) {
|
|
7
|
+
p.log.error("At least one macro (-p, -c, or -f) is required");
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
// Validate meal if provided
|
|
11
|
+
if (options.meal) {
|
|
12
|
+
const normalizedMeal = options.meal.toLowerCase();
|
|
13
|
+
if (!VALID_MEALS.includes(normalizedMeal)) {
|
|
14
|
+
p.log.error(`Invalid meal "${options.meal}". Use: Breakfast, Lunch, Dinner, or Snacks`);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// Build entry description
|
|
19
|
+
const parts = [];
|
|
20
|
+
if (options.protein)
|
|
21
|
+
parts.push(`${options.protein}g protein`);
|
|
22
|
+
if (options.carbs)
|
|
23
|
+
parts.push(`${options.carbs}g carbs`);
|
|
24
|
+
if (options.fat)
|
|
25
|
+
parts.push(`${options.fat}g fat`);
|
|
26
|
+
const mealLabel = options.meal
|
|
27
|
+
? options.meal.charAt(0).toUpperCase() + options.meal.slice(1).toLowerCase()
|
|
28
|
+
: "Uncategorized";
|
|
29
|
+
p.intro("🍎 crono quick-add");
|
|
30
|
+
const s = p.spinner();
|
|
31
|
+
s.start("Connecting...");
|
|
32
|
+
try {
|
|
33
|
+
const kernel = await getKernelClient();
|
|
34
|
+
await kernel.addQuickEntry({
|
|
35
|
+
protein: options.protein,
|
|
36
|
+
carbs: options.carbs,
|
|
37
|
+
fat: options.fat,
|
|
38
|
+
meal: options.meal,
|
|
39
|
+
}, (msg) => s.message(msg));
|
|
40
|
+
s.stop("Done.");
|
|
41
|
+
p.outro(`Added: ${parts.join(", ")} → ${mealLabel}`);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
s.stop("Failed.");
|
|
45
|
+
p.log.error(`Failed to add entry: ${error}`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=quick-add.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quick-add.js","sourceRoot":"","sources":["../../src/commands/quick-add.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAStD,MAAM,WAAW,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAE/D,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAwB;IACrD,0CAA0C;IAC1C,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACvD,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,4BAA4B;IAC5B,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAClD,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YAC1C,CAAC,CAAC,GAAG,CAAC,KAAK,CACT,iBAAiB,OAAO,CAAC,IAAI,6CAA6C,CAC3E,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,0BAA0B;IAC1B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,OAAO,CAAC,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC;IAC/D,IAAI,OAAO,CAAC,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC;IACzD,IAAI,OAAO,CAAC,GAAG;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;IAEnD,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI;QAC5B,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;QAC5E,CAAC,CAAC,eAAe,CAAC;IAEpB,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAE9B,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IACtB,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAEzB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAC;QACvC,MAAM,MAAM,CAAC,aAAa,CACxB;YACE,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB,EACD,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CACxB,CAAC;QAEF,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChB,CAAC,CAAC,KAAK,CAAC,UAAU,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,SAAS,EAAE,CAAC,CAAC;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,wBAAwB,KAAK,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weight.d.ts","sourceRoot":"","sources":["../../src/commands/weight.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA2DlE"}
|