27 lines
2.6 KiB
TypeScript
27 lines
2.6 KiB
TypeScript
import { AppFocusManager, type AppFocusSnapshot } from "@/runtime/app-management/app-focus-manager";
|
|
import { AppInstanceManager, type AppInstanceRecord, type AppInstanceSnapshot } from "@/runtime/app-management/app-instance-manager";
|
|
import type { AppScope } from "@/runtime/app-management/app-registry";
|
|
|
|
export type AppWorkspaceSnapshot = { version: 1; instances: AppInstanceSnapshot; focus: AppFocusSnapshot };
|
|
|
|
/** Coordinates legal transitions and restoration; it never mounts a DOM Host. */
|
|
export class AppLifecycleManager {
|
|
public readonly instances = new AppInstanceManager();
|
|
public readonly focus = new AppFocusManager();
|
|
public start(input: { instance_id: string; app_scope: AppScope; conversation_id?: string; app_session_id?: string; parent_instance_id?: string; continued_from_app_session_id?: string }, now: string): AppInstanceRecord { return this.instances.create(input, now); }
|
|
public foreground(instanceID: string, now: string): AppInstanceRecord {
|
|
const current = this.instances.get(instanceID); if (!current) throw new Error("Unknown App Instance.");
|
|
const prior = this.focus.foreground();
|
|
if (prior && prior !== instanceID) { const record = this.instances.get(prior); if (record?.state === "foreground") this.instances.transition(prior, "background", now); }
|
|
const next = this.instances.transition(instanceID, "foreground", now); this.focus.push(instanceID); return next;
|
|
}
|
|
public background(instanceID: string, now: string): AppInstanceRecord { const next = this.instances.transition(instanceID, "background", now); if (this.focus.foreground() === instanceID) this.focus.remove(instanceID); return next; }
|
|
public suspend(instanceID: string, now: string): AppInstanceRecord { const next = this.instances.transition(instanceID, "suspended", now); if (this.focus.foreground() === instanceID) this.focus.remove(instanceID); return next; }
|
|
public close(instanceID: string, now: string, error?: string): AppInstanceRecord | undefined {
|
|
const current = this.instances.get(instanceID); if (!current || current.state === "stopped" || current.state === "failed") return current;
|
|
this.instances.transition(instanceID, "stopping", now); const finished = this.instances.transition(instanceID, error ? "failed" : "stopped", now, error); this.focus.remove(instanceID); return finished;
|
|
}
|
|
public restore(snapshot: AppWorkspaceSnapshot): void { this.instances.restore(snapshot?.instances); this.focus.restore(snapshot?.focus, id => Boolean(this.instances.get(id))); }
|
|
public snapshot(): AppWorkspaceSnapshot { return { version: 1, instances: this.instances.snapshot(), focus: this.focus.snapshot() }; }
|
|
}
|