@abapify/acds

中文文档
0.4.33发布于 2026/11/02MITTypeScriptES Module构建来源已验证近 30 天下载 2573

ABAP CDS source parser — tokenizer, parser, and AST for all DDL-based ABAP source types

原始使用文档
文档目录11 节
  1. Overview
  2. Supported Definitions
  3. Parser Features
  4. Installation
  5. Quick Start
  6. API
  7. parse(source: string): ParseResult
  8. AST Types
  9. Architecture
  10. Roadmap
  11. Dependencies

@abapify/acds

ABAP CDS source parser — tokenizer, parser, and typed AST for DDL-based ABAP source types.

Overview

Parses .acds (ABAP CDS DDL) source code into a fully typed Abstract Syntax Tree. Built on Chevrotain for fast, error-recovering parsing.

Supported Definitions

CDS ConstructAST NodeExample
TableTableDefinitiondefine table [entity] ztable { ... }
Root table ent.TableDefinitiondefine root table entity ztable { ... }
StructureStructureDefinitiondefine structure zstruct { ... }
Simple typeSimpleTypeDefinitiondefine type ztype : abap.char(10);
View entityViewEntityDefinitiondefine [root] view entity zv as select ...
Legacy viewViewEntityDefinitiondefine view zv as select ... (legacy)
Abstract entityAbstractEntityDefinitiondefine abstract entity zae { ... }
Custom entityCustomEntityDefinitiondefine custom entity zce { ... }
External entityExternalEntityDefinitiondefine external entity zee { ... } with federated data provided at runtime;
Table functionTableFunctionDefinitiondefine table function ztf returns { ... }
Scalar functionScalarFunctionDefinitiondefine scalar function zsf ...
HierarchyHierarchyDefinitiondefine hierarchy zh as parent child hierarchy(...) { ... }
AspectAspectDefinitiondefine aspect za { ... }
AnnotationAnnotationDefinitiondefine annotation za: Boolean;
Access policyAccessPolicyDefinitiondefine accesspolicy zap { ... }
ServiceServiceDefinitiondefine service zsvc { ... }
ExtensionExtensionDefinitionextend view entity zv with { ... }
Metadata ext.MetadataExtensionannotate entity ZView with { ... }
Role (DCL)RoleDefinitiondefine role zr { grant select ... }

