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/lib/app/index.js
CHANGED
|
@@ -1,25 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
const { checkAndLogin } = require('./login');
|
|
2
|
+
const { build } = require('./commands/build');
|
|
3
|
+
const { deploy } = require('./commands/deploy');
|
|
4
|
+
const { generate } = require('./commands/generate');
|
|
5
|
+
const { publish } = require('./commands/publish');
|
|
6
|
+
const { choosePartner } = require('./inquirers/choose-partner');
|
|
7
|
+
const { chooseApp } = require('./inquirers/choose-app');
|
|
3
8
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
.command('serve')
|
|
8
|
-
.description('Start a local development server for the theme app')
|
|
9
|
-
.action(require('./commands/serve').serve);
|
|
9
|
+
const generateExtension = async () => {
|
|
10
|
+
(await checkAndLogin()) && (await generate());
|
|
11
|
+
};
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
const deployExtension = async () => {
|
|
14
|
+
(await checkAndLogin()) && (await deploy());
|
|
15
|
+
};
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
.action(require('./commands/versions').versions);
|
|
17
|
+
const publishExtension = async () => {
|
|
18
|
+
(await checkAndLogin()) && (await publish());
|
|
19
|
+
};
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
const retry = async (options) => {
|
|
22
|
+
if (options.partner) {
|
|
23
|
+
(await checkAndLogin()) && (await choosePartner()) && (await chooseApp());
|
|
24
|
+
}
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
if (options.app) {
|
|
27
|
+
(await checkAndLogin()) && (await chooseApp());
|
|
28
|
+
}
|
|
29
|
+
};
|
|
22
30
|
|
|
23
31
|
module.exports = {
|
|
24
|
-
|
|
32
|
+
generateExtension,
|
|
33
|
+
deployExtension,
|
|
34
|
+
publishExtension,
|
|
35
|
+
buildExtension: build,
|
|
36
|
+
retry
|
|
25
37
|
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const inquirer = require('inquirer');
|
|
4
|
+
|
|
5
|
+
const { PARNTER_URL } = require('../constants');
|
|
6
|
+
const { getApp, getValue, PARTNER_KEYS } = require('../db/partner');
|
|
7
|
+
const { line } = require('../log');
|
|
8
|
+
|
|
9
|
+
const requestLastVersion = async () => {
|
|
10
|
+
try {
|
|
11
|
+
const app = getApp();
|
|
12
|
+
if (!app) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const extensionId = getValue(PARTNER_KEYS.EXTENSION_ID);
|
|
16
|
+
const partnerId = getValue(PARTNER_KEYS.PARTNER_ID);
|
|
17
|
+
|
|
18
|
+
const url = `${PARNTER_URL}/api/partner/apps/${app.uid}/theme_extensions/${extensionId}/last_version`;
|
|
19
|
+
const res = await axios.get(url, {
|
|
20
|
+
headers: {
|
|
21
|
+
cookie: `awesomev2=${getValue(PARTNER_KEYS.SESSION_ID)};`,
|
|
22
|
+
'x-shoplazza-partner-id': partnerId
|
|
23
|
+
},
|
|
24
|
+
validateStatus(status) {
|
|
25
|
+
if (status === 404) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
return status >= 200 && status < 299;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (res.data.errors) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return res.data.version;
|
|
37
|
+
} catch (e) {
|
|
38
|
+
console.log(chalk.red(e.message || e));
|
|
39
|
+
console.log(chalk.red(JSON.stringify(e.response?.data)));
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const requestVersionsData = async (params = {}) => {
|
|
44
|
+
try {
|
|
45
|
+
const app = getApp();
|
|
46
|
+
if (!app) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const extensionId = getValue(PARTNER_KEYS.EXTENSION_ID);
|
|
50
|
+
const partnerId = getValue(PARTNER_KEYS.PARTNER_ID);
|
|
51
|
+
|
|
52
|
+
const url = `${PARNTER_URL}/api/partner/apps/${app.uid}/theme_extensions/${extensionId}/versions`;
|
|
53
|
+
const res = await axios.get(url, {
|
|
54
|
+
params,
|
|
55
|
+
headers: {
|
|
56
|
+
cookie: `awesomev2=${getValue(PARTNER_KEYS.SESSION_ID)};`,
|
|
57
|
+
'x-shoplazza-partner-id': partnerId
|
|
58
|
+
},
|
|
59
|
+
validateStatus(status) {
|
|
60
|
+
if (status === 404) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return status >= 200 && status < 299;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (res.data.errors) {
|
|
68
|
+
throw new Error(JSON.stringify(res.data.errors));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return res.data.data;
|
|
72
|
+
} catch (e) {
|
|
73
|
+
console.log(chalk.red(e.message || e));
|
|
74
|
+
console.log(chalk.red(JSON.stringify(e.response?.data)));
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const inputVersion = async () => {
|
|
79
|
+
line();
|
|
80
|
+
const lastVersionData = await requestLastVersion({ limit: 1 });
|
|
81
|
+
const hint = lastVersionData ? chalk.gray(`(last version: ${lastVersionData.version})`) : '';
|
|
82
|
+
|
|
83
|
+
const answer = await inquirer.prompt([
|
|
84
|
+
{
|
|
85
|
+
type: 'input',
|
|
86
|
+
name: 'extensionVersion',
|
|
87
|
+
message: `${chalk.blue('Input your extension version')} ${hint}:`,
|
|
88
|
+
prefix: `${chalk.green('⭐️')}`
|
|
89
|
+
}
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
return answer['extensionVersion'];
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const selectVersion = async () => {
|
|
96
|
+
line();
|
|
97
|
+
|
|
98
|
+
const versionDataList = await requestVersionsData();
|
|
99
|
+
if (!versionDataList) {
|
|
100
|
+
console.log(chalk.red('Please deploy a version first!'));
|
|
101
|
+
line();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const answer = await inquirer.prompt([
|
|
105
|
+
{
|
|
106
|
+
type: 'list',
|
|
107
|
+
name: 'versionData',
|
|
108
|
+
message: `${chalk.blue('Choose a version to publish:')}`,
|
|
109
|
+
default: versionDataList[0].version,
|
|
110
|
+
prefix: `${chalk.blue('🐱')}`,
|
|
111
|
+
choices: versionDataList.map((v) => {
|
|
112
|
+
return {
|
|
113
|
+
name: `${v.version} ${v.published ? chalk.green('published') : ''}`,
|
|
114
|
+
value: {
|
|
115
|
+
version: v.version,
|
|
116
|
+
appId: v.app_id,
|
|
117
|
+
versionId: v.version_id,
|
|
118
|
+
extensionId: v.extension_id
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
]);
|
|
124
|
+
|
|
125
|
+
return answer['versionData'];
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
module.exports = {
|
|
129
|
+
inputVersion,
|
|
130
|
+
selectVersion
|
|
131
|
+
};
|
package/lib/checkout/api.js
CHANGED
|
@@ -8,7 +8,6 @@ const { isDebug } = require('./console');
|
|
|
8
8
|
const { getProjectConfig } = require('./util');
|
|
9
9
|
const chalk = require('chalk');
|
|
10
10
|
const { consoleWarn } = require('./console');
|
|
11
|
-
const { useOss } = require('../oss');
|
|
12
11
|
|
|
13
12
|
const FILE_SIGN_URL = '/checkout_extensions/file/sign';
|
|
14
13
|
const CREATE_URL = '/checkout_extensions/create';
|
|
@@ -20,7 +19,6 @@ const UNDEPLOY_URL = '/checkout_extensions/undeploy';
|
|
|
20
19
|
const PREVIEW_URL = '/checkout_extensions/preview';
|
|
21
20
|
|
|
22
21
|
let configJson = undefined;
|
|
23
|
-
let uploadOss = null;
|
|
24
22
|
|
|
25
23
|
const request = new Axios.create();
|
|
26
24
|
|
|
@@ -66,6 +64,9 @@ request.interceptors.response.use(
|
|
|
66
64
|
if (isDebug()) {
|
|
67
65
|
console.log(`\n<== error ${error.response.status}: ${error.response.config.url}`);
|
|
68
66
|
}
|
|
67
|
+
if (!error.response) {
|
|
68
|
+
throw chalk.red('Network error, please check your connection.');
|
|
69
|
+
}
|
|
69
70
|
if (error.response?.status == 403) {
|
|
70
71
|
return Promise.reject(new Error('Token permission failure'));
|
|
71
72
|
}
|
|
@@ -73,20 +74,42 @@ request.interceptors.response.use(
|
|
|
73
74
|
}
|
|
74
75
|
);
|
|
75
76
|
|
|
77
|
+
async function upload(path, name) {
|
|
78
|
+
const form = new FormData();
|
|
79
|
+
const url = await request(`${FILE_SIGN_URL}?key=${name}`)
|
|
80
|
+
.then((data) => {
|
|
81
|
+
return data.data;
|
|
82
|
+
})
|
|
83
|
+
.then(async (data) => {
|
|
84
|
+
const url = data.write_host;
|
|
85
|
+
form.append('policy', data.policy);
|
|
86
|
+
form.append('OSSAccessKeyId', data.access_id);
|
|
87
|
+
form.append('success_action_status', 200);
|
|
88
|
+
form.append('signature', data.sign);
|
|
89
|
+
form.append('x-oss-forbid-overwrite', 'true');
|
|
90
|
+
form.append('key', name);
|
|
91
|
+
form.append('file', fs.createReadStream(path));
|
|
92
|
+
await request.post(`https:${url}`, form, { headers: form.getHeaders() }).catch((error) => {
|
|
93
|
+
if (error.response?.data.includes('<Code>FileAlreadyExists</Code>')) {
|
|
94
|
+
consoleWarn('The current file already exists, not need to upload.');
|
|
95
|
+
return;
|
|
96
|
+
} else {
|
|
97
|
+
return Promise.reject(error);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
return `${data.read_host}${data.read_host.endsWith('/') ? '' : '/'}${name}`;
|
|
101
|
+
});
|
|
102
|
+
loading('succeed upload').succeed();
|
|
103
|
+
return url;
|
|
104
|
+
}
|
|
105
|
+
|
|
76
106
|
async function uploadFile(dirPath, file) {
|
|
77
|
-
|
|
78
|
-
uploadOss = useOss(
|
|
79
|
-
configJson.token,
|
|
80
|
-
new URL(configJson.store).hostname,
|
|
81
|
-
`✗ No store found. Please check your "extension.config.js" file.`
|
|
82
|
-
).uploadOss;
|
|
83
|
-
}
|
|
84
|
-
return uploadOss(`${dirPath}/${file}`);
|
|
107
|
+
return upload(`${dirPath}/${file}`, `chick-extension/${file}`);
|
|
85
108
|
}
|
|
86
109
|
async function uploadDir(dirPath, files) {
|
|
87
110
|
return Promise.all(
|
|
88
111
|
files.map((file) => {
|
|
89
|
-
return
|
|
112
|
+
return upload(`${dirPath}/${file}`, `chick-extension/${file}`);
|
|
90
113
|
})
|
|
91
114
|
);
|
|
92
115
|
}
|
package/lib/commands/login.js
CHANGED
|
@@ -8,7 +8,7 @@ const log = require('../log');
|
|
|
8
8
|
const { getShopDetail } = require('../openAPI/api');
|
|
9
9
|
const getCode = require('../auth/getCode');
|
|
10
10
|
const { postAccessToken, getUserInfo, postExchangeToken, postStoreToken } = require('../auth');
|
|
11
|
-
const { loginIntoPartner } = require('../
|
|
11
|
+
const { loginIntoPartner } = require('../app/login');
|
|
12
12
|
|
|
13
13
|
let spinner;
|
|
14
14
|
|
package/lib/commands/logout.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const Sentry = require('@sentry/node');
|
|
2
2
|
const chalk = require('chalk');
|
|
3
3
|
const { empty: emptyUser } = require('../db/user');
|
|
4
|
-
const { logoutPartner } = require('../
|
|
4
|
+
const { logoutPartner } = require('../app/logout');
|
|
5
5
|
const log = require('../log');
|
|
6
6
|
|
|
7
7
|
const logoutStore = () => {
|
package/lib/openAPI/index.js
CHANGED
|
@@ -12,23 +12,17 @@ const openAPI = axios.create({
|
|
|
12
12
|
headers: { 'Access-Token': get('exchange_token') }
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
-
openAPI.interceptors.request.use(
|
|
16
|
-
(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
chalk.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
process.exit(-1);
|
|
24
|
-
}
|
|
25
|
-
return config;
|
|
26
|
-
},
|
|
27
|
-
(error) => {
|
|
28
|
-
console.error(chalk.red(`[REQUEST ERROR] ${error.message}`));
|
|
29
|
-
return Promise.reject(error);
|
|
15
|
+
openAPI.interceptors.request.use((config) => {
|
|
16
|
+
if (!get('store_domain')) {
|
|
17
|
+
log.error(
|
|
18
|
+
chalk.red(
|
|
19
|
+
`\n✗ No store found. Please run ${chalk.cyan('shoplazza login --store STORE')} to login to a specific store`
|
|
20
|
+
)
|
|
21
|
+
);
|
|
22
|
+
process.exit(-1);
|
|
30
23
|
}
|
|
31
|
-
|
|
24
|
+
return config;
|
|
25
|
+
});
|
|
32
26
|
|
|
33
27
|
openAPI.interceptors.response.use(
|
|
34
28
|
function (response) {
|
|
@@ -45,11 +39,6 @@ openAPI.interceptors.response.use(
|
|
|
45
39
|
return openAPI(error.config);
|
|
46
40
|
});
|
|
47
41
|
}
|
|
48
|
-
error.response && console.error(
|
|
49
|
-
chalk.red(
|
|
50
|
-
`[RESPONSE ERROR] ${error.response.status} ${error.response.config.baseURL}${error.response.config.url}`
|
|
51
|
-
)
|
|
52
|
-
);
|
|
53
42
|
return Promise.reject(error);
|
|
54
43
|
}
|
|
55
44
|
);
|
package/lib/utils.js
CHANGED
|
@@ -2,8 +2,6 @@ const path = require('path');
|
|
|
2
2
|
const fs = require('fs-extra');
|
|
3
3
|
const AdmZip = require('adm-zip');
|
|
4
4
|
const chalk = require('chalk');
|
|
5
|
-
const chokidar = require('chokidar');
|
|
6
|
-
const fsExtra = require('fs-extra');
|
|
7
5
|
|
|
8
6
|
const {
|
|
9
7
|
SSO_AUTH_URL,
|
|
@@ -113,53 +111,3 @@ const SSO_AUTH_URL_MAP = {
|
|
|
113
111
|
exports.getSSOAuthUrl = (store) => {
|
|
114
112
|
return SSO_AUTH_URL_MAP[getEnv(store)];
|
|
115
113
|
};
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* 监听文件夹变化
|
|
119
|
-
* @param {string} workspace - 需要监听的文件夹路径
|
|
120
|
-
* @param {Object} options - 配置项
|
|
121
|
-
* @param {Function} [options.onAdd] - 文件添加时的回调函数,接收文件路径作为参数
|
|
122
|
-
* @param {Function} [options.onChange] - 文件更改时的回调函数,接收文件路径作为参数
|
|
123
|
-
* @param {Function} [options.onDelete] - 文件删除时的回调函数,接收文件路径作为参数
|
|
124
|
-
* @param {any} [options.xxx] - 其他chokidar.watch配置项
|
|
125
|
-
* @returns {Function} - 取消监听的函数
|
|
126
|
-
*/
|
|
127
|
-
exports.initWatcher = (workspace, options = {}) => {
|
|
128
|
-
if (!fsExtra.pathExistsSync(workspace)) {
|
|
129
|
-
console.error(chalk.red(`[ERROR] "${workspace}" does not exist.`));
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
const defaultOptions = {
|
|
133
|
-
persistent: true,
|
|
134
|
-
ignoreInitial: true
|
|
135
|
-
};
|
|
136
|
-
const { onAdd = () => {}, onChange = () => {}, onDelete = () => {}, ...restOptions } = options;
|
|
137
|
-
const watcherOptions = { ...defaultOptions, ...restOptions };
|
|
138
|
-
const watcher = chokidar.watch(workspace, watcherOptions);
|
|
139
|
-
|
|
140
|
-
watcher.on('add', (filePath) => {
|
|
141
|
-
console.log(chalk.cyan(`[ADD] ${filePath}`));
|
|
142
|
-
onAdd(filePath);
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
watcher.on('change', (filePath) => {
|
|
146
|
-
console.log(chalk.yellow(`[CHANGE] ${filePath}`));
|
|
147
|
-
onChange(filePath);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
watcher.on('unlink', (filePath) => {
|
|
151
|
-
console.log(chalk.red(`[DELETE] ${filePath}`));
|
|
152
|
-
onDelete(filePath);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
watcher.on('error', (error) => {
|
|
156
|
-
console.error(chalk.red(`[ERROR] ${error}`));
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
const stopWatcher = () => {
|
|
160
|
-
console.log(chalk.green('[INFO] Stopping watcher...'));
|
|
161
|
-
watcher.close();
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
return stopWatcher;
|
|
165
|
-
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shoplazza-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "bin/shoplazza",
|
|
6
6
|
"engines": {
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"@sentry/tracing": "^6.19.7",
|
|
27
27
|
"adm-zip": "^0.5.9",
|
|
28
28
|
"ali-oss": "^6.17.1",
|
|
29
|
+
"archiver": "^5.3.1",
|
|
29
30
|
"axios": "^1.6.8",
|
|
30
31
|
"better-sqlite3": "^11.5.0",
|
|
31
32
|
"chalk": "^4.1.2",
|
|
@@ -63,7 +64,6 @@
|
|
|
63
64
|
"semver": "~7.3.5",
|
|
64
65
|
"serve-static": "^1.15.0",
|
|
65
66
|
"spark-md5": "^3.0.2",
|
|
66
|
-
"table": "^6.9.0",
|
|
67
67
|
"uglify-js": "^3.17.4",
|
|
68
68
|
"update-notifier": "^5.1.0",
|
|
69
69
|
"vite": "~4.3.1",
|
package/lib/app/api/api.js
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
const { get, post, put, del, patch } = require('./request');
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 获取主题列表
|
|
5
|
-
*/
|
|
6
|
-
async function getThemeList() {
|
|
7
|
-
return get('/themes');
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* 获取店铺私有主题插件列表
|
|
12
|
-
* @returns
|
|
13
|
-
*/
|
|
14
|
-
async function getThemeAppList() {
|
|
15
|
-
return [
|
|
16
|
-
{
|
|
17
|
-
name: '主题插件1',
|
|
18
|
-
version: '1.0.0',
|
|
19
|
-
description: '主题插件1的描述'
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
name: '主题插件2',
|
|
23
|
-
version: '2.0.0',
|
|
24
|
-
description: '主题插件2的描述'
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
name: '主题插件3',
|
|
28
|
-
version: '3.0.0',
|
|
29
|
-
description: '主题插件3的描述'
|
|
30
|
-
}
|
|
31
|
-
];
|
|
32
|
-
// return get('/theme-extensions');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* 创建主题插件
|
|
37
|
-
*/
|
|
38
|
-
async function toCreateThemeApp(data) {
|
|
39
|
-
return put('/theme-extensions', data);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* 上传主题插件
|
|
44
|
-
*/
|
|
45
|
-
async function toUploadThemeApp(data) {
|
|
46
|
-
return patch(`theme-extensions/${data.appId}/dev-doctree`, data);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* 获取任务状态
|
|
51
|
-
*/
|
|
52
|
-
async function getTaskStatus(data) {
|
|
53
|
-
return get(`/theme-extensions/version-tasks/${data.taskId}`);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* 获取主题插件版本列表
|
|
58
|
-
*/
|
|
59
|
-
async function getThemeAppVersionList(data) {
|
|
60
|
-
return [
|
|
61
|
-
{ version: '1.0.0', date: '2023-01-01', description: 'Initial release' },
|
|
62
|
-
{ version: '1.1.0', date: '2023-02-01', description: 'Added new features and bug fixes' },
|
|
63
|
-
{ version: '1.2.0', date: '2023-03-01', description: 'Fixed bugs and improved performance' },
|
|
64
|
-
{ version: '1.3.0', date: '2023-04-01', description: 'Optimized performance and added new features' },
|
|
65
|
-
{ version: '1.4.0', date: '2023-05-01', description: 'Fixed bugs and improved user experience' }
|
|
66
|
-
];
|
|
67
|
-
// return get(`/theme-extensions/:${data.appId}/versions`);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* 创建主题插件版本
|
|
72
|
-
*/
|
|
73
|
-
async function toCreateThemeAppVersion(data) {
|
|
74
|
-
return post(`/theme-extensions/version-tasks`, data);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* 部署主题插件
|
|
79
|
-
*/
|
|
80
|
-
async function toDeployThemeApp(data) {
|
|
81
|
-
return post(`theme-extensions/publications`, data);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
module.exports = {
|
|
85
|
-
getThemeList,
|
|
86
|
-
getThemeAppList,
|
|
87
|
-
toCreateThemeApp,
|
|
88
|
-
toUploadThemeApp,
|
|
89
|
-
getThemeAppVersionList,
|
|
90
|
-
toCreateThemeAppVersion,
|
|
91
|
-
toDeployThemeApp,
|
|
92
|
-
getTaskStatus
|
|
93
|
-
};
|
package/lib/app/api/request.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
const instance = require('../../openAPI/index');
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 基础的 API 请求方法
|
|
5
|
-
* @param {string} method 请求方法 (GET, POST, PUT, DELETE)
|
|
6
|
-
* @param {string} url 请求的路径
|
|
7
|
-
* @param {Object} data 请求的数据(适用于 POST、PUT)
|
|
8
|
-
* @param {Object} params 请求的 URL 参数(适用于 GET)
|
|
9
|
-
*/
|
|
10
|
-
async function request({ method, url, data, params }) {
|
|
11
|
-
const response = await instance({
|
|
12
|
-
method,
|
|
13
|
-
url,
|
|
14
|
-
data,
|
|
15
|
-
params
|
|
16
|
-
});
|
|
17
|
-
return response; // 返回请求结果
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* GET 请求封装
|
|
22
|
-
* @param {string} url 请求的路径
|
|
23
|
-
* @param {Object} params 请求的 URL 参数
|
|
24
|
-
*/
|
|
25
|
-
async function get(url, params) {
|
|
26
|
-
return request({ method: 'get', url, params });
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* POST 请求封装
|
|
31
|
-
* @param {string} url 请求的路径
|
|
32
|
-
* @param {Object} data 请求的数据
|
|
33
|
-
*/
|
|
34
|
-
async function post(url, data) {
|
|
35
|
-
return request({ method: 'post', url, data });
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* PUT 请求封装
|
|
40
|
-
* @param {string} url 请求的路径
|
|
41
|
-
* @param {Object} data 请求的数据
|
|
42
|
-
*/
|
|
43
|
-
async function put(url, data) {
|
|
44
|
-
return request({ method: 'put', url, data });
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* DELETE 请求封装
|
|
49
|
-
* @param {string} url 请求的路径
|
|
50
|
-
* @param {Object} params 请求的 URL 参数
|
|
51
|
-
*/
|
|
52
|
-
async function del(url, params) {
|
|
53
|
-
return request({ method: 'delete', url, params });
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* PATCH 请求封装
|
|
58
|
-
* @param {string} url 请求的路径
|
|
59
|
-
* @param {Object} data 请求的数据
|
|
60
|
-
*/
|
|
61
|
-
async function patch(url, data) {
|
|
62
|
-
return request({ method: 'patch', url, data });
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
module.exports = {
|
|
67
|
-
get,
|
|
68
|
-
post,
|
|
69
|
-
put,
|
|
70
|
-
del,
|
|
71
|
-
patch
|
|
72
|
-
};
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
const inquirer = require('inquirer');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const fsExtra = require('fs-extra');
|
|
4
|
-
const chalk = require('chalk');
|
|
5
|
-
const { WORKSPACE_PATH, THEME_APP_TYPE } = require('../utils/config');
|
|
6
|
-
const { replacePlaceholders, renameFile } = require('../utils');
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* 交互式命令行
|
|
10
|
-
*/
|
|
11
|
-
async function usePrompt() {
|
|
12
|
-
return await inquirer.prompt([
|
|
13
|
-
{
|
|
14
|
-
type: 'list',
|
|
15
|
-
name: 'themeAppType',
|
|
16
|
-
message: 'Select theme app type:',
|
|
17
|
-
choices: [THEME_APP_TYPE.BASIC_APP.description, THEME_APP_TYPE.EMBEDS_APP.description],
|
|
18
|
-
prefix: '*'
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
type: 'input',
|
|
22
|
-
name: 'projectName',
|
|
23
|
-
message: 'Please enter the theme app project name:',
|
|
24
|
-
prefix: '*',
|
|
25
|
-
validate: (projectName) => {
|
|
26
|
-
if (!projectName.trim()) {
|
|
27
|
-
return 'Project name cannot be empty';
|
|
28
|
-
}
|
|
29
|
-
return true;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
]);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* 初始化项目
|
|
37
|
-
*/
|
|
38
|
-
async function initProj(projectPath, projectName) {
|
|
39
|
-
// 替换占位符 key文件相对路径 value替换的内容
|
|
40
|
-
const replacementConfig = {
|
|
41
|
-
'package.json': { projectName },
|
|
42
|
-
'theme-app/blocks/index.liquid': { projectName },
|
|
43
|
-
'theme-app.config.json': { projectName }
|
|
44
|
-
};
|
|
45
|
-
for (const [filePath, replacements] of Object.entries(replacementConfig)) {
|
|
46
|
-
const fullPath = path.resolve(projectPath, filePath);
|
|
47
|
-
await replacePlaceholders(fullPath, replacements);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// 重命名文件
|
|
51
|
-
const filesToRename = ['assets/index.css', 'blocks/index.liquid', 'snippets/index.liquid'];
|
|
52
|
-
for (const file of filesToRename) {
|
|
53
|
-
const filePath = path.resolve(projectPath, 'theme-app', file);
|
|
54
|
-
await renameFile(filePath, `${projectName}${file.includes('snippets') ? '_snippet' : ''}`);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* 控制台提示信息
|
|
60
|
-
*/
|
|
61
|
-
function consoleTips(projectName) {
|
|
62
|
-
console.log(chalk.green(`Theme app project "${projectName}" has been successfully created.`));
|
|
63
|
-
console.log(chalk.bold(`To get started:\n`));
|
|
64
|
-
console.log(` ${chalk.cyan(`cd ${projectName}`)}`);
|
|
65
|
-
console.log(` ${chalk.cyan(`npm start`)}\n`);
|
|
66
|
-
console.log(chalk.greenBright(`Happy coding! 🎉🎉🎉`));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* 创建项目
|
|
71
|
-
*/
|
|
72
|
-
async function _create(themeAppDescription, projectName) {
|
|
73
|
-
const projectPath = path.resolve(WORKSPACE_PATH, projectName);
|
|
74
|
-
const projectExists = await fsExtra.pathExists(projectPath);
|
|
75
|
-
|
|
76
|
-
if (projectExists) {
|
|
77
|
-
throw new Error(`Project directory "${projectName}" already exists.`);
|
|
78
|
-
}
|
|
79
|
-
await fsExtra.ensureDir(projectPath);
|
|
80
|
-
const templatePath =
|
|
81
|
-
THEME_APP_TYPE.BASIC_APP.description === themeAppDescription
|
|
82
|
-
? THEME_APP_TYPE.BASIC_APP.templatePath
|
|
83
|
-
: THEME_APP_TYPE.EMBEDS_APP.templatePath;
|
|
84
|
-
await fsExtra.copy(templatePath, projectPath);
|
|
85
|
-
await initProj(projectPath, projectName);
|
|
86
|
-
consoleTips(projectName);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
async function create() {
|
|
90
|
-
try {
|
|
91
|
-
const { themeAppType, projectName } = await usePrompt();
|
|
92
|
-
await _create(themeAppType, projectName);
|
|
93
|
-
} catch (error) {
|
|
94
|
-
console.error(chalk.red(`[ERROR IN CREATE] ${error.message}`));
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
module.exports = {
|
|
99
|
-
create
|
|
100
|
-
};
|