Giter VIP home page Giter VIP logo

africastalking-node.js's Introduction

Africa's Talking Node.js SDK

NPM

The wrapper provides convenient access to the Africa's Talking API from applications written for Node.js.

Documentation

Take a look at the API docs here.

Install

You can install the package from npm by running:

$ npm install --save africastalking

Usage

The package needs to be configured with your app username and API key, which you can get from the dashboard.

You can use this SDK for either production or sandbox apps. For sandbox, the app username is ALWAYS sandbox

const credentials = {
    apiKey: 'YOUR_API_KEY',         // use your sandbox app API key for development in the test environment
    username: 'YOUR_USERNAME',      // use 'sandbox' for development in the test environment
};
const AfricasTalking = require('africastalking')(credentials);

// Initialize a service e.g. SMS
const sms = AfricasTalking.SMS

// Use the service
const options = {
    to: ['+254711XXXYYY', '+254733YYYZZZ'],
    message: "I'm a lumberjack and its ok, I work all night and sleep all day"
}

// Send message and capture the response or error
sms.send(options)
    .then( response => {
        console.log(response);
    })
    .catch( error => {
        console.log(error);
    });

See example for more usage examples.

Initialization

Initialize the SDK as a requirement by doing require('africastalking')(options). After initialization, you can get instances of offered services as follows:

Services

All methods are asynchronous

All phone numbers use the international format. e.g. +234xxxxxxxx.

SMS

  • send({ to, from, message, enqueue }): Send an SMS to one or more phone numbers

  • send([{ to, from, message, enqueue }]): Send multiple SMSes to one or more phone numbers

    • to: Recipient(s) phone number. Can either a single phone number or an array of phone numbers REQUIRED
    • from: Shortcode or alphanumeric ID that is registered with Africa's Talking account
    • message: SMS content. REQUIRED
    • enqueue: Set to true if you would like to deliver as many messages to the API without waiting for an acknowledgement from telcos.
  • sendPremium({ to, from, message, enqueue, keyword, linkId, retryDurationInHours }): Send premium SMS

    • keyword: You premium product keyword
    • linkId: We forward the linkId to your application when the user send a message to your service
    • retryDurationInHours: It specifies the number of hours your subscription message should be retried in case it's not delivered to the subscriber
  • fetchMessages({ lastReceivedId }): Manually retrieve your messages

    • lastReceivedId: "This is the id of the message that you last processed". Defaults to 0
  • fetchSubscription({ shortCode, keyword, lastReceivedId }): Fetch your premium subscription data

    • shortCode: This is the premium short code mapped to your account. REQUIRED
    • keyword: A premium keyword under the above short code and mapped to your account. REQUIRED
    • lastReceivedId: "This is the id of the message that you last processed". Defaults to 0
  • createSubscription({ shortCode, keyword, phoneNumber }): Create a premium subscription

    • shortCode: This is the premium short code mapped to your account. REQUIRED
    • keyword: A premium keyword under the above short code and mapped to your account. REQUIRED
    • phoneNumber: The phone number to be subscribed. REQUIRED

For more information on:

Airtime

  • send({ recipients }): Send airtime to a bunch of phone numbers.

    • recipients: An array of objects containing the following keys:

      • phoneNumber: Recipient of airtime. REQUIRED.
      • currencyCode: 3-digit ISO format currency code. REQUIRED.
      • amount: Amount to charge. REQUIRED.
    • maxNumRetry: This allows you to specify the maximum number of retries in case of failed airtime deliveries due to various reasons such as telco unavailability. The default retry period is 8 hours and retries occur every 60seconds. For example, setting maxNumRetry=4 means the transaction will be retried every 60seconds for the next 4 hours.OPTIONAL.

  • findTransactionStatus(transactionId): Find the status of a given airtime transaction.

    • transactionId: ID of the transaction you would like to find.

For more information, please read https://developers.africastalking.com/docs/airtime/sending

