theatre/packages/dataverse/src/PointerProxy.ts

64 lines
1.8 KiB
TypeScript
Raw Normal View History

2023-01-21 21:57:28 +01:00
import Atom from './Atom'
import {val} from './val'
import type {Pointer} from './pointer'
import {getPointerMeta} from './pointer'
2021-06-18 13:05:06 +02:00
import pointer from './pointer'
import type {$FixMe, $IntentionalAny} from './types'
2022-12-01 15:09:53 +01:00
import prism from './prism/prism'
import type {Prism} from './prism/Interface'
2023-01-21 21:57:28 +01:00
import type {PointerToPrismProvider} from './pointerToPrism'
2021-06-18 13:05:06 +02:00
2022-01-19 13:06:13 +01:00
/**
* Allows creating pointer-prisms where the pointer can be switched out.
2022-01-19 13:06:13 +01:00
*
* @remarks
* This allows reacting not just to value changes at a certain pointer, but changes
* to the proxied pointer too.
*/
2021-06-18 13:05:06 +02:00
export default class PointerProxy<O extends {}>
implements PointerToPrismProvider
2021-06-18 13:05:06 +02:00
{
2022-01-19 13:06:13 +01:00
/**
* @internal
*/
readonly $$isPointerToPrismProvider = true
2022-12-01 18:56:34 +01:00
private readonly _currentPointerBox: Atom<Pointer<O>>
2022-01-19 13:06:13 +01:00
/**
* Convenience pointer pointing to the root of this PointerProxy.
*
* @remarks
2022-12-01 14:26:17 +01:00
* Allows convenient use of {@link pointerToPrism} and {@link val}.
2022-01-19 13:06:13 +01:00
*/
2021-06-18 13:05:06 +02:00
readonly pointer: Pointer<O>
constructor(currentPointer: Pointer<O>) {
2022-12-01 18:56:34 +01:00
this._currentPointerBox = new Atom(currentPointer)
2021-06-18 13:05:06 +02:00
this.pointer = pointer({root: this as $FixMe, path: []})
}
2022-01-19 13:06:13 +01:00
/**
* Sets the underlying pointer.
2022-02-23 22:53:39 +01:00
* @param p - The pointer to be proxied.
2022-01-19 13:06:13 +01:00
*/
2021-06-18 13:05:06 +02:00
setPointer(p: Pointer<O>) {
this._currentPointerBox.set(p)
}
2022-01-19 13:06:13 +01:00
/**
2022-12-01 14:41:46 +01:00
* Returns a prism of the value at the provided sub-path of the proxied pointer.
2022-01-19 13:06:13 +01:00
*
2022-12-01 14:41:46 +01:00
* @param path - The path to create the prism at.
2022-01-19 13:06:13 +01:00
*/
pointerToPrism<P>(pointer: Pointer<P>): Prism<P> {
const {path} = getPointerMeta(pointer)
return prism(() => {
2022-12-01 14:41:46 +01:00
const currentPointer = this._currentPointerBox.prism.getValue()
2021-06-18 13:05:06 +02:00
const subPointer = path.reduce(
(pointerSoFar, pathItem) => (pointerSoFar as $IntentionalAny)[pathItem],
currentPointer,
2021-06-18 13:05:06 +02:00
)
return val(subPointer) as P
2021-06-18 13:05:06 +02:00
})
}
}