@reopt-ai/data-contract 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.
@@ -0,0 +1,374 @@
1
+ import { z } from 'zod';
2
+ export { zDate, zInstant } from './index.cjs';
3
+
4
+ /**
5
+ * `POST /api/v1/query/*` — the read contract.
6
+ *
7
+ * Server credentials, project-scoped: the authenticated client's projectId must
8
+ * equal the `projectId` in the body, or the request is refused. Reads are POSTs
9
+ * because the inputs nest (funnel steps, channel filters) and would not survive
10
+ * a query string; consumers cache on their own side, so HTTP cache semantics
11
+ * buy nothing here.
12
+ *
13
+ * Response shapes mirror the existing dashboard computations exactly — this
14
+ * plane re-exposes them, it does not add new math.
15
+ */
16
+
17
+ /** Bucket width for a time series. */
18
+ declare const zGranularity: z.ZodEnum<{
19
+ hour: "hour";
20
+ day: "day";
21
+ week: "week";
22
+ month: "month";
23
+ }>;
24
+ type Granularity = z.infer<typeof zGranularity>;
25
+ /**
26
+ * IANA time zone name, e.g. `Asia/Seoul`. Decides two things at once: where a
27
+ * calendar day starts, and therefore which bucket an event falls in.
28
+ *
29
+ * A Korean brand reading "23 Aug: 120 visits" means 23 Aug in Seoul. Computed
30
+ * in UTC, that headline silently covers 23 Aug 09:00 through 24 Aug 09:00 —
31
+ * wrong by nine hours in a way nothing on the page reveals.
32
+ *
33
+ * Validated against the runtime's own zone database rather than a regex, so an
34
+ * unknown name fails here with a clear message instead of deep inside a query.
35
+ */
36
+ declare const zTimezone: z.ZodString;
37
+ declare function isValidTimeZone(value: string): boolean;
38
+ /**
39
+ * Acquisition-channel filter. Every field is a set — an event matches when its
40
+ * value is in the set; omitted fields do not constrain. Mirrors the dashboard's
41
+ * `channelFilterSchema` field-for-field.
42
+ */
43
+ declare const zChannelFilter: z.ZodOptional<z.ZodObject<{
44
+ referrerTypes: z.ZodOptional<z.ZodArray<z.ZodString>>;
45
+ channelTypes: z.ZodOptional<z.ZodArray<z.ZodString>>;
46
+ utmSources: z.ZodOptional<z.ZodArray<z.ZodString>>;
47
+ utmMediums: z.ZodOptional<z.ZodArray<z.ZodString>>;
48
+ utmCampaigns: z.ZodOptional<z.ZodArray<z.ZodString>>;
49
+ }, z.core.$strip>>;
50
+ type ChannelFilter = z.infer<typeof zChannelFilter>;
51
+ /**
52
+ * Staleness is reported as two independent numbers, never as one sum, because
53
+ * the two have different remedies: a stale cache resolves itself at the next
54
+ * TTL, while ingest lag means the read model is genuinely behind and the right
55
+ * response is an "aggregating" badge, not a refresh.
56
+ */
57
+ declare const zQueryMeta: z.ZodObject<{
58
+ projectId: z.ZodString;
59
+ computedAt: z.ZodString;
60
+ cacheAgeSeconds: z.ZodNumber;
61
+ ingestLagSeconds: z.ZodNumber;
62
+ cached: z.ZodBoolean;
63
+ timezone: z.ZodString;
64
+ requestId: z.ZodString;
65
+ }, z.core.$strip>;
66
+ type QueryMeta = z.infer<typeof zQueryMeta>;
67
+ /** Every query response is `{ data, meta }`. */
68
+ declare function zQueryEnvelope<T extends z.ZodTypeAny>(data: T): z.ZodObject<{
69
+ data: T;
70
+ meta: z.ZodObject<{
71
+ projectId: z.ZodString;
72
+ computedAt: z.ZodString;
73
+ cacheAgeSeconds: z.ZodNumber;
74
+ ingestLagSeconds: z.ZodNumber;
75
+ cached: z.ZodBoolean;
76
+ timezone: z.ZodString;
77
+ requestId: z.ZodString;
78
+ }, z.core.$strip>;
79
+ }, z.core.$strip>;
80
+ /**
81
+ * v1 breaks down by `properties` JSON keys only. Built-in columns
82
+ * (country / os / browser / utm_*) have a totals breakdown in the backend but
83
+ * no *time series* variant, and this plane does not add new computations.
84
+ */
85
+ declare const zTimeseriesBreakdown: z.ZodObject<{
86
+ kind: z.ZodLiteral<"property">;
87
+ key: z.ZodString;
88
+ topN: z.ZodDefault<z.ZodNumber>;
89
+ }, z.core.$strip>;
90
+ type TimeseriesBreakdown = z.infer<typeof zTimeseriesBreakdown>;
91
+ declare const zEventsTimeseriesInput: z.ZodObject<{
92
+ projectId: z.ZodString;
93
+ startDate: z.ZodString;
94
+ endDate: z.ZodString;
95
+ granularity: z.ZodDefault<z.ZodEnum<{
96
+ hour: "hour";
97
+ day: "day";
98
+ week: "week";
99
+ month: "month";
100
+ }>>;
101
+ eventName: z.ZodOptional<z.ZodString>;
102
+ breakdown: z.ZodOptional<z.ZodObject<{
103
+ kind: z.ZodLiteral<"property">;
104
+ key: z.ZodString;
105
+ topN: z.ZodDefault<z.ZodNumber>;
106
+ }, z.core.$strip>>;
107
+ segmentId: z.ZodOptional<z.ZodString>;
108
+ timezone: z.ZodOptional<z.ZodString>;
109
+ }, z.core.$strip>;
110
+ type EventsTimeseriesInput = z.input<typeof zEventsTimeseriesInput>;
111
+ declare const zTimeseriesPoint: z.ZodObject<{
112
+ date: z.ZodString;
113
+ count: z.ZodNumber;
114
+ }, z.core.$strip>;
115
+ type TimeseriesPoint = z.infer<typeof zTimeseriesPoint>;
116
+ declare const zEventsTimeseriesData: z.ZodObject<{
117
+ granularity: z.ZodEnum<{
118
+ hour: "hour";
119
+ day: "day";
120
+ week: "week";
121
+ month: "month";
122
+ }>;
123
+ timezone: z.ZodString;
124
+ series: z.ZodArray<z.ZodObject<{
125
+ date: z.ZodString;
126
+ count: z.ZodNumber;
127
+ }, z.core.$strip>>;
128
+ breakdown: z.ZodOptional<z.ZodArray<z.ZodObject<{
129
+ value: z.ZodString;
130
+ points: z.ZodArray<z.ZodObject<{
131
+ date: z.ZodString;
132
+ count: z.ZodNumber;
133
+ }, z.core.$strip>>;
134
+ }, z.core.$strip>>>;
135
+ }, z.core.$strip>;
136
+ type EventsTimeseriesData = z.infer<typeof zEventsTimeseriesData>;
137
+ declare const zEventsTimeseriesResponse: z.ZodObject<{
138
+ data: z.ZodObject<{
139
+ granularity: z.ZodEnum<{
140
+ hour: "hour";
141
+ day: "day";
142
+ week: "week";
143
+ month: "month";
144
+ }>;
145
+ timezone: z.ZodString;
146
+ series: z.ZodArray<z.ZodObject<{
147
+ date: z.ZodString;
148
+ count: z.ZodNumber;
149
+ }, z.core.$strip>>;
150
+ breakdown: z.ZodOptional<z.ZodArray<z.ZodObject<{
151
+ value: z.ZodString;
152
+ points: z.ZodArray<z.ZodObject<{
153
+ date: z.ZodString;
154
+ count: z.ZodNumber;
155
+ }, z.core.$strip>>;
156
+ }, z.core.$strip>>>;
157
+ }, z.core.$strip>;
158
+ meta: z.ZodObject<{
159
+ projectId: z.ZodString;
160
+ computedAt: z.ZodString;
161
+ cacheAgeSeconds: z.ZodNumber;
162
+ ingestLagSeconds: z.ZodNumber;
163
+ cached: z.ZodBoolean;
164
+ timezone: z.ZodString;
165
+ requestId: z.ZodString;
166
+ }, z.core.$strip>;
167
+ }, z.core.$strip>;
168
+ type EventsTimeseriesResponse = z.infer<typeof zEventsTimeseriesResponse>;
169
+ declare const zFunnelInput: z.ZodObject<{
170
+ projectId: z.ZodString;
171
+ steps: z.ZodArray<z.ZodString>;
172
+ startDate: z.ZodString;
173
+ endDate: z.ZodString;
174
+ windowSeconds: z.ZodDefault<z.ZodNumber>;
175
+ segmentId: z.ZodOptional<z.ZodString>;
176
+ channelFilter: z.ZodOptional<z.ZodObject<{
177
+ referrerTypes: z.ZodOptional<z.ZodArray<z.ZodString>>;
178
+ channelTypes: z.ZodOptional<z.ZodArray<z.ZodString>>;
179
+ utmSources: z.ZodOptional<z.ZodArray<z.ZodString>>;
180
+ utmMediums: z.ZodOptional<z.ZodArray<z.ZodString>>;
181
+ utmCampaigns: z.ZodOptional<z.ZodArray<z.ZodString>>;
182
+ }, z.core.$strip>>;
183
+ timezone: z.ZodOptional<z.ZodString>;
184
+ }, z.core.$strip>;
185
+ type FunnelInput = z.input<typeof zFunnelInput>;
186
+ declare const zFunnelStep: z.ZodObject<{
187
+ step: z.ZodNumber;
188
+ name: z.ZodString;
189
+ users: z.ZodNumber;
190
+ conversionRate: z.ZodNumber;
191
+ dropoffRate: z.ZodNumber;
192
+ dropoffUsers: z.ZodNumber;
193
+ }, z.core.$strip>;
194
+ declare const zFunnelData: z.ZodObject<{
195
+ steps: z.ZodArray<z.ZodObject<{
196
+ step: z.ZodNumber;
197
+ name: z.ZodString;
198
+ users: z.ZodNumber;
199
+ conversionRate: z.ZodNumber;
200
+ dropoffRate: z.ZodNumber;
201
+ dropoffUsers: z.ZodNumber;
202
+ }, z.core.$strip>>;
203
+ totalUsers: z.ZodNumber;
204
+ overallConversionRate: z.ZodNumber;
205
+ }, z.core.$strip>;
206
+ type FunnelData = z.infer<typeof zFunnelData>;
207
+ declare const zFunnelResponse: z.ZodObject<{
208
+ data: z.ZodObject<{
209
+ steps: z.ZodArray<z.ZodObject<{
210
+ step: z.ZodNumber;
211
+ name: z.ZodString;
212
+ users: z.ZodNumber;
213
+ conversionRate: z.ZodNumber;
214
+ dropoffRate: z.ZodNumber;
215
+ dropoffUsers: z.ZodNumber;
216
+ }, z.core.$strip>>;
217
+ totalUsers: z.ZodNumber;
218
+ overallConversionRate: z.ZodNumber;
219
+ }, z.core.$strip>;
220
+ meta: z.ZodObject<{
221
+ projectId: z.ZodString;
222
+ computedAt: z.ZodString;
223
+ cacheAgeSeconds: z.ZodNumber;
224
+ ingestLagSeconds: z.ZodNumber;
225
+ cached: z.ZodBoolean;
226
+ timezone: z.ZodString;
227
+ requestId: z.ZodString;
228
+ }, z.core.$strip>;
229
+ }, z.core.$strip>;
230
+ type FunnelResponse = z.infer<typeof zFunnelResponse>;
231
+ declare const zRetentionInterval: z.ZodEnum<{
232
+ day: "day";
233
+ week: "week";
234
+ month: "month";
235
+ }>;
236
+ declare const zRetentionInput: z.ZodObject<{
237
+ projectId: z.ZodString;
238
+ startDate: z.ZodString;
239
+ endDate: z.ZodString;
240
+ interval: z.ZodDefault<z.ZodEnum<{
241
+ day: "day";
242
+ week: "week";
243
+ month: "month";
244
+ }>>;
245
+ periods: z.ZodDefault<z.ZodNumber>;
246
+ startEvent: z.ZodOptional<z.ZodString>;
247
+ returnEvent: z.ZodOptional<z.ZodString>;
248
+ retentionType: z.ZodDefault<z.ZodEnum<{
249
+ bounded: "bounded";
250
+ unbounded: "unbounded";
251
+ }>>;
252
+ cohortMode: z.ZodDefault<z.ZodEnum<{
253
+ "first-ever": "first-ever";
254
+ "first-in-window": "first-in-window";
255
+ }>>;
256
+ segmentId: z.ZodOptional<z.ZodString>;
257
+ channelFilter: z.ZodOptional<z.ZodObject<{
258
+ referrerTypes: z.ZodOptional<z.ZodArray<z.ZodString>>;
259
+ channelTypes: z.ZodOptional<z.ZodArray<z.ZodString>>;
260
+ utmSources: z.ZodOptional<z.ZodArray<z.ZodString>>;
261
+ utmMediums: z.ZodOptional<z.ZodArray<z.ZodString>>;
262
+ utmCampaigns: z.ZodOptional<z.ZodArray<z.ZodString>>;
263
+ }, z.core.$strip>>;
264
+ timezone: z.ZodOptional<z.ZodString>;
265
+ }, z.core.$strip>;
266
+ type RetentionInput = z.input<typeof zRetentionInput>;
267
+ declare const zRetentionCell: z.ZodObject<{
268
+ period: z.ZodNumber;
269
+ users: z.ZodNumber;
270
+ rate: z.ZodNumber;
271
+ }, z.core.$strip>;
272
+ declare const zRetentionData: z.ZodObject<{
273
+ matrix: z.ZodArray<z.ZodObject<{
274
+ cohortDate: z.ZodString;
275
+ cohortSize: z.ZodNumber;
276
+ retention: z.ZodArray<z.ZodObject<{
277
+ period: z.ZodNumber;
278
+ users: z.ZodNumber;
279
+ rate: z.ZodNumber;
280
+ }, z.core.$strip>>;
281
+ }, z.core.$strip>>;
282
+ averageRetention: z.ZodArray<z.ZodObject<{
283
+ period: z.ZodNumber;
284
+ rate: z.ZodNumber;
285
+ }, z.core.$strip>>;
286
+ interval: z.ZodEnum<{
287
+ day: "day";
288
+ week: "week";
289
+ month: "month";
290
+ }>;
291
+ periods: z.ZodNumber;
292
+ retentionType: z.ZodEnum<{
293
+ bounded: "bounded";
294
+ unbounded: "unbounded";
295
+ }>;
296
+ timezone: z.ZodString;
297
+ }, z.core.$strip>;
298
+ type RetentionData = z.infer<typeof zRetentionData>;
299
+ declare const zRetentionResponse: z.ZodObject<{
300
+ data: z.ZodObject<{
301
+ matrix: z.ZodArray<z.ZodObject<{
302
+ cohortDate: z.ZodString;
303
+ cohortSize: z.ZodNumber;
304
+ retention: z.ZodArray<z.ZodObject<{
305
+ period: z.ZodNumber;
306
+ users: z.ZodNumber;
307
+ rate: z.ZodNumber;
308
+ }, z.core.$strip>>;
309
+ }, z.core.$strip>>;
310
+ averageRetention: z.ZodArray<z.ZodObject<{
311
+ period: z.ZodNumber;
312
+ rate: z.ZodNumber;
313
+ }, z.core.$strip>>;
314
+ interval: z.ZodEnum<{
315
+ day: "day";
316
+ week: "week";
317
+ month: "month";
318
+ }>;
319
+ periods: z.ZodNumber;
320
+ retentionType: z.ZodEnum<{
321
+ bounded: "bounded";
322
+ unbounded: "unbounded";
323
+ }>;
324
+ timezone: z.ZodString;
325
+ }, z.core.$strip>;
326
+ meta: z.ZodObject<{
327
+ projectId: z.ZodString;
328
+ computedAt: z.ZodString;
329
+ cacheAgeSeconds: z.ZodNumber;
330
+ ingestLagSeconds: z.ZodNumber;
331
+ cached: z.ZodBoolean;
332
+ timezone: z.ZodString;
333
+ requestId: z.ZodString;
334
+ }, z.core.$strip>;
335
+ }, z.core.$strip>;
336
+ type RetentionResponse = z.infer<typeof zRetentionResponse>;
337
+ declare const QUERY_ERROR_CODES: readonly ["unauthorized", "project_scope_mismatch", "query_scope_missing", "validation_failed", "unsupported_combination", "rate_limited", "query_timeout", "internal_error"];
338
+ declare const zQueryErrorCode: z.ZodEnum<{
339
+ unauthorized: "unauthorized";
340
+ project_scope_mismatch: "project_scope_mismatch";
341
+ query_scope_missing: "query_scope_missing";
342
+ validation_failed: "validation_failed";
343
+ unsupported_combination: "unsupported_combination";
344
+ rate_limited: "rate_limited";
345
+ query_timeout: "query_timeout";
346
+ internal_error: "internal_error";
347
+ }>;
348
+ type QueryErrorCode = z.infer<typeof zQueryErrorCode>;
349
+ declare const zQueryError: z.ZodObject<{
350
+ status: z.ZodNumber;
351
+ code: z.ZodEnum<{
352
+ unauthorized: "unauthorized";
353
+ project_scope_mismatch: "project_scope_mismatch";
354
+ query_scope_missing: "query_scope_missing";
355
+ validation_failed: "validation_failed";
356
+ unsupported_combination: "unsupported_combination";
357
+ rate_limited: "rate_limited";
358
+ query_timeout: "query_timeout";
359
+ internal_error: "internal_error";
360
+ }>;
361
+ error: z.ZodString;
362
+ message: z.ZodOptional<z.ZodString>;
363
+ errors: z.ZodOptional<z.ZodUnknown>;
364
+ requestId: z.ZodOptional<z.ZodString>;
365
+ }, z.core.$strip>;
366
+ type QueryError = z.infer<typeof zQueryError>;
367
+ /** Paths, so the client and the route handlers cannot drift apart. */
368
+ declare const QUERY_API_PATHS: {
369
+ readonly eventsTimeseries: "/api/v1/query/events/timeseries";
370
+ readonly funnel: "/api/v1/query/funnel";
371
+ readonly retention: "/api/v1/query/retention";
372
+ };
373
+
374
+ 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, zChannelFilter, zEventsTimeseriesData, zEventsTimeseriesInput, zEventsTimeseriesResponse, zFunnelData, zFunnelInput, zFunnelResponse, zFunnelStep, zGranularity, zQueryEnvelope, zQueryError, zQueryErrorCode, zQueryMeta, zRetentionCell, zRetentionData, zRetentionInput, zRetentionInterval, zRetentionResponse, zTimeseriesBreakdown, zTimeseriesPoint, zTimezone };