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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@northscaler/message-support

v0.2.0

Published

Messaging primitives for Node.js

Downloads

7

Readme

@northscaler/message-support

Message factories to use in your CQRS or asynchronous, message-based architectures.

Types of messages

This library supports three types of messages:

  • request,
  • response, and
  • event

messages.

Key message features

There are three top-level sections to each message:

  • data: the payload of the message, which is usually an object,
  • meta: data about the message, including
    • id: the unique message id,
    • origin: the location (component & hostname) where the message was created,
    • instant: the instant in time the message was created,
    • traceId: a trace id that can be used for distributed tracing which can be given or is generated, and
    • correlationId: an id that, if present, indicates that something is awaiting a response,
  • error: present if there is an error processing a message, including
    • name: the Error.name value,
    • message: the Error.message value,
    • stack: if so configured (false by default), the Error.stack value,
    • code: the Error.code value, if present,
    • info: the Error.info value, containing contextual information provided with the Error, if present,
    • cause: if so configured (false by default), the Error.cause value, holding the cause of the Error, if present.

In addition, all message types have an action in a type-dependent location.

  • For a request message, it's in the meta.request section.
  • For an event message, it's the meta.event section.
  • For a response message, it's in the meta.response section.

Each message type may include other, type-specific fields as documented.

Custom data

The data section is never inspected, as it is always application-specific. Sometimes, applications need more than just an action property in the message. You are free to add properties anywhere you like after the factory has created the message. Common properties like this include

  • scope, domain or context, indicating some conceptual boundary that only applies to certain message processors and usually placed next to action,
  • type, indicating the type of the entity being manipulated for CRUD operations and is also usually placed next to action, and
  • auth, security, securityContext, user or userContext, holding information about the authenticated user (like user id, roles played, scopes granted, etc) causing the activity and is usually placed directly in the meta section.

Request messages

Use the RequestMessageFactory to create a request message.

const { RequestMessageFactory } = require('@northscaler/message-support').factories
const pkg = require('.../package.json') // or whatever

const factory = new RequestMessageFactory({
  componentName: pkg.name,
  componentVersion: pkg.version
})

const message = factory.create({
  data: { username: 'matthew', email: '[email protected]' },
  action: 'CREATE_USER',
  traceId: '456',
  correlationId: '789'
})

console.log(JSON.stringify(message, null, 2))

/* logs something like:
{
  "data": {
    "username": "matthew",
    "email": "[email protected]"
  },
  "meta": {
    "id": "c6cac4e6-47e4-4e6c-b0eb-95984c04b9f3",
    "instant": "2020-09-18T18:40:52.069Z",
    "traceId": "456",
    "origin": {
      "component": "@northscaler/message-support",
      "version": "0.1.0-pre.0",
      "hostname": "rocky.local"
    },
    "request": {
      "action": "CREATE_USER"
    },
    "correlationId": "789"
  }
}
*/

Event messages

Use the EventMessageFactory to create event messages. There are two temporal kinds of event messages, past & future, and two kinds of past events, successful & unsuccessful.

The most common is a success event:

const { CodedError } = require('@northscaler/error-support')
const { EventMessageFactory } = require('../main/factories') // require('@northscaler/message-support').factories
const pkg = require('../../package.json') // or whatever

const TestError = CodedError({ name: 'TestError' })
const NestedTestError = CodedError({ name: 'NestedTestError' })

const factory = new EventMessageFactory({
  componentName: pkg.name,
  componentVersion: pkg.version,
  includeErrorStacks: true,
  includeErrorCauses: true
})

let message = factory.createSuccess({
  data: { username: 'matthew', email: '[email protected]' },
  action: 'CREATE_USER',
  traceId: '456',
  correlationId: '789'
})

/* logs something like:
{
  "data": {
    "username": "matthew",
    "email": "[email protected]"
  },
  "meta": {
    "id": "5cfc0636-c1a8-4878-b2fd-d954db7157ea",
    "instant": "2020-09-18T19:10:56.072Z",
    "traceId": "456",
    "origin": {
      "component": "@northscaler/message-support",
      "version": "0.1.0-pre.0",
      "hostname": "rocky.local"
    },
    "event": {
      "did": "CREATE_USER",
      "status": "SUCCESS"
    }
  }
}
*/

Another common one is a failure event:

message = factory.createFailure({
  data: { username: 'matthew', email: '[email protected]' },
  action: 'CREATE_USER',
  error: new TestError({ message: 'boom', cause: new NestedTestError({ message: 'bang' }) }),
  traceId: '456',
  correlationId: '789'
})

console.log(JSON.stringify(message, null, 2))

