Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Error calling module function" with WebSocketLink (apollo-link-ws) #1285

Open
darkbasic opened this issue Apr 16, 2018 · 11 comments
Open

"Error calling module function" with WebSocketLink (apollo-link-ws) #1285

darkbasic opened this issue Apr 16, 2018 · 11 comments

Comments

@darkbasic
Copy link

https://github.com/darkbasic/nativescript-repro2/blob/master/app/app.module.ts

    const subscriptionLink = new WebSocketLink({
      uri: 'ws://localhost:3000/subscriptions',
      options: {
        reconnect: true,
      },
      webSocketImpl: SocketIO,
    });

3

Full Error: https://paste.ubuntu.com/p/NrffmYWRDJ/

Removing the previous snippet of code fixes the error.

I think it could be related to #1284

@tsonevn
Copy link
Contributor

tsonevn commented Apr 17, 2018

Hi @darkbasic,
The apollo-link-ws plugin seems not to be supported in NativeScript due to some DOM related dependencies. For using WebSocket's in NativeScript, you can use nativescript-websockets plugin.

@darkbasic
Copy link
Author

Hi @tsonevn

    const subscriptionLink = new WebSocketLink({
      uri: 'ws://localhost:3000/subscriptions',
      options: {
        reconnect: true,
      },
      webSocketImpl: SocketIO,
    });

As you can see from the previous code snippet I'm using SocketIO as webSocketImpl.
I also tried with nativescript-websockets without luck.

I cannot use plain nativescript-websockets (I still need to pass through WebSocketLink) because the websocket will be used for Graphql subscriptions.

@darkbasic darkbasic reopened this Apr 30, 2018
@darkbasic
Copy link
Author

export * from './server'; is the culprit:
https://github.com/apollographql/subscriptions-transport-ws/blob/master/src/index.ts

Even if we don't use nor even import SubscriptionServer, this is enough to trigger the error.
Commenting out export * from './server'; from subscriptions-transport-ws is enough to fix the issue, but this is not a solution I can pursue with the upstream, because they need to export it for node.js users.

If they'll accept such a PR I could export ony the client in a different namespace like subscriptions-transport-ws/client, but this is a workaround. Why does Nativescript trigger errors for a class which I didn't even import?

@parktheredcar
Copy link

Not directly an angular issue but more of an apollo-link-ws issue. At any rate, this can be worked around using webpack's NormalModuleReplacementPlugin to swap in nativescript-websockets for /^ws$/. Not perfect, but it beats hacking apart a copy of apollo-link-ws.

@tafelnl
Copy link

tafelnl commented Nov 21, 2019

@darkbasic

Thanks for sharing. One question: which websocket implementation did you end up using? SocketIO, nativescript or the default?

@Richard095
Copy link

HI recently I have the same probleme, Im trying to implement, realtime with apollo client using angular, and at configure the subscriptions, getting ERROR, there is solution to this problem. I,m lost :(, how alternative i try to use https://market.nativescript.org/plugins/nativescript-subscriptions-transport-ws, but i didnt had success.

@dudipsh
Copy link

dudipsh commented Jun 27, 2020

@Richard095
Hey, did you found a solution ?

@Richard095
Copy link

@Richard095
Hey, did you found a solution ?

Hi, No, by time issues, i decided to change to SocketIO,It was a good option on Real-Time.

@Richard095
Copy link

This seems to be the only way;)

Apparently yes, I had that problem a long time ago, however I think SocketIO is also going well. Only in this way was I able to continue with my project.

@dudipsh
Copy link

dudipsh commented Feb 23, 2021

@Richard095, @darkbasic, @NickIliev
Half a year later ...
It works for me!!

