Examples

In this section, we will create a provider from scratch, and develop each step to illustrate comprehensively how to create a new provider

We're assuming here that the provider is name custom-provider, and that there is a back end capable of returning the content to populate the three screens of the app : home / all videos / news.

The code snippets above only use node 6.9.1 valid syntax, so no babel.js configuration is required.

Scaffolding the project

The first step is to prepare the project. To do this, you can either start from the provided starter kit, or follow these steps :

  1. create a folder called zapp-pipes-provider-custom-provider
  2. in this folder, create a new npm package by running the following command npm init --scope=applicaster. Make sure the package name is @applicaster/zapp-pipes-provider-custom-provider and the entry point is index.js
  3. Create a src folder, and an index.js file at the root of your project, where the package.json file is located.
  4. In the index.js file, add the following :

const provider = require('./src');
module.exports = provider;
  1. in the src folder, create an index.js file. This is where the provider code will be. add the following code :

const provider = {
  name: 'custom-provider'
};

/* we will add the rest of the provider code here */

Identification of the feeds

Now that your project folder is ready, the next step consist in identifying the feeds the provider needs to return, and how to retrieve them. When configuring your feed in Zapp's feed manager, you will be able to define a type and a url for each feed. this means that at each request, your provider will be invoked with a two parameters : type and url. You can use these parameters to retrieve the feed data, and define who to parse them.

Let's define 2 feeds, which will share the same type : 'xml-feed'

Feeds don't have to be xml. they can also be json. You can define a different type to identify a different parsing process depending on the type of the feed. Let's add a feed with the type 'json-feed' :

You can now start to write the provider manifest :

// in src/index.js

provider.manifest = {
  handlers: ['xml-feed', 'json-feed'], // handlers are the types the providers knows how to handle. If you add a type, don't forget to add it to the manifest !
  help: {
    'xml-feed': {
      description: 'retrieves an parses an xml feed from http://myfeedserver.com',
      params: {
        url: 'url of the feed you want to retrieve',
      }
    }, 
    'json-feed': {
      description: 'retrieves and parses a json feed from http://myfeedserver.com',
      params: {
        url: 'url of the feed you want to retrieve',
      }
    }
  }
};

This manifest declares that the providers knows how to handle feed urls with ?type=xml-feed and ?type=json-feed, and explains what these types are and how to use them.

You can then start to write the handler function. As explained in the provider structure documentation, the handler function of the provider is a curried function, which gets injected with the nativeBridge, and the type and url parameters. You can use these parameters, and the nativeBridge features to process the url requested by the app :

provider.handler = nativeBridge => params => {
  const { type, url } = params; 

  if (type !== 'xml-feed' && type !== 'json-feed') {
    return nativeBridge.throwError(`Don't know how to process request of type ${ type}`);
  }

  // ...

};

Note that the above is not necessary. If a url with a type that is not listed in the provider's manifest is called, the bundle will automatically return an error. Feel free to declare different type of requests that needs to be handled differently, to support various cases.

Now, depending on the feedName, you need to fetch the required data, format it, and return it in the bridge. Let's imagine here you have a back end with a simple endpoint that takes the feedName as parameter. You can use the nativeBridge fetch request to do that :

// index.js
provider.handler = nativeBridge => params => {
  const { type, url } = params; 

  if (type !== 'xml-feed' && type !== 'json-feed') {
    return nativeBridge.throwError(`Don't know how to process request of type ${ type}`);
  }

  // you can define different javascript modules to process different types of feeds. 
  // we're assuming here we have a getFeedFetcherForType functions
  // which returns the module required to process a feed of the given type
  const feedFetcher = getFeedFetcherForType(type);

  // Asuming all feedFetcher use the url to retrieve the data,
  // parse it, and format it to the expected format

  return feedFetcher(url)
    .catch(error => nativeBridge.throwError('something wrong happened !'))
    .then(feed => nativeBridge.sendResponse(feed));

    // FeedFetcher should return a promise with the data to be sent back to the app
    // when this promise resolves, don't forget to call the nativeBridge response and error methods to close the loop
    // without these functions, the data will never reach back to the app

};

With the code above, your provider will return the corresponding feed to the app. But it is likely that your feed format is slightly different from the one expected by the app, which is documented here. So the last thing you need to do is to format the feed as expected by our specifications. Create a formatFeed.js file in the src folder, and export a function that will parse and format your feed :

// formatFeed.js

function formatFeed(type, inputFeed) {
  // transform feed appropriately

  return outputFeed;
}

module.exports = formatFeed;

Now you can import this at the top of the index.js file

//index.js file

const formatFeed = require('./formatFeed');

You can now use this function to finalize your provider handler :

// index.js
provider.handler = nativeBridge => params => {
  const { type, url } = params;

  if (type !== 'xml-feed' && type !== 'json-feed') {
    return nativeBridge.throwError(`Don't know how to process request of type ${ type}`);
  }

  const feedFetcher = getFeedFetcherForType(type);

  return feedFetcher(url)
    .catch(error => nativeBridge.throwError('something wrong happened !'))
    .then(feed => formatFeed(type, feed))
    .then(feed => nativeBridge.sendResponse(feed));

};

There is one last bit to add to finalize your provider : you need to add the information to run integration tests. Let's define a feedName of type test. We will add its url in the test property of the provider, and mock the request to the back end.


provider.test = {
  testCommand: 'custom-provider://fetchData?type=feed&feedName=test',
  requestMocks: [{
    host: 'http://myapi.com',
    method: 'get',
    path: '/feedName/test',
    expectedResponse: // put here the expected raw response from calling http://myapi.com/feedName/test
  }],
};

that's it ! now you can export your provider :

// index.js

module.exports = provider;

and publish your package by running npm publish

your provider is ready to be used !

results matching ""

    No results matching ""