@sap/cds-dk 6.2.3 → 6.3.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.
Files changed (70) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/bin/bind.js +4 -4
  3. package/bin/deploy/to-h2.js +4 -0
  4. package/bin/deploy/to-sqlite.js +6 -4
  5. package/bin/help.js +1 -1
  6. package/bin/login.js +1 -0
  7. package/bin/push.js +29 -7
  8. package/lib/bind/userCdsrcJsonStorageProvider.js +4 -4
  9. package/lib/client/activate.js +1 -1
  10. package/lib/client/base_command.js +10 -10
  11. package/lib/client/helper/dependency_helper.js +10 -1
  12. package/lib/client/helper/logging.js +6 -2
  13. package/lib/client/pull.js +6 -6
  14. package/lib/client/push.js +33 -14
  15. package/lib/client/settings_manager.js +53 -22
  16. package/lib/compile/openapi/csdl2openapi.js +1 -1
  17. package/lib/compile/to-xsuaa.js +1 -1
  18. package/lib/import/odata/v2parser.js +37 -1
  19. package/lib/import/odata/v4parser.js +101 -23
  20. package/lib/init/constants.js +1 -1
  21. package/lib/init/index.js +23 -45
  22. package/lib/init/template/approuter/index.js +44 -48
  23. package/lib/init/template/auditlog/index.js +14 -10
  24. package/lib/init/template/cf-manifest/index.js +9 -11
  25. package/lib/init/template/connectivity/index.js +10 -10
  26. package/lib/init/template/data/index.js +20 -19
  27. package/lib/init/template/destinations/index.js +14 -9
  28. package/lib/init/template/enterprise-messaging/index.js +14 -9
  29. package/lib/init/template/extensibility/index.js +14 -9
  30. package/lib/init/template/hana/index.js +51 -57
  31. package/lib/init/template/helm/index.js +27 -59
  32. package/lib/init/template/helm/subchart/templates/_helpers.tpl +38 -0
  33. package/lib/init/template/helm/subchart/templates/deployment.yaml +12 -12
  34. package/lib/init/template/helm/subchart/values.md +565 -194
  35. package/lib/init/template/helm/subchart/values.schema.json +163 -8
  36. package/lib/init/template/helm/subchart/values.yaml +17 -1
  37. package/lib/init/template/html5-repo/index.js +15 -11
  38. package/lib/init/template/java/index.js +15 -11
  39. package/lib/init/template/kibana-logging/index.js +30 -31
  40. package/lib/init/template/lint/index.js +17 -18
  41. package/lib/init/template/mta/index.js +18 -40
  42. package/lib/init/template/mtx/index.js +2 -3
  43. package/lib/init/template/multitenancy/index.js +27 -20
  44. package/lib/init/template/nodejs/index.js +18 -20
  45. package/lib/init/template/notebook/index.js +5 -434
  46. package/lib/init/template/pipeline/index.js +10 -10
  47. package/lib/init/template/samples/index.js +7 -16
  48. package/lib/init/template/templateBase.js +17 -18
  49. package/lib/init/template/toggles/files/cdsrc.json +5 -0
  50. package/lib/init/template/toggles/files/cdsrc.json.hbs +7 -0
  51. package/lib/init/template/toggles/index.js +12 -6
  52. package/lib/init/template/xsuaa/index.js +44 -41
  53. package/lib/init/types.d.ts +0 -59
  54. package/lib/init/util/commandUtil.js +6 -7
  55. package/lib/init/util/fsUtil.js +23 -109
  56. package/lib/init/util/merge.js +319 -0
  57. package/lib/init/util/mvnArchetypeUtil.js +6 -5
  58. package/lib/init/util/projectReader.js +125 -300
  59. package/lib/init/util/spinner.js +10 -8
  60. package/lib/init/util/templateUtil.js +25 -368
  61. package/lib/lint/Linter.js +2 -3
  62. package/lib/lint/checks.js +0 -1
  63. package/lib/lint/io.js +18 -34
  64. package/npm-shrinkwrap.json +1132 -1190
  65. package/package.json +3 -3
  66. package/lib/init/template/notebook/cap_magic.py +0 -118
  67. package/lib/init/template/notebook/files/{{{name}}}.ipynb.hbs +0 -90
  68. package/lib/init/template/notebook/files/{{{name}}}.json +0 -102
  69. package/lib/init/template/notebook/notebook.js +0 -394
  70. package/lib/init/util/logger.js +0 -42
