npm package: @orbis-systems/omni-sdk-ts
Description: Omni SDK is designed to help clients consume Orbis APIs with ease. Omni SDK takes care of all the heavy lifting and provides out of the box ready to use objects.
Author: Teddy Radenkov
Latest version: 2.9.10

# Omni SDK - Everything you need to build Orbis clients

Omni SDK is designed to help clients consume Orbis APIs with ease. Omni SDK takes care of all the heavy lifting and provides out of the box ready to use objects.

### Installation
`npm install @orbis-systems/omni-sdk-ts`

#### Example of a use case
```typescript
import { Orbis, Accounts, Avatar, Passport, Logos } from '@orbis-systems/omni-sdk-ts';

const orbis = Orbis.connect({ api_url: '', token_id: 'orbis_token' });
const accounts = Accounts.connect( { api_url: '', token_id: 'accounts_id' });
const passport = Passport.connect( { api_key: 'key', api_secret: 'secret'});
const logos = Logos.connect({ api_key: 'key', api_secret: 'secret' });
const avatar = Avatar.connect({ api_url: '' });

const sdk = { orbis, passport, accounts, logos };

const login = await sdk.orbis.client.login('username', 'password');
const logout = await sdk.orbis.client.logout();
```

`Note` `api_url` contact orbis to for correct environment configuration.

## Configuration
```typescript
interface IOrbisConnect {
    api_url: string
    token_id: string
    auto_renew_token?: boolean
    error_handling?: boolean
    onUnauthorized?: () => void
    request_timeout?: number
}

interface IAccountsConnect {
    api_url: string
    token_id: string
    auto_renew_token?: boolean
    error_handling?: boolean
    onUnauthorized?: () => void
    request_timeout?: number
}

interface IPassportConnect {
    api_key: string
    api_secret: string
    error_handling?: boolean
    onUnauthorized?: () => void
    request_timeout?: number
}

interface ILogosConnect {
    api_key: string
    api_secret: string
    error_handling?: boolean
    onUnauthorized?: () => void
    request_timeout?: number
}

interface IAvatarConnect {
    api_url: string
    error_handling?: boolean
    onUnauthorized?: () => void
    request_timeout?: number
}

interface ICustomStorage {
  setItem: (key: string, value: string) => Promise<void> | void
  getItem: (key: string) => Promise<string | undefined> | string | undefined
  removeItem: (key: string) => Promise<void> | void
}
```

#### Accounts.connect(config: IAccountsConnect): IGetAccountsSDK
`config`

+ `api_url: string` `required` 
    + Sets api to which Accounts needs to connect to.

+ `token_id: string` `required`
    + Specifies Accounts token property name that is used as a key to store the token into storage.
    
+ `auto_renew_token: boolean` `optional` Default: `true`
    + Specifies whether Accounts should track and auto renew tokens that are up for renewal.
    
