# datasource-ows

Base datasource for connecting to Orchard Web Services (OWS).

## Usage

### Implementing the abstract OwsDataSource class

```ts
import { OwsDataSource } from '@theorchard/datasource-ows';

interface MyOwsDataSourceConfig {
    owsServiceBaseUrl: string;
}

const TEN_MINUTES = 60 * 10;

class MyObjectDataSource extends OwsDataSource {
    constructor(config: MyOwsDataSourceConfig) {
        super();
        this.baseURL = config.owsServiceBaseUrl;
    }

    getMyObject(id: string) {
        return this.get('/object', { id });
    }

    getCachedObjects() {
        return this.get('/objects', {}, { cacheOptions: { ttl: TEN_MINUTES } });
    }

    updateMyObject(body: MyObjectType) {
        return this.post('/object', body);
    }

    createMyObject(body: MyObjectType) {
        return this.put('/object', body);
    }

    deleteMyObject(id: string) {
        return this.delete('/object', { id });
    }
}
```

### Using mocking features

The OwsDataSource class exposes a `mock` method that lets you register a fixed payload for a given url. Handy when the external service endpoint is not ready.

```ts
import { OwsDataSource, OwsDataSourceConfig } from '@theorchard/datasource-ows';

class MyOwsDataSource extends OwsDataSource {
    constructor(config: MyOwsDataSourceConfig) {
        super(config);

        this.mock({
            url: '/new-api-url-not-implemented',
            method: 'GET',
            payload: Promise.resolve([
                { id: '1', value: 'item one' },
                { id: '2', value: 'item two' },
            ]),
        });
    }

    getNewObjects() {
        return this.get('/new-api-url-not-implemented');
    }
}
```

### Using jest extender for comparing sanitized values

Suppose you are testing the usage of sanitize:

```
async getVendor(vendorId) {
    const response = await this.get(sanitize`vendor/${vendorId}`);

    return toCamel(response);
}
```

You will not be able to do something like:

```
it('sends a GET request', () =>
    expect(owsAbacusAccount.get)
        .toHaveBeenCalledWith('vendor/1'));
```

without this test failure:

```
    Expected: "vendor/1"
    Received: {"getValue": [Function getValue], Symbol(Sanitized String): Symbol(Sanitized String)}
```

You will need to use the `toHaveSanitizedValue` matcher like so:

```
it('sends a GET request', () =>
    expect(owsAbacusAccount.get)
        .toHaveBeenCalledWith(
            expect.toHaveSanitizedValue('vendor/1')));
```

You can also check that the sanitized value is not something:

```
test('GET request was sent', () =>
    expect(owsAccount.get).toHaveBeenCalledWith(
        expect.not.toHaveSanitizedValue('vendor/100')));
```

## Logging and error handling

All errors (except 404) during requests are automatically logged.

On 404 errors the datasource will log the error to the output and return `null`. **NOT** throwing an exception.
