@cap-js/cds-typer 0.35.0 → 0.36.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.
@@ -124,7 +124,6 @@ const isInlineEnumType = (element, csn) => element.enum
124
124
  * @param {[string, string][]} kvs - a list of key-value pairs. Values that are falsey are replaced by
125
125
  * @param {import('../printers/javascript').Printer} jsp - the printer to use
126
126
  */
127
- // ??= for inline enums. If there is some static property of that name, we don't want to override it (for example: ".actions"
128
127
  const stringifyEnumImplementation = (name, kvs, jsp) => jsp.printExport(
129
128
  name,
130
129
  `{ ${kvs.map(([k,v]) => `${normalise(k)}: ${v}`).join(', ')} }`,
@@ -312,11 +312,24 @@ class Resolver {
312
312
  }[element.constructor.name] ?? []
313
313
 
314
314
  if (toOne && toMany) {
315
- /** @type { EntityCSN | { type: string } } */
316
- // @ts-expect-error - nope, it is not undefined
317
- const target = element.items ?? (typeof element.target === 'string'
318
- ? { type: element.target }
319
- : element.target)
315
+ /**
316
+ * Resolve a property from a CSN entity. If it is a reference, leave it as is.
317
+ * If it is a string, return an object with type set to the string.
318
+ * @param {Record<string, any>} el - the element to check
319
+ * @param {string} property - the property to check
320
+ * @returns {import('../typedefs').resolver.EntityCSN | { type: string }}
321
+ */
322
+ const getTarget = (el, property) => typeof el[property] === 'string'
323
+ ? { type: el[property] }
324
+ : el[property]
325
+
326
+ /** @type { EntityCSN | { type: string } | undefined } */
327
+ const target = element.items
328
+ ?? getTarget(element, 'target')
329
+ ?? getTarget(element, 'targetAspect') // Composition of aspects
330
+ if (!target) {
331
+ throw new Error(`Could not resolve target of ${element}`)
332
+ }
320
333
  /** set `notNull = true` to avoid repeated `| not null` TS construction */
321
334
  // @ts-expect-error - yes, we know that notNull is not part of the type in some cases
322
335
  target.notNull = true
package/lib/visitor.js CHANGED
@@ -19,6 +19,7 @@ const { createMember } = require('./components/class')
19
19
  const { overrideNameProperty } = require('./printers/javascript')
20
20
 
21
21
  const baseDefinitions = getBaseDefinitions()
22
+ const MAX_TRANSITIVE_RESOLUTION_STEPS = 10
22
23
 
23
24
  /** @typedef {import('./file').File} File */
24
25
  /** @typedef {import('./typedefs').visitor.Context} Context */
@@ -276,6 +277,31 @@ class Visitor {
276
277
  }))
277
278
  if (typeof e?.type !== 'string' && e?.type?.ref) {
278
279
  e.resolvedType = /** @type {string} */(lookUpRefType(this.csn, e.type.ref)?.type)
280
+ try {
281
+ /**
282
+ * multi-level resolution does not contain a .ref property:
283
+ * ```cds
284
+ * entity A {
285
+ * x: enum ...
286
+ * }
287
+ * entity B {
288
+ * x: A:x
289
+ * }
290
+ * entity C {
291
+ * x: B:x
292
+ * }
293
+ * ```
294
+ * results in B.x having a ref to [A,x], but C.x only has a string 'A.x' as type.
295
+ * So we have to do yet another round of resolution on this string.
296
+ * We attempt to follow this chain for MAX_TRANSITIVE_RESOLUTION_STEPS tops,
297
+ * but we could finish earlier, when the type is a primitive ("string"), which
298
+ * then jumps to the catch {} to leave e.resolvedType at the last, resolvable type.
299
+ */
300
+ for (let i = 0; i < MAX_TRANSITIVE_RESOLUTION_STEPS; i++) {
301
+ const { csn } = this.resolver.resolveTypeName(/** @type {string} */(e.resolvedType))
302
+ e.resolvedType = csn.type
303
+ }
304
+ } catch { /* ignore */ }
279
305
  }
280
306
  file.addInlineEnum(clean, fq, e.name, csnToEnumPairs(e, {unwrapVals: true}), buffer, eDoc)
281
307
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cap-js/cds-typer",
3
- "version": "0.35.0",
3
+ "version": "0.36.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",
@@ -48,7 +48,7 @@
48
48
  "@stylistic/eslint-plugin-js": "^4.2.0",
49
49
  "acorn": "^8.10.0",
50
50
  "eslint": "^9",
51
- "eslint-plugin-jsdoc": "^50.2.2",
51
+ "eslint-plugin-jsdoc": "^51.2.1",
52
52
  "typescript": ">=4.6.4"
53
53
  },
54
54
  "cds": {