shoplazza-cli 1.0.6 → 1.0.7
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/bin/shoplazza +14 -3
- package/lib/app/commands/build.js +53 -74
- package/lib/app/commands/deploy.js +210 -39
- package/lib/app/commands/generate.js +50 -0
- package/lib/app/commands/publish.js +52 -0
- package/lib/app/extensions/index.js +13 -0
- package/lib/app/extensions/theme-app.js +103 -0
- package/lib/app/index.js +29 -17
- package/lib/app/inquirers/version.js +131 -0
- package/lib/checkout/api.js +34 -11
- package/lib/commands/login.js +1 -1
- package/lib/commands/logout.js +1 -1
- package/lib/openAPI/index.js +10 -21
- package/lib/utils.js +0 -52
- package/package.json +2 -2
- package/lib/app/api/api.js +0 -93
- package/lib/app/api/request.js +0 -72
- package/lib/app/commands/create.js +0 -100
- package/lib/app/commands/list.js +0 -31
- package/lib/app/commands/serve.js +0 -118
- package/lib/app/commands/versions.js +0 -44
- package/lib/app/template/basic-app/.ci/k8s.yaml +0 -4
- package/lib/app/template/basic-app/README.md +0 -84
- package/lib/app/template/basic-app/package.json +0 -15
- package/lib/app/template/basic-app/theme-app/assets/index.css +0 -4
- package/lib/app/template/basic-app/theme-app/blocks/index.liquid +0 -14
- package/lib/app/template/basic-app/theme-app/snippets/index.liquid +0 -8
- package/lib/app/template/basic-app/theme-app.config.json +0 -4
- package/lib/app/template/embed-app/.ci/k8s.yaml +0 -4
- package/lib/app/template/embed-app/README.md +0 -84
- package/lib/app/template/embed-app/package.json +0 -15
- package/lib/app/template/embed-app/theme-app/assets/index.css +0 -4
- package/lib/app/template/embed-app/theme-app/blocks/index.liquid +0 -15
- package/lib/app/template/embed-app/theme-app/locales/ar-SA.json +0 -3
- package/lib/app/template/embed-app/theme-app/locales/de-DE.json +0 -3
- package/lib/app/template/embed-app/theme-app/locales/en-US.json +0 -3
- package/lib/app/template/embed-app/theme-app/locales/es-ES.json +0 -3
- package/lib/app/template/embed-app/theme-app/locales/fr-FR.json +0 -3
- package/lib/app/template/embed-app/theme-app/locales/id-ID.json +0 -3
- package/lib/app/template/embed-app/theme-app/locales/it-IT.json +0 -3
- package/lib/app/template/embed-app/theme-app/locales/ja-JP.json +0 -3
- package/lib/app/template/embed-app/theme-app/locales/ko-KR.json +0 -3
- package/lib/app/template/embed-app/theme-app/locales/nl-NL.json +0 -3
- package/lib/app/template/embed-app/theme-app/locales/pl-PL.json +0 -3
- package/lib/app/template/embed-app/theme-app/locales/pt-PT.json +0 -3
- package/lib/app/template/embed-app/theme-app/locales/ru-RU.json +0 -3
- package/lib/app/template/embed-app/theme-app/locales/th-TH.json +0 -3
- package/lib/app/template/embed-app/theme-app/locales/zh-CN.json +0 -3
- package/lib/app/template/embed-app/theme-app/locales/zh-TW.json +0 -3
- package/lib/app/template/embed-app/theme-app/snippets/index.liquid +0 -8
- package/lib/app/template/embed-app/theme-app.config.json +0 -4
- package/lib/app/utils/config.js +0 -29
- package/lib/app/utils/index.js +0 -220
- package/lib/oss.js +0 -102
- /package/lib/{common → app}/constants.js +0 -0
- /package/lib/{common → app}/db/partner.js +0 -0
- /package/lib/{common → app}/inquirers/choose-app.js +0 -0
- /package/lib/{common → app}/inquirers/choose-partner.js +0 -0
- /package/lib/{common → app}/log.js +0 -0
- /package/lib/{common → app}/login.js +0 -0
- /package/lib/{common → app}/logout.js +0 -0
package/bin/shoplazza
CHANGED
|
@@ -10,7 +10,8 @@ const report = require('../lib/report');
|
|
|
10
10
|
require('../lib/tracing');
|
|
11
11
|
|
|
12
12
|
const { makeCheckoutCommand } = require('../lib/checkout');
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
const { generateExtension, deployExtension, publishExtension, buildExtension, retry } = require('../lib/app');
|
|
14
15
|
|
|
15
16
|
Sentry.init({
|
|
16
17
|
dsn: 'https://89964605acaf4db8839f2d5237396d6c@sentry.shoplazza.com/730',
|
|
@@ -112,11 +113,21 @@ theme
|
|
|
112
113
|
.option('-t, --theme <theme>', 'The ID of the theme that you want to delete.')
|
|
113
114
|
.action(require('../lib/commands/theme/delete'));
|
|
114
115
|
|
|
116
|
+
const app = program.command('app').description('Shoplazza app extensions cli');
|
|
117
|
+
|
|
118
|
+
app.command('generate').command('extension').description('Generate your extension').action(generateExtension);
|
|
119
|
+
app.command('deploy').command('extension').description('Deploy your extension to cdn').action(deployExtension);
|
|
120
|
+
app.command('publish').command('extension').description('Publish your extension').action(publishExtension);
|
|
121
|
+
app.command('build').description('Build your extension').action(buildExtension);
|
|
122
|
+
app
|
|
123
|
+
.command('retry')
|
|
124
|
+
.description('Retry to do some tasks.')
|
|
125
|
+
.option('-p, --partner', 'Retry get and choose your partner list.')
|
|
126
|
+
.option('-a, --app', 'Retry get and choose your app list.')
|
|
127
|
+
.action(retry);
|
|
115
128
|
|
|
116
129
|
// checkout cli
|
|
117
130
|
makeCheckoutCommand(program);
|
|
118
|
-
// theme app cli
|
|
119
|
-
initThemeAppCommand(program);
|
|
120
131
|
|
|
121
132
|
program.parse(process.argv);
|
|
122
133
|
!program.args.length && program.help();
|
|
@@ -1,87 +1,66 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
|
-
const
|
|
2
|
+
const ora = require('ora');
|
|
3
|
+
const fs = require('fs-extra');
|
|
3
4
|
const path = require('path');
|
|
4
|
-
const { getThemeAppConfig, compareVersions } = require('../utils');
|
|
5
|
-
const { getThemeAppVersionList, toCreateThemeAppVersion } = require('../api/api');
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
await
|
|
6
|
+
const { zipTheme } = require('../../utils');
|
|
7
|
+
const { line, done } = require('../log');
|
|
8
|
+
const { buildThemeAssets } = require('../extensions/theme-app');
|
|
9
|
+
|
|
10
|
+
const isFileExist = (path) => {
|
|
11
|
+
return fs.existsSync(path);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const clearManifest = async () => {
|
|
15
|
+
try {
|
|
16
|
+
if (isFileExist('./assets-manifest.json') && isFileExist('./assets')) {
|
|
17
|
+
const mainfest = JSON.parse(fs.readFileSync('./assets-manifest.json', { encoding: 'utf-8' }));
|
|
18
|
+
await Promise.all(
|
|
19
|
+
Object.values(mainfest).map((path) => {
|
|
20
|
+
if (isFileExist(path)) {
|
|
21
|
+
return fs.unlink(path);
|
|
22
|
+
}
|
|
23
|
+
return Promise.resolve(true);
|
|
24
|
+
})
|
|
25
|
+
);
|
|
26
|
+
await fs.unlink('./assets-manifest.json');
|
|
28
27
|
}
|
|
28
|
+
return true;
|
|
29
|
+
} catch (e) {
|
|
30
|
+
console.log(e);
|
|
29
31
|
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* 交互式命令行
|
|
34
|
-
*/
|
|
35
|
-
async function usePrompt() {
|
|
36
|
-
const versionList = await getThemeAppVersionList();
|
|
37
|
-
const latestVersion = versionList[versionList.length - 1];
|
|
32
|
+
};
|
|
38
33
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
chalk.white(`(${latestVersion.description})`) +
|
|
43
|
-
chalk.gray(` [Released on: ${latestVersion.date}]`)
|
|
44
|
-
);
|
|
34
|
+
const getZipName = () => {
|
|
35
|
+
return path.basename(process.cwd());
|
|
36
|
+
};
|
|
45
37
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
validate: (newVersion) => {
|
|
52
|
-
if (!/^[0-9]+\.[0-9]+\.[0-9]+$/.test(newVersion)) {
|
|
53
|
-
return chalk.red('❌ Version must follow the format X.Y.Z (e.g., 1.0.0).');
|
|
54
|
-
}
|
|
55
|
-
if (compareVersions(newVersion, latestVersion.version) !== 1) {
|
|
56
|
-
return chalk.red('❌ Version must be greater than the latest version.');
|
|
57
|
-
}
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
type: 'input',
|
|
63
|
-
name: 'description',
|
|
64
|
-
message: 'Enter the description for this version:',
|
|
65
|
-
validate: (description) => {
|
|
66
|
-
if (!description.trim()) {
|
|
67
|
-
return chalk.red('❌ Description cannot be empty.');
|
|
68
|
-
}
|
|
69
|
-
return true;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
]);
|
|
73
|
-
}
|
|
38
|
+
const generateZip = async (name) => {
|
|
39
|
+
const zipPath = `${process.cwd()}/${name}.zip`;
|
|
40
|
+
isFileExist(zipPath) && (await fs.unlink(zipPath));
|
|
41
|
+
zipTheme(process.cwd(), name);
|
|
42
|
+
};
|
|
74
43
|
|
|
75
|
-
async
|
|
44
|
+
const zipApp = async () => {
|
|
45
|
+
const spinner = ora(chalk.cyan('Building your app and generate zip package ...')).start();
|
|
76
46
|
try {
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
47
|
+
const zipName = getZipName();
|
|
48
|
+
await generateZip(zipName);
|
|
49
|
+
spinner.succeed(chalk.cyan(`Success to build your app and generate zip package: ${chalk.green(`${zipName}.zip`)}`));
|
|
50
|
+
return true;
|
|
51
|
+
} catch (e) {
|
|
52
|
+
spinner.fail(e.message);
|
|
82
53
|
}
|
|
83
|
-
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const build = async () => {
|
|
57
|
+
line();
|
|
58
|
+
(await clearManifest()) && (await buildThemeAssets('./assets')) && (await zipApp());
|
|
59
|
+
done();
|
|
60
|
+
line();
|
|
61
|
+
};
|
|
84
62
|
|
|
85
63
|
module.exports = {
|
|
86
|
-
build
|
|
64
|
+
build,
|
|
65
|
+
getZipName
|
|
87
66
|
};
|
|
@@ -1,47 +1,218 @@
|
|
|
1
|
-
const
|
|
2
|
-
const chalk = require('chalk');
|
|
1
|
+
const axios = require('axios');
|
|
3
2
|
const ora = require('ora');
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
message: 'Select a version to deploy:',
|
|
28
|
-
choices
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const fs = require('fs-extra');
|
|
5
|
+
const SparkMD5 = require('spark-md5');
|
|
6
|
+
const FormData = require('form-data');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
const { PARNTER_URL } = require('../constants');
|
|
10
|
+
const { getValue, PARTNER_KEYS, getApp, set } = require('../db/partner');
|
|
11
|
+
const { getZipName } = require('./build');
|
|
12
|
+
const { inputVersion } = require('../inquirers/version');
|
|
13
|
+
const { line, done } = require('../log');
|
|
14
|
+
|
|
15
|
+
const getZipPath = () => {
|
|
16
|
+
const spinner = ora(chalk.cyan('Finding your built zip ...')).start();
|
|
17
|
+
try {
|
|
18
|
+
const zipName = getZipName();
|
|
19
|
+
const filename = fs.readdirSync(process.cwd()).find((name) => {
|
|
20
|
+
const extname = path.extname(name).replace('.', '');
|
|
21
|
+
return extname === 'zip' && name.startsWith(zipName);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
if (!filename) {
|
|
25
|
+
throw new Error('not zip');
|
|
29
26
|
}
|
|
30
|
-
]);
|
|
31
|
-
}
|
|
32
27
|
|
|
33
|
-
|
|
28
|
+
const fileInfo = fs.statSync(`${process.cwd()}/${filename}`);
|
|
29
|
+
|
|
30
|
+
spinner.succeed(
|
|
31
|
+
chalk.cyan(
|
|
32
|
+
`Success to find your zip: ${chalk.green(`${filename} ${(fileInfo.size / (1024 * 1024)).toFixed(2)}M`)}`
|
|
33
|
+
)
|
|
34
|
+
);
|
|
35
|
+
return path.resolve(process.cwd(), filename);
|
|
36
|
+
} catch (e) {
|
|
37
|
+
spinner.fail(chalk.red('Failed to find your zip, be sure you have built app in root dir!'));
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const getBufferAndMd5 = async (filePath) => {
|
|
42
|
+
const spinner = ora(chalk.cyan('Begin to read zip and generate md5 code ...')).start();
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
return await new Promise((resolve, reject) => {
|
|
46
|
+
const spark = new SparkMD5.ArrayBuffer();
|
|
47
|
+
let buffers = [];
|
|
48
|
+
|
|
49
|
+
const rs = fs.createReadStream(filePath, { autoClose: true });
|
|
50
|
+
rs.on('data', (data) => {
|
|
51
|
+
buffers.push(data);
|
|
52
|
+
spark.append(data);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
rs.on('end', () => {
|
|
56
|
+
const md5 = spark.end();
|
|
57
|
+
const completedBuffer = Buffer.concat(buffers);
|
|
58
|
+
spinner.succeed(chalk.cyan('Success to analyse zip'));
|
|
59
|
+
resolve([completedBuffer, md5 + '.zip']);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
rs.on('error', (err) => {
|
|
63
|
+
reject(err);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
} catch (e) {
|
|
67
|
+
spinner.fail(chalk.red('Failed to analyse zip, please try again!'));
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const getSign = async () => {
|
|
72
|
+
const spinner = ora(chalk.cyan('Waiting get file sign ...')).start();
|
|
73
|
+
|
|
34
74
|
try {
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
await
|
|
41
|
-
|
|
42
|
-
|
|
75
|
+
const app = getApp();
|
|
76
|
+
const partnerId = getValue(PARTNER_KEYS.PARTNER_ID);
|
|
77
|
+
const sessionId = getValue(PARTNER_KEYS.SESSION_ID);
|
|
78
|
+
|
|
79
|
+
const url = `${PARNTER_URL}/api/partner/apps/${app.uid}/theme_extensions/file/signv2`;
|
|
80
|
+
const res = await axios.get(url, {
|
|
81
|
+
headers: {
|
|
82
|
+
Cookie: `awesomev2=${sessionId}`,
|
|
83
|
+
'x-shoplazza-partner-id': partnerId
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
spinner.succeed(chalk.cyan('Success to get file sign'));
|
|
87
|
+
return res.data;
|
|
88
|
+
} catch (e) {
|
|
89
|
+
spinner.fail(chalk.red(e.message || e));
|
|
43
90
|
}
|
|
44
|
-
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const deployOss = async () => {
|
|
94
|
+
const path = getZipPath();
|
|
95
|
+
if (path) {
|
|
96
|
+
const [buffer, md5] = await getBufferAndMd5(path);
|
|
97
|
+
const signData = await getSign();
|
|
98
|
+
if (!signData) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const spinner = ora(chalk.cyan('Deploying your zip to cdn ...')).start();
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
const formData = new FormData();
|
|
106
|
+
formData.append('policy', signData.policy);
|
|
107
|
+
formData.append('OSSAccessKeyId', signData.access_id);
|
|
108
|
+
formData.append('success_action_status', 200);
|
|
109
|
+
formData.append('signature', signData.sign);
|
|
110
|
+
formData.append('x-oss-forbid-overwrite', 'true');
|
|
111
|
+
formData.append('key', md5);
|
|
112
|
+
formData.append('file', buffer);
|
|
113
|
+
|
|
114
|
+
const url = `https:${signData.write_host}/`;
|
|
115
|
+
const res = await axios.post(url, formData, {
|
|
116
|
+
global: true,
|
|
117
|
+
maxContentLength: 100000000,
|
|
118
|
+
maxBodyLength: 1000000000
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
if (res.status !== 200) {
|
|
122
|
+
throw new Error(`${res.status} ${resstatusText}`);
|
|
123
|
+
}
|
|
124
|
+
spinner.succeed();
|
|
125
|
+
return md5;
|
|
126
|
+
} catch (e) {
|
|
127
|
+
// 409 repeat filename
|
|
128
|
+
if (e?.response?.status === 409) {
|
|
129
|
+
spinner.succeed();
|
|
130
|
+
return md5;
|
|
131
|
+
}
|
|
132
|
+
spinner.fail();
|
|
133
|
+
console.log(chalk.red(e.message || e));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const deployPartner = async () => {
|
|
139
|
+
const md5 = await deployOss();
|
|
140
|
+
if (!md5) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const spinner = ora(chalk.cyan('Deploying your zip to PARTNER ...')).start();
|
|
145
|
+
try {
|
|
146
|
+
const app = getApp();
|
|
147
|
+
if (!app) {
|
|
148
|
+
spinner.fail(chalk.red('Please choose your partner first!'));
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const partnerId = getValue(PARTNER_KEYS.PARTNER_ID);
|
|
153
|
+
const url = `${PARNTER_URL}/api/partner/apps/${app.uid}/theme_extensions`;
|
|
154
|
+
const res = await axios.put(
|
|
155
|
+
url,
|
|
156
|
+
{
|
|
157
|
+
title: getZipName(),
|
|
158
|
+
name: getZipName(),
|
|
159
|
+
file_name: md5
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
headers: {
|
|
163
|
+
cookie: `awesomev2=${getValue(PARTNER_KEYS.SESSION_ID)};`,
|
|
164
|
+
'x-shoplazza-partner-id': partnerId
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
set({ [PARTNER_KEYS.EXTENSION_ID]: res.data.extension_id });
|
|
170
|
+
spinner.succeed();
|
|
171
|
+
return true;
|
|
172
|
+
} catch (e) {
|
|
173
|
+
spinner.fail();
|
|
174
|
+
console.log(e.message || e);
|
|
175
|
+
console.log(chalk.red(JSON.stringify(e.response.data)));
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const createVersion = async (version) => {
|
|
180
|
+
const spinner = ora(chalk.cyan('Creating your version task ...')).start();
|
|
181
|
+
|
|
182
|
+
try {
|
|
183
|
+
const app = getApp();
|
|
184
|
+
const extensionId = getValue(PARTNER_KEYS.EXTENSION_ID);
|
|
185
|
+
const partnerId = getValue(PARTNER_KEYS.PARTNER_ID);
|
|
186
|
+
|
|
187
|
+
const url = `${PARNTER_URL}/api/partner/apps/${app.uid}/theme_extensions/${extensionId}/version_tasks`;
|
|
188
|
+
await axios.post(
|
|
189
|
+
url,
|
|
190
|
+
{
|
|
191
|
+
version
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
headers: {
|
|
195
|
+
cookie: `awesomev2=${getValue(PARTNER_KEYS.SESSION_ID)};`,
|
|
196
|
+
'x-shoplazza-partner-id': partnerId
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
);
|
|
200
|
+
spinner.succeed();
|
|
201
|
+
return true;
|
|
202
|
+
} catch (e) {
|
|
203
|
+
spinner.fail();
|
|
204
|
+
console.log(chalk.red(e.message || e));
|
|
205
|
+
console.log(chalk.red(JSON.stringify(e.response?.data)));
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const deploy = async () => {
|
|
210
|
+
line();
|
|
211
|
+
ora(chalk.cyan('Deploy Begin')).succeed();
|
|
212
|
+
let version;
|
|
213
|
+
(await deployPartner()) && (version = await inputVersion()) && (await createVersion(version)) && done();
|
|
214
|
+
line();
|
|
215
|
+
};
|
|
45
216
|
|
|
46
217
|
module.exports = {
|
|
47
218
|
deploy
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const inquirer = require('inquirer');
|
|
2
|
+
const { set, PARTNER_KEYS } = require('../db/partner');
|
|
3
|
+
const { themeAppHandler, checkoutUIHandler } = require('../extensions');
|
|
4
|
+
const { line } = require('../log');
|
|
5
|
+
|
|
6
|
+
const EXTENSION_TYPES = {
|
|
7
|
+
CHECKOUT_UI: 'checkout_ui',
|
|
8
|
+
THEME_APP: 'theme_app'
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const generate = async () => {
|
|
12
|
+
line();
|
|
13
|
+
const answer = await inquirer.prompt([
|
|
14
|
+
{
|
|
15
|
+
type: 'list',
|
|
16
|
+
name: 'extensionType',
|
|
17
|
+
message: 'Choose your extension type ↓',
|
|
18
|
+
default: EXTENSION_TYPES.THEME_APP,
|
|
19
|
+
prefix: '*',
|
|
20
|
+
choices: [
|
|
21
|
+
{
|
|
22
|
+
name: 'Theme App Extension',
|
|
23
|
+
value: EXTENSION_TYPES.THEME_APP
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
type: 'input',
|
|
29
|
+
name: 'extensionName',
|
|
30
|
+
message: 'Input your extesion name: ',
|
|
31
|
+
default: 'my-extension',
|
|
32
|
+
prefix: '*'
|
|
33
|
+
}
|
|
34
|
+
]);
|
|
35
|
+
line();
|
|
36
|
+
|
|
37
|
+
set({ [PARTNER_KEYS.EXTENSION_TYPE]: answer.extensionType });
|
|
38
|
+
|
|
39
|
+
if (answer.extensionType === EXTENSION_TYPES.THEME_APP) {
|
|
40
|
+
await themeAppHandler(answer.extensionName);
|
|
41
|
+
} else if (answer.extensionType === EXTENSION_TYPES.CHECKOUT_UI) {
|
|
42
|
+
await checkoutUIHandler(answer.extensionName);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
line();
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
module.exports = {
|
|
49
|
+
generate
|
|
50
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const { default: axios } = require('axios');
|
|
2
|
+
const { selectVersion } = require('../inquirers/version');
|
|
3
|
+
const { PARNTER_URL } = require('../constants');
|
|
4
|
+
const { get, getValue, PARTNER_KEYS } = require('../db/partner');
|
|
5
|
+
const ora = require('ora');
|
|
6
|
+
const chalk = require('chalk');
|
|
7
|
+
const { getZipName } = require('./build');
|
|
8
|
+
const { done, line } = require('../log');
|
|
9
|
+
|
|
10
|
+
const publishVersion = async ({ version, appId, versionId, extensionId }) => {
|
|
11
|
+
const spinner = ora(chalk.cyan('Waiting publish ...'));
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const partnerId = getValue(PARTNER_KEYS.PARTNER_ID);
|
|
15
|
+
if (!partnerId) {
|
|
16
|
+
spinner.fail(chalk.red('Please choose a partner first!'));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const url = `${PARNTER_URL}/api/partner/apps/${appId}/theme_extensions/${extensionId}/publications`;
|
|
21
|
+
await axios.post(
|
|
22
|
+
url,
|
|
23
|
+
{
|
|
24
|
+
name: getZipName(),
|
|
25
|
+
version_id: versionId,
|
|
26
|
+
type: 'enable'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
headers: {
|
|
30
|
+
cookie: `awesomev2=${getValue(PARTNER_KEYS.SESSION_ID)};`,
|
|
31
|
+
'x-shoplazza-partner-id': partnerId
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
spinner.succeed();
|
|
37
|
+
return true;
|
|
38
|
+
} catch (e) {
|
|
39
|
+
spinner.fail(e.message || e);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const publish = async () => {
|
|
44
|
+
const versionData = await selectVersion();
|
|
45
|
+
await publishVersion(versionData);
|
|
46
|
+
done();
|
|
47
|
+
line();
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
module.exports = {
|
|
51
|
+
publish
|
|
52
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const { generateThemeDirectory } = require('./theme-app');
|
|
2
|
+
const { done } = require('../log');
|
|
3
|
+
|
|
4
|
+
const themeAppHandler = async (dirname = './') => {
|
|
5
|
+
(await generateThemeDirectory(dirname)) && done();
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const checkoutUIHandler = async () => {};
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
themeAppHandler,
|
|
12
|
+
checkoutUIHandler
|
|
13
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const ora = require('ora');
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const glob = require('glob');
|
|
5
|
+
const repo = require('download-git-repo');
|
|
6
|
+
const CleanCSS = require('clean-css');
|
|
7
|
+
const UglifyJS = require('uglify-js');
|
|
8
|
+
|
|
9
|
+
const crypto = require('crypto');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const { line } = require('../log');
|
|
12
|
+
|
|
13
|
+
const rev = (input) => crypto.createHash('md5').update(input).digest('hex').slice(0, 8);
|
|
14
|
+
const cleanCSS = new CleanCSS({
|
|
15
|
+
advanced: false,
|
|
16
|
+
aggressiveMerging: false
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const generateThemeDirectory = async (dirname = './') => {
|
|
20
|
+
const spinner = ora(chalk.cyan(`Waiting generate your theme app project...`)).start();
|
|
21
|
+
try {
|
|
22
|
+
await new Promise((resolve, reject) => {
|
|
23
|
+
repo('Shoplazza/theme-extension-template', dirname, {}, (err) => {
|
|
24
|
+
if (err) {
|
|
25
|
+
reject(JSON.stringify(err));
|
|
26
|
+
} else {
|
|
27
|
+
resolve(true);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
spinner.succeed(chalk.cyan(`Generate app successfully`));
|
|
33
|
+
return true;
|
|
34
|
+
} catch (e) {
|
|
35
|
+
spinner.fail();
|
|
36
|
+
console.log(chalk.red(e));
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const buildThemeAssets = async (outputDir = './dist', pathPrefix = '.') => {
|
|
41
|
+
line();
|
|
42
|
+
ora(chalk.cyan(`Prepare Build assets ...`)).succeed();
|
|
43
|
+
|
|
44
|
+
const manifest = {};
|
|
45
|
+
|
|
46
|
+
// build assets css
|
|
47
|
+
const spinner = ora(chalk.cyan(`Build assets ...`)).start();
|
|
48
|
+
try {
|
|
49
|
+
const cssPathnames = glob.sync('./assets/*.css');
|
|
50
|
+
const jsPathnames = glob.sync('./assets/*.js');
|
|
51
|
+
|
|
52
|
+
const pathnames = [...cssPathnames, ...jsPathnames];
|
|
53
|
+
for (const pathname of pathnames) {
|
|
54
|
+
const filename = path.basename(pathname);
|
|
55
|
+
const extname = path.extname(pathname);
|
|
56
|
+
const fileContent = fs.readFileSync(pathname, 'utf8');
|
|
57
|
+
const hash = rev(fileContent);
|
|
58
|
+
|
|
59
|
+
let minified = '';
|
|
60
|
+
let filenameWithHash = '';
|
|
61
|
+
if (extname.includes('css')) {
|
|
62
|
+
minified = cleanCSS.minify(fileContent);
|
|
63
|
+
if (minified.errors.length) {
|
|
64
|
+
spinner.fail(minified.errors);
|
|
65
|
+
process.exit(-1);
|
|
66
|
+
}
|
|
67
|
+
filenameWithHash = `${filename.split('.')[0]}-${hash}.css`;
|
|
68
|
+
const assetsPath = `${outputDir}/${filenameWithHash}`;
|
|
69
|
+
fs.ensureFileSync(assetsPath);
|
|
70
|
+
fs.writeFileSync(assetsPath, minified.styles);
|
|
71
|
+
} else if (extname.includes('js')) {
|
|
72
|
+
minified = UglifyJS.minify(fileContent);
|
|
73
|
+
if (minified.error) {
|
|
74
|
+
log.error(minified.error);
|
|
75
|
+
process.exit(-1);
|
|
76
|
+
}
|
|
77
|
+
filenameWithHash = `${filename.split('.')[0]}-${hash}.js`;
|
|
78
|
+
const assetsPath = `${outputDir}/${filenameWithHash}`;
|
|
79
|
+
fs.ensureFileSync(assetsPath);
|
|
80
|
+
fs.writeFileSync(assetsPath, minified.code);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
manifest[filename] = pathPrefix + '/assets/' + filenameWithHash;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
fs.writeFileSync(`./assets-manifest.json`, JSON.stringify(manifest));
|
|
87
|
+
spinner.succeed(chalk.cyan(`Build assets done`));
|
|
88
|
+
return true;
|
|
89
|
+
} catch (e) {
|
|
90
|
+
spinner.fail(chalk.red(e.message));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// build assets js
|
|
94
|
+
const jsSpinner = ora(chalk.cyan(`Build js ...`)).start();
|
|
95
|
+
try {
|
|
96
|
+
jsSpinner.succeed(chalk.cyan(`Build js done`));
|
|
97
|
+
} catch (e) {}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
module.exports = {
|
|
101
|
+
generateThemeDirectory,
|
|
102
|
+
buildThemeAssets
|
|
103
|
+
};
|