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

@eqxjs/transporter-diameter

v1.0.0

Published

TypeScript library for the Diameter protocol (RFC 6733) – encode/decode, socket management, and custom dictionaries

Downloads

92

Readme

@eqxjs/transporter-diameter

A TypeScript library for the Diameter protocol (RFC 6733), providing:

  • Binary encode / decode of Diameter messages and AVPs
  • TCP socket management with automatic message framing
  • Capability exchange (CER/CEA), device watchdog (DWR/DWA), and graceful disconnect (DPR/DPA)
  • Extensible dictionary system (base RFC 6733 + 3GPP out of the box)
  • Full JSDoc on every public API

Table of contents


Installation

npm install @eqxjs/transporter-diameter

Requires Node.js ≥ 18.


Quick start

Encode / decode

import { DiameterCodec, DiameterDictionary, DiameterMessage, DiameterAVP } from '@eqxjs/transporter-diameter';

const dict  = new DiameterDictionary().loadBase();
const codec = new DiameterCodec(dict);

// Build a Capabilities-Exchange-Request
const cer = new DiameterMessage({
  commandCode:   257,
  applicationId: 0,
  flags: { request: true, proxiable: true },
});
cer.addAVPByName('Origin-Host',  'client.example.com', dict);
cer.addAVPByName('Origin-Realm', 'example.com',        dict);
cer.addAVPByName('Vendor-Id',    0,                    dict);
cer.addAVPByName('Product-Name', 'my-app',             dict);

const wireBuffer = codec.encodeMessage(cer);
console.log('Encoded', wireBuffer.length, 'bytes');

const decoded = codec.decodeMessage(wireBuffer);
console.log(decoded.getCommandName(dict)); // Capabilities-Exchange-Request

Client

import { DiameterClient, DiameterDictionary, DiameterMessage, ResultCode } from '@eqxjs/transporter-diameter';

const dict   = new DiameterDictionary().loadBase();
const client = new DiameterClient(
  { originHost: 'client.example.com', originRealm: 'example.com', applicationIds: [3] },
  dict,
);

const peer = await client.connect('diameter.example.com', 3868);

const acr = new DiameterMessage({ commandCode: 271, applicationId: 3,
  flags: { request: true, proxiable: true } });
acr.addAVPByName('Session-Id',               'client.example.com;1;1', dict);
acr.addAVPByName('Origin-Host',              'client.example.com',      dict);
acr.addAVPByName('Origin-Realm',             'example.com',             dict);
acr.addAVPByName('Destination-Realm',        'example.com',             dict);
acr.addAVPByName('Accounting-Record-Type',   1,                         dict);
acr.addAVPByName('Accounting-Record-Number', 1,                         dict);
acr.addAVPByName('Acct-Application-Id',      3,                         dict);

const aca = await client.request(peer, acr);
console.log('Result-Code:', aca.getAVPValue('Result-Code', dict)); // 2001

await client.close();

Server

import { DiameterServer, DiameterDictionary, ResultCode } from '@eqxjs/transporter-diameter';

const dict   = new DiameterDictionary().loadBase();
const server = new DiameterServer(
  { originHost: 'server.example.com', originRealm: 'example.com', applicationIds: [3] },
  dict,
);

// Register a handler for Accounting-Request (ACR)
server.route(271, async (request) => {
  const answer = request.toAnswer(ResultCode.DIAMETER_SUCCESS);
  answer.addAVPByName('Origin-Host',  'server.example.com', dict);
  answer.addAVPByName('Origin-Realm', 'example.com',        dict);
  return answer;
});

await server.listen(3868);
console.log('Listening on port 3868');

Examples

For practical working examples, see the example/ folder:

To run the examples:

cd example
npm install        # install dependencies
npm run integrated # run the integrated client-server example
npm run server     # or run server in one terminal
npm run client     # and client in another
npm run server-request # server-initiated request demo
npm run custom-dict # or explore custom dictionaries
npm run redis-routing # ioredis adapter setup demo

Redis pub/sub routing adapter

For microservice deployments, you can share Diameter routing events via Redis Pub/Sub (powered by ioredis).

When routingAdapter is configured on server instances, unmatched inbound requests are forwarded internally over Redis to other instances with matching handlers. You only configure adapters and routes; publish/subscribe plumbing is managed by the library.

