1 | import { Lambda, once, untrackedEnd, untrackedStart, die } from "../internal"
|
2 |
|
3 | export type IInterceptor<T> = (change: T) => T | null
|
4 |
|
5 | export interface IInterceptable<T> {
|
6 | interceptors_: IInterceptor<T>[] | undefined
|
7 | }
|
8 |
|
9 | export function hasInterceptors(interceptable: IInterceptable<any>) {
|
10 | return interceptable.interceptors_ !== undefined && interceptable.interceptors_.length > 0
|
11 | }
|
12 |
|
13 | export function registerInterceptor<T>(
|
14 | interceptable: IInterceptable<T>,
|
15 | handler: IInterceptor<T>
|
16 | ): Lambda {
|
17 | const interceptors = interceptable.interceptors_ || (interceptable.interceptors_ = [])
|
18 | interceptors.push(handler)
|
19 | return once(() => {
|
20 | const idx = interceptors.indexOf(handler)
|
21 | if (idx !== -1) interceptors.splice(idx, 1)
|
22 | })
|
23 | }
|
24 |
|
25 | export function interceptChange<T>(
|
26 | interceptable: IInterceptable<T | null>,
|
27 | change: T | null
|
28 | ): T | null {
|
29 | const prevU = untrackedStart()
|
30 | try {
|
31 |
|
32 | const interceptors = [...(interceptable.interceptors_ || [])]
|
33 | for (let i = 0, l = interceptors.length; i < l; i++) {
|
34 | change = interceptors[i](change)
|
35 | if (change && !(change as any).type) die(14)
|
36 | if (!change) break
|
37 | }
|
38 | return change
|
39 | } finally {
|
40 | untrackedEnd(prevU)
|
41 | }
|
42 | }
|