# ut-port

> UT port base

Latest version **6.45.3** (published 2025-08-05) · Apache-2.0 license · 0 weekly downloads

## Install

```sh
npm install ut-port
pnpm add ut-port
yarn add ut-port
bun add ut-port
```

## Health

**Score 35/100 (D)** — status: stable.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: stale.

## Facts

| | |
|---|---|
| Version | 6.45.3 |
| Published | 2025-08-05 |
| First published | 2017-10-21 |
| Weekly downloads | 0 |
| License | Apache-2.0 |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 10 |
| Unpacked size | 422.7 KB |
| Known vulnerabilities | 0 (+2 in 2 direct dependencies) |
| Install scripts | no |
| GitHub stars | 0 |
| Maintainers | kalin.krustev |

## Links

- npm: https://www.npmjs.com/package/ut-port
- Repository: https://github.com/softwaregroup-bg/ut-port
- Homepage: https://github.com/softwaregroup-bg/ut-port#readme
- Issues: https://github.com/softwaregroup-bg/ut-port/issues
- npm.io page: https://npm.io/package/ut-port

## Dependencies (10)

- [ajv](https://npm.io/package/ajv.md) 8.6.3
- [uuid](https://npm.io/package/uuid.md) 8.3.2
- [ut-queue](https://npm.io/package/ut-queue.md) ^6.2.2
- [ajv-formats](https://npm.io/package/ajv-formats.md) 2.1.1
- [pull-stream](https://npm.io/package/pull-stream.md) 3.6.9
- [stack-utils](https://npm.io/package/stack-utils.md) 2.0.5
- [pull-paramap](https://npm.io/package/pull-paramap.md) 1.2.2
- [ut-function.merge](https://npm.io/package/ut-function.merge.md) ^1.5.6
- [stream-to-pull-stream](https://npm.io/package/stream-to-pull-stream.md) 1.7.2
- [browser-process-hrtime](https://npm.io/package/browser-process-hrtime.md) 1.0.0

## Recent versions

- 6.45.3 (latest) — 2025-08-05
- 6.30.0-start-namespace.1 (start-namespace) — 2020-07-29
- 6.26.0-validations.1 (validations) — 2020-04-30
- 6.8.1-amret.0 (amret) — 2019-04-17
- 6.7.1-accu.0 (accu) — 2019-02-26
- 6.8.0-rc-godfather.15 (rc-godfather) — 2019-01-25
- 6.7.0-rc-einstein.4 (rc-einstein) — 2018-07-08
- 6.45.2 — 2023-07-21
- 6.45.1 — 2023-02-21
- 6.45.0 — 2023-02-21
- 6.44.1 — 2022-11-04
- 6.44.0 — 2022-10-13
- 6.43.12 — 2022-08-18
- 6.43.11 — 2022-06-02
- 6.43.10 — 2022-05-30
- … 140 more at https://npm.io/package/ut-port/versions

## README

# UT Port

Base class to be usually extended when creating new ports.

## Scope

- Define base API for all ports.
- Define facade API for managing multiple ports.
- Initialize logging
- Initialize metrics

## API

This exports 2 APIs:

```javascript
{
    Port,
    ports
}
```

## Port public API

```Port({bus, logFactory, config})``` - create and return a port with the API below

- ```bus``` - bus to be used by the port, saved in ```this.bus```
- ```logFactory``` - factory for creating loggers
- ```config``` - port configuration to be merged with the port default in this.config

```Port.prototype.init()``` - initializes internal variables of the port

```Port.prototype.start()``` - starts the port, so that it can process messages.
  Usually here ports start to listen or initiate network / filesystem I/O

- ```result``` - return promise so that ```start``` method of the next ports
  can be called after the returned promise resolves

```Port.prototype.ready()``` - this is called after all ports are started

- ```result``` - return promise so that ```ready``` method of the next ports
  can be called after the returned promise resolves. Usually if promise is
  returned, it will be resolved when the I/O operation initiated by the start
  method has finished.

```Port.prototype.stop()``` - stops further processing of messages, closes
connections / stops listening

```Port.prototype.disconnect(reason)``` - throws disconnect error

- ```reason``` - the reason for the disconnect error. This reason is logged in
  the error log and set as cause in the thrown error.

```Port.prototype.pull(what, context)``` - creates pull streams for the port

- ```what``` - can be one of the following:
  - falsy - the method will return an object with method ```push``` that can
  be used to add messages received from outside
  - net stream - use the stream to send and receive messages from outside
  - promise returning method - will execute the method. The method can
  communicate with external systems or just execute locally

- ```context``` - context with which the pull streams are associated

## Ports public API

```ports({bus, logFactory})``` - create and return a ports object.

Returns the API below, which is accessible through the bus in the ```ports``` namespace

- ```bus``` - bus to use when creating ports
- ```logFactory``` - logger factory to use when creating ports

```ports.get({port})``` - get port by id

- ```port``` - id of the port

```ports.fetch()``` - returns array with all the created ports

```ports.create(portsConfig, envConfig)``` - create a new port

- ```portsConfig``` - port configuration coming from the implementation.
  Can be array or single value of the following:
  - function - will call the function with envConfig as parameter, the function
  should return object to be used as configuration
  - object - will be used as configuration

  When portConfig is array, multiple ports are created, with configurations
  taken from the array.

- ```envConfig``` - port configuration coming from the environment.

  If envConfig contains a property named `port`, then the value of
  this property will be merged to the port configuration.

  If envConfig contains a property matching the port id, then the value of
  this property will also be merged to the port configuration but with a higher
  priority than the `port` property.

```ports.start()``` - start all ports

```ports.stop({port})``` - stop port

- ```port``` - id of the port to stop

```ports.move({port, x, y})``` - set UI coordinates and returns the port

- ```port``` - id of the port to set coordinates

- ```x, y``` - coordinates to set

## Port telemetry

Port telemetry includes two sets of data, which ports collect. These are
generally split in non numeric and numeric data, also know as `logs` and
`metrics`. When reporting these, the port uses a standard list of tags / fields
to annotate the date. Their names are:

- `impl` - name of the implementation or application
- `location` - name of datacenter, cluster, etc. where the microservice runs
- `hostname` - name of host where the microservice runs
- `pid` - process id of the microservice
- `env` - name of environment, usually `dev`, `test`, `uat`, `prod`, etc.
- `service` - name of microservice
- `context` - type of port, usually `sql port`, `http port`, `httpserver port`, etc.
- `name` - id of port

### Port logging

Each port initializes its own logger instance, so that logging level
can be set per each port. By default, all ports will use `info` level
for logging. The default can be changed using the configuration key `utPort.logLevel`:

```json
{
  "utPort": {
    "logLevel": "debug"
  }
}
```

In addition to the standard tags, logging defines the following additional ones:

- `msg` - includes information in text form, which can be used for indexing and searching
- `level` - describes the logging level and can be one of:
  - `60` - `fatal` - application has reached an unrecoverable condition
  - `50` - `error` - expected error, the application will continue to process
  further requests
  - `40` - `warn` - application is processing unexpected data and will process
  it in an inefficient way
  - `30` - `info` - standard level of logging, that is of daily use of an
  application operator
  - `20` - `debug` - more verbose level of logging, that includes additional details,
  useful for application developers, may include data on API calls, parameters
  and results
  - `10` - `trace` - most detailed level, which may include low level details like
  network traces
- `@meta` - API metadata, which includes the fields:
  - `@meta.method` - method name
  - `@meta.opcode` - optional operation code that defines the method variant to execute
  - `@meta.mtid` - describes the type of message and can be one of:
    - `event` - the application is processing an internal event
    - `request` - the application is processing an API request call
    - `error` - the application is processing an API response of type error
    - `notification` - the application is processing an API notification call
    - `convert` - the application is converting data from one format to another
  - `@meta.trace`
  - `@meta.conId`
- `error` - when logging errors, this contains additional information for the error,
  represented in the following fields:
  `error.type` - string, representing the type of error
  `error.method` - the name of the method, which resulted with error
  `error.stack` - the call stack at the time of the error
  `error.cause` - any previous errors, that caused this error

### Port metrics

Each port configures a default set of metrics, named as follows:

- `time_#`, `time_#_min`, `time_#_max` - average, minimum and maximum stage
  execution time in milliseconds. Depending on execution stage, `#` can be one of:
  - `q` - Time spent in the incoming queue
  - `r` - Time spent in the `receive` hook
  - `e` - Time spent in the `encode` hook
  - `x` - Time spent in the `execute` hook
  - `d` - Time spent in the `decode` hook
  - `s` - Time spent in the `send` hook
  - `w` - Time spent in dispatch stage
- `time_rate` - count of completed executions per second
- `time_count` - count of completed executions
- `count_a#`, `count_a#_min`, `count_a#_max` - current, minimum and maximum concurrent
  executions per stage. `#` can be one of:
  - `r` - Count of concurrently executing `receive` hooks
  - `e` - Count of concurrently executing `encode` hooks
  - `x` - Count of concurrently executing `execute` hooks
  - `d` - Count of concurrently executing `decode` hooks
  - `s` - Count of concurrently executing `send` hooks
  - `w` - Count of concurrently executing dispatches
- `ms` - Count of sent messages per second
- `mr` - Count of received messages per second
- `bs` - Count of sent bytes per second
- `br` - Count of received bytes per second

In addition to the standard tags, metrics define the following additional ones:

- `m` - Method name. A special method name `*` is used to aggregate metrics
  for all methods.

### Telemetry tools

Various open source tools are available to store, index and visualize
telemetry data.

#### Elasticsearch

To index logs in an optimal way, an index can be created in elasticsearch using
the following request [elastic-index-ut-http](./doc/elastic-index-ut.http)

#### Grafana

To visualize metrics, the file
[grafana-ut-metrics.json](./doc/grafana-ut-metrics.json)
can be imported in Grafana as a dashboard. It requires
that metrics are stored in Prometheus and a datasource
pointed to it exists in Grafana.

### Automatic method import bindings

When defining modules, one can define a list of all bus
methods that are going to be used withing the code as part of the
factory function parameters definition.

Example:

```js
// module wrapper
module.exports = () => function utModule() {
    return {
        orchestrator: () => [
            require('./api/script')
        ]
    }
};

// script
module.exports = function script({
    import: {
        userIdentityLookup
        db$userIdentityLookup
    }
}) {
    return {
        test() {
            await userIdentityLookup(params);
            // is identical to this.bus.importMethod('user.identity.lookup')(params)
            await db$userIdentityLookup(params);
            // is identical to this.bus.importMethod('db/user.identity.lookup')(params)
        }
    };
};

// additionally, the import options can be defined
// per method in the js/json configuration as follows
{
  utModule: {
      orchestrator: true,
      script: {
          import: {
              userIdentityLookup: {
                  cache: {
                      ttl: 6 * 60 * 60 * 1000
                  }
              }
          }
      }
  }
}
```

Also annotation-like syntax can be used
to define multiple configurations for one
and the same method

Example:

```js
// module wrapper
module.exports = () => function utModule() {
    return {
        orchestrator: () => [
            require('./api/script')
        ]
    }
};

// script
module.exports = function script({
    import: {
        '@shortCache namespace.entity.action': alias
    }
}) {
    return {
        test() {
            // alias(params) is identical
            // to this.bus.importMethod('namespace.entity.action')(params)
        }
    };
};

// in the js/json configuration multiple options sets
// can be defined for the method above
// and they will be merged recursively
// in the specified order
// in this case: shortCache <- namespace.entity.action
{
  utModule: {
      orchestrator: true,
      script: {
          import: {
              shortCache: {
                  cache: {
                      ttl: 60 * 1000
                  }
              },
              'namespace.entity.action': {
                  cache: {
                      before: 'get',
                      after: 'set',
                      key: ({key}) => ({
                          id: key,
                          segment: 'namespace.entity.action'
                      })
                  }
              }
          }
      }
  }
}
```

---
_Source: https://npm.io/package/ut-port · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
