@purveyors/cli 0.9.5 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +199 -21
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +4 -3
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/catalog.d.ts.map +1 -1
- package/dist/commands/catalog.js +55 -31
- package/dist/commands/catalog.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +61 -12
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/context.d.ts.map +1 -1
- package/dist/commands/context.js +32 -231
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/inventory.d.ts.map +1 -1
- package/dist/commands/inventory.js +5 -0
- package/dist/commands/inventory.js.map +1 -1
- package/dist/commands/manifest.d.ts +3 -0
- package/dist/commands/manifest.d.ts.map +1 -0
- package/dist/commands/manifest.js +28 -0
- package/dist/commands/manifest.js.map +1 -0
- package/dist/commands/roast.d.ts.map +1 -1
- package/dist/commands/roast.js +5 -0
- package/dist/commands/roast.js.map +1 -1
- package/dist/commands/sales.d.ts.map +1 -1
- package/dist/commands/sales.js +5 -0
- package/dist/commands/sales.js.map +1 -1
- package/dist/index.js +6 -105
- package/dist/index.js.map +1 -1
- package/dist/lib/catalog.d.ts.map +1 -1
- package/dist/lib/catalog.js +2 -6
- package/dist/lib/catalog.js.map +1 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +8 -2
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/errors.d.ts +13 -1
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +153 -10
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +1 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/inventory.d.ts +1 -0
- package/dist/lib/inventory.d.ts.map +1 -1
- package/dist/lib/inventory.js +3 -1
- package/dist/lib/inventory.js.map +1 -1
- package/dist/lib/manifest.d.ts +100 -0
- package/dist/lib/manifest.d.ts.map +1 -0
- package/dist/lib/manifest.js +919 -0
- package/dist/lib/manifest.js.map +1 -0
- package/dist/lib/output.d.ts +10 -0
- package/dist/lib/output.d.ts.map +1 -1
- package/dist/lib/output.js +33 -18
- package/dist/lib/output.js.map +1 -1
- package/dist/lib/roast.d.ts +1 -0
- package/dist/lib/roast.d.ts.map +1 -1
- package/dist/lib/roast.js +5 -1
- package/dist/lib/roast.js.map +1 -1
- package/dist/lib/sales.d.ts +1 -0
- package/dist/lib/sales.d.ts.map +1 -1
- package/dist/lib/sales.js +5 -1
- package/dist/lib/sales.js.map +1 -1
- package/dist/program.d.ts +4 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +131 -0
- package/dist/program.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Coffee intelligence from your terminal.
|
|
|
4
4
|
|
|
5
5
|
`purvey` is the official CLI for [purveyors.io](https://purveyors.io). It gives coffee professionals and AI agents direct access to the Purveyors platform from the terminal: catalog search, inventory tracking, roast logging, sales records, tasting notes, and Artisan `.alog` import.
|
|
6
6
|
|
|
7
|
-
Run `purvey context` for the dense
|
|
7
|
+
Run `purvey manifest` for the machine-readable contract, `purvey context` for the dense human-readable reference, or import `@purveyors/cli/manifest` in-process.
|
|
8
8
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
|
@@ -25,24 +25,37 @@ purvey --version
|
|
|
25
25
|
## Quick Start
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
# 1. Authenticate
|
|
28
|
+
# 1. Authenticate before using catalog, inventory, roast, sales, or tasting commands
|
|
29
29
|
purvey auth login
|
|
30
30
|
|
|
31
|
-
#
|
|
31
|
+
# For agents, CI, or remote machines, use headless flow:
|
|
32
|
+
# purvey auth login --headless
|
|
33
|
+
|
|
34
|
+
# 2. Confirm the session and role
|
|
32
35
|
purvey auth status
|
|
33
36
|
|
|
34
|
-
# 3. Search the catalog
|
|
37
|
+
# 3. Search the catalog (requires viewer role, granted on sign-in)
|
|
35
38
|
purvey catalog search --origin "Ethiopia" --stocked --pretty
|
|
36
39
|
|
|
37
|
-
# 4. Check inventory
|
|
40
|
+
# 4. Check inventory (requires member role)
|
|
38
41
|
purvey inventory list --stocked --pretty
|
|
39
42
|
|
|
40
43
|
# 5. Import a roast from Artisan
|
|
41
44
|
purvey roast import ~/artisan/my-roast.alog --coffee-id 7 --pretty
|
|
45
|
+
|
|
46
|
+
# 6. (Agents/scripts) Get the machine-readable CLI contract in one command
|
|
47
|
+
purvey manifest
|
|
48
|
+
|
|
49
|
+
# 7. (Humans/agents) Get the dense readable CLI reference
|
|
50
|
+
purvey context
|
|
42
51
|
```
|
|
43
52
|
|
|
44
53
|
## Authentication
|
|
45
54
|
|
|
55
|
+
No pre-existing session is required for `auth`, `config`, `context`, or `manifest`.
|
|
56
|
+
|
|
57
|
+
**All remote data commands require a valid authenticated session.** `catalog`, `inventory`, `roast`, `sales`, and `tasting` all require auth.
|
|
58
|
+
|
|
46
59
|
`purvey` uses Google OAuth through purveyors.io.
|
|
47
60
|
|
|
48
61
|
Interactive login:
|
|
@@ -55,6 +68,9 @@ Headless login for agents, CI, and remote machines:
|
|
|
55
68
|
|
|
56
69
|
```bash
|
|
57
70
|
purvey auth login --headless
|
|
71
|
+
# CLI prints a Google OAuth URL
|
|
72
|
+
# Open it in any browser and sign in
|
|
73
|
+
# Paste the full callback URL back into the terminal
|
|
58
74
|
```
|
|
59
75
|
|
|
60
76
|
Status:
|
|
@@ -75,14 +91,18 @@ Credentials are stored at `~/.config/purvey/credentials.json`.
|
|
|
75
91
|
|
|
76
92
|
### Auth roles
|
|
77
93
|
|
|
78
|
-
|
|
94
|
+
Two roles gate different command groups:
|
|
79
95
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
96
|
+
| Role | Commands |
|
|
97
|
+
| -------- | ------------------------------------------------------------------- |
|
|
98
|
+
| `viewer` | `catalog search`, `catalog get`, `catalog stats`, `catalog similar` |
|
|
99
|
+
| `member` | All viewer commands, plus `inventory`, `roast`, `sales`, `tasting` |
|
|
100
|
+
|
|
101
|
+
Both roles are granted when you sign in through purveyors.io. The `viewer` role is the minimum required for catalog access; the `member` role is required for any personal data or write operations.
|
|
102
|
+
|
|
103
|
+
`auth`, `config`, `context`, and `manifest` work without a pre-existing session. `config list/get/set/reset` are local-only commands, `context` is a local reference command, and `manifest` emits the machine-readable CLI contract.
|
|
84
104
|
|
|
85
|
-
|
|
105
|
+
Commands that require a higher role will exit with code `3` (auth error) if you are not signed in or your role is insufficient. Run `purvey auth status` to confirm your current role before scripting.
|
|
86
106
|
|
|
87
107
|
## Output and Scripting
|
|
88
108
|
|
|
@@ -112,10 +132,49 @@ purvey auth status 2>/dev/null | jq -r '.email'
|
|
|
112
132
|
|
|
113
133
|
Operational messages go to stderr, so stdout stays script-friendly.
|
|
114
134
|
|
|
135
|
+
Fatal errors also stay on stderr, but the payload format depends on mode:
|
|
136
|
+
|
|
137
|
+
- interactive terminal with no explicit output flag: human-readable text
|
|
138
|
+
- `--json`, `--pretty`, or `--csv`: JSON error envelope on stderr
|
|
139
|
+
- piped or redirected with no explicit flag: compact JSON error envelope on stderr
|
|
140
|
+
|
|
141
|
+
That same contract applies to parser-level mistakes too, including unknown options, unknown commands, and missing required arguments.
|
|
142
|
+
|
|
143
|
+
The JSON error envelope includes:
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{ "error": true, "code": "INVALID_ARGUMENT", "exitCode": 2, "message": "..." }
|
|
147
|
+
```
|
|
148
|
+
|
|
115
149
|
### Output caveats worth knowing
|
|
116
150
|
|
|
117
|
-
- `purvey auth status` prints human-readable output in an interactive terminal unless you pass `--json`, `--pretty`, or `--csv`. When piped or redirected, it emits JSON.
|
|
151
|
+
- `purvey auth status` prints human-readable output in an interactive terminal unless you pass `--json`, `--pretty`, or `--csv`. When piped or redirected, it emits JSON on stdout even when unauthenticated.
|
|
152
|
+
- `purvey config list/get/set/reset` stay human-readable in an interactive terminal, but emit JSON on stdout when you pass `--json` or `--pretty`, or when stdout is non-interactive. `--csv` is not supported for config commands.
|
|
118
153
|
- `--json` is an explicit alias for the default compact JSON mode, and it forces JSON even in an interactive terminal.
|
|
154
|
+
- `--csv` affects successful stdout output only; fatal errors still use JSON on stderr.
|
|
155
|
+
|
|
156
|
+
## Exit Codes
|
|
157
|
+
|
|
158
|
+
All `purvey` commands exit with a numeric code your scripts can check with `$?`.
|
|
159
|
+
|
|
160
|
+
| Code | Meaning |
|
|
161
|
+
| ---- | ----------------------------------------------------------------------------------------- |
|
|
162
|
+
| `0` | Success |
|
|
163
|
+
| `1` | Unexpected or unclassified error |
|
|
164
|
+
| `2` | Invalid argument or bad input |
|
|
165
|
+
| `3` | Auth error: not logged in, expired session, or insufficient role |
|
|
166
|
+
| `4` | Not found |
|
|
167
|
+
| `5` | Dependency conflict (for example, `inventory delete` without `--force` when roasts exist) |
|
|
168
|
+
| `6` | Local config error |
|
|
169
|
+
|
|
170
|
+
Scripting pattern:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
purvey catalog search --origin "Ethiopia" --stocked --json
|
|
174
|
+
if [ $? -eq 3 ]; then
|
|
175
|
+
purvey auth login --headless
|
|
176
|
+
fi
|
|
177
|
+
```
|
|
119
178
|
|
|
120
179
|
## Command Reference
|
|
121
180
|
|
|
@@ -144,6 +203,9 @@ Operational messages go to stderr, so stdout stays script-friendly.
|
|
|
144
203
|
- `--supplier <name>` -- filter by supplier/source name (partial match, case-insensitive)
|
|
145
204
|
- `--ids <n,n,...>` -- fetch specific catalog IDs (comma-separated, ignores limit)
|
|
146
205
|
- `--stocked` -- only show currently stocked coffees
|
|
206
|
+
- `--variety <text>` -- filter by coffee variety/cultivar (partial match)
|
|
207
|
+
- `--drying-method <text>` -- filter by drying method (partial match)
|
|
208
|
+
- `--stocked-days <n>` -- only show coffees stocked within N days
|
|
147
209
|
- `--sort <price|price-desc|name|origin|newest>` -- sort results
|
|
148
210
|
- `--offset <n>` -- skip N results for pagination
|
|
149
211
|
- `--limit <n>` -- maximum results to return (default: 10)
|
|
@@ -171,12 +233,17 @@ purvey catalog similar 1182 --json | jq '.[0]'
|
|
|
171
233
|
- `purvey inventory get <id>`
|
|
172
234
|
- `purvey inventory add`
|
|
173
235
|
- `purvey inventory update <id>`
|
|
174
|
-
- `purvey inventory delete <id>`
|
|
236
|
+
- `purvey inventory delete <id>` (use `--force` to cascade delete dependent roasts and sales)
|
|
175
237
|
|
|
176
238
|
`inventory list` options:
|
|
177
239
|
|
|
178
240
|
- `--stocked` -- only show currently stocked beans
|
|
241
|
+
- `--catalog-id <id>` -- filter by catalog ID
|
|
242
|
+
- `--purchase-date-start <YYYY-MM-DD>` -- only show purchases on or after this date
|
|
243
|
+
- `--purchase-date-end <YYYY-MM-DD>` -- only show purchases on or before this date
|
|
244
|
+
- `--origin <country>` -- filter by country of origin (partial match)
|
|
179
245
|
- `--limit <n>` -- maximum results (default: 20)
|
|
246
|
+
- `--offset <n>` -- skip N results for pagination (default: 0)
|
|
180
247
|
|
|
181
248
|
`inventory add` flags:
|
|
182
249
|
|
|
@@ -200,6 +267,8 @@ Examples:
|
|
|
200
267
|
|
|
201
268
|
```bash
|
|
202
269
|
purvey inventory list --stocked --pretty
|
|
270
|
+
purvey inventory list --limit 20 --offset 20 # page 2
|
|
271
|
+
purvey inventory list --csv > inventory.csv
|
|
203
272
|
purvey inventory add --catalog-id 128 --qty 10 --cost 8.50
|
|
204
273
|
purvey inventory add --catalog-id 42 --qty 5 --cost 6.25 --tax-ship 4.00
|
|
205
274
|
purvey inventory update 7 --stocked false
|
|
@@ -221,11 +290,13 @@ purvey inventory delete 7 --yes
|
|
|
221
290
|
- `--coffee-id <id>` -- filter by inventory item ID (green_coffee_inv.id)
|
|
222
291
|
- `--roast-id <id>` -- filter by exact roast profile ID
|
|
223
292
|
- `--batch-name <text>` -- filter by batch name (partial match, case-insensitive)
|
|
293
|
+
- `--coffee-name <text>` -- filter by bean name (partial match, case-insensitive)
|
|
224
294
|
- `--date-start <YYYY-MM-DD>` -- only show roasts on or after this date
|
|
225
295
|
- `--date-end <YYYY-MM-DD>` -- only show roasts on or before this date
|
|
226
296
|
- `--stocked` -- only show roasts for currently stocked beans
|
|
227
297
|
- `--catalog-id <id>` -- filter by coffee_catalog ID
|
|
228
298
|
- `--limit <n>` -- maximum results (default: 20)
|
|
299
|
+
- `--offset <n>` -- skip N results for pagination (default: 0)
|
|
229
300
|
|
|
230
301
|
`roast get <id>` options:
|
|
231
302
|
|
|
@@ -272,6 +343,7 @@ Examples:
|
|
|
272
343
|
purvey roast list --catalog-id 128 --pretty
|
|
273
344
|
purvey roast list --batch-name "Ethiopia Guji" --pretty
|
|
274
345
|
purvey roast list --date-start 2026-03-01 --date-end 2026-03-31
|
|
346
|
+
purvey roast list --limit 20 --offset 20 # page 2
|
|
275
347
|
purvey roast create --coffee-id 7 --batch-name "Ethiopia Guji Light" --oz-in 16
|
|
276
348
|
purvey roast update 123 --targets "Aim for FC at 390F, 18% dev"
|
|
277
349
|
purvey roast import ~/artisan/ethiopia.alog --coffee-id 7
|
|
@@ -285,6 +357,15 @@ purvey roast watch ~/artisan/ --auto-match
|
|
|
285
357
|
- `purvey sales update <id>`
|
|
286
358
|
- `purvey sales delete <id>`
|
|
287
359
|
|
|
360
|
+
`sales list` filters:
|
|
361
|
+
|
|
362
|
+
- `--roast-id <id>` -- filter by roast profile ID
|
|
363
|
+
- `--date-start <YYYY-MM-DD>` -- only show sales on or after this date
|
|
364
|
+
- `--date-end <YYYY-MM-DD>` -- only show sales on or before this date
|
|
365
|
+
- `--buyer <name>` -- filter by buyer name (partial match, case-insensitive)
|
|
366
|
+
- `--limit <n>` -- maximum results (default: 20)
|
|
367
|
+
- `--offset <n>` -- skip N results for pagination (default: 0)
|
|
368
|
+
|
|
288
369
|
`sales record` flags:
|
|
289
370
|
|
|
290
371
|
- `--roast-id <id>` -- [REQUIRED] roast_data.roast_id
|
|
@@ -306,20 +387,23 @@ Examples:
|
|
|
306
387
|
```bash
|
|
307
388
|
purvey sales record --roast-id 123 --oz 12 --price 22.00 --buyer "Jane Smith"
|
|
308
389
|
purvey sales list --pretty
|
|
390
|
+
purvey sales list --limit 20 --offset 20 # page 2
|
|
309
391
|
purvey sales update 5 --price 24.00
|
|
310
392
|
purvey sales delete 5 --yes
|
|
311
393
|
```
|
|
312
394
|
|
|
313
395
|
### tasting
|
|
314
396
|
|
|
315
|
-
- `purvey tasting get <
|
|
316
|
-
- `purvey tasting rate [
|
|
397
|
+
- `purvey tasting get <catalog-id>` -- retrieve tasting notes (uses `coffee_catalog.catalog_id`)
|
|
398
|
+
- `purvey tasting rate [inventory-id]` -- record cupping scores (uses `green_coffee_inv.id`)
|
|
399
|
+
|
|
400
|
+
**ID distinction:** `tasting get` takes a `catalog_id`; `tasting rate` takes an `inventory id`. These are different numbers. Use `purvey catalog search` to find a `catalog_id` and `purvey inventory list` to find your `inventory id`.
|
|
317
401
|
|
|
318
|
-
`purvey tasting get <
|
|
402
|
+
`purvey tasting get <catalog-id>` options:
|
|
319
403
|
|
|
320
404
|
- `--filter <user|supplier|both>` -- which notes to show (default: both)
|
|
321
405
|
|
|
322
|
-
`purvey tasting rate [
|
|
406
|
+
`purvey tasting rate [inventory-id]` options:
|
|
323
407
|
|
|
324
408
|
- `--aroma <1-5>` -- [REQUIRED in flag mode]
|
|
325
409
|
- `--body <1-5>` -- [REQUIRED in flag mode]
|
|
@@ -333,7 +417,9 @@ purvey sales delete 5 --yes
|
|
|
333
417
|
Examples:
|
|
334
418
|
|
|
335
419
|
```bash
|
|
420
|
+
# catalog_id 128 = the bean in the catalog
|
|
336
421
|
purvey tasting get 128 --filter both --pretty
|
|
422
|
+
# inventory id 7 = your physical purchase from inventory
|
|
337
423
|
purvey tasting rate 7 --aroma 4 --body 3 --acidity 5 --sweetness 4 --aftertaste 4
|
|
338
424
|
purvey tasting rate 42 --aroma 3 --body 3 --acidity 3 --sweetness 3 --aftertaste 3 --notes "Underextracted"
|
|
339
425
|
```
|
|
@@ -349,18 +435,53 @@ Current config key:
|
|
|
349
435
|
|
|
350
436
|
- `form-mode`: when set to `true`, write commands enter interactive mode when required args are missing
|
|
351
437
|
|
|
438
|
+
Output behavior:
|
|
439
|
+
|
|
440
|
+
- Interactive terminals keep config commands human-readable by default
|
|
441
|
+
- `--json` or `--pretty`, or any non-interactive stdout, emits JSON on stdout
|
|
442
|
+
- `--csv` is not supported for config commands
|
|
443
|
+
|
|
352
444
|
Examples:
|
|
353
445
|
|
|
354
446
|
```bash
|
|
355
447
|
purvey config set form-mode true
|
|
356
448
|
purvey config get form-mode
|
|
449
|
+
purvey config get form-mode --json
|
|
450
|
+
purvey config reset --json
|
|
357
451
|
```
|
|
358
452
|
|
|
359
453
|
### context
|
|
360
454
|
|
|
361
455
|
- `purvey context`
|
|
456
|
+
- `purvey context --json`
|
|
457
|
+
- `purvey context --pretty`
|
|
458
|
+
|
|
459
|
+
`purvey context` defaults to dense, human-readable, source-aware CLI reference text.
|
|
460
|
+
|
|
461
|
+
Use `--json` or `--pretty` when you want the same machine-readable manifest that `purvey manifest` emits.
|
|
462
|
+
|
|
463
|
+
### manifest
|
|
464
|
+
|
|
465
|
+
- `purvey manifest`
|
|
466
|
+
- `purvey manifest --pretty`
|
|
362
467
|
|
|
363
|
-
Use this when an agent needs
|
|
468
|
+
Use this when an agent or script needs the machine-readable contract directly. `purvey manifest` emits compact JSON by default.
|
|
469
|
+
|
|
470
|
+
`purvey manifest` and `purvey context --json` emit the same JSON manifest.
|
|
471
|
+
|
|
472
|
+
If you want indented JSON, add `--pretty` to either command.
|
|
473
|
+
|
|
474
|
+
### in-process manifest
|
|
475
|
+
|
|
476
|
+
- `@purveyors/cli/manifest`
|
|
477
|
+
|
|
478
|
+
Use this when you need the same contract from Node.js without shelling out to the CLI. This package subpath is exported via `./manifest` in `package.json`.
|
|
479
|
+
|
|
480
|
+
```ts
|
|
481
|
+
import { getCliManifest } from '@purveyors/cli/manifest';
|
|
482
|
+
|
|
483
|
+
const manifest = getCliManifest();
|
|
484
|
+
```
|
|
364
485
|
|
|
365
486
|
## Common Workflows
|
|
366
487
|
|
|
@@ -412,6 +533,7 @@ Use the right ID for the right command.
|
|
|
412
533
|
Start here:
|
|
413
534
|
|
|
414
535
|
```bash
|
|
536
|
+
purvey manifest
|
|
415
537
|
purvey context
|
|
416
538
|
```
|
|
417
539
|
|
|
@@ -429,7 +551,56 @@ The CLI is designed to be agent-friendly:
|
|
|
429
551
|
- structured output on stdout
|
|
430
552
|
- headless auth flow
|
|
431
553
|
- copy-pasteable examples
|
|
432
|
-
- a dedicated `
|
|
554
|
+
- a dedicated `manifest` command for machine-readable onboarding
|
|
555
|
+
- a dedicated `context` command for dense human-readable onboarding
|
|
556
|
+
- `purvey context --json` parity with `purvey manifest`
|
|
557
|
+
- an `@purveyors/cli/manifest` export for in-process access
|
|
558
|
+
- documented exit codes for programmatic error handling
|
|
559
|
+
- `--offset` + `--limit` pagination on all list commands
|
|
560
|
+
|
|
561
|
+
The scripting contract: stdout is always structured success data (JSON or CSV). stderr carries status/spinner output plus fatal errors. In structured or non-interactive modes, fatal errors are JSON envelopes on stderr; in interactive no-flag mode, they stay human-readable. Exit codes are stable and documented above. Never expect success data on stderr.
|
|
562
|
+
|
|
563
|
+
## Troubleshooting
|
|
564
|
+
|
|
565
|
+
**`Error: not logged in` or exit code 3**
|
|
566
|
+
|
|
567
|
+
```bash
|
|
568
|
+
purvey auth login
|
|
569
|
+
# or for headless environments:
|
|
570
|
+
purvey auth login --headless
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
**Catalog commands fail with auth error after logging in**
|
|
574
|
+
|
|
575
|
+
Run `purvey auth status` to confirm you have a `viewer` or `member` role. Both are granted automatically on sign-in. If auth status shows a stale session, run `purvey auth logout` then log in again.
|
|
576
|
+
|
|
577
|
+
**Wrong ID type passed to a command**
|
|
578
|
+
|
|
579
|
+
The most common mistake is mixing up ID types. Check the [ID Reference](#id-reference) section above. Use `purvey catalog search` to find `catalog_id` values; use `purvey inventory list` to find `inventory id` values.
|
|
580
|
+
|
|
581
|
+
**Pagination: only seeing the first 20 results**
|
|
582
|
+
|
|
583
|
+
All list commands default to 20 results. Use `--limit` and `--offset` to page through larger sets:
|
|
584
|
+
|
|
585
|
+
```bash
|
|
586
|
+
purvey inventory list --limit 20 --offset 0 # page 1
|
|
587
|
+
purvey inventory list --limit 20 --offset 20 # page 2
|
|
588
|
+
purvey inventory list --limit 20 --offset 40 # page 3
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
**`inventory delete` fails with dependency conflict (exit code 5)**
|
|
592
|
+
|
|
593
|
+
The item has dependent roast profiles or sales records. Use `--force` to cascade delete:
|
|
594
|
+
|
|
595
|
+
```bash
|
|
596
|
+
purvey inventory delete 7 --force --yes
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
**Enable verbose error output**
|
|
600
|
+
|
|
601
|
+
```bash
|
|
602
|
+
PURVEY_DEBUG=1 purvey <command>
|
|
603
|
+
```
|
|
433
604
|
|
|
434
605
|
## Development
|
|
435
606
|
|
|
@@ -445,12 +616,19 @@ npm test
|
|
|
445
616
|
|
|
446
617
|
Key files:
|
|
447
618
|
|
|
448
|
-
- `src/index.ts`:
|
|
619
|
+
- `src/index.ts`: executable entrypoint
|
|
620
|
+
- `src/program.ts`: top-level CLI registration and global options
|
|
449
621
|
- `src/commands/`: command definitions and help text
|
|
450
622
|
- `src/lib/`: business logic and Supabase integration
|
|
451
|
-
- `src/commands/context.ts`: dense agent reference
|
|
623
|
+
- `src/commands/context.ts`: dense human-readable agent reference
|
|
624
|
+
- `src/commands/manifest.ts`: machine-readable CLI manifest command
|
|
625
|
+
- `src/lib/manifest.ts`: shared manifest contract and renderer
|
|
626
|
+
- `package.json`: package metadata and export surface, including `./manifest`
|
|
452
627
|
- `AGENTS.md`: contributor guide
|
|
453
628
|
|
|
629
|
+
Live documentation: [purveyors.io/docs](https://purveyors.io/docs)
|
|
630
|
+
Package: [npmjs.com/package/@purveyors/cli](https://www.npmjs.com/package/@purveyors/cli)
|
|
631
|
+
|
|
454
632
|
## License
|
|
455
633
|
|
|
456
634
|
Sustainable Use License. See [LICENSE.md](./LICENSE.md).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuUpC;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAkF1C"}
|
package/dist/commands/auth.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createServer } from 'http';
|
|
|
3
3
|
import { createAnonClient, validateSession } from '../lib/supabase.js';
|
|
4
4
|
import { writeCredentials, deleteCredentials } from '../lib/config.js';
|
|
5
5
|
import { outputData, shouldUseInteractiveOutput, success, info, warn } from '../lib/output.js';
|
|
6
|
-
import { withErrorHandling, AuthError } from '../lib/errors.js';
|
|
6
|
+
import { withErrorHandling, AuthError, exitCodeForError } from '../lib/errors.js';
|
|
7
7
|
import chalk from 'chalk';
|
|
8
8
|
import ora from 'ora';
|
|
9
9
|
const DEFAULT_CALLBACK_HOST = 'localhost';
|
|
@@ -159,12 +159,13 @@ const statusAction = withErrorHandling(async (_, cmd) => {
|
|
|
159
159
|
authenticated: false,
|
|
160
160
|
message: 'Not logged in. Run `purvey auth login` to authenticate.',
|
|
161
161
|
};
|
|
162
|
+
const error = new AuthError(result.message);
|
|
162
163
|
if (isInteractive) {
|
|
163
164
|
warn(result.message);
|
|
164
|
-
process.exit(
|
|
165
|
+
process.exit(exitCodeForError(error));
|
|
165
166
|
}
|
|
166
167
|
outputData(result, opts);
|
|
167
|
-
process.exit(
|
|
168
|
+
process.exit(exitCodeForError(error));
|
|
168
169
|
}
|
|
169
170
|
const result = {
|
|
170
171
|
authenticated: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,0BAA0B,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/commands/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAKL,mBAAmB,EACnB,mBAAmB,EAEpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAiC,MAAM,mBAAmB,CAAC;AAIlG,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/commands/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAKL,mBAAmB,EACnB,mBAAmB,EAEpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAiC,MAAM,mBAAmB,CAAC;AAIlG,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,CAAC;AAoCpD;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAwS7C"}
|
package/dist/commands/catalog.js
CHANGED
|
@@ -1,9 +1,34 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import { outputData, info
|
|
3
|
-
import { withErrorHandling } from '../lib/errors.js';
|
|
2
|
+
import { outputData, info } from '../lib/output.js';
|
|
3
|
+
import { withErrorHandling, PrvrsError } from '../lib/errors.js';
|
|
4
4
|
import { requireAuth } from '../lib/auth-guard.js';
|
|
5
5
|
import { searchCatalog, getCatalog, getCatalogStats, findSimilarBeans, computeCatalogStats, sanitizeFilterValue, catalogSortFields, } from '../lib/catalog.js';
|
|
6
6
|
export { sanitizeFilterValue, computeCatalogStats };
|
|
7
|
+
function parseFiniteNumberArg(rawValue, message) {
|
|
8
|
+
const trimmed = rawValue.trim();
|
|
9
|
+
if (trimmed.length === 0) {
|
|
10
|
+
throw new PrvrsError('INVALID_ARGUMENT', message);
|
|
11
|
+
}
|
|
12
|
+
const parsed = Number(trimmed);
|
|
13
|
+
if (!Number.isFinite(parsed)) {
|
|
14
|
+
throw new PrvrsError('INVALID_ARGUMENT', message);
|
|
15
|
+
}
|
|
16
|
+
return parsed;
|
|
17
|
+
}
|
|
18
|
+
function parsePositiveIntegerArg(rawValue, message) {
|
|
19
|
+
const parsed = parseFiniteNumberArg(rawValue, message);
|
|
20
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
21
|
+
throw new PrvrsError('INVALID_ARGUMENT', message);
|
|
22
|
+
}
|
|
23
|
+
return parsed;
|
|
24
|
+
}
|
|
25
|
+
function parseNonNegativeIntegerArg(rawValue, message) {
|
|
26
|
+
const parsed = parseFiniteNumberArg(rawValue, message);
|
|
27
|
+
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
28
|
+
throw new PrvrsError('INVALID_ARGUMENT', message);
|
|
29
|
+
}
|
|
30
|
+
return parsed;
|
|
31
|
+
}
|
|
7
32
|
// ─── Command builder ──────────────────────────────────────────────────────────
|
|
8
33
|
/**
|
|
9
34
|
* `purvey catalog` — Browse the coffee catalog.
|
|
@@ -68,12 +93,10 @@ Notes:
|
|
|
68
93
|
`)
|
|
69
94
|
.action(withErrorHandling(async (opts, cmd) => {
|
|
70
95
|
const globalOpts = cmd.optsWithGlobals();
|
|
71
|
-
const { supabase } = await requireAuth('viewer');
|
|
72
96
|
// Validate --sort if provided
|
|
73
97
|
const sortValue = opts.sort;
|
|
74
98
|
if (sortValue && !catalogSortFields.includes(sortValue)) {
|
|
75
|
-
|
|
76
|
-
process.exit(1);
|
|
99
|
+
throw new PrvrsError('INVALID_ARGUMENT', `Invalid --sort value: "${sortValue}". Must be one of: ${catalogSortFields.join(', ')}`);
|
|
77
100
|
}
|
|
78
101
|
// Parse --ids: comma-separated integers
|
|
79
102
|
let parsedIds;
|
|
@@ -84,35 +107,40 @@ Notes:
|
|
|
84
107
|
.filter(Boolean);
|
|
85
108
|
const nums = [];
|
|
86
109
|
for (const token of raw) {
|
|
87
|
-
|
|
88
|
-
if (isNaN(n) || n <= 0) {
|
|
89
|
-
warn(`Invalid --ids value: "${token}". Each ID must be a positive integer.`);
|
|
90
|
-
process.exit(1);
|
|
91
|
-
}
|
|
92
|
-
nums.push(n);
|
|
110
|
+
nums.push(parsePositiveIntegerArg(token, `Invalid --ids value: "${token}". Each ID must be a positive integer.`));
|
|
93
111
|
}
|
|
94
112
|
parsedIds = nums;
|
|
95
113
|
}
|
|
114
|
+
const priceMin = opts.priceMin !== undefined
|
|
115
|
+
? parseFiniteNumberArg(opts.priceMin, `Invalid --price-min: "${opts.priceMin}". Must be a number.`)
|
|
116
|
+
: undefined;
|
|
117
|
+
const priceMax = opts.priceMax !== undefined
|
|
118
|
+
? parseFiniteNumberArg(opts.priceMax, `Invalid --price-max: "${opts.priceMax}". Must be a number.`)
|
|
119
|
+
: undefined;
|
|
120
|
+
const stockedDays = opts.stockedDays !== undefined
|
|
121
|
+
? parsePositiveIntegerArg(opts.stockedDays, `Invalid --stocked-days: "${opts.stockedDays}". Must be a positive integer.`)
|
|
122
|
+
: undefined;
|
|
123
|
+
const offset = opts.offset !== undefined
|
|
124
|
+
? parseNonNegativeIntegerArg(opts.offset, `Invalid --offset: "${opts.offset}". Must be a non-negative integer.`)
|
|
125
|
+
: undefined;
|
|
126
|
+
const limit = parsePositiveIntegerArg(opts.limit, `Invalid --limit: "${opts.limit}". Must be a positive integer.`);
|
|
127
|
+
const { supabase } = await requireAuth('viewer');
|
|
96
128
|
const data = await searchCatalog(supabase, {
|
|
97
129
|
origin: opts.origin,
|
|
98
130
|
process: opts.process,
|
|
99
|
-
priceMin
|
|
100
|
-
priceMax
|
|
131
|
+
priceMin,
|
|
132
|
+
priceMax,
|
|
101
133
|
flavor: opts.flavor,
|
|
102
134
|
name: opts.name,
|
|
103
135
|
supplier: opts.supplier,
|
|
104
136
|
ids: parsedIds,
|
|
105
137
|
variety: opts.variety,
|
|
106
138
|
dryingMethod: opts.dryingMethod,
|
|
107
|
-
stockedDays
|
|
108
|
-
? Math.max(1, parseInt(opts.stockedDays, 10))
|
|
109
|
-
: undefined,
|
|
139
|
+
stockedDays,
|
|
110
140
|
stocked: opts.stocked ? true : undefined,
|
|
111
141
|
sort: sortValue,
|
|
112
|
-
offset
|
|
113
|
-
|
|
114
|
-
: undefined,
|
|
115
|
-
limit: Math.max(1, parseInt(opts.limit, 10)),
|
|
142
|
+
offset,
|
|
143
|
+
limit,
|
|
116
144
|
});
|
|
117
145
|
if (data.length === 0) {
|
|
118
146
|
info('No coffees found matching your criteria.');
|
|
@@ -137,8 +165,9 @@ Notes:
|
|
|
137
165
|
`)
|
|
138
166
|
.action(withErrorHandling(async (id, _opts, cmd) => {
|
|
139
167
|
const globalOpts = cmd.optsWithGlobals();
|
|
168
|
+
const catalogId = parsePositiveIntegerArg(id, `Invalid ID: "${id}". Please provide a numeric coffee_catalog ID.`);
|
|
140
169
|
const { supabase } = await requireAuth('viewer');
|
|
141
|
-
const data = await getCatalog(supabase,
|
|
170
|
+
const data = await getCatalog(supabase, catalogId);
|
|
142
171
|
outputData(data, globalOpts);
|
|
143
172
|
}));
|
|
144
173
|
// ── catalog stats ─────────────────────────────────────────────────────────
|
|
@@ -184,15 +213,11 @@ Notes:
|
|
|
184
213
|
`)
|
|
185
214
|
.action(withErrorHandling(async (id, opts, cmd) => {
|
|
186
215
|
const globalOpts = cmd.optsWithGlobals();
|
|
187
|
-
const
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
warn(`Invalid ID: "${id}". Please provide a numeric coffee_catalog ID.`);
|
|
191
|
-
process.exit(1);
|
|
192
|
-
}
|
|
193
|
-
const threshold = parseFloat(opts.threshold);
|
|
194
|
-
const limit = Math.max(1, parseInt(opts.limit, 10));
|
|
216
|
+
const coffeeId = parsePositiveIntegerArg(id, `Invalid ID: "${id}". Please provide a numeric coffee_catalog ID.`);
|
|
217
|
+
const threshold = parseFiniteNumberArg(opts.threshold, `Invalid --threshold: "${opts.threshold}". Must be a number between 0 and 1.`);
|
|
218
|
+
const limit = parsePositiveIntegerArg(opts.limit, `Invalid --limit: "${opts.limit}". Must be a positive integer.`);
|
|
195
219
|
const stockedOnly = Boolean(opts.stockedOnly);
|
|
220
|
+
const { supabase } = await requireAuth('viewer');
|
|
196
221
|
// Confirm the target bean exists before running similarity lookup.
|
|
197
222
|
const { data: targetBean, error: targetError } = await supabase
|
|
198
223
|
.from('coffee_catalog')
|
|
@@ -200,8 +225,7 @@ Notes:
|
|
|
200
225
|
.eq('catalog_id', coffeeId)
|
|
201
226
|
.single();
|
|
202
227
|
if (targetError || !targetBean) {
|
|
203
|
-
|
|
204
|
-
process.exit(1);
|
|
228
|
+
throw new PrvrsError('NOT_FOUND', `Coffee ID ${coffeeId} not found in catalog.`);
|
|
205
229
|
}
|
|
206
230
|
// Call the lib function
|
|
207
231
|
const results = await findSimilarBeans(supabase, {
|