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

@cardos/service-bus-portal

v1.0.13

Published

A modular, composable cross-context communication system for Web Workers, iframes, Shared Workers, and Service Workers

Downloads

18

Readme

@cardos/service-bus-portal

A modular, composable cross-context communication system for Web Workers, iframes, Shared Workers, and Service Workers.

Features

  • 🔄 Cross-Context Communication: Seamless communication between different JavaScript execution contexts
  • 🏗️ Modular Architecture: Clean separation of concerns with type-safe interfaces
  • 🎯 Multiple Portal Types: Support for PostMessage, EventTarget, and custom communication channels
  • 🔧 Service Bus Integration: Easy integration with existing service bus patterns
  • 📦 TypeScript First: Full TypeScript support with comprehensive type definitions
  • 🚀 Lightweight: Minimal bundle size with zero dependencies
  • 🧪 Testable: Each component can be tested independently

Installation

npm install @cardos/service-bus-portal

Quick Start

Basic Usage

import { PortalFactory, PortalServiceBusProxy } from '@cardos/service-bus-portal';

// Create a portal for Web Worker communication
const portal = PortalFactory.createWorkerPortal(worker);

// Create a proxy for remote service calls
const proxy = new PortalServiceBusProxy(portal);
await proxy.connect();

// Create a typed proxy
const serviceProxy = proxy.createProxy() as MyServices;

// Use the proxy
const result = await serviceProxy['math.add'](5, 3);

Multi-Portal Composition

import { PortalComposer } from '@cardos/service-bus-portal';

const composer = new PortalComposer();

// Add multiple portals
composer.addPortal(workerPortal);
composer.addPortal(iframePortal);

// Create connectors for each portal
composer.createConnector(workerPortal.id, serviceBus);
composer.createConnector(iframePortal.id, serviceBus);

// Connect all portals
await composer.connectAll();

Portal Types

PostMessage Portal

For communication between different windows, workers, or iframes:

const portal = PortalFactory.createPostMessagePortal(
  'my-portal',
  'window-to-worker',
  worker,
  { timeoutMs: 5000 }
);

EventTarget Portal

For communication within the same context using custom events:

const portal = PortalFactory.createEventTargetPortal(
  'event-portal',
  'window-to-window',
  document,
  'my-channel'
);

Worker Portal

Convenient factory for Web Worker communication:

const portal = PortalFactory.createWorkerPortal(worker);

Iframe Portal

Convenient factory for iframe communication:

const portal = PortalFactory.createIframePortal(iframe);

Service Bus Integration

Creating a Connector

Expose services through a portal:

import { PortalServiceBusConnector } from '@cardos/service-bus-portal';

const connector = new PortalServiceBusConnector(portal, serviceBus);
await connector.connect();

### Creating a Proxy

Create a proxy for remote service calls:

```typescript
import { PortalServiceBusProxy } from '@cardos/service-bus-portal';

const proxy = new PortalServiceBusProxy(portal);
await proxy.connect();

const serviceProxy = proxy.createProxy() as MyServices;

## Advanced Configuration

### Portal Configuration

```typescript
const config = {
  timeoutMs: 15000,
  retryAttempts: 3,
  security: {
    allowedOrigins: ['https://myapp.com'],
    requireAuthentication: true
  },
  metadata: {
    version: '1.0.0',
    environment: 'production'
  }
};

const portal = PortalFactory.createPostMessagePortal(
  'secure-portal',
  'window-to-worker',
  worker,
  config
);

Error Handling and Retries

const robustProxy = new Proxy(serviceProxy, {
  get(target, prop) {
    const originalMethod = target[prop as keyof typeof target];
    
    if (typeof originalMethod === 'function') {
      return async (...args: unknown[]) => {
        let lastError: Error;
        
        for (let attempt = 1; attempt <= 3; attempt++) {
          try {
            return await (originalMethod as any)(...args);
          } catch (error) {
            lastError = error as Error;
            console.warn(`Service call failed (attempt ${attempt}/3):`, error);
            
            if (attempt < 3) {
              await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
            }
          }
        }
        
        throw lastError!;
      };
    }
    
    return originalMethod;
  }
});

Type Safety

Defining Service Types

interface MainThreadServices {
  'math.add': (a: number, b: number) => Promise<number>;
  'math.multiply': (a: number, b: number) => Promise<number>;
  'storage.getItem': (key: string) => Promise<string | null>;
  'storage.setItem': (key: string, value: string) => Promise<boolean>;
}

const serviceProxy = proxy.createProxy() as MainThreadServices;

API Reference

PortalFactory

createPostMessagePortal(id, type, target, config?)

Creates a PostMessage-based portal.

createEventTargetPortal(id, type, eventTarget, channel, config?)

Creates an EventTarget-based portal.

createWorkerPortal(worker, config?)

Creates a portal for Web Worker communication.

createIframePortal(iframe, config?)

Creates a portal for iframe communication.

PortalServiceBusProxy

constructor(portal)

Creates a new proxy instance.

connect()

Connects the portal.

disconnect()

Disconnects the portal and cleans up pending requests.

createProxy()

Creates a proxy object for remote service calls.

PortalComposer

addPortal(portal)

Adds a portal to the composer.

removePortal(portalId)

Removes a portal from the composer.

createConnector(portalId, serviceBus)

Creates a service bus connector for a portal.

createProxy(portalId)

Creates a service bus proxy for a portal.

connectAll()

Connects all portals.

disconnectAll()

Disconnects all portals.

Examples

For comprehensive examples demonstrating Web Worker, iframe, and multi-portal communication, see the examples directory.

Quick Examples

Web Worker Communication:

import { PortalFactory, PortalServiceBusProxy } from '@cardos/service-bus-portal';

// Create worker portal
const worker = new Worker('/worker.js');
const portal = PortalFactory.createWorkerPortal(worker);
const proxy = new PortalServiceBusProxy(portal);
await proxy.connect();

// Use worker services
const services = proxy.createProxy() as WorkerServices;
const result = await services['math.add'](5, 3);

Iframe Communication:

import { PortalFactory, PortalServiceBusProxy } from '@cardos/service-bus-portal';

// Create iframe portal
const iframe = document.createElement('iframe');
iframe.src = '/iframe-page.html';
const portal = PortalFactory.createIframePortal(iframe);
const proxy = new PortalServiceBusProxy(portal);
await proxy.connect();

// Use iframe services
const services = proxy.createProxy() as IframeServices;
const html = await services['ui.render']('button', { text: 'Click me' });

Multi-Portal Composition:

import { PortalComposer } from '@cardos/service-bus-portal';

const composer = new PortalComposer();
composer.addPortal(workerPortal);
composer.addPortal(iframePortal);
await composer.connectAll();

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

License

MIT License - see LICENSE for details.