# Kopi Locator
This library is used for implementing service locator pattern in Node.js applications

## Installation
Using `npm`:
```npm install --save kopi-locator```

## Usage
### Getting the locator
```
const locator = require('kopi-locator');
```

### Create a new instance of locator
```
const locator = require('kopi-locator');
const newLocator = locator.instantiate();
```

### Registering a Service (factory)
To register a service, provide the following:

- `name`: [string] this name will be used as the key to locate the required service/dependency
- `factory`: [function] this will be a constructor/function to create an instance of the service
- `dependencies`: [array] this will be a list of dependency names as registered in the locator. The names should be in the order of what the factory constructor/function expects to receive in its parameters

```
const locator = require('kopi-locator');

// Creating the service, with dependencies as the constructor
const serviceA = (dependencyB) => ({
  doSomethingInA: () => dependencyB.doSomethingInB() + 20,
});

const serviceB = () => ({
  doSomethingInB: () => 10,
});

// Register in Locator
const run = async () => {
  try {
    // Register service factories and instances
    await locator.register('serviceA', serviceA, ['serviceB']);
    await locator.register('serviceB', serviceB);

    return Promise.resolve();
  } catch (error) {
    return Promise.reject(error);
  }
};

run()
  .then(() => console.log('completed'))
  .catch(error => console.error(error));
```

### Setting an Instance or Value
When a value or an already available instance is expected to be injected or added to the locator, use the `set` method.

These fields are required:

- `name`: [string] this name will be used as the key to locate the required service/dependency
- `value`: [object/value/instance] this will be the instance associated with the given name

```
const locator = require('kopi-locator');

// Creating the service, with dependencies as the constructor
const instanceA = ({
  data: 123,
});

const valueB = 456;

// Register in Locator
const run = async () => {
  try {
    // Register service factories and instances
    await locator.set('instanceA', instanceA);
    await locator.set('valueB', valueB);

    return Promise.resolve();
  } catch (error) {
    return Promise.reject(error);
  }
};

run()
  .then(() => console.log('completed'))
  .catch(error => console.error(error));
```

### Getting Instance/Value/Service 
When getting an instance, if an instance is already present, the same instance will be returned.

If the instance has yet to be created, the locator will attempt to create an instance of the service using the registered factory.
This includes nested creation of the dependencies required for the service, as specified during registration.

```
const locator = require('kopi-locator');

const run = async () => {
  try {
    /* Not showing code for registering/setting */

    // Getting Service
    const instanceA = await locator.get('instanceA');
    const valueB = await locator.get('valueB');
    const serviceC = await locator.get('serviceC');

    return Promise.resolve();
  } catch (error) {
    return Promise.reject(error);
  }
};

run()
  .then(() => console.log('completed'))
  .catch(error => console.error(error));
```