@purveyors/cli 0.2.1 → 0.3.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/dist/commands/catalog.d.ts +4 -56
- package/dist/commands/catalog.d.ts.map +1 -1
- package/dist/commands/catalog.js +14 -81
- package/dist/commands/catalog.js.map +1 -1
- package/dist/commands/inventory.d.ts +2 -25
- package/dist/commands/inventory.d.ts.map +1 -1
- package/dist/commands/inventory.js +47 -147
- package/dist/commands/inventory.js.map +1 -1
- package/dist/commands/roast.d.ts +2 -41
- package/dist/commands/roast.d.ts.map +1 -1
- package/dist/commands/roast.js +138 -125
- package/dist/commands/roast.js.map +1 -1
- package/dist/commands/sales.d.ts +2 -10
- package/dist/commands/sales.d.ts.map +1 -1
- package/dist/commands/sales.js +30 -109
- package/dist/commands/sales.js.map +1 -1
- package/dist/commands/tasting.d.ts +4 -38
- package/dist/commands/tasting.d.ts.map +1 -1
- package/dist/commands/tasting.js +18 -108
- package/dist/commands/tasting.js.map +1 -1
- package/dist/lib/artisan/db.d.ts +37 -0
- package/dist/lib/artisan/db.d.ts.map +1 -0
- package/dist/lib/artisan/db.js +51 -0
- package/dist/lib/artisan/db.js.map +1 -0
- package/dist/lib/artisan/import.d.ts +16 -0
- package/dist/lib/artisan/import.d.ts.map +1 -0
- package/dist/lib/artisan/import.js +447 -0
- package/dist/lib/artisan/import.js.map +1 -0
- package/dist/lib/artisan/index.d.ts +9 -0
- package/dist/lib/artisan/index.d.ts.map +1 -0
- package/dist/lib/artisan/index.js +7 -0
- package/dist/lib/artisan/index.js.map +1 -0
- package/dist/lib/artisan/parser.d.ts +19 -0
- package/dist/lib/artisan/parser.d.ts.map +1 -0
- package/dist/lib/artisan/parser.js +376 -0
- package/dist/lib/artisan/parser.js.map +1 -0
- package/dist/lib/artisan/temperature.d.ts +52 -0
- package/dist/lib/artisan/temperature.d.ts.map +1 -0
- package/dist/lib/artisan/temperature.js +101 -0
- package/dist/lib/artisan/temperature.js.map +1 -0
- package/dist/lib/artisan/types.d.ts +195 -0
- package/dist/lib/artisan/types.d.ts.map +1 -0
- package/dist/lib/artisan/types.js +35 -0
- package/dist/lib/artisan/types.js.map +1 -0
- package/dist/lib/artisan/validator.d.ts +14 -0
- package/dist/lib/artisan/validator.d.ts.map +1 -0
- package/dist/lib/artisan/validator.js +228 -0
- package/dist/lib/artisan/validator.js.map +1 -0
- package/dist/lib/catalog.d.ts +87 -0
- package/dist/lib/catalog.d.ts.map +1 -0
- package/dist/lib/catalog.js +111 -0
- package/dist/lib/catalog.js.map +1 -0
- package/dist/lib/index.d.ts +6 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +11 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/inventory.d.ts +80 -0
- package/dist/lib/inventory.d.ts.map +1 -0
- package/dist/lib/inventory.js +205 -0
- package/dist/lib/inventory.js.map +1 -0
- package/dist/lib/roast.d.ts +127 -0
- package/dist/lib/roast.d.ts.map +1 -0
- package/dist/lib/roast.js +284 -0
- package/dist/lib/roast.js.map +1 -0
- package/dist/lib/sales.d.ts +53 -0
- package/dist/lib/sales.d.ts.map +1 -0
- package/dist/lib/sales.js +155 -0
- package/dist/lib/sales.js.map +1 -0
- package/dist/lib/tasting.d.ts +76 -0
- package/dist/lib/tasting.d.ts.map +1 -0
- package/dist/lib/tasting.js +136 -0
- package/dist/lib/tasting.js.map +1 -0
- package/package.json +13 -2
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
// ─── Zod schemas ──────────────────────────────────────────────────────────────
|
|
3
|
+
export const searchCatalogSchema = z.object({
|
|
4
|
+
origin: z.string().optional(),
|
|
5
|
+
process: z.string().optional(),
|
|
6
|
+
priceMin: z.number().optional(),
|
|
7
|
+
priceMax: z.number().optional(),
|
|
8
|
+
flavor: z.string().optional(),
|
|
9
|
+
stocked: z.boolean().optional(),
|
|
10
|
+
limit: z.number().int().min(1).default(10),
|
|
11
|
+
});
|
|
12
|
+
export const getCatalogSchema = z.object({
|
|
13
|
+
id: z.number().int().positive(),
|
|
14
|
+
});
|
|
15
|
+
export const getCatalogStatsSchema = z.object({});
|
|
16
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
17
|
+
/**
|
|
18
|
+
* Strip PostgREST special characters from user-supplied filter values.
|
|
19
|
+
* Prevents injection into .or() filter strings where values are interpolated directly.
|
|
20
|
+
* Removes: ( ) , . * % that have meaning in PostgREST filter syntax.
|
|
21
|
+
*/
|
|
22
|
+
export function sanitizeFilterValue(value) {
|
|
23
|
+
return value.replace(/[(),.*%]/g, '');
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Aggregate stats from an array of catalog items.
|
|
27
|
+
* Pure function — no I/O, safe to unit test.
|
|
28
|
+
*/
|
|
29
|
+
export function computeCatalogStats(items) {
|
|
30
|
+
const stocked = items.filter((i) => i.stocked === true).length;
|
|
31
|
+
const byOrigin = {};
|
|
32
|
+
for (const item of items) {
|
|
33
|
+
const key = item.country ?? item.continent ?? 'Unknown';
|
|
34
|
+
byOrigin[key] = (byOrigin[key] ?? 0) + 1;
|
|
35
|
+
}
|
|
36
|
+
const prices = items.map((i) => i.cost_lb).filter((p) => p !== null);
|
|
37
|
+
const avgPricePerLb = prices.length > 0
|
|
38
|
+
? Math.round((prices.reduce((a, b) => a + b, 0) / prices.length) * 100) / 100
|
|
39
|
+
: null;
|
|
40
|
+
const priceRange = {
|
|
41
|
+
min: prices.length > 0 ? Math.min(...prices) : null,
|
|
42
|
+
max: prices.length > 0 ? Math.max(...prices) : null,
|
|
43
|
+
};
|
|
44
|
+
return { total: items.length, stocked, byOrigin, avgPricePerLb, priceRange };
|
|
45
|
+
}
|
|
46
|
+
// ─── Pure lib functions ───────────────────────────────────────────────────────
|
|
47
|
+
/**
|
|
48
|
+
* Search the coffee catalog with optional filters.
|
|
49
|
+
*/
|
|
50
|
+
export async function searchCatalog(supabase, opts) {
|
|
51
|
+
const parsed = searchCatalogSchema.parse(opts);
|
|
52
|
+
let query = supabase.from('coffee_catalog').select('*');
|
|
53
|
+
if (parsed.origin) {
|
|
54
|
+
const o = sanitizeFilterValue(parsed.origin);
|
|
55
|
+
query = query.or(`country.ilike.%${o}%,continent.ilike.%${o}%,region.ilike.%${o}%`);
|
|
56
|
+
}
|
|
57
|
+
if (parsed.process) {
|
|
58
|
+
const p = sanitizeFilterValue(parsed.process);
|
|
59
|
+
query = query.ilike('processing', `%${p}%`);
|
|
60
|
+
}
|
|
61
|
+
if (parsed.priceMin !== undefined) {
|
|
62
|
+
query = query.gte('cost_lb', parsed.priceMin);
|
|
63
|
+
}
|
|
64
|
+
if (parsed.priceMax !== undefined) {
|
|
65
|
+
query = query.lte('cost_lb', parsed.priceMax);
|
|
66
|
+
}
|
|
67
|
+
if (parsed.flavor) {
|
|
68
|
+
const keywords = parsed.flavor
|
|
69
|
+
.split(',')
|
|
70
|
+
.map((k) => sanitizeFilterValue(k.trim()))
|
|
71
|
+
.filter(Boolean);
|
|
72
|
+
const flavorFilters = keywords
|
|
73
|
+
.flatMap((kw) => [
|
|
74
|
+
`description_short.ilike.%${kw}%`,
|
|
75
|
+
`description_long.ilike.%${kw}%`,
|
|
76
|
+
`cupping_notes.ilike.%${kw}%`,
|
|
77
|
+
`farm_notes.ilike.%${kw}%`,
|
|
78
|
+
])
|
|
79
|
+
.join(',');
|
|
80
|
+
query = query.or(flavorFilters);
|
|
81
|
+
}
|
|
82
|
+
if (parsed.stocked) {
|
|
83
|
+
query = query.eq('stocked', true);
|
|
84
|
+
}
|
|
85
|
+
const { data, error } = await query.limit(parsed.limit);
|
|
86
|
+
if (error)
|
|
87
|
+
throw error;
|
|
88
|
+
return (data ?? []);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Fetch a single catalog item by ID.
|
|
92
|
+
*/
|
|
93
|
+
export async function getCatalog(supabase, id) {
|
|
94
|
+
getCatalogSchema.parse({ id });
|
|
95
|
+
const { data, error } = await supabase.from('coffee_catalog').select('*').eq('id', id).single();
|
|
96
|
+
if (error)
|
|
97
|
+
throw error;
|
|
98
|
+
return data;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Fetch aggregate statistics for the coffee catalog.
|
|
102
|
+
*/
|
|
103
|
+
export async function getCatalogStats(supabase) {
|
|
104
|
+
const { data, error } = await supabase
|
|
105
|
+
.from('coffee_catalog')
|
|
106
|
+
.select('id, country, continent, cost_lb, stocked');
|
|
107
|
+
if (error)
|
|
108
|
+
throw error;
|
|
109
|
+
return computeCatalogStats((data ?? []));
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/lib/catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AAMA,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Barrel export — re-exports all lib modules for convenience.
|
|
2
|
+
// Usage: import { searchCatalog, listInventory } from '@purveyors/cli/lib'
|
|
3
|
+
// Or use individual subpath imports:
|
|
4
|
+
// import { searchCatalog } from '@purveyors/cli/catalog'
|
|
5
|
+
// import { listInventory } from '@purveyors/cli/inventory'
|
|
6
|
+
export * from './catalog.js';
|
|
7
|
+
export * from './inventory.js';
|
|
8
|
+
export * from './roast.js';
|
|
9
|
+
export * from './sales.js';
|
|
10
|
+
export * from './tasting.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,2EAA2E;AAC3E,qCAAqC;AACrC,2DAA2D;AAC3D,6DAA6D;AAE7D,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
3
|
+
export interface InventoryItem {
|
|
4
|
+
id: number;
|
|
5
|
+
rank: number | null;
|
|
6
|
+
notes: string | null;
|
|
7
|
+
cupping_notes: string | null;
|
|
8
|
+
purchase_date: string | null;
|
|
9
|
+
purchased_qty_lbs: number | null;
|
|
10
|
+
bean_cost: number | null;
|
|
11
|
+
tax_ship_cost: number | null;
|
|
12
|
+
last_updated: string;
|
|
13
|
+
user: string;
|
|
14
|
+
catalog_id: number | null;
|
|
15
|
+
stocked: boolean | null;
|
|
16
|
+
coffee_catalog: {
|
|
17
|
+
id: number;
|
|
18
|
+
name: string | null;
|
|
19
|
+
source: string | null;
|
|
20
|
+
country: string | null;
|
|
21
|
+
region: string | null;
|
|
22
|
+
processing: string | null;
|
|
23
|
+
cost_lb: number | null;
|
|
24
|
+
description_short: string | null;
|
|
25
|
+
stocked: boolean | null;
|
|
26
|
+
} | null;
|
|
27
|
+
}
|
|
28
|
+
export declare const INVENTORY_LIST_SELECT: string;
|
|
29
|
+
export declare const INVENTORY_DETAIL_SELECT: string;
|
|
30
|
+
export declare const listInventorySchema: z.ZodObject<{
|
|
31
|
+
stocked: z.ZodOptional<z.ZodBoolean>;
|
|
32
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
33
|
+
}, z.core.$strip>;
|
|
34
|
+
export type ListInventoryInput = z.input<typeof listInventorySchema>;
|
|
35
|
+
export declare const getInventorySchema: z.ZodObject<{
|
|
36
|
+
id: z.ZodNumber;
|
|
37
|
+
}, z.core.$strip>;
|
|
38
|
+
export type GetInventoryInput = z.input<typeof getInventorySchema>;
|
|
39
|
+
export declare const addInventorySchema: z.ZodObject<{
|
|
40
|
+
catalogId: z.ZodNumber;
|
|
41
|
+
qty: z.ZodNumber;
|
|
42
|
+
cost: z.ZodOptional<z.ZodNumber>;
|
|
43
|
+
taxShip: z.ZodOptional<z.ZodNumber>;
|
|
44
|
+
notes: z.ZodOptional<z.ZodString>;
|
|
45
|
+
purchaseDate: z.ZodOptional<z.ZodString>;
|
|
46
|
+
}, z.core.$strip>;
|
|
47
|
+
export type AddInventoryInput = z.input<typeof addInventorySchema>;
|
|
48
|
+
export declare const updateInventorySchema: z.ZodObject<{
|
|
49
|
+
qty: z.ZodOptional<z.ZodNumber>;
|
|
50
|
+
cost: z.ZodOptional<z.ZodNumber>;
|
|
51
|
+
taxShip: z.ZodOptional<z.ZodNumber>;
|
|
52
|
+
notes: z.ZodOptional<z.ZodString>;
|
|
53
|
+
stocked: z.ZodOptional<z.ZodBoolean>;
|
|
54
|
+
}, z.core.$strip>;
|
|
55
|
+
export type UpdateInventoryInput = z.input<typeof updateInventorySchema>;
|
|
56
|
+
export declare const deleteInventorySchema: z.ZodObject<{
|
|
57
|
+
id: z.ZodNumber;
|
|
58
|
+
}, z.core.$strip>;
|
|
59
|
+
export type DeleteInventoryInput = z.input<typeof deleteInventorySchema>;
|
|
60
|
+
/**
|
|
61
|
+
* List green coffee inventory for a user.
|
|
62
|
+
*/
|
|
63
|
+
export declare function listInventory(supabase: SupabaseClient, userId: string, opts: ListInventoryInput): Promise<InventoryItem[]>;
|
|
64
|
+
/**
|
|
65
|
+
* Fetch a single inventory item by ID (must belong to userId).
|
|
66
|
+
*/
|
|
67
|
+
export declare function getInventory(supabase: SupabaseClient, userId: string, id: number): Promise<InventoryItem>;
|
|
68
|
+
/**
|
|
69
|
+
* Add a new inventory item for a user.
|
|
70
|
+
*/
|
|
71
|
+
export declare function addInventory(supabase: SupabaseClient, userId: string, input: AddInventoryInput): Promise<InventoryItem>;
|
|
72
|
+
/**
|
|
73
|
+
* Update an existing inventory item (must belong to userId).
|
|
74
|
+
*/
|
|
75
|
+
export declare function updateInventory(supabase: SupabaseClient, userId: string, id: number, input: UpdateInventoryInput): Promise<InventoryItem>;
|
|
76
|
+
/**
|
|
77
|
+
* Delete an inventory item (must belong to userId).
|
|
78
|
+
*/
|
|
79
|
+
export declare function deleteInventory(supabase: SupabaseClient, userId: string, id: number): Promise<void>;
|
|
80
|
+
//# sourceMappingURL=inventory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../../src/lib/inventory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { AuthError, PrvrsError } from './errors.js';
|
|
3
|
+
// ─── Shared select columns ────────────────────────────────────────────────────
|
|
4
|
+
export const INVENTORY_LIST_SELECT = [
|
|
5
|
+
'id',
|
|
6
|
+
'rank',
|
|
7
|
+
'notes',
|
|
8
|
+
'cupping_notes',
|
|
9
|
+
'purchase_date',
|
|
10
|
+
'purchased_qty_lbs',
|
|
11
|
+
'bean_cost',
|
|
12
|
+
'tax_ship_cost',
|
|
13
|
+
'last_updated',
|
|
14
|
+
'user',
|
|
15
|
+
'catalog_id',
|
|
16
|
+
'stocked',
|
|
17
|
+
'coffee_catalog!catalog_id (id, name, source, country, region, processing, cost_lb, description_short, stocked)',
|
|
18
|
+
].join(', ');
|
|
19
|
+
export const INVENTORY_DETAIL_SELECT = [
|
|
20
|
+
'id',
|
|
21
|
+
'rank',
|
|
22
|
+
'notes',
|
|
23
|
+
'cupping_notes',
|
|
24
|
+
'purchase_date',
|
|
25
|
+
'purchased_qty_lbs',
|
|
26
|
+
'bean_cost',
|
|
27
|
+
'tax_ship_cost',
|
|
28
|
+
'last_updated',
|
|
29
|
+
'user',
|
|
30
|
+
'catalog_id',
|
|
31
|
+
'stocked',
|
|
32
|
+
'coffee_catalog!catalog_id (id, name, source, country, region, processing, cost_lb, description_short, description_long, farm_notes, cupping_notes, stocked)',
|
|
33
|
+
].join(', ');
|
|
34
|
+
// ─── Zod schemas ──────────────────────────────────────────────────────────────
|
|
35
|
+
export const listInventorySchema = z.object({
|
|
36
|
+
stocked: z.boolean().optional(),
|
|
37
|
+
limit: z.number().int().min(1).default(20),
|
|
38
|
+
});
|
|
39
|
+
export const getInventorySchema = z.object({
|
|
40
|
+
id: z.number().int().positive(),
|
|
41
|
+
});
|
|
42
|
+
export const addInventorySchema = z.object({
|
|
43
|
+
catalogId: z.number().int().positive(),
|
|
44
|
+
qty: z.number().positive(),
|
|
45
|
+
cost: z.number().optional(),
|
|
46
|
+
taxShip: z.number().optional(),
|
|
47
|
+
notes: z.string().optional(),
|
|
48
|
+
purchaseDate: z.string().optional(),
|
|
49
|
+
});
|
|
50
|
+
export const updateInventorySchema = z
|
|
51
|
+
.object({
|
|
52
|
+
qty: z.number().positive().optional(),
|
|
53
|
+
cost: z.number().optional(),
|
|
54
|
+
taxShip: z.number().optional(),
|
|
55
|
+
notes: z.string().optional(),
|
|
56
|
+
stocked: z.boolean().optional(),
|
|
57
|
+
})
|
|
58
|
+
.refine((v) => Object.keys(v).some((k) => v[k] !== undefined), {
|
|
59
|
+
message: 'No update fields provided. Pass at least one of: qty, cost, taxShip, notes, stocked.',
|
|
60
|
+
});
|
|
61
|
+
export const deleteInventorySchema = z.object({
|
|
62
|
+
id: z.number().int().positive(),
|
|
63
|
+
});
|
|
64
|
+
// ─── Pure lib functions ───────────────────────────────────────────────────────
|
|
65
|
+
/**
|
|
66
|
+
* List green coffee inventory for a user.
|
|
67
|
+
*/
|
|
68
|
+
export async function listInventory(supabase, userId, opts) {
|
|
69
|
+
const parsed = listInventorySchema.parse(opts);
|
|
70
|
+
let query = supabase.from('green_coffee_inv').select(INVENTORY_LIST_SELECT).eq('user', userId);
|
|
71
|
+
if (parsed.stocked) {
|
|
72
|
+
query = query.eq('stocked', true);
|
|
73
|
+
}
|
|
74
|
+
const { data, error } = await query
|
|
75
|
+
.order('last_updated', { ascending: false })
|
|
76
|
+
.limit(parsed.limit);
|
|
77
|
+
if (error)
|
|
78
|
+
throw error;
|
|
79
|
+
return (data ?? []);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Fetch a single inventory item by ID (must belong to userId).
|
|
83
|
+
*/
|
|
84
|
+
export async function getInventory(supabase, userId, id) {
|
|
85
|
+
getInventorySchema.parse({ id });
|
|
86
|
+
const { data, error } = await supabase
|
|
87
|
+
.from('green_coffee_inv')
|
|
88
|
+
.select(INVENTORY_DETAIL_SELECT)
|
|
89
|
+
.eq('id', id)
|
|
90
|
+
.eq('user', userId)
|
|
91
|
+
.single();
|
|
92
|
+
if (error) {
|
|
93
|
+
if (error.code === 'PGRST116') {
|
|
94
|
+
throw new AuthError(`Inventory item ${id} not found or does not belong to you.`);
|
|
95
|
+
}
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
return data;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Add a new inventory item for a user.
|
|
102
|
+
*/
|
|
103
|
+
export async function addInventory(supabase, userId, input) {
|
|
104
|
+
const parsed = addInventorySchema.parse(input);
|
|
105
|
+
const todayIso = () => new Date().toISOString().slice(0, 10);
|
|
106
|
+
const insertPayload = {
|
|
107
|
+
user: userId,
|
|
108
|
+
catalog_id: parsed.catalogId,
|
|
109
|
+
purchased_qty_lbs: parsed.qty,
|
|
110
|
+
purchase_date: parsed.purchaseDate ?? todayIso(),
|
|
111
|
+
};
|
|
112
|
+
if (parsed.cost !== undefined)
|
|
113
|
+
insertPayload.bean_cost = parsed.cost;
|
|
114
|
+
if (parsed.taxShip !== undefined)
|
|
115
|
+
insertPayload.tax_ship_cost = parsed.taxShip;
|
|
116
|
+
if (parsed.notes !== undefined)
|
|
117
|
+
insertPayload.notes = parsed.notes;
|
|
118
|
+
const { data: inserted, error: insertError } = await supabase
|
|
119
|
+
.from('green_coffee_inv')
|
|
120
|
+
.insert(insertPayload)
|
|
121
|
+
.select('id')
|
|
122
|
+
.single();
|
|
123
|
+
if (insertError)
|
|
124
|
+
throw insertError;
|
|
125
|
+
// Re-fetch with catalog join
|
|
126
|
+
const { data, error } = await supabase
|
|
127
|
+
.from('green_coffee_inv')
|
|
128
|
+
.select(INVENTORY_LIST_SELECT)
|
|
129
|
+
.eq('id', inserted.id)
|
|
130
|
+
.single();
|
|
131
|
+
if (error)
|
|
132
|
+
throw error;
|
|
133
|
+
return data;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Update an existing inventory item (must belong to userId).
|
|
137
|
+
*/
|
|
138
|
+
export async function updateInventory(supabase, userId, id, input) {
|
|
139
|
+
getInventorySchema.parse({ id });
|
|
140
|
+
const parsed = updateInventorySchema.parse(input);
|
|
141
|
+
// Verify ownership
|
|
142
|
+
const { data: existing, error: fetchError } = await supabase
|
|
143
|
+
.from('green_coffee_inv')
|
|
144
|
+
.select('id')
|
|
145
|
+
.eq('id', id)
|
|
146
|
+
.eq('user', userId)
|
|
147
|
+
.single();
|
|
148
|
+
if (fetchError || !existing) {
|
|
149
|
+
throw new AuthError(`Inventory item ${id} not found or does not belong to you.`);
|
|
150
|
+
}
|
|
151
|
+
const updates = {};
|
|
152
|
+
if (parsed.qty !== undefined)
|
|
153
|
+
updates.purchased_qty_lbs = parsed.qty;
|
|
154
|
+
if (parsed.cost !== undefined)
|
|
155
|
+
updates.bean_cost = parsed.cost;
|
|
156
|
+
if (parsed.taxShip !== undefined)
|
|
157
|
+
updates.tax_ship_cost = parsed.taxShip;
|
|
158
|
+
if (parsed.notes !== undefined)
|
|
159
|
+
updates.notes = parsed.notes;
|
|
160
|
+
if (parsed.stocked !== undefined)
|
|
161
|
+
updates.stocked = parsed.stocked;
|
|
162
|
+
if (Object.keys(updates).length === 0) {
|
|
163
|
+
throw new PrvrsError('INVALID_ARGUMENT', 'No update fields provided. Pass at least one of: qty, cost, taxShip, notes, stocked.');
|
|
164
|
+
}
|
|
165
|
+
const { error: updateError } = await supabase
|
|
166
|
+
.from('green_coffee_inv')
|
|
167
|
+
.update(updates)
|
|
168
|
+
.eq('id', id)
|
|
169
|
+
.eq('user', userId);
|
|
170
|
+
if (updateError)
|
|
171
|
+
throw updateError;
|
|
172
|
+
// Re-fetch the updated row
|
|
173
|
+
const { data, error } = await supabase
|
|
174
|
+
.from('green_coffee_inv')
|
|
175
|
+
.select(INVENTORY_LIST_SELECT)
|
|
176
|
+
.eq('id', id)
|
|
177
|
+
.single();
|
|
178
|
+
if (error)
|
|
179
|
+
throw error;
|
|
180
|
+
return data;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Delete an inventory item (must belong to userId).
|
|
184
|
+
*/
|
|
185
|
+
export async function deleteInventory(supabase, userId, id) {
|
|
186
|
+
deleteInventorySchema.parse({ id });
|
|
187
|
+
// Verify ownership
|
|
188
|
+
const { data: existing, error: fetchError } = await supabase
|
|
189
|
+
.from('green_coffee_inv')
|
|
190
|
+
.select('id')
|
|
191
|
+
.eq('id', id)
|
|
192
|
+
.eq('user', userId)
|
|
193
|
+
.single();
|
|
194
|
+
if (fetchError || !existing) {
|
|
195
|
+
throw new AuthError(`Inventory item ${id} not found or does not belong to you.`);
|
|
196
|
+
}
|
|
197
|
+
const { error: deleteError } = await supabase
|
|
198
|
+
.from('green_coffee_inv')
|
|
199
|
+
.delete()
|
|
200
|
+
.eq('id', id)
|
|
201
|
+
.eq('user', userId);
|
|
202
|
+
if (deleteError)
|
|
203
|
+
throw deleteError;
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=inventory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inventory.js","sourceRoot":"","sources":["../../src/lib/inventory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
3
|
+
import type { ArtisanImportResult } from './artisan/import.js';
|
|
4
|
+
export interface RoastProfile {
|
|
5
|
+
roast_id: number;
|
|
6
|
+
batch_name: string | null;
|
|
7
|
+
coffee_id: number | null;
|
|
8
|
+
coffee_name: string | null;
|
|
9
|
+
roast_date: string | null;
|
|
10
|
+
oz_in: number | null;
|
|
11
|
+
oz_out: number | null;
|
|
12
|
+
weight_loss_percent: number | null;
|
|
13
|
+
roast_notes: string | null;
|
|
14
|
+
user: string;
|
|
15
|
+
last_updated: string;
|
|
16
|
+
roaster_type: string | null;
|
|
17
|
+
roaster_size: string | null;
|
|
18
|
+
temperature_unit: string | null;
|
|
19
|
+
charge_time: number | null;
|
|
20
|
+
drop_time: number | null;
|
|
21
|
+
fc_start_time: number | null;
|
|
22
|
+
fc_end_time: number | null;
|
|
23
|
+
fc_start_temp: number | null;
|
|
24
|
+
drop_temp: number | null;
|
|
25
|
+
charge_temp: number | null;
|
|
26
|
+
dry_percent: number | null;
|
|
27
|
+
maillard_percent: number | null;
|
|
28
|
+
development_percent: number | null;
|
|
29
|
+
total_roast_time: number | null;
|
|
30
|
+
data_source: string | null;
|
|
31
|
+
roast_uuid: string | null;
|
|
32
|
+
temperatures?: TemperatureEntry[];
|
|
33
|
+
events?: RoastEventEntry[];
|
|
34
|
+
}
|
|
35
|
+
export interface TemperatureEntry {
|
|
36
|
+
roast_id: number;
|
|
37
|
+
time_seconds: number;
|
|
38
|
+
bean_temp: number | null;
|
|
39
|
+
environmental_temp: number | null;
|
|
40
|
+
}
|
|
41
|
+
export interface RoastEventEntry {
|
|
42
|
+
roast_id: number;
|
|
43
|
+
time_seconds: number;
|
|
44
|
+
event_type: number | null;
|
|
45
|
+
event_value: string | null;
|
|
46
|
+
}
|
|
47
|
+
export declare const listRoastsSchema: z.ZodObject<{
|
|
48
|
+
coffeeId: z.ZodOptional<z.ZodNumber>;
|
|
49
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
50
|
+
}, z.core.$strip>;
|
|
51
|
+
export type ListRoastsInput = z.input<typeof listRoastsSchema>;
|
|
52
|
+
export declare const getRoastSchema: z.ZodObject<{
|
|
53
|
+
id: z.ZodNumber;
|
|
54
|
+
includeTemps: z.ZodOptional<z.ZodBoolean>;
|
|
55
|
+
includeEvents: z.ZodOptional<z.ZodBoolean>;
|
|
56
|
+
}, z.core.$strip>;
|
|
57
|
+
export type GetRoastInput = z.input<typeof getRoastSchema>;
|
|
58
|
+
export declare const createRoastSchema: z.ZodObject<{
|
|
59
|
+
coffeeId: z.ZodNumber;
|
|
60
|
+
batchName: z.ZodOptional<z.ZodString>;
|
|
61
|
+
ozIn: z.ZodOptional<z.ZodNumber>;
|
|
62
|
+
ozOut: z.ZodOptional<z.ZodNumber>;
|
|
63
|
+
roastDate: z.ZodOptional<z.ZodString>;
|
|
64
|
+
notes: z.ZodOptional<z.ZodString>;
|
|
65
|
+
}, z.core.$strip>;
|
|
66
|
+
export type CreateRoastInput = z.input<typeof createRoastSchema>;
|
|
67
|
+
export declare const deleteRoastSchema: z.ZodObject<{
|
|
68
|
+
id: z.ZodNumber;
|
|
69
|
+
}, z.core.$strip>;
|
|
70
|
+
export type DeleteRoastInput = z.input<typeof deleteRoastSchema>;
|
|
71
|
+
/**
|
|
72
|
+
* List roast profiles for a user.
|
|
73
|
+
*/
|
|
74
|
+
export declare function listRoasts(supabase: SupabaseClient, userId: string, opts: ListRoastsInput): Promise<RoastProfile[]>;
|
|
75
|
+
/**
|
|
76
|
+
* Fetch a single roast profile by ID (must belong to userId).
|
|
77
|
+
* Optionally includes temperature curve and roast events.
|
|
78
|
+
*/
|
|
79
|
+
export declare function getRoast(supabase: SupabaseClient, userId: string, id: number, opts?: {
|
|
80
|
+
includeTemps?: boolean;
|
|
81
|
+
includeEvents?: boolean;
|
|
82
|
+
}): Promise<RoastProfile>;
|
|
83
|
+
/**
|
|
84
|
+
* Create a new roast profile (coffeeId must be an inventory item belonging to userId).
|
|
85
|
+
*/
|
|
86
|
+
export declare function createRoast(supabase: SupabaseClient, userId: string, input: CreateRoastInput): Promise<RoastProfile>;
|
|
87
|
+
/**
|
|
88
|
+
* Delete a roast profile (must belong to userId).
|
|
89
|
+
*/
|
|
90
|
+
export declare function deleteRoast(supabase: SupabaseClient, userId: string, id: number): Promise<void>;
|
|
91
|
+
export declare const importRoastSchema: z.ZodObject<{
|
|
92
|
+
fileContent: z.ZodString;
|
|
93
|
+
fileName: z.ZodString;
|
|
94
|
+
coffeeId: z.ZodNumber;
|
|
95
|
+
batchName: z.ZodOptional<z.ZodString>;
|
|
96
|
+
ozIn: z.ZodOptional<z.ZodNumber>;
|
|
97
|
+
roastNotes: z.ZodOptional<z.ZodString>;
|
|
98
|
+
}, z.core.$strip>;
|
|
99
|
+
export type ImportRoastInput = z.input<typeof importRoastSchema>;
|
|
100
|
+
export interface ImportRoastResult extends ArtisanImportResult {
|
|
101
|
+
roast_id: number;
|
|
102
|
+
batch_name: string;
|
|
103
|
+
coffee_name: string;
|
|
104
|
+
coffee_id: number;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Extract the input weight in ounces from an Artisan .alog weight array.
|
|
108
|
+
* Falls back to undefined if weight data is absent or unparseable.
|
|
109
|
+
*
|
|
110
|
+
* @param weight - The `weight` field from ArtisanRoastData: [input, output, unit]
|
|
111
|
+
*/
|
|
112
|
+
export declare function extractOzFromAlog(weight: [number, number, string] | undefined): number | undefined;
|
|
113
|
+
/**
|
|
114
|
+
* Generate a default batch name: "{coffee_name} {YYYY-MM-DD}".
|
|
115
|
+
*/
|
|
116
|
+
export declare function defaultBatchName(coffeeName: string, dateIso: string): string;
|
|
117
|
+
/**
|
|
118
|
+
* Import a roast from an Artisan .alog file in one step:
|
|
119
|
+
* 1. Verify inventory ownership + get coffee name
|
|
120
|
+
* 2. Create a new roast_profile row
|
|
121
|
+
* 3. Run the full Artisan import (temperatures, events, profile metadata)
|
|
122
|
+
* 4. Return the combined result
|
|
123
|
+
*
|
|
124
|
+
* The supabase client must already be authenticated as userId.
|
|
125
|
+
*/
|
|
126
|
+
export declare function importRoastFromFile(supabase: SupabaseClient, userId: string, input: ImportRoastInput): Promise<ImportRoastResult>;
|
|
127
|
+
//# sourceMappingURL=roast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roast.d.ts","sourceRoot":"","sources":["../../src/lib/roast.ts"],"names":[],"mappings":"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"}
|