@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.mjs CHANGED
@@ -1,21 +1,35 @@
1
- // src/build.ts
2
- var build_default = {
3
- // Injected during build
4
- clientVersion: false ? "?" : '"1.0.1"',
5
- // Optionally injected by flare-vite-plugin-sourcemap-uploader
6
- flareJsKey: typeof FLARE_JS_KEY === "undefined" ? "" : FLARE_JS_KEY,
7
- sourcemapVersion: typeof FLARE_SOURCEMAP_VERSION === "undefined" ? "" : FLARE_SOURCEMAP_VERSION
8
- };
1
+ // src/env/index.ts
2
+ var CLIENT_VERSION = false ? "?" : '"2.0.0-rc.1"';
3
+ var KEY = typeof FLARE_JS_KEY === "undefined" ? "" : FLARE_JS_KEY;
4
+ var SOURCEMAP_VERSION = typeof FLARE_SOURCEMAP_VERSION === "undefined" ? "" : FLARE_SOURCEMAP_VERSION;
9
5
 
10
- // src/util/index.ts
6
+ // src/util/assert.ts
11
7
  function assert(value, message, debug) {
12
8
  if (debug && !value) {
13
- console.error(
14
- `Flare JavaScript client v${build_default.clientVersion}: ${message}`
15
- );
9
+ console.error(`Flare JavaScript client v${CLIENT_VERSION}: ${message}`);
16
10
  }
17
11
  return !!value;
18
12
  }
13
+
14
+ // src/util/assertKey.ts
15
+ function assertKey(key, debug) {
16
+ return assert(
17
+ key,
18
+ "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.",
19
+ debug
20
+ );
21
+ }
22
+
23
+ // src/util/assertSolutionProvider.ts
24
+ function assertSolutionProvider(solutionProvider, debug) {
25
+ return assert("canSolve" in solutionProvider, "A solution provider without a [canSolve] property was added.", debug) && assert(
26
+ "getSolutions" in solutionProvider,
27
+ "A solution provider without a [getSolutions] property was added.",
28
+ debug
29
+ );
30
+ }
31
+
32
+ // src/util/flatJsonStringify.ts
19
33
  function flatJsonStringify(json) {
20
34
  let cache = [];
21
35
  const flattenedStringifiedJson = JSON.stringify(json, function(_, value) {
@@ -34,15 +48,45 @@ function flatJsonStringify(json) {
34
48
  cache = null;
35
49
  return flattenedStringifiedJson;
36
50
  }
37
- function now() {
38
- return Math.round(Date.now() / 1e3);
39
- }
51
+
52
+ // src/util/flattenOnce.ts
40
53
  function flattenOnce(array) {
41
54
  return array.reduce((flat, toFlatten) => {
42
55
  return flat.concat(toFlatten);
43
56
  }, []);
44
57
  }
45
58
 
59
+ // src/util/now.ts
60
+ function now() {
61
+ return Math.round(Date.now() / 1e3);
62
+ }
63
+
64
+ // src/api/Api.ts
65
+ var Api = class {
66
+ report(report, url, key, reportBrowserExtensionErrors) {
67
+ return fetch(url, {
68
+ method: "POST",
69
+ headers: {
70
+ "Content-Type": "application/json",
71
+ "X-Api-Token": key,
72
+ "X-Requested-With": "XMLHttpRequest",
73
+ "X-Report-Browser-Extension-Errors": JSON.stringify(reportBrowserExtensionErrors)
74
+ },
75
+ body: flatJsonStringify({
76
+ ...report,
77
+ key
78
+ })
79
+ }).then(
80
+ (response) => {
81
+ if (response.status !== 204) {
82
+ console.error(`Received response with status ${response.status} from Flare`);
83
+ }
84
+ },
85
+ (error) => console.error(error)
86
+ );
87
+ }
88
+ };
89
+
46
90
  // src/context/cookie.ts
47
91
  function cookie() {
48
92
  if (!window.document.cookie) {
@@ -84,7 +128,7 @@ function requestData() {
84
128
  return { request_data: { queryString } };
85
129
  }
86
130
 
87
- // src/context/index.ts
131
+ // src/context/collectContext.ts
88
132
  function collectContext(additionalContext) {
89
133
  if (typeof window === "undefined") {
90
134
  return additionalContext;
@@ -97,7 +141,33 @@ function collectContext(additionalContext) {
97
141
  };
98
142
  }
99
143
 
100
- // src/stacktrace/index.ts
144
+ // src/solutions/getSolutions.ts
145
+ function getSolutions(solutionProviders, error, extraSolutionParameters = {}) {
146
+ return new Promise((resolve) => {
147
+ const canSolves = solutionProviders.reduce(
148
+ (canSolves2, provider) => {
149
+ canSolves2.push(Promise.resolve(provider.canSolve(error, extraSolutionParameters)));
150
+ return canSolves2;
151
+ },
152
+ []
153
+ );
154
+ Promise.all(canSolves).then((resolvedCanSolves) => {
155
+ const solutionPromises = [];
156
+ resolvedCanSolves.forEach((canSolve, i) => {
157
+ if (canSolve) {
158
+ solutionPromises.push(
159
+ Promise.resolve(solutionProviders[i].getSolutions(error, extraSolutionParameters))
160
+ );
161
+ }
162
+ });
163
+ Promise.all(solutionPromises).then((solutions) => {
164
+ resolve(flattenOnce(solutions));
165
+ });
166
+ });
167
+ });
168
+ }
169
+
170
+ // src/stacktrace/createStackTrace.ts
101
171
  import ErrorStackParser from "error-stack-parser";
102
172
 
103
173
  // src/stacktrace/fileReader.ts
@@ -121,9 +191,7 @@ function getCodeSnippet(url, lineNumber, columnNumber) {
121
191
  trimmedColumnNumber: null
122
192
  });
123
193
  }
124
- return resolve(
125
- readLinesFromFile(fileText, lineNumber, columnNumber)
126
- );
194
+ return resolve(readLinesFromFile(fileText, lineNumber, columnNumber));
127
195
  });
128
196
  });
