Hi all,
Many of us are leveraging SAP CAP (Node.js with TypeScript) for our projects.
While CAP provides an abstract mechanism to derive RESTful oData services given a CDS data model there's always room for more efficiency and improvement in the implementing communication between business logic, service, and persistence layer.
It shall be noted at this point, that improvements have been attempted with regard to the service layer communication using cds-routing-handler However, this framework does not appear to be maintained, especially for newer versions of CAP.
-
1. CDS-TS-Dispatcher: Simplifying SAP CAP TypeScript Development
2. CDS-TS-Repository: Simplify SAP CAP Entity persistance with BaseRepository
3. SAP CAP: Controller - Service - Repository design pattern
Crafted by developers for developers by ABS & DxFrontier team
-
Before we dive in, you should have a basic understanding of SAP CAP NodeJS and TypeScript. If you need a refresher, here are some helpful resources Official SAP CAP TypeScript
We introduce two powerful npm packages developed by the ABS & DxFrontier team:
In this blog, we will concentrate on the CDS-TS-Dispatcher.
The goal of CDS-TS-Dispatcher is to significantly reduce the boilerplate code required to implement the SAP CAP TypeScript handlers by using TypeScript decorators and Dependency Injection.
Now, let's get started with CDS-TS-Dispatcher. We'll walk you through the steps to integrate it into your SAP CAP TypeScript project, providing code snippets and configuration examples for a smooth onboarding.
Use the following steps if you want to create a new SAP CAP typescript project.
1: We'll start by installing @sap/cds-dk globally
npm i -g @Sap/cds-dk typescript ts-node
2: Create a new folder
mkdir new-sap-cap-project
cd new-sap-cap-project
3: Initialize the CDS folder structure :
cds init
4: Add packages
npm install @dxfrontier/cds-ts-dispatcher
npm install --save-dev @types/node
5: Add tsconfig.json
tsc --init
6: It is recommended to use the following tsconfig.json properties
{
"compilerOptions": {
/* Base Options: */
"esModuleInterop": true,
"skipLibCheck": true,
"allowJs": true,
"strictPropertyInitialization": false,
"forceConsistentCasingInFileNames": true,
"allowSyntheticDefaultImports": true,
"strictNullChecks": true,
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
/* Allow decorators */
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
/* Strictness */
"strict": true,
"lib": ["es2022"],
"outDir": "./gen/srv"
},
"include": ["./srv"]
}
7: Run the CDS-TS server and happy TS coding
cds-ts watch
Example 1 :
Handling after read event using the @AfterRead decorator
import { AfterRead, TypedRequest } from "@dxfrontier/cds-ts-dispatcher";
import { MyEntity } from 'YOUR_CDS_TYPER_ENTITIES_LOCATION';
@AfterRead()
public async afterReadMethod(results: MyEntity[], req: TypedRequest<MyEntity>) {
// ...
}
Example 2:
Handling after read, before read, and singe instance capable using the @AfterRead, @SingleInstanceCapable & @BeforeRead decorators.
import { AfterRead, SingleInstanceCapable, BeforeRead, TypedRequest } from '@dxfrontier/cds-ts-dispatcher';
@AfterRead() // Will handle single instance and entity set
@SingleInstanceCapable() // All methods above '@SingleInstanceCapable()' will be triggered when single instance is requested and entity set
@BeforeRead() // Will handle only entity set
public async singeInstanceMethodAndEntitySet(results : MyEntity[], req: TypedRequest<MyEntity>, isSingleInstance: boolean) {
if(isSingleInstance) {
return this.customerService.handleSingleInstance(req)
}
return this.customerService.handleEntitySet(req)
}
Example 3:
Handling Dependency injection by using the @Inject decorator
import { EntityHandler, Inject } from '@dxfrontier/cds-ts-dispatcher';
import type { Service } from '@dxfrontier/cds-ts-dispatcher';
@EntityHandler(MyEntity)
class CustomerHandler {
@Inject(CustomerService) private customerService: CustomerService
@Inject(SRV) private srv: Service
// ...
constructor() {}
// ...
}
Example 4:
Bootstrap is very simple :
import { CDSDispatcher } from '@dxfrontier/cds-ts-dispatcher';
export = new CDSDispatcher([
// Entities
BookHandler,
// ...
]).initialize();
Simplify Entity Manipulation with CDS-QL: BaseRepository
The goal of CDS-QL BaseRepository is to significantly reduce the boilerplate code required to implement data access layers for persistence entities by providing out-of-the-box actions on the database. It offers a simplified interface for common database actions such as :
import { Repository } from '@dxfrontier/cds-ts-dispatcher';
import { BaseRepository } from '@dxfrontier/cds-ts-repository';
import { MyEntity } from 'YOUR_CDS_TYPER_ENTITIES_LOCATION';
@Repository()
export class CustomerRepository extends BaseRepository<MyEntity> {
constructor() {
super(MyEntity);
}
public async aMethod() {
const created = await this.create(...)
const createdMany = await this.createMany(...)
const updated = await this.update(...)
const exists = await this.exists(...)
const delete = await this.delete(...)
const deleteMany = await this.deleteMany(...)
// ...
}
}
You can find additional documentation for BaseRepository at CDS-TS-Repository GitHub
In conclusion, CDS-TS-Dispatcher combined with CDS-TS-Repository is a powerful tool that can speed up your SAP CAP TypeScript projects by eliminating repetitive code and being a better fit for common team architecture setups.
Find an example of usage of the CDS-TS-Samples GitHub
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
9 | |
8 | |
5 | |
5 | |
4 | |
4 | |
4 | |
3 | |
3 | |
3 |