@purveyors/cli 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/commands/catalog.d.ts +4 -56
  2. package/dist/commands/catalog.d.ts.map +1 -1
  3. package/dist/commands/catalog.js +14 -81
  4. package/dist/commands/catalog.js.map +1 -1
  5. package/dist/commands/config.d.ts +7 -0
  6. package/dist/commands/config.d.ts.map +1 -0
  7. package/dist/commands/config.js +82 -0
  8. package/dist/commands/config.js.map +1 -0
  9. package/dist/commands/inventory.d.ts +2 -25
  10. package/dist/commands/inventory.d.ts.map +1 -1
  11. package/dist/commands/inventory.js +109 -149
  12. package/dist/commands/inventory.js.map +1 -1
  13. package/dist/commands/roast.d.ts +2 -41
  14. package/dist/commands/roast.d.ts.map +1 -1
  15. package/dist/commands/roast.js +445 -126
  16. package/dist/commands/roast.js.map +1 -1
  17. package/dist/commands/sales.d.ts +2 -10
  18. package/dist/commands/sales.d.ts.map +1 -1
  19. package/dist/commands/sales.js +100 -112
  20. package/dist/commands/sales.js.map +1 -1
  21. package/dist/commands/tasting.d.ts +4 -38
  22. package/dist/commands/tasting.d.ts.map +1 -1
  23. package/dist/commands/tasting.js +93 -116
  24. package/dist/commands/tasting.js.map +1 -1
  25. package/dist/index.js +8 -0
  26. package/dist/index.js.map +1 -1
  27. package/dist/lib/ai.d.ts +36 -0
  28. package/dist/lib/ai.d.ts.map +1 -0
  29. package/dist/lib/ai.js +38 -0
  30. package/dist/lib/ai.js.map +1 -0
  31. package/dist/lib/artisan/db.d.ts +37 -0
  32. package/dist/lib/artisan/db.d.ts.map +1 -0
  33. package/dist/lib/artisan/db.js +51 -0
  34. package/dist/lib/artisan/db.js.map +1 -0
  35. package/dist/lib/artisan/import.d.ts +16 -0
  36. package/dist/lib/artisan/import.d.ts.map +1 -0
  37. package/dist/lib/artisan/import.js +447 -0
  38. package/dist/lib/artisan/import.js.map +1 -0
  39. package/dist/lib/artisan/index.d.ts +9 -0
  40. package/dist/lib/artisan/index.d.ts.map +1 -0
  41. package/dist/lib/artisan/index.js +7 -0
  42. package/dist/lib/artisan/index.js.map +1 -0
  43. package/dist/lib/artisan/parser.d.ts +19 -0
  44. package/dist/lib/artisan/parser.d.ts.map +1 -0
  45. package/dist/lib/artisan/parser.js +376 -0
  46. package/dist/lib/artisan/parser.js.map +1 -0
  47. package/dist/lib/artisan/temperature.d.ts +52 -0
  48. package/dist/lib/artisan/temperature.d.ts.map +1 -0
  49. package/dist/lib/artisan/temperature.js +101 -0
  50. package/dist/lib/artisan/temperature.js.map +1 -0
  51. package/dist/lib/artisan/types.d.ts +195 -0
  52. package/dist/lib/artisan/types.d.ts.map +1 -0
  53. package/dist/lib/artisan/types.js +35 -0
  54. package/dist/lib/artisan/types.js.map +1 -0
  55. package/dist/lib/artisan/validator.d.ts +14 -0
  56. package/dist/lib/artisan/validator.d.ts.map +1 -0
  57. package/dist/lib/artisan/validator.js +228 -0
  58. package/dist/lib/artisan/validator.js.map +1 -0
  59. package/dist/lib/catalog.d.ts +87 -0
  60. package/dist/lib/catalog.d.ts.map +1 -0
  61. package/dist/lib/catalog.js +111 -0
  62. package/dist/lib/catalog.js.map +1 -0
  63. package/dist/lib/config.d.ts +26 -0
  64. package/dist/lib/config.d.ts.map +1 -1
  65. package/dist/lib/config.js +59 -0
  66. package/dist/lib/config.js.map +1 -1
  67. package/dist/lib/index.d.ts +6 -0
  68. package/dist/lib/index.d.ts.map +1 -0
  69. package/dist/lib/index.js +11 -0
  70. package/dist/lib/index.js.map +1 -0
  71. package/dist/lib/interactive/forms.d.ts +33 -0
  72. package/dist/lib/interactive/forms.d.ts.map +1 -0
  73. package/dist/lib/interactive/forms.js +139 -0
  74. package/dist/lib/interactive/forms.js.map +1 -0
  75. package/dist/lib/interactive/watch.d.ts +66 -0
  76. package/dist/lib/interactive/watch.d.ts.map +1 -0
  77. package/dist/lib/interactive/watch.js +494 -0
  78. package/dist/lib/interactive/watch.js.map +1 -0
  79. package/dist/lib/inventory.d.ts +80 -0
  80. package/dist/lib/inventory.d.ts.map +1 -0
  81. package/dist/lib/inventory.js +205 -0
  82. package/dist/lib/inventory.js.map +1 -0
  83. package/dist/lib/roast.d.ts +127 -0
  84. package/dist/lib/roast.d.ts.map +1 -0
  85. package/dist/lib/roast.js +284 -0
  86. package/dist/lib/roast.js.map +1 -0
  87. package/dist/lib/sales.d.ts +53 -0
  88. package/dist/lib/sales.d.ts.map +1 -0
  89. package/dist/lib/sales.js +155 -0
  90. package/dist/lib/sales.js.map +1 -0
  91. package/dist/lib/tasting.d.ts +76 -0
  92. package/dist/lib/tasting.d.ts.map +1 -0
  93. package/dist/lib/tasting.js +136 -0
  94. package/dist/lib/tasting.js.map +1 -0
  95. package/package.json +15 -2
