// Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ import { watch } from 'vue' import type { OperationSubscriptionOptionsReturn, OperationSubscriptionsResult, WatchResultCallback, } from '#shared/types/server/apollo/handler.ts' import BaseHandler from './BaseHandler.ts' import type { FetchResult, OperationVariables } from '@apollo/client/core' import type { UseSubscriptionReturn } from '@vue/apollo-composable' import type { Ref, WatchStopHandle } from 'vue' export default class SubscriptionHandler< TResult = OperationSubscriptionsResult, TVariables extends OperationVariables = OperationVariables, > extends BaseHandler< TResult, TVariables, UseSubscriptionReturn > { public subscribed = false public options(): OperationSubscriptionOptionsReturn { return this.operationResult.options } public start(): void { this.operationResult.start() } public stop(): void { this.operationResult.stop() } public result(): Ref | undefined> { return this.operationResult.result } public onResult( callback: ( result: FetchResult< TResult, Record, Record >, ) => void, ) { this.operationResult.onResult(callback) } public async onSubscribed(): Promise | undefined> { return new Promise((resolve, reject) => { let errorUnsubscribe!: () => void let resultUnsubscribe!: () => void const onFirstResultLoaded = () => { resultUnsubscribe() errorUnsubscribe() } resultUnsubscribe = watch(this.result(), (result) => { this.subscribed = true // Remove the watchers again after the promise was resolved. onFirstResultLoaded() return resolve(result || null) }) errorUnsubscribe = watch(this.operationError(), (error) => { onFirstResultLoaded() return reject(error) }) }) } public watchOnResult( callback: WatchResultCallback, ): WatchStopHandle { return watch( this.result(), (result) => { if (!result) { return } callback(result) }, { // Needed for when the component is mounted after the first mount, in this case // result will already contain the data and the watch will otherwise not be triggered. immediate: true, }, ) } }