/* logs something like:
{
  "data": {
    "username": "matthew",
    "email": "[email protected]"
  },
  "error": {
    "name": "TestError",
    "code": "E_TEST",
    "cause": {
      "name": "NestedTestError",
      "code": "E_NESTED_TEST",
      "message": "E_NESTED_TEST: bang",
      "stack": null
    },
    "message": "E_TEST: boom: E_NESTED_TEST: bang",
    "stack": null
  },
  "meta": {
    "id": "e6232595-35cd-461f-9488-a7b69efd31b1",
    "instant": "2020-09-18T19:07:52.359Z",
    "traceId": "456",
    "origin": {
      "component": "@northscaler/message-support",
      "version": "0.1.0-pre.0",
      "hostname": "rocky.local"
    },
    "event": {
      "did": "CREATE_USER",
      "status": "FAILURE"
    }
  }
}
*/

You can also send events indicating that something is about to happen:

message = factory.createFuture({
  data: { username: 'matthew', email: '[email protected]' },
  action: 'CREATE_USER',
  traceId: '456',
  correlationId: '789'
})

console.log(JSON.stringify(message, null, 2))

/* logs something like:
{
  "data": {
    "username": "matthew",
    "email": "[email protected]"
  },
  "meta": {
    "id": "d5f024da-2ad9-43a2-aa9c-7d992088db96",
    "instant": "2020-09-18T19:14:46.625Z",
    "traceId": "456",
    "origin": {
      "component": "@northscaler/message-support",
      "version": "0.1.0-pre.0",
      "hostname": "rocky.local"
    },
    "event": {
      "will": "CREATE_USER"
    }
  }
}
*/

Response messages

Use the ResponseMessageFactory to create response messages for request messages that include a correlationId, indicating that something is expecting a response after the request is handled. There are two kinds of response messages, successful & unsuccessful.

The most common is a successful response. This example uses the convenience method createSuccessFromRequest.

const { CodedError } = require('@northscaler/error-support')
const { ResponseMessageFactory, RequestMessageFactory } = require('../main/factories') // require('@northscaler/message-support').factories
const pkg = require('../../package.json') // or whatever

const TestError = CodedError({ name: 'TestError' })
const NestedTestError = CodedError({ name: 'NestedTestError' })

const requestFactory = new RequestMessageFactory({
  componentName: pkg.name,
  componentVersion: pkg.version,
  includeErrorStacks: false,
  includeErrorCauses: true
})

const responseFactory = new ResponseMessageFactory({
  componentName: pkg.name,
  componentVersion: pkg.version,
  includeErrorStacks: false,
  includeErrorCauses: true
})

// this is the request to which we're going to send a response message
const request = requestFactory.create({
  data: { username: 'matthew', email: '[email protected]' },
  action: 'CREATE_USER',
  traceId: '456',
  correlationId: '789'
})

// say the service we delegated to assigned id '246' to the user, so add that to the data
let message = responseFactory.createSuccessFromRequest({ request, data: { ...request.data, id: '246' } })

console.log(JSON.stringify(message, null, 2))

/* logs something like:
{
  "data": {
    "username": "matthew",
    "email": "[email protected]",
    "id": "246"
  },
  "meta": {
    "id": "cdd0617b-d6f8-46be-ae84-700b86d7ac30",
    "instant": "2020-09-18T19:25:33.464Z",
    "traceId": "456",
    "origin": {
      "component": "@northscaler/message-support",
      "version": "0.1.0-pre.0",
      "hostname": "rocky.local"
    },
    "response": {
      "status": "SUCCESS",
      "elapsedMillis": 134
    },
    "correlationId": "789"
  }
}
*/

Here is a failure response. This example uses the convenience method createFailureFromRequest.

message = responseFactory.createFailureFromRequest({
  request,
  data: request.data,
  error: new TestError({ message: 'boom', cause: new NestedTestError({ message: 'bang' }) })
})

console.log(JSON.stringify(message, null, 2))

/* logs something like:
{
  "data": {
    "username": "matthew",
    "email": "[email protected]"
  },
  "error": {
    "name": "TestError",
    "code": "E_TEST",
    "cause": {
      "name": "NestedTestError",
      "code": "E_NESTED_TEST",
      "message": "E_NESTED_TEST: bang",
      "stack": null
    },
    "message": "E_TEST: boom: E_NESTED_TEST: bang",
    "stack": null
  },
  "meta": {
    "id": "840f5486-fe35-4661-9435-796aa0ce3483",
    "instant": "2020-09-18T19:35:36.181Z",
    "traceId": "456",
    "origin": {
      "component": "@northscaler/message-support",
      "version": "0.1.0-pre.0",
      "hostname": "rocky.local"
    },
    "response": {
      "status": "FAILURE",
      "elapsedMillis": 4
    },
    "correlationId": "789"
  }
}
*/

There is also a more general method called create to which these convenience methods delegate.