hydrousdb 1.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,178 @@
1
+ import { a9 as HttpClient, c as AnalyticsQuery, V as RequestOptions, e as AnalyticsResponse, D as DateRange, C as CountResult, p as DistributionItem, a1 as SumResult, a2 as TimeSeriesPoint, r as FieldTimeSeriesPoint, a3 as TopNItem, F as FieldStatsResult, s as Filter, u as FilteredRecordsResult, M as MultiMetricItem, a0 as StorageStatsResult } from '../http-CIXLF5GV.mjs';
2
+ export { d as AnalyticsQueryType } from '../http-CIXLF5GV.mjs';
3
+
4
+ type AnalyticsResult<T> = Omit<AnalyticsResponse, 'data'> & {
5
+ data: T;
6
+ queryType: string;
7
+ bucketKey: string | null;
8
+ projectId: string;
9
+ };
10
+ declare class AnalyticsClient {
11
+ private readonly http;
12
+ constructor(http: HttpClient);
13
+ private get path();
14
+ /**
15
+ * Run any analytics query with full control over the payload.
16
+ * Prefer the typed convenience methods below for everyday use.
17
+ */
18
+ query<T = unknown>(payload: AnalyticsQuery, opts?: RequestOptions): Promise<AnalyticsResult<T>>;
19
+ /**
20
+ * Total record count, optionally scoped to a date range.
21
+ * Server `queryType`: **"count"**
22
+ *
23
+ * @example
24
+ * const { data } = await db.analytics.count();
25
+ * console.log(data.count); // 1234
26
+ *
27
+ * // With date range
28
+ * const { data } = await db.analytics.count({
29
+ * dateRange: { startDate: '2025-01-01', endDate: '2025-12-31' }
30
+ * });
31
+ */
32
+ count(options?: {
33
+ dateRange?: DateRange;
34
+ } & RequestOptions): Promise<AnalyticsResult<CountResult>>;
35
+ /**
36
+ * Value distribution (histogram) for a field.
37
+ * Server `queryType`: **"distribution"**
38
+ *
39
+ * @example
40
+ * const { data } = await db.analytics.distribution('status');
41
+ * // [{ value: 'active', count: 80 }, { value: 'archived', count: 20 }]
42
+ */
43
+ distribution(field: string, options?: {
44
+ limit?: number;
45
+ order?: 'asc' | 'desc';
46
+ dateRange?: DateRange;
47
+ } & RequestOptions): Promise<AnalyticsResult<DistributionItem[]>>;
48
+ /**
49
+ * Sum a numeric field, with optional group-by.
50
+ * Server `queryType`: **"sum"**
51
+ *
52
+ * @example
53
+ * const { data } = await db.analytics.sum('revenue', { groupBy: 'region' });
54
+ */
55
+ sum(field: string, options?: {
56
+ groupBy?: string;
57
+ limit?: number;
58
+ dateRange?: DateRange;
59
+ } & RequestOptions): Promise<AnalyticsResult<SumResult>>;
60
+ /**
61
+ * Record count grouped over time.
62
+ * Server `queryType`: **"timeSeries"**
63
+ *
64
+ * @example
65
+ * const { data } = await db.analytics.timeSeries({ granularity: 'day' });
66
+ * // [{ date: '2025-01-01', count: 42 }, ...]
67
+ */
68
+ timeSeries(options?: {
69
+ granularity?: 'hour' | 'day' | 'week' | 'month';
70
+ dateRange?: DateRange;
71
+ } & RequestOptions): Promise<AnalyticsResult<TimeSeriesPoint[]>>;
72
+ /**
73
+ * Aggregate a numeric field over time.
74
+ * Server `queryType`: **"fieldTimeSeries"**
75
+ *
76
+ * @example
77
+ * const { data } = await db.analytics.fieldTimeSeries('revenue', {
78
+ * granularity: 'month',
79
+ * aggregation: 'sum',
80
+ * });
81
+ */
82
+ fieldTimeSeries(field: string, options?: {
83
+ aggregation?: 'sum' | 'avg' | 'min' | 'max' | 'count';
84
+ granularity?: 'hour' | 'day' | 'week' | 'month';
85
+ dateRange?: DateRange;
86
+ } & RequestOptions): Promise<AnalyticsResult<FieldTimeSeriesPoint[]>>;
87
+ /**
88
+ * Top N most frequent values for a field.
89
+ * Server `queryType`: **"topN"**
90
+ *
91
+ * @example
92
+ * const { data } = await db.analytics.topN('country', 5);
93
+ * // [{ label: 'US', value: 'US', count: 500 }, ...]
94
+ */
95
+ topN(field: string, n?: number, options?: {
96
+ labelField?: string;
97
+ order?: 'asc' | 'desc';
98
+ dateRange?: DateRange;
99
+ } & RequestOptions): Promise<AnalyticsResult<TopNItem[]>>;
100
+ /**
101
+ * Statistical summary for a numeric field: min, max, avg, stddev, p50, p90, p99.
102
+ * Server `queryType`: **"stats"**
103
+ *
104
+ * @example
105
+ * const { data } = await db.analytics.stats('score');
106
+ * console.log(data.avg, data.p99);
107
+ */
108
+ stats(field: string, options?: {
109
+ dateRange?: DateRange;
110
+ } & RequestOptions): Promise<AnalyticsResult<FieldStatsResult>>;
111
+ /**
112
+ * Filtered, paginated raw records with optional field projection.
113
+ * Supports filter ops: == != > < >= <= CONTAINS
114
+ * Server `queryType`: **"records"**
115
+ *
116
+ * @example
117
+ * const { data } = await db.analytics.records({
118
+ * filters: [{ field: 'role', op: '==', value: 'admin' }],
119
+ * selectFields: ['email', 'createdAt'],
120
+ * limit: 25,
121
+ * });
122
+ * console.log(data.data, data.hasMore);
123
+ */
124
+ records(options?: {
125
+ filters?: Filter[];
126
+ selectFields?: string[];
127
+ limit?: number;
128
+ offset?: number;
129
+ orderBy?: string;
130
+ order?: 'asc' | 'desc';
131
+ dateRange?: DateRange;
132
+ } & RequestOptions): Promise<AnalyticsResult<FilteredRecordsResult>>;
133
+ /**
134
+ * Multiple aggregations in a single BigQuery call — ideal for dashboard stat cards.
135
+ * Server `queryType`: **"multiMetric"**
136
+ *
137
+ * @example
138
+ * const { data } = await db.analytics.multiMetric([
139
+ * { name: 'totalRevenue', field: 'amount', aggregation: 'sum' },
140
+ * { name: 'avgScore', field: 'score', aggregation: 'avg' },
141
+ * { name: 'userCount', field: 'userId', aggregation: 'count' },
142
+ * ]);
143
+ * console.log(data.totalRevenue, data.avgScore, data.userCount);
144
+ */
145
+ multiMetric(metrics: MultiMetricItem[], options?: {
146
+ dateRange?: DateRange;
147
+ } & RequestOptions): Promise<AnalyticsResult<Record<string, number>>>;
148
+ /**
149
+ * Storage statistics for the bucket — total records, bytes, avg/min/max size.
150
+ * Server `queryType`: **"storageStats"**
151
+ *
152
+ * @example
153
+ * const { data } = await db.analytics.storageStats();
154
+ * console.log(data.totalRecords, data.totalBytes);
155
+ */
156
+ storageStats(options?: {
157
+ dateRange?: DateRange;
158
+ } & RequestOptions): Promise<AnalyticsResult<StorageStatsResult>>;
159
+ /**
160
+ * Compare a metric across multiple buckets in one query.
161
+ * Server `queryType`: **"crossBucket"**
162
+ *
163
+ * @example
164
+ * const { data } = await db.analytics.crossBucket({
165
+ * bucketKeys: ['sales', 'refunds', 'trials'],
166
+ * field: 'amount',
167
+ * aggregation: 'sum',
168
+ * });
169
+ */
170
+ crossBucket(options: {
171
+ bucketKeys: string[];
172
+ field: string;
173
+ aggregation?: 'sum' | 'avg' | 'min' | 'max' | 'count';
174
+ dateRange?: DateRange;
175
+ } & RequestOptions): Promise<AnalyticsResult<unknown>>;
176
+ }
177
+
178
+ export { AnalyticsClient, AnalyticsQuery, AnalyticsResponse, CountResult, DateRange, DistributionItem, FieldStatsResult, FieldTimeSeriesPoint, Filter, FilteredRecordsResult, MultiMetricItem, StorageStatsResult, SumResult, TimeSeriesPoint, TopNItem };
@@ -0,0 +1,178 @@
1
+ import { a9 as HttpClient, c as AnalyticsQuery, V as RequestOptions, e as AnalyticsResponse, D as DateRange, C as CountResult, p as DistributionItem, a1 as SumResult, a2 as TimeSeriesPoint, r as FieldTimeSeriesPoint, a3 as TopNItem, F as FieldStatsResult, s as Filter, u as FilteredRecordsResult, M as MultiMetricItem, a0 as StorageStatsResult } from '../http-CIXLF5GV.js';
2
+ export { d as AnalyticsQueryType } from '../http-CIXLF5GV.js';
3
+
4
+ type AnalyticsResult<T> = Omit<AnalyticsResponse, 'data'> & {
5
+ data: T;
6
+ queryType: string;
7
+ bucketKey: string | null;
8
+ projectId: string;
9
+ };
10
+ declare class AnalyticsClient {
11
+ private readonly http;
12
+ constructor(http: HttpClient);
13
+ private get path();
14
+ /**
15
+ * Run any analytics query with full control over the payload.
16
+ * Prefer the typed convenience methods below for everyday use.
17
+ */
18
+ query<T = unknown>(payload: AnalyticsQuery, opts?: RequestOptions): Promise<AnalyticsResult<T>>;
19
+ /**
20
+ * Total record count, optionally scoped to a date range.
21
+ * Server `queryType`: **"count"**
22
+ *
23
+ * @example
24
+ * const { data } = await db.analytics.count();
25
+ * console.log(data.count); // 1234
26
+ *
27
+ * // With date range
28
+ * const { data } = await db.analytics.count({
29
+ * dateRange: { startDate: '2025-01-01', endDate: '2025-12-31' }
30
+ * });
31
+ */
32
+ count(options?: {
33
+ dateRange?: DateRange;
34
+ } & RequestOptions): Promise<AnalyticsResult<CountResult>>;
35
+ /**
36
+ * Value distribution (histogram) for a field.
37
+ * Server `queryType`: **"distribution"**
38
+ *
39
+ * @example
40
+ * const { data } = await db.analytics.distribution('status');
41
+ * // [{ value: 'active', count: 80 }, { value: 'archived', count: 20 }]
42
+ */
43
+ distribution(field: string, options?: {
44
+ limit?: number;
45
+ order?: 'asc' | 'desc';
46
+ dateRange?: DateRange;
47
+ } & RequestOptions): Promise<AnalyticsResult<DistributionItem[]>>;
48
+ /**
49
+ * Sum a numeric field, with optional group-by.
50
+ * Server `queryType`: **"sum"**
51
+ *
52
+ * @example
53
+ * const { data } = await db.analytics.sum('revenue', { groupBy: 'region' });
54
+ */
55
+ sum(field: string, options?: {
56
+ groupBy?: string;
57
+ limit?: number;
58
+ dateRange?: DateRange;
59
+ } & RequestOptions): Promise<AnalyticsResult<SumResult>>;
60
+ /**
61
+ * Record count grouped over time.
62
+ * Server `queryType`: **"timeSeries"**
63
+ *
64
+ * @example
65
+ * const { data } = await db.analytics.timeSeries({ granularity: 'day' });
66
+ * // [{ date: '2025-01-01', count: 42 }, ...]
67
+ */
68
+ timeSeries(options?: {
69
+ granularity?: 'hour' | 'day' | 'week' | 'month';
70
+ dateRange?: DateRange;
71
+ } & RequestOptions): Promise<AnalyticsResult<TimeSeriesPoint[]>>;
72
+ /**
73
+ * Aggregate a numeric field over time.
74
+ * Server `queryType`: **"fieldTimeSeries"**
75
+ *
76
+ * @example
77
+ * const { data } = await db.analytics.fieldTimeSeries('revenue', {
78
+ * granularity: 'month',
79
+ * aggregation: 'sum',
80
+ * });
81
+ */
82
+ fieldTimeSeries(field: string, options?: {
83
+ aggregation?: 'sum' | 'avg' | 'min' | 'max' | 'count';
84
+ granularity?: 'hour' | 'day' | 'week' | 'month';
85
+ dateRange?: DateRange;
86
+ } & RequestOptions): Promise<AnalyticsResult<FieldTimeSeriesPoint[]>>;
87
+ /**
88
+ * Top N most frequent values for a field.
89
+ * Server `queryType`: **"topN"**
90
+ *
91
+ * @example
92
+ * const { data } = await db.analytics.topN('country', 5);
93
+ * // [{ label: 'US', value: 'US', count: 500 }, ...]
94
+ */
95
+ topN(field: string, n?: number, options?: {
96
+ labelField?: string;
97
+ order?: 'asc' | 'desc';
98
+ dateRange?: DateRange;
99
+ } & RequestOptions): Promise<AnalyticsResult<TopNItem[]>>;
100
+ /**
101
+ * Statistical summary for a numeric field: min, max, avg, stddev, p50, p90, p99.
102
+ * Server `queryType`: **"stats"**
103
+ *
104
+ * @example
105
+ * const { data } = await db.analytics.stats('score');
106
+ * console.log(data.avg, data.p99);
107
+ */
108
+ stats(field: string, options?: {
109
+ dateRange?: DateRange;
110
+ } & RequestOptions): Promise<AnalyticsResult<FieldStatsResult>>;
111
+ /**
112
+ * Filtered, paginated raw records with optional field projection.
113
+ * Supports filter ops: == != > < >= <= CONTAINS
114
+ * Server `queryType`: **"records"**
115
+ *
116
+ * @example
117
+ * const { data } = await db.analytics.records({
118
+ * filters: [{ field: 'role', op: '==', value: 'admin' }],
119
+ * selectFields: ['email', 'createdAt'],
120
+ * limit: 25,
121
+ * });
122
+ * console.log(data.data, data.hasMore);
123
+ */
124
+ records(options?: {
125
+ filters?: Filter[];
126
+ selectFields?: string[];
127
+ limit?: number;
128
+ offset?: number;
129
+ orderBy?: string;
130
+ order?: 'asc' | 'desc';
131
+ dateRange?: DateRange;
132
+ } & RequestOptions): Promise<AnalyticsResult<FilteredRecordsResult>>;
133
+ /**
134
+ * Multiple aggregations in a single BigQuery call — ideal for dashboard stat cards.
135
+ * Server `queryType`: **"multiMetric"**
136
+ *
137
+ * @example
138
+ * const { data } = await db.analytics.multiMetric([
139
+ * { name: 'totalRevenue', field: 'amount', aggregation: 'sum' },
140
+ * { name: 'avgScore', field: 'score', aggregation: 'avg' },
141
+ * { name: 'userCount', field: 'userId', aggregation: 'count' },
142
+ * ]);
143
+ * console.log(data.totalRevenue, data.avgScore, data.userCount);
144
+ */
145
+ multiMetric(metrics: MultiMetricItem[], options?: {
146
+ dateRange?: DateRange;
147
+ } & RequestOptions): Promise<AnalyticsResult<Record<string, number>>>;
148
+ /**
149
+ * Storage statistics for the bucket — total records, bytes, avg/min/max size.
150
+ * Server `queryType`: **"storageStats"**
151
+ *
152
+ * @example
153
+ * const { data } = await db.analytics.storageStats();
154
+ * console.log(data.totalRecords, data.totalBytes);
155
+ */
156
+ storageStats(options?: {
157
+ dateRange?: DateRange;
158
+ } & RequestOptions): Promise<AnalyticsResult<StorageStatsResult>>;
159
+ /**
160
+ * Compare a metric across multiple buckets in one query.
161
+ * Server `queryType`: **"crossBucket"**
162
+ *
163
+ * @example
164
+ * const { data } = await db.analytics.crossBucket({
165
+ * bucketKeys: ['sales', 'refunds', 'trials'],
166
+ * field: 'amount',
167
+ * aggregation: 'sum',
168
+ * });
169
+ */
170
+ crossBucket(options: {
171
+ bucketKeys: string[];
172
+ field: string;
173
+ aggregation?: 'sum' | 'avg' | 'min' | 'max' | 'count';
174
+ dateRange?: DateRange;
175
+ } & RequestOptions): Promise<AnalyticsResult<unknown>>;
176
+ }
177
+
178
+ export { AnalyticsClient, AnalyticsQuery, AnalyticsResponse, CountResult, DateRange, DistributionItem, FieldStatsResult, FieldTimeSeriesPoint, Filter, FilteredRecordsResult, MultiMetricItem, StorageStatsResult, SumResult, TimeSeriesPoint, TopNItem };
@@ -0,0 +1,221 @@
1
+ 'use strict';
2
+
3
+ // src/analytics/client.ts
4
+ var AnalyticsClient = class {
5
+ constructor(http) {
6
+ this.http = http;
7
+ }
8
+ get path() {
9
+ return `/api/analytics/${this.http.bucketKey}/${this.http.bucketKey}`;
10
+ }
11
+ // ── Raw query ─────────────────────────────────────────────────────────────
12
+ /**
13
+ * Run any analytics query with full control over the payload.
14
+ * Prefer the typed convenience methods below for everyday use.
15
+ */
16
+ async query(payload, opts) {
17
+ return this.http.post(this.path, payload, opts);
18
+ }
19
+ // ── count ──────────────────────────────────────────────────────────────────
20
+ /**
21
+ * Total record count, optionally scoped to a date range.
22
+ * Server `queryType`: **"count"**
23
+ *
24
+ * @example
25
+ * const { data } = await db.analytics.count();
26
+ * console.log(data.count); // 1234
27
+ *
28
+ * // With date range
29
+ * const { data } = await db.analytics.count({
30
+ * dateRange: { startDate: '2025-01-01', endDate: '2025-12-31' }
31
+ * });
32
+ */
33
+ async count(options) {
34
+ return this.query({ queryType: "count", dateRange: options?.dateRange }, options);
35
+ }
36
+ // ── distribution ───────────────────────────────────────────────────────────
37
+ /**
38
+ * Value distribution (histogram) for a field.
39
+ * Server `queryType`: **"distribution"**
40
+ *
41
+ * @example
42
+ * const { data } = await db.analytics.distribution('status');
43
+ * // [{ value: 'active', count: 80 }, { value: 'archived', count: 20 }]
44
+ */
45
+ async distribution(field, options) {
46
+ return this.query({
47
+ queryType: "distribution",
48
+ field,
49
+ limit: options?.limit,
50
+ order: options?.order,
51
+ dateRange: options?.dateRange
52
+ }, options);
53
+ }
54
+ // ── sum ────────────────────────────────────────────────────────────────────
55
+ /**
56
+ * Sum a numeric field, with optional group-by.
57
+ * Server `queryType`: **"sum"**
58
+ *
59
+ * @example
60
+ * const { data } = await db.analytics.sum('revenue', { groupBy: 'region' });
61
+ */
62
+ async sum(field, options) {
63
+ return this.query({
64
+ queryType: "sum",
65
+ field,
66
+ groupBy: options?.groupBy,
67
+ limit: options?.limit,
68
+ dateRange: options?.dateRange
69
+ }, options);
70
+ }
71
+ // ── timeSeries ─────────────────────────────────────────────────────────────
72
+ /**
73
+ * Record count grouped over time.
74
+ * Server `queryType`: **"timeSeries"**
75
+ *
76
+ * @example
77
+ * const { data } = await db.analytics.timeSeries({ granularity: 'day' });
78
+ * // [{ date: '2025-01-01', count: 42 }, ...]
79
+ */
80
+ async timeSeries(options) {
81
+ return this.query({
82
+ queryType: "timeSeries",
83
+ granularity: options?.granularity,
84
+ dateRange: options?.dateRange
85
+ }, options);
86
+ }
87
+ // ── fieldTimeSeries ────────────────────────────────────────────────────────
88
+ /**
89
+ * Aggregate a numeric field over time.
90
+ * Server `queryType`: **"fieldTimeSeries"**
91
+ *
92
+ * @example
93
+ * const { data } = await db.analytics.fieldTimeSeries('revenue', {
94
+ * granularity: 'month',
95
+ * aggregation: 'sum',
96
+ * });
97
+ */
98
+ async fieldTimeSeries(field, options) {
99
+ return this.query({
100
+ queryType: "fieldTimeSeries",
101
+ field,
102
+ aggregation: options?.aggregation,
103
+ granularity: options?.granularity,
104
+ dateRange: options?.dateRange
105
+ }, options);
106
+ }
107
+ // ── topN ───────────────────────────────────────────────────────────────────
108
+ /**
109
+ * Top N most frequent values for a field.
110
+ * Server `queryType`: **"topN"**
111
+ *
112
+ * @example
113
+ * const { data } = await db.analytics.topN('country', 5);
114
+ * // [{ label: 'US', value: 'US', count: 500 }, ...]
115
+ */
116
+ async topN(field, n = 10, options) {
117
+ return this.query({
118
+ queryType: "topN",
119
+ field,
120
+ n,
121
+ labelField: options?.labelField,
122
+ order: options?.order,
123
+ dateRange: options?.dateRange
124
+ }, options);
125
+ }
126
+ // ── stats ──────────────────────────────────────────────────────────────────
127
+ /**
128
+ * Statistical summary for a numeric field: min, max, avg, stddev, p50, p90, p99.
129
+ * Server `queryType`: **"stats"**
130
+ *
131
+ * @example
132
+ * const { data } = await db.analytics.stats('score');
133
+ * console.log(data.avg, data.p99);
134
+ */
135
+ async stats(field, options) {
136
+ return this.query({ queryType: "stats", field, dateRange: options?.dateRange }, options);
137
+ }
138
+ // ── records ────────────────────────────────────────────────────────────────
139
+ /**
140
+ * Filtered, paginated raw records with optional field projection.
141
+ * Supports filter ops: == != > < >= <= CONTAINS
142
+ * Server `queryType`: **"records"**
143
+ *
144
+ * @example
145
+ * const { data } = await db.analytics.records({
146
+ * filters: [{ field: 'role', op: '==', value: 'admin' }],
147
+ * selectFields: ['email', 'createdAt'],
148
+ * limit: 25,
149
+ * });
150
+ * console.log(data.data, data.hasMore);
151
+ */
152
+ async records(options) {
153
+ return this.query({
154
+ queryType: "records",
155
+ filters: options?.filters,
156
+ selectFields: options?.selectFields,
157
+ limit: options?.limit,
158
+ offset: options?.offset,
159
+ orderBy: options?.orderBy,
160
+ order: options?.order,
161
+ dateRange: options?.dateRange
162
+ }, options);
163
+ }
164
+ // ── multiMetric ────────────────────────────────────────────────────────────
165
+ /**
166
+ * Multiple aggregations in a single BigQuery call — ideal for dashboard stat cards.
167
+ * Server `queryType`: **"multiMetric"**
168
+ *
169
+ * @example
170
+ * const { data } = await db.analytics.multiMetric([
171
+ * { name: 'totalRevenue', field: 'amount', aggregation: 'sum' },
172
+ * { name: 'avgScore', field: 'score', aggregation: 'avg' },
173
+ * { name: 'userCount', field: 'userId', aggregation: 'count' },
174
+ * ]);
175
+ * console.log(data.totalRevenue, data.avgScore, data.userCount);
176
+ */
177
+ async multiMetric(metrics, options) {
178
+ return this.query({
179
+ queryType: "multiMetric",
180
+ metrics,
181
+ dateRange: options?.dateRange
182
+ }, options);
183
+ }
184
+ // ── storageStats ───────────────────────────────────────────────────────────
185
+ /**
186
+ * Storage statistics for the bucket — total records, bytes, avg/min/max size.
187
+ * Server `queryType`: **"storageStats"**
188
+ *
189
+ * @example
190
+ * const { data } = await db.analytics.storageStats();
191
+ * console.log(data.totalRecords, data.totalBytes);
192
+ */
193
+ async storageStats(options) {
194
+ return this.query({ queryType: "storageStats", dateRange: options?.dateRange }, options);
195
+ }
196
+ // ── crossBucket ────────────────────────────────────────────────────────────
197
+ /**
198
+ * Compare a metric across multiple buckets in one query.
199
+ * Server `queryType`: **"crossBucket"**
200
+ *
201
+ * @example
202
+ * const { data } = await db.analytics.crossBucket({
203
+ * bucketKeys: ['sales', 'refunds', 'trials'],
204
+ * field: 'amount',
205
+ * aggregation: 'sum',
206
+ * });
207
+ */
208
+ async crossBucket(options) {
209
+ return this.query({
210
+ queryType: "crossBucket",
211
+ bucketKeys: options.bucketKeys,
212
+ field: options.field,
213
+ aggregation: options.aggregation,
214
+ dateRange: options.dateRange
215
+ }, options);
216
+ }
217
+ };
218
+
219
+ exports.AnalyticsClient = AnalyticsClient;
220
+ //# sourceMappingURL=index.js.map
221
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/analytics/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { HttpClient } from '../utils/http.js';\nimport type {\n AnalyticsQuery,\n AnalyticsResponse,\n DateRange,\n Filter,\n MultiMetricItem,\n RequestOptions,\n CountResult,\n DistributionItem,\n SumResult,\n TimeSeriesPoint,\n FieldTimeSeriesPoint,\n TopNItem,\n FieldStatsResult,\n FilteredRecordsResult,\n StorageStatsResult,\n} from '../types/index.js';\n\n// Typed wrapper so callers get proper return types\ntype AnalyticsResult<T> = Omit<AnalyticsResponse, 'data'> & { data: T; queryType: string; bucketKey: string | null; projectId: string };\n\nexport class AnalyticsClient {\n constructor(private readonly http: HttpClient) {}\n\n private get path() {\n // POST /api/analytics/:bucketKey/:key — bucketKey and apiKey both in URL\n return `/api/analytics/${this.http.bucketKey}/${this.http.bucketKey}`;\n }\n\n // ── Raw query ─────────────────────────────────────────────────────────────\n\n /**\n * Run any analytics query with full control over the payload.\n * Prefer the typed convenience methods below for everyday use.\n */\n async query<T = unknown>(payload: AnalyticsQuery, opts?: RequestOptions): Promise<AnalyticsResult<T>> {\n return this.http.post<AnalyticsResult<T>>(this.path, payload, opts);\n }\n\n // ── count ──────────────────────────────────────────────────────────────────\n\n /**\n * Total record count, optionally scoped to a date range.\n * Server `queryType`: **\"count\"**\n *\n * @example\n * const { data } = await db.analytics.count();\n * console.log(data.count); // 1234\n *\n * // With date range\n * const { data } = await db.analytics.count({\n * dateRange: { startDate: '2025-01-01', endDate: '2025-12-31' }\n * });\n */\n async count(options?: { dateRange?: DateRange } & RequestOptions): Promise<AnalyticsResult<CountResult>> {\n return this.query<CountResult>({ queryType: 'count', dateRange: options?.dateRange }, options);\n }\n\n // ── distribution ───────────────────────────────────────────────────────────\n\n /**\n * Value distribution (histogram) for a field.\n * Server `queryType`: **\"distribution\"**\n *\n * @example\n * const { data } = await db.analytics.distribution('status');\n * // [{ value: 'active', count: 80 }, { value: 'archived', count: 20 }]\n */\n async distribution(\n field: string,\n options?: { limit?: number; order?: 'asc' | 'desc'; dateRange?: DateRange } & RequestOptions\n ): Promise<AnalyticsResult<DistributionItem[]>> {\n return this.query<DistributionItem[]>({\n queryType: 'distribution',\n field,\n limit: options?.limit,\n order: options?.order,\n dateRange: options?.dateRange,\n }, options);\n }\n\n // ── sum ────────────────────────────────────────────────────────────────────\n\n /**\n * Sum a numeric field, with optional group-by.\n * Server `queryType`: **\"sum\"**\n *\n * @example\n * const { data } = await db.analytics.sum('revenue', { groupBy: 'region' });\n */\n async sum(\n field: string,\n options?: { groupBy?: string; limit?: number; dateRange?: DateRange } & RequestOptions\n ): Promise<AnalyticsResult<SumResult>> {\n return this.query<SumResult>({\n queryType: 'sum',\n field,\n groupBy: options?.groupBy,\n limit: options?.limit,\n dateRange: options?.dateRange,\n }, options);\n }\n\n // ── timeSeries ─────────────────────────────────────────────────────────────\n\n /**\n * Record count grouped over time.\n * Server `queryType`: **\"timeSeries\"**\n *\n * @example\n * const { data } = await db.analytics.timeSeries({ granularity: 'day' });\n * // [{ date: '2025-01-01', count: 42 }, ...]\n */\n async timeSeries(options?: {\n granularity?: 'hour' | 'day' | 'week' | 'month';\n dateRange?: DateRange;\n } & RequestOptions): Promise<AnalyticsResult<TimeSeriesPoint[]>> {\n return this.query<TimeSeriesPoint[]>({\n queryType: 'timeSeries',\n granularity: options?.granularity,\n dateRange: options?.dateRange,\n }, options);\n }\n\n // ── fieldTimeSeries ────────────────────────────────────────────────────────\n\n /**\n * Aggregate a numeric field over time.\n * Server `queryType`: **\"fieldTimeSeries\"**\n *\n * @example\n * const { data } = await db.analytics.fieldTimeSeries('revenue', {\n * granularity: 'month',\n * aggregation: 'sum',\n * });\n */\n async fieldTimeSeries(\n field: string,\n options?: {\n aggregation?: 'sum' | 'avg' | 'min' | 'max' | 'count';\n granularity?: 'hour' | 'day' | 'week' | 'month';\n dateRange?: DateRange;\n } & RequestOptions\n ): Promise<AnalyticsResult<FieldTimeSeriesPoint[]>> {\n return this.query<FieldTimeSeriesPoint[]>({\n queryType: 'fieldTimeSeries',\n field,\n aggregation: options?.aggregation,\n granularity: options?.granularity,\n dateRange: options?.dateRange,\n }, options);\n }\n\n // ── topN ───────────────────────────────────────────────────────────────────\n\n /**\n * Top N most frequent values for a field.\n * Server `queryType`: **\"topN\"**\n *\n * @example\n * const { data } = await db.analytics.topN('country', 5);\n * // [{ label: 'US', value: 'US', count: 500 }, ...]\n */\n async topN(\n field: string,\n n = 10,\n options?: { labelField?: string; order?: 'asc' | 'desc'; dateRange?: DateRange } & RequestOptions\n ): Promise<AnalyticsResult<TopNItem[]>> {\n return this.query<TopNItem[]>({\n queryType: 'topN',\n field,\n n,\n labelField: options?.labelField,\n order: options?.order,\n dateRange: options?.dateRange,\n }, options);\n }\n\n // ── stats ──────────────────────────────────────────────────────────────────\n\n /**\n * Statistical summary for a numeric field: min, max, avg, stddev, p50, p90, p99.\n * Server `queryType`: **\"stats\"**\n *\n * @example\n * const { data } = await db.analytics.stats('score');\n * console.log(data.avg, data.p99);\n */\n async stats(\n field: string,\n options?: { dateRange?: DateRange } & RequestOptions\n ): Promise<AnalyticsResult<FieldStatsResult>> {\n return this.query<FieldStatsResult>({ queryType: 'stats', field, dateRange: options?.dateRange }, options);\n }\n\n // ── records ────────────────────────────────────────────────────────────────\n\n /**\n * Filtered, paginated raw records with optional field projection.\n * Supports filter ops: == != > < >= <= CONTAINS\n * Server `queryType`: **\"records\"**\n *\n * @example\n * const { data } = await db.analytics.records({\n * filters: [{ field: 'role', op: '==', value: 'admin' }],\n * selectFields: ['email', 'createdAt'],\n * limit: 25,\n * });\n * console.log(data.data, data.hasMore);\n */\n async records(options?: {\n filters?: Filter[];\n selectFields?: string[];\n limit?: number;\n offset?: number;\n orderBy?: string;\n order?: 'asc' | 'desc';\n dateRange?: DateRange;\n } & RequestOptions): Promise<AnalyticsResult<FilteredRecordsResult>> {\n return this.query<FilteredRecordsResult>({\n queryType: 'records',\n filters: options?.filters,\n selectFields: options?.selectFields,\n limit: options?.limit,\n offset: options?.offset,\n orderBy: options?.orderBy,\n order: options?.order,\n dateRange: options?.dateRange,\n }, options);\n }\n\n // ── multiMetric ────────────────────────────────────────────────────────────\n\n /**\n * Multiple aggregations in a single BigQuery call — ideal for dashboard stat cards.\n * Server `queryType`: **\"multiMetric\"**\n *\n * @example\n * const { data } = await db.analytics.multiMetric([\n * { name: 'totalRevenue', field: 'amount', aggregation: 'sum' },\n * { name: 'avgScore', field: 'score', aggregation: 'avg' },\n * { name: 'userCount', field: 'userId', aggregation: 'count' },\n * ]);\n * console.log(data.totalRevenue, data.avgScore, data.userCount);\n */\n async multiMetric(\n metrics: MultiMetricItem[],\n options?: { dateRange?: DateRange } & RequestOptions\n ): Promise<AnalyticsResult<Record<string, number>>> {\n return this.query<Record<string, number>>({\n queryType: 'multiMetric',\n metrics,\n dateRange: options?.dateRange,\n }, options);\n }\n\n // ── storageStats ───────────────────────────────────────────────────────────\n\n /**\n * Storage statistics for the bucket — total records, bytes, avg/min/max size.\n * Server `queryType`: **\"storageStats\"**\n *\n * @example\n * const { data } = await db.analytics.storageStats();\n * console.log(data.totalRecords, data.totalBytes);\n */\n async storageStats(\n options?: { dateRange?: DateRange } & RequestOptions\n ): Promise<AnalyticsResult<StorageStatsResult>> {\n return this.query<StorageStatsResult>({ queryType: 'storageStats', dateRange: options?.dateRange }, options);\n }\n\n // ── crossBucket ────────────────────────────────────────────────────────────\n\n /**\n * Compare a metric across multiple buckets in one query.\n * Server `queryType`: **\"crossBucket\"**\n *\n * @example\n * const { data } = await db.analytics.crossBucket({\n * bucketKeys: ['sales', 'refunds', 'trials'],\n * field: 'amount',\n * aggregation: 'sum',\n * });\n */\n async crossBucket(options: {\n bucketKeys: string[];\n field: string;\n aggregation?: 'sum' | 'avg' | 'min' | 'max' | 'count';\n dateRange?: DateRange;\n } & RequestOptions): Promise<AnalyticsResult<unknown>> {\n return this.query<unknown>({\n queryType: 'crossBucket',\n bucketKeys: options.bucketKeys,\n field: options.field,\n aggregation: options.aggregation,\n dateRange: options.dateRange,\n }, options);\n }\n}\n"]}