@mmuscat/angular-error-boundary
Version:
Error Boundaries for Angular, with a bit of Suspense.
92 lines • 9.36 kB
JavaScript
import { Component, ContentChildren, ErrorHandler, Injectable, Output, SkipSelf, TemplateRef, EventEmitter, } from "@angular/core";
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
export class ErrorLogger {
error(error) {
console.error(error);
}
}
ErrorLogger.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0", ngImport: i0, type: ErrorLogger, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
ErrorLogger.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.0", ngImport: i0, type: ErrorLogger, providedIn: "root" });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0", ngImport: i0, type: ErrorLogger, decorators: [{
type: Injectable,
args: [{ providedIn: "root" }]
}] });
export class ErrorBoundary {
constructor(changeDetectorRef, logger, errorHandler) {
this.changeDetectorRef = changeDetectorRef;
this.logger = logger;
this.errorHandler = errorHandler;
this.hasError = false;
this.error = new EventEmitter();
}
ngDoCheck() {
if (this.hasError)
return;
try {
this.changeDetectorRef.detectChanges();
}
catch (error) {
this.handleError(error);
}
}
ngAfterViewInit() {
this.changeDetectorRef.detach();
}
handleError(fault) {
try {
this.hasError = true;
this.changeDetectorRef.detectChanges();
this.logger.error(fault);
this.error.emit(new ErrorEvent("ErrorBoundary", {
error: fault,
}));
}
catch (doubleFault) {
this.errorHandler.handleError(fault);
if (fault !== doubleFault) {
this.errorHandler.handleError(doubleFault);
}
}
}
retry() {
this.hasError = false;
this.changeDetectorRef.detectChanges();
}
}
ErrorBoundary.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0", ngImport: i0, type: ErrorBoundary, deps: [{ token: i0.ChangeDetectorRef }, { token: ErrorLogger }, { token: i0.ErrorHandler, skipSelf: true }], target: i0.ɵɵFactoryTarget.Component });
ErrorBoundary.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.0", type: ErrorBoundary, selector: "error-boundary", outputs: { error: "error" }, providers: [
{
provide: ErrorHandler,
useExisting: ErrorBoundary,
},
], queries: [{ propertyName: "template", predicate: TemplateRef }], ngImport: i0, template: `
<ng-container *ngIf="hasError; else template?.first ?? null">
<ng-content select="fallback, [fallback]"></ng-content>
</ng-container>
`, isInline: true, directives: [{ type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0", ngImport: i0, type: ErrorBoundary, decorators: [{
type: Component,
args: [{
selector: "error-boundary",
template: `
<ng-container *ngIf="hasError; else template?.first ?? null">
<ng-content select="fallback, [fallback]"></ng-content>
</ng-container>
`,
providers: [
{
provide: ErrorHandler,
useExisting: ErrorBoundary,
},
],
}]
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: ErrorLogger }, { type: i0.ErrorHandler, decorators: [{
type: SkipSelf
}] }]; }, propDecorators: { error: [{
type: Output
}], template: [{
type: ContentChildren,
args: [TemplateRef, { descendants: false }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3ItYm91bmRhcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9wYWNrYWdlcy9ib3VuZGFyeS9zcmMvZXJyb3ItYm91bmRhcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUVKLFNBQVMsRUFDVCxlQUFlLEVBRWYsWUFBWSxFQUNaLFVBQVUsRUFDVixNQUFNLEVBRU4sUUFBUSxFQUNSLFdBQVcsRUFDWCxZQUFZLEdBRWQsTUFBTSxlQUFlLENBQUE7OztBQUl0QixNQUFNLE9BQU8sV0FBVztJQUNyQixLQUFLLENBQUMsS0FBYztRQUNqQixPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFBO0lBQ3ZCLENBQUM7O3dHQUhTLFdBQVc7NEdBQVgsV0FBVyxjQURFLE1BQU07MkZBQ25CLFdBQVc7a0JBRHZCLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFOztBQXFCbEMsTUFBTSxPQUFPLGFBQWE7SUE0Q3ZCLFlBQ1UsaUJBQW9DLEVBQ3BDLE1BQW1CLEVBQ04sWUFBMEI7UUFGdkMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFtQjtRQUNwQyxXQUFNLEdBQU4sTUFBTSxDQUFhO1FBQ04saUJBQVksR0FBWixZQUFZLENBQWM7UUFFOUMsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUE7UUFDckIsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLFlBQVksRUFBYyxDQUFBO0lBQzlDLENBQUM7SUEzQ0QsU0FBUztRQUNOLElBQUksSUFBSSxDQUFDLFFBQVE7WUFBRSxPQUFNO1FBQ3pCLElBQUk7WUFDRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsYUFBYSxFQUFFLENBQUE7U0FDeEM7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNiLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUE7U0FDekI7SUFDSixDQUFDO0lBRUQsZUFBZTtRQUNaLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsQ0FBQTtJQUNsQyxDQUFDO0lBRUQsV0FBVyxDQUFDLEtBQWM7UUFDdkIsSUFBSTtZQUNELElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFBO1lBQ3BCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxhQUFhLEVBQUUsQ0FBQTtZQUN0QyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQTtZQUN4QixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FDWixJQUFJLFVBQVUsQ0FBQyxlQUFlLEVBQUU7Z0JBQzdCLEtBQUssRUFBRSxLQUFLO2FBQ2QsQ0FBQyxDQUNKLENBQUE7U0FDSDtRQUFDLE9BQU8sV0FBVyxFQUFFO1lBQ25CLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFBO1lBQ3BDLElBQUksS0FBSyxLQUFLLFdBQVcsRUFBRTtnQkFDeEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUE7YUFDNUM7U0FDSDtJQUNKLENBQUM7SUFFRCxLQUFLO1FBQ0YsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUE7UUFDckIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGFBQWEsRUFBRSxDQUFBO0lBQ3pDLENBQUM7OzBHQTFDUyxhQUFhLG1EQThDTCxXQUFXOzhGQTlDbkIsYUFBYSxzRUFQWjtRQUNSO1lBQ0csT0FBTyxFQUFFLFlBQVk7WUFDckIsV0FBVyxFQUFFLGFBQWE7U0FDNUI7S0FDSCxtREFPZ0IsV0FBVyw2QkFqQmxCOzs7O0lBSVQ7MkZBUVMsYUFBYTtrQkFkekIsU0FBUzttQkFBQztvQkFDUixRQUFRLEVBQUUsZ0JBQWdCO29CQUMxQixRQUFRLEVBQUU7Ozs7SUFJVDtvQkFDRCxTQUFTLEVBQUU7d0JBQ1I7NEJBQ0csT0FBTyxFQUFFLFlBQVk7NEJBQ3JCLFdBQVcsZUFBZTt5QkFDNUI7cUJBQ0g7aUJBQ0g7MEZBK0NvQixXQUFXOzBCQUN6QixRQUFROzRDQTdDWixLQUFLO3NCQURKLE1BQU07Z0JBS1AsUUFBUTtzQkFEUCxlQUFlO3VCQUFDLFdBQVcsRUFBRSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICBDb21wb25lbnQsXG4gICBDb250ZW50Q2hpbGRyZW4sXG4gICBEb0NoZWNrLFxuICAgRXJyb3JIYW5kbGVyLFxuICAgSW5qZWN0YWJsZSxcbiAgIE91dHB1dCxcbiAgIFF1ZXJ5TGlzdCxcbiAgIFNraXBTZWxmLFxuICAgVGVtcGxhdGVSZWYsXG4gICBFdmVudEVtaXR0ZXIsXG4gICBBZnRlclZpZXdJbml0LFxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiXG5pbXBvcnQgeyBOZ0lmQ29udGV4dCB9IGZyb20gXCJAYW5ndWxhci9jb21tb25cIlxuXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46IFwicm9vdFwiIH0pXG5leHBvcnQgY2xhc3MgRXJyb3JMb2dnZXIge1xuICAgZXJyb3IoZXJyb3I6IHVua25vd24pIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpXG4gICB9XG59XG5cbkBDb21wb25lbnQoe1xuICAgc2VsZWN0b3I6IFwiZXJyb3ItYm91bmRhcnlcIixcbiAgIHRlbXBsYXRlOiBgXG4gICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiaGFzRXJyb3I7IGVsc2UgdGVtcGxhdGU/LmZpcnN0ID8/IG51bGxcIj5cbiAgICAgICAgIDxuZy1jb250ZW50IHNlbGVjdD1cImZhbGxiYWNrLCBbZmFsbGJhY2tdXCI+PC9uZy1jb250ZW50PlxuICAgICAgPC9uZy1jb250YWluZXI+XG4gICBgLFxuICAgcHJvdmlkZXJzOiBbXG4gICAgICB7XG4gICAgICAgICBwcm92aWRlOiBFcnJvckhhbmRsZXIsXG4gICAgICAgICB1c2VFeGlzdGluZzogRXJyb3JCb3VuZGFyeSxcbiAgICAgIH0sXG4gICBdLFxufSlcbmV4cG9ydCBjbGFzcyBFcnJvckJvdW5kYXJ5IGltcGxlbWVudHMgRG9DaGVjaywgQWZ0ZXJWaWV3SW5pdCB7XG4gICBAT3V0cHV0KClcbiAgIGVycm9yXG4gICBoYXNFcnJvclxuXG4gICBAQ29udGVudENoaWxkcmVuKFRlbXBsYXRlUmVmLCB7IGRlc2NlbmRhbnRzOiBmYWxzZSB9KVxuICAgdGVtcGxhdGU/OiBRdWVyeUxpc3Q8VGVtcGxhdGVSZWY8TmdJZkNvbnRleHQ8Ym9vbGVhbj4+PlxuXG4gICBuZ0RvQ2hlY2soKSB7XG4gICAgICBpZiAodGhpcy5oYXNFcnJvcikgcmV0dXJuXG4gICAgICB0cnkge1xuICAgICAgICAgdGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5kZXRlY3RDaGFuZ2VzKClcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICB0aGlzLmhhbmRsZUVycm9yKGVycm9yKVxuICAgICAgfVxuICAgfVxuXG4gICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgICB0aGlzLmNoYW5nZURldGVjdG9yUmVmLmRldGFjaCgpXG4gICB9XG5cbiAgIGhhbmRsZUVycm9yKGZhdWx0OiB1bmtub3duKSB7XG4gICAgICB0cnkge1xuICAgICAgICAgdGhpcy5oYXNFcnJvciA9IHRydWVcbiAgICAgICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpXG4gICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihmYXVsdClcbiAgICAgICAgIHRoaXMuZXJyb3IuZW1pdChcbiAgICAgICAgICAgIG5ldyBFcnJvckV2ZW50KFwiRXJyb3JCb3VuZGFyeVwiLCB7XG4gICAgICAgICAgICAgICBlcnJvcjogZmF1bHQsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgIClcbiAgICAgIH0gY2F0Y2ggKGRvdWJsZUZhdWx0KSB7XG4gICAgICAgICB0aGlzLmVycm9ySGFuZGxlci5oYW5kbGVFcnJvcihmYXVsdClcbiAgICAgICAgIGlmIChmYXVsdCAhPT0gZG91YmxlRmF1bHQpIHtcbiAgICAgICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyLmhhbmRsZUVycm9yKGRvdWJsZUZhdWx0KVxuICAgICAgICAgfVxuICAgICAgfVxuICAgfVxuXG4gICByZXRyeSgpIHtcbiAgICAgIHRoaXMuaGFzRXJyb3IgPSBmYWxzZVxuICAgICAgdGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5kZXRlY3RDaGFuZ2VzKClcbiAgIH1cblxuICAgY29uc3RydWN0b3IoXG4gICAgICBwdWJsaWMgY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmLFxuICAgICAgcHVibGljIGxvZ2dlcjogRXJyb3JMb2dnZXIsXG4gICAgICBAU2tpcFNlbGYoKSBwcml2YXRlIGVycm9ySGFuZGxlcjogRXJyb3JIYW5kbGVyLFxuICAgKSB7XG4gICAgICB0aGlzLmhhc0Vycm9yID0gZmFsc2VcbiAgICAgIHRoaXMuZXJyb3IgPSBuZXcgRXZlbnRFbWl0dGVyPEVycm9yRXZlbnQ+KClcbiAgIH1cbn1cbiJdfQ==