Recommended flow:

  1. Create a single RedisPubSubAdapter instance (shared by your app components).
  2. Call connect() once during startup.
  3. Pass the adapter in DiameterServer options as routingAdapter.
  4. Register routes normally on worker/server instances.
  5. Start servers with listen().

Routing flow:

sequenceDiagram
    participant App
    participant Redis as RedisPubSubAdapter
    participant Edge as Edge DiameterServer
    participant Worker as Worker DiameterServer

    App->>Redis: connect()
    App->>Edge: new DiameterServer({ routingAdapter: Redis })
    App->>Worker: new DiameterServer({ routingAdapter: Redis })
    App->>Worker: route(271, handler)
    App->>Edge: listen(3868)
    App->>Worker: listen(3869)

    Note over Edge,Worker: Incoming request has no local handler on Edge
    Edge->>Redis: publish(routing:request, encoded request)
    Redis-->>Worker: subscribed request event
    Worker->>Worker: execute route handler
    Worker->>Redis: publish(routing:response, encoded answer)
    Redis-->>Edge: subscribed response event
    Edge-->>App: send Diameter answer to requester

    App->>Edge: close()
    App->>Worker: close()
    App->>Redis: close()
import {
  DiameterServer,
  DiameterDictionary,
  RedisPubSubAdapter,
  ResultCode,
} from '@eqxjs/transporter-diameter';

const dict = new DiameterDictionary().loadBase();
const bus = new RedisPubSubAdapter({
  url: 'redis://127.0.0.1:6379',
  channelPrefix: 'diameter:prod:',
});

await bus.connect();

const edgeServer = new DiameterServer(
  {
    originHost: 'edge-a.example.com',
    originRealm: 'example.com',
    applicationIds: [3],
    routingAdapter: bus,
  },
  dict,
);

const workerServer = new DiameterServer(
  {
    originHost: 'worker-b.example.com',
    originRealm: 'example.com',
    applicationIds: [3],
    routingAdapter: bus,
  },
  dict,
);

workerServer.route(271, async (request) => {
  const answer = request.toAnswer(ResultCode.DIAMETER_SUCCESS);
  answer.addAVPByName('Origin-Host', 'worker-b.example.com', dict);
  answer.addAVPByName('Origin-Realm', 'example.com', dict);
  return answer;
});

await edgeServer.listen(3868);
await workerServer.listen(3869);

// Requests arriving at edgeServer are internally routed to workerServer.

// On shutdown:
await edgeServer.close();
await workerServer.close();
await bus.close();

Redis adapter API:

  • connect() opens publisher/subscriber clients
  • publish(channel, message) publishes a string payload
  • subscribe(channel, handler) listens and returns an async unsubscribe function
  • unsubscribe(channel) removes a single subscription
  • close() unsubscribes all channels and closes Redis clients

Architecture overview

graph TB
    subgraph Public API
        Client[DiameterClient]
        Server[DiameterServer]
    end

    subgraph Transport
        Peer[DiameterPeer<br/>State machine + Watchdog]
        Conn[DiameterConnection<br/>TCP framing]
    end

    subgraph Core
        Codec[DiameterCodec<br/>Encode / Decode]
        Message[DiameterMessage]
        AVP[DiameterAVP]
    end

    subgraph Dictionary
        Dict[DiameterDictionary]
        Base[base-dictionary<br/>RFC 6733]
        GTHPP[3gpp<br/>Cx · Sh · Gx · Rx]
        Tmpl[template<br/>Pre-compiled]
    end

    Client --> Peer
    Server --> Conn
    Peer   --> Conn
    Conn   --> Codec
    Codec  --> Message
    Codec  --> AVP
    Client --> Codec
    Server --> Codec
    Peer   --> Dict
    Conn   --> Dict
    Dict   --> Base
    Dict   --> GTHPP
    Dict   --> Tmpl

Implementation flows

Encoding a message

