| 25 | |
| 26 | @Injectable() |
| 27 | export class WebhooksService { |
| 28 | private readonly logger = new Logger(WebhooksService.name); |
| 29 | |
| 30 | constructor( |
| 31 | private readonly repository: WebhookRepository, |
| 32 | private readonly deliveryRepository: WebhookDeliveryRepository, |
| 33 | private readonly workflowsService: WorkflowsService, |
| 34 | private readonly temporalService: TemporalService, |
| 35 | ) {} |
| 36 | |
| 37 | // Management methods (auth required) |
| 38 | |
| 39 | async list(auth: AuthContext | null): Promise<WebhookConfiguration[]> { |
| 40 | const organizationId = this.requireOrganizationId(auth); |
| 41 | const records = await this.repository.list({ organizationId }); |
| 42 | return records.map((r) => this.mapConfigurationRecord(r)); |
| 43 | } |
| 44 | |
| 45 | async get(auth: AuthContext | null, id: string): Promise<WebhookConfiguration> { |
| 46 | const organizationId = this.requireOrganizationId(auth); |
| 47 | const record = await this.repository.findById(id, { organizationId }); |
| 48 | if (!record) { |
| 49 | throw new NotFoundException(`Webhook ${id} not found`); |
| 50 | } |
| 51 | return this.mapConfigurationRecord(record); |
| 52 | } |
| 53 | |
| 54 | async create( |
| 55 | auth: AuthContext | null, |
| 56 | dto: { |
| 57 | workflowId: string; |
| 58 | workflowVersionId?: string; |
| 59 | name: string; |
| 60 | description?: string; |
| 61 | parsingScript: string; |
| 62 | expectedInputs: { |
| 63 | id: string; |
| 64 | label: string; |
| 65 | type: string; |
| 66 | required: boolean; |
| 67 | description?: string; |
| 68 | }[]; |
| 69 | }, |
| 70 | ): Promise<WebhookConfiguration> { |
| 71 | // Validate workflow exists and user has admin access |
| 72 | await this.workflowsService.ensureWorkflowAdminAccess(dto.workflowId, auth); |
| 73 | |
| 74 | // Get organization ID |
| 75 | const organizationId = this.requireOrganizationId(auth); |
| 76 | |
| 77 | // Generate unique webhook path |
| 78 | const webhookPath = this.generateWebhookPath(); |
| 79 | |
| 80 | // Validate expected inputs against workflow's entry point |
| 81 | await this.validateExpectedInputs(dto.workflowId, dto.expectedInputs, auth); |
| 82 | |
| 83 | const record = await this.repository.create({ |
| 84 | workflowId: dto.workflowId, |
nothing calls this directly
no outgoing calls
no test coverage detected