@abapify/acds 0.4.15 → 0.4.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,13 +8,27 @@ Parses `.acds` (ABAP CDS DDL) source code into a fully typed Abstract Syntax Tre
8
8
 
9
9
  ### Supported Definitions
10
10
 
11
- | CDS Construct | AST Node | Example |
12
- | ------------- | ---------------------- | ------------------------------------ |
13
- | Table | `TableDefinition` | `define table ztable { ... }` |
14
- | Structure | `StructureDefinition` | `define structure zstruct { ... }` |
15
- | Simple type | `SimpleTypeDefinition` | `define type ztype : abap.char(10);` |
16
- | Service | `ServiceDefinition` | `define service zsvc { ... }` |
17
- | Metadata ext. | `MetadataExtension` | `annotate entity ZView with { ... }` |
11
+ | CDS Construct | AST Node | Example |
12
+ | --------------- | -------------------------- | ----------------------------------------------------------------------------- |
13
+ | Table | `TableDefinition` | `define table [entity] ztable { ... }` |
14
+ | Root table ent. | `TableDefinition` | `define root table entity ztable { ... }` |
15
+ | Structure | `StructureDefinition` | `define structure zstruct { ... }` |
16
+ | Simple type | `SimpleTypeDefinition` | `define type ztype : abap.char(10);` |
17
+ | View entity | `ViewEntityDefinition` | `define [root] view entity zv as select ...` |
18
+ | Legacy view | `ViewEntityDefinition` | `define view zv as select ...` (`legacy`) |
19
+ | Abstract entity | `AbstractEntityDefinition` | `define abstract entity zae { ... }` |
20
+ | Custom entity | `CustomEntityDefinition` | `define custom entity zce { ... }` |
21
+ | External entity | `ExternalEntityDefinition` | `define external entity zee { ... } with federated data provided at runtime;` |
22
+ | Table function | `TableFunctionDefinition` | `define table function ztf returns { ... }` |
23
+ | Scalar function | `ScalarFunctionDefinition` | `define scalar function zsf ...` |
24
+ | Hierarchy | `HierarchyDefinition` | `define hierarchy zh as parent child hierarchy(...) { ... }` |
25
+ | Aspect | `AspectDefinition` | `define aspect za { ... }` |
26
+ | Annotation | `AnnotationDefinition` | `define annotation za: Boolean;` |
27
+ | Access policy | `AccessPolicyDefinition` | `define accesspolicy zap { ... }` |
28
+ | Service | `ServiceDefinition` | `define service zsvc { ... }` |
29
+ | Extension | `ExtensionDefinition` | `extend view entity zv with { ... }` |
30
+ | Metadata ext. | `MetadataExtension` | `annotate entity ZView with { ... }` |
31
+ | Role (DCL) | `RoleDefinition` | `define role zr { grant select ... }` |
18
32
 
19
33
  ### Parser Features
20
34
 
@@ -23,7 +37,11 @@ Parses `.acds` (ABAP CDS DDL) source code into a fully typed Abstract Syntax Tre
23
37
  - **Built-in types** — `abap.char(10)`, `abap.dec(11,2)`, `abap.dats`, etc.
24
38
  - **Named types** — data element and qualified name references
25
39
  - **Include directives** — `include <structure>` with optional suffix
26
- - **Comments** — line (`//`) and block (`/* */`) comments are skipped
40
+ - **Comments** — line (`//`, `--`) and block (`/* */`) comments are skipped
41
+ - **Case-insensitive keywords** — `DEFINE VIEW ENTITY` and `define view entity` both parse; identifiers keep their original spelling
42
+ - **FROM clause** — join chains, parameterized sources, FROM associations
43
+ - **View flavours** — `define view entity <name>` and the legacy `define view <name>`
44
+ - **Projection elements** — paths, calls (`coalesce(a, b)`, `sum(x)`) and `cast(x as type [preserving type])`
27
45
 
28
46
  ## Installation
29
47
 
@@ -83,10 +101,20 @@ type CdsDefinition =
83
101
  | TableDefinition
84
102
  | StructureDefinition
85
103
  | SimpleTypeDefinition
104
+ | ViewEntityDefinition
105
+ | AbstractEntityDefinition
106
+ | CustomEntityDefinition
107
+ | ExternalEntityDefinition
108
+ | TableFunctionDefinition
109
+ | ScalarFunctionDefinition
110
+ | HierarchyDefinition
111
+ | AspectDefinition
112
+ | AnnotationDefinition
113
+ | AccessPolicyDefinition
86
114
  | ServiceDefinition
115
+ | ExtensionDefinition
87
116
  | MetadataExtension
88
- | RoleDefinition // Phase 2 placeholder
89
- | ViewEntityDefinition; // Phase 3 placeholder
117
+ | RoleDefinition;
90
118
  ```
91
119
 
92
120
  #### Definitions
@@ -173,6 +201,117 @@ type AnnotationValue =
173
201
  | { kind: 'object'; properties: AnnotationProperty[] };
174
202
  ```
175
203
 
204
+ #### FROM clause (view entities)
205
+
206
+ ```typescript
207
+ interface ViewEntityDefinition {
208
+ kind: 'viewEntity';
209
+ name: string;
210
+ annotations: Annotation[];
211
+ legacy?: boolean; // true for the legacy `define view <name>` syntax
212
+ root?: boolean; // `define root view entity`
213
+ writable?: boolean; // `define writable view entity`
214
+ providerContract?: string; // `provider contract transactional_query`
215
+ sourceKind: DataSourceKind; // 'select' | 'projection'
216
+ distinct?: boolean; // `select distinct`
217
+ source: DataSource; // the root data source
218
+ joins: JoinClause[]; // ordered join chain — empty when there are no joins
219
+ fromAssociations?: AssociationDeclaration[]; // associations of the FROM region
220
+ aspectBindings?: AspectBinding[]; // `bind aspect` bindings
221
+ parameters: ParameterDefinition[];
222
+ members: ViewMember[];
223
+ where?: Expression;
224
+ groupBy?: string[];
225
+ having?: Expression;
226
+ setOperations?: SetOperation[]; // union/intersect/except branches
227
+ }
228
+
229
+ interface DataSource {
230
+ name: string;
231
+ alias?: string;
232
+ parameters?: DataSourceParameter[]; // parameterized source
233
+ }
234
+
235
+ interface DataSourceParameter {
236
+ name: string; // e.g. 'P_StartDate'
237
+ value: string; // raw binding: ':P_Key1StartDate', '$session.client', "'X'"
238
+ }
239
+
240
+ type JoinType = 'inner' | 'leftOuter' | 'rightOuter' | 'fullOuter' | 'cross';
241
+
242
+ // Conditioned joins always carry an ON condition — the grammar enforces it.
243
+ interface ConditionedJoinClause {
244
+ kind: 'join';
245
+ joinType: 'inner' | 'leftOuter' | 'rightOuter' | 'fullOuter';
246
+ source: JoinSource; // DataSource | JoinGroup
247
+ on: Expression; // the ON condition (opaque)
248
+ cardinality?: WordCardinality; // `many to one join` / `to one join`
249
+ }
250
+
251
+ // A cross join never carries an ON condition.
252
+ interface CrossJoinClause {
253
+ kind: 'join';
254
+ joinType: 'cross';
255
+ source: JoinSource;
256
+ }
257
+
258
+ type JoinClause = ConditionedJoinClause | CrossJoinClause;
259
+
260
+ // A join source is either a plain data source or a parenthesized group.
261
+ type JoinSource = DataSource | JoinGroup;
262
+
263
+ // `join (A join B on …) on …` — the group acts as a single join source.
264
+ interface JoinGroup {
265
+ kind: 'joinGroup';
266
+ source: JoinSource; // nested — may itself be a group
267
+ joins: JoinClause[]; // the join chain inside the parentheses
268
+ }
269
+ ```
270
+
271
+ Supported join spellings (normalized to `JoinType`):
272
+
273
+ | spelling | `joinType` | Notes |
274
+ | ------------------ | ------------ | -------------------------------- |
275
+ | `JOIN` | `inner` | |
276
+ | `INNER JOIN` | `inner` | |
277
+ | `LEFT JOIN` | `leftOuter` | `OUTER` is optional |
278
+ | `LEFT OUTER JOIN` | `leftOuter` | |
279
+ | `RIGHT JOIN` | `rightOuter` | `OUTER` is optional |
280
+ | `RIGHT OUTER JOIN` | `rightOuter` | |
281
+ | `FULL JOIN` | `fullOuter` | `OUTER` is optional |
282
+ | `FULL OUTER JOIN` | `fullOuter` | |
283
+ | `CROSS JOIN` | `cross` | must not carry an `ON` condition |
284
+
285
+ The `ON` condition is **required** for inner and outer joins and **not allowed**
286
+ for a cross join — the grammar enforces this.
287
+
288
+ The accepted join syntax is the same for every view flavour: a CDS view entity
289
+ (`define view entity`) and a classic SQL view (`define view`) accept exactly the
290
+ same spellings. `FULL [OUTER] JOIN` is the SQL-standard full outer join — it is
291
+ not part of the ABAP CDS DDL join syntax, but it is supported so that HANA CDS /
292
+ CAP CDS sources (which use the standard SQL join syntax) can be read with the
293
+ same parser.
294
+
295
+ Example:
296
+
297
+ ```typescript
298
+ const { ast } = parse(`
299
+ define view entity ZC_Cube as select from I_Item as _Item
300
+ left outer join ZI_Other as _Other
301
+ on _Item.key = _Other.key
302
+ association [0..1] to I_Product as _Product
303
+ on $projection.Product = _Product.Product
304
+ {
305
+ key _Item.key
306
+ }
307
+ `);
308
+
309
+ const view = ast.definitions[0] as ViewEntityDefinition;
310
+ view.joins[0].joinType; // 'leftOuter'
311
+ view.joins[0].source.alias; // '_Other'
312
+ view.fromAssociations?.[0].target; // 'I_Product'
313
+ ```
314
+
176
315
  #### Errors
177
316
 
178
317
  ```typescript
@@ -206,13 +345,13 @@ Source string
206
345
 
207
346
  ## Roadmap
208
347
 
209
- - ✅ **DDL**: tables, structures, simple types, view entities, projection views, abstract/custom entities, services (SRVD), metadata extensions (DDLX), parameters, associations, compositions
210
- - ✅ **DCL**: role definitions with grant-select + where clauses
348
+ - ✅ **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
349
+ - ✅ **DCL**: role definitions — `switchable`, grant-select + `where`, `with optional elements`, `combination mode and|or|redefinition`, `inherit`, `inheriting conditions`
211
350
  - ✅ **Annotations**: full value grammar (strings, enums, booleans, numbers, arrays, objects, dotted keys)
212
351
  - ✅ **Tooling**: AST walker helpers, semantic validators (`SemanticDiagnostic`), grammar coverage metadata
352
+ - ✅ **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`
353
+ - ✅ **Elements**: `case … end`, arithmetic, casts, calls (incl. `f()`), window `over (…)`, paths, `: localized`, `: redirected to`, `distinct`, `where`/`group by`/`having`, `union [all]`/`intersect`/`except`
213
354
  - 🔜 **Expression grammar** (structured `on`/`where` trees — currently opaque `{ source, tokens }`)
214
- - 🔜 **Joins** (`inner join`, `left outer join …`), CASE/CAST, aggregates, GROUP BY, UNION
215
- - 🔜 **`define aspect` (DRAS), `define hierarchy`, cache definitions (DTDC/DTSC), scalar functions (DSFD)**
216
355
  - 🔜 **BDEF / behavior definitions** (owned by epic E10)
217
356
 
218
357
  ## Dependencies