GithubHelp home page GithubHelp logo

gonebusy / gonebusy-nodejs-client Goto Github PK

View Code? Open in Web Editor NEW
1.0 4.0 3.0 202 KB

A NodeJS client for access to the Gonebusy API

License: Other

JavaScript 100.00%
gonebusy nodejs-client nodejs sdk

gonebusy-nodejs-client's Introduction

Build Status npm version

Getting Started

Install

npm install --only=production --save gonebusy-nodejs-client

Sandbox

We have a Sandbox environment to play with!

Just use sandbox.gonebusy.com instead of where you see beta.gonebusy.com referenced, including where to create an account to retrieve your API Key.

The Sandbox environment is completely separate from the Live site - that includes meaning your Sandbox API Key will not work in the Live environment.

Quick Start

Have you followed Install above?

The following shows how to import the library and use it with Bluebird Promises:

Then try the following:

  1. Import the module:

    var gonebusy = require('gonebusy-nodejs-client');
  2. Configure the environment for Sandbox testing

    gonebusy.Configuration.currentEnvironment = 'sandbox'
  3. Configure your API Key:

    var authorization = 'Token ac98ed08b5b0a9e7c43a233aeba841ce'; // Default Sandbox token
  4. Get a list of Services for the current user:

    gonebusy.ServicesController.getServices(authorization).then((result)=>{
        console.log(result);
    }).catch((e)=>{
        console.log(e);
    })

    Output of console.log():

    GetServicesResponse {
    services:
     [ EntitiesServiceResponse {
         id: '3f58d6bb-59ba-4e7f-aeaa-2544c384d9d7',
         ownerId: '281ce067-50dc-4746-ac78-ded592655699',
         name: 'name',
         shortName: 'short_name',
         duration: 15,
         maxDuration: 15,
         description: A Service for Samples,
         priceModelId: '5d9cea4f-9e6a-46bd-9c7f-6195a88753eb',
         isActive: true,
         categories: [],
         resources: [],
         schedules: [] },
     ...
     ]
    }
    

Using Request Body Helpers

For any controller operations that expect a request body, or a set of params, there exist CreateXXXBody/UpdateXXXByIdBody/etc. helper objects corresponding to the operation. The helper objects allow your request code to be constructed with params that conform to the GoneBusy API while still supporting Node/ES6-style property access.

The following is an example of how to use the CreateServiceBody helper object when creating a new Service:

  1. Create an instance of CreateServiceBody to wrap your desired attributes into an object:

    var new_service = new gonebusy.CreateServiceBody({
      name: 'My Sample Service',
      duration: 30,
      max_duration: 30,
      description: 'Sample Service for Testing',
      short_name: 'MyService'
    });
  2. Note that the property passed to the constructor uses snake_case but the underlying BaseModel object allows access via ES6 camelCase or even a traditional getter:

    new_service.shortName;
    new_service.getShortName();

    Both output:

    'MyService'

    Setters work as well:

    new_service.setShortName('My Sample x2');
    new_service.getShortName();

    Outputs:

    'My Sample x2'
  3. Let's send off the request to create our new Service:

    gonebusy.ServicesController.createService(
        'Token ac98ed08b5b0a9e7c43a233aeba841ce',
        new_service
        ).then((result)=>{
            console.log(result);
        }).catch((e)=>{
            console.log(e);
        })

    Output of console.log():

      CreateServiceResponse {
        service:
          EntitiesServiceResponse {
              id: 'eaf76f54-f994-11e7-9c01-4fba28763be3',
              ownerId: '00000000-0000-0000-0000-000000000080',
              name: 'My Sample Service',
              shortName: 'MyService x2',
              duration: 30,
              maxDuration: 30,
              description: 'Sample Service for Testing',
              priceModelId: 'eafb2bbc-f994-11e7-9c03-83290988f60b',
              isActive: true,
              categories: [],
              resources: [ '00000000-0000-0000-0000-000000000034' ],
              schedules: [ 'eb0246c2-f994-11e7-9c04-639c2510affb' ] } }

Using Response Helpers

Just as with Request Body helpers, there are Response helper objects corresponding to each CreateXXXBody/UpdateXXXByIdBody/etc. operation.

gonebusy-nodejs-client's People

Contributors

alexagranov avatar blaze34 avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar  avatar

gonebusy-nodejs-client's Issues

