@chirpier/chirpier-js 0.1.6 → 0.2.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/dist/index.js CHANGED
@@ -14,6 +14,17 @@ var __extends = (this && this.__extends) || (function () {
14
14
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
15
  };
16
16
  })();
17
+ var __assign = (this && this.__assign) || function () {
18
+ __assign = Object.assign || function(t) {
19
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
20
+ s = arguments[i];
21
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
22
+ t[p] = s[p];
23
+ }
24
+ return t;
25
+ };
26
+ return __assign.apply(this, arguments);
27
+ };
17
28
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
18
29
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
19
30
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -63,26 +74,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
63
74
  return (mod && mod.__esModule) ? mod : { "default": mod };
64
75
  };
65
76
  Object.defineProperty(exports, "__esModule", { value: true });
66
- exports.monitor = exports.initialize = exports.Chirpier = exports.ChirpierError = exports.LogLevel = void 0;
67
- // Import necessary dependencies
77
+ exports.flush = exports.stop = exports.logEvent = exports.initialize = exports.createClient = exports.Client = exports.ChirpierError = void 0;
68
78
  var axios_1 = __importDefault(require("axios"));
69
79
  var axios_retry_1 = __importDefault(require("axios-retry"));
70
- var js_base64_1 = require("js-base64");
80
+ var dotenv_1 = __importDefault(require("dotenv"));
71
81
  var constants_1 = require("./constants");
72
82
  var async_lock_1 = __importDefault(require("async-lock"));
73
- // Define logging levels
74
- var LogLevel;
75
- (function (LogLevel) {
76
- LogLevel[LogLevel["None"] = 0] = "None";
77
- LogLevel[LogLevel["Error"] = 1] = "Error";
78
- LogLevel[LogLevel["Info"] = 2] = "Info";
79
- LogLevel[LogLevel["Debug"] = 3] = "Debug";
80
- })(LogLevel = exports.LogLevel || (exports.LogLevel = {}));
81
83
  // Custom error class for Chirpier-specific errors
