@cap-js/cds-typer 0.32.0 → 0.33.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/cds-plugin.js CHANGED
@@ -4,10 +4,10 @@ const cds = require('@sap/cds')
4
4
  const util = require('util')
5
5
  const exec = util.promisify(require('child_process').exec)
6
6
  const typer = require('./lib/compile')
7
-
8
7
  const { fs, path } = cds.utils
9
8
  const DEBUG = cds.debug('cli|build')
10
9
  const BUILD_CONFIG = 'tsconfig.cdsbuild.json'
10
+ const { configuration } = require('./lib/config')
11
11
 
12
12
  /**
13
13
  * Check if the project is a TypeScript project by looking for a dependency on TypeScript.
@@ -52,93 +52,103 @@ const rmFiles = async (dir, exts) => fs.existsSync(dir)
52
52
  )
53
53
  : undefined
54
54
 
55
- // FIXME: remove once cds7 has been phased out
56
- if (!cds?.version || cds.version < '8.0.0') {
57
- DEBUG?.('typescript build task requires @sap/cds-dk version >= 8.0.0, skipping registration')
58
- return
59
- }
60
-
61
- // requires @sap/cds-dk version >= 7.5.0
62
- cds.build?.register?.('typescript', class extends cds.build.Plugin {
63
- static taskDefaults = { src: '.' }
64
- static hasTask() { return isTypeScriptProject() }
65
-
66
- // lower priority than the nodejs task
67
- get priority() { return -1 }
68
-
69
- get #appFolder () { return cds?.env?.folders?.app ?? 'app' }
70
-
71
- /**
72
- * cds.env > tsconfig.compilerOptions.paths > '@cds-models' (default)
73
- */
74
- get #modelDirectoryName () {
75
- const outputDirectory = cds.env.typer?.outputDirectory
76
- if (outputDirectory) return outputDirectory
77
- try {
78
- // expected format: { '#cds-models/*': [ './@cds-models/*' ] }
79
- // ^^^^^^^^^^^
80
- // relevant part - may be changed by user
81
- const config = JSON.parse(fs.readFileSync ('tsconfig.json', 'utf8'))
82
- const alias = config.compilerOptions.paths['#cds-models/*'][0]
83
- const directory = alias.match(/(?:\.\/)?(.*)\/\*/)[1]
84
- return normalize(directory) // could contain forward slashes in tsconfig.json
85
- } catch {
86
- DEBUG?.('tsconfig.json not found, not parsable, or inconclusive. Using default model directory name')
87
- }
88
- return '@cds-models'
55
+ // IIFE to be able to return early
56
+ ;(() => {
57
+ // FIXME: remove once cds7 has been phased out
58
+ if (!cds?.version || cds.version < '8.0.0') {
59
+ DEBUG?.('typescript build task requires @sap/cds-dk version >= 8.0.0, skipping registration')
60
+ return
89
61
  }
90
62
 
91
- init() {
92
- this.task.dest = path.join(cds.root, cds.env.build.target, cds.env.folders.srv)
63
+ // by checking configuration instead of cds.env, we make sure the user can set
64
+ // this configuration in both camelCase and snake_case.
65
+ if (configuration.buildTask === false) { // unset is considered true
66
+ DEBUG?.('skipping typescript build task registration based on configuration option')
67
+ return
93
68
  }
94
69
 
95
- async #runCdsTyper () {
96
- DEBUG?.('running cds-typer')
97
- cds.env.typer ??= {}
98
- cds.env.typer.outputDirectory ??= this.#modelDirectoryName
99
- await typer.compileFromFile('*')
100
- }
70
+ // requires @sap/cds-dk version >= 7.5.0
71
+ cds.build?.register?.('typescript', class extends cds.build.Plugin {
72
+ static taskDefaults = { src: '.' }
73
+ static hasTask() { return isTypeScriptProject() }
74
+
75
+ // lower priority than the nodejs task
76
+ get priority() { return -1 }
77
+
78
+ get #appFolder () { return cds?.env?.folders?.app ?? 'app' }
79
+
80
+ /**
81
+ * cds.env > tsconfig.compilerOptions.paths > '@cds-models' (default)
82
+ */
83
+ get #modelDirectoryName () {
84
+ const outputDirectory = cds.env.typer?.outputDirectory
85
+ if (outputDirectory) return outputDirectory
86
+ try {
87
+ // expected format: { '#cds-models/*': [ './@cds-models/*' ] }
88
+ // ^^^^^^^^^^^
89
+ // relevant part - may be changed by user
90
+ const config = JSON.parse(fs.readFileSync ('tsconfig.json', 'utf8'))
91
+ const alias = config.compilerOptions.paths['#cds-models/*'][0]
92
+ const directory = alias.match(/(?:\.\/)?(.*)\/\*/)[1]
93
+ return normalize(directory) // could contain forward slashes in tsconfig.json
94
+ } catch {
95
+ DEBUG?.('tsconfig.json not found, not parsable, or inconclusive. Using default model directory name')
96
+ }
97
+ return '@cds-models'
98
+ }
101
99
 
102
- async #buildWithConfig () {
103
- // possibly referencing their tsconfig.json via "extends", specifying the "compilerOptions.outDir" and
104
- // manually adding irrelevant folders (read: gen/ and app/) to the "exclude" array.
105
- DEBUG?.(`building with config ${BUILD_CONFIG}`)
106
- return exec(`npx tsc --project ${BUILD_CONFIG}`)
107
- }
100
+ init() {
101
+ this.task.dest = path.join(cds.root, cds.env.build.target, cds.env.folders.srv)
102
+ }
108
103
 
109
- async #buildWithoutConfig () {
110
- DEBUG?.('building without config')
111
- // this will include gen/ that was created by the nodejs task
112
- // _within_ the project directory. So we need to remove it afterwards.
113
- await exec(`npx tsc --outDir "${this.task.dest.replace(/\\/g, '/')}"`) // see https://github.com/cap-js/cds-typer/issues/374
114
- rmDirIfExists(path.join(this.task.dest, cds.env.build.target))
115
- rmDirIfExists(path.join(this.task.dest, this.#appFolder))
116
- }
104
+ async #runCdsTyper () {
105
+ DEBUG?.('running cds-typer')
106
+ cds.env.typer ??= {}
107
+ cds.env.typer.outputDirectory ??= this.#modelDirectoryName
108
+ await typer.compileFromFile('*')
109
+ }
117
110
 
118
- async #copyCleanModel (buildDirCdsModels) {
119
- // copy models again, to revert transpilation thereof.
120
- // We only need the index.js files in un-transpiled form.
121
- await this.copy(this.#modelDirectoryName).to(buildDirCdsModels)
122
- await rmFiles(buildDirCdsModels, ['.ts'])
123
- }
111
+ async #buildWithConfig () {
112
+ // possibly referencing their tsconfig.json via "extends", specifying the "compilerOptions.outDir" and
113
+ // manually adding irrelevant folders (read: gen/ and app/) to the "exclude" array.
114
+ DEBUG?.(`building with config ${BUILD_CONFIG}`)
115
+ return exec(`npx tsc --project ${BUILD_CONFIG}`)
116
+ }
124
117
 
125
- async build() {
126
- await this.#runCdsTyper()
127
- const buildDirCdsModels = path.join(this.task.dest, this.#modelDirectoryName)
128
- // remove the js files generated by the nodejs buildtask,
129
- // leaving only json, cds, and other static files
130
- await rmFiles(this.task.dest, ['.js', '.ts'])
131
-
132
- try {
133
- await (buildConfigExists()
134
- ? this.#buildWithConfig()
135
- : this.#buildWithoutConfig()
136
- )
137
- } catch (error) {
138
- throw error.stdout
139
- ? new Error(error.stdout)
140
- : error
118
+ async #buildWithoutConfig () {
119
+ DEBUG?.('building without config')
120
+ // this will include gen/ that was created by the nodejs task
121
+ // _within_ the project directory. So we need to remove it afterwards.
122
+ await exec(`npx tsc --outDir "${this.task.dest.replace(/\\/g, '/')}"`) // see https://github.com/cap-js/cds-typer/issues/374
123
+ rmDirIfExists(path.join(this.task.dest, cds.env.build.target))
124
+ rmDirIfExists(path.join(this.task.dest, this.#appFolder))
141
125
  }
142
- this.#copyCleanModel(buildDirCdsModels)
143
- }
144
- })
126
+
127
+ async #copyCleanModel (buildDirCdsModels) {
128
+ // copy models again, to revert transpilation thereof.
129
+ // We only need the index.js files in un-transpiled form.
130
+ await this.copy(this.#modelDirectoryName).to(buildDirCdsModels)
131
+ await rmFiles(buildDirCdsModels, ['.ts'])
132
+ }
133
+
134
+ async build() {
135
+ await this.#runCdsTyper()
136
+ const buildDirCdsModels = path.join(this.task.dest, this.#modelDirectoryName)
137
+ // remove the js files generated by the nodejs buildtask,
138
+ // leaving only json, cds, and other static files
139
+ await rmFiles(this.task.dest, ['.js', '.ts'])
140
+
141
+ try {
142
+ await (buildConfigExists()
143
+ ? this.#buildWithConfig()
144
+ : this.#buildWithoutConfig()
145
+ )
146
+ } catch (error) {
147
+ throw error.stdout
148
+ ? new Error(error.stdout)
149
+ : error
150
+ }
151
+ this.#copyCleanModel(buildDirCdsModels)
152
+ }
153
+ })
154
+ })()
package/lib/cli.js CHANGED
@@ -182,7 +182,7 @@ const flags = enrichFlagSchema({
182
182
  inlineDeclarations: {
183
183
  desc: `Whether to resolve inline type declarations${EOL}flat: (x_a, x_b, ...)${EOL}or structured: (x: {a, b}).`,
184
184
  allowed: ['flat', 'structured'],
185
- default: 'structured'
185
+ default: 'flat'
186
186
  },
187
187
  propertiesOptional: parameterTypes.boolean({
188
188
  desc: `If set to true, properties in entities are${EOL}always generated as optional (a?: T).`,
@@ -192,11 +192,19 @@ const flags = enrichFlagSchema({
192
192
  desc: `If set to true, floating point properties are generated${EOL}as IEEE754 compatible '(number | string)' instead of 'number'.`,
193
193
  default: 'false'
194
194
  }),
195
+ legacyBinaryTypes: parameterTypes.boolean({
196
+ desc: `If set to true, Binary and LargeBinary are generated${EOL}as strings.`,
197
+ default: 'false'
198
+ }),
195
199
  targetModuleType: {
196
200
  desc: `Output format for generated .js files.${EOL}Setting it to auto tries to derive the module type from${EOL}the package.json and falls back to CJS.`,
197
201
  allowed: ['esm', 'cjs', 'auto'],
198
202
  default: 'auto'
199
- }
203
+ },
204
+ buildTask: parameterTypes.boolean({
205
+ desc: `If set to true, the typescript build task will not be registered/ executed.${EOL}This value must be set in your project configuration.${EOL}Passing it as parameter to the cds-typer CLI has no effect.`,
206
+ default: 'true'
207
+ })
200
208
  })
201
209
 
202
210
  const hint = () => 'Missing or invalid parameter(s). Call with --help for more details.'
@@ -81,6 +81,8 @@ export type CdsTime = ${timeRegex};
81
81
  * @see {@link CdsDate}
82
82
  */
83
83
  export type CdsTimestamp = string;
84
+
85
+ export type CdsMap = { [key: string]: unknown };
84
86
  `)
85
87
 
86
88
  module.exports = { baseDefinitions }
package/lib/file.js CHANGED
@@ -420,10 +420,6 @@ class SourceFile extends File {
420
420
  */
421
421
  getImports() {
422
422
  const buffer = new Buffer()
423
- if (this.services.names.length) {
424
- // currently only needed to extend cds.Service and would trigger unused-variable-errors in strict configs
425
- buffer.add('import cds from \'@sap/cds\'') // TODO should go to visitor#printService, but can't express this as Path
426
- }
427
423
  const file = configuration.targetModuleType === 'esm'
428
424
  ? '/index.js'
429
425
  : ''
@@ -6,9 +6,9 @@ class BuiltinResolver {
6
6
  #builtins = {
7
7
  UUID: 'string',
8
8
  String: 'string',
9
- Binary: 'string',
9
+ Binary: 'Buffer',
10
10
  LargeString: 'string',
11
- LargeBinary: 'Buffer | string | {value: import("stream").Readable, $mediaContentType: string, $mediaContentDispositionFilename?: string, $mediaContentDispositionType?: string}',
11
+ LargeBinary: 'import("stream").Readable',
12
12
  Vector: 'string',
13
13
  Integer: 'number',
14
14
  UInt8: 'number',
@@ -21,6 +21,7 @@ class BuiltinResolver {
21
21
  Float: 'number',
22
22
  Double: 'number',
23
23
  Boolean: 'boolean',
24
+ Map: '__.CdsMap',
24
25
  // note: the date-related types are strings on purpose, which reflects their runtime behaviour
25
26
  Date: '__.CdsDate', // yyyy-mm-dd
26
27
  DateTime: '__.CdsDateTime', // yyyy-mm-dd + time + TZ (precision: seconds)
@@ -34,14 +35,19 @@ class BuiltinResolver {
34
35
  /**
35
36
  * @param {object} options - additional resolution options
36
37
  * @param {boolean} [options.IEEE754Compatible] - if true, the Decimal, DecimalFloat, Float, and Double types are also allowed to be strings
38
+ * @param {boolean} [options.legacyBinaryTypes] - if true, the Binary and LargeBinary types are strings
37
39
  */
38
- constructor ({ IEEE754Compatible } = {}) {
40
+ constructor ({ IEEE754Compatible, legacyBinaryTypes } = {}) {
39
41
  if (IEEE754Compatible) {
40
42
  this.#builtins.Decimal = '(number | string)'
41
43
  this.#builtins.DecimalFloat = '(number | string)'
42
44
  this.#builtins.Float = '(number | string)'
43
45
  this.#builtins.Double = '(number | string)'
44
46
  }
47
+ if (legacyBinaryTypes) {
48
+ this.#builtins.Binary = 'string'
49
+ this.#builtins.LargeBinary = 'Buffer | string | {value: import("stream").Readable, $mediaContentType: string, $mediaContentDispositionFilename?: string, $mediaContentDispositionType?: string}'
50
+ }
45
51
  this.#builtins = Object.freeze(this.#builtins)
46
52
  }
47
53
 
@@ -32,7 +32,7 @@ class Resolver {
32
32
  this.visitor = visitor
33
33
 
34
34
  /** @type {BuiltinResolver} */
35
- this.builtinResolver = new BuiltinResolver({ IEEE754Compatible: configuration.IEEE754Compatible })
35
+ this.builtinResolver = new BuiltinResolver({ IEEE754Compatible: configuration.IEEE754Compatible, legacyBinaryTypes: configuration.legacyBinaryTypes })
36
36
 
37
37
  /** @type {Library[]} */
38
38
  this.libraries = [new Library(require.resolve('../../library/cds.hana.ts'))]
@@ -288,6 +288,8 @@ class Resolver {
288
288
  const typeInfo = this.resolveType(element, file, options)
289
289
  const cardinality = getMaxCardinality(element)
290
290
 
291
+ /** @type {string|undefined} */
292
+ let typeNamespaceIdent = undefined
291
293
  let typeName = typeInfo.plainName ?? typeInfo.type
292
294
 
293
295
  // only applies to builtin types, because the association/ composition _themselves_ are the (builtin) types we are checking, not their generic parameter!
@@ -333,9 +335,10 @@ class Resolver {
333
335
  if (!parent.isCwd(file.path.asDirectory())) {
334
336
  file.addImport(parent)
335
337
  // prepend namespace
336
- typeName = `${parent.asIdentifier()}.${typeName}`
337
- typeInfo.inflection.singular = `${parent.asIdentifier()}.${typeInfo.inflection.singular}`
338
- typeInfo.inflection.plural = `${parent.asIdentifier()}.${typeInfo.inflection.plural}`
338
+ typeNamespaceIdent = parent.asIdentifier()
339
+ typeName = [typeNamespaceIdent, typeName].join('.')
340
+ typeInfo.inflection.singular = [typeNamespaceIdent, typeInfo.inflection.singular].join('.')
341
+ typeInfo.inflection.plural = [typeNamespaceIdent, typeInfo.inflection.plural].join('.')
339
342
  }
340
343
 
341
344
  if (element.type.ref?.length > 1) {
@@ -362,12 +365,23 @@ class Resolver {
362
365
  // handle typeof (unless it has already been handled above)
363
366
  const target = element.target?.name ?? element.type?.ref?.join('.') ?? element.type
364
367
  if (target && !typeInfo.isDeepRequire) {
365
- const { propertyAccess, scope } = this.visitor.entityRepository.getByFq(target) ?? {}
366
- if (scope?.length) {
368
+ const { propertyAccess, scope } = this.visitor.entityRepository.getByFq(target) ?? {}
369
+ if (scope?.length && typeInfo.inflection) {
370
+ let { singular, plural } = typeInfo.inflection
371
+ // remove already added namespace, so the scope is added after the namespace
372
+ // i.e. _common.Book.texts instead of Book._common.texts
373
+ if (typeNamespaceIdent) {
374
+ if (singular.startsWith(typeNamespaceIdent)) {
375
+ singular = singular.substring(typeNamespaceIdent.length+1)
376
+ }
377
+ if (plural.startsWith(typeNamespaceIdent)) {
378
+ plural = plural.substring(typeNamespaceIdent.length+1)
379
+ }
380
+ }
367
381
  // update inflections with proper prefix, e.g. Books.text, Books.texts
368
382
  typeInfo.inflection = {
369
- singular: [...scope, typeInfo.inflection?.singular].join('.'),
370
- plural: [...scope, typeInfo.inflection?.plural].join('.')
383
+ singular: [typeNamespaceIdent, ...scope, singular].filter(Boolean).join('.'),
384
+ plural: [typeNamespaceIdent,...scope, plural].filter(Boolean).join('.')
371
385
  }
372
386
  } else if (propertyAccess?.length) {
373
387
  const element = target.slice(0, -propertyAccess.join('.').length - 1)
package/lib/typedefs.d.ts CHANGED
@@ -206,6 +206,10 @@ export module config {
206
206
  */
207
207
  IEEE754Compatible: boolean
208
208
  targetModuleType: 'cjs' | 'esm' | 'auto'
209
+ /**
210
+ * `legacyBinaryTypes = true` -> Binary and LargeBinary are generated as `string` and a union type respectively
211
+ */
212
+ legacyBinaryTypes: boolean
209
213
  }
210
214
  }
211
215
 
package/lib/visitor.js CHANGED
@@ -531,17 +531,21 @@ class Visitor {
531
531
  const { namespace } = this.entityRepository.getByFqOrThrow(fq)
532
532
  const file = this.fileRepository.getNamespaceFile(namespace)
533
533
  const buffer = file.services.buffer
534
- const serviceNameSimple = service.name.split('.').pop()
535
534
 
536
535
  docify(service.doc).forEach(d => { buffer.add(d) })
537
536
  // file.addImport(new Path(['cds'], '')) TODO make sap/cds import work
538
- buffer.addIndentedBlock(`export class ${serviceNameSimple} extends cds.Service {`, () => {
537
+ buffer.addIndentedBlock('export default class {', () => {
539
538
  Object.entries(service.operations ?? {}).forEach(([name, {doc}]) => {
540
539
  buffer.add(docify(doc))
541
- buffer.add(`declare ${name}: typeof ${name}`)
540
+ buffer.add(createMember({
541
+ name,
542
+ type: `typeof ${name}`,
543
+ isStatic: true,
544
+ isReadonly: true,
545
+ isDeclare: true,
546
+ }))
542
547
  })
543
548
  }, '}')
544
- buffer.add(`export default ${serviceNameSimple}`)
545
549
  buffer.blankLine()
546
550
  file.addService(service.name)
547
551
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cap-js/cds-typer",
3
- "version": "0.32.0",
3
+ "version": "0.33.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",
@@ -11,12 +11,12 @@
11
11
  "CLI"
12
12
  ],
13
13
  "author": "SAP SE (https://www.sap.com)",
14
- "license": "SEE LICENSE IN LICENSE",
14
+ "license": "Apache-2.0",
15
15
  "scripts": {
16
- "test:unit": "jest --projects test/unit.jest.config.js",
17
- "test:integration": "jest --projects test/int.jest.config.js",
18
- "test:smoke": "jest --projects test/smoke.jest.config.js",
19
- "test:all": "jest",
16
+ "test:unit": "node test/testRunner.js ./test/unit ./test/unit/setup.mjs",
17
+ "test:integration": "node test/testRunner.js ./test/integration ./test/integration/setup.mjs",
18
+ "test:smoke": "node test/testRunner.js ./test/smoke ./test/smoke/setup.mjs",
19
+ "test:all": "npm run test:smoke && npm run test:unit",
20
20
  "test": "npm run test:smoke && npm run test:unit",
21
21
  "lint": "npx eslint .",
22
22
  "lint:fix": "npx eslint . --fix",
@@ -31,9 +31,7 @@
31
31
  "files": [
32
32
  "lib/",
33
33
  "library",
34
- "CHANGELOG.md",
35
34
  "index.js",
36
- "LICENSE",
37
35
  "README.md",
38
36
  "cds-plugin.js"
39
37
  ],
@@ -48,27 +46,21 @@
48
46
  "devDependencies": {
49
47
  "@cap-js/cds-types": "^0",
50
48
  "@sap/cds": "^8",
51
- "@stylistic/eslint-plugin-js": "^2.7.2",
49
+ "@stylistic/eslint-plugin-js": "^3.0.0",
52
50
  "acorn": "^8.10.0",
53
51
  "eslint": "^9",
54
52
  "eslint-plugin-jsdoc": "^50.2.2",
55
53
  "globals": "^15.0.0",
56
- "jest": "^29",
57
54
  "typescript": ">=4.6.4"
58
55
  },
59
- "jest": {
60
- "projects": [
61
- "test/smoke.jest.config.js",
62
- "test/unit.jest.config.js"
63
- ]
64
- },
65
56
  "cds": {
66
57
  "typer": {
67
58
  "output_directory": "@cds-models",
68
59
  "inline_declarations": "flat",
69
60
  "target_module_type": "auto",
70
61
  "properties_optional": true,
71
- "use_entities_proxy": false
62
+ "use_entities_proxy": false,
63
+ "build_task": true
72
64
  },
73
65
  "schema": {
74
66
  "buildTaskType": {
@@ -119,7 +111,7 @@
119
111
  "flat",
120
112
  "structured"
121
113
  ],
122
- "default": "structured"
114
+ "default": "flat"
123
115
  },
124
116
  "properties_optional": {
125
117
  "type": "boolean",
@@ -131,6 +123,11 @@
131
123
  "description": "If set to true, floating point properties are generated\nas IEEE754 compatible '(number | string)' instead of 'number'.",
132
124
  "default": false
133
125
  },
126
+ "legacy_binary_types": {
127
+ "type": "boolean",
128
+ "description": "If set to true, Binary and LargeBinary are generated\nas strings.",
129
+ "default": false
130
+ },
134
131
  "target_module_type": {
135
132
  "type": "string",
136
133
  "description": "Output format for generated .js files.\nSetting it to auto tries to derive the module type from\nthe package.json and falls back to CJS.",
@@ -140,6 +137,11 @@
140
137
  "auto"
141
138
  ],
142
139
  "default": "auto"
140
+ },
141
+ "build_task": {
142
+ "type": "boolean",
143
+ "description": "If set to true, the typescript build task will not be registered/ executed.\nThis value must be set in your project configuration.\nPassing it as parameter to the cds-typer CLI has no effect.",
144
+ "default": true
143
145
  }
144
146
  }
145
147
  }
package/CHANGELOG.md DELETED
@@ -1,382 +0,0 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- ## [Unreleased]
6
-
7
- ### Added
8
- ### Changed
9
- ### Deprecated
10
- ### Removed
11
- ### Fixed
12
- ### Security
13
-
14
- ## [0.32.0] - 2025-01-14
15
-
16
- ### Added
17
- - dedicated classes for inline compositions
18
- - dedicated text-classes for entities with `localized` elements
19
-
20
- ### Changed
21
- - prefixed builtin types like `Promise` and `Record` with `globalThis.`, to allow using names of builtin types for entities without collisions
22
- - bumped peer-dependency to `@cap-js/cds-types` to `>=0.9`
23
- ### Deprecated
24
- ### Removed
25
- ### Fixed
26
- - referencing another entity's property of type `cds.String` in an enum will now properly quote the generated values
27
- ### Security
28
-
29
- ## [0.31.0] - 2024-12-16
30
- ### Fixed
31
- - type-referencing a property that is a key no longer breaks the referring property
32
- - when targeting ESM, all imports within the generated types now add a `/index.js`-suffix to conform to modern module resolution mechanisms
33
- - leaving `target_module_type` at `'auto'` now properly acts on a detected `"type":"module"`
34
-
35
- ### Added
36
- - cds aspects now generate a synthetic plural type too, to be used in `composition of many`
37
-
38
- ## [0.30.0] - 2024-12-02
39
-
40
- ### Changed
41
- - [breaking] when running cds-typer in a CAP project, the default for the `outputDirectory` option will be `./@cds-models` instead of `./`. This default takes the lowest precedence after setting it in the project's `cds.env`, or explicitly as CLI argument.
42
-
43
- ### Fixed
44
- - cds-typer no longer ignores the selected `outputDirectory`, which would also cause an issue during build
45
-
46
- ## [0.29.0] - 2024-11-20
47
- ### Added
48
- - [breaking] cds-typer now tries to automatically detect whether it has to generate ESM or CommonJS in the emitted _index.js_ files. This behaviour can be overridden via the `--targetModuleType` option. _If you rely on these generated index.js files to be CJS despite your project being of ESM type, you need to manually tell cds-typer to generate CJS files!_
49
-
50
- ### Fixed
51
- - The static `.keys` property now properly reels in key types from inherited classes.
52
-
53
- ## [0.28.1] - 2024-11-07
54
- ### Fixed
55
- - `cds build` no longer fails on Windows with an `EINVAL` error.
56
- - `cds build` also supports custom model paths in `tsconfig.json` that do not end with `/index.ts`. This is the case for projects running with `tsx`.
57
-
58
- ## [0.28.0] - 24-10-24
59
- ### Added
60
- - Schema definition for `cds.typer` options in `package.json` and `.cdsrc-*.json` files
61
- - Added a static `elements` property to all entities, which allows access to the `LinkedDefinitions` instance of an entity's elements
62
- - Schema definition for `typescript` cds build task.
63
- - `.drafts` property of any entity `E` is now of type `DraftOf<E>`, or `DraftsOf<E>` for plurals, respectively. This type exposes dditional properties that are available on drafts during runtime.
64
-
65
- ### Fixed
66
- - Entity elements of named structured types are flattened when using the option `--inlineDeclarations flat`
67
- - `override` modifier on `.kind` property is now only generated if the property is actually inherited, satisfying strict `tsconfig.json`s
68
- - Properly support mandatory (`not null`) action parameters with `array of` types
69
- - Static property `.drafts` is only create for entity classes that are actually draft enabled
70
-
71
- ## [0.27.0] - 2024-10-02
72
- ### Changed
73
- - Any configuration variable (via CLI or `cds.env`) can now be passed in snake_case in addition to camelCase
74
- - Action parameters are now generated as optional by default, which is how the runtime treats them. Mandatory parameters have to be marked as `not null` in CDS/CDL, or `notNull` in CSN.
75
-
76
- ### Fixed
77
- - Fix build task for projects with spaces
78
- - Fix a bug where cds-typer would produce redundant type declarations when the model contains an associations to another entity's property
79
- - Reintroduce default value `'.'` for `--outputDirectory`
80
-
81
- ## [0.26.0] - 2024-09-11
82
- ### Added
83
- - Added a static `.keys` property in all entities. That property is dictionary which holds all properties as keys that are marked as `key` in CDS
84
- - Added a CLI option `--useEntitiesProxy`. When set to `true`, all entities are wrapped into `Proxy` objects during runtime, allowing top level imports of entity types.
85
- - Added a static `.kind` property for entities and types, which contains `'entity'` or `'type'` respectively
86
- - Apps need to provide `@sap/cds` version `8.2` or higher.
87
- - Apps need to provide `@cap-js/cds-types` version `0.6.4` or higher.
88
- - Typed methods are now generated for calls of unbound actions. Named and positional call styles are supported, e.g. `service.action({one, two})` and `service.action(one, two)`.
89
- - Action parameters can be optional in the named call style (`service.action({one:1, ...})`).
90
- - Actions for ABAP RFC modules cannot be called with positional parameters, but only with named ones. They have 'parameter categories' (import/export/changing/tables) that cannot be called in a flat order.
91
- - Services now have their own export (named like the service itself). The current default export is not usable in some scenarios from CommonJS modules.
92
- - Enums and operation parameters can have doc comments
93
-
94
- ## [0.25.0] - 2024-08-13
95
- ### Added
96
- - Declaring a type alias on an enum in cds now also exports it on value level in the resulting type
97
-
98
- ### Fixed
99
- - Classes representing views and projections will no longer carry ancestry to avoid clashes thereof with aliases fields
100
-
101
- ### Changed
102
- - All properties are now preceeded with the `declare` modifier to pass strict tsconfigs using `useDefineForClassFields` or `noImplicitOverride`
103
- - The static `actions` property of generated classes now includes the types from all inherited classes to also suggest actions defined in a base entity/aspect/type.
104
-
105
- ## [0.24.0] - 2024-07-18
106
- ### Fixed
107
- - Suppressed an error that would incorrectly point out naming clashes when an entity was named in singular inflection in the model
108
- - CDS aspects now also generate a aspect-function in singular inflection, similar to how entities do
109
-
110
- ### Changed
111
- - Aspects generate named classes again so that tooltips will show more meaningful provenance for properties
112
- - The TypeScript task for `cds build` no longer looks for tsconfig.json to determine if the project has TS nature and instead checks the dependencies in the project's package.json for an occurrence of `typescript`
113
-
114
- ## [0.23.0] - 2024-07-04
115
-
116
- ### Fixed
117
- - Plurals no longer have `is_singular` attached in the resulting .js files
118
- - Properties are properly propagated beyond just one level of inheritance
119
-
120
- ## [0.22.0] - 2024-06-20
121
-
122
- ### Fixed
123
- - Fixed a bug where keys would sometimes inconsistently become nullable
124
-
125
- ### Changed
126
- - Logging now internally uses `cds.log` and pipes output into the `cds-typer` logger, which can be configured via `cds.env` in addition to explicitly passing a `--logLevel` parameter to CLI. Users now have to use the levels defined in [`cds.log.levels`](https://cap.cloud.sap/docs/node.js/cds-log#log-levels). The formerly valid levels `WARNING`, `CRITICAL`, and `NONE` are now deprecated and automatically mapped to valid levels for now.
127
-
128
- ## [0.21.2] - 2024-06-06
129
- ### Fixed
130
- - The typescript build task will no longer attempt to run unless at least cds 8 is installed
131
-
132
- ## [0.21.1] - 2024-06-03
133
- ### Fixed
134
- - Added missing _cds-plugin.js_ to exported files to properly enable calling `cds build --for typescript`
135
-
136
- ## [0.21.0] - 2024-05-31
137
- ### Added
138
- - Added `IEEE754Compatible` flag which, when set to `true`, generates decimal fields as `(number | string)` instead of `number`. This flag will be removed in the long run
139
- - Added plugin to `cds build` TypeScript projects. Can be explicitly called using `cds build --for typescript`
140
-
141
- ### Changed
142
- - Types representing CDS events are now only `declare`d to avoid having to make their properties optional
143
- - Singular forms in generated _index.js_ files now contain a `.is_singular` property as marker for distinguished handling of singular and plural in the runtime
144
- - Parameters passed to the CLI now take precedence over configuration contained in the `typer` section of `cds.env`
145
-
146
- ### Fixed
147
- - Entities ending with an "s" are no longer incorrectly truncated within `extends`-clauses
148
- - Entity names prefixed with their own namespace (e.g. `Name.Name`, `Name.NameAttachments`) are not stripped of their name prefix
149
-
150
- ## [0.20.2] - 2024-04-29
151
- ### Fixed
152
- - Referring to a property's type in a function/ action parameter no longer refers to the enclosing entity
153
-
154
- ## [0.20.1] - 2024-04-24
155
- ### Fixed
156
- - Void actions no longer crash the type generation process
157
-
158
- ## [0.20.0] - 2024-04-23
159
- ### Added
160
- - Types for actions and functions now expose a `.kind` property which holds the string `'function'` or `'action'` respectively
161
- - Added the `CdsDate`, `CdsDateTime`, `CdsTime`, `CdsTimestamp` types, which are each represented as a `string`.
162
- - Plural types can now also contain an optional numeric `$count` property
163
-
164
- ### Changed
165
- - Empty `.actions` properties and operations without parameters are now typed as `Record<never, never>` to make it clear they contain nothing and also to satisfy overzealous linters
166
-
167
- ### Fixed
168
- - Composition of aspects now properly resolve implicit `typeof` references in their properties
169
- - Importing an enum into a service will now generate an alias to the original enum, instead of incorrectly duplicating the definition
170
- - Returning entities from actions/ functions and using them as parameters will now properly use the singular inflection instead of returning an array thereof
171
- - Aspects are now consistently named and called in their singular form
172
- - Only detect inflection clash if singular and plural share the same namespace. This also no longer reports `sap.common` as erroneous during type creation
173
-
174
- ## [0.19.0] - 2024-03-28
175
- ### Added
176
- - Support for `cds.Vector`, which will be represented as `string`
177
-
178
- ## [0.18.2] - 2024-03-21
179
- ### Fixed
180
- - Resolving `@sap/cds` will now look in the CWD first to ensure a consistent use the same CDS version across different setups
181
- - Types of function parameters starting with `cds.` are not automatically considered builtin anymore and receive a more thorough check against an allow-list
182
-
183
-
184
- ## [0.18.1] - 2024-03-13
185
- ### Fix
186
- - Remove faulty plural for CDS `type` definitions from the generated _index.js_ files
187
-
188
- ## [0.18.0] - 2024-03-12
189
- ### Added
190
- - Improved support for projections, including projections on inline definitions, and on views, as well as support for explicit exclusion and selection of properties
191
-
192
- ### Changed
193
- - [breaking] CDS `type` definitions will not be inflected. Whatever inflection you define them in will be assumed treated as a singular form and will not receive a plural form anymore
194
-
195
- ## [0.17.0] - 2024-03-05
196
- ### Fixed
197
- - Fixed a bug where refering to an externally defined enum via the `typeof` syntax would crash the type generation
198
-
199
- ## [0.16.0] - 2024-02-01
200
- ### Changed
201
- - Changed default log level from `NONE` to `ERROR`. See the doc to manually pass in another log level for cds-typer runs
202
- - Name collisions between automatically generated foreign key fields (`.…_ID`, `.…_code`, etc.) with explicitly named fields will now raise an error
203
- - Generate CDS types that are actually structured types as if they were entities. This allows the correct representation of mixing aspects and types in CDS inheritance, and also fixes issues with inline enums in such types
204
-
205
- ### Fixed
206
- - Externally defined enums can now be used as parameter types in actions
207
-
208
- ## [0.15.0] - 2023-12-21
209
- ### Added
210
- - Support for [scoped entities](https://cap.cloud.sap/docs/cds/cdl#scoped-names)
211
- - Support for [delimited identifiers](https://cap.cloud.sap/docs/cds/cdl#delimited-identifiers)
212
-
213
- ### Fixed
214
- - Inline enums are now available during runtime as well
215
- - Inline enums can now be used as action parameter types as well. These enums will not have a runtime representation, but will only assert type safety!
216
- - Arrays of inline enum values can now be used as action parameters too. But they will only be represented by their enclosing type for now, i.e. `string`, `number`, etc.
217
- - Foreign keys of projection entities are now propagated as well
218
-
219
- ## [0.14.0] - 2023-12-13
220
- ### Added
221
- - Entities that are database views now also receive typings
222
-
223
- ## [0.13.0] - 2023-12-06
224
- ### Changed
225
- - Enums are now generated ecplicitly in the respective _index.js_ files and don't have to extract their values from the model at runtime anymore
226
-
227
- ### Added
228
- - The `excluding` clause in projections now actually excludes the specified properties in the generated types
229
-
230
- ## [0.12.0] - 2023-11-23
231
-
232
- ### Changed
233
- - Generate `cds.LargeBinary` as string, buffer, _or readable_ in the case of media content
234
-
235
- ### Added
236
- - Added support for the `not null` modifier
237
-
238
- ### Fixed
239
- - Now using names of enum values in generated _index.js_ files if no explicit value is present
240
-
241
- ## [0.11.1] - 2023-10-12
242
-
243
- ### Changed
244
-
245
- ### Added
246
- ### Fixed
247
- - Fixed how service names are exported as default export
248
-
249
- ## [0.11.0] - 2023-10-10
250
-
251
- ### Changed
252
-
253
- ### Added
254
- - Autoexposed entities in services are now also generated
255
- - Each generated class now contains their original fully qualified name in a static `.name` property
256
- - Inline enums that are defined as literal type of properties are now supported as well (note: this feature is experimental. The location to which enums are generated might change in the future!)
257
-
258
- ### Fixed
259
- - Fixed an error when an entity uses `type of` on a property they have inherited from another entity
260
- - Fixed an error during draftability propagation when defining compositions on types that are declared inline
261
-
262
- ### Removed
263
- - `compileFromCSN` is no longer part of the package's API
264
-
265
- ## [0.10.0] - 2023-09-21
266
-
267
- ### Changed
268
- - Actions and functions are now attached to a static `.actions` property of each generated class. This reflects the runtime behaviour better than the former way of generating instance methods
269
-
270
- ### Added
271
-
272
- ### Fixed
273
-
274
- ## [0.9.0] - 2023-09-08
275
-
276
- ### Changed
277
-
278
- ### Added
279
- - Support for drafts via `@odata.draft.enabled` annotation
280
-
281
- ### Fixed
282
- - Foreign keys are now propagated more than one level (think: `x_ID_ID_ID`)
283
-
284
- ## [0.8.0] - 2023-09-05
285
-
286
- ### Changed
287
-
288
- ### Added
289
-
290
- ### Fixed
291
- - Foreign keys that are inherited via aspects are now also generated in addition to the resolved property (see 0.7.0)
292
- - Explicitly annotated `@singular` and `@plural` names are now properly used in generated _index.js_ files
293
-
294
- ## [0.7.0] - 2023-08-22
295
-
296
- ### Changed
297
-
298
- ### Added
299
- - Support for `[many] $self` syntax in bound action parameters
300
- - Foreign keys are now present in the generated types in addition to the resolved property
301
-
302
- ### Fixed
303
- ## [0.6.1] - 2023-08-10
304
-
305
- ### Changed
306
-
307
- ### Added
308
-
309
- ### Fixed
310
- - Removed a warning about circular imports
311
-
312
- ## [0.6.0] - 2023-08-07
313
-
314
- ### Added
315
- - Support for `event` syntax
316
-
317
- ### Fixed
318
- - Initialise bound actions with stubs to support `"strict":true` in _tsconfig.json_
319
- - Add leading underscore to appease `noUnusedParameters` in strict tsconfigs
320
- - No longer inflect `type` definitions when they are referenced within entities or other type definitions
321
-
322
- ## [0.5.0] - 2023-07-25
323
-
324
- ### Changed
325
- - Facilitate strict property checks. Note: `checkJs: true` must be present in the project's _jsconfig.json_ or _tsconfig.json_ respectively for this feature to become effective
326
-
327
- ### Added
328
- - Support for `array of` syntax
329
-
330
- ### Fixed
331
- - Generate `string` type for date-related types in CDS definitions
332
- - Generate `Buffer | string` type for the CDS type `LargeBinary`
333
-
334
- ## [0.4.0] - 2023-07-06
335
- ### Added
336
- - Support for enums when they are defined separately (not inline in the property type of an entity)
337
-
338
- ## [0.3.0] - 2023-06-26
339
- ### Added
340
- - Support `function` definitions (apart from `action`s)
341
- ### Changed
342
- - Bump version to next minor
343
-
344
- ### Fixed
345
- - Properly import CDS `type` definitions when they are referenced elsewhere
346
-
347
- ## [0.2.5-beta.1] - 2023-06-13
348
-
349
- ### Changed
350
- - Bump version
351
-
352
- ## [0.2.4] - 2023-06-12
353
- - Enable use of annotated singular/ plural names in associations/ compositions
354
- - Rename package from `@sap/cds-dts-generator` to `@cap-js/cds-typer`
355
-
356
- ## [0.2.3] - 2023-05-17
357
- - Add missing library files
358
-
359
- ## [0.2.2] - 2023-05-17
360
- - Make class hierarchy flatter
361
-
362
- ## [0.2.1] - 2023-05-16
363
- - Add missing files
364
-
365
- ## [0.2.0] - 2023-05-15
366
- - use native Typescript AST in unit tests
367
- - add `propertiesOptional` flag
368
- - support flat, as well as nested inline declarations
369
- - support `typeof` syntax
370
- - read rudimentary configuration from cds.env
371
- - export bound and unbound actions
372
- - allow inline type definitions within compositions
373
- - enable use of additional type libraries (HANA types available as first library)
374
- - provide proper JSDoc for all modules
375
- - export entity types for singular variants alongside plural types
376
-
377
- ## [0.1.1] - 2023-01-26
378
- - add TL;DR section to README
379
- - allow multiple positional arguments
380
-
381
- ## [0.1.0] - 2023-01-01
382
- - initial code base