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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bloomreach/navapp-communication

v3.3.5

Published

<!-- Copyright 2021-2026 Bloomreach

Readme

Navapp Communication

@bloomreach/navapp-communication is the library the Bloomreach navigation application (navapp) and the applications it hosts use to talk to each other.

The navapp loads every application in its own iframe, possibly from another origin. This library sets up a typed, promise-based API across the iframe boundary in both directions:

  • the parent (navapp) exposes a ParentApi that applications call, e.g. to update the browser URL, show a mask or close a popup;
  • each child (an application in an iframe) exposes a ChildApi that the navapp calls, e.g. to navigate, collect navigation items or log out.

Under the hood it uses Penpal (v4) for the postMessage handshake and method calls.

┌──────────────────────── navapp (parent) ────────────────────────┐
│  connectToChild({ iframe, methods: ParentApi }) → ChildApi       │
│                                                                  │
│   ┌──── iframe: CMS ─────┐        ┌──── iframe: popup app ────┐  │
│   │ connectToParent({    │        │ connectToParent({         │  │
│   │   methods: ChildApi  │        │   methods: ChildApi       │  │
│   │ }) → ParentApi       │        │ }) → ParentApi            │  │
│   └──────────────────────┘        └───────────────────────────┘  │
└──────────────────────────────────────────────────────────────────┘

Children never talk to each other directly. When one application needs something from another (for example a popup asking the CMS to open a document), it calls a ParentApi method and the navapp forwards the call to the right child.

Who uses it

| Consumer | Role | |---|---| | community/navigation-application | Parent: implements ParentApi in ConnectionService | | CMS (Wicket) | Child: loads the UMD bundle and implements ChildApi in navapp-bridge.js | | community/channel-manager/ui | Child | | community/cms/frontend | Child | | enterprise/wpm/frontend/project-management | Child | | enterprise/ai-service/client/assistant-angular | Child (popup) |

Each consumer pins its own version in its package.json, so they don't all use the same release.

Usage

Install the library together with its peer dependency:

npm install @bloomreach/navapp-communication penpal@^4

In a child application

Connect to the parent once, when the application starts, and keep the returned ParentApi:

import { ChildApi, connectToParent, ParentApi } from '@bloomreach/navapp-communication';

const childApi: ChildApi = {
  getConfig: async () => ({ apiVersion: '3.3.0' }),
  navigate: async (location, triggeredBy) => router.navigate(location.path),
  beforeNavigation: async () => !hasUnsavedChanges(),
};

const parentApi: ParentApi = await connectToParent({
  parentOrigin: window.location.origin, // must match the navapp origin, or the connection is refused
  methods: childApi,
});

const { userSettings } = await parentApi.getConfig();
await parentApi.updateNavLocation({ path: 'documents/123', breadcrumbLabel: 'My document' });

All ChildApi methods are optional. Implement only the ones your application supports.

In the parent (navapp)

import { connectToChild, ParentApi } from '@bloomreach/navapp-communication';

const childApi = await connectToChild({
  iframe,                         // the iframe element hosting the child
  methods: parentApi,             // the ParentApi implementation
  connectionTimeout: 30000,       // ms to wait for the handshake
  methodInvocationTimeout: 30000, // ms to wait for each child method call
});

const navItems = await childApi.getNavItems?.();

Without a bundler

The library is also published as a UMD bundle (dist/index.umd.js) that registers the global window.brNavappCommunication. It expects Penpal to be loaded first as the global Penpal. This is how the CMS uses it.

Behavior to know about

  • Optional methods are called with optional chaining. A connected app only exposes the methods it implements, and an older app may not know a newer method, so call them as api.someMethod?.().
  • Method timeouts. connectToChild wraps every child method so it rejects with "<method> call timed out" after methodInvocationTimeout ms, or 5 minutes if you don't set one. beforeNavigation is never wrapped, because it may wait for the user to answer a dialog. Pass 0 or a negative value to turn the timeouts off.
  • Handshake retries. Penpal v4 sends its handshake only once, so a child that loads before the parent is listening would never connect. connectToParent re-sends the handshake every second until the parent replies.
  • Version check. getVersion() returns the library version. The navapp reports it as ParentConfig.apiVersion, and children report the version they implement as ChildConfig.apiVersion.

Adding a method to the API

A new capability usually touches the library, the navapp and at least one child:

  1. Add the method to ParentApi and/or ChildApi in src/lib/api.ts, with a doc comment. Make new methods optional (myMethod?: ...), so apps built against an older version still compile and run. Export any new types from the same file.
  2. Implement it in the navapp's ConnectionService (getParentApiMethods) and add a spec.
  3. Implement or call it in the child applications that need it, using optional chaining.
  4. Bump the library version (minor for new optional methods), publish it (see Releasing), and update the dependency in every consumer that uses the new types.

TypeScript consumers only see the new types after step 4. Until then their builds fail with errors like Property 'myMethod' does not exist on type 'ParentApi'. To try changes before releasing, build the library and copy dist/* into the consumer's node_modules/@bloomreach/navapp-communication/dist/. The next npm ci reverts it.

The CMS bridge (navapp-bridge.js) is plain JavaScript and Penpal matches methods by name, so it doesn't need a new library version.

Development

The toolchain for this library is older than the Angular applications' (see the repository CLAUDE.md for the expected Node and npm versions).

npm ci                  # install dependencies
npm run build           # build dist/ (UMD, ES module and type definitions) with rollup
npm start               # rebuild on every change
npm run test:single-run # run the unit tests once
npm test                # run the tests in watch mode, with coverage
npm run lint            # lint src/
npm run docs            # generate the API docs with TypeDoc

npm run build prints a series of (!) Plugin typescript warnings about node_modules/@types/node and undici-types. They come from the TypeScript version used here being too old to parse recent Node type definitions that the test tooling brings in. They are harmless: the build ends with created dist/index.js and created dist/index.d.ts.

Releasing

There is no CI job that publishes this library. A release is done by hand:

  1. Bump version in package.json (and package-lock.json).
  2. Run the tests, then npm publish from this directory. prepack builds dist/ first. Publishing needs write access to the @bloomreach npm scope.
  3. Update the version in the consumers that need the release, and refresh their lockfiles.