• This repository has been archived on 23/Aug/2023
  • Stars
    star
    202
  • Rank 193,691 (Top 4 %)
  • Language
    JavaScript
  • License
    Apache License 2.0
  • Created over 6 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

✨ Iguazu is a simple Redux-powered Async Query engine


iguazu - Iguazu

npm version Main Health Check

Iguazu is a simple Redux-powered Async Query engine. By using a Higher-Order Component, Iguazu transparently manages dispatching async requests and injecting into React props. Iguazu has an ecosystem of adapters for various querying + caching strategies: Iguazu RPC, Iguazu GraphQL and Iguazu REST.

πŸ‘©β€πŸ’» Hiring πŸ‘¨β€πŸ’»

Want to get paid for your contributions to iguazu?

Send your resume to [email protected]

πŸ“– Table of Contents

✨ Features

  • Streamlines dispatching, load states, and injecting into React props
  • Parallel and sequential async requests
  • Server-side rendering ready

Motivation

react-redux works great for when you want to take data that already exists in state and inject it as props into a React component, but it doesn't help you at all with the flow of loading asynchronous data into state. If a react component relies on asynchronous data you typically have to do three things:

  1. Define a load action responsible for fetching the asynchronous data, which should be triggered on mount and when the component receives new props that change what data should be loaded
  2. Define a mapStateToProps function and use selectors to get the data out of state
  3. Determine whether the state is actually loaded based on the props the selectors return

Iguazu seeks to simplify this flow into one step.

πŸ€Ήβ€ Usage

Installation

npm install --save iguazu

Base Concepts

Iguazu exports a Higher Order Component (HOC) connectAsync similar to React Redux's connect. Instead of taking a mapStateToProps function, it takes a loadDataAsProps function. It should return a map where each key is the name of a prop that will contain some asynchronous data and the value is the load function that will load that data if it is not already loaded. The load function must synchronously return an object with the keys data, status, error, and promise. The key data should be the data returned from the asynchronous call. The key status should be either loading to signal the asynchronous call is in flight or complete to signal it has returned. The key error should be a truthy value if there was an error while loading. The key promise should be the promise of the asynchronous call.

For each key defined in the loadDataAsProps function, the HOC will pass a prop to the wrapped component that contains the data. It will also pass two function props, isLoading and loadedWithErrors, which will tell you if any of the async props are still loading or loaded with errors respectively. If you are only interested in a subset of async props, you can pass an array of the props names as the first argument. There will also be a prop named loadErrors that maps the load error, if there is one, for each prop. You can use this if you want to more granularly dig into what failed.

Example:

/* actions.js */
import React from 'react';
import { connectAsync } from 'iguazu';

export function queryMyData(param) {
  return (dispatch, getState) => {
    const data = getState().path.to.myData[param];
    const status = data ? 'complete' : 'loading';
    const promise = data ? Promise.resolve : dispatch(fetchMyData(param));

    return { data, status, promise };
  };
}

export function queryMyOtherData(param) { /* Essentially the same as queryMyData */ }

/* MyContainer.jsx */
function MyContainer({
  isLoading,
  loadedWithErrors,
  myData,
  myOtherData,
}) {
  if (isLoading()) {
    return <div>Loading...</div>;
  }

  if (loadedWithErrors()) {
    return <div>Oh no! Something went wrong</div>;
  }

  return (
    <div>
      myData =
      {' '}
      {myData}
      myOtherData =
      {' '}
      {myOtherData}
    </div>
  );
}

function loadDataAsProps({ store, ownProps }) {
  const { dispatch, getState } = store;
  return {
    myData: () => dispatch(queryMyData(ownProps.someParam)),
    myOtherData: () => dispatch(queryMyOtherData(getState().someOtherParam)),
  };
}

export default connectAsync({ loadDataAsProps })(MyContainer);

You can see that by moving the logic responsible for selecting out the cached data and triggering a fetch if needed into the actions makes the components much simpler.

Advanced Concepts

SSR

The main benefits of server side rendering are improved perceived speed and SEO. With perceived speed, the general best practice is to get something in front of the user's eyes as fast as possible. Typically that means you shouldn't wait for any data before rendering to string. For SEO, it's more important that you render the full content, and if that content is dynamic, you'll need to wait on some data. Usually not every view is important for SEO, such as logged in views, so the best option is to only preload data you absolutely have to for SEO. For this reason, Iguazu makes SSR data preloading opt in. If you would like a component's data to be loaded prior to rendering on the server, you can add a property named ssr with the value of true.

Example:

/* server.js */
import express from 'express';

const app = express();
/* Component.jsx */
function loadDataAsProps() { /* ... */ }
loadDataAsProps.ssr = true;

Helper methods

Sometimes you might want to enable SSR preloading for a component, but only for some of its data. Iguazu provides some helper methods, defer and noncritical, to more granularly load data on the server. If you wrap a load function with defer, it will not execute the load function at all and will just return a status of loading. If you wrap a function with noncritical, the load function will execute, but its promise will be caught so that if it rejects it won't cause the Promise.all to reject and return before the other more critical pieces of data have returned.

Example:

import { defer, noncritical } from 'iguazu';

function loadDataAsProps() {
  return {
    clientOnlyData: defer(() => dispatch(loadClientData())),
    tryToLoadOnServerData: noncritical(() => dispatch(loadIffyData())),
  };
}

Iguazu will also pass a parameter to the load function that tells it whether it is running on the server or not. You might want to use this if you expect data to have a specific shape when it is not loaded, because defer will just return data as undefined.

Example:

function MyComponent({ someData }) {
  return <ul>{someData.list.map((item) => <li key={item.toString()}>{item}</li>)}</ul>;
}

function loadDataAsProps() {
  return {
    someData: ({ isServer }) => (isServer ? { data: { list: [] }, status: 'loading' } : dispatch(loadSomeData())),
  };
}

Synchronization

Let's say you have a dynamic dashboard of components that are all responsible for loading their own data, but you want to wait until they are all loaded to render them so that you don't see a bunch of spinners or a partially loaded page. Since Iguazu attaches the loadDataAsProps function as a static, parent components can easily wait until their children's data is loaded before rendering them.

import React from 'react';
import { iguazuReduce } from 'iguazu';
import ComponentA from './ComponentA';
import ComponentB from './ComponentB';

function MyComponent({ isLoading }) {
  if (isLoading()) {
    return (<div>Loading...</div>);
  }

  return (
    <div>
      <ComponentA someParam="someParam" />
      <ComponentB />
    </div>
  );
}

function loadDataAsProps({ store, ownProps }) {
  return {
    ComponentA: () => iguazuReduce(ComponentA.loadDataAsProps)({
      store, ownProps: { someParam: 'someParam' },
    }),
    ComponentB: () => iguazuReduce(ComponentB.loadDataAsProps)({ store, ownProps: {} }),
  };
}

Sequencing

Quite often you need the results of one asynchronous call to get the inputs for another call. One way to do this is by simply using components.

Example:

import React from 'react';
import { connectAsync } from 'iguazu';

function Parent({ isLoading, parent }) {
  if (isLoading()) {
    return <div>Loading Your Profile...</div>;
  }

  return (
    <div>
      <div>
        You:
        <PersonInfo info={parent} />
      </div>
      <KidsContainer parentId={parent.id} />
    </div>
  );
}

function parentLoadDataAsProps({ store: { dispatch } }) {
  return {
    parents: () => dispatch(loadLoggedInParent()),
  };
}

const ParentContainer = connectAsync({ loadDataAsProps: parentLoadDataAsProps })(Parent);

function Kids({ isLoading, kids }) {
  if (isLoading()) {
    return <div>Loading Kids...</div>;
  }

  return (
    <div>
      Kids:
      {kids.map((kid) => (<PersonInfo key={kid.name} info={kid} />))}
    </div>
  );
}

function kidsLoadDataAsProps({ store: { dispatch }, ownProps: { parentId } }) {
  return {
    kids: () => dispatch(loadKidsByParent(parentId)),
  };
}

const KidsContainer = connectAsync({ loadDataAsProps: kidsLoadDataAsProps })(Kids);

function PersonInfo({ info: { name, age } }) {
  return (
    <div>
      <span>
        name:
        {' '}
        {name}
      </span>
      <span>
        age:
        {' '}
        {age}
      </span>
    </div>
  );
}

Suppose you want to synchronize the parent and kid components so that you show a loading spinner until they are both done loading their data. Or maybe you only have one component that needs some sequenced data and it doesn't make sense to create a new component for each nested piece of data. In these cases you can use the load helper, sequence. You can pass it an array of load functions that need to run in order and depend on data returned from previous functions.

Example:

import React from 'react';
import { connectAsync, sequence } from 'iguazu';

function Parent({ isLoading, parent, kids }) {
  if (isLoading()) {
    return <div>Loading Your Profile...</div>;
  }

  return (
    <div>
      <div>
        You:
        <PersonInfo info={parent} />
      </div>
      <Kids kids={kids} />
    </div>
  );
}

function parentLoadDataAsProps({ store: { dispatch } }) {
  const sequenceLoadFunctions = sequence([
    { key: 'parent', handler: () => dispatch(loadLoggedInParent()) },
    { key: 'kids', handler: ({ parent }) => dispatch(loadKidsByParent(parent.id)) },
  ]);

  return {
    ...sequenceLoadFunctions,
  };
}

const ParentContainer = connectAsync({ loadDataAsProps: parentLoadDataAsProps })(Parent);

function Kids({ kids }) {
  return (
    <div>
      Kids:
      {kids.map((kid) => (<PersonInfo key={kid.name} info={kid} />))}
    </div>
  );
}

function PersonInfo({ info: { name, age } }) {
  return (
    <div>
      <span>
        name:
        {name}
      </span>
      <span>
        age:
        {age}
      </span>
    </div>
  );
}

Sequenced function handlers are called with the results from all previous functions in case your inputs need to be derived from more than one previous call.

const sequenceLoadFunctions = sequence([
  { key: 'first', handler: () => dispatch(loadFirst()) },
  { key: 'second', handler: ({ first }) => dispatch(loadSecond(first.someParam)) },
  { key: 'third', handler: ({ first, second }) => dispatch(loadThird(first.someParam, second.anotherParam)) },
]);

If you need to make two calls in parallel before you make a third, you can use a combination of iguazuReduce and sequence to accomplish your goal.

const sequenceLoadFunctions = sequence([
  {
    key: 'first',
    handler: iguazuReduce(() => ({
      firstA: () => dispatch(loadFirstA()),
      firstB: () => dispatch(loadFirstB()),
    })),
  },
  {
    key: 'second', handler: ({ first: { firstA, firstB } }) => dispatch(loadSecond(firstA, firstB)),
  },
]);

Function handlers require the previous calls to succeed to continue to the next by default. In the event a request returns with an error all remaining calls are flagged with the same error. To bypass this default behavior, you can wrap the function handler in noncritical to continue without the previous results.

const sequenceLoadFunctions = sequence([
  { key: 'first', handler: () => dispatch(loadFirst()) },
  { key: 'second', handler: noncritical(({ first }) => dispatch(loadSecond(first.someParam))) },
  { key: 'unrelated', handler: () => dispatch(loadUnrelated()) },
]);

Updating

Iguazu processes updates on Redux state changes by comparing the previous and next responses from loadDataAsProps using shallowequal by default. You are able to declare a comparator function when calling connectAsync to manage how the previous and next responses from loadDataAsProps are compared.

import { deepEqual } from 'fast-equals';

function loadDataAsProps({ store, ownProps }) {
  const { dispatch, getState } = store;
  return {
    myData: () => dispatch(queryToDeeplyNestedData(ownProps.someParam)),
    myOtherData: () => dispatch(queryMyOtherData(getState().someOtherParam)),
  };
}

export default connectAsync({
  loadDataAsProps,
  stateChangeComparator: deepEqual,
})(MyContainer);

Limiting

As some functions called within loadDataAsProps can be expensive when ran on every Redux state change, you are able to declare a limiter function when calling connectAsync. Calls to loadDataAsProps are not limited by default.

function loadDataAsProps({ store, ownProps }) {
  const { dispatch, getState } = store;
  return {
    myData: () => dispatch(expensiveQueryToData(ownProps.someParam)),
    myOtherData: () => dispatch(queryMyOtherData(getState().someOtherParam)),
  };
}

export default connectAsync({
  loadDataAsProps,
  stateChangeLimiter: (onStateChange) => debounce(onStateChange, 100),
})(MyContainer);

Updating and Refreshing Data

In the case that we need to update a remote resource and refresh stale data:

/* MyUpdatingComponent.jsx */
import React, { Component, Fragment } from 'react';
import { compose } from 'redux';
import { connect } from 'react-redux';
import { connectAsync } from 'iguazu';

import { getMyDataAction, updateMyDataAction } from './iguazuActionCreators';

class MyUpdatingComponent extends Component {
  constructor(props) {
    super(props);
    this.state = { message: '' };
  }

  handleClick = () => {
    const { updateMyData, getMyData } = this.props;
    // Send updateMyData request
    const { promise: updateMyDataPromise } = updateMyData('someParam');
    return updateMyDataPromise
      .then(() => {
        // Refresh getMyData to get new results
        const { promise: myDataPromise } = getMyData();
        return myDataPromise;
      })
      .then(() => {
        this.setState({ message: 'Success!' });
      });
  };

  render() {
    const { isLoading, loadedWithErrors, myData } = this.props;
    const { message } = this.state;

    if (isLoading()) {
      return <div>Loading...</div>;
    }

    if (loadedWithErrors()) {
      return <div>Oh no! Something went wrong</div>;
    }

    return (
      <Fragment>
        {message}
        <button type="button" onClick={this.handleClick}>Update</button>
        <h1>My Data</h1>
        {myData}
      </Fragment>
    );
  }
}

// Hook up action creator functions to props to call later
function mapDispatchToProps(dispatch) {
  return {
    // Update some remote resource
    updateMyData: (someParam) => dispatch(updateMyDataAction(someParam)),
    // Fetch some remote resource
    getMyData: () => dispatch(getMyDataAction()),
  };
}

// Hook up data dispatches on component load
function loadDataAsProps({ store }) {
  const { dispatch } = store;
  return {
    // Fetch some remote resource and inject it into props as myData
    myData: () => dispatch(getMyDataAction()),
  };
}

export default compose(
  connect(undefined, mapDispatchToProps),
  connectAsync({ loadDataAsProps })
)(MyUpdatingComponent);

Global Configuration

Iguazu is also capable of consuming global configuration that will be applied to all instances of connectAsync. These options will be applied unless otherwise overridden by providing the equivalent setting in the connectAsync call.

import { shallowEqual, deepEqual } from 'fast-equals';
import { configureIguazu } from 'iguazu';

configureIguazu({
  stateChangeComparator: shallowEqual, // applied globally.
  stateChangeLimiter: (onStateChange) => debounce(onStateChange, 100), // applied globally.
});

/* ... */

function loadDataAsProps({ store, ownProps }) {
  const { dispatch, getState } = store;
  return {
    myData: () => dispatch(queryToDeeplyNestedData(ownProps.someParam)),
    myOtherData: () => dispatch(expensiveQueryToData(ownProps.someParam)),
  };
}

export default connectAsync({
  loadDataAsProps,
  stateChangeComparator: deepEqual, // override global setting.
  stateChangeLimiter: (onStateChange) => debounce(onStateChange, 500), // override global setting.
})(MyContainer);

Known Issues

  • Using iguazuReduce within a sequence returns the response to the next handler as an array if the data is not loaded. Pass in promiseAsObject to iguazuReduce to resolve until next major version.
const sequenceLoadFunctions = sequence([
  {
    key: 'first',
    handler: () => iguazuReduce(ComponentA.loadDataAsProps, { promiseAsObject: true })({
      store, ownProps: { someParam: 'someParam' },
    }),
  },
  { key: 'second', handler: ({ first }) => dispatch(loadSecond(first.someParam)) },
]);

πŸš€ Upgrading

v2.x.x to v3.x.x

  • Upgraded to React Redux 7.x.x, Redux 4.x.x, and Redux Thunk 2.x.x
  • Using new React Context Consumer for retrieving Redux store.
  • Added a ReduxConsumer wrapping component to connectAsync which, may break jest snapshots.
  • Removed enableSSR, disableSSR, and isSSR methods in favor of checking for window to determine Server versus Client in SSR mode
  • loadDataAsProps functions receive isServer as an argument rather than ssr now.
  • Moved react, react-dom, react-redux, redux, and redux-thunk to peerDependencies
  • Removed lodash and decreased gzip bundle size from ~9.6kb to ~4.5kb gzipped.
  • Iguazu adapters remain compatible, just upgrade dependency on iguazu to ^3.0.0.

πŸ† Contributing

We welcome Your interest in the American Express Open Source Community on Github. Any Contributor to any Open Source Project managed by the American Express Open Source Community must accept and sign an Agreement indicating agreement to the terms below. Except for the rights granted in this Agreement to American Express and to recipients of software distributed by American Express, You reserve all right, title, and interest, if any, in and to Your Contributions. Please fill out the Agreement.

Please feel free to open pull requests and see CONTRIBUTING.md to learn how to get started contributing.

πŸ—οΈ License

Any contributions made under this project will be governed by the Apache License 2.0.

πŸ—£οΈ Code of Conduct

This project adheres to the American Express Community Guidelines. By participating, you are expected to honor these guidelines.

More Repositories

1

jest-image-snapshot

✨ Jest matcher for image comparisons. Most commonly used for visual regression testing.
JavaScript
3,821
star
2

react-albus

✨ React component library for building declarative multi-step flows.
JavaScript
1,094
star
3

earlybird

EarlyBird is a sensitive data detection tool capable of scanning source code repositories for clear text password violations, PII, outdated cryptography methods, key files and more.
Go
697
star
4

xcprojectlint

A security blanket for Xcode project files
Swift
504
star
5

nodes

A GraphQL JVM Client - Java, Kotlin, Scala, etc.
Java
307
star
6

one-app

✨ a fresh, modular take on web application development
JavaScript
292
star
7

baton

HTTP load testing witten in Go
Go
264
star
8

busybee

BusyBee is an alternative API for IdlingResources in Espresso tests
Kotlin
189
star
9

jest-json-schema

✨ JSON schema matcher for Jest
JavaScript
169
star
10

parrot

✨ Scenario-based HTTP mocking
JavaScript
137
star
11

unify-flowret

A lightweight Java based orchestration engine
Java
98
star
12

holocron

✨Set of packages that are used to compose and load React components, enabling the updating and launching of server side rendered user experiences without server restarts
JavaScript
80
star
13

unify-jdocs

A new way of working with JSON documents without using model classes or JSON schemas
Java
72
star
14

hyperledger-fabric-sdk-php

Client SDK for Hyperledger Fabric for use in PHP applications
PHP
47
star
15

react-seo

✨ Simple SEO tag manager for React
JavaScript
45
star
16

fetchye

✨ If you know how to use Fetch, you know how to use Fetchye [fetch-yae]. Simple React Hooks, Centralized Cache, Infinitely Extensible.
JavaScript
41
star
17

eslint-config-amex

✨ This is American Express' eslint config
JavaScript
40
star
18

one-app-cli

✨A set of command line interface (CLI) tools for bundling One App, it's modules, and property files(locale and environment specific files).
JavaScript
36
star
19

k8s-prometheus-proxy

JavaScript
28
star
20

css-to-js

✨ Tool for transforming CSS into JS
JavaScript
28
star
21

grpc-k8s-health-check

A gRPC client-server application illustrating health checks of gRPC servers on Kubernetes
Go
27
star
22

amex-api-java-client-core

Library for authenticating with APIs published to the Amex for Developers portal.
Java
26
star
23

simplemli

Encode and Decode Message Length Indicators for TCP/IP socket based protocols
Go
25
star
24

synapse

Synapse is a set of lightweight foundational framework modules for rapid development, built-in with enterprise-grade maturity and quality.
Java
25
star
25

sfdx-cli-plugin

A plugin for the Salesforce DX CLI based on the Open CLI Framework (OCLIF)
TypeScript
24
star
26

one-service-worker

✨ Minimal, light-weight, Promise based library that unifies the service worker and browser threads under one API
JavaScript
23
star
27

purgecss-loader

✨ A Webpack loader to strip unused selectors from your CSS
JavaScript
22
star
28

redux-lifesaver

✨ redux-lifesaver is a middleware that keeps track of how many times actions of the same type are dispatched within a given period.
JavaScript
22
star
29

iguazu-rest

✨ Iguazu REST is a plugin for the Iguazu ecosystem that allows for pre-built async calls for REST with smart caching.
JavaScript
21
star
30

bucketlist

See what's in your BitBucket Server
Kotlin
18
star
31

react-conditional-flow

React components on top of control flow operations like if, if-else, if-else-if, switch-case, & try-catch
JavaScript
17
star
32

redux-idle-callback

✨ Redux middleware to dispatch actions during a Redux store's idle periods
JavaScript
16
star
33

babel-preset-amex

✨ Standard babel preset for American Express
JavaScript
16
star
34

iguazu-graphql

✨ Iguazu GraphQL is a plugin for the Iguazu ecosystem that allows for GraphQL requests backed by a simple cache.
JavaScript
16
star
35

amex-jest-preset

✨ An opinionated Jest preset
JavaScript
14
star
36

fetch-enhancers

✨ Library of middleware for enhancing Fetch
JavaScript
13
star
37

amex-jest-preset-react

✨ An opinionated Jest preset for React modules
JavaScript
13
star
38

xcode-result-bundle-processor

xcode-result-bundle-processor converts Xcode test result bundles into friendly HTML reports
Ruby
12
star
39

lumberjack

✨ Lumberjack is a minimal, configurable Console with utilities.
JavaScript
12
star
40

vitruvius

✨Vitruvius extends redux's combineReducers to allow developers to include a buildInitialState method on their reducer
JavaScript
11
star
41

jexm

Library to facilitate reading from Excel files
Java
10
star
42

targeted-offers-client

SDK for AMEX targeted offers API
JavaScript
10
star
43

task-status-pr-checker

This is triggered when a pull request is created. If the pull request has pending tasks. The pull request won't be merged and the status is updated on the pull request checks.
JavaScript
10
star
44

codeandsolve

9
star
45

parrot-jest-image-snapshot-example

✨ Example demonstrating usage of parrot for more deterministic jest-image-snapshot tests
JavaScript
9
star
46

amex-api-dotnet-client-core

Library for authenticating with APIs published to the Amex for Developers portal.
C#
9
star
47

express-checkout-tutorials

Code samples for use with Express Checkout API
HTML
8
star
48

one-app-ducks

✨Redux ducks used within the One App ecosystem.
JavaScript
8
star
49

env-config-utils

✨ Utilities for runtime configuration validations
JavaScript
8
star
50

create-shared-react-context

✨A memoized wrapper around React.createContext. Used by One App as a dependency to pass React context between Holocron modules without external usage.
JavaScript
8
star
51

middle-manager

An easy migration path away from the Java WorkManager concurrency API
Java
7
star
52

dux-socket

WebSocket middleware for Redux applications
JavaScript
7
star
53

one-app-dev-cdn

✨ Load remote modules for local development
JavaScript
7
star
54

gabby

Gabby provides a way to interface with several chatbot providers through "adapters". Adapters interface with different services such as api.ai and Watson Conversation.
TypeScript
7
star
55

json-parse-context

✨ Add the context of a json parse error to the error message with syntax highlighting if possible.
JavaScript
6
star
56

jacos

Java/Spring based SDK to enable insert, update and upsert of files and records in the SalesForce in Bulk, Single Record and Multi Record Mode
Java
6
star
57

react-iterative-flow

JavaScript
6
star
58

one-app-dev-proxy

✨ Proxy requests to remote servers locally while also allowing for an express middleware to be provided and applied to all requests
JavaScript
6
star
59

easydist

An end-to-end distributed deep learning tool that mimics the single-machine keras programming model
Python
6
star
60

findxcprojorphan

Finds source files unreferenced in Xcode project
Ruby
5
star
61

SPAN

A stored procedures framework
Java
5
star
62

jakasu

Powerful config driven SDK to easily consume events from one or multiple Kafka topics in both standard and streaming modes
Java
5
star
63

iguazu-rpc

✨ Iguazu RPC is a plugin for the Iguazu ecosystem that allows for configurable async calls and caching strategies.
JavaScript
5
star
64

fabric-integration

Project born out of a need to have a "stable" interface to the Fabric node SDK across various versions.
TypeScript
5
star
65

mlflow-server-proxy

Jupyter server proxy extension for mlflow tracking server
Python
4
star
66

bloom

BLooM is a configuration driven bigdata framework to load massive data into MemSQL
Java
4
star
67

suwannee

RESTful API to enable smart contract interaction from any language or platform
TypeScript
4
star
68

create-using-template

JavaScript
4
star
69

un-locode-java

Java
4
star
70

dydaq

DyDaQ framework connects GraphQL service layer with database efficiently
Java
4
star
71

omnitransform

Declarative and config driven Big Data/ETL framework based on Apache Spark
Java
3
star
72

rate-limiting-scheduled-executor

Java
3
star
73

jakapu

Config driven SDK to publish events into any Kafka topic without writing code
Java
3
star
74

yelp-search

Programmatically search Yelp for businesses using the public version 2.0 of the Yelp Search API
Swift
3
star
75

hide

Config Driven Big Data component which can generate data extracts in various formats from any Hive Tables
Shell
3
star
76

connectchain

Python
2
star
77

chaincode-guide

1
star