npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@keeex/sdk-helper

v2.3.2

Published

Shared code for SDK libraries

Downloads

9

Readme

@keeex/sdk-helper

Bugs Code Smells Maintainability Rating Security Rating Vulnerabilities Technical Debt Coverage

General description

Shared code to build SDK libraries.

Features:

  • Simplified raw HTTP calls
  • Authentication
  • Handling of input values transformations into either JSON or FormData
  • Handling of file inputs
  • Handling of generic pagination values
  • Handling of URI arguments and query arguments
  • Handling of file replies
  • Grabing useful data from complex reply
  • Progress callback
  • Concurrent request limitation
  • Separate request queues
  • Input/output filtering

Usage

Setting up a SDK using this library is done by providing settings describing how the API is accessed, as well as individual descriptions for all API calls. These individual descriptions are used to create functions that can be used to call the API directly.

Short example:

import SdkBase from "@keeex/sdk-helper/lib/sdk.js";
import {
  toAPI as dateToAPI,
  fromAPI as dateFromAPI,
} from "@keeex/sdk-helper/lib/filters/date";

const routeFilter = {
  toAPI: {lastKnownDate: dateToAPI},
  fromAPI: {newDate: dateFromAPI},
};

export default class Sdk extends SdkBase {
  public retrieveDate;

  constructor(config) {
    super(
      {baseURL: config.uri},
      {},
      {type: "autocookie"},
    );
    this.retrieveDate = this.directApiCall<{lastKnownDate: Date}, {newDate: Date}}({
      method: "post",
      route: "/api/v1/date/retrieve",
      authenticated: false,
      filters: routeFilter,
      replyDataPath: "",
    });
  }
}

const sdk = new Sdk({uri: "https://invalid.invalid"});
const result = await sdk.retrieveDate({lastKnownDate: new Date()});
console.log("Reply:", result.newDate);

The above example create an SDK that exposes only one function called retrieveDate. This function takes as input an object with all the inputs (in this case there is only one property: lastKnownDate). It then returns the full reply from the server with one property: newDate. The filter automatically convert a Date object into its ISO8601 string representation before the call, and converts the reply back from an ISO8601 string representation to a Date object.

An alternative to directApiCall() named createApiCall() exists; it will return an object exposing the raw reply body as well as the HTTP status code alongside the filtered data.

Pagination

Instead of directApiCall() it is possible to call paginatedApiCall(). In that case the input accepts extra PaginationInput fields, and the reply will follow the PaginatedResponse interface.

Authentication

This library handles two types of authentication: HTTP-header based and cookie based. The third argument of the Sdk class constructor defines the authorization scheme to use. If not provided, no authorization is handled. If provided, routes that are defined with the authenticated property to true requires the user to previously be authenticated.

To indicate to an Sdk instance that authentication completed, call the setAuthToken() method with a suitable value. undefined or any other false-y value indicates no authentication.

Cookie-based authentication

This mode is basically a passthrough. Cookies are handled by the browser. To use this method of authentication, pass a config object with the single property type set to autocookie.

HTTP-header based authentication

This mode allows the caller to provide a value passed as an HTTP header. In this case setAuthToken()) expects a non-empty string argument to indicate authentication.

To use this method, pass a config object with the following properties:

  • type: must be header
  • headerName: name of the header to use. Defaults to Authorization
  • valueTemplate: a template for the value of the header; the word %token% will be replaced by the provided token. Defaults to Bearer %token%

Defining API routes

To create a function that implements an API route, the directApiCall() method must be called. It takes a single parameter which define the behavior of the route. It is an object with the following properties (all properties are optional except for route):

  • route: path to the API route relative to the base URL
  • queue: request queue to use. Defaults to a default queue.
  • method: HTTP method. Defaults to GET.
  • authenticated: true to restrict this call when non authenticated
  • queryParams: list of "input" properties to pass as query arguments
  • bodyParams: list of "input" properties to pass in the body
  • fileParams: list of "input" properties that are expected to be files
  • axiosOptions: custom axios options
  • paginated: true to handle special pagination "input" values (deprecated, see Pagination)
  • replyDataPath: JSON path in the reply where the useful output is located
  • filters: filters to apply to input arguments and output values

The function returned by this call accepts a single parameter which is an "input" object. This "input" object's properties will then be parsed accordingly to the API specification.

URI arguments

It is possible to use some part of the "input" as URI arguments. To do so, sections of the route must start with a : character.

For example, a route defined by /api/v1/item/:id will grab the id property from the "input" object and put it in the URI before the request is performed.

Query arguments

All properties names passed into queryParams will be appended to the route using ?key=value accordingly.

Body arguments

All properties names passed into bodyParams will be put in either a JSON object sent as the body for the request, or into a multipart/form-data, depending on the presence of files or not in that request.

File arguments

If fileParams is present, the body will be a multipart/form-data body and treat the properties names in fileParams as files to be appended to it.

The file who's properties names are in fileParams are required unless the properties names are prefixed with ?.

Getting JSON path from reply

A minor feature is the ability to directly return a specific value from the reply. A "JSON" path can be specified (properties names separated with a .). Once a request complete, this path will be used and the value located in the given property will be returned. This path is specified in the replyDataPath property of an API route definition.

This library have three behavior regarding this:

  • undefined: do not return anything
  • empty: return everything
  • a path: return only the value pointed by the path

File replies

If a route returns a binary blob (a file) a special replyDataPath value should be provided to handle it. The value can be either <stream> or <arraybuffer>. In both case the reply will be returned as-is from axios.

Progress callback

Functions returned by directApiCall() accepts a second parameter: a function that will be called regularly during the upload/download process. This functions takes two arguments: the first is the progress percentage, the second is a boolean set to true if we're in the upload phase.

Queue control

The default setting of this library is to not allow more than two concurrent requests on a single queue. However, to allow for long operations to coexist with short requests, it is possible to specify which "queue" is used by an API call. By putting a queue name on the queue property of an API call description, it can use a separate queue.

There is no restriction to the number of queues; keep in mind however that running too many concurrent requests can results in dropped replies in some circumstances.

If no queue name is provided a default queue is used.

Data filtering

This library have a built-in option to filter/transform data before sending them to the API, and when receiving a reply.

At its core, a filter is a function that takes a value of one type and returns (using a promise) the converted value. The filters property in API route definitions is an object that have two properties:

  • toAPI
  • fromAPI

Each of these properties is an object whose keys represent the keys to filter and values are filter functions.

A special case exists, for API calls that returns a single value and not an object. In that case, a special property named <root> can be set on the filters list to be applied to the reply value itself and not on its properties. If this property is present, no other properties will be handled.

Built-in filters

A list of built-in filters is provided in the lib/filters directory:

  • binary: conversion from/to buffers and hex/base64
  • date: conversion from/to Date objects and ISO8601 string representations
  • fixed: conversion from/to "fixed" decimal numbers, with fixed number of decimals
  • nullstring: unify empty string and null values to/from null

Utility filters

To be able to handle complex objects, special utility filters are available. With them it is possible to filter data behind arrays and properties.

  • array: apply a filter to all values of an array
  • props: apply various filters to the properties of an object