TenantAtlas/apps/platform/.pnpm-store/v10/files/c9/2f6051f955d8b2b5bd777a3311df8faba1a3d91ec5bbb5f115df7c9f491aa2c45cf30f987e7302dab4bf1530e8273e3d5706dbf3d4a3b11cf4aeeff79a7cef
ahmido 1fec9c6f9d
Some checks failed
Main Confidence / confidence (push) Failing after 45s
feat: compress governance operator outcomes (#253)
## Summary
- introduce surface-aware compressed governance outcomes and reuse the shared truth/explanation seams for operator-first summaries
- apply the compressed outcome hierarchy across baseline, evidence, review, review-pack, canonical review/evidence, and artifact-oriented operation-run surfaces
- expand spec 214 fixtures and Pest coverage, and fix tenant-panel route assertions by generating explicit tenant-panel URLs in the affected Filament tests

## Validation
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- focused governance compression suite from `specs/214-governance-outcome-compression/quickstart.md` passed (`68` tests, `445` assertions)
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/InventoryItemResourceTest.php tests/Feature/Filament/BackupSetUiEnforcementTest.php tests/Feature/Filament/RestoreRunUiEnforcementTest.php` passed (`18` tests, `81` assertions)

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #253
2026-04-19 12:30:36 +00:00

140 lines
4.4 KiB
Plaintext

import { Observable } from '../Observable';
import { ObservableInput, OperatorFunction, ObservedValueOf } from '../types';
import { Subscription } from '../Subscription';
import { innerFrom } from '../observable/innerFrom';
import { createOperatorSubscriber } from './OperatorSubscriber';
import { operate } from '../util/lift';
export function catchError<T, O extends ObservableInput<any>>(
selector: (err: any, caught: Observable<T>) => O
): OperatorFunction<T, T | ObservedValueOf<O>>;
/**
* Catches errors on the observable to be handled by returning a new observable or throwing an error.
*
* <span class="informal">
* It only listens to the error channel and ignores notifications.
* Handles errors from the source observable, and maps them to a new observable.
* The error may also be rethrown, or a new error can be thrown to emit an error from the result.
* </span>
*
* ![](catch.png)
*
* This operator handles errors, but forwards along all other events to the resulting observable.
* If the source observable terminates with an error, it will map that error to a new observable,
* subscribe to it, and forward all of its events to the resulting observable.
*
* ## Examples
*
* Continue with a different Observable when there's an error
*
* ```ts
* import { of, map, catchError } from 'rxjs';
*
* of(1, 2, 3, 4, 5)
* .pipe(
* map(n => {
* if (n === 4) {
* throw 'four!';
* }
* return n;
* }),
* catchError(err => of('I', 'II', 'III', 'IV', 'V'))
* )
* .subscribe(x => console.log(x));
* // 1, 2, 3, I, II, III, IV, V
* ```
*
* Retry the caught source Observable again in case of error, similar to `retry()` operator
*
* ```ts
* import { of, map, catchError, take } from 'rxjs';
*
* of(1, 2, 3, 4, 5)
* .pipe(
* map(n => {
* if (n === 4) {
* throw 'four!';
* }
* return n;
* }),
* catchError((err, caught) => caught),
* take(30)
* )
* .subscribe(x => console.log(x));
* // 1, 2, 3, 1, 2, 3, ...
* ```
*
* Throw a new error when the source Observable throws an error
*
* ```ts
* import { of, map, catchError } from 'rxjs';
*
* of(1, 2, 3, 4, 5)
* .pipe(
* map(n => {
* if (n === 4) {
* throw 'four!';
* }
* return n;
* }),
* catchError(err => {
* throw 'error in source. Details: ' + err;
* })
* )
* .subscribe({
* next: x => console.log(x),
* error: err => console.log(err)
* });
* // 1, 2, 3, error in source. Details: four!
* ```
*
* @see {@link onErrorResumeNext}
* @see {@link repeat}
* @see {@link repeatWhen}
* @see {@link retry }
* @see {@link retryWhen}
*
* @param selector A function that takes as arguments `err`, which is the error, and `caught`, which
* is the source observable, in case you'd like to "retry" that observable by returning it again.
* Whatever observable is returned by the `selector` will be used to continue the observable chain.
* @return A function that returns an Observable that originates from either
* the source or the Observable returned by the `selector` function.
*/
export function catchError<T, O extends ObservableInput<any>>(
selector: (err: any, caught: Observable<T>) => O
): OperatorFunction<T, T | ObservedValueOf<O>> {
return operate((source, subscriber) => {
let innerSub: Subscription | null = null;
let syncUnsub = false;
let handledResult: Observable<ObservedValueOf<O>>;
innerSub = source.subscribe(
createOperatorSubscriber(subscriber, undefined, undefined, (err) => {
handledResult = innerFrom(selector(err, catchError(selector)(source)));
if (innerSub) {
innerSub.unsubscribe();
innerSub = null;
handledResult.subscribe(subscriber);
} else {
// We don't have an innerSub yet, that means the error was synchronous
// because the subscribe call hasn't returned yet.
syncUnsub = true;
}
})
);
if (syncUnsub) {
// We have a synchronous error, we need to make sure to
// finalize right away. This ensures that callbacks in the `finalize` operator are called
// at the right time, and that finalization occurs at the expected
// time between the source error and the subscription to the
// next observable.
innerSub.unsubscribe();
innerSub = null;
handledResult!.subscribe(subscriber);
}
});
}