senecajs/seneca

View on GitHub
lib/sub.ts

Summary

Maintainability
A
2 hrs
Test Coverage
/* Copyright © 2020-2023 Richard Rodger and other contributors, MIT License. */
'use strict'

import { MakeArgu, Skip, One, Empty } from 'gubu'


import {
  pattern as common_pattern,
  parse_jsonic,
} from './common'


const Argu = MakeArgu('seneca')


const SubArgu: any = Argu('sub', {
  props: One(Empty(String), Object),
  moreprops: Skip(Object),
  action: Function,
})


// Subscribe to messages.
function api_sub(this: any) {
  const self = this

  const args = SubArgu(arguments)

  // TODO: this is duplicated - need to be a util
  args.pattern = Object.assign(
    {},
    args.moreprops ? args.moreprops : null,
    'string' === typeof args.props ?
      parse_jsonic(args.props, 'add_string_pattern_syntax') :
      args.props,
  )


  const raw_pattern = args.pattern
  const action = args.action

  let is_inward = !!raw_pattern.in$
  let is_outward = !!raw_pattern.out$

  if (!is_outward) {
    is_inward = true // Default if nothing specified
  }

  let pattern = raw_pattern

  if (false !== raw_pattern.translate$) {

    // Must be exact match to ensure consistent translation
    let translation = this.private$.translationrouter.find(raw_pattern)

    if (translation) {
      pattern = translation(raw_pattern)
    }
  }

  const sub_pattern = self.util.clean(pattern)

  const routers = [
    is_inward ? self.private$.subrouter.inward : null,
    is_outward ? self.private$.subrouter.outward : null,
  ].filter((r) => r)

  routers.forEach((router) => {
    // Exact match, create if needed
    let sub_actions = router.find(sub_pattern, true)
    if (!sub_actions) {
      router.add(sub_pattern, (sub_actions = []))
      sub_actions.pattern = common_pattern(sub_pattern)
    }
    sub_actions.push(action)
  })

  return self
}

export {
  api_sub
}