All skills
secondsky avatar

/sap-cap-capire

@620a19a
by Eddiesecondsky/sap-skills456 stars
120

SAP Cloud Application Programming Model (CAP) development skill using Capire documentation. Use when: building CAP applications, defining CDS models, implementing services, working with SAP HANA/SQLite/PostgreSQL databases, deploying to SAP BTP Cloud Foundry or Kyma, implementing Fiori UIs, handling authorization, multitenancy, or messaging. Covers CDL/CQL/CSN syntax, Node.js and Java runtimes, event handlers, OData services, and CAP plugins.

Use this Skill: https://skilld.dev/gh/secondsky/sap-skills/sap-cap-capire

This session only. Nothing lands on disk.

referencescsn-cqn-cxn.md

≈2.2k tokens on demand. Your agent reads this file only when SKILL.md points to it.

CDS Schema & Query Notations Reference

Source: https://cap.cloud.sap/docs/cds/csn, https://cap.cloud.sap/docs/cds/cqn, https://cap.cloud.sap/docs/cds/cxn

CSN - Core Schema Notation

CSN is a compact notation for representing CDS models as plain JavaScript objects.

Root-Level Structure

{
  requires: ['@sap/cds/common', './db/schema'],  // Imported models
  definitions: { /* Named definitions */ },       // Types, entities, services
  extensions: [ /* Unapplied aspects */ ],        // Extensions array
  i18n: { 'de': {}, 'fr': {} }                   // Translations
}

Definition Kinds

Kind Description
context Namespace container
service Service definition
entity Entity definition
type Type definition
action Unbound action
function Unbound function
annotation Annotation definition

Type Definitions

// Scalar types
{ type: "cds.String", length: 100 }
{ type: "cds.Decimal", precision: 11, scale: 3 }
{ type: "cds.Integer" }
{ type: "cds.UUID" }
{ type: "cds.Boolean" }
{ type: "cds.Date" }
{ type: "cds.DateTime" }
{ type: "cds.Timestamp" }

// Structured types
{ elements: {
    foo: { type: "cds.Integer" },
    bar: { type: "cds.String" }
}}

// Array types
{ items: { type: "cds.Integer" } }

// Enumeration types
{ enum: {
    asc: {},
    desc: {},
    custom: { val: 'custom-value' }
}}

Entity Definition

{
  kind: "entity",
  elements: {
    ID: { type: "cds.UUID", key: true },
    name: { type: "cds.String", notNull: true },
    virtual_field: { type: "cds.String", virtual: true }
  }
}

Association Definition

{
  type: "cds.Association",
  target: "Books",
  cardinality: { src: 1, min: 0, max: "*" },
  on: [{ ref: ["author_ID"] }, "=", { ref: ["author", "ID"] }],
  keys: [{ ref: ["ID"] }]
}

Views with Query

{
  kind: "entity",
  query: { SELECT: { from: { ref: ["Books"] }, columns: ["*"] } },
  // or simpler:
  projection: { from: { ref: ["Books"] }, columns: ["*"] }
}

Annotations

{
  '@title': "Display Name",
  '@readonly': true,
  '@UI.LineItem': [{ Value: { '=': 'name' } }]
}

Extensions

{
  extensions: [
    { extend: "Books", includes: ["managed"] },
    { extend: "Books", elements: { newField: { type: "cds.String" } } },
    { annotate: "Books", '@readonly': true }
  ]
}

CQN - Core Query Notation

CQN represents CDS queries as plain JavaScript objects.

Three Ways to Create Queries

// 1. CQL parsing
let query = cds.ql`SELECT from Books`

// 2. Query builder
let query = SELECT.from('Books')

// 3. Direct CQN object
let query = { SELECT: { from: { ref: ['Books'] } } }

// Execute
let results = await cds.run(query)

SELECT Structure

{
  SELECT: {
    distinct: true,           // Optional: distinct results
    count: true,              // Optional: adds $count to result (OData-style)
    one: true,                // Optional: returns single object or undefined (not array)
    from: source,             // Required: source table/view
    columns: column[],        // Optional: projection
    where: expr[],            // Optional: filter
    having: expr[],           // Optional: group filter
    groupBy: expr[],          // Optional: grouping
    orderBy: order[],         // Optional: sorting
    limit: { rows, offset }   // Optional: pagination
  }
}

Result Behavior:

  • Default: Returns array of records [{...}, {...}]
  • one: true: Returns single object {...} or undefined if no match (not array)
  • count: true: Returns records with $count property indicating total matches
  • Always check for undefined/empty results before accessing properties

Source Types

// Simple reference
{ ref: ['Books'] }

// Aliased
{ ref: ['Books'], as: 'b' }

// JOIN
{
  join: 'left',  // 'inner' | 'left' | 'right'
  args: [source1, source2],
  on: expr
}

// Subquery
{ SELECT: { from: { ref: ['Books'] } } }

Column Expressions

// All columns
'*'

// Simple reference
{ ref: ['title'] }

// Aliased
{ ref: ['title'], as: 'bookTitle' }

// With expand (to-many)
{ ref: ['chapters'], expand: ['*'] }

// With inline (flattened)
{ ref: ['author'], inline: ['name', 'country'] }

// Function call
{ func: 'count', args: [{ ref: ['ID'] }], as: 'total' }

WHERE Expressions

// Simple comparison
[{ ref: ['price'] }, '>', { val: 100 }]

// AND/OR
[{ ref: ['price'] }, '>', { val: 100 }, 'and', { ref: ['stock'] }, '>', { val: 0 }]

