@mmuscat/angular-error-boundary
Version:
Error Boundaries for Angular, with a bit of Suspense.
1 lines • 15.2 kB
Source Map (JSON)
{"version":3,"file":"mmuscat-angular-error-boundary.mjs","sources":["../../../packages/boundary/src/cloak.ts","../../../packages/boundary/src/error-boundary.ts","../../../packages/boundary/src/fallback.ts","../../../packages/boundary/src/boundary.module.ts","../../../packages/boundary/src/public-api.ts","../../../packages/boundary/src/mmuscat-angular-error-boundary.ts"],"sourcesContent":["import { isObservable, Observable, Observer, Subject, Subscriber } from \"rxjs\"\nimport {\n AfterContentInit,\n ChangeDetectorRef,\n Component,\n ContentChildren,\n Directive,\n ElementRef,\n ErrorHandler,\n EventEmitter,\n Input,\n OnDestroy,\n Output,\n QueryList,\n Renderer2,\n SkipSelf,\n} from \"@angular/core\"\n\nclass ValueSubscriber extends Subscriber<any> {\n next() {\n super.complete()\n this.unsubscribe()\n }\n\n error(error: unknown) {\n super.error(error)\n this.unsubscribe()\n }\n\n complete() {\n super.complete()\n this.unsubscribe()\n }\n\n unsubscribe() {\n this.boundary.subscription.remove(this)\n super.unsubscribe()\n }\n\n constructor(private boundary: NgCloak, observer: CloakObserver) {\n super(observer)\n boundary.subscription.add(this)\n }\n}\n\nclass CloakObserver implements Observer<any> {\n next(source: Observable<any>) {\n const subscriber = new ValueSubscriber(this.boundary, this)\n subscriber.add(source.subscribe(subscriber))\n }\n error(error: unknown) {\n this.boundary.handleError(error)\n }\n complete() {\n const { boundary } = this\n if (boundary.refCount > 0) {\n boundary.refCount--\n if (boundary.refCount === 0) {\n boundary.cloak(false)\n }\n }\n }\n constructor(private boundary: NgCloak) {}\n}\n\n@Component({\n selector: \"ng-cloak\",\n template: `\n <ng-content\n select=\"fallback, [fallback]\"\n *ngIf=\"cloaked; else content\"\n ></ng-content>\n <ng-template #content>\n <ng-content></ng-content>\n </ng-template>\n `,\n providers: [\n {\n provide: ErrorHandler,\n useExisting: NgCloak,\n },\n ],\n})\nexport class NgCloak implements AfterContentInit, OnDestroy {\n cloaked\n observer\n subscription\n queue\n refCount\n parent?: NgCloakList\n\n @Output()\n cloakChange\n\n get element() {\n return this.elementRef.nativeElement\n }\n\n register(parent: NgCloakList) {\n this.parent = parent\n }\n\n handleError(value: unknown) {\n if (isObservable(value)) {\n this.refCount++\n this.queue.next(value)\n this.cloak(true)\n } else {\n this.refCount = 0\n this.subscription.unsubscribe()\n this.subscription = this.subscribe()\n this.cloak(false)\n this.errorHandler.handleError(value)\n }\n }\n\n cloak(cloaked: boolean) {\n this.cloaked = cloaked\n if (cloaked) this.changeDetectorRef.detach()\n else this.changeDetectorRef.reattach()\n if (!this.parent) this.render()\n }\n\n render() {\n this.changeDetectorRef.detectChanges()\n }\n\n subscribe() {\n return this.queue.subscribe(this.observer)\n }\n\n ngAfterContentInit() {\n this.cloak(this.refCount > 0)\n }\n\n ngOnDestroy() {\n this.subscription.unsubscribe()\n }\n\n constructor(\n private elementRef: ElementRef,\n @SkipSelf() private errorHandler: ErrorHandler,\n public changeDetectorRef: ChangeDetectorRef,\n ) {\n this.cloaked = false\n this.refCount = 0\n this.observer = new CloakObserver(this)\n this.queue = new Subject<Observable<any>>()\n this.subscription = this.subscribe()\n this.cloakChange = new EventEmitter()\n }\n}\n\nclass CloakListObserver {\n next() {\n this.list.render(this.children)\n }\n constructor(\n private list: NgCloakList,\n private child: NgCloak,\n private children: NgCloak[],\n ) {}\n}\n\n@Directive({\n selector: \"cloak-list\",\n})\nexport class NgCloakList implements AfterContentInit {\n @Input()\n revealOrder: \"together\" | \"forwards\" | \"reverse\"\n\n @Input()\n tail?: \"collapsed\" | \"hidden\"\n\n @ContentChildren(NgCloak, { descendants: true })\n children?: QueryList<NgCloak>\n\n render(children: NgCloak[]) {\n const {\n elementRef: { nativeElement },\n renderer,\n revealOrder,\n tail,\n } = this\n let child\n let previous = null\n let renderChildren: NgCloak[] = children.slice()\n if (revealOrder === \"reverse\") {\n renderChildren = renderChildren.reverse()\n }\n while ((child = renderChildren.shift())) {\n if (tail === \"hidden\" && child.cloaked) break\n if (revealOrder === \"reverse\") {\n renderer.insertBefore(nativeElement, child, previous)\n } else {\n renderer.appendChild(nativeElement, child.element)\n }\n previous = child\n child.render()\n if (tail === \"collapsed\" && child.cloaked) break\n }\n while ((child = renderChildren.shift())) {\n renderer.removeChild(nativeElement, child.element)\n }\n }\n\n subscribe(children: NgCloak[]) {\n for (const child of children) {\n child.cloakChange.subscribe(\n new CloakListObserver(this, child, children),\n )\n }\n }\n\n ngAfterContentInit() {\n if (this.children) {\n this.subscribe(this.children.toArray())\n }\n }\n\n constructor(private elementRef: ElementRef, private renderer: Renderer2) {\n this.revealOrder = \"together\"\n }\n}\n","import {\n ChangeDetectorRef,\n Component,\n ContentChildren,\n DoCheck,\n ErrorHandler,\n Injectable,\n Output,\n QueryList,\n SkipSelf,\n TemplateRef,\n EventEmitter,\n AfterViewInit,\n} from \"@angular/core\"\nimport { NgIfContext } from \"@angular/common\"\n\n@Injectable({ providedIn: \"root\" })\nexport class ErrorLogger {\n error(error: unknown) {\n console.error(error)\n }\n}\n\n@Component({\n selector: \"error-boundary\",\n template: `\n <ng-container *ngIf=\"hasError; else template?.first ?? null\">\n <ng-content select=\"fallback, [fallback]\"></ng-content>\n </ng-container>\n `,\n providers: [\n {\n provide: ErrorHandler,\n useExisting: ErrorBoundary,\n },\n ],\n})\nexport class ErrorBoundary implements DoCheck, AfterViewInit {\n @Output()\n error\n hasError\n\n @ContentChildren(TemplateRef, { descendants: false })\n template?: QueryList<TemplateRef<NgIfContext<boolean>>>\n\n ngDoCheck() {\n if (this.hasError) return\n try {\n this.changeDetectorRef.detectChanges()\n } catch (error) {\n this.handleError(error)\n }\n }\n\n ngAfterViewInit() {\n this.changeDetectorRef.detach()\n }\n\n handleError(fault: unknown) {\n try {\n this.hasError = true\n this.changeDetectorRef.detectChanges()\n this.logger.error(fault)\n this.error.emit(\n new ErrorEvent(\"ErrorBoundary\", {\n error: fault,\n }),\n )\n } catch (doubleFault) {\n this.errorHandler.handleError(fault)\n if (fault !== doubleFault) {\n this.errorHandler.handleError(doubleFault)\n }\n }\n }\n\n retry() {\n this.hasError = false\n this.changeDetectorRef.detectChanges()\n }\n\n constructor(\n public changeDetectorRef: ChangeDetectorRef,\n public logger: ErrorLogger,\n @SkipSelf() private errorHandler: ErrorHandler,\n ) {\n this.hasError = false\n this.error = new EventEmitter<ErrorEvent>()\n }\n}\n","import {Directive} from \"@angular/core\";\n\n@Directive({ selector: \"fallback, [fallback]\"})\nexport class Fallback {}","import { NgModule } from \"@angular/core\"\nimport {NgCloak, NgCloakList} from \"./cloak\"\nimport {CommonModule} from \"@angular/common\";\nimport {ErrorBoundary} from \"./error-boundary\";\nimport {Fallback} from \"./fallback\";\n\n@NgModule({\n imports: [CommonModule],\n declarations: [ErrorBoundary, NgCloakList, NgCloak, Fallback],\n exports: [ErrorBoundary, NgCloakList, NgCloak, Fallback],\n})\nexport class BoundaryModule {}\n","/*\n * Public API Surface of boundary\n */\n\nexport * from \"./cloak\"\nexport * from \"./error-boundary\"\nexport * from \"./boundary.module\"\nexport * from \"./fallback\"\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}