@chirpier/chirpier-js 0.1.4 → 0.1.6

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 CHANGED
@@ -1,19 +1,21 @@
1
1
  # Chirpier SDK
2
2
 
3
- The Chirpier SDK is a lightweight, library for monitoring and tracking streams of data in both browser and server environments. With built-in retry logic, and offline handling, the Chirpier SDK makes it easy to collect and send data to the Chirpier API.
3
+ The Chirpier SDK for JavaScript is a simple, lightweight, and efficient SDK to emit event data to Chirpier direct from your JavaScript applications.
4
4
 
5
5
  ## Features
6
6
 
7
+ - Easy-to-use API for sending events to Chirpier
8
+ - Automatic batching of events for improved performance
9
+ - Automatic retry mechanism with exponential backoff
10
+ - Thread-safe operations
11
+ - Periodic flushing of the event queue
7
12
  - Environment Agnostic: Works seamlessly in both browser and Node.js environments.
8
- - Retry Logic: Includes retry mechanisms with exponential backoff for failed requests.
9
- - Offline Support: Queues events when offline and sends them when the connection is restored.
10
- - Easy Integration: Simple API for quick integration into your projects.
11
13
 
12
14
  ## Installation
13
15
 
14
- You can install the Chirpier SDK via npm:
16
+ Install Chirpier SDK using npm:
15
17
 
16
- ```
18
+ ``` bash
17
19
  npm install @chirpier/chirpier-js
18
20
  ```
19
21
 
@@ -23,9 +25,11 @@ npm install @chirpier/chirpier-js
23
25
 
24
26
  To start using the SDK, you need to initialize it with your API key. The SDK works in both browser and Node.js environments.
25
27
 
28
+ Here's a quick example of how to use the Chirpier SDK:
29
+
26
30
  #### In a Browser
27
31
 
28
- ```
32
+ ```js
29
33
  import { initialize, monitor, Event } from '@chirpier/chirpier-js';
30
34
 
31
35
  // Initialize the SDK with your API key
@@ -34,14 +38,14 @@ initialize({ key: 'your-api-key' });
34
38
  // Send a data stream tied to a group of streams
35
39
  monitor({
36
40
  group_id: '02e4f4d8-415e-4fc1-b01a-677ac5bc9207',
37
- stream_name: 'Sales',
41
+ stream_name: 'My measurement',
38
42
  value: 15.30,
39
43
  } as Event);
40
44
  ```
41
45
 
42
46
  #### In a Server (e.g., Express.js)
43
47
 
44
- ```
48
+ ```js
45
49
  const express = require('express');
46
50
  const { initialize, monitor, Event } = require('@chirpier/chirpier-js');
47
51
 
@@ -49,7 +53,7 @@ const app = express();
49
53
  const port = 3000;
50
54
 
51
55
  // Initialize the SDK with your API key
52
- initialize({ key: 'your-api-key' });
56
+ initialize({ key: 'your-api-key', region: 'us-west' });
53
57
 
54
58
  app.use(express.json());
55
59
 
@@ -71,16 +75,81 @@ app.listen(port, () => {
71
75
  });
72
76
  ```
73
77
 
74
- ## Example
78
+ ### Usage
75
79
 
76
- ```
80
+ ```js
77
81
  // Initialize the SDK with your API key
78
- initialize({ key: 'your-api-key' });
82
+ initialize({ key: 'your-api-key', region: 'us-west' });
79
83
 
80
84
  // Monitor an event
81
85
  monitor({
82
- group_id: 'group UUID',
86
+ group_id: '02e4f4d8-415e-4fc1-b01a-677ac5bc9207',
83
87
  stream_name: 'My measurement',
84
88
  value: 15.3,
85
89
  });
86
90
  ```
