@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/README.md +184 -108
- package/dist/__tests__/chirpier.test.js +435 -100
- package/dist/constants.d.ts +7 -6
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +5 -4
- package/dist/index.d.ts +129 -56
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +483 -203
- package/package.json +5 -5
- package/src/__tests__/chirpier.test.ts +296 -92
- package/src/constants.ts +7 -6
- package/src/index.ts +492 -206
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 =
|
|
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.
|
|
67
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
115
|
-
|
|
116
|
-
throw new ChirpierError("
|
|
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
|
-
|
|
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 =
|
|
121
|
-
this.timeout =
|
|
122
|
-
this.batchSize =
|
|
123
|
-
this.flushDelay =
|
|
146
|
+
this.retries = retries;
|
|
147
|
+
this.timeout = timeout;
|
|
148
|
+
this.batchSize = batchSize;
|
|
149
|
+
this.flushDelay = flushDelay;
|
|
124
150
|
this.logLevel = logLevel;
|
|
125
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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
|
-
|
|
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
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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.
|
|
185
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
236
|
-
|
|
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.
|
|
240
|
-
|
|
241
|
-
this.
|
|
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 (
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
272
|
-
|
|
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
|
-
|
|
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.
|
|
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,
|
|
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
|
-
|
|
328
|
-
|
|
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 (
|
|
334
|
-
|
|
369
|
+
if (this.flushTimeoutId) {
|
|
370
|
+
clearTimeout(this.flushTimeoutId);
|
|
371
|
+
this.flushTimeoutId = null;
|
|
335
372
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
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
|
-
|
|
341
|
-
return [4 /*yield*/,
|
|
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
|
-
|
|
353
|
-
|
|
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.
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
function
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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
|
|
602
|
+
return (0, uuid_1.v7)();
|
|
370
603
|
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
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
|
-
|
|
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 (
|
|
387
|
-
|
|
388
|
-
|
|
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 (
|
|
397
|
-
|
|
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
|
-
|
|
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
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
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;
|