Creates the errands table (with conflictFiles column), errand-repository port interface, DrizzleErrandRepository adapter, and wires the repository into TRPCContext, the DI container, _helpers.ts requireErrandRepository guard, and the test harness. Also fixes pre-existing TS error in controller.test.ts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
239 lines
7.4 KiB
TypeScript
239 lines
7.4 KiB
TypeScript
/**
|
|
* Router Helpers
|
|
*
|
|
* Shared require*() helpers that validate context dependencies
|
|
* and throw TRPCError when a required dependency is missing.
|
|
*/
|
|
|
|
import { TRPCError } from '@trpc/server';
|
|
import type { TRPCContext } from '../context.js';
|
|
import type { TaskRepository } from '../../db/repositories/task-repository.js';
|
|
import type { MessageRepository } from '../../db/repositories/message-repository.js';
|
|
import type { InitiativeRepository } from '../../db/repositories/initiative-repository.js';
|
|
import type { PhaseRepository } from '../../db/repositories/phase-repository.js';
|
|
import type { PageRepository } from '../../db/repositories/page-repository.js';
|
|
import type { ProjectRepository } from '../../db/repositories/project-repository.js';
|
|
import type { AccountRepository } from '../../db/repositories/account-repository.js';
|
|
import type { ChangeSetRepository } from '../../db/repositories/change-set-repository.js';
|
|
import type { LogChunkRepository } from '../../db/repositories/log-chunk-repository.js';
|
|
import type { ConversationRepository } from '../../db/repositories/conversation-repository.js';
|
|
import type { ChatSessionRepository } from '../../db/repositories/chat-session-repository.js';
|
|
import type { ReviewCommentRepository } from '../../db/repositories/review-comment-repository.js';
|
|
import type { ErrandRepository } from '../../db/repositories/errand-repository.js';
|
|
import type { DispatchManager, PhaseDispatchManager } from '../../dispatch/types.js';
|
|
import type { CoordinationManager } from '../../coordination/types.js';
|
|
import type { BranchManager } from '../../git/branch-manager.js';
|
|
import type { ExecutionOrchestrator } from '../../execution/orchestrator.js';
|
|
import type { PreviewManager } from '../../preview/index.js';
|
|
import type { ProjectSyncManager } from '../../git/remote-sync.js';
|
|
|
|
export function requireAgentManager(ctx: TRPCContext) {
|
|
if (!ctx.agentManager) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Agent manager not available',
|
|
});
|
|
}
|
|
return ctx.agentManager;
|
|
}
|
|
|
|
export function requireTaskRepository(ctx: TRPCContext): TaskRepository {
|
|
if (!ctx.taskRepository) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Task repository not available',
|
|
});
|
|
}
|
|
return ctx.taskRepository;
|
|
}
|
|
|
|
export function requireMessageRepository(ctx: TRPCContext): MessageRepository {
|
|
if (!ctx.messageRepository) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Message repository not available',
|
|
});
|
|
}
|
|
return ctx.messageRepository;
|
|
}
|
|
|
|
export function requireDispatchManager(ctx: TRPCContext): DispatchManager {
|
|
if (!ctx.dispatchManager) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Dispatch manager not available',
|
|
});
|
|
}
|
|
return ctx.dispatchManager;
|
|
}
|
|
|
|
export function requireCoordinationManager(ctx: TRPCContext): CoordinationManager {
|
|
if (!ctx.coordinationManager) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Coordination manager not available',
|
|
});
|
|
}
|
|
return ctx.coordinationManager;
|
|
}
|
|
|
|
export function requireInitiativeRepository(ctx: TRPCContext): InitiativeRepository {
|
|
if (!ctx.initiativeRepository) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Initiative repository not available',
|
|
});
|
|
}
|
|
return ctx.initiativeRepository;
|
|
}
|
|
|
|
export function requirePhaseRepository(ctx: TRPCContext): PhaseRepository {
|
|
if (!ctx.phaseRepository) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Phase repository not available',
|
|
});
|
|
}
|
|
return ctx.phaseRepository;
|
|
}
|
|
|
|
export function requirePhaseDispatchManager(ctx: TRPCContext): PhaseDispatchManager {
|
|
if (!ctx.phaseDispatchManager) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Phase dispatch manager not available',
|
|
});
|
|
}
|
|
return ctx.phaseDispatchManager;
|
|
}
|
|
|
|
export function requirePageRepository(ctx: TRPCContext): PageRepository {
|
|
if (!ctx.pageRepository) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Page repository not available',
|
|
});
|
|
}
|
|
return ctx.pageRepository;
|
|
}
|
|
|
|
export function requireProjectRepository(ctx: TRPCContext): ProjectRepository {
|
|
if (!ctx.projectRepository) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Project repository not available',
|
|
});
|
|
}
|
|
return ctx.projectRepository;
|
|
}
|
|
|
|
export function requireAccountRepository(ctx: TRPCContext): AccountRepository {
|
|
if (!ctx.accountRepository) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Account repository not available',
|
|
});
|
|
}
|
|
return ctx.accountRepository;
|
|
}
|
|
|
|
export function requireChangeSetRepository(ctx: TRPCContext): ChangeSetRepository {
|
|
if (!ctx.changeSetRepository) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Change set repository not available',
|
|
});
|
|
}
|
|
return ctx.changeSetRepository;
|
|
}
|
|
|
|
export function requireLogChunkRepository(ctx: TRPCContext): LogChunkRepository {
|
|
if (!ctx.logChunkRepository) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Log chunk repository not available',
|
|
});
|
|
}
|
|
return ctx.logChunkRepository;
|
|
}
|
|
|
|
export function requireBranchManager(ctx: TRPCContext): BranchManager {
|
|
if (!ctx.branchManager) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Branch manager not available',
|
|
});
|
|
}
|
|
return ctx.branchManager;
|
|
}
|
|
|
|
export function requireExecutionOrchestrator(ctx: TRPCContext): ExecutionOrchestrator {
|
|
if (!ctx.executionOrchestrator) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Execution orchestrator not available',
|
|
});
|
|
}
|
|
return ctx.executionOrchestrator;
|
|
}
|
|
|
|
export function requirePreviewManager(ctx: TRPCContext): PreviewManager {
|
|
if (!ctx.previewManager) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Preview manager not available',
|
|
});
|
|
}
|
|
return ctx.previewManager;
|
|
}
|
|
|
|
export function requireConversationRepository(ctx: TRPCContext): ConversationRepository {
|
|
if (!ctx.conversationRepository) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Conversation repository not available',
|
|
});
|
|
}
|
|
return ctx.conversationRepository;
|
|
}
|
|
|
|
export function requireChatSessionRepository(ctx: TRPCContext): ChatSessionRepository {
|
|
if (!ctx.chatSessionRepository) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Chat session repository not available',
|
|
});
|
|
}
|
|
return ctx.chatSessionRepository;
|
|
}
|
|
|
|
export function requireReviewCommentRepository(ctx: TRPCContext): ReviewCommentRepository {
|
|
if (!ctx.reviewCommentRepository) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Review comment repository not available',
|
|
});
|
|
}
|
|
return ctx.reviewCommentRepository;
|
|
}
|
|
|
|
export function requireProjectSyncManager(ctx: TRPCContext): ProjectSyncManager {
|
|
if (!ctx.projectSyncManager) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Project sync manager not available',
|
|
});
|
|
}
|
|
return ctx.projectSyncManager;
|
|
}
|
|
|
|
export function requireErrandRepository(ctx: TRPCContext): ErrandRepository {
|
|
if (!ctx.errandRepository) {
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Errand repository not available',
|
|
});
|
|
}
|
|
return ctx.errandRepository;
|
|
}
|