veo-sdk 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.
package/CONTRACT.md ADDED
@@ -0,0 +1,144 @@
1
+ # Contrato HTTP entre @veo/sdk y veo-backend
2
+
3
+ Versión: **v1**
4
+
5
+ Este documento es la fuente de verdad sobre el contrato HTTP. Cualquier
6
+ cambio debe reflejarse simultáneamente en ambos repos.
7
+
8
+ ## Base URL
9
+
10
+ - Producción: `https://api.veo.io`
11
+ - Desarrollo: `http://localhost:3001`
12
+
13
+ ## Versionado
14
+
15
+ Todos los endpoints viven bajo `/v1/`. Cambios incompatibles requieren
16
+ nueva versión (`/v2/`).
17
+
18
+ ## Authentication
19
+
20
+ Todos los endpoints requieren API key del workspace:
21
+
22
+ - **Header:** `X-Api-Key: pk_xxx`
23
+ - **O query param:** `?key=pk_xxx` (necesario para `navigator.sendBeacon`)
24
+
25
+ Si la API key falta o es inválida: `401 Unauthorized`.
26
+
27
+ ## Headers comunes
28
+
29
+ | Header | Requerido | Valor |
30
+ |--------|-----------|-------|
31
+ | `Content-Type` | Sí | `application/json` |
32
+ | `X-Api-Key` | Sí (o query) | `pk_xxx` |
33
+ | `X-Sdk-Version` | Recomendado | `0.0.1` |
34
+
35
+ ## Endpoints
36
+
37
+ ### POST /v1/identify
38
+
39
+ Crea o actualiza un end_user y opcionalmente su organization.
40
+
41
+ **Request body:**
42
+ ```json
43
+ {
44
+ "endUser": {
45
+ "id": "user_123",
46
+ "anonymousId": "anon_xyz",
47
+ "traits": {
48
+ "email": "user@example.com",
49
+ "role": "admin",
50
+ "plan": "free"
51
+ }
52
+ },
53
+ "organization": {
54
+ "id": "acme-corp",
55
+ "attributes": {
56
+ "plan": "pro",
57
+ "mrr": 99.99,
58
+ "industry": "saas"
59
+ }
60
+ }
61
+ }
62
+ ```
63
+
64
+ **Response 200:**
65
+ ```json
66
+ {
67
+ "endUserId": "user_123",
68
+ "organizationId": "acme-corp",
69
+ "workspaceId": "uuid"
70
+ }
71
+ ```
72
+
73
+ **Errors:**
74
+ - `400` - payload inválido
75
+ - `401` - API key inválida
76
+
77
+ ---
78
+
79
+ ### POST /v1/events
80
+
81
+ Ingesta batch de eventos (máx 100 por request).
82
+
83
+ **Request body:**
84
+ ```json
85
+ {
86
+ "events": [
87
+ {
88
+ "actionId": "01900000-0000-7000-8000-000000000001",
89
+ "endUserId": "user_123",
90
+ "organizationId": "acme-corp",
91
+ "sessionId": "session_abc",
92
+ "actionType": "track",
93
+ "actionName": "project_created",
94
+ "occurredAt": "2026-05-08T10:00:00.000Z",
95
+ "pageUrl": "https://app.example.com/dashboard",
96
+ "pagePath": "/dashboard",
97
+ "pageTitle": "Dashboard",
98
+ "pageReferrer": "https://google.com",
99
+ "actionProperties": {
100
+ "templateId": "blank"
101
+ }
102
+ }
103
+ ]
104
+ }
105
+ ```
106
+
107
+ **Action types válidos:**
108
+ - `pageview` - usuario visitó una página
109
+ - `track` - evento custom con nombre
110
+ - `identify` - usuario se identificó (también triggea upsert)
111
+ - `guide` - interacción con guía (futuro)
112
+
113
+ **Response 200:**
114
+ ```json
115
+ {
116
+ "accepted": 95,
117
+ "deduped": 5
118
+ }
119
+ ```
120
+
121
+ **Errors:**
122
+ - `400` - batch vacío, payload inválido, o > 100 eventos
123
+ - `401` - API key inválida
124
+ - `413` - body demasiado grande
125
+
126
+ ---
127
+
128
+ ## Idempotencia
129
+
130
+ Cada `actionId` es único. El backend mantiene ventana de 24h para
131
+ detectar duplicados. Si el SDK reintenta por timeout, el evento NO se
132
+ duplica.
133
+
134
+ ## Reglas
135
+
136
+ - `occurredAt` siempre en ISO 8601 con timezone (Z o offset)
137
+ - `traits` y `attributes` son JSONB, sin schema fijo
138
+ - Máximo 64KB por campo JSONB
139
+ - Máximo 100 eventos por request
140
+ - Encoding: UTF-8
141
+
142
+ ## SDK Version
143
+
144
+ El SDK debe enviar `X-Sdk-Version` en cada request para trazabilidad.
package/README.md ADDED
@@ -0,0 +1,141 @@
1
+ # @veo/sdk
2
+
3
+ SDK oficial de Veo para web apps. Captura eventos de analytics y muestra
4
+ guías in-app (tooltips, modales, walkthroughs).
5
+
6
+ ## Stack
7
+
8
+ - TypeScript estricto
9
+ - Cero dependencias en runtime
10
+ - 3 formatos: ESM, CJS, IIFE (CDN)
11
+ - < 10KB gzipped
12
+
13
+ ## Instalación
14
+
15
+ ### npm
16
+
17
+ ```bash
18
+ pnpm add @veo/sdk
19
+ ```
20
+
21
+ ```ts
22
+ import { init } from '@veo/sdk';
23
+
24
+ const veo = init({
25
+ apiKey: 'pk_xxx',
26
+ apiUrl: 'https://api.veo.io',
27
+ });
28
+
29
+ veo.identify({ visitor: { id: 'user_123', traits: { email: 'a@b.com' } } });
30
+ veo.track('button_clicked');
31
+ ```
32
+
33
+ ### CDN (sin bundler)
34
+
35
+ ```html
36
+ <script src="https://cdn.veo.io/sdk/v1.js"></script>
37
+ <script>
38
+ veo.init({ apiKey: 'pk_xxx', apiUrl: 'https://api.veo.io' });
39
+ veo.identify({ visitor: { id: 'user_123' } });
40
+ </script>
41
+ ```
42
+
43
+ ### Snippet (recomendado)
44
+
45
+ Ver `snippet/snippet.html` para el snippet copy-paste.
46
+
47
+ ## API
48
+
49
+ (En desarrollo. Implementación completa en sprints siguientes.)
50
+
51
+ - `init(config)` - inicializa el SDK
52
+ - `identify(payload)` - identifica un usuario
53
+ - `track(name, properties?)` - emite evento custom
54
+ - `pageview(path?)` - emite pageview (automático en SPAs)
55
+ - `reset()` - limpia identidad
56
+ - `flush()` - fuerza envío de la queue
57
+
58
+ ## Autocaptura
59
+
60
+ Al hacer `init()`, el SDK captura automáticamente **clicks, submits y changes**
61
+ del DOM (sin código por evento), estilo Pendo/PostHog. Cada interacción genera
62
+ un `track('$autocapture', …)` con metadata del elemento (tag, id, clases
63
+ "humanas", texto, atributos, selector CSS y ancestros). Va por la misma queue
64
+ (mismo batching/retry) que el resto de eventos.
65
+
66
+ Privacidad agresiva por defecto: **nunca** se captura el `value` de inputs, ni
67
+ el texto de campos de entrada, y se ignoran inputs sensibles
68
+ (`password`, `email`, `tel`, datos de tarjeta, campos con `name`/`id` tipo
69
+ `password`/`ssn`/`credit`/`card`).
70
+
71
+ ### Opt-out de un elemento (y su subárbol)
72
+
73
+ ```html
74
+ <button data-veo-ignore>No me trackees</button>
75
+ <div class="veo-ignore"> … nada aquí se captura … </div>
76
+ ```
77
+
78
+ ### Nombre semántico (tagging)
79
+
80
+ `data-veo-tag` da un nombre estable al elemento (prioritario en el selector,
81
+ ideal para definir "features" en el dashboard aunque cambien clases/estructura):
82
+
83
+ ```html
84
+ <button data-veo-tag="checkout-cta">Comprar</button>
85
+ ```
86
+
87
+ ### Configuración
88
+
89
+ ```ts
90
+ init({
91
+ apiKey: 'pk_xxx',
92
+ apiUrl: 'https://api.veo.io',
93
+ autocapture: {
94
+ captureClicks: true, // default
95
+ captureSubmits: true, // default
96
+ captureChanges: true, // default (solo selects y checkbox/radio)
97
+ maskAllText: false, // true → no capturar texto visible
98
+ blockSelectors: ['.private', '#chat-widget'], // ignorar selectores propios
99
+ throttleMs: 100, // anti-spam por elemento
100
+ maxTextLength: 200, // truncado de textos
101
+ captureAncestors: 5, // niveles de ancestros (máx 10)
102
+ },
103
+ });
104
+
105
+ // Deshabilitar por completo:
106
+ init({ apiKey: 'pk_xxx', apiUrl: '…', autocapture: false });
107
+ ```
108
+
109
+ ## Desarrollo
110
+
111
+ ```bash
112
+ # Setup
113
+ pnpm install
114
+
115
+ # Desarrollo (watch)
116
+ pnpm dev
117
+
118
+ # Build
119
+ pnpm build
120
+
121
+ # Tests
122
+ pnpm test
123
+
124
+ # Ver tamaño del bundle
125
+ pnpm size
126
+
127
+ # Lint
128
+ pnpm lint
129
+ ```
130
+
131
+ ## Roadmap
132
+
133
+ - ✅ Sprint 1: Core (identify, track, pageview, SPA router)
134
+ - ✅ Sprint A: Autocaptura de clicks/submits/changes (PII-safe)
135
+ - ⬜ Sprint 4: Guías in-app (tooltips, modales, banners)
136
+ - ⬜ Sprint 5: Walkthroughs multi-paso
137
+ - ⬜ Futuro: Session replay
138
+
139
+ ## Licencia
140
+
141
+ UNLICENSED (proyecto privado)