zmp-cli 3.12.0 → 3.13.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/.vscode/launch.json +17 -20
- package/.vscode/settings.json +3 -2
- package/config/index.js +0 -1
- package/create/templates/zaui/generate-scripts.js +2 -2
- package/create/utils/generate-app-config.js +5 -4
- package/create/utils/generate-package-json.js +6 -7
- package/index.js +39 -1
- package/login/index.js +0 -2
- package/package.json +2 -1
- package/sync/index-to-app-config.js +143 -0
- package/sync/index.js +55 -0
package/.vscode/launch.json
CHANGED
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
]
|
|
21
|
-
}
|
|
2
|
+
// Use IntelliSense to learn about possible attributes.
|
|
3
|
+
// Hover to view descriptions of existing attributes.
|
|
4
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"configurations": [
|
|
7
|
+
{
|
|
8
|
+
"type": "pwa-node",
|
|
9
|
+
"request": "launch",
|
|
10
|
+
"name": "Launch Program",
|
|
11
|
+
"skipFiles": ["<node_internals>/**"],
|
|
12
|
+
"program": "${workspaceFolder}/index.js",
|
|
13
|
+
"args": ["sync-config", "--root-element", "#__next", "out/index.html"],
|
|
14
|
+
"cwd": "${workspaceFolder}/../next-mini-app/",
|
|
15
|
+
"console": "integratedTerminal"
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
package/.vscode/settings.json
CHANGED
package/config/index.js
CHANGED
|
@@ -2,7 +2,7 @@ const indent = require('../../utils/indent');
|
|
|
2
2
|
const stylesExtension = require('../../utils/styles-extension');
|
|
3
3
|
|
|
4
4
|
module.exports = (options) => {
|
|
5
|
-
const { cssPreProcessor, includeTailwind } = options;
|
|
5
|
+
const { cssPreProcessor, includeTailwind, framework } = options;
|
|
6
6
|
|
|
7
7
|
let scripts = '';
|
|
8
8
|
|
|
@@ -30,7 +30,7 @@ module.exports = (options) => {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// Mount React App
|
|
33
|
-
const root = createRoot(document.getElementById('app'));
|
|
33
|
+
${framework === 'react-typescript' ? "const root = createRoot(document.getElementById('app')!);" : "const root = createRoot(document.getElementById('app'));"}
|
|
34
34
|
root.render(React.createElement(App));
|
|
35
35
|
`
|
|
36
36
|
);
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
const generateRoutes = require('../templates/generate-routes');
|
|
2
|
-
|
|
3
1
|
module.exports = function generateAppConfig(options) {
|
|
4
2
|
const { name } = options;
|
|
5
3
|
|
|
6
4
|
// Window config
|
|
7
5
|
const appConfig = {
|
|
8
6
|
title: name,
|
|
7
|
+
headerTitle: name,
|
|
9
8
|
headerColor: '#1843EF',
|
|
10
9
|
textColor: 'white',
|
|
11
10
|
statusBarColor: '#1843EF',
|
|
12
11
|
leftButton: 'back',
|
|
12
|
+
statusBar: 'normal',
|
|
13
|
+
actionBarHidden: false,
|
|
14
|
+
hideAndroidBottomNavigationBar: false,
|
|
15
|
+
hideIOSSafeAreaBottom: false,
|
|
13
16
|
};
|
|
14
|
-
const routes = generateRoutes(options);
|
|
15
17
|
// Content
|
|
16
18
|
const content = JSON.stringify(
|
|
17
19
|
{
|
|
@@ -20,7 +22,6 @@ module.exports = function generateAppConfig(options) {
|
|
|
20
22
|
listCSS: [],
|
|
21
23
|
listSyncJS: [],
|
|
22
24
|
listAsyncJS: [],
|
|
23
|
-
pages: routes,
|
|
24
25
|
},
|
|
25
26
|
'',
|
|
26
27
|
2
|
|
@@ -18,7 +18,6 @@ module.exports = function generatePackageJson(options) {
|
|
|
18
18
|
: ['zmp-framework', 'zmp-sdk', 'swiper'];
|
|
19
19
|
const dependenciesVue = ['vue@3', 'zmp-framework'];
|
|
20
20
|
const dependenciesReact = ['react', 'react-dom', 'prop-types'];
|
|
21
|
-
const dependenciesReactTs = ['@types/react', '@types/react-dom'];
|
|
22
21
|
const tailwindDependencies = [
|
|
23
22
|
'autoprefixer',
|
|
24
23
|
'tailwindcss',
|
|
@@ -36,17 +35,17 @@ module.exports = function generatePackageJson(options) {
|
|
|
36
35
|
}
|
|
37
36
|
}
|
|
38
37
|
|
|
39
|
-
if (framework === 'react-typescript') {
|
|
40
|
-
dependencies.push(...dependenciesReactTs);
|
|
41
|
-
if (package === 'zmp-ui') {
|
|
42
|
-
dependencies.push('@types/react-router-dom');
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
38
|
const devDependencies = [
|
|
46
39
|
'cross-env',
|
|
47
40
|
'postcss-preset-env@6.7.0',
|
|
48
41
|
'vite@2.6.14',
|
|
49
42
|
];
|
|
43
|
+
if (framework === 'react-typescript') {
|
|
44
|
+
devDependencies.push('@types/react', '@types/react-dom');
|
|
45
|
+
if (package === 'zmp-ui') {
|
|
46
|
+
devDependencies.push('@types/react-router-dom');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
50
49
|
// CSS PreProcessor
|
|
51
50
|
if (cssPreProcessor === 'stylus') devDependencies.push(...['stylus']);
|
|
52
51
|
else if (cssPreProcessor === 'less') devDependencies.push(...['less']);
|
package/index.js
CHANGED
|
@@ -19,12 +19,14 @@ const createApp = require('./create/index');
|
|
|
19
19
|
const startApp = require('./start/index');
|
|
20
20
|
const buildApp = require('./build/index');
|
|
21
21
|
const deployApp = require('./deploy/index');
|
|
22
|
+
const syncApp = require('./sync/index');
|
|
22
23
|
const migrateApp = require('./migrate/index');
|
|
23
24
|
const os = require('os');
|
|
24
25
|
// const generateAssets = require('./assets/index');
|
|
25
26
|
// const server = require('./ui/server');
|
|
26
27
|
const pkg = require('./package.json');
|
|
27
28
|
const config = require('./config');
|
|
29
|
+
const { versionStatus } = require('./utils/constants');
|
|
28
30
|
|
|
29
31
|
const cwd = process.cwd();
|
|
30
32
|
|
|
@@ -191,6 +193,11 @@ program
|
|
|
191
193
|
.command('deploy')
|
|
192
194
|
.option('-D, --dev', 'Deploy in Development server')
|
|
193
195
|
.option('-M, --mode <m>', 'Env mode')
|
|
196
|
+
.option('-p, --passive', 'Passive mode (non-interactive)')
|
|
197
|
+
.option('-e, --existing', 'Deploy existing project')
|
|
198
|
+
.option('-t, --testing', 'Deploy testing version')
|
|
199
|
+
.option('-m, --desc <message>', 'Version description')
|
|
200
|
+
.option('-o, --outputDir <output>', 'Output folder. Default www')
|
|
194
201
|
.option(
|
|
195
202
|
'-P, --port <n>',
|
|
196
203
|
'Specify UI server port. By default it is 3001',
|
|
@@ -199,7 +206,17 @@ program
|
|
|
199
206
|
.description('Deploy a ZMP project')
|
|
200
207
|
.action(async (options) => {
|
|
201
208
|
const currentProject = getCurrentProject(cwd);
|
|
202
|
-
|
|
209
|
+
let opts = options;
|
|
210
|
+
if (options.existing) {
|
|
211
|
+
opts.customProject = true;
|
|
212
|
+
} else {
|
|
213
|
+
if (!options.passive) {
|
|
214
|
+
opts = await getDeployOptions(currentProject);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (options.testing) {
|
|
218
|
+
opts.versionStatus = versionStatus.TESTING;
|
|
219
|
+
}
|
|
203
220
|
if (opts.quit) process.exit(1);
|
|
204
221
|
await deployApp(
|
|
205
222
|
{
|
|
@@ -213,6 +230,27 @@ program
|
|
|
213
230
|
process.exit(0);
|
|
214
231
|
});
|
|
215
232
|
|
|
233
|
+
program
|
|
234
|
+
.usage('<command> [options]')
|
|
235
|
+
.command('sync-config <source>')
|
|
236
|
+
.option(
|
|
237
|
+
'-r, --root-element <selector>',
|
|
238
|
+
'Custom entry point, default is #app'
|
|
239
|
+
)
|
|
240
|
+
.description(
|
|
241
|
+
'Automatically update app-config.json resources list based on index.html'
|
|
242
|
+
)
|
|
243
|
+
.action(async (source, options) => {
|
|
244
|
+
await syncApp(
|
|
245
|
+
{
|
|
246
|
+
source,
|
|
247
|
+
...options,
|
|
248
|
+
},
|
|
249
|
+
logger
|
|
250
|
+
);
|
|
251
|
+
process.exit(0);
|
|
252
|
+
});
|
|
253
|
+
|
|
216
254
|
program
|
|
217
255
|
.usage('<command> [options]')
|
|
218
256
|
.command('migrate')
|
package/login/index.js
CHANGED
|
@@ -111,7 +111,6 @@ module.exports = async (options = {}, logger, { exitOnError = true } = {}) => {
|
|
|
111
111
|
clearInterval(intervalCheckLogin);
|
|
112
112
|
const token = resData.data && resData.data.jwt;
|
|
113
113
|
envUtils.setEnv(config.env.token, token);
|
|
114
|
-
envUtils.setEnv(config.env.accessToken, token);
|
|
115
114
|
logger.statusDone('Login Success!');
|
|
116
115
|
return resolve();
|
|
117
116
|
}
|
|
@@ -146,7 +145,6 @@ module.exports = async (options = {}, logger, { exitOnError = true } = {}) => {
|
|
|
146
145
|
const dataDecoded = jwt.decode(token);
|
|
147
146
|
envUtils.setEnv(config.env.appId, dataDecoded.appId);
|
|
148
147
|
envUtils.setEnv(config.env.token, token);
|
|
149
|
-
envUtils.setEnv(config.env.accessToken, options.token);
|
|
150
148
|
} catch (error) {
|
|
151
149
|
return reject(error);
|
|
152
150
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zmp-cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.13.0",
|
|
4
4
|
"description": "ZMP command line utility (CLI)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"copy-webpack-plugin": "^7.0.0",
|
|
57
57
|
"cpy": "^7.3.0",
|
|
58
58
|
"css-minimizer-webpack-plugin": "^1.2.0",
|
|
59
|
+
"dom-parser": "^0.1.6",
|
|
59
60
|
"envfile": "^6.14.0",
|
|
60
61
|
"exec-sh": "^0.3.2",
|
|
61
62
|
"express": "^4.17.1",
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
const DomParser = require('dom-parser');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const axios = require('axios');
|
|
4
|
+
|
|
5
|
+
async function generateListResourcesFromIndex(html, { outputDir, rootElement }) {
|
|
6
|
+
const listCSS = [];
|
|
7
|
+
const listSyncJS = [];
|
|
8
|
+
const listAsyncJS = [];
|
|
9
|
+
let inlineJS = '';
|
|
10
|
+
try {
|
|
11
|
+
const parser = new DomParser();
|
|
12
|
+
const doc = parser.parseFromString(html, 'text/html');
|
|
13
|
+
const headInlines = [];
|
|
14
|
+
const bodyInlines = [];
|
|
15
|
+
|
|
16
|
+
const scripts = doc.getElementsByTagName('script');
|
|
17
|
+
for (const script of scripts) {
|
|
18
|
+
const src = script.getAttribute('src');
|
|
19
|
+
const type = script.getAttribute('type');
|
|
20
|
+
const async = script.getAttribute('async');
|
|
21
|
+
const inline = script.innerHTML;
|
|
22
|
+
try {
|
|
23
|
+
if (inline) {
|
|
24
|
+
bodyInlines.push(script.outerHTML);
|
|
25
|
+
} else {
|
|
26
|
+
let scriptName = src;
|
|
27
|
+
if (src.includes('://')) {
|
|
28
|
+
let filename = src.substring(src.lastIndexOf('/') + 1);
|
|
29
|
+
filename = `cdn.` + filename;
|
|
30
|
+
const response = await axios({
|
|
31
|
+
method: 'get',
|
|
32
|
+
url: src,
|
|
33
|
+
responseType: 'stream',
|
|
34
|
+
});
|
|
35
|
+
const fileStream = fs.createWriteStream(`${outputDir}/${filename}`);
|
|
36
|
+
response.data.pipe(fileStream);
|
|
37
|
+
|
|
38
|
+
await new Promise((resolve, reject) => {
|
|
39
|
+
fileStream.on('finish', resolve);
|
|
40
|
+
fileStream.on('error', reject);
|
|
41
|
+
});
|
|
42
|
+
scriptName = filename;
|
|
43
|
+
}
|
|
44
|
+
if (type === 'module' && !scriptName.endsWith('module.js')) {
|
|
45
|
+
const newName = src.slice(0, -3).concat('.module.js');
|
|
46
|
+
fs.rename(scriptName, newName);
|
|
47
|
+
scriptName = newName;
|
|
48
|
+
}
|
|
49
|
+
(async ? listAsyncJS : listSyncJS).push(scriptName);
|
|
50
|
+
}
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.warn(
|
|
53
|
+
'\n⚠️ Unable to download resource from CDN. Please handle this file manually!',
|
|
54
|
+
src
|
|
55
|
+
);
|
|
56
|
+
console.error(error.message);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const styles = doc.getElementsByTagName('style');
|
|
61
|
+
styles.forEach((style) => {
|
|
62
|
+
const inline = style.innerHTML;
|
|
63
|
+
if (inline) {
|
|
64
|
+
headInlines.push(style.outerHTML);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const links = doc.getElementsByTagName('link');
|
|
69
|
+
for (const link of links) {
|
|
70
|
+
const rel = link.getAttribute('rel');
|
|
71
|
+
const href = link.getAttribute('href');
|
|
72
|
+
try {
|
|
73
|
+
if (rel === 'stylesheet') {
|
|
74
|
+
let filename = href;
|
|
75
|
+
if (href.includes('://')) {
|
|
76
|
+
filename = href.substring(href.lastIndexOf('/') + 1);
|
|
77
|
+
filename = `cdn.` + filename;
|
|
78
|
+
const response = await axios({
|
|
79
|
+
method: 'get',
|
|
80
|
+
url: href,
|
|
81
|
+
responseType: 'stream',
|
|
82
|
+
});
|
|
83
|
+
const fileStream = fs.createWriteStream(`${outputDir}/${filename}`);
|
|
84
|
+
response.data.pipe(fileStream);
|
|
85
|
+
|
|
86
|
+
await new Promise((resolve, reject) => {
|
|
87
|
+
fileStream.on('finish', resolve);
|
|
88
|
+
fileStream.on('error', reject);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
listCSS.push(filename);
|
|
92
|
+
}
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.error(
|
|
95
|
+
'\n⚠️ Unable to download resource from CDN. Please handle this file manually!',
|
|
96
|
+
href
|
|
97
|
+
);
|
|
98
|
+
console.error(error.message);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const metas = doc.getElementsByTagName('meta');
|
|
103
|
+
metas.forEach((meta) => {
|
|
104
|
+
headInlines.push(meta.outerHTML);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
if (rootElement && rootElement !== '#app') {
|
|
108
|
+
let html = `<${rootElement} />`;
|
|
109
|
+
if (rootElement.startsWith('#')) {
|
|
110
|
+
html = `<div id="${rootElement.substring(1)}" />`;
|
|
111
|
+
}
|
|
112
|
+
if (rootElement.startsWith('.')) {
|
|
113
|
+
html = `<div class="${rootElement.substring(1)}" />`;
|
|
114
|
+
}
|
|
115
|
+
if (rootElement.startsWith('<')) {
|
|
116
|
+
html = rootElement;
|
|
117
|
+
}
|
|
118
|
+
bodyInlines.unshift(html);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
inlineJS += headInlines
|
|
122
|
+
.map(
|
|
123
|
+
(inline) =>
|
|
124
|
+
`document.head.innerHTML += \`${inline.replaceAll('`', '\\`')}\`;`
|
|
125
|
+
)
|
|
126
|
+
.join('\n');
|
|
127
|
+
inlineJS += '\n';
|
|
128
|
+
inlineJS += bodyInlines
|
|
129
|
+
.map(
|
|
130
|
+
(inline) =>
|
|
131
|
+
`document.body.innerHTML += \`${inline.replaceAll('`', '\\`')}\`;`
|
|
132
|
+
)
|
|
133
|
+
.join('\n');
|
|
134
|
+
listSyncJS.unshift('inline.js');
|
|
135
|
+
} catch (error) {
|
|
136
|
+
console.error(error.message);
|
|
137
|
+
}
|
|
138
|
+
return { listCSS, listSyncJS, listAsyncJS, inlineJS };
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
module.exports = {
|
|
142
|
+
generateListResourcesFromIndex,
|
|
143
|
+
};
|
package/sync/index.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const fse = require('../utils/fs-extra');
|
|
4
|
+
const config = require('../config');
|
|
5
|
+
const { generateListResourcesFromIndex } = require('./index-to-app-config');
|
|
6
|
+
|
|
7
|
+
const waitText = chalk.gray('(Please wait, it can take a while)');
|
|
8
|
+
const defaultLogger = {
|
|
9
|
+
statusStart() {},
|
|
10
|
+
statusDone() {},
|
|
11
|
+
statusText() {},
|
|
12
|
+
statusError() {},
|
|
13
|
+
text() {},
|
|
14
|
+
error() {},
|
|
15
|
+
showOnUI() {},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
module.exports = async (options = {}, logger = defaultLogger) => {
|
|
19
|
+
logger.statusStart(`Synchronization configuration ${waitText}`);
|
|
20
|
+
const cwd = process.cwd();
|
|
21
|
+
const { source, rootElement } = options;
|
|
22
|
+
const appConfigFilename = config.filename.appConfig;
|
|
23
|
+
const resolvePath = (dir) => {
|
|
24
|
+
return path.join(cwd, dir);
|
|
25
|
+
};
|
|
26
|
+
function errorExit(err) {
|
|
27
|
+
logger.error(err.stderr || err);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
let appConfigJson;
|
|
31
|
+
try {
|
|
32
|
+
appConfigJson = require(resolvePath(appConfigFilename));
|
|
33
|
+
} catch (err) {
|
|
34
|
+
errorExit(new Error(config.error_msg.app_config_not_found));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const html = fse.readFileSync(source).toString();
|
|
38
|
+
const outputDir = path.dirname(source);
|
|
39
|
+
const { listCSS, listSyncJS, listAsyncJS, inlineJS } =
|
|
40
|
+
await generateListResourcesFromIndex(html, { outputDir, rootElement });
|
|
41
|
+
Object.assign(appConfigJson, {
|
|
42
|
+
listCSS,
|
|
43
|
+
listSyncJS,
|
|
44
|
+
listAsyncJS,
|
|
45
|
+
});
|
|
46
|
+
if (inlineJS) {
|
|
47
|
+
fse.writeFileSync(resolvePath(`${outputDir}/inline.js`), inlineJS);
|
|
48
|
+
}
|
|
49
|
+
const output = JSON.stringify(appConfigJson, null, 2);
|
|
50
|
+
fse.writeFileSync(resolvePath(appConfigFilename), output);
|
|
51
|
+
logger.statusDone(
|
|
52
|
+
`${chalk.bold.green('Configuration synchronization completed!')} 💪`
|
|
53
|
+
);
|
|
54
|
+
logger.text({ listCSS, listSyncJS, listAsyncJS });
|
|
55
|
+
};
|