@reopt-ai/data-contract 0.3.0 → 0.6.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 (84) hide show
  1. package/README.md +11 -4
  2. package/dist/{chunk-2LJ7JLDX.js → chunk-33BCA2LH.js} +8 -16
  3. package/dist/chunk-33BCA2LH.js.map +1 -0
  4. package/dist/chunk-3EEANNYN.cjs +62 -0
  5. package/dist/chunk-3EEANNYN.cjs.map +1 -0
  6. package/dist/{chunk-3A7WZ7L6.js → chunk-5BRCHDS3.js} +26 -7
  7. package/dist/chunk-5BRCHDS3.js.map +1 -0
  8. package/dist/chunk-6ZJOC4NJ.js +111 -0
  9. package/dist/chunk-6ZJOC4NJ.js.map +1 -0
  10. package/dist/chunk-FP2X3PRK.js +62 -0
  11. package/dist/chunk-FP2X3PRK.js.map +1 -0
  12. package/dist/{chunk-I2T4HRBM.cjs → chunk-FUGY5ANJ.cjs} +131 -19
  13. package/dist/chunk-FUGY5ANJ.cjs.map +1 -0
  14. package/dist/chunk-IXPP5K4I.js +19 -0
  15. package/dist/chunk-IXPP5K4I.js.map +1 -0
  16. package/dist/{chunk-J4VD3TLV.js → chunk-IY4MXH35.js} +30 -4
  17. package/dist/chunk-IY4MXH35.js.map +1 -0
  18. package/dist/chunk-JHHCT3GA.cjs +19 -0
  19. package/dist/chunk-JHHCT3GA.cjs.map +1 -0
  20. package/dist/chunk-KRJPEMFD.cjs +111 -0
  21. package/dist/chunk-KRJPEMFD.cjs.map +1 -0
  22. package/dist/{chunk-55IWO4S3.js → chunk-L3WJGIKD.js} +123 -11
  23. package/dist/chunk-L3WJGIKD.js.map +1 -0
  24. package/dist/{chunk-ATPS4UV6.cjs → chunk-LA5F5KR6.cjs} +33 -7
  25. package/dist/chunk-LA5F5KR6.cjs.map +1 -0
  26. package/dist/{chunk-RDPPPFGO.cjs → chunk-OGL3P7IH.cjs} +30 -11
  27. package/dist/chunk-OGL3P7IH.cjs.map +1 -0
  28. package/dist/{chunk-KXEQGD3E.cjs → chunk-YSAEOYPD.cjs} +9 -17
  29. package/dist/chunk-YSAEOYPD.cjs.map +1 -0
  30. package/dist/client.cjs +87 -43
  31. package/dist/client.cjs.map +1 -1
  32. package/dist/client.d.cts +8 -2
  33. package/dist/client.d.ts +8 -2
  34. package/dist/client.js +50 -6
  35. package/dist/client.js.map +1 -1
  36. package/dist/control.cjs +15 -4
  37. package/dist/control.cjs.map +1 -1
  38. package/dist/control.d.cts +43 -1
  39. package/dist/control.d.ts +43 -1
  40. package/dist/control.js +16 -5
  41. package/dist/events.cjs +17 -0
  42. package/dist/events.cjs.map +1 -0
  43. package/dist/events.d.cts +59 -0
  44. package/dist/events.d.ts +59 -0
  45. package/dist/events.js +17 -0
  46. package/dist/events.js.map +1 -0
  47. package/dist/identity.cjs +47 -0
  48. package/dist/identity.cjs.map +1 -0
  49. package/dist/identity.d.cts +90 -0
  50. package/dist/identity.d.ts +90 -0
  51. package/dist/identity.js +47 -0
  52. package/dist/identity.js.map +1 -0
  53. package/dist/index.cjs +4 -2
  54. package/dist/index.cjs.map +1 -1
  55. package/dist/index.d.cts +7 -17
  56. package/dist/index.d.ts +7 -17
  57. package/dist/index.js +7 -5
  58. package/dist/ingest.cjs +16 -2
  59. package/dist/ingest.cjs.map +1 -1
  60. package/dist/ingest.d.cts +6 -3
  61. package/dist/ingest.d.ts +6 -3
  62. package/dist/ingest.js +16 -2
  63. package/dist/query.cjs +28 -3
  64. package/dist/query.cjs.map +1 -1
  65. package/dist/query.d.cts +299 -18
  66. package/dist/query.d.ts +299 -18
  67. package/dist/query.js +29 -4
  68. package/dist/report.cjs +85 -0
  69. package/dist/report.cjs.map +1 -0
  70. package/dist/report.d.cts +167 -0
  71. package/dist/report.d.ts +167 -0
  72. package/dist/report.js +85 -0
  73. package/dist/report.js.map +1 -0
  74. package/dist/version-CC4_BBvq.d.cts +26 -0
  75. package/dist/version-CC4_BBvq.d.ts +26 -0
  76. package/package.json +18 -2
  77. package/dist/chunk-2LJ7JLDX.js.map +0 -1
  78. package/dist/chunk-3A7WZ7L6.js.map +0 -1
  79. package/dist/chunk-55IWO4S3.js.map +0 -1
  80. package/dist/chunk-ATPS4UV6.cjs.map +0 -1
  81. package/dist/chunk-I2T4HRBM.cjs.map +0 -1
  82. package/dist/chunk-J4VD3TLV.js.map +0 -1
  83. package/dist/chunk-KXEQGD3E.cjs.map +0 -1
  84. package/dist/chunk-RDPPPFGO.cjs.map +0 -1
