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