@purveyors/cli 0.1.0 → 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/README.md +23 -23
- package/dist/commands/auth.js +4 -4
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/catalog.d.ts +5 -57
- package/dist/commands/catalog.d.ts.map +1 -1
- package/dist/commands/catalog.js +15 -82
- package/dist/commands/catalog.js.map +1 -1
- package/dist/commands/inventory.d.ts +3 -26
- package/dist/commands/inventory.d.ts.map +1 -1
- package/dist/commands/inventory.js +53 -153
- package/dist/commands/inventory.js.map +1 -1
- package/dist/commands/roast.d.ts +3 -42
- package/dist/commands/roast.d.ts.map +1 -1
- package/dist/commands/roast.js +144 -131
- package/dist/commands/roast.js.map +1 -1
- package/dist/commands/sales.d.ts +3 -11
- package/dist/commands/sales.d.ts.map +1 -1
- package/dist/commands/sales.js +35 -114
- package/dist/commands/sales.js.map +1 -1
- package/dist/commands/tasting.d.ts +5 -39
- package/dist/commands/tasting.d.ts.map +1 -1
- package/dist/commands/tasting.js +21 -111
- package/dist/commands/tasting.js.map +1 -1
- package/dist/index.js +23 -23
- package/dist/index.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/config.d.ts +1 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +20 -2
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/errors.js +2 -2
- package/dist/lib/errors.js.map +1 -1
- 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/supabase.js +2 -2
- package/dist/lib/supabase.js.map +1 -1
- 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 +24 -13
|
@@ -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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"}
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ declare const CREDENTIALS_FILE: string;
|
|
|
7
7
|
export declare function ensureConfigDir(): Promise<void>;
|
|
8
8
|
/**
|
|
9
9
|
* Read stored credentials from disk. Returns null if not found.
|
|
10
|
+
* Migrates legacy credentials from ~/.config/prvrs/ (v0.1.x) to ~/.config/purvey/ on first run.
|
|
10
11
|
*/
|
|
11
12
|
export declare function readCredentials(): Promise<StoredCredentials | null>;
|
|
12
13
|
/**
|
package/dist/lib/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,QAAA,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,QAAA,MAAM,UAAU,QAAuC,CAAC;AACxD,QAAA,MAAM,gBAAgB,QAAuC,CAAC;AAM9D;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAErD;AAED;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAqBzE;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9E;AAED;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMvD;AAED,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC"}
|
package/dist/lib/config.js
CHANGED
|
@@ -2,8 +2,11 @@ import { homedir } from 'os';
|
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { mkdir, readFile, writeFile, unlink, access } from 'fs/promises';
|
|
4
4
|
import { constants } from 'fs';
|
|
5
|
-
const CONFIG_DIR = join(homedir(), '.config', '
|
|
5
|
+
const CONFIG_DIR = join(homedir(), '.config', 'purvey');
|
|
6
6
|
const CREDENTIALS_FILE = join(CONFIG_DIR, 'credentials.json');
|
|
7
|
+
// Legacy path from v0.1.x (was ~/.config/prvrs/)
|
|
8
|
+
const LEGACY_CONFIG_DIR = join(homedir(), '.config', 'prvrs');
|
|
9
|
+
const LEGACY_CREDENTIALS_FILE = join(LEGACY_CONFIG_DIR, 'credentials.json');
|
|
7
10
|
/**
|
|
8
11
|
* Ensure the config directory exists with secure permissions.
|
|
9
12
|
*/
|
|
@@ -12,6 +15,7 @@ export async function ensureConfigDir() {
|
|
|
12
15
|
}
|
|
13
16
|
/**
|
|
14
17
|
* Read stored credentials from disk. Returns null if not found.
|
|
18
|
+
* Migrates legacy credentials from ~/.config/prvrs/ (v0.1.x) to ~/.config/purvey/ on first run.
|
|
15
19
|
*/
|
|
16
20
|
export async function readCredentials() {
|
|
17
21
|
try {
|
|
@@ -20,7 +24,21 @@ export async function readCredentials() {
|
|
|
20
24
|
return JSON.parse(raw);
|
|
21
25
|
}
|
|
22
26
|
catch {
|
|
23
|
-
|
|
27
|
+
// Not found at new path — check legacy location and migrate if present
|
|
28
|
+
try {
|
|
29
|
+
await access(LEGACY_CREDENTIALS_FILE, constants.R_OK);
|
|
30
|
+
const raw = await readFile(LEGACY_CREDENTIALS_FILE, 'utf-8');
|
|
31
|
+
const creds = JSON.parse(raw);
|
|
32
|
+
// Migrate to new path
|
|
33
|
+
await writeCredentials(creds);
|
|
34
|
+
// Clean up old file (best-effort)
|
|
35
|
+
const { unlink: unlinkSync } = await import('fs/promises');
|
|
36
|
+
await unlinkSync(LEGACY_CREDENTIALS_FILE).catch(() => { });
|
|
37
|
+
return creds;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
24
42
|
}
|
|
25
43
|
}
|
|
26
44
|
/**
|
package/dist/lib/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAG/B,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAG/B,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AACxD,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;AAE9D,iDAAiD;AACjD,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AAC9D,MAAM,uBAAuB,GAAG,IAAI,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAAC;AAE5E;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC5D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,gBAAgB,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAsB,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;QACvE,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,uBAAuB,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;YACtD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,uBAAuB,EAAE,OAAO,CAAC,CAAC;YAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAsB,CAAC;YACnD,sBAAsB;YACtB,MAAM,gBAAgB,CAAC,KAAK,CAAC,CAAC;YAC9B,kCAAkC;YAClC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;YAC3D,MAAM,UAAU,CAAC,uBAAuB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAC1D,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAAwB;IAC7D,MAAM,eAAe,EAAE,CAAC;IACxB,MAAM,SAAS,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACrF,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,6BAA6B;IAC/B,CAAC;AACH,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC"}
|
package/dist/lib/errors.js
CHANGED
|
@@ -27,13 +27,13 @@ export class ConfigError extends PrvrsError {
|
|
|
27
27
|
export function fatal(error) {
|
|
28
28
|
if (error instanceof PrvrsError) {
|
|
29
29
|
console.error(chalk.red(`✖ ${error.message}`));
|
|
30
|
-
if (process.env.
|
|
30
|
+
if (process.env.PURVEY_DEBUG && error.details) {
|
|
31
31
|
console.error(chalk.dim('Details:'), error.details);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
else if (error instanceof Error) {
|
|
35
35
|
console.error(chalk.red(`✖ ${error.message}`));
|
|
36
|
-
if (process.env.
|
|
36
|
+
if (process.env.PURVEY_DEBUG && error.stack) {
|
|
37
37
|
console.error(chalk.dim(error.stack));
|
|
38
38
|
}
|
|
39
39
|
}
|
package/dist/lib/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnB,IAAI,CAAS;IACb,OAAO,CAAW;IAElC,YAAY,IAAY,EAAE,OAAe,EAAE,OAAiB;QAC1D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAED,MAAM,OAAO,SAAU,SAAQ,UAAU;IACvC,YAAY,OAAe,EAAE,OAAiB;QAC5C,KAAK,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,OAAO,WAAY,SAAQ,UAAU;IACzC,YAAY,OAAe,EAAE,OAAiB;QAC5C,KAAK,CAAC,cAAc,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,KAAc;IAClC,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC/C,IAAI,OAAO,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnB,IAAI,CAAS;IACb,OAAO,CAAW;IAElC,YAAY,IAAY,EAAE,OAAe,EAAE,OAAiB;QAC1D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAED,MAAM,OAAO,SAAU,SAAQ,UAAU;IACvC,YAAY,OAAe,EAAE,OAAiB;QAC5C,KAAK,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,OAAO,WAAY,SAAQ,UAAU;IACzC,YAAY,OAAe,EAAE,OAAiB;QAC5C,KAAK,CAAC,cAAc,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,KAAc;IAClC,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC/C,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAC9C,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;SAAM,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC/C,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAC5C,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,EAAiC;IAEjC,OAAO,KAAK,EAAE,GAAG,IAAO,EAAE,EAAE;QAC1B,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,KAAK,CAAC,KAAK,CAAC,CAAC;QACf,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -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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"}
|