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.
- package/package.json +4 -3
- package/src/application.js +40 -20
- package/src/applications/application.angular.js +11 -3
- package/src/applications/application.nextjs.js +231 -0
- package/src/applications/application.react.js +15 -5
- package/src/templates/nextjs/application/.env +1 -0
- package/src/templates/nextjs/application/devextreme.json +63 -0
- package/src/templates/nextjs/application/next.config.mjs +32 -0
- package/src/templates/nextjs/application/public/logo192.png +0 -0
- package/src/templates/nextjs/application/public/logo512.png +0 -0
- package/src/templates/nextjs/application/public/manifest.json +25 -0
- package/src/templates/nextjs/application/public/robots.txt +3 -0
- package/src/templates/nextjs/application/src/app/actions/auth.ts +76 -0
- package/src/templates/nextjs/application/src/app/auth/[type]/page.tsx +49 -0
- package/src/templates/nextjs/application/src/app/layout.tsx +17 -0
- package/src/templates/nextjs/application/src/app/lib/session.ts +47 -0
- package/src/templates/nextjs/application/src/app/pages/layout.tsx +18 -0
- package/src/templates/nextjs/application/src/app-info.tsx +5 -0
- package/src/templates/nextjs/application/src/app-navigation.tsx +21 -0
- package/src/templates/nextjs/application/src/components/change-password-form/ChangePasswordForm.tsx +86 -0
- package/src/templates/nextjs/application/src/components/create-account-form/CreateAccountForm.scss +19 -0
- package/src/templates/nextjs/application/src/components/create-account-form/CreateAccountForm.tsx +107 -0
- package/src/templates/nextjs/application/src/components/footer/Footer.scss +12 -0
- package/src/templates/nextjs/application/src/components/footer/Footer.tsx +5 -0
- package/src/templates/nextjs/application/src/components/header/Header.scss +40 -0
- package/src/templates/nextjs/application/src/components/header/Header.tsx +38 -0
- package/src/templates/nextjs/application/src/components/index.tsx +7 -0
- package/src/templates/nextjs/application/src/components/login-form/LoginForm.scss +12 -0
- package/src/templates/nextjs/application/src/components/login-form/LoginForm.tsx +101 -0
- package/src/templates/nextjs/application/src/components/reset-password-form/ResetPasswordForm.scss +12 -0
- package/src/templates/nextjs/application/src/components/reset-password-form/ResetPasswordForm.tsx +78 -0
- package/src/templates/nextjs/application/src/components/side-navigation-menu/SideNavigationMenu.scss +71 -0
- package/src/templates/nextjs/application/src/components/side-navigation-menu/SideNavigationMenu.tsx +88 -0
- package/src/templates/nextjs/application/src/components/theme-switcher/ThemeSwitcher.tsx +21 -0
- package/src/templates/nextjs/application/src/components/user-panel/UserPanel.scss +51 -0
- package/src/templates/nextjs/application/src/components/user-panel/UserPanel.tsx +55 -0
- package/src/templates/nextjs/application/src/dx-styles.scss +106 -0
- package/src/templates/nextjs/application/src/index.css +12 -0
- package/src/templates/nextjs/application/src/layouts/index.tsx +3 -0
- package/src/templates/nextjs/application/src/layouts/side-nav-inner-toolbar/side-nav-inner-toolbar.scss +17 -0
- package/src/templates/nextjs/application/src/layouts/side-nav-inner-toolbar/side-nav-inner-toolbar.tsx +133 -0
- package/src/templates/nextjs/application/src/layouts/side-nav-outer-toolbar/side-nav-outer-toolbar.scss +10 -0
- package/src/templates/nextjs/application/src/layouts/side-nav-outer-toolbar/side-nav-outer-toolbar.tsx +119 -0
- package/src/templates/nextjs/application/src/layouts/single-card/single-card.scss +42 -0
- package/src/templates/nextjs/application/src/layouts/single-card/single-card.tsx +16 -0
- package/src/templates/nextjs/application/src/middleware.ts +46 -0
- package/src/templates/nextjs/application/src/theme.tsx +66 -0
- package/src/templates/nextjs/application/src/themes/metadata.additional.dark.json +11 -0
- package/src/templates/nextjs/application/src/themes/metadata.additional.json +11 -0
- package/src/templates/nextjs/application/src/themes/metadata.base.dark.json +8 -0
- package/src/templates/nextjs/application/src/themes/metadata.base.json +7 -0
- package/src/templates/nextjs/application/src/types.tsx +60 -0
- package/src/templates/nextjs/application/src/utils/default-user.tsx +7 -0
- package/src/templates/nextjs/application/src/utils/media-query.tsx +56 -0
- package/src/templates/nextjs/application/src/variables.scss +53 -0
- package/src/templates/nextjs/page/page.scss +0 -0
- package/src/templates/nextjs/page/page.tsx +13 -0
- package/src/templates/nextjs/sample-pages/home/home.scss +37 -0
- package/src/templates/nextjs/sample-pages/home/page.tsx +101 -0
- package/src/templates/nextjs/sample-pages/profile/page.tsx +61 -0
- package/src/templates/nextjs/sample-pages/profile/profile.scss +19 -0
- package/src/templates/nextjs/sample-pages/tasks/page.tsx +112 -0
- package/src/templates/nextjs/sample-pages/tasks/tasks.scss +3 -0
- package/src/templates/react/application/src/components/header/Header.scss +1 -1
- package/src/templates/react/application/src/dx-styles.scss +3 -3
- package/src/templates/vue-v3/application/src/components/header-toolbar.vue +1 -1
- package/src/templates/vue-v3/application/src/dx-styles.scss +4 -3
- package/src/utility/latest-versions.js +6 -4
- package/src/utility/module.js +11 -3
- package/src/utility/prompts/react-app-type.js +17 -0
- package/src/utility/run-command.js +10 -2
- 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-
|
|
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": "
|
|
77
|
+
"gitHead": "12a211ead8510e78eb1f33b6a34664823d73a4a7"
|
|
77
78
|
}
|
package/src/application.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
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=
|
|
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 = /
|
|
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;
|
|
Binary file
|
|
Binary file
|
|
@@ -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,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
|
+
}
|