npm package: @oroinc/json-api-sdk-generator
Description: The official JavaScript and TypeScript generator library for the Oro JSON:API.
Author: Oro, Inc.
Latest version: 0.1.0

# Requirements
- JAVA 11 version is the minimal version supported. It might already be installed on your machine.
  To install JDK follow (the official instructions)[https://www.oracle.com/java/technologies/downloads/].
- Node.js 22 LT later versions.

# OroCommerce TypeScript Client

This is a TypeScript client for the **OroCommerce REST API**.
You can use it as a dependency if you need to integrate OroCommerce APIs into your application.

To use this client, you will need access to the OroCommerce Backoffice to download the OpenAPI Specification,
or someone must provide you with the specification file. Valid file formats are JSON and YAML.
For more information, refer to the official documentation:
[OpenAPI Specifications Management](https://doc.oroinc.com/user/back-office/system/integrations/openapi-specifications/#admin-openapi-specifications)

This package is developed as a wrapper around the [typescript-fetch](https://openapi-generator.tech/docs/generators/typescript-fetch) library,
with internal utilities to work with the OroCommerce REST **JSON:API**.

# Installing the Package

The OpenAPI Generator is a Java-based tool, but it can be installed via an npm-compatible package:

```bash
pnpm install @oroinc/json-api-sdk-generator -s
```

After installing the package, you need to create a configuration file named `oroapi.config.cjs` in the root of your repository.
This configuration file must include the following fields:
- `input` — the relative path to your OpenAPI specification file
- `output` — the relative path where the generated code should be saved
- `cleanOutputDir` — that determines whether to remove all existing files from the output directory before generating new SDK files. When set to `true`, the directory will be cleaned;

> **Note:** Both paths must be located within your project directory.

## Example
```` javascript
// oroapi.config.cjs
module.exports = {
    input: 'specification.yml',
    output: 'jsonapi-generated',
    cleanOutputDir: true
};

````

You can customize the generation process using the `additionalProperties` field.
For a full list of available options, refer to the official documentation [Typescript Getch Config Options](https://openapi-generator.tech/docs/generators/typescript-fetch#config-options).

To execute code generation, you should run a command without parameters.

```bash
pnpm run oro-generate-api
```

When you run it for the first time, it will select a stable version of the Java program and download it.
The npm will put the Java program's version number in a new file called `openapitools.json`.
You should add this file to your version control.

# Working with SDK

To use the generated code, you have to set up a `Configuration` object to be able to make requests to the origin server:

````
import {Configuration, OauthApi, ProductsApi} from './jsonapi-generated';

const config = new Configuration({
    basePath: 'https://your-orocommerce-application',
});

````
Then you can make an OauthApi object to get a JWT token, and then initialize the ProductsApi to make requests.
On these objects, you can call individual methods that make requests to the REST api, for example:

````
const authApi = new OauthApi(config);

const loginResult = await authApi.oauthtokenPost({
    oauthTokenRequestModel: {
        grantType: 'password',
        clientId: '',
        clientSecret: '',
        username: '',
        password: ''
    }
});

const apiConfig = new Configuration({
    basePath: config.basePath,
    accessToken: `${loginResult.tokenType} ${loginResult.accessToken}`,
    headers: {
        Accept: 'application/vnd.api+json'
    }
});

const productsApi: Promise<ProductsCollectionModel[]>  = new ProductsApi(apiConfig);
````

The returned data is statically typed as `ProductsCollectionModel[]`.
Please check the example repo for more details.

# Fixing code generation

The generator may not correctly handle certain types, such as `Mixed`, because of circular dependencies in their type declarations.
It may be necessary to manually edit the specification file to resolve these dependencies.

An example of how to fix the `mixed` property is shown in the code snippet below.
````yaml
    mixed:
        type: object
        anyOf:
            - type: string
            - type: integer
            - type: number
            - type: boolean
            - type: 'null'
            - type: object
              additionalProperties:
                  $ref: '#/components/schemas/mixed'
            - type: array
              items:
                  $ref: '#/components/schemas/mixed'
````

# Normalizing response data

The SDK automatically normalizes JSON:API responses to make it easier to work with it in headless applications. This process transforms complex `JSON:API` structures into flattened objects with resolved relationships.

## What gets normalized:
- Relations in the `included` section are resolved based on model `relationships` if present.

## Example transformation:

**The Original JSON:API response:**
```json
{
    "data": {
        "type": "products",
        "id": "1",
        "attributes": {
            "name": "Sample Product",
            "price": 99.99
        },
        "relationships": {
            "category": {
                "data": {
                  "type": "categories",
                  "id": "5"
                }
            }
        }
    },
    "included": [
        {
            "type": "categories",
            "id": "5",
            "attributes": {
                "name": "Electronics"
            }
        }
    ]
}
```

**The Normalized Result:**
```json
{
    "id": "1",
    "type": "products",
    "attributes": {
        "name": "Sample Product",
        "price": 99.99
    },
    "category": {
        "id": "5",
        "type": "categories",
        "name": "Electronics"
    }
}
```

This normalization reduces the complexity of working with nested JSON:API structures and provides better TypeScript support.

## Working with normalized vs raw responses

By default, all `GET` methods (like `productsGet`) return normalized data. If you need access to the original `JSON:API` response structure, you have to set  the configuration `normalizeApiJson` property to `false`.
This pattern applies to all entity `GET` methods.

```javascript
const config = new Configuration({
    basePath: basePath,
    headers: {
        Accept: 'application/vnd.api+json'
    },
    normalizeApiJson: false
});

const productsApi = new ProductsApi(config);

// Will return original JSON data
const products = await productsApi.productsIdGet({
    id: 5
});
```