Booking API would respond with 400 status if used with curl

This is related to #12

However this one corresponds to pure API call with curl without using nodejs-client

Here are the steps to reproduce

  1. Using Swagger API UI to test

Go to
http://sandbox.gonebusy.com/docs/api_sandbox#!/bookings/create_booking

Specify auth token

Token xxx

Specify body

{
  service_id: 7891245607,  //should use your service id
  date: '2016-01-14',
  time: '11:30',
  duration: 30
}
  1. Using curl.
    Corresponding curl request as generated by swagger
curl -X POST --header 'Content-Type: application/json' --header 'Accept: text/html' --header 'Authorization: Token xxx' -d '{ \ 
service_id: xxx, \ 
date: %272017-01-14%27, \ 
time: %2711:30%27, \ 
duration: 30 \ 
}' 'http://sandbox.gonebusy.com/api/v1/bookings/new'

It responds with 400 status. Response has headers only and no body at all.

I created this issue as it references to pure API call without using client.

BookingsController.createBooking possibly wouldn't send request params passed to it.

Hi.
The code example below is expected to create new booking according to docs.
Providing valuable part only and omiting imports and promosification.

const authorization = "Token xxx";
const createBookingBody = new CreateBookingBody({
  service_id: 7891245607,    //real service ID
  date: '2017-01-14',
  time: '11:30',
  duration: 30                        //can be removed without affecting responce
});

BookingsController
  .createBookingAsync({ authorization, createBookingBody })
  .then(response => { console.log('creating booking: ', response); });

Request responds with:

422 {"message":"422 Unprocessable Entity - Validation failed: Size cannot be zero"}

If I look at request details request body is not sent to API that's why I blame client in this scenario.
Sending params without BodyHelper won't change anything.

Create booking response time doesn't correspond to one passed in params

Here is the basic client code to reproduce


// omiting imports and bluebird promisification

// params to create new booking with
const params = {
      service_id,
      date: '2017-01-29',
      time: '13:15'
};

Next step

// using body helper to format passed params
const createBookingBody = new CreateBookingBody(params);

// making call to API
// authorization holds token
BookingsController.createBookingAsync({ authorization, createBookingBody });

Response is successful, however it holds unexpected data under "time_window" key so I need to understand how to treat it.

{  
   "booking":{  
      "workflow_state":"new",
      "user_message":null,
      "time_window":{  
         "start_date":"2017-01-29",
         "end_date":null,
         "id":2950361046,
         "start_time":"7am",
         "end_time":"8am",
         "total_minutes":30,
         "recurs_by":"once",
         "frequency":"single",
         "occurrence":"every",
         "date_recurs_by":null,
         "days":[  
            "sunday"
         ],
         "negation":true
      },
      "id":3824405197,
      "owner_id":1952670850
   }
}
  1. Passed booking time was '13-15' and response has next structure responsible for booking time
         "start_time":"7am",
         "end_time":"8am",
         "total_minutes":30

Here I have 2 question.

  • Why is this time different from sent one (I would expect both to use UTC)
  • How do I determine booked time from the response? Is it 7-00 to 7-30 or 7-30 to 8-00 or 7-15 to 7-45?
    In both cases response format seems not handful to work with.

Another issue here is debugging.
First I tried to understand whether params that are passed are not affected by body helper and are sent to API as is.

Below is Chrome Network request dump.

POST /api/v1/bookings/new HTTP/1.1
Host: sandbox.gonebusy.com
Connection: keep-alive
Content-Length: 62
accept: application/json
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36
authorization: Token xxx
content-type: application/json; charset=utf-8
Referer: http://localhost:3000/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,uk;q=0.6,ru;q=0.4

No request body is passed according to browser inspector.

Below is request saved as cUrl

curl 'http://sandbox.gonebusy.com/api/v1/bookings/new' 
-X POST 
-H 'authorization: Token xxx' 
-H 'Origin: http://localhost:3000' 
-H 'Accept-Encoding: gzip, deflate' 
-H 'Accept-Language: en-US,en;q=0.8,uk;q=0.6,ru;q=0.4' 
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36' 
-H 'content-type: application/json; charset=utf-8' 
-H 'accept: application/json' 
-H 'Referer: http://localhost:3000/' 
-H 'Connection: keep-alive' 
-H 'Content-Length: 62' --compressed

