{"version":3,"sources":["../src/utils/wsClient.ts"],"names":["ApolloClient","split","fromPromise","setContext","onError","GraphQLWsLink","getMainDefinition","createUploadLink","createClient","UNAUTHENTICATED","WsClient","accountApi","onRefreshTokenError","refreshTokens","refreshToken","tokenStore","error","eventsApi","EVENTS","NaluriChatError","accessToken","_","headers","wsUrl","webSocketLink","httpUploadLink","query","definition","graphQLErrors","networkError","operation","forward","errors","message","locations","path","extensions","value","oldHeaders","authLink","wsLink","uploadHttpLink","terminatingLink","chatCache_default","version_default"],"mappings":"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","sourcesContent":["import {\n  ApolloClient,\n  split,\n  fromPromise,\n  NormalizedCacheObject,\n  type ServerError,\n} from '@apollo/client/core';\nimport { setContext } from '@apollo/client/link/context';\nimport { onError } from '@apollo/client/link/error';\nimport { GraphQLWsLink } from '@apollo/client/link/subscriptions';\nimport { getMainDefinition } from '@apollo/client/utilities';\nimport { createUploadLink } from 'apollo-upload-client';\nimport { createClient } from 'graphql-ws';\nimport { AccountApi } from '@/api/account.api';\nimport { eventsApi, EVENTS } from '@/api/events.api';\nimport cache from '@/config/chatCache';\n// import { EventManager } from '@/core/eventManager';\nimport { NaluriChatError } from '@/errors';\nimport { tokenStore, AuthTokens } from '@/utils/tokenStore';\nimport { wsUrl } from '@/utils/wsURL';\nimport version from './version';\n\nconst UNAUTHENTICATED = 'UNAUTHENTICATED';\n\nexport class WsClient {\n  private apolloClient: ApolloClient<NormalizedCacheObject>;\n  constructor(\n    private readonly accountApi: AccountApi,\n    private readonly onRefreshTokenError?: () => Promise<void>,\n    private readonly refreshTokens?: () => Promise<AuthTokens>\n  ) {\n    this.createClient();\n    this.refreshTokens = async () => {\n      const refreshToken = tokenStore.getItem('refreshToken');\n      try {\n        return await this.accountApi.refresh(refreshToken);\n      } catch (error) {\n        if (eventsApi.isReady())\n          eventsApi.track(EVENTS.REFRESH_ERROR, {\n            error,\n            action: '@chatApiInstance::refreshTokens',\n          });\n\n        if (this.onRefreshTokenError) {\n          await this.onRefreshTokenError();\n        }\n\n        throw new NaluriChatError({\n          message: 'Failed to refresh token',\n          code: '4009',\n        });\n      }\n    };\n  }\n\n  public instance() {\n    return this.apolloClient;\n  }\n\n  private _authLink(accessToken) {\n    return setContext((_, { headers }) => {\n      return {\n        headers: {\n          ...headers,\n          Authorization: `Bearer ${accessToken}`,\n          'x-api-key': this.accountApi.getApiKey(),\n        },\n      };\n    });\n  }\n\n  private _websocketLink(accessToken) {\n    return new GraphQLWsLink(\n      createClient({\n        url: `${wsUrl(this.accountApi.getApiUrl())}/graphql`,\n        connectionParams: {\n          authorization: `Bearer ${accessToken}`,\n          'x-api-key': this.accountApi.getApiKey(),\n        },\n        shouldRetry: () => true,\n        retryAttempts: Infinity,\n        keepAlive: 10000, // 10 seconds\n      })\n    );\n  }\n\n  private _terminatingLink(webSocketLink, httpUploadLink) {\n    return split(\n      ({ query }) => {\n        const definition = getMainDefinition(query);\n        return (\n          definition.kind === 'OperationDefinition' &&\n          definition.operation === 'subscription'\n        );\n      },\n      webSocketLink,\n      httpUploadLink\n    );\n  }\n\n  private _uploadhttpLink() {\n    return createUploadLink({\n      uri: `${this.accountApi.getApiUrl()}/graphql`,\n    });\n  }\n\n  private _errorLink = () => {\n    return onError(({ graphQLErrors, networkError, operation, forward }) => {\n      if (graphQLErrors)\n        return this._handleGraphQLErrors(graphQLErrors, operation, forward);\n      if (networkError) {\n        return this._handleNetworkError(networkError, operation, forward);\n      }\n      return forward(operation);\n    });\n  };\n\n  private _handleGraphQLErrors(errors, operation, forward) {\n    errors.forEach(({ message, locations, path, extensions }) => {\n      console.debug(\n        `[GraphQL error]: Message: ${message}, Location: ${JSON.stringify(\n          locations\n        )}, Path: ${path}, Extension: ${extensions}`\n      );\n\n      if (extensions?.code === UNAUTHENTICATED) {\n        // this.eventManager?.emit('token_expired');\n\n        if (this.refreshTokens) {\n          return fromPromise(this.refreshTokens())\n            .filter(\n              (value) => !!Object.keys(value).length && !!value?.accessToken\n            )\n            .flatMap((value) => {\n              const oldHeaders = operation.getContext().headers;\n\n              operation.setContext({\n                headers: {\n                  ...oldHeaders,\n                  authorization: `Bearer ${value.accessToken}`,\n                },\n              });\n\n              this.refreshClient(value.accessToken);\n\n              return forward(operation);\n            });\n        }\n      }\n      return forward(operation);\n    });\n  }\n\n  private _handleNetworkError(error, operation, forward) {\n    console.log(`[Network error]: ${error}`);\n    if (error.name === 'ServerError') {\n      const serverError = error as ServerError;\n\n      if (serverError.response.status === 401) {\n        if (this.refreshTokens) {\n          return fromPromise(this.refreshTokens())\n            .filter(\n              (value) => !!Object.keys(value).length && !!value?.accessToken\n            )\n            .flatMap((value) => {\n              const oldHeaders = operation.getContext().headers;\n\n              operation.setContext({\n                headers: {\n                  ...oldHeaders,\n                  authorization: `Bearer ${value.accessToken}`,\n                },\n              });\n\n              this.refreshClient(value.accessToken);\n\n              return forward(operation);\n            });\n        }\n      }\n    }\n    return forward(operation);\n  }\n\n  public refreshClient(accessToken: string) {\n    tokenStore.setItem('accessToken', accessToken);\n    this.createClient();\n  }\n\n  public createClient(): void {\n    const accessToken = tokenStore.getItem('accessToken');\n    const authLink = this._authLink(accessToken);\n    const wsLink = this._websocketLink(accessToken);\n    const uploadHttpLink = this._uploadhttpLink();\n\n    const errorLink = this._errorLink();\n    const httpUploadLink = errorLink.concat(\n      authLink.concat(uploadHttpLink as any)\n    );\n\n    const terminatingLink = this._terminatingLink(wsLink, httpUploadLink);\n\n    if (this.apolloClient) this.apolloClient.stop();\n\n    this.apolloClient = new ApolloClient({\n      link: terminatingLink,\n      cache: cache,\n      headers: {\n        authorization: `Bearer ${accessToken}`,\n        'x-api-key': this.accountApi.getApiKey(),\n        'User-Agent': `Naluri Chat SDK /JS (${version}})`,\n        'x-nl-sdk-version': version,\n      },\n      defaultOptions: {\n        watchQuery: {\n          refetchWritePolicy: 'merge',\n        },\n      },\n    });\n  }\n}\n"]}