NestJS SAP RFC Client
NestJS SAP RFC Client, providing convenient ABAP business logic consumption from NestJS
npm install nestjs-sap-rfc --save
Register SapModule
module in app.module.ts
import { SapModule } from 'nestjs-sap-rfc';
import { Module } from '@nestjs/common';
@Module({
imports: [
SapModule.createPool({
isGlobal: true, // for global module
name: 'service_name', // for multiple modules (OPTIONAL)
connectionParameters: {
/* see RfcConnectionParameters */
},
clientOptions: {
/* see RfcClientOptions */
},
poolOptions: {
/* see RfcPoolOptions */
},
}),
],
})
export class AppModule {}
Connection Pool (Async Module)
import { SapModule } from 'nestjs-sap-rfc';
import { Module } from '@nestjs/common';
@Module({
imports: [
SapModule.createPoolAsync({
isGlobal: true, // for global module
name: 'service_name', // for multiple modules (OPTIONAL)
useFactory: () => {
return {
connectionParameters: {
/* see RfcConnectionParameters */
},
clientOptions: {
/* see RfcClientOptions */
},
poolOptions: {
/* see RfcPoolOptions */
},
};
},
}),
],
})
export class AppModule {}
Connection Pool (Async Module + ConfigService)
import { SapModule } from 'nestjs-sap-rfc';
import { Module } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@Module({
imports: [
SapModule.createPoolAsync({
isGlobal: true, // for global module
name: 'service_name', // for multiple modules (OPTIONAL)
useFactory: (config: ConfigService) => {
return {
connectionParameters: {
/* see RfcConnectionParameters */
/* config.get(...) */
},
clientOptions: {
/* see RfcClientOptions */
/* config.get(...) */
},
poolOptions: {
/* see RfcPoolOptions */
/* config.get(...) */
},
};
},
inject: [ConfigService],
}),
],
})
export class AppModule {}
import { SapModule } from 'nestjs-sap-rfc';
import { Module } from '@nestjs/common';
@Module({
imports: [
SapModule.createClient({
isGlobal: true, // for global module
name: 'service_name', // for multiple modules (OPTIONAL)
connectionParameters: {
/* see RfcConnectionParameters */
},
clientOptions: {
/* see RfcClientOptions */
},
}),
],
})
export class AppModule {}
Direct Client (Async Module)
import { SapModule } from 'nestjs-sap-rfc';
import { Module } from '@nestjs/common';
@Module({
imports: [
SapModule.createClientAsync({
isGlobal: true, // for global module
name: 'service_name', // for multiple modules (OPTIONAL)
useFactory: () => {
return {
connectionParameters: {
/* see RfcConnectionParameters */
},
clientOptions: {
/* see RfcClientOptions */
},
};
},
}),
],
})
export class AppModule {}
Direct Client (Async Module + ConfigService)
import { SapModule } from 'nestjs-sap-rfc';
import { Module } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@Module({
imports: [
SapModule.createClientAsync({
isGlobal: true, // for global module
name: 'service_name', // for multiple modules (OPTIONAL)
useFactory: (config: ConfigService) => {
return {
connectionParameters: {
/* see RfcConnectionParameters */
},
clientOptions: {
/* see RfcClientOptions */
},
};
},
inject: [ConfigService],
}),
],
})
export class AppModule {}
Inject SapService
import { InjectSapService, SapService, SapRfcObject, SapRfcStructure } from 'nestjs-sap-rfc';
import { Injectable } from '@nestjs/common';
// RfcStructure
type PositionData = SapRfcStructure; // SAP structure
// RfcStructure
interface NestedData extends SapRfcStructure {
readonly E_NESTED?: string; // SAP field name
}
// MySapInterface
interface MySapInterface extends SapRfcObject {
readonly E_NAME?: string; // SAP field name
readonly E_DATA?: PositionData; // SAP field name
readonly E_DATA2?: NestedData; // SAP field name
readonly E_ERROR?: string; // SAP field name
readonly I_OBJID?: string; // SAP field name
}
@Injectable()
export class MyService {
/**
* @param {SapService} sapService
*/
constructor(
@InjectSapService()
private readonly sapService: SapService,
) {}
public async test(): MySapInterface {
return this.sapService.execute<MySapInterface>('rfcName', {
...rfcParams,
});
}
}
Inject SapService by name
import { InjectSapService, SapService, SapRfcObject, SapRfcStructure } from 'nestjs-sap-rfc';
import { Injectable } from '@nestjs/common';
// RfcStructure
type PositionData = SapRfcStructure; // SAP structure
// RfcStructure
interface NestedData extends SapRfcStructure {
readonly E_NESTED?: string; // SAP field name
}
// MySapInterface
interface MySapInterface extends SapRfcObject {
readonly E_NAME?: string; // SAP field name
readonly E_DATA?: PositionData; // SAP field name
readonly E_DATA2?: NestedData; // SAP field name
readonly E_ERROR?: string; // SAP field name
readonly I_OBJID?: string; // SAP field name
}
@Injectable()
export class MyService {
/**
* @param {SapService} sapService
*/
constructor(
@InjectSapService('service_name')
private readonly sapService: SapService,
) {}
public async test(): MySapInterface {
return this.sapService.execute<MySapInterface>('rfcName', {
...rfcParams,
});
}
}
Transactions are created using SapService. Example:
import { InjectSapService, SapService, SapRfcObject, SapRfcStructure } from 'nestjs-sap-rfc';
import { Injectable } from '@nestjs/common';
// RfcStructure
type PositionData = SapRfcStructure; // SAP structure
// RfcStructure
interface NestedData extends SapRfcStructure {
readonly E_NESTED?: string; // SAP field name
}
// MySapInterface
interface MySapInterface extends SapRfcObject {
readonly E_NAME?: string; // SAP field name
readonly E_DATA?: PositionData; // SAP field name
readonly E_DATA2?: NestedData; // SAP field name
readonly E_ERROR?: string; // SAP field name
readonly I_OBJID?: string; // SAP field name
}
@Injectable()
export class MyService {
/**
* @param {SapService} sapService
*/
constructor(
@InjectSapService()
private readonly sapService: SapService,
) {}
public async runTransaction(): MySapInterface {
await this.sapService.transaction(async (sapClient: SapClient) => {
// call rfcs using sapClient
});
}
}
Everything you want to run in a transaction must be executed in a callback:
@Injectable()
export class MyService {
/**
* @param {SapService} sapService
*/
constructor(
@InjectSapService()
private readonly sapService: SapService,
) {}
public async runTransaction(): MySapInterface {
await this.sapService.transaction(async (sapClient: SapClient) => {
await sapClient.call('rfcName_1', {
...rfcParams,
});
await sapClient.call('rfcName_2', {
...rfcParams,
});
});
}
}
The most important restriction when working in a transaction is to ALWAYS use the provided instance of SapClient. All operations MUST be executed using the provided SapClient.
# unit tests
$ npm run test
# test coverage
$ npm run test:cov
The docs can be generated on-demand. This will produce a documentation folder with the required front-end files.
# generate docs for code
$ npm run doc
# generate docs for code and serve on http://localhost:8080
$ npm run doc:serve
commitizen is a command line utility that makes it easier to create commit messages following the conventional commit format specification.
Use npm run commit
instead of git commit
to use commitizen.
The following improvements are currently in progress:
- Dynamic Configuration
- Transaction with auto commit and rollback
- Resource injection by name
- Update to node-rfc 3.x