npm package: @statlertronik/collection-json-utils
Description: Helper Library for collection-json Hypermedia Format
Author: Dariusz Dziara
Latest version: 2.3.2

# @statlertronik/collection-json-utils
Helper utility to generate data for '[Collection+JSON - Hypermedia Type](http://amundsen.com/media-types/collection/)'

# How to use it

to install:
```javascript
npm install @statlertronik/collection-json-utils
```

in code (typescript):

```javascript
/*--------------------------------------------------------------------*/
/* Creating 'Collection+JSON' response object with collection data    */
/* and with references to 'queries' & 'template' objects.             */
/*--------------------------------------------------------------------*/
import { 
    CJ_MEDIA_TYPE,
    ICollectionJSON, 
    buildCJResponse,
    addCJLink,
    IItem,
    addCJItem,
    addItemData,
    addItemLink
    } from '@statlertronik/collection-json-utils';

// create 'Collection+JSON' response object and initialize its 'version' and "href" properties
const cj: ICollectionJSON = buildCJResponse("1.0", "http://example.com/api/groups");

// add items to 'links' property array of 'Collection+JSON' response
addCJLink(cj, "http://example.com/api/groups/?queries" /*hr*/, "queries" /*rel*/);
addCJLink(cj, "http://example.com/api/groups/?template" /*hr*/, "template" /*rel*/);

// add items to 'items' property array of 'Collection+JSON' response
{
    const itm: IItem = addCJItem(cj, "http://example.com/api/groups/1"): 

    addItemData(itm, "name" /*name*/, "Writers" /*value*/, "Name" /*prompt*/);
    addItemData(itm, "active" /*name*/, "false" /*value*/, "Active" /*prompt*/);

    addItemLink(itm, "http://example.com/api/images/13" /*hr*/, "avatar" /*rel*/, "Avatar" /*prompt*/, "image" /*render*/);        
}

{
    const itm: IItem = addCJItem(cj, "http://example.com/api/groups/2"): 

    addItemData(itm, "name" /*name*/, "Others" /*value*/, "Name" /*prompt*/);
    addItemData(itm, "active" /*name*/, "true" /*value*/, "Active" /*prompt*/);

    addItemLink(itm, "http://example.com/api/images/24" /*hr*/, "avatar" /*rel*/, "Avatar" /*prompt*/, "image" /*render*/);    
}

// now convert it to JSON string and send it to client with HTTP 'content-type' set to 'CJ_MEDIA_TYPE'
...
```

