Giter VIP home page Giter VIP logo

kite.js's Introduction

Kite.js

Build Status NPM version

kite for node.js and browser.

Installation

npm install kite.js

or via git:

git clone git://github.com/koding/kite.js.git
npm i

This would automatically fire the initial build for you. Or else once you clone the repository you can do:

npm run bundle

which generates a bundle for the browser, and you can find the output under ./dist/

Getting started

In node:

const { Kite, Kontrol } = require('kite.js');

In the browser:

<script src="./dist/bundle.js"></script>

will expose Kite and Kontrol over window

API

Kite

You can use the Kite constructor with a URL:

const { Kite } = require('kite');
let k = new Kite('ws://my-math-service.com');
k.tell('square', 4).then(console.log.bind(console));
// logs "16"

kite.connect()

Open a connection to the remote service. Called the first time in the constructor.

kite.disconnect()

Close the connection, if it is open.

kite.tell(method, params)

Send an RPC to the remote service, and receive the response. Returns a Promise.

Kontrol

Parameters can be like following for Kontrol;

var params = {
  query: { /* kontrol query */ }
  who: { /* kite.who query */  }
}

You need a valid query object to work with Kontrol; The kontrol query is used by kontrol to select matching kites by the following criteria, which are order from general to specific:

type KontrolQuery struct {
  username    string
  environment string
  name        string
  version     string
  region      string
  hostname    string
  id          string
}

The order matters, and more general criteria cannot be omitted. In other words, if you want to query by name, you must also provide values for username and environment; if you want to query by region, you need to provide values for all of username, environment, name and version.

Kite Descriptors

Kite Descriptors are provided by Kontrol, and looks like this:

let kiteDescriptor = {
  kite: {
    name: "A Kite Name",
    version: "1.0.0"
  },
  token: "A token provided by kontrol",
  url: "wss://example.com/sample-kite"
};

kite.who

Kites can implement custom load-balancing strategies for other instances of their kind. This works by delegation: First kontrol will query for any kite matching the given criteria; If it matches one, it will forward the kite.who query to the kite.who method a matching kite. The contents of the kite.who query are application-layer concerns, and are not scrutinized by kontrol, which merely forwards them along to the target kite. The target kite can treat this information however it likes, but is required to respond to the kite.who method with a new query that will match the kite which is designated to be the new target kite. It is acceptable for the kite to respond with a query matching itself.

This can be useful if the kite is using some kind of session state. If a given kite has already allocated resources or has some state stored locally, the user can be reconnected to that instance via this mechanism.

kontrol.fetchKites(params)

This method will respond with any kites that matched the query, after any potential load balancing negotiation. The matching kites will not be connected. You can connect to one by calling its .connect() method.

kontrol.fetchKite(params)

This works by querying using fetchKites, and then simply choosing one of the kites matching the given query, after load balancing negotiation.

kontrol.watchKites(params)

This works like fetchKites, but will also stream through any updates matching the query as they occur. It will respond with an additional parameter, the watcherID which is a numeric handle that can be used to cancel that watchKites operation.

This feature won't work in conjunction with kite.who

kontrol.cancelWatcher(id)

Given the numeric watcherID handle provided by watchKites, cancelWatcher can be used to clear the associated watch operation.

kontrol.createKite(kiteDescriptor)

Given a kite descriptor, this method will instantiate a proper Kite instance.

License

MIT (c) 2017 Koding

kite.js's People

Contributors

humanchimp avatar gokmen avatar usirin avatar tetsuo avatar cihangir avatar sinan avatar alex-ionochkin avatar cenkalti avatar

Stargazers

