@purveyors/cli 0.9.6 → 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.
Files changed (45) hide show
  1. package/README.md +182 -20
  2. package/dist/commands/auth.d.ts.map +1 -1
  3. package/dist/commands/auth.js +4 -3
  4. package/dist/commands/auth.js.map +1 -1
  5. package/dist/commands/catalog.d.ts.map +1 -1
  6. package/dist/commands/catalog.js +55 -31
  7. package/dist/commands/catalog.js.map +1 -1
  8. package/dist/commands/config.d.ts.map +1 -1
  9. package/dist/commands/config.js +61 -12
  10. package/dist/commands/config.js.map +1 -1
  11. package/dist/commands/context.d.ts.map +1 -1
  12. package/dist/commands/context.js +32 -234
  13. package/dist/commands/context.js.map +1 -1
  14. package/dist/commands/manifest.d.ts +3 -0
  15. package/dist/commands/manifest.d.ts.map +1 -0
  16. package/dist/commands/manifest.js +28 -0
  17. package/dist/commands/manifest.js.map +1 -0
  18. package/dist/index.js +6 -105
  19. package/dist/index.js.map +1 -1
  20. package/dist/lib/config.d.ts.map +1 -1
  21. package/dist/lib/config.js +8 -2
  22. package/dist/lib/config.js.map +1 -1
  23. package/dist/lib/errors.d.ts +13 -1
  24. package/dist/lib/errors.d.ts.map +1 -1
  25. package/dist/lib/errors.js +153 -10
  26. package/dist/lib/errors.js.map +1 -1
  27. package/dist/lib/index.d.ts +1 -0
  28. package/dist/lib/index.d.ts.map +1 -1
  29. package/dist/lib/index.js +1 -0
  30. package/dist/lib/index.js.map +1 -1
  31. package/dist/lib/manifest.d.ts +100 -0
  32. package/dist/lib/manifest.d.ts.map +1 -0
  33. package/dist/lib/manifest.js +919 -0
  34. package/dist/lib/manifest.js.map +1 -0
  35. package/dist/lib/output.d.ts +10 -0
  36. package/dist/lib/output.d.ts.map +1 -1
  37. package/dist/lib/output.js +33 -18
  38. package/dist/lib/output.js.map +1 -1
  39. package/dist/program.d.ts +4 -0
  40. package/dist/program.d.ts.map +1 -0
  41. package/dist/program.js +131 -0
  42. package/dist/program.js.map +1 -0
  43. package/dist/types/index.d.ts +4 -0
  44. package/dist/types/index.d.ts.map +1 -1
  45. package/package.json +2 -1
@@ -1,8 +1,23 @@
1
1
  import { Command } from 'commander';
2
2
  import { withErrorHandling, PrvrsError } from '../lib/errors.js';
3
- import { readConfig, writeConfig, getConfigValue, setConfigValue, isValidConfigKey, } from '../lib/config.js';
4
- import { success, info } from '../lib/output.js';
3
+ import { readConfig, writeConfig, setConfigValue, isValidConfigKey } from '../lib/config.js';
4
+ import { outputData, shouldUseInteractiveOutput, success, info } from '../lib/output.js';
5
5
  // ─── Command builder ──────────────────────────────────────────────────────────
