4.0.3 • Published 1 month ago

nestjs-sap-rfc v4.0.3

Weekly downloads
-
License
MIT
Repository
github
Last release
1 month ago

GitHub CodeQL Sonar CI Publish GitHub package.json version GitHub package.json dependency version (prod) semantic-release Commitizen friendly code style: prettier Conventional Commits Quality Gate Status Coverage Code Smells Vulnerabilities Security Rating GitHub repo size npm npm type definitions npm

📚 Description

NestJS SAP RFC Client, providing convenient ABAP business logic consumption from NestJS

🛠️ Installation

SAP NWRFC SDK installation

npm install nestjs-sap-rfc --save

🏃 Getting Started

Register SapModule module in app.module.ts

Connection Pool

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 {}

Direct Client

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,
    });
  }
}

Creating and using transactions

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.

✅ Test

# unit tests
$ npm run test

# test coverage
$ npm run test:cov

💡 Generate Docs

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

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.

🔨 Built With

✔️ Roadmap

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
4.0.3

1 month ago

4.0.2

1 month ago

4.0.1

3 months ago

4.0.0

4 months ago

3.0.32

5 months ago

3.0.33

5 months ago

3.0.31

5 months ago

3.0.30

5 months ago

3.0.27

7 months ago

3.0.28

5 months ago

3.0.26

7 months ago

3.0.29

5 months ago

3.0.25

8 months ago

3.0.17

11 months ago

3.0.23

9 months ago

3.0.24

8 months ago

3.0.21

9 months ago

3.0.22

9 months ago

3.0.20

10 months ago

3.0.18

11 months ago

3.0.19

10 months ago

3.0.16

1 year ago

3.0.9

1 year ago

3.0.12

1 year ago

3.0.13

1 year ago

3.0.10

1 year ago

3.0.11

1 year ago

3.0.14

1 year ago

3.0.15

1 year ago

3.0.4

2 years ago

3.0.3

2 years ago

3.0.8

1 year ago

3.0.7

1 year ago

3.0.6

1 year ago

3.0.5

2 years ago

3.0.2

2 years ago

3.0.1

2 years ago

1.4.0

2 years ago

2.0.3

2 years ago

2.0.2

2 years ago

2.0.5

2 years ago

2.0.4

2 years ago

2.0.6

2 years ago

1.3.10

2 years ago

1.3.11

2 years ago

2.0.1

2 years ago

2.0.0

2 years ago

3.0.0

2 years ago

1.3.9

2 years ago

1.3.7

2 years ago

1.3.6

2 years ago

1.3.5

2 years ago

1.3.8

2 years ago

1.2.9

2 years ago

1.3.4

2 years ago

1.3.3

2 years ago

1.3.2

2 years ago

1.3.1

2 years ago

1.3.0

2 years ago

1.2.8

2 years ago

1.2.7

2 years ago

1.2.6

2 years ago

1.2.5

2 years ago