Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Feature-rich and pluggable offline-first API wrapper for the browser, node.js and react-native. Easily wire-up your API and make your app work offline in minutes !
Easily write offline-first react-native and web applications with your own REST API. This module supports every major features for network requests : middlewares, fine-grained control over caching logic, custom caching driver... and works in isomorphic (universal) environments.
npm install --save apipeline # with npm
yarn add apipeline # with yarn
click to enlarge
Since this plugin is a fully-fledged wrapper and not just a network helper, you need to set up your API configuration.
Here's an example :
const API_OPTIONS = {
fetchMethod: yourFetchMethod, // documented below
domains: { default: 'http://myapi.tld', staging: 'http://staging.myapi.tld' },
prefixes: { default: '/api/v1', apiV2: '/api/v2' },
debugAPI: true,
printNetworkRequests: true
};
Here, we have set up the wrapper so it can use 2 different domains, a production API (the default one) and a staging API.
We also have 2 different prefixes, so, if you're versioning your APIs by appending /v2
in your URLs for example, you'll be able to easily request each versions. Please note that this is totally optional.
Check out all the API options here
Since you can use apipeline in any javascript environement (react—native / browsers / node.js), you need to tell the plugin which function it should use to fetch data.
You can use anything you want as long as it follows the fetch specification.
react-native
: it's easy, just use fetch
which is defined globallyfetch
on the most recent browser or use a polyfill like unfetch or whatwg-fetchfetch
polyfill like node-fetchFrom now on, we'll call all your API's endpoint services. Now that you have set up your options, you need to declare your services. Easy peasy :
const API_SERVICES = {
articles: {
path: 'articles',
},
documents: {
domain: 'staging',
prefix: 'apiV2',
path: 'documents/:documentId',
disableCache: true
},
login: {
path: 'login',
method: 'POST',
expiration: 5 * 60 * 1000
}
};
Here, we declared 3 services :
articles
that will fetch data from http://myapi.tld/api/v1/articles
documents
that will fetch data from http://staging.myapi.tld/api/v2/documents/:documentId
and won't cache anythinglogin
that will make a POST
request on http://myapi.tld/api/v1/login
with a 5 minutes cachingThese are just examples, there are much more options for your services, check them out here.
This step is optional, but if you want the wrapper to handle all of the offline goodness for you, you have to tell the plugin which cache driver it should use.
In order to do that, just pass your driver as the 3rd argument of APIPeline when instantiating your api, or use api.setCacheDriver
.
react-native
: you can import AsyncStorage
or use the baked-in sqlite driverlocalforage
plugin is usually a good choiceExamples :
In react-native
:
import { AsyncStorage } from 'react-native';
import APIpeline from 'apipeline';
const api = new APIPeline(API_OPTIONS, API_SERVICES, AsyncStorage);
In an isomorphic setting (next.js for instance):
import APIpeline from 'apipeline';
import clientFetch from 'unfetch';
import serverFetch from 'isomorphic-unfetch';
import localforage from 'localforage';
const isServer = typeof window === 'undefined';
// ... API and services configuration
const api = isServer ?
new APIpeline(API_OPTIONS, API_SERVICES) :
new APIpeline(API_OPTIONS, API_SERVICES, localforage);
export default api;
Now that we have our API options and services configured, let's call our API !
import React, { Component } from 'react';
import APIpeline from 'apipeline';
// ... API and services configurations and instantiation
export default class demo extends Component {
componentDidMount () {
this.fetchSampleData();
}
async fetchSampleData () {
try {
const request = await api.get(
'documents',
{
pathParameters: { documentId: 'xSfdk21' }
}
);
console.log('Our fetched document data', request);
} catch (err) {
// Handle any error
}
}
render () {
// ...
}
}
In this short example, we're firing a GET
request on the path http://staging.myapi.tld/api/v2/documents/xSfdk21
. If you don't understand how this path is constructed, see path and query parameters.
A couple of notes :
get
, post
, fetch
, fetchHeaders
... methods are promises, which means you can either use async/await
or get().then().catch()
if you prefer.APIPeline
without API_OPTIONS
and/or API_SERVICES
and set them later with api.setOptions
and api.setServices
methods if the need arises.Name | Description | Parameters | Return value |
---|---|---|---|
fetch | Fires a network request to one of your service with additional options, see fetch options | service: string, options?: IFetchOptions | Promise<any> |
get , post , head ... | Each HTTP method has a dedicated method that acts just like fetch | service: string, options?: IFetchOptions | Promise<any> |
fetchHeaders | Just like fetch but only returns the HTTP headers of the reponse | service: string, options?: IFetchOptions | Promise<any> |
clearCache | Clears all the cache, or just the one of a specific service | service?: string | Promise<void> |
setOptions | Sets or update the API options of the wrapper | options: IAPIOptions | void |
setServices | Sets or update your services definitions | services: IAPIServices | void |
setCacheDriver | Sets or update your custom cache driver, see using your own driver for caching | driver: IAPIDriver | void |
These are the global options for the wrapper. Some of them can be overriden at the service definition level, or with the option
parameter of the fetch
method. Only fetchMethod
, domains
and prefixes
are required.
Key | Type | Description | Example |
---|---|---|---|
fetchMethod | function read more here | Required, a spec compliant function | an imported fetch polyfill |
domains | { default: string, [key: string]: string } | Required, full URL to your domains | domains: {default: 'http://myapi.tld', staging: 'http://staging.myapi.tld' }, |
prefixes | { default: string, [key: string]: string } | Required, prefixes your API uses, default is required, leave it blank if you don't have any | { default: '/api/v1', apiV2: '/api/v2' } |
encodeParameters | boolean | Optional, automatically encodes UTF8 chars in queryParameters & pathParameters | true (defaults to false ) |
middlewares | APIMiddleware[] | Optionnal middlewares, see middlewares | [authFunc, trackFunc] |
responseMiddleware | ResponseMiddleware | Optionnal middleware to alter your API responses, see middlewares | alterFunction |
debugAPI | boolean | Optional, enables debugging mode, printing what's the wrapper doing | true (defaults to false ) |
printNetworkRequests | boolean | Optional, prints all your network requests | true (defaults to false ) |
disableCache | boolean | Optional, completely disables caching (overriden by service definitions & fetch 's option parameter) | true (defaults to false ) |
cacheExpiration | number | Optional default expiration of cached data in ms (overriden by service definitions & fetch 's option parameter) | 5 * 60 * 1000 |
cachePrefix | string | Optional, prefix of the keys stored on your cache, defaults to offlineApiCache | 'myOwnCache' (defaults to APIPelineCache ) |
ignoreHeadersWhenCaching | boolean | Optional, your requests will be cached independently from the headers you sent. | true (defaults to false ) |
capServices | boolean | Optional, enable capping for every service, defaults to false , see limiting the size of your cache | true (defaults to false ) |
capLimit | number | Optional quantity of cached items for each service, see limiting the size of your cache | 100 (defaults to 50 ) |
These are the options for each of your services, the only required key is path
. Default values are supplied for the others.
Key | Type | Description | Example |
---|---|---|---|
path | string | Required path to your endpoint, see path and query parameters | article/:articleId |
expiration | number | Optional time in ms before this service's cached data becomes stale, defaults to 5 minutes | 5 * 60 * 1000 |
method | GET | Optional HTTP method of your request, defaults to GET | OPTIONS... |
domain | string | Optional specific domain to use for this service, provide the key you set in your domains API option | staging |
prefix | string | Optional specific prefix to use for this service, provide the key you set in your prefixes API option | apiV2 |
middlewares | APIMiddleware[] | Optional array of middlewares that override the ones set globally in your middlewares API option, see middlewares | [serviceSpecificMiddleware] |
responseMiddleware | ResponseMiddleware | Optionnal middleware to alter your API responses that override the one set globally in your middlewares API option, see middlewares | alterFunction |
disableCache | boolean | Optional, disables the cache for this service (override your API's global options) | true (defaults to false ) |
capService | boolean | Optional, enable or disable capping for this specific service, see limiting the size of your cache | true (defaults to false ) |
capLimit | number | Optional quantity of cached items for this specific service, defaults to 50 , see limiting the size of your cache | 42 (defaults to 50 ) |
ignoreHeadersWhenCaching | boolean | Optional, your requests will be cached independently from the headers you sent. | true (defaults to false ) |
rawData | boolean | Disables JSON parsing from your network requests, useful if you want to fetch XML or anything else from your api | true (defaults to false ) |
The options
parameter of the fetch
and fetchHeaders
method overrides the configuration you set globally in your API options, and the one you set for your services definitions. For instance, this is a good way of making very specific calls without having to declare another service just to tweak a single option.
Important notes :
Key | Type | Description | Example |
---|---|---|---|
pathParameters | { [key: string]: string } | Parameters to replace in your path, see path and query parameters | { documentId: 'xSfdk21' } |
queryParameters | { [key: string]: string } | Query parameters that will be appended to your service's path, , see path and query parameters | { refresh: true, orderBy: 'date' } |
headers | { [key: string]: string } | HTTP headers you need to pass in your request | { 'User-Agent': 'My very own agent' } |
middlewares | APIMiddleware[] | Optional array of middlewares that override the ones set globally in your middlewares API option and in your service's definition, , see middlewares | [superSpecificMiddleware] |
responseMiddleware | ResponseMiddleware | Optionnal middleware to alter your API responses that override the one set globally in your middlewares API option and in your service's definition, see middlewares | alterFunction |
fetchOptions | any | Optional, any value passed here will be merged into the options of react-native's fetch method so you'll be able to configure anything not provided by the wrapper itself | { body: 'user_email=hey@itsme.org' } (POST request example) |
The URL to your endpoints are being constructed with your domain name, your optional prefix, and your optional pathParameters
and queryParameters
.
The pathParameters
will replace the parameters in your service's path. For instance, a request fired with this path : /documents/:documentId
, and these pathParameters
: { documentId: 'xSfdk21' }
will become /documents/xSfdk21
.
The queryParameters
are regular query string parameters. For instance, a request fired with this path : /weather
and these queryParameters
: { days: 'mon,tue,sun', location: 'Paris,France' }
will become /weather?days=mon,tue,sun&location=Paris,France
.
💡 Pro-tip : Both query and path parameters can be undefined, in this case they simply won't be processed when generating your route. You don't have to create an intermediate variable holding your options to handle whether or not your variables are defined.
Learn more about enabling capping in the documentation
Check out middlewares documentation and examples
💡 You can now use SQLite instead of AsyncStorage without additional code !
Check out drivers documentation and how to enable the SQLite driver
Every API interfaces can be seen here so you don't need to poke around the parameters in your console to be aware of what's available to you :)
💡 These are Typescript defintions, so they should be displayed in your editor/IDE if it supports it.
FAQs
Feature-rich and pluggable offline-first API wrapper for the browser, node.js and react-native. Easily wire-up your API and make your app work offline in minutes !
The npm package apipeline receives a total of 6 weekly downloads. As such, apipeline popularity was classified as not popular.
We found that apipeline demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.