@purveyors/cli 0.32.2 → 0.33.1
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 +22 -27
- package/dist/commands/catalog.d.ts.map +1 -1
- package/dist/commands/catalog.js +23 -32
- package/dist/commands/catalog.js.map +1 -1
- package/dist/commands/inventory.d.ts.map +1 -1
- package/dist/commands/inventory.js +46 -36
- package/dist/commands/inventory.js.map +1 -1
- package/dist/commands/market.d.ts.map +1 -1
- package/dist/commands/market.js +9 -6
- package/dist/commands/market.js.map +1 -1
- package/dist/commands/price-index.d.ts.map +1 -1
- package/dist/commands/price-index.js +9 -6
- package/dist/commands/price-index.js.map +1 -1
- package/dist/commands/procurement.d.ts.map +1 -1
- package/dist/commands/procurement.js +9 -6
- package/dist/commands/procurement.js.map +1 -1
- package/dist/commands/roast.d.ts.map +1 -1
- package/dist/commands/roast.js +83 -83
- package/dist/commands/roast.js.map +1 -1
- package/dist/commands/sales.d.ts.map +1 -1
- package/dist/commands/sales.js +29 -30
- package/dist/commands/sales.js.map +1 -1
- package/dist/commands/tasting.d.ts.map +1 -1
- package/dist/commands/tasting.js +22 -16
- package/dist/commands/tasting.js.map +1 -1
- package/dist/lib/ai.d.ts +5 -43
- package/dist/lib/ai.d.ts.map +1 -1
- package/dist/lib/ai.js +4 -84
- package/dist/lib/ai.js.map +1 -1
- package/dist/lib/catalog.d.ts +8 -25
- package/dist/lib/catalog.d.ts.map +1 -1
- package/dist/lib/catalog.js +44 -129
- package/dist/lib/catalog.js.map +1 -1
- package/dist/lib/cherry.d.ts +46 -0
- package/dist/lib/cherry.d.ts.map +1 -0
- package/dist/lib/cherry.js +87 -0
- package/dist/lib/cherry.js.map +1 -0
- package/dist/lib/interactive/forms.d.ts.map +1 -1
- package/dist/lib/interactive/forms.js +16 -10
- package/dist/lib/interactive/forms.js.map +1 -1
- package/dist/lib/interactive/watch.js +1 -1
- package/dist/lib/interactive/watch.js.map +1 -1
- package/dist/lib/inventory.d.ts.map +1 -1
- package/dist/lib/inventory.js +11 -4
- package/dist/lib/inventory.js.map +1 -1
- package/dist/lib/manifest.d.ts +2 -0
- package/dist/lib/manifest.d.ts.map +1 -1
- package/dist/lib/manifest.js +39 -14
- package/dist/lib/manifest.js.map +1 -1
- package/dist/lib/market.d.ts.map +1 -1
- package/dist/lib/numeric-contracts.d.ts +24 -0
- package/dist/lib/numeric-contracts.d.ts.map +1 -0
- package/dist/lib/numeric-contracts.js +9 -0
- package/dist/lib/numeric-contracts.js.map +1 -0
- package/dist/lib/roast.d.ts.map +1 -1
- package/dist/lib/roast.js +21 -7
- package/dist/lib/roast.js.map +1 -1
- package/dist/lib/sales.d.ts.map +1 -1
- package/dist/lib/sales.js +7 -4
- package/dist/lib/sales.js.map +1 -1
- package/dist/lib/strict-number.d.ts +20 -0
- package/dist/lib/strict-number.d.ts.map +1 -0
- package/dist/lib/strict-number.js +41 -0
- package/dist/lib/strict-number.js.map +1 -0
- package/dist/lib/tasting.d.ts.map +1 -1
- package/dist/lib/tasting.js +6 -4
- package/dist/lib/tasting.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a user-supplied decimal number without accepting trailing garbage.
|
|
3
|
+
*
|
|
4
|
+
* `parseFloat` accepts values such as `12.5abc`; this parser requires the
|
|
5
|
+
* entire trimmed value to be a finite decimal number.
|
|
6
|
+
*/
|
|
7
|
+
export function parseStrictFiniteNumber(value) {
|
|
8
|
+
const trimmed = value.trim();
|
|
9
|
+
if (trimmed === '')
|
|
10
|
+
return Number.NaN;
|
|
11
|
+
if (!/^[+-]?(?:(?:\d+(?:\.\d*)?)|(?:\.\d+))(?:[eE][+-]?\d+)?$/.test(trimmed)) {
|
|
12
|
+
return Number.NaN;
|
|
13
|
+
}
|
|
14
|
+
const parsed = Number(trimmed);
|
|
15
|
+
return Number.isFinite(parsed) ? parsed : Number.NaN;
|
|
16
|
+
}
|
|
17
|
+
export const POSTGRES_INT4_MAX = 2_147_483_647;
|
|
18
|
+
/**
|
|
19
|
+
* Parse a user-supplied base-10 integer without accepting decimals, exponents,
|
|
20
|
+
* or trailing garbage. Bounds are inclusive.
|
|
21
|
+
*/
|
|
22
|
+
export function parseStrictInteger(value, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) {
|
|
23
|
+
const trimmed = value.trim();
|
|
24
|
+
if (!/^[+-]?\d+$/.test(trimmed))
|
|
25
|
+
return Number.NaN;
|
|
26
|
+
const parsed = Number(trimmed);
|
|
27
|
+
return Number.isSafeInteger(parsed) && parsed >= min && parsed <= max ? parsed : Number.NaN;
|
|
28
|
+
}
|
|
29
|
+
/** Parse a positive PostgreSQL int4 identifier. */
|
|
30
|
+
export function parseStrictInt4Id(value) {
|
|
31
|
+
return parseStrictInteger(value, 1, POSTGRES_INT4_MAX);
|
|
32
|
+
}
|
|
33
|
+
/** Parse a non-negative pagination offset. */
|
|
34
|
+
export function parseStrictOffset(value) {
|
|
35
|
+
return parseStrictInteger(value, 0, Number.MAX_SAFE_INTEGER);
|
|
36
|
+
}
|
|
37
|
+
/** Parse a positive integer count, optionally capped by its command contract. */
|
|
38
|
+
export function parseStrictPositiveCount(value, max = Number.MAX_SAFE_INTEGER) {
|
|
39
|
+
return parseStrictInteger(value, 1, max);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=strict-number.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strict-number.js","sourceRoot":"","sources":["../../src/lib/strict-number.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACnD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,KAAK,EAAE;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC;IACtC,IAAI,CAAC,yDAAyD,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7E,OAAO,MAAM,CAAC,GAAG,CAAC;IACpB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC/B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;AACvD,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAE/C;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,KAAa,EACb,GAAG,GAAG,MAAM,CAAC,gBAAgB,EAC7B,GAAG,GAAG,MAAM,CAAC,gBAAgB;IAE7B,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC;IAEnD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC/B,OAAO,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;AAC9F,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,kBAAkB,CAAC,KAAK,EAAE,CAAC,EAAE,iBAAiB,CAAC,CAAC;AACzD,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,kBAAkB,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAC/D,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,wBAAwB,CAAC,KAAa,EAAE,GAAG,GAAG,MAAM,CAAC,gBAAgB;IACnF,OAAO,kBAAkB,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tasting.d.ts","sourceRoot":"","sources":["../../src/lib/tasting.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,
|
|
1
|
+
{"version":3,"file":"tasting.d.ts","sourceRoot":"","sources":["../../src/lib/tasting.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAMtF,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;AAEzD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,gBAAgB,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,eAAO,MAAM,mBAAmB;;;;EAAuC,CAAC;AAExE,eAAO,MAAM,qBAAqB;;;;;;;iBAGhC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEzE,eAAO,MAAM,kBAAkB,aAAiC,CAAC;AAEjE,eAAO,MAAM,gBAAgB;;;;;;;;iBAQ3B,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAI/D,wDAAwD;AACxD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,mEAAmE;AACnE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CASnE;AAID;;;GAGG;AACH,wBAAsB,eAAe,CACnC,EAAE,EAAE,MAAM,EACV,MAAM,GAAE,aAAsB,GAC7B,OAAO,CAAC,WAAW,CAAC,CAQtB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,eAAe,EACtB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,aAAa,CAAC,CAQxB"}
|
package/dist/lib/tasting.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { PrvrsError } from './errors.js';
|
|
3
|
-
import { getInventory } from './inventory.js';
|
|
3
|
+
import { getInventory, getInventorySchema } from './inventory.js';
|
|
4
4
|
import { createParchmentClient, unwrapParchment } from './parchment.js';
|
|
5
|
+
import { POSTGRES_INT4_MAX, parseStrictInteger } from './strict-number.js';
|
|
5
6
|
// ─── Zod schemas ──────────────────────────────────────────────────────────────
|
|
6
7
|
export const tastingFilterSchema = z.enum(['user', 'supplier', 'both']);
|
|
7
8
|
export const getTastingNotesSchema = z.object({
|
|
8
|
-
bean_id: z.number().int().
|
|
9
|
+
bean_id: z.number().int().min(1).max(POSTGRES_INT4_MAX).describe('Required coffee bean ID'),
|
|
9
10
|
filter: tastingFilterSchema.default('both'),
|
|
10
11
|
});
|
|
11
12
|
export const cuppingScoreSchema = z.number().int().min(1).max(5);
|
|
@@ -25,8 +26,8 @@ export function isValidCuppingScore(value) {
|
|
|
25
26
|
}
|
|
26
27
|
/** Parse and validate a cupping score flag value (for CLI use). */
|
|
27
28
|
export function parseCuppingScore(raw, flag) {
|
|
28
|
-
const n =
|
|
29
|
-
if (
|
|
29
|
+
const n = parseStrictInteger(raw, 1, 5);
|
|
30
|
+
if (!Number.isFinite(n) || !isValidCuppingScore(n)) {
|
|
30
31
|
throw new PrvrsError('INVALID_ARGUMENT', `--${flag} must be an integer between 1 and 5 (got "${raw}").`);
|
|
31
32
|
}
|
|
32
33
|
return n;
|
|
@@ -46,6 +47,7 @@ export async function getTastingNotes(id, filter = 'both') {
|
|
|
46
47
|
* Rate an owned inventory lot through the canonical Parchment API.
|
|
47
48
|
*/
|
|
48
49
|
export async function rateCoffee(id, input, tokenOverride) {
|
|
50
|
+
getInventorySchema.parse({ id });
|
|
49
51
|
const parsed = rateCoffeeSchema.parse(input);
|
|
50
52
|
const client = await createParchmentClient('member', tokenOverride);
|
|
51
53
|
unwrapParchment(await client.tasting.rate(id, parsed), 'Tasting rate');
|
package/dist/lib/tasting.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tasting.js","sourceRoot":"","sources":["../../src/lib/tasting.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAsB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"tasting.js","sourceRoot":"","sources":["../../src/lib/tasting.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@purveyors/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.1",
|
|
4
4
|
"description": "The official CLI for purveyors.io — coffee intelligence from your terminal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"./lib": "./dist/lib/index.js",
|
|
17
17
|
"./manifest": "./dist/lib/manifest.js",
|
|
18
18
|
"./market": "./dist/lib/market.js",
|
|
19
|
+
"./cherry": "./dist/lib/cherry.js",
|
|
19
20
|
"./ai": "./dist/lib/ai.js"
|
|
20
21
|
},
|
|
21
22
|
"files": [
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
},
|
|
57
58
|
"dependencies": {
|
|
58
59
|
"@clack/prompts": "^1.1.0",
|
|
59
|
-
"@purveyors/sdk": "^0.11.
|
|
60
|
+
"@purveyors/sdk": "^0.11.1",
|
|
60
61
|
"chalk": "^5.4.1",
|
|
61
62
|
"commander": "^13.1.0",
|
|
62
63
|
"ora": "^8.2.0",
|