autotel-subscribers 4.0.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 (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +669 -0
  3. package/dist/amplitude.cjs +2486 -0
  4. package/dist/amplitude.cjs.map +1 -0
  5. package/dist/amplitude.d.cts +49 -0
  6. package/dist/amplitude.d.ts +49 -0
  7. package/dist/amplitude.js +2463 -0
  8. package/dist/amplitude.js.map +1 -0
  9. package/dist/event-subscriber-base-CnF3V56W.d.cts +182 -0
  10. package/dist/event-subscriber-base-CnF3V56W.d.ts +182 -0
  11. package/dist/factories.cjs +16660 -0
  12. package/dist/factories.cjs.map +1 -0
  13. package/dist/factories.d.cts +304 -0
  14. package/dist/factories.d.ts +304 -0
  15. package/dist/factories.js +16624 -0
  16. package/dist/factories.js.map +1 -0
  17. package/dist/index.cjs +16575 -0
  18. package/dist/index.cjs.map +1 -0
  19. package/dist/index.d.cts +179 -0
  20. package/dist/index.d.ts +179 -0
  21. package/dist/index.js +16539 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/middleware.cjs +220 -0
  24. package/dist/middleware.cjs.map +1 -0
  25. package/dist/middleware.d.cts +227 -0
  26. package/dist/middleware.d.ts +227 -0
  27. package/dist/middleware.js +208 -0
  28. package/dist/middleware.js.map +1 -0
  29. package/dist/mixpanel.cjs +2940 -0
  30. package/dist/mixpanel.cjs.map +1 -0
  31. package/dist/mixpanel.d.cts +47 -0
  32. package/dist/mixpanel.d.ts +47 -0
  33. package/dist/mixpanel.js +2932 -0
  34. package/dist/mixpanel.js.map +1 -0
  35. package/dist/posthog.cjs +4115 -0
  36. package/dist/posthog.cjs.map +1 -0
  37. package/dist/posthog.d.cts +299 -0
  38. package/dist/posthog.d.ts +299 -0
  39. package/dist/posthog.js +4113 -0
  40. package/dist/posthog.js.map +1 -0
  41. package/dist/segment.cjs +6822 -0
  42. package/dist/segment.cjs.map +1 -0
  43. package/dist/segment.d.cts +49 -0
  44. package/dist/segment.d.ts +49 -0
  45. package/dist/segment.js +6794 -0
  46. package/dist/segment.js.map +1 -0
  47. package/dist/slack.cjs +368 -0
  48. package/dist/slack.cjs.map +1 -0
  49. package/dist/slack.d.cts +126 -0
  50. package/dist/slack.d.ts +126 -0
  51. package/dist/slack.js +366 -0
  52. package/dist/slack.js.map +1 -0
  53. package/dist/webhook.cjs +100 -0
  54. package/dist/webhook.cjs.map +1 -0
  55. package/dist/webhook.d.cts +53 -0
  56. package/dist/webhook.d.ts +53 -0
  57. package/dist/webhook.js +98 -0
  58. package/dist/webhook.js.map +1 -0
  59. package/examples/quickstart-custom-subscriber.ts +144 -0
  60. package/examples/subscriber-bigquery.ts +219 -0
  61. package/examples/subscriber-databricks.ts +280 -0
  62. package/examples/subscriber-kafka.ts +326 -0
  63. package/examples/subscriber-kinesis.ts +307 -0
  64. package/examples/subscriber-posthog.ts +421 -0
  65. package/examples/subscriber-pubsub.ts +336 -0
  66. package/examples/subscriber-snowflake.ts +232 -0
  67. package/package.json +141 -0
  68. package/src/amplitude.test.ts +231 -0
  69. package/src/amplitude.ts +148 -0
  70. package/src/event-subscriber-base.ts +325 -0
  71. package/src/factories.ts +197 -0
  72. package/src/index.ts +50 -0
  73. package/src/middleware.ts +489 -0
  74. package/src/mixpanel.test.ts +194 -0
  75. package/src/mixpanel.ts +134 -0
  76. package/src/mock-event-subscriber.ts +333 -0
  77. package/src/posthog.test.ts +629 -0
  78. package/src/posthog.ts +530 -0
  79. package/src/segment.test.ts +228 -0
  80. package/src/segment.ts +148 -0
  81. package/src/slack.ts +383 -0
  82. package/src/streaming-event-subscriber.ts +323 -0
  83. package/src/testing/index.ts +37 -0
  84. package/src/testing/mock-webhook-server.ts +242 -0
  85. package/src/testing/subscriber-test-harness.ts +365 -0
  86. package/src/webhook.test.ts +264 -0
  87. package/src/webhook.ts +158 -0
@@ -0,0 +1,336 @@
1
+ /**
2
+ * Google Cloud Pub/Sub Streaming Subscriber Example
3
+ *
4
+ * Production-ready Pub/Sub subscriber for GCP-native event streaming.
5
+ *
6
+ * Installation:
7
+ * ```bash
8
+ * pnpm add @google-cloud/pubsub
9
+ * ```
10
+ *
11
+ * Features:
12
+ * - Ordered delivery with ordering keys
13
+ * - Automatic batching and flow control
14
+ * - Backpressure handling
15
+ * - Message deduplication
16
+ * - Dead letter queue support
17
+ * - Graceful shutdown
18
+ *
19
+ * Setup:
20
+ * ```bash
21
+ * # Create topic
22
+ * gcloud pubsub topics create events-events \
23
+ * --message-retention-duration=7d
24
+ *
25
+ * # Create subscription (for consumers)
26
+ * gcloud pubsub subscriptions create events-events-sub \
27
+ * --topic=events-events \
28
+ * --ack-deadline=60 \
29
+ * --message-retention-duration=7d
30
+ * ```
31
+ *
32
+ * Usage:
33
+ * ```typescript
34
+ * import { Events } from 'autotel/events';
35
+ * import { PubSubSubscriber } from './adapter-pubsub';
36
+ *
37
+ * const events = new Events('app', {
38
+ * subscribers: [
39
+ * new PubSubSubscriber({
40
+ * projectId: 'my-gcp-project',
41
+ * topicName: 'events-events',
42
+ * enableMessageOrdering: true,
43
+ * partitionStrategy: 'userId',
44
+ * maxBufferSize: 10000,
45
+ * maxBatchSize: 1000,
46
+ * bufferOverflowStrategy: 'block'
47
+ * })
48
+ * ]
49
+ * });
50
+ *
51
+ * // Events ordered by userId
52
+ * await events.trackEvent('order.completed', {
53
+ * userId: 'user_123',
54
+ * amount: 99.99
55
+ * });
56
+ * ```
57
+ */
58
+
59
+ import {
60
+ StreamingEventSubscriber,
61
+ type BufferOverflowStrategy,
62
+ } from '../src/streaming-event-subscriber';
63
+ import type { EventPayload } from '../src/event-subscriber-base';
64
+ import { PubSub, Topic } from '@google-cloud/pubsub';
65
+
66
+ type PartitionStrategy = 'userId' | 'tenantId' | 'eventType' | 'none';
67
+
68
+ export interface PubSubSubscriberConfig {
69
+ /** GCP Project ID */
70
+ projectId: string;
71
+
72
+ /** Pub/Sub topic name */
73
+ topicName: string;
74
+
75
+ /** Enable message ordering (default: true) */
76
+ enableMessageOrdering?: boolean;
77
+
78
+ /** Partitioning strategy for ordering keys (default: 'userId') */
79
+ partitionStrategy?: PartitionStrategy;
80
+
81
+ /** Enable/disable subscriber */
82
+ enabled?: boolean;
83
+
84
+ /** Maximum buffer size (default: 10000) */
85
+ maxBufferSize?: number;
86
+
87
+ /** Maximum batch size (default: 1000) */
88
+ maxBatchSize?: number;
89
+
90
+ /** Buffer overflow strategy (default: 'block') */
91
+ bufferOverflowStrategy?: BufferOverflowStrategy;
92
+
93
+ /** Flush interval in ms (default: 1000) */
94
+ flushIntervalMs?: number;
95
+
96
+ /** Service account key file path (optional, uses GOOGLE_APPLICATION_CREDENTIALS if not set) */
97
+ keyFilename?: string;
98
+
99
+ /** Enable batching settings (default: true) */
100
+ enableBatching?: boolean;
101
+
102
+ /** Max outstanding messages (flow control) (default: 1000) */
103
+ maxOutstandingMessages?: number;
104
+
105
+ /** Max outstanding bytes (flow control) (default: 100MB) */
106
+ maxOutstandingBytes?: number;
107
+ }
108
+
109
+ export class PubSubSubscriber extends StreamingEventSubscriber {
110
+ readonly name = 'PubSubSubscriber';
111
+ readonly version = '1.0.0';
112
+
113
+ private client: PubSub;
114
+ private topic: Topic;
115
+ private subscriberConfig: Required<
116
+ Omit<PubSubSubscriberConfig, 'keyFilename'>
117
+ > & {
118
+ keyFilename?: string;
119
+ };
120
+
121
+ constructor(config: PubSubSubscriberConfig) {
122
+ super({
123
+ maxBufferSize: config.maxBufferSize ?? 10_000,
124
+ maxBatchSize: config.maxBatchSize ?? 1000,
125
+ bufferOverflowStrategy: config.bufferOverflowStrategy ?? 'block',
126
+ flushIntervalMs: config.flushIntervalMs ?? 1000,
127
+ });
128
+
129
+ // Set config defaults
130
+ this.adapterConfig = {
131
+ projectId: config.projectId,
132
+ topicName: config.topicName,
133
+ enableMessageOrdering: config.enableMessageOrdering ?? true,
134
+ partitionStrategy: config.partitionStrategy ?? 'userId',
135
+ enabled: config.enabled ?? true,
136
+ maxBufferSize: config.maxBufferSize ?? 10_000,
137
+ maxBatchSize: config.maxBatchSize ?? 1000,
138
+ bufferOverflowStrategy: config.bufferOverflowStrategy ?? 'block',
139
+ flushIntervalMs: config.flushIntervalMs ?? 1000,
140
+ keyFilename: config.keyFilename,
141
+ enableBatching: config.enableBatching ?? true,
142
+ maxOutstandingMessages: config.maxOutstandingMessages ?? 1000,
143
+ maxOutstandingBytes: config.maxOutstandingBytes ?? 100 * 1024 * 1024, // 100MB
144
+ };
145
+
146
+ this.enabled = this.adapterConfig.enabled;
147
+
148
+ if (this.enabled) {
149
+ this.initializePubSub();
150
+ }
151
+ }
152
+
153
+ private initializePubSub(): void {
154
+ try {
155
+ const options: any = {
156
+ projectId: this.adapterConfig.projectId,
157
+ };
158
+
159
+ if (this.adapterConfig.keyFilename) {
160
+ options.keyFilename = this.adapterConfig.keyFilename;
161
+ }
162
+
163
+ this.client = new PubSub(options);
164
+
165
+ // Get topic reference
166
+ this.topic = this.client.topic(this.adapterConfig.topicName);
167
+
168
+ // Configure topic settings (combine all options in single call to avoid overwriting)
169
+ const publishOptions: any = {};
170
+
171
+ if (this.adapterConfig.enableMessageOrdering) {
172
+ publishOptions.messageOrdering = true;
173
+ }
174
+
175
+ if (this.adapterConfig.enableBatching) {
176
+ publishOptions.batching = {
177
+ maxMessages: this.adapterConfig.maxBatchSize,
178
+ maxMilliseconds: this.adapterConfig.flushIntervalMs,
179
+ };
180
+ publishOptions.flowControlOptions = {
181
+ maxOutstandingMessages: this.adapterConfig.maxOutstandingMessages,
182
+ maxOutstandingBytes: this.adapterConfig.maxOutstandingBytes,
183
+ };
184
+ }
185
+
186
+ // Set all options at once to avoid overwriting previous settings
187
+ if (Object.keys(publishOptions).length > 0) {
188
+ this.topic.setPublishOptions(publishOptions);
189
+ }
190
+
191
+ console.log('[PubSubSubscriber] Initialized successfully');
192
+ } catch (error) {
193
+ console.error('[PubSubSubscriber] Failed to initialize:', error);
194
+ this.enabled = false;
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Get ordering key (partition key) based on configured strategy
200
+ *
201
+ * Pub/Sub uses ordering keys to ensure messages with same key
202
+ * are delivered in order to subscribers.
203
+ */
204
+ protected getPartitionKey(payload: EventPayload): string {
205
+ switch (this.adapterConfig.partitionStrategy) {
206
+ case 'userId': {
207
+ return payload.attributes?.userId?.toString() || '';
208
+ }
209
+
210
+ case 'tenantId': {
211
+ return payload.attributes?.tenantId?.toString() || '';
212
+ }
213
+
214
+ case 'eventType': {
215
+ return payload.type;
216
+ } // 'event', 'funnel', 'outcome', 'value'
217
+
218
+ case 'none': {
219
+ return '';
220
+ } // No ordering
221
+
222
+ default: {
223
+ return '';
224
+ }
225
+ }
226
+ }
227
+
228
+ /**
229
+ * Send batch of events to Pub/Sub
230
+ */
231
+ protected async sendBatch(events: EventPayload[]): Promise<void> {
232
+ // Publish all messages concurrently
233
+ const publishPromises = events.map((event) => {
234
+ const data = Buffer.from(JSON.stringify(event));
235
+ const orderingKey = this.getPartitionKey(event);
236
+
237
+ const message: any = {
238
+ data,
239
+ attributes: {
240
+ eventType: event.type,
241
+ eventName: event.name,
242
+ timestamp: event.timestamp,
243
+ },
244
+ };
245
+
246
+ // Add ordering key if message ordering is enabled
247
+ if (
248
+ this.adapterConfig.enableMessageOrdering &&
249
+ orderingKey
250
+ ) {
251
+ message.orderingKey = orderingKey;
252
+ }
253
+
254
+ return this.topic.publishMessage(message);
255
+ });
256
+
257
+ try {
258
+ // Wait for all publishes to complete
259
+ const messageIds = await Promise.all(publishPromises);
260
+
261
+ // Success - log metrics
262
+ if (process.env.DEBUG) {
263
+ console.log(
264
+ `[PubSubSubscriber] Published ${events.length} messages (IDs: ${messageIds.slice(0, 3).join(', ')}${events.length > 3 ? '...' : ''})`
265
+ );
266
+ }
267
+ } catch (error: any) {
268
+ console.error(
269
+ `[PubSubSubscriber] Failed to publish ${events.length} messages:`,
270
+ error
271
+ );
272
+
273
+ // Handle specific Pub/Sub errors
274
+ if (error.code === 10) {
275
+ console.error(
276
+ '[PubSubSubscriber] Flow control limits exceeded - reduce rate or increase limits'
277
+ );
278
+ }
279
+
280
+ if (error.code === 5) {
281
+ console.error(
282
+ `[PubSubSubscriber] Topic not found: ${this.adapterConfig.topicName}`
283
+ );
284
+ }
285
+
286
+ throw error;
287
+ }
288
+ }
289
+
290
+ /**
291
+ * Handle errors (override from EventSubscriber)
292
+ */
293
+ protected handleError(error: Error, payload: EventPayload): void {
294
+ console.error(
295
+ `[PubSubSubscriber] Failed to process ${payload.type} event:`,
296
+ error,
297
+ {
298
+ eventName: payload.name,
299
+ orderingKey: this.getPartitionKey(payload),
300
+ topicName: this.adapterConfig.topicName,
301
+ }
302
+ );
303
+ }
304
+
305
+ /**
306
+ * Graceful shutdown
307
+ */
308
+ async shutdown(): Promise<void> {
309
+ console.log('[PubSubSubscriber] Starting graceful shutdown...');
310
+
311
+ // Flush buffer and drain pending requests
312
+ await super.shutdown();
313
+
314
+ // Flush any remaining messages in topic's internal buffer
315
+ if (this.topic) {
316
+ try {
317
+ await this.topic.flush();
318
+ console.log('[PubSubSubscriber] Flushed topic buffer');
319
+ } catch (error) {
320
+ console.error('[PubSubSubscriber] Error flushing topic:', error);
321
+ }
322
+ }
323
+
324
+ // Close Pub/Sub client
325
+ if (this.client) {
326
+ try {
327
+ await this.client.close();
328
+ console.log('[PubSubSubscriber] Closed Pub/Sub client');
329
+ } catch (error) {
330
+ console.error('[PubSubSubscriber] Error closing client:', error);
331
+ }
332
+ }
333
+
334
+ console.log('[PubSubSubscriber] Shutdown complete');
335
+ }
336
+ }
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Snowflake Subscriber Example
3
+ *
4
+ * Sends events events to Snowflake data warehouse.
5
+ * This is a complete, production-ready implementation.
6
+ *
7
+ * Installation:
8
+ * ```bash
9
+ * pnpm add snowflake-sdk
10
+ * ```
11
+ *
12
+ * Setup Snowflake table:
13
+ * ```sql
14
+ * CREATE TABLE events_events (
15
+ * event_id VARCHAR(36) PRIMARY KEY,
16
+ * event_type VARCHAR(50) NOT NULL,
17
+ * event_name VARCHAR(255) NOT NULL,
18
+ * attributes VARIANT,
19
+ * funnel VARCHAR(100),
20
+ * step VARCHAR(50),
21
+ * operation VARCHAR(100),
22
+ * outcome VARCHAR(50),
23
+ * value DECIMAL(18,2),
24
+ * timestamp TIMESTAMP_NTZ NOT NULL,
25
+ * created_at TIMESTAMP_NTZ DEFAULT CURRENT_TIMESTAMP()
26
+ * );
27
+ *
28
+ * CREATE INDEX idx_event_type ON events_events(event_type);
29
+ * CREATE INDEX idx_event_name ON events_events(event_name);
30
+ * CREATE INDEX idx_timestamp ON events_events(timestamp);
31
+ * ```
32
+ *
33
+ * Usage:
34
+ * ```typescript
35
+ * import { Events } from 'autotel/events';
36
+ * import { SnowflakeSubscriber } from './adapter-snowflake';
37
+ *
38
+ * const events = new Events('app', {
39
+ * subscribers: [
40
+ * new SnowflakeSubscriber({
41
+ * account: 'xy12345.us-east-1',
42
+ * username: process.env.SNOWFLAKE_USER!,
43
+ * password: process.env.SNOWFLAKE_PASS!,
44
+ * database: 'ANALYTICS',
45
+ * schema: 'PUBLIC',
46
+ * warehouse: 'COMPUTE_WH',
47
+ * table: 'events_events'
48
+ * })
49
+ * ]
50
+ * });
51
+ *
52
+ * events.trackEvent('order.completed', { orderId: 'ord_123', amount: 99.99 });
53
+ * ```
54
+ */
55
+
56
+ import {
57
+ EventSubscriber,
58
+ type EventPayload,
59
+ } from '../src/event-subscriber-base';
60
+ import snowflake from 'snowflake-sdk';
61
+
62
+ export interface SnowflakeSubscriberConfig {
63
+ /** Snowflake account (e.g., 'xy12345.us-east-1') */
64
+ account: string;
65
+ /** Username */
66
+ username: string;
67
+ /** Password */
68
+ password: string;
69
+ /** Database name */
70
+ database: string;
71
+ /** Schema name (default: 'PUBLIC') */
72
+ schema?: string;
73
+ /** Warehouse name (default: 'COMPUTE_WH') */
74
+ warehouse?: string;
75
+ /** Table name (default: 'events_events') */
76
+ table?: string;
77
+ /** Enable/disable subscriber */
78
+ enabled?: boolean;
79
+ /** Batch size (default: 100) */
80
+ batchSize?: number;
81
+ /** Flush interval in ms (default: 10000) */
82
+ flushInterval?: number;
83
+ }
84
+
85
+ export class SnowflakeSubscriber extends EventSubscriber {
86
+ readonly name = 'SnowflakeSubscriber';
87
+ readonly version = '1.0.0';
88
+
89
+ private connection: snowflake.Connection;
90
+ private config: Required<SnowflakeSubscriberConfig>;
91
+ private buffer: EventPayload[] = [];
92
+ private flushIntervalHandle: NodeJS.Timeout | null = null;
93
+
94
+ constructor(config: SnowflakeSubscriberConfig) {
95
+ super();
96
+
97
+ // Set defaults
98
+ this.config = {
99
+ schema: 'PUBLIC',
100
+ warehouse: 'COMPUTE_WH',
101
+ table: 'events_events',
102
+ enabled: true,
103
+ batchSize: 100,
104
+ flushInterval: 10_000,
105
+ ...config,
106
+ };
107
+
108
+ this.enabled = this.config.enabled;
109
+
110
+ if (this.enabled) {
111
+ this.initializeConnection();
112
+ this.startFlushInterval();
113
+ }
114
+ }
115
+
116
+ private initializeConnection(): void {
117
+ this.connection = snowflake.createConnection({
118
+ account: this.config.account,
119
+ username: this.config.username,
120
+ password: this.config.password,
121
+ database: this.config.database,
122
+ schema: this.config.schema,
123
+ warehouse: this.config.warehouse,
124
+ });
125
+
126
+ // Connect asynchronously
127
+ this.connection.connect((err) => {
128
+ if (err) {
129
+ console.error('[SnowflakeSubscriber] Failed to connect:', err);
130
+ this.enabled = false;
131
+ } else {
132
+ console.log('[SnowflakeSubscriber] Connected successfully');
133
+ }
134
+ });
135
+ }
136
+
137
+ private startFlushInterval(): void {
138
+ this.flushIntervalHandle = setInterval(() => {
139
+ void this.flushBuffer();
140
+ }, this.config.flushInterval);
141
+ }
142
+
143
+ protected async sendToDestination(payload: EventPayload): Promise<void> {
144
+ this.buffer.push(payload);
145
+
146
+ // Auto-flush at batch size
147
+ if (this.buffer.length >= this.config.batchSize) {
148
+ await this.flushBuffer();
149
+ }
150
+ }
151
+
152
+ private async flushBuffer(): Promise<void> {
153
+ if (this.buffer.length === 0) return;
154
+
155
+ const batch = [...this.buffer];
156
+ this.buffer = [];
157
+
158
+ try {
159
+ await this.insertBatch(batch);
160
+ } catch (error) {
161
+ console.error('[SnowflakeSubscriber] Failed to flush batch:', error);
162
+ // Re-add to buffer for retry
163
+ this.buffer.unshift(...batch);
164
+ }
165
+ }
166
+
167
+ private async insertBatch(events: EventPayload[]): Promise<void> {
168
+ const sql = `
169
+ INSERT INTO ${this.config.table}
170
+ (event_id, event_type, event_name, attributes, funnel, step, operation, outcome, value, timestamp)
171
+ SELECT
172
+ column1 as event_id,
173
+ column2 as event_type,
174
+ column3 as event_name,
175
+ PARSE_JSON(column4) as attributes,
176
+ column5 as funnel,
177
+ column6 as step,
178
+ column7 as operation,
179
+ column8 as outcome,
180
+ column9 as value,
181
+ TO_TIMESTAMP_NTZ(column10) as timestamp
182
+ FROM VALUES ${events.map(() => '(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)').join(', ')}
183
+ `;
184
+
185
+ const binds = events.flatMap((event) => [
186
+ crypto.randomUUID(),
187
+ event.type,
188
+ event.name,
189
+ JSON.stringify(event.attributes || {}),
190
+ event.funnel || null,
191
+ event.step || null,
192
+ event.operation || null,
193
+ event.outcome || null,
194
+ event.value || null,
195
+ event.timestamp,
196
+ ]);
197
+
198
+ return new Promise((resolve, reject) => {
199
+ this.connection.execute({
200
+ sqlText: sql,
201
+ binds,
202
+ complete: (err, _stmt, _rows) => {
203
+ if (err) reject(err);
204
+ else resolve();
205
+ },
206
+ });
207
+ });
208
+ }
209
+
210
+ async shutdown(): Promise<void> {
211
+ // Clear flush interval
212
+ if (this.flushIntervalHandle) {
213
+ clearInterval(this.flushIntervalHandle);
214
+ this.flushIntervalHandle = null;
215
+ }
216
+
217
+ // Flush remaining events
218
+ await this.flushBuffer();
219
+
220
+ // Wait for pending requests
221
+ await super.shutdown();
222
+
223
+ // Close connection
224
+ if (this.connection) {
225
+ this.connection.destroy((err) => {
226
+ if (err) {
227
+ console.error('[SnowflakeSubscriber] Error closing connection:', err);
228
+ }
229
+ });
230
+ }
231
+ }
232
+ }
package/package.json ADDED
@@ -0,0 +1,141 @@
1
+ {
2
+ "name": "autotel-subscribers",
3
+ "version": "4.0.0",
4
+ "description": "Write Once, Observe Anywhere - Event subscribers for autotel (PostHog, Mixpanel, Amplitude, Segment)",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "type": "module",
8
+ "sideEffects": false,
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ },
15
+ "./posthog": {
16
+ "types": "./dist/posthog.d.ts",
17
+ "import": "./dist/posthog.js",
18
+ "require": "./dist/posthog.cjs"
19
+ },
20
+ "./mixpanel": {
21
+ "types": "./dist/mixpanel.d.ts",
22
+ "import": "./dist/mixpanel.js",
23
+ "require": "./dist/mixpanel.cjs"
24
+ },
25
+ "./segment": {
26
+ "types": "./dist/segment.d.ts",
27
+ "import": "./dist/segment.js",
28
+ "require": "./dist/segment.cjs"
29
+ },
30
+ "./amplitude": {
31
+ "types": "./dist/amplitude.d.ts",
32
+ "import": "./dist/amplitude.js",
33
+ "require": "./dist/amplitude.cjs"
34
+ },
35
+ "./webhook": {
36
+ "types": "./dist/webhook.d.ts",
37
+ "import": "./dist/webhook.js",
38
+ "require": "./dist/webhook.cjs"
39
+ },
40
+ "./slack": {
41
+ "types": "./dist/slack.d.ts",
42
+ "import": "./dist/slack.js",
43
+ "require": "./dist/slack.cjs"
44
+ },
45
+ "./factories": {
46
+ "types": "./dist/factories.d.ts",
47
+ "import": "./dist/factories.js",
48
+ "require": "./dist/factories.cjs"
49
+ },
50
+ "./middleware": {
51
+ "types": "./dist/middleware.d.ts",
52
+ "import": "./dist/middleware.js",
53
+ "require": "./dist/middleware.cjs"
54
+ },
55
+ "./testing": {
56
+ "types": "./dist/testing/index.d.ts",
57
+ "import": "./dist/testing/index.js",
58
+ "require": "./dist/testing/index.cjs"
59
+ }
60
+ },
61
+ "files": [
62
+ "dist",
63
+ "src",
64
+ "examples",
65
+ "README.md"
66
+ ],
67
+ "keywords": [
68
+ "autotel",
69
+ "opentelemetry",
70
+ "analytics",
71
+ "posthog",
72
+ "mixpanel",
73
+ "amplitude",
74
+ "segment",
75
+ "webhook",
76
+ "adapters",
77
+ "business-metrics",
78
+ "product-analytics",
79
+ "telemetry",
80
+ "observability"
81
+ ],
82
+ "author": "Jag Reehal<jag@jagreehal.com> (https://jagreehal.com)",
83
+ "license": "MIT",
84
+ "peerDependencies": {
85
+ "autotel": "2.1.0"
86
+ },
87
+ "peerDependenciesMeta": {
88
+ "posthog-node": {
89
+ "optional": true
90
+ },
91
+ "mixpanel": {
92
+ "optional": true
93
+ },
94
+ "@segment/analytics-node": {
95
+ "optional": true
96
+ },
97
+ "@amplitude/analytics-node": {
98
+ "optional": true
99
+ }
100
+ },
101
+ "devDependencies": {
102
+ "@amplitude/analytics-node": "^1.5.26",
103
+ "@arethetypeswrong/cli": "^0.18.2",
104
+ "@cloudflare/workers-types": "^4.20251121.0",
105
+ "@prisma/client": "^7.0.0",
106
+ "@segment/analytics-node": "^2.3.0",
107
+ "@types/node": "^24.10.1",
108
+ "@typescript-eslint/eslint-plugin": "^8.47.0",
109
+ "@typescript-eslint/parser": "^8.47.0",
110
+ "drizzle-orm": "^0.44.7",
111
+ "eslint-config-prettier": "^10.1.8",
112
+ "eslint-plugin-unicorn": "^62.0.0",
113
+ "mixpanel": "^0.19.1",
114
+ "mongoose": "^9.0.0",
115
+ "posthog-node": "^5.13.2",
116
+ "prettier": "^3.6.2",
117
+ "rimraf": "^6.1.2",
118
+ "tsup": "^8.5.1",
119
+ "typescript": "^5.9.3",
120
+ "typescript-eslint": "^8.47.0",
121
+ "vitest": "^4.0.13",
122
+ "autotel": "2.1.0"
123
+ },
124
+ "repository": {
125
+ "type": "git",
126
+ "url": "https://github.com/jagreehal/autotel"
127
+ },
128
+ "bugs": {
129
+ "url": "https://github.com/jagreehal/autotel/issues"
130
+ },
131
+ "homepage": "https://github.com/jagreehal/autotel#readme",
132
+ "scripts": {
133
+ "build": "tsup",
134
+ "dev": "tsup --watch",
135
+ "lint": "npx eslint 'src/**/*.ts' 'examples/**/*.ts'",
136
+ "lint:fix": "npx eslint 'src/**/*.ts' 'examples/**/*.ts' --fix",
137
+ "type-check": "tsc --noEmit",
138
+ "test": "vitest run",
139
+ "test:watch": "vitest"
140
+ }
141
+ }