@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.
- 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/config.d.ts +7 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +82 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/inventory.d.ts +2 -25
- package/dist/commands/inventory.d.ts.map +1 -1
- package/dist/commands/inventory.js +109 -149
- 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 +445 -126
- 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 +100 -112
- 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 +93 -116
- package/dist/commands/tasting.js.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/ai.d.ts +36 -0
- package/dist/lib/ai.d.ts.map +1 -0
- package/dist/lib/ai.js +38 -0
- package/dist/lib/ai.js.map +1 -0
- 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 +26 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +59 -0
- package/dist/lib/config.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/interactive/forms.d.ts +33 -0
- package/dist/lib/interactive/forms.d.ts.map +1 -0
- package/dist/lib/interactive/forms.js +139 -0
- package/dist/lib/interactive/forms.js.map +1 -0
- package/dist/lib/interactive/watch.d.ts +66 -0
- package/dist/lib/interactive/watch.d.ts.map +1 -0
- package/dist/lib/interactive/watch.js +494 -0
- package/dist/lib/interactive/watch.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 +15 -2
|
@@ -1,60 +1,8 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*/
|
|
7
|
-
export declare function sanitizeFilterValue(value: string): string;
|
|
8
|
-
export interface CatalogItem {
|
|
9
|
-
id: number;
|
|
10
|
-
name: string | null;
|
|
11
|
-
source: string | null;
|
|
12
|
-
continent: string | null;
|
|
13
|
-
country: string | null;
|
|
14
|
-
region: string | null;
|
|
15
|
-
processing: string | null;
|
|
16
|
-
drying_method: string | null;
|
|
17
|
-
cultivar_detail: string | null;
|
|
18
|
-
grade: string | null;
|
|
19
|
-
appearance: string | null;
|
|
20
|
-
type: string | null;
|
|
21
|
-
description_short: string | null;
|
|
22
|
-
description_long: string | null;
|
|
23
|
-
farm_notes: string | null;
|
|
24
|
-
cupping_notes: string | null;
|
|
25
|
-
ai_description: string | null;
|
|
26
|
-
roast_recs: string | null;
|
|
27
|
-
cost_lb: number | null;
|
|
28
|
-
lot_size: string | null;
|
|
29
|
-
bag_size: string | null;
|
|
30
|
-
score_value: number | null;
|
|
31
|
-
stocked: boolean | null;
|
|
32
|
-
stocked_date: string | null;
|
|
33
|
-
unstocked_date: string | null;
|
|
34
|
-
arrival_date: string | null;
|
|
35
|
-
last_updated: string | null;
|
|
36
|
-
public_coffee: boolean | null;
|
|
37
|
-
wholesale: boolean | null;
|
|
38
|
-
price_tiers: Array<{
|
|
39
|
-
min_lbs: number;
|
|
40
|
-
price: number;
|
|
41
|
-
}> | null;
|
|
42
|
-
}
|
|
43
|
-
export interface CatalogStats {
|
|
44
|
-
total: number;
|
|
45
|
-
stocked: number;
|
|
46
|
-
byOrigin: Record<string, number>;
|
|
47
|
-
avgPricePerLb: number | null;
|
|
48
|
-
priceRange: {
|
|
49
|
-
min: number | null;
|
|
50
|
-
max: number | null;
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Aggregate stats from an array of catalog items.
|
|
55
|
-
* Pure function — no I/O, safe to unit test.
|
|
56
|
-
*/
|
|
57
|
-
export declare function computeCatalogStats(items: CatalogItem[]): CatalogStats;
|
|
2
|
+
import { computeCatalogStats, sanitizeFilterValue } from '../lib/catalog.js';
|
|
3
|
+
import type { CatalogItem, CatalogStats } from '../lib/catalog.js';
|
|
4
|
+
export type { CatalogItem, CatalogStats };
|
|
5
|
+
export { sanitizeFilterValue, computeCatalogStats };
|
|
58
6
|
/**
|
|
59
7
|
* `purvey catalog` — Browse the public coffee catalog.
|
|
60
8
|
* The coffee_catalog table is publicly readable; no auth required.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/commands/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/commands/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAIL,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAInE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,CAAC;AAIpD;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAmE7C"}
|
package/dist/commands/catalog.js
CHANGED
|
@@ -2,37 +2,8 @@ import { Command } from 'commander';
|
|
|
2
2
|
import { createAnonClient } from '../lib/supabase.js';
|
|
3
3
|
import { outputData, info } from '../lib/output.js';
|
|
4
4
|
import { withErrorHandling } from '../lib/errors.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* Strip PostgREST special characters from user-supplied filter values.
|
|
8
|
-
* Prevents injection into .or() filter strings where values are interpolated directly.
|
|
9
|
-
* Removes: ( ) , . * % that have meaning in PostgREST filter syntax.
|
|
10
|
-
*/
|
|
11
|
-
export function sanitizeFilterValue(value) {
|
|
12
|
-
return value.replace(/[(),.*]/g, '');
|
|
13
|
-
}
|
|
14
|
-
// ─── Pure logic (exported for unit testing) ───────────────────────────────────
|
|
15
|
-
/**
|
|
16
|
-
* Aggregate stats from an array of catalog items.
|
|
17
|
-
* Pure function — no I/O, safe to unit test.
|
|
18
|
-
*/
|
|
19
|
-
export function computeCatalogStats(items) {
|
|
20
|
-
const stocked = items.filter((i) => i.stocked === true).length;
|
|
21
|
-
const byOrigin = {};
|
|
22
|
-
for (const item of items) {
|
|
23
|
-
const key = item.country ?? item.continent ?? 'Unknown';
|
|
24
|
-
byOrigin[key] = (byOrigin[key] ?? 0) + 1;
|
|
25
|
-
}
|
|
26
|
-
const prices = items.map((i) => i.cost_lb).filter((p) => p !== null);
|
|
27
|
-
const avgPricePerLb = prices.length > 0
|
|
28
|
-
? Math.round((prices.reduce((a, b) => a + b, 0) / prices.length) * 100) / 100
|
|
29
|
-
: null;
|
|
30
|
-
const priceRange = {
|
|
31
|
-
min: prices.length > 0 ? Math.min(...prices) : null,
|
|
32
|
-
max: prices.length > 0 ? Math.max(...prices) : null,
|
|
33
|
-
};
|
|
34
|
-
return { total: items.length, stocked, byOrigin, avgPricePerLb, priceRange };
|
|
35
|
-
}
|
|
5
|
+
import { searchCatalog, getCatalog, getCatalogStats, computeCatalogStats, sanitizeFilterValue, } from '../lib/catalog.js';
|
|
6
|
+
export { sanitizeFilterValue, computeCatalogStats };
|
|
36
7
|
// ─── Command builder ──────────────────────────────────────────────────────────
|
|
37
8
|
/**
|
|
38
9
|
* `purvey catalog` — Browse the public coffee catalog.
|
|
@@ -54,43 +25,16 @@ export function buildCatalogCommand() {
|
|
|
54
25
|
.action(withErrorHandling(async (opts, cmd) => {
|
|
55
26
|
const globalOpts = cmd.optsWithGlobals();
|
|
56
27
|
const supabase = createAnonClient();
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
if (opts.priceMax !== undefined) {
|
|
69
|
-
query = query.lte('cost_lb', parseFloat(opts.priceMax));
|
|
70
|
-
}
|
|
71
|
-
if (opts.flavor) {
|
|
72
|
-
const keywords = opts.flavor
|
|
73
|
-
.split(',')
|
|
74
|
-
.map((k) => sanitizeFilterValue(k.trim()))
|
|
75
|
-
.filter(Boolean);
|
|
76
|
-
const flavorFilters = keywords
|
|
77
|
-
.flatMap((kw) => [
|
|
78
|
-
`description_short.ilike.%${kw}%`,
|
|
79
|
-
`description_long.ilike.%${kw}%`,
|
|
80
|
-
`cupping_notes.ilike.%${kw}%`,
|
|
81
|
-
`farm_notes.ilike.%${kw}%`,
|
|
82
|
-
])
|
|
83
|
-
.join(',');
|
|
84
|
-
query = query.or(flavorFilters);
|
|
85
|
-
}
|
|
86
|
-
if (opts.stocked) {
|
|
87
|
-
query = query.eq('stocked', true);
|
|
88
|
-
}
|
|
89
|
-
const limit = Math.max(1, parseInt(opts.limit, 10));
|
|
90
|
-
const { data, error } = await query.limit(limit);
|
|
91
|
-
if (error)
|
|
92
|
-
throw error;
|
|
93
|
-
if (!data || data.length === 0) {
|
|
28
|
+
const data = await searchCatalog(supabase, {
|
|
29
|
+
origin: opts.origin,
|
|
30
|
+
process: opts.process,
|
|
31
|
+
priceMin: opts.priceMin !== undefined ? parseFloat(opts.priceMin) : undefined,
|
|
32
|
+
priceMax: opts.priceMax !== undefined ? parseFloat(opts.priceMax) : undefined,
|
|
33
|
+
flavor: opts.flavor,
|
|
34
|
+
stocked: opts.stocked ? true : undefined,
|
|
35
|
+
limit: Math.max(1, parseInt(opts.limit, 10)),
|
|
36
|
+
});
|
|
37
|
+
if (data.length === 0) {
|
|
94
38
|
info('No coffees found matching your criteria.');
|
|
95
39
|
return;
|
|
96
40
|
}
|
|
@@ -103,13 +47,7 @@ export function buildCatalogCommand() {
|
|
|
103
47
|
.action(withErrorHandling(async (id, _opts, cmd) => {
|
|
104
48
|
const globalOpts = cmd.optsWithGlobals();
|
|
105
49
|
const supabase = createAnonClient();
|
|
106
|
-
const
|
|
107
|
-
.from('coffee_catalog')
|
|
108
|
-
.select('*')
|
|
109
|
-
.eq('id', parseInt(id, 10))
|
|
110
|
-
.single();
|
|
111
|
-
if (error)
|
|
112
|
-
throw error;
|
|
50
|
+
const data = await getCatalog(supabase, parseInt(id, 10));
|
|
113
51
|
outputData(data, globalOpts);
|
|
114
52
|
}));
|
|
115
53
|
// ── catalog stats ─────────────────────────────────────────────────────────
|
|
@@ -119,12 +57,7 @@ export function buildCatalogCommand() {
|
|
|
119
57
|
.action(withErrorHandling(async (_opts, cmd) => {
|
|
120
58
|
const globalOpts = cmd.optsWithGlobals();
|
|
121
59
|
const supabase = createAnonClient();
|
|
122
|
-
const
|
|
123
|
-
.from('coffee_catalog')
|
|
124
|
-
.select('id, country, continent, cost_lb, stocked');
|
|
125
|
-
if (error)
|
|
126
|
-
throw error;
|
|
127
|
-
const stats = computeCatalogStats((data ?? []));
|
|
60
|
+
const stats = await getCatalogStats(supabase);
|
|
128
61
|
outputData(stats, globalOpts);
|
|
129
62
|
}));
|
|
130
63
|
return catalog;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/commands/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/commands/catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAoG5C"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { withErrorHandling, PrvrsError } from '../lib/errors.js';
|
|
3
|
+
import { readConfig, writeConfig, getConfigValue, setConfigValue, isValidConfigKey, } from '../lib/config.js';
|
|
4
|
+
import { success, info } from '../lib/output.js';
|
|
5
|
+
// ─── Command builder ──────────────────────────────────────────────────────────
|
|
6
|
+
/**
|
|
7
|
+
* `purvey config` — Manage purvey CLI settings.
|
|
8
|
+
* Config is stored in ~/.config/purvey/config.json.
|
|
9
|
+
*/
|
|
10
|
+
export function buildConfigCommand() {
|
|
11
|
+
const config = new Command('config').description('Manage purvey CLI settings');
|
|
12
|
+
// ── config list ───────────────────────────────────────────────────────────
|
|
13
|
+
config
|
|
14
|
+
.command('list')
|
|
15
|
+
.description('Show all configuration values')
|
|
16
|
+
.action(withErrorHandling(async () => {
|
|
17
|
+
const cfg = await readConfig();
|
|
18
|
+
const keys = Object.keys(cfg);
|
|
19
|
+
if (keys.length === 0) {
|
|
20
|
+
info('No config values set. Use `purvey config set <key> <value>` to configure.');
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
console.log('');
|
|
24
|
+
for (const key of keys) {
|
|
25
|
+
console.log(` ${key} = ${String(cfg[key])}`);
|
|
26
|
+
}
|
|
27
|
+
console.log('');
|
|
28
|
+
}));
|
|
29
|
+
// ── config get <key> ──────────────────────────────────────────────────────
|
|
30
|
+
config
|
|
31
|
+
.command('get <key>')
|
|
32
|
+
.description('Get a single configuration value')
|
|
33
|
+
.action(withErrorHandling(async (key) => {
|
|
34
|
+
if (!isValidConfigKey(key)) {
|
|
35
|
+
throw new PrvrsError('INVALID_ARGUMENT', `Unknown config key: "${key}". Valid keys: form-mode.`);
|
|
36
|
+
}
|
|
37
|
+
const value = await getConfigValue(key);
|
|
38
|
+
if (value === undefined) {
|
|
39
|
+
info(`${key} is not set.`);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
console.log(value);
|
|
43
|
+
}
|
|
44
|
+
}));
|
|
45
|
+
// ── config set <key> <value> ──────────────────────────────────────────────
|
|
46
|
+
config
|
|
47
|
+
.command('set <key> <value>')
|
|
48
|
+
.description('Set a configuration value')
|
|
49
|
+
.addHelpText('after', `
|
|
50
|
+
Supported keys:
|
|
51
|
+
form-mode true/false — when true, write commands auto-enter form mode
|
|
52
|
+
if required args are missing
|
|
53
|
+
|
|
54
|
+
Examples:
|
|
55
|
+
$ purvey config set form-mode true
|
|
56
|
+
$ purvey config set form-mode false
|
|
57
|
+
$ purvey config get form-mode
|
|
58
|
+
$ purvey config list
|
|
59
|
+
`)
|
|
60
|
+
.action(withErrorHandling(async (key, value) => {
|
|
61
|
+
if (!isValidConfigKey(key)) {
|
|
62
|
+
throw new PrvrsError('INVALID_ARGUMENT', `Unknown config key: "${key}". Valid keys: form-mode.`);
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
await setConfigValue(key, value);
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
throw new PrvrsError('INVALID_ARGUMENT', err instanceof Error ? err.message : String(err));
|
|
69
|
+
}
|
|
70
|
+
success(`Config updated: ${key} = ${value}`);
|
|
71
|
+
}));
|
|
72
|
+
// ── config reset ──────────────────────────────────────────────────────────
|
|
73
|
+
config
|
|
74
|
+
.command('reset')
|
|
75
|
+
.description('Reset all configuration to defaults')
|
|
76
|
+
.action(withErrorHandling(async () => {
|
|
77
|
+
await writeConfig({});
|
|
78
|
+
success('Config reset to defaults.');
|
|
79
|
+
}));
|
|
80
|
+
return config;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,29 +1,6 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
rank: number | null;
|
|
5
|
-
notes: string | null;
|
|
6
|
-
cupping_notes: string | null;
|
|
7
|
-
purchase_date: string | null;
|
|
8
|
-
purchased_qty_lbs: number | null;
|
|
9
|
-
bean_cost: number | null;
|
|
10
|
-
tax_ship_cost: number | null;
|
|
11
|
-
last_updated: string;
|
|
12
|
-
user: string;
|
|
13
|
-
catalog_id: number | null;
|
|
14
|
-
stocked: boolean | null;
|
|
15
|
-
coffee_catalog: {
|
|
16
|
-
id: number;
|
|
17
|
-
name: string | null;
|
|
18
|
-
source: string | null;
|
|
19
|
-
country: string | null;
|
|
20
|
-
region: string | null;
|
|
21
|
-
processing: string | null;
|
|
22
|
-
cost_lb: number | null;
|
|
23
|
-
description_short: string | null;
|
|
24
|
-
stocked: boolean | null;
|
|
25
|
-
} | null;
|
|
26
|
-
}
|
|
2
|
+
import type { InventoryItem } from '../lib/inventory.js';
|
|
3
|
+
export type { InventoryItem };
|
|
27
4
|
/**
|
|
28
5
|
* `purvey inventory` — Manage your green coffee inventory.
|
|
29
6
|
* Requires authentication.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../../src/commands/inventory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../../src/commands/inventory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKzD,YAAY,EAAE,aAAa,EAAE,CAAC;AAI9B;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAyT/C"}
|