Protocol Dispatcher

The table a primitive with several wire protocols looks its backend up in. A caller names a protocol, and the dispatcher answers the module that speaks it, or refuses with a message naming the ones it knows.

It separates three cases a hand-written lookup tends to merge. A name nobody registered is unknown, and the refusal lists what is known so a typo is visible. A name registered as deferred is one this version does not speak yet, and its refusal says so and points at the protocol to use instead, rather than reading as a typo. A missing name is neither, and says the option is required.

Every name is checked when the dispatcher is built, so a backend registered without a create function is caught at construction rather than on the first request that asks for it.

b.protocolDispatcher.create(opts) #

stable0.2.18
{
  name:             string,  // what the primitive is called in messages; required
  protocols:        object,  // { : module-with-create }; required
  deferred:         object,  // { : { description?, since? } } — known but unimplemented
  fallbackProtocol: string,  // named in a deferred refusal as the one to use
  errorClass:       function,// FrameworkError subclass the refusals are built from
}

Build the table and answer the handle to read it. The handle carries name, resolve(protocol), and protocols and deferred as sorted arrays of the names in each.

resolve answers the registered backend, and throws otherwise: protocol-dispatcher/missing-protocol when nothing was named, protocol-dispatcher/protocol-not-implemented for a deferred name, and protocol-dispatcher/unknown-protocol for anything else, with the known names listed. errorClass makes those throws the owning primitive's own error type, so a caller catches one class rather than two.

Validation is config-time, and each refusal carries its own code: an opts that is not an object throws protocol-dispatcher/bad-opts, a missing or empty name throws protocol-dispatcher/bad-name, a protocols that is not an object throws protocol-dispatcher/bad-protocols, an entry within it that is not an object with a create function throws protocol-dispatcher/bad-protocol-entry, a deferred that is not an object throws protocol-dispatcher/bad-deferred, a fallbackProtocol that is not a non-empty string throws protocol-dispatcher/bad-fallback, and an errorClass that is not a constructor throws protocol-dispatcher/bad-error-class.

var b = require("@blamejs/core");
var dispatch = b.protocolDispatcher.create({
  name:      "objectStore",
  protocols: { s3: require("./s3"), azure: require("./azure") },
  deferred:  { gcs: { description: "Google Cloud Storage", since: "0.9.0" } },
  fallbackProtocol: "s3",
});
dispatch.protocols;          // → ["azure", "s3"]
dispatch.resolve("s3");      // → the s3 module
dispatch.resolve("gcs");     // throws protocol-dispatcher/protocol-not-implemented

Last updated 2026-10-12T14:21:56.879Z by seeder.