@qurvo/sdk-node 0.0.2
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 +190 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +88 -0
- package/dist/index.js.map +1 -0
- package/package.json +27 -0
package/README.md
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# @qurvo/sdk-node
|
|
2
|
+
|
|
3
|
+
Server-side SDK for [Qurvo](https://qurvo.ru) analytics. Track events, identify users, and manage user properties from your Node.js backend.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @qurvo/sdk-node
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @qurvo/sdk-node
|
|
11
|
+
# or
|
|
12
|
+
yarn add @qurvo/sdk-node
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { Qurvo } from '@qurvo/sdk-node';
|
|
19
|
+
|
|
20
|
+
const qurvo = new Qurvo({
|
|
21
|
+
apiKey: 'qk_your_api_key',
|
|
22
|
+
endpoint: 'https://ingest.yourapp.com',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Track events
|
|
26
|
+
qurvo.track({
|
|
27
|
+
distinct_id: 'user-123',
|
|
28
|
+
event: 'purchase',
|
|
29
|
+
properties: { plan: 'premium', amount: 49.99 },
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Identify a user
|
|
33
|
+
qurvo.identify({
|
|
34
|
+
distinct_id: 'user-123',
|
|
35
|
+
user_properties: { email: 'jane@example.com', name: 'Jane Doe' },
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Flush remaining events on shutdown
|
|
39
|
+
await qurvo.shutdown();
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Configuration
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
const qurvo = new Qurvo({
|
|
46
|
+
apiKey: 'qk_...', // Required. Your project API key
|
|
47
|
+
endpoint: 'https://...', // Ingest API URL (default: http://localhost:3001)
|
|
48
|
+
flushInterval: 5000, // Batch send interval in ms (default: 5000)
|
|
49
|
+
flushSize: 20, // Send batch when queue reaches this size (default: 20)
|
|
50
|
+
maxQueueSize: 1000, // Maximum events in queue (default: 1000)
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## API
|
|
55
|
+
|
|
56
|
+
### `qurvo.track({ distinct_id, event, properties? })`
|
|
57
|
+
|
|
58
|
+
Track a custom event.
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
qurvo.track({
|
|
62
|
+
distinct_id: 'user-123',
|
|
63
|
+
event: 'file_uploaded',
|
|
64
|
+
properties: {
|
|
65
|
+
file_type: 'pdf',
|
|
66
|
+
file_size_mb: 4.2,
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### `qurvo.identify({ distinct_id, user_properties })`
|
|
72
|
+
|
|
73
|
+
Identify a user and set their properties. Sends a `$identify` event.
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
qurvo.identify({
|
|
77
|
+
distinct_id: 'user-123',
|
|
78
|
+
user_properties: {
|
|
79
|
+
email: 'jane@example.com',
|
|
80
|
+
name: 'Jane Doe',
|
|
81
|
+
created_at: '2025-01-15',
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### `qurvo.set({ distinct_id, properties })`
|
|
87
|
+
|
|
88
|
+
Set user properties. Overwrites existing values.
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
qurvo.set({
|
|
92
|
+
distinct_id: 'user-123',
|
|
93
|
+
properties: { plan: 'enterprise', company: 'Acme Inc.' },
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### `qurvo.setOnce({ distinct_id, properties })`
|
|
98
|
+
|
|
99
|
+
Set user properties only if they haven't been set before.
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
qurvo.setOnce({
|
|
103
|
+
distinct_id: 'user-123',
|
|
104
|
+
properties: { referral_source: 'google', first_seen: new Date().toISOString() },
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### `qurvo.screen({ distinct_id, screen_name, properties? })`
|
|
109
|
+
|
|
110
|
+
Track a screen view (useful for mobile apps or SSR).
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
qurvo.screen({
|
|
114
|
+
distinct_id: 'user-123',
|
|
115
|
+
screen_name: 'HomeScreen',
|
|
116
|
+
properties: { tab: 'trending' },
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### `await qurvo.shutdown()`
|
|
121
|
+
|
|
122
|
+
Flush all remaining events and stop the queue. Call this before your process exits to ensure no events are lost.
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
process.on('SIGTERM', async () => {
|
|
126
|
+
await qurvo.shutdown();
|
|
127
|
+
process.exit(0);
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## How It Works
|
|
132
|
+
|
|
133
|
+
- **Event queue** batches events and sends them every 5 seconds or when the batch reaches 20 events.
|
|
134
|
+
- **Retry with backoff** on network failures: 1s, 2s, 4s, 8s... up to 30s between retries.
|
|
135
|
+
- **Overflow protection**: when the queue reaches `maxQueueSize`, the oldest events are dropped.
|
|
136
|
+
- **Graceful shutdown**: `shutdown()` stops the timer and flushes all remaining events.
|
|
137
|
+
|
|
138
|
+
## Special Events
|
|
139
|
+
|
|
140
|
+
| Event | Trigger |
|
|
141
|
+
|---|---|
|
|
142
|
+
| `$identify` | `identify()` call |
|
|
143
|
+
| `$set` | `set()` call |
|
|
144
|
+
| `$set_once` | `setOnce()` call |
|
|
145
|
+
| `$screen` | `screen()` call |
|
|
146
|
+
|
|
147
|
+
## Express Example
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
import express from 'express';
|
|
151
|
+
import { Qurvo } from '@qurvo/sdk-node';
|
|
152
|
+
|
|
153
|
+
const app = express();
|
|
154
|
+
const qurvo = new Qurvo({
|
|
155
|
+
apiKey: 'qk_your_api_key',
|
|
156
|
+
endpoint: 'https://ingest.yourapp.com',
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
app.post('/api/checkout', (req, res) => {
|
|
160
|
+
const userId = req.user.id;
|
|
161
|
+
|
|
162
|
+
qurvo.track({
|
|
163
|
+
distinct_id: userId,
|
|
164
|
+
event: 'checkout_completed',
|
|
165
|
+
properties: { cart_total: req.body.total, items: req.body.items.length },
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
res.json({ ok: true });
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Graceful shutdown
|
|
172
|
+
process.on('SIGTERM', async () => {
|
|
173
|
+
await qurvo.shutdown();
|
|
174
|
+
process.exit(0);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
app.listen(3000);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## TypeScript
|
|
181
|
+
|
|
182
|
+
The package ships with full TypeScript type definitions.
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
import { Qurvo, type NodeSdkConfig } from '@qurvo/sdk-node';
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## License
|
|
189
|
+
|
|
190
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { SdkConfig } from '@qurvo/sdk-core';
|
|
2
|
+
export interface NodeSdkConfig extends SdkConfig {
|
|
3
|
+
endpoint?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class Qurvo {
|
|
6
|
+
private queue;
|
|
7
|
+
private config;
|
|
8
|
+
constructor(config: NodeSdkConfig);
|
|
9
|
+
track(params: {
|
|
10
|
+
distinct_id: string;
|
|
11
|
+
event: string;
|
|
12
|
+
properties?: Record<string, unknown>;
|
|
13
|
+
}): void;
|
|
14
|
+
identify(params: {
|
|
15
|
+
distinct_id: string;
|
|
16
|
+
user_properties: Record<string, unknown>;
|
|
17
|
+
}): void;
|
|
18
|
+
set(params: {
|
|
19
|
+
distinct_id: string;
|
|
20
|
+
properties: Record<string, unknown>;
|
|
21
|
+
}): void;
|
|
22
|
+
setOnce(params: {
|
|
23
|
+
distinct_id: string;
|
|
24
|
+
properties: Record<string, unknown>;
|
|
25
|
+
}): void;
|
|
26
|
+
screen(params: {
|
|
27
|
+
distinct_id: string;
|
|
28
|
+
screen_name: string;
|
|
29
|
+
properties?: Record<string, unknown>;
|
|
30
|
+
}): void;
|
|
31
|
+
shutdown(): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAgB,MAAM,iBAAiB,CAAC;AAK/D,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,KAAK;IAChB,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,MAAM,CAAgB;gBAElB,MAAM,EAAE,aAAa;IAejC,KAAK,CAAC,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE;IAc1F,QAAQ,CAAC,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE;IAclF,GAAG,CAAC,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE;IAcxE,OAAO,CAAC,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE;IAc5E,MAAM,CAAC,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE;IAc3F,QAAQ;CAIf"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Qurvo = void 0;
|
|
4
|
+
const sdk_core_1 = require("@qurvo/sdk-core");
|
|
5
|
+
const SDK_NAME = '@qurvo/sdk-node';
|
|
6
|
+
const SDK_VERSION = '0.0.1';
|
|
7
|
+
class Qurvo {
|
|
8
|
+
queue;
|
|
9
|
+
config;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
const endpoint = config.endpoint || 'http://localhost:3001';
|
|
13
|
+
const transport = new sdk_core_1.FetchTransport();
|
|
14
|
+
this.queue = new sdk_core_1.EventQueue(transport, `${endpoint}/v1/batch`, config.apiKey, config.flushInterval || 5000, config.flushSize || 20, config.maxQueueSize || 1000);
|
|
15
|
+
this.queue.start();
|
|
16
|
+
}
|
|
17
|
+
track(params) {
|
|
18
|
+
const payload = {
|
|
19
|
+
event: params.event,
|
|
20
|
+
distinct_id: params.distinct_id,
|
|
21
|
+
properties: params.properties,
|
|
22
|
+
context: {
|
|
23
|
+
sdk_name: SDK_NAME,
|
|
24
|
+
sdk_version: SDK_VERSION,
|
|
25
|
+
},
|
|
26
|
+
timestamp: new Date().toISOString(),
|
|
27
|
+
};
|
|
28
|
+
this.queue.enqueue(payload);
|
|
29
|
+
}
|
|
30
|
+
identify(params) {
|
|
31
|
+
const payload = {
|
|
32
|
+
event: '$identify',
|
|
33
|
+
distinct_id: params.distinct_id,
|
|
34
|
+
user_properties: params.user_properties,
|
|
35
|
+
context: {
|
|
36
|
+
sdk_name: SDK_NAME,
|
|
37
|
+
sdk_version: SDK_VERSION,
|
|
38
|
+
},
|
|
39
|
+
timestamp: new Date().toISOString(),
|
|
40
|
+
};
|
|
41
|
+
this.queue.enqueue(payload);
|
|
42
|
+
}
|
|
43
|
+
set(params) {
|
|
44
|
+
const payload = {
|
|
45
|
+
event: '$set',
|
|
46
|
+
distinct_id: params.distinct_id,
|
|
47
|
+
user_properties: { $set: params.properties },
|
|
48
|
+
context: {
|
|
49
|
+
sdk_name: SDK_NAME,
|
|
50
|
+
sdk_version: SDK_VERSION,
|
|
51
|
+
},
|
|
52
|
+
timestamp: new Date().toISOString(),
|
|
53
|
+
};
|
|
54
|
+
this.queue.enqueue(payload);
|
|
55
|
+
}
|
|
56
|
+
setOnce(params) {
|
|
57
|
+
const payload = {
|
|
58
|
+
event: '$set_once',
|
|
59
|
+
distinct_id: params.distinct_id,
|
|
60
|
+
user_properties: { $set_once: params.properties },
|
|
61
|
+
context: {
|
|
62
|
+
sdk_name: SDK_NAME,
|
|
63
|
+
sdk_version: SDK_VERSION,
|
|
64
|
+
},
|
|
65
|
+
timestamp: new Date().toISOString(),
|
|
66
|
+
};
|
|
67
|
+
this.queue.enqueue(payload);
|
|
68
|
+
}
|
|
69
|
+
screen(params) {
|
|
70
|
+
const payload = {
|
|
71
|
+
event: '$screen',
|
|
72
|
+
distinct_id: params.distinct_id,
|
|
73
|
+
properties: { $screen_name: params.screen_name, ...params.properties },
|
|
74
|
+
context: {
|
|
75
|
+
sdk_name: SDK_NAME,
|
|
76
|
+
sdk_version: SDK_VERSION,
|
|
77
|
+
},
|
|
78
|
+
timestamp: new Date().toISOString(),
|
|
79
|
+
};
|
|
80
|
+
this.queue.enqueue(payload);
|
|
81
|
+
}
|
|
82
|
+
async shutdown() {
|
|
83
|
+
this.queue.stop();
|
|
84
|
+
await this.queue.flush();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.Qurvo = Qurvo;
|
|
88
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@qurvo/sdk-node",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Server-side SDK for Qurvo analytics — event tracking, user identification",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@qurvo/sdk-core": "0.0.2"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/node": "^22.0.0",
|
|
19
|
+
"typescript": "^5.7.0",
|
|
20
|
+
"@qurvo/tsconfig": "0.0.0"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc",
|
|
24
|
+
"dev": "tsc --watch",
|
|
25
|
+
"clean": "rm -rf dist .turbo"
|
|
26
|
+
}
|
|
27
|
+
}
|