MobileData

  • send({ productName, recipients })

    • productName: This is the application's product name.
    • recipients: An array of objects containing the following keys:
  • findTransaction({ transactionId }): Find a mobile data transaction

  • fetchWalletBalance(): Fetch a mobile data product balance

For more information, please read the https://developers.africastalking.com/docs/data/overview

Voice

  • call({ callFrom, callTo }): Initiate a phone call

    • callFrom: Your Africa's Talking issued virtual phone number. REQUIRED
    • callTo: Comma-separated string of phone numbers to call. REQUIRED
    • clientRequestId: Additional information that can be used to tag the call in your callback URL.
  • fetchQuedCalls({ phoneNumber }): Get queued calls

    • phoneNumber: Your Africa's Talking issued virtual phone number. REQUIRED
  • uploadMediaFile({ phoneNumber, url }): Upload voice media file

    • phoneNumber: Your Africa's Talking issued virtual phone number. REQUIRED
    • url: URL to your media file. REQUIRED

Helpers that will construct proper xml to send back to Africa's Taking API when it comes POSTing.

  • Say, Play, GetDigits, Dial, Record, Enqueue, Dequeue, Conference, Redirect, Reject

Remember to send back an HTTP 200.

For more information, please read https://developers.africastalking.com/docs/voice/overview and issue #15

USSD

For more information, please read https://developers.africastalking.com/docs/ussd/overview

Token

  • generateAuthToken(): Generate an auth token to use for authentication instead of an API key.

Application

  • fetchApplicationData(): Get app information. e.g. balance

For more information, please read https://developers.africastalking.com/docs/application

Development

Run all tests:

$ npm install
$ npm test

or on Windows...

$ npm install
$ npm run test-windows

Issues

If you find a bug, please file an issue on our issue tracker on GitHub.

africastalking-node.js's People

Contributors

aksalj avatar alpha1202 avatar calvinkarundu avatar cooleraid avatar crispinkoech avatar daggieblanqx avatar dependabot[bot] avatar favourori avatar gachez avatar habbes avatar hassanbahati avatar ianjuma avatar ibrixze avatar kevokevoh avatar mayomi1 avatar mbuguanewton avatar mrteey avatar ndrymes avatar pbombo avatar roboflank avatar tawn33y 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

africastalking-node.js's Issues

Simpler USSD builder for complex menus

Hello, the method for building USSD menus as shown in the docs (using a series of if/switch statements on the input) seems tedious and impractical in the case of complex nested menus.

I've written a simple library that is compatible with the Africastalking API to make this easier. It takes a different approach by treating each menu screen as state and the whole ussd session as state machine, and uses rules based on input values, regular expressions or functions to link two states.

Here's the the library (ussd-menu-builder). The library is usable but lacks unit tests and has an incomplete documentation. I intend to finish those up before pushing to npm.

I thought I'd share it with you guys. You probably won't add it to your official NodeJs library cause it maybe a bit opinionated, but you could use it when giving tutorials or other projects.

Broken links on README.md file

There are multiple broken links on the README.md file.
This is because ATs documentation link changed:

-https://docs.africastalking.com/
+https://developers.africastalking.com/

The link to npm is also broken

Updating dependencies

There are some few dependencies that require upgrading. As shown by the image below the libraries using hapi require an update

Screenshot 2023-10-26 at 3 44 19 PM

api helper to set response of 200

Maybe we can set a response of 200 when replying; without this, the AT API retries to send a DLR or message to US even when we received; but didn't acknowledge.

Support for Deno

I need Africa's to be able to import africastalking on Deno as a third party package. I'll be glad if anyone made it happen.

Vulnerability Report

I rannpm audit on my project and encountered the following vulnerabilities as seen in the image below; Is there a recommended plan to fix it? Maybe, you could run npm audit to view possible vulnerabilities and fixes.
screen shot 2018-09-14 at 4 12 13 pm