webpack.config.js

 plugins: [
      // Define useful constants like TNS_WEBPACK
      new webpack.NormalModuleReplacementPlugin(
          /^ws$/,
          'nativescript-websockets'
      ),

main.ts

const WS = require('nativescript-websockets');
var WebSocket = require('nativescript-websockets');

graphql.module.ts

import {NgModule, NO_ERRORS_SCHEMA} from '@angular/core';
import {NativeScriptHttpClientModule, NativeScriptModule} from "@nativescript/angular";

import {HTTP_INTERCEPTORS, HttpClient, HttpClientModule, HttpHeaders} from '@angular/common/http';

// @ts-ignore
import {Apollo, APOLLO_OPTIONS, ApolloModule} from 'apollo-angular';
import {Subject} from 'rxjs';
import {WebSocketLink} from "@apollo/client/link/ws";

import {RouterModule} from "@angular/router";
import {tap} from "rxjs/internal/operators";

import {getMainDefinition} from '@apollo/client/utilities';

const uri = 'http://192.168.1.21:3000/graphql';
const GRAPHQL_ENDPOINT = 'ws://192.168.1.21:3000/graphql';


const errorSubject = new Subject<any>();
const getErrorSubject = () => errorSubject.asObservable();
import {HttpLink} from 'apollo-angular/http';

import {ApolloLink, InMemoryCache, split} from '@apollo/client/core';
import {onError} from "@apollo/client/link/error";
import {RetryLink} from "@apollo/client/link/retry";

const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiZW1haWwiOiJkdWRpcHNoQGdtYWlsLmNvbSIsInZlcmlmaWVkIjp0cnVlLCJyb2xlcyI6W3siaWQiOjEsIm5hbWUiOiJERUZBVUxUX1JPTEVfQURNSU4iLCJkZXNjcmlwdGlvbiI6bnVsbCwicmVhZCI6WyIyMTQ3NDE4MDc1IiwiOCJdLCJ1cGRhdGUiOlsiMjE0NzQ4MzYwMSIsIjgiXSwiZGVzdHJveSI6WyIyMTQ3NDE4MDc1IiwiOCJdLCJyZWFkT3RoZXIiOlsiMjE0NzQ4MzYwMSIsIjgiXSwidXBkYXRlT3RoZXIiOlsiMjE0NzQxODA3NSIsIjgiXSwiZGVzdHJveU90aGVyIjpbIjIxNDc0MTgwNzUiLCI4Il0sImFwcGx5T25PdGhlcnMiOmZhbHNlLCJyb2xlTGV2ZWwiOjR9XSwibGVnYWxOYW1lIjoiRHVkaSBQYXJ0dXNoIiwiYWNjb3VudElkIjoxLCJhY2Nlc3NMZXZlbCI6NCwiYnVja2V0TmFtZSI6Ii90aW1lLXRhbGstYnVja2V0cy1jb21wYW55LXRlc3Rjb21wMSIsImVtcGxveWVlQ2hhdElkIjoiNjAzMjIxY2JkZWE5MjM4OGY5OTFiODI4IiwiY2hhdEFwcElkIjoiNjAzMjIxY2JkZWE5MjM4OGY5OTFiODI1IiwiY2hhdEJvdElkIjoiNjAzMjIxY2JkZWE5MjM4OGY5OTFiODI2IiwibXlDaGFubmVsSWQiOiI2MDMyMjFjY2RlYTkyMzg4Zjk5MWI4MmMiLCJpYXQiOjE2MTM5MDQ2NTIsImV4cCI6MTYxNDUwOTQ1Mn0.ISt0akAnQn6Adjd-nYXHcyapRT7zAwkcBIvz3s31gGs";

const HTTP_STATUS = {
    NO_CONNECTION: 0,
    INTERNAL_SERVER_ERROR: 500,
    SERVICE_UNAVAILABLE: 503,
    GATEWAY_TIMEOUT: 504,
    BAD_GATEWAY: 502,
    UNAUTHORIZED: 401,
    FORBIDDEN: 403,
    OK: 200,
    CREATED: 201,
};
@NgModule({
    imports: [
        RouterModule,
        NativeScriptHttpClientModule,
    ],
    providers: [],
    schemas: [
        NO_ERRORS_SCHEMA
    ]

})


export class GraphQLModule {
    constructor(
        apollo: Apollo,
        httpLink: HttpLink,
    ) {
        const http = httpLink.create({
            uri
        });
        const error = onError(({networkError, graphQLErrors}) => {
            console.log('ERROR@@@@')
            console.log(networkError)
            console.log(graphQLErrors)
        })

        const wsClient = new WebSocketLink({
            uri: 'ws://192.168.1.21:3000/graphql',
            options: {
                reconnect: true,
                connectionParams: {
                    authorization: token,
                },
            },
            connectionParams: async () => {
                return {
                    authorization: token
                };
            },
            webSocketImpl: WebSocket,
            reconnectionAttempts: 99,
        });
        const retryLink = new RetryLink({
            delay: {
                initial: 1000,
                max: Infinity,
            },
            attempts: {
                max: 10,
                retryIf: (error) => {
                    console.log(error)
                    return error.status === HTTP_STATUS.SERVICE_UNAVAILABLE ||
                        error.status === HTTP_STATUS.GATEWAY_TIMEOUT
                }
            },
        });
        const auth = new ApolloLink((operation, forward) => {
            operation.setContext({
                headers: new HttpHeaders().set('authorization', `${token}`),
            });

            return forward(operation);
        });

        const link = split(
            ({query}) => {
                const {kind, operation}: any = getMainDefinition(query);
                return kind === 'OperationDefinition' && operation === 'subscription';
            },
            wsClient,
            auth.concat(http)
        );
        getErrorSubject().subscribe((data) => {
            console.log(data)

        }, (error) => console.log(error));

        apollo.create({
            link: ApolloLink.from([retryLink, link]),
            cache: new InMemoryCache({
                addTypename: false,
                dataIdFromObject: (object: any) => object.id
            }),
            defaultOptions: {
                watchQuery: {
                    errorPolicy: 'all'
                }
            }
        });


    }
}




`

@NazoSnare
Copy link

@Richard095, @darkbasic, @NickIliev
Half a year later ...
It works for me!!

main.ts

const WS = require('nativescript-websockets');
var WebSocket = require('nativescript-websockets');

graphql.module.ts

import {NgModule, NO_ERRORS_SCHEMA} from '@angular/core';
import {NativeScriptHttpClientModule, NativeScriptModule} from "@nativescript/angular";

import {HTTP_INTERCEPTORS, HttpClient, HttpClientModule, HttpHeaders} from '@angular/common/http';

// @ts-ignore
import {Apollo, APOLLO_OPTIONS, ApolloModule} from 'apollo-angular';
import {Subject} from 'rxjs';
import {WebSocketLink} from "@apollo/client/link/ws";

import {RouterModule} from "@angular/router";
import {tap} from "rxjs/internal/operators";

import {getMainDefinition} from '@apollo/client/utilities';

const uri = 'http://192.168.1.21:3000/graphql';
const GRAPHQL_ENDPOINT = 'ws://192.168.1.21:3000/graphql';


const errorSubject = new Subject<any>();
const getErrorSubject = () => errorSubject.asObservable();
import {HttpLink} from 'apollo-angular/http';

import {ApolloLink, InMemoryCache, split} from '@apollo/client/core';
import {onError} from "@apollo/client/link/error";
import {RetryLink} from "@apollo/client/link/retry";

const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiZW1haWwiOiJkdWRpcHNoQGdtYWlsLmNvbSIsInZlcmlmaWVkIjp0cnVlLCJyb2xlcyI6W3siaWQiOjEsIm5hbWUiOiJERUZBVUxUX1JPTEVfQURNSU4iLCJkZXNjcmlwdGlvbiI6bnVsbCwicmVhZCI6WyIyMTQ3NDE4MDc1IiwiOCJdLCJ1cGRhdGUiOlsiMjE0NzQ4MzYwMSIsIjgiXSwiZGVzdHJveSI6WyIyMTQ3NDE4MDc1IiwiOCJdLCJyZWFkT3RoZXIiOlsiMjE0NzQ4MzYwMSIsIjgiXSwidXBkYXRlT3RoZXIiOlsiMjE0NzQxODA3NSIsIjgiXSwiZGVzdHJveU90aGVyIjpbIjIxNDc0MTgwNzUiLCI4Il0sImFwcGx5T25PdGhlcnMiOmZhbHNlLCJyb2xlTGV2ZWwiOjR9XSwibGVnYWxOYW1lIjoiRHVkaSBQYXJ0dXNoIiwiYWNjb3VudElkIjoxLCJhY2Nlc3NMZXZlbCI6NCwiYnVja2V0TmFtZSI6Ii90aW1lLXRhbGstYnVja2V0cy1jb21wYW55LXRlc3Rjb21wMSIsImVtcGxveWVlQ2hhdElkIjoiNjAzMjIxY2JkZWE5MjM4OGY5OTFiODI4IiwiY2hhdEFwcElkIjoiNjAzMjIxY2JkZWE5MjM4OGY5OTFiODI1IiwiY2hhdEJvdElkIjoiNjAzMjIxY2JkZWE5MjM4OGY5OTFiODI2IiwibXlDaGFubmVsSWQiOiI2MDMyMjFjY2RlYTkyMzg4Zjk5MWI4MmMiLCJpYXQiOjE2MTM5MDQ2NTIsImV4cCI6MTYxNDUwOTQ1Mn0.ISt0akAnQn6Adjd-nYXHcyapRT7zAwkcBIvz3s31gGs";

const HTTP_STATUS = {
    NO_CONNECTION: 0,
    INTERNAL_SERVER_ERROR: 500,
    SERVICE_UNAVAILABLE: 503,
    GATEWAY_TIMEOUT: 504,
    BAD_GATEWAY: 502,
    UNAUTHORIZED: 401,
    FORBIDDEN: 403,
    OK: 200,
    CREATED: 201,
};
@NgModule({
    imports: [
        RouterModule,
        NativeScriptHttpClientModule,
    ],
    providers: [],
    schemas: [
        NO_ERRORS_SCHEMA
    ]

})


export class GraphQLModule {
    constructor(
        apollo: Apollo,
        httpLink: HttpLink,
    ) {
        const http = httpLink.create({
            uri
        });
        const error = onError(({networkError, graphQLErrors}) => {
            console.log('ERROR@@@@')
            console.log(networkError)
            console.log(graphQLErrors)
        })

        const wsClient = new WebSocketLink({
            uri: 'ws://192.168.1.21:3000/graphql',
            options: {
                reconnect: true,
                connectionParams: {
                    authorization: token,
                },
            },
            connectionParams: async () => {
                return {
                    authorization: token
                };
            },
            webSocketImpl: WebSocket,
            reconnectionAttempts: 99,
        });
        const retryLink = new RetryLink({
            delay: {
                initial: 1000,
                max: Infinity,
            },
            attempts: {
                max: 10,
                retryIf: (error) => {
                    console.log(error)
                    return error.status === HTTP_STATUS.SERVICE_UNAVAILABLE ||
                        error.status === HTTP_STATUS.GATEWAY_TIMEOUT
                }
            },
        });
        const auth = new ApolloLink((operation, forward) => {
            operation.setContext({
                headers: new HttpHeaders().set('authorization', `${token}`),
            });

            return forward(operation);
        });

        const link = split(
            ({query}) => {
                const {kind, operation}: any = getMainDefinition(query);
                return kind === 'OperationDefinition' && operation === 'subscription';
            },
            wsClient,
            auth.concat(http)
        );
        getErrorSubject().subscribe((data) => {
            console.log(data)

        }, (error) => console.log(error));

        apollo.create({
            link: ApolloLink.from([retryLink, link]),
            cache: new InMemoryCache({
                addTypename: false,
                dataIdFromObject: (object: any) => object.id
            }),
            defaultOptions: {
                watchQuery: {
                    errorPolicy: 'all'
                }
            }
        });


    }
}




`

I don't understand

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants