Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@elastic.io/oih-standard-library

Package Overview
Dependencies
Maintainers
14
Versions
68
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@elastic.io/oih-standard-library

Library for OIH standards implementation

  • 1.1.1
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
17
decreased by-5.56%
Maintainers
14
Weekly downloads
 
Created
Source

CircleCI

OIH Standard Library

Table of Contents

Actions

Upsert Object

For implementing UpsertObject action in most cases you need to extend from UpsertObjectById or UpsertObjectByUniqueCriteria classes and following methods:

  • lookupObject(criteria: any, objectType: any, cfg?: any, msg?: any)
  • createObject(object, cfg, msg)
  • updateObject(criteria: any, objectType: any, object: any, cfg?: any, msg?: any) If you need completely custom behaviour you can extend from Upsert class and override process, in this case following OIH standard is your responsibility.

Note:

  • Its your responsibility to ensure that lookupObject returns only 1 object.
  • lookupObject method must return null to indicate that object hasn't been found.
Upsert Object By Id
  1. Create Action
  2. Create class that extends UpsertObjectById class
  3. Implement lookupObject(),createObject(),updateObject() methods. Example below.
  4. Optional override methods:
  • getType - default implementation expects objectType to be present in input configuration,
  • getCriteria - by default, returns id value from body in input message or null,
  • getObjectFromMessage- by default, returns body object from input message.
  1. Create instance of your class and pass logger to constructor. const myUpsertObjectByIDImpl = new MyUpsertObjectByIdImpl(logger);
  2. Export myUpsertObjectByIDImpl.process(msg, cfg, snapshot) as process method. Example below.
Example of Usage

Works in sailor > 2.4.2 Upsert Object Action

const { UpsertObjectById } = require('@elastic.io/oih-standard-library/lib/actions/upsert');

class MyUpsertObjectByIdImpl extends UpsertObjectById {
 async lookupObject(criteria, objectType, cfg, msg) {
   const existObject = await getObjectInAPI(criteria, objectType, cfg, msg);
   if (existObject) { return existObject; }
   return null;
 }

 async createObject(object, cfg, msg) {
   return await createObjectInAPI(object, cfg, msg);
 }

 async updateObject(criteria, objectType, object, cfg, msg) {
   return await updateObjectInAPI(criteria, objectType, object, cfg, msg);
 }
 // You can also override getType, getCriteria and getObjectFromMessage methods if needed
}

async function process(msg, cfg, snapshot = {}) {
 const upsertAction = new MyUpsertObjectByIdImpl(this.logger); // Sailor version > 2.4.2
 return upsertAction.process(msg, cfg, snapshot);
}
module.exports.process = process;
Upsert By Unique Criteria

The same as Upsert Object By Id but getCriteria method by default returns value of field uniqueCriteria that is defined in input configuration, from the body in the input message.

Create Object

Similar to upsert object but needed for the following cases:

  • Objects that can be created but can not be updated after creation (e.g. Invoices)
  • Cases where you want to create an object and its children
  • Cases where the id of the object includes information in the object (e.g. The ID of a sales line is the sales order ID + SKU).
Example Use Case

See above.

Lookup Object (at most 1)

For implementing LookupObject action in most cases you need to extend from LookupObjectById or LookupObjectByUniqueCriteria classes. If you need completely custom behaviour you can extend from LookupObject class and override process and lookupObject method, in this case following OIH standard is your responsibility.

Lookup Object By Id

Note:

  • Its your responsibility to ensure that lookupObject returns only 1 object. This implementation assume that id is unique for objectType.
  • lookupObject method must return null to indicate that object hasn't been found.
  1. Create Action
  2. Create class that extends LookupObjectById class
  3. Override lookupObject() methods. Example below.
  4. Optional override getType and getId methods. Default implementation expects objectType to be present in input configuration and id in input message.
  5. Create instance of your class and pass logger to constructor. const myLookupByIDImpl = new MyLookupByIdImpl(logger);
  6. Export myLookupByIDImpl.process(msg, cfg, snapshot) as process method. Example below.
Example of Usage

Works in sailor > 2.4.2 Lookup Action

const { LookupById } = require('@elastic.io/oih-standard-library/lib/actions/lookupObject');

class MyLookupByIDImpl extends LookupById {


  async lookupObject(id, objectType, cfg, msg) { // In most cases you need just id, type and cfg
    const result = await lookupObjectInAPI(id,  objectType, cfg, msg); // Lookup object
    return result; // Return found object. If you return null, it will indicate no object found.
  }
  // You can also override getType and getId methods if needed
}
   