```javascript
/*--------------------------------------------------------------------*/
/* Creating 'Collection+JSON' response object with collection data,   */
/* 'queries' and 'template'.                                          */
/*--------------------------------------------------------------------*/
import { 
    CJ_MEDIA_TYPE,
    ICollectionJSON, 
    buildCJResponse,
    addCJLink,
    IItem,
    addCJItem,
    addItemData,
    IQuery,
    addCJQuery,
    addQueryData,
    addCJTemplateData
    } from '@statlertronik/collection-json-utils';

// create 'Collection+JSON' response object and initialize its 'version' and "href" properties
const cj: ICollectionJSON = buildCJResponse("1.0", "http://example.com/api/groups");

// add items to 'links' property array of 'Collection+JSON' response
addCJLink(cj, "http://example.com/api/groups/page/?offset=10&length=5" /*hr*/, "next" /*rel*/);
addCJLink(cj, "http://example.com/api/groups/page/?offset=0&length=5" /*hr*/, "prev" /*rel*/);
addCJLink(cj, "http://example.com/api/groups/page/?offset=0&length=5" /*hr*/, "first" /*rel*/);
addCJLink(cj, "http://example.com/api/groups/page/?offset=95&length=5" /*hr*/, "last" /*rel*/);

// add items to 'items' property array of 'Collection+JSON' response
{
    const itm: IItem = addCJItem(cj, "http://example.com/api/groups/1"): 

    addItemData(itm, "name" /*name*/, "Writers" /*value*/, "Name" /*prompt*/);
    addItemData(itm, "active" /*name*/, "false" /*value*/, "Active" /*prompt*/);

    addItemLink(itm, "http://example.com/api/images/13" /*hr*/, "avatar" /*rel*/, "Avatar" /*prompt*/, "image" /*render*/);        
}

{
    const itm: IItem = addCJItem(cj, "http://example.com/api/groups/2"): 

    addItemData(itm, "name" /*name*/, "Others" /*value*/, "Name" /*prompt*/);
    addItemData(itm, "active" /*name*/, "true" /*value*/, "Active" /*prompt*/);

    addItemLink(itm, "http://example.com/api/images/24" /*hr*/, "avatar" /*rel*/, "Avatar" /*prompt*/, "image" /*render*/);    
}

// add items to 'queries' property array of 'Collection+JSON' response
{
    const qry: IQuery = addCJQuery(cj, "http://example.com/api/groups/search" /*href*/, "search" /*rel*/, "Search" /*prompt*/);

    addQueryData(qry, "search" /*name*/, "" /*value*/);
}

// add template data to 'template' propery 'data' array
addCJTemplateData(cj, "name" /*name*/, "Name" /*prompt*/);
addCJTemplateData(cj, "active" /*name*/, "Active" /*prompt*/);

// now convert it to JSON string and send it to client with HTTP 'content-type' set to 'CJ_MEDIA_TYPE'
...
```

```javascript
/*--------------------------------------------------------------------*/
/* Creating 'Collection+JSON' response object with error              */
/*--------------------------------------------------------------------*/
import { 
    CJ_MEDIA_TYPE,
    ICollectionJSON, 
    buildCJResponse,
    setCJError,
    } from '@statlertronik/collection-json-utils';

// create 'Collection+JSON' response object and initialize its 'version' and "href" properties
const cj: ICollectionJSON = buildCJResponse("1.0" /*ver*/, "http://example.com/api/groups" /*hr*/);

// add error object
setCJError(cj, "Server Error" /*title*/, "E7720" /*code*/, "Some unexpected event occured" /*message*/);

// now convert it to JSON string and send it to client with HTTP 'content-type' set to 'CJ_MEDIA_TYPE'
...
```

```javascript
/*--------------------------------------------------------------------*/
/* Converting collection-JSON response object to array of             */
/* IDataRowObjWithRef objects corresponding to items.                 */
/* Client does it when it receives response from server.              */
/*--------------------------------------------------------------------*/
import { 
    CJ_MEDIA_TYPE,
    ICollectionJSON, 
    IDataRowObjWithRef,
    cjConvertItems2ArrayOfObjects
    } from '@statlertronik/collection-json-utils';

// receive and convert JSON string to Collection+JSON response object
const cj: ICollectionJSON = ...;

const a: IDataRowObjWithRef[] = cjConvertItems2ArrayOfObjects(cj)

...
```

```javascript
/*--------------------------------------------------------------------*/
/* Creating 'Collection+JSON' write object                            */
/*--------------------------------------------------------------------*/
import { 
    CJ_MEDIA_TYPE,
    ITemplateResponse, 
    buildTemplateResponse,
    addTemplateRespData
    } from '@statlertronik/collection-json-utils';

// create 'Collection+JSON' write object
const templateResp: ITemplateResponse = buildTemplateResponse();

// add write object data
addTemplateRespData(templateResp, "name" /*name*/, "Pilots" /*value*/);
addTemplateRespData(templateResp, "active" /*name*/, "true" /*value*/);

// now convert it to JSON string and send it to server with HTTP 'content-type' set to 'CJ_MEDIA_TYPE'
...
```

