devextreme-cli 1.3.2 → 1.3.3

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 (58) hide show
  1. package/index.js +4 -2
  2. package/package.json +8 -3
  3. package/src/application.js +17 -17
  4. package/src/applications/application.angular.js +38 -21
  5. package/src/applications/application.react.js +81 -37
  6. package/src/applications/application.vue.js +70 -33
  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} +6 -6
  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} +7 -7
  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} +6 -6
  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} +7 -7
  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} +8 -10
  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/layouts/{index.js → index.tsx} +0 -0
  34. package/src/templates/react/application/src/layouts/side-nav-inner-toolbar/{side-nav-inner-toolbar.js → side-nav-inner-toolbar.tsx} +12 -9
  35. package/src/templates/react/application/src/layouts/side-nav-outer-toolbar/{side-nav-outer-toolbar.js → side-nav-outer-toolbar.tsx} +11 -10
  36. package/src/templates/react/application/src/layouts/single-card/{single-card.js → single-card.tsx} +2 -1
  37. package/src/templates/react/application/src/{polyfills.js → polyfills.tsx} +0 -0
  38. package/src/templates/react/application/src/types.tsx +53 -0
  39. package/src/templates/react/application/src/utils/{default-user.js → default-user.tsx} +0 -0
  40. package/src/templates/react/application/src/utils/{media-query.js → media-query.tsx} +4 -3
  41. package/src/templates/react/application/src/utils/{patches.js → patches.tsx} +1 -1
  42. package/src/templates/react/page/{page.js → page.tsx} +0 -0
  43. package/src/templates/react/sample-pages/home/{home.js → home.tsx} +0 -0
  44. package/src/templates/react/sample-pages/{index.js → index.tsx} +0 -0
  45. package/src/templates/react/sample-pages/profile/{profile.js → profile.tsx} +0 -0
  46. package/src/templates/react/sample-pages/tasks/{tasks.js → tasks.tsx} +1 -1
  47. package/src/templates/vue-v2/application/devextreme.json +2 -1
  48. package/src/templates/vue-v3/application/devextreme.json +2 -1
  49. package/src/utility/prompts/layout.js +9 -21
  50. package/src/utility/prompts/prompts.js +24 -8
  51. package/src/utility/prompts/typescript.js +18 -0
  52. package/src/utility/prompts/vue-version.js +9 -21
  53. package/src/utility/template-creator.js +11 -6
  54. package/src/utility/typescript-extension.js +24 -0
  55. package/src/templates/react/application/src/UnauthenticatedContent.js +0 -35
  56. package/src/templates/react/application/src/app-routes.js +0 -24
  57. package/src/templates/react/application/src/components/index.js +0 -7
  58. 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.2",
3
+ "version": "1.3.3",
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": "bab9c1bd00964b2f33258bf0b5a5a68107b68fb4"
77
+ "gitHead": "023ac50deaac92bd44a283079f55491f4db30049"
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,23 +15,23 @@ 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') {
@@ -1,4 +1,4 @@
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');
@@ -32,10 +32,14 @@ async function runSchematicCommand(schematicCommand, options, evaluatingOptions)
32
32
  }
33
33
 
34
34
  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);
35
+ const hasNg = await hasSutableNgCli();
36
+ const npmCommandName = hasNg ? 'ng' : 'npx';
37
+ const ngCommandArguments = hasNg
38
+ ? []
39
+ : ['-p', '@angular/cli@13.3.7', 'ng'];
40
+
41
+ ngCommandArguments.push(...commandArguments);
42
+ return runCommand(npmCommandName, ngCommandArguments, evaluatingOptions);
39
43
  }
40
44
 
