npm package: @nsw.io/data
Description: This library is useful for easily extracting data out of an expression. It indeed uses [JSONata](https://docs.jsonata.org/overview) library but is wrapped to produce a simpler format/raw data.
Author: Elias Martinez
Latest version: 0.0.1

# Miner

This library is useful for easily extracting data out of an expression. It indeed uses [JSONata](https://docs.jsonata.org/overview) library but is wrapped to produce a simpler format/raw data.

## Examples

Simple Query
```ts
 // given
  const data = { test: 'foo' };
  const field = 'test';

  // when
  const result = await miner(data, field);

  // then
  expect(result).toEqual('foo'); 
```

Nested Objects
```ts
  // given
  const data = { test: { test2: 'foo' } };
  const field = 'test';

  // given
  const result = await miner(data, field);

  // then
  expect(result).toEqual({ test2: 'foo' });
```

Arrays
```ts
// given
const data = { test: [{ myField: 'foo' }, { myField: 'bar' }] };
const field = 'test.myField';

// given
const result = await miner(data, field);

// then
expect(result).toEqual(['foo', 'bar']);
```

Arrays with Filters
```ts
//given
const data = {
  test: [
    { category: 'a', myField: 'foo' },
    { category: 'b', myField: 'bar' },
    { category: 'b', myField: 'baz' },
  ],
};
const field = 'test[category="b"].myField';

// when
const result = await miner(data, field);

// then
expect(result).toEqual(['bar', 'baz']);
```

Complex Queries
```ts
 //given
const data = {
  test: [
    { category: 'a', myField: 1 },
    { category: 'b', myField: 2 },
    { category: 'b', myField: 3 },
    { category: 'b', myField: 4 },
  ],
};
const field = '$sum(test[category="b" and myField>2].myField)';

// when
const result = await miner(data, field);

// then
expect(result).toEqual(7);
```

## What is this useful for?
Imagine you have an angular application where you need to render a list of information out of your complex data (tables, lists, summaries). With this tool you can create now an angular pipe

```ts
@Pipe(name="extract")
export class Extract implements PipeTransform {
  transform(data:Record<string, unknown>, field: string): unknown {
    return miner(data, field)
  }
}
```
Now in your html you can do
```html
<div *ngFor"let item of elements">
  <div class="card">
    <h1>item | extract: 'product.name'</h1>
    <h2>item | extract: 'product.price' | currency<h2>
  </div>
<div>
<div class="total">{{ {data:elements} | extract: '$sum(elements.price)' | currency }}</div>
```
And it becomes real useful when you don't now what you are displaying. Or your fields are "dynamic"

Let's say we have a database/document that contains the fields we are displaying in a table

```ts
@Component({
  selector:'my-table',
  template: 'my-table.html'
})
class MyTable {
  columnsResolver = inject(ColumnsResolverService)
  dataResolver = inject(MyDataResolver)
  columns$: Observable<Column[]>
  data$: Observable<Column[]>

  ngOnInit() {
    this.columns$ = this.columnsResolver.get()
    this.data$ = this.dataResolver.get()
  }
}
```
Now the HTML
```html
<table *ngIf="columns$ | async as columns">
  <tr>
    <th *ngFor="let col of columns">
      {{col.header}}
    <th>
  <tr>
  <ng-container *ngIf="data$ | async as elements">
    <tr *ngFor="let element of elements">
      <td *ngFor="let col of columns">
        {{element | extract: col.field}}
      <td>
    </tr>
  <ng-container>
</table>
```
And just like that you have a dynamic table based on a set of configurations, as you can see, you don't need to know the column header/fields values NOR structure, as long as `field` contains the proper JSONata expression. 
This means that if you have complex data like 
```json
{
  "Account Name": "Firefly",
  "Order": [
    {
      "OrderID": "order103",
      "Product": [
        {
          "Product Name": "Bowler Hat",
          "ProductID": 858383,
          "Description": {
            "Width": 300,
            "Height": 200,
            "Weight": 0.75
          },
          "Price": 34.45,
          "Quantity": 2
        },
        {
          "Product Name": "Trilby hat",
          "ProductID": 858236,
          "Description": {
            "Width": 300,
            "Height": 200,
            "Weight": 0.6
          },
          "Price": 21.67,
          "Quantity": 1
        }
      ]
    },
  ]
}
```
You could navigate through all the levels of your information as long as the field passed to the miner is well/properly formatted. For more information about JSONata expression, visit their site at [docs.jsonata.org](https://docs.jsonata.org/overview)

# Contributing

## Building

Run `nx build data` to build the library.

## Running unit tests

Run `nx test data` to execute the unit tests via [Jest](https://jestjs.io).