devextreme-cli 1.3.1 → 1.4.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.
Files changed (70) hide show
  1. package/index.js +4 -2
  2. package/package.json +8 -3
  3. package/src/application.js +19 -19
  4. package/src/applications/application.angular.js +48 -46
  5. package/src/applications/application.react.js +76 -39
  6. package/src/applications/application.vue.js +71 -34
  7. package/src/commands.json +3 -0
  8. package/src/templates/react/application/src/{App.js → App.tsx} +0 -0
  9. package/src/templates/react/application/src/{Content.js → Content.tsx} +11 -9
  10. package/src/templates/react/application/src/UnauthenticatedContent.tsx +46 -0
  11. package/src/templates/react/application/src/api/{auth.js → auth.tsx} +4 -4
  12. package/src/templates/react/application/src/{app-info.js → app-info.tsx} +0 -0
  13. package/src/templates/react/application/src/{app-navigation.js → app-navigation.tsx} +0 -0
  14. package/src/templates/react/application/src/app-routes.tsx +24 -0
  15. package/src/templates/react/application/src/components/change-password-form/{change-password-form.js → ChangePasswordForm.tsx} +9 -8
  16. package/src/templates/react/application/src/components/create-account-form/{create-account-form.scss → CreateAccountForm.scss} +0 -0
  17. package/src/templates/react/application/src/components/create-account-form/{create-account-form.js → CreateAccountForm.tsx} +10 -9
  18. package/src/templates/react/application/src/components/footer/{footer.scss → Footer.scss} +0 -0
  19. package/src/templates/react/application/src/components/footer/{footer.js → Footer.tsx} +1 -1
  20. package/src/templates/react/application/src/components/header/{header.scss → Header.scss} +0 -0
  21. package/src/templates/react/application/src/components/header/{header.js → Header.tsx} +4 -3
  22. package/src/templates/react/application/src/components/index.tsx +7 -0
  23. package/src/templates/react/application/src/components/login-form/{login-form.scss → LoginForm.scss} +0 -0
  24. package/src/templates/react/application/src/components/login-form/{login-form.js → LoginForm.tsx} +7 -7
  25. package/src/templates/react/application/src/components/reset-password-form/{reset-password-form.scss → ResetPasswordForm.scss} +0 -0
  26. package/src/templates/react/application/src/components/reset-password-form/{reset-password-form.js → ResetPasswordForm.tsx} +8 -8
  27. package/src/templates/react/application/src/components/side-navigation-menu/{side-navigation-menu.scss → SideNavigationMenu.scss} +0 -0
  28. package/src/templates/react/application/src/components/side-navigation-menu/{side-navigation-menu.js → SideNavigationMenu.tsx} +10 -12
  29. package/src/templates/react/application/src/components/user-panel/{user-panel.scss → UserPanel.scss} +0 -0
  30. package/src/templates/react/application/src/components/user-panel/{user-panel.js → UserPanel.tsx} +8 -8
  31. package/src/templates/react/application/src/contexts/{auth.js → auth.tsx} +6 -5
  32. package/src/templates/react/application/src/contexts/navigation.tsx +35 -0
  33. package/src/templates/react/application/src/dx-styles.scss +25 -13
  34. package/src/templates/react/application/src/layouts/{index.js → index.tsx} +0 -0
  35. package/src/templates/react/application/src/layouts/side-nav-inner-toolbar/side-nav-inner-toolbar.scss +1 -16
  36. package/src/templates/react/application/src/layouts/side-nav-inner-toolbar/{side-nav-inner-toolbar.js → side-nav-inner-toolbar.tsx} +20 -15
  37. package/src/templates/react/application/src/layouts/side-nav-outer-toolbar/side-nav-outer-toolbar.scss +0 -9
  38. package/src/templates/react/application/src/layouts/side-nav-outer-toolbar/{side-nav-outer-toolbar.js → side-nav-outer-toolbar.tsx} +19 -16
  39. package/src/templates/react/application/src/layouts/single-card/{single-card.js → single-card.tsx} +2 -1
  40. package/src/templates/react/application/src/{polyfills.js → polyfills.tsx} +0 -0
  41. package/src/templates/react/application/src/types.tsx +57 -0
  42. package/src/templates/react/application/src/utils/{default-user.js → default-user.tsx} +0 -0
  43. package/src/templates/react/application/src/utils/{media-query.js → media-query.tsx} +4 -3
  44. package/src/templates/react/application/src/utils/{patches.js → patches.tsx} +1 -1
  45. package/src/templates/react/page/{page.js → page.tsx} +0 -0
  46. package/src/templates/react/sample-pages/home/{home.js → home.tsx} +0 -0
  47. package/src/templates/react/sample-pages/{index.js → index.tsx} +0 -0
  48. package/src/templates/react/sample-pages/profile/{profile.js → profile.tsx} +0 -0
  49. package/src/templates/react/sample-pages/tasks/{tasks.js → tasks.tsx} +1 -1
  50. package/src/templates/vue-v2/application/devextreme.json +2 -1
  51. package/src/templates/vue-v2/application/src/dx-styles.scss +12 -0
  52. package/src/templates/vue-v2/application/src/layouts/side-nav-inner-toolbar.vue +0 -15
  53. package/src/templates/vue-v2/application/src/layouts/side-nav-outer-toolbar.vue +0 -9
  54. package/src/templates/vue-v3/application/devextreme.json +2 -1
  55. package/src/templates/vue-v3/application/src/dx-styles.scss +12 -0
  56. package/src/templates/vue-v3/application/src/layouts/side-nav-inner-toolbar.vue +2 -17
  57. package/src/templates/vue-v3/application/src/layouts/side-nav-outer-toolbar.vue +0 -9
  58. package/src/themebuider.js +19 -4
  59. package/src/utility/latest-versions.js +3 -3
  60. package/src/utility/ng-version.js +35 -0
  61. package/src/utility/prompts/layout.js +9 -21
  62. package/src/utility/prompts/prompts.js +24 -8
  63. package/src/utility/prompts/typescript.js +18 -0
  64. package/src/utility/prompts/vue-version.js +9 -21
  65. package/src/utility/template-creator.js +11 -6
  66. package/src/utility/typescript-extension.js +24 -0
  67. package/src/templates/react/application/src/UnauthenticatedContent.js +0 -35
  68. package/src/templates/react/application/src/app-routes.js +0 -24
  69. package/src/templates/react/application/src/components/index.js +0 -7
  70. package/src/templates/react/application/src/contexts/navigation.js +0 -34