91
+
92
+ ## API Reference
93
+
94
+ ### Initialize
95
+
96
+ Initialize the Chirpier client with your API key and region. Find your API key in the Chirpier Integration page.
97
+
98
+ ```js
99
+ initialize({ key: 'your-api-key', region: 'region' });
100
+ ```
101
+
102
+ - `your-api-key` (str): Your Chirpier integration key
103
+ - `region` (str): Your local region - options are `us-west`, `eu-west`, `asia-southeast`
104
+
105
+ ### Event
106
+
107
+ All events emitted to Chirpier must have the following properties:
108
+
109
+ ```js
110
+ event = {
111
+ group_id: '02e4f4d8-415e-4fc1-b01a-677ac5bc9207',
112
+ stream_name: 'My measurement',
113
+ value: 15.3,
114
+ };
115
+ ```
116
+
117
+ - `group_id` (str): UUID of the monitoring group
118
+ - `stream_name` (str): Name of the measurement stream
119
+ - `value` (float): Numeric value to record
120
+
121
+ ### Monitor
122
+
123
+ Send an event to Chirpier using the `monitor` function.
124
+
125
+ ```js
126
+ monitor(event);
127
+ ```
128
+
129
+ ## Test
130
+
131
+ Run the test suite to ensure everything works as expected:
132
+
133
+ ```bash
134
+ npx jest
135
+ ```
136
+
137
+ ## Contributing
138
+
139
+ We welcome contributions! To contribute:
140
+
141
+ 1. Fork this repository.
142
+ 2. Create a new branch for your feature or bug fix.
143
+ 3. Submit a pull request with a clear explanation of your changes.
144
+
145
+ ## License
146
+
147
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
148
+
149
+ ## Support
150
+
151
+ If you encounter any problems or have any questions, please open an issue on the GitHub repository or contact us at <contact@chirpier.co>.
152
+
153
+ ---
154
+
155
+ Start tracking your events seamlessly with Chirpier SDK!
@@ -57,9 +57,11 @@ describe("Chirpier SDK", function () {
57
57
  test("should initialize with default values", function () {
58
58
  (0, index_1.initialize)({
59
59
  key: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
60
- logLevel: index_1.LogLevel.None
60
+ logLevel: index_1.LogLevel.None,
61
+ });
62
+ var chirpier = index_1.Chirpier.getInstance({
63
+ key: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
61
64
  });
62
- var chirpier = index_1.Chirpier.getInstance({});
63
65
  // Setup mock server
64
66
  var mock = new axios_mock_adapter_1.default(axios_1.default);
65
67
  mock.onPost(constants_1.DEFAULT_API_ENDPOINT).reply(200, { success: true });
@@ -74,13 +76,13 @@ describe("Chirpier SDK", function () {
74
76
  expect(function () {
75
77
  (0, index_1.initialize)({
76
78
  key: "api_key",
77
- logLevel: index_1.LogLevel.None
79
+ logLevel: index_1.LogLevel.None,
78
80
  });
79
81
  }).toThrow(index_1.ChirpierError);
80
82
  expect(function () {
81
83
  (0, index_1.initialize)({
82
84
  key: "api_key",
83
- logLevel: index_1.LogLevel.None
85
+ logLevel: index_1.LogLevel.None,
84
86
  });
85
87
  }).toThrow("Invalid API key: Not a valid JWT");
86
88
  });
@@ -95,7 +97,7 @@ describe("Chirpier SDK", function () {
95
97
  mock.onPost(constants_1.DEFAULT_API_ENDPOINT).reply(200, { success: true });
96
98
  (0, index_1.initialize)({
97
99
  key: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
98
- logLevel: index_1.LogLevel.None
100
+ logLevel: index_1.LogLevel.None,
99
101
  });
100
102
  event = {
101
103
  group_id: "bfd9299d-817a-452f-bc53-6e154f2281fc",
@@ -122,23 +124,31 @@ describe("Chirpier SDK", function () {
122
124
  }
123
125
  });
124
126
  }); });
125
- test("should throw error for invalid event", function () { return __awaiter(void 0, void 0, void 0, function () {
126
- var chirpier, invalidEvent;
127
+ test("should silently drop invalid event", function () { return __awaiter(void 0, void 0, void 0, function () {
128
+ var mock, invalidEvent, consoleSpy;
127
129
  return __generator(this, function (_a) {
128
130
  switch (_a.label) {
129
131
  case 0:
132
+ mock = new axios_mock_adapter_1.default(axios_1.default);
133
+ mock.onPost(constants_1.DEFAULT_API_ENDPOINT).reply(200, { success: true });
130
134
  (0, index_1.initialize)({
131
135
  key: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
132
- logLevel: index_1.LogLevel.None
136
+ logLevel: index_1.LogLevel.Debug,
133
137
  });
134
- chirpier = index_1.Chirpier.getInstance({});
135
138
  invalidEvent = {
136
- group_id: "bfd9299d-817a-452f-bc53-6e154f2281fc",
139
+ group_id: "invalid-uuid",
140
+ stream_name: "",
141
+ value: 0,
137
142
  };
138
- return [4 /*yield*/, expect(chirpier === null || chirpier === void 0 ? void 0 : chirpier.monitor(invalidEvent)).rejects.toThrow(index_1.ChirpierError)];
143
+ consoleSpy = jest.spyOn(console, "debug");
144
+ return [4 /*yield*/, (0, index_1.monitor)(invalidEvent)];
139
145
  case 1:
140
146
  _a.sent();
141
- // Clean up the mock
147
+ expect(consoleSpy).toHaveBeenCalledWith("Invalid event format, dropping event:", invalidEvent);
148
+ expect(mock.history.post.length).toBe(0); // No request should be made
149
+ // Clean up
150
+ mock.reset();
151
+ consoleSpy.mockRestore();
142
152
  index_1.Chirpier.stop();
143
153
  return [2 /*return*/];
144
154
  }
@@ -153,7 +163,7 @@ describe("Chirpier SDK", function () {
153
163
  mock.onPost(constants_1.DEFAULT_API_ENDPOINT).reply(200, { success: true });
154
164
  (0, index_1.initialize)({
155
165
  key: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
156
- logLevel: index_1.LogLevel.None
166
+ logLevel: index_1.LogLevel.None,
157
167
  });
158
168
  event = {
159
169
  group_id: "bfd9299d-817a-452f-bc53-6e154f2281fc",
@@ -182,7 +192,7 @@ describe("Chirpier SDK", function () {
182
192
  mock.onPost(constants_1.DEFAULT_API_ENDPOINT).reply(200, { success: true });
183
193
  (0, index_1.initialize)({
184
194
  key: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
185
- logLevel: index_1.LogLevel.None
195
+ logLevel: index_1.LogLevel.None,
186
196
  });
187
197
  event = {
188
198
  group_id: "bfd9299d-817a-452f-bc53-6e154f2281fc",
@@ -1,7 +1,7 @@
1
- export declare const DEFAULT_API_ENDPOINT = "https://events.chirpier.co/v1.0/events";
2
1
  export declare const DEFAULT_RETRIES = 15;
3
2
  export declare const DEFAULT_TIMEOUT = 5000;
4
- export declare const DEFAULT_BATCH_SIZE = 100;
3
+ export declare const DEFAULT_BATCH_SIZE = 350;
5
4
  export declare const DEFAULT_FLUSH_DELAY = 500;
6
- export declare const MAX_QUEUE_SIZE = 2000;
5
+ export declare const MAX_QUEUE_SIZE = 50000;
6
+ export declare const DEFAULT_API_ENDPOINT = "https://eu-west.chirpier.co/v1.0/events";
7
7
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,oBAAoB,2CAA2C,CAAC;AAC7E,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,eAAe,OAAO,CAAA;AACnC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,cAAc,OAAO,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,eAAe,OAAO,CAAA;AACnC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,cAAc,QAAQ,CAAC;AACpC,eAAO,MAAM,oBAAoB,4CAA4C,CAAA"}
package/dist/constants.js CHANGED
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  // constants.ts
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.MAX_QUEUE_SIZE = exports.DEFAULT_FLUSH_DELAY = exports.DEFAULT_BATCH_SIZE = exports.DEFAULT_TIMEOUT = exports.DEFAULT_RETRIES = exports.DEFAULT_API_ENDPOINT = void 0;
5
- exports.DEFAULT_API_ENDPOINT = 'https://events.chirpier.co/v1.0/events';
4
+ exports.DEFAULT_API_ENDPOINT = exports.MAX_QUEUE_SIZE = exports.DEFAULT_FLUSH_DELAY = exports.DEFAULT_BATCH_SIZE = exports.DEFAULT_TIMEOUT = exports.DEFAULT_RETRIES = void 0;
6
5
  exports.DEFAULT_RETRIES = 15;
7
6
  exports.DEFAULT_TIMEOUT = 5000;
8
- exports.DEFAULT_BATCH_SIZE = 100;
7
+ exports.DEFAULT_BATCH_SIZE = 350;
9
8
  exports.DEFAULT_FLUSH_DELAY = 500;
10
- exports.MAX_QUEUE_SIZE = 2000;
9
+ exports.MAX_QUEUE_SIZE = 50000;
10
+ exports.DEFAULT_API_ENDPOINT = "https://eu-west.chirpier.co/v1.0/events";
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ export declare enum LogLevel {
6
6
  }
7
7
  interface Options {
8
8
  key: string;
9
+ region?: "us-west" | "eu-west" | "asia-southeast";
9
10
  logLevel?: LogLevel;
10
11
  }
11
12
  export interface Event {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAeA,oBAAY,QAAQ;IAClB,IAAI,IAAI;IACR,KAAK,IAAI;IACT,IAAI,IAAI;IACR,KAAK,IAAI;CACV;AAGD,UAAU,OAAO;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAGD,MAAM,WAAW,KAAK;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAGD,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAK5B;AAQD;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmB;IAC7C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmB;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IAEpC;;;OAGG;IACH,OAAO;IA6CP;;;;OAIG;WACW,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI;IAO5D;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAapB;;;OAGG;IACU,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBjD;;OAEG;YACW,UAAU;IA8DxB;;;OAGG;YACW,UAAU;WAKJ,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAa1C;AAqCD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAsBjD;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAW1C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,oBAAY,QAAQ;IAClB,IAAI,IAAI;IACR,KAAK,IAAI;IACT,IAAI,IAAI;IACR,KAAK,IAAI;CACV;AAGD,UAAU,OAAO;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,gBAAgB,CAAC;IAClD,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAGD,MAAM,WAAW,KAAK;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAGD,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAK5B;AAQD;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAEvB;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAEvB;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IAEpC;;;OAGG;IACH,OAAO;IAyDP;;;;OAIG;WACW,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI;IAO5D;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAapB;;;OAGG;IACU,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IA6BjD;;OAEG;YACW,UAAU;IA8DxB;;;OAGG;YACW,UAAU;WAKJ,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAa1C;AAsCD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAsBjD;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAW1C"}
package/dist/index.js CHANGED
@@ -101,14 +101,22 @@ var Chirpier = /** @class */ (function () {
101
101
  function Chirpier(options) {
102
102
  this.eventQueue = [];
103
103
  this.flushTimeoutId = null;
104
- this.queueLock = new async_lock_1.default();
105
- this.flushLock = new async_lock_1.default();
106
- var key = options.key, _a = options.logLevel, logLevel = _a === void 0 ? LogLevel.None : _a;
104
+ this.queueLock = new async_lock_1.default({
105
+ maxPending: constants_1.MAX_QUEUE_SIZE,
106
+ });
107
+ this.flushLock = new async_lock_1.default({
108
+ maxPending: constants_1.MAX_QUEUE_SIZE,
109
+ });
110
+ var key = options.key, _a = options.region, region = _a === void 0 ? "eu-west" : _a, _b = options.logLevel, logLevel = _b === void 0 ? LogLevel.None : _b;
107
111
  if (!key || typeof key !== "string") {
108
112
  throw new ChirpierError("API key is required and must be a string");
109
113
  }
114
+ if (typeof region !== "string" &&
115
+ !["us-west", "eu-west", "asia-southeast"].includes(region)) {
116
+ throw new ChirpierError("Region must be one of: us-west, eu-west, asia-southeast");
117
+ }
118
+ this.apiEndpoint = "https://".concat(region, ".chirpier.co/v1.0/events");
110
119
  this.apiKey = key;
111
- this.apiEndpoint = constants_1.DEFAULT_API_ENDPOINT;
112
120
  this.retries = constants_1.DEFAULT_RETRIES;
113
121
  this.timeout = constants_1.DEFAULT_TIMEOUT;
114
122
  this.batchSize = constants_1.DEFAULT_BATCH_SIZE;
@@ -131,7 +139,10 @@ var Chirpier = /** @class */ (function () {
131
139
  return Math.pow(2, retryCount) * 1000; // Exponential backoff starting at 1 second
132
140
  },
133
141
  retryCondition: function (error) {
134
- return (axios_retry_1.default.isNetworkError(error) || axios_retry_1.default.isRetryableError(error));
142
+ // Retry on network errors, 5xx errors, and 429 (Too Many Requests)
143
+ return (axios_retry_1.default.isNetworkError(error) ||
144
+ axios_retry_1.default.isRetryableError(error) ||
145
+ (error.response && error.response.status) === 429);
135
146
  },
136
147
  shouldResetTimeout: true,
137
148
  });
@@ -171,12 +182,18 @@ var Chirpier = /** @class */ (function () {
171
182
  switch (_a.label) {
172
183
  case 0:
173
184
  if (!this.isValidEvent(event)) {
174
- throw new ChirpierError("Invalid event format. Must include group_id, stream_name, and numeric value.");
185
+ if (this.logLevel >= LogLevel.Debug) {
186
+ console.debug("Invalid event format, dropping event:", event);
187
+ }
188
+ return [2 /*return*/]; // Silently drop the event
175
189
  }
176
190
  return [4 /*yield*/, this.queueLock.acquire("queue", function () { return __awaiter(_this, void 0, void 0, function () {
177
191
  return __generator(this, function (_a) {
178
192
  if (this.eventQueue.length >= constants_1.MAX_QUEUE_SIZE) {
179
- throw new ChirpierError("Event queue is full.");
193
+ if (this.logLevel >= LogLevel.Debug) {
194
+ console.debug("Event queue is full, dropping event:", event);
195
+ }
196
+ return [2 /*return*/]; // Silently drop the event
180
197
  }
181
198
  this.eventQueue.push({ event: event, timestamp: Date.now(), retryCount: 0 });
182
199
  return [2 /*return*/];
@@ -367,6 +384,7 @@ function isValidJWT(token) {
367
384
  return typeof header === "object" && typeof payload === "object";
368
385
  }
369
386
  catch (error) {
387
+ console.error("Failed to validate JWT:", error);
370
388
  return false;
371
389
  }
372
390
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chirpier/chirpier-js",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Chirpier SDK for JavaScript",
5
5
  "keywords": [
6
6
  "chirpier",
@@ -1,4 +1,11 @@
1
- import { Chirpier, ChirpierError, Event, LogLevel, initialize, monitor } from "../index";
1
+ import {
2
+ Chirpier,
3
+ ChirpierError,
4
+ Event,
5
+ LogLevel,
6
+ initialize,
7
+ monitor,
8
+ } from "../index";
2
9
  import {
3
10
  DEFAULT_API_ENDPOINT,
4
11
  DEFAULT_RETRIES,
@@ -27,9 +34,11 @@ describe("Chirpier SDK", () => {
27
34
  test("should initialize with default values", () => {
28
35
  initialize({
29
36
  key: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
30
- logLevel: LogLevel.None
37
+ logLevel: LogLevel.None,
38
+ });
39
+ const chirpier = Chirpier.getInstance({
40
+ key: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
31
41
  });
32
- const chirpier = Chirpier.getInstance({} as any);
33
42
 
34
43
  // Setup mock server
35
44
  const mock = new MockAdapter(axios);
@@ -48,13 +57,13 @@ describe("Chirpier SDK", () => {
48
57
  expect(() => {
49
58
  initialize({
50
59
  key: "api_key",
51
- logLevel: LogLevel.None
60
+ logLevel: LogLevel.None,
52
61
  });
53
62
  }).toThrow(ChirpierError);
54
63
  expect(() => {
55
64
  initialize({
56
65
  key: "api_key",
57
- logLevel: LogLevel.None
66
+ logLevel: LogLevel.None,
58
67
  });
59
68
  }).toThrow("Invalid API key: Not a valid JWT");
60
69
  });
@@ -68,7 +77,7 @@ describe("Chirpier SDK", () => {
68
77
 
69
78
  initialize({
70
79
  key: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
71
- logLevel: LogLevel.None
80
+ logLevel: LogLevel.None,
72
81
  });
73
82
 
74
83
  const event: Event = {
@@ -96,21 +105,34 @@ describe("Chirpier SDK", () => {
96
105
  Chirpier.stop();
97
106
  });
98
107
 
99
- test("should throw error for invalid event", async () => {
108
+ test("should silently drop invalid event", async () => {
109
+ const mock = new MockAdapter(axios);
110
+ mock.onPost(DEFAULT_API_ENDPOINT).reply(200, { success: true });
111
+
100
112
  initialize({
101
113
  key: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
102
- logLevel: LogLevel.None
114
+ logLevel: LogLevel.Debug,
103
115
  });
104
- const chirpier = Chirpier.getInstance({} as any);
105
116
 
106
117
  const invalidEvent = {
107
- group_id: "bfd9299d-817a-452f-bc53-6e154f2281fc",
108
- } as any;
109
- await expect(chirpier?.monitor(invalidEvent)).rejects.toThrow(
110
- ChirpierError
118
+ group_id: "invalid-uuid",
119
+ stream_name: "",
120
+ value: 0,
121
+ } as Event;
122
+
123
+ const consoleSpy = jest.spyOn(console, "debug");
124
+
125
+ await monitor(invalidEvent);
126
+
127
+ expect(consoleSpy).toHaveBeenCalledWith(
128
+ "Invalid event format, dropping event:",
129
+ invalidEvent
111
130
  );
131
+ expect(mock.history.post.length).toBe(0); // No request should be made
112
132
 
113
- // Clean up the mock
133
+ // Clean up
134
+ mock.reset();
135
+ consoleSpy.mockRestore();
114
136
  Chirpier.stop();
115
137
  });
116
138
 
@@ -120,7 +142,7 @@ describe("Chirpier SDK", () => {
120
142
 
121
143
  initialize({
122
144
  key: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
123
- logLevel: LogLevel.None
145
+ logLevel: LogLevel.None,
124
146
  });
125
147
 
126
148
  const event: Event = {
@@ -147,7 +169,7 @@ describe("Chirpier SDK", () => {
147
169
 
148
170
  initialize({
149
171
  key: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
150
- logLevel: LogLevel.None
172
+ logLevel: LogLevel.None,
151
173
  });
152
174
 
153
175
  const event: Event = {
package/src/constants.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  // constants.ts
2
2
 
3
- export const DEFAULT_API_ENDPOINT = 'https://events.chirpier.co/v1.0/events';
4
3
  export const DEFAULT_RETRIES = 15;
5
4
  export const DEFAULT_TIMEOUT = 5000
6
- export const DEFAULT_BATCH_SIZE = 100;
5
+ export const DEFAULT_BATCH_SIZE = 350;
7
6
  export const DEFAULT_FLUSH_DELAY = 500;
8
- export const MAX_QUEUE_SIZE = 2000;
7
+ export const MAX_QUEUE_SIZE = 50000;
8
+ export const DEFAULT_API_ENDPOINT = "https://eu-west.chirpier.co/v1.0/events"
package/src/index.ts CHANGED
@@ -3,7 +3,6 @@ import axios, { AxiosInstance } from "axios";
3
3
  import axiosRetry from "axios-retry";
4
4
  import { Base64 } from "js-base64";
5
5
  import {
6
- DEFAULT_API_ENDPOINT,
7
6
  DEFAULT_RETRIES,
8
7
  DEFAULT_TIMEOUT,
9
8
  DEFAULT_BATCH_SIZE,
@@ -23,6 +22,7 @@ export enum LogLevel {
23
22
  // Define the options interface for Chirpier initialization
24
23
  interface Options {
25
24
  key: string;
25
+ region?: "us-west" | "eu-west" | "asia-southeast";
26
26
  logLevel?: LogLevel;
27
27
  }
28
28
 
@@ -62,8 +62,12 @@ export class Chirpier {
62
62
  private readonly batchSize: number;
63
63
  private readonly flushDelay: number;
64
64
  private flushTimeoutId: NodeJS.Timeout | null = null;
65
- private readonly queueLock = new AsyncLock();
66
- private readonly flushLock = new AsyncLock();
65
+ private readonly queueLock = new AsyncLock({
66
+ maxPending: MAX_QUEUE_SIZE,
67
+ });
68
+ private readonly flushLock = new AsyncLock({
69
+ maxPending: MAX_QUEUE_SIZE,
70
+ });
67
71
  private readonly logLevel: LogLevel;
68
72
 
69
73
  /**
@@ -71,14 +75,23 @@ export class Chirpier {
71
75
  * @param options - Configuration options for the SDK.
72
76
  */
73
77
  private constructor(options: Options) {
74
- const { key, logLevel = LogLevel.None } = options;
78
+ const { key, region = "eu-west", logLevel = LogLevel.None } = options;
75
79
 
76
80
  if (!key || typeof key !== "string") {
77
81
  throw new ChirpierError("API key is required and must be a string");
78
82
  }
79
83
 
84
+ if (
85
+ typeof region !== "string" &&
86
+ !["us-west", "eu-west", "asia-southeast"].includes(region)
87
+ ) {
88
+ throw new ChirpierError(
89
+ "Region must be one of: us-west, eu-west, asia-southeast"
90
+ );
91
+ }
92
+
93
+ this.apiEndpoint = `https://${region}.chirpier.co/v1.0/events`;
80
94
  this.apiKey = key;
81
- this.apiEndpoint = DEFAULT_API_ENDPOINT;
82
95
  this.retries = DEFAULT_RETRIES;
83
96
  this.timeout = DEFAULT_TIMEOUT;
84
97
  this.batchSize = DEFAULT_BATCH_SIZE;
@@ -107,8 +120,11 @@ export class Chirpier {
107
120
  return Math.pow(2, retryCount) * 1000; // Exponential backoff starting at 1 second
108
121
  },
109
122
  retryCondition: (error) => {
123
+ // Retry on network errors, 5xx errors, and 429 (Too Many Requests)
110
124
  return (
111
- axiosRetry.isNetworkError(error) || axiosRetry.isRetryableError(error)
125
+ axiosRetry.isNetworkError(error) ||
126
+ axiosRetry.isRetryableError(error) ||
127
+ (error.response && error.response.status) === 429
112
128
  );
113
129
  },
114
130
  shouldResetTimeout: true,
@@ -151,14 +167,18 @@ export class Chirpier {
151
167
  */
152
168
  public async monitor(event: Event): Promise<void> {
153
169
  if (!this.isValidEvent(event)) {
154
- throw new ChirpierError(
155
- "Invalid event format. Must include group_id, stream_name, and numeric value."
156
- );
170
+ if (this.logLevel >= LogLevel.Debug) {
171
+ console.debug("Invalid event format, dropping event:", event);
172
+ }
173
+ return; // Silently drop the event
157
174
  }
158
175
 
159
176
  await this.queueLock.acquire("queue", async () => {
160
177
  if (this.eventQueue.length >= MAX_QUEUE_SIZE) {
161
- throw new ChirpierError("Event queue is full.");
178
+ if (this.logLevel >= LogLevel.Debug) {
179
+ console.debug("Event queue is full, dropping event:", event);
180
+ }
181
+ return; // Silently drop the event
162
182
  }
163
183
 
164
184
  this.eventQueue.push({ event, timestamp: Date.now(), retryCount: 0 });
@@ -294,6 +314,7 @@ function isValidJWT(token: string): boolean {
294
314
  const payload = JSON.parse(base64UrlDecode(parts[1]));
295
315
  return typeof header === "object" && typeof payload === "object";
296
316
  } catch (error) {
317
+ console.error("Failed to validate JWT:", error);
297
318
  return false;
298
319
  }
299
320
  }