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

localsync

v2.0.6

Published

a lightweight module to sync JS objects in realtime across tabs / windows of a browser.

Downloads

16,974

Readme

NPM

a lightweight module to sync JS objects in realtime across tabs / windows of a browser.

See this blog post for detailed information regarding the issues localsync solves.

Features

  • Uses local storage event emitters to sync objects in realtime across tabs.
  • Never calls the tab that the event occurred on.
  • Falls back to cookie polling internally if using an unsupported browser (IE 9+ / Edge).
  • Isomorphic.
  • Tested with Jest.
  • Written with TypeScript.

Build Status

NPM

Install

yarn add localsync

OR

npm install localsync


Version 2

How to use

import { localsync } from "localsync";

/** Create a publisher that optionally transforms some data to a payload to be transmitted to other tabs. */
const publisher = (userID, firstName, lastName) => ({
  userID,
  firstName,
  lastName
});

/** Create a subscriber that will receive published payloads on all tabs that did not trigger the sync. */
const subscriber = (current, previous, url) => {
  console.info(
    `Another tab at url ${url} switched user from "${previous.firstName} ${previous.lastName}" to "${current.firstName} ${current.lastName}".`
  );
  // do something with `current.userID`
};

/**
 * Create a synchronizer channel.
 *
 * @remarks
 * `localsync` supports N number of synchronizers for different things across your app.
 * The key 'user' defines a localsync synchronization channel.
 */
const createUserSync = localsync({ channel: "user" });

/**
 * Create a controller for the synchronizer.
 *
 * @remarks
 * To create the controller, you must pass the publisher and the subscriber.
 */
const userController = createUserSync(publisher, subscriber);

/**
 * Start synchronizing.
 * Passing true tells localsync to poll the current storage mechanism once on
 * start for any pre-existing state that may be there (cross session).
 * Defaults to false - may change to true in a future major version.
 */
userController.start(true);

/**
 * IE / Edge do not support local storage across multiple tabs.
 * localsync will automatically fallback to a cookie polling mechanism here. You don't need to do anything else.
 */
if (userController.isFallback) {
  console.warn(
    "browser doesnt support local storage synchronization, falling back to cookie synchronization."
  );
}

/**
 * `isServer` can be used to detect if the current code is running in a server environment (for SSR).
 */
if (userController.isServer) {
  console.debug("Detected a SSR environment.");
}

/** Trigger an action that will get handled on other tabs. */
userController.trigger(1, "jimmy", "john");

/** Trigger an action that will get handled on other tabs. */
userController.trigger(1, "jimmy", "john");

console.info(
  userController.mechanism
); /** => 'storagesync' on chrome, 'cookiesync' on IE */

setTimeout(() => {
  /** Trigger another action in 5 seconds. */
  userController.trigger(2, "jane", "wonka");
}, 5000);

setTimeout(() => {
  /** If its still running, stop syncing in 10 seconds. */
  if (userController.isRunning) {
    userController.stop();
  }
}, 10000);

API

const createSync = localsync({ channel: string, level?: LogLevel, fallback?: FallbackOptions })

const sync = createSync((publisher: (...args) => TMessage, subscriber: (message: TMessage) => void);

const { start, stop, trigger, isRunning, isFallback } = sync;

Input

| name | type | default | description | | ---------- | -------- | ----------- | ------------------------------------------------------------------------ | | channel | string | required | a string that is used for this synchronization instance. | | level | string | 'INFO' | the log level to use when tracing (ERROR, WARN, INFO, DEBUG) | | fallback | object | see below | optional fallback options if you need more control over cookie fallback. |

FallbackOptions

| name | type | default | description | | --------------- | --------- | ----------- | ------------------------------------------------------------------ | | pollFrequency | number | 3000 | The number in milliseconds that should be used for cookie polling | | path | string | '/' | The path to use for cookies | | secure | boolean | false | Whether to set the secure flag on cookies or not (not recommended) | | httpOnly | boolean | false | Whether to set the http only flag on cookies or not |

Output

Interface of localsync returned controller

| name | type | defaults | description | | ------------ | ---------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | start | function | N/A | Call to start syncing. Accepts one boolean parameter (default false). If passed true, will run the synchronization on start. | | stop | function | N/A | Call to stop syncing | | trigger | function | N/A | Call to trigger a sync to occur to all other clients | | mechanism | string | (storage|cookie|server)sync | The underlying mechanism that was selected for synchronization | | isRunning | boolean | false | Is synchronization currently enabled | | isFallback | boolean | false | Is the selected mechanism a fallback strategy | | isServer | boolean | false | Is the current client running in a server environment |

Structure and Roadmap

localsync has a singular purpose: to synchronize events from one client to many using a common interface and the least invasive mechanism for the current browsing medium.

Internally, localsync is comprised of several small sync packages that all adhere to the common localsync interface. The main localsync package does no actual synchronization on its own but rather determines the most appropriate synchronization strategy and calls upon the necessary packages to invoke it. All the packages with brief descriptions are listed here:

Guaranteed synchronization between clients of the same browser (Chrome :left_right_arrow: Chrome, IE :left_right_arrow: IE, etc.)

  • localsync - Determines synchronization mechanism and invokes it.

Mechanism packages


Version 1 API

const sync = localsync(key: string, action: (...args) => payload, handler: payload => {}, [opts: Object])

const { start, stop, trigger, isRunning, isFallback } = sync

Input

key: a string that is used for this synchronization instance (you may have multiple instances of localsync each with different keys to sync different types of data).

action: a function that will be called when this client's trigger function is invoked. The action will be passed any arguments provided to the trigger function and should return the payload to be delivered to other clients for the given localsync key.

handler: a function that will be invoked on this client when any other client's trigger function is invoked. NOTE: This handler will NEVER be called due to this clients trigger function being called, only other clients.

opts: An optional object argument that may be specified to control how localsync operates. Supported values are shown below.

| name | type | default | description | | --------------- | --------- | ----------- | ---------------------------------------------------------------------------------------------- | | tracing | boolean | false | toggles tracing for debugging purposes | | logger | Object | console | the logger object to trace to | | loglevel | string | 'info' | the log level to use when tracing (error, warn, info, trace) | | pollFrequency | number | 3000 | fallback: cookiesync the number in milliseconds that should be used for cookie polling | | idLength | number | 8 | fallback: cookiesync the number of characters to use for tracking the current instance (tab) | | path | string | '/' | fallback: cookiesync The path to use for cookies | | secure | boolean | false | fallback: cookiesync Whether to set the secure flag on cookies or not (not recommended) | | httpOnly | boolean | false | fallback: cookiesync Whether to set the http only flag on cookies or not |


Contributing

To setup localsync for use in development run the following steps at CLI:

git clone https://github.com/noderaider/localsync
cd localsync
yarn
yarn build

Then from your project:

npm link ../localsync/packages/localsync
# start your project, localsync should hot reload as you update its source code.

Feature / bug fixes via pull requests encouraged!