41
45
  function localPackageExists(packageName) {
@@ -50,9 +54,24 @@ function localPackageExists(packageName) {
50
54
 
51
55
  function hasSutableNgCli() {
52
56
  return new Promise((resolve, reject) => {
57
+ if(globalNgCliVersion !== '') {
58
+ resolve(true);
59
+ }
60
+
53
61
  exec('ng v', (err, stdout, stderr) => {
54
- const parsingResult = !stderr && parseNgCliVersion(stdout);
55
- if(parsingResult && parsingResult.compare(minNgCliVersion) < 0) {
62
+ if(!!err) {
63
+ resolve(false);
64
+ return;
65
+ }
66
+
67
+ const parsingResult = parseNgCliVersion(stdout);
68
+ if(!parsingResult) {
69
+ resolve(false);
70
+ }
71
+
72
+ const isSupportVersion = parsingResult.compare(minNgCliVersion) >= 0
73
+ && parsingResult.compare(new semver('14.0.0')) < 0;
74
+ if(isSupportVersion) {
56
75
  globalNgCliVersion = parsingResult.version;
57
76
  resolve(true);
58
77
  } else {
@@ -70,7 +89,9 @@ const install = (options) => {
70
89
  runSchematicCommand('install', { ...options, globalNgCliVersion });
71
90
  };
72
91
 
73
- const create = (appName, options) => {
92
+ const create = async(appName, options) => {
93
+ const layout = await getLayoutInfo(options.layout);
94
+
74
95
  const commandArguments = [
75
96
  'new',
76
97
  appName,
@@ -80,22 +101,18 @@ const create = (appName, options) => {
80
101
  '--skip-install=true',
81
102
  ];
82
103
 
83
- getLayoutInfo(options.layout).then(layoutInfo => {
84
- runNgCommand(commandArguments).then(() => {
85
- const appPath = path.join(process.cwd(), appName);
104
+ await runNgCommand(commandArguments);
86
105
 
87
- options.resolveConflicts = 'override';
88
- options.updateBudgets = true;
89
- options.layout = layoutInfo.layout;
90
- addTemplate(appName, options, {
91
- cwd: appPath
92
- });
106
+ const appPath = path.join(process.cwd(), appName);
93
107
 
94
- changeMainTs(appPath);
95
- }).catch((e) => {
96
- console.log(e);
97
- });
108
+ options.resolveConflicts = 'override';
109
+ options.updateBudgets = true;
110
+ options.layout = layout;
111
+ addTemplate(appName, options, {
112
+ cwd: appPath
98
113
  });
114
+
115
+ changeMainTs(appPath);
99
116
  };
100
117
 
101
118
  const addTemplate = (appName, options, evaluatingOptions) => {
@@ -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,25 +10,39 @@ 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-router-dom', version: '^5.0.0' },
34
+ { name: 'react-router-dom', version: '^6.3.0' },
25
35
  ];
26
36
  const scripts = [
27
37
  { name: 'build-themes', value: 'devextreme build' },
28
38
  { name: 'postinstall', value: 'npm run build-themes' }
29
39
  ];
30
40
 
41
+ if(isTypeScript) {
42
+ dependencies.push({ name: '@types/react-router-dom', version: '^5.1.5' });
43
+ dependencies.push({ name: '@types/react', version: '^17.0.39' });
44
+ }
45
+
31
46
  packageJsonUtils.addDependencies(appPath, dependencies);
32
47
  packageJsonUtils.updateScripts(appPath, scripts);
33
48
  packageJsonUtils.updateName(appPath, appName);
@@ -41,48 +56,66 @@ const updateJsonPropName = (path, name) => {
41
56
  });
42
57
  };
43
58
 
44
- const create = (appName, options) => {
45
- const commandArguments = ['-p=create-react-app', 'create-react-app', appName];
59
+ const create = async(appName, options) => {
60
+ const templateType = await getTemplateTypeInfo(options.template);
61
+ const layoutType = await getLayoutInfo(options.layout);
46
62
 
47
- getLayoutInfo(options.layout).then((layoutInfo) => {
48
- runCommand('npx', commandArguments).then(() => {
49
- const appPath = path.join(process.cwd(), appName);
50
- const humanizedName = stringUtils.humanize(appName);
51
- const templateOptions = Object.assign({}, options, {
52
- project: humanizedName,
53
- layout: stringUtils.classify(layoutInfo.layout)
54
- });
55
- modifyIndexHtml(appPath, humanizedName);
56
- addTemplate(appPath, appName, templateOptions);
57
- });
63
+ const templateOptions = Object.assign({}, options, {
64
+ project: stringUtils.humanize(appName),
65
+ layout: stringUtils.classify(layoutType),
66
+ isTypeScript: typescriptUtils.isTypeScript(templateType)
58
67
  });
68
+
69
+ const commandArguments = ['-p=create-react-app', 'create-react-app', appName];
70
+ if(templateOptions.isTypeScript) {
71
+ commandArguments.push('--template typescript');
72
+ }
73
+
74
+ await runCommand('npx', commandArguments);
75
+
76
+ const appPath = path.join(process.cwd(), appName);
77
+
78
+ modifyIndexHtml(appPath, templateOptions.project);
79
+ addTemplate(appPath, appName, templateOptions);
59
80
  };
60
81
 
61
82
  const modifyIndexHtml = (appPath, appName) => {
62
83
  const indexHtmlPath = path.join(appPath, 'public', 'index.html');
63
- let htmlContent = fs.readFileSync(indexHtmlPath).toString();
64
84
 
85
+ let htmlContent = fs.readFileSync(indexHtmlPath).toString();
65
86
  htmlContent = htmlContent.replace(/<title>(\w+\s*)+<\/title>/, `<title>${appName}<\/title>`);
66
87
  htmlContent = htmlContent.replace('<body>', '<body class="dx-viewport">');
88
+
67
89
  fs.writeFileSync(indexHtmlPath, htmlContent);
68
90
  };
69
91
 
92
+ const getCorrectPath = (extension, pathToApp, isTypeScript) => {
93
+ return extension === '.ts' || extension === '.tsx' ? typescriptUtils.setFileExtension(pathToApp, isTypeScript) : pathToApp;
94
+ };
95
+
70
96
  const addTemplate = (appPath, appName, templateOptions) => {
71
- const templateSourcePath = path.join(__dirname, '..', 'templates', 'react', 'application');
97
+ const applicationTemplatePath = path.join(
98
+ templateCreator.getTempaltePath('react'),
99
+ 'application'
100
+ );
101
+
72
102
  const manifestPath = path.join(appPath, 'public', 'manifest.json');
73
- const indexPath = path.join(appPath, 'src', 'index.js');
103
+ const indexPath = path.join(appPath, 'src', templateOptions.isTypeScript ? 'index.tsx' : 'index.js');
104
+
74
105
  const styles = [
75
106
  './themes/generated/theme.additional.css',
76
107
  './themes/generated/theme.base.css',
77
108
  'devextreme/dist/css/dx.common.css'
78
109
  ];
79
110
 
80
- templateCreator.moveTemplateFilesToProject(templateSourcePath, appPath, templateOptions);
111
+ templateCreator.moveTemplateFilesToProject(applicationTemplatePath, appPath, templateOptions, getCorrectPath);
81
112
  removeFile(path.join(appPath, 'src', 'App.css'));
113
+ !templateOptions.isTypeScript && removeFile(path.join(appPath, 'src', 'types.js'));
82
114
  if(!templateOptions.empty) {
83
- addSamplePages(appPath);
115
+ addSamplePages(appPath, templateOptions);
84
116
  }
85
- preparePackageJsonForTemplate(appPath, appName);
117
+
118
+ preparePackageJsonForTemplate(appPath, appName, templateOptions.isTypeScript);
86
119
  updateJsonPropName(manifestPath, appName);
87
120
  addPolyfills(packageJsonUtils.getPackageJsonPath(), indexPath);
88
121
  install({}, appPath, styles);
@@ -90,7 +123,8 @@ const addTemplate = (appPath, appName, templateOptions) => {
90
123
 
91
124
  const install = (options, appPath, styles) => {
92
125
  appPath = appPath ? appPath : process.cwd();
93
- const pathToMainComponent = path.join(appPath, 'src', 'App.js');
126
+
127
+ const pathToMainComponent = path.join(appPath, 'src', `App${getExtension(appPath)}`);
94
128
  addStylesToApp(pathToMainComponent, styles || defaultStyles);
95
129
  packageJsonUtils.addDevextreme(appPath, options.dxversion, 'react');
96
130
 
@@ -119,7 +153,7 @@ const getComponentPageName = (viewName) => {
119
153
  const getNavigationData = (viewName, componentName, icon) => {
120
154
  const pagePath = stringUtils.dasherize(viewName);
121
155
  return {
122
- route: `\n {\n path: \'/${pagePath}\',\n component: ${componentName}\n }`,
156
+ route: `\n {\n path: \'/${pagePath}\',\n element: ${componentName}\n }`,
123
157
  navigation: `\n {\n text: \'${stringUtils.humanize(viewName)}\',\n path: \'/${pagePath}\',\n icon: \'${icon}\'\n }`
124
158
  };
125
159
  };
@@ -130,7 +164,7 @@ const createPathToPage = (pageName) => {
130
164
 
131
165
  if(!fs.existsSync(pagesPath)) {
132
166
  fs.mkdirSync(pagesPath);
133
- createPagesIndex();
167
+ fs.writeFileSync(pathToPagesIndex(), '');
134
168
  }
135
169
 
136
170
  if(!fs.existsSync(newPagePath)) {
@@ -140,27 +174,37 @@ const createPathToPage = (pageName) => {
140
174
  return newPagePath;
141
175
  };
142
176
 
143
- const createPagesIndex = () => {
144
- fs.writeFileSync(pathToPagesIndex, '');
145
- };
177
+ const addSamplePages = (appPath, templateOptions) => {
178
+ const samplePageTemplatePath = path.join(
179
+ templateCreator.getTempaltePath('react'),
180
+ 'sample-pages'
181
+ );
146
182
 
147
- const addSamplePages = (appPath) => {
148
- const templateSourcePath = path.join(__dirname, '..', 'templates', 'react', 'sample-pages');
149
183
  const pagesPath = path.join(appPath, 'src', 'pages');
150
184
  fs.mkdirSync(pagesPath);
151
- templateCreator.moveTemplateFilesToProject(templateSourcePath, pagesPath, {});
185
+ templateCreator.moveTemplateFilesToProject(samplePageTemplatePath, pagesPath, {
186
+ isTypeScript: templateOptions.isTypeScript
187
+ }, getCorrectPath);
152
188
  };
153
189
 
154
190
  const addView = (pageName, options) => {
191
+ const pageTemplatePath = path.join(
192
+ templateCreator.getTempaltePath('react'),
193
+ 'page'
194
+ );
195
+ const extension = getExtension(process.cwd());
196
+
155
197
  const componentName = getComponentPageName(pageName);
156
198
  const pathToPage = createPathToPage(pageName);
157
- const pageTemplatePath = path.join(__dirname, '..', 'templates', 'react', 'page');
158
- const routingModulePath = path.join(process.cwd(), 'src', 'app-routes.js');
159
- const navigationModulePath = path.join(process.cwd(), 'src', 'app-navigation.js');
199
+ const routingModulePath = path.join(process.cwd(), 'src', `app-routes${extension}`);
200
+ const navigationModulePath = path.join(process.cwd(), 'src', `app-navigation${extension}`);
160
201
  const navigationData = getNavigationData(pageName, componentName, options && options.icon || 'folder');
161
202
 
162
- templateCreator.addPageToApp(pageName, pathToPage, pageTemplatePath);
163
- moduleUtils.insertExport(pathToPagesIndex, componentName, `./${pageName}/${pageName}`);
203
+ const getCorrectExtension = (fileExtension) => {
204
+ return fileExtension === '.tsx' ? extension : fileExtension;
205
+ };
206
+ templateCreator.addPageToApp(pageName, pathToPage, pageTemplatePath, getCorrectExtension);
207
+ moduleUtils.insertExport(pathToPagesIndex(), componentName, `./${pageName}/${pageName}`);
164
208
  moduleUtils.insertImport(routingModulePath, './pages', componentName);
165
209
  insertItemToArray(routingModulePath, navigationData.route);
166
210
  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
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);
package/src/commands.json CHANGED
@@ -18,6 +18,9 @@
18
18
  }, {
19
19
  "name": "--version",
20
20
  "description": "Specifies whether to generate a Vue 2 or Vue 3 application. Available values: 2 (default) and 3"
21
+ }, {
22
+ "name": "--template",
23
+ "description": "Create template with typescsript support. Specifies for React & Vue application"
21
24
  }]
22
25
  }]
23
26
  }, {
@@ -1,5 +1,4 @@
1
- import React from 'react';
2
- import { Switch, Route<%=^empty%>, Redirect<%=/empty%> } from 'react-router-dom';
1
+ import { Routes, Route, Navigate } from 'react-router-dom';
3
2
  import appInfo from './app-info';
4
3
  import routes from './app-routes';
5
4
  import { <%=layout%> as SideNavBarLayout } from './layouts';
@@ -8,17 +7,19 @@ import { Footer } from './components';
8
7
  export default function Content() {
9
8
  return (
10
9
  <SideNavBarLayout title={appInfo.title}>
11
- <Switch>
12
- {routes.map(({ path, component }) => (
10
+ <Routes>
11
+ {routes.map(({ path, element }) => (
13
12
  <Route
14
- exact
15
13
  key={path}
16
14
  path={path}
17
- component={component}
15
+ element={element}
18
16
  />
19
- ))}<%=^empty%>
20
- <Redirect to={'/home'} /><%=/empty%>
21
- </Switch>
17
+ ))}
18
+ <Route
19
+ path='*'
20
+ element={<Navigate to='/home' />}
21
+ />
22
+ </Routes>
22
23
  <Footer>
23
24
  Copyright © 2011-{new Date().getFullYear()} {appInfo.title} Inc.
24
25
  <br />
@@ -28,3 +29,4 @@ export default function Content() {
28
29
  </SideNavBarLayout>
29
30
  );
30
31
  }
32
+