// IN list
[{ ref: ['status'] }, 'in', { list: [{ val: 'active' }, { val: 'pending' }] }]

// LIKE
[{ ref: ['name'] }, 'like', { val: '%CAP%' }]

// EXISTS subquery
['exists', { SELECT: { from: { ref: ['Orders'] }, where: [...] } }]

ORDER BY

{
  orderBy: [
    { ref: ['price'], sort: 'desc', nulls: 'last' },
    { ref: ['name'], sort: 'asc' }
  ]
}

INSERT

// With entries (name-value pairs)
{
  INSERT: {
    into: { ref: ['Books'] },
    entries: [
      { ID: 201, title: 'Book 1' },
      { ID: 202, title: 'Book 2' }
    ]
  }
}

// With columns and values (single row)
{
  INSERT: {
    into: { ref: ['Books'] },
    columns: ['ID', 'title'],
    values: [201, 'Book 1']
  }
}

// With rows (multiple records)
{
  INSERT: {
    into: { ref: ['Books'] },
    columns: ['ID', 'title'],
    rows: [
      [201, 'Book 1'],
      [202, 'Book 2']
    ]
  }
}

// Deep insert
{
  INSERT: {
    into: { ref: ['Authors'] },
    entries: [{
      ID: 1, name: 'Author',
      books: [
        { ID: 101, title: 'Book 1' },
        { ID: 102, title: 'Book 2' }
      ]
    }]
  }
}

UPDATE

{
  UPDATE: {
    entity: { ref: ['Books'] },
    where: [{ ref: ['ID'] }, '=', { val: 201 }],
    data: { stock: 100 },           // Scalar values only
    with: { stock: { xpr: [{ ref: ['stock'] }, '+', { val: 1 }] } }  // Expressions allowed
  }
}

DELETE

{
  DELETE: {
    from: { ref: ['Books'] },
    where: [{ ref: ['ID'] }, '=', { val: 201 }]
  }
}

UPSERT

{
  UPSERT: {
    into: { ref: ['Books'] },
    entries: [{ ID: 201, title: 'Updated Title', stock: 50 }]
  }
}

CXN - Core Expression Notation

CXN defines the structure of expressions within CQN.

Expression Types

// Literal value
{ val: 'string' }
{ val: 123 }
{ val: true }
{ val: null }

// Special literals
{ val: "2024-01-15", literal: 'date' }
{ val: "13:05:23", literal: 'time' }
{ val: "2024-01-15T13:05:23Z", literal: 'timestamp' }

// Reference
{ ref: ['field'] }
{ ref: ['entity', 'field'] }

// Complex reference with filter
{ ref: [{ id: 'Books', where: [...] }] }

// Function call
{ func: 'sum', args: [{ ref: ['amount'] }] }
{ func: 'concat', args: [{ ref: ['first'] }, { val: ' ' }, { ref: ['last'] }] }

// Expression sequence
{ xpr: [{ ref: ['a'] }, '+', { ref: ['b'] }] }

// List/tuple
{ list: [{ val: 1 }, { val: 2 }, { val: 3 }] }

// Binding parameter
{ ref: ['?'], param: true }
{ ref: ['name'], param: true }

// Subquery
{ SELECT: { from: { ref: ['Books'] } } }

Operators

// Comparison
'=' | '==' | '!=' | '<' | '<=' | '>' | '>='

// Logical
'and' | 'or' | 'not'

// Pattern matching
'like' | 'in' | 'between'

// Null check
'is null' | 'is not null'

// Existence
'exists'

Window Functions

{
  func: 'rank',
  args: [],
  xpr: ['over', {
    partitionBy: [{ ref: ['category'] }],
    orderBy: [{ ref: ['price'], sort: 'desc' }]
  }]
}

CASE Expression

{
  xpr: [
    'case',
    'when', { xpr: [{ ref: ['status'] }, '=', { val: 'A' }] },
    'then', { val: 'Active' },
    'when', { xpr: [{ ref: ['status'] }, '=', { val: 'I' }] },
    'then', { val: 'Inactive' },
    'else', { val: 'Unknown' },
    'end'
  ]
}

Common CDS Built-in Functions

Function Description
concat(a, b) String concatenation
contains(str, sub) String contains check
substring(str, start, len) Extract substring
length(str) String length
tolower(str) Lowercase conversion
toupper(str) Uppercase conversion
trim(str) Remove whitespace
year(date) Extract year
month(date) Extract month
day(date) Extract day
now() Current timestamp
sum(field) Aggregate sum
avg(field) Aggregate average
min(field) Aggregate minimum
max(field) Aggregate maximum
count(field) Count records
countdistinct(field) Count distinct

Source: SKILL.md on GitHub

1 alert16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The analyzed skill is a reference and template package providing guidance for SAP Cloud Application Programming Model (CAP) development, configuration, data privacy, and testing. It contains no executable scripts, hardcoded credentials, or malicious behavior.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    12/34 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 620a19a. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 weeks ago.

Activeupdated 2 months ago
Other metadata
metadata
{
  "maintainer": "Eduard Jiglau",
  "maintainer_email": "hello@sap-ai-skills.com",
  "website": "https://sap-ai-skills.com",
  "version": "2.4.1",
  "last_verified": "2026-02-22",
  "cap_version": "@sap/cds 9.7.x",
  "mcp_version": "@cap-js/mcp-server 0.0.5",
  "lsp_version": "@sap/cds-lsp 9.7.x"
}

README badge

README badge for secondsky/sap-skills/sap-cap-capire