> For the complete documentation index, see [llms.txt](https://jbreckmckye.gitbook.io/node-ts-architecture/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jbreckmckye.gitbook.io/node-ts-architecture/step-by-step/library-root.md).

# Library root

{% hint style="warning" %}
This project and documentation are work in progress
{% endhint %}

{% hint style="info" %}
Example code: [src/lib/index](https://github.com/jbreckmckye/node-typescript-architecture/tree/master/src/lib/context)
{% endhint %}

The library root exports two things:

* a `createLibrary` function
* a bunch of types

### createLibrary

This function is used in each app to instantiate a library from a set of adapters.

```typescript
import * as Operations from './operations'

import { ContextAdapter, wrapAdapter, mergeAdapters } from './context'

export function createLibrary <Adapter extends ContextAdapter> (adapter: Adapter) {
  return {
    book: {
      add:    wrapAdapter(adapter, Operations.addBook)
    },
    loan: {
      take:   wrapAdapter(adapter, Operations.loanBook),
      return: wrapAdapter(adapter, Operations.returnBook)
    },
    user: {
      add:    wrapAdapter(adapter, Operations.addUser),
      remove: wrapAdapter(adapter, Operations.removeUser)
    }
  }
}

```

So, the adapter essentially maps over the set of operations and calls `wrapAdapter` (discussed in the last chapter).

The resulting type looks like this:

```typescript
type = {
  book: {
    add: (input: AddInput, params?: AdapterParams) => Promise<AddOutput>
  },
  loan: {
    take: (input: LoanInput, params?: AdapterParams) => Promise<TakeLoanOutput>,
    return: (input: ReturnInput, params?: AdapterParams) => Promise<ReturnBookOutput>
  },
  user: {
    add: (input: AddUserInput, params?: AdapterParams) => Promise<AddUserOutput>,
    remove: (input: RemoveUserInput, params?: AdapterParams) => Promise<RemoveUserOutput>
  }
}
```

So, to recap on how this works - taking as example calling `user.add` -

1. We call `user.add` with the user input params (name, address, etc) and any adapter params (an object of things that might be used by the adapters).
2. The function created by `wrapAdapter` calls the adapter passed into `createLibrary`
3. That adapter may be a merged adapter calling all the others
4. Now the resulting context is passed to the operation
5. The operation does its business and either returns the output, or throws an error

Exactly how adapters work is documented in the next chapter.

### Other exports

In the example code we've exported quite a few types from Lib:

```typescript
import * as Operations from './operations'
import * as Entities from './entities'
import * as Errors from './errors'
import * as Events from './events'
import * as Ctx from './context'

import { ContextAdapter, wrapAdapter, mergeAdapters } from './context'

export {
  Ctx,
  Entities,
  Errors,
  Events,
  mergeAdapters
}
```

* Exporting the **Ctx Type** helps us type our adapters
* Exporting **Entities Types** lets us use the library in a type-safe way
* Exporting **Errors Types** lets us do useful things with typed errors
* Exporting **Event Types** lets us read from events in a safe way
* Exporting **mergeAdapters** is necessary for any apps

(Obviously for JS projects only mergeAdapters is needed)

### Now we have a library

The library is essentially a unit of 'pure' code - that is, all our domain operations, without side effects. It's now ready to be given adapters to emit outputs, and passed to bindings to receive inputs from the outside world.&#x20;
