luchy 0.2.0 → 1.0.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/README.md +245 -95
- package/dist/api/index.d.ts +21 -9
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +46 -8
- package/dist/api/schema.d.ts +367 -79
- package/dist/identity.d.ts +35 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/index.d.ts +23 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +61 -8
- package/dist/react-router.d.ts +121 -53
- package/dist/react-router.d.ts.map +1 -1
- package/dist/react-router.js +185 -48
- package/dist/script/luchy.js +62 -9
- package/dist/script/luchy.js.br +0 -0
- package/dist/script/luchy.js.gz +0 -0
- package/dist/script/luchy.min.js +62 -9
- package/dist/script/luchy.min.js.br +0 -0
- package/dist/script/luchy.min.js.gz +0 -0
- package/dist/server.d.ts +71 -39
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +114 -26
- package/package.json +17 -2
package/dist/api/schema.d.ts
CHANGED
|
@@ -118,7 +118,7 @@ export interface paths {
|
|
|
118
118
|
patch?: never;
|
|
119
119
|
trace?: never;
|
|
120
120
|
};
|
|
121
|
-
"/
|
|
121
|
+
"/ingest/identify": {
|
|
122
122
|
parameters: {
|
|
123
123
|
query?: never;
|
|
124
124
|
header?: never;
|
|
@@ -127,6 +127,7 @@ export interface paths {
|
|
|
127
127
|
};
|
|
128
128
|
get?: never;
|
|
129
129
|
put?: never;
|
|
130
|
+
/** @description Stores person profile traits. Requires the project's secret key (`lsk_…`) as the bearer token; the public ingest key is rejected. */
|
|
130
131
|
post: {
|
|
131
132
|
parameters: {
|
|
132
133
|
query?: never;
|
|
@@ -136,17 +137,17 @@ export interface paths {
|
|
|
136
137
|
};
|
|
137
138
|
requestBody?: {
|
|
138
139
|
content: {
|
|
139
|
-
"application/json": components["schemas"]["
|
|
140
|
+
"application/json": components["schemas"]["IdentifyInput"];
|
|
140
141
|
};
|
|
141
142
|
};
|
|
142
143
|
responses: {
|
|
143
|
-
/** @description
|
|
144
|
+
/** @description Profile stored */
|
|
144
145
|
200: {
|
|
145
146
|
headers: {
|
|
146
147
|
[name: string]: unknown;
|
|
147
148
|
};
|
|
148
149
|
content: {
|
|
149
|
-
"application/json": components["schemas"]["
|
|
150
|
+
"application/json": components["schemas"]["IdentifyResponse"];
|
|
150
151
|
};
|
|
151
152
|
};
|
|
152
153
|
/** @description Invalid request body or validation error */
|
|
@@ -158,6 +159,131 @@ export interface paths {
|
|
|
158
159
|
"application/json": components["schemas"]["ValidationErrorResponse"];
|
|
159
160
|
};
|
|
160
161
|
};
|
|
162
|
+
/** @description Missing or invalid secret key */
|
|
163
|
+
401: {
|
|
164
|
+
headers: {
|
|
165
|
+
[name: string]: unknown;
|
|
166
|
+
};
|
|
167
|
+
content: {
|
|
168
|
+
"application/json": components["schemas"]["ErrorResponse"];
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
/** @description Internal server error */
|
|
172
|
+
500: {
|
|
173
|
+
headers: {
|
|
174
|
+
[name: string]: unknown;
|
|
175
|
+
};
|
|
176
|
+
content: {
|
|
177
|
+
"application/json": components["schemas"]["ServerErrorResponse"];
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
delete?: never;
|
|
183
|
+
options?: never;
|
|
184
|
+
head?: never;
|
|
185
|
+
patch?: never;
|
|
186
|
+
trace?: never;
|
|
187
|
+
};
|
|
188
|
+
"/analytics/query": {
|
|
189
|
+
parameters: {
|
|
190
|
+
query?: never;
|
|
191
|
+
header?: never;
|
|
192
|
+
path?: never;
|
|
193
|
+
cookie?: never;
|
|
194
|
+
};
|
|
195
|
+
get?: never;
|
|
196
|
+
put?: never;
|
|
197
|
+
/** @description Metrics for the key's project. */
|
|
198
|
+
post: {
|
|
199
|
+
parameters: {
|
|
200
|
+
query?: never;
|
|
201
|
+
header?: never;
|
|
202
|
+
path?: never;
|
|
203
|
+
cookie?: never;
|
|
204
|
+
};
|
|
205
|
+
requestBody?: {
|
|
206
|
+
content: {
|
|
207
|
+
"application/json": components["schemas"]["AnalyticsQueryRequest"];
|
|
208
|
+
};
|
|
209
|
+
};
|
|
210
|
+
responses: {
|
|
211
|
+
/** @description Query result */
|
|
212
|
+
200: {
|
|
213
|
+
headers: {
|
|
214
|
+
[name: string]: unknown;
|
|
215
|
+
};
|
|
216
|
+
content: {
|
|
217
|
+
"application/json": components["schemas"]["AnalyticsQueryResponse"];
|
|
218
|
+
};
|
|
219
|
+
};
|
|
220
|
+
/** @description Invalid request */
|
|
221
|
+
400: {
|
|
222
|
+
headers: {
|
|
223
|
+
[name: string]: unknown;
|
|
224
|
+
};
|
|
225
|
+
content: {
|
|
226
|
+
"application/json": components["schemas"]["ValidationErrorResponse"];
|
|
227
|
+
};
|
|
228
|
+
};
|
|
229
|
+
/** @description Internal server error */
|
|
230
|
+
500: {
|
|
231
|
+
headers: {
|
|
232
|
+
[name: string]: unknown;
|
|
233
|
+
};
|
|
234
|
+
content: {
|
|
235
|
+
"application/json": components["schemas"]["ServerErrorResponse"];
|
|
236
|
+
};
|
|
237
|
+
};
|
|
238
|
+
};
|
|
239
|
+
};
|
|
240
|
+
delete?: never;
|
|
241
|
+
options?: never;
|
|
242
|
+
head?: never;
|
|
243
|
+
patch?: never;
|
|
244
|
+
trace?: never;
|
|
245
|
+
};
|
|
246
|
+
"/analytics/sql": {
|
|
247
|
+
parameters: {
|
|
248
|
+
query?: never;
|
|
249
|
+
header?: never;
|
|
250
|
+
path?: never;
|
|
251
|
+
cookie?: never;
|
|
252
|
+
};
|
|
253
|
+
get?: never;
|
|
254
|
+
put?: never;
|
|
255
|
+
/** @description Read-only SQL over the whole database — not scoped to the key’s project. Luchy is single-owner, so any valid query key may use it; filter on project_id yourself. */
|
|
256
|
+
post: {
|
|
257
|
+
parameters: {
|
|
258
|
+
query?: never;
|
|
259
|
+
header?: never;
|
|
260
|
+
path?: never;
|
|
261
|
+
cookie?: never;
|
|
262
|
+
};
|
|
263
|
+
requestBody?: {
|
|
264
|
+
content: {
|
|
265
|
+
"application/json": components["schemas"]["SqlRequest"];
|
|
266
|
+
};
|
|
267
|
+
};
|
|
268
|
+
responses: {
|
|
269
|
+
/** @description Rows */
|
|
270
|
+
200: {
|
|
271
|
+
headers: {
|
|
272
|
+
[name: string]: unknown;
|
|
273
|
+
};
|
|
274
|
+
content: {
|
|
275
|
+
"application/json": components["schemas"]["SqlResponse"];
|
|
276
|
+
};
|
|
277
|
+
};
|
|
278
|
+
/** @description Invalid request */
|
|
279
|
+
400: {
|
|
280
|
+
headers: {
|
|
281
|
+
[name: string]: unknown;
|
|
282
|
+
};
|
|
283
|
+
content: {
|
|
284
|
+
"application/json": components["schemas"]["ValidationErrorResponse"];
|
|
285
|
+
};
|
|
286
|
+
};
|
|
161
287
|
/** @description Internal server error */
|
|
162
288
|
500: {
|
|
163
289
|
headers: {
|
|
@@ -175,6 +301,42 @@ export interface paths {
|
|
|
175
301
|
patch?: never;
|
|
176
302
|
trace?: never;
|
|
177
303
|
};
|
|
304
|
+
"/analytics/schema": {
|
|
305
|
+
parameters: {
|
|
306
|
+
query?: never;
|
|
307
|
+
header?: never;
|
|
308
|
+
path?: never;
|
|
309
|
+
cookie?: never;
|
|
310
|
+
};
|
|
311
|
+
/** @description Tables, columns and conventions for writing /analytics/sql queries. */
|
|
312
|
+
get: {
|
|
313
|
+
parameters: {
|
|
314
|
+
query?: never;
|
|
315
|
+
header?: never;
|
|
316
|
+
path?: never;
|
|
317
|
+
cookie?: never;
|
|
318
|
+
};
|
|
319
|
+
requestBody?: never;
|
|
320
|
+
responses: {
|
|
321
|
+
/** @description Schema documentation */
|
|
322
|
+
200: {
|
|
323
|
+
headers: {
|
|
324
|
+
[name: string]: unknown;
|
|
325
|
+
};
|
|
326
|
+
content: {
|
|
327
|
+
"application/json": components["schemas"]["AnalyticsSchemaResponse"];
|
|
328
|
+
};
|
|
329
|
+
};
|
|
330
|
+
};
|
|
331
|
+
};
|
|
332
|
+
put?: never;
|
|
333
|
+
post?: never;
|
|
334
|
+
delete?: never;
|
|
335
|
+
options?: never;
|
|
336
|
+
head?: never;
|
|
337
|
+
patch?: never;
|
|
338
|
+
trace?: never;
|
|
339
|
+
};
|
|
178
340
|
"/health": {
|
|
179
341
|
parameters: {
|
|
180
342
|
query?: never;
|
|
@@ -275,6 +437,15 @@ export interface components {
|
|
|
275
437
|
* @example https://google.com
|
|
276
438
|
*/
|
|
277
439
|
referrer?: string;
|
|
440
|
+
/**
|
|
441
|
+
* @description Pageview properties
|
|
442
|
+
* @example {
|
|
443
|
+
* "plan": "pro"
|
|
444
|
+
* }
|
|
445
|
+
*/
|
|
446
|
+
payload?: {
|
|
447
|
+
[key: string]: string | number | boolean;
|
|
448
|
+
};
|
|
278
449
|
/**
|
|
279
450
|
* @description The user agent string
|
|
280
451
|
* @example Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36
|
|
@@ -286,10 +457,20 @@ export interface components {
|
|
|
286
457
|
*/
|
|
287
458
|
language?: string;
|
|
288
459
|
/**
|
|
289
|
-
* @description The user country code
|
|
460
|
+
* @description The user country code. Wins over the country Cloudflare infers from the request.
|
|
290
461
|
* @example US
|
|
291
462
|
*/
|
|
292
463
|
country?: string;
|
|
464
|
+
/**
|
|
465
|
+
* @description Signed identity token (`base64url(json).base64url(hmac)`). An invalid token is ignored and the event is stored anonymously.
|
|
466
|
+
* @example eyJ1IjoidV8xIn0.3q2-7w
|
|
467
|
+
*/
|
|
468
|
+
identity?: string;
|
|
469
|
+
/**
|
|
470
|
+
* @description Client IP, for server-side senders. Only used to derive the daily visitor hash; never stored. Defaults to the connecting IP.
|
|
471
|
+
* @example 203.0.113.7
|
|
472
|
+
*/
|
|
473
|
+
ip?: string;
|
|
293
474
|
};
|
|
294
475
|
/** @description Event tracking data */
|
|
295
476
|
EventInput: {
|
|
@@ -339,99 +520,206 @@ export interface components {
|
|
|
339
520
|
*/
|
|
340
521
|
language?: string;
|
|
341
522
|
/**
|
|
342
|
-
* @description The user country code
|
|
523
|
+
* @description The user country code. Wins over the country Cloudflare infers from the request.
|
|
343
524
|
* @example US
|
|
344
525
|
*/
|
|
345
526
|
country?: string;
|
|
527
|
+
/**
|
|
528
|
+
* @description Signed identity token (`base64url(json).base64url(hmac)`). An invalid token is ignored and the event is stored anonymously.
|
|
529
|
+
* @example eyJ1IjoidV8xIn0.3q2-7w
|
|
530
|
+
*/
|
|
531
|
+
identity?: string;
|
|
532
|
+
/**
|
|
533
|
+
* @description Client IP, for server-side senders. Only used to derive the daily visitor hash; never stored. Defaults to the connecting IP.
|
|
534
|
+
* @example 203.0.113.7
|
|
535
|
+
*/
|
|
536
|
+
ip?: string;
|
|
346
537
|
};
|
|
347
|
-
/**
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
538
|
+
/** @description Profile stored */
|
|
539
|
+
IdentifyResponse: {
|
|
540
|
+
/** @example true */
|
|
541
|
+
success: boolean;
|
|
542
|
+
};
|
|
543
|
+
/** @description Error response */
|
|
544
|
+
ErrorResponse: {
|
|
545
|
+
/**
|
|
546
|
+
* @description Error message
|
|
547
|
+
* @example Invalid request body
|
|
548
|
+
*/
|
|
549
|
+
error: string;
|
|
550
|
+
/**
|
|
551
|
+
* @description Detailed error information
|
|
552
|
+
* @example Invalid JSON format
|
|
553
|
+
*/
|
|
554
|
+
details: string;
|
|
555
|
+
};
|
|
556
|
+
/** @description Person profile traits */
|
|
557
|
+
IdentifyInput: {
|
|
558
|
+
/**
|
|
559
|
+
* @description The stable user id, the same one identity tokens carry as `user`.
|
|
560
|
+
* @example usr_7Hq2mXk9
|
|
561
|
+
*/
|
|
562
|
+
user: string;
|
|
563
|
+
/**
|
|
564
|
+
* @description Merged into the stored profile. `null` deletes a trait. The dashboard labels a person by `name`, else `email`, else the id.
|
|
565
|
+
* @example {
|
|
566
|
+
* "name": "María Pérez",
|
|
567
|
+
* "email": "maria@example.com"
|
|
568
|
+
* }
|
|
569
|
+
*/
|
|
570
|
+
traits: {
|
|
571
|
+
[key: string]: string | number | boolean | unknown | unknown;
|
|
572
|
+
};
|
|
573
|
+
};
|
|
574
|
+
AnalyticsPeriod: {
|
|
575
|
+
from: string;
|
|
576
|
+
to: string;
|
|
577
|
+
totals: {
|
|
578
|
+
events?: number;
|
|
579
|
+
pageviews?: number;
|
|
580
|
+
sessions?: number;
|
|
581
|
+
visitors?: number;
|
|
582
|
+
users?: number;
|
|
583
|
+
avg_duration?: number;
|
|
584
|
+
bounce_rate?: number;
|
|
585
|
+
};
|
|
586
|
+
rows?: {
|
|
587
|
+
events?: number;
|
|
588
|
+
pageviews?: number;
|
|
589
|
+
sessions?: number;
|
|
590
|
+
visitors?: number;
|
|
591
|
+
users?: number;
|
|
592
|
+
avg_duration?: number;
|
|
593
|
+
bounce_rate?: number;
|
|
594
|
+
key: string | number | unknown;
|
|
595
|
+
}[];
|
|
596
|
+
series?: {
|
|
597
|
+
events?: number;
|
|
598
|
+
pageviews?: number;
|
|
599
|
+
sessions?: number;
|
|
600
|
+
visitors?: number;
|
|
601
|
+
users?: number;
|
|
602
|
+
avg_duration?: number;
|
|
603
|
+
bounce_rate?: number;
|
|
604
|
+
bucket: string;
|
|
605
|
+
}[];
|
|
606
|
+
};
|
|
607
|
+
AnalyticsQueryResponse: {
|
|
608
|
+
current: components["schemas"]["AnalyticsPeriod"];
|
|
609
|
+
previous?: components["schemas"]["AnalyticsPeriod"];
|
|
610
|
+
delta?: {
|
|
611
|
+
events?: {
|
|
612
|
+
abs: number;
|
|
613
|
+
/** @description null when previous is 0 */
|
|
614
|
+
pct: number | null;
|
|
615
|
+
};
|
|
616
|
+
pageviews?: {
|
|
617
|
+
abs: number;
|
|
618
|
+
/** @description null when previous is 0 */
|
|
619
|
+
pct: number | null;
|
|
620
|
+
};
|
|
621
|
+
sessions?: {
|
|
622
|
+
abs: number;
|
|
623
|
+
/** @description null when previous is 0 */
|
|
624
|
+
pct: number | null;
|
|
625
|
+
};
|
|
626
|
+
visitors?: {
|
|
627
|
+
abs: number;
|
|
628
|
+
/** @description null when previous is 0 */
|
|
629
|
+
pct: number | null;
|
|
630
|
+
};
|
|
631
|
+
users?: {
|
|
632
|
+
abs: number;
|
|
633
|
+
/** @description null when previous is 0 */
|
|
634
|
+
pct: number | null;
|
|
635
|
+
};
|
|
636
|
+
avg_duration?: {
|
|
637
|
+
abs: number;
|
|
638
|
+
/** @description null when previous is 0 */
|
|
639
|
+
pct: number | null;
|
|
640
|
+
};
|
|
641
|
+
bounce_rate?: {
|
|
642
|
+
abs: number;
|
|
643
|
+
/** @description null when previous is 0 */
|
|
644
|
+
pct: number | null;
|
|
645
|
+
};
|
|
364
646
|
};
|
|
365
|
-
|
|
647
|
+
};
|
|
648
|
+
AnalyticsQueryRequest: {
|
|
649
|
+
/**
|
|
650
|
+
* @description Inclusive start (ISO 8601)
|
|
651
|
+
* @example 2025-01-01T00:00:00Z
|
|
652
|
+
*/
|
|
653
|
+
from: string;
|
|
654
|
+
/**
|
|
655
|
+
* @description Exclusive end (ISO 8601)
|
|
656
|
+
* @example 2025-02-01T00:00:00Z
|
|
657
|
+
*/
|
|
658
|
+
to: string;
|
|
659
|
+
/**
|
|
660
|
+
* @description IANA timezone for buckets, hour and weekday. Default UTC.
|
|
661
|
+
* @example America/Santo_Domingo
|
|
662
|
+
*/
|
|
366
663
|
tz?: string;
|
|
367
664
|
/**
|
|
368
|
-
* @description
|
|
665
|
+
* @description Every metric is computed. visitors = distinct coalesce(user, visitor_hash); avg_duration in seconds; bounce_rate in %.
|
|
369
666
|
* @example [
|
|
370
667
|
* "pageviews",
|
|
371
668
|
* "visitors"
|
|
372
669
|
* ]
|
|
373
670
|
*/
|
|
374
|
-
metrics: ("
|
|
671
|
+
metrics: ("events" | "pageviews" | "sessions" | "visitors" | "users" | "avg_duration" | "bounce_rate")[];
|
|
672
|
+
/**
|
|
673
|
+
* @description A fixed field or `props.<key>` (a key of the event payload). `hour` and `weekday` (0 = Sunday) are in `tz`.
|
|
674
|
+
* @example tenant
|
|
675
|
+
*/
|
|
676
|
+
breakdown?: ("page" | "event" | "type" | "source" | "referrer" | "country" | "device" | "browser" | "os" | "tenant" | "user" | "actor" | "hour" | "weekday") | string;
|
|
375
677
|
/**
|
|
376
|
-
* @description
|
|
678
|
+
* @description [field, op, value]; `in` takes a list.
|
|
377
679
|
* @example [
|
|
378
|
-
*
|
|
680
|
+
* [
|
|
681
|
+
* "props.role",
|
|
682
|
+
* "eq",
|
|
683
|
+
* "admin"
|
|
684
|
+
* ]
|
|
379
685
|
* ]
|
|
380
686
|
*/
|
|
381
|
-
|
|
382
|
-
/**
|
|
383
|
-
* @description
|
|
384
|
-
* @
|
|
385
|
-
*/
|
|
386
|
-
|
|
387
|
-
/**
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
pagination?: {
|
|
394
|
-
/**
|
|
395
|
-
* @default 100
|
|
396
|
-
* @example 50
|
|
397
|
-
*/
|
|
398
|
-
limit: number;
|
|
399
|
-
/**
|
|
400
|
-
* @default 0
|
|
401
|
-
* @example 0
|
|
402
|
-
*/
|
|
403
|
-
offset: number;
|
|
404
|
-
};
|
|
405
|
-
/** @description Additional data to include in response */
|
|
406
|
-
include?: {
|
|
407
|
-
/** @default false */
|
|
408
|
-
time_labels: boolean;
|
|
409
|
-
/** @default false */
|
|
410
|
-
total_rows: boolean;
|
|
411
|
-
/**
|
|
412
|
-
* @default daily
|
|
413
|
-
* @enum {string}
|
|
414
|
-
*/
|
|
415
|
-
granularity: "hourly" | "daily" | "weekly" | "monthly" | "yearly";
|
|
687
|
+
filters?: ((("page" | "event" | "type" | "source" | "referrer" | "country" | "device" | "browser" | "os" | "tenant" | "user" | "actor" | "hour" | "weekday") | string) | ("eq" | "neq" | "in") | (string | number | boolean | unknown | (string | number | boolean | unknown | unknown)[] | unknown))[][];
|
|
688
|
+
/**
|
|
689
|
+
* @description Adds a zero-filled time series
|
|
690
|
+
* @enum {string}
|
|
691
|
+
*/
|
|
692
|
+
granularity?: "hour" | "day" | "week" | "month";
|
|
693
|
+
/** @description Also runs the query on another range and returns deltas */
|
|
694
|
+
compare?: "previous_period" | {
|
|
695
|
+
/** @example 2025-01-01T00:00:00Z */
|
|
696
|
+
from: string;
|
|
697
|
+
/** @example 2025-02-01T00:00:00Z */
|
|
698
|
+
to: string;
|
|
416
699
|
};
|
|
700
|
+
/** @description Max breakdown rows (default 100) */
|
|
701
|
+
limit?: number;
|
|
417
702
|
};
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
QueryResponse: {
|
|
423
|
-
/** @description Query results */
|
|
424
|
-
results: {
|
|
425
|
-
dimensions: string[];
|
|
426
|
-
metrics: number[];
|
|
427
|
-
time_series?: number[];
|
|
703
|
+
SqlResponse: {
|
|
704
|
+
columns: string[];
|
|
705
|
+
rows: {
|
|
706
|
+
[key: string]: unknown;
|
|
428
707
|
}[];
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
708
|
+
truncated: boolean;
|
|
709
|
+
};
|
|
710
|
+
SqlRequest: {
|
|
711
|
+
/**
|
|
712
|
+
* @description One SELECT or WITH statement. See GET /analytics/schema.
|
|
713
|
+
* @example SELECT tenant, COUNT(*) AS actions FROM events WHERE project_id = ? GROUP BY tenant
|
|
714
|
+
*/
|
|
715
|
+
query: string;
|
|
716
|
+
/** @description Bound to `?` placeholders in order */
|
|
717
|
+
params?: (string | number | boolean | unknown | unknown)[];
|
|
718
|
+
/** @description Max rows (default 1000) */
|
|
719
|
+
limit?: number;
|
|
720
|
+
};
|
|
721
|
+
AnalyticsSchemaResponse: {
|
|
722
|
+
doc: string;
|
|
435
723
|
};
|
|
436
724
|
/** @description Health check response */
|
|
437
725
|
HealthResponse: {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signed identity tokens.
|
|
3
|
+
*
|
|
4
|
+
* Ingest only trusts who a hit belongs to when the app vouches for it: the
|
|
5
|
+
* server signs `{ user, actor?, tenant? }` with the project's secret key,
|
|
6
|
+
* the token travels with the hit (browser or server), and ingest verifies it.
|
|
7
|
+
* An unsigned or tampered token is dropped and the hit is stored anonymous, so
|
|
8
|
+
* a visitor cannot attribute traffic to someone else by editing the page.
|
|
9
|
+
*
|
|
10
|
+
* WebCrypto only — runs in Workers, Node >= 18, Bun and Deno.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Who a hit belongs to. `user` is the account being viewed as, `actor` the
|
|
16
|
+
* person actually acting when they differ (impersonation), `tenant` the app's
|
|
17
|
+
* own workspace/client id.
|
|
18
|
+
*/
|
|
19
|
+
export type LuchyIdentity = {
|
|
20
|
+
user: string;
|
|
21
|
+
actor?: string;
|
|
22
|
+
tenant?: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Signs an identity for ingest.
|
|
26
|
+
*
|
|
27
|
+
* Format: `base64url(JSON({ u, a?, t? })) + "." + base64url(HMAC-SHA256(secret, firstPart))`.
|
|
28
|
+
* The short keys keep the token small: it is rendered into every page.
|
|
29
|
+
*
|
|
30
|
+
* ```ts
|
|
31
|
+
* const token = await signIdentity({ user: 'u_1', tenant: '5' }, env.LUCHY_SECRET);
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function signIdentity(identity: LuchyIdentity, secret: string): Promise<string>;
|
|
35
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAgB9E;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,aAAa,EACvB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAgBjB"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
|
+
export type { LuchyIdentity } from './identity.js';
|
|
2
|
+
/** A property bag. Nested objects are not supported by the ingest API. */
|
|
3
|
+
export type LuchyProps = Record<string, string | number | boolean>;
|
|
1
4
|
export type LuchyInitOptions = {
|
|
2
5
|
endpoint?: string;
|
|
3
6
|
apiKey: string;
|
|
4
7
|
trackLocalhost?: boolean;
|
|
8
|
+
/** A signed identity token (see `signIdentity` in `luchy/server`). */
|
|
9
|
+
identity?: string;
|
|
10
|
+
/** Merged into the payload of every event and pageview. */
|
|
11
|
+
props?: LuchyProps;
|
|
12
|
+
/**
|
|
13
|
+
* The script tag the tracker was loaded from. When set, `data-identity` and
|
|
14
|
+
* `data-props` are read from it on every send (so a server re-render after
|
|
15
|
+
* login is picked up), and `identify`/`reset` write to it.
|
|
16
|
+
*/
|
|
17
|
+
script?: Element;
|
|
5
18
|
};
|
|
6
19
|
export type LuchyTrackerOptions = {
|
|
7
20
|
autoPageviews?: boolean;
|
|
@@ -13,10 +26,19 @@ export type LuchyTracker = {
|
|
|
13
26
|
trackPageview(data?: {
|
|
14
27
|
pathname?: string;
|
|
15
28
|
referrer?: string;
|
|
29
|
+
payload?: LuchyProps;
|
|
16
30
|
}): Promise<void>;
|
|
17
|
-
trackEvent(name: string, payload?:
|
|
31
|
+
trackEvent(name: string, payload?: LuchyProps, options?: {
|
|
18
32
|
type?: string;
|
|
19
33
|
}): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Attributes everything sent from now on to a signed identity token, for
|
|
36
|
+
* SPAs that learn who the user is after load. `props` replace the current
|
|
37
|
+
* ones.
|
|
38
|
+
*/
|
|
39
|
+
identify(token: string, props?: LuchyProps): void;
|
|
40
|
+
/** Back to anonymous, e.g. on logout. Drops props too. */
|
|
41
|
+
reset(): void;
|
|
20
42
|
setOptions(options: LuchyTrackerOptions): void;
|
|
21
43
|
};
|
|
22
44
|
/**
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,0EAA0E;AAC1E,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAEnE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,aAAa,CAAC,IAAI,CAAC,EAAE;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,UAAU,CAAC;KACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClB,UAAU,CACR,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,UAAU,EACpB,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAClD,0DAA0D;IAC1D,KAAK,IAAI,IAAI,CAAC;IACd,UAAU,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAAC;CAChD,CAAC;AAgBF;;GAEG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,gBAAgB,GAAG,YAAY,CA2Z7D"}
|