Rasit avatar Charles P. Cross avatar frankfanslc avatar ericens avatar Yasin ATEŞ avatar CatlinCao avatar Pierre-Henry avatar Ahmet Tarik GUNAL avatar  avatar adamo-in-space avatar CHANG, TZU-YEN avatar Michael avatar Eliza Zhang avatar TuNA avatar Yijun Zhao avatar  avatar necmi acikyol avatar resilient |rəˈzilyənt| red avatar Rodrigo Oler avatar Kasper Isager Dalsgarð avatar zj8487 avatar Nahar P avatar Jake Lacey avatar Hakan Karadis avatar  avatar Pranay Prakash avatar mr.james avatar GreatGreg avatar Abhishek Gahlot avatar SDF avatar Dennis Hernández avatar Adam Stankiewicz avatar Gabriel Francisco avatar Vaughn Iverson avatar Santi Lertsumran avatar Jacopo Daeli avatar Angus H. avatar chris avatar Jeff Kingyens avatar Gurpartap Singh avatar buhe avatar Adam avatar Erhan Abibula avatar Andrew Valish avatar Grégory Horion avatar Haokang Den avatar Evander Otieno avatar Dimitri Walters avatar Michael Hood avatar Alix Axel avatar Lucas avatar Dana Woodman avatar Emir Karşıyakalı avatar Michael Anthony avatar Val Packett avatar Gosha Spark avatar Damon Zhao avatar Alexandre Mclean avatar Shirkey avatar Athan avatar  avatar Anton Taraev avatar Thomas Sileo avatar Dusan Blagojevic avatar Marcin Skarbek avatar Victor Borja avatar Michael Desa avatar metakeule avatar Omer Katz avatar  avatar Eak Netpanya avatar  avatar Burak Can avatar Senthil Arivudainambi avatar  avatar

Watchers

Darren Jones avatar Joao Da Silva avatar Devrim Yasar avatar  avatar James Cloos avatar Michael Anthony avatar  avatar 塵子曦 avatar Eugene Palchukovsky avatar Ricky Ogtip avatar  avatar

kite.js's Issues

Allow kite creation with an existing transport/ws

This is crucial for creating a bi-directional connection between client/server. And would be used by rope.

This can be hooked into the KiteServer connection event.
We are emitting a Session object with connection event, and this occurs right after a server class receives a connection.
Since a low-level server class (e.g WebSocketServer and SockJsServer classes) will have a connection info attached to it and it's a similar object in which we are creating ourselves in Kite base class (this.ws = new WebSocket()) having a way to create a Kite object with an existing connection object would be really helpful here.

  • This is gonna be implemented in Kite base class, and it's gonna accept a connection via transport option.
  • If a transport option is present in the option, it's gonna immediately wrap the connection and it's gonna behave as it's connected.
  • This is gonna affect connect and onOpen functions.
    • onOpen is gonna be called immediately if a transport option is set to get things going.
    • connect is gonna be a noop.
  • autoReconnect option is gonna be redundant when a transport option is present, as we don't know how we are gonna connect back to a connection if we didn't create it.
  • url option will not gonna be used.

Let's say we have a KiteServer running on ws://localhost:9999:

import { KiteServer } from 'kite.js'

const server = new KiteServer({
  name: 'square',
  auth: false,
  api: {
    square(x, done) { done(null, x * x) }
  }
})

server.listen(9999)

After transport option feature is implemented we will be able to connect to this server with 2 different ways:

import { Kite } from 'kite.js'
import WebSocket from 'ws'

// first the usual one:
const kite = new Kite({
  url: 'ws://localhost:9999',
  auth: false,
})

kite.connect()

// with transport option we will be able to reuse a `ws` connection:
const ws = new WebSocket('ws://localhost:9999')
const kite = new Kite({
  auth: false,
  transport: ws
})

Why do we need this?

Rope server implementation requires bi-directional communication between 2 ends of the websocket connection. If we were to have this way of passing transport objects on Kite client creation, required implementation for Rope can be satisfied within the api limits of Kite and KiteServer:

After introduction of transport option, following would be how we could interact with the other end of the connection:

// client.js
import { Kite } from 'kite.js'

const kite = new Kite({
  name: 'basic-whoami',
  api: {
    whoami(callback) {
      callback(null, 'square')
    }
  }
})
// server.js
import { Kite, KiteServer } from 'kite.js'

const server = new KiteServer({
  name: 'square',
  auth: false,
  api: {
    square(x, done) { done(null, x * x) }
  }
})

// add an event listener directly onto server object of created KiteServer.
server.server.on('connection', connection => {
  const otherKite = new Kite({
    auth: false,
    transport: connection
  })

  otherKite.tell('whoami').then(res => console.log(`Hello my name is ${res}`))
  // => Hello my name is square
})

server.listen(9999)

What i was trying to explain in the beginning was instead of attaching an event listener of the internal server object, we can use existing connection event of KiteServer, and the connection/session object emitted with it will have a kite object attached to it, so if we were to rewrite the last example:

// server.js
import { Kite, KiteServer } from 'kite.js'

const server = new KiteServer({
  name: 'square',
  auth: false,
  api: {
    square(x, done) { done(null, x * x) }
  }
})

// add an event listener directly to our KiteServer instance connection object
// connection object passed to it will have a reference to the caller kite which is an instance of `Kite`
server.on('connection', connection => {
  const otherKite = connection.kite
  otherKite.tell('whoami').then(res => console.log(`Hello my name is ${res}`))
  // => Hello my name is square
})
server.listen(9999)

/cc @gokmen

[kite] ERROR Websocket error!

I'm getting this issue and I'm not to sure why, could anybody guide me, do I need to configure some extra stuff?

[kite] INFO      Trying to connect to ws://localhost:3636/kite
[kite] ERROR   Websocket error!
[kite] INFO      ws://localhost:3636/kite: disconnected
        import { Kite } from 'kite.js';

        const k = new Kite("ws://localhost:3636/kite");
        k.tell('square', 3).then(data => console.log(data));

Server works fine...

	k := kite.New("math", "1.0.0")

	k.HandleFunc("square", func(r *kite.Request) (interface{}, error) {
		a := r.Args.One().MustFloat64()
		result := a * a
		return result, nil
	})

	k.Config.Port = 3636
	k.Config.DisableAuthentication = true
	k.Run()

Client works fine...

        k := kite.New("exp2", "1.0.0")

	mathWorker := k.NewClient("http://localhost:3636/kite")
	mathWorker.Dial()

	response, _ := mathWorker.Tell("square", 4)
	fmt.Println("result: ", response.MustFloat64())

If you need me to provide extra information, just let me know I'll get back to you ASAP.

Generalize Kite transports & deprecate ws property

Current kite client implementation is tightly coupled with websocket transform, the transport object it's using is assigned to kite.ws property. But we already have 2 different servers:

  • websocket
  • sockjs

Since client implementation of these 2 servers are identical, only changing url to ws://someurl to http://someurl satisfies the kite initialization/connection. This works until we want to support another transport protocol which has different api characteristics (e.g: webrtc).

We are already accepting transformOptions and transformClass via options on Kite initialization step. I propose extending this feature with following steps:

  • change the property name to transport
  • generalize the construction of transport by defining a KiteTransport interface, and simply initialize given transportClass with given transportOptions without any explicit check like we currently do here:
class Kite extends Emitter {
  // ...
  connect() {
    const { url, transportOptions, transportClass } = this.options
    
    // first initialize the transport
    this.transport = new transportClass(url, transportOptions)
    
    // assign event handlers
    this.transport.addEventListener(Event.open, ...)
    
    // then connect to it.
    this.transport.connect()
  }
  // ...
}
  • Following is the KiteTransport interface i imagined
import { Event } from 'kite.js/lib/constants'

declare type TransportEvent =
  | Event.OPEN
  | Event.CLOSE
  | Event.MESSAGE
  | Event.ERROR
  | Event.INFO

declare interface TransportEventResponder {
  [Event.OPEN]: () => void,
  [Event.CLOSE]: (event: Object) => void,
  [Event.MESSAGE]: ({ data: Object }) => void,
  [Event.ERROR]: (error: Object) => void,
  [Event.INFO]: (info: Object) => void
}

declare interface KiteTransport {
  uri: string;
  options: Object;
  responder: TransportEventResponder;
  constructor(uri, options);
  addEventListener(eventName: TransportEvent, handler: Function): void;
  connect();
  disconnect(reconnect: bool);
  send(message: string): void;
}
  • Corresponding WebSocketTransport class would be like the following:
// ws-transport.js
import { KiteTransport } from 'kite.js'
import { Event } from 'kite.js/lib/constants'
import WebSocket from 'ws'

export default class WebSocketTransport extends KiteTransport {

  constructor(url, options) {
    // assigns url, and options to `this`.
    super(url, options)
    this.responder = null
  }
  
  connect() {
    this.responder = new WebSocket(this.url)
  }
  
  addEventListener(eventName, handler) {
    this.ready(() => {
      this.responder.addEventListener(eventName, handler)
    })
  }
  
  disconnect(reconnect) {
    if (this.responder) {
      this.responder.close()
      this.responder = null
    }
    
    if (reconnect) {
      this.connect()
    }
  }
  
  send(message) {
    if (!this.responder) {
      throw new Error(`responder is not set`)
    }
    this.responder.send(message)
  }
}

and to initialize a kite using this transport i would use it just as before:

import { Kite } from 'kite.js'
import WebSocketTransport from './ws-transport'

const kite = new Kite({
  url: 'ws://localhost',
  transportClass: WebSocketTransport
})
  • Once we complete this transition we can extend Kite api to accept a transports option allowing us to register multiple transports (please note these code snippets are just imaginary code as a brain storm, not sure how feasible it would be to implement these):
const kite = new Kite({
  transports: [{
    transport: WebSocketTransport,
    options: wsOptions
  }, {
    transport: SockJsTransport,
    options: sockJsOptions
  }]
})

kite.connect()

// maybe passing url with `connect()` call?
// kite.connect(someUrlComingFromSomewhereElse)

The aim here is to allow us using multiple transports without touching any of the existing kite code. I am still not sure how url would work in the scenario where we have multiple transports.


To sum up, since ws is used internal-only, (1) replacing it with a transport property can be done without introducing a breaking change. (2) extending kite api to accept multiple transports should be done once we are satisfied with the api and the way it's gonna work, therefore it implicitly depends on (1).

In the future i see several kite-server-<transport> packages exporting both Server classes and their Transport classes to be used by clients.

@gokmen thoughts?

KiteProtocol primer

This is gonna be rather long, so bear with me to the end, and sorry in advance.

Let's start with our old friend math kite, with only one method defined on
it named square, which will take a number and it's gonna return square of that
number:

// math-server.js
const { KiteServer } = require('kite.js')

const math = new KiteServer({
  name: 'math',
  auth: false,
  api: {
    square: function(x, done) {
      done(null, x * x)
    },
  },
})

math.listen(7780)

The client for corresponding server will connect to it like this:

const { Kite } = require('kite.js')

const kite = new Kite({
  // assuming that they are running on the same host.
  url: 'http://0.0.0.0:7780',
  autoReconnect: false,
  autoConnect: false,
})

kite.on('open', () => {
  kite.tell('square', 5).then(res => console.log('result:', res))
  // => result: 25
})

kite.connect()

So what exactly is happening here?

Under the hood, Kite uses dnode-protocol to make calls to the each side
of the connection, but since dnode-protocol doesn't try to specify a
structure on how to send messages with extra/meta information (kite info,
authentication info, etc), we need to define our own structure.

It currently works like this:

Request from client:

{
  "arguments": [
    {
      "kite": {
        "id": "d43382a0-6b41-485c-8a44-48e5a851f302",
        "username": "anonymous",
        "environment": "browser-environment",
        "name": "math-remote",
        "version": "1.0.9",
        "region": "browser-region",
        "hostname": "browser-hostname"
      },
      "withArgs": 5,
      "responseCallback": "[Function]"
    }
  ],
  "callbacks": {
    "0": [
      "0",
      "responseCallback"
    ]
  },
  "links": [],
  "method": "square"
}

Response from server:

{
  "method": 0,
  "arguments": [
    {
      "error": null,
      "result": 25
    }
  ],
  "callbacks": {},
  "links": []
}

The way it works right now:

  • We pack all the information in a temporary object(1).
  • We specify this object as the only argument on the dnode-protocol request.
  • We specifically name the callback as responseCallback in the temporary object.
  • Once the responder(server) gets this request, we read this object(1)
    • It first checks if this is a special request by checking that the first
      argument on the request satisfies our rules.
    • If so, it first transforms this special object(1) to a valid dnode-protocol request, then since it's a normal dnode-protocol request right now, it lets it's proto to handle this request.
    • Therefore, the response will be another valid dnode-protocol message to be handled by the client's proto.

Problems with current implementation

  1. Packed object has a withArgs property to define arguments even though the
    dnode-protocol defines an arguments object.
  2. Packed object has a responseCallback as its callback resulting in always
    having callbacks: { '0': ['0', 'responseCallback'] } which means having to
    send a string as to define which callback is gonna be called each time. (More
    bytes over the wire)
  3. withArgs is an array if there is more than one argument that needs to be
    passed, while it's a simple value without an array if there is only one
    argument needs passing (like our math kite's square method). This creates
    an unnecessary inconsistencies between requests, and therefor we need to
    handle this in a special way by checking if withArgs is an array or not.
  4. The request is transformed into a regular dnode-protocol message before
    it reaches to the handler defined on the api, so even though we send the
    requester's kite info, the transformed object doesn't have this info.
    Meaning that the handlers cannot know who is making the request.
  5. We are wrapping response in an object with a shape of {error, result},
    this requires first wrapping on the sender side, and de-wrapping on the
    responder side, resulting in unnecessary computation, and also more bytes
    over the wire.
  6. Both requests and responses are being handled by the same method, namely
    handleIncomingMessage, which violates Single Responsibility Pattern
    resulting in more complex code, therefore more confusion.

Solution Proposal

  • As far as I can see, the only reason we are using a specially packed object
    is to send the requester's info and authentication info.
  • Instead of using a specially packed object with redundant properties, let's
    use dnode-protocol's regular arguments array, and let's send requester's
    info and authentication details as last argument.
  • Instead of sending a responseCallback named property inside the object,
    let's make sure that the argument before last one is a function definition.
  • Instead of sending an object with a shape of {error, result} as response
    message, let's again use the arguments array, and make sure it only has 2
    arguments, first is error and second is result.

The shape of request/response after proposed changes

Request from client:

{
  "arguments": [
    5,
    "[Function]",
    {
      "kite": {
        "id": "645f0802-51fc-4961-bdd0-55aed0245eae",
        "username": "anonymous",
        "environment": "browser-environment",
        "name": "browser-kite",
        "version": "1.0.9",
        "region": "browser-region",
        "hostname": "browser-hostname"
      }
    }
  ],
  "callbacks": {
    "0": [
      "1"
    ]
  },
  "links": [],
  "method": "square"
}

Response from server:

{
  "method": 0,
  "arguments": [
    null,
    25
  ],
  "links": [],
  "callbacks": {}
}

The code needs to be written will be the same, except now the handlers will
have information about the requester as their last argument:

// math-server.js
const { KiteServer } = require('kite.js')

const math = new KiteServer({
  name: 'math',
  auth: false,
  api: {
    square: function(x, done, { kite, authentication }) {
      console.log('kite info:', kite)
      // => kite info: {
      //   kite: {
      //     id: '645f0802-51fc-4961-bdd0-55aed0245eae',
      //     username: 'anonymous',
      //     environment: 'browser-environment',
      //     name: 'browser-kite',
      //     version: '1.0.9',
      //     region: 'browser-region',
      //     hostname: 'browser-hostname',
      //   },
      // }

      // send the response
      done(null, x * x)
    },
  },
})

This solves Problem 1, 2, 3, 4, 5 and the details of the implementation will
try to address Problem 6 as well, but since this problem is mostly related with
maintanence issues, it can be deferred to a later time.

Plan of action

  • Refactor the current implementation without introducing new classes/types and
    make sure all the current tests are passing.
  • Create a KiteRequest class which is responsible for creation and validation
    of request messages.
  • Create a KiteResponse class which is responsible for creation and
    validation of response messages.
  • Create a KiteProtocol class which is going to delegate to KiteRequest and
    KiteResponse classes for making sure that the connection and messages
    between 2 kites are correctly transferred, denies the requests/responses if
    something is wrong.

With these changes the connection between js version of kites will be
backwards compatible, but in order to be fully compatible and if we agree that
this is the way to go, golang implementation will need to adapt to these
changes as well.

Please let me know if there is something missing, or if I am assuming more than
I should, so that we can come up with a proper protocol definition.

/cc @gokmen @cihangir @rjeczalik @szkl @ppknap @sinan

Add build instructions

I am trying to build kite-bundle.js file from the source but I get following error.

➜  kite.js git:(master) gulp
module.js:338
    throw err;
          ^
Error: Cannot find module 'coffee-script/register'
    at Function.Module._resolveFilename (module.js:336:15)
    at Function.Module._load (module.js:278:25)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (/Users/cenk/go/src/github.com/koding/kite.js/gulpfile.js:1:63)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Module.require (module.js:365:17)

I installed coffeescript and gulp packages before I run gulp command.

tighten down event api

Right now we're emitting rather a lot of events. I'd like to pair this down, and perhaps change the names of the events. For now we emit both connected and ready when the underlying connection is open. I think we should get rid of both of these, and replace them with a single open event. We have a similar "problem" with the disconnected event. We should rename it close. The error event is perhaps ok, except for the fact that the node EventEmitter implementation special cases this event. The user has to explicitly listen for it, or it will get converted into an "unknown, uncaught error event" or something equally useless. For this reason, it might be better to a) add a default handler for this event that does not mask the original error, or b) call the event something else, like fail or kiteError. Opening for discussion.,

Define components of kite

This is gonna be the epic which is gonna track the progress of introduction of the several Kite components.

remove noisy array wrappings

right now the API is a big ugly:

k.tell('square', [4], log)

I'd like to remove the unnecessary boxing wherever we can.

make this repo public

I don't think we are quite ready to release this yet, but there are advantages to having this open-sourced soon. For instance, we can use testling-ci for free if this project is open source.

switch to gulp

Makefile is increasingly hard to maintain. Work is underway to switch to gulp.

Replace enableLogging util with injectable Logger class

instead of relying on a function (enableLogging) that depends on a kite being an EventEmitter instance, create a new KiteLogger class and allow logger option to be passed while creating a kite:

const { Logger, Kite } = require('kite.js')
const { DebugLevel } = require('kite.js/lib/constants')
const Kite = new Kite({
  name: 'foo',
  logger: new Logger({
    name: 'foo',
    level: DebugLevel.INFO,
    handlers: {
      error: (...args) => sendToPaperTrail('error', ...args),
      warn: (...args) => sendToPaperTrail('warn', ...args),
      info: (...args) => sendToPaperTrail('info', ...args),
    }
  })
})
  • a logger will use console.error, console.warn, console.info as its handlers if any of them is not being passed

    const logger = new Logger({name: 'foo'})
    logger.critical('message is here, hello world')
    // => [foo] CRITICAL      message is here, hello world
  • a logger will expose 6 methods in which the passed handlers are being used:

    • logger.critical(...args): void -> handlers.error
    • logger.error(...args): void -> handlers.error
    • logger.warning(...args): void -> handlers.warn
    • logger.notice(...args): void -> handlers.info
    • logger.info(...args): void -> handlers.info
    • logger.debug(...args): void -> handlers.info
  • a logger will accept a level option while it's being created which will be used to decide when one of the methods are gonna produce logs (each method has its own DebugLevel associated with it)

    • These are the defined DebugLevels available:

      export const DebugLevel = {
        CRITICAL: 0,
        ERROR: 1,
        WARNING: 2,
        NOTICE: 3,
        INFO: 4,
        DEBUG: 5,
      }
    • This will allow each exposed method to work since all debug levels are lower than DebugLevel.DEBUG which is 0:

      const logger = new Logger({
        name: 'foo',
        level: DebugLevel.DEBUG
      })
      
      logger.debug('Hello world - debug') // DebugLevel.DEBUG == 5
      logger.warn('Hello world - warn') // DebugLevel.WARNING == 2
      logger.critical('Hello world - critical') // DebugLevel.CRITICAL == 0
      // => [kite] DEBUG      Hello world - debug
      // => [kite] WARNING    Hello world - warning
      // => [kite] CRITICAL   Hello world - critical
    • But this will only work for critical as only the DebugLevel.CRITICAL is lower or equal to 0.

      const logger = new Logger({
        name: 'foo',
        level: DebugLevel.CRITICAL
      })
      
      logger.debug('Hello world - debug') // DebugLevel.DEBUG == 5
      logger.warn('Hello world - warn') // DebugLevel.WARNING == 2
      logger.critical('Hello world - critical') // DebugLevel.CRITICAL == 0
      // => [kite] CRITICAL   Hello world - critical

Using kite.js in the browser Error?!

Hello, I tried to use kite.js in the browser, but I always get the same error at kite-bundle.js:3045 that Promise.method is a undefined function.

Change default value of autoConnect & autoReconnect option

I am finding myself to write new Kite({url: '...', autoConnect: false, autoReconnect: false}) all the time in following scenarios:

  • writing unit tests for kite
  • if i am initializing other objects other than kite as well, i want to have a preparation phase and want to call kite.connect() afterwards.
  • if i want to have a kite as a singleton e.g export default new Kite({ ... })

Having to write auto{Connect,Reconnect} all the time is a little bit tedious.

I would probably not need autoReconnect, since it's about connecting after disconnecting. But i still would expect from an object to connect something when i tell it to.

@gokmen I think this is good enough to be one of our breaking changes for moving forward to v2.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.