82
84
  var ChirpierError = /** @class */ (function (_super) {
83
85
  __extends(ChirpierError, _super);
84
- function ChirpierError(message) {
86
+ function ChirpierError(message, code) {
85
87
  var _this = _super.call(this, message) || this;
88
+ _this.code = code;
86
89
  _this.name = "ChirpierError";
87
90
  Object.setPrototypeOf(_this, ChirpierError.prototype);
88
91
  return _this;
@@ -90,56 +93,74 @@ var ChirpierError = /** @class */ (function (_super) {
90
93
  return ChirpierError;
91
94
  }(Error));
92
95
  exports.ChirpierError = ChirpierError;
93
- /**
94
- * Main Chirpier class for monitoring events.
95
- */
96
- var Chirpier = /** @class */ (function () {
97
- /**
98
- * Initializes a new instance of the Chirpier class.
99
- * @param options - Configuration options for the SDK.
100
- */
101
- function Chirpier(options) {
102
- this.eventQueue = [];
96
+ var Client = /** @class */ (function () {
97
+ function Client(options) {
98
+ if (options === void 0) { options = {}; }
99
+ this.logQueue = [];
103
100
  this.flushTimeoutId = null;
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;
111
- if (!key || typeof key !== "string") {
112
- throw new ChirpierError("API key is required and must be a string");
101
+ var providedKey = options.key, _a = options.apiEndpoint, apiEndpoint = _a === void 0 ? constants_1.DEFAULT_API_ENDPOINT : _a, _b = options.servicerEndpoint, servicerEndpoint = _b === void 0 ? constants_1.DEFAULT_SERVICER_ENDPOINT : _b, _c = options.logLevel, logLevel = _c === void 0 ? 0 /* LogLevel.None */ : _c, _d = options.retries, retries = _d === void 0 ? constants_1.DEFAULT_RETRIES : _d, _e = options.timeout, timeout = _e === void 0 ? constants_1.DEFAULT_TIMEOUT : _e, _f = options.batchSize, batchSize = _f === void 0 ? constants_1.DEFAULT_BATCH_SIZE : _f, _g = options.flushDelay, flushDelay = _g === void 0 ? constants_1.DEFAULT_FLUSH_DELAY : _g, _h = options.maxQueueSize, maxQueueSize = _h === void 0 ? constants_1.MAX_QUEUE_SIZE : _h;
102
+ var key = resolveAPIKey(providedKey);
103
+ if (!key) {
104
+ throw new ChirpierError("API key is required", "INVALID_KEY");
105
+ }
106
+ if (!isValidAPIKey(key)) {
107
+ throw new ChirpierError("Invalid API key: must start with 'chp_'", "INVALID_KEY");
108
+ }
109
+ if (apiEndpoint !== undefined) {
110
+ if (typeof apiEndpoint !== "string" || apiEndpoint.trim().length === 0) {
111
+ throw new ChirpierError("apiEndpoint must be a non-empty string", "INVALID_API_ENDPOINT");
112
+ }
113
+ var parsedURL = void 0;
114
+ try {
115
+ parsedURL = new URL(apiEndpoint);
116
+ }
117
+ catch (_j) {
118
+ throw new ChirpierError("apiEndpoint must be a valid absolute URL", "INVALID_API_ENDPOINT");
119
+ }
120
+ if (parsedURL.protocol !== "https:" && parsedURL.protocol !== "http:") {
121
+ throw new ChirpierError("apiEndpoint must use http or https", "INVALID_API_ENDPOINT");
122
+ }
123
+ }
124
+ // Validate numeric options
125
+ if (retries < 0 || !Number.isInteger(retries)) {
126
+ throw new ChirpierError("Retries must be a non-negative integer", "INVALID_RETRIES");
113
127
  }
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");
128
+ if (timeout <= 0) {
129
+ throw new ChirpierError("Timeout must be positive", "INVALID_TIMEOUT");
117
130
  }
118
- this.apiEndpoint = "https://".concat(region, ".chirpier.co/v1.0/events");
131
+ if (batchSize <= 0 || !Number.isInteger(batchSize)) {
132
+ throw new ChirpierError("Batch size must be a positive integer", "INVALID_BATCH_SIZE");
133
+ }
134
+ if (flushDelay < 0) {
135
+ throw new ChirpierError("Flush delay must be non-negative", "INVALID_FLUSH_DELAY");
136
+ }
137
+ if (maxQueueSize <= 0 || !Number.isInteger(maxQueueSize)) {
138
+ throw new ChirpierError("Max queue size must be a positive integer", "INVALID_QUEUE_SIZE");
139
+ }
140
+ this.apiEndpoint = apiEndpoint !== null && apiEndpoint !== void 0 ? apiEndpoint : constants_1.DEFAULT_API_ENDPOINT;
141
+ this.servicerEndpoint = servicerEndpoint !== null && servicerEndpoint !== void 0 ? servicerEndpoint : constants_1.DEFAULT_SERVICER_ENDPOINT;
119
142
  this.apiKey = key;
120
- this.retries = constants_1.DEFAULT_RETRIES;
121
- this.timeout = constants_1.DEFAULT_TIMEOUT;
122
- this.batchSize = constants_1.DEFAULT_BATCH_SIZE;
123
- this.flushDelay = constants_1.DEFAULT_FLUSH_DELAY;
143
+ this.retries = retries;
144
+ this.timeout = timeout;
145
+ this.batchSize = batchSize;
146
+ this.flushDelay = flushDelay;
147
+ this.maxQueueSize = maxQueueSize;
124
148
  this.logLevel = logLevel;
125
- // Create axios instance with authorization header
149
+ this.queueLock = new async_lock_1.default({ maxPending: this.maxQueueSize });
150
+ this.flushLock = new async_lock_1.default({ maxPending: this.maxQueueSize });
126
151
  this.axiosInstance = axios_1.default.create({
127
152
  headers: { Authorization: "Bearer ".concat(this.apiKey) },
128
153
  timeout: this.timeout,
129
154
  });
130
- // Add the interceptor here
131
- this.axiosInstance.interceptors.response.use(function (response) { return response; }, function (error) {
132
- // Don't handle the error here; let axios-retry handle it
133
- return Promise.reject(error);
134
- });
135
- // Apply axios-retry to your Axios instance
155
+ this.axiosInstance.interceptors.response.use(function (response) { return response; }, function (error) { return Promise.reject(error); });
136
156
  (0, axios_retry_1.default)(this.axiosInstance, {
137
157
  retries: this.retries,
138
158
  retryDelay: function (retryCount) {
139
- return Math.pow(2, retryCount) * 1000; // Exponential backoff starting at 1 second
159
+ var baseDelay = Math.pow(2, retryCount) * 1000;
160
+ var jitter = Math.random() * 0.3 * baseDelay;
161
+ return baseDelay + jitter;
140
162
  },
141
163
  retryCondition: function (error) {
142
- // Retry on network errors, 5xx errors, and 429 (Too Many Requests)
143
164
  return (axios_retry_1.default.isNetworkError(error) ||
144
165
  axios_retry_1.default.isRetryableError(error) ||
145
166
  (error.response && error.response.status) === 429);
@@ -147,61 +168,91 @@ var Chirpier = /** @class */ (function () {
147
168
  shouldResetTimeout: true,
148
169
  });
149
170
  }
150
- /**
151
- * Gets the singleton instance of Chirpier, creating it if it doesn't exist.
152
- * @param options - Configuration options for the SDK.
153
- * @returns The Chirpier instance.
154
- */
155
- Chirpier.getInstance = function (options) {
156
- if (!Chirpier.instance && options.key) {
157
- Chirpier.instance = new Chirpier(options);
171
+ Client.prototype.isValidLog = function (log) {
172
+ var now = Date.now();
173
+ var oldestAllowed = now - 30 * 24 * 60 * 60 * 1000;
174
+ var newestAllowed = now + 24 * 60 * 60 * 1000;
175
+ if (typeof log.event !== "string" || log.event.trim().length === 0) {
176
+ return false;
177
+ }
178
+ if (typeof log.value !== "number" || !Number.isFinite(log.value)) {
179
+ return false;
180
+ }
181
+ if (log.agent_id !== undefined && typeof log.agent_id !== "string") {
182
+ return false;
183
+ }
184
+ if (log.meta !== undefined) {
185
+ try {
186
+ var serializedMeta = JSON.stringify(log.meta);
187
+ if (serializedMeta === undefined) {
188
+ return false;
189
+ }
190
+ }
191
+ catch (_a) {
192
+ return false;
193
+ }
194
+ }
195
+ if (log.occurred_at !== undefined) {
196
+ var occurredAtMillis = log.occurred_at instanceof Date
197
+ ? log.occurred_at.getTime()
198
+ : new Date(log.occurred_at).getTime();
199
+ if (!Number.isFinite(occurredAtMillis)) {
200
+ return false;
201
+ }
202
+ if (occurredAtMillis < oldestAllowed || occurredAtMillis > newestAllowed) {
203
+ return false;
204
+ }
158
205
  }
159
- return Chirpier.instance;
206
+ return true;
160
207
  };
161
- /**
162
- * Validates the event structure.
163
- * @param event - The event to validate.
164
- * @returns True if valid, false otherwise.
165
- */
166
- Chirpier.prototype.isValidEvent = function (event) {
167
- return (typeof event.group_id === "string" &&
168
- /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(event.group_id) &&
169
- event.group_id.trim().length > 0 &&
170
- typeof event.stream_name === "string" &&
171
- event.stream_name.trim().length > 0 &&
172
- typeof event.value === "number");
208
+ Client.prototype.normalizeLog = function (log) {
209
+ var normalizedLog = {
210
+ event: log.event.trim(),
211
+ value: log.value,
212
+ };
213
+ if (typeof log.agent_id === "string") {
214
+ var trimmedAgentID = log.agent_id.trim();
215
+ if (trimmedAgentID.length > 0) {
216
+ normalizedLog.agent_id = trimmedAgentID;
217
+ }
218
+ }
219
+ if (log.meta !== undefined) {
220
+ normalizedLog.meta = log.meta;
221
+ }
222
+ if (log.occurred_at !== undefined) {
223
+ var occurredAtDate = log.occurred_at instanceof Date ? log.occurred_at : new Date(log.occurred_at);
224
+ normalizedLog.occurred_at = occurredAtDate.toISOString();
225
+ }
226
+ return normalizedLog;
173
227
  };
174
- /**
175
- * Monitors an event by adding it to the queue and scheduling a flush if necessary.
176
- * @param event - The event to monitor.
177
- */
178
- Chirpier.prototype.monitor = function (event) {
228
+ Client.prototype.log = function (log) {
179
229
  return __awaiter(this, void 0, void 0, function () {
230
+ var normalizedLog, queueFull;
180
231
  var _this = this;
181
232
  return __generator(this, function (_a) {
182
233
  switch (_a.label) {
183
234
  case 0:
184
- if (!this.isValidEvent(event)) {
185
- if (this.logLevel >= LogLevel.Debug) {
186
- console.debug("Invalid event format, dropping event:", event);
187
- }
188
- return [2 /*return*/]; // Silently drop the event
235
+ if (!this.isValidLog(log)) {
236
+ throw new ChirpierError("Invalid log format: event must not be empty, value must be a finite number, agent_id must be a string when provided, meta must be JSON-encodable, and occurred_at must be within the last 30 days and no more than 1 day in the future", "INVALID_LOG");
189
237
  }
238
+ normalizedLog = this.normalizeLog(log);
239
+ queueFull = false;
190
240
  return [4 /*yield*/, this.queueLock.acquire("queue", function () { return __awaiter(_this, void 0, void 0, function () {
191
241
  return __generator(this, function (_a) {
192
- if (this.eventQueue.length >= constants_1.MAX_QUEUE_SIZE) {
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
242
+ if (this.logQueue.length >= this.maxQueueSize) {
243
+ queueFull = true;
244
+ return [2 /*return*/];
197
245
  }
198
- this.eventQueue.push({ event: event, timestamp: Date.now(), retryCount: 0 });
246
+ this.logQueue.push({ log: normalizedLog, timestamp: Date.now(), retryCount: 0 });
199
247
  return [2 /*return*/];
200
248
  });
201
249
  }); })];
202
250
  case 1:
203
251
  _a.sent();
204
- if (!(this.eventQueue.length >= this.batchSize)) return [3 /*break*/, 3];
252
+ if (queueFull) {
253
+ throw new ChirpierError("Log queue is full (max size: ".concat(this.maxQueueSize, ")"), "QUEUE_FULL");
254
+ }
255
+ if (!(this.logQueue.length >= this.batchSize)) return [3 /*break*/, 3];
205
256
  return [4 /*yield*/, this.flushQueue()];
206
257
  case 2:
207
258
  _a.sent();
@@ -216,84 +267,70 @@ var Chirpier = /** @class */ (function () {
216
267
  });
217
268
  });
218
269
  };
219
- /**
220
- * Flushes the event queue by sending all events to the API.
221
- */
222
- Chirpier.prototype.flushQueue = function () {
270
+ Client.prototype.flushQueue = function () {
223
271
  return __awaiter(this, void 0, void 0, function () {
224
272
  var _this = this;
225
273
  return __generator(this, function (_a) {
226
274
  switch (_a.label) {
227
- case 0:
228
- // Acquire the flush lock
229
- return [4 /*yield*/, this.flushLock.acquire("flush", function () { return __awaiter(_this, void 0, void 0, function () {
230
- var eventsToSend, error_1, retryableEvents_1, _i, eventsToSend_1, queuedEvent;
275
+ case 0: return [4 /*yield*/, this.flushLock.acquire("flush", function () { return __awaiter(_this, void 0, void 0, function () {
276
+ var logsToSend, error_1, retryableLogs_1, _i, logsToSend_1, queuedLog;
231
277
  var _this = this;
232
278
  return __generator(this, function (_a) {
233
279
  switch (_a.label) {
234
280
  case 0:
235
- eventsToSend = [];
236
- // Extract events from the queue under the queue lock
237
- return [4 /*yield*/, this.queueLock.acquire("eventQueue", function () { return __awaiter(_this, void 0, void 0, function () {
281
+ logsToSend = [];
282
+ return [4 /*yield*/, this.queueLock.acquire("logQueue", function () { return __awaiter(_this, void 0, void 0, function () {
238
283
  return __generator(this, function (_a) {
239
- if (this.eventQueue.length > 0) {
240
- eventsToSend = __spreadArray([], this.eventQueue, true);
241
- this.eventQueue = [];
284
+ if (this.logQueue.length > 0) {
285
+ logsToSend = __spreadArray([], this.logQueue, true);
286
+ this.logQueue = [];
242
287
  }
243
288
  return [2 /*return*/];
244
289
  });
245
290
  }); })];
246
291
  case 1:
247
- // Extract events from the queue under the queue lock
248
292
  _a.sent();
249
- if (eventsToSend.length === 0) {
293
+ if (logsToSend.length === 0) {
250
294
  return [2 /*return*/];
251
295
  }
252
296
  _a.label = 2;
253
297
  case 2:
254
298
  _a.trys.push([2, 4, , 6]);
255
- // Clear any pending flush timeout
256
299
  if (this.flushTimeoutId) {
257
300
  clearTimeout(this.flushTimeoutId);
258
301
  this.flushTimeoutId = null;
259
302
  }
260
- // Attempt to send events
261
- return [4 /*yield*/, this.sendEvents(eventsToSend.map(function (qe) { return qe.event; }))];
303
+ return [4 /*yield*/, this.sendLogs(logsToSend.map(function (queuedLog) { return queuedLog.log; }))];
262
304
  case 3:
263
- // Attempt to send events
264
305
  _a.sent();
265
- if (this.logLevel >= LogLevel.Info) {
266
- console.info("Successfully sent ".concat(eventsToSend.length, " events"));
306
+ if (this.logLevel >= 2 /* LogLevel.Info */) {
307
+ console.info("Successfully sent ".concat(logsToSend.length, " logs"));
267
308
  }
268
309
  return [3 /*break*/, 6];
269
310
  case 4:
270
311
  error_1 = _a.sent();
271
- // Log failure
272
- if (this.logLevel >= LogLevel.Error) {
273
- console.error("Failed to send events:", error_1);
312
+ if (this.logLevel >= 1 /* LogLevel.Error */) {
313
+ console.error("Failed to send logs:", error_1);
274
314
  }
275
- retryableEvents_1 = [];
276
- for (_i = 0, eventsToSend_1 = eventsToSend; _i < eventsToSend_1.length; _i++) {
277
- queuedEvent = eventsToSend_1[_i];
278
- if (queuedEvent.retryCount >= this.retries) {
279
- if (this.logLevel >= LogLevel.Error) {
280
- console.error("Dropping event after ".concat(this.retries, " retries:"), queuedEvent.event);
315
+ retryableLogs_1 = [];
316
+ for (_i = 0, logsToSend_1 = logsToSend; _i < logsToSend_1.length; _i++) {
317
+ queuedLog = logsToSend_1[_i];
318
+ if (queuedLog.retryCount >= this.retries) {
319
+ if (this.logLevel >= 1 /* LogLevel.Error */) {
320
+ console.error("Dropping log after ".concat(this.retries, " retries:"), queuedLog.log);
281
321
  }
282
- continue; // Skip adding this event back to the queue
322
+ continue;
283
323
  }
284
- // Increment retry count and add back to the queue
285
- queuedEvent.retryCount++;
286
- retryableEvents_1.push(queuedEvent);
324
+ queuedLog.retryCount++;
325
+ retryableLogs_1.push(queuedLog);
287
326
  }
288
- // Requeue remaining retryable events
289
- return [4 /*yield*/, this.queueLock.acquire("eventQueue", function () { return __awaiter(_this, void 0, void 0, function () {
327
+ return [4 /*yield*/, this.queueLock.acquire("logQueue", function () { return __awaiter(_this, void 0, void 0, function () {
290
328
  return __generator(this, function (_a) {
291
- this.eventQueue = __spreadArray(__spreadArray([], retryableEvents_1, true), this.eventQueue, true);
329
+ this.logQueue = __spreadArray(__spreadArray([], retryableLogs_1, true), this.logQueue, true);
292
330
  return [2 /*return*/];
293
331
  });
294
332
  }); })];
295
333
  case 5:
296
- // Requeue remaining retryable events
297
334
  _a.sent();
298
335
  return [3 /*break*/, 6];
299
336
  case 6: return [2 /*return*/];
@@ -301,22 +338,17 @@ var Chirpier = /** @class */ (function () {
301
338
  });
302
339
  }); })];
303
340
  case 1:
304
- // Acquire the flush lock
305
341
  _a.sent();
306
342
  return [2 /*return*/];
307
343
  }
308
344
  });
309
345
  });
310
346
  };
311
- /**
312
- * Sends multiple events to the API in a batch.
313
- * @param events - The array of events to send.
314
- */
315
- Chirpier.prototype.sendEvents = function (events) {
347
+ Client.prototype.sendLogs = function (logs) {
316
348
  return __awaiter(this, void 0, void 0, function () {
317
349
  return __generator(this, function (_a) {
318
350
  switch (_a.label) {
319
- case 0: return [4 /*yield*/, this.axiosInstance.post(this.apiEndpoint, events)];
351
+ case 0: return [4 /*yield*/, this.axiosInstance.post(this.apiEndpoint, logs)];
320
352
  case 1:
321
353
  _a.sent();
322
354
  return [2 /*return*/];
@@ -324,89 +356,299 @@ var Chirpier = /** @class */ (function () {
324
356
  });
325
357
  });
326
358
  };
327
- // Stop the timeout and uninitialize the Chirpier instance
328
- Chirpier.stop = function () {
359
+ Client.prototype.flush = function () {
360
+ return __awaiter(this, void 0, void 0, function () {
361
+ return __generator(this, function (_a) {
362
+ switch (_a.label) {
363
+ case 0: return [4 /*yield*/, this.flushQueue()];
364
+ case 1:
365
+ _a.sent();
366
+ return [2 /*return*/];
367
+ }
368
+ });
369
+ });
370
+ };
371
+ Client.prototype.shutdown = function () {
329
372
  return __awaiter(this, void 0, void 0, function () {
330
373
  return __generator(this, function (_a) {
331
374
  switch (_a.label) {
332
375
  case 0:
333
- if (!Chirpier.instance) {
334
- return [2 /*return*/];
376
+ if (this.flushTimeoutId) {
377
+ clearTimeout(this.flushTimeoutId);
378
+ this.flushTimeoutId = null;
335
379
  }
336
- if (Chirpier.instance.flushTimeoutId) {
337
- clearTimeout(Chirpier.instance.flushTimeoutId);
338
- Chirpier.instance.flushTimeoutId = null;
380
+ return [4 /*yield*/, this.flushQueue()];
381
+ case 1:
382
+ _a.sent();
383
+ return [2 /*return*/];
384
+ }
385
+ });
386
+ });
387
+ };
388
+ Client.prototype.close = function () {
389
+ return __awaiter(this, void 0, void 0, function () {
390
+ return __generator(this, function (_a) {
391
+ switch (_a.label) {
392
+ case 0: return [4 /*yield*/, this.shutdown()];
393
+ case 1:
394
+ _a.sent();
395
+ return [2 /*return*/];
396
+ }
397
+ });
398
+ });
399
+ };
400
+ Client.prototype.listEvents = function () {
401
+ return __awaiter(this, void 0, void 0, function () {
402
+ var response;
403
+ return __generator(this, function (_a) {
404
+ switch (_a.label) {
405
+ case 0: return [4 /*yield*/, this.axiosInstance.get("".concat(this.servicerEndpoint, "/events"))];
406
+ case 1:
407
+ response = _a.sent();
408
+ return [2 /*return*/, response.data];
409
+ }
410
+ });
411
+ });
412
+ };
413
+ Client.prototype.getEvent = function (eventID) {
414
+ return __awaiter(this, void 0, void 0, function () {
415
+ var response;
416
+ return __generator(this, function (_a) {
417
+ switch (_a.label) {
418
+ case 0: return [4 /*yield*/, this.axiosInstance.get("".concat(this.servicerEndpoint, "/events/").concat(eventID))];
419
+ case 1:
420
+ response = _a.sent();
421
+ return [2 /*return*/, response.data];
422
+ }
423
+ });
424
+ });
425
+ };
426
+ Client.prototype.updateEvent = function (eventID, payload) {
427
+ return __awaiter(this, void 0, void 0, function () {
428
+ var response;
429
+ return __generator(this, function (_a) {
430
+ switch (_a.label) {
431
+ case 0: return [4 /*yield*/, this.axiosInstance.put("".concat(this.servicerEndpoint, "/events/").concat(eventID), payload)];
432
+ case 1:
433
+ response = _a.sent();
434
+ return [2 /*return*/, response.data];
435
+ }
436
+ });
437
+ });
438
+ };
439
+ Client.prototype.listPolicies = function () {
440
+ return __awaiter(this, void 0, void 0, function () {
441
+ var response;
442
+ return __generator(this, function (_a) {
443
+ switch (_a.label) {
444
+ case 0: return [4 /*yield*/, this.axiosInstance.get("".concat(this.servicerEndpoint, "/policies"))];
445
+ case 1:
446
+ response = _a.sent();
447
+ return [2 /*return*/, response.data];
448
+ }
449
+ });
450
+ });
451
+ };
452
+ Client.prototype.createPolicy = function (payload) {
453
+ return __awaiter(this, void 0, void 0, function () {
454
+ var response;
455
+ return __generator(this, function (_a) {
456
+ switch (_a.label) {
457
+ case 0: return [4 /*yield*/, this.axiosInstance.post("".concat(this.servicerEndpoint, "/policies"), payload)];
458
+ case 1:
459
+ response = _a.sent();
460
+ return [2 /*return*/, response.data];
461
+ }
462
+ });
463
+ });
464
+ };
465
+ Client.prototype.listAlerts = function (status) {
466
+ return __awaiter(this, void 0, void 0, function () {
467
+ var endpoint, response;
468
+ return __generator(this, function (_a) {
469
+ switch (_a.label) {
470
+ case 0:
471
+ endpoint = status
472
+ ? "".concat(this.servicerEndpoint, "/alerts?status=").concat(encodeURIComponent(status))
473
+ : "".concat(this.servicerEndpoint, "/alerts");
474
+ return [4 /*yield*/, this.axiosInstance.get(endpoint)];
475
+ case 1:
476
+ response = _a.sent();
477
+ return [2 /*return*/, response.data];
478
+ }
479
+ });
480
+ });
481
+ };
482
+ Client.prototype.getAlertDeliveries = function (alertID, options) {
483
+ if (options === void 0) { options = {}; }
484
+ return __awaiter(this, void 0, void 0, function () {
485
+ var params, suffix, response;
486
+ return __generator(this, function (_a) {
487
+ switch (_a.label) {
488
+ case 0:
489
+ params = new URLSearchParams();
490
+ if (options.kind) {
491
+ params.set("kind", options.kind);
492
+ }
493
+ if (typeof options.limit === "number") {
494
+ params.set("limit", String(options.limit));
495
+ }
496
+ if (typeof options.offset === "number") {
497
+ params.set("offset", String(options.offset));
339
498
  }
340
- // Flush any remaining events in the queue
341
- return [4 /*yield*/, Chirpier.instance.flushQueue()];
499
+ suffix = params.toString() ? "?".concat(params.toString()) : "";
500
+ return [4 /*yield*/, this.axiosInstance.get("".concat(this.servicerEndpoint, "/alerts/").concat(alertID, "/deliveries").concat(suffix))];
501
+ case 1:
502
+ response = _a.sent();
503
+ return [2 /*return*/, response.data];
504
+ }
505
+ });
506
+ });
507
+ };
508
+ Client.prototype.acknowledgeAlert = function (alertID) {
509
+ return __awaiter(this, void 0, void 0, function () {
510
+ var response;
511
+ return __generator(this, function (_a) {
512
+ switch (_a.label) {
513
+ case 0: return [4 /*yield*/, this.axiosInstance.post("".concat(this.servicerEndpoint, "/alerts/").concat(alertID, "/acknowledge"))];
514
+ case 1:
515
+ response = _a.sent();
516
+ return [2 /*return*/, response.data];
517
+ }
518
+ });
519
+ });
520
+ };
521
+ Client.prototype.archiveAlert = function (alertID) {
522
+ return __awaiter(this, void 0, void 0, function () {
523
+ var response;
524
+ return __generator(this, function (_a) {
525
+ switch (_a.label) {
526
+ case 0: return [4 /*yield*/, this.axiosInstance.post("".concat(this.servicerEndpoint, "/alerts/").concat(alertID, "/archive"))];
527
+ case 1:
528
+ response = _a.sent();
529
+ return [2 /*return*/, response.data];
530
+ }
531
+ });
532
+ });
533
+ };
534
+ Client.prototype.testWebhook = function (webhookID) {
535
+ return __awaiter(this, void 0, void 0, function () {
536
+ return __generator(this, function (_a) {
537
+ switch (_a.label) {
538
+ case 0: return [4 /*yield*/, this.axiosInstance.post("".concat(this.servicerEndpoint, "/webhooks/").concat(webhookID, "/test"))];
342
539
  case 1:
343
- // Flush any remaining events in the queue
344
540
  _a.sent();
345
- // Uninitialize the Chirpier instance
346
- Chirpier.instance = null;
347
541
  return [2 /*return*/];
348
542
  }
349
543
  });
350
544
  });
351
545
  };
352
- Chirpier.instance = null;
353
- return Chirpier;
546
+ Client.prototype.getEventLogs = function (eventID, options) {
547
+ if (options === void 0) { options = {}; }
548
+ return __awaiter(this, void 0, void 0, function () {
549
+ var params, suffix, response;
550
+ return __generator(this, function (_a) {
551
+ switch (_a.label) {
552
+ case 0:
553
+ params = new URLSearchParams();
554
+ if (options.period) {
555
+ params.set("period", options.period);
556
+ }
557
+ if (typeof options.limit === "number") {
558
+ params.set("limit", String(options.limit));
559
+ }
560
+ if (typeof options.offset === "number") {
561
+ params.set("offset", String(options.offset));
562
+ }
563
+ suffix = params.toString() ? "?".concat(params.toString()) : "";
564
+ return [4 /*yield*/, this.axiosInstance.get("".concat(this.servicerEndpoint, "/events/").concat(eventID, "/logs").concat(suffix))];
565
+ case 1:
566
+ response = _a.sent();
567
+ return [2 /*return*/, response.data];
568
+ }
569
+ });
570
+ });
571
+ };
572
+ Client.prototype.resolveAlert = function (alertID) {
573
+ return __awaiter(this, void 0, void 0, function () {
574
+ var response;
575
+ return __generator(this, function (_a) {
576
+ switch (_a.label) {
577
+ case 0: return [4 /*yield*/, this.axiosInstance.post("".concat(this.servicerEndpoint, "/alerts/").concat(alertID, "/resolve"))];
578
+ case 1:
579
+ response = _a.sent();
580
+ return [2 /*return*/, response.data];
581
+ }
582
+ });
583
+ });
584
+ };
585
+ return Client;
354
586
  }());
355
- exports.Chirpier = Chirpier;
356
- /**
357
- * Decodes a base64url encoded string.
358
- * @param str - The base64url encoded string to decode.
359
- * @returns The decoded string.
360
- */
361
- function base64UrlDecode(str) {
362
- // Replace '-' with '+' and '_' with '/'
363
- var base64 = str.replace(/-/g, "+").replace(/_/g, "/");
364
- // Pad the base64 string
365
- var padding = base64.length % 4;
366
- if (padding !== 0) {
367
- base64 += "=".repeat(4 - padding);
368
- }
369
- return js_base64_1.Base64.decode(base64);
587
+ exports.Client = Client;
588
+ var instance = null;
589
+ function createClient(config) {
590
+ if (config === void 0) { config = {}; }
591
+ return new Client(config);
370
592
  }
371
- /**
372
- * Validates if the provided token is a valid JWT.
373
- * @param token - The token to validate.
374
- * @returns True if valid, false otherwise.
375
- */
376
- function isValidJWT(token) {
377
- var parts = token.split(".");
378
- if (parts.length !== 3) {
379
- return false;
593
+ exports.createClient = createClient;
594
+ function isNodeEnvironment() {
595
+ return typeof process !== "undefined" && !!(process.versions && process.versions.node);
596
+ }
597
+ function isValidAPIKey(token) {
598
+ return token.startsWith("chp_") && token.length > "chp_".length;
599
+ }
600
+ function loadDotEnvKey() {
601
+ if (!isNodeEnvironment()) {
602
+ return undefined;
380
603
  }
381
604
  try {
382
- var header = JSON.parse(base64UrlDecode(parts[0]));
383
- var payload = JSON.parse(base64UrlDecode(parts[1]));
384
- return typeof header === "object" && typeof payload === "object";
605
+ dotenv_1.default.config({ path: ".env", override: false });
385
606
  }
386
- catch (error) {
387
- console.error("Failed to validate JWT:", error);
388
- return false;
607
+ catch (_a) {
608
+ return undefined;
389
609
  }
610
+ var envKey = process.env.CHIRPIER_API_KEY;
611
+ if (typeof envKey !== "string") {
612
+ return undefined;
613
+ }
614
+ var trimmedKey = envKey.trim();
615
+ return trimmedKey.length > 0 ? trimmedKey : undefined;
616
+ }
617
+ function resolveAPIKey(providedKey) {
618
+ if (typeof providedKey === "string" && providedKey.trim().length > 0) {
619
+ return providedKey.trim();
620
+ }
621
+ if (typeof process !== "undefined" && process.env && typeof process.env.CHIRPIER_API_KEY === "string") {
622
+ var envKey = process.env.CHIRPIER_API_KEY.trim();
623
+ if (envKey.length > 0) {
624
+ return envKey;
625
+ }
626
+ }
627
+ return loadDotEnvKey();
390
628
  }
391
- /**
392
- * Initializes the Chirpier SDK.
393
- * @param options - Configuration options for the SDK.
394
- */
395
629
  function initialize(options) {
396
- if (!isValidJWT(options.key)) {
397
- throw new ChirpierError("Invalid API key: Not a valid JWT");
630
+ if (options === void 0) { options = {}; }
631
+ var resolvedKey = resolveAPIKey(options.key);
632
+ if (!resolvedKey) {
633
+ throw new ChirpierError("API key is required", "INVALID_KEY");
634
+ }
635
+ if (!isValidAPIKey(resolvedKey)) {
636
+ throw new ChirpierError("Invalid API key: must start with 'chp_'", "INVALID_KEY");
637
+ }
638
+ if (instance) {
639
+ return;
398
640
  }
399
641
  try {
400
- Chirpier.getInstance(options);
642
+ instance = new Client(__assign(__assign({}, options), { key: resolvedKey }));
401
643
  }
402
644
  catch (error) {
403
645
  if (error instanceof ChirpierError) {
404
- if (options.logLevel && options.logLevel >= LogLevel.Error) {
646
+ if (options.logLevel && options.logLevel >= 1 /* LogLevel.Error */) {
405
647
  console.error("Failed to initialize Chirpier SDK:", error.message);
406
648
  }
407
649
  }
408
650
  else {
409
- if (options.logLevel && options.logLevel >= LogLevel.Error) {
651
+ if (options.logLevel && options.logLevel >= 1 /* LogLevel.Error */) {
410
652
  console.error("An unexpected error occurred during Chirpier SDK initialization:", error);
411
653
  }
412
654
  }
@@ -414,17 +656,55 @@ function initialize(options) {
414
656
  }
415
657
  }
416
658
  exports.initialize = initialize;
417
- /**
418
- * Monitors an event using the Chirpier SDK.
419
- * @param event - The event to monitor.
420
- */
421
- function monitor(event) {
422
- var instance = Chirpier.getInstance({});
423
- if (!instance) {
424
- throw new ChirpierError("Chirpier SDK is not initialized. Please call initialize() first.");
425
- }
426
- instance.monitor(event).catch(function (error) {
427
- console.error("Error in monitor function:", error);
659
+ function logEvent(log) {
660
+ return __awaiter(this, void 0, void 0, function () {
661
+ return __generator(this, function (_a) {
662
+ switch (_a.label) {
663
+ case 0:
664
+ if (!instance) {
665
+ throw new ChirpierError("Chirpier SDK is not initialized. Please call initialize() first.", "NOT_INITIALIZED");
666
+ }
667
+ return [4 /*yield*/, instance.log(log)];
668
+ case 1:
669
+ _a.sent();
670
+ return [2 /*return*/];
671
+ }
672
+ });
673
+ });
674
+ }
675
+ exports.logEvent = logEvent;
676
+ function stop() {
677
+ return __awaiter(this, void 0, void 0, function () {
678
+ return __generator(this, function (_a) {
679
+ switch (_a.label) {
680
+ case 0:
681
+ if (!instance) {
682
+ return [2 /*return*/];
683
+ }
684
+ return [4 /*yield*/, instance.shutdown()];
685
+ case 1:
686
+ _a.sent();
687
+ instance = null;
688
+ return [2 /*return*/];
689
+ }
690
+ });
691
+ });
692
+ }
693
+ exports.stop = stop;
694
+ function flush() {
695
+ return __awaiter(this, void 0, void 0, function () {
696
+ return __generator(this, function (_a) {
697
+ switch (_a.label) {
698
+ case 0:
699
+ if (!instance) {
700
+ throw new ChirpierError("Chirpier SDK is not initialized. Please call initialize() first.", "NOT_INITIALIZED");
701
+ }
702
+ return [4 /*yield*/, instance.flush()];
703
+ case 1:
704
+ _a.sent();
705
+ return [2 /*return*/];
706
+ }
707
+ });
428
708
  });
429
709
  }
430
- exports.monitor = monitor;
710
+ exports.flush = flush;