package/dist/query.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  export { zDate, zInstant } from './index.js';
3
+ import './version-CC4_BBvq.js';
3
4
 
4
5
  /**
5
6
  * `POST /api/v1/query/*` — the read contract.
@@ -16,10 +17,10 @@ export { zDate, zInstant } from './index.js';
16
17
 
17
18
  /** Bucket width for a time series. */
18
19
  declare const zGranularity: z.ZodEnum<{
19
- hour: "hour";
20
+ month: "month";
20
21
  day: "day";
22
+ hour: "hour";
21
23
  week: "week";
22
- month: "month";
23
24
  }>;
24
25
  type Granularity = z.infer<typeof zGranularity>;
25
26
  /**
@@ -54,13 +55,29 @@ type ChannelFilter = z.infer<typeof zChannelFilter>;
54
55
  * TTL, while ingest lag means the read model is genuinely behind and the right
55
56
  * response is an "aggregating" badge, not a refresh.
56
57
  */
58
+ declare const zQuerySource: z.ZodEnum<{
59
+ rollup: "rollup";
60
+ raw: "raw";
61
+ mixed: "mixed";
62
+ }>;
63
+ type QuerySource = z.infer<typeof zQuerySource>;
57
64
  declare const zQueryMeta: z.ZodObject<{
58
65
  projectId: z.ZodString;
59
66
  computedAt: z.ZodString;
60
67
  cacheAgeSeconds: z.ZodNumber;
61
- ingestLagSeconds: z.ZodNumber;
68
+ ingestLagSeconds: z.ZodNullable<z.ZodNumber>;
69
+ ingestLagStatus: z.ZodEnum<{
70
+ unknown: "unknown";
71
+ known: "known";
72
+ }>;
73
+ ingestDeadLetterCount: z.ZodNullable<z.ZodNumber>;
62
74
  cached: z.ZodBoolean;
63
75
  timezone: z.ZodString;
76
+ source: z.ZodEnum<{
77
+ rollup: "rollup";
78
+ raw: "raw";
79
+ mixed: "mixed";
80
+ }>;
64
81
  requestId: z.ZodString;
65
82
  }, z.core.$strip>;
66
83
  type QueryMeta = z.infer<typeof zQueryMeta>;
@@ -71,9 +88,19 @@ declare function zQueryEnvelope<T extends z.ZodTypeAny>(data: T): z.ZodObject<{
71
88
  projectId: z.ZodString;
72
89
  computedAt: z.ZodString;
73
90
  cacheAgeSeconds: z.ZodNumber;
74
- ingestLagSeconds: z.ZodNumber;
91
+ ingestLagSeconds: z.ZodNullable<z.ZodNumber>;
92
+ ingestLagStatus: z.ZodEnum<{
93
+ unknown: "unknown";
94
+ known: "known";
95
+ }>;
96
+ ingestDeadLetterCount: z.ZodNullable<z.ZodNumber>;
75
97
  cached: z.ZodBoolean;
76
98
  timezone: z.ZodString;
99
+ source: z.ZodEnum<{
100
+ rollup: "rollup";
101
+ raw: "raw";
102
+ mixed: "mixed";
103
+ }>;
77
104
  requestId: z.ZodString;
78
105
  }, z.core.$strip>;
79
106
  }, z.core.$strip>;
@@ -88,17 +115,29 @@ declare const zTimeseriesBreakdown: z.ZodObject<{
88
115
  topN: z.ZodDefault<z.ZodNumber>;
89
116
  }, z.core.$strip>;
90
117
  type TimeseriesBreakdown = z.infer<typeof zTimeseriesBreakdown>;
