npm package: @inmation/inmation-api-client
Description: inmation Web API Client
Author: inmation Software
Latest version: 1.9.4

# inmation-api-client

This API client can be used with the AspenTech Inmation Web API server.

## Disclaimer

AspenTech Inmation is a registered trademark of Aspen Technology, Inc. further referred to as AspenTech.

This application, is provided for convenience purposes only and is not an official product of AspenTech. While every effort has been made to ensure its functionality and reliability, it is important to note that this tool has not undergone formal quality assurance testing or approval by AspenTech.

The creators of this application have developed it to facilitate easy and powerful configuration of inmation platforms. However, AspenTech does not endorse or guarantee the accuracy, completeness, or suitability of this application for any particular purpose.

Users of this application should understand that it is provided on an "as-is" basis, and AspenTech shall not be held liable for any direct, indirect, incidental, special, or consequential damages arising from its use. 

By using this application, you acknowledge and agree that you do so at your own risk. While efforts have been made to minimize errors and bugs, AspenTech cannot guarantee that the application will be free from defects or that it will meet your specific requirements.

This disclaimer is subject to change without notice. Please review the latest version of this disclaimer regularly.

Thank you for your understanding.

## Install

Install with `npm install @inmation/inmation-api-client`

## How to use it

### Authentication

- `authority` can be `inmation`, `ad` (Active Directory - domain account), `machine` (local account)
- `username` can provided in 'User Principal Name' or 'Down-Level Logon Name'

source: [https://docs.microsoft.com/en-us/windows/desktop/secauthn/user-name-formats](https://docs.microsoft.com/en-us/windows/desktop/secauthn/user-name-formats)

Optional `auth` authentication and `authorization` fields:

```javascript
const options = {
    auth: {
        username: "",
        password: "",
        authority: "inmation | ad | machine",
        grant_type: "password",
        include_claims: ["email", "family_name", "given_name", "middle_name", "phone_number"],
        disconnect_on_access_denied: false
    },
    authorization: "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
};
```

`include_claims` can only be used in combination with `authority` set to `ad`. The token will not be returned to the client but passed via the `req` argument into `ExecFunction` implementation.

`disconnect_on_access_denied` set this to `false` to force the Web API server to keep the websocket connection open in an unauthorized state when the authentication request results in an access denied (401) response. A `onWSConnectionChanged` will be invoked informing the connection is `Connected` but `Authenticated` is set to `false`.  
By default the connection will be closed with Close Status 1002 and reason 'Access token expired.'.  

Note: check Web API version which authorization options its supports.

Example Active Directory authentication:

```javascript
const options = {
    auth: {
        username: "user@domain.com",
        password: "secret",
        authority: "ad",
        grant_type: "password"
    }
};
```

Example Bearer token authentication:

```javascript
const options = {
    auth: {
        authorization: "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
    }
};
```

Example Basic authentication:

```javascript
const options = {
    auth: {
        authorization: "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
    }
};
```

### WebSocket Options

These options only applies for the Node.js and not for the Browser's WebSocket component. See [Node.js WebSocket library](https://github.com/websockets/ws).

```javascript
const options = {
    wsOptions: {
        rejectUnauthorized: true
    }
};
```

### Connect and Subscribe snippet

```javascript
const { Client, model } = require('inmation/inmation-api-client');

const wsURL = 'ws://HOSTNAME:8002/ws';
const options = {
    auth: {
        username: "user@domain.com",
        password: "secret",
        authority: "ad",
        grant_type: "password"
    }
};

const client = new Client();

client.onWSConnectionChanged((connectionInfo) => {
    const webAPIStatusInfo = connectionInfo.webapi_status || {};
    const webAPIStatus = webAPIStatusInfo.status || 'unknown'
    console.log(`Connection state: ${connectionInfo.state}, ${connectionInfo.stateString}, Authenticated: ${connectionInfo.authenticated}, Web API Status: ${webAPIStatus}`);
    const auditTrail = webAPIStatusInfo.audit_trail
    if (auditTrail) {
        console.log(`Audit Trail enabled: ${auditTrail.enabled}, user_comment_mandatory: ${auditTrail.user_comment_mandatory}`);
    }
    const tokenResponse = connectionInfo.token_response
    if (tokenResponse) {
        console.log(`Token response token_type: ${tokenResponse.token_type}, expires_in: ${tokenResponse.expires_in} seconds`);
        console.log(`Token response access_token: ${tokenResponse.access_token}`);
    }
});

client.onDataChanged((err, items) => {
    if (err) console.log(err.message);
    for (const item of items) {
        console.log(`Path: ${item.p} value: ${item.v}`);
    }
});

client.onError((err) => {
    console.log(`Error: ${err.message}`);
});

console.log(`Connect to : ${wsURL}`);
client.connectWS(wsURL, (err) => {
    if (err) return console.log(err.message);

    // Make sure you have some IO, Generic or Data Holder Items in inmation and copy their path(s) over here.
    const items = [new model.Item('/System/Core/Simulation/Saw100'), new model.Item('/System/Core/Simulation/Saw200')];

    client.subscribeToDataChanges(items, (err) => {
        if (err) console.log(err.message);
    });
}, options);
```

### Mass snippet with Scope Comment

```lua
const e1 = {
    path: "/System/Core/Playground/Item01",
    operation: 'REMOVE'
};
const e2 = {
    path: "/System/Core/Playground/Item02",
    ObjectName: "Item02",
    class: 123
};
const e3 = {
    path: "/System/Core/Playground/ItemWithProps",
    ObjectName: "ItemWithProps",
    class: 'HolderItem',
    "CustomOptions.CustomProperties.CustomPropertyName": ["Message", "Value"],
    "CustomOptions.CustomProperties.CustomPropertyValue": ["Hello World", "100"]
}
const e4 = {
    path: "/System/Core/Playground/ItemLibArray",
    ObjectName: "ItemLibArray",
    class: 'GenFolder',
    "ScriptLibrary.LuaModuleName": ['script01', 'script02'],
    "ScriptLibrary.AdvancedLuaScript": ["return 'Hello'", "return 'World'"]
}
const e5 = {
    path: "/System/Core/Playground/ItemLibArrayDict",
    ObjectName: "ItemLibArrayDict",
    class: 'GenFolder',
    ScriptLibrary: {
        ScriptList: [
            {
                LuaModuleName: 'script01',
                AdvancedLuaScript: "return 'Hello'"
            },
            {

                LuaModuleName: 'script02',
                AdvancedLuaScript: "return 'World'"
            }
        ]
    }
}
const e6 = {
    path: "/System/Core/Playground/ActionItem",
    ObjectName: "ActionItem",
    class: 'ActionItem',
    AdvancedLuaScript: "return 100"
}
const items = [e1, e2, e3, e4, e5, e6];

const client = new Client();


client.connectWS(wsURL, (err, connectionInfo) => {
    if (err) return console.log(err.message);
    client.mass(items, (err, data) => {
        if (err) return console.log(`Error: ${err.message}`);
        if (data) {
            console.log(`Data: ${JSON.stringify(data)}`);
        }
    },{
        scc: "This is my scope comment"
    });
}, options);
```

### Re-authenticate snippet

Same attributes as in the `auth` part of the options for the `connectWS`.

```javascript
let auth = {
    username: "USERNAME",
    password: "PASSWORD"
    grant_type: "password"
};
```

Example Bearer token authentication:

```javascript
const auth: {
    authorization: "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
};
```

Example Basic authentication:

```javascript
const auth: {
    authorization: "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
};
```

```javascript
client.authenticate(auth, () => {
});
```