async function process(msg, cfg, snapshot = {}) {
  const lookupAction = new MyLookupByIDImpl(this.logger); // Sailor version > 2.4.2
  return lookupAction.process(msg, cfg, snapshot);
}

module.exports.process = process;
Lookup Object By Unique Criteria

Note:

  • In case when lookupObject method has found more than 1 object it must return an array or throw error.
  • lookupObject method must return null to indicate that object hasn't been found.
  1. Create Action
  2. Create class that extends LookupObjectByUniqueCriteria class
  3. Override lookupObject() methods. Example below.
  4. Optional override getType and getCriteria methods. Default implementation expects objectType to be present in input configuration and id in input message.
  5. Create instance of your class and pass logger to constructor. const myLookupObjectByUniqueCriteriaImpl = new MyLookupObjectByUniqueCriteriaImpl(logger);
  6. Export myLookupObjectByUniqueCriteriaImpl.process(msg, cfg, snapshot) as process method. Example below.
Example of Usage

Works in sailor > 2.4.2 Lookup Action

const { LookupByUniqueCriteria } = require('@elastic.io/oih-standard-library/lib/actions/lookupObject');

class  MyLookupObjectByUniqueCriteriaImpl extends  LookupByUniqueCriteria {


  async lookupObject(criteria, objectType, cfg, msg) { // In most cases you need just criteria, type and cfg
    const result = await lookupObjectInAPI(id,  objectType, cfg, msg); // Lookup object
    if (result instanceof Array) {
      // return it or throw error. If result.length > 1 error will be thrown by action  
  } 
  return result; // Return found object. If you return null, it will indicate no object found.
  }
  // You can also override getType and getCriteria methods if needed
}
   

async function process(msg, cfg, snapshot = {}) {
  const lookupAction = new MyLookupObjectByUniqueCriteriaImpl(this.logger); // Sailor version > 2.4.2
  return lookupAction.process(msg, cfg, snapshot);
}

module.exports.process = process;

Lookup Objects (Plural)

For implementing Lookup Objects (plural), you will have to extend from LookupObjects class. You must provide the functions getObjectsByCriteria(objectType, criteria: Array, msg?, cfg?, pageSize?, firstPage?, orderBy?): and getMetaModel(cfg)

Steps for implementation
  1. Create Action
  2. Create class that extends LookupObjects (plural)
  3. Override getObjectsByCriteria() and getMetaModel()
  4. Optionally override methods like getCriteria(). Default implementation assumes a specific format to the metadata fields as provided by getInMetadata(), so you may wish to also override this function
  5. Create instance of your class and pass the logger method to the constructor.
  6. Export myLookupObjects.process(msg, cfg, snapshot) as process method. Example below:
Example
const { LookupObjects } = require('@elastic.io/oih-standard-library/lib/actions/lookupObjects');

class MyLookupObjects extends LookupObjects {

  async getObjectsByCriteria(objectType, criteria, msg, cfg) { // In most cases you need objectType, criteria
    const results = await lookupObjects(objectType, criteria); // Perform lookup
    return results; // Return lookup results
  }

  async getMetaModel(cfg) {
    const metaModel = {};
    const properties = {
      fields: ['field1', 'field2'],
      conditions: ['=', 'in'],
      orderEnum: ['asc', 'desc'],
      includeOrder: false,
      additionalFields: 'additionalField',
      criteriaLinkEnum: ['and', 'or'],
      disableCriteriaLink: false
    };
    metaModel.in = this.getInMetadata(cfg, properties);
    metaModel.out = {
      type: object,
      ...
    };
    return metaModel;
  }
}
   

async function process(msg, cfg, snapshot = {}) {
  const deleteAction = new MyLookupObjects(this.logger, this.emit); // Sailor version > 2.4.2
  return deleteAction.process(msg, cfg, snapshot);
}

module.exports.process = process;

Delete Object

For implementing Delete action in most cases you need to extend from DeleteById or DeleteByUniqueCriteria classes. If you need completely custom behaviour you can extend from Delete class and override process and deleteObject method, in this case following OIH standard is your responsibility.

Delete By ID

