From 93f2f60ff1d467ab9c729ffd9dce4b2a92ce1e28 Mon Sep 17 00:00:00 2001 From: Johan Nyman Date: Sun, 25 Feb 2018 12:00:38 +0100 Subject: [PATCH] feat: Core ddp-connector and init strategy --- package.json | 7 +- src/MosIntegration.ts | 34 ----- src/__tests__/MosIntegration.spec.ts | 12 +- src/connector.ts | 44 ++++++ src/connectors/ddpConnector.ts | 215 +++++++++++++++++++++++++++ src/coreHandler.ts | 18 +++ src/ddp.d.ts | 38 +++++ src/index.ts | 6 +- src/mosHandler.ts | 46 ++++++ yarn.lock | 123 ++++++++++++++- 10 files changed, 492 insertions(+), 51 deletions(-) delete mode 100644 src/MosIntegration.ts create mode 100644 src/connector.ts create mode 100644 src/connectors/ddpConnector.ts create mode 100644 src/coreHandler.ts create mode 100644 src/ddp.d.ts create mode 100644 src/mosHandler.ts diff --git a/package.json b/package.json index 37921da..6c7906e 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,10 @@ "production" ], "dependencies": { - "tslib": "^1.6.0", - "mos-connection": "git+https://Mfn2bXzQtEFXHKpo12x2y78QJMR7gUZz:x-oauth-basic@bitbucket.org/superflytv/mos-connection.git" + "ddp": "^0.12.1", + "ddp-ejson": "~0.8.1-3", + "ddp-random": "~0.8.1-1", + "mos-connection": "git+https://Mfn2bXzQtEFXHKpo12x2y78QJMR7gUZz:x-oauth-basic@bitbucket.org/superflytv/mos-connection.git", + "tslib": "^1.6.0" } } diff --git a/src/MosIntegration.ts b/src/MosIntegration.ts deleted file mode 100644 index 20e1671..0000000 --- a/src/MosIntegration.ts +++ /dev/null @@ -1,34 +0,0 @@ - -import {MosConnection} from "mos-connection" - -export default class MosIntegration { - static init() { - - const myMos = new MosConnection({ - mosID: "YAAS", - ncs: { - ncsID: "WINSERVERSOMETHINGENPS", - host: "192.168.0.1" - }, - /*ncsBuddy?: { - ncsID: string; - host: string; - },*/ - profiles: { - '0': true, - '1': false, - '2': false, - '3': false, - '4': false, - '5': false, - '6': false, - '7': false, - } - }); - - myMos; - - } -} - - diff --git a/src/__tests__/MosIntegration.spec.ts b/src/__tests__/MosIntegration.spec.ts index ecf63e5..8e01a30 100644 --- a/src/__tests__/MosIntegration.spec.ts +++ b/src/__tests__/MosIntegration.spec.ts @@ -1,13 +1,15 @@ -import MosIntegration from "../MosIntegration" +import {Connector} from "../connector" -test('Simple test', () => { +test('Simple test', async () => { - var myMosC = new MosIntegration(); + var c = new Connector(); - MosIntegration.init(); + await c.init() - expect(myMosC).toBeInstanceOf(MosIntegration) + expect(c).toBeInstanceOf(Connector) + + return 1; }) diff --git a/src/connector.ts b/src/connector.ts new file mode 100644 index 0000000..5caec9a --- /dev/null +++ b/src/connector.ts @@ -0,0 +1,44 @@ + +import {MosHandler} from "./mosHandler" +import {CoreHandler} from "./coreHandler" + + + +export class Connector { + + private mosHandler:MosHandler; + private coreHandler:CoreHandler; + + + async init():Promise { + + await this.initCore() + + + + await this.initMos(); + + + + return 0; + + } + initCore() { + + this.coreHandler = new CoreHandler(); + + return this.coreHandler.init(); + + } + initMos():Promise { + + + // TODO: maybe get some config data from core here? + + this.mosHandler = new MosHandler(); + + return this.mosHandler.init(); + + } +} + diff --git a/src/connectors/ddpConnector.ts b/src/connectors/ddpConnector.ts new file mode 100644 index 0000000..0ded601 --- /dev/null +++ b/src/connectors/ddpConnector.ts @@ -0,0 +1,215 @@ +let ddp: any = require("ddp"); + +import {EventEmitter} from 'events'; + + + + +export interface DDPConnectorOptions { + host: string; + port: number; + path?: string; + ssl?: boolean; + debug?: boolean; +} +export interface Observer { + added: (id:string) => void; + changed:(id:string, oldFields:any, clearedFields:any, newFields:any) => void; + removed:(id:string, oldValue:any) => void; +} +export interface DDPClient { + on:(event:string, data?:any) => void, + close:() => void, + connect:(callback?:(error:Error, wasReconnect:boolean) => void) => void, + + call:(methodName:string, data:Array, callback:(err:Error, result:any) => void) => void + subscribe: (subscriptionName:string, data:Array, callback:() => void) => void + observe: (collectionName:string) => Observer + + collections: { + [collectionName:string]: { + [id:string]: { + _id: string, + [attr:string]: any + } + } + } + + socket:any, + session:string, + + host: string, + port: number, + path: string, + ssl: boolean, + useSockJS: boolean; + autoReconnect: boolean; + autoReconnectTimer: number; + ddpVersion: any; +} + + + + +export class DDPConnector extends EventEmitter { + private _options:DDPConnectorOptions; + public ddpClient:DDPClient; + private _connected:boolean = false; + private _connecting:boolean = false; + private _connectionId:string; + + onConnectionChanged?: (connected:boolean) => void; + onConnected?: () => void; + onDisconnected?: () => void; + + + constructor(options:DDPConnectorOptions) { + super(); + + this._options = options; + + } + createClient() { + var o = { + host: this._options.host, + port: this._options.port, + path: this._options.path || '', + ssl: this._options.ssl || false, + useSockJS: true, + autoReconnect: true, + autoReconnectTimer: 1000, + maintain_collections: true, + ddpVersion: "1" + }; + if (!this.ddpClient) { + + this.ddpClient = new ddp(o); + this.ddpClient.on("socket-close", () => { + + this._onclientConnectionChange(false) + + }); + this.ddpClient.on("message", (message: any) => this._onClientMessage(message)); + this.ddpClient.on("socket-error", (error: any) => this._onClientError(error)); + + + + } else { + + + if (this.ddpClient.socket) { + this.ddpClient.close(); + } + + + this.ddpClient.host = o.host; + this.ddpClient.port = o.port; + this.ddpClient.path = o.path; + this.ddpClient.ssl = o.ssl; + this.ddpClient.useSockJS = o.useSockJS; + this.ddpClient.autoReconnect = o.autoReconnect; + this.ddpClient.autoReconnectTimer = o.autoReconnectTimer ; + this.ddpClient.ddpVersion = o.ddpVersion ; + + + this.ddpClient.connect(); + + } + + this.ddpClient.on("connected", () => { + + this._onclientConnectionChange(true); + }); + this.ddpClient.on("failed", (error: any) => this._onClientConnectionFailed(error)); + } + public connect() { + return new Promise((resolve, reject) => { + + if (!this.ddpClient) { + this.createClient(); + } + + if (this.ddpClient && !this._connecting) { + + this._connecting = true; + + this.ddpClient.connect((error: Object, isReconnecting: boolean) => { + this._connecting = false; + + + if (error) { + reject(error); + } else { + resolve(); + } + }); + } + }); + } + public close() { + if (this.ddpClient) { + this.ddpClient.close(); + delete this.ddpClient; + } + } + public get connected(): boolean{ + return this._connected; + } + public forceReconnect(): void { + this.createClient(); + } + + private _onclientConnectionChange(connected:boolean) { + if (connected !== this._connected) { + this._connected = connected; + + if (connected) { + this._connectionId = this.ddpClient.session; + } + + //log.debug("DDP: _onclientConnectionChange "+connected); + + if (this.onConnectionChanged) { + this.onConnectionChanged(this._connected); + } + if (this.onConnected && this._connected) { + this.onConnected(); + } + if (this.onDisconnected && !this._connected) { + this.onDisconnected(); + } + + /*if(!this._connected && this.autoReconnect){ + this._createClient(); + this.handleAutoReconnect(); + } + if (this._connected) { + this._failedConnectionAttempts = 0; + } + */ + } + } + private _onClientConnectionFailed(error:Error) { + + if (this.listenerCount('failed') > 0) { + + this.emit('failed', error); + } else { + console.log('failed',error); + // last resort retry strategy: + setTimeout(() => { + if (!this._connected) { + this.forceReconnect(); + } + }, 5000); + } + } + + private _onClientMessage(message:any) { + //console.log('message',message); + message; + } + private _onClientError(error:Error) { + this.emit('error', error); + } +} \ No newline at end of file diff --git a/src/coreHandler.ts b/src/coreHandler.ts new file mode 100644 index 0000000..e507f0e --- /dev/null +++ b/src/coreHandler.ts @@ -0,0 +1,18 @@ +import {DDPConnector} from "./connectors/ddpConnector" + + +export class CoreHandler { + + private ddp:DDPConnector; + + init() { + + this.ddp = new DDPConnector({ + host: '127.0.0.1', + port: 3000, + }); + + this.ddp.createClient(); + + } +} \ No newline at end of file diff --git a/src/ddp.d.ts b/src/ddp.d.ts new file mode 100644 index 0000000..2c27ec0 --- /dev/null +++ b/src/ddp.d.ts @@ -0,0 +1,38 @@ +/// + +declare module DDP { + interface DDPStatic { + subscribe(name: string, ...rest: any[]): Meteor.SubscriptionHandle; + call(method: string, ...parameters: any[]): void; + apply(method: string, ...parameters: any[]): void; + methods(IMeteorMethodsDictionary: any): any; + status(): DDPStatus; + reconnect(): void; + disconnect(): void; + onReconnect(): void; + } + + function _allSubscriptionsReady(): boolean; + + type Status = 'connected' | 'connecting' | 'failed' | 'waiting' | 'offline'; + + interface DDPStatus { + connected: boolean; + status: Status; + retryCount: number; + retryTime?: number; + reason?: string; + } + + function connect(url: string): DDPStatic; +} + +declare module DDPCommon { + interface MethodInvocation { + new (options: {}): MethodInvocation; + + unblock(): void; + + setUserId(userId: number): void; + } +} diff --git a/src/index.ts b/src/index.ts index 69e77a9..3b60fb5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,7 @@ -import MosIntegration from "./MosIntegration" +import {Connector} from "./connector" -MosIntegration.init(); \ No newline at end of file +var c = new Connector(); + +c.init(); \ No newline at end of file diff --git a/src/mosHandler.ts b/src/mosHandler.ts new file mode 100644 index 0000000..fdd8209 --- /dev/null +++ b/src/mosHandler.ts @@ -0,0 +1,46 @@ +import {MosConnection} from "mos-connection" + +export class MosHandler { + + public mos:MosConnection; + + init() { + + this.mos = new MosConnection({ + acceptConnections: true, // default:true + acceptConnectionFrom: ['127.0.0.1'], + + profiles: { + '0': true, + '1': false, + '2': false, + '3': false, + '4': false, + '5': false, + '6': false, + '7': false, + } + }); + + this.mos.onConnection(() => { + // a new connection has been made + + + + }); + + // Connect to ENPS: + return this.mos.connect({ + ncs: { + ncsID: "WINSERVERSOMETHINGENPS", + host: "192.168.0.1" + }, + /*ncsBuddy?: { + ncsID: string; + host: string; + },*/ + }).then(() => { + // called when a connection has been made + }) + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 5bebddb..7958c38 100644 --- a/yarn.lock +++ b/yarn.lock @@ -265,7 +265,7 @@ async@^1.4.0: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" -async@^2.1.4: +async@^2.0.1, async@^2.1.4: version "2.6.0" resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" dependencies: @@ -566,6 +566,12 @@ binary-extensions@^1.0.0: version "1.8.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774" +bl@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.1.2.tgz#fdca871a99713aa00d19e3bbba41c44787a65398" + dependencies: + readable-stream "~2.0.5" + block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" @@ -1104,6 +1110,29 @@ dateformat@^1.0.11, dateformat@^1.0.12: get-stdin "^4.0.1" meow "^3.3.0" +ddp-ejson@0.8.1-3, ddp-ejson@~0.8.1-3: + version "0.8.1-3" + resolved "https://registry.yarnpkg.com/ddp-ejson/-/ddp-ejson-0.8.1-3.tgz#e9d67466ab789bd74e7d97074a36e240690eeec2" + dependencies: + ddp-underscore-patched "0.8.1-2" + +ddp-random@~0.8.1-1: + version "0.8.1-1" + resolved "https://registry.yarnpkg.com/ddp-random/-/ddp-random-0.8.1-1.tgz#3de3111724d6bf730a729a7c0a38369eba00f143" + +ddp-underscore-patched@0.8.1-2: + version "0.8.1-2" + resolved "https://registry.yarnpkg.com/ddp-underscore-patched/-/ddp-underscore-patched-0.8.1-2.tgz#65a414e9f22ec5a82aa16386e34366b48fcecf1d" + +ddp@^0.12.1: + version "0.12.1" + resolved "https://registry.yarnpkg.com/ddp/-/ddp-0.12.1.tgz#1443514c3c1334a5fdb3dfae7a180a4f698105b7" + dependencies: + ddp-ejson "0.8.1-3" + ddp-underscore-patched "0.8.1-2" + faye-websocket "0.11.0" + request "2.74.x" + debug-log@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" @@ -1357,6 +1386,12 @@ fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" +faye-websocket@0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.0.tgz#d9ccf0e789e7db725d74bc4877d23aa42972ac50" + dependencies: + websocket-driver ">=0.5.1" + fb-watchman@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" @@ -1449,6 +1484,14 @@ forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" +form-data@~1.0.0-rc4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-1.0.1.tgz#ae315db9a4907fa065502304a66d7733475ee37c" + dependencies: + async "^2.0.1" + combined-stream "^1.0.5" + mime-types "^2.1.11" + form-data@~2.1.1: version "2.1.4" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" @@ -1844,6 +1887,10 @@ html-encoding-sniffer@^1.0.2: dependencies: whatwg-encoding "^1.0.1" +http-parser-js@>=0.4.0: + version "0.4.10" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" + http-signature@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" @@ -1888,7 +1935,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -2804,18 +2851,18 @@ mime-db@~1.33.0: version "1.33.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" +mime-types@^2.1.11, mime-types@~2.1.17: + version "2.1.18" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" + dependencies: + mime-db "~1.33.0" + mime-types@^2.1.12, mime-types@~2.1.7: version "2.1.15" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed" dependencies: mime-db "~1.27.0" -mime-types@~2.1.17: - version "2.1.18" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" - dependencies: - mime-db "~1.33.0" - mimic-fn@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" @@ -2919,6 +2966,10 @@ node-status-codes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-status-codes/-/node-status-codes-1.0.0.tgz#5ae5541d024645d32a58fcddc9ceecea7ae3ac2f" +node-uuid@~1.4.7: + version "1.4.8" + resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907" + nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" @@ -3293,6 +3344,10 @@ q@^1.4.1: version "1.5.0" resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1" +qs@~6.2.0: + version "6.2.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe" + qs@~6.3.0: version "6.3.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" @@ -3382,6 +3437,17 @@ readable-stream@^2.0.1: string_decoder "~1.0.3" util-deprecate "~1.0.1" +readable-stream@~2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~0.10.x" + util-deprecate "~1.0.1" + readdirp@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" @@ -3470,6 +3536,32 @@ request-promise-native@^1.0.5: stealthy-require "^1.1.0" tough-cookie ">=2.3.3" +request@2.74.x: + version "2.74.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.74.0.tgz#7693ca768bbb0ea5c8ce08c084a45efa05b892ab" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + bl "~1.1.2" + caseless "~0.11.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~1.0.0-rc4" + har-validator "~2.0.6" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + node-uuid "~1.4.7" + oauth-sign "~0.8.1" + qs "~6.2.0" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "~0.4.1" + request@2.79.0: version "2.79.0" resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" @@ -3832,6 +3924,10 @@ string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + string_decoder@~1.0.0, string_decoder@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" @@ -4259,6 +4355,17 @@ webidl-conversions@^4.0.1, webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" +websocket-driver@>=0.5.1: + version "0.7.0" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.0.tgz#0caf9d2d755d93aee049d4bdd0d3fe2cca2a24eb" + dependencies: + http-parser-js ">=0.4.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" + whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz#57c235bc8657e914d24e1a397d3c82daee0a6ba3"