129
197
  }
@@ -153,9 +221,7 @@ function readLinesFromFile(fileText, lineNumber, columnNumber, maxSnippetLineLen
153
221
  maxSnippetLineLength
154
222
  );
155
223
  if (displayLine === lineNumber) {
156
- trimmedColumnNumber = Math.round(
157
- maxSnippetLineLength / 2
158
- );
224
+ trimmedColumnNumber = Math.round(maxSnippetLineLength / 2);
159
225
  }
160
226
  continue;
161
227
  }
@@ -168,16 +234,12 @@ function readLinesFromFile(fileText, lineNumber, columnNumber, maxSnippetLineLen
168
234
  return { codeSnippet, trimmedColumnNumber };
169
235
  }
170
236
 
171
- // src/stacktrace/index.ts
172
- function createStackTrace(error) {
237
+ // src/stacktrace/createStackTrace.ts
238
+ function createStackTrace(error, debug) {
173
239
  return new Promise((resolve) => {
174
240
  if (!hasStack(error)) {
175
- assert(
176
- false,
177
- "Couldn't generate stacktrace of below error:",
178
- flare.debug
179
- );
180
- if (flare.debug) {
241
+ assert(false, "Couldn't generate stacktrace of below error:", debug);
242
+ if (debug) {
181
243
  console.error(error);
182
244
  }
183
245
  return resolve([
@@ -197,11 +259,7 @@ function createStackTrace(error) {
197
259
  Promise.all(
198
260
  ErrorStackParser.parse(error).map((frame) => {
199
261
  return new Promise((resolve2) => {
200
- getCodeSnippet(
201
- frame.fileName,
202
- frame.lineNumber,
203
- frame.columnNumber
204
- ).then((snippet) => {
262
+ getCodeSnippet(frame.fileName, frame.lineNumber, frame.columnNumber).then((snippet) => {
205
263
  resolve2({
206
264
  line_number: frame.lineNumber || 1,
207
265
  column_number: frame.columnNumber || 1,
@@ -221,93 +279,56 @@ function hasStack(err) {
221
279
  return !!err && (!!err.stack || !!err.stacktrace || !!err["opera#sourceloc"]) && typeof (err.stack || err.stacktrace || err["opera#sourceloc"]) === "string" && err.stack !== `${err.name}: ${err.message}`;
222
280
  }
223
281
 
224
- // src/solutions/index.ts
225
- function getSolutions(solutionProviders, error, extraSolutionParameters = {}) {
226
- return new Promise((resolve) => {
227
- const canSolves = solutionProviders.reduce(
228
- (canSolves2, provider) => {
229
- canSolves2.push(
230
- Promise.resolve(
231
- provider.canSolve(error, extraSolutionParameters)
232
- )
233
- );
234
- return canSolves2;
235
- },
236
- []
237
- );
238
- Promise.all(canSolves).then((resolvedCanSolves) => {
239
- const solutionPromises = [];
240
- resolvedCanSolves.forEach((canSolve, i) => {
241
- if (canSolve) {
242
- solutionPromises.push(
243
- Promise.resolve(
244
- solutionProviders[i].getSolutions(
245
- error,
246
- extraSolutionParameters
247
- )
248
- )
249
- );
250
- }
251
- });
252
- Promise.all(solutionPromises).then((solutions) => {
253
- resolve(flattenOnce(solutions));
254
- });
255
- });
256
- });
257
- }
258
-
259
- // src/FlareClient.ts
260
- var FlareClient = class {
261
- constructor() {
262
- this.version = build_default.clientVersion;
282
+ // src/Flare.ts
283
+ var Flare = class {
284
+ constructor(http = new Api()) {
285
+ this.http = http;
263
286
  this.config = {
264
- key: "",
265
- reportingUrl: "https://reporting.flareapp.io/api/reports",
287
+ key: KEY,
288
+ version: CLIENT_VERSION,
289
+ sourcemapVersion: SOURCEMAP_VERSION,
290
+ stage: "",
266
291
  maxGlowsPerReport: 30,
267
- maxReportsPerMinute: 500
292
+ reportingUrl: "https://reporting.flareapp.io/api/reports",
293
+ reportBrowserExtensionErrors: false,
294
+ debug: false,
295
+ beforeEvaluate: (error) => error,
296
+ beforeSubmit: (report) => report
268
297
  };
269
298
  this.glows = [];
270
299
  this.context = { context: {} };
271
- this.beforeEvaluate = (error) => error;
272
- this.beforeSubmit = (report) => report;
273
- this.reportedErrorsTimestamps = [];
274
300
  this.solutionProviders = [];
275
- this.sourcemapVersion = build_default.sourcemapVersion;
276
- this.debug = false;
277
- this.stage = void 0;
278
301
  }
279
- light(key = build_default.flareJsKey, debug = false) {
280
- this.debug = debug;
281
- if (!assert(
282
- key && typeof key === "string",
283
- "An empty or incorrect Flare key was passed, errors will not be reported.",
284
- this.debug
285
- ) || !assert(
286
- Promise,
287
- "ES6 promises are not supported in this environment, errors will not be reported.",
288
- this.debug
289
- )) {
290
- return this;
291
- }
302
+ light(key = KEY, debug = false) {
292
303
  this.config.key = key;
304
+ this.config.debug = debug;
293
305
  return this;
294
306
  }
295
- glow(name, level = "info", metaData = []) {
307
+ configure(config) {
308
+ this.config = { ...this.config, ...config };
309
+ return this;
310
+ }
311
+ test() {
312
+ return this.report(new Error("The Flare client is set up correctly!"));
313
+ }
314
+ glow(name, level = "info", data = []) {
296
315
  const time = now();
297
316
  this.glows.push({
298
317
  name,
299
318
  message_level: level,
300
- meta_data: metaData,
319
+ meta_data: data,
301
320
  time,
302
321
  microtime: time
303
322
  });
304
323
  if (this.glows.length > this.config.maxGlowsPerReport) {
305
- this.glows = this.glows.slice(
306
- this.glows.length - this.config.maxGlowsPerReport
307
- );
324
+ this.glows = this.glows.slice(this.glows.length - this.config.maxGlowsPerReport);
308
325
  }
309
326
  return this;
310
327
  }
328
+ clearGlows() {
329
+ this.glows = [];
330
+ return this;
331
+ }
311
332
  addContext(name, value) {
312
333
  this.context.context[name] = value;
313
334
  return this;
@@ -316,74 +337,54 @@ var FlareClient = class {
316
337
  this.context[groupName] = value;
317
338
  return this;
318
339
  }
319
- registerSolutionProvider(provider) {
320
- if (!assert(
321
- "canSolve" in provider,
322
- "A solution provider without a [canSolve] property was added.",
323
- this.debug
324
- ) || !assert(
325
- "getSolutions" in provider,
326
- "A solution provider without a [getSolutions] property was added.",
327
- this.debug
328
- )) {
340
+ registerSolutionProvider(solutionProvider) {
341
+ if (!assertSolutionProvider(solutionProvider, this.config.debug)) {
329
342
  return this;
330
343
  }
331
- this.solutionProviders.push(provider);
344
+ this.solutionProviders.push(solutionProvider);
332
345
  return this;
333
346
  }
334
- reportMessage(message, context = {}, exceptionClass = "Log") {
335
- const seenAt = now();
336
- createStackTrace(Error()).then((stacktrace) => {
337
- stacktrace.shift();
338
- const report = {
339
- notifier: `Flare JavaScript client v${build_default.clientVersion}`,
340
- exception_class: exceptionClass,
341
- seen_at: seenAt,
342
- message,
343
- language: "javascript",
344
- glows: this.glows,
345
- context: collectContext({ ...context, ...this.context }),
346
- stacktrace,
347
- sourcemap_version_id: this.sourcemapVersion,
348
- solutions: [],
349
- stage: this.stage
350
- };
351
- this.sendReport(report);
352
- });
347
+ async report(error, context = {}, extraSolutionParameters = {}) {
348
+ const errorToReport = await this.config.beforeEvaluate(error);
349
+ if (!errorToReport) {
350
+ return;
351
+ }
352
+ const report = await this.createReportFromError(error, context, extraSolutionParameters);
353
+ if (!report) {
354
+ return;
355
+ }
356
+ return this.sendReport(report);
353
357
  }
354
- report(error, context = {}, extraSolutionParameters = {}) {
355
- Promise.resolve(this.beforeEvaluate(error)).then(
356
- (reportReadyForEvaluation) => {
357
- if (!reportReadyForEvaluation) {
358
- return;
359
- }
360
- this.createReport(error, context, extraSolutionParameters).then(
361
- (report) => report ? this.sendReport(report) : {}
362
- );
363
- }
364
- );
358
+ async reportMessage(message, context = {}, exceptionClass = "Log") {
359
+ const stackTrace = await createStackTrace(Error(), this.config.debug);
360
+ stackTrace.shift();
361
+ this.sendReport({
362
+ notifier: `Flare JavaScript client v${CLIENT_VERSION}`,
363
+ exception_class: exceptionClass,
364
+ seen_at: now(),
365
+ message,
366
+ language: "javascript",
367
+ glows: this.glows,
368
+ context: collectContext({ ...context, ...this.context }),
369
+ stacktrace: stackTrace,
370
+ sourcemap_version_id: this.config.sourcemapVersion,
371
+ solutions: [],
372
+ stage: this.config.stage
373
+ });
365
374
  }
366
- createReport(error, context = {}, extraSolutionParameters = {}) {
367
- if (!assert(error, "No error provided.", this.debug)) {
375
+ createReportFromError(error, context = {}, extraSolutionParameters = {}) {
376
+ if (!assert(error, "No error provided.", this.config.debug)) {
368
377
  return Promise.resolve(false);
369
378
  }
370
379
  const seenAt = now();
371
380
  return Promise.all([
372
- getSolutions(
373
- this.solutionProviders,
374
- error,
375
- extraSolutionParameters
376
- ),
377
- createStackTrace(error)
381
+ getSolutions(this.solutionProviders, error, extraSolutionParameters),
382
+ createStackTrace(error, this.config.debug)
378
383
  ]).then((result) => {
379
384
  const [solutions, stacktrace] = result;
380
- assert(
381
- stacktrace.length,
382
- "Couldn't generate stacktrace of this error: " + error,
383
- this.debug
384
- );
385
+ assert(stacktrace.length, "Couldn't generate stacktrace of this error: " + error, this.config.debug);
385
386
  return {
386
- notifier: `Flare JavaScript client v${build_default.clientVersion}`,
387
+ notifier: `Flare JavaScript client v${CLIENT_VERSION}`,
387
388
  exception_class: error.constructor && error.constructor.name ? error.constructor.name : "undefined",
388
389
  seen_at: seenAt,
389
390
  message: error.message,
@@ -391,69 +392,40 @@ var FlareClient = class {
391
392
  glows: this.glows,
392
393
  context: collectContext({ ...context, ...this.context }),
393
394
  stacktrace,
394
- sourcemap_version_id: this.sourcemapVersion,
395
+ sourcemap_version_id: this.config.sourcemapVersion,
395
396
  solutions,
396
- stage: this.stage
397
+ stage: this.config.stage
397
398
  };
398
399
  });
399
400
  }
400
- sendReport(report) {
401
- if (!assert(
402
- this.config.key,
403
- "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.",
404
- this.debug
405
- )) {
401
+ async sendReport(report) {
402
+ if (!assertKey(this.config.key, this.config.debug)) {
406
403
  return;
407
404
  }
408
- if (this.maxReportsPerMinuteReached()) {
405
+ const reportToSubmit = await this.config.beforeSubmit(report);
406
+ if (!reportToSubmit) {
409
407
  return;
410
408
  }
411
- Promise.resolve(this.beforeSubmit(report)).then(
412
- (reportReadyForSubmit) => {
413
- if (!reportReadyForSubmit) {
414
- return;
415
- }
416
- fetch(this.config.reportingUrl, {
417
- method: "POST",
418
- headers: {
419
- "Content-Type": "application/json",
420
- "X-Requested-With": "XMLHttpRequest",
421
- "x-api-token": this.config.key
422
- },
423
- body: flatJsonStringify({
424
- ...reportReadyForSubmit,
425
- key: this.config.key
426
- })
427
- }).then(
428
- (response) => {
429
- if (response.status !== 204) {
430
- console.error(
431
- `Received response with status ${response.status} from Flare`
432
- );
433
- }
434
- },
435
- (error) => console.error(error)
436
- );
437
- this.reportedErrorsTimestamps.push(Date.now());
438
- }
409
+ return this.http.report(
410
+ reportToSubmit,
411
+ this.config.reportingUrl,
412
+ this.config.key,
413
+ this.config.reportBrowserExtensionErrors
439
414
  );
440
415
  }
441
- maxReportsPerMinuteReached() {
442
- if (this.reportedErrorsTimestamps.length >= this.config.maxReportsPerMinute) {
443
- const nErrorsBack = this.reportedErrorsTimestamps[this.reportedErrorsTimestamps.length - this.config.maxReportsPerMinute];
444
- if (nErrorsBack > Date.now() - 60 * 1e3) {
445
- return true;
446
- }
447
- }
448
- return false;
416
+ // Deprecated, the following methods exist for backwards compatibility.
417
+ set beforeEvaluate(beforeEvaluate) {
418
+ this.config.beforeEvaluate = beforeEvaluate ?? "";
449
419
  }
450
- test() {
451
- this.report(new Error("The Flare client is set up correctly!"));
452
- return this;
420
+ set beforeSubmit(beforeSubmit) {
421
+ this.config.beforeSubmit = beforeSubmit ?? "";
422
+ }
423
+ set stage(stage) {
424
+ this.config.stage = stage ?? "";
453
425
  }
454
426
  };
455
427
 
456
- // src/browserClient/index.ts
428
+ // src/browser/catchWindowErrors.ts
457
429
  function catchWindowErrors() {
458
430
  if (typeof window === "undefined") {
459
431
  return;
@@ -483,12 +455,12 @@ function catchWindowErrors() {
483
455
  }
484
456
 
485
457
  // src/index.ts
486
- var flare = new FlareClient();
458
+ var flare = new Flare();
487
459
  if (typeof window !== "undefined" && window) {
488
460
  window.flare = flare;
461
+ catchWindowErrors();
489
462
  }
490
- catchWindowErrors();
491
463
  export {
492
- flare,
493
- readLinesFromFile
464
+ Flare,
465
+ flare
494
466
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flareapp/js",
3
- "version": "1.0.1",
3
+ "version": "2.0.0-rc.1",
4
4
  "description": "JavaScript client for flareapp.io",
5
5
  "homepage": "https://flareapp.io",
6
6
  "bugs": {