@purveyors/cli 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.
Files changed (59) hide show
  1. package/LICENSE.md +53 -0
  2. package/README.md +175 -0
  3. package/dist/commands/auth.d.ts +6 -0
  4. package/dist/commands/auth.d.ts.map +1 -0
  5. package/dist/commands/auth.js +193 -0
  6. package/dist/commands/auth.js.map +1 -0
  7. package/dist/commands/catalog.d.ts +63 -0
  8. package/dist/commands/catalog.d.ts.map +1 -0
  9. package/dist/commands/catalog.js +132 -0
  10. package/dist/commands/catalog.js.map +1 -0
  11. package/dist/commands/inventory.d.ts +32 -0
  12. package/dist/commands/inventory.d.ts.map +1 -0
  13. package/dist/commands/inventory.js +287 -0
  14. package/dist/commands/inventory.js.map +1 -0
  15. package/dist/commands/roast.d.ts +48 -0
  16. package/dist/commands/roast.d.ts.map +1 -0
  17. package/dist/commands/roast.js +225 -0
  18. package/dist/commands/roast.js.map +1 -0
  19. package/dist/commands/sales.d.ts +17 -0
  20. package/dist/commands/sales.d.ts.map +1 -0
  21. package/dist/commands/sales.js +226 -0
  22. package/dist/commands/sales.js.map +1 -0
  23. package/dist/commands/tasting.d.ts +46 -0
  24. package/dist/commands/tasting.d.ts.map +1 -0
  25. package/dist/commands/tasting.js +174 -0
  26. package/dist/commands/tasting.js.map +1 -0
  27. package/dist/index.d.ts +3 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +68 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/lib/config.d.ts +21 -0
  32. package/dist/lib/config.d.ts.map +1 -0
  33. package/dist/lib/config.js +45 -0
  34. package/dist/lib/config.js.map +1 -0
  35. package/dist/lib/errors.d.ts +20 -0
  36. package/dist/lib/errors.d.ts.map +1 -0
  37. package/dist/lib/errors.js +58 -0
  38. package/dist/lib/errors.js.map +1 -0
  39. package/dist/lib/output.d.ts +22 -0
  40. package/dist/lib/output.d.ts.map +1 -0
  41. package/dist/lib/output.js +86 -0
  42. package/dist/lib/output.js.map +1 -0
  43. package/dist/lib/prompts.d.ts +11 -0
  44. package/dist/lib/prompts.d.ts.map +1 -0
  45. package/dist/lib/prompts.js +22 -0
  46. package/dist/lib/prompts.js.map +1 -0
  47. package/dist/lib/supabase.d.ts +22 -0
  48. package/dist/lib/supabase.d.ts.map +1 -0
  49. package/dist/lib/supabase.js +87 -0
  50. package/dist/lib/supabase.js.map +1 -0
  51. package/dist/types/database.types.d.ts +13 -0
  52. package/dist/types/database.types.d.ts.map +1 -0
  53. package/dist/types/database.types.js +8 -0
  54. package/dist/types/database.types.js.map +1 -0
  55. package/dist/types/index.d.ts +28 -0
  56. package/dist/types/index.d.ts.map +1 -0
  57. package/dist/types/index.js +5 -0
  58. package/dist/types/index.js.map +1 -0
  59. package/package.json +58 -0
