npm package: @spartacus-easy/rest
Description: ## Description This Spartacus library helps to integrate with [Easy Rest](https://sap.github.io/easy-extension-framework/easy-rest/).
Latest version: 221121.5.1

# @spartacus-easy/rest

## Description
This Spartacus library helps to integrate with [Easy Rest](https://sap.github.io/easy-extension-framework/easy-rest/).

## Features 

Spartacus Easy Rest makes it easier to implement custom [Adapters](https://help.sap.com/docs/SAP_COMMERCE_COMPOSABLE_STOREFRONT/eaef8c61b6d9477daf75bff9ac1b7eb4/5a1394b745374f59b98c409754fbdaf7.html?locale=en-US#loiodccdb9b70f7943fab8c58f3cc1a93e50) for Easy Rest by providing the following features :

* Easy Rest endpoint configuration similarly to [OCC endpoint configuration](https://help.sap.com/docs/SAP_COMMERCE_COMPOSABLE_STOREFRONT/eaef8c61b6d9477daf75bff9ac1b7eb4/5a1394b745374f59b98c409754fbdaf7.html?locale=en-US#configuring-endpoints). By default the Easy Rest base URL is the same as OCC, using the specific `/easyrest` prefix 
* `EasyRestEndpointsService` to build parameterized Easy Rest Enpoint URLs based on configuration similarly to `OccEndpointsService`

## How to Install
The library can be installed in the Spartacus project with the following command:

```bash
$ yarn add @spartacus-easy/rest
```

## Example

In the following example, we assume that you have already implemented and configured an Easy Rest service to access a Cart custom sub-resource mapped to `{baseSiteId}/users/{userId}/carts/{cartId}/customResource/{resourceId}`.

The next sections describe how implement an Easy Rest Adapter to communicate with the Easy Rest backend.

## Define Model and Adapter interfaces

Model and Adapter interfaces define the API to communicate with the backend.

1. Generate the custom resource Model interface :
   ```bash
   $ yarn ng g interface CustomResource model 
   ```
3. Generate the Adapter class :
   ```bash
   $ yarn ng g class CustomResource --type adapters
   ```
3. Define Adapter class as follow :
   ```ts
   import { Observable } from "rxjs";
   import { CustomResource } from "./custom-resource.model";

   export abstract class CustomResourceAdapter {
     /**
      * Abstract method used to get custom resource
      *
      * @param userId
      * @param cartId
      * @param resourceId
      */
     abstract get(
       userId: string,
       cartId: string,
       resourceId: string
     ): Observable<CustomResource>;
   }
   ```
   
Notice how nothing is specific to Easy Rest here.

### Easy Rest Adapter class

The Easy Rest Adapter class implements the communication with Easy Rest backend using the `EasyRestEndpoints` service.

1. Generate Easy Rest Adapter class :
   ```bash
   $ yarn ng g class EasyRestCustomResource --type adapters
   ```
2. Implement Easy Rest Adapter class :
   ```ts
   import { HttpClient, HttpHeaders } from '@angular/common/http';
   import { Injectable, InjectionToken } from '@angular/core';
   import { EasyRestEndpointsService } from '@spartacus-easy/rest';
   import {
     Converter,
     ConverterService,
     normalizeHttpError,
   } from '@spartacus/core';
   import { Observable, throwError } from 'rxjs';
   import { catchError } from 'rxjs/operators';
   import { CustomResourceAdapter } from './custom-resource.adapters';
   import { CustomResource } from './custom-resource.model';
   
   export const CUSTOM_RESOURCE_NORMALIZER = new InjectionToken<
     Converter<any, CustomResource>
   >('CustomResourceNormalizer');
   
   @Injectable({
     providedIn: 'root',
   })
   export class EasyRestCustomResourceAdapter implements CustomResourceAdapter {
   
     constructor(
        protected http: HttpClient,
        protected converter: ConverterService,
        protected easyRestEndpoints: EasyRestEndpointsService
     ) {}
   
     get(
       userId: string,
       cartId: string,
       resourceId: string
     ): Observable<CustomResource> {
       return this.http
         .get<CustomResource>(
           this.getGetCustomResourceEndpoint(userId, cartId, resourceId),
           {
             headers: new HttpHeaders().set('Content-Type', 'application/json'),
           }
         )
         .pipe(
           catchError((error) => throwError(normalizeHttpError(error))),
           this.converter.pipeable(CUSTOM_RESOURCE_NORMALIZER)
         );
     }

     protected getGetCustomResourceEndpoint(
       userId: string,
       cartId: string,
       resourceId: string,
     ): string {
       return this.easyRestEndpoints.buildUrl('getCustomResource', {
         urlParams: { userId, cartId, resourceId },
       });
     }
   }
   ```

Notice how the `EasyRestEndpoints` service is used to build the Easy Rest enpoint URL from `getCustomResource` endpoint which will be defined in the next section.

### Setup and Configure Easy Rest module

The Easy Rest Module provides Easy Rest configuration and Adapter implementation.

1. Generate the module :
   ```bash
   $ yarn ng g module CustomEasyRest
   ```
2. Import the Easy Rest module :
   ```ts
   import { CommonModule } from '@angular/common';
   import { NgModule } from '@angular/core';
   import { EasyRestConfig, EasyRestModule } from '@spartacus-easy/rest';
   import { provideConfig } from '@spartacus/core';
   import { EasyRestCustomResourceAdapter } from './easy-rest-custom-resource.adapters';
   import { CustomResourceAdapter } from './custom-resource.adapters';

   export const easyRestConfig: EasyRestConfig = {
     backend: {
       easyRest: {
         endpoints: {
           getCustomResource:
             'users/${userId}/carts/${cartId}/customResource/${resourceId}',
         },
       },
     },
   };

   @NgModule({
     imports: [CommonModule, EasyRestModule],
     providers: [
       provideConfig(easyRestConfig),
       {
         provide: CustomResourceAdapter,
         useClass: EasyRestCustomResourceAdapter,
       },
     ],
   })
   export class CustomEasyRestModule {}
   ```

Notice how the `getCustomResource` Easy Rest endpoint used in the previous section is defined. Also the `baseSiteId` parameter does not need to be defined as it will be automatically be injected based on the current site.