@badgie/crm-cli 0.2.2 → 0.3.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/AGENTS.md +3 -2
- package/dist/bin.js +1 -25
- package/dist/bin.js.map +1 -1
- package/dist/commands/clients.js +15 -8
- package/dist/commands/clients.js.map +1 -1
- package/dist/commands/directory.js +38 -12
- package/dist/commands/directory.js.map +1 -1
- package/dist/commands/finance.js +17 -12
- package/dist/commands/finance.js.map +1 -1
- package/dist/commands/leads.js +108 -61
- package/dist/commands/leads.js.map +1 -1
- package/dist/commands/outbound.js +85 -28
- package/dist/commands/outbound.js.map +1 -1
- package/dist/commands/tasks.js +202 -61
- package/dist/commands/tasks.js.map +1 -1
- package/dist/commands/top-clients.js +45 -15
- package/dist/commands/top-clients.js.map +1 -1
- package/dist/core/bulk.js +68 -0
- package/dist/core/bulk.js.map +1 -0
- package/dist/core/compat.js +25 -0
- package/dist/core/compat.js.map +1 -0
- package/dist/core/errors.js +105 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/resolve.js +80 -0
- package/dist/core/resolve.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bulk.js","sourceRoot":"","sources":["../../src/core/bulk.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Backward-compatibility shim for the v0.3.0 positional arg flip.
|
|
2
|
+
// Old: `set-status <id> <verb>` / `assign <id> <member>`
|
|
3
|
+
// New: `set-status <verb> [id]` / `assign <member> [id]` (so bulk can omit id)
|
|
4
|
+
//
|
|
5
|
+
// Muscle memory is strong — if we detect the old order at runtime, swap silently
|
|
6
|
+
// and print a one-line deprecation to stderr. Keeps existing scripts working.
|
|
7
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8
|
+
// swap the two fields if it looks like the user typed the old `<id> <verb>` order.
|
|
9
|
+
// Heuristic: fieldA (the new verb slot) looks like a UUID AND fieldB (the new id
|
|
10
|
+
// slot) exists but is NOT a UUID. Under the new contract, fieldA is never a UUID
|
|
11
|
+
// (status/member/statusId are names or team_member refs that resolve by name),
|
|
12
|
+
// so a UUID there is a strong signal of the old order.
|
|
13
|
+
export function swapIfLegacyOrder(args, verbField, idField, cmd) {
|
|
14
|
+
const verb = args[verbField];
|
|
15
|
+
const id = args[idField];
|
|
16
|
+
if (!verb || !UUID_RE.test(verb))
|
|
17
|
+
return;
|
|
18
|
+
if (!id || UUID_RE.test(id))
|
|
19
|
+
return;
|
|
20
|
+
// likely legacy: <uuid> <name-or-verb>
|
|
21
|
+
args[verbField] = id;
|
|
22
|
+
args[idField] = verb;
|
|
23
|
+
process.stderr.write(`⚠ v0.3.0: ${cmd} now takes <${verbField}> [${idField}] (old order was <${idField}> <${verbField}>). Auto-swapping; please update your scripts to the new order.\n`);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=compat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compat.js","sourceRoot":"","sources":["../../src/core/compat.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,yDAAyD;AACzD,+EAA+E;AAC/E,EAAE;AACF,iFAAiF;AACjF,8EAA8E;AAE9E,MAAM,OAAO,GAAG,iEAAiE,CAAA;AAEjF,mFAAmF;AACnF,iFAAiF;AACjF,iFAAiF;AACjF,+EAA+E;AAC/E,uDAAuD;AACvD,MAAM,UAAU,iBAAiB,CAC/B,IAAwC,EACxC,SAAiB,EACjB,OAAe,EACf,GAAW;IAEX,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,CAAA;IAC5B,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,CAAA;IACxB,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAM;IACxC,IAAI,CAAC,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAAE,OAAM;IACnC,uCAAuC;IACvC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAA;IACpB,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;IACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,cAAc,GAAG,eAAe,SAAS,MAAM,OAAO,qBAAqB,OAAO,MAAM,SAAS,mEAAmE,CACrK,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// Rich error formatter for Supabase / PostgrestError / HTTP errors.
|
|
2
|
+
// Lives here (not bin.ts) so handlers can reuse it for per-row bulk error rendering.
|
|
3
|
+
const PG_HINTS = {
|
|
4
|
+
'23502': (c) => `missing required field${c ? `: --${toKebab(c)}` : ''}`,
|
|
5
|
+
'23503': (c) => `${c ?? 'reference'} points to a row that doesn't exist; verify the ID`,
|
|
6
|
+
'23505': (c) => `duplicate value${c ? ` for ${c}` : ''}; that record already exists`,
|
|
7
|
+
'23514': (c) => `value not allowed${c ? ` for ${c}` : ''}; check the column's check constraint / enum values`,
|
|
8
|
+
'22P02': (c) => `wrong data type${c ? ` for ${c}` : ''} (e.g. sending text where the column expects integer)`,
|
|
9
|
+
'42501': () => `permission denied — RLS policy rejected this. Verify auth with \`badgie-crm whoami\`, or set BADGIE_SERVICE_KEY for admin scripts`,
|
|
10
|
+
'42P01': () => `table not found — likely a typo in the query`,
|
|
11
|
+
'42703': () => `column not found — likely a typo`,
|
|
12
|
+
PGRST301: () => `JWT expired. Run \`badgie-crm login\` again`,
|
|
13
|
+
PGRST116: () => `no matching row (or more than one). If you queried by name, the value may be ambiguous`,
|
|
14
|
+
};
|
|
15
|
+
export function formatError(err) {
|
|
16
|
+
if (err instanceof Error) {
|
|
17
|
+
const hint = messageHint(err.message);
|
|
18
|
+
return hint ? `${err.message} | hint: ${hint}` : err.message;
|
|
19
|
+
}
|
|
20
|
+
if (err && typeof err === 'object') {
|
|
21
|
+
const e = err;
|
|
22
|
+
const parts = [];
|
|
23
|
+
const message = typeof e.message === 'string' ? e.message : '';
|
|
24
|
+
const details = typeof e.details === 'string' ? e.details : '';
|
|
25
|
+
const hintField = typeof e.hint === 'string' ? e.hint : '';
|
|
26
|
+
const code = typeof e.code === 'string' ? e.code : '';
|
|
27
|
+
if (message)
|
|
28
|
+
parts.push(message);
|
|
29
|
+
if (details)
|
|
30
|
+
parts.push(`details: ${details}`);
|
|
31
|
+
const hint = deriveHint(code, message, details) ?? hintField;
|
|
32
|
+
if (hint)
|
|
33
|
+
parts.push(`hint: ${hint}`);
|
|
34
|
+
if (code)
|
|
35
|
+
parts.push(`code: ${code}`);
|
|
36
|
+
if (parts.length > 0)
|
|
37
|
+
return parts.join(' | ');
|
|
38
|
+
try {
|
|
39
|
+
return JSON.stringify(err);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return String(err);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return String(err);
|
|
46
|
+
}
|
|
47
|
+
// One-line variant for bulk result tables: drop hints and details.
|
|
48
|
+
export function shortError(err) {
|
|
49
|
+
if (err instanceof Error)
|
|
50
|
+
return err.message;
|
|
51
|
+
if (err && typeof err === 'object') {
|
|
52
|
+
const e = err;
|
|
53
|
+
if (typeof e.message === 'string' && e.message)
|
|
54
|
+
return e.message;
|
|
55
|
+
try {
|
|
56
|
+
return JSON.stringify(err);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return String(err);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return String(err);
|
|
63
|
+
}
|
|
64
|
+
function deriveHint(code, message, details) {
|
|
65
|
+
const col = extractColumn(message) ?? extractColumn(details);
|
|
66
|
+
if (code && PG_HINTS[code])
|
|
67
|
+
return PG_HINTS[code](col);
|
|
68
|
+
return messageHint(`${message} ${details}`);
|
|
69
|
+
}
|
|
70
|
+
function messageHint(text) {
|
|
71
|
+
const lower = text.toLowerCase();
|
|
72
|
+
if (lower.includes('jwt') && (lower.includes('expired') || lower.includes('invalid'))) {
|
|
73
|
+
return PG_HINTS.PGRST301();
|
|
74
|
+
}
|
|
75
|
+
if (lower.includes('invalid api key') || lower.includes('401 unauthorized')) {
|
|
76
|
+
return 'not authenticated. Run `badgie-crm login` or set BADGIE_SERVICE_KEY';
|
|
77
|
+
}
|
|
78
|
+
if (lower.includes('fetch failed') || lower.includes('enotfound') || lower.includes('econnrefused')) {
|
|
79
|
+
return 'network / DNS error. Check internet and BADGIE_SUPABASE_URL';
|
|
80
|
+
}
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
// Parses column names from Postgres error text. Handles:
|
|
84
|
+
// null value in column "foo" of relation ...
|
|
85
|
+
// Key (foo)=(bar) is not present in table ...
|
|
86
|
+
// column "foo" of relation ...
|
|
87
|
+
// duplicate key value violates unique constraint "tbl_foo_key"
|
|
88
|
+
function extractColumn(text) {
|
|
89
|
+
if (!text)
|
|
90
|
+
return undefined;
|
|
91
|
+
const quoted = /column "([a-z0-9_]+)"/i.exec(text);
|
|
92
|
+
if (quoted)
|
|
93
|
+
return quoted[1];
|
|
94
|
+
const keyed = /Key \(([a-z0-9_]+)\)=/i.exec(text);
|
|
95
|
+
if (keyed)
|
|
96
|
+
return keyed[1];
|
|
97
|
+
const inserting = /inserting NULL into column "?([a-z0-9_]+)"?/i.exec(text);
|
|
98
|
+
if (inserting)
|
|
99
|
+
return inserting[1];
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
function toKebab(s) {
|
|
103
|
+
return s.replace(/_/g, '-').toLowerCase();
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2
|
+
const RESOLVERS = {
|
|
3
|
+
team_member: {
|
|
4
|
+
table: 'team_members',
|
|
5
|
+
searchColumns: ['full_name', 'email'],
|
|
6
|
+
displayColumn: 'full_name',
|
|
7
|
+
suggest: (v) => `badgie-crm team list --search "${v}"`,
|
|
8
|
+
},
|
|
9
|
+
client: {
|
|
10
|
+
table: 'clients',
|
|
11
|
+
searchColumns: ['name', 'email'],
|
|
12
|
+
displayColumn: 'name',
|
|
13
|
+
suggest: (v) => `badgie-crm clients list --search "${v}"`,
|
|
14
|
+
},
|
|
15
|
+
lead: {
|
|
16
|
+
table: 'leads',
|
|
17
|
+
searchColumns: ['title'],
|
|
18
|
+
displayColumn: 'title',
|
|
19
|
+
suggest: (v) => `badgie-crm leads list --search "${v}"`,
|
|
20
|
+
},
|
|
21
|
+
lead_status: {
|
|
22
|
+
table: 'lead_statuses',
|
|
23
|
+
searchColumns: ['name'],
|
|
24
|
+
displayColumn: 'name',
|
|
25
|
+
suggest: () => `badgie-crm admin lead-statuses list`,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
// Cache lookups for the duration of a single CLI invocation so bulk operations
|
|
29
|
+
// don't hit the DB N times for the same name.
|
|
30
|
+
const cache = new Map();
|
|
31
|
+
export async function resolveRef(client, kind, value) {
|
|
32
|
+
if (UUID_RE.test(value))
|
|
33
|
+
return value;
|
|
34
|
+
const key = `${kind}:${value.toLowerCase()}`;
|
|
35
|
+
const hit = cache.get(key);
|
|
36
|
+
if (hit)
|
|
37
|
+
return hit;
|
|
38
|
+
const cfg = RESOLVERS[kind];
|
|
39
|
+
const escaped = value.replace(/[%,]/g, ' ').trim();
|
|
40
|
+
if (!escaped)
|
|
41
|
+
throw new Error(`Empty ${kind} reference`);
|
|
42
|
+
const orFilter = cfg.searchColumns.map((c) => `${c}.ilike.%${escaped}%`).join(',');
|
|
43
|
+
const { data, error } = await client
|
|
44
|
+
.from(cfg.table)
|
|
45
|
+
.select(`id, ${cfg.displayColumn}, ${cfg.searchColumns.join(', ')}`)
|
|
46
|
+
.or(orFilter)
|
|
47
|
+
.limit(6);
|
|
48
|
+
if (error)
|
|
49
|
+
throw error;
|
|
50
|
+
const rows = (data ?? []);
|
|
51
|
+
if (rows.length === 0) {
|
|
52
|
+
throw new Error(`No ${kind} matches "${value}". Try \`${cfg.suggest(value)}\` to list candidates.`);
|
|
53
|
+
}
|
|
54
|
+
// If there's an exact (case-insensitive) match on any search column, prefer it
|
|
55
|
+
// over ambiguity. Lets "Rita" win when there's also "Rita Perez" and "Rita L".
|
|
56
|
+
const lower = value.toLowerCase();
|
|
57
|
+
const exact = rows.filter((r) => cfg.searchColumns.some((c) => {
|
|
58
|
+
const v = r[c];
|
|
59
|
+
return typeof v === 'string' && v.toLowerCase() === lower;
|
|
60
|
+
}));
|
|
61
|
+
const finalRows = exact.length === 1 ? exact : rows;
|
|
62
|
+
if (finalRows.length > 1) {
|
|
63
|
+
const candidates = finalRows
|
|
64
|
+
.slice(0, 4)
|
|
65
|
+
.map((r) => ` ${r[cfg.displayColumn] ?? '(no name)'} (${r.id})`)
|
|
66
|
+
.join('\n');
|
|
67
|
+
throw new Error(`Ambiguous ${kind} "${value}" — ${finalRows.length} matches. Candidates:\n${candidates}\nUse the full name/email or paste the UUID.`);
|
|
68
|
+
}
|
|
69
|
+
const id = String(finalRows[0].id);
|
|
70
|
+
cache.set(key, id);
|
|
71
|
+
return id;
|
|
72
|
+
}
|
|
73
|
+
// Convenience wrapper: resolves only if the opts value is a non-empty string.
|
|
74
|
+
// Returns null when absent (mirroring what handlers want for nullable columns).
|
|
75
|
+
export async function maybeResolve(client, kind, value) {
|
|
76
|
+
if (typeof value !== 'string' || value.trim() === '')
|
|
77
|
+
return null;
|
|
78
|
+
return resolveRef(client, kind, value);
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/core/resolve.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED