Git Product home page Git Product logo

opentok-node's Introduction

OpenTok Node SDK

Build Status Contributor Covenant

Tokbox is now known as Vonage

The OpenTok Node SDK provides methods for:

If you are looking for the JavaScript Client SDK please see the @opentok/client NPM module.

Note!

This library is designed to work with the Tokbox/OpenTok platform, part of the Vonage Video API. If you are looking to use the Vonage Video API and using the Vonage Customer Dashboard, you will want to install the Vonage Server SDK for Node, which includes support for the Vonage Video API.

Not sure which exact platform you are using? Take a look at this guide.

If you are using the Tokbox platform, do not worry! The Tokbox platform is not going away, and this library will continue to be updated. While we encourage customers to check out the new Unified platform, there is no rush to switch. Both platforms run the exact same infrastructure and capabilities, with the main difference being a unified billing interface and easier access to Vonage’s other CPaaS APIs.

If you are new to the Vonage Video API, head on over to the Vonage Customer Dashboard to sign up for a developer account and check out the Vonage Server SDK for Node.

Installation using npm (recommended):

npm helps manage dependencies for node projects. Find more info here: http://npmjs.org.

Run this command to install the package and adding it to your package.json:

$ npm install opentok --save

Usage

Initializing

Import the module to get a constructor function for an OpenTok object, then call it with new to instantiate an OpenTok object with your own API Key and API Secret.

const OpenTok = require("opentok");
const opentok = new OpenTok(apiKey, apiSecret);

Increasing Timeouts

The library currently has a 20 second timeout for requests. If you're on a slow network, and you need to increase the timeout, you can pass it (in milliseconds) when instantiating the OpenTok object.

const OpenTok = require("opentok");
const opentok = new OpenTok(apiKey, apiSecret, { timeout: 30000});

Creating Sessions

To create an OpenTok Session, use the OpenTok.createSession(properties, callback) method. The properties parameter is an optional object used to specify whether the session uses the OpenTok Media Router, to specify a location hint, and to specify whether the session will be automatically archived or not. The callback has the signature function(error, session). The session returned in the callback is an instance of Session. Session objects have a sessionId property that is useful to be saved to a persistent store (such as a database).

// Create a session that will attempt to transmit streams directly between
// clients. If clients cannot connect, the session uses the OpenTok TURN server:
opentok.createSession(function (err, session) {
  if (err) return console.log(err);

  // save the sessionId
  db.save("session", session.sessionId, done);
});

// The session will the OpenTok Media Router:
opentok.createSession({ mediaMode: "routed" }, function (err, session) {
  if (err) return console.log(err);

  // save the sessionId
  db.save("session", session.sessionId, done);
});

// A Session with a location hint
opentok.createSession({ location: "12.34.56.78" }, function (err, session) {
  if (err) return console.log(err);

  // save the sessionId
  db.save("session", session.sessionId, done);
});

// A Session with an automatic archiving
opentok.createSession({ mediaMode: "routed", archiveMode: "always" }, function (
  err,
  session
) {
  if (err) return console.log(err);

  // save the sessionId
  db.save("session", session.sessionId, done);
});

Generating Tokens

Once a Session is created, you can start generating Tokens for clients to use when connecting to it. You can generate a token by calling the OpenTok.generateToken(sessionId, options) method. Another way is to call the generateToken(options) method of a Session object. The options parameter is an optional object used to set the role, expire time, and connection data of the Token. For layout control in archives and broadcasts, the initial layout class list of streams published from connections using this token can be set as well.

// Generate a Token from just a sessionId (fetched from a database)
token = opentok.generateToken(sessionId);

// Generate a Token from a session object (returned from createSession)
token = session.generateToken();

// Set some options in a Token
token = session.generateToken({
  role: "moderator",
  expireTime: new Date().getTime() / 1000 + 7 * 24 * 60 * 60, // in one week
  data: "name=Johnny",
  initialLayoutClassList: ["focus"],
});

Working with archives

You can start the recording of an OpenTok Session using the OpenTok.startArchive(sessionId, options, callback) method. The options parameter is an optional object used to set the name of the Archive. The callback has the signature function(err, archive). The archive returned in the callback is an instance of Archive. Note that you can only start an archive on a Session with connected clients.

opentok.startArchive(sessionId, { name: "Important Presentation" }, function (
  err,
  archive
) {
  if (err) {
    return console.log(err);
  } else {
    // The id property is useful to save off into a database
    console.log("new archive:" + archive.id);
  }
});

You can also disable audio or video recording by setting the hasAudio or hasVideo property of the options parameter to false:

var archiveOptions = {
  name: "Important Presentation",
  hasVideo: false, // Record audio only
};
opentok.startArchive(sessionId, archiveOptions, function (err, archive) {
  if (err) {
    return console.log(err);
  } else {
    // The id property is useful to save to a database
    console.log("new archive:" + archive.id);
  }
});

By default, all streams are recorded to a single (composed) file. You can record the different streams in the session to individual files (instead of a single composed file) by setting the outputMode option to 'individual' when you call the OpenTok.startArchive() method:

var archiveOptions = {
  name: "Important Presentation",
  outputMode: "individual",
};
opentok.startArchive(sessionId, archiveOptions, function (err, archive) {
  if (err) {
    return console.log(err);
  } else {
    // The id property is useful to save off into a database
    console.log("new archive:" + archive.id);
  }
});

You can stop the recording of a started Archive using the OpenTok.stopArchive(archiveId, callback) method. You can also do this using the Archive.stop(callback) method an Archive instance. The callback has a signature function(err, archive). The archive returned in the callback is an instance of Archive.

opentok.stopArchive(archiveId, function (err, archive) {
  if (err) return console.log(err);

  console.log("Stopped archive:" + archive.id);
});

archive.stop(function (err, archive) {
  if (err) return console.log(err);
});

To get an Archive instance (and all the information about it) from an archiveId, use the OpenTok.getArchive(archiveId, callback) method. The callback has a function signature function(err, archive). You can inspect the properties of the archive for more details.

opentok.getArchive(archiveId, function (err, archive) {
  if (err) return console.log(err);

  console.log(archive);
});

To delete an Archive, you can call the OpenTok.deleteArchive(archiveId, callback) method or the delete(callback) method of an Archive instance. The callback has a signature function(err).

// Delete an Archive from an archiveId (fetched from database)
opentok.deleteArchive(archiveId, function (err) {
  if (err) console.log(err);
});

// Delete an Archive from an Archive instance, returned from the OpenTok.startArchive(),
// OpenTok.getArchive(), or OpenTok.listArchives() methods
archive.delete(function (err) {
  if (err) console.log(err);
});

You can also get a list of all the Archives you've created (up to 1000) with your API Key. This is done using the OpenTok.listArchives(options, callback) method. The parameter options is an optional object used to specify an offset and count to help you paginate through the results. The callback has a signature function(err, archives, totalCount). The archives returned from the callback is an array of Archive instances. The totalCount returned from the callback is the total number of archives your API Key has generated.

opentok.listArchives({ offset: 100, count: 50 }, function (
  error,
  archives,
  totalCount
) {
  if (error) return console.log("error:", error);

  console.log(totalCount + " archives");
  for (var i = 0; i < archives.length; i++) {
    console.log(archives[i].id);
  }
});

Note that you can also create an automatically archived session, by passing in 'always' as the archiveMode option when you call the OpenTok.createSession() method (see "Creating Sessions," above).

For composed archives, you can set change the layout dynamically, using the OpenTok.setArchiveLayout(archiveId, type, stylesheet, screenshareType, callback) method:

opentok.setArchiveLayout(archiveId, type, null, null, function (err) {
  if (err) return console.log("error:", error);
});

You can set the initial layout class for a client's streams by setting the layout option when you create the token for the client, using the OpenTok.generateToken() method. And you can change the layout classes for streams in a session by calling the OpenTok.setStreamClassLists(sessionId, classListArray, callback) method.

Setting the layout of composed archives is optional. By default, composed archives use the "best fit" layout (see Customizing the video layout for composed archives).

For more information on archiving, see the OpenTok archiving developer guide.

Working with live streaming broadcasts

Important: Only routed OpenTok sessions support live streaming broadcasts.

To start a live streaming broadcast of an OpenTok session, call the OpenTok.startBroadcast() method. Pass in three parameters: the session ID for the session, options for the broadcast, and a callback function:

var broadcastOptions = {
  outputs: {
    hls: {},
    rtmp: [
      {
        id: "foo",
        serverUrl: "rtmp://myfooserver/myfooapp",
        streamName: "myfoostream",
      },
      {
        id: "bar",
        serverUrl: "rtmp://mybarserver/mybarapp",
        streamName: "mybarstream",
      },
    ],
  },
  maxDuration: 5400,
  resolution: "640x480",
  layout: {
    type: "verticalPresentation",
  },
};
opentok.startBroadcast(sessionId, broadcastOptions, function (
  error,
  broadcast
) {
  if (error) {
    return console.log(error);
  }
  return console.log("Broadcast started: ", broadcast.id);
});

See the API reference for details on the options parameter.

On success, a Broadcast object is passed into the callback function as the second parameter. The Broadcast object has properties that define the broadcast, including a broadcastUrls property, which has URLs for the broadcast streams. See the API reference for details.

Call the OpenTok.stopBroadcast() method to stop a live streaming broadcast pass in the broadcast ID (the id property of the Broadcast object) as the first parameter. The second parameter is the callback function:

opentok.stopBroadcast(broadcastId, function (error, broadcast) {
  if (error) {
    return console.log(error);
  }
  return console.log("Broadcast stopped: ", broadcast.id);
});

You can also call the stop() method of the Broadcast object to stop a broadcast.

Call the Opentok.getBroadcast() method, passing in a broadcast ID, to get a Broadcast object.

You can also get a list of all the Broadcasts you've created (up to 1000) with your API Key. This is done using the OpenTok.listBroadcasts(options, callback) method. The parameter options is an optional object used to specify an offset, count, and sessionId to help you paginate through the results. The callback has a signature function(err, broadcasts, totalCount). The broadcasts returned from the callback is an array of Broadcast instances. The totalCount returned from the callback is the total number of broadcasts your API Key has generated.

opentok.listBroadcasts({ offset: 100, count: 50 }, function (
  error,
  broadcasts,
  totalCount
) {
  if (error) return console.log("error:", error);

  console.log(totalCount + " broadcasts");
  for (var i = 0; i < broadcasts.length; i++) {
    console.log(broadcasts[i].id);
  }
});

To change the broadcast layout, call the OpenTok.setBroadcastLayout() method, passing in the broadcast ID and the layout type.

You can set the initial layout class for a client's streams by setting the layout option when you create the token for the client, using the OpenTok.generateToken() method. And you can change the layout classes for streams in a session by calling the OpenTok.setStreamClassLists(sessionId, classListArray, callback) method.

Setting the layout of a live streaming broadcast is optional. By default, live streaming broadcasts use the "best fit" layout.

Sending signals

You can send a signal to all participants in an OpenTok Session by calling the OpenTok.signal(sessionId, connectionId, payload, callback) method and setting the connectionId parameter to null:

var sessionId =
  "2_MX2xMDB-flR1ZSBOb3YgMTkgMTE6MDk6NTggUFNUIDIwMTN-MC2zNzQxNzIxNX2";
opentok.signal(sessionId, null, { type: "chat", data: "Hello!" }, function (
  error
) {
  if (error) return console.log("error:", error);
});

Or send a signal to a specific participant in the session by calling the OpenTok.signal(sessionId, connectionId, payload, callback) method and setting all paramters, including connectionId:

var sessionId =
  "2_MX2xMDB-flR1ZSBOb3YgMTkgMTE6MDk6NTggUFNUIDIwMTN-MC2zNzQxNzIxNX2";
var connectionId = "02e80876-02ab-47cd-8084-6ddc8887afbc";
opentok.signal(
  sessionId,
  connectionId,
  { type: "chat", data: "Hello!" },
  function (error) {
    if (error) return console.log("error:", error);
  }
);

This is the server-side equivalent to the signal() method in the OpenTok client SDKs. See OpenTok signaling developer guide .

Disconnecting participants

You can disconnect participants from an OpenTok Session using the OpenTok.forceDisconnect(sessionId, connectionId, callback) method.

opentok.forceDisconnect(sessionId, connectionId, function (error) {
  if (error) return console.log("error:", error);
});

This is the server-side equivalent to the forceDisconnect() method in OpenTok.js: https://www.tokbox.com/developer/guides/moderation/js/#force_disconnect.

Forcing clients in a session to mute published audio

You can force the publisher of a specific stream to stop publishing audio using the Opentok.forceMuteStream(sessionId)method.

You can force the publisher of all streams in a session (except for an optional list of streams) to stop publishing audio using the Opentok.forceMuteAll() method. You can then disable the mute state of the session by calling the Opentok.disableForceMute() method.

Working with SIP Interconnect

You can add an audio-only stream from an external third-party SIP gateway using the SIP Interconnect feature. This requires a SIP URI, the session ID you wish to add the audio-only stream to, and a token to connect to that session ID.

var options = {
  from: "15551115555",
  secure: true,
};
opentok.dial(sessionId, token, sipUri, options, function (error, sipCall) {
  if (error) return console.log("error: ", error);

  console.log(
    "SIP audio stream Id: " +
      sipCall.streamId +
      " added to session ID: " +
      sipCall.sessionId
  );
});

For more information, see the OpenTok SIP Interconnect developer guide.

Getting Stream Info

You can get information on an active stream in an OpenTok session:

var sessionId =
  "2_MX6xMDB-fjE1MzE3NjQ0MTM2NzZ-cHVTcUIra3JUa0kxUlhsVU55cTBYL0Y1flB";
var streamId = "2a84cd30-3a33-917f-9150-49e454e01572";
opentok.getStream(sessionId, streamId, function (error, streamInfo) {
  if (error) {
    console.log(error.message);
  } else {
    console.log(stream.id); // '2a84cd30-3a33-917f-9150-49e454e01572'
    console.log(stream.videoType); // 'camera'
    console.log(stream.name); // 'Bob'
    console.log(stream.layoutClassList); // ['main']
  }
});

Pass a session ID, stream ID, and callback function to the OpenTok.getStream() method. The callback function is called when the operation completes. It takes two parameters: error (in the case of an error) or stream. On sucessful completion, the stream object is set, containing properties of the stream.

To get information on all active streams in a session, call the OpenTok.listStreams() method, passing in a session ID and a callback function. Upon sucess, the callback function is invoked with an array of Stream objects passed into the second parameter:

opentok.listStreams(sessionId, function(error, streams) {
  if (error) {
    console.log(error.message);
  } else {
    streams.map(function(stream) {
      console.log(stream.id); // '2a84cd30-3a33-917f-9150-49e454e01572'
      console.log(stream.videoType); // 'camera'
      console.log(stream.name); // 'Bob'
      console.log(stream.layoutClassList); // ['main']
    }));
  }
});

Samples

There are sample applications included in this repository. To get going as fast as possible, clone the whole repository and read the README in each of the sample directories:

Documentation

Reference documentation is available at https://tokbox.com/developer/sdks/node/reference/index.html.

Requirements

You need an OpenTok API key and API secret, which you can obtain by logging into your TokBox account.

The OpenTok Node SDK requires Node.js 14 or higher. It may work on older versions but they are no longer tested.

Release Notes

See the Releases page for details about each release.

Important changes since v2.2.0

Changes in v2.2.3:

The default setting for the createSession() method is to create a session with the media mode set to relayed. In previous versions of the SDK, the default setting was to use the OpenTok Media Router (media mode set to routed). In a relayed session, clients will attempt to send streams directly between each other (peer-to-peer); if clients cannot connect due to firewall restrictions, the session uses the OpenTok TURN server to relay audio-video streams.

Changes in v2.2.0:

This version of the SDK includes support for working with OpenTok archives.

The createSession() method has changed to take one parameter: an options object that has location and mediaMode properties. The mediaMode property replaces the properties.p2p.preference parameter in the previous version of the SDK.

The generateToken() has changed to take two parameters: the session ID and an options object that has role, expireTime and data properties.

See the reference documentation http://www.tokbox.com/opentok/libraries/server/node/reference/index.html and in the docs directory of the SDK.

Development and Contributing

Interested in contributing? We ❤️ pull requests! See the Development and Contribution guidelines.

Getting Help

We love to hear from you so if you have questions, comments or find a bug in the project, let us know! You can either:

opentok-node's People

Contributors

agutoli avatar aiham avatar alexlakatos avatar almet avatar aoberoi avatar bambooonedata avatar bsstoner avatar dependabot[bot] avatar dragonmantank avatar eauge avatar fongchin avatar hbaqai avatar jcague avatar jeffswartz avatar manchuck avatar marinaserranomontes avatar mend-for-github-com[bot] avatar michaeljolley avatar moficodes avatar msach22 avatar natim avatar pardel avatar rviscarra avatar songz avatar synthmusic avatar theoptimisticfactory avatar thepatrick avatar vamis avatar voltrevo avatar westy92 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

opentok-node's Issues

Update README.md to follow the standard outline

  • Install:
  • Install using npm
  • Download manually (using GitHub releases)
  • Usage:
  • Initializing
  • Creating Sessions
  • Generating Tokens
  • Working with Archives
  • Documentation
  • Requirements
  • Changes / Release Notes
  • Contributing / Testing

implement tests for proxy support

the current problem with the tests is that they look no different from the tests that don't use a proxy. hence there is no way to verify that the proxy is actually working, we only know that we didn't break the request by setting the proxy configuration.

generateToken should throw Errors instead of returning null

returning null assumes that a developer will be checking the return value, which almost never happens in the javascript ecosystem. this type of a mistake is one that is usually encountered in development (the wrong parameters are passed to the method), therefore its reasonable to blow up by throwing an Error.

Readme Link Incorrect

Most Readme links in documentation point to pages on tokbox that no longer exist.

Global variables are being rewritten

Dear Opentok Support,

I am currently investigating Opentok and its API. Have noticed, that in _doRequest() function you use global variables "options" and "req". It breaks the application built on Express, req is always empty after I request an opentok session (call _doRequest). Please, make them private variables, it is easy and won't affect the code flow, but will enhance the stability and compatibility.

Thanks!

createSession modifies passed in options object

Using this api and passing the options { mediaMode : "routed" } doesn't actually seem to created a routed connection. When I connect iOS clients they can't publish to more than one subscriber.... however, if I hard code tokens and session ids generated by the online dashboard for OpenTok, everything works perfectly.

I'm now going to implement a version of my own using the OpenTok REST api and the "https" request module to see if this avoids the issue.

export the default apiUrl

it is useful in scenarios where the apiUrl is optionally set, and the consumer needs to use the URL somewhere else in their code.

refactor archiving implementation to be more seamless

the current archiving implementation is built as a functional "extension" of the OpenTok object definition. it would be nice to clean this up to make the code less repetitive and harmonious. this also includes the jasmine based tests (which contrast with the other mocha based tests).

it would be favorable to keep the implementation of archiving decoupled. one possible solution is to export a "mix-in" function from lib/archiving.js that could be used to extend OpenTok.prototype.

Round expireTime number automatically

This issue is related to #75 and #73.

In addition to allowing a Date object to be given as the expireTime, it also makes sense to solve the common issue of a fractional number being specified by just automatically rounding the number to a whole number.

throw an error when constructors fail

It seems to not be a loud enough signal to return an Error object when the OpenTok constructor fails. this occurs when the apiKey or apiSecret arguments are invalid. A louder signal would be to throw the Error, and that seems to be the best practice recommendation.

Release on npm.js

The currently released version on npm.js is 0.3.4 which is too old. It's also referencing the bsstoner/opentok repository.

Would it be possible to release it with the 1.0.1 version?
Thanks!

Proposal: generateToken's expireTime also accept a Date object

