@badgie/crm-cli 0.1.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 (63) hide show
  1. package/AGENTS.md +91 -0
  2. package/README.md +136 -0
  3. package/dist/bin.js +149 -0
  4. package/dist/bin.js.map +1 -0
  5. package/dist/commands/admin.js +90 -0
  6. package/dist/commands/admin.js.map +1 -0
  7. package/dist/commands/clients.js +135 -0
  8. package/dist/commands/clients.js.map +1 -0
  9. package/dist/commands/directory.js +175 -0
  10. package/dist/commands/directory.js.map +1 -0
  11. package/dist/commands/docs.js +98 -0
  12. package/dist/commands/docs.js.map +1 -0
  13. package/dist/commands/finance.js +311 -0
  14. package/dist/commands/finance.js.map +1 -0
  15. package/dist/commands/intelligence.js +147 -0
  16. package/dist/commands/intelligence.js.map +1 -0
  17. package/dist/commands/leads-list.js +25 -0
  18. package/dist/commands/leads-list.js.map +1 -0
  19. package/dist/commands/leads.js +224 -0
  20. package/dist/commands/leads.js.map +1 -0
  21. package/dist/commands/login.js +11 -0
  22. package/dist/commands/login.js.map +1 -0
  23. package/dist/commands/logout.js +6 -0
  24. package/dist/commands/logout.js.map +1 -0
  25. package/dist/commands/marketing.js +135 -0
  26. package/dist/commands/marketing.js.map +1 -0
  27. package/dist/commands/operations.js +232 -0
  28. package/dist/commands/operations.js.map +1 -0
  29. package/dist/commands/outbound.js +172 -0
  30. package/dist/commands/outbound.js.map +1 -0
  31. package/dist/commands/query.js +189 -0
  32. package/dist/commands/query.js.map +1 -0
  33. package/dist/commands/search.js +71 -0
  34. package/dist/commands/search.js.map +1 -0
  35. package/dist/commands/tasks.js +239 -0
  36. package/dist/commands/tasks.js.map +1 -0
  37. package/dist/commands/top-clients.js +82 -0
  38. package/dist/commands/top-clients.js.map +1 -0
  39. package/dist/commands/webhooks.js +82 -0
  40. package/dist/commands/webhooks.js.map +1 -0
  41. package/dist/commands/welcome.js +81 -0
  42. package/dist/commands/welcome.js.map +1 -0
  43. package/dist/commands/whoami.js +16 -0
  44. package/dist/commands/whoami.js.map +1 -0
  45. package/dist/core/auth.js +107 -0
  46. package/dist/core/auth.js.map +1 -0
  47. package/dist/core/config.js +53 -0
  48. package/dist/core/config.js.map +1 -0
  49. package/dist/core/env.js +46 -0
  50. package/dist/core/env.js.map +1 -0
  51. package/dist/core/format.js +88 -0
  52. package/dist/core/format.js.map +1 -0
  53. package/dist/core/http.js +42 -0
  54. package/dist/core/http.js.map +1 -0
  55. package/dist/core/list-query.js +35 -0
  56. package/dist/core/list-query.js.map +1 -0
  57. package/dist/core/services/leads.js +41 -0
  58. package/dist/core/services/leads.js.map +1 -0
  59. package/dist/core/supabase.js +53 -0
  60. package/dist/core/supabase.js.map +1 -0
  61. package/dist/registry.js +2 -0
  62. package/dist/registry.js.map +1 -0
  63. package/package.json +57 -0
