Options
All
  • Public
  • Public/Protected
  • All
Menu

Namespace data

Provides methods for creating and configuring a data layer, providing applications the ability to invoke data operations for various endpoints.

// esm
import { data } from '@paychex/core';

// cjs
const { data } = require('@paychex/core');

// iife
const { data } = window['@paychex/core'];

// amd
require(['@paychex/core'], function({ data }) { ... });
define(['@paychex/core'], function({ data }) { ... });

Basic Concepts

A proxy is a runtime set of rules that will be applied (in order) to transform Requests prior to sending them to an Adapter. You can configure the proxy rules at any time.

An adapter converts a Request into a Promise resolved with a Response. It should never throw an Error; instead, if a failure occurs, it should set the appropriate properties on the Response. The following adapter repositories can be used:

adapter description
@paychex/adapter-xhr Uses XMLHttpRequest to fulfill a data operation. Works in web browsers.
@paychex/adapter-node Uses https to fulfill a data operation. Works in NodeJS.

A data pipeline is a sequence of steps whose job is to retrieve data. For that reason, even the simplest data pipeline requires these 3 steps:

  1. convert a DataDefinition object into a Request
  2. pass that Request to the appropriate Adapter, which will
  3. perform an operation (typically a network call) and return a Response

The data module contains a factory method that creates a DataLayer. The DataLayer can perform all 3 steps above.

However, data pipelines usually are more complex and require additional business logic to be applied correctly. Some additional logic you may want to apply to your pipelines includes:

  • caching responses
  • retrying on certain failures
  • reauthenticating if a 401 is returned

These features and more are available through wrapper functions in the utils module.

Combine functions from both modules to create a generic data pipeline that meets your most common needs. Consumers of your pipeline can bolt on additional wrapping functions to meet their unique requirements.

// datalayer.js

import rules from '~/config/proxy';

const proxy = data.createProxy();
const { fetch, createRequest } = data.createDataLayer(proxy);

proxy.use(...rules);

// we extend the functionality of `fetch` by wrapping
// it and returning a function with the same signature
// that proxies to the real fetch while adding custom
// error handling logic
function withCustomErrors(fetch) {
return async function useCustomErrors(request) {
return await fetch(request)
.catch(errors.rethrow({ app: 'my app' }));
};
}

let pipeline = fetch;
// add custom error handling
pipeline = data.utils.withCustomErrors(pipeline);
// add default request headers
pipeline = data.utils.withHeaders(pipeline, {
'x-app-name': 'my-app'
});

export {
proxy,
createRequest,
fetch: pipeline // return our extended pipeline
}
// consumer.js

import { fetch, createRequest } from './datalayer.mjs';

const datacall = {
base: 'endpoint',
path: '/:id/info'
};

// automatically retry failed requests using
// an exponential falloff between attempts;
// the version of fetch we bring in has already
// been wrapped to add custom error data and
// request headers; this shows how we can combine
// cross-cutting logic with custom one-off logic
const load = data.utils.withRetry(fetch, data.utils.falloff());

export async function loadData(id) {
const params = { id };
const request = createRequest(datacall, params);
const response = await load(request)
.catch(errors.rethrow(fatal(params)));
return response.data;
}

Index

Type aliases

HeadersMap: Record<string, string | string[]>

Map of strings representing either Request headers or Response meta headers. The header name is the key and the header data is the value. If you pass an array of strings as the value, the strings will be combined and separated by commas.

example
import { fetch, createRequest } from '~/path/to/datalayer';

async function loadData() {
const request = createRequest({
base: 'my-app',
path: '/path/to/data',
headers: {
'content-type': 'application/json',
'accept': [
'application/json',
'text/plain',
'*∕*'
]
}
});
const response = await fetch(request);
console.log(response.meta.headers);
return response.data;
}

Functions

  • Creates a new DataLayer instance that can retrieve data from various sources.

    throws

    A proxy must be passed to createDataLayer.

    example
    // datalayer.js

    import xhr from '@paychex/adapter-xhr';
    import proxy from '~/path/to/my/proxy';

    const { fetch, createRequest } = data.createDataLayer(proxy, xhr);

    // we can extend the base functionality of fetch before
    // returning it to consumers:

    const pipeline = data.utils.withHeaders(fetch, {
    'x-app-platform': 'android',
    'content-type': 'application/json'
    });

    export {
    createRequest,
    fetch: pipeline
    }

    Parameters

    • proxy: DataProxy

      The Proxy to use to construct requests.

    • adapter: Adapter

      The default adapter to use for requests.

    Returns DataLayer

    A DataLayer that can be used to retrieve data asynchronously.

  • Creates a new proxy instance.

    example
    import rules from '~/config/proxy'
    export const proxy = data.createProxy();
    proxy.use(rules);

    Returns DataProxy