@sneat/logging 0.27.26 → 0.27.28

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.
@@ -6,6 +6,22 @@ import { ERROR_LOGGER_DEFAULTS } from './error-logger-defaults';
6
6
  import * as i0 from "@angular/core";
7
7
  import * as i1 from "@ionic/angular";
8
8
  const defaultErrorToastDuration = 7000;
9
+ export function isPermissionDenied(e) {
10
+ if (!e || typeof e !== 'object') {
11
+ return false;
12
+ }
13
+ const code = e.code;
14
+ if (code === 'permission-denied' || code === 'firestore/permission-denied') {
15
+ return true;
16
+ }
17
+ const msg = e.message;
18
+ if (typeof msg === 'string') {
19
+ return (msg.includes('permission-denied') ||
20
+ msg.includes("false for '") ||
21
+ msg.includes('PERMISSION_DENIED'));
22
+ }
23
+ return false;
24
+ }
9
25
  export class ErrorLoggerService {
10
26
  constructor(toastController, defaults) {
11
27
  this.toastController = toastController;
@@ -40,7 +56,10 @@ export class ErrorLoggerService {
40
56
  return;
41
57
  }
42
58
  }
43
- if (options?.report === undefined || options.report) {
59
+ const isDenied = isPermissionDenied(e);
60
+ if (options?.report === undefined
61
+ ? !isDenied && (this.defaults?.report ?? true)
62
+ : options.report) {
44
63
  if (window.location.hostname !== 'localhost') {
45
64
  try {
46
65
  const eventId = message
@@ -57,7 +76,7 @@ export class ErrorLoggerService {
57
76
  }
58
77
  }
59
78
  }
60
- const show = options?.show ?? this.defaults?.show ?? true;
79
+ const show = options?.show ?? (isDenied ? false : (this.defaults?.show ?? true));
61
80
  if (show) {
62
81
  this.showError(e, options?.showDuration);
63
82
  }
@@ -1 +1 @@
1
- {"version":3,"file":"error-logger.service.js","sourceRoot":"","sources":["../../../../../libs/logging/src/lib/error-logger.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { HttpErrorResponse } from '@angular/common/http';\nimport { Inject, Injectable, Optional } from '@angular/core';\nimport { ToastController } from '@ionic/angular';\nimport { captureException, showReportDialog } from '@sentry/angular';\nimport { IErrorLogger, ILogErrorOptions } from '@sneat/core';\nimport { ERROR_LOGGER_DEFAULTS } from './error-logger-defaults';\n\nconst defaultErrorToastDuration = 7000;\n\n@Injectable()\nexport class ErrorLoggerService implements IErrorLogger {\n constructor(\n @Optional() private readonly toastController: ToastController,\n @Optional()\n @Inject(ERROR_LOGGER_DEFAULTS)\n private readonly defaults: ILogErrorOptions | null,\n ) {}\n\n public readonly logErrorHandler =\n (message?: string, options?: ILogErrorOptions) => (e: unknown) =>\n this.logError(e, message, options);\n\n public readonly logError = (\n e: unknown,\n message?: string,\n options?: ILogErrorOptions,\n ): void => {\n // logError(e, message, options) is easy to call with `e` and `message`\n // swapped (both a string and unknown/undefined are type-legal in either\n // slot, so the compiler can't catch it). A string `e` combined with a\n // non-string `message` is the tell-tale sign of that swap — e.g. a real\n // Error/HttpErrorResponse landing in `message`, where its fields (like\n // HttpErrorResponse's server-provided message) are never read. Warn\n // loudly so it isn't silently swallowed again.\n if (\n typeof e === 'string' &&\n message !== undefined &&\n typeof message !== 'string'\n ) {\n console.error(\n 'ErrorLoggerService.logError: arguments look swapped — got a string for `e` and a non-string for `message`. Expected logError(error: unknown, message?: string, options?).',\n { e, message },\n );\n }\n console.error(\n `ErrorLoggerService.logError: ${message || 'Error'}:`,\n e,\n '; Logging options:',\n options,\n );\n // Server rendering must record the error without invoking browser-only\n // Sentry feedback UI or Ionic toasts.\n if (typeof window === 'undefined') {\n return;\n }\n if (e === true || e === false) {\n try {\n // noinspection ExceptionCaughtLocallyJS\n throw new Error(`got boolean value as an error: ${e}: ${message}`);\n } catch (ex) {\n console.error('Argument exception at logError():', ex, options);\n return;\n }\n }\n if (options?.report === undefined || options.report) {\n if (window.location.hostname !== 'localhost') {\n try {\n const eventId = message\n ? captureException(message, { originalException: e })\n : captureException(e);\n\n // console.log('Captured error by Sentry with eventId:', eventId);\n const feedback =\n options?.feedback ?? this.defaults?.feedback ?? true;\n if (feedback) {\n showReportDialog({ eventId });\n }\n } catch (ex) {\n console.error(\n 'Sentry failed to capture or show error report dialog',\n ex,\n );\n }\n }\n }\n const show = options?.show ?? this.defaults?.show ?? true;\n if (show) {\n this.showError(e, options?.showDuration);\n }\n return; // return message ? { error: e, message } : e;\n };\n\n public showError(e: unknown, duration?: number): void {\n let clientMessage: string | undefined;\n\n if ((e as { message?: string }).message) {\n clientMessage =\n (clientMessage &&\n `${clientMessage}: ${(e as { message?: string }).message}`) ||\n (e as { message?: string }).message;\n } else if (!clientMessage) {\n clientMessage = (e as object).toString();\n }\n if (!clientMessage) {\n throw new Error('showError() have not received a message to display');\n }\n if (duration && duration < 0) {\n throw new Error('showError received negative duration');\n }\n\n let message = clientMessage;\n\n let serverMessage: string | undefined;\n if (e instanceof HttpErrorResponse) {\n const e2 = e as HttpErrorResponse;\n serverMessage = e2.error?.error?.message;\n if (serverMessage) {\n message += `.\\n\\nServer returned error message: ${serverMessage}`;\n }\n }\n if (!this.toastController) {\n console.warn('ToastController not available, cannot show error toast');\n return;\n }\n this.toastController\n .create({\n message,\n duration: duration || defaultErrorToastDuration,\n keyboardClose: true,\n buttons: [\n {\n icon: 'close',\n side: 'end',\n handler: () =>\n this.toastController.dismiss().catch((e) =>\n this.logError(e, 'Failed to dismiss error dialog', {\n show: false,\n }),\n ),\n },\n ],\n color: 'danger',\n header: 'Something went wrong',\n position: 'top',\n })\n .then((toast) =>\n toast\n .present()\n .catch(\n this.logErrorHandler(\n 'Failed to present toast with error message:',\n { show: false },\n ),\n ),\n )\n .catch(\n this.logErrorHandler('Failed to create a toast with error message:', {\n show: false,\n }),\n );\n }\n}\n"]}
1
+ {"version":3,"file":"error-logger.service.js","sourceRoot":"","sources":["../../../../../libs/logging/src/lib/error-logger.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { HttpErrorResponse } from '@angular/common/http';\nimport { Inject, Injectable, Optional } from '@angular/core';\nimport { ToastController } from '@ionic/angular';\nimport { captureException, showReportDialog } from '@sentry/angular';\nimport { IErrorLogger, ILogErrorOptions } from '@sneat/core';\nimport { ERROR_LOGGER_DEFAULTS } from './error-logger-defaults';\n\nconst defaultErrorToastDuration = 7000;\n\nexport function isPermissionDenied(e: unknown): boolean {\n if (!e || typeof e !== 'object') {\n return false;\n }\n const code = (e as { code?: unknown }).code;\n if (code === 'permission-denied' || code === 'firestore/permission-denied') {\n return true;\n }\n const msg = (e as { message?: unknown }).message;\n if (typeof msg === 'string') {\n return (\n msg.includes('permission-denied') ||\n msg.includes(\"false for '\") ||\n msg.includes('PERMISSION_DENIED')\n );\n }\n return false;\n}\n\n@Injectable()\nexport class ErrorLoggerService implements IErrorLogger {\n constructor(\n @Optional() private readonly toastController: ToastController,\n @Optional()\n @Inject(ERROR_LOGGER_DEFAULTS)\n private readonly defaults: ILogErrorOptions | null,\n ) {}\n\n public readonly logErrorHandler =\n (message?: string, options?: ILogErrorOptions) => (e: unknown) =>\n this.logError(e, message, options);\n\n public readonly logError = (\n e: unknown,\n message?: string,\n options?: ILogErrorOptions,\n ): void => {\n // logError(e, message, options) is easy to call with `e` and `message`\n // swapped (both a string and unknown/undefined are type-legal in either\n // slot, so the compiler can't catch it). A string `e` combined with a\n // non-string `message` is the tell-tale sign of that swap — e.g. a real\n // Error/HttpErrorResponse landing in `message`, where its fields (like\n // HttpErrorResponse's server-provided message) are never read. Warn\n // loudly so it isn't silently swallowed again.\n if (\n typeof e === 'string' &&\n message !== undefined &&\n typeof message !== 'string'\n ) {\n console.error(\n 'ErrorLoggerService.logError: arguments look swapped — got a string for `e` and a non-string for `message`. Expected logError(error: unknown, message?: string, options?).',\n { e, message },\n );\n }\n console.error(\n `ErrorLoggerService.logError: ${message || 'Error'}:`,\n e,\n '; Logging options:',\n options,\n );\n // Server rendering must record the error without invoking browser-only\n // Sentry feedback UI or Ionic toasts.\n if (typeof window === 'undefined') {\n return;\n }\n if (e === true || e === false) {\n try {\n // noinspection ExceptionCaughtLocallyJS\n throw new Error(`got boolean value as an error: ${e}: ${message}`);\n } catch (ex) {\n console.error('Argument exception at logError():', ex, options);\n return;\n }\n }\n const isDenied = isPermissionDenied(e);\n if (\n options?.report === undefined\n ? !isDenied && (this.defaults?.report ?? true)\n : options.report\n ) {\n if (window.location.hostname !== 'localhost') {\n try {\n const eventId = message\n ? captureException(message, { originalException: e })\n : captureException(e);\n\n // console.log('Captured error by Sentry with eventId:', eventId);\n const feedback =\n options?.feedback ?? this.defaults?.feedback ?? true;\n if (feedback) {\n showReportDialog({ eventId });\n }\n } catch (ex) {\n console.error(\n 'Sentry failed to capture or show error report dialog',\n ex,\n );\n }\n }\n }\n const show =\n options?.show ?? (isDenied ? false : (this.defaults?.show ?? true));\n if (show) {\n this.showError(e, options?.showDuration);\n }\n return; // return message ? { error: e, message } : e;\n };\n\n public showError(e: unknown, duration?: number): void {\n let clientMessage: string | undefined;\n\n if ((e as { message?: string }).message) {\n clientMessage =\n (clientMessage &&\n `${clientMessage}: ${(e as { message?: string }).message}`) ||\n (e as { message?: string }).message;\n } else if (!clientMessage) {\n clientMessage = (e as object).toString();\n }\n if (!clientMessage) {\n throw new Error('showError() have not received a message to display');\n }\n if (duration && duration < 0) {\n throw new Error('showError received negative duration');\n }\n\n let message = clientMessage;\n\n let serverMessage: string | undefined;\n if (e instanceof HttpErrorResponse) {\n const e2 = e as HttpErrorResponse;\n serverMessage = e2.error?.error?.message;\n if (serverMessage) {\n message += `.\\n\\nServer returned error message: ${serverMessage}`;\n }\n }\n if (!this.toastController) {\n console.warn('ToastController not available, cannot show error toast');\n return;\n }\n this.toastController\n .create({\n message,\n duration: duration || defaultErrorToastDuration,\n keyboardClose: true,\n buttons: [\n {\n icon: 'close',\n side: 'end',\n handler: () =>\n this.toastController.dismiss().catch((e) =>\n this.logError(e, 'Failed to dismiss error dialog', {\n show: false,\n }),\n ),\n },\n ],\n color: 'danger',\n header: 'Something went wrong',\n position: 'top',\n })\n .then((toast) =>\n toast\n .present()\n .catch(\n this.logErrorHandler(\n 'Failed to present toast with error message:',\n { show: false },\n ),\n ),\n )\n .catch(\n this.logErrorHandler('Failed to create a toast with error message:', {\n show: false,\n }),\n );\n }\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import { ToastController } from '@ionic/angular';
2
2
  import { IErrorLogger, ILogErrorOptions } from '@sneat/core';
3
3
  import * as i0 from "@angular/core";
4
+ export declare function isPermissionDenied(e: unknown): boolean;
4
5
  export declare class ErrorLoggerService implements IErrorLogger {
5
6
  private readonly toastController;
6
7
  private readonly defaults;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sneat/logging",
3
- "version": "0.27.26",
3
+ "version": "0.27.28",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },