diff --git a/.travis.yml b/.travis.yml index 0e6a5976..e9aa18cf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,6 @@ node_js: - 11 script: - npm test - - npx prettier-check **/*.ts[x] + - npm run prettier-check - npm run coveralls - npm run lint diff --git a/package.json b/package.json index 6b4e6fe9..d8904e6c 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,8 @@ "test": "react-scripts test --coverage", "eject": "react-scripts eject", "coveralls": "cat ./coverage/lcov.info | node node_modules/.bin/coveralls", - "lint": "node_modules/.bin/eslint src/**/*.ts[x]" + "lint": "node_modules/.bin/eslint src/**/*.{ts,tsx}", + "prettier-check": "node_modules/.bin/prettier --check src/**/*.{ts,tsx}" }, "eslintConfig": { "extends": [ diff --git a/src/App.tsx b/src/App.tsx index 0e4fcd92..d987cd94 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -8,7 +8,7 @@ import { ConnectedInput } from "./components/input"; import { ConiqlPlugin } from "./connection/coniql"; const App: React.FC = (): JSX.Element => { - initialiseStore(new ConiqlPlugin("wsurl")); + initialiseStore(new ConiqlPlugin("localhost:8000")); let store = getStore(); return ( diff --git a/src/connection/coniql.ts b/src/connection/coniql.ts index 0aefd101..d86b4da5 100644 --- a/src/connection/coniql.ts +++ b/src/connection/coniql.ts @@ -8,26 +8,27 @@ import { InMemoryCache, NormalizedCacheObject } from "apollo-cache-inmemory"; import { NType } from "../cs"; import { Connection, ConnectionCallback } from "./plugin"; -const httpUri = "htop://localhost:8000/graphql"; -const wsUri = "ws://localhost:8000/subscriptions"; +function createLink(socket: string): ApolloLink { + const link: ApolloLink = ApolloLink.split( + ({ query }): boolean => { + // https://github.com/apollographql/apollo-client/issues/3090 + const definition = getMainDefinition(query); + return ( + definition.kind === "OperationDefinition" && + definition.operation === "subscription" + ); + }, + new WebSocketLink({ + uri: `ws://${socket}/subscriptions`, + options: { + reconnect: true + } + }), + new HttpLink({ uri: `http://${socket}/graphql` }) + ); -const link: ApolloLink = ApolloLink.split( - ({ query }): boolean => { - // https://github.com/apollographql/apollo-client/issues/3090 - const definition = getMainDefinition(query); - return ( - definition.kind === "OperationDefinition" && - definition.operation === "subscription" - ); - }, - new WebSocketLink({ - uri: wsUri, - options: { - reconnect: true - } - }), - new HttpLink({ uri: httpUri }) -); + return link; +} const cache = new InMemoryCache(); @@ -40,20 +41,16 @@ const PV_SUBSCRIPTION = gql` `; export class ConiqlPlugin implements Connection { - private url: string; - private client: ApolloClient | null; - private callback: ((pvName: string, data: NType) => void) | null; + private client: ApolloClient; + private callback: (pvName: string, data: NType) => void; - public constructor( - websocketUrl: string - ) { - this.url = websocketUrl; - this.client = null; - this.callback = null; + public constructor(socket: string) { + const link = createLink(socket); + this.client = new ApolloClient({ link, cache }); + this.callback = (_p, _v): void => {}; } - public connect(callback: ConnectionCallback):void { - this.client = new ApolloClient({ link, cache }); + public connect(callback: ConnectionCallback): void { this.callback = callback; } @@ -62,7 +59,7 @@ export class ConiqlPlugin implements Connection { } public subscribe(pvName1: string): void { - this.client! + this.client .subscribe({ query: PV_SUBSCRIPTION, variables: { pvName: pvName1 } @@ -70,7 +67,7 @@ export class ConiqlPlugin implements Connection { .subscribe({ next: (data): void => { console.log("data", data); //eslint-disable-line no-console - this.callback!(pvName1, data.data.subscribeFloatScalar); + this.callback(pvName1, data.data.subscribeFloatScalar); }, error: (err): void => { console.error("err", err); //eslint-disable-line no-console diff --git a/src/connection/plugin.ts b/src/connection/plugin.ts index 98bb13f1..4858f308 100644 --- a/src/connection/plugin.ts +++ b/src/connection/plugin.ts @@ -1,12 +1,11 @@ import { NType } from "../cs"; -import { ConiqlPlugin } from "./coniql"; -export type ConnectionCallback = (pvName:string, value:NType) => void; +export type ConnectionCallback = (pvName: string, value: NType) => void; export interface Connection { subscribe: (pvName: string) => void; putPv: (pvName: string, value: NType) => void; getValue: (pvName: string) => NType; - connect: (callback:ConnectionCallback) => void; + connect: (callback: ConnectionCallback) => void; isConnected: () => boolean; } diff --git a/src/connection/sim.ts b/src/connection/sim.ts index a8d0b561..6c66f34b 100644 --- a/src/connection/sim.ts +++ b/src/connection/sim.ts @@ -3,34 +3,28 @@ import { NType } from "../cs"; import { ValueCache } from "../redux/csState"; export class SimulatorPlugin implements Connection { - private url: string; - private value: number; private localPvs: ValueCache; - private onUpdate: ConnectionCallback | null; + private onUpdate: ConnectionCallback; private timeout: NodeJS.Timeout | null; - public constructor( - websocketUrl: string - ) { - this.url = websocketUrl; - this.value = 0; + public constructor() { this.localPvs = {}; - this.onUpdate = null; + this.onUpdate = (_p, _v): void => {}; this.subscribe = this.subscribe.bind(this); this.putPv = this.putPv.bind(this); /* Set up the sine PV. */ this.timeout = null; } - public connect(callback:ConnectionCallback){ + public connect(callback: ConnectionCallback): void { this.onUpdate = callback; this.timeout = setInterval( - (): void => this.onUpdate!("sim://sine", this.getValue("sim://sine")), + (): void => this.onUpdate("sim://sine", this.getValue("sim://sine")), 2000 ); } - public isConnected(): boolean{ + public isConnected(): boolean { return this.onUpdate != null; } @@ -38,14 +32,14 @@ export class SimulatorPlugin implements Connection { console.log(`creating connection to ${pvName}`); //eslint-disable-line no-console if (pvName.startsWith("loc://")) { this.localPvs[pvName] = { type: "NTScalarDouble", value: 0 }; - this.onUpdate!(pvName, { type: "NTScalarDouble", value: 0 }); + this.onUpdate(pvName, { type: "NTScalarDouble", value: 0 }); } } public putPv(pvName: string, value: NType): void { if (pvName.startsWith("loc://")) { this.localPvs[pvName] = value; - this.onUpdate!(pvName, value); + this.onUpdate(pvName, value); } } diff --git a/src/hooks/useCs.ts b/src/hooks/useCs.ts index db51625d..526bb73b 100644 --- a/src/hooks/useCs.ts +++ b/src/hooks/useCs.ts @@ -6,9 +6,9 @@ import { NType } from "../cs"; export function useSubscription(pvName: string): void { const dispatch = useDispatch(); - useEffect((): any => { + useEffect((): any => { dispatch({ type: SUBSCRIBE, payload: { pvName: pvName } }); - return ():any => { + return (): any => { dispatch({ type: UNSUBSCRIBE, payload: {} }); }; }, [dispatch, pvName]); diff --git a/src/redux/connectionMiddleware.ts b/src/redux/connectionMiddleware.ts index 815d364c..7d23072a 100644 --- a/src/redux/connectionMiddleware.ts +++ b/src/redux/connectionMiddleware.ts @@ -14,10 +14,9 @@ function pvChanged(pvName: string, value: NType): void { // eslint doesn't deal with currying very well: // (x:any): any => (y:any): any => (z:any): any is perverse // eslint-disable-next-line @typescript-eslint/explicit-function-return-type -export const connectionMiddleware = (connection:Connection) => (store: any) => (next: any): any => ( - action: any -): any => { - +export const connectionMiddleware = (connection: Connection) => ( + store: any +) => (next: any): any => (action: any): any => { if (!connection.isConnected()) { connection.connect(pvChanged); } diff --git a/src/redux/csState.ts b/src/redux/csState.ts index 4ed7d1a4..d4160fc7 100644 --- a/src/redux/csState.ts +++ b/src/redux/csState.ts @@ -1,5 +1,5 @@ import { PV_CHANGED, ActionType, SUBSCRIBE, WRITE_PV } from "./actions"; -import { NType } from "../cs" +import { NType } from "../cs"; const initialState: CsState = { valueCache: {} diff --git a/src/redux/store.ts b/src/redux/store.ts index 0a82c5b7..344a48f8 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -1,4 +1,4 @@ -import { createStore, applyMiddleware, Store} from "redux"; +import { createStore, applyMiddleware, Store } from "redux"; import { csReducer, CsState } from "./csState"; import { connectionMiddleware } from "./connectionMiddleware"; @@ -6,16 +6,21 @@ import { Connection } from "../connection/plugin"; // Setting this to Action or Action seems to trip up the type system type MyStore = Store; -let store : MyStore | null = null; +let store: MyStore | null = null; -export function initialiseStore(connection: Connection): void{ - store = createStore(csReducer, applyMiddleware(connectionMiddleware(connection))); +export function initialiseStore(connection: Connection): void { + store = createStore( + csReducer, + applyMiddleware(connectionMiddleware(connection)) + ); } -function raiseStoreEmpty() : never { - throw new Error("store singleton is not initialised. (see initialiseStore())"); +function raiseStoreEmpty(): never { + throw new Error( + "store singleton is not initialised. (see initialiseStore())" + ); } export function getStore(): MyStore { - return store || raiseStoreEmpty(); + return store || raiseStoreEmpty(); }