@purveyors/cli 0.24.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -19
- package/dist/commands/catalog.d.ts.map +1 -1
- package/dist/commands/catalog.js +11 -47
- package/dist/commands/catalog.js.map +1 -1
- package/dist/commands/inventory.d.ts.map +1 -1
- package/dist/commands/inventory.js +17 -44
- package/dist/commands/inventory.js.map +1 -1
- package/dist/commands/market.d.ts +8 -0
- package/dist/commands/market.d.ts.map +1 -0
- package/dist/commands/market.js +190 -0
- package/dist/commands/market.js.map +1 -0
- package/dist/commands/roast.d.ts +3 -0
- package/dist/commands/roast.d.ts.map +1 -1
- package/dist/commands/roast.js +15 -11
- package/dist/commands/roast.js.map +1 -1
- package/dist/commands/sales.d.ts.map +1 -1
- package/dist/commands/sales.js +15 -11
- package/dist/commands/sales.js.map +1 -1
- package/dist/commands/tasting.d.ts.map +1 -1
- package/dist/commands/tasting.js +1 -2
- package/dist/commands/tasting.js.map +1 -1
- package/dist/lib/auth-guard.d.ts.map +1 -1
- package/dist/lib/auth-guard.js +14 -6
- package/dist/lib/auth-guard.js.map +1 -1
- package/dist/lib/catalog.d.ts +12 -14
- package/dist/lib/catalog.d.ts.map +1 -1
- package/dist/lib/catalog.js +177 -520
- package/dist/lib/catalog.js.map +1 -1
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +1 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/interactive/forms.d.ts +1 -1
- package/dist/lib/interactive/forms.d.ts.map +1 -1
- package/dist/lib/interactive/forms.js +3 -10
- package/dist/lib/interactive/forms.js.map +1 -1
- package/dist/lib/inventory.d.ts +8 -16
- package/dist/lib/inventory.d.ts.map +1 -1
- package/dist/lib/inventory.js +44 -227
- package/dist/lib/inventory.js.map +1 -1
- package/dist/lib/manifest.d.ts.map +1 -1
- package/dist/lib/manifest.js +91 -16
- package/dist/lib/manifest.js.map +1 -1
- package/dist/lib/market.d.ts +239 -0
- package/dist/lib/market.d.ts.map +1 -0
- package/dist/lib/market.js +29 -0
- package/dist/lib/market.js.map +1 -0
- package/dist/lib/parchment-base.d.ts +3 -0
- package/dist/lib/parchment-base.d.ts.map +1 -0
- package/dist/lib/parchment-base.js +9 -0
- package/dist/lib/parchment-base.js.map +1 -0
- package/dist/lib/parchment.d.ts +10 -1
- package/dist/lib/parchment.d.ts.map +1 -1
- package/dist/lib/parchment.js +18 -7
- package/dist/lib/parchment.js.map +1 -1
- package/dist/lib/roast.d.ts +16 -24
- package/dist/lib/roast.d.ts.map +1 -1
- package/dist/lib/roast.js +33 -224
- package/dist/lib/roast.js.map +1 -1
- package/dist/lib/sales.d.ts +12 -6
- package/dist/lib/sales.d.ts.map +1 -1
- package/dist/lib/sales.js +13 -27
- package/dist/lib/sales.js.map +1 -1
- package/dist/lib/supabase.d.ts.map +1 -1
- package/dist/lib/supabase.js +14 -9
- package/dist/lib/supabase.js.map +1 -1
- package/dist/lib/tasting.d.ts +1 -1
- package/dist/lib/tasting.d.ts.map +1 -1
- package/dist/lib/tasting.js +5 -53
- package/dist/lib/tasting.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +6 -1
- package/dist/program.js.map +1 -1
- package/package.json +3 -2
package/dist/lib/inventory.js
CHANGED
|
@@ -1,37 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
export const INVENTORY_LIST_SELECT = [
|
|
6
|
-
'id',
|
|
7
|
-
'rank',
|
|
8
|
-
'notes',
|
|
9
|
-
'cupping_notes',
|
|
10
|
-
'purchase_date',
|
|
11
|
-
'purchased_qty_lbs',
|
|
12
|
-
'bean_cost',
|
|
13
|
-
'tax_ship_cost',
|
|
14
|
-
'last_updated',
|
|
15
|
-
'user',
|
|
16
|
-
'catalog_id',
|
|
17
|
-
'stocked',
|
|
18
|
-
'coffee_catalog!catalog_id (id, name, source, country, region, processing, cost_lb, price_per_lb, price_tiers, description_short, stocked)',
|
|
19
|
-
].join(', ');
|
|
20
|
-
export const INVENTORY_DETAIL_SELECT = [
|
|
21
|
-
'id',
|
|
22
|
-
'rank',
|
|
23
|
-
'notes',
|
|
24
|
-
'cupping_notes',
|
|
25
|
-
'purchase_date',
|
|
26
|
-
'purchased_qty_lbs',
|
|
27
|
-
'bean_cost',
|
|
28
|
-
'tax_ship_cost',
|
|
29
|
-
'last_updated',
|
|
30
|
-
'user',
|
|
31
|
-
'catalog_id',
|
|
32
|
-
'stocked',
|
|
33
|
-
'coffee_catalog!catalog_id (id, name, source, country, region, processing, cost_lb, price_per_lb, price_tiers, description_short, description_long, farm_notes, cupping_notes, stocked)',
|
|
34
|
-
].join(', ');
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { PrvrsError } from './errors.js';
|
|
4
|
+
import { createParchmentClient, unwrapParchment } from './parchment.js';
|
|
35
5
|
// ─── Zod schemas ──────────────────────────────────────────────────────────────
|
|
36
6
|
export const listInventorySchema = z.object({
|
|
37
7
|
stocked_only: z.boolean().optional().describe('Only show currently stocked beans'),
|
|
@@ -71,227 +41,74 @@ export const deleteInventorySchema = z.object({
|
|
|
71
41
|
/**
|
|
72
42
|
* List green coffee inventory for a user.
|
|
73
43
|
*/
|
|
74
|
-
export async function listInventory(
|
|
44
|
+
export async function listInventory(opts) {
|
|
75
45
|
const parsed = listInventorySchema.parse(opts);
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
query = query.lte('purchase_date', parsed.purchaseDateEnd);
|
|
88
|
-
}
|
|
89
|
-
// origin filter: look up matching catalog IDs first, then restrict inventory
|
|
90
|
-
if (parsed.origin) {
|
|
91
|
-
const safe = sanitizeFilterValue(parsed.origin);
|
|
92
|
-
const { data: catalogRows, error: catError } = await supabase
|
|
93
|
-
.from('coffee_catalog')
|
|
94
|
-
.select('id')
|
|
95
|
-
.ilike('country', `%${safe}%`);
|
|
96
|
-
if (catError)
|
|
97
|
-
throw catError;
|
|
98
|
-
const catalogIds = (catalogRows ?? []).map((r) => r.id);
|
|
99
|
-
if (catalogIds.length === 0) {
|
|
100
|
-
return [];
|
|
101
|
-
}
|
|
102
|
-
query = query.in('catalog_id', catalogIds);
|
|
103
|
-
}
|
|
104
|
-
const offset = parsed.offset ?? 0;
|
|
105
|
-
const { data, error } = await query
|
|
106
|
-
.order('last_updated', { ascending: false })
|
|
107
|
-
.range(offset, offset + parsed.limit - 1);
|
|
108
|
-
if (error)
|
|
109
|
-
throw error;
|
|
110
|
-
return (data ?? []);
|
|
46
|
+
const client = await createParchmentClient('member');
|
|
47
|
+
const envelope = unwrapParchment(await client.inventory.list({
|
|
48
|
+
stocked_only: parsed.stocked_only,
|
|
49
|
+
catalogId: parsed.catalogId,
|
|
50
|
+
purchaseDateStart: parsed.purchaseDateStart,
|
|
51
|
+
purchaseDateEnd: parsed.purchaseDateEnd,
|
|
52
|
+
origin: parsed.origin,
|
|
53
|
+
limit: parsed.limit,
|
|
54
|
+
offset: parsed.offset,
|
|
55
|
+
}), 'Inventory list');
|
|
56
|
+
return envelope.data;
|
|
111
57
|
}
|
|
112
58
|
/**
|
|
113
59
|
* Fetch a single inventory item by ID (must belong to userId).
|
|
114
60
|
*/
|
|
115
|
-
export async function getInventory(
|
|
61
|
+
export async function getInventory(id) {
|
|
116
62
|
getInventorySchema.parse({ id });
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
.
|
|
121
|
-
.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
throw error;
|
|
63
|
+
const client = await createParchmentClient('member');
|
|
64
|
+
const pageSize = 100;
|
|
65
|
+
for (let offset = 0;; offset += pageSize) {
|
|
66
|
+
const envelope = unwrapParchment(await client.inventory.list({ limit: pageSize, offset }), 'Inventory get');
|
|
67
|
+
const item = envelope.data.find((row) => row.id === id);
|
|
68
|
+
if (item)
|
|
69
|
+
return item;
|
|
70
|
+
if (envelope.data.length < pageSize)
|
|
71
|
+
break;
|
|
128
72
|
}
|
|
129
|
-
|
|
73
|
+
throw new PrvrsError('NOT_FOUND', `Inventory item ${id} not found or does not belong to you.`);
|
|
130
74
|
}
|
|
131
75
|
/**
|
|
132
76
|
* Add a new inventory item for a user.
|
|
133
77
|
*/
|
|
134
|
-
export async function addInventory(
|
|
78
|
+
export async function addInventory(input, tokenOverride) {
|
|
135
79
|
const parsed = addInventorySchema.parse(input);
|
|
136
|
-
const
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
catalog_id: parsed.catalogId,
|
|
140
|
-
purchased_qty_lbs: parsed.qty,
|
|
141
|
-
purchase_date: parsed.purchaseDate ?? todayIso(),
|
|
142
|
-
};
|
|
143
|
-
if (parsed.cost !== undefined)
|
|
144
|
-
insertPayload.bean_cost = parsed.cost;
|
|
145
|
-
if (parsed.taxShip !== undefined)
|
|
146
|
-
insertPayload.tax_ship_cost = parsed.taxShip;
|
|
147
|
-
if (parsed.notes !== undefined)
|
|
148
|
-
insertPayload.notes = parsed.notes;
|
|
149
|
-
const { data: inserted, error: insertError } = await supabase
|
|
150
|
-
.from('green_coffee_inv')
|
|
151
|
-
.insert(insertPayload)
|
|
152
|
-
.select('id')
|
|
153
|
-
.single();
|
|
154
|
-
if (insertError)
|
|
155
|
-
throw insertError;
|
|
156
|
-
// Re-fetch with catalog join
|
|
157
|
-
const { data, error } = await supabase
|
|
158
|
-
.from('green_coffee_inv')
|
|
159
|
-
.select(INVENTORY_LIST_SELECT)
|
|
160
|
-
.eq('id', inserted.id)
|
|
161
|
-
.single();
|
|
162
|
-
if (error)
|
|
163
|
-
throw error;
|
|
164
|
-
return data;
|
|
80
|
+
const client = await createParchmentClient('member', tokenOverride);
|
|
81
|
+
const envelope = unwrapParchment(await client.inventory.create(parsed, { idempotencyKey: randomUUID() }), 'Inventory create');
|
|
82
|
+
return envelope.data;
|
|
165
83
|
}
|
|
166
84
|
/**
|
|
167
85
|
* Update an existing inventory item (must belong to userId).
|
|
168
86
|
*/
|
|
169
|
-
export async function updateInventory(
|
|
87
|
+
export async function updateInventory(id, input) {
|
|
170
88
|
getInventorySchema.parse({ id });
|
|
171
89
|
const parsed = updateInventorySchema.parse(input);
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
.select('id')
|
|
176
|
-
.eq('id', id)
|
|
177
|
-
.eq('user', userId)
|
|
178
|
-
.single();
|
|
179
|
-
if (fetchError || !existing) {
|
|
180
|
-
throw new AuthError(`Inventory item ${id} not found or does not belong to you.`);
|
|
181
|
-
}
|
|
182
|
-
const updates = {};
|
|
183
|
-
if (parsed.qty !== undefined)
|
|
184
|
-
updates.purchased_qty_lbs = parsed.qty;
|
|
185
|
-
if (parsed.cost !== undefined)
|
|
186
|
-
updates.bean_cost = parsed.cost;
|
|
187
|
-
if (parsed.taxShip !== undefined)
|
|
188
|
-
updates.tax_ship_cost = parsed.taxShip;
|
|
189
|
-
if (parsed.notes !== undefined)
|
|
190
|
-
updates.notes = parsed.notes;
|
|
191
|
-
if (parsed.stocked !== undefined)
|
|
192
|
-
updates.stocked = parsed.stocked;
|
|
193
|
-
if (Object.keys(updates).length === 0) {
|
|
194
|
-
throw new PrvrsError('INVALID_ARGUMENT', 'No update fields provided. Pass at least one of: qty, cost, taxShip, notes, stocked.');
|
|
195
|
-
}
|
|
196
|
-
const { error: updateError } = await supabase
|
|
197
|
-
.from('green_coffee_inv')
|
|
198
|
-
.update(updates)
|
|
199
|
-
.eq('id', id)
|
|
200
|
-
.eq('user', userId);
|
|
201
|
-
if (updateError)
|
|
202
|
-
throw updateError;
|
|
203
|
-
// Re-fetch the updated row
|
|
204
|
-
const { data, error } = await supabase
|
|
205
|
-
.from('green_coffee_inv')
|
|
206
|
-
.select(INVENTORY_LIST_SELECT)
|
|
207
|
-
.eq('id', id)
|
|
208
|
-
.single();
|
|
209
|
-
if (error)
|
|
210
|
-
throw error;
|
|
211
|
-
return data;
|
|
90
|
+
const client = await createParchmentClient('member');
|
|
91
|
+
const envelope = unwrapParchment(await client.inventory.update(id, parsed), 'Inventory update');
|
|
92
|
+
return envelope.data;
|
|
212
93
|
}
|
|
213
94
|
/**
|
|
214
95
|
* Delete an inventory item (must belong to userId).
|
|
215
96
|
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
* When `opts.force` is true, all dependent sales and roast profiles are
|
|
221
|
-
* deleted first (user-scoped), then the inventory item is removed.
|
|
222
|
-
*
|
|
223
|
-
* Returns counts of what was removed so the caller can surface a summary.
|
|
97
|
+
* The canonical API refuses deletion when dependent roast or sales rows exist.
|
|
98
|
+
* Client-side force cascading is intentionally unsupported because it would
|
|
99
|
+
* bypass the API's per-resource authorization, idempotency, and audit controls.
|
|
224
100
|
*/
|
|
225
|
-
export async function deleteInventory(
|
|
101
|
+
export async function deleteInventory(id, opts) {
|
|
226
102
|
deleteInventorySchema.parse({ id });
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
.from('green_coffee_inv')
|
|
230
|
-
.select('id')
|
|
231
|
-
.eq('id', id)
|
|
232
|
-
.eq('user', userId)
|
|
233
|
-
.single();
|
|
234
|
-
if (fetchError || !existing) {
|
|
235
|
-
throw new AuthError(`Inventory item ${id} not found or does not belong to you.`);
|
|
236
|
-
}
|
|
237
|
-
// Pre-flight dependency check
|
|
238
|
-
const { count: roastCount, error: roastCountErr } = await supabase
|
|
239
|
-
.from('roast_profiles')
|
|
240
|
-
.select('roast_id', { count: 'exact', head: true })
|
|
241
|
-
.eq('coffee_id', id)
|
|
242
|
-
.eq('user', userId);
|
|
243
|
-
if (roastCountErr)
|
|
244
|
-
throw roastCountErr;
|
|
245
|
-
const { count: salesCount, error: salesCountErr } = await supabase
|
|
246
|
-
.from('sales')
|
|
247
|
-
.select('id', { count: 'exact', head: true })
|
|
248
|
-
.eq('green_coffee_inv_id', id)
|
|
249
|
-
.eq('user', userId);
|
|
250
|
-
if (salesCountErr)
|
|
251
|
-
throw salesCountErr;
|
|
252
|
-
const dependentRoasts = roastCount ?? 0;
|
|
253
|
-
const dependentSales = salesCount ?? 0;
|
|
254
|
-
if (dependentRoasts > 0 || dependentSales > 0) {
|
|
255
|
-
if (!opts?.force) {
|
|
256
|
-
const parts = [];
|
|
257
|
-
if (dependentRoasts > 0)
|
|
258
|
-
parts.push(`${dependentRoasts} roast profile${dependentRoasts === 1 ? '' : 's'}`);
|
|
259
|
-
if (dependentSales > 0)
|
|
260
|
-
parts.push(`${dependentSales} sale record${dependentSales === 1 ? '' : 's'}`);
|
|
261
|
-
throw new PrvrsError('DEPENDENCY_CONFLICT', `Cannot delete inventory item ${id} — it has ${parts.join(' and ')}. ` +
|
|
262
|
-
`Delete them first, or use --force to cascade delete all dependent records.`);
|
|
263
|
-
}
|
|
264
|
-
// Force path: delete dependents first (sales, then roast profiles), then inventory
|
|
265
|
-
if (dependentSales > 0) {
|
|
266
|
-
const { error: delSalesErr } = await supabase
|
|
267
|
-
.from('sales')
|
|
268
|
-
.delete()
|
|
269
|
-
.eq('green_coffee_inv_id', id)
|
|
270
|
-
.eq('user', userId);
|
|
271
|
-
if (delSalesErr)
|
|
272
|
-
throw delSalesErr;
|
|
273
|
-
}
|
|
274
|
-
if (dependentRoasts > 0) {
|
|
275
|
-
const { error: delRoastsErr } = await supabase
|
|
276
|
-
.from('roast_profiles')
|
|
277
|
-
.delete()
|
|
278
|
-
.eq('coffee_id', id)
|
|
279
|
-
.eq('user', userId);
|
|
280
|
-
if (delRoastsErr)
|
|
281
|
-
throw delRoastsErr;
|
|
282
|
-
}
|
|
103
|
+
if (opts?.force) {
|
|
104
|
+
throw new PrvrsError('INVALID_ARGUMENT', '--force is no longer supported. Delete dependent roast profiles and sales explicitly before deleting the inventory item.');
|
|
283
105
|
}
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
.delete()
|
|
287
|
-
.eq('id', id)
|
|
288
|
-
.eq('user', userId);
|
|
289
|
-
if (deleteError)
|
|
290
|
-
throw deleteError;
|
|
106
|
+
const client = await createParchmentClient('member');
|
|
107
|
+
unwrapParchment(await client.inventory.delete(id), 'Inventory delete');
|
|
291
108
|
return {
|
|
292
109
|
deletedInventoryId: id,
|
|
293
|
-
deletedRoasts:
|
|
294
|
-
deletedSales:
|
|
110
|
+
deletedRoasts: 0,
|
|
111
|
+
deletedSales: 0,
|
|
295
112
|
};
|
|
296
113
|
}
|
|
297
114
|
//# sourceMappingURL=inventory.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inventory.js","sourceRoot":"","sources":["../../src/lib/inventory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"inventory.js","sourceRoot":"","sources":["../../src/lib/inventory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAgCxE,iFAAiF;AAEjF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,YAAY,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;IAClF,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,2BAA2B,CAAC;IAChF,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;IACtF,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;IAClF,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;IAC9F,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;IAC7F,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;CACtF,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACtC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACpC,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC;KACnC,MAAM,CAAC;IACN,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACrC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC;KACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAmB,CAAC,KAAK,SAAS,CAAC,EAAE;IAC/E,OAAO,EAAE,sFAAsF;CAChG,CAAC,CAAC;AAIL,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC,CAAC;AAcH,iFAAiF;AAEjF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAwB;IAC1D,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,eAAe,CAC9B,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;QAC3C,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC,EACF,gBAAgB,CACjB,CAAC;IACF,OAAO,QAAQ,CAAC,IAAuB,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,EAAU;IAC3C,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,GAAG,CAAC;IACrB,KAAK,IAAI,MAAM,GAAG,CAAC,GAAI,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,eAAe,CAC9B,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EACxD,eAAe,CAChB,CAAC;QACF,MAAM,IAAI,GAAI,QAAQ,CAAC,IAAwB,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7E,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;QACtB,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,QAAQ;YAAE,MAAM;IAC7C,CAAC;IACD,MAAM,IAAI,UAAU,CAAC,WAAW,EAAE,kBAAkB,EAAE,uCAAuC,CAAC,CAAC;AACjG,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAwB,EACxB,aAAsB;IAEtB,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACpE,MAAM,QAAQ,GAAG,eAAe,CAC9B,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,UAAU,EAAE,EAAE,CAAC,EACvE,kBAAkB,CACnB,CAAC;IACF,OAAO,QAAQ,CAAC,IAAqB,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,EAAU,EACV,KAA2B;IAE3B,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,kBAAkB,CAAC,CAAC;IAChG,OAAO,QAAQ,CAAC,IAAqB,CAAC;AACxC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,EAAU,EACV,IAA6B;IAE7B,qBAAqB,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACpC,IAAI,IAAI,EAAE,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,UAAU,CAClB,kBAAkB,EAClB,0HAA0H,CAC3H,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACrD,eAAe,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,kBAAkB,CAAC,CAAC;IACvE,OAAO;QACL,kBAAkB,EAAE,EAAE;QACtB,aAAa,EAAE,CAAC;QAChB,YAAY,EAAE,CAAC;KAChB,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/lib/manifest.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/lib/manifest.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/manifest.js
CHANGED
|
@@ -54,7 +54,7 @@ const exitCodes = [
|
|
|
54
54
|
{
|
|
55
55
|
exitCode: EXIT_CODES.DEPENDENCY_CONFLICT,
|
|
56
56
|
code: 'DEPENDENCY_CONFLICT',
|
|
57
|
-
description: 'dependency conflict, for example
|
|
57
|
+
description: 'dependency conflict, for example deleting an inventory lot with dependents',
|
|
58
58
|
},
|
|
59
59
|
{ exitCode: EXIT_CODES.CONFIG_ERROR, code: 'CONFIG_ERROR', description: 'local config error' },
|
|
60
60
|
];
|
|
@@ -83,7 +83,7 @@ const idTypes = [
|
|
|
83
83
|
{
|
|
84
84
|
name: 'roast_id',
|
|
85
85
|
source: 'roast_data row',
|
|
86
|
-
usedBy: ['roast get/delete', 'roast list --roast-id', 'sales --roast-id'],
|
|
86
|
+
usedBy: ['roast get/delete', 'roast list --roast-id', 'sales record --roast-id'],
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
89
|
name: 'sale_id',
|
|
@@ -233,13 +233,12 @@ const commandGroups = [
|
|
|
233
233
|
flags: '--all',
|
|
234
234
|
description: 'Use all visible catalog rows instead of the default stocked-only scope.',
|
|
235
235
|
},
|
|
236
|
-
{ flags: '--sample-size <n>', defaultValue: 5000 },
|
|
237
236
|
{ flags: '--limit <n>', defaultValue: 60 },
|
|
238
237
|
],
|
|
239
238
|
notes: [
|
|
240
239
|
'Counts values from catalog rows visible to the current client.',
|
|
241
240
|
'Defaults to currently stocked catalog rows; use --all for all visible rows.',
|
|
242
|
-
'Output metadata reports stocked_only/scope, rows_examined,
|
|
241
|
+
'Output metadata reports stocked_only/scope, rows_examined, and truncation for deterministic agent use.',
|
|
243
242
|
],
|
|
244
243
|
examples: [
|
|
245
244
|
'purvey catalog facets supplier --pretty',
|
|
@@ -500,15 +499,7 @@ const commandGroups = [
|
|
|
500
499
|
idType: 'inventory_id',
|
|
501
500
|
},
|
|
502
501
|
],
|
|
503
|
-
options: [
|
|
504
|
-
{ flags: '--yes' },
|
|
505
|
-
{
|
|
506
|
-
flags: '--force',
|
|
507
|
-
notes: [
|
|
508
|
-
'Cascade delete dependent roast profiles and sales records before deleting the item.',
|
|
509
|
-
],
|
|
510
|
-
},
|
|
511
|
-
],
|
|
502
|
+
options: [{ flags: '--yes' }],
|
|
512
503
|
},
|
|
513
504
|
],
|
|
514
505
|
},
|
|
@@ -653,7 +644,7 @@ const commandGroups = [
|
|
|
653
644
|
summary: 'List your sales, sorted by sell date',
|
|
654
645
|
auth: 'member',
|
|
655
646
|
options: [
|
|
656
|
-
{ flags: '--
|
|
647
|
+
{ flags: '--coffee-id <id>' },
|
|
657
648
|
{ flags: '--date-start <YYYY-MM-DD>' },
|
|
658
649
|
{ flags: '--date-end <YYYY-MM-DD>' },
|
|
659
650
|
{ flags: '--buyer <name>' },
|
|
@@ -661,6 +652,7 @@ const commandGroups = [
|
|
|
661
652
|
{ flags: '--offset <n>', defaultValue: 0 },
|
|
662
653
|
],
|
|
663
654
|
notes: [
|
|
655
|
+
'--coffee-id filters by green_coffee_inv.id through the canonical sales API.',
|
|
664
656
|
'--date-start and --date-end accept YYYY-MM-DD and compose into a range.',
|
|
665
657
|
'--offset + --limit enables pagination through large result sets.',
|
|
666
658
|
],
|
|
@@ -859,6 +851,83 @@ const commandGroups = [
|
|
|
859
851
|
examples: ['purvey manifest', 'purvey manifest --pretty'],
|
|
860
852
|
},
|
|
861
853
|
},
|
|
854
|
+
{
|
|
855
|
+
name: 'market',
|
|
856
|
+
summary: 'Market Index decision surface: value signals, movement stats, and metadata trends via the canonical API',
|
|
857
|
+
auth: 'mixed',
|
|
858
|
+
subcommands: [
|
|
859
|
+
{
|
|
860
|
+
name: 'signals',
|
|
861
|
+
summary: 'Actionable market value signals; unfiltered summary is a public teaser',
|
|
862
|
+
auth: 'none',
|
|
863
|
+
options: [
|
|
864
|
+
{ flags: '--summary' },
|
|
865
|
+
{
|
|
866
|
+
flags: '--type <type>',
|
|
867
|
+
notes: ['repeatable or comma-separated: price_drop|below_market|value_quality'],
|
|
868
|
+
},
|
|
869
|
+
{ flags: '--origin <origin>' },
|
|
870
|
+
{ flags: '--process <method>' },
|
|
871
|
+
{ flags: '--market <retail|wholesale|all>' },
|
|
872
|
+
{ flags: '--min-discount <n>' },
|
|
873
|
+
{ flags: '--min-score <n>' },
|
|
874
|
+
{ flags: '--window <7d|30d>' },
|
|
875
|
+
{ flags: '--limit <n>' },
|
|
876
|
+
],
|
|
877
|
+
notes: [
|
|
878
|
+
'Backed by the canonical API GET /v1/market/signals via @purveyors/sdk against api.purveyors.io.',
|
|
879
|
+
'--summary is the only unauthenticated slice (counts only); any filter requires Parchment Intelligence access, enforced server-side (403 on denial).',
|
|
880
|
+
'--json emits the API response verbatim (§3.3 evidence object, §3.4 enums); no client-side reshaping.',
|
|
881
|
+
],
|
|
882
|
+
examples: [
|
|
883
|
+
'purvey market signals --summary --pretty',
|
|
884
|
+
'purvey market signals --type price_drop --type below_market --origin "Ethiopia" --json',
|
|
885
|
+
],
|
|
886
|
+
},
|
|
887
|
+
{
|
|
888
|
+
name: 'stats',
|
|
889
|
+
summary: 'Price movement-significance stats; unfiltered retail slice is public',
|
|
890
|
+
auth: 'none',
|
|
891
|
+
options: [
|
|
892
|
+
{ flags: '--origin <origin>' },
|
|
893
|
+
{ flags: '--process <method>' },
|
|
894
|
+
{ flags: '--market <retail|wholesale|all>' },
|
|
895
|
+
{ flags: '--window <7d|30d>' },
|
|
896
|
+
{ flags: '--baseline-weeks <n>' },
|
|
897
|
+
],
|
|
898
|
+
notes: [
|
|
899
|
+
'Backed by the canonical API GET /v1/price-index/stats via @purveyors/sdk.',
|
|
900
|
+
'The no-origin/no-process retail slice is public; origin/process/wholesale filters require Intelligence access.',
|
|
901
|
+
],
|
|
902
|
+
examples: [
|
|
903
|
+
'purvey market stats --pretty',
|
|
904
|
+
'purvey market stats --origin "Colombia" --window 30d --json',
|
|
905
|
+
],
|
|
906
|
+
},
|
|
907
|
+
{
|
|
908
|
+
name: 'metadata',
|
|
909
|
+
summary: 'Metadata-trend index; process/retail/month slice is public',
|
|
910
|
+
auth: 'none',
|
|
911
|
+
options: [
|
|
912
|
+
{ flags: '--dimension <process|disclosure|score>' },
|
|
913
|
+
{ flags: '--origin <origin>' },
|
|
914
|
+
{ flags: '--market <retail|wholesale|all>' },
|
|
915
|
+
{ flags: '--grain <week|month>' },
|
|
916
|
+
{ flags: '--from <date>' },
|
|
917
|
+
{ flags: '--to <date>' },
|
|
918
|
+
],
|
|
919
|
+
notes: [
|
|
920
|
+
'Backed by the canonical API GET /v1/market/metadata-index via @purveyors/sdk.',
|
|
921
|
+
'Public slice: dimension=process, no origin, market=retail, grain=month; anything else requires Intelligence access.',
|
|
922
|
+
'cultivar and drying dimensions are out of scope for v1 (await taxonomy normalization).',
|
|
923
|
+
],
|
|
924
|
+
examples: [
|
|
925
|
+
'purvey market metadata --pretty',
|
|
926
|
+
'purvey market metadata --dimension score --origin "Ethiopia" --grain month --json',
|
|
927
|
+
],
|
|
928
|
+
},
|
|
929
|
+
],
|
|
930
|
+
},
|
|
862
931
|
{
|
|
863
932
|
name: 'price-index',
|
|
864
933
|
summary: 'Parchment Price Index aggregate snapshots; requires price-index (PPI) access',
|
|
@@ -1017,7 +1086,7 @@ const errorPatterns = [
|
|
|
1017
1086
|
{
|
|
1018
1087
|
title: 'Dependency conflict on delete',
|
|
1019
1088
|
exitCodes: [EXIT_CODES.DEPENDENCY_CONFLICT],
|
|
1020
|
-
guidance: ['
|
|
1089
|
+
guidance: ['Delete dependent roast profiles and sales records explicitly, then retry.'],
|
|
1021
1090
|
},
|
|
1022
1091
|
{
|
|
1023
1092
|
title: 'Mutually exclusive watch flags',
|
|
@@ -1106,12 +1175,18 @@ function renderRoles(roleContracts, groups) {
|
|
|
1106
1175
|
.filter((group) => group.auth === 'none' && group.name !== 'auth')
|
|
1107
1176
|
.map((group) => group.name)
|
|
1108
1177
|
.sort();
|
|
1178
|
+
const mixedAccessCommands = groups
|
|
1179
|
+
.filter((group) => group.auth === 'mixed')
|
|
1180
|
+
.map((group) => group.name)
|
|
1181
|
+
.sort();
|
|
1109
1182
|
return [
|
|
1110
1183
|
'ROLES',
|
|
1111
1184
|
'-----',
|
|
1112
1185
|
`No pre-existing session required for: ${unauthenticatedCommands.join(', ')}.`,
|
|
1113
1186
|
`Local-only commands: ${localOnlyCommands.join(', ')}.`,
|
|
1114
|
-
|
|
1187
|
+
`Mixed public and entitled access: ${mixedAccessCommands.join(', ')}.`,
|
|
1188
|
+
'Mixed-access public teaser slices can run without a session; filtered or non-public slices require server-side entitlements.',
|
|
1189
|
+
'Commands that talk to purveyors.io generally require authentication unless listed above as public, local-only, or mixed-access teaser slices.',
|
|
1115
1190
|
...roleContracts.map((role) => `${role.role.padEnd(7, ' ')} ${role.description}`),
|
|
1116
1191
|
'',
|
|
1117
1192
|
'Both roles are granted on sign-in through purveyors.io.',
|