```javascript
/*--------------------------------------------------------------------*/
/* Creating 'Collection+JSON' write object from JavaScript plain      */
/* object.                                                            */
/*--------------------------------------------------------------------*/
import { 
    CJ_MEDIA_TYPE,
    ITemplateResponse, 
    ICJPlainObject,
    cjConvertObject2TemplateResponse
    } from '@statlertronik/collection-json-utils';

// JavaScript plain object containing data for ITemplateResponse object
const o: ICJPlainObject = {
    name: "Citizens",
    active: false,
    size: 100 
}

// create 'Collection+JSON' write object
const templateResp: ITemplateResponse = cjConvertObject2TemplateResponse(o, ["size"] /*ignore*/);

// now convert it to JSON string and send it to server with HTTP 'content-type' set to 'CJ_MEDIA_TYPE'
...
```

```javascript
/*--------------------------------------------------------------------*/
/* Converting 'Collection+JSON' ITemplate object to IColumnsInfo      */
/* object. It happens when server receives write object or client     */
/* receives collection object with template.                          */
/*--------------------------------------------------------------------*/
import { 
    CJ_MEDIA_TYPE,
    ITemplate,
    cjExtractColumnsValuesFromTemplate
    } from '@statlertronik/collection-json-utils';

// receives ITemplate object
templ: ITemplate = ...

try {
    const columns: IColumnsInfo = cjExtractColumnsValuesFromTemplate(templ, ["active"] /*extra_column_names*/);

    ...
}
catch(e) {
    ...
}
```


# API

## Basic

```javascript
// string representing this hypermedia type used as value of HTTP 'content-type' header
const CJ_MEDIA_TYPE;
```

```javascript
interface IData {
    name: STRING;
    value?: VALUE;
    prompt?: STRING;
}
```

```javascript
interface ILink {
    rel: STRING;
    href: STRING;
    name?: STRING;
    render?: RENDER_TYPE;
    prompt?: STRING;
}
```

```javascript
interface IItem {
    href?: URI;
    data?: IData[];
    links?: ILink[];
}
```

```javascript
interface IQuery {
    href: URI;
    rel: STRING;
    prompt?: STRING;
    name?: STRING;
    data?: IData[];
}
```

```javascript
interface ITemplate {
    data?: IData[];
}
```

```javascript
interface ICJError {
    title?: STRING;
    code?: STRING;
    message?: STRING;
}
```

```javascript
interface ICollection {
    version?: STRING;
    href?: URI;
    links?: ILink[];
    items?: IItem[];
    queries?: IQuery[];
    template?: ITemplate;
    error?: ICJError;
}
```

```javascript
interface ICollectionJSON {
    collection: ICollection;
}
```

```javascript
interface ITemplateResponse {
    template: ITemplate;
}
```

#### `buildCJResponse(ver: STRING, hr: URI): ICollectionJSON`

Function creates Collection-JSON root object containing version and href.

**Parameters**
Name | Meaning
-------|-------
ver | version
hr | href to the resource

#### `addCJLink(cj: ICollectionJSON, hr: URI, rel: STRING, name?: STRING, prompt?: STRING, render?: RENDER_TYPE): void`

Function adds single 'ILink' object to Collection-JSON root object

**Parameters**
Name | Meaning
-------|-------
cj | Collection-JSON root object returned by buildCJResponse(...)
hr | href of the resource
rel | type of 'href'
name | name of the link
prompt | prompt string
render | interpretation of reference, either 'image' or 'link' (default = 'link') 

#### `addCJItem(cj: ICollectionJSON, href?: URI): IItem`

Function adds 'IItem' object to Collection-JSON root object

**Parameters**

Name | Meaning
-------|-------
cj|Collection-JSON root object returned by buildCJResponse(...)
href | reference to the resource

#### `addItemData(itm: IItem, name: STRING, value?: VALUE, prompt?: STRING): void`

Function adds 'IData' object to 'IItem' object

**Parameters**

Name | Meaning
-------|-------
itm | 'IItem' object returned by addCJItem(...)
name | name of column
value | value of column
prompt | prompt string

