chore: remove effects leftovers, dead SyncedState.set, add modules/resources skill refs

This commit is contained in:
edmand46
2026-09-17 14:15:37 +03:00
parent 4ab406c5cd
commit 34c53bbb68
14 changed files with 89 additions and 208 deletions
-7
View File
@@ -18,7 +18,6 @@ import type { RudderContext } from '../core/context.js';
import { request, type RequestContext } from '../transport/request.js';
import { createDefaultTokenStore } from '../token/TokenStore.js';
import { AuthService } from '../auth/AuthService.js';
import { EffectsCenter, type Effects } from '../effects/EffectsCenter.js';
import { SyncEngine } from '../state/SyncEngine.js';
import { PlayerDomain } from '../domains/PlayerDomain.js';
import { CatalogDomain } from '../domains/CatalogDomain.js';
@@ -33,7 +32,6 @@ export class RudderClient {
public readonly options: ResolvedRudderClientOptions;
public readonly auth: AuthService;
public readonly effects: Effects;
public readonly player: PlayerDomain;
public readonly catalog: CatalogDomain;
@@ -42,7 +40,6 @@ export class RudderClient {
public readonly modules: ModulesDomain;
private readonly resourcesDomain: ResourcesDomain;
private readonly effectsCenter: EffectsCenter;
private readonly syncEngine: SyncEngine;
private readonly ctx: RudderContext;
private readonly transportContext: RequestContext;
@@ -74,12 +71,8 @@ export class RudderClient {
},
};
this.effectsCenter = new EffectsCenter(this.options.onEffectError);
this.effects = this.effectsCenter;
this.ctx = {
options: this.options,
effects: this.effectsCenter,
request: <TResponse>(method: string, path: string, body?: unknown) =>
request<TResponse>(method, path, body, this.transportContext),
};
-6
View File
@@ -25,12 +25,6 @@ export interface RudderClientOptions {
/** Revision sync poll interval in milliseconds (default: 30000, ±20% jitter). */
syncIntervalMs?: number;
/**
* Called when an effect handler (or effect preparation) throws.
* Defaults to `console.error`.
*/
onEffectError?: (error: unknown) => void;
}
/** Client options with all defaults resolved — what `client.options` exposes. */
+1 -3
View File
@@ -1,9 +1,8 @@
import type { ResolvedRudderClientOptions } from '../client/RudderClientOptions.js';
import type { EffectsCenter } from '../effects/EffectsCenter.js';
/**
* RudderContext — the low-level surface every feature service depends on:
* the HTTP transport, client options, and the effects bus.
* the HTTP transport and client options.
*
* Built once by {@link RudderClient} and injected into each service. Services
* depend on this narrow interface instead of on the client itself, so the
@@ -11,6 +10,5 @@ import type { EffectsCenter } from '../effects/EffectsCenter.js';
*/
export interface RudderContext {
readonly options: ResolvedRudderClientOptions;
readonly effects: EffectsCenter;
request<TResponse>(method: string, path: string, body?: unknown): Promise<TResponse>;
}
-103
View File
@@ -1,103 +0,0 @@
export type EffectUnsubscribe = () => void;
export interface NotificationEffect {
readonly title: string;
readonly message: string;
done(): Promise<void>;
}
export interface WaitEffect {
readonly deadlineUtc: Date;
}
export interface ScenarioCompletedEffect {
readonly runId: string;
readonly scenarioSlug: string;
}
export interface ScenarioFailedEffect {
readonly runId: string;
readonly scenarioSlug: string;
readonly nodeId: string;
readonly error: Error;
}
type EffectHandler<TEffect> = (effect: TEffect) => void | Promise<void>;
export interface Effects {
onNotification(handler: EffectHandler<NotificationEffect>): EffectUnsubscribe;
onWait(handler: EffectHandler<WaitEffect>): EffectUnsubscribe;
onScenarioCompleted(handler: EffectHandler<ScenarioCompletedEffect>): EffectUnsubscribe;
onScenarioFailed(handler: EffectHandler<ScenarioFailedEffect>): EffectUnsubscribe;
}
export class EffectsCenter implements Effects {
private readonly notificationHandlers = new Set<EffectHandler<NotificationEffect>>();
private readonly waitHandlers = new Set<EffectHandler<WaitEffect>>();
private readonly scenarioCompletedHandlers = new Set<EffectHandler<ScenarioCompletedEffect>>();
private readonly scenarioFailedHandlers = new Set<EffectHandler<ScenarioFailedEffect>>();
constructor(
private readonly onError: (error: unknown) => void = (error) =>
console.error('[Rudder] Effect handler failed', error),
) {}
onNotification(handler: EffectHandler<NotificationEffect>): EffectUnsubscribe {
return this.addHandler(this.notificationHandlers, handler);
}
onWait(handler: EffectHandler<WaitEffect>): EffectUnsubscribe {
return this.addHandler(this.waitHandlers, handler);
}
onScenarioCompleted(handler: EffectHandler<ScenarioCompletedEffect>): EffectUnsubscribe {
return this.addHandler(this.scenarioCompletedHandlers, handler);
}
onScenarioFailed(handler: EffectHandler<ScenarioFailedEffect>): EffectUnsubscribe {
return this.addHandler(this.scenarioFailedHandlers, handler);
}
/** @internal */
emitNotification(effect: NotificationEffect): void {
this.emit(this.notificationHandlers, effect);
}
/** @internal */
emitWait(effect: WaitEffect): void {
this.emit(this.waitHandlers, effect);
}
/** @internal */
emitScenarioCompleted(effect: ScenarioCompletedEffect): void {
this.emit(this.scenarioCompletedHandlers, effect);
}
/** @internal */
emitScenarioFailed(effect: ScenarioFailedEffect): void {
this.emit(this.scenarioFailedHandlers, effect);
}
private addHandler<TEffect>(
handlers: Set<EffectHandler<TEffect>>,
handler: EffectHandler<TEffect>,
): EffectUnsubscribe {
handlers.add(handler);
return () => {
handlers.delete(handler);
};
}
private emit<TEffect>(
handlers: Set<EffectHandler<TEffect>>,
effect: TEffect,
): void {
for (const handler of handlers) {
try {
Promise.resolve(handler(effect)).catch((error) => this.onError(error));
} catch (error) {
this.onError(error);
}
}
}
}
-10
View File
@@ -45,16 +45,6 @@ export type { ResourcesDomain, ResourceHandle } from './domains/ResourcesDomain.
export type { StorageDomain } from './domains/StorageDomain.js';
export type { ProjectStorageDomain } from './domains/ProjectStorageDomain.js';
// Effects
export type {
Effects,
EffectUnsubscribe,
NotificationEffect,
WaitEffect,
ScenarioCompletedEffect,
ScenarioFailedEffect,
} from './effects/EffectsCenter.js';
// Generated wire types — the shapes returned by the observable state and
// handles, so consumers can name them instead of re-declaring mirrors.
export type { Player, PlayerProfile, PlayerProfileIdentity, Wallet } from './generated/player.js';
+2 -14
View File
@@ -76,8 +76,8 @@ export class SyncedState<T> {
if (this.listeners.size === 0 && this.snapshot.status === 'idle') return;
this.invalidateScheduled = true;
queueMicrotask(() => {
// A reset() or set() between scheduling and flushing cancels the reload
// (fresh data arrived, or the entity was dropped on logout).
// A reset() between scheduling and flushing cancels the reload
// (the entity was dropped on logout).
if (!this.invalidateScheduled) return;
this.invalidateScheduled = false;
if (this.listeners.size === 0 && this.snapshot.status === 'idle') return;
@@ -85,18 +85,6 @@ export class SyncedState<T> {
});
}
/**
* Applies externally-provided data (e.g. scenario config patches).
*
* @internal
*/
set(data: T): void {
this.generation++;
this.pending = undefined;
this.invalidateScheduled = false;
this.setSnapshot({ status: 'ready', data });
}
/**
* Drops all state back to idle (logout).
*