@@ -0,0 +1,32 @@
1
+ import { Command } from 'commander';
2
+ export interface InventoryItem {
3
+ id: number;
4
+ rank: number | null;
5
+ notes: string | null;
6
+ cupping_notes: string | null;
7
+ purchase_date: string | null;
8
+ purchased_qty_lbs: number | null;
9
+ bean_cost: number | null;
10
+ tax_ship_cost: number | null;
11
+ last_updated: string;
12
+ user: string;
13
+ catalog_id: number | null;
14
+ stocked: boolean | null;
15
+ coffee_catalog: {
16
+ id: number;
17
+ name: string | null;
18
+ source: string | null;
19
+ country: string | null;
20
+ region: string | null;
21
+ processing: string | null;
22
+ cost_lb: number | null;
23
+ description_short: string | null;
24
+ stocked: boolean | null;
25
+ } | null;
26
+ }
27
+ /**
28
+ * `prvrs inventory` — Manage your green coffee inventory.
29
+ * Requires authentication.
30
+ */
31
+ export declare function buildInventoryCommand(): Command;
32
+ //# sourceMappingURL=inventory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../../src/commands/inventory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE;QACd,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;QACjC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;KACzB,GAAG,IAAI,CAAC;CACV;AAsBD;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAkV/C"}
@@ -0,0 +1,287 @@
1
+ import { Command } from 'commander';
2
+ import { createAuthenticatedClient } from '../lib/supabase.js';
3
+ import { outputData, info, success } from '../lib/output.js';
4
+ import { withErrorHandling, AuthError, PrvrsError } from '../lib/errors.js';
5
+ import { confirm, todayIso } from '../lib/prompts.js';
6
+ // ─── Shared select columns ────────────────────────────────────────────────────
7
+ const LIST_SELECT = [
8
+ 'id',
9
+ 'rank',
10
+ 'notes',
11
+ 'cupping_notes',
12
+ 'purchase_date',
13
+ 'purchased_qty_lbs',
14
+ 'bean_cost',
15
+ 'tax_ship_cost',
16
+ 'last_updated',
17
+ 'user',
18
+ 'catalog_id',
19
+ 'stocked',
20
+ 'coffee_catalog!catalog_id (id, name, source, country, region, processing, cost_lb, description_short, stocked)',
21
+ ].join(', ');
22
+ // ─── Command builder ──────────────────────────────────────────────────────────
23
+ /**
24
+ * `prvrs inventory` — Manage your green coffee inventory.
25
+ * Requires authentication.
26
+ */
27
+ export function buildInventoryCommand() {
28
+ const inventory = new Command('inventory').description('Manage your green coffee inventory');
29
+ // ── inventory list ────────────────────────────────────────────────────────
30
+ inventory
31
+ .command('list')
32
+ .description('List your green coffee inventory with catalog details')
33
+ .option('--stocked', 'Only show currently stocked beans')
34
+ .option('--limit <n>', 'Maximum results to return', '20')
35
+ .action(withErrorHandling(async (opts, cmd) => {
36
+ const globalOpts = cmd.optsWithGlobals();
37
+ const supabase = await createAuthenticatedClient();
38
+ const { data: { user }, } = await supabase.auth.getUser();
39
+ if (!user) {
40
+ throw new AuthError('Not logged in. Run `prvrs auth login` first.');
41
+ }
42
+ let query = supabase.from('green_coffee_inv').select(LIST_SELECT).eq('user', user.id);
43
+ if (opts.stocked) {
44
+ query = query.eq('stocked', true);
45
+ }
46
+ const limit = Math.max(1, parseInt(opts.limit, 10));
47
+ const { data, error } = await query
48
+ .order('last_updated', { ascending: false })
49
+ .limit(limit);
50
+ if (error)
51
+ throw error;
52
+ if (!data || data.length === 0) {
53
+ info('No inventory items found.');
54
+ return;
55
+ }
56
+ outputData(data, globalOpts);
57
+ }));
58
+ // ── inventory get <id> ────────────────────────────────────────────────────
59
+ inventory
60
+ .command('get <id>')
61
+ .description('Fetch a single inventory item by ID (must be yours)')
62
+ .action(withErrorHandling(async (id, _opts, cmd) => {
63
+ const globalOpts = cmd.optsWithGlobals();
64
+ const supabase = await createAuthenticatedClient();
65
+ const { data: { user }, } = await supabase.auth.getUser();
66
+ if (!user) {
67
+ throw new AuthError('Not logged in. Run `prvrs auth login` first.');
68
+ }
69
+ const selectColumns = [
70
+ 'id',
71
+ 'rank',
72
+ 'notes',
73
+ 'cupping_notes',
74
+ 'purchase_date',
75
+ 'purchased_qty_lbs',
76
+ 'bean_cost',
77
+ 'tax_ship_cost',
78
+ 'last_updated',
79
+ 'user',
80
+ 'catalog_id',
81
+ 'stocked',
82
+ 'coffee_catalog!catalog_id (id, name, source, country, region, processing, cost_lb, description_short, description_long, farm_notes, cupping_notes, stocked)',
83
+ ].join(', ');
84
+ const { data, error } = await supabase
85
+ .from('green_coffee_inv')
86
+ .select(selectColumns)
87
+ .eq('id', parseInt(id, 10))
88
+ .eq('user', user.id)
89
+ .single();
90
+ if (error) {
91
+ if (error.code === 'PGRST116') {
92
+ throw new AuthError(`Inventory item ${id} not found or does not belong to you.`);
93
+ }
94
+ throw error;
95
+ }
96
+ outputData(data, globalOpts);
97
+ }));
98
+ // ── inventory add ─────────────────────────────────────────────────────────
99
+ inventory
100
+ .command('add')
101
+ .description('Add a new green coffee inventory item')
102
+ .requiredOption('--catalog-id <id>', 'Coffee catalog entry ID')
103
+ .requiredOption('--qty <lbs>', 'Quantity purchased in pounds')
104
+ .option('--cost <dollars>', 'Bean cost in dollars')
105
+ .option('--tax-ship <dollars>', 'Tax and shipping cost in dollars')
106
+ .option('--notes <text>', 'Notes for this inventory item')
107
+ .option('--purchase-date <YYYY-MM-DD>', 'Purchase date (defaults to today)')
108
+ .action(withErrorHandling(async (opts, cmd) => {
109
+ const globalOpts = cmd.optsWithGlobals();
110
+ const supabase = await createAuthenticatedClient();
111
+ const { data: { user }, } = await supabase.auth.getUser();
112
+ if (!user) {
113
+ throw new AuthError('Not logged in. Run `prvrs auth login` first.');
114
+ }
115
+ const catalogId = parseInt(opts.catalogId, 10);
116
+ if (isNaN(catalogId)) {
117
+ throw new PrvrsError('INVALID_ARGUMENT', `Invalid --catalog-id: "${opts.catalogId}".`);
118
+ }
119
+ const qty = parseFloat(opts.qty);
120
+ if (isNaN(qty) || qty <= 0) {
121
+ throw new PrvrsError('INVALID_ARGUMENT', `Invalid --qty: "${opts.qty}". Must be a positive number.`);
122
+ }
123
+ const insertPayload = {
124
+ user: user.id,
125
+ catalog_id: catalogId,
126
+ purchased_qty_lbs: qty,
127
+ purchase_date: opts.purchaseDate ?? todayIso(),
128
+ };
129
+ if (opts.cost !== undefined) {
130
+ const cost = parseFloat(opts.cost);
131
+ if (isNaN(cost))
132
+ throw new PrvrsError('INVALID_ARGUMENT', `Invalid --cost: "${opts.cost}".`);
133
+ insertPayload.bean_cost = cost;
134
+ }
135
+ if (opts.taxShip !== undefined) {
136
+ const taxShip = parseFloat(opts.taxShip);
137
+ if (isNaN(taxShip))
138
+ throw new PrvrsError('INVALID_ARGUMENT', `Invalid --tax-ship: "${opts.taxShip}".`);
139
+ insertPayload.tax_ship_cost = taxShip;
140
+ }
141
+ if (opts.notes !== undefined) {
142
+ insertPayload.notes = opts.notes;
143
+ }
144
+ const { data: inserted, error: insertError } = await supabase
145
+ .from('green_coffee_inv')
146
+ .insert(insertPayload)
147
+ .select('id')
148
+ .single();
149
+ if (insertError)
150
+ throw insertError;
151
+ // Re-fetch the full row with catalog join
152
+ const { data, error } = await supabase
153
+ .from('green_coffee_inv')
154
+ .select(LIST_SELECT)
155
+ .eq('id', inserted.id)
156
+ .single();
157
+ if (error)
158
+ throw error;
159
+ success(`Inventory item ${inserted.id} created.`);
160
+ outputData(data, globalOpts);
161
+ }));
162
+ // ── inventory update <id> ─────────────────────────────────────────────────
163
+ inventory
164
+ .command('update <id>')
165
+ .description('Update an existing inventory item (must be yours)')
166
+ .option('--qty <lbs>', 'Updated quantity in pounds')
167
+ .option('--cost <dollars>', 'Updated bean cost')
168
+ .option('--tax-ship <dollars>', 'Updated tax/shipping cost')
169
+ .option('--notes <text>', 'Updated notes')
170
+ .option('--stocked <bool>', 'Mark as stocked (true/false)')
171
+ .action(withErrorHandling(async (id, opts, cmd) => {
172
+ const globalOpts = cmd.optsWithGlobals();
173
+ const supabase = await createAuthenticatedClient();
174
+ const { data: { user }, } = await supabase.auth.getUser();
175
+ if (!user) {
176
+ throw new AuthError('Not logged in. Run `prvrs auth login` first.');
177
+ }
178
+ const itemId = parseInt(id, 10);
179
+ if (isNaN(itemId)) {
180
+ throw new PrvrsError('INVALID_ARGUMENT', `Invalid inventory ID: "${id}".`);
181
+ }
182
+ // Verify ownership
183
+ const { data: existing, error: fetchError } = await supabase
184
+ .from('green_coffee_inv')
185
+ .select('id')
186
+ .eq('id', itemId)
187
+ .eq('user', user.id)
188
+ .single();
189
+ if (fetchError || !existing) {
190
+ throw new AuthError(`Inventory item ${id} not found or does not belong to you.`);
191
+ }
192
+ // Build partial update — only include fields that were explicitly passed
193
+ const updates = {};
194
+ if (opts.qty !== undefined) {
195
+ const qty = parseFloat(opts.qty);
196
+ if (isNaN(qty) || qty <= 0)
197
+ throw new PrvrsError('INVALID_ARGUMENT', `Invalid --qty: "${opts.qty}".`);
198
+ updates.purchased_qty_lbs = qty;
199
+ }
200
+ if (opts.cost !== undefined) {
201
+ const cost = parseFloat(opts.cost);
202
+ if (isNaN(cost))
203
+ throw new PrvrsError('INVALID_ARGUMENT', `Invalid --cost: "${opts.cost}".`);
204
+ updates.bean_cost = cost;
205
+ }
206
+ if (opts.taxShip !== undefined) {
207
+ const taxShip = parseFloat(opts.taxShip);
208
+ if (isNaN(taxShip))
209
+ throw new PrvrsError('INVALID_ARGUMENT', `Invalid --tax-ship: "${opts.taxShip}".`);
210
+ updates.tax_ship_cost = taxShip;
211
+ }
212
+ if (opts.notes !== undefined) {
213
+ updates.notes = opts.notes;
214
+ }
215
+ if (opts.stocked !== undefined) {
216
+ const stockedStr = opts.stocked.toLowerCase();
217
+ if (stockedStr !== 'true' && stockedStr !== 'false') {
218
+ throw new PrvrsError('INVALID_ARGUMENT', `--stocked must be "true" or "false".`);
219
+ }
220
+ updates.stocked = stockedStr === 'true';
221
+ }
222
+ if (Object.keys(updates).length === 0) {
223
+ throw new PrvrsError('INVALID_ARGUMENT', 'No update fields provided. Pass at least one of: --qty, --cost, --tax-ship, --notes, --stocked.');
224
+ }
225
+ const { error: updateError } = await supabase
226
+ .from('green_coffee_inv')
227
+ .update(updates)
228
+ .eq('id', itemId)
229
+ .eq('user', user.id);
230
+ if (updateError)
231
+ throw updateError;
232
+ // Re-fetch the updated row
233
+ const { data, error } = await supabase
234
+ .from('green_coffee_inv')
235
+ .select(LIST_SELECT)
236
+ .eq('id', itemId)
237
+ .single();
238
+ if (error)
239
+ throw error;
240
+ success(`Inventory item ${itemId} updated.`);
241
+ outputData(data, globalOpts);
242
+ }));
243
+ // ── inventory delete <id> ─────────────────────────────────────────────────
244
+ inventory
245
+ .command('delete <id>')
246
+ .description('Delete an inventory item (must be yours)')
247
+ .option('-y, --yes', 'Skip confirmation prompt')
248
+ .action(withErrorHandling(async (id, opts, cmd) => {
249
+ void cmd; // global opts not needed for delete
250
+ const supabase = await createAuthenticatedClient();
251
+ const { data: { user }, } = await supabase.auth.getUser();
252
+ if (!user) {
253
+ throw new AuthError('Not logged in. Run `prvrs auth login` first.');
254
+ }
255
+ const itemId = parseInt(id, 10);
256
+ if (isNaN(itemId)) {
257
+ throw new PrvrsError('INVALID_ARGUMENT', `Invalid inventory ID: "${id}".`);
258
+ }
259
+ // Verify ownership
260
+ const { data: existing, error: fetchError } = await supabase
261
+ .from('green_coffee_inv')
262
+ .select('id, catalog_id')
263
+ .eq('id', itemId)
264
+ .eq('user', user.id)
265
+ .single();
266
+ if (fetchError || !existing) {
267
+ throw new AuthError(`Inventory item ${id} not found or does not belong to you.`);
268
+ }
269
+ if (!opts.yes) {
270
+ const ok = await confirm(`Delete inventory item ${itemId}?`);
271
+ if (!ok) {
272
+ info('Aborted.');
273
+ return;
274
+ }
275
+ }
276
+ const { error: deleteError } = await supabase
277
+ .from('green_coffee_inv')
278
+ .delete()
279
+ .eq('id', itemId)
280
+ .eq('user', user.id);
281
+ if (deleteError)
282
+ throw deleteError;
283
+ success(`Inventory item ${itemId} deleted.`);
284
+ }));
285
+ return inventory;
286
+ }
287
+ //# sourceMappingURL=inventory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory.js","sourceRoot":"","sources":["../../src/commands/inventory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import { Command } from 'commander';
2
+ export interface RoastProfile {
3
+ roast_id: number;
4
+ batch_name: string | null;
5
+ coffee_id: number | null;
6
+ coffee_name: string | null;
7
+ roast_date: string | null;
8
+ oz_in: number | null;
9
+ oz_out: number | null;
10
+ weight_loss_percent: number | null;
11
+ roast_notes: string | null;
12
+ user: string;
13
+ last_updated: string;
14
+ roaster_type: string | null;
15
+ roaster_size: string | null;
16
+ temperature_unit: string | null;
17
+ charge_time: number | null;
18
+ drop_time: number | null;
19
+ fc_start_time: number | null;
20
+ fc_end_time: number | null;
21
+ fc_start_temp: number | null;
22
+ drop_temp: number | null;
23
+ charge_temp: number | null;
24
+ dry_percent: number | null;
25
+ maillard_percent: number | null;
26
+ development_percent: number | null;
27
+ total_roast_time: number | null;
28
+ data_source: string | null;
29
+ roast_uuid: string | null;
30
+ }
31
+ export interface TemperatureEntry {
32
+ roast_id: number;
33
+ time_seconds: number;
34
+ bean_temp: number | null;
35
+ environmental_temp: number | null;
36
+ }
37
+ export interface RoastEventEntry {
38
+ roast_id: number;
39
+ time_seconds: number;
40
+ event_type: number | null;
41
+ event_value: string | null;
42
+ }
43
+ /**
44
+ * `prvrs roast` — Browse and manage your roast profiles.
45
+ * Requires authentication.
46
+ */
47
+ export declare function buildRoastCommand(): Command;
48
+ //# sourceMappingURL=roast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roast.d.ts","sourceRoot":"","sources":["../../src/commands/roast.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAID;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAwR3C"}
@@ -0,0 +1,225 @@
1
+ import { Command } from 'commander';
2
+ import { createAuthenticatedClient } from '../lib/supabase.js';
3
+ import { outputData, info, success } from '../lib/output.js';
4
+ import { withErrorHandling, AuthError, PrvrsError } from '../lib/errors.js';
5
+ import { confirm, todayIso } from '../lib/prompts.js';
6
+ // ─── Command builder ──────────────────────────────────────────────────────────
7
+ /**
8
+ * `prvrs roast` — Browse and manage your roast profiles.
9
+ * Requires authentication.
10
+ */
11
+ export function buildRoastCommand() {
12
+ const roast = new Command('roast').description('Browse and manage your roast profiles');
13
+ // ── roast list ────────────────────────────────────────────────────────────
14
+ roast
15
+ .command('list')
16
+ .description('List your roast profiles, sorted by date (newest first)')
17
+ .option('--coffee-id <id>', 'Filter by green_coffee_inv ID')
18
+ .option('--limit <n>', 'Maximum results to return', '20')
19
+ .action(withErrorHandling(async (opts, cmd) => {
20
+ const globalOpts = cmd.optsWithGlobals();
21
+ const supabase = await createAuthenticatedClient();
22
+ const { data: { user }, } = await supabase.auth.getUser();
23
+ if (!user) {
24
+ throw new AuthError('Not logged in. Run `prvrs auth login` first.');
25
+ }
26
+ let query = supabase
27
+ .from('roast_profiles')
28
+ .select('roast_id, batch_name, coffee_id, coffee_name, roast_date, oz_in, oz_out, weight_loss_percent, roast_notes, roaster_type, roaster_size, temperature_unit, total_roast_time, development_percent, data_source, last_updated')
29
+ .eq('user', user.id);
30
+ if (opts.coffeeId !== undefined) {
31
+ query = query.eq('coffee_id', parseInt(opts.coffeeId, 10));
32
+ }
33
+ const limit = Math.max(1, parseInt(opts.limit, 10));
34
+ const { data, error } = await query.order('roast_date', { ascending: false }).limit(limit);
35
+ if (error)
36
+ throw error;
37
+ if (!data || data.length === 0) {
38
+ info('No roast profiles found.');
39
+ return;
40
+ }
41
+ outputData(data, globalOpts);
42
+ }));
43
+ // ── roast get <id> ────────────────────────────────────────────────────────
44
+ roast
45
+ .command('get <id>')
46
+ .description('Fetch a single roast profile by roast_id')
47
+ .option('--include-temps', 'Include temperature curve data (roast_temperatures)')
48
+ .option('--include-events', 'Include roast events (roast_events)')
49
+ .action(withErrorHandling(async (id, opts, cmd) => {
50
+ const globalOpts = cmd.optsWithGlobals();
51
+ const supabase = await createAuthenticatedClient();
52
+ const { data: { user }, } = await supabase.auth.getUser();
53
+ if (!user) {
54
+ throw new AuthError('Not logged in. Run `prvrs auth login` first.');
55
+ }
56
+ const roastId = parseInt(id, 10);
57
+ // Fetch the profile, verifying ownership
58
+ const { data: profile, error: profileError } = await supabase
59
+ .from('roast_profiles')
60
+ .select('*')
61
+ .eq('roast_id', roastId)
62
+ .eq('user', user.id)
63
+ .single();
64
+ if (profileError) {
65
+ if (profileError.code === 'PGRST116') {
66
+ throw new AuthError(`Roast profile ${id} not found or does not belong to you.`);
67
+ }
68
+ throw profileError;
69
+ }
70
+ const result = { ...profile };
71
+ // Optionally fetch temperature curve
72
+ if (opts.includeTemps) {
73
+ const { data: temps, error: tempError } = await supabase
74
+ .from('roast_temperatures')
75
+ .select('roast_id, time_seconds, bean_temp, environmental_temp')
76
+ .eq('roast_id', roastId)
77
+ .order('time_seconds', { ascending: true });
78
+ if (tempError)
79
+ throw tempError;
80
+ result.temperatures = temps ?? [];
81
+ }
82
+ // Optionally fetch roast events
83
+ if (opts.includeEvents) {
84
+ const { data: events, error: eventsError } = await supabase
85
+ .from('roast_events')
86
+ .select('roast_id, time_seconds, event_type, event_value')
87
+ .eq('roast_id', roastId)
88
+ .order('time_seconds', { ascending: true });
89
+ if (eventsError)
90
+ throw eventsError;
91
+ result.events = events ?? [];
92
+ }
93
+ outputData(result, globalOpts);
94
+ }));
95
+ // ── roast create ──────────────────────────────────────────────────────────
96
+ roast
97
+ .command('create')
98
+ .description('Create a new roast profile')
99
+ .requiredOption('--coffee-id <id>', 'green_coffee_inv ID for this roast')
100
+ .option('--batch-name <name>', "Batch name (defaults to coffee name + today's date)")
101
+ .option('--oz-in <oz>', 'Green weight in ounces')
102
+ .option('--oz-out <oz>', 'Roasted weight in ounces')
103
+ .option('--roast-date <YYYY-MM-DD>', 'Roast date (defaults to today)')
104
+ .option('--notes <text>', 'Roast notes')
105
+ .action(withErrorHandling(async (opts, cmd) => {
106
+ const globalOpts = cmd.optsWithGlobals();
107
+ const supabase = await createAuthenticatedClient();
108
+ const { data: { user }, } = await supabase.auth.getUser();
109
+ if (!user) {
110
+ throw new AuthError('Not logged in. Run `prvrs auth login` first.');
111
+ }
112
+ const coffeeId = parseInt(opts.coffeeId, 10);
113
+ if (isNaN(coffeeId)) {
114
+ throw new PrvrsError('INVALID_ARGUMENT', `Invalid --coffee-id: "${opts.coffeeId}".`);
115
+ }
116
+ // Verify ownership of the inventory item and get coffee name for default batch name
117
+ const { data: invItem, error: invError } = await supabase
118
+ .from('green_coffee_inv')
119
+ .select('id, coffee_catalog!catalog_id (name)')
120
+ .eq('id', coffeeId)
121
+ .eq('user', user.id)
122
+ .single();
123
+ if (invError || !invItem) {
124
+ throw new AuthError(`Inventory item ${coffeeId} not found or does not belong to you.`);
125
+ }
126
+ const roastDate = opts.roastDate ?? todayIso();
127
+ // Default batch name: coffee name + roast date
128
+ let batchName = opts.batchName;
129
+ if (!batchName) {
130
+ const catalogRaw = invItem.coffee_catalog;
131
+ const catalog = Array.isArray(catalogRaw) ? (catalogRaw[0] ?? null) : catalogRaw;
132
+ const coffeeName = catalog?.name ?? `Coffee #${coffeeId}`;
133
+ batchName = `${coffeeName} — ${roastDate}`;
134
+ }
135
+ const insertPayload = {
136
+ user: user.id,
137
+ coffee_id: coffeeId,
138
+ batch_name: batchName,
139
+ roast_date: roastDate,
140
+ };
141
+ if (opts.ozIn !== undefined) {
142
+ const ozIn = parseFloat(opts.ozIn);
143
+ if (isNaN(ozIn) || ozIn <= 0)
144
+ throw new PrvrsError('INVALID_ARGUMENT', `Invalid --oz-in: "${opts.ozIn}".`);
145
+ insertPayload.oz_in = ozIn;
146
+ }
147
+ if (opts.ozOut !== undefined) {
148
+ const ozOut = parseFloat(opts.ozOut);
149
+ if (isNaN(ozOut) || ozOut <= 0)
150
+ throw new PrvrsError('INVALID_ARGUMENT', `Invalid --oz-out: "${opts.ozOut}".`);
151
+ insertPayload.oz_out = ozOut;
152
+ }
153
+ if (opts.notes !== undefined) {
154
+ insertPayload.roast_notes = opts.notes;
155
+ }
156
+ const { data: inserted, error: insertError } = await supabase
157
+ .from('roast_profiles')
158
+ .insert(insertPayload)
159
+ .select('roast_id')
160
+ .single();
161
+ if (insertError)
162
+ throw insertError;
163
+ // Re-fetch the full row
164
+ const { data, error } = await supabase
165
+ .from('roast_profiles')
166
+ .select('roast_id, batch_name, coffee_id, coffee_name, roast_date, oz_in, oz_out, weight_loss_percent, roast_notes, roaster_type, total_roast_time, data_source, last_updated')
167
+ .eq('roast_id', inserted.roast_id)
168
+ .single();
169
+ if (error)
170
+ throw error;
171
+ success(`Roast profile ${inserted.roast_id} created.`);
172
+ outputData(data, globalOpts);
173
+ }));
174
+ // ── roast delete <id> ─────────────────────────────────────────────────────
175
+ roast
176
+ .command('delete <id>')
177
+ .description('Delete a roast profile (must be yours)')
178
+ .option('-y, --yes', 'Skip confirmation prompt')
179
+ .action(withErrorHandling(async (id, opts, cmd) => {
180
+ void cmd; // global opts not needed for delete
181
+ const supabase = await createAuthenticatedClient();
182
+ const { data: { user }, } = await supabase.auth.getUser();
183
+ if (!user) {
184
+ throw new AuthError('Not logged in. Run `prvrs auth login` first.');
185
+ }
186
+ const roastId = parseInt(id, 10);
187
+ if (isNaN(roastId)) {
188
+ throw new PrvrsError('INVALID_ARGUMENT', `Invalid roast ID: "${id}".`);
189
+ }
190
+ // Verify ownership
191
+ const { data: existing, error: fetchError } = await supabase
192
+ .from('roast_profiles')
193
+ .select('roast_id, batch_name')
194
+ .eq('roast_id', roastId)
195
+ .eq('user', user.id)
196
+ .single();
197
+ if (fetchError || !existing) {
198
+ throw new AuthError(`Roast profile ${id} not found or does not belong to you.`);
199
+ }
200
+ if (!opts.yes) {
201
+ const label = existing.batch_name ? `"${existing.batch_name}"` : `#${roastId}`;
202
+ const ok = await confirm(`Delete roast profile ${label}?`);
203
+ if (!ok) {
204
+ info('Aborted.');
205
+ return;
206
+ }
207
+ }
208
+ const { error: deleteError } = await supabase
209
+ .from('roast_profiles')
210
+ .delete()
211
+ .eq('roast_id', roastId)
212
+ .eq('user', user.id);
213
+ if (deleteError)
214
+ throw deleteError;
215
+ success(`Roast profile ${roastId} deleted.`);
216
+ }));
217
+ // ── roast import-artisan <id> <file.alog> ─────────────────────────────────
218
+ // TODO (Phase 3): Wire up artisan import.
219
+ // The .alog parser runs server-side on the SvelteKit API. This command needs
220
+ // to POST the file content to the app's /api/artisan-import endpoint, which
221
+ // requires the SvelteKit server URL to be configurable (not just Supabase URL).
222
+ // Tracked for Phase 3 implementation.
223
+ return roast;
224
+ }
225
+ //# sourceMappingURL=roast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roast.js","sourceRoot":"","sources":["../../src/commands/roast.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { Command } from 'commander';
2
+ export interface Sale {
3
+ id: number;
4
+ roast_id: number | null;
5
+ oz_sold: number | null;
6
+ sale_price: number | null;
7
+ buyer: string | null;
8
+ sell_date: string | null;
9
+ user: string;
10
+ last_updated: string;
11
+ }
12
+ /**
13
+ * `prvrs sales` — Record and manage coffee sales.
14
+ * Requires authentication.
15
+ */
16
+ export declare function buildSalesCommand(): Command;
17
+ //# sourceMappingURL=sales.d.ts.map