PR #3 introduced a circular-import temporal-dead-zone bug that didn't surface in unit tests but crashed the service at startup: src/index.ts imports './modules/index.js' for side effects → src/modules/interactive/index.ts calls registerResponseHandler() → that function is declared in src/index.ts → but src/index.ts's const responseHandlers = [] hasn't been initialized yet (we're in the middle of its module-init) → ReferenceError: Cannot access 'responseHandlers' before initialization Same issue for registerResponseHandler itself (the function reference resolves to undefined) and for onShutdown in the approvals module. Caught when the operator started the service and systemd flagged the process as crashing in auto-restart loop. Fix: extract responseHandlers + registerResponseHandler + shutdownCallbacks + onShutdown into src/response-registry.ts, which has no dependencies on src/index.ts or on modules. index.ts re-exports the same surface for any existing consumers; modules import directly from response-registry.js. The bug was latent because: - Unit tests import pieces, never src/index.ts's main() flow. - Host builds clean because TypeScript doesn't catch runtime circular init order. - Only surfaces when the ES module loader actually executes src/index.ts as the entry point. Verified: service boots on Linux host with approvals + interactive loaded; OneCLI handler starts via onDeliveryAdapterReady callback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
46 lines
1.4 KiB
TypeScript
46 lines
1.4 KiB
TypeScript
/**
|
|
* Response handler + shutdown callback registries.
|
|
*
|
|
* Extracted from index.ts so that modules calling `registerResponseHandler()`
|
|
* or `onShutdown()` at import time don't hit a TDZ error on the const-array
|
|
* declarations. index.ts imports src/modules/index.js for its side effects,
|
|
* which triggers module registrations that would otherwise happen before
|
|
* index.ts's own const initializers have run.
|
|
*
|
|
* Keep this file dependency-free (log.js is fine, but nothing from
|
|
* modules/* or index.ts itself). Any file imported here must not in turn
|
|
* import from src/index.ts, or the cycle returns.
|
|
*/
|
|
|
|
export interface ResponsePayload {
|
|
questionId: string;
|
|
value: string;
|
|
userId: string | null;
|
|
channelType: string;
|
|
platformId: string;
|
|
threadId: string | null;
|
|
}
|
|
|
|
export type ResponseHandler = (payload: ResponsePayload) => Promise<boolean>;
|
|
|
|
const responseHandlers: ResponseHandler[] = [];
|
|
|
|
export function registerResponseHandler(handler: ResponseHandler): void {
|
|
responseHandlers.push(handler);
|
|
}
|
|
|
|
export function getResponseHandlers(): readonly ResponseHandler[] {
|
|
return responseHandlers;
|
|
}
|
|
|
|
type ShutdownCallback = () => void | Promise<void>;
|
|
const shutdownCallbacks: ShutdownCallback[] = [];
|
|
|
|
export function onShutdown(cb: ShutdownCallback): void {
|
|
shutdownCallbacks.push(cb);
|
|
}
|
|
|
|
export function getShutdownCallbacks(): readonly ShutdownCallback[] {
|
|
return shutdownCallbacks;
|
|
}
|