High vulnerability with [email protected]

image

High vulnerability with unirest -> hawk -> cryptiles. If this is something we think won't break if we upgrade, can submit the pull request. Any info before I attempt that?

Typescript support

It would be amazing if we have typescript support for the nodejs sdk, currently it doesn't have the support for nodejs

Kindly provide docs for any of your demo apps

This will be even much more elaborate than it's now : ) An example is

├── app
│   ├── build
│   ├── node_modules
│   ├── src
│       ├── final
│       ├── work
|          ├── step-1
|          ├── step-2
|          ├── step-n
|          ├── step-final

destructuring an undefined key

Line 21 of airtime.js in the lib folder of the npm package has a bug, or rather the code in the said line 21 cannot work with the code on the documentation.

Validation throws errors should not throw errors outside promise

I noticed in SMS.send and other api wrapper methods you're calling _validateParams() outside the Promise wrapper and throwing an error. This means the user has to wrap the method call in try-catch block to prevent a crash but still has to check for other errors using the catch() hook of the Promise, this seems counter-intuitive. Wouldn't it be better to just include the _validateParams() call within the promise block so that an error thrown is handled in the promise's catch() hook?
Maybe you can add a property to the error thrown to indicate that it was a validation error.

Airtime Error in customAxios folder: ...data

Hello Africastalking,

I am having an issue with my node application which gives me the error:

/var/www/server/node_modules/africastalking/lib/customAxios/airtime.js:7
...data,
^^^
SyntaxError: Unexpected token ...

I think it refers to the three dots before the variable data.

How can this be solved because it runs okay on my localhost but when I try to run it on the server it gives me the said error.

Thank you.

Airtime Implementation

Hello, I would like to use the airtime API but noticed it's not yet implemented. I would like to add the implementation and make a pull request if you don't mind.

I'm going to implement the airtime.send(options) as shown in the repository doc.

Do you have any coding guide or convention I ought to follow?

`npm test` show fetchAccount() fail with 401 error on fresh install

In a fresh clone of the AT nodejs API, there is one test failure for AfricasTalking.fetchAccount().

Steps to Reproduce

  1. git clone https://github.com/AfricasTalkingLtd/africastalking-node.js
  2. npm install
  3. npm test

Expected Result

  15 passing (16s)

Actual Result

  14 passing (14s)
  1 failing

  1) Account fetched account info:
     Error: timeout of 5000ms exceeded. Ensure the done() callback is being called in this test.

empty sessionId in params object

I get an undefined with

    var endSession = false;
    var message = '';

    var sessionId = params.sessionId;
    var serviceCode = params.serviceCode;
    var phoneNumber = params.phoneNumber;

    console.log(sessionId, serviceCode, phoneNumber, params.text);

result:

undefined '*384*306#' '+254701435178' '1'

Request for Contribution Guide

Problem

Contributors to the AfricaIsTalking API would benefit from having clear and comprehensive guidelines on how to contribute effectively to the project. Currently, there is no contribution guide available, making it challenging for newcomers to get started and for existing contributors to follow best practices consistently.

Solution

We propose creating a Contribution Guide for the AfricaIsTalking API. This guide will provide step-by-step instructions and best practices for contributing to the project. It should cover topics such as:

  • Setting up the development environment
  • How to submit bug reports and feature requests
  • Guidelines for writing and formatting code
  • The pull request process
  • Code review expectations
  • Testing and quality assurance procedures
  • Licensing and code of conduct

Benefits

A well-structured contribution guide will have several advantages:

  1. Onboarding New Contributors: Newcomers will find it easier to understand the project's workflow and coding standards, reducing the barrier to entry.

  2. Consistency: Contributors will follow a consistent process when submitting contributions, making it easier for maintainers to review and merge changes.

  3. Improved Code Quality: By providing guidelines for writing code and running tests, we can ensure that contributions meet the project's quality standards.

  4. Community Growth: A clear contribution guide can attract more contributors, fostering a healthy and active open-source community.

