devextreme-cli 1.11.0-alpha.0 → 1.11.0-beta.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 (72) hide show
  1. package/package.json +4 -3
  2. package/src/application.js +40 -20
  3. package/src/applications/application.angular.js +11 -3
  4. package/src/applications/application.nextjs.js +231 -0
  5. package/src/applications/application.react.js +15 -5
  6. package/src/templates/nextjs/application/.env +1 -0
  7. package/src/templates/nextjs/application/devextreme.json +63 -0
  8. package/src/templates/nextjs/application/next.config.mjs +32 -0
  9. package/src/templates/nextjs/application/public/logo192.png +0 -0
  10. package/src/templates/nextjs/application/public/logo512.png +0 -0
  11. package/src/templates/nextjs/application/public/manifest.json +25 -0
  12. package/src/templates/nextjs/application/public/robots.txt +3 -0
  13. package/src/templates/nextjs/application/src/app/actions/auth.ts +76 -0
  14. package/src/templates/nextjs/application/src/app/auth/[type]/page.tsx +49 -0
  15. package/src/templates/nextjs/application/src/app/layout.tsx +17 -0
  16. package/src/templates/nextjs/application/src/app/lib/session.ts +47 -0
  17. package/src/templates/nextjs/application/src/app/pages/layout.tsx +18 -0
  18. package/src/templates/nextjs/application/src/app-info.tsx +5 -0
  19. package/src/templates/nextjs/application/src/app-navigation.tsx +21 -0
  20. package/src/templates/nextjs/application/src/components/change-password-form/ChangePasswordForm.tsx +86 -0
  21. package/src/templates/nextjs/application/src/components/create-account-form/CreateAccountForm.scss +19 -0
  22. package/src/templates/nextjs/application/src/components/create-account-form/CreateAccountForm.tsx +107 -0
  23. package/src/templates/nextjs/application/src/components/footer/Footer.scss +12 -0
  24. package/src/templates/nextjs/application/src/components/footer/Footer.tsx +5 -0
  25. package/src/templates/nextjs/application/src/components/header/Header.scss +40 -0
  26. package/src/templates/nextjs/application/src/components/header/Header.tsx +38 -0
  27. package/src/templates/nextjs/application/src/components/index.tsx +7 -0
  28. package/src/templates/nextjs/application/src/components/login-form/LoginForm.scss +12 -0
  29. package/src/templates/nextjs/application/src/components/login-form/LoginForm.tsx +101 -0
  30. package/src/templates/nextjs/application/src/components/reset-password-form/ResetPasswordForm.scss +12 -0
  31. package/src/templates/nextjs/application/src/components/reset-password-form/ResetPasswordForm.tsx +78 -0
  32. package/src/templates/nextjs/application/src/components/side-navigation-menu/SideNavigationMenu.scss +71 -0
  33. package/src/templates/nextjs/application/src/components/side-navigation-menu/SideNavigationMenu.tsx +88 -0
  34. package/src/templates/nextjs/application/src/components/theme-switcher/ThemeSwitcher.tsx +21 -0
  35. package/src/templates/nextjs/application/src/components/user-panel/UserPanel.scss +51 -0
  36. package/src/templates/nextjs/application/src/components/user-panel/UserPanel.tsx +55 -0
  37. package/src/templates/nextjs/application/src/dx-styles.scss +106 -0
  38. package/src/templates/nextjs/application/src/index.css +12 -0
  39. package/src/templates/nextjs/application/src/layouts/index.tsx +3 -0
  40. package/src/templates/nextjs/application/src/layouts/side-nav-inner-toolbar/side-nav-inner-toolbar.scss +17 -0
  41. package/src/templates/nextjs/application/src/layouts/side-nav-inner-toolbar/side-nav-inner-toolbar.tsx +133 -0
  42. package/src/templates/nextjs/application/src/layouts/side-nav-outer-toolbar/side-nav-outer-toolbar.scss +10 -0
  43. package/src/templates/nextjs/application/src/layouts/side-nav-outer-toolbar/side-nav-outer-toolbar.tsx +119 -0
  44. package/src/templates/nextjs/application/src/layouts/single-card/single-card.scss +42 -0
  45. package/src/templates/nextjs/application/src/layouts/single-card/single-card.tsx +16 -0
  46. package/src/templates/nextjs/application/src/middleware.ts +46 -0
  47. package/src/templates/nextjs/application/src/theme.tsx +66 -0
  48. package/src/templates/nextjs/application/src/themes/metadata.additional.dark.json +11 -0
  49. package/src/templates/nextjs/application/src/themes/metadata.additional.json +11 -0
  50. package/src/templates/nextjs/application/src/themes/metadata.base.dark.json +8 -0
  51. package/src/templates/nextjs/application/src/themes/metadata.base.json +7 -0
  52. package/src/templates/nextjs/application/src/types.tsx +60 -0
  53. package/src/templates/nextjs/application/src/utils/default-user.tsx +7 -0
  54. package/src/templates/nextjs/application/src/utils/media-query.tsx +56 -0
  55. package/src/templates/nextjs/application/src/variables.scss +53 -0
  56. package/src/templates/nextjs/page/page.scss +0 -0
  57. package/src/templates/nextjs/page/page.tsx +13 -0
  58. package/src/templates/nextjs/sample-pages/home/home.scss +37 -0
  59. package/src/templates/nextjs/sample-pages/home/page.tsx +101 -0
  60. package/src/templates/nextjs/sample-pages/profile/page.tsx +61 -0
  61. package/src/templates/nextjs/sample-pages/profile/profile.scss +19 -0
  62. package/src/templates/nextjs/sample-pages/tasks/page.tsx +112 -0
  63. package/src/templates/nextjs/sample-pages/tasks/tasks.scss +3 -0
  64. package/src/templates/react/application/src/components/header/Header.scss +1 -1
  65. package/src/templates/react/application/src/dx-styles.scss +3 -3
  66. package/src/templates/vue-v3/application/src/components/header-toolbar.vue +1 -1
  67. package/src/templates/vue-v3/application/src/dx-styles.scss +4 -3
  68. package/src/utility/latest-versions.js +6 -4
  69. package/src/utility/module.js +11 -3
  70. package/src/utility/prompts/react-app-type.js +17 -0
  71. package/src/utility/run-command.js +10 -2
  72. package/src/utility/template-creator.js +8 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devextreme-cli",
