Using TypeScript with SAP CAP

 

Introduction

CAP supports JavaScript out of the box. Setting up TypeScript involves taking some extra steps. Here we go through setting up CAP to use TypeScript.

Original article here.

Project Setup

cds init my-cap-ts-app
cd my-cap-ts-app
npm install

Data Model

Create db/schema.cds as follows:

namespace com.test;
using { managed } from ‘@sap/cds/common’;
entity Data: managed {
  key ID : UUID;
  x: Integer;
  y: Integer;
}

Edit package.json to use SQlite as follows:

{
  ...
  “cds”: {
    “requires”: {
      “db”: {
        “kind”: “sqlite”,
        “credentials”: {
          “database”: “db.sqlite”
        }
      }
    }
  }
}

Define a service by creating srv/test-service.cds:

using { com.test as db } from ‘../db/schema’;
service TestService {
  entity Data as projection on db.Data;
}

At this point you should be able to deploy the project and run it as a usual JavaScript SAP CAP application. Before doing so we configure the project for TypeScript in the following section.

Configuring Project for TypeScript

Start by installing the following development packages:

npm install --save-dev typescript @cap-js/cds-types

Here we installtypescript , the TypeScript compiler, which is used for type checking. We also install @cap-js/cds-types , the official type declarations for @sap/cds

Next, create tsconfig.json in the project root:

{
  “compilerOptions”: {
    “target”: “ES2022”,
    “module”: “NodeNext”,
    “moduleResolution”: “NodeNext”,
    “strict”: true,
    “esModuleInterop”: true,
    “skipLibCheck”: true
  },
  “include”: [”srv/**/*”],
  “exclude”: [”node_modules”, “gen”]
}

The configuration is set up without outDir or rootDir specified because cds-ts , the drop in replacement cds, will run TypeScript directly.

Next adjust the package.json scripts as follows:

“scripts”: {
  “start”: “cds-ts serve”,
  “dev”: “cds-ts watch”
}

At this point you should still be able to deploy the project using either cds deploy or cds-ts deploy and run the project using dsnpm run devor npm run start

Implement Service

We can now implement services in TypeScript. Create srv/test-service.ts:

import cds from ‘@sap/cds’
const LOG = cds.log(”test”);
export class TestService extends cds.ApplicationService {
  async init() {
    this.before(’READ’, ‘Data’, (req) => {
      LOG.log(`[TestService] READ requested by: ${req.user.id}`)
    })
    this.before(’CREATE’, ‘Data’, (req) => {
      const { x, y } = req.data
      if (x == null || y == null) {
        return req.reject(400, ‘Both x and y are required’)
      }
      if (typeof x !== ‘number’ || typeof y !== ‘number’) {
        return req.reject(400, ‘x and y must be numbers’)
      }
    })
    this.after(’CREATE’, ‘Data’, (data: any) => {
      LOG.log(`[TestService] Created record with ID: ${data.ID}`)
    })
    return super.init()
  }
}

Test the Application

Start the server as follows:

npm run start

You can now call the OData endpoints and test the service, for example:

curl -X POST http://localhost:4004/odata/v4/test/Data \
  -H “Content-Type: application/json” \
  -d ‘{”x”: 10, “y”: 20}’

To see the validation get triggered, try the following:

curl -X POST http://localhost:4004/odata/v4/test/Data \
  -H “Content-Type: application/json” \
  -d ‘{”x”: 10}’

This should respond with the following:

{
  “error”: {
    “message”: “Both x and y are required”,
    “code”: “400”,
    “@Common.numericSeverity”: 4
  }
}

References

Comments

Popular Posts