Acceptance Criteria:

  • Create a new file named CONTRIBUTING.md in the project repository.
  • Document the contribution process, coding standards, and testing procedures in the CONTRIBUTING.md file.
  • Include information on how to report issues and request features.
  • Mention the project's code of conduct and licensing.
  • Ensure that the guide is clear, concise, and easy to follow.
  • Share the contribution guide with the project's community through relevant channels.

Additional Information:

We believe that providing a contribution guide will greatly enhance the development experience for all contributors and help the AfricaIsTalking API project thrive. Your input and contributions to creating this guide are highly appreciated.

Please feel free to discuss and offer suggestions related to this issue. Thank you for your support and dedication to the project!

ES6 branch

It would be interesting to make use of ES6 features already available on stable node such as generators

node v5

node v5 advisory on the README? I think we'll just make the move this early and ignore the es5 branch.

and just maybe have this instead:

Ubuntu

curl -sL https://deb.nodesource.com/setup_5.x | sudo -E bash -
sudo apt-get install -y nodejs

Other platforms

https://nodejs.org/en/download/package-manager/

are we shooting for backward compatibility?

401 on sandbox

Hi,

I just upgraded from 0.0.2 to 0.0.9 so that I can use the sandbox.

When I instrument my app using my production API account + key, it works great:

c2-dev-6 { username: 'ABC',
c2-dev-6   apiKey: 'XXX',
c2-dev-6   format: 'json',
c2-dev-6   sandbox: 'false' }

But when I instrument my app using my sandbox API account + key, I get 401 when I send a message:

c2-dev-7 { username: 'ABC',
c2-dev-7   apiKey: 'YYY',
c2-dev-7   format: 'json',
c2-dev-7   sandbox: true }

Any thoughts? I've tried passing true as both as a string and boolean.

ENOTFOUND Error when sending sms

Hey,

Getting the following error whenever I try sending a message either through the sandbox api and even the production one:

{ Error: getaddrinfo ENOTFOUND api.africastalking.com api.africastalking.com:443
    at errnoException (dns.js:28:10)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:76:26)
  code: 'ENOTFOUND',
  errno: 'ENOTFOUND',
  syscall: 'getaddrinfo',
  hostname: 'api.africastalking.com',
  host: 'api.africastalking.com',
  port: 443 }

Thanks!

Vulnerability Report on Axios


                       === npm audit security report ===


                                 Manual Review
             Some vulnerabilities require your attention to resolve

          Visit https://go.npm.me/audit-guide for additional guidance


  High            Server-Side Request Forgery

  Package         axios

  Patched in      >=0.21.1

  Dependency of   africastalking

  Path            africastalking > axios

  More info       https://npmjs.com/advisories/1594

Publish new edits

@aksalj The voice call promise would reject as the return status from AT's API would be 200 instead of 201. I edited the test to cater for both responses. This shouldn't be a problem as both 200 and 201 technically refer to successful requests.

Implement Payments / Premium SMS

Finish up on premium SMS and implement payments.

  • Implement premiumSMS
  • Implement checkout (C2B) @pbombo

payments

var options = {
  'phoneNumber': '+2547XXXXXXXX',  
  'productId': 'ATX_Id324324153452', 
  'amount': 'KES 2000' 
}

Payment.send(options)
  .then(success)
  .catch(error);

send different messages to different numbers simultaneously ?