package/AGENTS.md ADDED
@@ -0,0 +1,91 @@
1
+ # AGENTS.md — `badgie-crm` para agentes IA
2
+
3
+ Este archivo es la guía canónica para que un agente (openclaw, Claude, Cursor, custom GPT…) use el CLI `badgie-crm` de forma segura y efectiva.
4
+
5
+ ## Qué es
6
+
7
+ CLI oficial del Badgie CRM. 70 comandos sobre Supabase. Instalación: ver `cli/README.md`.
8
+
9
+ ## Fuente de verdad (machine-readable)
10
+
11
+ ```bash
12
+ badgie-crm docs --json
13
+ ```
14
+
15
+ Devuelve el manifest completo: `{ version, commands: [{ command, path, summary, description, args, options, tags, examples }] }`. Cárgalo al inicio de cada sesión como tu catálogo de tools.
16
+
17
+ Para filtrar por módulo:
18
+ ```bash
19
+ badgie-crm docs finance --json
20
+ ```
21
+
22
+ ## Convenciones críticas
23
+
24
+ 1. **Salida**: JSON por defecto, parseable. Añade `--pretty` solo cuando quieras texto para un humano.
25
+ 2. **Tags por comando** (los lees en el manifest):
26
+ - `[read]` — consulta, seguro, idempotente.
27
+ - `[write]` — muta la DB. Confirmable pero no destructivo.
28
+ - `[destructive]` — irreversible (delete, wipes). **Pide confirmación antes**.
29
+ - `[http]` — requiere que la app Next esté arriba Y que el endpoint acepte Bearer token. Si falla, avisa al usuario antes de reintentar.
30
+ 3. **Exit code**: `0` = ok, `1` = error (mensaje en stderr).
31
+ 4. **Filtros ad-hoc**: si no hay flag ergonómico, usa `badgie-crm query <table> --where col:op:val` (ops: eq, neq, gt, gte, lt, lte, like, ilike, in, is, not). `--where` es repetible.
32
+
33
+ ## Patrón recomendado para agentes
34
+
35
+ 1. `badgie-crm whoami` → verifica auth.
36
+ 2. `badgie-crm docs --json` → cárgate el catálogo.
37
+ 3. Ante una petición del humano:
38
+ - Traduce a un comando `[read]` primero para verificar estado.
39
+ - Si vas a mutar, muestra el comando propuesto al humano y espera confirmación (especialmente si lleva `[destructive]`).
40
+ 4. Siempre incluye `--limit` razonable (default 50) para no agotar contexto.
41
+ 5. Prefiere `query count <table> --where ...` antes de listar cuando solo necesites saber cuántos hay.
42
+
43
+ ## Ejemplos orientativos
44
+
45
+ ```bash
46
+ # "¿Cuántas facturas de salarios hay en marzo?"
47
+ badgie-crm query count invoices \
48
+ --where "category:ilike:salar" \
49
+ --where "invoice_date:gte:2026-03-01" \
50
+ --where "invoice_date:lte:2026-03-31"
51
+
52
+ # "Lista los leads nuevos asignados a greg"
53
+ badgie-crm leads list --status nuevo --assigned-to <uuid-greg> --pretty
54
+
55
+ # "Busca cualquier cosa que mencione 'valencia'"
56
+ badgie-crm search valencia
57
+
58
+ # "Qué columnas tiene la tabla X"
59
+ badgie-crm query describe <table> --pretty
60
+
61
+ # "Registra un intento de contacto fallido sobre un lead"
62
+ badgie-crm leads log-attempt <lead-uuid> --type call --result no_answer --notes "buzón"
63
+ ```
64
+
65
+ ## Setup rápido como skill de openclaw
66
+
67
+ 1. Instala el CLI en la máquina donde corra el agente:
68
+ ```bash
69
+ git clone <repo> && cd <repo>/cli && npm install && npm run build && npm link
70
+ ```
71
+ 2. Autentica una vez: `badgie-crm login` (o exporta `BADGIE_CRM_SERVICE_KEY` para modo no interactivo en CI/servidor).
72
+ 3. Crea el skill en el agente apuntando a este `AGENTS.md` + referenciando el manifest:
73
+ ```
74
+ Tool source: bash `badgie-crm docs --json`
75
+ Auth check: bash `badgie-crm whoami`
76
+ Entry docs: <ruta local del repo>/cli/AGENTS.md
77
+ ```
78
+ 4. Verifica: `badgie-crm docs --agent-hints` imprime guidance adicional.
79
+
80
+ ## Qué NO hacer
81
+
82
+ - **No** construyas queries SQL por tu cuenta — usa los comandos tipados.
83
+ - **No** uses `[destructive]` sin confirmación explícita del humano.
84
+ - **No** asumas nombres de columnas — usa `query describe <table>` para descubrirlas.
85
+ - **No** mezcles `--pretty` con parseo JSON (rompe el output).
86
+
87
+ ## Límites conocidos
88
+
89
+ - Comandos con tag `[http]` requieren que la app Next esté viva Y aceptando Bearer tokens. Hoy los endpoints siguen leyendo cookies — algunos fallarán hasta que se extiendan. Ver `tasks/badgie-crm-cli-mcp.md`.
90
+ - El CLI en modo `service` (env `BADGIE_CRM_SERVICE_KEY`) bypasa RLS: **solo en entornos confiables**.
91
+ - Mutaciones masivas (bulk update) aún no tienen comandos dedicados — usa `query` en modo lectura para verificar y pide al humano si necesitas un script ad-hoc.
package/README.md ADDED
@@ -0,0 +1,136 @@
1
+ # @badgie/crm-cli (`badgie-crm`)
2
+
3
+ CLI para operar el Badgie CRM desde la terminal. Reemplaza los scripts sueltos de `/scripts/` y prepara el terreno para exponer el CRM vía MCP a agentes IA (openclaw, Claude Desktop, Cursor...).
4
+
5
+ **Nombre del binario: `badgie-crm`** — dejamos `badgie` reservado para el CLI principal de Badgie (próximo).
6
+
7
+ ## Instalación (desarrollo)
8
+
9
+ Desde la raíz del repo:
10
+
11
+ ```bash
12
+ cd cli
13
+ npm install
14
+ npm run build
15
+ npm link # expone `badgie-crm` como binario global
16
+ ```
17
+
18
+ Después, desde cualquier sitio:
19
+
20
+ ```bash
21
+ badgie-crm # banner + estado + atajos
22
+ badgie-crm --help
23
+ ```
24
+
25
+ Para desarrollo rápido sin `build` continuo:
26
+
27
+ ```bash
28
+ cd cli && npm run dev -- leads list --pretty
29
+ ```
30
+
31
+ ## Configuración
32
+
33
+ El CLI lee credenciales de Supabase en este orden:
34
+
35
+ 1. `BADGIE_CRM_SUPABASE_URL` / `BADGIE_CRM_SUPABASE_ANON_KEY` (env vars explícitas).
36
+ 2. `BADGIE_SUPABASE_URL` / `BADGIE_SUPABASE_ANON_KEY` (retrocompat).
37
+ 3. `NEXT_PUBLIC_SUPABASE_URL` / `NEXT_PUBLIC_SUPABASE_ANON_KEY` del `.env.local` del repo.
38
+ 4. Valores guardados en `~/.badgie-crm/config.json` tras el primer `badgie-crm login`.
39
+
40
+ Si tenías un `~/.badgie/config.json` de la versión anterior, se migra automáticamente la primera vez que se arranca el CLI.
41
+
42
+ ## Autenticación
43
+
44
+ Dos modos:
45
+
46
+ ### Modo usuario (interactivo, respeta RLS)
47
+
48
+ ```bash
49
+ badgie-crm login
50
+ ```
51
+
52
+ Te pide email + contraseña de tu cuenta Badgie (el mismo login que la app web). Aplica las mismas reglas: cuentas `@badgie.com` entran directas, otras deben tener fila en `team_members` activa. La sesión se guarda en `~/.badgie-crm/config.json` (permisos 0600) y los tokens se refrescan automáticamente.
53
+
54
+ ```bash
55
+ badgie-crm whoami # JSON
56
+ badgie-crm whoami --pretty # texto
57
+ badgie-crm logout # limpia la sesión
58
+ ```
59
+
60
+ ### Modo service (CI / automatización, bypassa RLS)
61
+
62
+ ```bash
63
+ export BADGIE_CRM_SERVICE_KEY=eyJhbGc...
64
+ badgie-crm leads list
65
+ ```
66
+
67
+ `BADGIE_CRM_SERVICE_KEY` (o `BADGIE_SERVICE_KEY` / `SUPABASE_SERVICE_ROLE_KEY`) tiene precedencia sobre la sesión interactiva. Úsalo solo en entornos confiables.
68
+
69
+ ## Módulos (70 comandos)
70
+
71
+ `leads`, `clients`, `contacts`, `tasks`, `development`, `finance`, `outbound`, `directory`, `marketing`, `intelligence`, `mission-control`, `top-clients`, `web-design`, `team`, `sports`, `activities`, `demos`, `onboarding`, `webhooks`, `admin`, `search`, `query`, `docs`.
72
+
73
+ Explora todo con:
74
+
75
+ ```bash
76
+ badgie-crm docs # tree completo
77
+ badgie-crm docs finance # filtrado por módulo
78
+ badgie-crm docs --json # manifest JSON para agentes IA
79
+ badgie-crm docs --agent-hints # guidance extra para LLMs
80
+ ```
81
+
82
+ ## Ejemplos frecuentes
83
+
84
+ ```bash
85
+ # Facturas de marzo de la categoría salarios
86
+ badgie-crm finance invoices list --category salarios --since 2026-03-01 --until 2026-03-31 --pretty
87
+
88
+ # Query genérico — cualquier columna de cualquier tabla
89
+ badgie-crm query invoices --where "category=salarios" --where "invoice_date:gte:2026-03-01" --pretty
90
+ badgie-crm query count bank_movements --where "amount:gte:1000" --where "movement_date:gte:2026-03-01"
91
+ badgie-crm query describe invoices --pretty
92
+
93
+ # Directory
94
+ badgie-crm directory schools list --sport golf --province Madrid --min-rating 4.5 --pretty
95
+
96
+ # Búsqueda global
97
+ badgie-crm search "valencia" --pretty
98
+ ```
99
+
100
+ ## Distribución al equipo
101
+
102
+ **Opción A — clone + link (hoy, más simple)**. Cada persona del equipo:
103
+ ```bash
104
+ git clone <repo-url> badgie-crm && cd badgie-crm/cli
105
+ npm install && npm run build && npm link
106
+ badgie-crm login
107
+ ```
108
+ Para actualizar: `git pull && cd cli && npm run build`.
109
+
110
+ **Opción B — publicar a npm (cuando queramos)**. Hoy `@badgie/crm-cli` está marcado `private`. Pasos cuando queramos publicar:
111
+ 1. Crear una org `@badgie` en npm (o usar GitHub Packages con scope `@badgie`).
112
+ 2. `npm login --scope=@badgie`.
113
+ 3. En `cli/package.json` quitar `"private": true` si lo añadimos, o publicar a GitHub Packages con `publishConfig`.
114
+ 4. `cd cli && npm publish --access restricted`.
115
+ 5. Equipo instala: `npm install -g @badgie/crm-cli`.
116
+
117
+ **Vercel no interviene.** Vercel despliega la app Next (`/app`). El CLI es un paquete npm independiente que el equipo instala en sus máquinas.
118
+
119
+ **Git**: sí, empuja el commit con `cli/` a GitHub para que el equipo pueda clonar. El CLI está excluido de la build de Next, así que el deploy de la app no se ve afectado.
120
+
121
+ ## Agentes IA (openclaw, Claude, Cursor…)
122
+
123
+ Ver `cli/AGENTS.md`. Dale eso al agente + el manifest JSON:
124
+ ```bash
125
+ badgie-crm docs --json > ~/.badgie-crm/manifest.json
126
+ ```
127
+ El agente carga ese JSON como catálogo de tools y respeta los tags `[read|write|destructive|http]` para saber qué es seguro.
128
+
129
+ ## Roadmap
130
+
131
+ Ver `tasks/badgie-crm-cli-mcp.md`. Próximo: **`badgie-crm mcp serve`** para que openclaw y otros agentes consuman el CRM como tools MCP tipadas (reutilizando el mismo registry).
132
+
133
+ ## Notas
134
+
135
+ - La carpeta `cli/` está excluida de la build de Next (`outputFileTracingExcludes` en `next.config.ts` + `exclude` en `tsconfig.json` raíz).
136
+ - `~/.badgie-crm/config.json` no debe commitearse — es local del usuario.
package/dist/bin.js ADDED
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { loginCommand } from './commands/login.js';
4
+ import { logoutCommand } from './commands/logout.js';
5
+ import { whoamiCommand } from './commands/whoami.js';
6
+ import { welcomeCommand } from './commands/welcome.js';
7
+ import { leadsModule } from './commands/leads.js';
8
+ import { clientsModule } from './commands/clients.js';
9
+ import { tasksModule } from './commands/tasks.js';
10
+ import { financeModule } from './commands/finance.js';
11
+ import { outboundModule } from './commands/outbound.js';
12
+ import { marketingModule } from './commands/marketing.js';
13
+ import { intelligenceModule } from './commands/intelligence.js';
14
+ import { operationsModule } from './commands/operations.js';
15
+ import { webhooksModule } from './commands/webhooks.js';
16
+ import { adminModule } from './commands/admin.js';
17
+ import { searchModule } from './commands/search.js';
18
+ import { queryModule } from './commands/query.js';
19
+ import { directoryModule } from './commands/directory.js';
20
+ import { topClientsModule } from './commands/top-clients.js';
21
+ import { createDocsModule } from './commands/docs.js';
22
+ const MODULES = [
23
+ leadsModule,
24
+ clientsModule,
25
+ tasksModule,
26
+ financeModule,
27
+ outboundModule,
28
+ marketingModule,
29
+ intelligenceModule,
30
+ operationsModule,
31
+ webhooksModule,
32
+ adminModule,
33
+ searchModule,
34
+ queryModule,
35
+ directoryModule,
36
+ topClientsModule,
37
+ ];
38
+ async function main() {
39
+ const program = new Command();
40
+ const docsModule = createDocsModule(() => [...MODULES, docsModule]);
41
+ const allModules = [...MODULES, docsModule];
42
+ program
43
+ .name('badgie')
44
+ .description('Badgie CRM CLI — operate the CRM from your terminal or as an MCP tool server.')
45
+ .version('0.1.0')
46
+ .action(wrap(welcomeCommand));
47
+ program
48
+ .command('welcome')
49
+ .description('Show the welcome banner')
50
+ .action(wrap(welcomeCommand));
51
+ program
52
+ .command('login')
53
+ .description('Sign in with email + password')
54
+ .action(wrap(loginCommand));
55
+ program
56
+ .command('logout')
57
+ .description('Clear the persisted session')
58
+ .action(wrap(logoutCommand));
59
+ program
60
+ .command('whoami')
61
+ .description('Show the current auth mode and user')
62
+ .option('--pretty', 'human-readable output')
63
+ .action(wrap(whoamiCommand));
64
+ for (const m of allModules)
65
+ registerModule(program, m);
66
+ await program.parseAsync(process.argv);
67
+ }
68
+ function registerModule(program, module) {
69
+ const nodes = new Map();
70
+ nodes.set('', program);
71
+ // Pass 1: create every Command node (parent and leaf) exactly once.
72
+ for (const spec of module.specs) {
73
+ let parent = program;
74
+ for (let i = 0; i < spec.path.length; i++) {
75
+ const key = spec.path.slice(0, i + 1).join('.');
76
+ let node = nodes.get(key);
77
+ if (!node) {
78
+ node = parent
79
+ .command(spec.path[i])
80
+ .description(i === spec.path.length - 1 ? spec.summary : `${spec.path[i]} commands`);
81
+ nodes.set(key, node);
82
+ }
83
+ parent = node;
84
+ }
85
+ }
86
+ // Pass 2: attach args, options, and action to each spec's node.
87
+ for (const spec of module.specs) {
88
+ const leaf = nodes.get(spec.path.join('.'));
89
+ attachLeaf(leaf, spec);
90
+ }
91
+ }
92
+ function attachLeaf(leaf, spec) {
93
+ leaf.description(spec.summary);
94
+ for (const a of spec.args ?? []) {
95
+ const tok = a.required ? `<${a.name}>` : `[${a.name}]`;
96
+ leaf.argument(tok, a.description);
97
+ }
98
+ for (const o of spec.options ?? []) {
99
+ if (o.collect) {
100
+ leaf.option(o.flag, o.description, (value, previous) => [...previous, value], []);
101
+ }
102
+ else if (o.defaultValue !== undefined) {
103
+ leaf.option(o.flag, o.description, String(o.defaultValue));
104
+ }
105
+ else {
106
+ leaf.option(o.flag, o.description);
107
+ }
108
+ }
109
+ if (spec.examples && spec.examples.length > 0) {
110
+ leaf.addHelpText('after', '\nExamples:\n' + spec.examples.map((e) => ' ' + e).join('\n'));
111
+ }
112
+ if (spec.description)
113
+ leaf.addHelpText('after', '\n' + spec.description);
114
+ leaf.action(async (...actionArgs) => {
115
+ const cmd = actionArgs[actionArgs.length - 1];
116
+ const opts = (cmd.optsWithGlobals
117
+ ? cmd.optsWithGlobals()
118
+ : cmd.opts());
119
+ const argMap = {};
120
+ (spec.args ?? []).forEach((a, i) => {
121
+ argMap[a.name] = actionArgs[i];
122
+ });
123
+ try {
124
+ await spec.handler(argMap, opts);
125
+ }
126
+ catch (err) {
127
+ const msg = err instanceof Error ? err.message : String(err);
128
+ console.error(`Error: ${msg}`);
129
+ process.exit(1);
130
+ }
131
+ });
132
+ }
133
+ function wrap(fn) {
134
+ return async (opts) => {
135
+ try {
136
+ await fn(opts);
137
+ }
138
+ catch (err) {
139
+ const msg = err instanceof Error ? err.message : String(err);
140
+ console.error(`Error: ${msg}`);
141
+ process.exit(1);
142
+ }
143
+ };
144
+ }
145
+ main().catch((err) => {
146
+ console.error(err);
147
+ process.exit(1);
148
+ });
149
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ import { getAuthedClient } from '../core/supabase.js';
2
+ import { output, parseColumns, parseLimit, commonListOptions } from '../core/format.js';
3
+ import { callAppApi } from '../core/http.js';
4
+ async function listUsers(_a, opts) {
5
+ const { client } = await getAuthedClient();
6
+ let q = client
7
+ .from('team_members')
8
+ .select('id, email, full_name, role, is_active, last_login_at, created_at')
9
+ .order('created_at', { ascending: false })
10
+ .limit(parseLimit(opts));
11
+ if (opts.activeOnly !== undefined)
12
+ q = q.eq('is_active', true);
13
+ const { data, error } = await q;
14
+ if (error)
15
+ throw error;
16
+ output(data ?? [], { pretty: !!opts.pretty, columns: parseColumns(opts) });
17
+ }
18
+ async function createUser(_a, opts) {
19
+ const res = await callAppApi('/api/admin/create-user', {
20
+ method: 'POST',
21
+ body: JSON.stringify({
22
+ email: opts.email,
23
+ full_name: opts.fullName,
24
+ role: opts.role,
25
+ }),
26
+ });
27
+ output(res, { pretty: !!opts.pretty });
28
+ }
29
+ async function deleteUser(args, opts) {
30
+ const res = await callAppApi('/api/admin/delete-user', {
31
+ method: 'POST',
32
+ body: JSON.stringify({ id: args.id }),
33
+ });
34
+ output(res, { pretty: !!opts.pretty });
35
+ }
36
+ async function updateFinanceAccess(args, opts) {
37
+ const res = await callAppApi('/api/admin/update-finance-access', {
38
+ method: 'POST',
39
+ body: JSON.stringify({ id: args.id, allowed: opts.allowed === 'true' }),
40
+ });
41
+ output(res, { pretty: !!opts.pretty });
42
+ }
43
+ export const adminModule = {
44
+ name: 'admin',
45
+ summary: 'Admin operations — users, permissions (requires service key or admin user)',
46
+ specs: [
47
+ {
48
+ path: ['admin', 'users', 'list'],
49
+ summary: 'List team_members',
50
+ tags: ['read'],
51
+ options: [
52
+ { flag: '--active-only', description: 'only active users' },
53
+ ...commonListOptions(),
54
+ ],
55
+ handler: listUsers,
56
+ },
57
+ {
58
+ path: ['admin', 'users', 'create'],
59
+ summary: 'Create a team member (calls the Next app)',
60
+ tags: ['write', 'http'],
61
+ options: [
62
+ { flag: '--email <email>', description: 'email (required)' },
63
+ { flag: '--full-name <text>', description: 'display name' },
64
+ { flag: '--role <role>', description: 'member role' },
65
+ { flag: '--pretty', description: 'human output' },
66
+ ],
67
+ handler: createUser,
68
+ },
69
+ {
70
+ path: ['admin', 'users', 'delete'],
71
+ summary: 'Delete a team member (destructive, calls the Next app)',
72
+ tags: ['destructive', 'http'],
73
+ args: [{ name: 'id', required: true, description: 'team_members.id' }],
74
+ options: [{ flag: '--pretty', description: 'human output' }],
75
+ handler: deleteUser,
76
+ },
77
+ {
78
+ path: ['admin', 'users', 'set-finance-access'],
79
+ summary: 'Toggle finance_access for a user (calls the Next app)',
80
+ tags: ['write', 'http'],
81
+ args: [{ name: 'id', required: true, description: 'team_members.id' }],
82
+ options: [
83
+ { flag: '--allowed <bool>', description: 'true|false (required)' },
84
+ { flag: '--pretty', description: 'human output' },
85
+ ],
86
+ handler: updateFinanceAccess,
87
+ },
88
+ ],
89
+ };
90
+ //# sourceMappingURL=admin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.js","sourceRoot":"","sources":["../../src/commands/admin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,135 @@
1
+ import { getAuthedClient } from '../core/supabase.js';
2
+ import { commonListOptions, output, parseColumns, parseLimit } from '../core/format.js';
3
+ async function listClients(_a, opts) {
4
+ const { client } = await getAuthedClient();
5
+ let q = client
6
+ .from('clients')
7
+ .select('id, name, email, phone, sport, city, type, status, assigned_to, created_at')
8
+ .order('created_at', { ascending: false })
9
+ .limit(parseLimit(opts));
10
+ if (typeof opts.sport === 'string')
11
+ q = q.ilike('sport', `%${opts.sport}%`);
12
+ if (typeof opts.city === 'string')
13
+ q = q.ilike('city', `%${opts.city}%`);
14
+ if (typeof opts.status === 'string')
15
+ q = q.eq('status', opts.status);
16
+ if (typeof opts.type === 'string')
17
+ q = q.eq('type', opts.type);
18
+ if (typeof opts.assignedTo === 'string')
19
+ q = q.eq('assigned_to', opts.assignedTo);
20
+ if (typeof opts.search === 'string')
21
+ q = q.or(`name.ilike.%${opts.search}%,email.ilike.%${opts.search}%`);
22
+ if (typeof opts.since === 'string')
23
+ q = q.gte('created_at', opts.since);
24
+ if (typeof opts.until === 'string')
25
+ q = q.lte('created_at', opts.until);
26
+ const { data, error } = await q;
27
+ if (error)
28
+ throw error;
29
+ output(data ?? [], { pretty: !!opts.pretty, columns: parseColumns(opts) });
30
+ }
31
+ async function getClient(args, opts) {
32
+ const { client } = await getAuthedClient();
33
+ const { data, error } = await client
34
+ .from('clients')
35
+ .select('*, assigned:team_members!clients_assigned_to_fkey(full_name, email)')
36
+ .eq('id', args.id)
37
+ .single();
38
+ if (error)
39
+ throw error;
40
+ output(data, { pretty: !!opts.pretty });
41
+ }
42
+ async function createClient_(_a, opts) {
43
+ const { client } = await getAuthedClient();
44
+ const { data, error } = await client
45
+ .from('clients')
46
+ .insert({
47
+ name: opts.name,
48
+ email: opts.email ?? null,
49
+ phone: opts.phone ?? null,
50
+ sport: opts.sport ?? null,
51
+ city: opts.city ?? null,
52
+ type: opts.type ?? null,
53
+ status: opts.status ?? null,
54
+ assigned_to: opts.assignedTo ?? null,
55
+ })
56
+ .select('*')
57
+ .single();
58
+ if (error)
59
+ throw error;
60
+ output(data, { pretty: !!opts.pretty });
61
+ }
62
+ async function listContacts(_a, opts) {
63
+ const { client } = await getAuthedClient();
64
+ let q = client
65
+ .from('contacts')
66
+ .select('id, first_name, last_name, email, phone, role, is_primary, client_id, created_at')
67
+ .order('created_at', { ascending: false })
68
+ .limit(parseLimit(opts));
69
+ if (typeof opts.clientId === 'string')
70
+ q = q.eq('client_id', opts.clientId);
71
+ const { data, error } = await q;
72
+ if (error)
73
+ throw error;
74
+ output(data ?? [], { pretty: !!opts.pretty, columns: parseColumns(opts) });
75
+ }
76
+ export const clientsModule = {
77
+ name: 'clients',
78
+ summary: 'Client & contact management',
79
+ specs: [
80
+ {
81
+ path: ['clients', 'list'],
82
+ summary: 'List clients (filter by sport, city, status, name)',
83
+ tags: ['read'],
84
+ options: [
85
+ { flag: '--sport <name>', description: 'filter by sport (ilike)' },
86
+ { flag: '--city <name>', description: 'filter by city (ilike)' },
87
+ { flag: '--status <status>', description: 'filter by status' },
88
+ { flag: '--type <type>', description: 'filter by client type' },
89
+ { flag: '--assigned-to <uuid>', description: 'filter by KAM' },
90
+ { flag: '--search <text>', description: 'search name or email (ilike)' },
91
+ { flag: '--since <date>', description: 'created_at >= YYYY-MM-DD' },
92
+ { flag: '--until <date>', description: 'created_at <= YYYY-MM-DD' },
93
+ ...commonListOptions(),
94
+ ],
95
+ examples: ['badgie-crm clients list --sport padel --pretty', 'badgie-crm clients list --search valencia', 'badgie-crm clients list --assigned-to <kam-uuid>'],
96
+ handler: listClients,
97
+ },
98
+ {
99
+ path: ['clients', 'get'],
100
+ summary: 'Show one client by id',
101
+ tags: ['read'],
102
+ args: [{ name: 'id', required: true, description: 'client uuid' }],
103
+ options: [{ flag: '--pretty', description: 'human output' }],
104
+ handler: getClient,
105
+ },
106
+ {
107
+ path: ['clients', 'create'],
108
+ summary: 'Create a client',
109
+ tags: ['write'],
110
+ options: [
111
+ { flag: '--name <text>', description: 'client name (required)' },
112
+ { flag: '--email <email>', description: 'primary email' },
113
+ { flag: '--phone <phone>', description: 'primary phone' },
114
+ { flag: '--sport <sport>', description: 'sport' },
115
+ { flag: '--city <city>', description: 'city' },
116
+ { flag: '--type <type>', description: 'client type' },
117
+ { flag: '--status <status>', description: 'status' },
118
+ { flag: '--assigned-to <uuid>', description: 'team_members.id' },
119
+ { flag: '--pretty', description: 'human output' },
120
+ ],
121
+ handler: createClient_,
122
+ },
123
+ {
124
+ path: ['contacts', 'list'],
125
+ summary: 'List contacts (optionally filtered by client)',
126
+ tags: ['read'],
127
+ options: [
128
+ { flag: '--client-id <uuid>', description: 'filter by client' },
129
+ ...commonListOptions(),
130
+ ],
131
+ handler: listContacts,
132
+ },
133
+ ],
134
+ };
135
+ //# sourceMappingURL=clients.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clients.js","sourceRoot":"","sources":["../../src/commands/clients.ts"],"names":[],"mappings":"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"}