@cap-js/cds-typer 0.21.0 → 0.21.1

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
@@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
6
6
 
7
7
  ## Version 0.22.0 - TBD
8
8
 
9
+ ## Version 0.21.1 - 2024-06-03
10
+ ### Fixed
11
+ - Added missing _cds-plugin.js_ to exported files to properly enable calling `cds build --for typescript`
12
+
13
+
9
14
  ## Version 0.21.0 - 2024-05-31
10
15
  ### Added
11
16
  - 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
package/cds-plugin.js ADDED
@@ -0,0 +1,126 @@
1
+ const { readdir, stat } = require('node:fs/promises')
2
+ const { normalize } = require('node:path')
3
+ const cds = require('@sap/cds')
4
+ const util = require('util')
5
+ const exec = util.promisify(require('child_process').exec)
6
+ const typer = require('./lib/compile')
7
+
8
+ const { fs, path } = cds.utils
9
+ const DEBUG = cds.debug('cli|build')
10
+ const BUILD_CONFIG = 'tsconfig.cdsbuild.json'
11
+
12
+ /**
13
+ * Check if a tsconfig file exists.
14
+ */
15
+ const tsConfigExists = () => fs.existsSync('tsconfig.json')
16
+
17
+ /**
18
+ * Check if separate tsconfig file that is used for building the project.
19
+ * @returns {boolean}
20
+ */
21
+ const buildConfigExists = () => fs.existsSync(BUILD_CONFIG)
22
+
23
+ /**
24
+ * @param {string} dir The directory to remove.
25
+ */
26
+ const rmDirIfExists = dir => {
27
+ try { fs.rmSync(dir, { recursive: true }) } catch { /* ignore */ }
28
+ }
29
+
30
+ /**
31
+ * Remove files with given extensions from a directory recursively.
32
+ * @param {string} dir The directory to start from.
33
+ * @param {string[]} exts The extensions to remove.
34
+ * @returns {Promise<void>}
35
+ */
36
+ const rmFiles = async (dir, exts) => fs.existsSync(dir)
37
+ ? Promise.all(
38
+ (await readdir(dir))
39
+ .map(async file => {
40
+ const filePath = path.join(dir, file)
41
+ if ((await stat(filePath)).isDirectory()) {
42
+ return rmFiles(filePath, exts)
43
+ } else if (exts.some(ext => file.endsWith(ext))) {
44
+ fs.unlinkSync(filePath)
45
+ }
46
+ })
47
+ )
48
+ : undefined
49
+
50
+ // requires @sap/cds-dk version >= 7.5.0
51
+ cds.build?.register?.('typescript', class extends cds.build.Plugin {
52
+ static taskDefaults = { src: '.' }
53
+ static hasTask() { return tsConfigExists() }
54
+
55
+ // lower priority than the nodejs task
56
+ get priority() { return -1 }
57
+
58
+ get #appFolder () { return cds?.env?.folders?.app ?? 'app' }
59
+
60
+ get #modelDirectoryName () {
61
+ try {
62
+ // expected format: { '#cds-models/*': [ './@cds-models/*/index.ts' ] }
63
+ // ^^^^^^^^^^^^^^^
64
+ // relevant part - may be changed by user
65
+ const config = JSON.parse(fs.readFileSync ('tsconfig.json', 'utf8'))
66
+ const alias = config.compilerOptions.paths['#cds-models/*'][0]
67
+ const directory = alias.match(/(?:\.\/)?(.*)\/\*\/index\.ts/)[1]
68
+ return normalize(directory) // could contain forward slashes in tsconfig.json
69
+ } catch {
70
+ DEBUG?.('tsconfig.json not found, not parsable, or inconclusive. Using default model directory name')
71
+ }
72
+ return '@cds-models'
73
+ }
74
+
75
+ init() {
76
+ this.task.dest = path.join(cds.root, cds.env.build.target, cds.env.folders.srv)
77
+ }
78
+
79
+ async #runCdsTyper () {
80
+ DEBUG?.('running cds-typer')
81
+ await typer.compileFromFile('*', { outputDirectory: this.#modelDirectoryName })
82
+ }
83
+
84
+ async #buildWithConfig () {
85
+ // possibly referencing their tsconfig.json via "extends", specifying the "compilerOptions.outDir" and
86
+ // manually adding irrelevant folders (read: gen/ and app/) to the "exclude" array.
87
+ DEBUG?.(`building with config ${BUILD_CONFIG}`)
88
+ return exec(`npx tsc --project ${BUILD_CONFIG}`)
89
+ }
90
+
91
+ async #buildWithoutConfig () {
92
+ DEBUG?.('building without config')
93
+ // this will include gen/ that was created by the nodejs task
94
+ // _within_ the project directory. So we need to remove it afterwards.
95
+ await exec(`npx tsc --outDir ${this.task.dest}`)
96
+ rmDirIfExists(path.join(this.task.dest, cds.env.build.target))
97
+ rmDirIfExists(path.join(this.task.dest, this.#appFolder))
98
+ }
99
+
100
+ async #copyCleanModel (buildDirCdsModels) {
101
+ // copy models again, to revert transpilation thereof.
102
+ // We only need the index.js files in un-transpiled form.
103
+ await this.copy(this.#modelDirectoryName).to(buildDirCdsModels)
104
+ await rmFiles(buildDirCdsModels, ['.ts'])
105
+ }
106
+
107
+ async build() {
108
+ await this.#runCdsTyper()
109
+ const buildDirCdsModels = path.join(this.task.dest, this.#modelDirectoryName)
110
+ // remove the js files generated by the nodejs buildtask,
111
+ // leaving only json, cds, and other static files
112
+ await rmFiles(this.task.dest, ['.js', '.ts'])
113
+
114
+ try {
115
+ await (buildConfigExists()
116
+ ? this.#buildWithConfig()
117
+ : this.#buildWithoutConfig()
118
+ )
119
+ } catch (error) {
120
+ throw error.stdout
121
+ ? new Error(error.stdout)
122
+ : error
123
+ }
124
+ this.#copyCleanModel(buildDirCdsModels)
125
+ }
126
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cap-js/cds-typer",
3
- "version": "0.21.0",
3
+ "version": "0.21.1",
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",
@@ -31,7 +31,8 @@
31
31
  "CHANGELOG.md",
32
32
  "index.js",
33
33
  "LICENSE",
34
- "README.md"
34
+ "README.md",
35
+ "cds-plugin.js"
35
36
  ],
36
37
  "types": "index.d.ts",
37
38
  "bin": {