-
Notifications
You must be signed in to change notification settings - Fork 342
NativeScript support #668
Comments
Did you ever happen to find a workaround or a fix for this? |
As a workaround, we are currently using Firebase Cloud Messaging to update our users. |
UP |
Having this same problem after updating to NativeScript 6.5.0 |
Not knowing NativeScript, this may or may not be related. The errors originally reported are consistent with those I encountered, and the issue ended up being my webpack config. See further detail: apollographql/apollo-link#1274 (comment) |
UP |
This seems to work, thanks! |
@PhilippS93, @vytautas-pranskunas- @tafelnl This is the solution that work for me!1: install plugins: [
// Define useful constants like TNS_WEBPACK
new webpack.NormalModuleReplacementPlugin(
/^ws$/,
'nativescript-websockets'
), 3: require ws in 'main.ts' 4: creare 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} 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 = environment.graphqlUrl + '/graphql';
const socketUrl = environment.graphqlSocketUrl
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";
import {environment} from "../environments/environment";
import {UserService} from "./shared/services/user.service";
import {setContext} from "@apollo/client/link/context";
import {SubscriptionService} from "./core/subscription.service";
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,
userService: UserService,
subscriptionService: SubscriptionService,
) {
const http = httpLink.create({
uri
});
const error = onError(({networkError, graphQLErrors}) => {
console.log('ERROR@@@@')
console.log(networkError)
console.log(graphQLErrors)
})
const wsClient = subscriptionService.getWSClient(socketUrl, {
// uri: socketUrl,
lazy: true,
reconnect: true,
options: {
reconnect: true,
connectionParams: {
authorization: userService.getAuthToken(),
},
},
connectionParams: async () => {
return {
authorization: await userService.getTokenPromise()
};
},
// webSocketImpl: WebSocket,
reconnectionAttempts: 99,
}, WebSocket) as any;
// wsClient.subscriptionClient.use([subscriptionMiddleware])
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 authLink = setContext((_, {headers}) => {
// get the authentication token from local storage if it exists
const token = userService.getAuthToken()
// return the headers to the context so httpLink can read them
return {
headers: {
...headers,
authorization: token || '',
}
}
});
const link = split(
({query}) => {
const {kind, operation}: any = getMainDefinition(query);
return kind === 'OperationDefinition' && operation === 'subscription';
},
wsClient,
authLink.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'
// }
// }
});
}
} 5: create subscription.service.ts import {Injectable} from '@angular/core';
import {SubscriptionClient} from 'subscriptions-transport-ws';
import {BehaviorSubject, Subject} from 'rxjs';
import {SocketStatus} from "./socket-status.enum";
import {SocketStatusCodeEnum} from "./socket-status";
import {WebSocketLink} from "@apollo/client/link/ws";
// DOT REMOVE THIS!!! //
require('nativescript-websockets');
var WebSocket = require('nativescript-websockets');
// DOT REMOVE THIS!!! //
@Injectable()
export class SubscriptionService {
private wsc: SubscriptionClient;
public wsl: WebSocketLink;
ws: WebSocket
status$: BehaviorSubject<SocketStatus> = new BehaviorSubject<SocketStatus>(null);
status;
constructor() {
}
public get getStatus() {
return this.status$.asObservable();
}
public getWSClient(uri, options, ws) {
if (this.wsc) {
return this.wsc;
}
if (uri && !this.wsc) {
this.ws = ws;
this.wsc = new SubscriptionClient(uri, options, ws);
}
if (this.wsc) {
this.bindEvent();
}
return this.wsc;
}
public close() {
if (this.wsc) {
this.wsc.close();
}
}
private bindEvent() {
const status = new SocketStatus()
this.wsc.onConnecting(() => {
status.name = 'Online';
status.statusCode = SocketStatusCodeEnum.ON_CONNECTING;
console.log(status)
this.status$.next(status);
});
this.wsc.onConnected(() => {
status.name = 'Online';
status.statusCode = SocketStatusCodeEnum.ON_CONNECTED;
this.status = status;
console.log(status)
this.status$.next(status);
});
this.wsc.onReconnecting(() => {
status.name = 'Reconnecting';
status.statusCode = SocketStatusCodeEnum.ON_RECONNECTING;
this.status = status;
console.log(status)
this.status$.next(status);
});
this.wsc.onReconnected(() => {
status.name = 'OnLine';
status.statusCode = SocketStatusCodeEnum.ON_RECONNECTED;
this.status = status;
console.log(status)
this.status$.next(status);
});
this.wsc.onDisconnected(() => {
status.name = 'Disconnected';
status.statusCode = SocketStatusCodeEnum.ON_DISCONNECTED;
this.status = status;
console.log(status)
this.status$.next(status);
});
this.wsc.onError(() => {
status.name = 'Error';
status.statusCode = SocketStatusCodeEnum.ON_ERROR;
this.status = status;
console.log(status)
this.status$.next(status);
});
}
} 6: finally add GraphQLModule, to app.module use subscription setOnMessageEvents$(token) {
this.graphQLService.onMessageEvents$(token).subscribe((res) => {
if (res) {
console.log(res)
}
})
} |
@dudipsh thanks for the solution above, seems to be working for me as well. Just one Q, does your cache works? does it write to |
yes, you need to add this
|
When using the proposed setup for Apollo Subscription setup in NativeScript (see: here), I get the following error (short extract):
This is related to: this and this.
Are there any plans for future implementation of NativeScript support?
Thank you,
Philipp
The text was updated successfully, but these errors were encountered: