@inslytic/sdk-node 0.1.1

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,41 @@
1
+ type InslyticNodeConfig = {
2
+ apiKey: string;
3
+ endpoint?: string;
4
+ flushInterval?: number;
5
+ maxBatchSize?: number;
6
+ maxRetries?: number;
7
+ };
8
+ type NodeEventPayload = {
9
+ eventName: string;
10
+ userId?: string | null;
11
+ anonymousId: string;
12
+ sessionId?: string;
13
+ properties?: Record<string, string>;
14
+ timestamp?: string;
15
+ consentGiven?: boolean;
16
+ };
17
+
18
+ declare class InslyticNode {
19
+ private queue;
20
+ private timer;
21
+ private endpoint;
22
+ private apiKey;
23
+ private maxBatchSize;
24
+ private maxRetries;
25
+ private flushing;
26
+ private shutdownRequested;
27
+ private shutdownHandlers;
28
+ constructor(config: InslyticNodeConfig);
29
+ track(event: NodeEventPayload): void;
30
+ identify(userId: string, _traits?: Record<string, string>): void;
31
+ flush(): Promise<void>;
32
+ shutdown(): Promise<void>;
33
+ get pending(): number;
34
+ private sendWithRetry;
35
+ private backoffMs;
36
+ private sleep;
37
+ private setupShutdownHandlers;
38
+ private removeShutdownHandlers;
39
+ }
40
+
41
+ export { InslyticNode, type InslyticNodeConfig, type NodeEventPayload };
@@ -0,0 +1,41 @@
1
+ type InslyticNodeConfig = {
2
+ apiKey: string;
3
+ endpoint?: string;
4
+ flushInterval?: number;
5
+ maxBatchSize?: number;
6
+ maxRetries?: number;
7
+ };
8
+ type NodeEventPayload = {
9
+ eventName: string;
10
+ userId?: string | null;
11
+ anonymousId: string;
12
+ sessionId?: string;
13
+ properties?: Record<string, string>;
14
+ timestamp?: string;
15
+ consentGiven?: boolean;
16
+ };
17
+
18
+ declare class InslyticNode {
19
+ private queue;
20
+ private timer;
21
+ private endpoint;
22
+ private apiKey;
23
+ private maxBatchSize;
24
+ private maxRetries;
25
+ private flushing;
26
+ private shutdownRequested;
27
+ private shutdownHandlers;
28
+ constructor(config: InslyticNodeConfig);
29
+ track(event: NodeEventPayload): void;
30
+ identify(userId: string, _traits?: Record<string, string>): void;
31
+ flush(): Promise<void>;
32
+ shutdown(): Promise<void>;
33
+ get pending(): number;
34
+ private sendWithRetry;
35
+ private backoffMs;
36
+ private sleep;
37
+ private setupShutdownHandlers;
38
+ private removeShutdownHandlers;
39
+ }
40
+
41
+ export { InslyticNode, type InslyticNodeConfig, type NodeEventPayload };
package/dist/index.js ADDED
@@ -0,0 +1,156 @@
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
+ InslyticNode: () => InslyticNode
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/client.ts
28
+ var DEFAULT_ENDPOINT = "https://api.inslytic.com";
29
+ var DEFAULT_FLUSH_INTERVAL = 1e4;
30
+ var DEFAULT_MAX_BATCH_SIZE = 20;
31
+ var DEFAULT_MAX_RETRIES = 3;
32
+ var InslyticNode = class {
33
+ queue = [];
34
+ timer = null;
35
+ endpoint;
36
+ apiKey;
37
+ maxBatchSize;
38
+ maxRetries;
39
+ flushing = false;
40
+ shutdownRequested = false;
41
+ shutdownHandlers = [];
42
+ constructor(config) {
43
+ this.endpoint = config.endpoint ?? DEFAULT_ENDPOINT;
44
+ this.apiKey = config.apiKey;
45
+ this.maxBatchSize = config.maxBatchSize ?? DEFAULT_MAX_BATCH_SIZE;
46
+ this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
47
+ const interval = config.flushInterval ?? DEFAULT_FLUSH_INTERVAL;
48
+ this.timer = setInterval(() => this.flush(), interval);
49
+ this.setupShutdownHandlers();
50
+ }
51
+ track(event) {
52
+ if (this.shutdownRequested) return;
53
+ this.queue.push({
54
+ eventName: event.eventName,
55
+ timestamp: event.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
56
+ userId: event.userId ?? null,
57
+ anonymousId: event.anonymousId,
58
+ sessionId: event.sessionId ?? "",
59
+ consentGiven: event.consentGiven ?? true,
60
+ properties: event.properties ?? {},
61
+ pageUrl: "",
62
+ pageTitle: "",
63
+ referrer: "",
64
+ utmSource: null,
65
+ utmMedium: null,
66
+ utmCampaign: null
67
+ });
68
+ if (this.queue.length >= this.maxBatchSize) {
69
+ this.flush();
70
+ }
71
+ }
72
+ identify(userId, _traits) {
73
+ this.track({
74
+ eventName: "$identify",
75
+ userId,
76
+ anonymousId: userId,
77
+ consentGiven: true
78
+ });
79
+ }
80
+ async flush() {
81
+ if (this.queue.length === 0 || this.flushing) return;
82
+ this.flushing = true;
83
+ try {
84
+ while (this.queue.length > 0) {
85
+ const batch = this.queue.splice(0, this.maxBatchSize);
86
+ await this.sendWithRetry(batch);
87
+ }
88
+ } finally {
89
+ this.flushing = false;
90
+ }
91
+ }
92
+ async shutdown() {
93
+ this.shutdownRequested = true;
94
+ if (this.timer) {
95
+ clearInterval(this.timer);
96
+ this.timer = null;
97
+ }
98
+ this.removeShutdownHandlers();
99
+ await this.flush();
100
+ }
101
+ get pending() {
102
+ return this.queue.length;
103
+ }
104
+ async sendWithRetry(batch) {
105
+ const url = `${this.endpoint}/v1/ingest`;
106
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
107
+ try {
108
+ const response = await fetch(url, {
109
+ method: "POST",
110
+ headers: {
111
+ "Content-Type": "application/json",
112
+ Authorization: `Bearer ${this.apiKey}`
113
+ },
114
+ body: JSON.stringify({ events: batch })
115
+ });
116
+ if (response.ok || response.status < 500) {
117
+ return;
118
+ }
119
+ if (attempt < this.maxRetries) {
120
+ await this.sleep(this.backoffMs(attempt));
121
+ }
122
+ } catch {
123
+ if (attempt < this.maxRetries) {
124
+ await this.sleep(this.backoffMs(attempt));
125
+ }
126
+ }
127
+ }
128
+ this.queue.unshift(...batch);
129
+ }
130
+ backoffMs(attempt) {
131
+ return Math.min(1e3 * 2 ** attempt, 3e4);
132
+ }
133
+ sleep(ms) {
134
+ return new Promise((resolve) => setTimeout(resolve, ms));
135
+ }
136
+ setupShutdownHandlers() {
137
+ if (typeof process === "undefined") return;
138
+ const handler = () => {
139
+ this.shutdown();
140
+ };
141
+ for (const signal of ["SIGTERM", "SIGINT"]) {
142
+ process.on(signal, handler);
143
+ this.shutdownHandlers.push(() => process.removeListener(signal, handler));
144
+ }
145
+ }
146
+ removeShutdownHandlers() {
147
+ for (const remove of this.shutdownHandlers) {
148
+ remove();
149
+ }
150
+ this.shutdownHandlers = [];
151
+ }
152
+ };
153
+ // Annotate the CommonJS export names for ESM import in node:
154
+ 0 && (module.exports = {
155
+ InslyticNode
156
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,129 @@
1
+ // src/client.ts
2
+ var DEFAULT_ENDPOINT = "https://api.inslytic.com";
3
+ var DEFAULT_FLUSH_INTERVAL = 1e4;
4
+ var DEFAULT_MAX_BATCH_SIZE = 20;
5
+ var DEFAULT_MAX_RETRIES = 3;
6
+ var InslyticNode = class {
7
+ queue = [];
8
+ timer = null;
9
+ endpoint;
10
+ apiKey;
11
+ maxBatchSize;
12
+ maxRetries;
13
+ flushing = false;
14
+ shutdownRequested = false;
15
+ shutdownHandlers = [];
16
+ constructor(config) {
17
+ this.endpoint = config.endpoint ?? DEFAULT_ENDPOINT;
18
+ this.apiKey = config.apiKey;
19
+ this.maxBatchSize = config.maxBatchSize ?? DEFAULT_MAX_BATCH_SIZE;
20
+ this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
21
+ const interval = config.flushInterval ?? DEFAULT_FLUSH_INTERVAL;
22
+ this.timer = setInterval(() => this.flush(), interval);
23
+ this.setupShutdownHandlers();
24
+ }
25
+ track(event) {
26
+ if (this.shutdownRequested) return;
27
+ this.queue.push({
28
+ eventName: event.eventName,
29
+ timestamp: event.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
30
+ userId: event.userId ?? null,
31
+ anonymousId: event.anonymousId,
32
+ sessionId: event.sessionId ?? "",
33
+ consentGiven: event.consentGiven ?? true,
34
+ properties: event.properties ?? {},
35
+ pageUrl: "",
36
+ pageTitle: "",
37
+ referrer: "",
38
+ utmSource: null,
39
+ utmMedium: null,
40
+ utmCampaign: null
41
+ });
42
+ if (this.queue.length >= this.maxBatchSize) {
43
+ this.flush();
44
+ }
45
+ }
46
+ identify(userId, _traits) {
47
+ this.track({
48
+ eventName: "$identify",
49
+ userId,
50
+ anonymousId: userId,
51
+ consentGiven: true
52
+ });
53
+ }
54
+ async flush() {
55
+ if (this.queue.length === 0 || this.flushing) return;
56
+ this.flushing = true;
57
+ try {
58
+ while (this.queue.length > 0) {
59
+ const batch = this.queue.splice(0, this.maxBatchSize);
60
+ await this.sendWithRetry(batch);
61
+ }
62
+ } finally {
63
+ this.flushing = false;
64
+ }
65
+ }
66
+ async shutdown() {
67
+ this.shutdownRequested = true;
68
+ if (this.timer) {
69
+ clearInterval(this.timer);
70
+ this.timer = null;
71
+ }
72
+ this.removeShutdownHandlers();
73
+ await this.flush();
74
+ }
75
+ get pending() {
76
+ return this.queue.length;
77
+ }
78
+ async sendWithRetry(batch) {
79
+ const url = `${this.endpoint}/v1/ingest`;
80
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
81
+ try {
82
+ const response = await fetch(url, {
83
+ method: "POST",
84
+ headers: {
85
+ "Content-Type": "application/json",
86
+ Authorization: `Bearer ${this.apiKey}`
87
+ },
88
+ body: JSON.stringify({ events: batch })
89
+ });
90
+ if (response.ok || response.status < 500) {
91
+ return;
92
+ }
93
+ if (attempt < this.maxRetries) {
94
+ await this.sleep(this.backoffMs(attempt));
95
+ }
96
+ } catch {
97
+ if (attempt < this.maxRetries) {
98
+ await this.sleep(this.backoffMs(attempt));
99
+ }
100
+ }
101
+ }
102
+ this.queue.unshift(...batch);
103
+ }
104
+ backoffMs(attempt) {
105
+ return Math.min(1e3 * 2 ** attempt, 3e4);
106
+ }
107
+ sleep(ms) {
108
+ return new Promise((resolve) => setTimeout(resolve, ms));
109
+ }
110
+ setupShutdownHandlers() {
111
+ if (typeof process === "undefined") return;
112
+ const handler = () => {
113
+ this.shutdown();
114
+ };
115
+ for (const signal of ["SIGTERM", "SIGINT"]) {
116
+ process.on(signal, handler);
117
+ this.shutdownHandlers.push(() => process.removeListener(signal, handler));
118
+ }
119
+ }
120
+ removeShutdownHandlers() {
121
+ for (const remove of this.shutdownHandlers) {
122
+ remove();
123
+ }
124
+ this.shutdownHandlers = [];
125
+ }
126
+ };
127
+ export {
128
+ InslyticNode
129
+ };
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@inslytic/sdk-node",
3
+ "version": "0.1.1",
4
+ "description": "Node.js server-side SDK for Inslytic — AI-powered product analytics",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/inslytic/inslytic",
9
+ "directory": "packages/sdk-node"
10
+ },
11
+ "keywords": [
12
+ "analytics",
13
+ "tracking",
14
+ "product-analytics",
15
+ "node",
16
+ "server-side",
17
+ "inslytic"
18
+ ],
19
+ "sideEffects": false,
20
+ "main": "./dist/index.js",
21
+ "module": "./dist/index.mjs",
22
+ "types": "./dist/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "import": {
26
+ "types": "./dist/index.d.mts",
27
+ "default": "./dist/index.mjs"
28
+ },
29
+ "require": {
30
+ "types": "./dist/index.d.ts",
31
+ "default": "./dist/index.js"
32
+ }
33
+ }
34
+ },
35
+ "files": [
36
+ "dist"
37
+ ],
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "engines": {
42
+ "node": ">=18"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^25.2.3",
46
+ "tsup": "^8.0.0",
47
+ "typescript": "^5.7.0",
48
+ "vitest": "^3.0.0"
49
+ },
50
+ "scripts": {
51
+ "build": "tsup src/index.ts --format esm,cjs --dts",
52
+ "dev": "tsup src/index.ts --format esm,cjs --dts --watch",
53
+ "test": "vitest run",
54
+ "typecheck": "tsc --noEmit",
55
+ "clean": "rm -rf dist .turbo node_modules"
56
+ }
57
+ }