@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.
- package/LICENSE.md +53 -0
- package/README.md +175 -0
- package/dist/commands/auth.d.ts +6 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +193 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/catalog.d.ts +63 -0
- package/dist/commands/catalog.d.ts.map +1 -0
- package/dist/commands/catalog.js +132 -0
- package/dist/commands/catalog.js.map +1 -0
- package/dist/commands/inventory.d.ts +32 -0
- package/dist/commands/inventory.d.ts.map +1 -0
- package/dist/commands/inventory.js +287 -0
- package/dist/commands/inventory.js.map +1 -0
- package/dist/commands/roast.d.ts +48 -0
- package/dist/commands/roast.d.ts.map +1 -0
- package/dist/commands/roast.js +225 -0
- package/dist/commands/roast.js.map +1 -0
- package/dist/commands/sales.d.ts +17 -0
- package/dist/commands/sales.d.ts.map +1 -0
- package/dist/commands/sales.js +226 -0
- package/dist/commands/sales.js.map +1 -0
- package/dist/commands/tasting.d.ts +46 -0
- package/dist/commands/tasting.d.ts.map +1 -0
- package/dist/commands/tasting.js +174 -0
- package/dist/commands/tasting.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +21 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +45 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/errors.d.ts +20 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +58 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/output.d.ts +22 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +86 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/lib/prompts.d.ts +11 -0
- package/dist/lib/prompts.d.ts.map +1 -0
- package/dist/lib/prompts.js +22 -0
- package/dist/lib/prompts.js.map +1 -0
- package/dist/lib/supabase.d.ts +22 -0
- package/dist/lib/supabase.d.ts.map +1 -0
- package/dist/lib/supabase.js +87 -0
- package/dist/lib/supabase.js.map +1 -0
- package/dist/types/database.types.d.ts +13 -0
- package/dist/types/database.types.d.ts.map +1 -0
- package/dist/types/database.types.js +8 -0
- package/dist/types/database.types.js.map +1 -0
- package/dist/types/index.d.ts +28 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- 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
|