@sap/cds-dk 8.4.1 → 8.5.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 +43 -2
- package/bin/add.js +2 -12
- package/bin/cds.js +5 -0
- package/bin/debug.js +90 -0
- package/bin/watch.js +12 -2
- package/lib/bind/index.js +1 -1
- package/lib/bind/userCdsrcJsonStorageProvider.js +0 -19
- package/lib/build/buildTaskEngine.js +1 -1
- package/lib/build/provider/hana/2migration.js +34 -20
- package/lib/build/provider/hana/index.js +74 -41
- package/lib/build/provider/internalBuildTaskProvider.js +1 -1
- package/lib/build/provider/mtx-extension/index.js +4 -4
- package/lib/build/provider/mtx-sidecar/index.js +2 -2
- package/lib/build/provider/nodejs/index.js +3 -19
- package/lib/build/util.js +41 -17
- package/lib/deploy/to-hana/hdiDeployUtil.js +14 -10
- package/lib/import/message.js +2 -1
- package/lib/import/odata/metadataconverter/MetadataConverter.js +5 -0
- package/lib/import/odata/v4parser.js +32 -43
- package/lib/index.js +14 -14
- package/lib/init/add.js +26 -0
- package/lib/init/constants.js +5 -6
- package/lib/init/index.js +17 -25
- package/lib/init/merge.js +1 -4
- package/lib/init/projectReader.js +75 -9
- package/lib/init/registries/mta.js +0 -1
- package/lib/init/template/approuter/files/package.json +1 -1
- package/lib/init/template/cloud-logging/files/package.json.hbs +1 -12
- package/lib/init/template/cloud-logging/files/values.yaml.hbs +16 -0
- package/lib/init/template/cloud-logging/index.js +14 -10
- package/lib/init/template/data/as-csv.js +1 -1
- package/lib/init/template/data/as-json.js +5 -5
- package/lib/init/template/data/index.js +1 -26
- package/lib/init/template/esm/files/package.json.hbs +3 -0
- package/lib/init/template/esm/index.js +16 -0
- package/lib/init/template/hana/files/package.json.hbs +18 -4
- package/lib/init/template/handler/files/handler.xs.hbs +56 -0
- package/lib/init/template/handler/index.js +84 -9
- package/lib/init/template/helm/index.js +4 -1
- package/lib/init/template/http/index.js +108 -39
- package/lib/init/template/sample/files/nodejs/{admin-service.js → admin-service.js.hbs} +8 -1
- package/lib/init/template/sample/files/nodejs/{cat-service.js → cat-service.js.hbs} +8 -3
- package/lib/init/template/sample/index.js +4 -2
- package/lib/init/template/side-by-side-extensibility/index.js +1 -0
- package/lib/init/template/telemetry/files/package.json.hbs +18 -0
- package/lib/init/template/telemetry/index.js +8 -2
- package/lib/init/template/typescript/files/package.json +1 -1
- package/lib/init/template/workzone-standard/index.js +1 -1
- package/lib/init/types.d.ts +0 -6
- package/lib/watch/node-watch.js +25 -9
- package/npm-shrinkwrap.json +28 -33
- package/package.json +1 -1
|
@@ -2,16 +2,21 @@ const https = require('node:https')
|
|
|
2
2
|
const axios = require('axios')
|
|
3
3
|
const asJson = require("../data/as-json")
|
|
4
4
|
const cds = require('../../../cds')
|
|
5
|
-
const cf = require(
|
|
5
|
+
const cf = require('../../../util/cf')
|
|
6
6
|
const { write, exists } = cds.utils
|
|
7
|
-
const { filterStringAsRegex } = require(
|
|
7
|
+
const { filterStringAsRegex } = require('../../add')
|
|
8
|
+
const { _readSpringBootConfig } = require('../../projectReader')
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {{name: string, entities:[], actions:[], urlPaths: string[], isJava:boolean}} ServiceData
|
|
12
|
+
* @typedef {Map<string, ServiceData>|undefined} ServiceMap
|
|
13
|
+
*/
|
|
8
14
|
|
|
9
15
|
module.exports = class HttpTemplate extends require('../../plugin') {
|
|
10
16
|
|
|
11
17
|
#nodeHost = "http://localhost:4004"
|
|
12
18
|
#javaHost = "http://localhost:8080"
|
|
13
19
|
#defaultOutputDir = "test/http"
|
|
14
|
-
#defaultAuth = `Authorization: Basic alice:`
|
|
15
20
|
|
|
16
21
|
static help() {
|
|
17
22
|
return 'add .http files for modeled services'
|
|
@@ -29,12 +34,14 @@ module.exports = class HttpTemplate extends require('../../plugin') {
|
|
|
29
34
|
'for-app': {
|
|
30
35
|
type: 'string',
|
|
31
36
|
short: 'a',
|
|
32
|
-
help:
|
|
37
|
+
help: `Specify the name of the app to generate requests for.
|
|
38
|
+
If not specified, localhost and default auth will be used.`
|
|
33
39
|
},
|
|
34
40
|
'out': {
|
|
35
41
|
type: 'string',
|
|
36
42
|
short: 'o',
|
|
37
|
-
help:
|
|
43
|
+
help: `The output directory.
|
|
44
|
+
By default, an \`http\` dir is created in either \`test/\`, \`tests/\`, \`__tests__/\`, or at the root level.`
|
|
38
45
|
},
|
|
39
46
|
'dry': {
|
|
40
47
|
type: 'boolean',
|
|
@@ -48,42 +55,16 @@ module.exports = class HttpTemplate extends require('../../plugin') {
|
|
|
48
55
|
cds.linked(csn)
|
|
49
56
|
|
|
50
57
|
const serviceInfo = cds.compile.to.serviceinfo(csn)
|
|
51
|
-
let [hostname, auth] = await this.#getHostnameAndAuth(serviceInfo)
|
|
52
58
|
let services = this.#collectServiceInfo(csn, serviceInfo)
|
|
53
59
|
if (!services) return
|
|
54
60
|
|
|
55
61
|
const payload = await this.#generatePayload(csn, services)
|
|
56
|
-
this.#generateRequests(services,
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async #getHostnameAndAuth(serviceInfo) {
|
|
60
|
-
if (!cds.cli.options['for-app']) {
|
|
61
|
-
if (serviceInfo[0].runtime === 'Java') {
|
|
62
|
-
return [this.#javaHost, null]
|
|
63
|
-
} else {
|
|
64
|
-
return [this.#nodeHost, this.#defaultAuth]
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const app = cds.cli.options['for-app']
|
|
69
|
-
// Later: differentiate between CF and Kyma
|
|
70
|
-
const env = await cf.getEnv(app)
|
|
71
|
-
if (!cds.cli.options.dry) console.error('Fetching credentials from Cloud Foundry app \'' + app + '\'...')
|
|
72
|
-
const hostname = `https://${env.application_env_json.VCAP_APPLICATION.application_uris[0]}`
|
|
73
|
-
const xsuaaCredentials = env.system_env_json.VCAP_SERVICES?.xsuaa[0]?.credentials ?? {}
|
|
74
|
-
const { url, clientid, clientsecret, certurl, certificate, key } = xsuaaCredentials
|
|
75
|
-
if (!url) throw new Error('No XSUAA service found in the environment of ' + app)
|
|
76
|
-
|
|
77
|
-
const auth = certificate ? { maxRedirects: 0, httpsAgent: new https.Agent({ cert: certificate, key }) }
|
|
78
|
-
: { auth: { username: clientid, password: clientsecret } }
|
|
79
|
-
const authUrl = `${certurl ?? url}/oauth/token`
|
|
80
|
-
const data = `grant_type=client_credentials&client_id=${encodeURI(clientid)}`
|
|
81
|
-
const config = { method: 'POST', timeout: 5000, data, ...auth }
|
|
82
|
-
const { access_token } = (await axios(authUrl, config)).data
|
|
83
|
-
const approuterAuth = `x-approuter-authorization: bearer ${access_token}`
|
|
84
|
-
return [hostname, approuterAuth]
|
|
62
|
+
await this.#generateRequests(services, payload, csn)
|
|
85
63
|
}
|
|
86
64
|
|
|
65
|
+
/**
|
|
66
|
+
* @returns {ServiceMap}
|
|
67
|
+
*/
|
|
87
68
|
#collectServiceInfo(csn, serviceInfo) {
|
|
88
69
|
const services = new Map()
|
|
89
70
|
|
|
@@ -103,7 +84,7 @@ module.exports = class HttpTemplate extends require('../../plugin') {
|
|
|
103
84
|
}
|
|
104
85
|
}
|
|
105
86
|
if (entities.length === 0 && actions.length === 0) return
|
|
106
|
-
services.set(s.name, { entities, urlPaths, actions })
|
|
87
|
+
services.set(s.name, { name: s.name, entities, urlPaths, actions, isJava: sInfo.runtime === 'Java' })
|
|
107
88
|
})
|
|
108
89
|
|
|
109
90
|
if (services.size === 0) {
|
|
@@ -124,6 +105,9 @@ module.exports = class HttpTemplate extends require('../../plugin') {
|
|
|
124
105
|
}
|
|
125
106
|
}
|
|
126
107
|
|
|
108
|
+
/**
|
|
109
|
+
* @param {ServiceMap} services
|
|
110
|
+
*/
|
|
127
111
|
async #generatePayload(csn, services) {
|
|
128
112
|
const payload = {}
|
|
129
113
|
for (const [, service] of services) {
|
|
@@ -143,9 +127,13 @@ module.exports = class HttpTemplate extends require('../../plugin') {
|
|
|
143
127
|
return payload
|
|
144
128
|
}
|
|
145
129
|
|
|
146
|
-
|
|
130
|
+
/**
|
|
131
|
+
* @param {ServiceMap} services
|
|
132
|
+
*/
|
|
133
|
+
async #generateRequests(services, payload, csn) {
|
|
147
134
|
let varsDefined = false // when writing requests for multiple services to stdout, define vars only once
|
|
148
135
|
for (const [serviceName, service] of services) {
|
|
136
|
+
let [hostname, auth] = await this.#getHostnameAndAuth(service, csn)
|
|
149
137
|
let requests = []
|
|
150
138
|
if (!cds.cli.options.dry || !varsDefined) {
|
|
151
139
|
requests.push(auth ? `@server = ${hostname}\n@auth = ${auth}\n` : `@server = ${hostname}\n`)
|
|
@@ -179,11 +167,11 @@ module.exports = class HttpTemplate extends require('../../plugin') {
|
|
|
179
167
|
else {
|
|
180
168
|
const postBody = JSON.stringify(entityData, null, 2)
|
|
181
169
|
let id
|
|
182
|
-
const compositeKey = Object.keys(e.keys).length > 1
|
|
170
|
+
const compositeKey = Object.keys(e.keys||{}).length > 1
|
|
183
171
|
if (compositeKey) {
|
|
184
172
|
id = [...e.keys].map(k => k.type === 'cds.String' ? `${k.name}='${entityData[k.name]}'` : `${k.name}=${entityData[k.name]}`).join(',')
|
|
185
173
|
} else {
|
|
186
|
-
id = entityData[Object.keys(e.keys)[0]]
|
|
174
|
+
id = entityData[Object.keys(e.keys||{})[0]]
|
|
187
175
|
}
|
|
188
176
|
compositeKey ? id = `(${id})` : id = `/${id}`
|
|
189
177
|
requests.push(`${requestTitle}\n# @name ${nameSlug}_POST\nPOST ${url}\n${headers}\n\n${postBody}\n`)
|
|
@@ -224,6 +212,87 @@ module.exports = class HttpTemplate extends require('../../plugin') {
|
|
|
224
212
|
}
|
|
225
213
|
}
|
|
226
214
|
|
|
215
|
+
async #getHostnameAndAuth(service, csn) {
|
|
216
|
+
if (!cds.cli.options['for-app']) {
|
|
217
|
+
const host = service.isJava ? this.#javaHost : this.#nodeHost
|
|
218
|
+
const users = Object.values(await this.#mockUsersForService(service, csn))
|
|
219
|
+
const authStr = users.length ? `Authorization: Basic ${users[0].name}:${users[0].password||''}` : null
|
|
220
|
+
return [host, authStr]
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (!this.approuterAuth) {
|
|
224
|
+
const app = cds.cli.options['for-app']
|
|
225
|
+
// Later: differentiate between CF and Kyma
|
|
226
|
+
const env = await cf.getEnv(app)
|
|
227
|
+
if (!cds.cli.options.dry) console.error('Fetching credentials from Cloud Foundry app \'' + app + '\'...')
|
|
228
|
+
this.hostname = `https://${env.application_env_json.VCAP_APPLICATION.application_uris[0]}`
|
|
229
|
+
const xsuaaCredentials = env.system_env_json.VCAP_SERVICES?.xsuaa[0]?.credentials ?? {}
|
|
230
|
+
const { url, clientid, clientsecret, certurl, certificate, key } = xsuaaCredentials
|
|
231
|
+
if (!url) throw new Error('No XSUAA service found in the environment of ' + app)
|
|
232
|
+
|
|
233
|
+
const auth = certificate ? { maxRedirects: 0, httpsAgent: new https.Agent({ cert: certificate, key }) }
|
|
234
|
+
: { auth: { username: clientid, password: clientsecret } }
|
|
235
|
+
const authUrl = `${certurl ?? url}/oauth/token`
|
|
236
|
+
const data = `grant_type=client_credentials&client_id=${encodeURI(clientid)}`
|
|
237
|
+
const config = { method: 'POST', timeout: 5000, data, ...auth }
|
|
238
|
+
const { access_token } = (await axios(authUrl, config)).data
|
|
239
|
+
this.approuterAuth = `x-approuter-authorization: bearer ${access_token}`
|
|
240
|
+
}
|
|
241
|
+
return [this.hostname, this.approuterAuth]
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Reads mock users from the cds.env or the application.yml,
|
|
246
|
+
* returning only those that match to the declared roles of the given service.
|
|
247
|
+
* @param {ServiceData} service
|
|
248
|
+
* @returns {Promise<Record<string, {password: string, roles: string[]}>>} a map of users
|
|
249
|
+
*/
|
|
250
|
+
async #mockUsersForService(service, csn) {
|
|
251
|
+
const declaredRoles = new Set()
|
|
252
|
+
Object.values(csn.definitions)
|
|
253
|
+
.filter(d => d.name.startsWith(service.name))
|
|
254
|
+
.map(d => d['@requires']).filter(Boolean)
|
|
255
|
+
.forEach(req => {
|
|
256
|
+
declaredRoles.add(...(Array.isArray(req) ? req : [req]))
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
const matchingUsers = {}
|
|
260
|
+
const addUserIfMatching = (roles, name, password) => {
|
|
261
|
+
if (!declaredRoles.size || declaredRoles.has('authenticated-user') || roles?.some(r => declaredRoles.has(r))) {
|
|
262
|
+
matchingUsers[name] = { name, password, roles }
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (service.isJava) {
|
|
267
|
+
const javaDefaultUsers = [
|
|
268
|
+
{ name: 'authenticated', roles: ['authenticated-user'] },
|
|
269
|
+
{ name: 'internal', roles: ['internal-user'] },
|
|
270
|
+
{ name: 'system', roles: ['system-user'] },
|
|
271
|
+
]
|
|
272
|
+
const javaUsers = []
|
|
273
|
+
this.javaConfig ??= await _readSpringBootConfig()
|
|
274
|
+
javaUsers.push(
|
|
275
|
+
...this.javaConfig
|
|
276
|
+
.map(cfg => cfg.cds?.security?.mock?.users) // {name: { password, roles }}
|
|
277
|
+
.filter(Boolean)
|
|
278
|
+
.flatMap(usrList => Object.entries(usrList).map(([name, {password, roles}]) => ({ name, password, roles: roles??[] })))
|
|
279
|
+
, ...javaDefaultUsers // add default users at end for lower priority
|
|
280
|
+
)
|
|
281
|
+
javaUsers.forEach(({name, password='', roles}) => addUserIfMatching(roles, name, password))
|
|
282
|
+
}
|
|
283
|
+
// Node
|
|
284
|
+
else if (cds.env.requires.auth?.users) {
|
|
285
|
+
const nodeUsers = Object.entries(cds.env.requires.auth.users)
|
|
286
|
+
nodeUsers.forEach(([name, {password, roles}]) => addUserIfMatching(roles, name, password))
|
|
287
|
+
}
|
|
288
|
+
// add a dummy user as a hint if no user matches the scopes
|
|
289
|
+
if (declaredRoles.size && !matchingUsers.length) {
|
|
290
|
+
const name = `no_user_found_for_roles_${Array.from(declaredRoles).join('_')}`
|
|
291
|
+
matchingUsers[name] = { name: name, password: '', roles: [] }
|
|
292
|
+
}
|
|
293
|
+
return matchingUsers
|
|
294
|
+
}
|
|
295
|
+
|
|
227
296
|
#write(requests, serviceName) {
|
|
228
297
|
const http = requests.join('\n')
|
|
229
298
|
if (cds.cli.options.dry) {
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
{{#isESM}}
|
|
2
|
+
import cds from '@sap/cds'
|
|
3
|
+
|
|
4
|
+
export class AdminService extends cds.ApplicationService { init() {
|
|
5
|
+
{{/isESM}}
|
|
6
|
+
{{^isESM}}
|
|
1
7
|
const cds = require('@sap/cds')
|
|
2
8
|
|
|
3
|
-
module.exports = class AdminService extends cds.ApplicationService { init(){
|
|
9
|
+
module.exports = class AdminService extends cds.ApplicationService { init() {
|
|
10
|
+
{{/isESM}}
|
|
4
11
|
|
|
5
12
|
const { Books } = this.entities
|
|
6
13
|
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
{{#isESM}}
|
|
2
|
+
import cds from '@sap/cds'
|
|
3
|
+
|
|
4
|
+
export class CatalogService extends cds.ApplicationService { init() {
|
|
5
|
+
{{/isESM}}
|
|
6
|
+
{{^isESM}}
|
|
1
7
|
const cds = require('@sap/cds')
|
|
2
8
|
|
|
3
|
-
class CatalogService extends cds.ApplicationService { init() {
|
|
9
|
+
module.exports = class CatalogService extends cds.ApplicationService { init() {
|
|
10
|
+
{{/isESM}}
|
|
4
11
|
|
|
5
12
|
const { Books } = cds.entities('sap.capire.bookshop')
|
|
6
13
|
const { ListOfBooks } = this.entities
|
|
@@ -34,5 +41,3 @@ class CatalogService extends cds.ApplicationService { init() {
|
|
|
34
41
|
// Delegate requests to the underlying generic service
|
|
35
42
|
return super.init()
|
|
36
43
|
}}
|
|
37
|
-
|
|
38
|
-
module.exports = CatalogService
|
|
@@ -2,6 +2,7 @@ const { join } = require('path')
|
|
|
2
2
|
const cds = require('../../../cds'), { exists, read, write, copy } = cds.utils
|
|
3
3
|
const { env4, readProject } = require('../../projectReader')
|
|
4
4
|
const { merge } = require('../../merge')
|
|
5
|
+
const { renderAndCopy } = require('../../template')
|
|
5
6
|
const mvn = require('../../mvn')
|
|
6
7
|
|
|
7
8
|
module.exports = class SampleTemplate extends require('../../plugin') {
|
|
@@ -13,19 +14,20 @@ module.exports = class SampleTemplate extends require('../../plugin') {
|
|
|
13
14
|
async run() {
|
|
14
15
|
const { db, srv, app } = env4('production').folders
|
|
15
16
|
const language = exists('pom.xml') ? 'java' : 'nodejs'
|
|
17
|
+
const project = readProject()
|
|
16
18
|
|
|
17
19
|
if (language === 'nodejs') {
|
|
18
20
|
await Promise.all([
|
|
19
21
|
copy(join(__dirname, 'files/db')).to(db),
|
|
20
22
|
copy(join(__dirname, 'files/srv')).to(srv)
|
|
21
23
|
])
|
|
22
|
-
await
|
|
24
|
+
await renderAndCopy(join(__dirname, 'files', language), srv, project)
|
|
23
25
|
await copy(join(__dirname, 'files/app')).to(app)
|
|
24
26
|
} else if (language === 'java') {
|
|
25
27
|
await mvn.add('sample')
|
|
26
28
|
}
|
|
27
29
|
|
|
28
|
-
const { appName, appPath, appUIPaths } =
|
|
30
|
+
const { appName, appPath, appUIPaths } = project
|
|
29
31
|
await merge(__dirname, 'files/package.json.hbs').into('package.json', { with: { appPath }})
|
|
30
32
|
|
|
31
33
|
// manifest.json must be unique
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dependencies": {
|
|
3
|
+
"@cap-js/telemetry": ">=0",
|
|
4
|
+
"@grpc/grpc-js": "^1",
|
|
5
|
+
"@opentelemetry/exporter-trace-otlp-grpc": "^0",
|
|
6
|
+
"@opentelemetry/exporter-metrics-otlp-grpc": "^0",
|
|
7
|
+
"@opentelemetry/host-metrics": "^0"
|
|
8
|
+
},
|
|
9
|
+
"cds": {
|
|
10
|
+
"requires": {
|
|
11
|
+
"[{{profile}}]": {
|
|
12
|
+
"telemetry": {
|
|
13
|
+
"kind": "to-cloud-logging"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const cds = require('../../../cds')
|
|
2
2
|
const { readProject } = require('../../projectReader')
|
|
3
|
+
const { merge, sort } = require('../../merge')
|
|
3
4
|
|
|
4
5
|
module.exports = class extends require('../../plugin') {
|
|
5
6
|
|
|
@@ -8,12 +9,17 @@ module.exports = class extends require('../../plugin') {
|
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
async canRun() {
|
|
11
|
-
const { hasMta, hasHelm, hasHelmUnifiedRuntime } = readProject()
|
|
12
|
-
if ((hasHelmUnifiedRuntime || hasHelm) && !hasMta) throw `'cds add telemetry' is not available for Kyma yet`
|
|
13
12
|
return true
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
requires() {
|
|
17
16
|
return ['cloud-logging']
|
|
18
17
|
}
|
|
18
|
+
|
|
19
|
+
async run() {
|
|
20
|
+
const project = readProject();
|
|
21
|
+
project.profile ??= 'production'
|
|
22
|
+
await merge(__dirname, 'files/package.json.hbs').into('package.json', { with: project })
|
|
23
|
+
await sort('package.json', 'dependencies')
|
|
24
|
+
}
|
|
19
25
|
}
|
package/lib/init/types.d.ts
CHANGED
package/lib/watch/node-watch.js
CHANGED
|
@@ -3,6 +3,7 @@ const LOG = cds.log('cli|watch'), DEBUG = cds.debug('cli|watch')
|
|
|
3
3
|
const { relative } = require('path')
|
|
4
4
|
|
|
5
5
|
module.exports = ({ cwd, script, ext, ignore=RegExp(), env={}, delay=200, options={} })=>{
|
|
6
|
+
const debugOpts = _debugOpts(options)
|
|
6
7
|
|
|
7
8
|
let child
|
|
8
9
|
|
|
@@ -20,18 +21,16 @@ module.exports = ({ cwd, script, ext, ignore=RegExp(), env={}, delay=200, option
|
|
|
20
21
|
|
|
21
22
|
// Re-starting child process...
|
|
22
23
|
const { fork } = require('child_process')
|
|
23
|
-
const restart = _coalesceEvents(delay, (
|
|
24
|
-
DEBUG?.('Restart', {events})
|
|
24
|
+
const restart = _coalesceEvents(delay, (eventsAndOpts) => {
|
|
25
|
+
DEBUG?.('Restart', {events: eventsAndOpts})
|
|
25
26
|
_kill (child, () => {
|
|
26
|
-
const execArgv = [...process.execArgv]
|
|
27
|
-
|
|
28
|
-
if (evt.type
|
|
29
|
-
if (evt.name
|
|
27
|
+
const execArgv = [...process.execArgv, ...debugOpts]
|
|
28
|
+
eventsAndOpts.forEach(evt => { // ad-hoc options from stdin
|
|
29
|
+
if (evt.type?.startsWith('--')) execArgv.push(evt.type)
|
|
30
|
+
if (evt.name?.startsWith('--')) execArgv.push(evt.name)
|
|
30
31
|
})
|
|
31
|
-
if (options.debug) execArgv.push('--inspect')
|
|
32
|
-
if (options['debug-brk']) execArgv.push('--inspect-brk')
|
|
33
32
|
|
|
34
|
-
const updated =
|
|
33
|
+
const updated = eventsAndOpts.filter(evt => evt.type && evt.type === 'update').map(evt => evt.name)
|
|
35
34
|
emitter.emit ('restart', updated)
|
|
36
35
|
child = fork (script, { cwd, env, stdio:'inherit', execArgv }, (err)=>{
|
|
37
36
|
if (err) console.error (err)
|
|
@@ -147,4 +146,21 @@ function _kill (child, cb=()=>{}) {
|
|
|
147
146
|
child.kill()
|
|
148
147
|
}
|
|
149
148
|
|
|
149
|
+
function _debugOpts(options={}) {
|
|
150
|
+
const o = []
|
|
151
|
+
if ('debug' in options) {
|
|
152
|
+
options.inspect = options.debug
|
|
153
|
+
delete options.debug
|
|
154
|
+
}
|
|
155
|
+
if ('inspect' in options) { // could be 0
|
|
156
|
+
if (typeof options.inspect === 'string') o.push(`--inspect=${options.inspect}`) // could be port and/or host
|
|
157
|
+
else o.push(`--inspect`)
|
|
158
|
+
}
|
|
159
|
+
if ('inspect-brk' in options) {
|
|
160
|
+
if (typeof options['inspect-brk'] === 'string') o.push(`--inspect-brk=${options['inspect-brk']}`)
|
|
161
|
+
else o.push(`--inspect-brk`)
|
|
162
|
+
}
|
|
163
|
+
return o
|
|
164
|
+
}
|
|
165
|
+
|
|
150
166
|
const _pending = Symbol.for('sap.cds.watch.pendingKill')
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sap/cds-dk",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.5.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@sap/cds-dk",
|
|
9
|
-
"version": "8.
|
|
9
|
+
"version": "8.5.0",
|
|
10
10
|
"license": "SEE LICENSE IN LICENSE",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@cap-js/asyncapi": "^1.0.0",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
45
|
"node_modules/@cap-js/db-service": {
|
|
46
|
-
"version": "1.
|
|
46
|
+
"version": "1.16.0",
|
|
47
47
|
"license": "SEE LICENSE",
|
|
48
48
|
"optional": true,
|
|
49
49
|
"dependencies": {
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
}
|
|
65
65
|
},
|
|
66
66
|
"node_modules/@cap-js/sqlite": {
|
|
67
|
-
"version": "1.7.
|
|
67
|
+
"version": "1.7.7",
|
|
68
68
|
"license": "SEE LICENSE",
|
|
69
69
|
"optional": true,
|
|
70
70
|
"dependencies": {
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
}
|
|
110
110
|
},
|
|
111
111
|
"node_modules/@eslint/config-array": {
|
|
112
|
-
"version": "0.
|
|
112
|
+
"version": "0.19.0",
|
|
113
113
|
"license": "Apache-2.0",
|
|
114
114
|
"dependencies": {
|
|
115
115
|
"@eslint/object-schema": "^2.1.4",
|
|
@@ -121,14 +121,14 @@
|
|
|
121
121
|
}
|
|
122
122
|
},
|
|
123
123
|
"node_modules/@eslint/core": {
|
|
124
|
-
"version": "0.
|
|
124
|
+
"version": "0.9.0",
|
|
125
125
|
"license": "Apache-2.0",
|
|
126
126
|
"engines": {
|
|
127
127
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
128
128
|
}
|
|
129
129
|
},
|
|
130
130
|
"node_modules/@eslint/eslintrc": {
|
|
131
|
-
"version": "3.
|
|
131
|
+
"version": "3.2.0",
|
|
132
132
|
"license": "MIT",
|
|
133
133
|
"dependencies": {
|
|
134
134
|
"ajv": "^6.12.4",
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
}
|
|
150
150
|
},
|
|
151
151
|
"node_modules/@eslint/js": {
|
|
152
|
-
"version": "9.
|
|
152
|
+
"version": "9.15.0",
|
|
153
153
|
"license": "MIT",
|
|
154
154
|
"engines": {
|
|
155
155
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
@@ -163,7 +163,7 @@
|
|
|
163
163
|
}
|
|
164
164
|
},
|
|
165
165
|
"node_modules/@eslint/plugin-kit": {
|
|
166
|
-
"version": "0.2.
|
|
166
|
+
"version": "0.2.3",
|
|
167
167
|
"license": "Apache-2.0",
|
|
168
168
|
"dependencies": {
|
|
169
169
|
"levn": "^0.4.1"
|
|
@@ -224,7 +224,7 @@
|
|
|
224
224
|
}
|
|
225
225
|
},
|
|
226
226
|
"node_modules/@sap/cds": {
|
|
227
|
-
"version": "8.
|
|
227
|
+
"version": "8.5.0",
|
|
228
228
|
"license": "SEE LICENSE IN LICENSE",
|
|
229
229
|
"dependencies": {
|
|
230
230
|
"@sap/cds-compiler": ">=5.1",
|
|
@@ -250,7 +250,7 @@
|
|
|
250
250
|
}
|
|
251
251
|
},
|
|
252
252
|
"node_modules/@sap/cds-compiler": {
|
|
253
|
-
"version": "5.
|
|
253
|
+
"version": "5.5.0",
|
|
254
254
|
"license": "SEE LICENSE IN LICENSE",
|
|
255
255
|
"dependencies": {
|
|
256
256
|
"antlr4": "4.9.3"
|
|
@@ -265,7 +265,7 @@
|
|
|
265
265
|
}
|
|
266
266
|
},
|
|
267
267
|
"node_modules/@sap/cds-fiori": {
|
|
268
|
-
"version": "1.2.
|
|
268
|
+
"version": "1.2.8",
|
|
269
269
|
"license": "SEE LICENSE IN LICENSE",
|
|
270
270
|
"peerDependencies": {
|
|
271
271
|
"@sap/cds": ">=7.6",
|
|
@@ -286,7 +286,7 @@
|
|
|
286
286
|
}
|
|
287
287
|
},
|
|
288
288
|
"node_modules/@sap/cds-mtxs": {
|
|
289
|
-
"version": "2.
|
|
289
|
+
"version": "2.4.0",
|
|
290
290
|
"license": "SEE LICENSE IN LICENSE",
|
|
291
291
|
"dependencies": {
|
|
292
292
|
"@sap/hdi-deploy": ">=4",
|
|
@@ -466,7 +466,7 @@
|
|
|
466
466
|
"license": "MIT"
|
|
467
467
|
},
|
|
468
468
|
"node_modules/axios": {
|
|
469
|
-
"version": "1.7.
|
|
469
|
+
"version": "1.7.8",
|
|
470
470
|
"license": "MIT",
|
|
471
471
|
"dependencies": {
|
|
472
472
|
"follow-redirects": "^1.15.6",
|
|
@@ -498,7 +498,7 @@
|
|
|
498
498
|
"optional": true
|
|
499
499
|
},
|
|
500
500
|
"node_modules/better-sqlite3": {
|
|
501
|
-
"version": "11.
|
|
501
|
+
"version": "11.6.0",
|
|
502
502
|
"hasInstallScript": true,
|
|
503
503
|
"license": "MIT",
|
|
504
504
|
"optional": true,
|
|
@@ -728,7 +728,7 @@
|
|
|
728
728
|
"license": "MIT"
|
|
729
729
|
},
|
|
730
730
|
"node_modules/cross-spawn": {
|
|
731
|
-
"version": "7.0.
|
|
731
|
+
"version": "7.0.6",
|
|
732
732
|
"license": "MIT",
|
|
733
733
|
"dependencies": {
|
|
734
734
|
"path-key": "^3.1.0",
|
|
@@ -886,24 +886,24 @@
|
|
|
886
886
|
}
|
|
887
887
|
},
|
|
888
888
|
"node_modules/eslint": {
|
|
889
|
-
"version": "9.
|
|
889
|
+
"version": "9.15.0",
|
|
890
890
|
"license": "MIT",
|
|
891
891
|
"dependencies": {
|
|
892
892
|
"@eslint-community/eslint-utils": "^4.2.0",
|
|
893
893
|
"@eslint-community/regexpp": "^4.12.1",
|
|
894
|
-
"@eslint/config-array": "^0.
|
|
895
|
-
"@eslint/core": "^0.
|
|
896
|
-
"@eslint/eslintrc": "^3.
|
|
897
|
-
"@eslint/js": "9.
|
|
898
|
-
"@eslint/plugin-kit": "^0.2.
|
|
894
|
+
"@eslint/config-array": "^0.19.0",
|
|
895
|
+
"@eslint/core": "^0.9.0",
|
|
896
|
+
"@eslint/eslintrc": "^3.2.0",
|
|
897
|
+
"@eslint/js": "9.15.0",
|
|
898
|
+
"@eslint/plugin-kit": "^0.2.3",
|
|
899
899
|
"@humanfs/node": "^0.16.6",
|
|
900
900
|
"@humanwhocodes/module-importer": "^1.0.1",
|
|
901
|
-
"@humanwhocodes/retry": "^0.4.
|
|
901
|
+
"@humanwhocodes/retry": "^0.4.1",
|
|
902
902
|
"@types/estree": "^1.0.6",
|
|
903
903
|
"@types/json-schema": "^7.0.15",
|
|
904
904
|
"ajv": "^6.12.4",
|
|
905
905
|
"chalk": "^4.0.0",
|
|
906
|
-
"cross-spawn": "^7.0.
|
|
906
|
+
"cross-spawn": "^7.0.5",
|
|
907
907
|
"debug": "^4.3.2",
|
|
908
908
|
"escape-string-regexp": "^4.0.0",
|
|
909
909
|
"eslint-scope": "^8.2.0",
|
|
@@ -922,8 +922,7 @@
|
|
|
922
922
|
"lodash.merge": "^4.6.2",
|
|
923
923
|
"minimatch": "^3.1.2",
|
|
924
924
|
"natural-compare": "^1.4.0",
|
|
925
|
-
"optionator": "^0.9.3"
|
|
926
|
-
"text-table": "^0.2.0"
|
|
925
|
+
"optionator": "^0.9.3"
|
|
927
926
|
},
|
|
928
927
|
"bin": {
|
|
929
928
|
"eslint": "bin/eslint.js"
|
|
@@ -1179,7 +1178,7 @@
|
|
|
1179
1178
|
}
|
|
1180
1179
|
},
|
|
1181
1180
|
"node_modules/flatted": {
|
|
1182
|
-
"version": "3.3.
|
|
1181
|
+
"version": "3.3.2",
|
|
1183
1182
|
"license": "ISC"
|
|
1184
1183
|
},
|
|
1185
1184
|
"node_modules/follow-redirects": {
|
|
@@ -1701,7 +1700,7 @@
|
|
|
1701
1700
|
}
|
|
1702
1701
|
},
|
|
1703
1702
|
"node_modules/object-inspect": {
|
|
1704
|
-
"version": "1.13.
|
|
1703
|
+
"version": "1.13.3",
|
|
1705
1704
|
"license": "MIT",
|
|
1706
1705
|
"engines": {
|
|
1707
1706
|
"node": ">= 0.4"
|
|
@@ -2211,10 +2210,6 @@
|
|
|
2211
2210
|
"node": ">=6"
|
|
2212
2211
|
}
|
|
2213
2212
|
},
|
|
2214
|
-
"node_modules/text-table": {
|
|
2215
|
-
"version": "0.2.0",
|
|
2216
|
-
"license": "MIT"
|
|
2217
|
-
},
|
|
2218
2213
|
"node_modules/to-regex-range": {
|
|
2219
2214
|
"version": "5.0.1",
|
|
2220
2215
|
"license": "MIT",
|
|
@@ -2386,7 +2381,7 @@
|
|
|
2386
2381
|
}
|
|
2387
2382
|
},
|
|
2388
2383
|
"node_modules/yaml": {
|
|
2389
|
-
"version": "2.6.
|
|
2384
|
+
"version": "2.6.1",
|
|
2390
2385
|
"license": "ISC",
|
|
2391
2386
|
"bin": {
|
|
2392
2387
|
"yaml": "bin.mjs"
|