3
- "version": "1.11.0-alpha.0",
3
+ "version": "1.11.0-beta.0",
4
4
  "description": "DevExtreme CLI",
5
5
  "keywords": [
6
6
  "devexpress",
@@ -71,7 +71,8 @@
71
71
  "tree-kill": "^1.2.2",
72
72
  "tree-kill-promise": "^1.0.12",
73
73
  "typescript": "^4.0.2",
74
- "typescript-eslint-parser": "^22.0.0"
74
+ "typescript-eslint-parser": "^22.0.0",
75
+ "wait-on": "8.0.0"
75
76
  },
76
- "gitHead": "4c13206f0278c88053f62682fd2a6ca0a8ea5866"
77
+ "gitHead": "12a211ead8510e78eb1f33b6a34664823d73a4a7"
77
78
  }
@@ -1,12 +1,34 @@
1
1
  const angularApplication = require('./applications/application.angular');
2
2
  const reactApplication = require('./applications/application.react');
3
+ const nextjsApplication = require('./applications/application.nextjs');
3
4
  const vueApplication = require('./applications/application.vue');
5
+ const getReactAppType = require('./utility/prompts/react-app-type');
4
6
  const printHelp = require('./help').printHelp;
5
7
 
6
8
  const isApplicationCommand = (command) => {
7
9
  return [ 'new', 'add' ].includes(command);
8
10
  };
9
11
 
