@flareapp/js 1.0.1 → 2.0.0-rc.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
@@ -30,29 +30,43 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
- flare: () => flare,
34
- readLinesFromFile: () => readLinesFromFile
33
+ Flare: () => Flare,
34
+ flare: () => flare
35
35
  });
36
36
  module.exports = __toCommonJS(src_exports);
37
37
 
38
- // src/build.ts
39
- var build_default = {
40
- // Injected during build
41
- clientVersion: false ? "?" : '"1.0.1"',
42
- // Optionally injected by flare-vite-plugin-sourcemap-uploader
43
- flareJsKey: typeof FLARE_JS_KEY === "undefined" ? "" : FLARE_JS_KEY,
44
- sourcemapVersion: typeof FLARE_SOURCEMAP_VERSION === "undefined" ? "" : FLARE_SOURCEMAP_VERSION
45
- };
38
+ // src/env/index.ts
39
+ var CLIENT_VERSION = false ? "?" : '"2.0.0-rc.1"';
40
+ var KEY = typeof FLARE_JS_KEY === "undefined" ? "" : FLARE_JS_KEY;
41
+ var SOURCEMAP_VERSION = typeof FLARE_SOURCEMAP_VERSION === "undefined" ? "" : FLARE_SOURCEMAP_VERSION;
46
42
 
47
- // src/util/index.ts
43
+ // src/util/assert.ts
48
44
  function assert(value, message, debug) {
49
45
  if (debug && !value) {
50
- console.error(
51
- `Flare JavaScript client v${build_default.clientVersion}: ${message}`
52
- );
46
+ console.error(`Flare JavaScript client v${CLIENT_VERSION}: ${message}`);
53
47
  }
54
48
  return !!value;
55
49
  }
50
+
51
+ // src/util/assertKey.ts
52
+ function assertKey(key, debug) {
53
+ return assert(
54
+ key,
55
+ "The client was not yet initialised with an API key. Run client.light('<flare-project-key>') when you initialise your app. If you are running in dev mode and didn't run the light command on purpose, you can ignore this error.",
56
+ debug
57
+ );
58
+ }
59
+
60
+ // src/util/assertSolutionProvider.ts
61
+ function assertSolutionProvider(solutionProvider, debug) {
62
+ return assert("canSolve" in solutionProvider, "A solution provider without a [canSolve] property was added.", debug) && assert(
63
+ "getSolutions" in solutionProvider,
64
+ "A solution provider without a [getSolutions] property was added.",
65
+ debug
66
+ );
67
+ }
68
+
69
+ // src/util/flatJsonStringify.ts
56
70
  function flatJsonStringify(json) {
57
71
  let cache = [];
58
72
  const flattenedStringifiedJson = JSON.stringify(json, function(_, value) {
@@ -71,15 +85,45 @@ function flatJsonStringify(json) {
71
85
  cache = null;
72
86
  return flattenedStringifiedJson;
73
87
  }
74
- function now() {
75
- return Math.round(Date.now() / 1e3);
76
- }
88
+
89
+ // src/util/flattenOnce.ts
77
90
  function flattenOnce(array) {
78
91
  return array.reduce((flat, toFlatten) => {
79
92
  return flat.concat(toFlatten);
80
93
  }, []);
81
94
  }
82
95
 
96
+ // src/util/now.ts
97
+ function now() {
98
+ return Math.round(Date.now() / 1e3);
99
+ }
100
+
101
+ // src/api/Api.ts
102
+ var Api = class {
103
+ report(report, url, key, reportBrowserExtensionErrors) {
104
+ return fetch(url, {
105
+ method: "POST",
106
+ headers: {
107
+ "Content-Type": "application/json",
108
+ "X-Api-Token": key,
109
+ "X-Requested-With": "XMLHttpRequest",
110
+ "X-Report-Browser-Extension-Errors": JSON.stringify(reportBrowserExtensionErrors)
111
+ },
112
+ body: flatJsonStringify({
113
+ ...report,
114
+ key
115
+ })
116
+ }).then(
117
+ (response) => {
118
+ if (response.status !== 204) {
119
+ console.error(`Received response with status ${response.status} from Flare`);
120
+ }
121
+ },
122
+ (error) => console.error(error)
123
+ );
124
+ }
125
+ };
126
+
83
127
  // src/context/cookie.ts
84
128
  function cookie() {
85
129
  if (!window.document.cookie) {
@@ -121,7 +165,7 @@ function requestData() {
121
165
  return { request_data: { queryString } };
122
166
  }
123
167
 
124
- // src/context/index.ts
168
+ // src/context/collectContext.ts
125
169
  function collectContext(additionalContext) {
126
170
  if (typeof window === "undefined") {
127
171
  return additionalContext;
@@ -134,7 +178,33 @@ function collectContext(additionalContext) {
134
178
  };
135
179
  }
136
180
 
137
- // src/stacktrace/index.ts
181
+ // src/solutions/getSolutions.ts
182
+ function getSolutions(solutionProviders, error, extraSolutionParameters = {}) {
183
+ return new Promise((resolve) => {
184
+ const canSolves = solutionProviders.reduce(
185
+ (canSolves2, provider) => {
186
+ canSolves2.push(Promise.resolve(provider.canSolve(error, extraSolutionParameters)));
187
+ return canSolves2;
188
+ },
189
+ []
190
+ );
191
+ Promise.all(canSolves).then((resolvedCanSolves) => {
192
+ const solutionPromises = [];
193
+ resolvedCanSolves.forEach((canSolve, i) => {
194
+ if (canSolve) {
195
+ solutionPromises.push(
196
+ Promise.resolve(solutionProviders[i].getSolutions(error, extraSolutionParameters))
197
+ );
198
+ }
199
+ });
200
+ Promise.all(solutionPromises).then((solutions) => {
201
+ resolve(flattenOnce(solutions));
202
+ });
203
+ });
204
+ });
205
+ }
206
+
207
+ // src/stacktrace/createStackTrace.ts
138
208
  var import_error_stack_parser = __toESM(require("error-stack-parser"));
139
209
 
140
210
  // src/stacktrace/fileReader.ts
@@ -158,9 +228,7 @@ function getCodeSnippet(url, lineNumber, columnNumber) {
158
228
  trimmedColumnNumber: null
159
229
  });
160
230
  }
161
- return resolve(
162
- readLinesFromFile(fileText, lineNumber, columnNumber)
163
- );
231
+ return resolve(readLinesFromFile(fileText, lineNumber, columnNumber));
164
232
  });
165
233
  });