Currently the expireTime option expects a unix timestamp in seconds. This means that every user would have to understand how to convert a Date object into a unix timestamp in seconds properly. I don't see any way to get this value without first going through a Date object. That conversion can be error-prone for users (see #71). This proposal is to make the API backwards compatible and accept Number | Date types.

Feature: integration testing

sometimes just checking against canned responses (fixtures) is not good enough.

the main use case for integration testing is running the suite against the internal nightly build environment to detect problems (incompatible API changes, bad handling in the SDKs, etc) early.

one of the challenges in running integration tests is that many of the operations being tested require a specific state on the server. for example: starting an archive successfully requires that at least one client connection to the specific OpenTok session exists, deleting an archive requires an archive to exist, stopping an archive requires a started archive, etc.

one approach is being explored in #65. this approach attempts to repurpose the unit tests to run in a different mode where they can hit live servers.

another approach could be scenario-driven, where a scripted set of operations are carried out sequentially. this could be better in address the challenge with server side state.

another technique that could be employed to address the server side state challenge is using a specific build of the client side opentok.js library that can run in node. the integration tests could "shell out" to a CLI that can conduct client side operations that will assist in setting up the proper state (like a client connection before starting an archive).

add JSON Schema validations

In the PHP SDK, we are using JSON Schema to validate what comes back from the server. This would be a nice catch for a Response Error where the version of the SDK is outdated against the API.

expireTime causes 1004 authentication error.

Works

token = opentok.generateToken( myToken, {
  role: 'moderator'
});

Broken

token = opentok.generateToken( myToken, {
  role: 'moderator',
  expireTime: (new Date().getTime() / 1000)+(7 * 24 * 60 * 60)
});

grunt task for release

Ideas:

  • update version strings (or check that they match)
  • make new commit, tag, push
  • shrinkwrap the module and upload it to GitHub Releases
  • upload to npm

finish implementing unit tests

find a suitable mocking solution so that network calls don't actually go over the network. this may be intertwined with adding a dependency injection interface into the OpenTokSDK constructor.

Standardize error handling

There needs to be a set of Error types defined and their meaning nailed down so that developers can predictably deal with error conditions.

This will also be subject to an internal API Review.

unable to deply latest version on heroku node.js app

2787 error Valid install targets:
2787 error ["0.10.0","0.8.3","0.9.0","0.9.1","0.9.5","1.0.0","1.1.0","1.1.1","1.2.0","1.9.0","1.9.1","1.9.2","1.9.3","1.9.5","1.9.7","1.9.8","1.9.9","2.0.0","2.0.1","2.0.
2787 error at installTargetsError (/tmp/build_5556f456-e0fe-43e4-8a0e-fb380ad7bac7/vendor/node/lib/node_modules/npm/lib/cache.js:685:10)
2787 error at /tmp/build_5556f456-e0fe-43e4-8a0e-fb380ad7bac7/vendor/node/lib/node_modules/npm/lib/cache.js:607:10
2787 error at saved (/tmp/build_5556f456-e0fe-43e4-8a0e-fb380ad7bac7/vendor/node/lib/node_modules/npm/node_modules/npm-registry-client/lib/get.js:138:7)
2787 error at Object.oncomplete (fs.js:107:15)
2788 error If you need help, you may report this log at:
2788 error http://github.com/isaacs/npm/issues
2788 error or email it to:
2788 error [email protected]
2789 error System Linux 3.8.11-ec2
2790 error command "/tmp/build_5556f456-e0fe-43e4-8a0e-fb380ad7bac7/vendor/node/bin/node" "/tmp/build_5556f456-e0fe-43e4-8a0e-fb380ad7bac7/vendor/node/bin/npm" "install"
2791 error cwd /tmp/build_5556f456-e0fe-43e4-8a0e-fb380ad7bac7
2792 error node -v v0.10.4
2793 error npm -v 1.2.18
2794 verbose exit [ 1, true ]

! Push rejected, failed to compile Node.js app

To [email protected]:office-hours-testing.git
! [remote rejected] development-bit -> master (pre-receive hook declined)

Session#generateToken fails

Calling session.generateToken() produces the following error:

Uncaught TypeError: Object #<Object> has no method 'generateToken'

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.