12
+ const handleWrongAppType = (appType, command) => {
13
+ console.error(`The '${appType}' application type is not valid`);
14
+ printHelp(command);
15
+ };
16
+
17
+ const createReact = async(appName, options, command) => {
18
+ const reactAppType = await getReactAppType(options['app-type']);
19
+
20
+ switch(reactAppType) {
21
+ case 'vite':
22
+ await reactApplication.create(appName, options);
23
+ return;
24
+ case 'nextjs':
25
+ await nextjsApplication.create(appName, options);
26
+ return;
27
+ default:
28
+ handleWrongAppType(reactAppType, command);
29
+ }
30
+ };
31
+
10
32
  const run = async(commands, options, devextremeConfig) => {
11
33
  if(!commands[1]) {
12
34
  console.error('Command is incomplete. Please specify parameters.');
@@ -23,15 +45,15 @@ const run = async(commands, options, devextremeConfig) => {
23
45
  await angularApplication.create(appName, options);
24
46
  return;
25
47
  case 'react-app':
26
- await reactApplication.create(appName, options);
48
+ await createReact(appName, options, commands[0]);
27
49
  return;
28
50
  case 'vue-app':
29
51
  await vueApplication.create(appName, options);
30
52
  return;
31
53
  default:
32
- console.error(`The '${app}' application type is not valid`);
33
- printHelp(commands[0]);
54
+ handleWrongAppType(app, commands[0]);
34
55
  }
56
+
35
57
  } else {
36
58
  if(commands[0] === 'add') {
37
59
  if(commands[1] === 'devextreme-angular') {
@@ -40,7 +62,12 @@ const run = async(commands, options, devextremeConfig) => {
40
62
  }
41
63
 
42
64
  if(commands[1] === 'devextreme-react') {
43
- reactApplication.install(options);
65
+ if(nextjsApplication.isNextJsApp()) {
66
+ nextjsApplication.install(options);
67
+ } else {
68
+ reactApplication.install(options);
69
+ }
70
+
44
71
  return;
45
72
  }
46
73
 
@@ -54,23 +81,16 @@ const run = async(commands, options, devextremeConfig) => {
54
81
  return;
55
82
  }
56
83
 
57
- if(devextremeConfig.applicationEngine === 'angular') {
58
- if(commands[1] === 'view') {
59
- angularApplication.addView(commands[2], options);
60
- } else {
61
- console.error('Invalid command');
62
- printHelp(commands[0]);
63
- }
64
- } else if(devextremeConfig.applicationEngine === 'react') {
65
- if(commands[1] === 'view') {
66
- reactApplication.addView(commands[2], options);
67
- } else {
68
- console.error('Invalid command');
69
- printHelp(commands[0]);
70
- }
71
- } else if(devextremeConfig.applicationEngine === 'vue') {
84
+ const app = {
85
+ 'angular': angularApplication,
86
+ 'react': reactApplication,
87
+ 'nextjs': nextjsApplication,
88
+ 'vue': vueApplication,
89
+ }[devextremeConfig.applicationEngine];
90
+
91
+ if(app) {
72
92
  if(commands[1] === 'view') {
73
- vueApplication.addView(commands[2], options);
93
+ app.addView(commands[2], options);
74
94
  } else {
75
95
  console.error('Invalid command');
76
96
  printHelp(commands[0]);
@@ -13,6 +13,7 @@ const modifyJson = require('../utility/modify-json-file');
13
13
  const schematicsVersion = latestVersions['devextreme-schematics'] || 'latest';
14
14
 
15
15
  const minNgCliVersion = new semver('17.0.0');
16
+ const ngCliWithZoneless = new semver('20.0.0');
16
17
 
17
18
  async function runSchematicCommand(schematicCommand, options, evaluatingOptions) {
18
19
  const collectionName = 'devextreme-schematics';
@@ -63,6 +64,7 @@ function localPackageExists(packageName) {
63
64
 
64
65
  const hasSutableNgCli = async() => {
65
66
  const localVersion = ngVersion.getLocalNgVersion();
67
+
66
68
  if(!localVersion) {
67
69
  return false;
68
70
  }
@@ -83,6 +85,7 @@ const bumpAngular = (appPath, versionTag) => {
83
85
  for(const depName in section) {
84
86
  section[depName] = depName.startsWith('@angular') ? versionTag : section[depName];
85
87
  }
88
+ return section;
86
89
  };
87
90
 
88
91
  return {
@@ -97,6 +100,7 @@ const bumpAngular = (appPath, versionTag) => {
97
100
  const create = async(appName, options) => {
98
101
  const layout = await getLayoutInfo(options.layout);
99
102
  const depsVersionTag = extractDepsVersionTag(options);
103
+ const currentNgVersion = ngVersion.getNgCliVersion().version;
100
104
 
101
105
  const commandArguments = [
102
106
  'new',
@@ -105,10 +109,14 @@ const create = async(appName, options) => {
105
109
  '--routing=false',
106
110
  '--skip-tests=true',
107
111
  '--skip-install=true',
108
- '--standalone=false',
112
+ '--standalone=true',
109
113
  '--ssr=false'
110
114
  ];
111
115
 
116
+ if(ngCliWithZoneless.compare(currentNgVersion) <= 0) {
117
+ commandArguments.push('--zoneless=false');
118
+ }
119
+
112
120
  await runNgCommand(commandArguments, options);
113
121
 
114
122
  const appPath = path.join(process.cwd(), appName);
@@ -150,9 +158,9 @@ const changeMainTs = (appPath) => {
150
158
  moduleWorker.insertImport(filePath, 'devextreme/ui/themes', 'themes', true);
151
159
 
152
160
  const fileContent = fs.readFileSync(filePath).toString();
153
- const bootstrapPattern = /platformBrowser(?:Dynamic)?\(\)\.bootstrapModule\(\s*AppModule\s*(?:,\s*\{[^}]*\})?\s*\)/;
161
+ const bootstrapPattern = /bootstrapApplication\([^)]+\)/;
154
162
  const firstChaptStr = fileContent.match(bootstrapPattern)[0];
155
- const lastChaptStr = '.catch(err => console.error(err));';
163
+ const lastChaptStr = '.catch((err) => console.error(err));';
156
164
 
157
165
  fs.writeFileSync(
158
166
  filePath,
@@ -0,0 +1,231 @@
1
+ const runCommand = require('../utility/run-command');
2
+ const path = require('path');
3
+ const fs = require('fs');
4
+ const getLayoutInfo = require('../utility/prompts/layout');
5
+ const getTemplateTypeInfo = require('../utility/prompts/typescript');
6
+ const templateCreator = require('../utility/template-creator');
7
+ const packageManager = require('../utility/package-manager');
8
+ const packageJsonUtils = require('../utility/package-json-utils');
9
+ const insertItemToArray = require('../utility/file-content').insertItemToArray;
10
+ const stringUtils = require('../utility/string');
11
+ const typescriptUtils = require('../utility/typescript-extension');
12
+ const removeFile = require('../utility/file-operations').remove;
13
+ const latestVersions = require('../utility/latest-versions');
14
+ const { extractDepsVersionTag } = require('../utility/extract-deps-version-tag');
15
+ const {
16
+ updateJsonPropName,
17
+ bumpReact,
18
+ getCorrectPath,
19
+ addStylesToApp,
20
+ getComponentPageName,
21
+ } = require('./application.react');
22
+
23
+ const defaultStyles = [
24
+ 'devextreme/dist/css/dx.light.css'
25
+ ];
26
+
27
+ const isNextJsApp = () => {
28
+ const appPath = process.cwd();
29
+
30
+ return fs.existsSync(path.join(appPath, 'next.config.ts')) || fs.existsSync(path.join(appPath, 'next.config.mjs'));
31
+ };
32
+
33
+ const isTsApp = (appPath) => {
34
+ return fs.existsSync(path.join(appPath, 'next.config.ts'));
35
+ };
36
+
37
+ const getExtension = (appPath) => {
38
+ return fs.existsSync(path.join(appPath, 'src/app', 'layout.tsx')) ? '.tsx' : '.jsx';
39
+ };
40
+
41
+ const pathToPagesIndex = () => {
42
+ const extension = getExtension(process.cwd());
43
+ return path.join(process.cwd(), 'src', 'views', `index${extension}`);
44
+ };
45
+
46
+ const preparePackageJsonForTemplate = (appPath, appName) => {
47
+ const dependencies = [
48
+ { name: 'devextreme-cli', version: latestVersions['devextreme-cli'], dev: true },
49
+ { name: 'jose', version: latestVersions['jose'] },
50
+ ];
51
+ const scripts = [
52
+ { name: 'build-themes', value: 'devextreme build' },
53
+ { name: 'postinstall', value: 'npm run build-themes' }
54
+ ];
55
+
56
+ packageJsonUtils.addDependencies(appPath, dependencies);
57
+ packageJsonUtils.updateScripts(appPath, scripts);
58
+ packageJsonUtils.updateName(appPath, appName);
59
+ };
60
+
61
+ const create = async(appName, options) => {
62
+ const templateType = await getTemplateTypeInfo(options.template);
63
+ const layoutType = await getLayoutInfo(options.layout);
64
+
65
+ const templateOptions = Object.assign({}, options, {
66
+ project: stringUtils.humanize(appName),
67
+ layout: stringUtils.classify(layoutType),
68
+ isTypeScript: typescriptUtils.isTypeScript(templateType)
69
+ });
70
+ const depsVersionTag = extractDepsVersionTag(options);
71
+
72
+ let commandArguments = [`-p=create-next-app@${depsVersionTag || latestVersions['create-next-app']}`, 'create-next-app', appName];
73
+
74
+ commandArguments = [
75
+ ...commandArguments,
76
+ `${templateOptions.isTypeScript ? '--typescript' : '--javascript'}`,
77
+ '--eslint',
78
+ '--no-tailwind',
79
+ '--src-dir',
80
+ '--app',
81
+ '--no-turbopack',
82
+ '--import-alias "@/*"',
83
+ ];
84
+
85
+ await runCommand('npx', commandArguments);
86
+
87
+ const appPath = path.join(process.cwd(), appName);
88
+
89
+ if(depsVersionTag) {
90
+ bumpReact(appPath, depsVersionTag, templateOptions.isTypeScript);
91
+ }
92
+
93
+ addTemplate(appPath, appName, templateOptions);
94
+ modifyAppFiles(appPath, templateOptions);
95
+ };
96
+
97
+ const modifyAppFiles = (appPath, { project, isTypeScript }) => {
98
+ const entryFilePath = path.join(appPath, `src/app/layout.${isTypeScript ? 'tsx' : 'jsx'}`);
99
+
100
+ let content = fs.readFileSync(entryFilePath).toString();
101
+ content = content.replace(/<title>[^<]+<\/title>/, `<title>${project}<\/title>`);
102
+
103
+ fs.writeFileSync(entryFilePath, content);
104
+ };
105
+
106
+ const addTemplate = (appPath, appName, templateOptions) => {
107
+ const applicationTemplatePath = path.join(
108
+ templateCreator.getTempaltePath('nextjs'),
109
+ 'application'
110
+ );
111
+
112
+ const manifestPath = path.join(appPath, 'public', 'manifest.json');
113
+
114
+ const styles = [
115
+ '../dx-styles.scss',
116
+ '../themes/generated/theme.additional.css',
117
+ '../themes/generated/theme.additional.dark.css',
118
+ '../themes/generated/theme.base.css',
119
+ '../themes/generated/theme.base.dark.css',
120
+ 'devextreme/dist/css/dx.common.css'
121
+ ];
122
+
123
+ templateCreator.moveTemplateFilesToProject(applicationTemplatePath, appPath, templateOptions, getCorrectPath);
124
+
125
+ !templateOptions.isTypeScript && removeFile(path.join(appPath, 'src', 'types.jsx'));
126
+ removeFile(path.join(appPath, 'src/app', 'page.js'));
127
+ removeFile(path.join(appPath, 'src/app', 'layout.js'));
128
+ removeFile(path.join(appPath, 'src/app', 'globals.scss'));
129
+
130
+ if(!templateOptions.empty) {
131
+ addSamplePages(appPath, templateOptions);
132
+ }
133
+
134
+ preparePackageJsonForTemplate(appPath, appName, templateOptions.isTypeScript);
135
+ updateJsonPropName(manifestPath, appName);
136
+ install({ isTypeScript: templateOptions.isTypeScript }, appPath, styles);
137
+ };
138
+
139
+ const getEntryFilePath = (options, appPath) => {
140
+ const extension = options.isTypeScript || isTsApp(appPath) ? 'ts' : 'js';
141
+ const srcFolder = fs.existsSync(path.join(appPath, 'src')) ? 'src' : '';
142
+ const isAppRouterApp = fs.existsSync(path.join(appPath, srcFolder, 'app')) && fs.lstatSync(appPath).isDirectory();
143
+
144
+ const entryFilePath = isAppRouterApp
145
+ ? path.join('app', `layout.${extension}`)
146
+ : path.join('pages', `_app.${extension}`);
147
+
148
+ const jsx = fs.existsSync(path.join(appPath, srcFolder, entryFilePath + 'x')) ? 'x' : '';
149
+
150
+ return path.join(srcFolder, entryFilePath + jsx);
151
+ };
152
+
153
+ const install = (options, appPath, styles) => {
154
+ appPath = appPath ? appPath : process.cwd();
155
+
156
+ const pathToMainComponent = path.join(appPath, getEntryFilePath(options, appPath));
157
+
158
+ addStylesToApp(pathToMainComponent, styles || defaultStyles);
159
+ packageJsonUtils.addDevextreme(appPath, options.dxversion, 'react');
160
+
161
+ packageManager.runInstall({ cwd: appPath });
162
+ };
163
+
164
+ const getNavigationData = (viewName, componentName, icon) => {
165
+ const pagePath = stringUtils.dasherize(viewName);
166
+ return {
167
+ navigation: `\n {\n text: \'${stringUtils.humanize(viewName)}\',\n path: \'/pages/${pagePath}\',\n icon: \'${icon}\'\n }`
168
+ };
169
+ };
170
+
171
+ const createPathToPage = (pageName) => {
172
+ const pagesPath = path.join(process.cwd(), 'src', 'app/pages');
173
+ const newPageFolderPath = path.join(pagesPath, pageName);
174
+
175
+ if(!fs.existsSync(pagesPath)) {
176
+ fs.mkdirSync(pagesPath);
177
+ fs.writeFileSync(pathToPagesIndex(), '');
178
+ }
179
+
180
+ if(!fs.existsSync(newPageFolderPath)) {
181
+ fs.mkdirSync(newPageFolderPath);
182
+ }
183
+
184
+ return newPageFolderPath;
185
+ };
186
+
187
+ const addSamplePages = (appPath, templateOptions) => {
188
+ const samplePageTemplatePath = path.join(
189
+ templateCreator.getTempaltePath('nextjs'),
190
+ 'sample-pages'
191
+ );
192
+
193
+ const pagesPath = path.join(appPath, 'src', 'app/pages');
194
+
195
+ templateCreator.moveTemplateFilesToProject(samplePageTemplatePath, pagesPath, {
196
+ isTypeScript: templateOptions.isTypeScript
197
+ }, getCorrectPath);
198
+ };
199
+
200
+ const addView = (pageName, options) => {
201
+ const pageTemplatePath = path.join(
202
+ templateCreator.getTempaltePath('nextjs'),
203
+ 'page'
204
+ );
205
+ const extension = getExtension(process.cwd());
206
+
207
+ const componentName = getComponentPageName(pageName);
208
+ const pathToPage = createPathToPage(pageName);
209
+ const navigationModulePath = path.join(process.cwd(), 'src', `app-navigation${extension}`);
210
+ const navigationData = getNavigationData(pageName, componentName, options && options.icon || 'folder');
211
+
212
+ const getCorrectExtension = (fileExtension) => {
213
+ return fileExtension === '.tsx' ? extension : fileExtension;
214
+ };
215
+
216
+ const getPageFileName = (pageName, pageItem) => {
217
+ return pageItem === 'page.tsx' ? 'page' : pageName;
218
+ };
219
+
220
+ templateCreator.addPageToApp(pageName, pathToPage, pageTemplatePath, getCorrectExtension, { getPageFileName });
221
+
222
+ insertItemToArray(navigationModulePath, navigationData.navigation);
223
+ };
224
+
225
+ module.exports = {
226
+ isNextJsApp,
227
+ install,
228
+ create,
229
+ addTemplate,
230
+ addView
231
+ };
@@ -52,14 +52,19 @@ const updateJsonPropName = (path, name) => {
52
52
  });
53
53
  };
54
54
 
55
- const bumpReact = (appPath, versionTag) => {
55
+ const bumpReact = (appPath, versionTag, isTypeScript) => {
56
56
  const dependencies = [
57
57
  { name: 'react', version: versionTag },
58
58
  { name: 'react-dom', version: versionTag },
59
- { name: '@types/react', version: versionTag, dev: true },
60
- { name: '@types/react-dom', version: versionTag, dev: true },
61
59
  ];
62
60
 
61
+ if(isTypeScript) {
62
+ dependencies.push(
63
+ { name: '@types/react', version: versionTag, dev: true },
64
+ { name: '@types/react-dom', version: versionTag, dev: true },
65
+ );
66
+ }
67
+
63
68
  packageJsonUtils.addDependencies(appPath, dependencies);
64
69
  };
65
70
 
@@ -86,7 +91,7 @@ const create = async(appName, options) => {
86
91
  modifyIndexHtml(appPath, templateOptions.project);
87
92
 
88
93
  if(depsVersionTag) {
89
- bumpReact(appPath, depsVersionTag);
94
+ bumpReact(appPath, depsVersionTag, templateOptions.isTypeScript);
90
95
  }
91
96
 
92
97
  addTemplate(appPath, appName, templateOptions);
@@ -219,5 +224,10 @@ module.exports = {
219
224
  install,
220
225
  create,
221
226
  addTemplate,
222
- addView
227
+ addView,
228
+ updateJsonPropName,
229
+ bumpReact,
230
+ getCorrectPath,
231
+ addStylesToApp,
232
+ getComponentPageName,
223
233
  };
@@ -0,0 +1 @@
1
+ SESSION_SECRET=<your_secret_key_goes_here>
@@ -0,0 +1,63 @@
1
+ {
2
+ "applicationEngine": "nextjs",
3
+ "build": {
4
+ "commands": [
5
+ {
6
+ "command": "build-theme",
7
+ "options": {
8
+ "inputFile": "src/themes/metadata.base.json",
9
+ "outputFile": "src/themes/generated/theme.base.css"
10
+ }
11
+ },
12
+ {
13
+ "command": "build-theme",
14
+ "options": {
15
+ "inputFile": "src/themes/metadata.base.dark.json",
16
+ "outputFile": "src/themes/generated/theme.base.dark.css"
17
+ }
18
+ },
19
+ {
20
+ "command": "build-theme",
21
+ "options": {
22
+ "inputFile": "src/themes/metadata.additional.json",
23
+ "outputFile": "src/themes/generated/theme.additional.css"
24
+ }
25
+ },
26
+ {
27
+ "command": "build-theme",
28
+ "options": {
29
+ "inputFile": "src/themes/metadata.additional.dark.json",
30
+ "outputFile": "src/themes/generated/theme.additional.dark.css"
31
+ }
32
+ },
33
+ {
34
+ "command": "export-theme-vars",
35
+ "options": {
36
+ "inputFile": "src/themes/metadata.base.json",
37
+ "outputFile": "src/themes/generated/variables.base.scss"
38
+ }
39
+ },
40
+ {
41
+ "command": "export-theme-vars",
42
+ "options": {
43
+ "inputFile": "src/themes/metadata.base.dark.json",
44
+ "outputFile": "src/themes/generated/variables.base.dark.scss"
45
+ }
46
+ },
47
+ {
48
+ "command": "export-theme-vars",
49
+ "options": {
50
+ "inputFile": "src/themes/metadata.additional.json",
51
+ "outputFile": "src/themes/generated/variables.additional.scss"
52
+ }
53
+ },
54
+ {
55
+ "command": "export-theme-vars",
56
+ "options": {
57
+ "inputFile": "src/themes/metadata.additional.dark.json",
58
+ "outputFile": "src/themes/generated/variables.additional.dark.scss"
59
+ }
60
+ }
61
+ ]
62
+ }
63
+ }
@@ -0,0 +1,32 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ async redirects() {
4
+ return [
5
+ {
6
+ source: '/',
7
+ destination: '/pages/home',
8
+ permanent: true,
9
+ },
10
+ {
11
+ source: '/login',
12
+ destination: '/auth/login',
13
+ permanent: true,
14
+ },
15
+ {
16
+ source: '/reset-password',
17
+ destination: '/auth/reset-password',
18
+ permanent: true,
19
+ },
20
+ {
21
+ source: '/create-account',
22
+ destination: '/auth/create-account',
23
+ permanent: true,
24
+ },
25
+ ]
26
+ },
27
+ images: {
28
+ remotePatterns: [new URL('https://js.devexpress.com/**')]
29
+ },
30
+ }
31
+
32
+ export default nextConfig;
@@ -0,0 +1,25 @@
1
+ {
2
+ "short_name": "React App",
3
+ "name": "Create React App Sample",
4
+ "icons": [
5
+ {
6
+ "src": "favicon.ico",
7
+ "sizes": "64x64 32x32 24x24 16x16",
8
+ "type": "image/x-icon"
9
+ },
10
+ {
11
+ "src": "logo192.png",
12
+ "type": "image/png",
13
+ "sizes": "192x192"
14
+ },
15
+ {
16
+ "src": "logo512.png",
17
+ "type": "image/png",
18
+ "sizes": "512x512"
19
+ }
20
+ ],
21
+ "start_url": ".",
22
+ "display": "standalone",
23
+ "theme_color": "#000000",
24
+ "background_color": "#ffffff"
25
+ }
@@ -0,0 +1,3 @@
1
+ # https://www.robotstxt.org/robotstxt.html
2
+ User-agent: *
3
+ Disallow:
@@ -0,0 +1,76 @@
1
+ 'use server'
2
+ import { redirect } from 'next/navigation'
3
+ import defaultUser from '@/utils/default-user';
4
+ import { createSession, deleteSession } from '@/app/lib/session'
5
+
6
+ export async function signUp(email<%=#isTypeScript%>: string<%=/isTypeScript%>, password<%=#isTypeScript%>: string<%=/isTypeScript%>) {
7
+ try {
8
+ // 1. Check if the user exists in the database and return isOk: false if so;
9
+ // 2. Otherwise, add the user to the database.
10
+ console.log(email, password);
11
+
12
+ return {
13
+ isOk: true,
14
+ }
15
+ } catch {
16
+ return {
17
+ isOk: false,
18
+ message: 'Unable to create an account',
19
+ }
20
+ }
21
+ }
22
+
23
+ export async function signIn(email<%=#isTypeScript%>: string<%=/isTypeScript%>, password<%=#isTypeScript%>: string<%=/isTypeScript%>) {
24
+ try {
25
+ // Verify that a user exists
26
+ console.log(email, password);
27
+
28
+ await createSession(defaultUser.id);
29
+
30
+ return {
31
+ isOk: true,
32
+ }
33
+ } catch {
34
+ return {
35
+ isOk: false,
36
+ message: 'Unable to sign in',
37
+ }
38
+ }
39
+ }
40
+
41
+ export async function signOut() {
42
+ await deleteSession();
43
+ redirect('/login');
44
+ }
45
+
46
+ export async function changePassword(email<%=#isTypeScript%>: string<%=/isTypeScript%>, recoveryCode<%=#isTypeScript%>?: string<%=/isTypeScript%>) {
47
+ try {
48
+ // Verify the recovery code
49
+ console.log(email, recoveryCode);
50
+
51
+ return {
52
+ isOk: true,
53
+ }
54
+ } catch {
55
+ return {
56
+ isOk: false,
57
+ message: 'Unable to change the password',
58
+ }
59
+ }
60
+ }
61
+
62
+ export async function resetPassword(email<%=#isTypeScript%>: string<%=/isTypeScript%>) {
63
+ try {
64
+ // Reset password
65
+ console.log(email);
66
+
67
+ return {
68
+ isOk: true,
69
+ }
70
+ } catch {
71
+ return {
72
+ isOk: false,
73
+ message: 'Unable to reset password',
74
+ }
75
+ }
76
+ }