Giter Club home page Giter Club logo

z-deduper's Introduction

Custom Zapier Deduper

This library will allow you to build a Custom Zapier deduper for your advanced polling triggers use cases in your Zapier app.

Installation

$ yarn add z-deduper

Usage

z-deduper uses the Zapier Storage REST API behind the scenes to implement a custom deduper that will allow a polling trigger to compare the current API response records with the records that were cached by the deduper in order to determine which ones are new records and which ones are only updated records when the API doesn't include any timestamps to indicate when a record has been created or updated.

To get started, you'll need to create an instance of z-deduper, you can do it like so:

const { getDeduper } = require("z-deduper");

const deduper = getDeduper("your_zap_id_goes_here");

Basically, the deduper should only run when the zap is enabled. You will need to take care of a few cases to get it to work properly.

Initializing the deduper

When the zap is turned on, Zapier will start populating its internal deduper and bundle.meta.isPopulatingDedupe will be set to true. At this point, you will have to initialize the deduper with as many records as possible (See the examples below).

// ...

const contacts = await fetchContacts(z);

if (bundle.meta.isPopulatingDedupe) {
  // Initialize the custom deduper
  await deduper.initialize(contacts);
}

// ...

Loading a sample

When the user is testing the trigger, Zapier will run the trigger to fetch some samples. In this case, bundle.meta.isLoadingSample will be set to true and the deduper should be bypassed.

const contacts = await fetchContacts(z);

if (bundle.meta.isLoadingSample) {
  // When the deduper cache is empty, it will actually return all the records
  const changes = deduper.findChanges(contacts);
  return changes.all;
}

When the zap is polling for data

When a polling interval comes around, the trigger should load the deduper cache first, call the findChanges method on the current API response records, and finally, it must call persistChanges to update the deduper cache.

findChanges method will return an object containing the following items:

  • created: An array containing the newly created records only.
  • updated: A an array containing the updated records only.
  • all: A combination of created and updated.
const contacts = await fetchContacts(z);

await deduper.load();
const changes = deduper.findChanges(contacts);
await deduper.persistChanges(contacts);

return changes.created; // or changes.updated;

Example 01: New Contact

Here's a quick example showing how to use the custom deduper to detect new records.

const zapier = require("zapier-platform-core");
const { getDeduper } = require("z-deduper");
const { apiUrl } = require("../config");

/**
 * Fetch a list of the contacts
 *
 * @param {zapier.ZObject} z
 */
async function fetchContacts(z) {
  // Make the request
  const response = await z.request({
    method: "GET",
    url: apiUrl,
  });
  const contacts = response.json;
  return contacts;
}

/**
 * On Contact Created
 *
 * @param {zapier.ZObject} z
 * @param {zapier.Bundle} bundle
 */
const perform = async (z, bundle) => {
  const zapId = bundle.meta.zap.id;
  if (!zapId) {
    throw new Error("Zap ID is required for the custom deduper to work");
  }
  // Get an instance of the custom deduper
  const deduper = getDeduper(zapId);

  // Fetch contacts from the API
  const contacts = await fetchContacts(z);

  if (bundle.meta.isPopulatingDedupe) {
    // Initialize the custom deduper
    await deduper.initialize(contacts);

    // Pass these to the Zapier Deduper
    const changes = deduper.findChanges(contacts);
    return changes.all;
  }

  if (bundle.meta.isLoadingSample) {
    const changes = deduper.findChanges(contacts);
    return changes.all;
  }

  // If we get here, it means that the zap is enabled
  // The follwing will run on each polling interval
  await deduper.load();
  const changes = deduper.findChanges(contacts);
  await deduper.persistChanges(contacts);

  // Returns only the newly created records
  return changes.created;
};

Example 02: Updated Contact

In this example, the deduper will help in detecting which contacts have been updated even though the contacts don't have any timestamps.

const zapier = require("zapier-platform-core");
const { getDeduper } = require("z-deduper");
const { apiUrl } = require("../config");

/**
 * Fetch a list of the contacts
 *
 * @param {ZObject} z
 */
async function fetchContacts(z) {
  // Make the request
  const response = await z.request({
    method: "GET",
    url: apiUrl,
  });
  const contacts = response.json;
  return contacts;
}

/**
 * On Contact updated
 *
 * @param {zapier.ZObject} z
 * @param {zapier.Bundle} bundle
 */
const perform = async (z, bundle) => {
  const zapId = bundle.meta.zap.id;
  if (!zapId) {
    throw new Error("Zap ID is required for the custom deduper to work");
  }
  // Get an instance of the custom deduper
  const deduper = getDeduper(zapId);

  // Fetch contacts from the API
  const contacts = await fetchContacts(z);

  if (bundle.meta.isPopulatingDedupe) {
    // Initialize the custom deduper
    await deduper.initialize(contacts);

    // Pass these to the Zapier Deduper
    const changes = deduper.findChanges(contacts);
    return changes.all;
  }

  if (bundle.meta.isLoadingSample) {
    const changes = deduper.findChanges(contacts);
    return changes.all;
  }

  // If we get here, it means that the zap is enabled
  // The follwing will run on each polling interval
  await deduper.load();
  const changes = deduper.findChanges(contacts);
  await deduper.persistChanges(contacts);

  // Returns only the updated records
  return changes.updated;
};

As you might have already noticed, both examples are very similar. The only difference is that the "New Contact" trigger will return changes.created whereas "Update Contact" will return changes.updated.

License

MIT

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.