package/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
  const args = require('minimist')(process.argv.slice(2), {
3
3
  alias: { v: 'version' }
4
4
  });
5
+
5
6
  const commands = args['_'];
6
7
  delete args['_'];
7
8
  const themeBuilder = require('./src/themebuider');
@@ -34,9 +35,10 @@ if(args.help) {
34
35
  process.exit();
35
36
  }
36
37
 
37
- const run = (commands, options) => {
38
+
39
+ const run = async(commands, options) => {
38
40
  if(application.isApplicationCommand(commands[0])) {
39
- application.run(commands, options, devextremeConfig.read());
41
+ await application.run(commands, options, devextremeConfig.read());
40
42
  } else if(themeBuilder.isThemeBuilderCommand(commands[0])) {
41
43
  options.command = commands[0];
42
44
  themeBuilder.run(options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devextreme-cli",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "description": "DevExtreme CLI",
5
5
  "keywords": [
6
6
  "devexpress",
@@ -49,13 +49,16 @@
49
49
  "strip-bom": "^4.0.0"
50
50
  },
51
51
  "devDependencies": {
52
+ "@typescript-eslint/eslint-plugin": "^4.15.1",
52
53
  "@typescript-eslint/parser": "^4.0.1",
53
54
  "babel-eslint": "^10.1.0",
54
55
  "cross-env": "^5.2.0",
55
56
  "eslint": "^7.8.0",
56
57
  "eslint-config-angular": "^0.5.0",
58
+ "eslint-config-prettier": "^8.5.0",
57
59
  "eslint-plugin-angular": "^4.0.1",
58
60
  "eslint-plugin-jest": "^22.5.1",
61
+ "eslint-plugin-prettier": "^4.0.0",
59
62
  "eslint-plugin-react": "^7.20.6",
60
63
  "eslint-plugin-react-hooks": "^4.1.0",
61
64
  "eslint-plugin-unused-imports": "^1.1.5",
@@ -63,11 +66,13 @@
63
66
  "eslint-stylish": "^0.2.0",
64
67
  "jest": "^27.3.1",
65
68
  "jest-image-snapshot": "^4.5.0",
69
+ "prettier": "^2.6.2",
66
70
  "puppeteer": "^2.1.1",
67
71
  "rimraf": "^2.6.3",
68
72
  "tree-kill": "^1.2.1",
69
73
  "tree-kill-promise": "^1.0.3",
70
- "typescript": "^4.0.2"
74
+ "typescript": "^4.0.2",
75
+ "typescript-eslint-parser": "^22.0.0"
71
76
  },
72
- "gitHead": "4f9873f14724ac858b6d0e73bacc124c147a7eb5"
77
+ "gitHead": "555ce7269749c1c6586a09062044da0477505bc9"
73
78
  }
@@ -4,10 +4,10 @@ const vueApplication = require('./applications/application.vue');
4
4
  const printHelp = require('./help').printHelp;
5
5
 
6
6
  const isApplicationCommand = (command) => {
7
- return [ 'new', 'add' ].indexOf(command) > -1;
7
+ return [ 'new', 'add' ].includes(command);
8
8
  };
9
9
 
10
- const run = (commands, options, devextremeConfig) => {
10
+ const run = async(commands, options, devextremeConfig) => {
11
11
  if(!commands[1]) {
12
12
  console.error('Command is incomplete. Please specify parameters.');
13
13
  printHelp(commands[0]);
@@ -15,27 +15,27 @@ const run = (commands, options, devextremeConfig) => {
15
15
  }
16
16
 
17
17
  if(commands[0] === 'new') {
18
- if(commands[1] === 'angular-app') {
19
- angularApplication.create(commands[2] || 'my-app', options);
20
- return;
21
- }
22
-
23
- if(commands[1] === 'react-app') {
24
- reactApplication.create(commands[2] || 'my-app', options);
25
- return;
26
- }
18
+ const app = commands[1];
19
+ const appName = commands[2] || 'my-app';
27
20
 
28
- if(commands[1] === 'vue-app') {
29
- vueApplication.create(commands[2] || 'my-app', options);
30
- return;
21
+ switch(app) {
22
+ case 'angular-app':
23
+ await angularApplication.create(appName, options);
24
+ return;
25
+ case 'react-app':
26
+ await reactApplication.create(appName, options);
27
+ return;
28
+ case 'vue-app':
29
+ await vueApplication.create(appName, options);
30
+ return;
31
+ default:
32
+ console.error(`The '${app}' application type is not valid`);
33
+ printHelp(commands[0]);
31
34
  }
32
-
33
- console.error(`The '${commands[1]}' application type is not valid`);
34
- printHelp(commands[0]);
35
35
  } else {
36
36
  if(commands[0] === 'add') {
37
37
  if(commands[1] === 'devextreme-angular') {
38
- angularApplication.install(options);
38
+ await angularApplication.install(options);
39
39
  return;
40
40
  }
41
41
 
@@ -50,7 +50,7 @@ const run = (commands, options, devextremeConfig) => {
50
50
  }
51
51
 
52
52
  if(commands[1] === 'angular-template') {
53
- angularApplication.addTemplate(commands[2], options);
53
+ await angularApplication.addTemplate(commands[2], options);
54
54
  return;
55
55
  }
56
56
 
@@ -1,14 +1,15 @@
1
- const getLayoutInfo = require('../utility/prompts/layout').getLayoutInfo;
1
+ const getLayoutInfo = require('../utility/prompts/layout');
2
2
  const path = require('path');
3
3
  const moduleWorker = require('../utility/module');
4
4
  const runCommand = require('../utility/run-command');
5
5
  const semver = require('semver').SemVer;
6
6
  const fs = require('fs');
7
- const exec = require('child_process').exec;
8
- const minNgCliVersion = new semver('8.0.0');
7
+ const dasherize = require('../utility/string').dasherize;
8
+ const ngVersion = require('../utility/ng-version');
9
9
  const latestVersions = require('../utility/latest-versions');
10
10
  const schematicsVersion = latestVersions['devextreme-schematics'] || 'latest';
11
- let globalNgCliVersion = '';
11
+
12
+ const minNgCliVersion = new semver('12.0.0');
12
13
 
13
14
  async function runSchematicCommand(schematicCommand, options, evaluatingOptions) {
14
15
  const collectionName = 'devextreme-schematics';
@@ -20,22 +21,26 @@ async function runSchematicCommand(schematicCommand, options, evaluatingOptions)
20
21
  }
21
22
 
22
23
  if(!localPackageExists(collectionName)) {
23
- await runNgCommand(['add', collectionPath, '--skipConfirmation=true'], evaluatingOptions);
24
+ await runNgCommand(['add', collectionPath, '--skip-confirmation=true'], evaluatingOptions);
24
25
  }
25
26
 
26
27
  const commandArguments = ['g', `${collectionName}:${schematicCommand}`];
27
28
  for(let option in options) {
28
- commandArguments.push(`--${option}=${options[option]}`);
29
+ commandArguments.push(`--${dasherize(option)}=${options[option]}`);
29
30
  }
30
31
 
31
32
  runNgCommand(commandArguments, evaluatingOptions);
32
33
  }
33
34
 
34
35
  async function runNgCommand(commandArguments, evaluatingOptions) {
35
- const ngCommandArguments = await hasSutableNgCli() ? [] : ['-p', '@angular/cli'];
36
-
37
- ngCommandArguments.push('ng', ...commandArguments);
38
- return runCommand('npx', ngCommandArguments, evaluatingOptions);
36
+ const hasNg = await hasSutableNgCli();
37
+ const npmCommandName = hasNg ? 'ng' : 'npx';
38
+ const ngCommandArguments = hasNg
39
+ ? []
40
+ : ['-p', '@angular/cli', 'ng'];
41
+
42
+ ngCommandArguments.push(...commandArguments);
43
+ return runCommand(npmCommandName, ngCommandArguments, evaluatingOptions);
39
44
  }
40
45
 
41
46
  function localPackageExists(packageName) {
@@ -48,29 +53,26 @@ function localPackageExists(packageName) {
48
53
  return fs.existsSync(packageJsonPath);
49
54
  }
50
55
 
51
- function hasSutableNgCli() {
52
- return new Promise((resolve, reject) => {
53
- exec('ng v', (err, stdout, stderr) => {
54
- const parsingResult = !stderr && parseNgCliVersion(stdout);
55
- if(parsingResult && parsingResult.compare(minNgCliVersion) < 0) {
56
- globalNgCliVersion = parsingResult.version;
57
- resolve(true);
58
- } else {
59
- resolve(false);
60
- }
61
- });
62
- });
63
- }
56
+ const hasSutableNgCli = async() => {
57
+ const localVersion = ngVersion.getLocalNgVersion();
58
+ if(!localVersion) {
59
+ return false;
60
+ }
64
61
 
65
- function parseNgCliVersion(stdout) {
66
- return new semver(/angular.cli:\s*(\S+)/ig.exec(stdout.toString())[1]);
67
- }
62
+ const isSupportVersion = localVersion.compare(minNgCliVersion) >= 0;
63
+ return isSupportVersion;
64
+ };
68
65
 
69
- const install = (options) => {
70
- runSchematicCommand('install', { ...options, globalNgCliVersion });
66
+ const install = async(options) => {
67
+ runSchematicCommand('install', {
68
+ ...options,
69
+ globalNgCliVersion: ngVersion.getNgCliVersion().version
70
+ });
71
71
  };
72
72
 
73
- const create = (appName, options) => {
73
+ const create = async(appName, options) => {
74
+ const layout = await getLayoutInfo(options.layout);
75
+
74
76
  const commandArguments = [
75
77
  'new',
76
78
  appName,
@@ -80,26 +82,26 @@ const create = (appName, options) => {
80
82
  '--skip-install=true',
81
83
  ];
82
84
 
83
- getLayoutInfo(options.layout).then(layoutInfo => {
84
- runNgCommand(commandArguments).then(() => {
85
- const appPath = path.join(process.cwd(), appName);
86
-
87
- options.resolveConflicts = 'override';
88
- options.updateBudgets = true;
89
- options.layout = layoutInfo.layout;
90
- addTemplate(appName, options, {
91
- cwd: appPath
92
- });
93
-
94
- changeMainTs(appPath);
95
- }).catch((e) => {
96
- console.log(e);
97
- });
85
+ await runNgCommand(commandArguments);
86
+
87
+ const appPath = path.join(process.cwd(), appName);
88
+
89
+ options.resolveConflicts = 'override';
90
+ options.updateBudgets = true;
91
+ options.layout = layout;
92
+ addTemplate(appName, options, {
93
+ cwd: appPath
98
94
  });
95
+
96
+ changeMainTs(appPath);
99
97
  };
100
98
 
101
- const addTemplate = (appName, options, evaluatingOptions) => {
102
- const schematicOptions = { ...(appName && { project: appName }), ...options };
99
+ const addTemplate = async(appName, options, evaluatingOptions) => {
100
+ const schematicOptions = {
101
+ ...(appName && { project: appName }),
102
+ ...options,
103
+ globalNgCliVersion: ngVersion.getNgCliVersion().version
104
+ };
103
105
  runSchematicCommand('add-app-template', schematicOptions, evaluatingOptions);
104
106
  };
105
107
 
@@ -1,7 +1,8 @@
1
1
  const runCommand = require('../utility/run-command');
2
2
  const path = require('path');
3
3
  const fs = require('fs');
4
- const getLayoutInfo = require('../utility/prompts/layout').getLayoutInfo;
4
+ const getLayoutInfo = require('../utility/prompts/layout');
5
+ const getTemplateTypeInfo = require('../utility/prompts/typescript');
5
6
  const templateCreator = require('../utility/template-creator');
6
7
  const packageManager = require('../utility/package-manager');
7
8
  const packageJsonUtils = require('../utility/package-json-utils');
@@ -9,21 +10,28 @@ const modifyJson = require('../utility/modify-json-file');
9
10
  const insertItemToArray = require('../utility/file-content').insertItemToArray;
10
11
  const moduleUtils = require('../utility/module');
11
12
  const stringUtils = require('../utility/string');
13
+ const typescriptUtils = require('../utility/typescript-extension');
12
14
  const removeFile = require('../utility/file-operations').remove;
13
- const pathToPagesIndex = path.join(process.cwd(), 'src', 'pages', 'index.js');
14
15
  const latestVersions = require('../utility/latest-versions');
15
16
  const defaultStyles = [
16
17
  'devextreme/dist/css/dx.light.css',
17
18
  'devextreme/dist/css/dx.common.css'
18
19
  ];
19
20
 
20
- const preparePackageJsonForTemplate = (appPath, appName) => {
21
+ const getExtension = (appPath) => {
22
+ return fs.existsSync(path.join(appPath, 'src', 'App.tsx')) ? '.tsx' : '.js';
23
+ };
24
+
25
+ const pathToPagesIndex = () => {
26
+ const extension = getExtension(process.cwd());
27
+ return path.join(process.cwd(), 'src', 'pages', `index${extension}`);
28
+ };
29
+
30
+ const preparePackageJsonForTemplate = (appPath, appName, isTypeScript) => {
21
31
  const dependencies = [
22
32
  { name: 'sass', version: '^1.34.1' },
23
33
  { name: 'devextreme-cli', version: latestVersions['devextreme-cli'], dev: true },
24
- { name: 'react', version: '^17.0.0' },
25
- { name: 'react-dom', version: '^17.0.0' },
26
- { name: 'react-router-dom', version: '^5.0.0' },
34
+ { name: 'react-router-dom', version: '^6.3.0' },
27
35
  ];
28
36
  const scripts = [
29
37
  { name: 'build-themes', value: 'devextreme build' },
@@ -43,48 +51,66 @@ const updateJsonPropName = (path, name) => {
43
51
  });
44
52
  };
45
53
 
46
- const create = (appName, options) => {
47
- const commandArguments = ['-p=create-react-app', 'create-react-app', appName];
54
+ const create = async(appName, options) => {
55
+ const templateType = await getTemplateTypeInfo(options.template);
56
+ const layoutType = await getLayoutInfo(options.layout);
48
57
 
49
- getLayoutInfo(options.layout).then((layoutInfo) => {
50
- runCommand('npx', commandArguments).then(() => {
51
- const appPath = path.join(process.cwd(), appName);
52
- const humanizedName = stringUtils.humanize(appName);
53
- const templateOptions = Object.assign({}, options, {
54
- project: humanizedName,
55
- layout: stringUtils.classify(layoutInfo.layout)
56
- });
57
- modifyIndexHtml(appPath, humanizedName);
58
- addTemplate(appPath, appName, templateOptions);
59
- });
58
+ const templateOptions = Object.assign({}, options, {
59
+ project: stringUtils.humanize(appName),
60
+ layout: stringUtils.classify(layoutType),
61
+ isTypeScript: typescriptUtils.isTypeScript(templateType)
60
62
  });
63
+
64
+ const commandArguments = ['-p=create-react-app', 'create-react-app', appName];
65
+ if(templateOptions.isTypeScript) {
66
+ commandArguments.push('--template typescript');
67
+ }
68
+
69
+ await runCommand('npx', commandArguments);
70
+
71
+ const appPath = path.join(process.cwd(), appName);
72
+
73
+ modifyIndexHtml(appPath, templateOptions.project);
74
+ addTemplate(appPath, appName, templateOptions);
61
75
  };
62
76
 
63
77
  const modifyIndexHtml = (appPath, appName) => {
64
78
  const indexHtmlPath = path.join(appPath, 'public', 'index.html');
65
- let htmlContent = fs.readFileSync(indexHtmlPath).toString();
66
79
 
80
+ let htmlContent = fs.readFileSync(indexHtmlPath).toString();
67
81
  htmlContent = htmlContent.replace(/<title>(\w+\s*)+<\/title>/, `<title>${appName}<\/title>`);
68
82
  htmlContent = htmlContent.replace('<body>', '<body class="dx-viewport">');
83
+
69
84
  fs.writeFileSync(indexHtmlPath, htmlContent);
70
85
  };
71
86
 
87
+ const getCorrectPath = (extension, pathToApp, isTypeScript) => {
88
+ return extension === '.ts' || extension === '.tsx' ? typescriptUtils.setFileExtension(pathToApp, isTypeScript) : pathToApp;
89
+ };
90
+
72
91
  const addTemplate = (appPath, appName, templateOptions) => {
73
- const templateSourcePath = path.join(__dirname, '..', 'templates', 'react', 'application');
92
+ const applicationTemplatePath = path.join(
93
+ templateCreator.getTempaltePath('react'),
94
+ 'application'
95
+ );
96
+
74
97
  const manifestPath = path.join(appPath, 'public', 'manifest.json');
75
- const indexPath = path.join(appPath, 'src', 'index.js');
98
+ const indexPath = path.join(appPath, 'src', templateOptions.isTypeScript ? 'index.tsx' : 'index.js');
99
+
76
100
  const styles = [
77
101
  './themes/generated/theme.additional.css',
78
102
  './themes/generated/theme.base.css',
79
103
  'devextreme/dist/css/dx.common.css'
80
104
  ];
81
105
 
82
- templateCreator.moveTemplateFilesToProject(templateSourcePath, appPath, templateOptions);
106
+ templateCreator.moveTemplateFilesToProject(applicationTemplatePath, appPath, templateOptions, getCorrectPath);
83
107
  removeFile(path.join(appPath, 'src', 'App.css'));
108
+ !templateOptions.isTypeScript && removeFile(path.join(appPath, 'src', 'types.js'));
84
109
  if(!templateOptions.empty) {
85
- addSamplePages(appPath);
110
+ addSamplePages(appPath, templateOptions);
86
111
  }
87
- preparePackageJsonForTemplate(appPath, appName);
112
+
113
+ preparePackageJsonForTemplate(appPath, appName, templateOptions.isTypeScript);
88
114
  updateJsonPropName(manifestPath, appName);
89
115
  addPolyfills(packageJsonUtils.getPackageJsonPath(), indexPath);
90
116
  install({}, appPath, styles);
@@ -92,7 +118,8 @@ const addTemplate = (appPath, appName, templateOptions) => {
92
118
 
93
119
  const install = (options, appPath, styles) => {
94
120
  appPath = appPath ? appPath : process.cwd();
95
- const pathToMainComponent = path.join(appPath, 'src', 'App.js');
121
+
122
+ const pathToMainComponent = path.join(appPath, 'src', `App${getExtension(appPath)}`);
96
123
  addStylesToApp(pathToMainComponent, styles || defaultStyles);
97
124
  packageJsonUtils.addDevextreme(appPath, options.dxversion, 'react');
98
125
 
@@ -121,7 +148,7 @@ const getComponentPageName = (viewName) => {
121
148
  const getNavigationData = (viewName, componentName, icon) => {
122
149
  const pagePath = stringUtils.dasherize(viewName);
123
150
  return {
124
- route: `\n {\n path: \'/${pagePath}\',\n component: ${componentName}\n }`,
151
+ route: `\n {\n path: \'/${pagePath}\',\n element: ${componentName}\n }`,
125
152
  navigation: `\n {\n text: \'${stringUtils.humanize(viewName)}\',\n path: \'/${pagePath}\',\n icon: \'${icon}\'\n }`
126
153
  };
127
154
  };
@@ -132,7 +159,7 @@ const createPathToPage = (pageName) => {
132
159
 
133
160
  if(!fs.existsSync(pagesPath)) {
134
161
  fs.mkdirSync(pagesPath);
135
- createPagesIndex();
162
+ fs.writeFileSync(pathToPagesIndex(), '');
136
163
  }
137
164
 
138
165
  if(!fs.existsSync(newPagePath)) {
@@ -142,27 +169,37 @@ const createPathToPage = (pageName) => {
142
169
  return newPagePath;
143
170
  };
144
171
 
145
- const createPagesIndex = () => {
146
- fs.writeFileSync(pathToPagesIndex, '');
147
- };
172
+ const addSamplePages = (appPath, templateOptions) => {
173
+ const samplePageTemplatePath = path.join(
174
+ templateCreator.getTempaltePath('react'),
175
+ 'sample-pages'
176
+ );
148
177
 
149
- const addSamplePages = (appPath) => {
150
- const templateSourcePath = path.join(__dirname, '..', 'templates', 'react', 'sample-pages');
151
178
  const pagesPath = path.join(appPath, 'src', 'pages');
152
179
  fs.mkdirSync(pagesPath);
153
- templateCreator.moveTemplateFilesToProject(templateSourcePath, pagesPath, {});
180
+ templateCreator.moveTemplateFilesToProject(samplePageTemplatePath, pagesPath, {
181
+ isTypeScript: templateOptions.isTypeScript
182
+ }, getCorrectPath);
154
183
  };
155
184
 
156
185
  const addView = (pageName, options) => {
186
+ const pageTemplatePath = path.join(
187
+ templateCreator.getTempaltePath('react'),
188
+ 'page'
189
+ );
190
+ const extension = getExtension(process.cwd());
191
+
157
192
  const componentName = getComponentPageName(pageName);
158
193
  const pathToPage = createPathToPage(pageName);
159
- const pageTemplatePath = path.join(__dirname, '..', 'templates', 'react', 'page');
160
- const routingModulePath = path.join(process.cwd(), 'src', 'app-routes.js');
161
- const navigationModulePath = path.join(process.cwd(), 'src', 'app-navigation.js');
194
+ const routingModulePath = path.join(process.cwd(), 'src', `app-routes${extension}`);
195
+ const navigationModulePath = path.join(process.cwd(), 'src', `app-navigation${extension}`);
162
196
  const navigationData = getNavigationData(pageName, componentName, options && options.icon || 'folder');
163
197
 
164
- templateCreator.addPageToApp(pageName, pathToPage, pageTemplatePath);
165
- moduleUtils.insertExport(pathToPagesIndex, componentName, `./${pageName}/${pageName}`);
198
+ const getCorrectExtension = (fileExtension) => {
199
+ return fileExtension === '.tsx' ? extension : fileExtension;
200
+ };
201
+ templateCreator.addPageToApp(pageName, pathToPage, pageTemplatePath, getCorrectExtension);
202
+ moduleUtils.insertExport(pathToPagesIndex(), componentName, `./${pageName}/${pageName}`);
166
203
  moduleUtils.insertImport(routingModulePath, './pages', componentName);
167
204
  insertItemToArray(routingModulePath, navigationData.route);
168
205
  insertItemToArray(navigationModulePath, navigationData.navigation);
@@ -1,7 +1,8 @@
1
1
  const path = require('path');
2
2
  const fs = require('fs');
3
- const getLayoutInfo = require('../utility/prompts/layout').getLayoutInfo;
4
- const getVersionInfo = require('../utility/prompts/vue-version').getVersionInfo;
3
+ const getLayoutInfo = require('../utility/prompts/layout');
4
+ const getVersionInfo = require('../utility/prompts/vue-version');
5
+ const getTemplateTypeInfo = require('../utility/prompts/typescript');
5
6
  const templateCreator = require('../utility/template-creator');
6
7
  const packageManager = require('../utility/package-manager');
7
8
  const packageJsonUtils = require('../utility/package-json-utils');
@@ -9,6 +10,7 @@ const runCommand = require('../utility/run-command');
9
10
  const insertItemToArray = require('../utility/file-content').insertItemToArray;
10
11
  const moduleUtils = require('../utility/module');
11
12
  const stringUtils = require('../utility/string');
13
+ const typescriptUtils = require('../utility/typescript-extension');
12
14
  const latestVersions = require('../utility/latest-versions');
13
15
  const defaultStyles = [
14
16
  'devextreme/dist/css/dx.light.css',
@@ -53,32 +55,42 @@ const preparePackageJsonForTemplate = (appPath, appName, version) => {
53
55
  packageJsonUtils.updateName(appPath, appName);
54
56
  };
55
57
 
56
- async function createVueApp(name, version) {
58
+ async function createVueApp(name, templateOptions) {
59
+ const { version, isTypeScript } = templateOptions;
57
60
  const argList = ['-p', '@vue/cli', 'vue', 'create', name];
58
61
 
59
- if(version === 'v2') {
60
- argList.push('-p "Default (Vue 2)"');
62
+ if(isTypeScript) {
63
+ const presetPath = path.join(__dirname, '..', 'templates-ts', `vue-${version}`);
64
+
65
+ argList.push(`-p "${presetPath}"`);
61
66
  } else {
62
- argList.push('-p "Default (Vue 3)"');
67
+ if(version === 'v2') {
68
+ argList.push('-p "Default (Vue 2)"');
69
+ } else {
70
+ argList.push('-p "Default (Vue 3)"');
71
+ }
63
72
  }
64
73
 
65
- return runCommand('npx', argList, { windowsVerbatimArguments: false });
74
+ return runCommand('npx', argList);
66
75
  }
67
76
 
68
77
  const create = async(appName, options) => {
69
- const versionInfo = await getVersionInfo(options.version);
70
- const layoutInfo = await getLayoutInfo(options.layout);
78
+ const version = await getVersionInfo(options.version);
79
+ const templateType = await getTemplateTypeInfo(options.template);
80
+ const layout = await getLayoutInfo(options.layout);
81
+
82
+ const templateOptions = {
83
+ project: stringUtils.humanize(appName),
84
+ layout: layout,
85
+ version: version,
86
+ isTypeScript: typescriptUtils.isTypeScript(templateType)
87
+ };
71
88
 
72
- await createVueApp(appName, versionInfo.version);
89
+ await createVueApp(appName, templateOptions);
73
90
 
74
91
  const appPath = path.join(process.cwd(), appName);
75
- const humanizedName = stringUtils.humanize(appName);
76
- const templateOptions = Object.assign({}, options, {
77
- project: humanizedName,
78
- layout: layoutInfo.layout
79
- });
80
- modifyIndexHtml(appPath, humanizedName);
81
- addTemplate(appPath, appName, templateOptions, versionInfo.version);
92
+ modifyIndexHtml(appPath, templateOptions.project);
93
+ addTemplate(appPath, appName, templateOptions);
82
94
  };
83
95
 
84
96
  const modifyIndexHtml = (appPath, appName) => {
@@ -90,27 +102,30 @@ const modifyIndexHtml = (appPath, appName) => {
90
102
  fs.writeFileSync(indexHtmlPath, htmlContent);
91
103
  };
92
104
 
93
- const getMainModulePath = (appPath) => {
94
- const jsModule = path.join(appPath, 'src', 'main.js');
95
-
96
- return fs.existsSync(jsModule) ? jsModule : path.join(appPath, 'src', 'main.ts');
105
+ const getCorrectPath = (extension, pathToApp) => {
106
+ return pathToApp;
97
107
  };
98
108
 
99
- const addTemplate = (appPath, appName, templateOptions, version) => {
109
+ const addTemplate = (appPath, appName, templateOptions) => {
110
+ const { version, isTypeScript } = templateOptions;
111
+
100
112
  if(!version) {
101
113
  version = getVueVersion();
102
114
  }
103
115
 
104
- const templateSourcePath = path.join(__dirname, '..', 'templates', `vue-${version}`, 'application');
116
+ const applicationTemplatePath = path.join(
117
+ templateCreator.getTempaltePath(`vue-${version}`, isTypeScript),
118
+ 'application'
119
+ );
105
120
  const styles = [
106
121
  './themes/generated/theme.additional.css',
107
122
  './themes/generated/theme.base.css',
108
123
  'devextreme/dist/css/dx.common.css'
109
124
  ];
110
125
 
111
- templateCreator.moveTemplateFilesToProject(templateSourcePath, appPath, templateOptions);
126
+ templateCreator.moveTemplateFilesToProject(applicationTemplatePath, appPath, templateOptions, getCorrectPath);
112
127
  if(!templateOptions.empty) {
113
- addSamplePages(appPath, version);
128
+ addSamplePages(appPath, templateOptions);
114
129
  }
115
130
  preparePackageJsonForTemplate(appPath, appName, version);
116
131
  install({}, appPath, styles);
@@ -125,21 +140,31 @@ const install = (options, appPath, styles) => {
125
140
  };
126
141
 
127
142
  const addStylesToApp = (appPath, styles) => {
128
- const mainModulePath = getMainModulePath(appPath);
143
+ const isTypeScript = typescriptUtils.isTypeScript(typescriptUtils.getTemplateType('vue'));
144
+
145
+ const mainModulePath = typescriptUtils.setFileExtension(
146
+ path.join(appPath, 'src', 'main.js'),
147
+ isTypeScript
148
+ );
129
149
 
130
150
  styles.forEach(style => {
131
151
  moduleUtils.insertImport(mainModulePath, style);
132
152
  });
133
153
  };
134
154
 
135
- const addSamplePages = (appPath, version) => {
155
+ const addSamplePages = (appPath, templateOptions) => {
156
+ const { version, isTypeScript } = templateOptions;
157
+
136
158
  if(!version) {
137
159
  version = getVueVersion();
138
160
  }
139
161
 
140
- const templateSourcePath = path.join(__dirname, '..', 'templates', `vue-${version}`, 'sample-pages');
162
+ const samplePageTemplatePath = path.join(
163
+ templateCreator.getTempaltePath(`vue-${version}`, isTypeScript),
164
+ 'sample-pages'
165
+ );
141
166
  const pagesPath = createPathToPage(appPath);
142
- templateCreator.moveTemplateFilesToProject(templateSourcePath, pagesPath, {});
167
+ templateCreator.moveTemplateFilesToProject(samplePageTemplatePath, pagesPath, {}, getCorrectPath);
143
168
  };
144
169
 
145
170
  const getComponentPageName = (viewName) => {
@@ -191,14 +216,26 @@ const createPathToPage = (appPath) => {
191
216
 
192
217
  const addView = (pageName, options) => {
193
218
  const version = getVueVersion();
219
+ const isTypeScript = typescriptUtils.isTypeScript(typescriptUtils.getTemplateType('vue'));
220
+
221
+ const pageTemplatePath = path.join(
222
+ templateCreator.getTempaltePath(`vue-${version}`, isTypeScript),
223
+ 'page'
224
+ );
225
+
194
226
  const componentName = getComponentPageName(pageName);
195
227
  const pathToPage = createPathToPage(process.cwd());
196
- const pageTemplatePath = path.join(__dirname, '..', 'templates', `vue-${version}`, 'page');
197
- const routingModulePath = path.join(process.cwd(), 'src', 'router.js');
198
- const navigationModulePath = path.join(process.cwd(), 'src', 'app-navigation.js');
228
+ const routingModulePath = typescriptUtils.setFileExtension(
229
+ path.join(process.cwd(), 'src', 'router.js'),
230
+ isTypeScript
231
+ );
232
+ const navigationModulePath = typescriptUtils.setFileExtension(
233
+ path.join(process.cwd(), 'src', 'app-navigation.js'),
234
+ isTypeScript
235
+ );
199
236
  const navigationData = getNavigationData(pageName, componentName, options && options.icon || 'folder', version);
200
-
201
- templateCreator.addPageToApp(pageName, pathToPage, pageTemplatePath);
237
+ const getCorrectExtension = (fileExtension) => fileExtension;
238
+ templateCreator.addPageToApp(pageName, pathToPage, pageTemplatePath, getCorrectExtension);
202
239
  moduleUtils.insertImport(routingModulePath, `./views/${pageName}`, componentName, true);
203
240
  insertItemToArray(routingModulePath, navigationData.route);
204
241
  insertItemToArray(navigationModulePath, navigationData.navigation);