+ `error_handling: 'boolean` `optional` Default: `true`
    + If set to `false` Accounts will NOT automatically catch and handle errors but instead throw the error which needs to be caught by the client, see [error handling](#error-handling) section.  

+ `onUnauthorized: Function` `optional`
    + Called when token has expired or is invalid on a 401 response from API. 

+ `request_timeout: number` `optional`
    + Specifies the after how long should the request timeout.

---

#### Accounts.storage.use(storage: IStorage)
`storage`

+ `storage: 'session' | 'local' | 'node' | ICustomStorage` `required` Default: `session` for web clients and `node` for server clients.
    + Describes the type of storage that will be used to store authorization token. Custom controller can be provided.
    
    + `ICustomStorage: Object`
        + Provides storage functions for authentication that Accounts needs to use to get, set or delete an API token.  
        
            + `setItem: Function` `required`
                + Retrieves a token.
                
            + `getItem: Function` `required`
                + Stores a given token.
                    
            + `removeItem: Function` `required`
                + Deletes a token.

---

#### Orbis.connect(config: IOrbisConnect): IGetOrbisSDK
`config`

+ `api_url: string` `required` 
    + Sets api to which Orbis needs to connect to.

+ `token_id: string` `required`
    + Specifies Orbis token property name that is used as a key to store the token into storage.
    
+ `auto_renew_token: boolean` `optional` Default: `true`
    + Specifies whether Orbis should track and auto renew tokens that are up for renewal.
    
+ `error_handling: 'boolean` `optional` Default: `true`
    + If set to `false` Orbis will NOT automatically catch and handle errors but instead throw the error which needs to be caught by the client, see [error handling](#error-handling) section.  

+ `onUnauthorized: Function` `optional`
    + Called when token has expired or is invalid on a 401 response from API. 

+ `request_timeout: number` `optional`
    + Specifies the after how long should the request timeout.

---

#### Orbis.storage.use(storage: IStorage)
`storage`

+ `storage: 'session' | 'local' | 'node' | ICustomStorage` `required` Default: `session` for web clients and `node` for server clients.
    + Describes the type of storage that will be used to store authorization token. Custom controller can be provided.
    
    + `ICustomStorage: Object`
        + Provides storage functions for authentication that Orbis needs to use to get, set or delete an API token.  
        
            + `setItem: Function` `required`
                + Retrieves a token.
                
            + `getItem: Function` `required`
                + Stores a given token.
                    
            + `removeItem: Function` `required`
                + Deletes a token.

---

#### Passport.connect(config: IPassportConnect): IGetPassportSDK
`config`

+ `api_key: string` `required`
    + Sets api key for Passport logos api

+ `api_secret: string` `required`
    + Sets api secret for Passport logos api
    
+ `error_handling: 'boolean` `optional` Default: `true`
    + If set to `false` Passport will NOT automatically catch and handle errors but instead throw the error which needs to be caught by the client, see [error handling](#error-handling) section.  

+ `onUnauthorized: Function` `optional`
    + Called when token has expired or is invalid on a 401 response from API. 

+ `request_timeout: number` `optional`
    + Specifies the after how long should the request timeout.

---

#### Logos.connect(config: ILogosConnect): IGetLogosSDK
`config`

+ `api_key: string` `required`
    + Sets api key for Logos logos api

+ `api_secret: string` `required`
    + Sets api secret for Logos logos api
    
+ `error_handling: 'boolean` `optional` Default: `true`
    + If set to `false` Logos will NOT automatically catch and handle errors but instead throw the error which needs to be caught by the client, see [error handling](#error-handling) section.  

+ `onUnauthorized: Function` `optional`
    + Called when token has expired or is invalid on a 401 response from API. 

+ `request_timeout: number` `optional`
    + Specifies the after how long should the request timeout.

---

#### Avatar.connect(config: IAvatarConnect): IGetAvatarSDK
`config`

+ `api_url: string` `required` 
    + Sets api to which Avatar needs to connect to.
    
+ `error_handling: 'boolean` `optional` Default: `true`
    + If set to `false` Avatar will NOT automatically catch and handle errors but instead throw the error which needs to be caught by the client, see [error handling](#error-handling) section.  

+ `onUnauthorized: Function` `optional`
    + Called when token has expired or is invalid on a 401 response from API. 

+ `request_timeout: number` `optional`
    + Specifies the after how long should the request timeout.
    

## Available APIs

+ `Orbis`
    + Trading platform
    
+ `Accounts`
    + On boarding platform

+ `Logos`
    + Company logos
    
+ `Passport`
    + Article and News platform
    
+ `Avatar`
    + User avatar service

## Authentication
Omni SDK provides a `client` object that is used to authenticate with each API. On a successful authentication Omni SDK calls `setItem(token_id, token)` function provided in `storage` or the default controller. All endpoints that are protected must be used after the client has authenticated, otherwise the `onUnauthorized()` function with be called. `client` object has the following methods:

+ Obis API:
    + `login(username: string, password: string)`
    
        ```typescript
        const login = await sdk.orbis.client.login('username', 'password');
        ```
    + `logout()`
    
        ```typescript
        const logout = await sdk.orbis.client.logout();
        ```
    + `updatePassword(currentPassword: string, newPassword: string)`
        ```typescript
        const update = await sdk.orbis.client.updatePassword('password', 'newPassword');
        ```
      
+ Accounts API:
    + `login(email: string, password: string, includes?: Array<string>)`
        ```typescript
        const login = await sdk.accounts.client.login('email', 'password', ['user.role']);
        ```

    + `updateToken(token: string, auto_new: boolean)`
        ```typescript
        sdk.accounts.client.updateToken('token', true);
        ```   
      
    + `logout()`
        ```typescript
        const logout = await sdk.accounts.client.logout();
        ```
      
+ Logos API and Passport API:
    + Provide `api_key` and `api_secret` to each configuration object for `logos` and `passport`
    
+ Avatar uses `Orbis API` and `Accounts API` token for authentication
      
## Storage
Omni SDK allows four different storage types `local`, `session`, `node` and `custom`. When custom is used the `ICustomStorage` object is required which supports synchronous and asynchronous methods. The following is an asynchronous: 
```typescript
import { Orbis } from '@orbis-systems/omni-sdk-ts';
//Default storage: `session` for web and `node` for server
Orbis.storage.use({
    //With a callback
    setItem: async (key, value): Promise<void> => {
        return new Promise((resolve, reject) => {
            db.set(key, value, (err) => {
                if(err){
                    reject('set_item'); //Will be caught and passed through to `on_controller_error` 
                }else{
                    resolve();
                }       
            });      
        });
    },
    //With async/await
    getItem: async (key): Promise<string | undefined> => {
        return await db.get(key); //If an error is thrown, it will be caught and passed through to `on_controller_error`
    }
});
```

## Endpoints
+ For authentication endpoints please refer to [authentication section](#authentication). 
+ For any other endpoints please refer to `orbis.dev` for the corresponding API documentation.

#### Endpoint structure
Besides authentication all endpoints have the same structure.

##### Accesss 
To call an endpoint for example; use the `sdk.orbis` object, access the method object and then add the endpoint name.
```typescript
//POST {{domain}}/api/user/info
sdk.orbis.post('user/info');

//GET {{domain}}/api/quotes/equity
sdk.orbis.get('quotes/equity');
```

##### Parameters `endpoint(url: Url, data?: any, config?: IEndpointRequest) => Promise<IClientResponse>`
+ `data` `optional` is anything that is required by the corresponding API.
```typescript
sdk.accounts.post('users/get', {
    user_id: 1 //Or anything else required for given endpoint
});
```
+ `config` `optional` can be used to override defaults
```typescript
{
  urlQuery?: string | number | Array<string | number> //Default: ''
  params?: any //Default {}
  headers?: { key: string]: string } //Default { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }
  responseType?: 'arraybuffer' | 'document' | 'json' | 'text' | 'stream' | 'blob' //Default json
  timeout?: number //Specifies after hold long should the request timeout  
}
```
`Note` `config` parameter is used ONLY for overwriting the default values if needed.

##### Error Handling
Omni SDK automatically catches and handles errors unless the `error_handling` is set to false. The following is an example of custom error handling:

```typescript
import { Orbis } from '@orbis-systems/omni-sdk-ts';
const orbis = Orbis.connect({ api_url: '', token_id: 'orbis_token', error_handling: false });
try{
    const login = await sdk.orbis.client.login('username', 'password');
    //Proceed with login.data
}catch(err){
    //Handle error
}
```

##### Return
```typescript
interface IClientResponse {
    data: any,
    status: number | null,
    success: boolean,
    error: AxiosError | null
}
```