@upstash/redis-analytics 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.
Files changed (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +175 -0
  3. package/dist/backend-client.d.ts +38 -0
  4. package/dist/backend-client.js +189 -0
  5. package/dist/client.d.ts +27 -0
  6. package/dist/client.js +157 -0
  7. package/dist/index.d.ts +11 -0
  8. package/dist/index.js +20 -0
  9. package/dist/protocol.d.ts +45 -0
  10. package/dist/protocol.js +4 -0
  11. package/dist/react.d.ts +33 -0
  12. package/dist/react.js +95 -0
  13. package/dist/services/events.d.ts +26 -0
  14. package/dist/services/events.js +143 -0
  15. package/dist/services/feature-flags.d.ts +14 -0
  16. package/dist/services/feature-flags.js +88 -0
  17. package/dist/services/logging.d.ts +13 -0
  18. package/dist/services/logging.js +66 -0
  19. package/dist/services/schema-registry.d.ts +15 -0
  20. package/dist/services/schema-registry.js +97 -0
  21. package/dist/services/search-index.d.ts +35 -0
  22. package/dist/services/search-index.js +293 -0
  23. package/dist/services/sessions.d.ts +18 -0
  24. package/dist/services/sessions.js +58 -0
  25. package/dist/types.d.ts +144 -0
  26. package/dist/types.js +2 -0
  27. package/dist/utils.d.ts +6 -0
  28. package/dist/utils.js +44 -0
  29. package/package.json +36 -0
  30. package/src/backend-client.ts +301 -0
  31. package/src/client.ts +245 -0
  32. package/src/index.ts +39 -0
  33. package/src/protocol.ts +57 -0
  34. package/src/react.ts +163 -0
  35. package/src/services/events.ts +187 -0
  36. package/src/services/feature-flags.ts +125 -0
  37. package/src/services/logging.ts +81 -0
  38. package/src/services/schema-registry.ts +125 -0
  39. package/src/services/search-index.ts +335 -0
  40. package/src/services/sessions.ts +86 -0
  41. package/src/types.ts +194 -0
  42. package/src/utils.ts +45 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Upstash, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,175 @@
1
+ # @upstash/redis-analytics
2
+
3
+ Unified analytics package for Upstash Redis. Provides both server-side (`AnalyticsBackendClient`) and browser-side (`AnalyticsClient`) functionality in a single package.
4
+
5
+ ## Purpose
6
+
7
+ This package is the complete analytics solution. It provides:
8
+
9
+ - Session management (creation, retrieval, validation)
10
+ - Event tracking and capture (standard + custom events)
11
+ - Feature flag management with A/B testing
12
+ - Redis Search index management (blue-green deployment)
13
+ - Custom event schema registry
14
+ - System logging
15
+ - Rate limiting
16
+ - Browser-side client with event batching
17
+
18
+ ## Architecture
19
+
20
+ ```
21
+ ┌─────────────────────────────────────┐
22
+ │ Applications │
23
+ │ (ui, app, user apps) │
24
+ └──────────────┬──────────────────────┘
25
+
26
+
27
+ ┌─────────────────────────────────────┐
28
+ │ @upstash/redis-analytics │
29
+ │ AnalyticsBackendClient (server) │
30
+ │ AnalyticsClient (browser) │
31
+ └──────────────┬──────────────────────┘
32
+
33
+
34
+ ┌─────────────────────────────────────┐
35
+ │ Upstash Redis + Redis Search │
36
+ └─────────────────────────────────────┘
37
+ ```
38
+
39
+ ## Package Structure
40
+
41
+ ```
42
+ src/
43
+ index.ts # barrel exports
44
+ backend-client.ts # AnalyticsBackendClient (server-side)
45
+ client.ts # AnalyticsClient (browser-side)
46
+ types.ts # all shared types
47
+ protocol.ts # request/response contract
48
+ utils.ts # helpers
49
+ services/
50
+ events.ts # EventService
51
+ sessions.ts # SessionService
52
+ feature-flags.ts # FeatureFlagService
53
+ schema-registry.ts # SchemaRegistry
54
+ search-index.ts # SearchIndexService
55
+ logging.ts # LoggingService
56
+ ```
57
+
58
+ ## Usage
59
+
60
+ ### Server-side (Next.js API route)
61
+
62
+ ```typescript
63
+ import { AnalyticsBackendClient } from "@upstash/redis-analytics";
64
+
65
+ const client = new AnalyticsBackendClient({
66
+ redis: {
67
+ url: process.env.UPSTASH_REDIS_REST_URL!,
68
+ token: process.env.UPSTASH_REDIS_REST_TOKEN!,
69
+ },
70
+ config: {
71
+ // All config is optional — only override what you need
72
+ session: { expirationMs: 7200000 },
73
+ schemaValidation: { checkFrequency: 0.01 }, // validate ~1% of events to reduce costs
74
+ },
75
+ });
76
+
77
+ // Single endpoint handler for Next.js
78
+ const handler = client.getHandler();
79
+ export const POST = handler;
80
+ export const GET = handler;
81
+
82
+ // Or use namespaced services directly
83
+ const session = await client.sessions.createSession();
84
+ await client.events.capturePageView(session.id, "/home");
85
+ const flags = await client.featureFlags.getDefinitions();
86
+ const logs = await client.logs.getLogs({ limit: 50 });
87
+ const info = await client.searchIndex.getInfo();
88
+ const schemas = await client.schemas.getAllSchemas();
89
+ ```
90
+
91
+ ### Browser-side (React/Next.js)
92
+
93
+ ```typescript
94
+ import { AnalyticsClient } from "@upstash/redis-analytics";
95
+
96
+ const analytics = new AnalyticsClient({
97
+ endpoint: "/api/analytics",
98
+ flushInterval: 2000, // batch events, flush every 2s
99
+ });
100
+
101
+ const session = await analytics.createSession();
102
+ await analytics.capturePageView(session.id, "/home");
103
+ await analytics.captureClick(session.id, "signup-button");
104
+ ```
105
+
106
+ ### Middleware & Session Metadata
107
+
108
+ Add middleware to `getHandler()` for authentication and to attach metadata to sessions.
109
+ The 3rd generic parameter provides type safety for session metadata.
110
+
111
+ ```typescript
112
+ import { AnalyticsBackendClient } from "@upstash/redis-analytics";
113
+
114
+ type MyEvents = { "custom:purchase": { productId: string; amount: number } };
115
+ type MyFlags = { theme: "light" | "dark" };
116
+ type MySessionMetadata = { userId: string; plan: string };
117
+
118
+ const client = new AnalyticsBackendClient<MyEvents, MyFlags, MySessionMetadata>({
119
+ redis: { url: "...", token: "..." },
120
+ });
121
+
122
+ const handler = client.getHandler({
123
+ middleware: async ({ request, analyticsRequest }) => {
124
+ const token = request.headers.get("authorization");
125
+ if (!token) {
126
+ return new Response(JSON.stringify({ success: false, error: "Unauthorized" }), { status: 401 });
127
+ }
128
+ const user = await verifyToken(token);
129
+ // Attach metadata to the session — stored in Redis, included in every event
130
+ return { sessionMetadata: { userId: user.id, plan: user.plan } };
131
+ },
132
+ });
133
+
134
+ export const POST = handler;
135
+ export const GET = handler;
136
+ ```
137
+
138
+ Session metadata is automatically:
139
+ - Stored with the session in Redis
140
+ - Included in every captured event under `sessionMetadata`
141
+ - Registered in the schema registry for search index queryability
142
+
143
+ ### Type Safety
144
+
145
+ ```typescript
146
+ import { AnalyticsBackendClient, AnalyticsClient } from "@upstash/redis-analytics";
147
+
148
+ type MyEvents = {
149
+ "custom:purchase": { productId: string; amount: number };
150
+ };
151
+
152
+ type MyFlags = {
153
+ theme: "light" | "dark";
154
+ };
155
+
156
+ type MySessionMetadata = {
157
+ userId: string;
158
+ plan: string;
159
+ };
160
+
161
+ // Backend accepts 3 generic parameters: events, flags, session metadata
162
+ const backend = new AnalyticsBackendClient<MyEvents, MyFlags, MySessionMetadata>({ ... });
163
+
164
+ // Frontend client accepts events and flags
165
+ const frontend = new AnalyticsClient<MyEvents, MyFlags>({ ... });
166
+ ```
167
+
168
+ ## Dependencies
169
+
170
+ - `@upstash/redis` - Redis client with Redis Search support
171
+ - `@upstash/ratelimit` - Distributed rate limiting
172
+
173
+ ## Development
174
+
175
+ This package is part of a monorepo using pnpm workspaces.
@@ -0,0 +1,38 @@
1
+ import type { ServerConfig } from "./types";
2
+ import type { AnalyticsRequest } from "./protocol";
3
+ import { LoggingService } from "./services/logging";
4
+ import { FeatureFlagService } from "./services/feature-flags";
5
+ import { SessionService } from "./services/sessions";
6
+ import { EventService } from "./services/events";
7
+ import { SchemaRegistry } from "./services/schema-registry";
8
+ import { SearchIndexService } from "./services/search-index";
9
+ export type MiddlewareResult<TSessionMetadata extends Record<string, unknown> = Record<string, unknown>> = {
10
+ sessionMetadata: TSessionMetadata;
11
+ };
12
+ export type HandlerOptions<TSessionMetadata extends Record<string, unknown> = Record<string, unknown>> = {
13
+ /**
14
+ * Middleware that runs before each request is processed.
15
+ * Return a Response to short-circuit (e.g. 401 Unauthorized).
16
+ * Return void to let the request proceed.
17
+ * Return { sessionMetadata } to attach metadata to the session (createSession only).
18
+ */
19
+ middleware?: (context: {
20
+ request: Request;
21
+ analyticsRequest: AnalyticsRequest;
22
+ }) => Response | void | MiddlewareResult<TSessionMetadata> | Promise<Response | void | MiddlewareResult<TSessionMetadata>>;
23
+ };
24
+ export declare class AnalyticsBackendClient<TCustomEvents extends Record<string, Record<string, unknown>> = Record<string, Record<string, unknown>>, TFeatureFlags extends Record<string, string> = Record<string, string>, TSessionMetadata extends Record<string, unknown> = Record<string, unknown>> {
25
+ readonly events: EventService;
26
+ readonly sessions: SessionService;
27
+ readonly featureFlags: FeatureFlagService;
28
+ readonly schemas: SchemaRegistry;
29
+ readonly logs: LoggingService;
30
+ readonly searchIndex: SearchIndexService;
31
+ private redis;
32
+ private config;
33
+ constructor(serverConfig: ServerConfig);
34
+ getHandler(options?: HandlerOptions<TSessionMetadata>): (request: Request) => Promise<Response>;
35
+ private handleRequest;
36
+ private parseGetRequest;
37
+ private processRequest;
38
+ }
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AnalyticsBackendClient = void 0;
4
+ const redis_1 = require("@upstash/redis");
5
+ const logging_1 = require("./services/logging");
6
+ const feature_flags_1 = require("./services/feature-flags");
7
+ const sessions_1 = require("./services/sessions");
8
+ const events_1 = require("./services/events");
9
+ const schema_registry_1 = require("./services/schema-registry");
10
+ const search_index_1 = require("./services/search-index");
11
+ const DEFAULT_CONFIG = {
12
+ session: {
13
+ expirationMs: 3600000, // 1 hour
14
+ },
15
+ featureFlags: {},
16
+ events: {
17
+ customEventRetentionDays: 7,
18
+ maxBatchSize: 20,
19
+ },
20
+ schemaValidation: {
21
+ checkFrequency: 1,
22
+ },
23
+ logging: {
24
+ retentionDays: 30,
25
+ enabledTypes: [
26
+ "schema_update",
27
+ "feature_flag_update",
28
+ "system_error",
29
+ "index_update",
30
+ ],
31
+ },
32
+ search: {
33
+ indexName: "events-idx",
34
+ autoUpdate: true,
35
+ rebuildOnStartup: false,
36
+ },
37
+ };
38
+ function deepMerge(target, source) {
39
+ const result = { ...target };
40
+ for (const key of Object.keys(source)) {
41
+ const sourceVal = source[key];
42
+ if (sourceVal === undefined)
43
+ continue;
44
+ const targetVal = result[key];
45
+ if (targetVal &&
46
+ typeof targetVal === "object" &&
47
+ !Array.isArray(targetVal) &&
48
+ typeof sourceVal === "object" &&
49
+ !Array.isArray(sourceVal)) {
50
+ result[key] = deepMerge(targetVal, sourceVal);
51
+ }
52
+ else {
53
+ result[key] = sourceVal;
54
+ }
55
+ }
56
+ return result;
57
+ }
58
+ class AnalyticsBackendClient {
59
+ constructor(serverConfig) {
60
+ this.redis = new redis_1.Redis({
61
+ url: serverConfig.redis.url,
62
+ token: serverConfig.redis.token,
63
+ });
64
+ this.config = deepMerge(DEFAULT_CONFIG, (serverConfig.config ?? {}));
65
+ this.logs = new logging_1.LoggingService(this.redis, this.config);
66
+ this.featureFlags = new feature_flags_1.FeatureFlagService(this.redis, this.config, this.logs);
67
+ this.sessions = new sessions_1.SessionService(this.redis, this.config, this.featureFlags, this.logs);
68
+ this.schemas = new schema_registry_1.SchemaRegistry(this.redis, this.config, this.logs);
69
+ this.searchIndex = new search_index_1.SearchIndexService(this.redis, this.config, this.schemas, this.featureFlags, this.logs);
70
+ this.events = new events_1.EventService(this.redis, this.config, this.schemas, this.logs);
71
+ }
72
+ // ─── Handler ──────────────────────────────────────────────────
73
+ getHandler(options) {
74
+ return (request) => this.handleRequest(request, options);
75
+ }
76
+ async handleRequest(request, options) {
77
+ try {
78
+ const method = request.method.toUpperCase();
79
+ let analyticsRequest;
80
+ if (method === "GET") {
81
+ const url = new URL(request.url);
82
+ const requestType = url.searchParams.get("requestType");
83
+ if (!requestType) {
84
+ return new Response(JSON.stringify({
85
+ success: false,
86
+ error: "Missing requestType query parameter",
87
+ }), { status: 400, headers: { "Content-Type": "application/json" } });
88
+ }
89
+ analyticsRequest = this.parseGetRequest(requestType, url.searchParams);
90
+ }
91
+ else {
92
+ analyticsRequest = (await request.json());
93
+ }
94
+ // Run middleware
95
+ let sessionMetadata;
96
+ if (options?.middleware) {
97
+ const middlewareResult = await options.middleware({
98
+ request,
99
+ analyticsRequest,
100
+ });
101
+ if (middlewareResult instanceof Response) {
102
+ return middlewareResult;
103
+ }
104
+ if (middlewareResult && typeof middlewareResult === "object" && "sessionMetadata" in middlewareResult) {
105
+ sessionMetadata = middlewareResult.sessionMetadata;
106
+ }
107
+ }
108
+ const result = await this.processRequest(analyticsRequest, sessionMetadata);
109
+ return new Response(JSON.stringify(result), {
110
+ status: result.success ? 200 : 400,
111
+ headers: { "Content-Type": "application/json" },
112
+ });
113
+ }
114
+ catch (error) {
115
+ const message = error instanceof Error ? error.message : "Unknown error";
116
+ const result = { success: false, error: message };
117
+ return new Response(JSON.stringify(result), {
118
+ status: 400,
119
+ headers: { "Content-Type": "application/json" },
120
+ });
121
+ }
122
+ }
123
+ parseGetRequest(requestType, params) {
124
+ switch (requestType) {
125
+ case "getSession":
126
+ return {
127
+ requestType: "getSession",
128
+ data: { sessionId: params.get("sessionId") },
129
+ };
130
+ case "getFeatureFlag":
131
+ return {
132
+ requestType: "getFeatureFlag",
133
+ data: {
134
+ sessionId: params.get("sessionId"),
135
+ flagName: params.get("flagName"),
136
+ },
137
+ };
138
+ case "getAllFeatureFlags":
139
+ return {
140
+ requestType: "getAllFeatureFlags",
141
+ data: { sessionId: params.get("sessionId") },
142
+ };
143
+ default:
144
+ throw new Error(`Unknown GET request type: ${requestType}`);
145
+ }
146
+ }
147
+ async processRequest(req, sessionMetadata) {
148
+ switch (req.requestType) {
149
+ case "captureEvent": {
150
+ await this.events.captureEvent(req.data);
151
+ return { success: true };
152
+ }
153
+ case "captureBatchEvents": {
154
+ await this.events.captureBatchEvents(req.data.events);
155
+ return { success: true };
156
+ }
157
+ case "getSession": {
158
+ const session = await this.sessions.getSession(req.data.sessionId);
159
+ return { success: true, data: session };
160
+ }
161
+ case "getFeatureFlag": {
162
+ const value = await this.sessions.getFeatureFlag(req.data.sessionId, req.data.flagName);
163
+ return { success: true, data: { value } };
164
+ }
165
+ case "getAllFeatureFlags": {
166
+ const flags = await this.sessions.getAllFeatureFlags(req.data.sessionId);
167
+ return { success: true, data: flags };
168
+ }
169
+ case "createSession": {
170
+ const session = await this.sessions.createSession({
171
+ featureFlags: req.data.featureFlags,
172
+ metadata: sessionMetadata,
173
+ });
174
+ // Register session metadata schema so it's available in search index
175
+ if (sessionMetadata && Object.keys(sessionMetadata).length > 0) {
176
+ await this.schemas.validateAndUpdateSchema("__session_metadata__", sessionMetadata);
177
+ }
178
+ return { success: true, data: session };
179
+ }
180
+ default: {
181
+ return {
182
+ success: false,
183
+ error: `Unknown request type: ${req.requestType}`,
184
+ };
185
+ }
186
+ }
187
+ }
188
+ }
189
+ exports.AnalyticsBackendClient = AnalyticsBackendClient;
@@ -0,0 +1,27 @@
1
+ import type { CaptureEventInput, ClientConfig, Session, SessionResult } from "./types";
2
+ export declare class AnalyticsClient<TCustomEvents extends Record<string, Record<string, unknown>> = Record<string, Record<string, unknown>>, TFeatureFlags extends Record<string, string> = Record<string, string>> {
3
+ private endpoint;
4
+ private flushInterval;
5
+ private maxBatchSize;
6
+ private eventQueue;
7
+ private flushTimer;
8
+ constructor(config?: ClientConfig);
9
+ private sendPost;
10
+ private sendGet;
11
+ private enqueueEvent;
12
+ flush(): Promise<void>;
13
+ createSession(options?: {
14
+ featureFlags?: {
15
+ [K in keyof TFeatureFlags]?: TFeatureFlags[K] | Record<string, number>;
16
+ };
17
+ }): Promise<Session<TFeatureFlags>>;
18
+ getSession(sessionId: string): Promise<SessionResult<TFeatureFlags>>;
19
+ captureEvent(input: CaptureEventInput<TCustomEvents>): Promise<void>;
20
+ capturePageView(sessionId: string, path: string): Promise<void>;
21
+ captureClick(sessionId: string, element: string): Promise<void>;
22
+ captureError(sessionId: string, message: string): Promise<void>;
23
+ captureWarning(sessionId: string, message: string): Promise<void>;
24
+ captureInfo(sessionId: string, message: string): Promise<void>;
25
+ getFeatureFlag<K extends string & keyof TFeatureFlags>(sessionId: string, flagName: K): Promise<TFeatureFlags[K] | null>;
26
+ getAllFeatureFlags(sessionId: string): Promise<TFeatureFlags>;
27
+ }
package/dist/client.js ADDED
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AnalyticsClient = void 0;
4
+ class AnalyticsClient {
5
+ constructor(config) {
6
+ this.eventQueue = [];
7
+ this.flushTimer = null;
8
+ this.endpoint = config?.endpoint ?? "/api/analytics";
9
+ this.flushInterval = config?.flushInterval ?? 0;
10
+ this.maxBatchSize = config?.maxBatchSize ?? 20;
11
+ }
12
+ async sendPost(request) {
13
+ const response = await fetch(this.endpoint, {
14
+ method: "POST",
15
+ headers: { "Content-Type": "application/json" },
16
+ body: JSON.stringify(request),
17
+ });
18
+ const result = await response.json();
19
+ if (!result.success) {
20
+ throw new Error(result.error ?? "Analytics request failed");
21
+ }
22
+ return result.data;
23
+ }
24
+ async sendGet(requestType, params) {
25
+ const searchParams = new URLSearchParams({ requestType, ...params });
26
+ const response = await fetch(`${this.endpoint}?${searchParams}`);
27
+ const result = await response.json();
28
+ if (!result.success) {
29
+ throw new Error(result.error ?? "Analytics request failed");
30
+ }
31
+ return result.data;
32
+ }
33
+ // ─── Batch Queue ─────────────────────────────────────────────
34
+ enqueueEvent(event) {
35
+ this.eventQueue.push(event);
36
+ if (this.flushTimer) {
37
+ clearTimeout(this.flushTimer);
38
+ }
39
+ this.flushTimer = setTimeout(() => {
40
+ this.flush();
41
+ }, this.flushInterval);
42
+ }
43
+ async flush() {
44
+ if (this.flushTimer) {
45
+ clearTimeout(this.flushTimer);
46
+ this.flushTimer = null;
47
+ }
48
+ if (this.eventQueue.length === 0)
49
+ return;
50
+ const events = [...this.eventQueue];
51
+ this.eventQueue = [];
52
+ if (events.length === 1) {
53
+ await this.sendPost({
54
+ requestType: "captureEvent",
55
+ data: events[0],
56
+ });
57
+ }
58
+ else {
59
+ // Send in chunks of maxBatchSize
60
+ for (let i = 0; i < events.length; i += this.maxBatchSize) {
61
+ const chunk = events.slice(i, i + this.maxBatchSize);
62
+ await this.sendPost({
63
+ requestType: "captureBatchEvents",
64
+ data: { events: chunk },
65
+ });
66
+ }
67
+ }
68
+ }
69
+ // ─── Session Management ──────────────────────────────────────
70
+ async createSession(options) {
71
+ return this.sendPost({
72
+ requestType: "createSession",
73
+ data: {
74
+ featureFlags: options?.featureFlags,
75
+ },
76
+ });
77
+ }
78
+ async getSession(sessionId) {
79
+ return this.sendGet("getSession", { sessionId });
80
+ }
81
+ // ─── Event Tracking ──────────────────────────────────────────
82
+ async captureEvent(input) {
83
+ const event = input;
84
+ if (this.flushInterval > 0) {
85
+ this.enqueueEvent(event);
86
+ return;
87
+ }
88
+ await this.sendPost({
89
+ requestType: "captureEvent",
90
+ data: event,
91
+ });
92
+ }
93
+ async capturePageView(sessionId, path) {
94
+ const event = { sessionId, eventName: "pageview", properties: { path } };
95
+ if (this.flushInterval > 0) {
96
+ this.enqueueEvent(event);
97
+ return;
98
+ }
99
+ await this.sendPost({
100
+ requestType: "captureEvent",
101
+ data: event,
102
+ });
103
+ }
104
+ async captureClick(sessionId, element) {
105
+ const event = { sessionId, eventName: "click", properties: { element } };
106
+ if (this.flushInterval > 0) {
107
+ this.enqueueEvent(event);
108
+ return;
109
+ }
110
+ await this.sendPost({
111
+ requestType: "captureEvent",
112
+ data: event,
113
+ });
114
+ }
115
+ async captureError(sessionId, message) {
116
+ const event = { sessionId, eventName: "error", properties: { message } };
117
+ if (this.flushInterval > 0) {
118
+ this.enqueueEvent(event);
119
+ return;
120
+ }
121
+ await this.sendPost({
122
+ requestType: "captureEvent",
123
+ data: event,
124
+ });
125
+ }
126
+ async captureWarning(sessionId, message) {
127
+ const event = { sessionId, eventName: "warning", properties: { message } };
128
+ if (this.flushInterval > 0) {
129
+ this.enqueueEvent(event);
130
+ return;
131
+ }
132
+ await this.sendPost({
133
+ requestType: "captureEvent",
134
+ data: event,
135
+ });
136
+ }
137
+ async captureInfo(sessionId, message) {
138
+ const event = { sessionId, eventName: "info", properties: { message } };
139
+ if (this.flushInterval > 0) {
140
+ this.enqueueEvent(event);
141
+ return;
142
+ }
143
+ await this.sendPost({
144
+ requestType: "captureEvent",
145
+ data: event,
146
+ });
147
+ }
148
+ // ─── Feature Flags ───────────────────────────────────────────
149
+ async getFeatureFlag(sessionId, flagName) {
150
+ const result = await this.sendGet("getFeatureFlag", { sessionId, flagName });
151
+ return result.value;
152
+ }
153
+ async getAllFeatureFlags(sessionId) {
154
+ return this.sendGet("getAllFeatureFlags", { sessionId });
155
+ }
156
+ }
157
+ exports.AnalyticsClient = AnalyticsClient;
@@ -0,0 +1,11 @@
1
+ export { AnalyticsBackendClient } from "./backend-client";
2
+ export type { HandlerOptions, MiddlewareResult } from "./backend-client";
3
+ export { AnalyticsClient } from "./client";
4
+ export { EventService } from "./services/events";
5
+ export { SessionService } from "./services/sessions";
6
+ export { FeatureFlagService } from "./services/feature-flags";
7
+ export { SchemaRegistry } from "./services/schema-registry";
8
+ export { SearchIndexService } from "./services/search-index";
9
+ export { LoggingService } from "./services/logging";
10
+ export type { AnalyticsConfig, CaptureEventInput, ClientConfig, DeepPartial, EventData, EventSchema, FeatureFlagAssignment, FeatureFlagConfig, FeatureFlagDefinition, FeatureFlagDefinitions, LogType, SchemaProperty, SchemaPropertyType, SearchIndexInfo, SDKOptions, ServerConfig, Session, SessionMetadata, SessionResult, StandardEventMap, StandardEventName, SystemLog, } from "./types";
11
+ export type { AnalyticsRequest, AnalyticsResponse } from "./protocol";
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LoggingService = exports.SearchIndexService = exports.SchemaRegistry = exports.FeatureFlagService = exports.SessionService = exports.EventService = exports.AnalyticsClient = exports.AnalyticsBackendClient = void 0;
4
+ var backend_client_1 = require("./backend-client");
5
+ Object.defineProperty(exports, "AnalyticsBackendClient", { enumerable: true, get: function () { return backend_client_1.AnalyticsBackendClient; } });
6
+ var client_1 = require("./client");
7
+ Object.defineProperty(exports, "AnalyticsClient", { enumerable: true, get: function () { return client_1.AnalyticsClient; } });
8
+ // Services (for advanced usage)
9
+ var events_1 = require("./services/events");
10
+ Object.defineProperty(exports, "EventService", { enumerable: true, get: function () { return events_1.EventService; } });
11
+ var sessions_1 = require("./services/sessions");
12
+ Object.defineProperty(exports, "SessionService", { enumerable: true, get: function () { return sessions_1.SessionService; } });
13
+ var feature_flags_1 = require("./services/feature-flags");
14
+ Object.defineProperty(exports, "FeatureFlagService", { enumerable: true, get: function () { return feature_flags_1.FeatureFlagService; } });
15
+ var schema_registry_1 = require("./services/schema-registry");
16
+ Object.defineProperty(exports, "SchemaRegistry", { enumerable: true, get: function () { return schema_registry_1.SchemaRegistry; } });
17
+ var search_index_1 = require("./services/search-index");
18
+ Object.defineProperty(exports, "SearchIndexService", { enumerable: true, get: function () { return search_index_1.SearchIndexService; } });
19
+ var logging_1 = require("./services/logging");
20
+ Object.defineProperty(exports, "LoggingService", { enumerable: true, get: function () { return logging_1.LoggingService; } });