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

@bobfrankston/msgapidefs

v0.1.34

Published

TypeScript definitions for msgapi JavaScript API (msgview/msger)

Downloads

648

Readme

@bobfrankston/msgapidefs

⚠️ SECURITY: msgapi gives full native OS access (filesystem, processes, networking). Intended ONLY for trusted apps — native apps written as web pages. Do not expose to untrusted content.

⚠️ EXPERIMENTAL: APIs are experimental and subject to change.

TypeScript definitions for the msgapi JavaScript API used by msga, msger, and msgview. See the Typescript definitions in msgapidefs.ts for more info

Workspace Structure

msgx (workspace root)
├── msgapidefs    - TypeScript type definitions for window.msgapi (this package)
├── msgcommon     - Shared CLI parsing, templates, pinning utilities
├── msger         - Rust/wry webview host (Windows, Linux)
├── msgview       - Electron webview host (Windows, Linux, Mac, Pi)
├── msga          - .NET MAUI webview host (Android, Windows)
├── build         - Release build orchestration script (build/build.ts)
└── md            - Shared documentation

Installation

npm install @bobfrankston/msgapidefs

Usage

// Import to register global window.msgapi type
import '../node_modules/@bobfrankston/msgapidefs/msgapidefs.js';
// Note: '../node_modules/@bobfrankston/msgapidefs/index.js' may also work via package.json exports

// Or import types explicitly
import type { MsgAPI, MsgResult } from '../node_modules/@bobfrankston/msgapidefs/msgapidefs.js';

// msgapi provides APIs not available in browsers/webviews
if (window.msgapi) {
    // Window control beyond browser capabilities
    window.msgapi.setFullscreen(true);
    window.msgapi.setAlwaysOnTop(true);

    // File system access (requires allowFs flag)
    const file = await window.msgapi.fs?.selectFile();
}

// For standard browser APIs, use native methods:
document.title = 'My App';  // Instead of msgapi.setTitle()
localStorage.setItem('key', 'value');  // Instead of msgapi.saveData()
window.close();  // Instead of msgapi.close() if not passing result

Platform Support

✅ = Current | 🔧 = Possible (recompile/rebuild needed) | ❌ = Not feasible

| Platform | msger (Rust/wry) | msgview (Electron) | msga (.NET MAUI) | |----------|:----------------:|:------------------:|:----------------:| | Windows | ✅ | ✅ | ✅ | | Linux | ✅ | ✅ | ❌ | | macOS | 🔧 wry supports it | ✅ | 🔧 Mac Catalyst | | Raspberry Pi | ⚠️ runs but no display | ✅ | ❌ | | Android | ❌ | ❌ | ✅ (primary) | | iOS | ❌ | ❌ | ❌ |

msger uses wry (Rust webview). Desktop platforms (Win/Linux/Mac) are mature. msger can cross-compile and run on the Pi but does not display properly (wry/GTK rendering issues) — not a priority to fix. msgview runs wherever Electron does — desktop only, no mobile. msga targets Android primarily; Windows for dev/testing. iOS would be the most realistic path — MAUI supports iOS natively, so msga could target it with an iOS build profile, Apple developer account, and platform-specific conditional code (#if IOS) for permissions and APIs. No current plans.

Implementation Status

✅ = Implemented | ⚠️ = Partial | ❌ = Not implemented

| API | msgview | msger | msga | Notes | |-----|:-------:|:-----:|:----:|-------| | Configuration | | | | | | version | ❌ | ❌ | ✅ | window.msgapi.version string | | setLogging(value?) | ❌ | ❌ | ✅ | Returns previous state | | setAutoUpdate(value?) | ❌ | ❌ | ✅ | 'auto'/'check'/'off'; msga Android only | | Window Control | | | | window.msgapi.* | | toggleFullscreen() | ❌ | ✅ | ✅ | msger: via window.msgapi (msger-api.js) | | setFullscreen(bool) | ✅ | ✅ | ✅ | | | minimize() | ✅ | ✅ | ✅ | msga: Windows only | | maximize() | ✅ | ✅ | ✅ | msga: Windows only | | setSize(w, h) | ✅ | ✅ | ✅ | msga: Windows only | | setPosition(x, y) | ✅ | ✅ | ✅ | msga: Windows only | | setAlwaysOnTop(bool) | ✅ | ✅ | ❌ | | | close(result?) | ✅ | ✅ | ✅ | | | navigate(url) | ❌ | ❌ | ✅ | msga only | | reload() | ❌ | ❌ | ✅ | msga only | | File System | | | | window.msgapi.fs.* | | fs.selectFile() | ❌ | ❌ | ✅ | msga: full JS bridge wired | | fs.selectFiles() | ❌ | ❌ | ✅ | msga: full JS bridge wired | | fs.saveFileAs() | ❌ | ❌ | ✅ | msga: Windows only | | fs.selectFolder() | ❌ | ❌ | ✅ | msga: Windows only | | fs.read(path) | ❌ | ❌ | ✅ | msga: binary→base64→TextDecoder | | fs.readAsDataUrl(path) | ❌ | ❌ | ✅ | msga: auto-detects MIME from extension | | fs.write(path, content) | ❌ | ❌ | ✅ | | | fs.list(path) | ❌ | ❌ | ✅ | msga: includes attributes/created on Windows | | fs.exists(path) | ❌ | ❌ | ✅ | | | fs.delete(path) | ❌ | ❌ | ✅ | | | Shell | | | | window.msgapi.shell.* | | shell.exec() | ❌ | ❌ | ✅ | Process with stdout/stderr; limited on non-rooted Android | | shell.open() | ❌ | ❌ | ✅ | Android: Intent.ACTION_VIEW; Windows: ShellExecute | | shell.showInFolder() | ❌ | ❌ | ❌ | Defined in interface, not yet implemented | | shell.trash() | ❌ | ❌ | ❌ | Defined in interface, not yet implemented | | UDP Networking | | | | window.msgapi.udp.* | | udp.send() | ✅ | ✅ | ✅ | Node dgram / Rust UdpSocket / C# UdpClient | | udp.listen() | ✅ | ✅ | ✅ | Background receive loop in all hosts | | udp.sendReceive() | ✅ | ✅ | ✅ | Send + wait with timeout | | udp.broadcast() | ✅ | ✅ | ✅ | 255.255.255.255 broadcast | | TCP Networking | | | | window.msgapi.tcp.* | | tcp.connect() | ✅ | ✅ | ✅ | Node net/tls / Rust TcpStream+native-tls / C# TcpClient+SslStream | | tcp.write() | ✅ | ✅ | ✅ | UTF-8 string data | | tcp.onData() | ✅ | ✅ | ✅ | Persistent callback, fires multiple times | | tcp.onClose() | ✅ | ✅ | ✅ | Connection closed notification | | tcp.onError() | ✅ | ✅ | ✅ | Error notification | | tcp.upgradeTLS() | ✅ | ✅ | ✅ | STARTTLS — upgrade plaintext to TLS | | tcp.close() | ✅ | ✅ | ✅ | Close connection | | HTTP Fetch | | | | window.msgapi.http.* | | http.fetch() | ✅ | ✅ | ✅ | Native HTTP — bypasses CORS/mixed-content | | Host Launcher Features | | | | Not part of window.msgapi; CLI / launcher-side | | Markdown rendering (.md/.markdown auto-render) | ✅ | ✅ | ❌ | Local file:// URL → rendered HTML via msgcommon/markdown (marked + light/dark CSS). msga could match it in MainPage.xaml.cs URL interception — not done yet. | | Unpacked Chrome extension loading (-extension <dir>) | ✅ | ❌ | ❌ | msgview-only via session.extensions.loadExtension. wry has no public extension API; WebKitGTK has none at all. msga would need a separate Android/WebView2 plumbing — not planned. |

msger now injects window.msgapi via msger-api.js with window control, UDP, and HTTP. File system and shell are not yet implemented in msger or msgview.

Markdown rendering (last two rows): both msger and msgview detect .md/.markdown URLs pointing at local files and render them via the shared renderMarkdown() helper in msgcommon/markdown — no extensions, no per-machine setup, GFM with light/dark CSS that follows prefers-color-scheme. Library callers can import { renderMarkdown, looksLikeMarkdown } from '@bobfrankston/msgcommon/markdown' directly. Extension loading is msgview-only by design: see the row's note.

httpudp-client auto-detects window.msgapi?.udp and uses native UDP when available, falling back to the httpudp WebSocket proxy otherwise.

See msgapi-plan.md for the full implementation plan and roadmap.

API Reference

Configuration

  • version - Host app version string (e.g., "1.2.0")
  • setLogging(value?) - Control debug logging. Returns previous state as string.
    • 'msga' - C# host logging only (logit-msga)
    • 'msgapi' - JS bridge logging only (logit-msgapi)
    • 'on' - Both streams
    • 'off' / 'none' - All off
    • null / '' - Query current state without changing
    • Returns: 'msga', 'msgapi', 'msga,msgapi', or 'none'
  • setAutoUpdate(value?) - Control APK auto-update behavior. Returns previous state as string. msga Android only.
    • 'auto' - Check versions.json, download + install silently (no prompt)
    • 'check' - Check versions.json, prompt "Install now?" before downloading
    • 'off' - No update checking
    • null / undefined - Query current state without changing
    • Default: 'auto' (configurable via AUTO_UPDATE in msga.env)
    • Checks on startup then every UPDATE_INTERVAL_MINUTES (default 60)

Window Control

  • toggleFullscreen() - Toggle fullscreen mode
  • setFullscreen(enabled: boolean) - Set fullscreen state
  • minimize() - Minimize window
  • maximize() - Toggle maximize/restore
  • setSize(width, height) - Set window size
  • setPosition(x, y) - Set window position
  • setAlwaysOnTop(enabled: boolean) - Keep window on top
  • close(result?) - Close window and return result to parent process

File System

File dialogs (user picks interactively — safe without special permissions):

  • fs.selectFile(options?) - Open file picker
  • fs.selectFiles(options?) - Open multi-file picker
  • fs.saveFileAs(content, filename?, options?) - Save file dialog
  • fs.selectFolder(options?) - Folder picker

Direct path operations (give the webview full filesystem access — msga only currently):

  • fs.read(path, options?) - Read file. Options: { encoding: 'utf8' | 'base64' | 'binary' }. Default 'utf8' returns string; 'base64' returns raw base64 string (efficient for images); 'binary' returns Uint8Array.
  • fs.readAsDataUrl(path, mimeType?) - Read file as data URL (data:image/jpeg;base64,...). Auto-detects MIME from extension if omitted.
  • fs.write(path, content) - Write file
  • fs.list(path) - List directory. Returns FileInfo[] with attributes (Win32 flags) and created on Windows.
  • fs.exists(path) - Check if file/directory exists
  • fs.delete(path) - Delete file or directory

Note: File system operations are currently implemented only in msga. msger and msgview do not yet have window.msgapi.fs — these hosts have their own internal fs mechanisms but have not wired them to the msgapi interface.

UDP Networking

Native UDP socket access — no WebSocket proxy needed when running inside a msgapi host.

  • udp.send(host, port, data) - Send UDP packet to specific host
  • udp.listen(port, callback) - Listen for incoming UDP packets (returns {close()} handle)
  • udp.sendReceive(host, port, data, timeoutMs?) - Send and wait for response
  • udp.broadcast(port, data) - Broadcast to local network

TCP Networking

Native TCP/TLS socket access — for IMAP, SMTP, and other stream protocols. Connections are long-lived; use stream IDs to manage multiple connections. TLS is handled natively — JS never sees the raw TLS handshake.

  • tcp.connect(host, port, tls) - Connect to host:port. If tls is true, connect with TLS directly (port 993). Returns a streamId (number).
  • tcp.write(streamId, data) - Write UTF-8 string data to stream.
  • tcp.onData(streamId, callback) - Register handler for incoming data. Persistent — fires multiple times as data arrives.
  • tcp.onClose(streamId, callback) - Register handler for connection close. hadError is true if closed due to error.
  • tcp.onError(streamId, callback) - Register handler for errors.
  • tcp.upgradeTLS(streamId, servername) - Upgrade a plaintext connection to TLS (STARTTLS). Used by IMAP/SMTP after negotiating capabilities on plaintext.
  • tcp.close(streamId) - Close the connection.
// Connect to Gmail IMAP (direct TLS on port 993)
const id = await window.msgapi.tcp.connect('imap.gmail.com', 993, true);
window.msgapi.tcp.onData(id, (data) => console.log('Server:', data));
window.msgapi.tcp.onClose(id, (hadError) => console.log('Closed', hadError));
window.msgapi.tcp.onError(id, (msg) => console.error('Error:', msg));

// STARTTLS example (connect plaintext, then upgrade)
const id2 = await window.msgapi.tcp.connect('imap.example.com', 143, false);
// ... negotiate STARTTLS capability ...
await window.msgapi.tcp.upgradeTLS(id2, 'imap.example.com');
// ... now on encrypted connection ...

Platform implementations: msgview uses Node.js net/tls, msger uses Rust std::net::TcpStream + native-tls, msga uses C# TcpClient + SslStream.

Used by: @bobfrankston/iflow-direct BridgeTransport — enables browser/WebView IMAP without a Node.js server.

Shell / Process Execution

Native process execution — run commands, open files with default handler. msga only currently.

  • shell.exec(command, args?, options?) - Run external command and capture output. Returns { stdout, stderr, exitCode }. Options: cwd, timeout (ms), stdin, encoding ('utf8'|'base64'). Limited on non-rooted Android.
  • shell.open(path) - Open file/URL with system default handler (Windows: ShellExecute, Android: Intent.ACTION_VIEW)
  • shell.showInFolder(path) - Select file in Explorer / file manager (not yet implemented)
  • shell.trash(path) - Move to Recycle Bin / Trash (not yet implemented)

HTTP Fetch

Native HTTP client — bypasses browser CORS and mixed-content restrictions. Use when an HTTPS-served web app needs to reach HTTP endpoints (e.g., local devices on the LAN).

  • http.fetch(url, init?) - Drop-in replacement for browser fetch(). Same RequestInit params, returns a real Response object (.ok, .status, .json(), .text(), .headers, .clone(), etc.)
// HTTP from an HTTPS page — blocked by browsers, works via msgapi
const r = await window.msgapi.http.fetch('http://192.168.1.5/api/status');
const data = await r.json();

// POST with headers and body
const r2 = await window.msgapi.http.fetch('http://192.168.1.5/api/cmd', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ cmd: 'reboot' })
});

Platform implementations: msga uses C# HttpClient, msger uses Rust ureq, msgview uses Node.js fetch(). All return a real Response object constructed on the JS side.

Unsupported init fields (silently ignored — not meaningful for native HTTP): mode, credentials, cache, signal, redirect. new Headers() objects are normalized to plain objects.

Examples

See samples.html for interactive examples and demos of all API features!

Test in msgview:

msgview -url "file:///path/to/node_modules/@bobfrankston/msgapidefs/samples.html"

Test in msger:

msger -url "file:///path/to/node_modules/@bobfrankston/msgapidefs/samples.html"

Test in browser:

# Open samples.html in your browser to test browser compatibility

The samples demonstrate:

  • Window control (fullscreen, minimize, maximize, resize, position)
  • Data persistence (save/load user preferences, session data, recent files)
  • Presentation mode example
  • Session management
  • And more!

Cross-Platform Implementation

msgapidefs defines the TypeScript interface only. Each host implements the window.msgapi bridge differently:

msgview (Electron)

  • Bridge: Electron contextBridge.exposeInMainWorld('msgapi', ...) in preload/preload.ts
  • Mechanism: ipcRenderer.invoke() calls to main process IPC handlers
  • Window control: Electron BrowserWindow API
  • File system: Node.js fs module via IPC, file dialogs via Electron dialog

msger (Rust/wry)

  • Bridge: JavaScript injected via wry with_initialization_script() in msger-native/src/main.rs
  • JS API: msger-native/src/msger-api.js creates window.msgapi object
  • Mechanism: window.ipc.postMessage(JSON.stringify(...)) to Rust IPC handler
  • Capabilities: Window control, UDP, HTTP fetch via window.msgapi
  • Limitations: wry 0.47.2 has IPC issues; close() uses window.close() workaround

msga (.NET MAUI)

  • Bridge: JavaScript injected via WebViewControl.EvaluateJavaScriptAsync() in MainPage.xaml.cs
  • JS API: GetMsgApiScript() creates window.msgapi object inline
  • Mechanism: msgapi:// URL interception — JS creates hidden iframes, C# intercepts in OnNavigating
  • Async: Promise callbacks via callNativeAsync()window._msgapiResolve() / _msgapiReject()
  • Window control: Platform-conditional (#if WINDOWS uses WinUI AppWindow APIs)
  • File system: MAUI FilePicker, Windows-specific FileSavePicker/FolderPicker
  • Platforms: Android (primary target), Windows (development/testing)

Adding New Sub-Objects

Each capability is an optional sub-object on MsgAPI (e.g., fs?, udp?). To add a new one:

  1. Define the interface in msgapidefs.ts as an optional sub-object on MsgAPI
  2. Implement the native side in each host:
    • msgview: Add IPC handlers in main.ts, expose in preload/preload.ts
    • msger: Add Rust handler in main.rs, expose in msger-api.js
    • msga: Add C# methods + JS injection in GetMsgApiScript() (see msga readme)
  3. Browser code uses optional chaining: window.msgapi?.newFeature?.method() — works everywhere, undefined when unavailable

See msgapi-plan.md for the full feature matrix and implementation status across all three hosts.

Related Packages

License

ISC