routes
— Route Messages
"Routing" is the term used for outbound processing of messages in Gofer Engine.
You can develop channel routes in either the JSON config route following the
Route
type, or you can use the OOP style and follow the ORoute
interface.
Using JSON Style
Alternatively use OOP style.
Using object configs offer simplified strongly typed configuration and allows the configs to be easily stringified to JSON and broken apart for exporting/importing.
The routes
property in the ChannelConfig
type takes a multidimensional
arrays of Route
s. This allows routes to be procecessed syncronously or
asyncronously. Routes within the same inner array will be called sequentially,
If a route sends to a tcp server, then the next route will be using the ACK
returned by that server.
import gofer, { ChannelConfig, Route, RouteFlow } from '@gofer-engine/engine';
const sendMsg: RouteFlow = {
kind: 'tcp',
tcp: {
host: 'localhost',
port: 5600,
msgType: 'HL7v2',
}
};
const storeAck: RouteFlow = {
kind: 'store',
file: {},
};
const route: Route = {
kind: 'route',
id: "ID_1",
name: "Example Config Route 1",
tags: [{ name: "Examples" }],
flows: [sendMsg, storeAck],
};
const channel: ChannelConfig = {
name: 'Example Channel Config',
source: {
kind: 'schedule',
schedule: {
msgType: 'HL7v2',
schedule: '0 /15 * * * *',
runner: {
kind: 'file',
file: {
directory: '/tmp',
filterOptions: {
filenameRegex: '.*\\.hl7',
}
},
}
},
},
ingestion: [
{
kind: 'ack',
ack: {
organization: 'Example Org',
}
},
],
routes: [route],
};
gofer.configs([channel]);
Using OOP Style
Alternatively use JSON style.
name
Call the name
method to name the route
.name('A Unique Route Name')
id
Call the id method to override the generated id given to the route. If not provided the id will be a UUID
.id(42)
filter
Call the filter method to filter the message. See Filter Flow for the function definition
.filter((msg) => msg.get('MSH-9.1') === 'ORM')
transform
Call the transform method to transform/modify the message. See Transform Flow for the function definition
.transform((msg) => msg.set('MSH-5', 'Gofer Engine'))
store
Call the store method to persist the message to a data store. See Store Config for the config definition
.store({ file: {} })
setVar
Call the setVar method to set a variable value for the specific scope. The varValue can either be the value itself or a function to callback to retrieve the value from the message and context. See Variables for more information on using variables.
.setVar('Msg', 'name', 'John Doe')
.setVar('Channel', 'facility', (msg) => msg.get('MSH-3.1'))
.setVar<{ bar: string }>('Global', 'foo', { bar: 'baz' })
setMsgVar
Call the setMsgVar method to set a variable value for the Message scope. Later in this message will be able to use this variable. The varValue can either be the value itself or a function to callback to retrieve the value from the message and context. See Variables for more information on using variables.
.setMsgVar('name', 'John Doe')
setRouteVar
Call the setMsgVar method to set a variable value for the Message scope. Later in this message will be able to use this variable. The varValue can either be the value itself or a function to callback to retrieve the value from the message and context. See Variables for more information on using variables.
.setRouteVar<number>('port', 5808)
setChannelVar
Call the setChannelVar method to set a variable value for the Channel scope. Later in this message or following messages within this same channel will be able to use this variable. The varValue can either be the value itself or a function to callback to retrieve the value from the message and context. See Variables for more information on using variables.
.setChannelVar('facility', (msg) => msg.get('MSH-3.1'))
setGlobalVar
Call the setGlobalVar method to set a variable value for the Global scope. Anywhere later in current or following messages within this same server will be able to use this variable. The varValue can either be the value itself or a function to callback to retrieve the value from the message and context. See Variables for more information on using variables.
.setGlobalVar<{ bar: string }>('foo', { bar: 'baz' })
getVar
Call the getVar method to get a previously set variable for the given scope by name. Define the callback function (cb) to do something with the value of the variable. You can use the value to filter or transform the message, or do something with the MessageContext.
To filter the message, return a boolean.
To transform the message, return the transformed Msg class instance You can return undefined or even not return anything (void)
.getVar('Msg', 'name', (name) => console.log(name))
getMsgVar
Call the getMsgVar method to get a previously set variable for the Msg scope.
.getMsgVar('name', (name, msg) => msg.set('PID-5.2', name))
getRouteVar
Call the getRouteVar method to get a previously set variable for the Route scope.
.getRouteVar('port', (port, _msg, context) =>
context.logger(`Using port ${port}`, 'debug'),
)
getChannelVar
Call the getChannelVar method to get a previously set variable for the Channel scope.
.getChannelVar<string>('facility', (facility, _, { logger }) => {
logger(`Received message from ${facility}`, 'info');
})
getGlobalVar
Call the getGlobalVar method to get a previously set variable for the Channel scope
.getGlobalVar<{ bar: string }>('foo', ({ bar }, msg) =>
msg.set('NTE-2', bar),
)
send
Call the send method to configure a destination to send the message.
For example, you can send the message via TCP to the IP and port provided by your EHR
.send('tcp', 'ehr.example.com', 5700)
You can also use a function to extract this information from the message, the context, or variables.
.send(
'tcp',
(_msg, { getChannelVar }) =>
`${getChannelVar<string>('facility')}.example.com`,
(_msg, context) => context.getRouteVar<number>('port'),
),
Another example, you can send the message to an HTTPS endpoint with a self-signed certificate, and provide basic authorization.
.send('https', {
host: 'ehr.example.com',
port: 443,
basicAuth: {
username: 'user',
password: 'pass',
},
rejectUnauthorized: false,
})
export
Call the export method to save the configuration to a JSON object. This method is mainly used for testing purposes and inner implementation.
Simplified types
type Route = {
kind: 'route';
id?: string | number;
name?: string;
tags?: Tag[];
queue?: QueueConfig;
flows:
| SetRequired<RouteFlowNamed, 'id'>[]
| (RouteFlow | RouteFlowNamed)[];
}
type RouteFlow =
| FilterFlow
| TransformFlow
| TransformOrFilterFlow
| ({ kind: "store" } & StoreConfig)
| Connection;
type Connection =
| { kind: "tcp"; tcp: TcpConfig }
| { kind: "http"; http: HTTPConfig }
| { kind: "https"; https: HTTPSConfig };
type RouteFlowNamed = {
kind: "flow";
id?: string | number; // a unique id for this route flow. If not provided will use UUID to generate. if not defined it may not be the same between deployments/reboots
name?: string; // a human readable name for this route flow. Preferrably unique
tags?: Tag[]; // Tags to help organize/identify route flows
queue?: QueueConfig;
flow: RouteFlow;
};
interface ORoute {
name: (name: string) => ORoute;
id: (id: string | number) => ORoute;
filter: (f: FilterFunc) => ORoute;
transform: (t: TransformFunc) => ORoute;
store: (s: StoreConfig) => ORoute;
setVar: <V>(scope: varTypes, varName: string, varValue: MsgVar<V>) => ORoute;
setMsgVar: <V>(varName: string, varValue: MsgVar<V>) => ORoute;
setRouteVar: <V>(varname: string, varValue: MsgVar<V>) => ORoute;
setChannelVar: <V>(varName: string, varValue: MsgVar<V>) => ORoute;
setGlobalVar: <V>(varName: string, varValue: MsgVar<V>) => ORoute;
getVar: <V>(scope: varTypes, varName: string, getVal: WithVarDo<V>) => ORoute;
getMsgVar: <V>(varName: string, getVal: WithValDo<V>) => ORoute;
getRouteVar: <V>(varName: string, getVal: WithValDo<V>) => ORoute;
getChannelVar: <V>(varName: string, getVal: WithValDo<V>) => ORoute;
getGlobalVar: <V>(varName: string, getVal: WithValDo<V>) => ORoute;
send(method: 'tcp', host: string, port: number): ORoute;
send(method: 'http', options: IHTTPConfig): ORoute;
send(method: 'https', options: IHTTPSConfig): ORoute;
export: () => SetRequired<Route, "id" | "flows">;
}
Advanced Config Style Conformance
For advanced type control, you can pass through generics to the Route
,
RouteFlow
, and RouteFlowNamed
typed.
- The first generic seen in source as
Filt
controls the type of the filter style to either (F
) Functional configs, (O
) Ojectified configs, or (B
) to allow Both config styles. - The second generic seen in source as
Tran
controls the type of the transformer style to either (F
) Functional configs, (O
) Ojectified configs, or (B
) to allow Both config styles. - The third generic seen in source as
Stct
controls controls the strictness of the configs to either (S
) Strictly require objectified configs with ids, or (L
) then allow looser config without requirind ids.