Parser Features

  • Error recovery — returns partial AST + structured errors on invalid input
  • Full annotation support — strings, enums, booleans, numbers, arrays, objects
  • Built-in types — abap.char(10), abap.dec(11,2), abap.dats, etc.
  • Named types — data element and qualified name references
  • Include directives — include <structure> with optional suffix
  • Comments — line (//, --) and block (/* */) comments are skipped
  • Case-insensitive keywords — DEFINE VIEW ENTITY and define view entity both parse; identifiers keep their original spelling
  • FROM clause — join chains, parameterized sources, FROM associations
  • View flavours — define view entity <name> and the legacy define view <name>
  • Projection elements — paths, calls (coalesce(a, b), sum(x)) and cast(x as type [preserving type])

Installation

bun add @abapify/acds

Quick Start

import { parse } from '@abapify/acds';

const result = parse(`
  @AbapCatalog.tableCategory : #TRANSPARENT
  @AbapCatalog.deliveryClass : #A
  define table ztable {
    key mandt : abap.clnt not null;
    key field1 : abap.char(10) not null;
    field2 : some_data_element;
  }
`);

if (result.errors.length === 0) {
  const table = result.ast.definitions[0]; // TableDefinition
  console.log(table.kind); // 'table'
  console.log(table.name); // 'ztable'
  console.log(table.members); // [FieldDefinition, FieldDefinition, ...]
  console.log(table.annotations); // [Annotation, Annotation]
}

API

parse(source: string): ParseResult

Parses a CDS source string through the full pipeline: tokenize → parse → visit.

interface ParseResult {
  /** The parsed AST (may be partial if there are errors) */
  ast: CdsSourceFile;
  /** Lexing and parsing errors */
  errors: CdsParseError[];
}

AST Types

Root

interface CdsSourceFile {
  definitions: CdsDefinition[];
}

type CdsDefinition =
  | TableDefinition
  | StructureDefinition
  | SimpleTypeDefinition
  | ViewEntityDefinition
  | AbstractEntityDefinition
  | CustomEntityDefinition
  | ExternalEntityDefinition
  | TableFunctionDefinition
  | ScalarFunctionDefinition
  | HierarchyDefinition
  | AspectDefinition
  | AnnotationDefinition
  | AccessPolicyDefinition
  | ServiceDefinition
  | ExtensionDefinition
  | MetadataExtension
  | RoleDefinition;

Definitions

interface TableDefinition {
  kind: 'table';
  name: string;
  annotations: Annotation[];
  members: TableMember[]; // FieldDefinition | IncludeDirective
}

interface StructureDefinition {
  kind: 'structure';
  name: string;
  annotations: Annotation[];
  members: TableMember[];
}

interface SimpleTypeDefinition {
  kind: 'simpleType';
  name: string;
  annotations: Annotation[];
  type: TypeRef;
}

interface ServiceDefinition {
  kind: 'service';
  name: string;
  annotations: Annotation[];
  exposes: ExposeStatement[];
}

interface MetadataExtension {
  kind: 'metadataExtension';
  entity: string;
  annotations: Annotation[];
  elements: AnnotatedElement[];
}

Fields & Types

interface FieldDefinition {
  annotations: Annotation[];
  name: string;
  type: TypeRef;
  isKey: boolean;
  notNull: boolean;
}

type TypeRef = BuiltinTypeRef | NamedTypeRef;

// abap.char(10), abap.dec(11,2)
interface BuiltinTypeRef {
  kind: 'builtin';
  name: string;
  length?: number;
  decimals?: number;
}

// Data element or qualified name
interface NamedTypeRef {
  kind: 'named';
  name: string;
}

Annotations

interface Annotation {
  key: string;
  value: AnnotationValue;
}

type AnnotationValue =
  | { kind: 'string'; value: string }
  | { kind: 'enum'; value: string } // #TRANSPARENT → 'TRANSPARENT'
  | { kind: 'boolean'; value: boolean }
  | { kind: 'number'; value: number }
  | { kind: 'array'; items: AnnotationValue[] }
  | { kind: 'object'; properties: AnnotationProperty[] };

FROM clause (view entities)

interface ViewEntityDefinition {
  kind: 'viewEntity';
  name: string;
  annotations: Annotation[];
  legacy?: boolean; // true for the legacy `define view <name>` syntax
  root?: boolean; // `define root view entity`
  writable?: boolean; // `define writable view entity`
  providerContract?: string; // `provider contract transactional_query`
  sourceKind: DataSourceKind; // 'select' | 'projection'
  distinct?: boolean; // `select distinct`
  source: DataSource; // the root data source
  joins: JoinClause[]; // ordered join chain — empty when there are no joins
  fromAssociations?: AssociationDeclaration[]; // associations of the FROM region
  aspectBindings?: AspectBinding[]; // `bind aspect` bindings
  parameters: ParameterDefinition[];
  members: ViewMember[];
  where?: Expression;
  groupBy?: string[];
  having?: Expression;
  setOperations?: SetOperation[]; // union/intersect/except branches
}

interface DataSource {
  name: string;
  alias?: string;
  parameters?: DataSourceParameter[]; // parameterized source
}

interface DataSourceParameter {
  name: string; // e.g. 'P_StartDate'
  value: string; // raw binding: ':P_Key1StartDate', '$session.client', "'X'"
}

type JoinType = 'inner' | 'leftOuter' | 'rightOuter' | 'fullOuter' | 'cross';

// Conditioned joins always carry an ON condition — the grammar enforces it.
interface ConditionedJoinClause {
  kind: 'join';
  joinType: 'inner' | 'leftOuter' | 'rightOuter' | 'fullOuter';
  source: JoinSource; // DataSource | JoinGroup
  on: Expression; // the ON condition (opaque)
  cardinality?: WordCardinality; // `many to one join` / `to one join`
}

// A cross join never carries an ON condition.
interface CrossJoinClause {
  kind: 'join';
  joinType: 'cross';
  source: JoinSource;
}

type JoinClause = ConditionedJoinClause | CrossJoinClause;

// A join source is either a plain data source or a parenthesized group.
type JoinSource = DataSource | JoinGroup;

// `join (A join B on …) on …` — the group acts as a single join source.
interface JoinGroup {
  kind: 'joinGroup';
  source: JoinSource; // nested — may itself be a group
  joins: JoinClause[]; // the join chain inside the parentheses
}

Supported join spellings (normalized to JoinType):

spellingjoinTypeNotes
JOINinner
INNER JOINinner
LEFT JOINleftOuterOUTER is optional
LEFT OUTER JOINleftOuter
RIGHT JOINrightOuterOUTER is optional
RIGHT OUTER JOINrightOuter
FULL JOINfullOuterOUTER is optional
FULL OUTER JOINfullOuter
CROSS JOINcrossmust not carry an ON condition

The ON condition is required for inner and outer joins and not allowed for a cross join — the grammar enforces this.

The accepted join syntax is the same for every view flavour: a CDS view entity (define view entity) and a classic SQL view (define view) accept exactly the same spellings. FULL [OUTER] JOIN is the SQL-standard full outer join — it is not part of the ABAP CDS DDL join syntax, but it is supported so that HANA CDS / CAP CDS sources (which use the standard SQL join syntax) can be read with the same parser.

Example:

const { ast } = parse(`
  define view entity ZC_Cube as select from I_Item as _Item
    left outer join ZI_Other as _Other
      on _Item.key = _Other.key
    association [0..1] to I_Product as _Product
      on $projection.Product = _Product.Product
  {
    key _Item.key
  }
`);

const view = ast.definitions[0] as ViewEntityDefinition;
view.joins[0].joinType; // 'leftOuter'
view.joins[0].source.alias; // '_Other'
view.fromAssociations?.[0].target; // 'I_Product'

Errors

interface CdsParseError {
  message: string;
  line: number;
  column: number;
  offset: number;
  length: number;
}

Architecture

Source string
  → CdsLexer (Chevrotain Lexer)     tokens.ts
  → CdsParser (Chevrotain CstParser) parser.ts
  → CdsVisitor (CST → AST)           visitor.ts
  → CdsSourceFile                     ast.ts
ModuleResponsibility
tokens.tsToken definitions (keywords, symbols, literals)
parser.tsGrammar rules (CST production)
visitor.tsCST → typed AST transformation
ast.tsAST node type definitions
errors.tsError normalization (lex + parse)
index.tsparse() entry point + re-exports

Roadmap

  • ✅ DDL: tables, structures, simple types, view entities (define [root] view entity, projection views + provider contract), legacy define view, abstract/custom/table/external entities, table/scalar functions, hierarchies, aspects (DRAS), DDLA annotation definitions, access policies, services (SRVD), metadata extensions (DDLX), extend view/entity forms, parameters, associations, compositions
  • ✅ DCL: role definitions — switchable, grant-select + where, with optional elements, combination mode and|or|redefinition, inherit, inheriting conditions
  • ✅ Annotations: full value grammar (strings, enums, booleans, numbers, arrays, objects, dotted keys)
  • ✅ Tooling: AST walker helpers, semantic validators (SemanticDiagnostic), grammar coverage metadata
  • ✅ FROM clause: join chains (inner, left [outer], right [outer], full [outer], cross) with word cardinalities and grouped joins, parameterized sources, FROM associations, path-expression data sources (_assoc[ ... ]), bind aspect
  • ✅ Elements: case … end, arithmetic, casts, calls (incl. f()), window over (…), paths, : localized, : redirected to, distinct, where/group by/having, union [all]/intersect/except
  • 🔜 Expression grammar (structured on/where trees — currently opaque { source, tokens })
  • 🔜 BDEF / behavior definitions (owned by epic E10)

Dependencies

  • chevrotain — Parser toolkit (lexer + CstParser + visitor)

版本与发布记录

@abapify/acds 共发布 28 个版本,首次发布于 2026/04/21;过去 12 个月发布了 28 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.4.33latest2026/11/025 天前
0.4.312026/11/016 天前
0.4.292026/10/308 天前
0.4.272026/10/308 天前
0.4.252026/10/309 天前
0.4.232026/10/2612 天前

关于 @abapify/acds 的常见问题

@abapify/acds 是什么?

ABAP CDS source parser — tokenizer, parser, and AST for all DDL-based ABAP source types

如何安装 @abapify/acds?

在项目目录运行 npm install @abapify/acds,或使用 pnpm add / yarn add / bun add。

@abapify/acds 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@abapify/acds 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@abapify/acds 可以商用吗?

@abapify/acds 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@abapify/acds 的下载量有多少?

根据 npm 官方下载统计,@abapify/acds 在 2026/10/05 – 2026/11/03 这 30 天内被下载 2,573 次,日均约 86 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@abapify/acds 还在维护吗?

最新版本 0.4.33 发布于 2026/11/02(5 天前);至今共发布 28 个版本,其中过去 12 个月发布了 28 个;首次发布于 2026/04/21。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。