JSPM

@napplet/core

0.3.1
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 27
  • Score
    100M100P100Q77442F
  • License MIT

Shared protocol types, constants, and message definitions for the napplet protocol

Package Exports

  • @napplet/core

Readme

@napplet/core

JSON envelope types and NUB dispatch infrastructure for the napplet ecosystem.

Getting Started

Package Overview

This package is the single source of truth for all protocol-level definitions in the napplet ecosystem. All other @napplet/* packages import their envelope types, dispatch infrastructure, and protocol constants from here.

Zero dependencies. No DOM or browser APIs. Works in any JavaScript runtime.

Installation

npm install @napplet/core

Quick Start

import {
  type NappletMessage, type NubDomain, type ShellSupports,
  type NubHandler, type NubDispatch,
  NUB_DOMAINS, SHELL_BRIDGE_URI, PROTOCOL_VERSION,
  createDispatch, registerNub, dispatch, getRegisteredDomains,
  ALL_CAPABILITIES, TOPICS,
} from '@napplet/core';

API Reference

Envelope Types

The JSON envelope wire format is the primary API introduced in NIP-5D v4. All messages between napplet and shell use a type field as a discriminant in domain.action format.

NappletMessage

Base interface for all messages exchanged between napplet and shell.

interface NappletMessage {
  /** Message type discriminant in "domain.action" format */
  type: string;
}

Concrete message types extend this interface with domain-specific payload fields:

// Example concrete message type:
interface RelaySubscribe extends NappletMessage {
  type: 'relay.subscribe';
  id: string;
  subId: string;
  filters: NostrFilter[];
}

The type field domain prefix (relay, identity, storage, ifc, theme, keys, media, notify, config, resource, connect, class) routes messages to the correct NUB handler via dispatch().

NubDomain

String literal union of the twelve NUB capability domains.

type NubDomain = 'relay' | 'identity' | 'storage' | 'ifc' | 'theme' | 'keys' | 'media' | 'notify' | 'config' | 'resource' | 'connect' | 'class';
Domain Scope
relay Relay proxy (subscribe, publish, query)
identity Read-only user identity queries
storage Scoped key-value storage proxy
ifc Inter-frame communication (dispatch + channel)
theme Theme tokens and appearance settings
keys Keyboard forwarding and action keybindings
media Media session control and playback
notify Shell-rendered notifications
config Per-napplet declarative configuration (JSON Schema-driven)
resource Byte-fetching primitive (URL to Blob)
connect User-gated direct network access
class Shell-assigned napplet class / security posture

NUB_DOMAINS

Runtime constant array of all NUB domain strings. Useful for iteration and validation.

const NUB_DOMAINS: readonly NubDomain[] = ['relay', 'identity', 'storage', 'ifc', 'theme', 'keys', 'media', 'notify', 'config', 'resource', 'connect', 'class'];

for (const domain of NUB_DOMAINS) {
  console.log(`Checking support for: ${domain}`);
}

ShellSupports

Interface for the shell capability query API.

interface ShellSupports {
  supports(capability: NubDomain | string): boolean;
}

Napplets call window.napplet.shell.supports(domain) to check whether the shell declared support for a NUB domain before using that domain's API.

NappletGlobalShell

Type for the window.napplet.shell namespace. Extends ShellSupports.

interface NappletGlobalShell extends ShellSupports {}

NUB Dispatch Infrastructure

The dispatch system allows NUB modules to self-register at import time. Inbound messages are routed to the correct NUB handler based on the domain prefix extracted from message.type (the part before the first .).

createDispatch()

Factory that returns an isolated { registerNub, dispatch, getRegisteredDomains } backed by its own Map<string, NubHandler>. Use for testing or multi-instance scenarios.

function createDispatch(): NubDispatch;
import { createDispatch } from '@napplet/core';

const { registerNub, dispatch } = createDispatch();
registerNub('relay', handleRelayMessage);
dispatch({ type: 'relay.subscribe' }); // true

registerNub(domain, handler)

Register a handler for a NUB domain on the module-level singleton registry. NUB modules call this at import time.

const registerNub: (domain: string, handler: NubHandler) => void;
import { registerNub } from '@napplet/core';

registerNub('relay', (msg) => {
  // handles all relay.* messages
  console.log('relay message:', msg.type);
});

Throws if the domain is already registered.

dispatch(message)

Dispatch a message to the handler matching its domain prefix. Returns true if a handler was found and called.

const dispatch: (message: NappletMessage) => boolean;
import { dispatch } from '@napplet/core';

dispatch({ type: 'relay.subscribe' });  // true (if relay handler registered)
dispatch({ type: 'unknown.action' });   // false
dispatch({ type: 'malformed' });         // false (no dot)

The domain is extracted by splitting message.type on the first .. A type with no . or an empty domain prefix returns false without throwing.

getRegisteredDomains()

Return all currently registered domain strings from the singleton registry.

const getRegisteredDomains: () => string[];
import { getRegisteredDomains } from '@napplet/core';

getRegisteredDomains(); // ['relay', 'identity', 'storage']

NubHandler

Callback type for NUB message handlers.

type NubHandler = (message: NappletMessage) => void;

NubDispatch

Interface returned by createDispatch().

interface NubDispatch {
  registerNub: (domain: string, handler: NubHandler) => void;
  dispatch: (message: NappletMessage) => boolean;
  getRegisteredDomains: () => string[];
}

Protocol Types

Types shared by all napplet packages for Nostr event structures and the capability system.

NostrEvent

Standard Nostr event structure (used by relay NUB and identity NUB).

interface NostrEvent {
  id: string;
  pubkey: string;
  created_at: number;
  kind: number;
  tags: string[][];
  content: string;
  sig: string;
}

NostrFilter

Subscription filter (used by relay NUB for relay.subscribe and relay.query).

interface NostrFilter {
  ids?: string[];
  authors?: string[];
  kinds?: number[];
  since?: number;
  until?: number;
  limit?: number;
  [key: `#${string}`]: string[] | undefined; // tag filters, e.g. '#t', '#e'
}

Capability

String union type listing all 10 protocol capability strings.

type Capability =
  | 'relay:read' | 'relay:write'
  | 'cache:read' | 'cache:write'
  | 'hotkey:forward'
  | 'sign:event' | 'sign:nip04' | 'sign:nip44'
  | 'state:read' | 'state:write';

Shell implementations use bitfield constants (CAP_*) for fast runtime checks. Capability strings are the human-readable protocol-level representation.

ALL_CAPABILITIES

readonly Capability[] containing all 10 capability strings.

for (const cap of ALL_CAPABILITIES) {
  console.log(cap); // 'relay:read', 'relay:write', ...
}

Subscription

Handle returned by relay.subscribe() and ifc.on().

interface Subscription {
  close(): void;
}

EventTemplate

Unsigned event template passed to relay.publish().

interface EventTemplate {
  kind: number;
  content: string;
  tags: string[][];
  created_at: number;
}

Protocol Constants

Constant Value Description
PROTOCOL_VERSION '4.0.0' Current napplet-shell protocol version (JSON envelope era, NIP-5D v4)
SHELL_BRIDGE_URI 'napplet://shell' URI identifying the shell bridge in relay tags
REPLAY_WINDOW_SECONDS 30 Maximum event age (seconds) for replay protection

Topic Constants

The TOPICS object contains string constants for IFC topic-based routing. These are legacy constants from the pre-envelope era — with JSON envelope messages, topic strings are passed directly in ifc.emit and ifc.subscribe payloads.

import { TOPICS } from '@napplet/core';

TOPICS.STATE_GET                // 'shell:state-get'
TOPICS.SHELL_CONFIG_GET         // 'shell:config-get'
TOPICS.WM_FOCUSED_WINDOW_CHANGED // 'wm:focused-window-changed'
// ... see source for full list

Note: With JSON envelope wire format (v0.16.0+), state operations use storage.* messages directly rather than IFC topic routing. These constants are retained for backward compatibility with shell runtime implementations.


Types

import type {
  NappletMessage, NubDomain, NamespacedCapability, ShellSupports, NappletGlobalShell,
  NubHandler, NubDispatch,
  NostrEvent, NostrFilter, Capability,
  Subscription, EventTemplate, NappletGlobal,
} from '@napplet/core';
Type Description
NappletMessage Base interface for all JSON envelope messages
NubDomain Union of the twelve NUB domain strings
NamespacedCapability Union of NubDomain | nub:* | perm:* for supports()
ShellSupports Interface with supports() capability query method
NappletGlobalShell Type for window.napplet.shell (extends ShellSupports)
NubHandler Callback type for NUB domain handlers
NubDispatch Interface returned by createDispatch()
NostrEvent Nostr event structure
NostrFilter Subscription filter for relay NUB
Capability Human-readable capability string union
Subscription Handle with close() returned by subscribe/on
EventTemplate Unsigned event template for publishing

Integration Note

@napplet/core is consumed by all packages in the napplet ecosystem for envelope types and NUB dispatch.

  • In this repo: @napplet/shim, @napplet/sdk, and @napplet/vite-plugin import NappletMessage, NubDomain, ShellSupports, and all shared protocol types from @napplet/core.
  • @napplet/nub domain modules (@napplet/nub/relay, @napplet/nub/identity, @napplet/nub/storage, @napplet/nub/ifc, @napplet/nub/keys, @napplet/nub/media, @napplet/nub/notify, @napplet/nub/config): extend NappletMessage for their domain-specific message types and call registerNub at import time. (The @napplet/nub/theme barrel is types-only — no registerNub side effect.)

Protocol Reference

  • NIP-5D -- Napplet-shell protocol specification

License

MIT