166
234
  }
@@ -190,9 +258,7 @@ function readLinesFromFile(fileText, lineNumber, columnNumber, maxSnippetLineLen
190
258
  maxSnippetLineLength
191
259
  );
192
260
  if (displayLine === lineNumber) {
193
- trimmedColumnNumber = Math.round(
194
- maxSnippetLineLength / 2
195
- );
261
+ trimmedColumnNumber = Math.round(maxSnippetLineLength / 2);
196
262
  }
197
263
  continue;
198
264
  }
@@ -205,16 +271,12 @@ function readLinesFromFile(fileText, lineNumber, columnNumber, maxSnippetLineLen
205
271
  return { codeSnippet, trimmedColumnNumber };
206
272
  }
207
273
 
208
- // src/stacktrace/index.ts
209
- function createStackTrace(error) {
274
+ // src/stacktrace/createStackTrace.ts
275
+ function createStackTrace(error, debug) {
210
276
  return new Promise((resolve) => {
211
277
  if (!hasStack(error)) {
212
- assert(
213
- false,
214
- "Couldn't generate stacktrace of below error:",
215
- flare.debug
216
- );
217
- if (flare.debug) {
278
+ assert(false, "Couldn't generate stacktrace of below error:", debug);
279
+ if (debug) {
218
280
  console.error(error);
219
281
  }
220
282
  return resolve([
@@ -234,11 +296,7 @@ function createStackTrace(error) {
234
296
  Promise.all(
235
297
  import_error_stack_parser.default.parse(error).map((frame) => {
236
298
  return new Promise((resolve2) => {
237
- getCodeSnippet(
238
- frame.fileName,
239
- frame.lineNumber,
240
- frame.columnNumber
241
- ).then((snippet) => {
299
+ getCodeSnippet(frame.fileName, frame.lineNumber, frame.columnNumber).then((snippet) => {
242
300
  resolve2({
243
301
  line_number: frame.lineNumber || 1,
244
302
  column_number: frame.columnNumber || 1,
@@ -258,93 +316,56 @@ function hasStack(err) {
258
316
  return !!err && (!!err.stack || !!err.stacktrace || !!err["opera#sourceloc"]) && typeof (err.stack || err.stacktrace || err["opera#sourceloc"]) === "string" && err.stack !== `${err.name}: ${err.message}`;
259
317
  }
260
318
 
261
- // src/solutions/index.ts
262
- function getSolutions(solutionProviders, error, extraSolutionParameters = {}) {
263
- return new Promise((resolve) => {
264
- const canSolves = solutionProviders.reduce(
265
- (canSolves2, provider) => {
266
- canSolves2.push(
267
- Promise.resolve(
268
- provider.canSolve(error, extraSolutionParameters)
269
- )
270
- );
271
- return canSolves2;
272
- },
273
- []
274
- );
275
- Promise.all(canSolves).then((resolvedCanSolves) => {
276
- const solutionPromises = [];
277
- resolvedCanSolves.forEach((canSolve, i) => {
278
- if (canSolve) {
279
- solutionPromises.push(
280
- Promise.resolve(
281
- solutionProviders[i].getSolutions(
282
- error,
283
- extraSolutionParameters
284
- )
285
- )
286
- );
287
- }
288
- });
289
- Promise.all(solutionPromises).then((solutions) => {
290
- resolve(flattenOnce(solutions));
291
- });
292
- });
293
- });
294
- }
295
-
296
- // src/FlareClient.ts
297
- var FlareClient = class {
298
- constructor() {
299
- this.version = build_default.clientVersion;
319
+ // src/Flare.ts
320
+ var Flare = class {
321
+ constructor(http = new Api()) {
322
+ this.http = http;
300
323
  this.config = {
301
- key: "",
302
- reportingUrl: "https://reporting.flareapp.io/api/reports",
324
+ key: KEY,
325
+ version: CLIENT_VERSION,
326
+ sourcemapVersion: SOURCEMAP_VERSION,
327
+ stage: "",
303
328
  maxGlowsPerReport: 30,
304
- maxReportsPerMinute: 500
329
+ reportingUrl: "https://reporting.flareapp.io/api/reports",
330
+ reportBrowserExtensionErrors: false,
331
+ debug: false,
332
+ beforeEvaluate: (error) => error,
333
+ beforeSubmit: (report) => report
305
334
  };
306
335
  this.glows = [];
307
336
  this.context = { context: {} };
308
- this.beforeEvaluate = (error) => error;
309
- this.beforeSubmit = (report) => report;
310
- this.reportedErrorsTimestamps = [];
311
337
  this.solutionProviders = [];
312
- this.sourcemapVersion = build_default.sourcemapVersion;
313
- this.debug = false;
314
- this.stage = void 0;
315
338
  }
316
- light(key = build_default.flareJsKey, debug = false) {
317
- this.debug = debug;
318
- if (!assert(
319
- key && typeof key === "string",
320
- "An empty or incorrect Flare key was passed, errors will not be reported.",
321
- this.debug
322
- ) || !assert(
323
- Promise,
324
- "ES6 promises are not supported in this environment, errors will not be reported.",
325
- this.debug
326
- )) {
327
- return this;
328
- }
339
+ light(key = KEY, debug = false) {
329
340
  this.config.key = key;
341
+ this.config.debug = debug;
330
342
  return this;
331
343
  }
332
- glow(name, level = "info", metaData = []) {
344
+ configure(config) {
345
+ this.config = { ...this.config, ...config };
346
+ return this;
347
+ }
348
+ test() {
349
+ return this.report(new Error("The Flare client is set up correctly!"));
350
+ }
351
+ glow(name, level = "info", data = []) {
333
352
  const time = now();
334
353
  this.glows.push({
335
354
  name,
336
355
  message_level: level,
337
- meta_data: metaData,
356
+ meta_data: data,
338
357
  time,
339
358
  microtime: time
340
359
  });
341
360
  if (this.glows.length > this.config.maxGlowsPerReport) {
342
- this.glows = this.glows.slice(
343
- this.glows.length - this.config.maxGlowsPerReport
344
- );
361
+ this.glows = this.glows.slice(this.glows.length - this.config.maxGlowsPerReport);
345
362
  }
346
363
  return this;
347
364
  }
365
+ clearGlows() {
366
+ this.glows = [];
367
+ return this;
368
+ }
348
369
  addContext(name, value) {
349
370
  this.context.context[name] = value;
350
371
  return this;
@@ -353,74 +374,54 @@ var FlareClient = class {
353
374
  this.context[groupName] = value;
354
375
  return this;
355
376
  }
356
- registerSolutionProvider(provider) {
357
- if (!assert(
358
- "canSolve" in provider,
359
- "A solution provider without a [canSolve] property was added.",
360
- this.debug
361
- ) || !assert(
362
- "getSolutions" in provider,
363
- "A solution provider without a [getSolutions] property was added.",
364
- this.debug
365
- )) {
377
+ registerSolutionProvider(solutionProvider) {
378
+ if (!assertSolutionProvider(solutionProvider, this.config.debug)) {
366
379
  return this;
367
380
  }
368
- this.solutionProviders.push(provider);
381
+ this.solutionProviders.push(solutionProvider);
369
382
  return this;
370
383
  }
371
- reportMessage(message, context = {}, exceptionClass = "Log") {
372
- const seenAt = now();
373
- createStackTrace(Error()).then((stacktrace) => {
374
- stacktrace.shift();
375
- const report = {
376
- notifier: `Flare JavaScript client v${build_default.clientVersion}`,
377
- exception_class: exceptionClass,
378
- seen_at: seenAt,
379
- message,
380
- language: "javascript",
381
- glows: this.glows,
382
- context: collectContext({ ...context, ...this.context }),
383
- stacktrace,
384
- sourcemap_version_id: this.sourcemapVersion,
385
- solutions: [],
386
- stage: this.stage
387
- };
388
- this.sendReport(report);
389
- });
384
+ async report(error, context = {}, extraSolutionParameters = {}) {
385
+ const errorToReport = await this.config.beforeEvaluate(error);
386
+ if (!errorToReport) {
387
+ return;
388
+ }
389
+ const report = await this.createReportFromError(error, context, extraSolutionParameters);
390
+ if (!report) {
391
+ return;
392
+ }
393
+ return this.sendReport(report);
390
394
  }
391
- report(error, context = {}, extraSolutionParameters = {}) {
392
- Promise.resolve(this.beforeEvaluate(error)).then(
393
- (reportReadyForEvaluation) => {
394
- if (!reportReadyForEvaluation) {
395
- return;
396
- }
397
- this.createReport(error, context, extraSolutionParameters).then(
398
- (report) => report ? this.sendReport(report) : {}
399
- );
400
- }
401
- );
395
+ async reportMessage(message, context = {}, exceptionClass = "Log") {
396
+ const stackTrace = await createStackTrace(Error(), this.config.debug);
397
+ stackTrace.shift();
398
+ this.sendReport({
399
+ notifier: `Flare JavaScript client v${CLIENT_VERSION}`,
400
+ exception_class: exceptionClass,
401
+ seen_at: now(),
402
+ message,
403
+ language: "javascript",
404
+ glows: this.glows,
405
+ context: collectContext({ ...context, ...this.context }),
406
+ stacktrace: stackTrace,
407
+ sourcemap_version_id: this.config.sourcemapVersion,
408
+ solutions: [],
409
+ stage: this.config.stage
410
+ });
402
411
  }
403
- createReport(error, context = {}, extraSolutionParameters = {}) {
404
- if (!assert(error, "No error provided.", this.debug)) {
412
+ createReportFromError(error, context = {}, extraSolutionParameters = {}) {
413
+ if (!assert(error, "No error provided.", this.config.debug)) {
405
414
  return Promise.resolve(false);
406
415
  }
407
416
  const seenAt = now();
408
417
  return Promise.all([
409
- getSolutions(
410
- this.solutionProviders,
411
- error,
412
- extraSolutionParameters
413
- ),
414
- createStackTrace(error)
418
+ getSolutions(this.solutionProviders, error, extraSolutionParameters),
419
+ createStackTrace(error, this.config.debug)
415
420
  ]).then((result) => {
416
421
  const [solutions, stacktrace] = result;
417
- assert(
418
- stacktrace.length,
419
- "Couldn't generate stacktrace of this error: " + error,
420
- this.debug
421
- );
422
+ assert(stacktrace.length, "Couldn't generate stacktrace of this error: " + error, this.config.debug);
422
423
  return {
423
- notifier: `Flare JavaScript client v${build_default.clientVersion}`,
424
+ notifier: `Flare JavaScript client v${CLIENT_VERSION}`,
424
425
  exception_class: error.constructor && error.constructor.name ? error.constructor.name : "undefined",
425
426
  seen_at: seenAt,
426
427
  message: error.message,
@@ -428,69 +429,40 @@ var FlareClient = class {
428
429
  glows: this.glows,
429
430
  context: collectContext({ ...context, ...this.context }),
430
431
  stacktrace,
431
- sourcemap_version_id: this.sourcemapVersion,
432
+ sourcemap_version_id: this.config.sourcemapVersion,
432
433
  solutions,
433
- stage: this.stage
434
+ stage: this.config.stage
434
435
  };
435
436
  });
436
437
  }
437
- sendReport(report) {
438
- if (!assert(
439
- this.config.key,
440
- "The client was not yet initialised with an API key. Run client.light('<flare-project-key>') when you initialise your app. If you are running in dev mode and didn't run the light command on purpose, you can ignore this error.",
441
- this.debug
442
- )) {
438
+ async sendReport(report) {
439
+ if (!assertKey(this.config.key, this.config.debug)) {
443
440
  return;
444
441
  }
445
- if (this.maxReportsPerMinuteReached()) {
442
+ const reportToSubmit = await this.config.beforeSubmit(report);
443
+ if (!reportToSubmit) {
446
444
  return;
447
445
  }
448
- Promise.resolve(this.beforeSubmit(report)).then(
449
- (reportReadyForSubmit) => {
450
- if (!reportReadyForSubmit) {
451
- return;
452
- }
453
- fetch(this.config.reportingUrl, {
454
- method: "POST",
455
- headers: {
456
- "Content-Type": "application/json",
457
- "X-Requested-With": "XMLHttpRequest",
458
- "x-api-token": this.config.key
459
- },
460
- body: flatJsonStringify({
461
- ...reportReadyForSubmit,
462
- key: this.config.key
463
- })
464
- }).then(
465
- (response) => {
466
- if (response.status !== 204) {
467
- console.error(
468
- `Received response with status ${response.status} from Flare`
469
- );
470
- }
471
- },
472
- (error) => console.error(error)
473
- );
474
- this.reportedErrorsTimestamps.push(Date.now());
475
- }
446
+ return this.http.report(
447
+ reportToSubmit,
448
+ this.config.reportingUrl,
449
+ this.config.key,
450
+ this.config.reportBrowserExtensionErrors
476
451
  );
477
452
  }
478
- maxReportsPerMinuteReached() {
479
- if (this.reportedErrorsTimestamps.length >= this.config.maxReportsPerMinute) {
480
- const nErrorsBack = this.reportedErrorsTimestamps[this.reportedErrorsTimestamps.length - this.config.maxReportsPerMinute];
481
- if (nErrorsBack > Date.now() - 60 * 1e3) {
482
- return true;
483
- }
484
- }
485
- return false;
453
+ // Deprecated, the following methods exist for backwards compatibility.
454
+ set beforeEvaluate(beforeEvaluate) {
455
+ this.config.beforeEvaluate = beforeEvaluate ?? "";
486
456
  }
487
- test() {
488
- this.report(new Error("The Flare client is set up correctly!"));
489
- return this;
457
+ set beforeSubmit(beforeSubmit) {
458
+ this.config.beforeSubmit = beforeSubmit ?? "";
459
+ }
460
+ set stage(stage) {
461
+ this.config.stage = stage ?? "";
490
462
  }
491
463
  };
492
464
 
493
- // src/browserClient/index.ts
465
+ // src/browser/catchWindowErrors.ts
494
466
  function catchWindowErrors() {
495
467
  if (typeof window === "undefined") {
496
468
  return;
@@ -520,13 +492,13 @@ function catchWindowErrors() {
520
492
  }
521
493
 
522
494
  // src/index.ts
523
- var flare = new FlareClient();
495
+ var flare = new Flare();
524
496
  if (typeof window !== "undefined" && window) {
525
497
  window.flare = flare;
498
+ catchWindowErrors();
526
499
  }
527
- catchWindowErrors();
528
500
  // Annotate the CommonJS export names for ESM import in node:
529
501
  0 && (module.exports = {
530
- flare,
531
- readLinesFromFile
502
+ Flare,
503
+ flare
532
504
  });