Skip to main content

Integration Modelling

Overview

K5 SDK enables Integration modelling for NestJS-based services, to easily manage integrations to external services within the Solution Designer UI, and provides easy access to integration methods.

When Integration Modelling is enabled, the K5 SDK provides dedicated integration modules per API dependency that can be imported into the project.

ℹ️note

Integration is controlled via the project configuration file k5-project.yml

❗️info

Usage

Assuming a Petstore integration namespaces, containing an API dependency is modelled through the Solution Designer UI, the PetstoreIntegrationModule module can be imported into the project as follows:

import { PetstoreIntegrationModule } from 'k5-sdk';

@Module({
imports: [PetstoreIntegrationModule],
controllers: [MyAPIController],
providers: [],
})
export class MyAPIModule {}

Then, controllers and services within your project can use the Petstore integration service as follows:

import { Request, Response } from 'express';
import { PetstoreIntegrationService, K5LoggerService } from 'k5-sdk';

@Controller('/my-api')
export class MyAPIController {
constructor(
private readonly logger: K5LoggerService,
private petStoreService: PetstoreIntegrationService,
) { }

@Post('/')
async postSomething( req: Request, res: Response): Promise<any> {
this.logger.info(`Starting "postSomething" operation`);
const findPetsResponse = await this.petStoreService.findPetsByStatus({ status: ['pending'] });
return findPetsResponse.data;
}
}

Accessing the Integration Models

K5 SDK exports Integration models, e.g. PetstoreIntegrationModels, which define types for integration API requests and responses, including schemas, query parameters, and headers. These models facilitate type-safe integration by ensuring consistency in request and response structures.

import { Request, Response } from 'express';
import { K5LoggerService, PetstoreIntegrationService, PetstoreIntegrationModels } from 'k5-sdk';

@Controller('/my-api')
export class MyAPIController {
constructor(
private readonly logger: K5LoggerService,
private petStoreService: PetstoreIntegrationService,
) { }

@Post('/')
async postSomething( req: Request, res: Response): Promise<Array<PetstoreIntegrationModels.Pet>> {
this.logger.info(`Starting "postSomething" operation`);

/**
* Status values that need to be considered for filter
* status: Array<'available' | 'pending' | 'sold'>;
*/
const queryParams: PetstoreIntegrationModels.PetstoreServiceFindPetsByStatusQueryParam = { status: ['available'] };

/**
* AxiosResponse<Array<Pet>>
*/
const findPetsResponse: PetstoreIntegrationModels.FindPetsByStatusResponse = await this.petStoreService.findPetsByStatus(queryParams);

return findPetsResponse.data;
}
}

API Binding

The k5 SDK also exports the K5APIBindingService which provides methods to acquire the API bindings of the integration services.

API bindings are externalized specifications created per API dependency. They can be used to store API-related configuration information, that may be stage-dependent.

API bindings are typically used to store, e.g.

  • url
  • username
  • password
  • API-Key
  • ... for the 3rd party service you want to access.

Example binding:

{
"url": "http://example.com/dev"
}

DEV-Bindings

Dev-Bindings provide an easy way to specify some default values, which are easily accessible on all non-production stages. They are meant to be used for rapid development to avoid long and extensive configuration outside of the project.

DEV-Binding can be created and speciified inside the Solution Designer. To do so, you go to the Integration Namespace you want to use for interacting with this API (or create a new namespace) and create an API dependency. There you will find an input field where you can place your information as JSON formatted key/value pairs.

warning

Please be aware, that all information entered into DEV bindings will go into the Git repository! To prevent this, you can instead create an API binding for the same purpose, since they get stored as OpenShift secrets inside the cluster.

Programmatically Access the Binding

API bindings can be accessed through the K5APIBindingService as follows:

import { Request, Response } from 'express';
import { K5LoggerService, K5APIBindingService } from 'k5-sdk';

@Controller('/my-api')
export class MyAPIController {
constructor(
private readonly logger: K5LoggerService,
private bindingService: K5APIBindingService,
) { }

@Post('/')
async postSomething( req: Request, res: Response): Promise<any> {
this.logger.info(`Starting "postSomething" operation`);
const myBinding = await this.bindingService.getPetstoreAPIBinding();
return {};
}
}

Local Development

To set API bindings during local development, create a local configuration file (YAML or JSON format) and place it in your project's root directory. Make sure it's added to the .gitignore file, so it will not get uploaded to your git repository.

This configuration file should then be loaded into the project using the loadConfigFile method provided by k5 SDK.

import { K5SDKModule, loadConfigFile } from 'k5-sdk';

@Module({
imports: [
ConfigModule.forRoot({ load: [loadConfigFile('local-config.yaml')] }),
K5SDKModule.forRoot({}),
],
controllers: [],
providers: [],
})
export class AppModule {}

To setup API bindings in the local config file, simply provide the k5ApiBindings property, containing the API bindings for each integration namespace's API dependency.

k5ApiBindings:
mypet-pet:
url: https://petstore.swagger.io/v2
k5_propagate_security_token: false
customProperty: customValue
ℹ️note

The key of the API bindings is the combination of the integration namespace name and the API dependency name, separated by a hyphen -.

Customization

Customizing the Integration Modules

The Integration modules module can be customized to use custom axios configurations, this is done through the axiosConfig optional property [type: CreateAxiosDefaults] of the forRoot method of the integration module.

import { PetstoreIntegrationModule } from 'k5-sdk';

@Module({
imports: [
PetstoreIntegrationModule.forRoot({
axiosConfig: { baseURL: 'https://petstore.swagger.io/v2/' }, // optional CreateAxiosDefaults
}),
],
controllers: [MyAPIController],
providers: [],
})
export class MyAPIModule {}

Customizing an Integration Method Call

Additionaly, every call to an integration service method can also use a custom config property [type: AxiosRequestConfig] as an optional last argument of the method, this enables customization of the request made to the integration service without overriding the default configuration used by the whole integration module.

import { Request, Response } from 'express';
import { PetstoreIntegrationService, K5LoggerService } from 'k5-sdk';

@Controller('/my-api')
export class MyAPIController {
constructor(
private readonly logger: K5LoggerService,
private petStoreService: PetstoreIntegrationService,
) { }

@Post('/')
async postSomething( req: Request, res: Response): Promise<any> {
this.logger.info(`Starting "postSomething" operation`);
const findPetsResponse = await this.petStoreService.findPetsByStatus(
{ status: ['pending'] },
{ decompress: true }, // optional AxiosRequestConfig
);
return findPetsResponse.data;
}
}