@datalyr/api 1.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.
package/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # @datalyr/node
2
+
3
+ Official Node.js SDK for Datalyr server-side tracking.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @datalyr/node
9
+ # or
10
+ yarn add @datalyr/node
11
+ # or
12
+ pnpm add @datalyr/node
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```javascript
18
+ const Datalyr = require('@datalyr/api');
19
+ // or
20
+ import Datalyr from '@datalyr/node';
21
+
22
+ // Initialize with your API key
23
+ const datalyr = new Datalyr('your_api_key_here');
24
+
25
+ // Track an event
26
+ await datalyr.track('user_123', 'Purchase Completed', {
27
+ amount: 99.99,
28
+ currency: 'USD',
29
+ products: ['item_1', 'item_2']
30
+ });
31
+
32
+ // Identify a user
33
+ await datalyr.identify('user_123', {
34
+ email: 'user@example.com',
35
+ name: 'John Doe',
36
+ plan: 'premium'
37
+ });
38
+
39
+ // Track a pageview
40
+ await datalyr.page('user_123', 'Homepage', {
41
+ url: 'https://example.com',
42
+ referrer: 'https://google.com'
43
+ });
44
+
45
+ // Group a user
46
+ await datalyr.group('user_123', 'company_456', {
47
+ name: 'Acme Corp',
48
+ industry: 'Technology'
49
+ });
50
+
51
+ // Clean up when done
52
+ await datalyr.close();
53
+ ```
54
+
55
+ ## Configuration
56
+
57
+ ```javascript
58
+ const datalyr = new Datalyr({
59
+ apiKey: 'your_api_key_here',
60
+ host: 'https://api.datalyr.com', // Optional: custom host
61
+ flushAt: 20, // Optional: batch size (default: 20)
62
+ flushInterval: 10000, // Optional: batch interval in ms (default: 10000)
63
+ debug: true, // Optional: enable debug logging (default: false)
64
+ timeout: 10000, // Optional: request timeout in ms (default: 10000)
65
+ retryLimit: 3, // Optional: max retries (default: 3)
66
+ maxQueueSize: 1000 // Optional: max events in queue (default: 1000)
67
+ });
68
+ ```
69
+
70
+ ## Stripe Webhook Example
71
+
72
+ ```javascript
73
+ const Datalyr = require('@datalyr/api');
74
+ const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
75
+
76
+ const datalyr = new Datalyr(process.env.DATALYR_API_KEY);
77
+
78
+ app.post('/webhooks/stripe', async (req, res) => {
79
+ const sig = req.headers['stripe-signature'];
80
+ const event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
81
+
82
+ switch (event.type) {
83
+ case 'checkout.session.completed':
84
+ await datalyr.track(
85
+ event.data.object.client_reference_id,
86
+ 'Purchase Completed',
87
+ {
88
+ amount: event.data.object.amount_total / 100,
89
+ currency: event.data.object.currency,
90
+ stripeSessionId: event.data.object.id
91
+ }
92
+ );
93
+ break;
94
+
95
+ case 'customer.subscription.created':
96
+ await datalyr.track(
97
+ event.data.object.metadata.userId,
98
+ 'Subscription Started',
99
+ {
100
+ plan: event.data.object.items.data[0].price.nickname,
101
+ mrr: event.data.object.items.data[0].price.unit_amount / 100,
102
+ interval: event.data.object.items.data[0].price.recurring.interval
103
+ }
104
+ );
105
+ break;
106
+ }
107
+
108
+ res.json({ received: true });
109
+ });
110
+ ```
111
+
112
+ ## API Reference
113
+
114
+ ### `new Datalyr(config)`
115
+
116
+ Creates a new Datalyr instance.
117
+
118
+ ### `track(userId, event, properties?)`
119
+
120
+ Track a custom event.
121
+
122
+ ### `identify(userId, traits?)`
123
+
124
+ Identify a user with traits.
125
+
126
+ ### `page(userId, name?, properties?)`
127
+
128
+ Track a pageview.
129
+
130
+ ### `group(userId, groupId, traits?)`
131
+
132
+ Associate a user with a group.
133
+
134
+ ### `flush()`
135
+
136
+ Manually flush the event queue.
137
+
138
+ ### `close()`
139
+
140
+ Flush remaining events and clean up resources.
141
+
142
+ ## License
143
+
144
+ MIT
@@ -0,0 +1,45 @@
1
+ interface DatalyrConfig {
2
+ apiKey: string;
3
+ host?: string;
4
+ flushAt?: number;
5
+ flushInterval?: number;
6
+ debug?: boolean;
7
+ timeout?: number;
8
+ retryLimit?: number;
9
+ maxQueueSize?: number;
10
+ }
11
+ interface TrackEvent {
12
+ userId?: string;
13
+ anonymousId?: string;
14
+ event: string;
15
+ properties?: Record<string, any>;
16
+ context?: Record<string, any>;
17
+ timestamp?: string;
18
+ }
19
+ declare class Datalyr {
20
+ private apiKey;
21
+ private host;
22
+ private debug;
23
+ private queue;
24
+ private flushAt;
25
+ private flushInterval;
26
+ private timeout;
27
+ private retryLimit;
28
+ private maxQueueSize;
29
+ private timer?;
30
+ private isFlushing;
31
+ private isClosing;
32
+ constructor(config: DatalyrConfig | string);
33
+ track(userId: string | null, event: string, properties?: any): Promise<void>;
34
+ identify(userId: string, traits?: any): Promise<void>;
35
+ page(userId: string, name?: string, properties?: any): Promise<void>;
36
+ group(userId: string, groupId: string, traits?: any): Promise<void>;
37
+ private enqueue;
38
+ flush(): Promise<void>;
39
+ private sendEvent;
40
+ private startFlushTimer;
41
+ private generateAnonymousId;
42
+ close(): Promise<void>;
43
+ }
44
+
45
+ export { Datalyr, type DatalyrConfig, type TrackEvent, Datalyr as default };
@@ -0,0 +1,45 @@
1
+ interface DatalyrConfig {
2
+ apiKey: string;
3
+ host?: string;
4
+ flushAt?: number;
5
+ flushInterval?: number;
6
+ debug?: boolean;
7
+ timeout?: number;
8
+ retryLimit?: number;
9
+ maxQueueSize?: number;
10
+ }
11
+ interface TrackEvent {
12
+ userId?: string;
13
+ anonymousId?: string;
14
+ event: string;
15
+ properties?: Record<string, any>;
16
+ context?: Record<string, any>;
17
+ timestamp?: string;
18
+ }
19
+ declare class Datalyr {
20
+ private apiKey;
21
+ private host;
22
+ private debug;
23
+ private queue;
24
+ private flushAt;
25
+ private flushInterval;
26
+ private timeout;
27
+ private retryLimit;
28
+ private maxQueueSize;
29
+ private timer?;
30
+ private isFlushing;
31
+ private isClosing;
32
+ constructor(config: DatalyrConfig | string);
33
+ track(userId: string | null, event: string, properties?: any): Promise<void>;
34
+ identify(userId: string, traits?: any): Promise<void>;
35
+ page(userId: string, name?: string, properties?: any): Promise<void>;
36
+ group(userId: string, groupId: string, traits?: any): Promise<void>;
37
+ private enqueue;
38
+ flush(): Promise<void>;
39
+ private sendEvent;
40
+ private startFlushTimer;
41
+ private generateAnonymousId;
42
+ close(): Promise<void>;
43
+ }
44
+
45
+ export { Datalyr, type DatalyrConfig, type TrackEvent, Datalyr as default };
package/dist/index.js ADDED
@@ -0,0 +1,241 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Datalyr: () => Datalyr,
24
+ default: () => index_default
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+ var Datalyr = class {
28
+ constructor(config) {
29
+ this.queue = [];
30
+ this.isFlushing = false;
31
+ this.isClosing = false;
32
+ if (typeof config === "string") {
33
+ this.apiKey = config;
34
+ this.host = "https://api.datalyr.com";
35
+ this.debug = false;
36
+ this.flushAt = 20;
37
+ this.flushInterval = 1e4;
38
+ this.timeout = 1e4;
39
+ this.retryLimit = 3;
40
+ this.maxQueueSize = 1e3;
41
+ } else {
42
+ this.apiKey = config.apiKey;
43
+ this.host = config.host || "https://api.datalyr.com";
44
+ this.debug = config.debug || false;
45
+ this.flushAt = config.flushAt || 20;
46
+ this.flushInterval = config.flushInterval || 1e4;
47
+ this.timeout = config.timeout || 1e4;
48
+ this.retryLimit = config.retryLimit || 3;
49
+ this.maxQueueSize = config.maxQueueSize || 1e3;
50
+ }
51
+ if (!this.apiKey) {
52
+ throw new Error("Datalyr API key is required");
53
+ }
54
+ if (!this.apiKey.startsWith("dk_")) {
55
+ console.warn('[Datalyr] API key should start with "dk_"');
56
+ }
57
+ if (this.flushAt < 1) this.flushAt = 1;
58
+ if (this.flushAt > 100) this.flushAt = 100;
59
+ if (this.timeout < 1e3) this.timeout = 1e3;
60
+ if (this.timeout > 6e4) this.timeout = 6e4;
61
+ if (this.maxQueueSize < 100) this.maxQueueSize = 100;
62
+ if (this.maxQueueSize > 1e4) this.maxQueueSize = 1e4;
63
+ this.startFlushTimer();
64
+ }
65
+ async track(userId, event, properties) {
66
+ if (this.isClosing) {
67
+ if (this.debug) {
68
+ console.warn("[Datalyr] SDK is closing, event dropped:", event);
69
+ }
70
+ return;
71
+ }
72
+ if (!event || typeof event !== "string") {
73
+ throw new Error("Event name is required and must be a string");
74
+ }
75
+ const trackEvent = {
76
+ userId: userId || void 0,
77
+ anonymousId: userId ? void 0 : this.generateAnonymousId(),
78
+ event,
79
+ properties: properties || {},
80
+ context: {
81
+ library: "@datalyr/api",
82
+ version: "1.0.0"
83
+ },
84
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
85
+ };
86
+ this.enqueue(trackEvent);
87
+ }
88
+ async identify(userId, traits) {
89
+ if (!userId) {
90
+ throw new Error("userId is required for identify");
91
+ }
92
+ return this.track(userId, "$identify", { $set: traits });
93
+ }
94
+ async page(userId, name, properties) {
95
+ return this.track(userId, "$pageview", { name, ...properties });
96
+ }
97
+ async group(userId, groupId, traits) {
98
+ if (!groupId) {
99
+ throw new Error("groupId is required for group");
100
+ }
101
+ return this.track(userId, "$group", { groupId, traits });
102
+ }
103
+ enqueue(event) {
104
+ if (this.queue.length >= this.maxQueueSize) {
105
+ if (this.debug) {
106
+ console.warn(`[Datalyr] Queue full (${this.maxQueueSize}), dropping oldest event`);
107
+ }
108
+ this.queue.shift();
109
+ }
110
+ this.queue.push(event);
111
+ if (this.debug) {
112
+ console.log("[Datalyr] Event queued:", event.event);
113
+ }
114
+ if (this.queue.length >= this.flushAt) {
115
+ this.flush().catch((err) => {
116
+ if (this.debug) {
117
+ console.error("[Datalyr] Auto-flush error:", err);
118
+ }
119
+ });
120
+ }
121
+ }
122
+ async flush() {
123
+ if (this.isFlushing || this.queue.length === 0) {
124
+ return;
125
+ }
126
+ this.isFlushing = true;
127
+ try {
128
+ const events = [...this.queue];
129
+ this.queue = [];
130
+ if (this.debug) {
131
+ console.log(`[Datalyr] Flushing ${events.length} events`);
132
+ }
133
+ const batchSize = 10;
134
+ const errors = [];
135
+ for (let i = 0; i < events.length; i += batchSize) {
136
+ const batch = events.slice(i, i + batchSize);
137
+ const promises = batch.map(
138
+ (event) => this.sendEvent(event).catch((err) => {
139
+ errors.push(err);
140
+ this.queue.unshift(event);
141
+ })
142
+ );
143
+ await Promise.allSettled(promises);
144
+ }
145
+ if (errors.length > 0 && this.debug) {
146
+ console.error(`[Datalyr] ${errors.length} events failed to send`);
147
+ }
148
+ } finally {
149
+ this.isFlushing = false;
150
+ }
151
+ }
152
+ async sendEvent(event, retryCount = 0) {
153
+ try {
154
+ const controller = new AbortController();
155
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
156
+ const response = await fetch(this.host, {
157
+ method: "POST",
158
+ headers: {
159
+ "X-API-Key": this.apiKey,
160
+ "Content-Type": "application/json"
161
+ },
162
+ body: JSON.stringify(event),
163
+ signal: controller.signal
164
+ });
165
+ clearTimeout(timeoutId);
166
+ if (!response.ok) {
167
+ let errorText = "";
168
+ try {
169
+ errorText = await response.text();
170
+ } catch {
171
+ }
172
+ if (response.status >= 400 && response.status < 500) {
173
+ throw new Error(`Client error: ${response.status} ${response.statusText} - ${errorText}`);
174
+ }
175
+ throw new Error(`Server error: ${response.status} ${response.statusText} - ${errorText}`);
176
+ }
177
+ if (this.debug) {
178
+ try {
179
+ const result = await response.json();
180
+ console.log("[Datalyr] Event sent successfully:", result);
181
+ } catch {
182
+ console.log("[Datalyr] Event sent successfully");
183
+ }
184
+ }
185
+ } catch (error) {
186
+ if (error.message?.startsWith("Client error:")) {
187
+ if (this.debug) {
188
+ console.error("[Datalyr] Permanent error, not retrying:", error.message);
189
+ }
190
+ throw error;
191
+ }
192
+ if (retryCount < this.retryLimit) {
193
+ if (this.debug) {
194
+ console.log(`[Datalyr] Retrying event (attempt ${retryCount + 1}/${this.retryLimit})`);
195
+ }
196
+ const backoffMs = Math.min(Math.pow(2, retryCount) * 1e3, 1e4);
197
+ await new Promise((resolve) => setTimeout(resolve, backoffMs));
198
+ return this.sendEvent(event, retryCount + 1);
199
+ }
200
+ throw error;
201
+ }
202
+ }
203
+ startFlushTimer() {
204
+ this.timer = setInterval(() => {
205
+ if (!this.isClosing) {
206
+ this.flush().catch((err) => {
207
+ if (this.debug) {
208
+ console.error("[Datalyr] Timer flush error:", err);
209
+ }
210
+ });
211
+ }
212
+ }, this.flushInterval);
213
+ if (this.timer.unref) {
214
+ this.timer.unref();
215
+ }
216
+ }
217
+ generateAnonymousId() {
218
+ return "anon_" + Math.random().toString(36).substring(2) + Date.now().toString(36);
219
+ }
220
+ // Cleanup
221
+ async close() {
222
+ this.isClosing = true;
223
+ if (this.timer) {
224
+ clearInterval(this.timer);
225
+ this.timer = void 0;
226
+ }
227
+ const flushPromise = this.flush();
228
+ const timeoutPromise = new Promise(
229
+ (resolve) => setTimeout(() => resolve(), 5e3)
230
+ );
231
+ await Promise.race([flushPromise, timeoutPromise]);
232
+ if (this.debug && this.queue.length > 0) {
233
+ console.warn(`[Datalyr] Closing with ${this.queue.length} events still queued`);
234
+ }
235
+ }
236
+ };
237
+ var index_default = Datalyr;
238
+ // Annotate the CommonJS export names for ESM import in node:
239
+ 0 && (module.exports = {
240
+ Datalyr
241
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,216 @@
1
+ // src/index.ts
2
+ var Datalyr = class {
3
+ constructor(config) {
4
+ this.queue = [];
5
+ this.isFlushing = false;
6
+ this.isClosing = false;
7
+ if (typeof config === "string") {
8
+ this.apiKey = config;
9
+ this.host = "https://api.datalyr.com";
10
+ this.debug = false;
11
+ this.flushAt = 20;
12
+ this.flushInterval = 1e4;
13
+ this.timeout = 1e4;
14
+ this.retryLimit = 3;
15
+ this.maxQueueSize = 1e3;
16
+ } else {
17
+ this.apiKey = config.apiKey;
18
+ this.host = config.host || "https://api.datalyr.com";
19
+ this.debug = config.debug || false;
20
+ this.flushAt = config.flushAt || 20;
21
+ this.flushInterval = config.flushInterval || 1e4;
22
+ this.timeout = config.timeout || 1e4;
23
+ this.retryLimit = config.retryLimit || 3;
24
+ this.maxQueueSize = config.maxQueueSize || 1e3;
25
+ }
26
+ if (!this.apiKey) {
27
+ throw new Error("Datalyr API key is required");
28
+ }
29
+ if (!this.apiKey.startsWith("dk_")) {
30
+ console.warn('[Datalyr] API key should start with "dk_"');
31
+ }
32
+ if (this.flushAt < 1) this.flushAt = 1;
33
+ if (this.flushAt > 100) this.flushAt = 100;
34
+ if (this.timeout < 1e3) this.timeout = 1e3;
35
+ if (this.timeout > 6e4) this.timeout = 6e4;
36
+ if (this.maxQueueSize < 100) this.maxQueueSize = 100;
37
+ if (this.maxQueueSize > 1e4) this.maxQueueSize = 1e4;
38
+ this.startFlushTimer();
39
+ }
40
+ async track(userId, event, properties) {
41
+ if (this.isClosing) {
42
+ if (this.debug) {
43
+ console.warn("[Datalyr] SDK is closing, event dropped:", event);
44
+ }
45
+ return;
46
+ }
47
+ if (!event || typeof event !== "string") {
48
+ throw new Error("Event name is required and must be a string");
49
+ }
50
+ const trackEvent = {
51
+ userId: userId || void 0,
52
+ anonymousId: userId ? void 0 : this.generateAnonymousId(),
53
+ event,
54
+ properties: properties || {},
55
+ context: {
56
+ library: "@datalyr/api",
57
+ version: "1.0.0"
58
+ },
59
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
60
+ };
61
+ this.enqueue(trackEvent);
62
+ }
63
+ async identify(userId, traits) {
64
+ if (!userId) {
65
+ throw new Error("userId is required for identify");
66
+ }
67
+ return this.track(userId, "$identify", { $set: traits });
68
+ }
69
+ async page(userId, name, properties) {
70
+ return this.track(userId, "$pageview", { name, ...properties });
71
+ }
72
+ async group(userId, groupId, traits) {
73
+ if (!groupId) {
74
+ throw new Error("groupId is required for group");
75
+ }
76
+ return this.track(userId, "$group", { groupId, traits });
77
+ }
78
+ enqueue(event) {
79
+ if (this.queue.length >= this.maxQueueSize) {
80
+ if (this.debug) {
81
+ console.warn(`[Datalyr] Queue full (${this.maxQueueSize}), dropping oldest event`);
82
+ }
83
+ this.queue.shift();
84
+ }
85
+ this.queue.push(event);
86
+ if (this.debug) {
87
+ console.log("[Datalyr] Event queued:", event.event);
88
+ }
89
+ if (this.queue.length >= this.flushAt) {
90
+ this.flush().catch((err) => {
91
+ if (this.debug) {
92
+ console.error("[Datalyr] Auto-flush error:", err);
93
+ }
94
+ });
95
+ }
96
+ }
97
+ async flush() {
98
+ if (this.isFlushing || this.queue.length === 0) {
99
+ return;
100
+ }
101
+ this.isFlushing = true;
102
+ try {
103
+ const events = [...this.queue];
104
+ this.queue = [];
105
+ if (this.debug) {
106
+ console.log(`[Datalyr] Flushing ${events.length} events`);
107
+ }
108
+ const batchSize = 10;
109
+ const errors = [];
110
+ for (let i = 0; i < events.length; i += batchSize) {
111
+ const batch = events.slice(i, i + batchSize);
112
+ const promises = batch.map(
113
+ (event) => this.sendEvent(event).catch((err) => {
114
+ errors.push(err);
115
+ this.queue.unshift(event);
116
+ })
117
+ );
118
+ await Promise.allSettled(promises);
119
+ }
120
+ if (errors.length > 0 && this.debug) {
121
+ console.error(`[Datalyr] ${errors.length} events failed to send`);
122
+ }
123
+ } finally {
124
+ this.isFlushing = false;
125
+ }
126
+ }
127
+ async sendEvent(event, retryCount = 0) {
128
+ try {
129
+ const controller = new AbortController();
130
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
131
+ const response = await fetch(this.host, {
132
+ method: "POST",
133
+ headers: {
134
+ "X-API-Key": this.apiKey,
135
+ "Content-Type": "application/json"
136
+ },
137
+ body: JSON.stringify(event),
138
+ signal: controller.signal
139
+ });
140
+ clearTimeout(timeoutId);
141
+ if (!response.ok) {
142
+ let errorText = "";
143
+ try {
144
+ errorText = await response.text();
145
+ } catch {
146
+ }
147
+ if (response.status >= 400 && response.status < 500) {
148
+ throw new Error(`Client error: ${response.status} ${response.statusText} - ${errorText}`);
149
+ }
150
+ throw new Error(`Server error: ${response.status} ${response.statusText} - ${errorText}`);
151
+ }
152
+ if (this.debug) {
153
+ try {
154
+ const result = await response.json();
155
+ console.log("[Datalyr] Event sent successfully:", result);
156
+ } catch {
157
+ console.log("[Datalyr] Event sent successfully");
158
+ }
159
+ }
160
+ } catch (error) {
161
+ if (error.message?.startsWith("Client error:")) {
162
+ if (this.debug) {
163
+ console.error("[Datalyr] Permanent error, not retrying:", error.message);
164
+ }
165
+ throw error;
166
+ }
167
+ if (retryCount < this.retryLimit) {
168
+ if (this.debug) {
169
+ console.log(`[Datalyr] Retrying event (attempt ${retryCount + 1}/${this.retryLimit})`);
170
+ }
171
+ const backoffMs = Math.min(Math.pow(2, retryCount) * 1e3, 1e4);
172
+ await new Promise((resolve) => setTimeout(resolve, backoffMs));
173
+ return this.sendEvent(event, retryCount + 1);
174
+ }
175
+ throw error;
176
+ }
177
+ }
178
+ startFlushTimer() {
179
+ this.timer = setInterval(() => {
180
+ if (!this.isClosing) {
181
+ this.flush().catch((err) => {
182
+ if (this.debug) {
183
+ console.error("[Datalyr] Timer flush error:", err);
184
+ }
185
+ });
186
+ }
187
+ }, this.flushInterval);
188
+ if (this.timer.unref) {
189
+ this.timer.unref();
190
+ }
191
+ }
192
+ generateAnonymousId() {
193
+ return "anon_" + Math.random().toString(36).substring(2) + Date.now().toString(36);
194
+ }
195
+ // Cleanup
196
+ async close() {
197
+ this.isClosing = true;
198
+ if (this.timer) {
199
+ clearInterval(this.timer);
200
+ this.timer = void 0;
201
+ }
202
+ const flushPromise = this.flush();
203
+ const timeoutPromise = new Promise(
204
+ (resolve) => setTimeout(() => resolve(), 5e3)
205
+ );
206
+ await Promise.race([flushPromise, timeoutPromise]);
207
+ if (this.debug && this.queue.length > 0) {
208
+ console.warn(`[Datalyr] Closing with ${this.queue.length} events still queued`);
209
+ }
210
+ }
211
+ };
212
+ var index_default = Datalyr;
213
+ export {
214
+ Datalyr,
215
+ index_default as default
216
+ };
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@datalyr/api",
3
+ "version": "1.0.0",
4
+ "description": "Datalyr API SDK for server-side tracking",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "scripts": {
9
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean",
10
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
11
+ "test": "node tests/test.js",
12
+ "prepublishOnly": "npm run build"
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "keywords": [
20
+ "datalyr",
21
+ "analytics",
22
+ "tracking",
23
+ "attribution",
24
+ "server-side",
25
+ "node"
26
+ ],
27
+ "author": "Datalyr",
28
+ "license": "MIT",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/datalyr/node-sdk"
32
+ },
33
+ "bugs": {
34
+ "url": "https://github.com/datalyr/node-sdk/issues"
35
+ },
36
+ "homepage": "https://datalyr.com",
37
+ "dependencies": {},
38
+ "devDependencies": {
39
+ "@types/node": "^20.0.0",
40
+ "tsup": "^8.0.0",
41
+ "typescript": "^5.0.0"
42
+ },
43
+ "engines": {
44
+ "node": ">=14.0.0"
45
+ }
46
+ }