feat(agent-browser): add opt-in preview data injection
This commit is contained in:
@@ -62,6 +62,10 @@ export type PreviewDataSessionInvalidationReason =
|
||||
| 'replaced'
|
||||
| 'manual';
|
||||
|
||||
export type PreviewDataSessionInvalidationListener = (
|
||||
reason: PreviewDataSessionInvalidationReason,
|
||||
) => void;
|
||||
|
||||
export type PreviewDataSessionOpenInput = {
|
||||
projectPath: string;
|
||||
origin: string;
|
||||
@@ -232,6 +236,7 @@ export class PreviewDataSessionManager {
|
||||
private readonly getAccountBinding: typeof getWorksSquareAccountBinding;
|
||||
private readonly isCurrentAccountBinding: typeof isCurrentWorksSquareAccountBinding;
|
||||
private readonly unsubscribeWorksSession: () => void;
|
||||
private readonly invalidationListeners = new Set<PreviewDataSessionInvalidationListener>();
|
||||
private session: InternalSession | null = null;
|
||||
private boundAccountBinding: WorksSquareAccountBinding | null;
|
||||
private disposed = false;
|
||||
@@ -285,6 +290,7 @@ export class PreviewDataSessionManager {
|
||||
throw new PreviewDataSessionError('runtime_unavailable', 'Preview data runtime is unavailable');
|
||||
}
|
||||
const token = tokenBytes.toString('base64url');
|
||||
this.invalidate('replaced');
|
||||
const snapshot: PreviewDataSessionSnapshot = Object.freeze({
|
||||
projectPath: active.path,
|
||||
projectId: active.projectId,
|
||||
@@ -307,6 +313,14 @@ export class PreviewDataSessionManager {
|
||||
return this.session?.snapshot ?? null;
|
||||
}
|
||||
|
||||
subscribeInvalidation(listener: PreviewDataSessionInvalidationListener): () => void {
|
||||
if (this.disposed) return () => undefined;
|
||||
this.invalidationListeners.add(listener);
|
||||
return () => {
|
||||
this.invalidationListeners.delete(listener);
|
||||
};
|
||||
}
|
||||
|
||||
getInjectionValue(hostPort = this.hostPort): PreviewDataInjectionValue | null {
|
||||
const session = this.session;
|
||||
if (!session || !Number.isSafeInteger(hostPort) || hostPort < 1 || hostPort > 65_535) {
|
||||
@@ -409,8 +423,16 @@ export class PreviewDataSessionManager {
|
||||
}
|
||||
}
|
||||
|
||||
invalidate(_reason: PreviewDataSessionInvalidationReason = 'manual'): void {
|
||||
invalidate(reason: PreviewDataSessionInvalidationReason = 'manual'): void {
|
||||
if (!this.session) return;
|
||||
this.session = null;
|
||||
for (const listener of this.invalidationListeners) {
|
||||
try {
|
||||
listener(reason);
|
||||
} catch {
|
||||
// A browser cleanup observer must not interrupt token invalidation.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
@@ -418,6 +440,7 @@ export class PreviewDataSessionManager {
|
||||
this.disposed = true;
|
||||
this.invalidate('main_shutdown');
|
||||
this.unsubscribeWorksSession();
|
||||
this.invalidationListeners.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user