src/models/make-ports.js
/**
 * Generate functions to handle I/O between the domain
 * and application layers. Each port is assigned an adapter,
 * which either invokes the port (inbound) or is invoked by
 * it (outbound). Ports can be instrumented for exceptions
 * and timeouts. They can also be piped together in a control
 * flow by specifying the output event of one port as the input
 * or triggering event of another.
 *
 * See the `ModelSpecification` for port configuration options.
 *
 * @param {import('./index').ports} ports - object containing domain interfaces
 * @param {object} adapters - object containing application adapters
 * @param {import('./observer').Observer} observer
 */
Generate functions to handle I/O between the domain
and application layers. Each port is assigned an adapter,
which either invokes the port (inbound) or is invoked by
it (outbound). Ports can be instrumented for exceptions
and timeouts. They can also be piped together in a control
flow by specifying the output event of one port as the input
or triggering event of another.

See the `ModelSpecification` for port configuration options.

@param {import('./index').ports} ports - object containing domain interfaces
@param {object} adapters - object containing application adapters
@param {import('./observer').Observer} observer
Generate functions to handle I / O between the domain and application layers . Each port is assigned an adapter which either invokes the port ( inbound ) or is invoked by it ( outbound ) . Ports can be instrumented for exceptions and timeouts . They can also be piped together in a control flow by specifying the output event of one port as the input or triggering event of another . See the ` ModelSpecification ` for port configuration options . @param { import ( ' . / index ' ) . ports } ports - object containing domain interfaces @param { object } adapters - object containing application adapters @param { import ( ' . / observer ' ) . Observer } observer
function makePorts(ports, adapters, observer) {
  if (!ports || !adapters) {
    return;
  }
  return Object.keys(ports)
    .map(function (port) {
      const portName = port;
      const portConf = ports[port];
      const disabled = portConf.disabled || !adapters[port];
      const rememberPort = addPortListener(
        portName,
        portConf,
        observer,
        disabled
      );
      return {
        async [port](...args) {
          if (disabled) {
            return;
          }
          const timer = setPortTimeout({
            portName,
            portConf,
            model: this,
            args,
          });
          try {
            const model = await adapters[port]({ model: this, port, args });
            timer.stopTimer();
            const saved = await updatePortFlow(model, port, rememberPort);
            if (rememberPort) {
              await saved.emit(portConf.producesEvent, portName);
            }
            return saved;
          } catch (error) {
            console.error({ file: __filename, func: port, args, error });
            if (timer.expired()) {
              await async(this.undo());
            }
          }
        },
      };
    })
    .reduce((p, c) => ({ ...p, ...c }));
}
function makePorts ( ports , adapters , observer ) { if ( ! ports || ! adapters ) { return ; } return Object . keys ( ports ) . map ( function ( port ) { const portName = port ; const portConf = ports [ port ] ; const disabled = portConf . disabled || ! adapters [ port ] ; const rememberPort = addPortListener ( portName , portConf , observer , disabled ) ; return { async [ port ] ( ... args ) { if ( disabled ) { return ; } const timer = setPortTimeout ( { portName , portConf , model : this , args , } ) ; try { const model = await adapters [ port ] ( { model : this , port , args } ) ; timer . stopTimer ( ) ; const saved = await updatePortFlow ( model , port , rememberPort ) ; if ( rememberPort ) { await saved . emit ( portConf . producesEvent , portName ) ; } return saved ; } catch ( error ) { console . error ( { file : __filename , func : port , args , error } ) ; if ( timer . expired ( ) ) { await async ( this . undo ( ) ) ; } } } , } ; } ) . reduce ( ( p , c ) => ( { ... p , ... c } ) ) ; }
Generate functions to handle I/O between the domain
 and application layers.
Generate functions to handle I / O between the domain and application layers .
// Listen for event that will invoke this port // The port function // Don't run if port is disabled // Handle port timeouts // Call the adapter and wait // Stop the timer // Remember what ports we called for undo and restart // Signal the next port to run. // Is the timer still running? // Try to back out previous transactions.