npm package: @stofloos/stofware-client
Description: A client SDK for interacting with the Stofware API.
Author: Stofloos
Latest version: 1.0.16

# StofwareClient

The `StofwareClient` is a TypeScript SDK to interact with the Stofware API. It provides comprehensive functionalities for CRUD operations, data aggregation, and interactions with views.

## Features

- Seamless CRUD operations on models.
- Aggregation functions for both models and views.
- Access to database views.
- JWT token-based authentication.
- Query filter chaining and fluent API design.

## Installation

Before you publish to npm:

```bash
npm install @stofloos/stofware-client
```

## Usage

### Initialization

Import and initialize `StofwareClient`:

```typescript
import { StofwareClient } from "@stofloos/stofware-client";

const client = new StofwareClient("<BASE_URL>", "<OPTIONAL_JWT_TOKEN>");
```

### Set or Update JWT Token

To set or update the JWT token:

```typescript
client.setToken("<YOUR_JWT_TOKEN>");
```

### CRUD Operations on Models

1. **Fetch data using setFilter:**

   ```typescript
   let filterGroup: QueryParametersFilterGroup = {
    operator: BooleanOperator.And,
    items: [
        {
            name: 'fieldName1',
            operator: QueryOperator.Equals,
            value: 'value1'
        }
    ],
    groups: [
        {
            operator: BooleanOperator.Or,
            items: [
                {
                    name: 'fieldName2',
                    operator: QueryOperator.Equals,
                    value: 'value2'
                },
                {
                    name: 'fieldName3',
                    operator: QueryOperator.Equals,
                    value: 'value3'
                }
            ]
        }
    ]
   };
   const data = client.model("entityName").setFilter(filterGroup).page(1).pageLimit(10).orderBy("fieldName", "DESC").getAll();
   ```

2. **Fetch data using appendFilter:**

   ```typescript
   const data = client.model("entityName").appendFilter("fieldName", "operator", "value", "AND").page(1).pageLimit(10).orderBy("fieldName", "DESC").getAll();
   ```

3. **(Deprecated) Fetch data using filters:**

   ```typescript
   const data = client.model("entityName").filter("fieldName", "EQ", "value").page(1).pageLimit(10).orderBy("fieldName", "DESC").getAll();
   ```

4. **Aggregation on models:**

   ```typescript
   const aggregatedData = client.model("entityName").aggregate(
   	[
   		{ field: "price", function: "sum" },
   		{ field: "quantity", function: "count" },
   	],
   	{ groupBy: "created_at", groupByFormat: "month" }
   );
   ```

5. **Create a new record:**

   ```typescript
   client.model("entityName").post({ ...data });
   ```

6. **Update a record:**

   ```typescript
   client.model("entityName").put(1, { ...data });
   ```

7. **Delete a record:**

   ```typescript
   client.model("entityName").delete(1);
   ```

### Operations on Views

1. **Fetch data from a view with setFilter:**

   ```typescript
   let filterGroup: QueryParametersFilterGroup = {
    operator: BooleanOperator.And,
    items: [
        {
            name: 'fieldName1',
            operator: QueryOperator.Equals,
            value: 'value1'
        }
    ],
    groups: [
        {
            operator: BooleanOperator.Or,
            items: [
                {
                    name: 'fieldName2',
                    operator: QueryOperator.Equals,
                    value: 'value2'
                },
                {
                    name: 'fieldName3',
                    operator: QueryOperator.Equals,
                    value: 'value3'
                }
            ]
        }
    ]
   };
   const data = client.model("viewName").setFilter(filterGroup).page(1).pageLimit(10).orderBy("fieldName", "DESC").getAll();
   ```

2. **Fetch data from a view with appendFilter:**

   ```typescript
   const data = client.model("viewName").appendFilter("fieldName", "operator", "value", "AND").page(1).pageLimit(10).orderBy("fieldName", "DESC").getAll();
   ```

3. **Fetch data from a view with filters:**

   ```typescript
   const viewData = client.view("viewName").filter("fieldName", "EQ", "value").orderBy("fieldName", "DESC").page(1).pageLimit(10).getAll();
   ```

4. **Aggregation on views:**

   ```typescript
   const viewAggregatedData = client.view("viewName").aggregate(
   	[
   		{ field: "price", function: "sum" },
   		{ field: "quantity", function: "count" },
   	],
   	{ groupBy: "company_name" }
   );
   ```

## Enhanced Data Functions

**EnhancedDataFunctions** is a set of utility methods to provide more powerful and flexible operations on data arrays, similar to how tools like Pandas allow manipulation and operations on dataframes. The provided functions are `pctChange`, `compareWith`, `add`, `sub`, `mul`, `div`, and the ability to set custom indices via `setIndex`.

### Setting Up

Firstly, wrap your dataset with `enhanceData` function:

```typescript
const enhancedData2023 = enhanceData(aggregatedData2023);
```

### Setting a Custom Index

To better target specific rows for operations, you can set a custom index. By default, the index is set to `id`.

```typescript
enhancedData2023.setIndex("organisation");
```

### Percentage Change

Compute the percentage change between the current and previous element:

```typescript
const result = enhancedData2023.pctChange(["sales", "revenue"]);
```

This will generate new columns like `salesPctChange` and `revenuePctChange`.

### Comparison with Another Dataset

To compare two datasets:

```typescript
const result = enhancedData2023.compareWith(otherData2023, ["sales", "revenue"]);
```

This will produce new columns like `salesCompared` and `revenueCompared`.

### Mathematical Operations

You can perform element-wise mathematical operations on the datasets:

```typescript
// Addition
const added = enhancedData2023.add(otherData2023, ["sales", "revenue"]);

// Subtraction
const subtracted = enhancedData2023.sub(otherData2023, ["sales", "revenue"]);

// Multiplication
const multiplied = enhancedData2023.mul(otherData2023, ["sales", "revenue"]);

// Division
const divided = enhancedData2023.div(otherData2023, ["sales", "revenue"]);
```

Each operation will work on the specified columns and return the result in the same columns.

### Chaining Operations

One of the powerful features is the ability to chain multiple operations:

```typescript
const result = enhancedData2023.pctChange(["sales"]).add(otherData2023, ["revenue"]).compareWith(yetAnotherData2023, ["revenue"]);
```

The above will first compute the percentage change for `sales`, then add the `revenue` from `otherData2023`, and finally compare `revenue` with `yetAnotherData2023`.

---

## License

This SDK is under the MIT license. See the LICENSE file for more details.