sequenceDiagram
    participant App
    participant DiameterMessage
    participant DiameterAVP
    participant DiameterCodec
    participant Buffer

    App->>DiameterMessage: new DiameterMessage({ commandCode, flags, … })
    App->>DiameterMessage: addAVPByName("Session-Id", "…", dict)
    DiameterMessage->>DiameterAVP: DiameterAVP.fromDictionary(263, value, dict)
    DiameterAVP-->>DiameterMessage: avp (value encoded to Buffer)
    App->>DiameterCodec: encodeMessage(message)
    DiameterCodec->>Buffer: write 20-byte header
    loop for each AVP
        DiameterCodec->>DiameterCodec: encodeAVP(avp)
        DiameterCodec->>Buffer: write AVP header + padded data
    end
    DiameterCodec-->>App: wire Buffer

Decoding a raw buffer (stream)

sequenceDiagram
    participant TCPSocket
    participant DiameterConnection
    participant DiameterCodec
    participant DiameterMessage
    participant App

    TCPSocket->>DiameterConnection: data event (chunk)
    DiameterConnection->>DiameterConnection: append chunk to rxBuf
    DiameterConnection->>DiameterCodec: extractMessages(rxBuf)
    loop while buffer has complete message
        DiameterCodec->>DiameterCodec: peek declared length (bytes 1-3)
        DiameterCodec->>DiameterCodec: decodeMessage(msgBuf)
        DiameterCodec->>DiameterMessage: parse header + AVPs
        DiameterCodec-->>DiameterConnection: DiameterMessage
    end
    DiameterCodec-->>DiameterConnection: remainder (partial bytes)
    DiameterConnection-->>App: emit 'message' event

Client connection lifecycle

sequenceDiagram
    participant App
    participant DiameterClient
    participant DiameterPeer
    participant DiameterConnection
    participant RemoteServer

    App->>DiameterClient: connect("host", 3868)
    DiameterClient->>DiameterPeer: new DiameterPeer(options, dict)
    DiameterPeer->>DiameterConnection: new DiameterConnection(socket)
    DiameterConnection->>RemoteServer: TCP connect
    RemoteServer-->>DiameterConnection: TCP ACK
    DiameterConnection-->>DiameterPeer: 'connect' event
    DiameterPeer->>RemoteServer: send CER (cmd=257, R=1)
    RemoteServer-->>DiameterPeer: receive CEA (cmd=257, R=0)
    DiameterPeer->>DiameterPeer: state → Open
    DiameterPeer->>DiameterPeer: start watchdog timer
    DiameterClient-->>App: resolved DiameterPeer

    App->>DiameterClient: request(peer, message)
    DiameterClient->>DiameterPeer: sendRequest(message)
    DiameterPeer->>RemoteServer: send request
    RemoteServer-->>DiameterPeer: receive answer (matched by Hop-by-Hop ID)
    DiameterPeer-->>App: resolved answer message

    App->>DiameterClient: close()
    DiameterClient->>DiameterPeer: disconnect()
    DiameterPeer->>RemoteServer: send DPR (cmd=282)
    RemoteServer-->>DiameterPeer: receive DPA
    DiameterPeer->>DiameterConnection: close()
    DiameterPeer->>DiameterPeer: state → Closed

Server request lifecycle

sequenceDiagram
    participant RemoteClient
    participant TCPServer
    participant DiameterServer
    participant DiameterConnection
    participant Handler

    RemoteClient->>TCPServer: TCP connect
    TCPServer->>DiameterServer: 'connection' event
    DiameterServer->>DiameterConnection: wrap socket
    RemoteClient->>DiameterConnection: send CER (cmd=257)
    DiameterConnection-->>DiameterServer: 'message' CER
    DiameterServer->>RemoteClient: send CEA (Result-Code=2001)

    RemoteClient->>DiameterConnection: send Request (e.g. ACR, cmd=271)
    DiameterConnection-->>DiameterServer: 'message' Request
    DiameterServer->>DiameterServer: _findHandler(271)
    DiameterServer->>Handler: handler(request)
    Handler-->>DiameterServer: answer message
    DiameterServer->>RemoteClient: send Answer (ACA)

    RemoteClient->>DiameterConnection: send DPR (cmd=282)
    DiameterServer->>RemoteClient: send DPA (Result-Code=2001)
    DiameterServer->>DiameterConnection: close()

Peer state machine

stateDiagram-v2
    [*] --> Closed

    Closed --> Wait_Conn_Ack : connect() called<br/>TCP connect initiated

    Wait_Conn_Ack --> Wait_I_CEA : socket 'connect'<br/>Send CER

    Wait_Conn_Ack --> Closed : socket error<br/>or timeout

    Wait_I_CEA --> Open : CEA received<br/>Result-Code = 2001<br/>Start watchdog

    Wait_I_CEA --> Closed : CEA error / timeout

    Open --> Open : DWR sent & DWA received<br/>(watchdog cycle)

    Open --> Open : application request ↔ answer

    Open --> Closing : disconnect() called<br/>Send DPR

    Open --> Closed : socket closed by peer<br/>or watchdog timeout

    Closing --> Closed : DPA received<br/>or socket closed

    Closed --> [*]

API reference

DiameterDictionary

| Method | Description | |--------|-------------| | loadBase() | Load the RFC 6733 base definitions. Chainable. | | load(data) | Merge additional dictionary data. Chainable. | | loadFromDict(xml) | Parse and load a legacy .dict XML dictionary. Chainable. | | addAVP(def) | Register a single AVP definition. | | addCommand(def) | Register a command definition. | | addApplication(def) | Register an application definition. | | getAVPByCode(code, vendorId?) | Look up an AVP by numeric code. | | getAVPByName(name) | Look up an AVP by name (case-insensitive). | | getAVPType(code, vendorId?) | Get the data type for an AVP code. | | getCommandByCode(code, applicationId?) | Look up a command by numeric code. | | getCommandByName(name) | Look up a command by name. | | getCommandName(code, applicationId?, isRequest?) | Resolve a human-readable command name. | | getApplicationById(id) | Look up an application definition by ID. | | resolveEnum(avpName, symbol) | Resolve an enum symbol to its integer value. | | getAllAVPs() | Return all registered AVP definitions. | | getAllCommands() | Return all registered command definitions. |

DiameterCodec

| Method | Description | |--------|-------------| | encodeMessage(msg) | Encode a DiameterMessage to a Buffer. | | decodeMessage(buf) | Decode a complete message from a Buffer. | | encodeAVP(avp) | Encode a single DiameterAVP (with padding). | | decodeAVP(buf, offset?) | Decode one AVP from a buffer at the given offset. | | extractMessages(buf) | Extract all complete messages from a TCP stream chunk. |

DiameterMessage

| Method / Property | Description | |-------------------|-------------| | commandCode | 24-bit command code. | | applicationId | Application ID. | | flags | MessageFlags — R, P, E, T bits. | | version | Protocol version (usually 1). | | hopByHopId | Hop-by-Hop identifier. | | endToEndId | End-to-End identifier. | | avps | Ordered AVP list. | | DiameterMessage.fromData(data) | Rebuild a message from decoded wire data. | | addAVP(avp) | Append a pre-built AVP. | | addAVPByName(name, value, dict) | Build and append an AVP via the dictionary. | | getAVP(code, vendorId?) | Get first matching AVP. | | getAVPs(code, vendorId?) | Get all matching AVPs. | | getAVPByName(name, dict) | Get first AVP by dictionary name. | | getAVPValue(name, dict) | Get decoded value of first matching AVP. | | isRequest() | Returns true when the R flag is set. | | toAnswer(resultCode?) | Create a pre-populated answer message. | | getCommandName(dict?) | Resolve human-readable command name. | | toString() | Return a short debug-friendly summary string. | | clone() | Shallow clone. | | DiameterMessage.createDWR(host, realm) | Build a Device-Watchdog-Request. | | DiameterMessage.createDWA(req, host, realm) | Build a Device-Watchdog-Answer. | | DiameterMessage.createDPR(host, realm, cause?) | Build a Disconnect-Peer-Request. |

DiameterAVP

| Method / Property | Description | |-------------------|-------------| | code | AVP code. | | flags | AVPFlags — V, M, P bits. | | vendorId | Vendor ID (when V flag set). | | value | Raw Buffer or DiameterAVP[] for Grouped. | | name | Human-readable name (from dictionary). | | type | Data type (AVPDataType). | | getValue() | Decode and return a typed JavaScript value. | | setValue(value, type?) | Encode a typed value to wire format. | | annotate(dict) | Populate name and type from dictionary. | | toString() | Return a short debug-friendly summary string. | | DiameterAVP.fromValue(code, value, type) | Factory — encode from typed value. | | DiameterAVP.fromDictionary(code, value, dict, vendorId?) | Factory — resolve type from dictionary. |

DiameterConnection

| Method / Property | Description | |-------------------|-------------| | state | Current connection state (idle/open/closing/closed). | | socket | Underlying TCP/TLS socket. | | isSecure | true when the socket is TLS-enabled. | | remoteAddress | Peer address as host:port. | | send(msg) | Encode and send a Diameter message. | | close() | Gracefully close the connection. | | destroy(error?) | Force-close the socket immediately. |

Events: message, connect, close, error

DiameterPeer

| Method / Property | Description | |-------------------|-------------| | connect() | TCP connect + CER/CEA handshake. Returns a Promise. | | sendRequest(req, timeout?) | Send request, wait for answer by Hop-by-Hop ID. | | send(msg) | Send a message without waiting for an answer. | | disconnect(cause?) | Send DPR, wait for DPA, close socket. | | state | Current PeerState. | | host | Remote host name/IP for the peer. | | port | Remote TCP port for the peer. | | remoteOriginHost | Peer identity learned from CER/CEA Origin-Host. | | remoteOriginRealm | Peer identity learned from CER/CEA Origin-Realm. |

Events: connect, close, error, request, answer, stateChange

DiameterClient

| Method | Description | |--------|-------------| | connect(host, port?) | Connect to a peer (reuses existing Open connections). | | request(peer, req, timeout?) | Send request via a specific peer. | | request(req, timeout?) | Auto-route request by Destination-HostDestination-Realm. | | setRoutingAdapter(adapter?) | Set or replace the client routing adapter. Returns the client instance. | | getRoutingAdapter() | Return the currently configured client routing adapter. | | close() | Disconnect all peers. | | getPeers() | Return all active peers. | | getPeer(host, port?) | Return a specific peer. |

ClientOptions includes routingAdapter?: DiameterRoutingAdapter.

DiameterServer

| Method | Description | |--------|-------------| | listen(port?, host?) | Start TCP server. | | route(codeOrName, handler) | Register a request handler. | | request(conn, req, timeout?) | Send a server-initiated request to a specific connection. | | request(req, timeout?) | Auto-route server-initiated request by Destination-HostDestination-Realm. | | setRoutingAdapter(adapter?) | Set or replace the server routing adapter. Returns the server instance. | | getRoutingAdapter() | Return the currently configured server routing adapter. | | close() | Stop server and close all connections. | | address() | Return bound AddressInfo. |

Events: listening, connection, disconnect, request, answer, error

ServerOptions includes routingAdapter?: DiameterRoutingAdapter.

DiameterRoutingAdapter

| Method | Description | |--------|-------------| | connect() | Initialize adapter resources and connections. | | publish(channel, message) | Publish a message payload to a logical channel. | | subscribe(channel, handler) | Subscribe to a logical channel and return an async unsubscribe function. | | unsubscribe(channel) | Remove an existing logical channel subscription. | | close() | Close adapter resources and active subscriptions. |

RedisPubSubAdapter

| API | Description | |-----|-------------| | new RedisPubSubAdapter(options?) | Create an ioredis-based implementation of DiameterRoutingAdapter. | | options.url | Redis connection URL, for example redis://127.0.0.1:6379. | | options.channelPrefix | Optional prefix prepended to every channel. | | options.redisOptions | Optional raw ioredis RedisOptions. |


Message routing

DiameterClient and DiameterServer can automatically select the correct peer / client connection without the caller needing to hold a reference to it.

Routing priority:

  1. Match a connected peer/client whose CER/CEA Origin-Host equals the request's Destination-Host.
  2. If no host match, match by Origin-Realm vs Destination-Realm.

Peer identity is learned automatically from the capability exchange (CER/CEA).

Client auto-routing

import { DiameterClient, DiameterDictionary, DiameterMessage } from '@eqxjs/transporter-diameter';

const dict   = new DiameterDictionary().loadBase();
const client = new DiameterClient(
  { originHost: 'client.example.com', originRealm: 'example.com', applicationIds: [3] },
  dict,
);

// Connect to multiple peers
await client.connect('peer-a.example.com', 3868);
await client.connect('peer-b.example.com', 3868);

// Build request — no need to specify which peer to use
const acr = new DiameterMessage({ commandCode: 271, applicationId: 3,
  flags: { request: true, proxiable: true } });
acr.addAVPByName('Destination-Host',  'peer-b.example.com', dict); // exact host match
acr.addAVPByName('Destination-Realm', 'example.com',        dict); // realm fallback

// request() selects peer-b automatically
const aca = await client.request(acr);
console.log('Result-Code:', aca.getAVPValue('Result-Code', dict));

Server auto-routing (server-initiated requests)

import { DiameterServer, DiameterDictionary, DiameterMessage } from '@eqxjs/transporter-diameter';

const dict   = new DiameterDictionary().loadBase();
const server = new DiameterServer(
  { originHost: 'server.example.com', originRealm: 'example.com', applicationIds: [3] },
  dict,
);

server.route(271, async (request) => {
  const answer = request.toAnswer();
  answer.addAVPByName('Origin-Host',  'server.example.com', dict);
  answer.addAVPByName('Origin-Realm', 'example.com',        dict);
  return answer;
});

await server.listen(3868);

// Later — push a server-initiated request to a connected client:
const push = new DiameterMessage({ commandCode: 258, applicationId: 3,
  flags: { request: true, proxiable: true } });
push.addAVPByName('Destination-Host',  'client-a.example.com', dict);
push.addAVPByName('Destination-Realm', 'example.com',          dict);

// server.request() selects the matching connected client automatically
const answer = await server.request(push);
console.log('Result-Code:', answer.getAVPValue('Result-Code', dict));

Constants and Helpers

| Export | Description | |--------|-------------| | MSG_HEADER_SIZE | Diameter message header size (20 bytes). | | nextHopByHopId() | Generate a new Hop-by-Hop identifier. | | nextEndToEndId() | Generate a new End-to-End identifier. | | parseDictXml(xml) | Parse a .dict XML dictionary into DictionaryData. |


Pre-compiled dictionaries

The library provides pre-compiled dictionary data for common Diameter implementations, avoiding runtime XML parsing overhead:

Template dictionary

The template dictionary includes vendor-specific extensions (Ericsson SCAP, AIS TORO, Huawei, Convergys) and applications (DCCA, 3GPP Re/Rf, etc.):

import { DiameterDictionary, templateDictionary } from '@eqxjs/transporter-diameter';

const dict = new DiameterDictionary()
  .loadBase()                    // RFC 6733 base
  .load(templateDictionary);     // + ~280 extension AVPs

This is useful when you need support for multiple vendors and applications without parsing a .dict file at runtime.

Parsing .dict files at runtime

For custom dictionary formats or ad-hoc extensions, use parseDictXml() to load XML dictionary files:

import * as fs from 'fs';
import { DiameterDictionary, parseDictXml } from '@eqxjs/transporter-diameter';

const dict = new DiameterDictionary()
  .loadBase()
  .loadFromDict(fs.readFileSync('my-dictionary.dict', 'utf8'));

Custom dictionary

import {
  DiameterDictionary,
  DictionaryData,
  VENDOR_3GPP,
} from '@eqxjs/transporter-diameter';

const myExtension: DictionaryData = {
  applications: [
    { id: 16777251, name: 'My Custom App' },
  ],
  commands: [
    {
      code: 999,
      name: 'My-Custom-Command',
      applicationId: 16777251,
      requestAVPs: ['Session-Id', 'Origin-Host', 'Origin-Realm', 'Custom-Data'],
      answerAVPs:  ['Session-Id', 'Result-Code', 'Origin-Host', 'Origin-Realm'],
    },
  ],
  avps: [
    {
      code: 9999,
      name: 'Custom-Data',
      type: 'UTF8String',
      vendorId: 99999,       // your vendor ID
      mandatory: true,
    },
  ],
};

const dict = new DiameterDictionary()
  .loadBase()          // RFC 6733
  .load(myExtension);  // your extension

Running tests

npm test                # run all tests
npm run test:cov        # run with coverage report
npm run build           # compile TypeScript to dist/

Protocol reference

| RFC / Spec | Description | |------------|-------------| | RFC 6733 | Diameter base protocol | | RFC 7155 | NASREQ application | | 3GPP TS 29.229 | Cx interface (IMS) | | 3GPP TS 29.329 | Sh interface (IMS) | | 3GPP TS 29.214 | Rx interface (Policy) |