@inspira-npm/events 0.0.0-stage → 0.3.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/catalog.d.ts +2 -0
- package/dist/catalog.js +246 -0
- package/dist/catalog.json +665 -0
- package/dist/click-record-B8KyALZZ.d.ts +31 -0
- package/dist/index-BShrVaIU.d.ts +203 -0
- package/dist/index.d.ts +202 -0
- package/dist/index.js +753 -0
- package/dist/server.d.ts +141 -0
- package/dist/server.js +445 -0
- package/dist/shared-D2s2QSYg.js +23 -0
- package/dist/version-DPt-j93d.js +4 -0
- package/package.json +39 -4
- package/README.md +0 -3
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as EventProps, c as isEventName, d as EventDefinition, f as EventSource, i as EventName, l as toJsonCatalog, n as Catalog, o as ImpressionEventName, r as CatalogJson, s as catalog, t as BrowserEventName, u as validateEventProps } from "./index-BShrVaIU.js";
|
|
2
|
+
export { BrowserEventName, Catalog, CatalogJson, type EventDefinition, EventName, EventProps, type EventSource, ImpressionEventName, catalog, isEventName, toJsonCatalog, validateEventProps };
|
package/dist/catalog.js
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { n as SDK_VERSION } from "./version-DPt-j93d.js";
|
|
2
|
+
import { a as service, i as position, n as itemId, r as placement, t as currency } from "./shared-D2s2QSYg.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
// src/catalog/define.ts
|
|
5
|
+
function defineEvent(definition) {
|
|
6
|
+
return definition;
|
|
7
|
+
}
|
|
8
|
+
// src/catalog/events/ads.ts
|
|
9
|
+
const adProps = {
|
|
10
|
+
ad_id: z.string().min(1).max(100).describe("`id` del ad tal como lo devuelve el ads engine"),
|
|
11
|
+
ad_type: z.string().min(1).max(50).describe("`adType` del engine: resort, hotel, destinations, promotions, banner…"),
|
|
12
|
+
placement,
|
|
13
|
+
position: position.optional(),
|
|
14
|
+
campaign_id: z.string().max(100).optional().describe("Campaña que sirvió el ad, si se conoce"),
|
|
15
|
+
token: z.string().max(2e3).optional().describe("Token firmado que el engine devuelve con cada ad (cuando exista); valida el evento")
|
|
16
|
+
};
|
|
17
|
+
const adEvents = {
|
|
18
|
+
ad_impression: defineEvent({
|
|
19
|
+
domain: "ads",
|
|
20
|
+
source: "browser",
|
|
21
|
+
since: "0.1.0",
|
|
22
|
+
description: "Impresión VISIBLE de un ad: ≥50% del ad en pantalla durante ≥1 s (estándar IAB). Una por ad y montaje.",
|
|
23
|
+
props: z.strictObject(adProps)
|
|
24
|
+
}),
|
|
25
|
+
ad_click: defineEvent({
|
|
26
|
+
domain: "ads",
|
|
27
|
+
source: "browser",
|
|
28
|
+
since: "0.1.0",
|
|
29
|
+
description: "Click en un ad. `click_id` viaja en la URL de destino (`?ipc=`) para atribuir conversiones.",
|
|
30
|
+
props: z.strictObject({
|
|
31
|
+
...adProps,
|
|
32
|
+
click_id: z.uuid().describe("Id único del click; también va en la URL de destino como ?ipc="),
|
|
33
|
+
destination_url: z.string().max(2e3).optional().describe("URL a la que lleva el ad")
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
};
|
|
37
|
+
// src/catalog/events/cards.ts
|
|
38
|
+
const cardProps = {
|
|
39
|
+
card_type: z.string().min(1).max(50).describe("Qué representa la card: hotel, resort, destination, activity, car, promotion…"),
|
|
40
|
+
item_id: itemId.describe("Id del ítem que representa la card"),
|
|
41
|
+
placement,
|
|
42
|
+
position: position.optional(),
|
|
43
|
+
list_id: z.string().max(100).optional().describe("Id de la lista o búsqueda que la contiene")
|
|
44
|
+
};
|
|
45
|
+
const cardEvents = {
|
|
46
|
+
card_impression: defineEvent({
|
|
47
|
+
domain: "cards",
|
|
48
|
+
source: "browser",
|
|
49
|
+
since: "0.1.0",
|
|
50
|
+
description: "Impresión VISIBLE de una card (≥50% en pantalla durante ≥1 s). Una por card y montaje.",
|
|
51
|
+
props: z.strictObject(cardProps)
|
|
52
|
+
}),
|
|
53
|
+
card_click: defineEvent({
|
|
54
|
+
domain: "cards",
|
|
55
|
+
source: "browser",
|
|
56
|
+
since: "0.1.0",
|
|
57
|
+
description: "Click en una card o en una de sus acciones.",
|
|
58
|
+
props: z.strictObject({
|
|
59
|
+
...cardProps,
|
|
60
|
+
action: z.enum([
|
|
61
|
+
"open",
|
|
62
|
+
"book",
|
|
63
|
+
"favorite",
|
|
64
|
+
"share",
|
|
65
|
+
"map"
|
|
66
|
+
]).optional().describe("Qué parte de la card se clickeó; sin valor = la card completa (open)")
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
};
|
|
70
|
+
// src/catalog/events/conversions.ts
|
|
71
|
+
const conversionEvents = { conversion: defineEvent({
|
|
72
|
+
domain: "conversions",
|
|
73
|
+
source: "server",
|
|
74
|
+
since: "0.1.0",
|
|
75
|
+
description: "Conversión confirmada (reserva, lead, registro). La envía un BACKEND server-to-server, nunca el navegador. Idempotente por `conversion_id`.",
|
|
76
|
+
props: z.strictObject({
|
|
77
|
+
conversion_id: z.string().min(1).max(100).describe("Referencia única (n.º de reserva/lead); reenviar el mismo id no duplica"),
|
|
78
|
+
type: z.enum([
|
|
79
|
+
"booking",
|
|
80
|
+
"lead",
|
|
81
|
+
"signup",
|
|
82
|
+
"purchase"
|
|
83
|
+
]).describe("Qué se convirtió: reserva, lead, registro o compra"),
|
|
84
|
+
service: service.optional(),
|
|
85
|
+
value: z.number().nonnegative().optional().describe("Monto de la conversión"),
|
|
86
|
+
currency: currency.optional(),
|
|
87
|
+
click_id: z.uuid().optional().describe("`tracker.getClickId()` del front; atribuye la conversión al click (`ad_click` u `outbound_click`) con ese id")
|
|
88
|
+
})
|
|
89
|
+
}) };
|
|
90
|
+
// src/catalog/events/map.ts
|
|
91
|
+
const zoom = z.number().min(0).max(22).describe("Nivel de zoom del mapa al momento del evento");
|
|
92
|
+
const mapEvents = {
|
|
93
|
+
map_marker_click: defineEvent({
|
|
94
|
+
domain: "map",
|
|
95
|
+
source: "browser",
|
|
96
|
+
since: "0.1.0",
|
|
97
|
+
description: "Click en un marcador del mapa (hotel, resort, punto de interés…).",
|
|
98
|
+
props: z.strictObject({
|
|
99
|
+
placement,
|
|
100
|
+
item_type: z.string().min(1).max(50).describe("Qué representa el marcador: hotel, resort, poi…"),
|
|
101
|
+
item_id: itemId.describe("Id del ítem que representa el marcador"),
|
|
102
|
+
zoom: zoom.optional()
|
|
103
|
+
})
|
|
104
|
+
}),
|
|
105
|
+
map_interaction: defineEvent({
|
|
106
|
+
domain: "map",
|
|
107
|
+
source: "browser",
|
|
108
|
+
since: "0.1.0",
|
|
109
|
+
description: "Interacción con el mapa que no es click en marcador. No se trackea el paneo (demasiado ruido).",
|
|
110
|
+
props: z.strictObject({
|
|
111
|
+
placement,
|
|
112
|
+
action: z.enum([
|
|
113
|
+
"zoom",
|
|
114
|
+
"cluster_click",
|
|
115
|
+
"search_area",
|
|
116
|
+
"popup_open",
|
|
117
|
+
"fullscreen"
|
|
118
|
+
]).describe("search_area = botón 'buscar en esta zona'"),
|
|
119
|
+
zoom: zoom.optional()
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
};
|
|
123
|
+
// src/catalog/events/navigation.ts
|
|
124
|
+
const navigationEvents = { outbound_click: defineEvent({
|
|
125
|
+
domain: "navigation",
|
|
126
|
+
source: "browser",
|
|
127
|
+
since: "0.2.0",
|
|
128
|
+
description: "Click en un link o CTA medido que lleva a otro sitio o página (p. ej. CTA de una landing → sitio principal). `click_id` viaja en la URL de destino (`?ipc=`); `via_click_id` encadena la atribución con el click por el que llegó el visitante.",
|
|
129
|
+
props: z.strictObject({
|
|
130
|
+
placement,
|
|
131
|
+
item_id: itemId.optional().describe("Id del ítem al que lleva el CTA (hotel, resort, oferta…), si lo hay"),
|
|
132
|
+
click_id: z.uuid().describe("Id único del click; también va en la URL de destino como ?ipc="),
|
|
133
|
+
via_click_id: z.uuid().optional().describe("Click id con el que LLEGÓ el visitante (`?ipc=` capturado en este sitio); lo pone el SDK"),
|
|
134
|
+
destination_url: z.string().max(2e3).optional().describe("URL a la que lleva el click")
|
|
135
|
+
})
|
|
136
|
+
}) };
|
|
137
|
+
// src/catalog/events/page.ts
|
|
138
|
+
const pageEvents = { page_view: defineEvent({
|
|
139
|
+
domain: "page",
|
|
140
|
+
source: "browser",
|
|
141
|
+
since: "0.1.0",
|
|
142
|
+
description: "Vista de página. Se dispara al cargar y en cada navegación del router (SPA). La URL ya va en el contexto del evento.",
|
|
143
|
+
props: z.strictObject({ page_type: z.string().max(50).optional().describe("Tipo de página estable: home, hotels-srp, hotel-details, checkout, landing…") })
|
|
144
|
+
}) };
|
|
145
|
+
// src/catalog/events/search.ts
|
|
146
|
+
const location = z.strictObject({
|
|
147
|
+
id: z.string().max(100).optional().describe("Id del destino/origen en el proveedor"),
|
|
148
|
+
name: z.string().max(200).optional().describe("Nombre de la sugerencia SELECCIONADA"),
|
|
149
|
+
type: z.enum([
|
|
150
|
+
"city",
|
|
151
|
+
"region",
|
|
152
|
+
"country",
|
|
153
|
+
"hotel",
|
|
154
|
+
"airport",
|
|
155
|
+
"poi"
|
|
156
|
+
]).optional().describe("Tipo de lugar de la sugerencia")
|
|
157
|
+
}).describe("Destino u origen elegido de las sugerencias");
|
|
158
|
+
const searchId = z.uuid().describe("Id de la búsqueda (generado en el cliente); une resultados y clicks de la misma búsqueda");
|
|
159
|
+
const searchEvents = {
|
|
160
|
+
search_performed: defineEvent({
|
|
161
|
+
domain: "search",
|
|
162
|
+
source: "browser",
|
|
163
|
+
since: "0.1.0",
|
|
164
|
+
description: "Búsqueda ejecutada (al recibir resultados). Una por búsqueda; un cambio de filtros que vuelve a buscar es otra.",
|
|
165
|
+
props: z.strictObject({
|
|
166
|
+
search_id: searchId,
|
|
167
|
+
service,
|
|
168
|
+
destination: location.optional(),
|
|
169
|
+
origin: location.optional().describe("Solo vuelos/traslados"),
|
|
170
|
+
check_in: z.iso.date().optional().describe("YYYY-MM-DD (o fecha de salida)"),
|
|
171
|
+
check_out: z.iso.date().optional().describe("YYYY-MM-DD (o fecha de regreso)"),
|
|
172
|
+
rooms: z.int().min(1).max(20).optional().describe("Habitaciones pedidas"),
|
|
173
|
+
adults: z.int().min(0).max(50).optional().describe("Adultos (total de la búsqueda)"),
|
|
174
|
+
children: z.int().min(0).max(50).optional().describe("Menores (total de la búsqueda)"),
|
|
175
|
+
results_count: z.int().nonnegative().optional().describe("Resultados devueltos; 0 = sin resultados"),
|
|
176
|
+
filters: z.record(z.string().max(50), z.union([
|
|
177
|
+
z.string().max(100),
|
|
178
|
+
z.number(),
|
|
179
|
+
z.boolean(),
|
|
180
|
+
z.array(z.string().max(100)).max(50)
|
|
181
|
+
])).optional().describe("Filtros activos: { stars: [4,5] → ['4','5'], price_max: 300, all_inclusive: true }"),
|
|
182
|
+
sort: z.string().max(50).optional().describe("Orden aplicado: price_asc, rating_desc…"),
|
|
183
|
+
page: z.int().min(1).optional().describe("Página de resultados (1-based)")
|
|
184
|
+
})
|
|
185
|
+
}),
|
|
186
|
+
search_result_click: defineEvent({
|
|
187
|
+
domain: "search",
|
|
188
|
+
source: "browser",
|
|
189
|
+
since: "0.1.0",
|
|
190
|
+
description: "Click en un resultado de búsqueda.",
|
|
191
|
+
props: z.strictObject({
|
|
192
|
+
search_id: searchId,
|
|
193
|
+
service,
|
|
194
|
+
item_id: itemId.describe("Id del resultado clickeado (hotel, vuelo, auto…)"),
|
|
195
|
+
position,
|
|
196
|
+
price: z.number().nonnegative().optional().describe("Precio mostrado en el resultado"),
|
|
197
|
+
currency: currency.optional()
|
|
198
|
+
})
|
|
199
|
+
})
|
|
200
|
+
};
|
|
201
|
+
// src/catalog/index.ts
|
|
202
|
+
/**
|
|
203
|
+
* Catálogo de eventos: la ÚNICA fuente de verdad de qué eventos existen y qué props llevan.
|
|
204
|
+
* El collector (inspira-promotions-laravel) valida contra `dist/catalog.json`, que se genera
|
|
205
|
+
* de aquí en el build. Para agregar un evento ver `docs/catalog.md`.
|
|
206
|
+
*/
|
|
207
|
+
const catalog = {
|
|
208
|
+
...pageEvents,
|
|
209
|
+
...adEvents,
|
|
210
|
+
...cardEvents,
|
|
211
|
+
...mapEvents,
|
|
212
|
+
...searchEvents,
|
|
213
|
+
...navigationEvents,
|
|
214
|
+
...conversionEvents
|
|
215
|
+
};
|
|
216
|
+
function isEventName(name) {
|
|
217
|
+
return Object.hasOwn(catalog, name);
|
|
218
|
+
}
|
|
219
|
+
/** Valida las props de un evento contra el catálogo (tests, herramientas server-side). */
|
|
220
|
+
function validateEventProps(name, props) {
|
|
221
|
+
if (!isEventName(name)) return {
|
|
222
|
+
success: false,
|
|
223
|
+
error: `unknown event: ${name}`
|
|
224
|
+
};
|
|
225
|
+
const result = catalog[name].props.safeParse(props);
|
|
226
|
+
return result.success ? { success: true } : {
|
|
227
|
+
success: false,
|
|
228
|
+
error: z.prettifyError(result.error)
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/** Catálogo serializado como JSON Schema (draft 2020-12) para el backend, el MCP y la skill. */
|
|
232
|
+
function toJsonCatalog() {
|
|
233
|
+
const events = {};
|
|
234
|
+
for (const [name, definition] of Object.entries(catalog)) events[name] = {
|
|
235
|
+
description: definition.description,
|
|
236
|
+
domain: definition.domain,
|
|
237
|
+
source: definition.source,
|
|
238
|
+
since: definition.since,
|
|
239
|
+
schema: z.toJSONSchema(definition.props, { io: "input" })
|
|
240
|
+
};
|
|
241
|
+
return {
|
|
242
|
+
sdk_version: SDK_VERSION,
|
|
243
|
+
events
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
export { catalog, isEventName, toJsonCatalog, validateEventProps };
|