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

@vendia/block-subscription-handler

v2.0.0

Published

A library to simplify the handling of Vendia Share Block Notifications in AWS Lambda

Downloads

13

Readme

@vendia/block-subscription-handler

A TypeScript library to simplify the handling of Vendia Share Block Notifications in AWS Lambda

What is it?

This library helps Vendia Share Customers build integrations using Block Notifications. Inside a Share Uni (universal application), any mutating changes (add,create,update,etc.) result in a block being written to the ledger supporting the Uni. When a block is written, notifications are emitted and can be consumed by a number of methods like AWS Lambda, providing a great opportunity for integrations.

See: Vendia Share Integrations for details regarding the configuration and permissions needed to use an AWS Lambda function with Vendia Share Unis as it is not covered in this README

The Problem?

When subscribing to block notifications from a Share Uni, the only information available regards the block itself and not the data that relates to it.

The Solution

This library parses block notifications and can provide data relating to the block through two methods. The first involves parsing the Graphql mutations that resulted in the block creation. The second involves introspecting these mutations to dynamically query the related objects from the Uni's world state. The How It Works section below shows these processes in more detail.

Usage

Install the module

//Typescript
import * as blockSubscriptionHandler from '@vendia/block-subscription-handler';

//CommonJS
const blockSubscriptionHandler = require('@vendia/block-subscription-handler');

Functions

Getting Mutations

Parse Amazon SNS or SQS messages for Block Notification Mutations

Using the library's GetMutationsFromSnsBlockEvent or GetMutationsFromSqsBlockEvent functions, the SNS or SQS messages containing block notifications can easily be parsed within the AWS Lambda service to return the GraphQL Mutations related to the block. This will require the ability to query the Uni that emitted the notifications.

The GetMutationsFromSnsBlockEvent function requires three arguments:

| Argument | Description | | -------------- | -------------------------------------------------------- | | event | The SNS event object presented to an AWS Lambda function | | vendiaShareURL | The Uni's GraphQL URL | | vendiaShareKey | The Uni's GraphQL API Key |

The GetMutationsFromSqsBlockEvent function requires three arguments:

| Argument | Description | | -------------- | -------------------------------------------------------- | | event | The SQS event object presented to an AWS Lambda function | | vendiaShareURL | The Uni's GraphQL URL | | vendiaShareKey | The Uni's GraphQL API Key |

Getting Block Data

Sometimes it is necessary to retrieve mutations along with Block-level fields like Owner and Commit Time. In these cases, parsing the entire block from SQS or SNS messages can be achieved with the GetBlockFromSqsBlockEvent and GetBlockFromSnsBlockEvent functions

The GetBlockFromSqsBlockEvent and GetBlockFromSnsBlockEvent functions accept the same inputs as the above GetMutationsFromSnsBlockEvent and GetMutationsFromSqsBlockEvent functions. Instead of returning a list of string mutations, these functions return an object with the following interface:

{
   _TX: [
      Owner: string,
      Mutations: ReadonlyArray<string>,
      TxId: string,
   ]
   CommitTime: string;
}

ParseMutation

Parse the object data for each mutation

The ParseMutation function is the fastest way to retrieve a typed object from the GraphQL mutation. This function uses only the Graphql Mutation AST to build a typed object. This is useful for mutations with operations like Add, Create, and Put. In the case of Update mutations, which are allowed to include partial data, the GetMutationObjectFromAPI function may be more desirable as it queries the API for all fields of a specific type regardless of their use in an Update.

The ParseMutation function requires one argument:

| Argument | Description | | -------- | ----------------- | | mutation | A string mutation |

Example Output

//input mutation
"addtopList(id:\"01797be0-cb8d-9bad-aa08-cc8356c11f95\",input: {innerList: [{name: \"innerListName\", object: {objectName: \"ObjectName\"}}], name: \"listName\"}){error}"

//output
{"__typename":"Event","arguments":{"id":"b4de7525-623b-11eb-a0cb-0db0d645b658","input":{"animal_id":"b434d448-623b-11eb-afea-59074c0526d3","organization_id":"6fe94056-5bd4-11eb-a9fc-0bb70a7f9c77","timestamp":1611929411261,"node_created":"Node-2","type":"intake","nested":{"thing":["intake"]},"sub_type":"Stray/OTC","location_description":"","three_legged":false,"address1":"","address2":"","city":"","state":"","zipcode":"","geo_location":[0,1]}},"operation":"add"}

GetMutationObjectFromAPI

Get the object data via GraphQL API Introspection

The GetMutationObjectFromAPI function uses GraphQL introspection to dynamically build a Get query for the type referenced in a mutation. This has the advantage of querying all fields on a type regardless of its mention in the mutation itself. This function requires access the to Uni's API and makes several API calls (one per type or nested type, and one for the Query).

The GetMutationObjectFromAPI function requires three arguments:

| Argument | Description | | -------------- | ------------------------- | | mutation | A string mutation | | vendiaShareURL | The Uni's GraphQL URL | | vendiaShareKey | The Uni's GraphQL API Key |

Example Output

//input mutation
"addtopList(id:\"01797be0-cb8d-9bad-aa08-cc8356c11f95\",input: {innerList: [{name: \"innerListName\", object: {objectName: \"ObjectName\"}}], name: \"listName\"}){error}"

//output
{"arguments":{"id":"01797be0-cb8d-9bad-aa08-cc8356c11f95","innerList":[{"name":"innerListName","object":{"objectName":"ObjectName"}}],"name":"listName"},"operation":"add","__typename":"topList"}

Full Example

import * as blockSubscriptionHandler from '@vendia/block-subscription-handler';

//or for commonjs
//const blockSubscriptionHandler = require('@vendia/block-subscription-handler');

const url = process.env.vendiaShareURL;
const key = process.env.vendiaShareKey;

exports.handler = async function (event) {
  console.log('EVENT' + JSON.stringify(event));

  //Parse mutations from AWS Lambda Event
  //Note an object like {CommitTime:string, Mutations[...string...]} is returned
  const Mutations =
    await blockSubscriptionHandler.GetMutationsFromSnsBlockEvent(
      event,
      url,
      key
    );

  /* If using  SQS and not the default SNS 
 await blockSubscriptionHandler.GetMutationsFromSqsBlockEvent(
      event,
      url,
      key
    );
*/
  console.log('Mutations ' + JSON.stringify(mutationData));
  console.log('Commit Time ' + mutationData.CommitTime);
  await Promise.all(
    Mutations.map(async function (m) {
      try {
        console.log('Processing mutation ' + m);
        const blockFromShare =
          await blockSubscriptionHandler.GetMutationObjectFromAPI(m, url, key);

        //Using ParseMutation
        const blockFromAST = blockSubscriptionHandler.ParseMutation(m);

        console.log('Block from AST Parsing: ' + JSON.stringify(blockFromAST));
        console.log('Block from API Query: ' + JSON.stringify(blockFromShare));
      } catch (ex) {
        console.error('Error ->' + ex);
      }
    })
  );
};

How it Works

This section details the inner working of each function used to parse mutations

ParseMutation

The ParseMutation function uses only the GraphQL AST of a mutation to generate a typed object. This approach uses the GraphQL-js Library to traverse the AST tree and build an typed object based upon the arguments in the mutation.

GetMutationObjectFromAPI

The GetMutationObjectFromAPI function uses GraphQL introspection to build a new Get Query for the type referenced by a graphql mutation. This process involves several steps:

  • Step 1: Parse the mutation for the Graphql Type Name and the Identifier reported in the Block mutation

  • Step 2: Introspect the input object type via Graphql Queries

  • Step 3: Observe any nested types and recursively query them via Graphql

  • Step 4: Generate a new Query to retrieve the type and its nested types and fields

  • Step 5: Execute the Query and return a typed object based upon the result.