Note:

  • Its your responsibility to ensure that deleteObject deletes only 1 object. This implementation assume that id is unique for objectType.
  • If deleteObject method is returning null empty object would be emitted. You can indicate with null that object hasn`t been deleted or found.
  1. Create Action
  2. Create class that extends DeleteById class
  3. Override deleteObject() methods. Example below.
  4. Optional override getType and getId methods. Default implementation expects objectType to be present in input configuration. For unique criteria: uniqueCriteria field name in input configuration and value in input message.
  5. Create instance of your class and pass logger to constructor. const myDeleteByIDImpl = new MyDeleteByIdImpl(logger);
  6. Export myDeleteByIDImpl.process(msg, cfg, snapshot) as process method. Example below.
Example of Usage

Works in sailor > 2.4.2 Delete Action

const { DeleteById } = require('@elastic.io/oih-standard-library/lib/actions/delete');

class MyDeleteByIDImpl extends DeleteById {


  async deleteObject(id, cfg, msg) { // In most cases you need just id, type and cfg
    const deletedID = await deleteObjectInAPI(id, cfg, msg); // Delete object
    return deletedID; // Return deleted object ID. If you return null, empty object would be emitted.
  }
  // You can also override getType and getId methods if needed
}
   

async function process(msg, cfg, snapshot = {}) {
  const deleteAction = new MyDeleteByIDImpl(this.logger); // Sailor version > 2.4.2
  return deleteAction.process(msg, cfg, snapshot);
}

module.exports.process = process;
Delete By Unique Criteria

Note:

  • If more than 1 object was found with same uniqueCriteria, error would be thrown by this implementation
  • If deleteObject method is returning null empty object would be emitted. You can indicate with null that object hasn`t been deleted or found.
  1. Create Action
  2. Create class that extends DeleteById class
  3. Override findObjectByCriteria and deleteObject() methods. Example below.
  4. Optional override getType and getCriteria methods. Default implementation expects objectType to be present in input configuration. For unique criteria: uniqueCriteria field name in input configuration and value in input message.
  5. Create instance of your class and pass logger to constructor. const myDeleteByCriteriaImpl = new MyDeleteByCriteriaImpl(logger);
  6. Export myDeleteByCriteriaImpl.process(msg, cfg, snapshot) as process method. Example below.
Example of Usage

Works in sailor > 2.4.2 Delete Action

const { DeleteByUniqueCriteria } = require('@elastic.io/oih-standard-library/lib/actions/delete');

class MyDeleteByCriteriaImpl extends DeleteByUniqueCriteria {

  async findObjectByUniqueCriteria(criteria, type, cfg, msg) { // In most cases you need just criteria, type and cfg
     // criteria sructure {
     //  uniqueCriteria: 'fieldName',
     //  value: 'fieldValue', 
     // }
     const object =  await findObjectInAPI(criteria, type, cfg, msg); // objects that match this criteria
     const numberOfObjects =  object.count; // You do not need to check or throw error in this case, action implementation will do this
     return { // return structure must contain object and numberOfObjects found
       object,
       numberOfObjects
     }
  }
  async deleteObject(object, cfg, msg) { // In most cases you need just object, type and cfg
    const deletedID = await deleteObjectInAPI(object, cfg, msg); // Delete object
    return deletedID; // Return deleted object ID if you return null, empty object would be emitted.
  }
  // You can also override getType and getId methods if needed
}
   

async function process(msg, cfg, snapshot = {}) {
  const deleteAction = new MyDeleteByCriteriaImpl(this.logger); // Sailor version > 2.4.2
  return deleteAction.process(msg, cfg, snapshot);
}

module.exports.process = process;

Lookup Set Of Objects

For implementing LookupObject action in most cases you need to extend from LookupSetOfObjectsSingleField class or wait for LookupSetOfObjectsMultipleField class to be implemented. If you need completely custom behaviour you can extend from LookupSetOfObjects class and override process and lookupSetOfObjects method, in this case following OIH standard is your responsibility.

Notes:

  • Lookup Set will handle the case when the set of items to lookup is empty.
  • Lookup Set will handle casting the result into an array.
  • Lookup Set will de-duplicate the incoming array and check size contraints.
  • Lookup Set will make sure all the items in the set that should be there are there and then rebound or error as appropreate.

Methods that must be overridden:

  • async lookupSetOfObjects(criteriaFieldName, objectType, itemsToLookup, cfg, msg) - Given an field name, object type and array of ids, find the objects in that set and return as an array