Again, no body(params) passed.

At first glance it's not clear if server gets params, but if you change booking day, response contains exactly the same day. So params are probably passed.

I just want a tip on a reason why I can not see request body in browser and thus can not debug the issue to at least ensure that I pass right params to API.

PricingModel create returns empty result

PricingModelsController.createPricingModel() call returns next pure json response

{
  "pricing_model": // @notice_me - singular!
  {
    "name":"Dog",
    "notes":null,
    "id":18,
    ...
    "price":99.0,
    "currency":"USD"
  }
}

Response passed to promise after being wrapped with EntitiesPricingModelResponse has empty keys

EntitiesPricingModelResponse: {
  currency:null,
  id:null 
  name:null
  notes:null
  ownerId:null
  price:null
  pricingModelType:null
}

It seems like client-library bug and presumably the reason is:

Parsed server response is passed to 'new CreatePricingModelResponse(parsed) '

parsed = new CreatePricingModelResponse(parsed);

CreatePricingModelResponse constructor expects data to be under plural key 'pricing_models' according to

this.pricingModels = new EntitiesPricingModelResponse(obj.pricing_models);

but response has singular 'pricing_model' key instead.

client and pure API params are not consistent

According to API docs http://sandbox.gonebusy.com/docs/api_sandbox#!/services/get_service_available_slots_by_id
pure API method specified above expects params to be passed as object with next keys

{
  date: '2017-01-01', // we omit this key in our particular case
  start_date: '2017-01-01',
  end_date: '2017-01-02'
}

It generates request to
http://sandbox.gonebusy.com/api/v1/services/197264885/available_slots?start_date=2014-01-01&end_date=2014-01-03

and it works fine (we get 200 response)

Code trying to reproduce the same request using nodejs-client

import gonebusy from 'gonebusy-nodejs-client/lib';
import { Promise } from 'bluebird';

// promisifying requests using bluebird according to docs
const ServicesController = Promise.promisifyAll(gonebusy.ServicesController);

const config = {
  baseUri: 'http://sandbox.gonebusy.com/api/v1'
};

//running request to API that must return promise
ServicesController.getServiceAvailableSlotsByIdAsync({
      authorization: sample_token,
      id: 197264885, //one used with curl API request
      start_date: '2014-01-01',
      end_date: '2014-01-03'
    })

Here the problems start

  1. In browser network tab we see next request details
Request URL:http://sandbox.gonebusy.com/api/v1/services/7891245607/available_slots?

Request Method:GET

Status Code:400 Bad Request

Response is
{"message":"Bad Request - Missing date params"}

Client didnt send start and end dates in params as can be seen from Request URL: http://sandbox.gonebusy.com/api/v1/services/7891245607/available_slots?
and server validation failed respectively.

Sources tell that client expects hash keys to be in camelCase according to
https://github.com/gonebusy/gonebusy-nodejs-client/blob/master/lib/Controllers/ServicesController.js#L419

So we must pass it like that

ServicesController.getServiceAvailableSlotsByIdAsync({
      authorization: sample_token,
      id: 197264885, //one used with curl API request
      startDate: '2014-01-01', // camelCase
      endDate: '2014-01-03' // camelCase
    })

and it works as expected then.

So client accepts keys in camelCase and transforms to the format that pure API expects to receive.
This should be documented and might also apply to other controllers.

  1. Another annoying thing is that though validation error can be seen in responce itself, bluebird logs its own console error, much less verbose and that is the one that you see first, before you may try looking at request itself.
    Bluebird, that i suspect to be this error logger, logs it like this

Unhandled rejection (<{"errorMessage":"Bad Request","errorCo...>, no stack trace)

This means bluebird wrapping doesn't not handle some errors correctly and needs further investigation.

  1. If we use underscore in params object keys, nodejs client just doesnt send those params to API and we get missing params validation error. However if we pass only one of 2 required params (startDate or endDate) correctly, API behaviour is inconsistent and it responds with html instead of json.

This can be reproduced by using next curt

curl -X GET --header 'Accept: text/html' --header 'Authorization: Token ac98ed08b5b0a9e7c43a233aeba841ce' 'http://sandbox.gonebusy.com/api/v1/services/197264885/available_slots?end_date=2014-01-03'

I am not providing html response here, but shortly it's gonebusy website html.

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.