@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 +153 -14
- package/dist/index.d.mts +427 -8
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3091 -245
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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
|
|
12
|
-
|
|
|
13
|
-
| Table
|
|
14
|
-
|
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
|
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 (
|
|
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
|
|
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
|
|
210
|
-
- ✅ **DCL**: role definitions
|
|
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
|