@cap-js/cds-typer 0.6.1 → 0.7.0

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/CHANGELOG.md CHANGED
@@ -4,12 +4,22 @@ All notable changes to this project will be documented in this file.
4
4
  This project adheres to [Semantic Versioning](http://semver.org/).
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/).
6
6
 
7
- ## Version 0.6.2 - TBD
7
+ ## Version 0.7.1 - TBD
8
8
 
9
9
  ### Changed
10
10
 
11
11
  ### Added
12
12
 
13
+ ### Fixed
14
+
15
+ ## Version 0.7.0 - 2023-08-22
16
+
17
+ ### Changed
18
+
19
+ ### Added
20
+ - Support for `[many] $self` syntax in bound action parameters
21
+ - Foreign keys are now present in the generated types in addition to the resolved property
22
+
13
23
  ### Fixed
14
24
  ## Version 0.6.1 - 2023-08-10
15
25
 
@@ -445,6 +445,10 @@ class Resolver {
445
445
  result.path = new Path(path) // FIXME: relative to current file
446
446
  result.csn = this.csn.definitions[t]
447
447
  result.plainName = this.trimNamespace(t)
448
+ } else if (t === '$self') {
449
+ result.type = 'this'
450
+ result.isBuiltin = true
451
+ result.plainName = 'this'
448
452
  } else {
449
453
  // type offered by some library
450
454
  const lib = this.libraries.find((lib) => lib.offers(t))
package/lib/visitor.js CHANGED
@@ -59,7 +59,6 @@ class Visitor {
59
59
  * @param {VisitorOptions} options
60
60
  */
61
61
  constructor(csn, options = {}, logger = new Logger()) {
62
- util.fixCSN(csn)
63
62
  this.options = { ...defaults, ...options }
64
63
  this.logger = logger
65
64
  this.csn = csn
@@ -130,16 +129,16 @@ class Visitor {
130
129
  buffer.indent()
131
130
  for (const [ename, element] of Object.entries(entity.elements ?? {})) {
132
131
  this.visitElement(ename, element, file, buffer)
132
+ // make foreign keys explicit
133
+ for (const [fkname, fkelement] of Object.entries(element.foreignKeys ?? {})) {
134
+ this.visitElement(`${ename}_${fkname}`, fkelement, file, buffer)
135
+ }
133
136
  }
134
137
  for (const [aname, action] of Object.entries(entity.actions ?? {})) {
135
- const lambdaString =
136
138
  buffer.add(
137
139
  SourceFile.stringifyLambda({
138
140
  name: aname,
139
- parameters: Object.entries(action.params ?? {}).map(([n, t]) => [
140
- n,
141
- this.resolver.resolveAndRequire(t, file).typeName,
142
- ]),
141
+ parameters: this.#stringifyFunctionParams(action.params, file),
143
142
  returns: action.returns ? this.resolver.resolveAndRequire(action.returns, file).typeName : 'any',
144
143
  initialiser: `undefined as unknown as this['${aname}']`
145
144
  })
@@ -226,17 +225,32 @@ class Visitor {
226
225
  buffer.add('')
227
226
  }
228
227
 
228
+ /**
229
+ * Stringifies function parameters in preparation of passing them to {@link SourceFile.stringifyLambda}.
230
+ * Resolves all parameters to a pair of parameter name and name of the resolved type.
231
+ * Also filters out parameters that indicate a binding parameter ({@link https://cap.cloud.sap/docs/releases/jan23#simplified-syntax-for-binding-parameters}).
232
+ * @param {[string, object][]} params - parameter list as found in CSN.
233
+ * @param {File} file - source file relative to which the parameter types should be resolved.
234
+ * @returns {[string, string][]} pair of names and types.
235
+ */
236
+ #stringifyFunctionParams(params, file) {
237
+ return params
238
+ ? Object.entries(params)
239
+ // filter params of type '[many] $self', as they are not to be part of the implementation
240
+ .filter(([, type]) => type?.type !== '$self' && !(type.items?.type === '$self'))
241
+ .map(([name, type]) => [
242
+ name,
243
+ this.resolver.resolveAndRequire(type, file).typeName,
244
+ ])
245
+ : []
246
+ }
247
+
229
248
  #printFunction(name, func) {
230
249
  // FIXME: mostly duplicate of printAction -> reuse
231
250
  this.logger.debug(`Printing function ${name}:\n${JSON.stringify(func, null, 2)}`)
232
251
  const ns = this.resolver.resolveNamespace(name.split('.'))
233
252
  const file = this.getNamespaceFile(ns)
234
- const params = func.params
235
- ? Object.entries(func.params).map(([pname, ptype]) => [
236
- pname,
237
- this.resolver.resolveAndRequire(ptype, file).typeName,
238
- ])
239
- : []
253
+ const params = this.#stringifyFunctionParams(func.params, file)
240
254
  const returns = this.resolver.resolveAndRequire(func.returns, file).typeName
241
255
  file.addFunction(name.split('.').at(-1), params, returns)
242
256
  }
@@ -245,12 +259,7 @@ class Visitor {
245
259
  this.logger.debug(`Printing action ${name}:\n${JSON.stringify(action, null, 2)}`)
246
260
  const ns = this.resolver.resolveNamespace(name.split('.'))
247
261
  const file = this.getNamespaceFile(ns)
248
- const params = action.params
249
- ? Object.entries(action.params).map(([pname, ptype]) => [
250
- pname,
251
- this.resolver.resolveAndRequire(ptype, file).typeName,
252
- ])
253
- : []
262
+ const params = this.#stringifyFunctionParams(action.params, file)
254
263
  const returns = this.resolver.resolveAndRequire(action.returns, file).typeName
255
264
  file.addAction(name.split('.').at(-1), params, returns)
256
265
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cap-js/cds-typer",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "description": "Generates .ts files for a CDS model to receive code completion in VS Code",
5
5
  "main": "index.js",
6
6
  "repository": "github:cap-js/cds-typer",