npm package: @runtimeterror/rt-lib
Description: Library for generating architecture diagrams from YAML files.
Author: Peter Schulze
Latest version: 1.4.0

# rt-lib

[![pipeline status](https://gitlab.com/runtime-terror-500/rt-lib/badges/master/pipeline.svg)](https://gitlab.com/runtime-terror-500/rt-lib/commits/master)

## Contributing

To get started, install packages with

```bash
$ npm install
```

Before submitting a merge request, please make sure all tests are passing and there are no linting errors.

### Test

To execute the test suite, run:

```bash
$ npm test
```

### Lint

For linting, we are following the [AirBnB JavaScript Style Guide](https://github.com/airbnb/javascript). To execute the linter run:

```bash
$ npm run lint
```

### Publish

Publishing to the NPM registry is done manually, due to limitations of the free GitLab CI.
To deploy a new version do the following:

1. Create a new branch from most current master branch.
2. In the root directory use the following to bump the version number:

```bash
$ npm version patch
```

OR

```bash
$ npm version minor
```

OR

```bash
$ npm version major
```

3. Merge the newly created branch into master and wait for pipelines to pass.
   **Note: use the --tags flag when pushing to the remote repo to push the tags
   associated with the version bump.
4. Pull down master.
5. Compile typescript to javascript:

```bash
$ npx tsc
```
6. Login to the NPM repository using:
```bash
$ npm login
```
7. Publish to the NPM repository using:
```bash
$ npm publish
```

## Definition for YAML Input File

### Global Constraints

The name of every element described in the YAML **must be unique**.

### Component

A self contained piece of a system that interacts with other pieces of that system.

#### Contents

- name
  - String
  - **unique**
- type
  - String
  - `component`
- description (optional)
  - String
  - A description of the component.
- relationships (optional)
  - List of strings
  - Each list item is a reference by name to a relationship that the component has to another component.
- children (optional)
  - List of strings
  - Each list item is a reference by name to a component that is a child of the component.
- metadata (optional)
  - List of key-value pairs.
  - Each key-value pair in the list represents a piece of extra information that may be important to note about the component.

#### Constraints

- The parent-child association between components cannot be cyclical.
  - I.e. `Component A` cannot have `Component B` as both an ancestor and a descendant.

#### Example

```yaml
"Component A":
  type: component
  description: Component A constructs filbert flanges for use in flux capactors.
  relationships:
    - Filbert Flange Exchange
  children:
    - Component B
    - Component C
  metadata:
    "Number of Nodes": 12
    "Web Server": Running Ruby on Rails 5.1
    "Log File Location": /var/log/component_a
```

#### Child Component

A component that is a child to a parent component.

##### Contents

The same as a regular component with the following differences:

- Cannot have the children element.
- parent (mandatory)
  - The component that references the child component in it's `children` field.

##### Constraints

- As of right now, we only support one level of nested components. Thus, a component may not have a `parent` field if the component referenced by that `parent` field also has a `parent` field.

##### Example

```yaml
"Component B":
  type: component
  description: Component B is the Filbert Flange Factory used by Component A.
  parent: Component A
```

### Relationship

A directed connection between two components.

#### Contents

- name
  - String
  - A **unique** name.
- type
  - String
  - `relationship`
- description (optional)
  - String
  - A description of the relationship.
- connections
  - An array of objects with the `to` and `from` keys indicating the nodes that the relationship originates and terminates from respectively.
- metadata (optional)
  - List of key-value pairs.
  - Each key-value pair in the list represents a piece of extra information that may be important to note about the relationship.

#### Constraints

- When a component is defined to have a relationship, that component must be referenced in the relationships `from` field, `to` field, or both.
  - I.e. For `Component A` to include `Relationship A` in it's definition, `Relationship A` must have either `from: Component A` or `to: Component A`in it's definition.
- Relationships can only exist between two top level components, or two components that share the same parent component.
  - I.e. A child of `Component A` cannot have a relationship to a child of `Component B`, or to `Component B`.
- Defining a reflexive relationship, i.e. a relationship where both the `from` and `to` fields refer to the same component, is not allowed. This sort of information must be captured either in relationships amongst child components, or in the metadata of the component.

#### Example

```yaml
"Filbert Flange Exchange":
  type: **relationship**
  description: Component A passes it's created Filbert Flanges to the Component D cluster.
  connections:
    - from: component A
      to: component D1
    - from: component A
      to: component D2
  metadata:
    protocol: https
    endpoint: component_d.com/filbert_flange_intake
    "rate limit": 500 requests / minute
    authentication: Basic
```

### Use Case

#### Contents

- name
  - String
  - A **unique** name.
- type
  - String
  - `use case`
- description (optional)
  - String
  - A description of the use case.
- path
  - An ordered list of components and relationships that represent how data flows through the system for the use case.
- metadata (optional)
  - List of key-value pairs.
  - Each key-value pair in the list represents a piece of extra information that may be important to note about the use case.

#### Constraints

- The path is ordered and must represent a valid path through the system involving components and relationships.
  - You cannot connect two components with a relationship that does not involve both of those components.
  - You cannot have a component in the path that is unconnected to other components in the path via a valid relationship.
- The path must only include top-level components and relationships, or only include components that share the same parent component and their relationships.

#### Example

```yaml
"Export Filbert Flanges":
  type: usecase
  description: "send filbert flanges from Component A to Component D using the Filbert Flange Exchange"
  path:
    - Component A
    - Filbert Flange Exchange
    - Component D
  metadata:
    artifact: Filbert Flange
    actors:
      - Bill
      - Ted
```