mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 10:21:52 +00:00
* fix undefined handling in INI * beta.14 * Partial -> DeepPartial in action request * boolean laziness kills * beta.16 * misc fixes * file transformers * infer validator source argument * simplify validator * readd toml * beta.17 * filter undefined instead of parse/stringify * handle arrays of objects in filterUndefined
90 lines
2.3 KiB
TypeScript
90 lines
2.3 KiB
TypeScript
import { T } from "@start9labs/start-sdk"
|
|
|
|
const CallbackIdCell = { inc: 1 }
|
|
|
|
const callbackRegistry = new FinalizationRegistry(
|
|
async (options: { cbs: Map<number, Function>; effects: T.Effects }) => {
|
|
await options.effects.clearCallbacks({
|
|
only: Array.from(options.cbs.keys()),
|
|
})
|
|
},
|
|
)
|
|
|
|
export class CallbackHolder {
|
|
constructor(private effects?: T.Effects) {}
|
|
|
|
private callbacks = new Map<number, Function>()
|
|
private onLeaveContextCallbacks: Function[] = []
|
|
private children: Map<string, CallbackHolder> = new Map()
|
|
private newId() {
|
|
return CallbackIdCell.inc++
|
|
}
|
|
addCallback(callback?: Function) {
|
|
if (!callback) {
|
|
return
|
|
}
|
|
const id = this.newId()
|
|
console.error("adding callback", id)
|
|
this.callbacks.set(id, callback)
|
|
if (this.effects)
|
|
callbackRegistry.register(this, {
|
|
cbs: this.callbacks,
|
|
effects: this.effects,
|
|
})
|
|
return id
|
|
}
|
|
child(name: string): CallbackHolder {
|
|
this.removeChild(name)
|
|
const child = new CallbackHolder(this.effects)
|
|
this.children.set(name, child)
|
|
return child
|
|
}
|
|
|
|
getChild(name: string): CallbackHolder | null {
|
|
return this.children.get(name) || null
|
|
}
|
|
|
|
removeChild(name: string) {
|
|
const child = this.children.get(name)
|
|
if (child) {
|
|
child.leaveContext()
|
|
this.children.delete(name)
|
|
}
|
|
}
|
|
private getCallback(index: number): Function | undefined {
|
|
let callback = this.callbacks.get(index)
|
|
if (callback) this.callbacks.delete(index)
|
|
else {
|
|
for (let [_, child] of this.children) {
|
|
callback = child.getCallback(index)
|
|
if (callback) return callback
|
|
}
|
|
}
|
|
return callback
|
|
}
|
|
callCallback(index: number, args: any[]): Promise<unknown> {
|
|
const callback = this.getCallback(index)
|
|
if (!callback) return Promise.resolve()
|
|
return Promise.resolve()
|
|
.then(() => callback(...args))
|
|
.catch((e) => console.error("callback failed", e))
|
|
}
|
|
onLeaveContext(fn: Function) {
|
|
this.onLeaveContextCallbacks.push(fn)
|
|
}
|
|
leaveContext() {
|
|
for (let [_, child] of this.children) {
|
|
child.leaveContext()
|
|
}
|
|
this.children = new Map()
|
|
for (let fn of this.onLeaveContextCallbacks) {
|
|
try {
|
|
fn()
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
this.onLeaveContextCallbacks = []
|
|
}
|
|
}
|