For one of my project, I want to send different messages to different numbers simultaneously, for instance,
when a loan is given out, a message (you have recieved a loan of <some amount> from person X is sent to the borrower, and another sent to the lender (You have sent <some amount> to person Y).
But africastalking seems not to have that options

What I propose could enable such flexibility;

import AfricasTalking from "africastalking";

const africasTalking = new AfricasTalking({
  username: "sandbox",
  apiKey: process.env.AFRICA_TALKING_KEY
});

const sms = africasTalking.SMS;

...

  sms.send([
   {
    to: phone1,
    message: `message to ${recipient1}.`
   },
   {
     to: phone2,
    message: `message to ${recipient2}.`
   }
  ])

...

what africastalking accepts;

  sms.send(
   {
    to: phone1,
    message: `message to ${recipient1}.`
   }
 )

SMS Message With A Different String Font Being Sent in a Cryptic Manner

Hello,

How does the SMS service deal with different fonts? When i use certain fonts, the message that's sent is in a different form. Some fonts are seemingly being parsed/escaped by ATs validation layer such that a string like 𝗛𝗲𝗹𝗹𝗼 is sent as d 'd 2d 1d 1d. How can I solve this? Using nodeJS for the backend

Use supertest to mock API responses

The test suite in npm test currently does not validate that the responses are handled for all libraries. Only the USSD API makes use of the supertest server to mock API responses. This ought to be extended to all libraries. From what I can tell, the following libraries need API response testing:

  • SMS
  • Account
  • Airtime
  • USSD

It doesn't look like the voice.js or payment.js libraries are tested.

Voice API `callTo` Parameter Only Initiates Call to Last Number in Array

Issue Description

The Voice API currently specifies the CallTo parameter as an array of phone numbers in comma-separated string format, which can be passed to the options object as shown below:

 const options = {
      callFrom: "+256******", // Set your Africa's Talking phone number in international format
      callTo: ["+2567*******", "+256*******"], // Set the numbers you want to call to in a comma-separated list
    };

However, when initiating a call, it appears that the API is only dialing the last number in the array, rather than calling all the numbers as expected.

Expected Behavior

The expected behavior is for the callTo parameter to facilitate calling all the numbers listed in the array, ensuring that each number in the list receives a call.

voice helpers

the voice helpers are very interesting; what approach do we take? plain xml response? or command to construct xml ? The helpers will be great, this will make voice so easy 👍

voice.say("X is a letter! It's not a word") 

Here the approach is to wrap say around root xml response - what of nested commands? and attributes, how to create the xml response?

Of course this is for incoming calls, with the callback url handler.
voice.call is ok. I don't think there's much there. I mean initiating a call.

voice.say("say something", voice="woman") // ?

Say then Play a URL

/*
<Say>Please listen to our awesome record</Say>
<Play url="http://www.myvoicemailserver.com/audio/vmail.wav"/>
*/
voice.say("Hi, listen to", play=url)

and how do we wrap getDigits when we say?

voice.say("say something I'm giving ... ", voice=woman, getDigits=True, record=True) // ?
// sadly without named parameters
// also, recording - maybe an attribute to be set

call redirect?

if (dtmfDigit === '9') {
   voice.redirect('http://some_url_callback');
}

then, this would be expected.

<Response>
  <Dial phoneNumbers="+254711XXXYYY,+254733YYYZZZ,[email protected]" ringBackTone="http://mymediafile.com/playme.mp3" record="true" sequential="true"/>
</Response>

maps to

// callerId specific to calling out from SIP
voice.dial(phoneNumbers=phones, maxDurationInSec=10, record=True, 
                ringBackTone="some_url", sequential="True", callerId="some_num");

Problem with this is that we need all possible mappings, and I think there's many cases, we might miss a few and not generate a proper functional XML string, but the XML response will still work.

So, basically we generate this by passing attributes on a command, is this a good approach?
we also need a SIP section, will look at this later.

The supplied authentication is invalid

I am using "africastalking": "^0.5.3"

With sandbox username and API Keys, I am able to send SMS. But when I swap the credentials to LIVE DATA, it returns The supplied authentication is invalid

Reverting back to SANDBOX environment data works well.

Promise Error

Great Library 😃
Though am running into an error when trying to send a simple sms. Seems to be something when returning a promise.
Here is the error
.then(function(s) {
^

TypeError: Cannot read property 'then' of undefined
Code:
var AfricasTalking = require('africastalking')(options);
var sms = AfricasTalking.SMS;
var opts = {
to: 0704654445,
message: 'Server is Running'
};
console.log(opts);

sms.send(opts)
.then(function(s) {
console.log(s);
})
.catch(function(error) {
console.log(error);
});

Error: Attempt to change mapping for "form" extension from "application/x-www-form-urlencoded" to "application/x-www-form-urlencoded". Pass `force=true`

I have issues when building app in production using africas talking api

e.js:56
        throw new Error(
              ^
Error: Attempt to change mapping for "form" extension from "application/x-www-form-urlencoded" to "application/x-www-form-urlencoded". Pass `force=true` to allow this, otherwise remove "form" from the list of extensions for "application/x-www-form-urlencoded".
    at Mime.define (/Users/mussa/Documents/Source/Vircap/vircap-backend/node_modules/mime/Mime.js:56:15)
    at Object.<anonymous> (/Users/mussa/Documents/Source/Vircap/vircap-backend/node_modules/unirest/index.js:26:6)

TypeScript Support

Will there be possible support for TypeScript in the future ? Also are PR's welcome from non-employees ?

Callback URL

Need a demo of a callback url in action, Im not sure I understand how the Callback URL works in node. The docs only have one demo and its in PHP only.

AfricasTalking.fetchAccount() return 401 error

The AfricasTalking.fetchAccount() call seems to work on the sandbox, but returns a 401 error on production apps. I think it's due to the header being apiKey instead of Apikey (lib/index.js line 77)

Security Venerability

We have been using the SDK for quite a while now, but of recent some real security issues has been popping up due to some outdated dependencies within the grpc dependency SDK

Below are list of vulnerable dependencies in grpc:

  1. mime
  2. hoek
  3. tunnel-agent
  4. minimist
  5. cryptiles

Screen Shot 2020-05-31 at 5 20 02 AM

Please I urge you guys to investigate the above-listed dependencies which require urgent update due to the severity of the vulnerability

Airtime/Application: base url not pointing to live API for non-sandbox usernames

Background

  • A previous commit introduced a bug into the SDK.
  • The commit, among other things, introduced a custom Axios module for making API requests, defined as follows:
// africastalking-node.js/lib/customAxios/index.js (line 5)
function initializeAxios (config, production = false) {
  // ...
}
  • By itself, this is okay. However, in the lib/airtime.js and lib/application.js files, the implementation is the cause of the bug:
// africastalking-node.js/lib/airtime.js (line 27)
const customAxios = initializeAxios(this.config, false);
  • This sets the baseUrl to the sandbox version at all times.

Rectification

  • Need to refactor the custom Axios module into something like this:
function initializeAxios (config) {
  const isSandbox = config.username === 'sandbox';
}
  • And in individual files:
const customAxios = initializeAxios(this.config);

Critical security warning in package

When installing the package just this morning, there was one critical security warning and several other deprecation warnings. The security one might be important to fix.

warning africastalking > unirest > request > [email protected]: This module moved to @hapi/hawk. Please make sure to switch over as this distribution is no longer supported and may contain bugs and critical security issues.
warning africastalking > unirest > request > [email protected]: Use uuid module instead
warning africastalking > unirest > request > hawk > [email protected]: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).
warning africastalking > unirest > request > hawk > [email protected]: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).
warning africastalking > unirest > request > hawk > boom > [email protected]: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).
warning africastalking > unirest > request > hawk > [email protected]: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).
warning africastalking > unirest > request > hawk > cryptiles > [email protected]: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).
warning africastalking > unirest > request > hawk > [email protected]: This module moved to @hapi/sntp. Please make sure to switch over as this distribution is no longer supported and may contain bugs and critical security issues.
warning africastalking > unirest > request > hawk > sntp > [email protected]: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).

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.