Warning, /firebird/packages/firebird-ng/display/src/lib/services/geometry-post-processing.service.ts is written in an unsupported language. File is not indexed.
0001 import { Injectable, Injector, inject } from '@angular/core';
0002 import {
0003 GEOMETRY_POST_PROCESSORS,
0004 GeometryPostProcessContext,
0005 GeometryPostProcessor,
0006 orderGeometryPostProcessors,
0007 } from '@dexvis/firebird-ng/api';
0008
0009 /** A post-processor that could not run, with the reason. */
0010 export interface GeometryPostProcessFailure {
0011 id: string;
0012 error: unknown;
0013 }
0014
0015 /**
0016 * Runs the registered geometry post-processors (`withGeometryPostProcessor`)
0017 * on a freshly loaded geometry, in their declared order. Each processor
0018 * class loads on the first geometry load and is instantiated once, through a
0019 * child injector so `inject()` works in its constructor.
0020 *
0021 * A failing processor does not stop the others or the load: the geometry
0022 * shows without that processor's changes, and the failure is returned for
0023 * the caller to report.
0024 */
0025 @Injectable({ providedIn: 'root' })
0026 export class GeometryPostProcessingService {
0027 private readonly injector = inject(Injector);
0028 private readonly registrations = inject(GEOMETRY_POST_PROCESSORS, { optional: true }) ?? [];
0029 private processors: Promise<Array<{ id: string; processor: GeometryPostProcessor | null; error?: unknown }>> | null = null;
0030
0031 /** Runs every processor on `context`; resolves with the failures. */
0032 async process(context: GeometryPostProcessContext): Promise<GeometryPostProcessFailure[]> {
0033 const failures: GeometryPostProcessFailure[] = [];
0034 for (const { id, processor, error } of await this.resolveProcessors()) {
0035 if (!processor) {
0036 failures.push({ id, error });
0037 continue;
0038 }
0039 try {
0040 await processor.process(context);
0041 } catch (processError) {
0042 failures.push({ id, error: processError });
0043 }
0044 }
0045 return failures;
0046 }
0047
0048 private resolveProcessors() {
0049 this.processors ??= (async () => {
0050 // An `after` cycle is a registration mistake: report it once per
0051 // processor and run none of them instead of guessing an order
0052 let ordered;
0053 try {
0054 ordered = orderGeometryPostProcessors(this.registrations);
0055 } catch (error) {
0056 return this.registrations.map(registration => ({ id: registration.id, processor: null, error }));
0057 }
0058 return Promise.all(ordered.map(async registration => {
0059 try {
0060 const processorClass = await registration.load();
0061 const child = Injector.create({ providers: [processorClass], parent: this.injector });
0062 return { id: registration.id, processor: child.get(processorClass) };
0063 } catch (error) {
0064 return { id: registration.id, processor: null, error };
0065 }
0066 }));
0067 })();
0068 return this.processors;
0069 }
0070 }