Methods that can be overridden (if the underlying functionality doesn't work):

  • async process(msg, cfg, snapshot) - Overwrite the entire process function
  • getType(cfg: any, msg: any) - Identify type from config
  • getItemsToLookup(msg: any, cfg: any) - Extract item info from the body
  • getMaxItemsToLookup(msg:any, cfg: any) - Provide max size of set: defaults to 100
  • getCriteriaFieldName(msg: any, cfg: any): string - Extract the criteria field from config
  • doesItemMatch(lookupCriteriaValue: any, item:any, msg:any, cfg:any): boolean - Check if a given object has the id value described in lookupCriteriaValue

Triggers

Get New And Updated Objects Polling

For implementing et New And Updated Objects Polling(Polling Trigger) extend from class PollingTrigger and override: getObjects, getObjectsFromPage methods. Note:

  1. getObjectsFromPage(objectType, startTime, endTime, page, cfg) - is expecting parameter page. Page is structure with fields: pageNumber, pageSize, singlePagePerInterval.
  2. getObjectsFromPage - must return following structure: { 'objects': 'result of polling' 'nextPage' : 'number or object, represents next page to poll' }.
  3. emitIndividually behaviour expects array to be returned by method: getObjects.
  4. Its responsibility of implementation to handle situation when startTime > endTime
How to implement:
  1. Create Trigger
  2. Create class that extends PollingTrigger
  3. Override getObjects() and getObjectsFromPage() methods
  4. Optionally override methods any other methods, see class PollingTrigger
  5. Create instance of your class and pass the logger nad emitter to the constructor.
  6. Export myPollingTrigger.process(cfg, snapshot) as process method. Example below:
Example of Usage
const PollingTrigger  = require('@elastic.io/oih-standard-library/lib/triggers/getNewAndUpdated');

class MyPollingTriggerImpl extends PollingTrigger {

  async getObjects(objectType, startTime, endTime, cfg) {
     return api.poll(objectType, startTime, endTime, cfg); // Poll object from API, Note: emitIndividually expects array to be returned by this method
  }
  async getObjectsFromPage(objectType, startTime, endTime, page, cfg) { 
     // page.pageNumber - current page,
     // page.pageSize - size of page to poll, 
     // page.singlePagePerInterval - is single page inteval, it is passed to this step but logic of this parameter already handled by process method 
     const result = await api.pollPage(objectType, page, startTime, endTime, cfg);
     return { nextPage: result.nextPage, objects: result.objects } // Must return structure like this
  }
}
   

async function process(cfg, snapshot) {
  const trigger = new MyPollingTriggerImpl(this.logger, this.emit); // Sailor version > 2.4.2
  return trigger.process(cfg, snapshot);
}

module.exports.process = process;

Webhooks

Firstly, Webhook subscription handling strategy should be implemented. For this purpose HandleWebhookSubscriptionByIdAbstractStrategy must be extended and createWebhooks & deleteWebhooks methods must be implemented. Also can be defined absolutely new strategy. For this purpose, just implement interface HandleSWebhookSubscriptionAbstractStrategy.

Example of Usage

const { HandleWebhookSubscriptionByIdAbstractStrategy, Webhook, defaultProcessWebhook } = require('@elastic.io/oih-standard-library/lib/triggers/webhook');

// implementation of subscription create strategy
// in this class we must implement create/delete WebhookSubscription methods 
class HandleWebhookSubscriptionByIdStrategy extends HandleWebhookSubscriptionByIdAbstractStrategy {
 constructor(client, logger) {
   super(logger);
   this.client = client;
 }

// According to superclass definition should return object with array of ids; Example: {ids: ['webhook1', 'webhook2']}
 async createWebhooks(objectType, eventTypes) {
   const webhooks = await Promise.all(eventTypes.map(eventType => this.client.create({
     topic: eventType,
     address: process.env.ELASTICIO_FLOW_WEBHOOK_URI,
     format: 'json',
   }, WEBHOOK_OBJECT_TYPE)));
   return { ids: webhooks.map(webhook => webhook.id) };
 }

 async deleteWebhooks(input) {
     await Promise.all(input.ids.map(id => this.client.delete({ id }, WEBHOOK_OBJECT_TYPE)));
 }
}

// construct Webhook object using HandleWebhookSubscriptionByIdStrategy strategy
function configuredWebhook(cfg, logger) {
 const credentials = {
   apiKey: cfg.apiKey,
   shopName: cfg.shopName,
   password: cfg.password,
 };
 const client = new Client(credentials);
 const handleWebhookSubscriptionByIdStrategy = new HandleWebhookSubscriptionByIdStrategy(client, logger);
 const webhook = new Webhook(logger, handleWebhookSubscriptionByIdStrategy);
 return webhook;
}

// Export startup and shutdown functions
async function startup(cfg) {
 const webhook = await configuredWebhook(cfg, this.logger);
 return webhook.startup(cfg);
}

async function shutdown(cfg, data) {
 const webhook = await configuredWebhook(cfg, this.logger);
 await webhook.shutdown(cfg, data);
}

// Export static process function
module.exports.process = defaultProcessWebhook;
module.exports.startup = startup;
module.exports.shutdown = shutdown;

Keywords

FAQs

Package last updated on 24 Jun 2020

Did you know?

Socket

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.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc