Files
start-os/container-runtime/src/Models/CallbackHolder.ts
Aiden McClelland 68955c29cb add transformers to file helpers (#2922)
* 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
2025-05-06 11:04:11 -06:00

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 = []
}
}