6
+ function resolveConfigOutput(cmd) {
7
+ const outputOptions = cmd.optsWithGlobals();
8
+ if (outputOptions.csv) {
9
+ throw new PrvrsError('INVALID_ARGUMENT', 'The config commands do not support --csv. Use text, --json, or --pretty.');
10
+ }
11
+ return {
12
+ outputOptions,
13
+ isInteractive: shouldUseInteractiveOutput(outputOptions),
14
+ };
15
+ }
16
+ function configValuePayload(key, value) {
17
+ return {
18
+ [key]: value ?? null,
19
+ };
20
+ }
6
21
  /**
7
22
  * `purvey config` — Manage purvey CLI settings.
8
23
  * Config is stored in ~/.config/purvey/config.json.
@@ -19,11 +34,18 @@ Examples:
19
34
 
20
35
  Notes:
21
36
  Config is stored at ~/.config/purvey/config.json.
22
- Shows all key = value pairs currently set.
37
+ Interactive terminals show human-readable key = value lines.
38
+ --json / --pretty, or any non-interactive use, emits the config object on stdout.
39
+ --csv is not supported.
23
40
  `)
24
- .action(withErrorHandling(async () => {
41
+ .action(withErrorHandling(async (_, cmd) => {
42
+ const { outputOptions, isInteractive } = resolveConfigOutput(cmd);
25
43
  const cfg = await readConfig();
26
44
  const keys = Object.keys(cfg);
45
+ if (!isInteractive) {
46
+ outputData(cfg, outputOptions);
47
+ return;
48
+ }
27
49
  if (keys.length === 0) {
28
50
  info('No config values set. Use `purvey config set <key> <value>` to configure.');
29
51
  return;
@@ -46,19 +68,27 @@ Supported keys:
46
68
  form-mode true/false — auto-enter interactive wizard when required args are missing
47
69
 
48
70
  Notes:
49
- Prints the raw value to stdout (no decorators), suitable for scripting.
50
- Prints "form-mode is not set." if the key has no value.
71
+ Interactive terminals print the raw value to stdout with no decorators.
72
+ --json / --pretty, or any non-interactive use, emits {"<key>": value|null}.
73
+ Prints "form-mode is not set." interactively if the key has no value.
74
+ --csv is not supported.
51
75
  `)
52
- .action(withErrorHandling(async (key) => {
76
+ .action(withErrorHandling(async (key, _opts, cmd) => {
53
77
  if (!isValidConfigKey(key)) {
54
78
  throw new PrvrsError('INVALID_ARGUMENT', `Unknown config key: "${key}". Valid keys: form-mode.`);
55
79
  }
56
- const value = await getConfigValue(key);
80
+ const { outputOptions, isInteractive } = resolveConfigOutput(cmd);
81
+ const cfg = await readConfig();
82
+ const value = cfg[key];
83
+ if (!isInteractive) {
84
+ outputData(configValuePayload(key, value), outputOptions);
85
+ return;
86
+ }
57
87
  if (value === undefined) {
58
88
  info(`${key} is not set.`);
59
89
  }
60
90
  else {
61
- console.log(value);
91
+ console.log(String(value));
62
92
  }
63
93
  }));
64
94
  // ── config set <key> <value> ──────────────────────────────────────────────
@@ -74,18 +104,29 @@ Examples:
74
104
  $ purvey config set form-mode true
75
105
  $ purvey config set form-mode false
76
106
  $ purvey config get form-mode
77
- $ purvey config list
107
+ $ purvey config set form-mode true --json
108
+
109
+ Notes:
110
+ Interactive terminals print a human-readable success line.
111
+ --json / --pretty, or any non-interactive use, emits the updated config value.
112
+ --csv is not supported.
78
113
  `)
79
- .action(withErrorHandling(async (key, value) => {
114
+ .action(withErrorHandling(async (key, value, _opts, cmd) => {
80
115
  if (!isValidConfigKey(key)) {
81
116
  throw new PrvrsError('INVALID_ARGUMENT', `Unknown config key: "${key}". Valid keys: form-mode.`);
82
117
  }
118
+ const { outputOptions, isInteractive } = resolveConfigOutput(cmd);
83
119
  try {
84
120
  await setConfigValue(key, value);
85
121
  }
86
122
  catch (err) {
87
123
  throw new PrvrsError('INVALID_ARGUMENT', err instanceof Error ? err.message : String(err));
88
124
  }
125
+ const cfg = await readConfig();
126
+ if (!isInteractive) {
127
+ outputData(configValuePayload(key, cfg[key]), outputOptions);
128
+ return;
129
+ }
89
130
  success(`Config updated: ${key} = ${value}`);
90
131
  }));
91
132
  // ── config reset ──────────────────────────────────────────────────────────
@@ -98,9 +139,17 @@ Examples:
98
139
 
99
140
  Notes:
100
141
  Clears all config values. Equivalent to deleting ~/.config/purvey/config.json.
142
+ Interactive terminals print a human-readable success line.
143
+ --json / --pretty, or any non-interactive use, emits {}.
144
+ --csv is not supported.
101
145
  `)
102
- .action(withErrorHandling(async () => {
146
+ .action(withErrorHandling(async (_, cmd) => {
147
+ const { outputOptions, isInteractive } = resolveConfigOutput(cmd);
103
148
  await writeConfig({});
149
+ if (!isInteractive) {
150
+ outputData({}, outputOptions);
151
+ return;
152
+ }
104
153
  success('Config reset to defaults.');
105
154
  }));
106
155
  return config;
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC7F,OAAO,EAAE,UAAU,EAAE,0BAA0B,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAGzF,iFAAiF;AAEjF,SAAS,mBAAmB,CAAC,GAAY;IAIvC,MAAM,aAAa,GAAG,GAAG,CAAC,eAAe,EAAmB,CAAC;IAE7D,IAAI,aAAa,CAAC,GAAG,EAAE,CAAC;QACtB,MAAM,IAAI,UAAU,CAClB,kBAAkB,EAClB,0EAA0E,CAC3E,CAAC;IACJ,CAAC;IAED,OAAO;QACL,aAAa;QACb,aAAa,EAAE,0BAA0B,CAAC,aAAa,CAAC;KACzD,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CACzB,GAAW,EACX,KAA0B;IAE1B,OAAO;QACL,CAAC,GAAG,CAAC,EAAE,KAAK,IAAI,IAAI;KACrB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,MAAM,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,4BAA4B,CAAC,CAAC;IAE/E,6EAA6E;IAC7E,MAAM;SACH,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,+BAA+B,CAAC;SAC5C,WAAW,CACV,OAAO,EACP;;;;;;;;;CASL,CACI;SACA,MAAM,CACL,iBAAiB,CAAC,KAAK,EAAE,CAAU,EAAE,GAAY,EAAE,EAAE;QACnD,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAClE,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAA4B,CAAC;QAEzD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,UAAU,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,2EAA2E,CAAC,CAAC;YAClF,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC,CAAC,CACH,CAAC;IAEJ,6EAA6E;IAC7E,MAAM;SACH,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CAAC,kCAAkC,CAAC;SAC/C,WAAW,CACV,OAAO,EACP;;;;;;;;;;;;CAYL,CACI;SACA,MAAM,CACL,iBAAiB,CAAC,KAAK,EAAE,GAAW,EAAE,KAA8B,EAAE,GAAY,EAAE,EAAE;QACpF,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,UAAU,CAClB,kBAAkB,EAClB,wBAAwB,GAAG,2BAA2B,CACvD,CAAC;QACJ,CAAC;QAED,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAClE,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QAEvB,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,UAAU,CAAC,kBAAkB,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,aAAa,CAAC,CAAC;YAC1D,OAAO;QACT,CAAC;QAED,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,GAAG,cAAc,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC,CAAC,CACH,CAAC;IAEJ,6EAA6E;IAC7E,MAAM;SACH,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,2BAA2B,CAAC;SACxC,WAAW,CACV,OAAO,EACP;;;;;;;;;;;;;;;CAeL,CACI;SACA,MAAM,CACL,iBAAiB,CACf,KAAK,EAAE,GAAW,EAAE,KAAa,EAAE,KAA8B,EAAE,GAAY,EAAE,EAAE;QACjF,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,UAAU,CAClB,kBAAkB,EAClB,wBAAwB,GAAG,2BAA2B,CACvD,CAAC;QACJ,CAAC;QAED,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAElE,IAAI,CAAC;YACH,MAAM,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,UAAU,CAClB,kBAAkB,EAClB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACjD,CAAC;QACJ,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAC;QAE/B,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,UAAU,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;YAC7D,OAAO;QACT,CAAC;QAED,OAAO,CAAC,mBAAmB,GAAG,MAAM,KAAK,EAAE,CAAC,CAAC;IAC/C,CAAC,CACF,CACF,CAAC;IAEJ,6EAA6E;IAC7E,MAAM;SACH,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,qCAAqC,CAAC;SAClD,WAAW,CACV,OAAO,EACP;;;;;;;;;CASL,CACI;SACA,MAAM,CACL,iBAAiB,CAAC,KAAK,EAAE,CAAU,EAAE,GAAY,EAAE,EAAE;QACnD,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAClE,MAAM,WAAW,CAAC,EAAE,CAAC,CAAC;QAEtB,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,UAAU,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACvC,CAAC,CAAC,CACH,CAAC;IAEJ,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyOpC,wBAAgB,mBAAmB,IAAI,OAAO,CAe7C"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,mBAAmB,IAAI,OAAO,CAkD7C"}
@@ -1,244 +1,42 @@
1
1
  import { Command } from 'commander';
2
- // This text is intentionally dense. An agent should be able to read it once,
3
- // then use the CLI correctly without hunting through help output.
4
- const CONTEXT_TEXT = `
5
- PURVEY CLI - Agent Reference
6
- ============================
7
- Official CLI for purveyors.io. Node.js 20+.
8
- Credentials file: ~/.config/purvey/credentials.json
9
- Config file: ~/.config/purvey/config.json
10
-
11
- ROLES
12
- -----
13
- viewer valid authenticated session; required for catalog commands
14
- member required for inventory, roast, sales, and tasting commands
15
-
16
- AUTH
17
- ----
18
- Interactive login:
19
- purvey auth login
20
-
21
- Headless login:
22
- purvey auth login --headless
23
- 1. CLI prints a Google OAuth URL
24
- 2. User opens it in any browser and signs in
25
- 3. User pastes the full callback URL back into the terminal
26
-
27
- Status:
28
- purvey auth status
29
- purvey auth status --pretty
30
-
31
- Logout:
32
- purvey auth logout
33
-
34
- OUTPUT
35
- ------
36
- Most commands emit compact JSON to stdout by default.
37
- Use --json to request compact JSON explicitly.
38
- Use --pretty for indented JSON.
39
- Use --csv for array-shaped results that support CSV output.
40
- User feedback goes to stderr.
41
-
42
- Important exception:
43
- - auth status prints human-readable output in an interactive TTY unless --json, --pretty, or --csv is passed; otherwise it emits structured output
44
-
45
- ID MAP
46
- ------
47
- catalog_id coffee_catalog row; used by catalog get, inventory add --catalog-id, tasting get, roast list --catalog-id
48
- inventory_id green_coffee_inv row; used by inventory get/update/delete, roast --coffee-id, roast list --coffee-id, tasting rate
49
- roast_id roast_data row; used by roast get/delete, roast list --roast-id, sales --roast-id
50
- sale_id coffee_sales row; used by sales update/delete
51
-
52
- COMMANDS
53
- --------
54
- auth
55
- login [--headless]
56
- status
57
- logout
58
-
59
- catalog
60
- search [options]
61
- --origin <text>
62
- --process <method>
63
- --price-min <n>
64
- --price-max <n>
65
- --flavor <keywords>
66
- --name <text>
67
- --supplier <name>
68
- --ids <n,n,...>
69
- --variety <text>
70
- --drying-method <text>
71
- --stocked-days <n>
72
- --stocked
73
- --sort <price|price-desc|name|origin|newest>
74
- --offset <n>
75
- --limit <n>
76
- get <catalog_id>
77
- stats
78
- similar <catalog_id>
79
- --threshold <0-1> default 0.70
80
- --limit <n> default 10
81
- --stocked-only
82
-
83
- inventory (member)
84
- list
85
- --stocked
86
- --catalog-id <catalog_id>
87
- --purchase-date-start <YYYY-MM-DD>
88
- --purchase-date-end <YYYY-MM-DD>
89
- --origin <country>
90
- --limit <n>
91
- --offset <n>
92
- get <inventory_id>
93
- add
94
- --catalog-id <id> required in flag mode
95
- --qty <lbs> required in flag mode
96
- --cost <dollars>
97
- --tax-ship <dollars>
98
- --notes <text>
99
- --purchase-date <YYYY-MM-DD>
100
- --form
101
- update <inventory_id>
102
- --qty <lbs>
103
- --cost <dollars>
104
- --tax-ship <dollars>
105
- --notes <text>
106
- --stocked <true|false>
107
- delete <inventory_id> [--yes] [--force]
108
- --force cascade delete dependent roast profiles and sales records before deleting the item
109
- without --force, delete fails with DEPENDENCY_CONFLICT if dependents exist
110
-
111
- roast (member)
112
- list
113
- --coffee-id <inventory_id>
114
- --roast-id <roast_id>
115
- --batch-name <text>
116
- --coffee-name <text>
117
- --date-start <YYYY-MM-DD>
118
- --date-end <YYYY-MM-DD>
119
- --stocked
120
- --catalog-id <catalog_id>
121
- --limit <n>
122
- --offset <n>
123
- get <roast_id>
124
- --include-temps
125
- --include-events
126
- create
127
- --coffee-id <inventory_id> required in flag mode
128
- --batch-name <name>
129
- --oz-in <oz>
130
- --oz-out <oz>
131
- --roast-date <YYYY-MM-DD>
132
- --notes <text>
133
- --form
134
- update <roast_id>
135
- --notes <text>
136
- --oz-out <oz>
137
- --batch-name <name>
138
- --targets <text>
139
- delete <roast_id> [--yes]
140
- import [file]
141
- --coffee-id <inventory_id> required in flag mode
142
- --batch-name <name>
143
- --oz-in <oz>
144
- --roast-notes <text>
145
- --form
146
- watch [directory]
147
- --coffee-id <inventory_id> required unless --auto-match
148
- --batch-prefix <name>
149
- --prompt-each
150
- --auto-match mutually exclusive with --coffee-id
151
- --resume
152
- --form
153
-
154
- sales (member)
155
- list
156
- --roast-id <roast_id>
157
- --date-start <YYYY-MM-DD>
158
- --date-end <YYYY-MM-DD>
159
- --buyer <name>
160
- --limit <n>
161
- --offset <n>
162
- record
163
- --roast-id <roast_id> required in flag mode
164
- --oz <amount> required in flag mode
165
- --price <dollars> required in flag mode
166
- --buyer <name>
167
- --sell-date <YYYY-MM-DD>
168
- --form
169
- update <sale_id>
170
- --oz <amount>
171
- --price <dollars>
172
- --buyer <name>
173
- --sell-date <YYYY-MM-DD>
174
- delete <sale_id> [--yes]
175
-
176
- tasting (member)
177
- get <catalog_id>
178
- --filter <user|supplier|both> default both
179
- rate [inventory_id]
180
- --aroma <1-5> required in flag mode
181
- --body <1-5> required in flag mode
182
- --acidity <1-5> required in flag mode
183
- --sweetness <1-5> required in flag mode
184
- --aftertaste <1-5> required in flag mode
185
- --brew-method <method>
186
- --notes <text>
187
- --form
188
-
189
- config
190
- list
191
- get <key>
192
- set <key> <value>
193
- reset
194
-
195
- Current config keys:
196
- form-mode true|false
197
-
198
- WORKFLOWS
199
- ---------
200
- Catalog -> inventory:
201
- purvey catalog search --origin "Ethiopia" --stocked --pretty
202
- purvey inventory add --catalog-id 128 --qty 10 --cost 8.50
203
-
204
- Import a roast from Artisan:
205
- purvey inventory list --stocked --pretty
206
- purvey roast import ~/artisan/ethiopia.alog --coffee-id 7 --pretty
207
-
208
- Watch a folder for new roasts:
209
- purvey roast watch ~/artisan/ --coffee-id 7
210
- purvey roast watch ~/artisan/ --auto-match
211
- purvey roast watch --resume
212
-
213
- Rate coffee and record a sale:
214
- purvey tasting rate 7 --aroma 4 --body 3 --acidity 5 --sweetness 4 --aftertaste 4
215
- purvey sales record --roast-id 123 --oz 12 --price 22.00 --buyer "Jane Smith"
216
-
217
- ERROR PATTERNS
218
- --------------
219
- Not logged in:
220
- run purvey auth login or purvey auth login --headless
221
-
222
- Wrong ID type:
223
- verify whether the command wants catalog_id, inventory_id, roast_id, or sale_id
224
-
225
- Missing required args in write commands:
226
- pass the required flags or use --form
227
-
228
- Mutually exclusive watch flags:
229
- roast watch forbids using --auto-match together with --coffee-id
230
- `.trim();
2
+ import { PrvrsError, withErrorHandling } from '../lib/errors.js';
3
+ import { getCliManifest, renderContextText } from '../lib/manifest.js';
4
+ import { outputData } from '../lib/output.js';
231
5
  export function buildContextCommand() {
232
6
  return new Command('context')
233
- .description('Output full CLI reference for AI agent onboarding')
7
+ .description('Output the dense human-readable CLI reference, or the JSON manifest with --json/--pretty')
8
+ .option('--json', 'Emit the machine-readable manifest contract as compact JSON')
9
+ .option('--pretty', 'Emit the machine-readable manifest contract as indented JSON')
234
10
  .addHelpText('after', `
11
+ Default output is dense human-readable reference text.
12
+ Use --json or --pretty for the same machine-readable manifest emitted by \`purvey manifest\`.
13
+
235
14
  Examples:
236
15
  purvey context
237
16
  purvey context | head -50
238
- purvey context > cli-reference.txt
17
+ purvey context --json
18
+ purvey context --pretty
19
+ purvey context --json > cli-manifest.json
20
+ purvey manifest
239
21
  `)
240
- .action(() => {
241
- console.log(CONTEXT_TEXT);
242
- });
22
+ .action(withErrorHandling(async (opts, cmd) => {
23
+ const globalOpts = cmd.optsWithGlobals();
24
+ const manifest = getCliManifest();
25
+ const wantsJson = Boolean(opts.json) ||
26
+ Boolean(opts.pretty) ||
27
+ Boolean(globalOpts.json) ||
28
+ Boolean(globalOpts.pretty);
29
+ if (globalOpts.csv) {
30
+ throw new PrvrsError('INVALID_ARGUMENT', 'The context command does not support --csv. Use text, --json, or --pretty.');
31
+ }
32
+ if (wantsJson) {
33
+ outputData(manifest, {
34
+ json: true,
35
+ pretty: Boolean(opts.pretty) || Boolean(globalOpts.pretty),
36
+ });
37
+ return;
38
+ }
39
+ console.log(renderContextText(manifest));
40
+ }));
243
41
  }
244
42
  //# sourceMappingURL=context.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,6EAA6E;AAC7E,kEAAkE;AAElE,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkOpB,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC;SAC1B,WAAW,CAAC,mDAAmD,CAAC;SAChE,WAAW,CACV,OAAO,EACP;;;;;CAKL,CACI;SACA,MAAM,CAAC,GAAG,EAAE;QACX,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC;SAC1B,WAAW,CACV,0FAA0F,CAC3F;SACA,MAAM,CAAC,QAAQ,EAAE,6DAA6D,CAAC;SAC/E,MAAM,CAAC,UAAU,EAAE,8DAA8D,CAAC;SAClF,WAAW,CACV,OAAO,EACP;;;;;;;;;;;CAWL,CACI;SACA,MAAM,CACL,iBAAiB,CAAC,KAAK,EAAE,IAA6B,EAAE,GAAY,EAAE,EAAE;QACtE,MAAM,UAAU,GAAG,GAAG,CAAC,eAAe,EAAmB,CAAC;QAC1D,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;QAClC,MAAM,SAAS,GACb,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAClB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;YACpB,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;YACxB,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAE7B,IAAI,UAAU,CAAC,GAAG,EAAE,CAAC;YACnB,MAAM,IAAI,UAAU,CAClB,kBAAkB,EAClB,4EAA4E,CAC7E,CAAC;QACJ,CAAC;QAED,IAAI,SAAS,EAAE,CAAC;YACd,UAAU,CAAC,QAAQ,EAAE;gBACnB,IAAI,EAAE,IAAI;gBACV,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC;aAC3D,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CACH,CAAC;AACN,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function buildManifestCommand(): Command;
3
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/commands/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,oBAAoB,IAAI,OAAO,CAgC9C"}
@@ -0,0 +1,28 @@
1
+ import { Command } from 'commander';
2
+ import { PrvrsError, withErrorHandling } from '../lib/errors.js';
3
+ import { getCliManifest } from '../lib/manifest.js';
4
+ import { outputData } from '../lib/output.js';
5
+ export function buildManifestCommand() {
6
+ return new Command('manifest')
7
+ .description('Output the machine-readable CLI manifest contract')
8
+ .option('--json', 'Emit the manifest as compact JSON (default)')
9
+ .option('--pretty', 'Emit the manifest as indented JSON')
10
+ .addHelpText('after', `
11
+ Examples:
12
+ purvey manifest
13
+ purvey manifest --pretty
14
+ purvey manifest > cli-manifest.json
15
+ purvey manifest | jq '.commandGroups[].name'
16
+ `)
17
+ .action(withErrorHandling(async (opts, cmd) => {
18
+ const globalOpts = cmd.optsWithGlobals();
19
+ if (globalOpts.csv) {
20
+ throw new PrvrsError('INVALID_ARGUMENT', 'The manifest command does not support --csv. Use --json or --pretty.');
21
+ }
22
+ outputData(getCliManifest(), {
23
+ json: true,
24
+ pretty: Boolean(opts.pretty) || Boolean(globalOpts.pretty),
25
+ });
26
+ }));
27
+ }
28
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/commands/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,MAAM,UAAU,oBAAoB;IAClC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC;SAC3B,WAAW,CAAC,mDAAmD,CAAC;SAChE,MAAM,CAAC,QAAQ,EAAE,6CAA6C,CAAC;SAC/D,MAAM,CAAC,UAAU,EAAE,oCAAoC,CAAC;SACxD,WAAW,CACV,OAAO,EACP;;;;;;CAML,CACI;SACA,MAAM,CACL,iBAAiB,CAAC,KAAK,EAAE,IAA6B,EAAE,GAAY,EAAE,EAAE;QACtE,MAAM,UAAU,GAAG,GAAG,CAAC,eAAe,EAAmB,CAAC;QAE1D,IAAI,UAAU,CAAC,GAAG,EAAE,CAAC;YACnB,MAAM,IAAI,UAAU,CAClB,kBAAkB,EAClB,sEAAsE,CACvE,CAAC;QACJ,CAAC;QAED,UAAU,CAAC,cAAc,EAAE,EAAE;YAC3B,IAAI,EAAE,IAAI;YACV,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC;SAC3D,CAAC,CAAC;IACL,CAAC,CAAC,CACH,CAAC;AACN,CAAC"}
package/dist/index.js CHANGED
@@ -1,108 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import { Command } from 'commander';
3
- import { buildAuthCommand } from './commands/auth.js';
4
- import { buildCatalogCommand } from './commands/catalog.js';
5
- import { buildConfigCommand } from './commands/config.js';
6
- import { buildContextCommand } from './commands/context.js';
7
- import { buildInventoryCommand } from './commands/inventory.js';
8
- import { buildRoastCommand } from './commands/roast.js';
9
- import { buildSalesCommand } from './commands/sales.js';
10
- import { buildTastingCommand } from './commands/tasting.js';
11
- import { readFileSync } from 'fs';
12
- import { fileURLToPath } from 'url';
13
- import { dirname, join } from 'path';
14
- const __filename = fileURLToPath(import.meta.url);
15
- const __dirname = dirname(__filename);
16
- // Read version from package.json at runtime
17
- let version = '0.0.1';
18
- try {
19
- const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
20
- version = pkg.version ?? version;
21
- }
22
- catch {
23
- // Fallback to hardcoded version
24
- }
25
- const program = new Command();
26
- program
27
- .name('purvey')
28
- .description('The official CLI for purveyors.io. Coffee intelligence from your terminal')
29
- .version(version, '-v, --version', 'Print version')
30
- .option('--json', 'Output compact JSON explicitly (same as the default)')
31
- .option('--pretty', 'Pretty-print JSON output with colors')
32
- .option('--csv', 'Output results as CSV where supported')
33
- .addHelpText('after', `
34
- Authentication:
35
- auth login Log in to purveyors.io (--headless for agents)
36
- auth status Show current login status and role
37
- auth logout Clear stored credentials
38
-
39
- Catalog (authenticated viewer session required):
40
- catalog search Search the coffee catalog with filters
41
- catalog get Get details for a specific coffee by ID
42
- catalog stats Aggregate statistics for the catalog
43
- catalog similar Find similar coffees by catalog ID
44
-
45
- Personal Data (member role required):
46
- inventory list List your green coffee inventory
47
- inventory get Get a single inventory item
48
- inventory add Add a bean to your inventory
49
- inventory update Update an inventory item
50
- inventory delete Delete an inventory item
51
- roast list List your roast profiles
52
- roast get Get a single roast profile
53
- roast create Create a new roast profile
54
- roast update Update a roast profile
55
- roast delete Delete a roast profile
56
- roast import Import an Artisan .alog roast file
57
- roast watch Watch a directory for new .alog files
58
- sales list List your sales records
59
- sales record Record a new sale
60
- sales update Update a sale record
61
- sales delete Delete a sale record
62
- tasting get Get tasting notes for a coffee
63
- tasting rate Rate a coffee bean with cupping scores
64
-
65
- Configuration:
66
- config list Show all config values
67
- config get Get a config value
68
- config set Set a config value
69
- config reset Reset config to defaults
70
-
71
- Agent Tools:
72
- context Output the dense CLI reference for agents
73
-
74
- Global Options:
75
- --json Output compact JSON explicitly
76
- --pretty Pretty-print JSON output
77
- --csv Output array results as CSV where supported
78
- --help Show help for any command
79
- --version Show version number
80
-
81
- Examples:
82
- $ purvey auth login --headless
83
- $ purvey catalog search --origin "Ethiopia" --process "natural" --pretty
84
- $ purvey catalog similar 1182 --threshold 0.85 --stocked-only --json | jq '.[0]'
85
- $ purvey inventory list --stocked --pretty
86
- $ purvey roast import my-roast.alog --coffee-id 128
87
- $ purvey roast watch ~/artisan/ --auto-match
88
- $ purvey tasting rate 42 --aroma 4 --body 3 --acidity 5 --sweetness 4 --aftertaste 4
89
- $ purvey context
90
-
91
- Documentation: https://github.com/reedwhetstone/purveyors-cli
92
- Agent reference: purvey context
93
- `);
94
- // Register subcommands
95
- program.addCommand(buildAuthCommand());
96
- program.addCommand(buildCatalogCommand());
97
- program.addCommand(buildConfigCommand());
98
- program.addCommand(buildContextCommand());
99
- program.addCommand(buildInventoryCommand());
100
- program.addCommand(buildRoastCommand());
101
- program.addCommand(buildSalesCommand());
102
- program.addCommand(buildTastingCommand());
103
- // Parse and dispatch
104
- program.parseAsync(process.argv).catch((err) => {
105
- console.error(err instanceof Error ? err.message : String(err));
106
- process.exit(1);
2
+ import { fatal } from './lib/errors.js';
3
+ import { createProgram } from './program.js';
4
+ createProgram()
5
+ .parseAsync(process.argv)
6
+ .catch((err) => {
7
+ fatal(err);
107
8
  });
108
9
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAErC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,4CAA4C;AAC5C,IAAI,OAAO,GAAG,OAAO,CAAC;AACtB,IAAI,CAAC;IACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IACrF,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;AACnC,CAAC;AAAC,MAAM,CAAC;IACP,gCAAgC;AAClC,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,2EAA2E,CAAC;KACxF,OAAO,CAAC,OAAO,EAAE,eAAe,EAAE,eAAe,CAAC;KAClD,MAAM,CAAC,QAAQ,EAAE,sDAAsD,CAAC;KACxE,MAAM,CAAC,UAAU,EAAE,sCAAsC,CAAC;KAC1D,MAAM,CAAC,OAAO,EAAE,uCAAuC,CAAC;KACxD,WAAW,CACV,OAAO,EACP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4DH,CACE,CAAC;AAEJ,uBAAuB;AACvB,OAAO,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC;AACvC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAC1C,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAC1C,OAAO,CAAC,UAAU,CAAC,qBAAqB,EAAE,CAAC,CAAC;AAC5C,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAE1C,qBAAqB;AACrB,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACtD,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,aAAa,EAAE;KACZ,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC;KACxB,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACtB,KAAK,CAAC,GAAG,CAAC,CAAC;AACb,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,QAAA,MAAM,UAAU,QAAuC,CAAC;AACxD,QAAA,MAAM,gBAAgB,QAAuC,CAAC;AAS9D,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,4DAA4D;AAC5D,QAAA,MAAM,WAAW,wBAAyB,CAAC;AAC3C,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,SAAS,CAE9D;AAID;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAErD;AAED;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAqBzE;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9E;AAED;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMvD;AAID;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC,CAQxD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrE;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAM7E;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAe9E;AAED,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAG3D,QAAA,MAAM,UAAU,QAAuC,CAAC;AACxD,QAAA,MAAM,gBAAgB,QAAuC,CAAC;AAS9D,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,4DAA4D;AAC5D,QAAA,MAAM,WAAW,wBAAyB,CAAC;AAC3C,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,SAAS,CAE9D;AAID;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAErD;AAED;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAqBzE;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9E;AAED;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMvD;AAID;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC,CAaxD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrE;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAM7E;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAe9E;AAED,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC"}
@@ -2,6 +2,7 @@ import { homedir } from 'os';
2
2
  import { join } from 'path';
3
3
  import { mkdir, readFile, writeFile, unlink, access } from 'fs/promises';
4
4
  import { constants } from 'fs';
5
+ import { ConfigError } from './errors.js';
5
6
  const CONFIG_DIR = join(homedir(), '.config', 'purvey');
6
7
  const CREDENTIALS_FILE = join(CONFIG_DIR, 'credentials.json');
7
8
  const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
@@ -74,12 +75,17 @@ export async function deleteCredentials() {
74
75
  export async function readConfig() {
75
76
  try {
76
77
  await access(CONFIG_FILE, constants.R_OK);
77
- const raw = await readFile(CONFIG_FILE, 'utf-8');
78
- return JSON.parse(raw);
79
78
  }
80
79
  catch {
81
80
  return {};
82
81
  }
82
+ try {
83
+ const raw = await readFile(CONFIG_FILE, 'utf-8');
84
+ return JSON.parse(raw);
85
+ }
86
+ catch (error) {
87
+ throw new ConfigError(`Config file is invalid or unreadable: ${CONFIG_FILE}.`, error);
88
+ }
83
89
  }
84
90
  /**
85
91
  * Write the purvey app config to ~/.config/purvey/config.json.
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}