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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@bringg/dashboard-sdk-pre

v0.2.16

Published

Bringg dashboard SDK

Readme

codecov

BRINGG DASHBOARD SDK

Examples:

Web ( >= ES5 )

<!doctype html>
<html lang="en">
<head>
  <!-- ... -->
  <script src="/bringg-dashboard-sdk.js"></script>
</head>
<body>
<!-- ... -->
<script>
BringgDashboardSDK.initWithEmail(email, password).then(bringgDashboardSDK => {
  bringgDashboardSDK.merchant.get().then(console.log).catch(console.error);
  bringgDashboardSDK.merchantConfiguration.get().then(console.log).catch(console.error);
});

BringgDashboardSDK.initWithAuthToken(region, authToken).then(bringgDashboardSDK => {
  bringgDashboardSDK.merchant.get().then(console.log).catch(console.error);
  bringgDashboardSDK.merchantConfiguration.get().then(console.log).catch(console.error);
});
</script>
</body>
</html>

Node.js ( >= ES5 )

const BringgDashboardSDK = require("bringg-dashboard-sdk");

BringgDashboardSDK.initWithEmail(email, password).then(bringgDashboardSDK => {
  bringgDashboardSDK.merchant.get().then(console.log).catch(console.error);
  bringgDashboardSDK.merchantConfiguration.get().then(console.log).catch(console.error);
});

BringgDashboardSDK.initWithAuthToken(region, authToken).then(bringgDashboardSDK => {
  bringgDashboardSDK.merchant.get().then(console.log).catch(console.error);
  bringgDashboardSDK.merchantConfiguration.get().then(console.log).catch(console.error);
});

TypeScript ( >= 2.6 )

import BringgDashboardSDK = require("bringg-dashboard-sdk");

async function runAwait() {
  try {
    const bringgDashboardSDK = await BringgDashboardSDK.initWithEmail(email, password);
    console.log(await bringgDashboardSDK.merchant.get());
    console.log(await bringgDashboardSDK.merchantConfiguration.get());
  } catch (e) {
    console.error(e);
  }

  try {
    const bringgDashboardSDK = await BringgDashboardSDK.initWithAuthToken(region, authToken);
    console.log(await bringgDashboardSDK.merchant.get());
    console.log(await bringgDashboardSDK.merchantConfiguration.get());
  } catch (e) {
    console.error(e);
  }
}

runAwait();

Running tests

yarn test

Running test in watch mode

yarn jest

Linting your code with tsLint

yarn lint

Fixing your code with prettier

yarn prettier

Linting your code and fixing it with one command(will run lint and prettier)

yarn fix

Compile your awesome code for production

yarn prod

DashboardSDK - Guidelines to writing new entities - 10/4/19

Each entity should have 3 parts - Public API, Entity Store, Http Service.

Previous Status

For example we want to expose VehicleType to our end users, we go to the sdk and first add Actions folder.

export enum VehicleTypesActionTypes {
  GET_VEHICLE_TYPES = 'GET_VEHICLE_TYPES',
  MARK_VEHICLE_TYPES_FETCHED = 'MARK_VEHICLE_TYPES_FETCHED',
  SAVE_REQUEST_ERROR = 'SAVE_REQUEST_ERROR',
}

export const Routes = {
  GET_VEHICLE_TYPES: new Route('/vehicle_types', HttpMethod.GET),
};

export function storeVehicleTypesAction(vehicleTypes: VehicleType[]): Actions<VehicleTypesActionTypes> {
  return {
    type: VehicleTypesActionTypes.GET_VEHICLE_TYPES,
    payload: vehicleTypes,
  };
}

export function markVehicleTypesFetchedAction(isFetched: boolean): Actions<VehicleTypesActionTypes> {
  return {
    type: VehicleTypesActionTypes.MARK_VEHICLE_TYPES_FETCHED,
    payload: isFetched,
  };
}

export function saveRequestErrorAction(requestType: VehicleTypesRequests, error: Error): Actions<VehicleTypesActionTypes> {
  return {
    type: VehicleTypesActionTypes.SAVE_REQUEST_ERROR,
    payload: {
      requestType,
      error,
    },
  };
}

export const vehicleTypessExtractor = (response: VehicleTypesResponse) => response.vehicle_types;

export const getVehicleTypesRequestAction = (sessionService: SessionBasedService): any => async (dispatch): Promise<Actions<VehicleTypesActionTypes>> => {
  {
    try {
      const vehicleTypes: VehicleType[] = await sessionService.handleAuthorizedRequest<VehicleTypesResponse, VehicleType[]>(
        Routes.GET_VEHICLE_TYPES,
        vehicleTypessExtractor,
        BringgException.serviceException('failed to get vehicles'),
      );

      dispatch(markVehicleTypesFetchedAction(true));

      return await dispatch(storeVehicleTypesAction(vehicleTypes));
    } catch (e) {
      await dispatch(saveRequestErrorAction(VehicleTypesRequests.GET_VEHICLE_TYPES, e));
      throw e;
    }
  }
};

We continue to next folder Reducers.

export const initState = fromJS({
  items: {},
  requests: {},
  fetched: false,
});

type requestErrorLog = requestErrors<VehicleTypesRequests>;

export type vehicleTypesState = ImmutableMap<{
  items: Map<number, VehicleType>;
  requests: ImmutableMap<requestErrorLog>;
  fetched: boolean;
}>;

export const storeVehicleTypes = (state: vehicleTypesState, vehicleTypes: VehicleType[]): vehicleTypesState =>
  state.set('items', immutableKeyBy(vehicleTypes, 'id'));

export const markVehicleTypesFetched = (state: vehicleTypesState, isFetched: boolean = true) => state.setIn(['fetched'], isFetched);

export const logRequestError = (state, requestType: VehicleTypesRequests, error: Error) => {
  return state.withMutations(state =>
    state.setIn(['requests', requestType, 'error'], error.toString()).setIn(['requests', requestType, 'timestamp'], Date.now()),
  );
};

export const vehicleTypesReducers = (state: vehicleTypesState = initState, action): vehicleTypesState => {
  switch (action.type) {
    case VehicleTypesActionTypes.SAVE_REQUEST_ERROR:
      return logRequestError(state, action.payload.requestType, action.payload.error);
    case VehicleTypesActionTypes.GET_VEHICLE_TYPES:
      return storeVehicleTypes(state, action.payload);
    case VehicleTypesActionTypes.MARK_VEHICLE_TYPES_FETCHED:
      return markVehicleTypesFetched(state, action.payload);
    default:
      return state;
  }
};

Then we go on and add a Service folder.

export default class VehicleTypesService extends SessionBasedService {
  private store: Redux.Store<CompleteStateStructure>;

  constructor(session: Session) {
    super(session.config.getApiEndpoint(), session);
    this.store = session.state.store;
  }

  @singleConcurrent()
  public async getAll(): Promise<VehicleType[]> {
    if (!this.areVehicleTypesFetched()) {
      await this.store.dispatch(getVehicleTypesRequestAction(this));
    }

    return this.getAllVehicleTypes();
  }

  private getAllVehicleTypes = (): VehicleType[] => {
    return this.store
      .getState()
      .vehicleTypes.getIn(['items'])
      .toList()
      .toJS();
  };

  private areVehicleTypesFetched = (): boolean => {
    return this.store.getState().vehicleTypes.getIn(['fetched']);
  };
}

Then we finally can expose our API folder :)

export default class VehicleTypes {
  private vehicleTypesService: VehicleTypesService;

  constructor(session: Session) {
    this.vehicleTypesService = new VehicleTypesService(session);
  }

  public async getAll(): Promise<VehicleType[]> {
    return await this.vehicleTypesService.getAll();
  }
}

Almost 200 hundred lines of code just to expose simply getAll of VehicleTypes.

We tried to simplify the proccess by creating BaseStore and using it in each new entity store instead of rewriting it each time.

Entity Store

We want to keep each entity state up to date always(http requests, realtime events), so we use store managment class to do it.

From now on we can use a new class named BaseStore which will be our base of every entity and manage its state.

For Example:

export default class ChatConversationStore extends BaseStore<ChatConversation>

Here we can extend our BaseStore and use it however we see fit to the new entity we develop(take from store if exists, if not fetch from server and store it).

  async getConversation(id: number): Promise<ChatConversation> {
    const chatConversation = this.getItem(id) || this._fetchConversation(id);

    return await chatConversation;
  }

Http Service

Http service is pretty much the same all over the sdk, here is simple example.

  GET_CHAT_CONVERSATION: new Route('/chat_conversations/{:id}', HttpMethod.GET)

  public async getChatConversation(id): Promise<ChatConversation> {
    const chatConversationResponse:  ChatConversationResponse = await this.handleAuthorizedRequest<ChatConversationResponse, ChatConversationResponse>(
      Routes.GET_CHAT_CONVERSATION, //route
      defaultExtractor, // extractor func can be passed here
      BringgException.serviceException('Failed to get chat conversation'),
      undefined, //payload
      { id }, //route params
      {}, // query params
    );

    return chatConversationResponse.conversation;
  }

Public API

Here we decide which endpoints and events we want to expose to the end user, which will be called from the entity store.

Example from ChatConversation

this.onItemRemoved = this.chatConversationStore.onItemRemoved; // remove event

public getConversation(id: number): Promise<ChatConversation> {
    return this.chatConversationStore.getConversation(id); // get item endpoint
}

BaseStore

Here we implemented RxJS,

we have our main stream of items $items which on each action(create,update,remove) we emit to the stream and accordingly aggregate the most update state.

Each store extends this class can use $items stream to aggregate which data he wants.(for example from tasks stream aggreate only open tasks.. )

  state$: Observable<Map<number, T>>; // aggregated state from main stream
  protected items$: Subject<Action>; // 1 main stream of items

  // Event Handlers
  protected onItemUpdateEvent: (item: T) => void = _.noop;
  protected onItemCreatedEvent: (item: T) => void = _.noop;
  protected onItemRemovedEvent: (item: number) => void = _.noop;
  protected onListUpdateEvent: (items: T[]) => void = _.noop;

  getItem = (itemId): T // Get Item From Store By Id

  addToStore(item: T) // Add item to store

  updateInStore(item: T) // update item in store

  getItems = (): T[] // get array of items of latest state in store

  addItems(items: T[]) // add array of items

  onItemCreated = (fn: (item: T) => void) => // set event handler for item removed

  onItemUpdate = (fn: (item: T) => void) => // set event handler for item updated

  onItemRemoved = (fn: (itemId: number) => void) // set event handler for item removed

  onListUpdate = (fn: (item: T[]) => void) // set event handler for list update

Entities Generator

In order to save time and make your life easier, there is a script to generate the basic implementation needed.

You can run it with : npm run entity-generator [name] [bringg-type-name]

The script will create a folder called [name] inside src folder.

The folder will include Service, Store and a few more files with basic implementation and according to our convention.

Next Steps:

In order to improve our SDK and our developing proccess.

  • Combine Store and Service to one.(instead of copy pasting same service all the time)