@aspectly/transports

中文文档
2.2.0发布于 2026/09/06MITTypeScriptESM + CJS零依赖构建来源已验证近 30 天下载 5799

Transport layer for Aspectly bridge - platform detection and message passing

原始使用文档
文档目录31 节
  1. Installation
  2. Overview
  3. Built-in Transports
  4. Auto-Detection
  5. Quick Start
  6. Auto-Detection (Recommended)
  7. Direct Transport Usage
  8. Custom Transport Registration
  9. API Reference
  10. Transport Interface
  11. Types
  12. TransportDetector Interface
  13. BaseTransport Class
  14. TransportRegistry
  15. Convenience Functions
  16. Built-in Transports
  17. CefSharpTransport
  18. WebKitTransport
  19. ReactNativeTransport
  20. AndroidTransport
  21. FlutterTransport
  22. IframeTransport
  23. WindowTransport
  24. PostMessageTransport
  25. NullTransport
  26. Subpath Entry Points
  27. Creating Custom Transports
  28. Example: Electron Transport
  29. Implementation Checklist
  30. Related Packages
  31. License

@aspectly/transports

npm version npm downloads

Transport layer for cross-platform communication between WebViews, iframes, and web applications.

Installation

# npm
npm install @aspectly/transports

# pnpm
pnpm add @aspectly/transports

# yarn
yarn add @aspectly/transports

Overview

@aspectly/transports provides a flexible abstraction layer for platform detection and message passing across different execution contexts. It automatically detects the current environment (CefSharp, WKWebView/WebKitGTK, React Native WebView, Android WebView, Flutter WebView, iframe, or browser window) and provides a unified API for bidirectional communication.

Built-in Transports

TransportDetectionPriorityUse Case
CefSharpTransportwindow.CefSharp.PostMessage100Desktop apps with CefSharp (Chromium Embedded Framework for .NET)
WebKitTransportwindow.webkit.messageHandlers.aspectly95iOS/macOS/visionOS WKWebView and Linux WebKitGTK
ReactNativeTransportwindow.ReactNativeWebView.postMessage90React Native WebView
AndroidTransportwindow.AspectlyAndroid.postMessage85Android WebView
FlutterTransportwindow.AspectlyFlutter.postMessage84Flutter webview_flutter
IframeTransportwindow.parent !== window80Web content inside iframes
WindowTransportwindow.opener !== null70Popup windows opened via window.open
PostMessageTransportAlways available (generic)10Generic window.postMessage fallback
NullTransportAlways availablefallbackFallback for SSR/testing (no-op)

Auto-Detection

The TransportRegistry automatically selects the appropriate transport based on priority order. Higher priority transports are checked first, ensuring the most specific transport is used:

cefsharp (100) > webkit (95) > react-native (90) > android (85) >
flutter (84) > iframe (80) > window (70) > postmessage (10) > null (fallback)

Quick Start

import { detectTransport } from '@aspectly/transports';

// Automatically detect the current environment
const transport = detectTransport();
// transport.name is one of: 'cefsharp', 'webkit', 'react-native', 'android',
// 'flutter', 'iframe', 'window', 'postmessage', or 'null'
console.log(`Using transport: ${transport.name}`);

// Send a message
transport.send(JSON.stringify({ type: 'hello', data: 'world' }));

// Subscribe to incoming messages
const unsubscribe = transport.subscribe((message) => {
  const data = JSON.parse(message);
  console.log('Received:', data);
});

// Cleanup when done
unsubscribe();

Direct Transport Usage

import { CefSharpTransport } from '@aspectly/transports';

const transport = new CefSharpTransport();

if (transport.isAvailable()) {
  transport.send(JSON.stringify({ method: 'getData' }));
}

Custom Transport Registration

import { registerTransport, detectTransport } from '@aspectly/transports';

// Register a custom transport with high priority
registerTransport({
  name: 'electron',
  priority: 150, // Higher than CefSharp (100)
  detect: () => {
    return typeof window !== 'undefined' &&
           window.electron?.send !== undefined;
  },
  createTransport: () => new ElectronTransport(),
});

// Now auto-detection will check your custom transport first
const transport = detectTransport();

API Reference

Transport Interface

The core interface implemented by all transports:

interface Transport {
  readonly name: string;
  isAvailable(): boolean;
  send(message: string): void;
  subscribe(listener: TransportListener): TransportUnsubscribe;
}

Properties:

  • name - Unique identifier for the transport (e.g., 'cefsharp', 'react-native')

Methods:

  • isAvailable() - Check if the transport is available in the current environment
  • send(message: string) - Send a message to the parent/host context
  • subscribe(listener) - Subscribe to incoming messages, returns cleanup function

Types

// Message listener callback
type TransportListener = (message: string) => void;

// Cleanup function returned by subscribe
type TransportUnsubscribe = () => void;

// Factory function for creating transports
type TransportFactory = () => Transport;

TransportDetector Interface

Used for registering custom transports:

interface TransportDetector {
  readonly name: string;
  readonly priority: number;
  detect(): boolean;
  createTransport(): Transport;
}

Properties:

  • name - Transport identifier
  • priority - Detection priority (higher values checked first)

Methods:

  • detect() - Return true if this transport is available
  • createTransport() - Create and return a transport instance

BaseTransport Class

Abstract base class providing common functionality:

abstract class BaseTransport implements Transport {
  abstract readonly name: string;
  abstract isAvailable(): boolean;
  abstract send(message: string): void;
  abstract subscribe(listener: TransportListener): TransportUnsubscribe;

  protected hasWindow(): boolean;
  protected getWindow(): Window | null;
}

Protected Helpers:

  • hasWindow() - Check if window is defined (SSR-safe)
  • getWindow() - Safely get the window object or null

TransportRegistry

Global registry for managing transport detectors:

class TransportRegistry {
  register(detector: TransportDetector): void;
  unregister(name: string): void;
  getDetectors(): readonly TransportDetector[];
  detect(forceRedetect?: boolean): Transport;
  clearCache(): void;
  reset(): void;
}

Methods:

  • register(detector) - Register a custom transport detector
  • unregister(name) - Remove a detector by name
  • getDetectors() - Get all registered detectors
  • detect(forceRedetect?) - Detect and return the appropriate transport (cached)
  • clearCache() - Clear the cached transport
  • reset() - Reset to default state (built-in detectors only)

Convenience Functions

// Detect the current transport
function detectTransport(forceRedetect?: boolean): Transport;

// Register a custom detector
function registerTransport(detector: TransportDetector): void;

Built-in Transports

CefSharpTransport

For desktop applications using CefSharp (Chromium Embedded Framework for .NET).

Detection: Checks for window.CefSharp.PostMessage Priority: 100 (highest)

import { CefSharpTransport } from '@aspectly/transports';

const transport = new CefSharpTransport();
transport.send(JSON.stringify({ action: 'openFile' }));

const unsubscribe = transport.subscribe((message) => {
  console.log('From C#:', message);
});

Messaging:

  • Sends messages via window.CefSharp.PostMessage(message)
  • Receives messages via window.postMessage events

WebKitTransport

For web content running inside an Apple WKWebView (iOS, macOS, visionOS) or a Linux WebKitGTK WebKitWebView. Both reuse the same window.webkit.messageHandlers.aspectly mechanism.

Detection: Checks for window.webkit.messageHandlers.aspectly Priority: 95

import { WebKitTransport } from '@aspectly/transports';

const transport = new WebKitTransport();
transport.send(JSON.stringify({ action: 'openFile' }));

Messaging:

  • Sends messages via window.webkit.messageHandlers.aspectly.postMessage(message)
  • Receives messages via window.postMessage events

ReactNativeTransport

For web content running inside React Native WebView.

Detection: Checks for window.ReactNativeWebView.postMessage Priority: 90

import { ReactNativeTransport } from '@aspectly/transports';

const transport = new ReactNativeTransport();
transport.send(JSON.stringify({ action: 'navigate' }));

Messaging:

  • Sends messages via window.ReactNativeWebView.postMessage(message)
  • Messages are wrapped in quotes for iOS compatibility: '${message}'
  • Receives messages via window.postMessage events

AndroidTransport

For web content running inside an Android WebView.

Detection: Checks for window.AspectlyAndroid.postMessage Priority: 85

import { AndroidTransport } from '@aspectly/transports';

const transport = new AndroidTransport();
transport.send(JSON.stringify({ action: 'navigate' }));

Messaging:

  • Sends messages via window.AspectlyAndroid.postMessage(message)
  • Receives messages via window.postMessage events

FlutterTransport

For web content running inside a Flutter webview_flutter WebViewController.

Detection: Checks for window.AspectlyFlutter.postMessage Priority: 84

import { FlutterTransport } from '@aspectly/transports';

const transport = new FlutterTransport();
transport.send(JSON.stringify({ action: 'navigate' }));

Messaging:

  • Sends messages via window.AspectlyFlutter.postMessage(message)
  • Receives messages via window.postMessage events

IframeTransport

For web content running inside an iframe.

Detection: Checks if window.parent !== window Priority: 80

import { IframeTransport } from '@aspectly/transports';

// Default: sends to any origin ('*')
const transport = new IframeTransport();

// Specify target origin for security
const secureTransport = new IframeTransport('https://parent-domain.com');

transport.send(JSON.stringify({ type: 'ready' }));

Constructor:

  • new IframeTransport(targetOrigin?: string) - Default: '*'

Messaging:

  • Sends messages via window.parent.postMessage(message, targetOrigin)
  • Receives messages via window.postMessage events

WindowTransport

For web content running inside a popup window opened via window.open.

Detection: Checks if window.opener !== null Priority: 70

import { WindowTransport } from '@aspectly/transports';

// Default: sends to any origin ('*')
const transport = new WindowTransport();

// Specify target origin for security
const secureTransport = new WindowTransport('https://opener-domain.com');

transport.send(JSON.stringify({ type: 'ready' }));

Constructor:

  • new WindowTransport(targetOrigin?: string) - Default: '*'

Messaging:

  • Sends messages via window.opener.postMessage(message, targetOrigin)
  • Receives messages via window.postMessage events

PostMessageTransport

Generic window.postMessage transport used as a last-resort fallback before NullTransport.

Detection: Always available Priority: 10 (lowest non-fallback)

import { PostMessageTransport } from '@aspectly/transports';

const transport = new PostMessageTransport();
transport.send(JSON.stringify({ type: 'ready' }));

Messaging:

  • Sends messages via window.postMessage(message, targetOrigin)
  • Receives messages via window.postMessage events

NullTransport

Fallback transport that performs no operations. Used when no other transport is available (e.g., SSR, testing).

Priority: Always available (fallback)

import { NullTransport } from '@aspectly/transports';

const transport = new NullTransport();
transport.isAvailable(); // true
transport.send('message'); // No-op (logs warning in development)
transport.subscribe(() => {}); // Returns no-op cleanup function

Behavior:

  • isAvailable() always returns true
  • send() is a no-op (logs warning in development mode)
  • subscribe() returns a no-op cleanup function

Subpath Entry Points

Each platform-specific transport is also exposed as its own subpath export, so you can import only the transport you need without pulling in the others:

Entry pointExports
@aspectly/transports/webkitWebKitTransport
@aspectly/transports/androidAndroidTransport
@aspectly/transports/flutterFlutterTransport
@aspectly/transports/cefsharpCefSharpTransport
@aspectly/transports/react-nativeReactNativeTransport
@aspectly/transports/iframeIframeTransport
@aspectly/transports/windowWindowTransport
import { WebKitTransport } from '@aspectly/transports/webkit';

const transport = new WebKitTransport();

The package root (@aspectly/transports) continues to re-export every transport along with the registry and convenience functions.

Creating Custom Transports

Example: Electron Transport

import { BaseTransport, registerTransport } from '@aspectly/transports';
import type { TransportListener, TransportUnsubscribe } from '@aspectly/transports';

// Extend BaseTransport for helper methods
class ElectronTransport extends BaseTransport {
  readonly name = 'electron';

  isAvailable(): boolean {
    const win = this.getWindow();
    return typeof win?.electron?.send === 'function';
  }

  send(message: string): void {
    const win = this.getWindow();
    if (!win?.electron?.send) {
      console.warn('[ElectronTransport] electron.send not available');
      return;
    }
    win.electron.send('message', message);
  }

  subscribe(listener: TransportListener): TransportUnsubscribe {
    const win = this.getWindow();
    if (!win?.electron?.on) {
      return () => {};
    }

    const handler = (_event: any, message: string) => {
      listener(message);
    };

    win.electron.on('message', handler);
    return () => {
      win.electron?.removeListener('message', handler);
    };
  }
}

// Register with high priority
registerTransport({
  name: 'electron',
  priority: 150,
  detect: () => {
    return typeof window !== 'undefined' &&
           window.electron?.send !== undefined;
  },
  createTransport: () => new ElectronTransport(),
});

Implementation Checklist

When creating a custom transport:

  1. ✓ Extend BaseTransport or implement Transport interface
  2. ✓ Provide unique name property
  3. ✓ Implement isAvailable() to check environment
  4. ✓ Implement send() to send messages
  5. ✓ Implement subscribe() to receive messages
  6. ✓ Return cleanup function from subscribe()
  7. ✓ Handle SSR/missing globals safely
  8. ✓ Create a TransportDetector for registration
  9. ✓ Set appropriate priority (higher = checked first)

License

MIT

版本与发布记录

@aspectly/transports 共发布 12 个版本,首次发布于 2026/03/08;过去 12 个月发布了 12 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
2.2.0latest2026/09/062 个月前
2.1.02026/06/294 个月前
2.0.152026/06/224 个月前
2.0.142026/03/177 个月前
2.0.132026/03/177 个月前
2.0.122026/03/177 个月前

关于 @aspectly/transports 的常见问题

@aspectly/transports 是什么?

Transport layer for Aspectly bridge - platform detection and message passing

如何安装 @aspectly/transports?

在项目目录运行 npm install @aspectly/transports,或使用 pnpm add / yarn add / bun add。

@aspectly/transports 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@aspectly/transports 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@aspectly/transports 可以商用吗?

@aspectly/transports 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@aspectly/transports 的下载量有多少?

根据 npm 官方下载统计,@aspectly/transports 在 2026/10/07 – 2026/11/05 这 30 天内被下载 5,799 次,日均约 193 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@aspectly/transports 还在维护吗?

最新版本 2.2.0 发布于 2026/09/06(2 个月前);至今共发布 12 个版本,其中过去 12 个月发布了 12 个;首次发布于 2026/03/08。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。