import { Resolver, Mutation, Query, Arg, Ctx, Int, Directive, Field, ObjectType } from 'type-graphql' import { labelStudioApi } from '../../utils/label-studio-api-client.js' @ObjectType({ description: 'Webhook information' }) export class Webhook { @Field(type => Int, { description: 'Webhook ID' }) id: number @Field({ description: 'Webhook URL' }) url: string @Field(type => Int, { description: 'Project ID' }) projectId: number @Field({ description: 'Is webhook active' }) isActive: boolean @Field({ description: 'Send payload with webhook' }) sendPayload: boolean } @Resolver() export class WebhookManagement { /** * Register webhook for a project */ @Mutation(returns => Webhook, { description: 'Register webhook for Label Studio project to receive real-time updates' }) @Directive('@privilege(category: "label-studio", privilege: "mutation")') async registerLabelStudioWebhook( @Arg('projectId', type => Int) projectId: number, @Ctx() context: ResolverContext ): Promise { try { // Get Things-Factory server URL from environment or request const serverUrl = process.env.SERVER_URL || 'http://localhost:3000' const webhookUrl = `${serverUrl}/label-studio/webhook` const webhook = await labelStudioApi.createWebhook({ project: projectId, url: webhookUrl, send_payload: true, send_for_all_actions: true, headers: { 'Content-Type': 'application/json' } }) return { id: webhook.id, url: webhook.url, projectId: webhook.project, isActive: webhook.is_active || true, sendPayload: webhook.send_payload || true } } catch (error) { console.error(`Failed to register webhook for project ${projectId}:`, error) throw new Error(`Failed to register webhook: ${error.message}`) } } /** * Get webhooks for a project */ @Query(returns => [Webhook], { description: 'Get all webhooks registered for a Label Studio project' }) @Directive('@privilege(category: "label-studio", privilege: "query")') async labelStudioWebhooks( @Arg('projectId', type => Int) projectId: number, @Ctx() context: ResolverContext ): Promise { try { const webhooks = await labelStudioApi.getWebhooks(projectId) return webhooks.map(webhook => ({ id: webhook.id, url: webhook.url, projectId: webhook.project, isActive: webhook.is_active || true, sendPayload: webhook.send_payload || true })) } catch (error) { console.error(`Failed to fetch webhooks for project ${projectId}:`, error) throw new Error(`Failed to fetch webhooks: ${error.message}`) } } /** * Delete webhook */ @Mutation(returns => Boolean, { description: 'Delete a webhook' }) @Directive('@privilege(category: "label-studio", privilege: "mutation")') async deleteLabelStudioWebhook( @Arg('webhookId', type => Int) webhookId: number, @Ctx() context: ResolverContext ): Promise { try { await labelStudioApi.deleteWebhook(webhookId) return true } catch (error) { console.error(`Failed to delete webhook ${webhookId}:`, error) throw new Error(`Failed to delete webhook: ${error.message}`) } } }