#### `addItemLink(itm: IItem, hr: URI, rel: STRING, name?: STRING, prompt?: STRING, render?: RENDER_TYPE): void`

Function adds 'ILink' object to 'IItem' object

**Parameters**

Name | Meaning
-------|-------
itm | 'IItem' object returned by addCJItem(...)
hr | href
rel | type of href
name | name of the link
prompt | prompt string
render | interpretation of reference, either 'image' or 'link' (default = 'link') 

#### `addCJQuery(cj: ICollectionJSON, href: URI, rel: STRING, prompt?: STRING): IQuery`

Function adds 'IQuery' object to Collection-JSON root object

**Parameters**

Name | Meaning
-------|-------
cj | Collection-JSON root object returned by buildCJResponse(...)
href | reference to the resource
rel | type of href
prompt | prompt string

#### `addQueryData(qry: IQuery, name: STRING, value: VALUE, prompt?: STRING): void`

Function adds 'IData' object to 'IQuery' object

**Parameters**

Name | Meaning
-------|-------
qry | 'IQuery' object returned by addCJQuery(...)
name | name of column
value | value of column
prompt | promppt string

#### `addCJTemplateData(cj: ICollectionJSON, name: STRING, prompt?: STRING): void`

Function adds data to 'ITemplate' object of Collection-JSON root object. It creates 'template' & 'template.data' if any of them is missing.

**Parameters**

Name | Meaning
-------|-------
cj | Collection-JSON root object returned by buildCJResponse(...)
name | name of the template 
prompt | prompt string

#### `setCJError(cj: ICollectionJSON, title?: STRING, code?: STRING, message?: STRING): void`

Function sets 'ICJError' object for Collection-JSON root object.

**Parameters**

Name | Meaning
-------|-------
cj | Collection-JSON root object
title | description
code | error code
message | error text

#### `buildTemplateResponse(): ITemplateResponse`

Function creates Collection-JSON ITemplateResponse object

#### `addTemplateRespData(templateResp: TemplateResponse, name: STRING, value?: VALUE, prompt?: STRING): void`

Function adds data to 'ITemplate' object of TemplateResponse object. It creates 'template.data' if missing.

**Parameters**

Name | Meaning
-------|-------
template - ITemplate object returned by addTemplateRespData()
name | name of the template 
value | value 
prompt | prompt string

## Advanced

```javascript
interface IDataRowObj {
    [index: string]: any;
}
```

```javascript
interface IDataRowObjWithRef {
    href?: string;
    data: IDataRowObj;
}
```

#### `cjConvertItems2ArrayOfObjects(cj: cjlib.ICollectionJSON): IDataRowObjWithRef[]`

Function creates array of IDataRowObjWithRef objects containing collection items.

**Parameters**

Name | Meaning
-------|-------
cj | collection-JSON response object if type ICollectionJSON

```javascript
interface IColumnsInfo {
    column_names: string[];
    column_values: cjlib.VALUE[];
    extra_column_names?: string[];
    extra_column_values?: cjlib.VALUE[];
}
```

#### `cjExtractColumnsValuesFromTemplate(templ: cjlib.ITemplate, extra_column_names?: string[]): IColumnsInfo | never`

Function creates an object containing arrays of column names/values from 'ITemplate' and returns it. It can also separately extract selected columns and place them in extra column names/value instead of in arrays of column names/values. It throws exception if templ.data is undefined or empty.

**Parameters**

Name | Meaning
-------|-------
templ | template object
extra_column_names | array of extra column names

```javascript
interface ICJPlainObject {
    [prop: string]: cjlib.VALUE;
}
```

#### `cjConvertObject2TemplateResponse(o: ICJPlainObject, ignore?: string[]): cjlib.ITemplateResponse`

Function creates 'ITemplateResponse' object populated from plain object.

**Parameters**

Name | Meaning
-------|-------
o | plain object
ignore | array of names of columns to ignore