@@ -1,7 +1,7 @@
1
- const cds = require('../../../cds'), { fs, path } = cds.utils
2
- const TemplateBase = require('../templateBase')
1
+ const cds = require('../../../cds')
2
+ const { path, copy, exists } = cds.utils
3
3
  const ProjectReader = require('../../util/projectReader')
4
-
4
+ const { mergeJSON, mergeYAML, sortDependencies } = require('../../util/merge')
5
5
  const {
6
6
  srvNode, srvJava, // Server
7
7
  mtxSidecar, // Additional Modules
@@ -9,10 +9,17 @@ const {
9
9
  providedMtxAPI, srvAPI, providedMtxSidecarAPI, requiredMtxSidecarAPI // APIs
10
10
  } = require('../_merging/registry-mta');
11
11
 
12
- module.exports = class MultitenancyTemplate extends TemplateBase {
12
+ module.exports = class MultitenancyTemplate extends require('../templateBase') {
13
13
  constructor(projectPath, generator) {
14
14
  super(projectPath, generator, __dirname)
15
- this.projectReader = new ProjectReader(this)
15
+ this.projectReader = new ProjectReader(projectPath)
16
+ }
17
+
18
+ static hasFacet(env, projectPath, options) {
19
+ // REVISIT: Check if this can be simplified
20
+ return options?.add?.has('mtx') || options?.add?.has('multitenancy') ||
21
+ !!env.requires?.multitenancy || !!env.requires?.db?.multiTenant ||
22
+ this.isJava && exists(path.join(projectPath, 'mtx', 'sidecar')) || false
16
23
  }
17
24
 
18
25
  async run() {
@@ -21,22 +28,22 @@ module.exports = class MultitenancyTemplate extends TemplateBase {
21
28
  if (isNodejs) {
22
29
  const packageJSONPath = path.join(this.projectPath, 'package.json')
23
30
  const cdsTemplateFile = forProfile ? 'cds.package.json.hbs' : 'cds.package.json'
24
- await this.templateUtil.mergeJSON(packageJSONPath, path.join(__dirname, 'files', cdsTemplateFile), projectDescriptor)
25
- await this.templateUtil.mergeJSON(packageJSONPath, path.join(__dirname, 'files', 'dependencies.package.json'))
26
- await this.templateUtil.sortDependencies(packageJSONPath)
31
+ await mergeJSON(packageJSONPath, path.join(__dirname, 'files', cdsTemplateFile), projectDescriptor)
32
+ await mergeJSON(packageJSONPath, path.join(__dirname, 'files', 'dependencies.package.json'))
33
+ await sortDependencies(packageJSONPath)
27
34
  } else if (isJava) {
28
35
  const cdsrcJSONPath = path.join(this.projectPath, '.cdsrc.json')
29
- await this.templateUtil.mergeJSON(cdsrcJSONPath, path.join(__dirname, 'files', 'java', '.cdsrc.json'))
30
- await fs.copy(path.join(__dirname, 'files', 'java', 'package.json'), path.join(this.projectPath, 'mtx', 'sidecar', 'package.json'))
36
+ await mergeJSON(cdsrcJSONPath, path.join(__dirname, 'files', 'java', '.cdsrc.json'))
37
+ await copy(path.join(__dirname, 'files', 'java', 'package.json'), path.join(this.projectPath, 'mtx', 'sidecar', 'package.json'))
31
38
  }
32
39
  await this.runDependentMerging()
33
40
  }
34
41
 
35
42
  async runDependentMerging() {
36
43
  const projectDescriptor = await this.projectReader.read()
37
- const { isNodejs, isJava, hasMtaDeployment, hasHelmDeployment, hasApprouter, hasXsuaa, hasHana } = projectDescriptor.cap
44
+ const { isNodejs, isJava, hasMta, hasHelm, hasApprouter, hasXsuaa, hasHana } = projectDescriptor.cap
38
45
 
39
- if (hasMtaDeployment) {
46
+ if (hasMta) {
40
47
  const modules = isNodejs ? [srvNode] : [srvJava, mtxSidecar]
41
48
  const srv = isNodejs ? srvNode : srvJava
42
49
  const services = [saasRegistry]
@@ -68,11 +75,11 @@ module.exports = class MultitenancyTemplate extends TemplateBase {
68
75
  const templateMtaPath = path.join(__dirname, `files`, `mta.yaml.hbs`)
69
76
  const mtaPath = path.join(this.projectPath, 'mta.yaml')
70
77
  const mergingRules = { additions, overwrites, relationships }
71
- await this.templateUtil.mergeYAML(mtaPath, templateMtaPath, projectDescriptor, mergingRules)
78
+ await mergeYAML(mtaPath, templateMtaPath, projectDescriptor, mergingRules)
72
79
  }
73
80
 
74
- if (hasHelmDeployment) {
75
- await this.templateUtil.mergeYAML(
81
+ if (hasHelm) {
82
+ await mergeYAML(
76
83
  path.join(this.projectPath, 'chart', 'values.yaml'),
77
84
  {
78
85
  xsuaa: {
@@ -83,12 +90,12 @@ module.exports = class MultitenancyTemplate extends TemplateBase {
83
90
  null, { forceOverwrite: true }
84
91
  )
85
92
  //if (hasXsuaa) { // REVISIT: Can we get rid of this dependency?
86
- await fs.copy(
93
+ await copy(
87
94
  path.join(__dirname, 'files', 'xsuaa.yaml'),
88
95
  path.join(this.projectPath, 'chart', 'templates', 'xsuaa.yaml')
89
96
  )
90
97
  //}
91
- await fs.copy(
98
+ await copy(
92
99
  path.join(__dirname, 'files', 'saas-registry.yaml'),
93
100
  path.join(this.projectPath, 'chart', 'templates', 'saas-registry.yaml')
94
101
  )
@@ -107,7 +114,7 @@ module.exports = class MultitenancyTemplate extends TemplateBase {
107
114
  }
108
115
 
109
116
  if (hasXsuaa) {
110
- await this.templateUtil.mergeJSON(
117
+ await mergeJSON(
111
118
  path.join(this.projectPath, 'xs-security.json'),
112
119
  path.join(__dirname, 'files', 'xs-security.json.hbs'),
113
120
  projectDescriptor,
@@ -125,9 +132,9 @@ module.exports = class MultitenancyTemplate extends TemplateBase {
125
132
  )
126
133
  }
127
134
 
128
- if (hasXsuaa && hasHelmDeployment) {
135
+ if (hasXsuaa && hasHelm) {
129
136
  // REVISIT: Shared xs-security.json location for Helm and MTA?
130
- await fs.copy(
137
+ await copy(
131
138
  path.join(this.projectPath, 'xs-security.json'),
132
139
  path.join(this.projectPath, 'chart', 'xs-security.json')
133
140
  )
@@ -1,15 +1,20 @@
1
1
  const path = require('path');
2
+ const { mkdirp } = require('../../../cds').utils
3
+ const { COMMAND_ADD, OPTION_JAVA, OPTION_NODEJS, URLS } = require('../../constants')
4
+ const { copyFiles } = require('../../util/templateUtil')
5
+ const LOG = console
2
6
 
3
- const TemplateBase = require('../templateBase');
4
- const { COMMAND_ADD, OPTION_JAVA, OPTION_NODEJS, URLS } = require('../../constants');
5
-
6
-
7
- module.exports = class NodeJSTemplate extends TemplateBase {
7
+ module.exports = class NodeJSTemplate extends require('../templateBase') {
8
8
  constructor(projectPath, generator) {
9
9
  super(projectPath, generator, __dirname);
10
10
  }
11
11
 
12
- async checkEnabled() { //NOSONAR
12
+ static hasFacet() {
13
+ // TODO: Implement
14
+ //return this.pLanguage === P_LANGUAGE_NODEJS
15
+ }
16
+
17
+ async canRun() {
13
18
  if (this.options._cmd === COMMAND_ADD) {
14
19
  throw new Error(`You can't change the type of an existing project.`);
15
20
  }
@@ -27,27 +32,20 @@ module.exports = class NodeJSTemplate extends TemplateBase {
27
32
  const values = {
28
33
  projectName: this.projectName
29
34
  }
30
- await this.templateUtil.copyFiles('.', this.projectPath, values, this.options.force);
31
-
32
- const dbFolderPath = path.join(this.projectPath, env.folders.db);
33
- await this.fsUtil.mkdirp(dbFolderPath);
34
-
35
- const srvFolderPath = path.join(this.projectPath, env.folders.srv);
36
- await this.fsUtil.mkdirp(srvFolderPath);
37
-
38
- const appFolderPath = path.join(this.projectPath, env.folders.app);
39
- await this.fsUtil.mkdirp(appFolderPath);
35
+ await copyFiles(path.join(__dirname, 'files'), this.projectPath, values, this.options.force)
40
36
 
41
- // used to call npm install here
37
+ await mkdirp(this.projectPath, env.folders.db);
38
+ await mkdirp(this.projectPath, env.folders.srv);
39
+ await mkdirp(this.projectPath, env.folders.app);
42
40
  }
43
41
 
44
42
  async finalize() {
45
43
  const relativeProjectPath = path.relative(this.cwd, this.projectPath);
46
44
  if (relativeProjectPath && relativeProjectPath !== '.') {
47
- this.logger.log(`Continue with 'cd ${relativeProjectPath}'`);
45
+ LOG.info(`Continue with 'cd ${relativeProjectPath}'`);
48
46
  }
49
47
 
50
- this.logger.log(`Find samples on ${URLS.SAMPLES}`);
51
- this.logger.log(`Learn about next steps at ${URLS.CAPIRE}`);
48
+ LOG.info(`Find samples on ${URLS.SAMPLES}`);
49
+ LOG.info(`Learn about next steps at ${URLS.CAPIRE}`);
52
50
  }
53
51
  }
@@ -1,442 +1,13 @@
1
- const TemplateBase = require('../templateBase');
2
-
3
- const os = require('os');
4
- const path = require('path');
5
- const axios = require('axios');
6
- const cp = require('child_process');
7
-
8
- const commandUtil = require('../../util/commandUtil');
9
1
  const term = require('../../../util/term');
10
- const Notebook = require('./notebook');
11
-
12
- const { URLS } = require('../../constants');
13
- const { IS_MAC, IS_WIN, PYTHON_VENV_NAME } = require('../../constants');
14
-
15
- const nbType = 'default';
16
- const nbRequired = [];
17
- const nbTypes = {
18
- 'default': ['/docs/get-started/in-a-nutshell'],
19
- 'mta': [
20
- '/docs/guides/databases#configure-hana',
21
- '/docs/advanced/deploy-to-cloud'
22
- ],
23
- 'mtx': ['/docs/guides/multitenancy#nodejs-stack']
24
- }
25
-
26
- const REGEX_REDIRECT = /<meta\s+http-equiv\s*=\s*"refresh"\s+content\s*=\s*".*\s+url\s*=\s*(.*)\s*"/i;
27
2
 
28
- module.exports = class NotebookTemplate extends TemplateBase {
3
+ module.exports = class NotebookTemplate extends require('../templateBase') {
29
4
  constructor(projectPath, generator) {
30
5
  super(projectPath, generator, __dirname);
31
- this.pythonCmd = null;
32
- this.pythonPckCmd = null;
33
- this.pythonPath = '';
34
- this.pythonPackages = '';
35
- this.pythonPathLib = '';
36
- this.hasVscode = false;
37
- this.hasJupyterlab = false;
38
- this.validPythonVenv = false;
39
- this.binPythonVenv = 'bin';
40
- this.libPythonVenv = 'lib';
41
- this.notebookEnv = '';
42
- this.notebookExtensions = '';
43
- this.hasNotebookExtension = false;
44
- this.scrapedCapire = {};
45
- this.nb_json = null;
46
- this.missingDependencies = [];
47
- this.logOutput = '';
48
- }
49
-
50
- async _collectMatchingCmds(matches) {
51
- let allCmds = '';
52
- for (const match of matches) {
53
- if (IS_WIN) {
54
- const matchReceived = await this._tryCatchReturn({
55
- error: null,
56
- cmd: `where`,
57
- args: [`${match}*`]
58
- })
59
- if (matchReceived) {
60
- allCmds += matchReceived;
61
- }
62
- } else {
63
- let compgenCmd = `compgen -c ${match}`;
64
- if (IS_MAC) {
65
- compgenCmd = `compgen -ac | grep ${match}`
66
- }
67
- const matchReceived = await this._tryCatchReturn({
68
- error: null,
69
- cmd: '/bin/bash',
70
- args: ['-c', `${compgenCmd}`]
71
- })
72
- if (matchReceived) {
73
- allCmds += matchReceived;
74
- }
75
- }
76
- }
77
- const cmds = [];
78
- for (const cmd of allCmds.split('\n')) {
79
- cmds.push(path.basename(cmd.trim()))
80
- }
81
- return cmds
82
- }
83
-
84
- async _pythonCmdCheck() {
85
- const pythonAliases = await this._collectMatchingCmds(['python']);
86
- for (const pythonAlias of pythonAliases) {
87
- try {
88
- let pythonVersion = await commandUtil.spawnCommand(pythonAlias, ['--version'], {
89
- cwd: this.projectPath
90
- }, undefined, true);
91
- pythonVersion = pythonVersion.replace('Python ', '');
92
- if (parseFloat(pythonVersion) >= parseFloat('3.8.5')) {
93
- this.pythonCmd = pythonAlias;
94
- break;
95
- }
96
- } catch (err) {
97
- // Do nothing
98
- }
99
- }
100
- if (this.pythonCmd === null) {
101
- this.missingDependencies.push('Python (>=v3.8.5):\n' +
102
- term.warn(` ${URLS.PYTHON}\n`));
103
- if (!IS_WIN) {
104
- this.logger.log(`When using the configure script, you must add ${term.bold('--with-ensurepip=install')}`)
105
- }
106
- }
107
- }
108
-
109
- async _pythonPckCmdCheck() {
110
- const pipAliases = await this._collectMatchingCmds(['pip', 'conda']);
111
- for (const pipAlias of pipAliases) {
112
- try {
113
- await commandUtil.spawnCommand(pipAlias, ['--version'], {
114
- cwd: this.projectPath
115
- }, undefined);
116
- this.pythonPckCmd = pipAlias;
117
- break;
118
- } catch (err) {
119
- // Do nothing
120
- }
121
- }
122
- if (this.pythonPckCmd === null) {
123
- try {
124
- await commandUtil.spawnCommand('conda', ['info'], {
125
- cwd: this.projectPath
126
- }, undefined, true);
127
- this.pythonPckCmd = 'conda';
128
- } catch (err) {
129
- this.missingDependencies.push(
130
- 'Python package manager:\n' +
131
- term.warn(` ${URLS.PYTHON_PIP}`)
132
- );
133
- }
134
- }
135
- }
136
-
137
- async _pythonPcksCheck() {
138
- const argPckCmd = 'list';
139
- if (this.pythonPckCmd !== null) {
140
- try {
141
- if (!this.pythonPackages) {
142
- this.pythonPackages = await commandUtil.spawnCommand(this.pythonPckCmd, [argPckCmd], {
143
- cwd: this.projectPath
144
- }, undefined, true);
145
- }
146
- } catch (err) {
147
- // Do nothing
148
- }
149
- }
150
- if (this.pythonPackages.includes('jupyterlab')) {
151
- this.hasJupyterlab = true;
152
- }
153
- }
154
-
155
- async _notebookViewerCheck() {
156
- try {
157
- await commandUtil.spawnCommand('code', ['--version'], {
158
- cwd: this.projectPath
159
- });
160
- this.hasVscode = true;
161
- } catch (err) {
162
- this.logger.log(`Consider installing vscode: ${URLS.VSCODE}`)
163
- }
164
- if (this.hasVscode) {
165
- this.notebookExtensions = await commandUtil.spawnCommand('code',
166
- ['--list-extensions', '--category', 'notebooks'], {
167
- cwd: this.projectPath
168
- }, undefined, true);
169
- if (this.notebookExtensions && this.notebookExtensions.includes('ms-python.python')) {
170
- this.hasNotebookExtension = true;
171
- }
172
- if (!this.hasNotebookExtension) {
173
- this.missingDependencies.push('No notebook viewer found!\n' +
174
- term.info(`Consider installing the VS Code Python extension:\n
175
- 'ms-python.python': ${URLS.VSCODE_NBVIEWER}\n`));
176
- }
177
- }
178
- }
179
-
180
- _getNotebookEnv() {
181
- this.notebookEnv = path.join(os.homedir(), PYTHON_VENV_NAME);
182
- let cmd;
183
- if (IS_WIN) {
184
- cmd = 'where';
185
- } else {
186
- cmd = 'which';
187
- }
188
- this.pythonPath = cp.execSync(`${cmd} ${this.pythonCmd}`).toString();
189
- }
190
-
191
- async _tryCatch(task) {
192
- try {
193
- await commandUtil.spawnCommand(
194
- task.cmd,
195
- task.args, {
196
- cwd: this.projectPath
197
- }, undefined, true);
198
- } catch (err) {
199
- if (task.error) {
200
- throw new Error(task.error);
201
- }
202
- }
203
- }
204
-
205
- async _tryCatchReturn(task) {
206
- try {
207
- const result = await commandUtil.spawnCommand(
208
- task.cmd,
209
- task.args, {
210
- cwd: this.projectPath
211
- }, undefined, true);
212
- return result;
213
- } catch (err) {
214
- if (task.error) {
215
- throw new Error(task.error);
216
- }
217
- }
218
- }
219
-
220
- async _createPythonVenv(pythonPackagesReq) {
221
- await this._tryCatch({
222
- error: "Failed to initialize virtualenv.\n" +
223
- "If you get the error [ ... 'ensurepip', '--upgrade', '--default-pip']', please install ensurepip via:\n" +
224
- `${term.bold('sudo apt-get install ' + this.pythonCmd + '-venv')}`,
225
- cmd: `${this.pythonCmd}`,
226
- args: ['-m', 'venv', `${this.notebookEnv}`]
227
- })
228
- if (IS_WIN) {
229
- await this._tryCatch({
230
- error: "Failed to prepare virtualenv",
231
- cmd: `"${path.join(this.notebookEnv, this.binPythonVenv, 'activate')} && ` +
232
- `pip install ${pythonPackagesReq.join(' ')} && ` +
233
- `${path.join(this.notebookEnv, this.binPythonVenv, 'ipython')} kernel install --user --name=${PYTHON_VENV_NAME} && ` +
234
- `deactivate"`,
235
- args: []
236
- })
237
- } else {
238
- await this._tryCatch({
239
- error: "Failed to prepare virtualenv",
240
- cmd: '/bin/sh',
241
- args: ['-c', `. ${path.join(this.notebookEnv, this.binPythonVenv, 'activate')}
242
- pip install ${pythonPackagesReq.join(' ')}
243
- ${path.join(this.notebookEnv, this.binPythonVenv, 'ipython')} kernel install --user --name=${PYTHON_VENV_NAME}
244
- deactivate`]
245
- })
246
- }
247
6
  }
248
7
 
249
- async _checkPythonVenv(pythonPackagesReq) {
250
- // Check if venv exists
251
- const pythonVenvPath = await this.fsUtil.pathExists(this.notebookEnv);
252
- if (pythonVenvPath) {
253
- if (IS_WIN) {
254
- this.pythonPathLib = path.join(this.notebookEnv, this.libPythonVenv, 'site-packages');
255
- } else {
256
- this.pythonPathLib = path.join(this.notebookEnv, this.libPythonVenv, 'python*', 'site-packages');
257
- }
258
- // Check if required packages exist
259
- for (const pck of pythonPackagesReq) {
260
- const pckExists = await this.fsUtil.pathExists(this.pythonPathLib, pck);
261
- if (!pckExists) {
262
- return false;
263
- }
264
- }
265
- // Check if required scripts exist
266
- let pythonScriptsReq;
267
- if (IS_WIN) {
268
- pythonScriptsReq = ['python.exe', 'ipython.exe', 'jupyter-kernel.exe'];
269
- } else {
270
- pythonScriptsReq = ['python', 'ipython', 'jupyter-kernel'];
271
- }
272
- for (const pck of pythonScriptsReq) {
273
- const pckExists = await this.fsUtil.pathExists(this.pythonPathLib, pck);
274
- if (!pckExists) {
275
- return false;
276
- }
277
- }
278
- } else {
279
- return false
280
- }
281
- return true;
282
- }
283
-
284
- async _url2Html(contentUrl) {
285
- const response = await axios.get(contentUrl, {
286
- headers: {
287
- 'Access-Control-Allow-Origin': '*'
288
- }, 'timeout': 20000
289
- });
290
- const match = REGEX_REDIRECT.exec(response.data);
291
- if (match && match[1]) {
292
- const newContentUrl = new URL(contentUrl);
293
- const newUrl = new URL(match[1], newContentUrl.origin);
294
- this._url2Html(newUrl)
295
- } else {
296
- return response.data;
297
- }
298
- }
299
-
300
- async _collectHtmlPages(nbReq) {
301
- if (!this.scrapedCapire[nbReq]) {
302
- let pageCollection = '';
303
- for (let p = 0; p < nbTypes[nbReq].length; p++) {
304
- const page = nbTypes[nbReq][p];
305
- try {
306
- const html = await this._url2Html(URLS.CAPIRE + page);
307
- if (!pageCollection) {
308
- pageCollection = html;
309
- } else {
310
- pageCollection += html;
311
- }
312
- } catch (err) {
313
- // Do nothing
314
- }
315
- }
316
- this.scrapedCapire[nbReq] = pageCollection;
317
- }
318
- }
319
-
320
- async _notebookInit(projectName) {
321
- // Create new notebook, overwrite if already exists
322
- await this.templateUtil.copyFiles('.', this.projectPath, { name: projectName, cap: URLS.CAPIRE }, true);
323
- this.nb_json = path.resolve('.', this.projectPath, `${projectName}.ipynb`);
324
- const exists = await this.fsUtil.pathExists(this.nb_json);
325
- const nb = exists ? await this.fsUtil.readJSON(this.nb_json) : {};
326
- return nb;
327
- }
328
-
329
- async _notebookWriteFromComponents(type) {
330
- if (type === 'mta') {
331
- nbRequired.push('default')
332
- } else if (type === 'mtx') {
333
- nbRequired.push('default')
334
- nbRequired.push('mta')
335
- }
336
- nbRequired.push(type)
337
-
338
- for (let n = 0; n < nbRequired.length; n++) {
339
- const nbReq = nbRequired[n];
340
-
341
- // Get notebook name
342
- let projectName = `${this.projectName}`
343
- if (nbReq !== 'default') {
344
- projectName = `${this.projectName}-${nbReq}`
345
- }
346
- await this._collectHtmlPages(nbReq);
347
- const nb = await this._notebookInit(projectName);
348
-
349
- // Add cap magic
350
- const stringPython = await this.fsUtil.readFile(path.join(__dirname, 'cap_magic.py'), 'UTF-8');
351
- nb['metadata']['cap_magic'] = stringPython;
352
-
353
- // Generate notebook
354
- this.logger.debug(` writing ${type} notebook...`)
355
- const notebook = new Notebook({ name: projectName, nb: nb, html: this.scrapedCapire[nbReq], url: URLS.CAPIRE, route: nbTypes[nbReq][0] });
356
- await this.fsUtil.writeJSON(this.nb_json, notebook.nb);
357
- }
358
- }
359
-
360
- async checkEnabled() {
361
- this.logger.warn('There is a new generation of notebooks. Find out more about the new VS Code based CAP Notebooks on https://cap.cloud.sap/docs/releases/jun22#vs-code-cap-notebooks.');
362
- this.logger.log();
363
- return true;
364
- }
365
-
366
- async run() {
367
-
368
- // REQUIRED: Python [python or python3]
369
- if (!this.pythonCmd) {
370
- await this._pythonCmdCheck()
371
- }
372
-
373
- // REQUIRED: Python package manager
374
- if (!this.pythonPckCmd) {
375
- await this._pythonPckCmdCheck()
376
- }
377
-
378
- // OPTIONAL: JupyterLab viewer in python packages
379
- if (!this.hasJupyterlab) {
380
- await this._pythonPcksCheck()
381
- }
382
-
383
- // OPTIONAL: Jupyter Notebook viewer in VS Code extensions
384
- if (!this.hasVscode && !this.hasNotebookExtension) {
385
- await this._notebookViewerCheck()
386
- }
387
-
388
- // If missing dependencies, throw error
389
- if (this.missingDependencies.length > 0) {
390
- let error = '\nYou are missing ' + this.missingDependencies.length + ' notebook dependencies!\n' +
391
- 'Please install the following components (in order!) and rerun your cds command:\n\n'
392
- for (let i = 0; i < this.missingDependencies.length; i++) {
393
- error += '(' + (i + 1) + ') ' + this.missingDependencies[i] + '\n';
394
- }
395
- throw new Error(error);
396
- } else {
397
- if (IS_WIN) {
398
- this.binPythonVenv = 'Scripts';
399
- this.libPythonVenv = 'Lib';
400
- }
401
- if (!this.pythonPath) {
402
- this._getNotebookEnv();
403
- }
404
- // If not exists, install virtualenv with required packages
405
- const pythonPackagesReq = ['ipykernel', 'notebook'];
406
- if (!this.validPythonVenv) {
407
- this.validPythonVenv = await this._checkPythonVenv(pythonPackagesReq);
408
- if (!this.validPythonVenv) {
409
- await this._createPythonVenv(pythonPackagesReq);
410
- }
411
- }
412
- // Generate notebook from components
413
- await this._notebookWriteFromComponents(nbType);
414
- }
415
- }
416
-
417
- async finalize() {
418
- this.logOutput = [' '];
419
- if (this.hasVscode && this.hasNotebookExtension) {
420
- this.logOutput.push(`To view the notebook in VS Code:`);
421
- this.logOutput.push(`\t1. ${term.info('Ctrl + Click')} the following link: ${term.info(`${this.nb_json}`)}`);
422
- this.logOutput.push(`\t2. Make sure to ${term.info('Trust')} the notebook in the popup window to enable markdown and code execution`);
423
- this.logOutput.push(`\t3. Run the notebook`);
424
- this.logOutput.push('');
425
- }
426
- if (this.pythonPackages.includes('notebook') && this.hasJupyterlab) {
427
- this.logOutput.push(`To view the notebook in JupyterLab:`);
428
- this.logOutput.push(`\t1. Open with JupyterLab: ${term.info(`python -m jupyterlab ${path.relative(process.cwd(), this.nb_json)}`)}`);
429
- this.logOutput.push(`\t2. Run the notebook`);
430
- this.logOutput.push('');
431
- }
432
- this.logOutput.push(`To view the notebook in your browser:`);
433
- this.logOutput.push(`\t1. Open with Jupyter: ${term.info(path.join(this.notebookEnv, this.binPythonVenv, 'jupyter') +
434
- ' notebook ' + path.relative(process.cwd(), this.nb_json))}`);
435
- this.logOutput.push(`\t2. Run the notebook`);
436
- this.logOutput.push('');
437
-
438
- for (const line of this.logOutput) {
439
- this.logger.log(line);
440
- }
8
+ async canRun() {
9
+ console.log(term.warn('CAP Jupyter Notebooks have been replaced by Custom CAP Notebooks for VS Code!'));
10
+ console.log(`They are now part of the CDS Editor: ${term.info('https://cap.cloud.sap/docs/tools/#add-cds-editor')}`);
11
+ return false;
441
12
  }
442
13
  }
@@ -1,21 +1,21 @@
1
1
  const path = require('path');
2
+ const { exists } = require('../../../cds').utils
3
+ const { copyFiles } = require('../../util/templateUtil')
4
+ const { URLS } = require('../../constants')
5
+ const LOG = console
2
6
 
3
- const TemplateBase = require('../templateBase');
4
- const { URLS } = require('../../constants');
5
-
6
-
7
- module.exports = class PipelineTemplate extends TemplateBase {
7
+ module.exports = class PipelineTemplate extends require('../templateBase') {
8
8
  constructor(projectPath, generator) {
9
9
  super(projectPath, generator, __dirname);
10
10
  }
11
11
 
12
- async checkEnabled() {
12
+ async canRun() {
13
13
  if (this.options.force) {
14
14
  return true;
15
15
  }
16
16
 
17
- if (await this.fsUtil.pathExists(path.join(this.projectPath, 'Jenkinsfile')) ||
18
- await this.fsUtil.pathExists(path.join(this.projectPath, '.pipeline/config.yml'))) {
17
+ if (exists(path.join(this.projectPath, 'Jenkinsfile')) ||
18
+ exists(path.join(this.projectPath, '.pipeline/config.yml'))) {
19
19
  throw new Error(`Pipeline support file exists. Use --force to overwrite.`);
20
20
  }
21
21
 
@@ -23,10 +23,10 @@ module.exports = class PipelineTemplate extends TemplateBase {
23
23
  }
24
24
 
25
25
  async run() {
26
- await this.templateUtil.copyFiles('.', this.projectPath, {}, this.options.force);
26
+ await copyFiles(path.join(__dirname, 'files'), this.projectPath, {}, this.options.force);
27
27
  }
28
28
 
29
29
  async finalize() {
30
- this.logger.log(`For information on project "Piper" and its pipelines see ${URLS.PIPELINE_HELP}`);
30
+ LOG.info(`For information on project "Piper" and its pipelines see ${URLS.PIPELINE_HELP}`);
31
31
  }
32
32
  }