Co-authored-by: Jason Woltje <jason@diversecanvas.com> Co-committed-by: Jason Woltje <jason@diversecanvas.com>
77 lines
2.7 KiB
TypeScript
77 lines
2.7 KiB
TypeScript
/**
|
|
* Connector registry (F4 Phase 1).
|
|
*
|
|
* A tiny extensible registry so connector implementations (Phase 2: tmux,
|
|
* Discord, Matrix) register a factory by kind and fleet core resolves one from
|
|
* roster config without branching on kind. Phase 1 ships the registry + the
|
|
* config→kind resolution; the connector factories land in Phase 2.
|
|
*/
|
|
|
|
import {
|
|
type ConnectorConfig,
|
|
type ConnectorKind,
|
|
type OrchestratorConnector,
|
|
DEFAULT_CONNECTOR_KIND,
|
|
} from './types.js';
|
|
|
|
/** The set of connector kinds the framework recognizes. */
|
|
export const KNOWN_CONNECTOR_KINDS: readonly ConnectorKind[] = ['tmux', 'discord', 'matrix'];
|
|
|
|
/** Type guard: is `value` a known connector kind? */
|
|
export function isKnownConnectorKind(value: unknown): value is ConnectorKind {
|
|
return typeof value === 'string' && (KNOWN_CONNECTOR_KINDS as readonly string[]).includes(value);
|
|
}
|
|
|
|
/**
|
|
* Resolve the connector kind from roster config. Absent config ⇒ the default
|
|
* (tmux) so existing rosters keep working unchanged (back-compat).
|
|
*/
|
|
export function resolveConnectorKind(config?: ConnectorConfig): ConnectorKind {
|
|
return config?.kind ?? DEFAULT_CONNECTOR_KIND;
|
|
}
|
|
|
|
/** A factory builds a live connector from its validated config. */
|
|
export type ConnectorFactory = (config: ConnectorConfig) => OrchestratorConnector;
|
|
|
|
/** Thrown when no factory is registered for a requested kind. */
|
|
export class ConnectorNotImplementedError extends Error {
|
|
constructor(public readonly kind: ConnectorKind) {
|
|
super(
|
|
`Connector "${kind}" is not implemented yet. ` +
|
|
`Register a factory via registerConnector('${kind}', …) (F4 Phase 2).`,
|
|
);
|
|
this.name = 'ConnectorNotImplementedError';
|
|
}
|
|
}
|
|
|
|
const registry = new Map<ConnectorKind, ConnectorFactory>();
|
|
|
|
/** Register a connector factory for a kind (idempotent — last registration wins). */
|
|
export function registerConnector(kind: ConnectorKind, factory: ConnectorFactory): void {
|
|
registry.set(kind, factory);
|
|
}
|
|
|
|
/** True when a factory is registered for `kind`. */
|
|
export function hasConnector(kind: ConnectorKind): boolean {
|
|
return registry.has(kind);
|
|
}
|
|
|
|
/**
|
|
* Build a connector from roster config. Throws `ConnectorNotImplementedError`
|
|
* when no factory is registered for the resolved kind (the Phase-1 default for
|
|
* every kind until Phase 2 registers them).
|
|
*/
|
|
export function createConnector(config?: ConnectorConfig): OrchestratorConnector {
|
|
const kind = resolveConnectorKind(config);
|
|
const factory = registry.get(kind);
|
|
if (!factory) {
|
|
throw new ConnectorNotImplementedError(kind);
|
|
}
|
|
return factory(config ?? { kind });
|
|
}
|
|
|
|
/** Test/runtime helper: drop all registrations. */
|
|
export function _resetConnectorRegistry(): void {
|
|
registry.clear();
|
|
}
|