118
+ /** Exact-match filter for a top-level event `properties` key. Multiple filters are ANDed. */
119
+ declare const zEventPropertyFilter: z.ZodObject<{
120
+ key: z.ZodString;
121
+ operator: z.ZodDefault<z.ZodLiteral<"eq">>;
122
+ value: z.ZodString;
123
+ }, z.core.$strip>;
124
+ type EventPropertyFilter = z.infer<typeof zEventPropertyFilter>;
91
125
  declare const zEventsTimeseriesInput: z.ZodObject<{
92
126
  projectId: z.ZodString;
93
127
  startDate: z.ZodString;
94
128
  endDate: z.ZodString;
95
129
  granularity: z.ZodDefault<z.ZodEnum<{
96
- hour: "hour";
130
+ month: "month";
97
131
  day: "day";
132
+ hour: "hour";
98
133
  week: "week";
99
- month: "month";
100
134
  }>>;
101
135
  eventName: z.ZodOptional<z.ZodString>;
136
+ propertyFilters: z.ZodOptional<z.ZodArray<z.ZodObject<{
137
+ key: z.ZodString;
138
+ operator: z.ZodDefault<z.ZodLiteral<"eq">>;
139
+ value: z.ZodString;
140
+ }, z.core.$strip>>>;
102
141
  breakdown: z.ZodOptional<z.ZodObject<{
103
142
  kind: z.ZodLiteral<"property">;
104
143
  key: z.ZodString;
@@ -106,6 +145,7 @@ declare const zEventsTimeseriesInput: z.ZodObject<{
106
145
  }, z.core.$strip>>;
107
146
  segmentId: z.ZodOptional<z.ZodString>;
108
147
  timezone: z.ZodOptional<z.ZodString>;
148
+ includeInternal: z.ZodDefault<z.ZodBoolean>;
109
149
  }, z.core.$strip>;
110
150
  type EventsTimeseriesInput = z.input<typeof zEventsTimeseriesInput>;
111
151
  /**
@@ -129,10 +169,10 @@ declare const zTimeseriesPoint: z.ZodObject<{
129
169
  type TimeseriesPoint = z.infer<typeof zTimeseriesPoint>;
130
170
  declare const zEventsTimeseriesData: z.ZodObject<{
131
171
  granularity: z.ZodEnum<{
132
- hour: "hour";
172
+ month: "month";
133
173
  day: "day";
174
+ hour: "hour";
134
175
  week: "week";
135
- month: "month";
136
176
  }>;
137
177
  timezone: z.ZodString;
138
178
  series: z.ZodArray<z.ZodObject<{
@@ -151,10 +191,10 @@ type EventsTimeseriesData = z.infer<typeof zEventsTimeseriesData>;
151
191
  declare const zEventsTimeseriesResponse: z.ZodObject<{
152
192
  data: z.ZodObject<{
153
193
  granularity: z.ZodEnum<{
154
- hour: "hour";
194
+ month: "month";
155
195
  day: "day";
196
+ hour: "hour";
156
197
  week: "week";
157
- month: "month";
158
198
  }>;
159
199
  timezone: z.ZodString;
160
200
  series: z.ZodArray<z.ZodObject<{
@@ -173,9 +213,19 @@ declare const zEventsTimeseriesResponse: z.ZodObject<{
173
213
  projectId: z.ZodString;
174
214
  computedAt: z.ZodString;
175
215
  cacheAgeSeconds: z.ZodNumber;
176
- ingestLagSeconds: z.ZodNumber;
216
+ ingestLagSeconds: z.ZodNullable<z.ZodNumber>;
217
+ ingestLagStatus: z.ZodEnum<{
218
+ unknown: "unknown";
219
+ known: "known";
220
+ }>;
221
+ ingestDeadLetterCount: z.ZodNullable<z.ZodNumber>;
177
222
  cached: z.ZodBoolean;
178
223
  timezone: z.ZodString;
224
+ source: z.ZodEnum<{
225
+ rollup: "rollup";
226
+ raw: "raw";
227
+ mixed: "mixed";
228
+ }>;
179
229
  requestId: z.ZodString;
180
230
  }, z.core.$strip>;
181
231
  }, z.core.$strip>;
@@ -195,6 +245,7 @@ declare const zFunnelInput: z.ZodObject<{
195
245
  utmCampaigns: z.ZodOptional<z.ZodArray<z.ZodString>>;
196
246
  }, z.core.$strip>>;
197
247
  timezone: z.ZodOptional<z.ZodString>;
248
+ includeInternal: z.ZodDefault<z.ZodBoolean>;
198
249
  }, z.core.$strip>;
199
250
  type FunnelInput = z.input<typeof zFunnelInput>;
200
251
  declare const zFunnelStep: z.ZodObject<{
@@ -235,26 +286,36 @@ declare const zFunnelResponse: z.ZodObject<{
235
286
  projectId: z.ZodString;
236
287
  computedAt: z.ZodString;
237
288
  cacheAgeSeconds: z.ZodNumber;
238
- ingestLagSeconds: z.ZodNumber;
289
+ ingestLagSeconds: z.ZodNullable<z.ZodNumber>;
290
+ ingestLagStatus: z.ZodEnum<{
291
+ unknown: "unknown";
292
+ known: "known";
293
+ }>;
294
+ ingestDeadLetterCount: z.ZodNullable<z.ZodNumber>;
239
295
  cached: z.ZodBoolean;
240
296
  timezone: z.ZodString;
297
+ source: z.ZodEnum<{
298
+ rollup: "rollup";
299
+ raw: "raw";
300
+ mixed: "mixed";
301
+ }>;
241
302
  requestId: z.ZodString;
242
303
  }, z.core.$strip>;
243
304
  }, z.core.$strip>;
244
305
  type FunnelResponse = z.infer<typeof zFunnelResponse>;
245
306
  declare const zRetentionInterval: z.ZodEnum<{
307
+ month: "month";
246
308
  day: "day";
247
309
  week: "week";
248
- month: "month";
249
310
  }>;
250
311
  declare const zRetentionInput: z.ZodObject<{
251
312
  projectId: z.ZodString;
252
313
  startDate: z.ZodString;
253
314
  endDate: z.ZodString;
254
315
  interval: z.ZodDefault<z.ZodEnum<{
316
+ month: "month";
255
317
  day: "day";
256
318
  week: "week";
257
- month: "month";
258
319
  }>>;
259
320
  periods: z.ZodDefault<z.ZodNumber>;
260
321
  startEvent: z.ZodOptional<z.ZodString>;
@@ -276,6 +337,7 @@ declare const zRetentionInput: z.ZodObject<{
276
337
  utmCampaigns: z.ZodOptional<z.ZodArray<z.ZodString>>;
277
338
  }, z.core.$strip>>;
278
339
  timezone: z.ZodOptional<z.ZodString>;
340
+ includeInternal: z.ZodDefault<z.ZodBoolean>;
279
341
  }, z.core.$strip>;
280
342
  type RetentionInput = z.input<typeof zRetentionInput>;
281
343
  declare const zRetentionCell: z.ZodObject<{
@@ -298,9 +360,9 @@ declare const zRetentionData: z.ZodObject<{
298
360
  rate: z.ZodNumber;
299
361
  }, z.core.$strip>>;
300
362
  interval: z.ZodEnum<{
363
+ month: "month";
301
364
  day: "day";
302
365
  week: "week";
303
- month: "month";
304
366
  }>;
305
367
  periods: z.ZodNumber;
306
368
  retentionType: z.ZodEnum<{
@@ -326,9 +388,9 @@ declare const zRetentionResponse: z.ZodObject<{
326
388
  rate: z.ZodNumber;
327
389
  }, z.core.$strip>>;
328
390
  interval: z.ZodEnum<{
391
+ month: "month";
329
392
  day: "day";
330
393
  week: "week";
331
- month: "month";
332
394
  }>;
333
395
  periods: z.ZodNumber;
334
396
  retentionType: z.ZodEnum<{
@@ -341,13 +403,230 @@ declare const zRetentionResponse: z.ZodObject<{
341
403
  projectId: z.ZodString;
342
404
  computedAt: z.ZodString;
343
405
  cacheAgeSeconds: z.ZodNumber;
344
- ingestLagSeconds: z.ZodNumber;
406
+ ingestLagSeconds: z.ZodNullable<z.ZodNumber>;
407
+ ingestLagStatus: z.ZodEnum<{
408
+ unknown: "unknown";
409
+ known: "known";
410
+ }>;
411
+ ingestDeadLetterCount: z.ZodNullable<z.ZodNumber>;
345
412
  cached: z.ZodBoolean;
346
413
  timezone: z.ZodString;
414
+ source: z.ZodEnum<{
415
+ rollup: "rollup";
416
+ raw: "raw";
417
+ mixed: "mixed";
418
+ }>;
347
419
  requestId: z.ZodString;
348
420
  }, z.core.$strip>;
349
421
  }, z.core.$strip>;
350
422
  type RetentionResponse = z.infer<typeof zRetentionResponse>;
423
+ /**
424
+ * Session-level traffic for a brand site, served from the hourly rollups.
425
+ * `newVisitors` counts sessions whose device was first seen inside them;
426
+ * `returningVisitors` is the rest. Both are session counts, not people —
427
+ * "visitor" is the vocabulary the dashboards already use.
428
+ */
429
+ declare const zTrafficOverviewInput: z.ZodObject<{
430
+ projectId: z.ZodString;
431
+ startDate: z.ZodString;
432
+ endDate: z.ZodString;
433
+ granularity: z.ZodDefault<z.ZodEnum<{
434
+ month: "month";
435
+ day: "day";
436
+ hour: "hour";
437
+ week: "week";
438
+ }>>;
439
+ timezone: z.ZodOptional<z.ZodString>;
440
+ }, z.core.$strip>;
441
+ type TrafficOverviewInput = z.input<typeof zTrafficOverviewInput>;
442
+ declare const zTrafficTotals: z.ZodObject<{
443
+ sessions: z.ZodNumber;
444
+ pageviews: z.ZodNumber;
445
+ newVisitors: z.ZodNumber;
446
+ returningVisitors: z.ZodNumber;
447
+ bounceRate: z.ZodNumber;
448
+ }, z.core.$strip>;
449
+ type TrafficTotals = z.infer<typeof zTrafficTotals>;
450
+ declare const zTrafficSeriesPoint: z.ZodObject<{
451
+ sessions: z.ZodNumber;
452
+ pageviews: z.ZodNumber;
453
+ newVisitors: z.ZodNumber;
454
+ returningVisitors: z.ZodNumber;
455
+ bounceRate: z.ZodNumber;
456
+ date: z.ZodString;
457
+ }, z.core.$strip>;
458
+ declare const zTrafficOverviewData: z.ZodObject<{
459
+ granularity: z.ZodEnum<{
460
+ month: "month";
461
+ day: "day";
462
+ hour: "hour";
463
+ week: "week";
464
+ }>;
465
+ timezone: z.ZodString;
466
+ totals: z.ZodObject<{
467
+ sessions: z.ZodNumber;
468
+ pageviews: z.ZodNumber;
469
+ newVisitors: z.ZodNumber;
470
+ returningVisitors: z.ZodNumber;
471
+ bounceRate: z.ZodNumber;
472
+ }, z.core.$strip>;
473
+ series: z.ZodArray<z.ZodObject<{
474
+ sessions: z.ZodNumber;
475
+ pageviews: z.ZodNumber;
476
+ newVisitors: z.ZodNumber;
477
+ returningVisitors: z.ZodNumber;
478
+ bounceRate: z.ZodNumber;
479
+ date: z.ZodString;
480
+ }, z.core.$strip>>;
481
+ }, z.core.$strip>;
482
+ type TrafficOverviewData = z.infer<typeof zTrafficOverviewData>;
483
+ declare const zTrafficOverviewResponse: z.ZodObject<{
484
+ data: z.ZodObject<{
485
+ granularity: z.ZodEnum<{
486
+ month: "month";
487
+ day: "day";
488
+ hour: "hour";
489
+ week: "week";
490
+ }>;
491
+ timezone: z.ZodString;
492
+ totals: z.ZodObject<{
493
+ sessions: z.ZodNumber;
494
+ pageviews: z.ZodNumber;
495
+ newVisitors: z.ZodNumber;
496
+ returningVisitors: z.ZodNumber;
497
+ bounceRate: z.ZodNumber;
498
+ }, z.core.$strip>;
499
+ series: z.ZodArray<z.ZodObject<{
500
+ sessions: z.ZodNumber;
501
+ pageviews: z.ZodNumber;
502
+ newVisitors: z.ZodNumber;
503
+ returningVisitors: z.ZodNumber;
504
+ bounceRate: z.ZodNumber;
505
+ date: z.ZodString;
506
+ }, z.core.$strip>>;
507
+ }, z.core.$strip>;
508
+ meta: z.ZodObject<{
509
+ projectId: z.ZodString;
510
+ computedAt: z.ZodString;
511
+ cacheAgeSeconds: z.ZodNumber;
512
+ ingestLagSeconds: z.ZodNullable<z.ZodNumber>;
513
+ ingestLagStatus: z.ZodEnum<{
514
+ unknown: "unknown";
515
+ known: "known";
516
+ }>;
517
+ ingestDeadLetterCount: z.ZodNullable<z.ZodNumber>;
518
+ cached: z.ZodBoolean;
519
+ timezone: z.ZodString;
520
+ source: z.ZodEnum<{
521
+ rollup: "rollup";
522
+ raw: "raw";
523
+ mixed: "mixed";
524
+ }>;
525
+ requestId: z.ZodString;
526
+ }, z.core.$strip>;
527
+ }, z.core.$strip>;
528
+ type TrafficOverviewResponse = z.infer<typeof zTrafficOverviewResponse>;
529
+ declare const zTrafficDimension: z.ZodEnum<{
530
+ referrer: "referrer";
531
+ channel: "channel";
532
+ utm: "utm";
533
+ }>;
534
+ type TrafficDimension = z.infer<typeof zTrafficDimension>;
535
+ declare const zTrafficSourcesInput: z.ZodObject<{
536
+ projectId: z.ZodString;
537
+ startDate: z.ZodString;
538
+ endDate: z.ZodString;
539
+ dimension: z.ZodEnum<{
540
+ referrer: "referrer";
541
+ channel: "channel";
542
+ utm: "utm";
543
+ }>;
544
+ limit: z.ZodDefault<z.ZodNumber>;
545
+ timezone: z.ZodOptional<z.ZodString>;
546
+ }, z.core.$strip>;
547
+ type TrafficSourcesInput = z.input<typeof zTrafficSourcesInput>;
548
+ declare const zTrafficSourceRow: z.ZodObject<{
549
+ sessions: z.ZodNumber;
550
+ pageviews: z.ZodNumber;
551
+ newVisitors: z.ZodNumber;
552
+ returningVisitors: z.ZodNumber;
553
+ bounceRate: z.ZodNumber;
554
+ key: z.ZodString;
555
+ channelType: z.ZodOptional<z.ZodString>;
556
+ referrerName: z.ZodOptional<z.ZodString>;
557
+ referrerType: z.ZodOptional<z.ZodString>;
558
+ utmSource: z.ZodOptional<z.ZodString>;
559
+ utmMedium: z.ZodOptional<z.ZodString>;
560
+ utmCampaign: z.ZodOptional<z.ZodString>;
561
+ }, z.core.$strip>;
562
+ type TrafficSourceRow = z.infer<typeof zTrafficSourceRow>;
563
+ declare const zTrafficSourcesData: z.ZodObject<{
564
+ dimension: z.ZodEnum<{
565
+ referrer: "referrer";
566
+ channel: "channel";
567
+ utm: "utm";
568
+ }>;
569
+ timezone: z.ZodString;
570
+ rows: z.ZodArray<z.ZodObject<{
571
+ sessions: z.ZodNumber;
572
+ pageviews: z.ZodNumber;
573
+ newVisitors: z.ZodNumber;
574
+ returningVisitors: z.ZodNumber;
575
+ bounceRate: z.ZodNumber;
576
+ key: z.ZodString;
577
+ channelType: z.ZodOptional<z.ZodString>;
578
+ referrerName: z.ZodOptional<z.ZodString>;
579
+ referrerType: z.ZodOptional<z.ZodString>;
580
+ utmSource: z.ZodOptional<z.ZodString>;
581
+ utmMedium: z.ZodOptional<z.ZodString>;
582
+ utmCampaign: z.ZodOptional<z.ZodString>;
583
+ }, z.core.$strip>>;
584
+ }, z.core.$strip>;
585
+ type TrafficSourcesData = z.infer<typeof zTrafficSourcesData>;
586
+ declare const zTrafficSourcesResponse: z.ZodObject<{
587
+ data: z.ZodObject<{
588
+ dimension: z.ZodEnum<{
589
+ referrer: "referrer";
590
+ channel: "channel";
591
+ utm: "utm";
592
+ }>;
593
+ timezone: z.ZodString;
594
+ rows: z.ZodArray<z.ZodObject<{
595
+ sessions: z.ZodNumber;
596
+ pageviews: z.ZodNumber;
597
+ newVisitors: z.ZodNumber;
598
+ returningVisitors: z.ZodNumber;
599
+ bounceRate: z.ZodNumber;
600
+ key: z.ZodString;
601
+ channelType: z.ZodOptional<z.ZodString>;
602
+ referrerName: z.ZodOptional<z.ZodString>;
603
+ referrerType: z.ZodOptional<z.ZodString>;
604
+ utmSource: z.ZodOptional<z.ZodString>;
605
+ utmMedium: z.ZodOptional<z.ZodString>;
606
+ utmCampaign: z.ZodOptional<z.ZodString>;
607
+ }, z.core.$strip>>;
608
+ }, z.core.$strip>;
609
+ meta: z.ZodObject<{
610
+ projectId: z.ZodString;
611
+ computedAt: z.ZodString;
612
+ cacheAgeSeconds: z.ZodNumber;
613
+ ingestLagSeconds: z.ZodNullable<z.ZodNumber>;
614
+ ingestLagStatus: z.ZodEnum<{
615
+ unknown: "unknown";
616
+ known: "known";
617
+ }>;
618
+ ingestDeadLetterCount: z.ZodNullable<z.ZodNumber>;
619
+ cached: z.ZodBoolean;
620
+ timezone: z.ZodString;
621
+ source: z.ZodEnum<{
622
+ rollup: "rollup";
623
+ raw: "raw";
624
+ mixed: "mixed";
625
+ }>;
626
+ requestId: z.ZodString;
627
+ }, z.core.$strip>;
628
+ }, z.core.$strip>;
629
+ type TrafficSourcesResponse = z.infer<typeof zTrafficSourcesResponse>;
351
630
  declare const QUERY_ERROR_CODES: readonly ["unauthorized", "project_scope_mismatch", "query_scope_missing", "validation_failed", "unsupported_combination", "project_purging", "rate_limited", "query_timeout", "internal_error"];
352
631
  declare const zQueryErrorCode: z.ZodEnum<{
353
632
  validation_failed: "validation_failed";
@@ -385,6 +664,8 @@ declare const QUERY_API_PATHS: {
385
664
  readonly eventsTimeseries: "/api/v1/query/events/timeseries";
386
665
  readonly funnel: "/api/v1/query/funnel";
387
666
  readonly retention: "/api/v1/query/retention";
667
+ readonly trafficOverview: "/api/v1/query/traffic/overview";
668
+ readonly trafficSources: "/api/v1/query/traffic/sources";
388
669
  };
389
670
 
390
- export { type ChannelFilter, type EventsTimeseriesData, type EventsTimeseriesInput, type EventsTimeseriesResponse, type FunnelData, type FunnelInput, type FunnelResponse, type Granularity, QUERY_API_PATHS, QUERY_ERROR_CODES, type QueryError, type QueryErrorCode, type QueryMeta, type RetentionData, type RetentionInput, type RetentionResponse, type TimeseriesBreakdown, type TimeseriesPoint, isValidTimeZone, zBucketStart, zChannelFilter, zEventsTimeseriesData, zEventsTimeseriesInput, zEventsTimeseriesResponse, zFunnelData, zFunnelInput, zFunnelResponse, zFunnelStep, zGranularity, zQueryEnvelope, zQueryError, zQueryErrorCode, zQueryMeta, zRetentionCell, zRetentionData, zRetentionInput, zRetentionInterval, zRetentionResponse, zTimeseriesBreakdown, zTimeseriesPoint, zTimezone };
671
+ export { type ChannelFilter, type EventPropertyFilter, type EventsTimeseriesData, type EventsTimeseriesInput, type EventsTimeseriesResponse, type FunnelData, type FunnelInput, type FunnelResponse, type Granularity, QUERY_API_PATHS, QUERY_ERROR_CODES, type QueryError, type QueryErrorCode, type QueryMeta, type QuerySource, type RetentionData, type RetentionInput, type RetentionResponse, type TimeseriesBreakdown, type TimeseriesPoint, type TrafficDimension, type TrafficOverviewData, type TrafficOverviewInput, type TrafficOverviewResponse, type TrafficSourceRow, type TrafficSourcesData, type TrafficSourcesInput, type TrafficSourcesResponse, type TrafficTotals, isValidTimeZone, zBucketStart, zChannelFilter, zEventPropertyFilter, zEventsTimeseriesData, zEventsTimeseriesInput, zEventsTimeseriesResponse, zFunnelData, zFunnelInput, zFunnelResponse, zFunnelStep, zGranularity, zQueryEnvelope, zQueryError, zQueryErrorCode, zQueryMeta, zQuerySource, zRetentionCell, zRetentionData, zRetentionInput, zRetentionInterval, zRetentionResponse, zTimeseriesBreakdown, zTimeseriesPoint, zTimezone, zTrafficDimension, zTrafficOverviewData, zTrafficOverviewInput, zTrafficOverviewResponse, zTrafficSeriesPoint, zTrafficSourceRow, zTrafficSourcesData, zTrafficSourcesInput, zTrafficSourcesResponse, zTrafficTotals };
package/dist/query.js CHANGED
@@ -4,6 +4,7 @@ import {
4
4
  isValidTimeZone,
5
5
  zBucketStart,
6
6
  zChannelFilter,
7
+ zEventPropertyFilter,
7
8
  zEventsTimeseriesData,
8
9
  zEventsTimeseriesInput,
9
10
  zEventsTimeseriesResponse,
@@ -16,6 +17,7 @@ import {
16
17
  zQueryError,
17
18
  zQueryErrorCode,
18
19
  zQueryMeta,
20
+ zQuerySource,
19
21
  zRetentionCell,
20
22
  zRetentionData,
21
23
  zRetentionInput,
@@ -23,12 +25,23 @@ import {
23
25
  zRetentionResponse,
24
26
  zTimeseriesBreakdown,
25
27
  zTimeseriesPoint,
26
- zTimezone
27
- } from "./chunk-55IWO4S3.js";
28
+ zTimezone,
29
+ zTrafficDimension,
30
+ zTrafficOverviewData,
31
+ zTrafficOverviewInput,
32
+ zTrafficOverviewResponse,
33
+ zTrafficSeriesPoint,
34
+ zTrafficSourceRow,
35
+ zTrafficSourcesData,
36
+ zTrafficSourcesInput,
37
+ zTrafficSourcesResponse,
38
+ zTrafficTotals
39
+ } from "./chunk-L3WJGIKD.js";
28
40
  import {
29
41
  zDate,
30
42
  zInstant
31
- } from "./chunk-2LJ7JLDX.js";
43
+ } from "./chunk-33BCA2LH.js";
44
+ import "./chunk-IXPP5K4I.js";
32
45
  export {
33
46
  QUERY_API_PATHS,
34
47
  QUERY_ERROR_CODES,
@@ -36,6 +49,7 @@ export {
36
49
  zBucketStart,
37
50
  zChannelFilter,
38
51
  zDate,
52
+ zEventPropertyFilter,
39
53
  zEventsTimeseriesData,
40
54
  zEventsTimeseriesInput,
41
55
  zEventsTimeseriesResponse,
@@ -49,6 +63,7 @@ export {
49
63
  zQueryError,
50
64
  zQueryErrorCode,
51
65
  zQueryMeta,
66
+ zQuerySource,
52
67
  zRetentionCell,
53
68
  zRetentionData,
54
69
  zRetentionInput,
@@ -56,6 +71,16 @@ export {
56
71
  zRetentionResponse,
57
72
  zTimeseriesBreakdown,
58
73
  zTimeseriesPoint,
59
- zTimezone
74
+ zTimezone,
75
+ zTrafficDimension,
76
+ zTrafficOverviewData,
77
+ zTrafficOverviewInput,
78
+ zTrafficOverviewResponse,
79
+ zTrafficSeriesPoint,
80
+ zTrafficSourceRow,
81
+ zTrafficSourcesData,
82
+ zTrafficSourcesInput,
83
+ zTrafficSourcesResponse,
84
+ zTrafficTotals
60
85
  };
61
86
  //# sourceMappingURL=query.js.map
@@ -0,0 +1,85 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/report.ts
2
+ var _zod = require('zod');
3
+ var REPORT_SPEC_VERSION = 1;
4
+ var zReportRange = _zod.z.string().regex(/^\d+[dhm]$/, "expected a relative range such as 7d or 24h");
5
+ var zReportInterval = _zod.z.enum(["minute", "hour", "day", "week", "month"]);
6
+ var zLegacyChartType = _zod.z.enum([
7
+ "linear",
8
+ "bar",
9
+ "pie",
10
+ "metric",
11
+ "area",
12
+ "gauge",
13
+ "scatter",
14
+ "table",
15
+ "sparkline"
16
+ ]);
17
+ var zCommon = {
18
+ version: _zod.z.literal(REPORT_SPEC_VERSION),
19
+ range: zReportRange.default("30d"),
20
+ segmentId: _zod.z.string().min(1).optional()
21
+ };
22
+ var zTimeseriesReportSpec = _zod.z.object({
23
+ ...zCommon,
24
+ kind: _zod.z.literal("timeseries"),
25
+ chartType: zLegacyChartType,
26
+ interval: zReportInterval,
27
+ events: _zod.z.array(_zod.z.object({ name: _zod.z.string().min(1).max(200) })).min(1).max(20),
28
+ breakdowns: _zod.z.array(_zod.z.string().min(1).max(200)).max(5).default([]),
29
+ comparePrevious: _zod.z.boolean().default(false)
30
+ });
31
+ var zFunnelReportSpec = _zod.z.object({
32
+ ...zCommon,
33
+ kind: _zod.z.literal("funnel"),
34
+ steps: _zod.z.array(_zod.z.string().min(1).max(200)).min(2).max(10),
35
+ windowSeconds: _zod.z.number().int().min(60).max(2592e3).default(86400)
36
+ });
37
+ var zRetentionReportSpec = _zod.z.object({
38
+ ...zCommon,
39
+ kind: _zod.z.literal("retention"),
40
+ interval: _zod.z.enum(["day", "week", "month"]).default("day"),
41
+ periods: _zod.z.number().int().min(1).max(30).default(7),
42
+ startEvent: _zod.z.string().min(1).max(200).optional(),
43
+ returnEvent: _zod.z.string().min(1).max(200).optional(),
44
+ retentionType: _zod.z.enum(["bounded", "unbounded"]).default("bounded"),
45
+ cohortMode: _zod.z.enum(["first-ever", "first-in-window"]).default("first-ever")
46
+ });
47
+ var zPathReportSpec = _zod.z.object({
48
+ ...zCommon,
49
+ kind: _zod.z.literal("path"),
50
+ limit: _zod.z.number().int().min(1).max(100).default(30),
51
+ startPage: _zod.z.string().max(2e3).optional(),
52
+ endPage: _zod.z.string().max(2e3).optional()
53
+ });
54
+ var zReportSpec = _zod.z.discriminatedUnion("kind", [
55
+ zTimeseriesReportSpec,
56
+ zFunnelReportSpec,
57
+ zRetentionReportSpec,
58
+ zPathReportSpec
59
+ ]);
60
+ function legacyReportToSpec(input) {
61
+ const events = _zod.z.array(_zod.z.object({ name: _zod.z.string().min(1).max(200) })).safeParse(input.events);
62
+ const breakdowns = _zod.z.array(_zod.z.string().min(1).max(200)).safeParse(input.breakdowns);
63
+ return zTimeseriesReportSpec.parse({
64
+ version: REPORT_SPEC_VERSION,
65
+ kind: "timeseries",
66
+ chartType: input.chartType,
67
+ interval: input.interval,
68
+ range: input.range,
69
+ events: events.success && events.data.length > 0 ? events.data : [{ name: "$pageview" }],
70
+ breakdowns: breakdowns.success ? breakdowns.data : []
71
+ });
72
+ }
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+
82
+
83
+
84
+ exports.REPORT_SPEC_VERSION = REPORT_SPEC_VERSION; exports.legacyReportToSpec = legacyReportToSpec; exports.zFunnelReportSpec = zFunnelReportSpec; exports.zLegacyChartType = zLegacyChartType; exports.zPathReportSpec = zPathReportSpec; exports.zReportInterval = zReportInterval; exports.zReportRange = zReportRange; exports.zReportSpec = zReportSpec; exports.zRetentionReportSpec = zRetentionReportSpec; exports.zTimeseriesReportSpec = zTimeseriesReportSpec;
85
+ //# sourceMappingURL=report.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/eric/reopt-ai/reopt-data/packages/data-contract/dist/report.cjs","../src/report.ts"],"names":[],"mappings":"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","file":"/Users/eric/reopt-ai/reopt-data/packages/data-contract/dist/report.cjs","sourcesContent":[null,"import { z } from \"zod\";\n\nexport const REPORT_SPEC_VERSION = 1 as const;\n\nexport const zReportRange = z.string().regex(/^\\d+[dhm]$/, \"expected a relative range such as 7d or 24h\");\nexport const zReportInterval = z.enum([\"minute\", \"hour\", \"day\", \"week\", \"month\"]);\nexport const zLegacyChartType = z.enum([\n \"linear\",\n \"bar\",\n \"pie\",\n \"metric\",\n \"area\",\n \"gauge\",\n \"scatter\",\n \"table\",\n \"sparkline\",\n]);\n\nconst zCommon = {\n version: z.literal(REPORT_SPEC_VERSION),\n range: zReportRange.default(\"30d\"),\n segmentId: z.string().min(1).optional(),\n};\n\nexport const zTimeseriesReportSpec = z.object({\n ...zCommon,\n kind: z.literal(\"timeseries\"),\n chartType: zLegacyChartType,\n interval: zReportInterval,\n events: z\n .array(z.object({ name: z.string().min(1).max(200) }))\n .min(1)\n .max(20),\n breakdowns: z.array(z.string().min(1).max(200)).max(5).default([]),\n comparePrevious: z.boolean().default(false),\n});\n\nexport const zFunnelReportSpec = z.object({\n ...zCommon,\n kind: z.literal(\"funnel\"),\n steps: z.array(z.string().min(1).max(200)).min(2).max(10),\n windowSeconds: z.number().int().min(60).max(2_592_000).default(86_400),\n});\n\nexport const zRetentionReportSpec = z.object({\n ...zCommon,\n kind: z.literal(\"retention\"),\n interval: z.enum([\"day\", \"week\", \"month\"]).default(\"day\"),\n periods: z.number().int().min(1).max(30).default(7),\n startEvent: z.string().min(1).max(200).optional(),\n returnEvent: z.string().min(1).max(200).optional(),\n retentionType: z.enum([\"bounded\", \"unbounded\"]).default(\"bounded\"),\n cohortMode: z.enum([\"first-ever\", \"first-in-window\"]).default(\"first-ever\"),\n});\n\nexport const zPathReportSpec = z.object({\n ...zCommon,\n kind: z.literal(\"path\"),\n limit: z.number().int().min(1).max(100).default(30),\n startPage: z.string().max(2_000).optional(),\n endPage: z.string().max(2_000).optional(),\n});\n\nexport const zReportSpec = z.discriminatedUnion(\"kind\", [\n zTimeseriesReportSpec,\n zFunnelReportSpec,\n zRetentionReportSpec,\n zPathReportSpec,\n]);\n\nexport type ReportSpec = z.infer<typeof zReportSpec>;\nexport type TimeseriesReportSpec = z.infer<typeof zTimeseriesReportSpec>;\n\n/** Convert a pre-ReportSpec row into the canonical v1 representation. */\nexport function legacyReportToSpec(input: {\n chartType: z.infer<typeof zLegacyChartType>;\n interval: z.infer<typeof zReportInterval>;\n range: string;\n events: unknown;\n breakdowns: unknown;\n}): TimeseriesReportSpec {\n const events = z.array(z.object({ name: z.string().min(1).max(200) })).safeParse(input.events);\n const breakdowns = z.array(z.string().min(1).max(200)).safeParse(input.breakdowns);\n return zTimeseriesReportSpec.parse({\n version: REPORT_SPEC_VERSION,\n kind: \"timeseries\",\n chartType: input.chartType,\n interval: input.interval,\n range: input.range,\n events: events.success && events.data.length > 0 ? events.data : [{ name: \"$pageview\" }],\n breakdowns: breakdowns.success ? breakdowns.data : [],\n });\n}\n"]}