@@ -1,19 +1,27 @@
1
1
  import { Command } from 'commander';
2
+ import * as p from '@clack/prompts';
2
3
  import { createAuthenticatedClient } from '../lib/supabase.js';
3
4
  import { outputData, info, success } from '../lib/output.js';
4
5
  import { withErrorHandling, AuthError, PrvrsError } from '../lib/errors.js';
5
- // ─── Validation helpers ───────────────────────────────────────────────────────
6
- /** Validate a cupping score is an integer in [1, 5]. */
7
- export function isValidCuppingScore(value) {
8
- return Number.isInteger(value) && value >= 1 && value <= 5;
9
- }
10
- /** Parse and validate a cupping score flag value. */
11
- export function parseCuppingScore(raw, flag) {
12
- const n = parseInt(raw, 10);
13
- if (isNaN(n) || !isValidCuppingScore(n)) {
14
- throw new PrvrsError('INVALID_ARGUMENT', `--${flag} must be an integer between 1 and 5 (got "${raw}").`);
15
- }
16
- return n;
6
+ import { getTastingNotes, rateCoffee, isValidCuppingScore, parseCuppingScore, } from '../lib/tasting.js';
7
+ import { pickBean, guardCancel } from '../lib/interactive/forms.js';
8
+ import { getConfigValue } from '../lib/config.js';
9
+ export { isValidCuppingScore, parseCuppingScore };
10
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
11
+ /** Prompt for a single cupping dimension score. */
12
+ async function promptCuppingScore(dimension) {
13
+ const raw = await p.text({
14
+ message: `${dimension} (1-5)`,
15
+ placeholder: '3',
16
+ validate: (v) => {
17
+ const n = parseInt(String(v), 10);
18
+ if (isNaN(n) || n < 1 || n > 5 || !Number.isInteger(n)) {
19
+ return `Must be an integer between 1 and 5.`;
20
+ }
21
+ },
22
+ });
23
+ guardCancel(raw);
24
+ return parseInt(String(raw), 10);
17
25
  }
18
26
  // ─── Command builder ──────────────────────────────────────────────────────────
19
27
  /**
@@ -43,59 +51,7 @@ export function buildTastingCommand() {
43
51
  if (!user) {
44
52
  throw new AuthError('Not logged in. Run `purvey auth login` first.');
45
53
  }
46
- const result = {
47
- beanId: catalogId,
48
- filter,
49
- supplier: null,
50
- user: null,
51
- };
52
- // ── Supplier notes (from coffee_catalog) ─────────────────────────
53
- if (filter === 'supplier' || filter === 'both') {
54
- const { data: catalogRow, error: catalogError } = await supabase
55
- .from('coffee_catalog')
56
- .select('id, name, processing, region, source, cupping_notes, ai_tasting_notes, ai_description')
57
- .eq('id', catalogId)
58
- .single();
59
- if (catalogError && catalogError.code !== 'PGRST116') {
60
- throw catalogError;
61
- }
62
- if (catalogRow) {
63
- result.supplier = {
64
- source: 'supplier',
65
- catalogId: catalogRow.id,
66
- name: catalogRow.name ?? null,
67
- processing: catalogRow.processing ?? null,
68
- region: catalogRow.region ?? null,
69
- cupping_notes: catalogRow.cupping_notes ?? null,
70
- ai_tasting_notes: catalogRow.ai_tasting_notes ?? null,
71
- ai_description: catalogRow.ai_description ?? null,
72
- };
73
- }
74
- }
75
- // ── User notes (from green_coffee_inv) ───────────────────────────
76
- if (filter === 'user' || filter === 'both') {
77
- // A user might have multiple inventory items from the same catalog entry
78
- const { data: invRows, error: invError } = await supabase
79
- .from('green_coffee_inv')
80
- .select('id, catalog_id, cupping_notes, notes')
81
- .eq('catalog_id', catalogId)
82
- .eq('user', user.id)
83
- .order('id', { ascending: false })
84
- .limit(1);
85
- if (invError)
86
- throw invError;
87
- if (invRows && invRows.length > 0) {
88
- const row = invRows[0];
89
- result.user = {
90
- source: 'user',
91
- inventoryId: row.id,
92
- catalogId: row.catalog_id ?? null,
93
- cupping_notes: row.cupping_notes ?? null,
94
- notes: row.notes ?? null,
95
- };
96
- }
97
- }
98
- // If nothing found at all, let the user know
54
+ const result = await getTastingNotes(supabase, user.id, catalogId, filter);
99
55
  if (result.supplier === null && result.user === null) {
100
56
  info(`No tasting notes found for bean ID ${catalogId} (filter: ${filter}).`);
101
57
  return;
@@ -104,68 +60,89 @@ export function buildTastingCommand() {
104
60
  }));
105
61
  // ── tasting rate <bean-id> ────────────────────────────────────────────────
106
62
  tasting
107
- .command('rate <bean-id>')
63
+ .command('rate')
108
64
  .description('Rate a bean from your inventory using cupping scores (updates green_coffee_inv)')
109
- .requiredOption('--aroma <1-5>', 'Aroma score (1-5)')
110
- .requiredOption('--body <1-5>', 'Body score (1-5)')
111
- .requiredOption('--acidity <1-5>', 'Acidity score (1-5)')
112
- .requiredOption('--sweetness <1-5>', 'Sweetness score (1-5)')
113
- .requiredOption('--aftertaste <1-5>', 'Aftertaste score (1-5)')
65
+ .argument('[bean-id]', 'Inventory item ID (green_coffee_inv), or use --form')
66
+ .option('--aroma <1-5>', 'Aroma score (1-5)')
67
+ .option('--body <1-5>', 'Body score (1-5)')
68
+ .option('--acidity <1-5>', 'Acidity score (1-5)')
69
+ .option('--sweetness <1-5>', 'Sweetness score (1-5)')
70
+ .option('--aftertaste <1-5>', 'Aftertaste score (1-5)')
114
71
  .option('--brew-method <method>', 'Brew method (e.g. pour_over, french_press, espresso)')
115
72
  .option('--notes <text>', 'Additional tasting notes')
73
+ .option('--form', 'Interactive form mode')
116
74
  .action(withErrorHandling(async (beanId, opts, cmd) => {
117
75
  const globalOpts = cmd.optsWithGlobals();
118
- const inventoryId = parseInt(beanId, 10);
119
- if (isNaN(inventoryId)) {
120
- throw new PrvrsError('INVALID_ARGUMENT', `Invalid bean ID: "${beanId}". Pass a green_coffee_inv ID.`);
121
- }
122
- // Parse and validate all scores
123
- const cupping = {
124
- aroma: parseCuppingScore(opts.aroma, 'aroma'),
125
- body: parseCuppingScore(opts.body, 'body'),
126
- acidity: parseCuppingScore(opts.acidity, 'acidity'),
127
- sweetness: parseCuppingScore(opts.sweetness, 'sweetness'),
128
- aftertaste: parseCuppingScore(opts.aftertaste, 'aftertaste'),
129
- rated_at: new Date().toISOString(),
130
- };
131
- if (opts.brewMethod !== undefined) {
132
- cupping.brew_method = opts.brewMethod;
133
- }
134
- if (opts.notes !== undefined) {
135
- cupping.notes = opts.notes;
136
- }
137
76
  const supabase = await createAuthenticatedClient();
138
77
  const { data: { user }, } = await supabase.auth.getUser();
139
78
  if (!user) {
140
79
  throw new AuthError('Not logged in. Run `purvey auth login` first.');
141
80
  }
142
- // Verify ownership of the inventory item
143
- const { data: existing, error: fetchError } = await supabase
144
- .from('green_coffee_inv')
145
- .select('id, catalog_id')
146
- .eq('id', inventoryId)
147
- .eq('user', user.id)
148
- .single();
149
- if (fetchError || !existing) {
150
- throw new AuthError(`Inventory item ${inventoryId} not found or does not belong to you.`);
81
+ // ── Interactive form mode ────────────────────────────────────────
82
+ // Auto-enter form mode if config form-mode is true and required args are missing
83
+ const formMode = opts.form || (!opts.id && (await getConfigValue('form-mode')) === 'true');
84
+ if (formMode) {
85
+ p.intro('Rate Coffee');
86
+ const bean = await pickBean(supabase, user.id);
87
+ const aroma = await promptCuppingScore('Aroma');
88
+ const body = await promptCuppingScore('Body');
89
+ const acidity = await promptCuppingScore('Acidity');
90
+ const sweetness = await promptCuppingScore('Sweetness');
91
+ const aftertaste = await promptCuppingScore('Aftertaste');
92
+ const notesRaw = await p.text({
93
+ message: 'Notes',
94
+ placeholder: 'optional',
95
+ });
96
+ guardCancel(notesRaw);
97
+ const confirmed = await p.confirm({ message: 'Save rating?' });
98
+ guardCancel(confirmed);
99
+ if (!confirmed) {
100
+ p.cancel('Aborted.');
101
+ return;
102
+ }
103
+ const notesStr = String(notesRaw).trim();
104
+ const data = await rateCoffee(supabase, user.id, bean.id, {
105
+ aroma,
106
+ body,
107
+ acidity,
108
+ sweetness,
109
+ aftertaste,
110
+ notes: notesStr !== '' ? notesStr : undefined,
111
+ });
112
+ p.outro(`Rating saved for "${bean.name}"!`);
113
+ outputData(data, globalOpts);
114
+ return;
115
+ }
116
+ // ── Flag-based mode ──────────────────────────────────────────────
117
+ if (!beanId) {
118
+ throw new PrvrsError('INVALID_ARGUMENT', 'Missing bean-id argument. Use --form for interactive mode.');
119
+ }
120
+ const inventoryId = parseInt(beanId, 10);
121
+ if (isNaN(inventoryId)) {
122
+ throw new PrvrsError('INVALID_ARGUMENT', `Invalid bean ID: "${beanId}". Pass a green_coffee_inv ID.`);
123
+ }
124
+ // Require all score flags in flag-based mode
125
+ const requiredFlags = ['aroma', 'body', 'acidity', 'sweetness', 'aftertaste'];
126
+ for (const flag of requiredFlags) {
127
+ if (opts[flag] === undefined) {
128
+ throw new PrvrsError('INVALID_ARGUMENT', `Missing --${flag}. Use --form for interactive mode.`);
129
+ }
151
130
  }
152
- // Update the cupping_notes JSONB field
153
- const { error: updateError } = await supabase
154
- .from('green_coffee_inv')
155
- // Pass object directly — Supabase JS serializes JSONB columns correctly
156
- .update({ cupping_notes: cupping })
157
- .eq('id', inventoryId)
158
- .eq('user', user.id);
159
- if (updateError)
160
- throw updateError;
161
- // Re-fetch the updated row
162
- const { data, error } = await supabase
163
- .from('green_coffee_inv')
164
- .select('id, catalog_id, cupping_notes, notes, last_updated')
165
- .eq('id', inventoryId)
166
- .single();
167
- if (error)
168
- throw error;
131
+ // Parse and validate all scores (CLI strings → numbers)
132
+ const aroma = parseCuppingScore(opts.aroma, 'aroma');
133
+ const body = parseCuppingScore(opts.body, 'body');
134
+ const acidity = parseCuppingScore(opts.acidity, 'acidity');
135
+ const sweetness = parseCuppingScore(opts.sweetness, 'sweetness');
136
+ const aftertaste = parseCuppingScore(opts.aftertaste, 'aftertaste');
137
+ const data = await rateCoffee(supabase, user.id, inventoryId, {
138
+ aroma,
139
+ body,
140
+ acidity,
141
+ sweetness,
142
+ aftertaste,
143
+ brewMethod: opts.brewMethod,
144
+ notes: opts.notes,
145
+ });
169
146
  success(`Cupping notes saved for inventory item ${inventoryId}.`);
170
147
  outputData(data, globalOpts);
171
148
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"tasting.js","sourceRoot":"","sources":["../../src/commands/tasting.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tasting.js","sourceRoot":"","sources":["../../src/commands/tasting.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
  import { Command } from 'commander';
3
3
  import { buildAuthCommand } from './commands/auth.js';
4
4
  import { buildCatalogCommand } from './commands/catalog.js';
5
+ import { buildConfigCommand } from './commands/config.js';
5
6
  import { buildInventoryCommand } from './commands/inventory.js';
6
7
  import { buildRoastCommand } from './commands/roast.js';
7
8
  import { buildSalesCommand } from './commands/sales.js';
@@ -49,6 +50,12 @@ Examples:
49
50
  $ purvey sales delete 5
50
51
  $ purvey tasting get 42 --filter both
51
52
  $ purvey tasting rate 7 --aroma 4 --body 3 --acidity 5 --sweetness 4 --aftertaste 4
53
+ $ purvey tasting rate --form # Interactive rating wizard
54
+ $ purvey inventory add --form # Interactive inventory wizard
55
+ $ purvey roast create --form # Interactive roast wizard
56
+ $ purvey sales record --form # Interactive sales wizard
57
+ $ purvey config set form-mode true # Auto-enter form mode when args missing
58
+ $ purvey config list # Show all config
52
59
  $ purvey --help # Show this help
53
60
 
54
61
  Docs: https://github.com/reedwhetstone/purveyors-cli
@@ -56,6 +63,7 @@ Docs: https://github.com/reedwhetstone/purveyors-cli
56
63
  // Register subcommands
57
64
  program.addCommand(buildAuthCommand());
58
65
  program.addCommand(buildCatalogCommand());
66
+ program.addCommand(buildConfigCommand());
59
67
  program.addCommand(buildInventoryCommand());
60
68
  program.addCommand(buildRoastCommand());
61
69
  program.addCommand(buildSalesCommand());
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAErC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,4CAA4C;AAC5C,IAAI,OAAO,GAAG,OAAO,CAAC;AACtB,IAAI,CAAC;IACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IACrF,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;AACnC,CAAC;AAAC,MAAM,CAAC;IACP,gCAAgC;AAClC,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,4EAA4E,CAAC;KACzF,OAAO,CAAC,OAAO,EAAE,eAAe,EAAE,eAAe,CAAC;KAClD,MAAM,CAAC,UAAU,EAAE,sCAAsC,CAAC;KAC1D,MAAM,CAAC,OAAO,EAAE,2DAA2D,CAAC;KAC5E,WAAW,CACV,OAAO,EACP;;;;;;;;;;;;;;;;;;;;;;;;;CAyBH,CACE,CAAC;AAEJ,uBAAuB;AACvB,OAAO,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC;AACvC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAC1C,OAAO,CAAC,UAAU,CAAC,qBAAqB,EAAE,CAAC,CAAC;AAC5C,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAE1C,qBAAqB;AACrB,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACtD,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAErC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,4CAA4C;AAC5C,IAAI,OAAO,GAAG,OAAO,CAAC;AACtB,IAAI,CAAC;IACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IACrF,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;AACnC,CAAC;AAAC,MAAM,CAAC;IACP,gCAAgC;AAClC,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,4EAA4E,CAAC;KACzF,OAAO,CAAC,OAAO,EAAE,eAAe,EAAE,eAAe,CAAC;KAClD,MAAM,CAAC,UAAU,EAAE,sCAAsC,CAAC;KAC1D,MAAM,CAAC,OAAO,EAAE,2DAA2D,CAAC;KAC5E,WAAW,CACV,OAAO,EACP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BH,CACE,CAAC;AAEJ,uBAAuB;AACvB,OAAO,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC;AACvC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAC1C,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;AACzC,OAAO,CAAC,UAAU,CAAC,qBAAqB,EAAE,CAAC,CAAC;AAC5C,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;AAE1C,qBAAqB;AACrB,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACtD,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * AI classification client for purveyors.io.
3
+ * Proxies requests through the purveyors.io API — never calls AI providers directly.
4
+ */
5
+ import type { SupabaseClient } from '@supabase/supabase-js';
6
+ export interface ClassifyRoastInput {
7
+ alogMetadata: {
8
+ title: string;
9
+ roastertype?: string;
10
+ beans?: string;
11
+ roastingnotes?: string;
12
+ weight?: [number, number, string];
13
+ };
14
+ inventory: Array<{
15
+ id: number;
16
+ coffee_name: string;
17
+ origin?: string;
18
+ processing?: string;
19
+ }>;
20
+ }
21
+ export interface ClassifyRoastResult {
22
+ match: {
23
+ inventoryId: number;
24
+ coffeeName: string;
25
+ confidence: number;
26
+ reasoning: string;
27
+ } | null;
28
+ }
29
+ /**
30
+ * Call the purveyors.io AI proxy to classify which inventory bean
31
+ * an .alog roast file corresponds to.
32
+ *
33
+ * Requires authenticated session. The proxy validates member role server-side.
34
+ */
35
+ export declare function classifyRoast(supabase: SupabaseClient, input: ClassifyRoastInput): Promise<ClassifyRoastResult>;
36
+ //# sourceMappingURL=ai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/lib/ai.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;KACnC,CAAC;IACF,SAAS,EAAE,KAAK,CAAC;QACf,EAAE,EAAE,MAAM,CAAC;QACX,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE;QACL,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,IAAI,CAAC;CACV;AAID;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CA+B9B"}
package/dist/lib/ai.js ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * AI classification client for purveyors.io.
3
+ * Proxies requests through the purveyors.io API — never calls AI providers directly.
4
+ */
5
+ // ─── Client ───────────────────────────────────────────────────────────────────
6
+ /**
7
+ * Call the purveyors.io AI proxy to classify which inventory bean
8
+ * an .alog roast file corresponds to.
9
+ *
10
+ * Requires authenticated session. The proxy validates member role server-side.
11
+ */
12
+ export async function classifyRoast(supabase, input) {
13
+ // Get the current session token for auth
14
+ const { data: { session }, } = await supabase.auth.getSession();
15
+ if (!session) {
16
+ throw new Error('Not authenticated. Run `purvey auth login` first.');
17
+ }
18
+ const baseUrl = process.env.PURVEYORS_BASE_URL ?? 'https://purveyors.io';
19
+ const response = await fetch(`${baseUrl}/api/ai/classify-roast`, {
20
+ method: 'POST',
21
+ headers: {
22
+ 'Content-Type': 'application/json',
23
+ Authorization: `Bearer ${session.access_token}`,
24
+ },
25
+ body: JSON.stringify(input),
26
+ });
27
+ if (!response.ok) {
28
+ if (response.status === 403) {
29
+ throw new Error('Member role required for AI features.');
30
+ }
31
+ if (response.status === 429) {
32
+ throw new Error('Rate limit exceeded. Try again later.');
33
+ }
34
+ throw new Error(`AI classification failed: ${response.statusText}`);
35
+ }
36
+ return response.json();
37
+ }
38
+ //# sourceMappingURL=ai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.js","sourceRoot":"","sources":["../../src/lib/ai.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA+BH,iFAAiF;AAEjF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAwB,EACxB,KAAyB;IAEzB,yCAAyC;IACzC,MAAM,EACJ,IAAI,EAAE,EAAE,OAAO,EAAE,GAClB,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;IACrC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,sBAAsB,CAAC;IAEzE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,wBAAwB,EAAE;QAC/D,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,OAAO,CAAC,YAAY,EAAE;SAChD;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;KAC5B,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,6BAA6B,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAkC,CAAC;AACzD,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { SupabaseClient } from '@supabase/supabase-js';
2
+ export interface TemperatureRow {
3
+ roast_id: number;
4
+ time_seconds: number;
5
+ bean_temp?: number | null;
6
+ environmental_temp?: number | null;
7
+ ambient_temp?: number | null;
8
+ ror_bean_temp?: number | null;
9
+ data_source: string;
10
+ }
11
+ export interface EventRow {
12
+ roast_id: number;
13
+ time_seconds: number;
14
+ event_type: number;
15
+ event_value: string | null;
16
+ event_string: string;
17
+ category: string;
18
+ subcategory: string;
19
+ user_generated: boolean;
20
+ automatic: boolean;
21
+ notes?: string;
22
+ }
23
+ export declare const BATCH_SIZE = 100;
24
+ /**
25
+ * Clear existing roast data scoped to artisan_import source.
26
+ * Deletes temperature rows by data_source and event rows by category.
27
+ */
28
+ export declare function clearRoastData(supabase: SupabaseClient, roastId: number, source: 'artisan_import' | 'live'): Promise<void>;
29
+ /**
30
+ * Batch-insert temperature rows into roast_temperatures.
31
+ */
32
+ export declare function insertTemperatures(supabase: SupabaseClient, entries: TemperatureRow[]): Promise<void>;
33
+ /**
34
+ * Batch-insert event rows into roast_events.
35
+ */
36
+ export declare function insertEvents(supabase: SupabaseClient, entries: EventRow[]): Promise<void>;
37
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../../src/lib/artisan/db.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID,eAAO,MAAM,UAAU,MAAM,CAAC;AAI9B;;;GAGG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,gBAAgB,GAAG,MAAM,GAChC,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,cAAc,EAAE,GACxB,OAAO,CAAC,IAAI,CAAC,CASf;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAS/F"}
@@ -0,0 +1,51 @@
1
+ // ── Constants ─────────────────────────────────────────────────────────────────
2
+ export const BATCH_SIZE = 100;
3
+ // ── Functions ─────────────────────────────────────────────────────────────────
4
+ /**
5
+ * Clear existing roast data scoped to artisan_import source.
6
+ * Deletes temperature rows by data_source and event rows by category.
7
+ */
8
+ export async function clearRoastData(supabase, roastId, source) {
9
+ await supabase
10
+ .from('roast_temperatures')
11
+ .delete()
12
+ .eq('roast_id', roastId)
13
+ .eq('data_source', source);
14
+ if (source === 'artisan_import') {
15
+ await supabase
16
+ .from('roast_events')
17
+ .delete()
18
+ .eq('roast_id', roastId)
19
+ .in('category', ['milestone', 'control', 'machine']);
20
+ }
21
+ else {
22
+ await supabase.from('roast_events').delete().eq('roast_id', roastId);
23
+ }
24
+ }
25
+ /**
26
+ * Batch-insert temperature rows into roast_temperatures.
27
+ */
28
+ export async function insertTemperatures(supabase, entries) {
29
+ for (let i = 0; i < entries.length; i += BATCH_SIZE) {
30
+ const batch = entries.slice(i, i + BATCH_SIZE);
31
+ const { error } = await supabase.from('roast_temperatures').insert(batch);
32
+ if (error) {
33
+ console.error('Error inserting temperature batch:', error);
34
+ throw error;
35
+ }
36
+ }
37
+ }
38
+ /**
39
+ * Batch-insert event rows into roast_events.
40
+ */
41
+ export async function insertEvents(supabase, entries) {
42
+ for (let i = 0; i < entries.length; i += BATCH_SIZE) {
43
+ const batch = entries.slice(i, i + BATCH_SIZE);
44
+ const { error } = await supabase.from('roast_events').insert(batch);
45
+ if (error) {
46
+ console.error('Error inserting event batch:', error);
47
+ throw error;
48
+ }
49
+ }
50
+ }
51
+ //# sourceMappingURL=db.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../../src/lib/artisan/db.ts"],"names":[],"mappings":"AA2BA,iFAAiF;AAEjF,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,CAAC;AAE9B,iFAAiF;AAEjF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,QAAwB,EACxB,OAAe,EACf,MAAiC;IAEjC,MAAM,QAAQ;SACX,IAAI,CAAC,oBAAoB,CAAC;SAC1B,MAAM,EAAE;SACR,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC;SACvB,EAAE,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAE7B,IAAI,MAAM,KAAK,gBAAgB,EAAE,CAAC;QAChC,MAAM,QAAQ;aACX,IAAI,CAAC,cAAc,CAAC;aACpB,MAAM,EAAE;aACR,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC;aACvB,EAAE,CAAC,UAAU,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;IACzD,CAAC;SAAM,CAAC;QACN,MAAM,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACvE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAwB,EACxB,OAAyB;IAEzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC;QAC/C,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1E,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,KAAK,CAAC,CAAC;YAC3D,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAwB,EAAE,OAAmB;IAC9E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC;QAC/C,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACpE,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;YACrD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { SupabaseClient } from '@supabase/supabase-js';
2
+ import type { ArtisanRoastData, MilestoneData, ProcessedRoastData } from './types.js';
3
+ export interface ArtisanImportResult {
4
+ success: boolean;
5
+ message: string;
6
+ milestones: MilestoneData;
7
+ phases: ProcessedRoastData['phases'];
8
+ total_time: number;
9
+ temperature_unit: 'F' | 'C';
10
+ milestone_events: number;
11
+ control_events: number;
12
+ }
13
+ export declare function parseArtisanFile(fileContent: string, fileName: string): Promise<ArtisanRoastData>;
14
+ export declare function transformArtisanData(parsedData: ArtisanRoastData, roastId: number): ProcessedRoastData;
15
+ export declare function importArtisanData(supabase: SupabaseClient, roastId: number, userId: string, fileContent: string, fileName: string, fileSize?: number): Promise<ArtisanImportResult>;
16
+ //# sourceMappingURL=import.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../../src/lib/artisan/import.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAMtF,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,aAAa,CAAC;IAC1B,MAAM,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,GAAG,GAAG,GAAG,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;CACxB;AAGD,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,gBAAgB,CAAC,CA8B3B;AAqCD,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,gBAAgB,EAC5B,OAAO,EAAE,MAAM,GACd,kBAAkB,CAkRpB;AAGD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,mBAAmB,CAAC,CA2J9B"}