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

forte-api

v2.6.3

Published

A wrapper for the Powerchord Forte REST API

Downloads

10

Readme

ForteAPI Travis npm package

Easily communicate with the Powerchord Forte REST API!

ForteAPI is a wrapper around the Powerchord Forte REST API that allows you to focus on the data you want, rather than urls and verbs used to get or update the data you want.

Install

$ npm i -S forte-api

Features

  • Simple API Simplifies REST API access so you can focus on data and not HTTP
  • Semi-Automatic token auth You simply provide secret keys, or a pre-existing token and ForteApi does the rest
  • Client Fingerprinting By default ForteApi will perform a browser fingerprint on the client via a non-blocking background process, i.e. WebWorker. This can be disabled via options if legal requirements dictate.

Documentation

Quick Start

An Isomorphic usage example:

server.js
import createApi from 'forte-api'

// a global to be injected in to your html markup
CLIENT_GLOBALS = {
    scope: {
        trunk: 'TRUNKID',
        branch: 'BRANCHID'
    }   
}

let creds = {
  privateKey: 'PRIVATEKEY',
  publicKey: 'PUBLICKEY'
}

// create a new api instance using secret keys
let api = createApi(creds, CLIENT_GLOBALS.scope)

// listen for authentication events to capture the token
api.on('auth', (err, token) => {
    if(err) {
        console.log('An api auth error occurred:', err)
        return
    }

    console.log('Api auth success:', token)
    creds.bearerToken = token
})

app.get('*', function(req, res, next) => {
  res.send(ReactDOM.renderToString(<App api={api} />))
})
client.js
import createApi from 'forte-api'

// presuming CLIENT_GLOBALS was injected in your markup by the server
let creds = { bearerToken: CLIENT_GLOBALS.BearerToken }

let api = createApi(creds, CLIENT_GLOBALS.scope)

ReactDOM.render(<App api={api} />, document.getElementById('app'));
app.js

let results = api.composite
    .query({...})
    .then(composed =>
        return api.location.get(id)
          .then(location => return {
            composed.data,
            location.data
          })
    )

API

Constructor

createApi(credentials, scope, [options])

Creates an instance of the Forte Api.

import createApi from 'forte-api'

let scope = {
  trunk: 'TRUNKID',
  branch: 'BRANCHID'
}

// defaults
let api = createApi(credentials, scope);

// override api options
let api = createApi(credentials, scope, options);
args
  • credentials: {Object} Used to manage Authentication for api requests.
    • bearerToken: {string} Used by default if not null. The token will be added as an Authorization header for all endpoint requests.
    • privateKey: {string}, publicKey: {string} server-side only If bearerToken is null, an attempt will be made to use the publicKey and privateKey fields to generate a bearerToken for you. You can use the on('auth', cb) handler to subscribe to the 'auth' event and capture the bearerToken for later use, e.g. injecting the token in a client-side global.
  • scope: {Object}
    • hostname: {string} Sets the hostname scope for all requests, this is typically the TLD for your XPerience.
    • trunk: {string} Sets the trunk scope for all requests. See Organization Scopes
    • branch: {string} Optional: sets the branch scope for all requests. Note, that an error will be thrown if branch is null when accessing endpoints that require it. See Organization Scopes
  • options: {Object}
    • url: {string} default: https://api.powerchord.io The base Api url.
    • fingerPrintingEnabled: {boolean} client-side only default: true If true, performs a browser fingerprint, once per session, via a non-blocking background process, i.e. WebWorker.

Organization Scopes

All api requests require at least a trunk scope and most also require a branch scope to be able to access your data.

The constructor requires a scope.trunk param, but for requests requiring branch scope you can also use api.withBranch(). This is particularly useful on the server side, where you may have non-branch api calls during bootstrapping, as well as branch scoped calls during individual page requests.

var creds = {...}
var scope = { trunk: 'TRUNKID' } // note the lack of a branch

var api = createApi(creds, scope, opts)

// use lifecycle middleware to resolve scope
app.use(lifecycle(api))

// do some non-branch calls via lifecycle middleware...
...

app.get('*', (req, res, next) => {
  // create a branch-scoped api instance for the app to use
  branchApi = api.withBranch(req.lifecycle.scope.branch)

  render(<App api={branchApi} />)
})

api.withBranch(ID)

A convenience method that creates a new api scoped to the specified ID. All configuration is replicated from the original api instance.

args:
  • ID: {string} The identifier of the branch that future request should be scoped to.
var scope = { trunk: 'TRUNKID' }
var api = createApi(creds, scope).withBranch('BRANCHID')

Or the equivalent:

var scope = { trunk: 'TRUNKID', branch: 'BRANCHID' }
var api = createApi(creds, scope)

api.getScope(): {object}

Returns the scope of the api.

result:
  • trunk: {string} The trunk ID of the scope.
  • branch: {string|null} The branch ID of the scope. Since only trunk is required, it is possible for the branch to be null if the api has not been given a branch scope.

Events

api.on('auth', callback(err, token))

When the api successfully creates a new Bearer Token session this method will be invoked with the new bearerToken value. If an error occured it will be returned via the err argument.

import createApi from 'forte-api'
let api = createApi(credentials, organization, options);

api.on('auth', (err, token) => {
    if(err) {
        console.log('An api auth error occurred:', err)
        return
    }
    console.log('Api auth success:', bearerToken)

    CLIENT_SIDE_GLOBALS.BearerToken = bearerToken
})

Endpoints

Endpoints are the main progamming point for api data access. They are the abstractions of the REST API endpoints. All of the endpoints return promises to allow chaining.

api.organizations.getOne('orgid').then(
  (response) => {
    console.log('success:', response.data)
  },
  (response) => {
    console.log('error:', response.statusText)
  }
)
Responses

All Endpoints return promises that have the following response signature for both success/error handlers:

  • data: {string|Object} The deserialized response body.
  • status: {number} HTTP status code of the response.
  • statusText: {string} HTTP status text of the response.
  • headers: {Object} HTTP headers of the response.

Organizations

api.organizations.getMany(filter): [{organization}, ...]

Returns an array of organization objects matching the filter option(s).

args:
  • filter: {Object} A json object that is used to filter results from the api.
// return all active items
api.organizations.getMany({status: 'active'}).then((response) => {
  console.log('organziations:', response.data)
})
api.organizations.getOne(id): {organization}

Returns one organization.

args:
  • id: {string} The id of the organization to get.
api.organizations.getOne('1').then((response) => {
  console.log('organization:', response.data)
})

Locations

api.locations.getMany(filter): [{location}, ...]

Returns an array of location objects matching the filter option(s).

args:
  • filter: {Object} A json object that is used to filter results from the api.
// return all active items
api.locations.getMany({status: 'active'}).then((response) => {
  console.log('locations:', response.data)
})
api.locations.getOne(id): {location}

Returns one location.

args:
  • id: {string} The id of the location to get.
api.locations.getOne('1').then((response) => {
  console.log('location:', response.data)
})

Content

api.content.getMany(type, filter): [{content}, ...]

Returns an array of content objects matching the type and filter option(s).

args:
  • type: {string} The type of content to get.
  • filter: {Object} A json object that is used to filter results from the api.
// return all active items
api.content.getMany('PRODUCT', {status: 'active'}).then((response) => {
  console.log('content items:', response.data)
})
api.content.getOne(type, id): {content}

Returns one content object.

args:
  • type: {string} The type of content to get.
  • id: {string} The id of the content to get.
api.locations.getOne('PRODUCT', '1').then((response) => {
  console.log('content item:', response.data)
})
api.content.getManyComplex(type, filter): [{content}, ...]

Returns an array of content objects matching the type and filter option(s).

args:
  • type: {string} The type of content to get.
  • filter: {Object} A json object that is used to filter results from the api.
// return all items that have values.showProducts = true paged with 10 per page
api.content.getManyComplex('PRODUCT', { pagination: { perPage: 10, page: 0 }, valuesFields: { showProducts: { equals: true } }}).then((response) => {
  console.log('headers:', response.header) // contains paging information

  // Available Pagination Headers
  // Powerchord-Pagination-Desc:false
  // Powerchord-Pagination-Page:0
  // Powerchord-Pagination-Pagecount:4
  // Powerchord-Pagination-Perpage:10
  // Powerchord-Pagination-Resultcount:40
  // Powerchord-Pagination-Sortby:title

  console.log('content items:', response.data)
})
api.content.aggregate(type, listFilter, aggregate): [{content}, ...]

Returns an object of results objects matching the type and filter option(s).

args:
  • type: {string} The type of content to get.
  • listFilter: {Object} A json object that is used to filter results from the api.
  • aggregate: {Object} A json object that is used to specify the value fields to perform an aggregate on.
// return aggregate values for the description value in the values.specifications collection
api.content.aggregate('PRODUCT',
{
  valuesFields: {
    showProduct: {
      equals:true
    }
  }
},
{
  parent:"specifications",
  category:"description",
  key:"value"
}).then((response) => {
  console.log('aggregate items:', response.data)
})

Analytics

api.analytics.track(events)

Writes events to the platform API.

args:
api.analytics.track({
    'pageview': {
        title: 'Hello World',
        location: 'http://my.site.com/welcome?u=me'
    }
})
Supported Analytics Events
pageview
  • title: {string} The title of the page.
  • location: {string} The full url of the page excluding the hash.
api.analytics.track({
    'pageview': {
        title: 'Hello World',
        location: 'http://my.site.com/welcome?u=me'
    }
})

Composite

advanced topic

api.composite.query(query)

Composite is an endpoint that takes a multi-entity structured query and returns all entities via one network call. While you are free to use this method directly, the mechanics of composite are complicated. Using forte-conductor is recommended.

args:
  • query: {Object}

Carts

The carts API follows a RESTful control flow pattern base on the Powerchord Platform API.

For example, given an API request of POST /carts/123/items/ the corresponding forte-api call would be carts.id(123).post({...})

For more detail regarding Paltform API see: Platform API docs