shoplazza-cli 1.0.13 → 1.1.1
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/README.md +12 -12
- package/bin/shoplazza +5 -3
- package/lib/app/api/cli.js +225 -0
- package/lib/app/api/openapi.js +121 -0
- package/lib/app/api/partnerOpenapi.js +104 -0
- package/lib/app/bin/index.js +20 -0
- package/lib/app/bin/javy/javy-arm-linux-v5.0.1 +0 -0
- package/lib/app/bin/javy/javy-arm-macos-v5.0.1 +0 -0
- package/lib/app/bin/javy/javy-x86_64-linux-v5.0.1 +0 -0
- package/lib/app/bin/javy/javy-x86_64-macos-v5.0.1 +0 -0
- package/lib/app/bin/javy/javy-x86_64-windows-v5.0.1 +0 -0
- package/lib/app/commands/config/actions/link.js +189 -0
- package/lib/app/commands/config/actions/use.js +40 -0
- package/lib/app/commands/config/index.js +25 -0
- package/lib/app/commands/config/link.js +11 -0
- package/lib/app/commands/config/use.js +11 -0
- package/lib/app/commands/deploy/actions/deploy.js +196 -0
- package/lib/app/commands/deploy/index.js +11 -0
- package/lib/app/commands/dev/actions/dev.js +206 -0
- package/lib/app/commands/dev/index.js +11 -0
- package/lib/app/commands/generate/actions/extension.js +97 -0
- package/lib/app/commands/generate/actions/generateCheckout.js +58 -0
- package/lib/app/commands/generate/actions/generateFunction.js +56 -0
- package/lib/app/commands/generate/actions/generateTheme.js +128 -0
- package/lib/app/commands/generate/extension.js +11 -0
- package/lib/app/commands/generate/index.js +22 -0
- package/lib/app/commands/index.js +82 -0
- package/lib/app/commands/info/actions/info.js +168 -0
- package/lib/app/commands/info/index.js +11 -0
- package/lib/app/commands/init/actions/init.js +176 -0
- package/lib/app/commands/init/index.js +14 -0
- package/lib/app/commands/versions/actions/list.js +210 -0
- package/lib/app/commands/versions/index.js +22 -0
- package/lib/app/commands/versions/list.js +14 -0
- package/lib/app/constant/code.js +7 -0
- package/lib/app/constant/color.js +18 -0
- package/lib/app/constant/extension.js +16 -0
- package/lib/app/constant/host.js +23 -0
- package/lib/app/constant/sso.js +7 -0
- package/lib/app/index.js +4 -25
- package/lib/app/services/auth/config.js +33 -0
- package/lib/app/services/auth/index.js +9 -0
- package/lib/app/services/auth/oauth-server.js +70 -0
- package/lib/app/services/auth/partner-token.js +45 -0
- package/lib/app/services/auth/sso-token.js +69 -0
- package/lib/app/services/auth/store-token.js +100 -0
- package/lib/app/services/auth/url-builder.js +23 -0
- package/lib/app/services/config/index.js +41 -0
- package/lib/app/services/devServer/app.js +76 -0
- package/lib/app/services/devServer/index.js +103 -0
- package/lib/app/services/devServer/middleware/hmacValidatorMiddleWare.js +20 -0
- package/lib/app/services/devServer/middleware/index.js +5 -0
- package/lib/app/services/devServer/tunnel/index.js +43 -0
- package/lib/app/services/devServer/tunnel/providers/cloudflare.js +364 -0
- package/lib/app/services/devServer/tunnel/providers/ngrok.js +70 -0
- package/lib/app/services/devServer/utils/index.js +5 -0
- package/lib/app/services/devServer/utils/secureCompare.js +5 -0
- package/lib/app/services/devServer/views/app.ejs +133 -0
- package/lib/app/services/extension-build/buildCheckout.js +47 -0
- package/lib/app/services/extension-build/buildFunction.js +57 -0
- package/lib/app/services/extension-build/buildTheme.js +100 -0
- package/lib/app/services/extension-build/index.js +23 -0
- package/lib/app/services/extension-build/plugins/vite-plugin-add-extension-id.js +26 -0
- package/lib/app/services/extension-build/plugins/vite-plugin-transform-extension-html.js +207 -0
- package/lib/app/services/extension-diff/index.js +132 -0
- package/lib/app/services/extension-upsert/index.js +21 -0
- package/lib/app/services/extension-upsert/upsertCheckout.js +44 -0
- package/lib/app/services/extension-upsert/upsertFunction.js +52 -0
- package/lib/app/services/extension-upsert/upsertTheme.js +113 -0
- package/lib/app/services/oss/index.js +45 -0
- package/lib/app/services/partner/index.js +52 -0
- package/lib/app/store/base-store.js +37 -0
- package/lib/app/store/config-store.js +55 -0
- package/lib/app/store/config.js +21 -0
- package/lib/app/store/index.js +14 -0
- package/lib/app/store/install-store.js +41 -0
- package/lib/app/store/sso-store.js +55 -0
- package/lib/app/utils/asyncPool.js +42 -0
- package/lib/app/utils/debug/index.js +16 -0
- package/lib/app/utils/env.js +24 -0
- package/lib/app/utils/error.js +20 -0
- package/lib/app/utils/git.js +20 -0
- package/lib/app/utils/json.js +27 -0
- package/lib/app/utils/path.js +33 -0
- package/lib/app/utils/platform.js +37 -0
- package/lib/app/utils/request/cli.js +72 -0
- package/lib/app/utils/request/debug.js +13 -0
- package/lib/app/utils/request/openapi.js +67 -0
- package/lib/app/utils/request/partnerOpenapi.js +47 -0
- package/lib/app/utils/toml.js +56 -0
- package/lib/app/utils/views/message.js +68 -0
- package/lib/app/utils/views/select.js +36 -0
- package/lib/app/utils/withTempDir.js +55 -0
- package/lib/checkout/api.js +2 -0
- package/lib/function/bin/javy/javy-arm-macos-v5.0.1 +0 -0
- package/lib/oss.js +5 -2
- package/lib/theme-extension/index.js +29 -0
- package/lib/utils/config.js +1 -1
- package/package.json +12 -1
- package/examples/checkout-extension/README.md +0 -19
- package/examples/checkout-extension/extension.config.js +0 -4
- package/examples/checkout-extension/extensions/add-shipping-desc/extension.json +0 -10
- package/examples/checkout-extension/extensions/add-shipping-desc/src/index.js +0 -7
- package/examples/checkout-extension/extensions/ext-1/extension.json +0 -10
- package/examples/checkout-extension/extensions/ext-1/src/content.html +0 -3
- package/examples/checkout-extension/extensions/ext-1/src/index.html +0 -5
- package/examples/checkout-extension/extensions/ext-1/src/index.js +0 -11
- package/examples/checkout-extension/extensions/ext-1/src/script.html +0 -3
- package/examples/checkout-extension/extensions/ext-1/src/style.html +0 -3
- package/examples/checkout-extension/extensions/product-list/extension.json +0 -10
- package/examples/checkout-extension/extensions/product-list/src/index.js +0 -5
- package/examples/checkout-extension/extensions/rewrite-navigate/extension.json +0 -10
- package/examples/checkout-extension/extensions/rewrite-navigate/src/content.html +0 -38
- package/examples/checkout-extension/extensions/rewrite-navigate/src/index.html +0 -5
- package/examples/checkout-extension/extensions/rewrite-navigate/src/index.js +0 -12
- package/examples/checkout-extension/extensions/rewrite-navigate/src/script.html +0 -26
- package/examples/checkout-extension/extensions/rewrite-navigate/src/style.html +0 -23
- package/examples/checkout-extension/package-lock.json +0 -121
- package/examples/checkout-extension/package.json +0 -17
- /package/lib/{app → theme-extension}/api/index.js +0 -0
- /package/lib/{app → theme-extension}/commands/build.js +0 -0
- /package/lib/{app → theme-extension}/commands/connect.js +0 -0
- /package/lib/{app → theme-extension}/commands/create.js +0 -0
- /package/lib/{app → theme-extension}/commands/deploy.js +0 -0
- /package/lib/{app → theme-extension}/commands/list.js +0 -0
- /package/lib/{app → theme-extension}/commands/release.js +0 -0
- /package/lib/{app → theme-extension}/commands/serve.js +0 -0
- /package/lib/{app → theme-extension}/commands/versions.js +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/README.md +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/extension.config.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/package.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/assets/index.css +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/assets-manifest.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/blocks/index.liquid +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/locales/ar-SA.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/locales/de-DE.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/locales/en-US.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/locales/es-ES.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/locales/fr-FR.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/locales/id-ID.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/locales/it-IT.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/locales/ja-JP.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/locales/ko-KR.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/locales/nl-NL.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/locales/pl-PL.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/locales/pt-PT.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/locales/ru-RU.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/locales/th-TH.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/locales/zh-CN.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/locales/zh-TW.json +0 -0
- /package/lib/{app → theme-extension}/template/basic-app/theme-app/snippets/index.liquid +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/README.md +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/extension.config.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/package.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/assets-manifest.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/blocks/index.liquid +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/locales/ar-SA.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/locales/de-DE.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/locales/en-US.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/locales/es-ES.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/locales/fr-FR.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/locales/id-ID.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/locales/it-IT.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/locales/ja-JP.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/locales/ko-KR.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/locales/nl-NL.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/locales/pl-PL.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/locales/pt-PT.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/locales/ru-RU.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/locales/th-TH.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/locales/zh-CN.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/locales/zh-TW.json +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/snippets/index.liquid +0 -0
- /package/lib/{app → theme-extension}/template/embed-app/theme-app/snippets/index_css.liquid +0 -0
- /package/lib/{app → theme-extension}/utils/config.js +0 -0
- /package/lib/{app → theme-extension}/utils/index.js +0 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const inquirer = require('inquirer');
|
|
5
|
+
|
|
6
|
+
const { createAppRequest, getAppListRequest, getAppConfigRequest } = require('../../../api/cli');
|
|
7
|
+
const { getPartner, promptCreateOrConnect } = require('../../../services/partner');
|
|
8
|
+
const { withErrorHandling } = require('../../../utils/error');
|
|
9
|
+
const { selectOne } = require('../../../utils/views/select');
|
|
10
|
+
const { getTomlConfigFiles, parseTomlFile, createTomlConfig } = require('../../../utils/toml');
|
|
11
|
+
const { slugify } = require('../../../utils/path');
|
|
12
|
+
const { successMessageRender } = require('../../../utils/views/message');
|
|
13
|
+
const { configStore } = require('../../../store');
|
|
14
|
+
|
|
15
|
+
// 处理 configFile 相关
|
|
16
|
+
async function handleConfigFile(projectDir) {
|
|
17
|
+
// 获取所有 TOML 配置文件
|
|
18
|
+
const tomlConfigFiles = getTomlConfigFiles(projectDir);
|
|
19
|
+
let configFile;
|
|
20
|
+
let isOverwrite = false;
|
|
21
|
+
if (tomlConfigFiles.length > 0) {
|
|
22
|
+
while (true) {
|
|
23
|
+
const { rawName } = await inquirer.prompt({
|
|
24
|
+
type: 'input',
|
|
25
|
+
name: 'rawName',
|
|
26
|
+
message: 'Configuration file name:',
|
|
27
|
+
validate: (input) => (input.trim() === '' ? "Configuration file can't be empty" : true)
|
|
28
|
+
});
|
|
29
|
+
configFile = `shoplazza.app.${slugify(rawName)}.toml`;
|
|
30
|
+
let isRename = false;
|
|
31
|
+
if (fs.existsSync(path.join(projectDir, configFile))) {
|
|
32
|
+
isRename = await selectOne(
|
|
33
|
+
[
|
|
34
|
+
{ name: `Yes, I'll choose a different name`, value: true },
|
|
35
|
+
{ name: `No, overwrite my existing configuration file`, value: false }
|
|
36
|
+
],
|
|
37
|
+
{
|
|
38
|
+
message: `Configuration file ${configFile} already exists. Do you want to choose a different configuration name?`,
|
|
39
|
+
autoPickSingle: false
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
isOverwrite = !isRename;
|
|
43
|
+
}
|
|
44
|
+
if (!isRename) {
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
configFile = 'shoplazza.app.toml';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return { configFile, isOverwrite };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 格式化 appList
|
|
56
|
+
function formatAppList(appList, projectDir) {
|
|
57
|
+
const configFiles = getTomlConfigFiles(projectDir);
|
|
58
|
+
const map = configFiles.reduce((acc, configFile) => {
|
|
59
|
+
const config = parseTomlFile(configFile);
|
|
60
|
+
acc[config.client_id] = configFile;
|
|
61
|
+
return acc;
|
|
62
|
+
}, {});
|
|
63
|
+
|
|
64
|
+
return appList.map((app) => {
|
|
65
|
+
return {
|
|
66
|
+
...app,
|
|
67
|
+
configFile: map[app.client_id] || ''
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 成功提示
|
|
73
|
+
function successTips({ configFile, appName }) {
|
|
74
|
+
successMessageRender(`${chalk.bold(`${configFile} is now linked to "${appName}" on Shoplazza`)}
|
|
75
|
+
|
|
76
|
+
Using ${configFile} as your default config.
|
|
77
|
+
|
|
78
|
+
Next steps
|
|
79
|
+
• Make updates to ${configFile} in your local project
|
|
80
|
+
• To update your config, run ${chalk.hex('#d079f8')('`shoplazza app deploy`')}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function linkAction(options) {
|
|
84
|
+
const { path: argPath = '.', clientId: argClientId } = options;
|
|
85
|
+
|
|
86
|
+
// 项目目录
|
|
87
|
+
const projectDir = path.resolve(argPath);
|
|
88
|
+
|
|
89
|
+
if (!fs.existsSync(projectDir)) {
|
|
90
|
+
throw new Error(`path not found: ${projectDir}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 选取 partner
|
|
94
|
+
const partner = await getPartner();
|
|
95
|
+
|
|
96
|
+
// 获取 app
|
|
97
|
+
const appListRes = await getAppListRequest(partner.id);
|
|
98
|
+
|
|
99
|
+
// 判断 创建 还是 链接
|
|
100
|
+
const isCreate = argClientId ? false : await promptCreateOrConnect(appListRes);
|
|
101
|
+
|
|
102
|
+
if (isCreate) {
|
|
103
|
+
// 创建
|
|
104
|
+
const appName = await inquirer
|
|
105
|
+
.prompt({
|
|
106
|
+
type: 'input',
|
|
107
|
+
name: 'app_name',
|
|
108
|
+
message: 'App name:',
|
|
109
|
+
validate: (input) => (input.trim() === '' ? "App name can't be empty" : true)
|
|
110
|
+
})
|
|
111
|
+
.then((r) => r.app_name);
|
|
112
|
+
|
|
113
|
+
// 规范化 appName
|
|
114
|
+
const normalizedAppName = slugify(appName);
|
|
115
|
+
|
|
116
|
+
const { configFile, isOverwrite } = await handleConfigFile(projectDir);
|
|
117
|
+
|
|
118
|
+
const { app } = await createAppRequest(partner.id, {
|
|
119
|
+
app_name: normalizedAppName
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
if (isOverwrite) {
|
|
123
|
+
fs.rmSync(path.join(projectDir, configFile));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
await createTomlConfig(path.join(projectDir, configFile), (config) => ({
|
|
127
|
+
...config,
|
|
128
|
+
client_id: app.client_id,
|
|
129
|
+
}));
|
|
130
|
+
|
|
131
|
+
// 缓存 app 相关信息
|
|
132
|
+
configStore.setProjectConfig(projectDir, {
|
|
133
|
+
clientId: app.client_id,
|
|
134
|
+
directory: projectDir,
|
|
135
|
+
configFile
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
successTips({ configFile, appName: app.name });
|
|
139
|
+
} else {
|
|
140
|
+
// 链接 app
|
|
141
|
+
|
|
142
|
+
// 处理 appList
|
|
143
|
+
const formattedAppList = formatAppList(appListRes.apps, projectDir);
|
|
144
|
+
// 连接已存在的 app
|
|
145
|
+
const clientId =
|
|
146
|
+
argClientId ||
|
|
147
|
+
(await selectOne(formattedAppList, {
|
|
148
|
+
autoPickSingle: false,
|
|
149
|
+
message: 'Which existing app is this for?',
|
|
150
|
+
formatChoice: (a) => ({ name: a.name + (a.configFile ? ` (${a.configFile}) ` : ''), value: a.client_id })
|
|
151
|
+
}));
|
|
152
|
+
|
|
153
|
+
let configFile;
|
|
154
|
+
let isOverwrite = false;
|
|
155
|
+
const currentApp = formattedAppList.find((a) => a.client_id === clientId);
|
|
156
|
+
if (currentApp.configFile) {
|
|
157
|
+
configFile = currentApp.configFile;
|
|
158
|
+
isOverwrite = true;
|
|
159
|
+
} else {
|
|
160
|
+
const { configFile: newConfigFile, isOverwrite: newIsOverwrite } = await handleConfigFile(projectDir);
|
|
161
|
+
configFile = newConfigFile;
|
|
162
|
+
isOverwrite = newIsOverwrite;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const { app } = await getAppConfigRequest(partner.id, clientId);
|
|
166
|
+
|
|
167
|
+
if (isOverwrite) {
|
|
168
|
+
fs.rmSync(path.join(projectDir, configFile));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
await createTomlConfig(path.join(projectDir, configFile), (config) => ({
|
|
172
|
+
...config,
|
|
173
|
+
client_id: app.client_id,
|
|
174
|
+
}));
|
|
175
|
+
|
|
176
|
+
// 缓存 app 相关信息
|
|
177
|
+
configStore.setProjectConfig(projectDir, {
|
|
178
|
+
clientId: app.client_id,
|
|
179
|
+
directory: projectDir,
|
|
180
|
+
configFile
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
successTips({ configFile, appName: app.name });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
module.exports = {
|
|
188
|
+
linkAction: withErrorHandling(linkAction)
|
|
189
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
|
|
3
|
+
const { getAppCompleteInfoRequest } = require('../../../api/cli');
|
|
4
|
+
const { configStore } = require('../../../store');
|
|
5
|
+
const { withErrorHandling } = require('../../../utils/error');
|
|
6
|
+
const { getTomlConfigFiles, parseTomlFile } = require('../../../utils/toml');
|
|
7
|
+
const { successMessageRender } = require('../../../utils/views/message');
|
|
8
|
+
const { selectOne } = require('../../../utils/views/select');
|
|
9
|
+
async function useAction(options) {
|
|
10
|
+
const { path: argPath = '.' } = options;
|
|
11
|
+
const projectDir = path.resolve(argPath);
|
|
12
|
+
|
|
13
|
+
const configFiles = getTomlConfigFiles(projectDir);
|
|
14
|
+
const selectedConfigFile = await selectOne(configFiles, {
|
|
15
|
+
message: 'Configuration file:',
|
|
16
|
+
formatChoice: (name) => ({
|
|
17
|
+
name,
|
|
18
|
+
value: name
|
|
19
|
+
})
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
if (!selectedConfigFile) {
|
|
23
|
+
throw new Error(`Couldn't find an app toml file at ${projectDir}, is this an app directory?`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const configInfo = await parseTomlFile(selectedConfigFile);
|
|
27
|
+
const { app } = await getAppCompleteInfoRequest(configInfo.client_id);
|
|
28
|
+
|
|
29
|
+
configStore.setProjectConfig(projectDir, {
|
|
30
|
+
configFile: selectedConfigFile,
|
|
31
|
+
clientId: app.client_id,
|
|
32
|
+
directory: projectDir
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
successMessageRender(`Using configuration file ${selectedConfigFile}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = {
|
|
39
|
+
useAction: withErrorHandling(useAction)
|
|
40
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const { Command } = require('commander');
|
|
2
|
+
const { useCommand } = require('./use');
|
|
3
|
+
const { linkCommand } = require('./link');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
|
|
6
|
+
const configCommand = new Command('config')
|
|
7
|
+
.description('Manage app configuration')
|
|
8
|
+
.addCommand(useCommand)
|
|
9
|
+
.addCommand(linkCommand);
|
|
10
|
+
|
|
11
|
+
configCommand.helpInformation = function () {
|
|
12
|
+
return `Manage app configuration.
|
|
13
|
+
|
|
14
|
+
${chalk.bold('USAGE')}
|
|
15
|
+
$ shoplazza app config COMMAND
|
|
16
|
+
|
|
17
|
+
${chalk.bold('COMMANDS')}
|
|
18
|
+
app config link Fetch your app configuration from the Partner Dashboard
|
|
19
|
+
app config use Activate an app configuration
|
|
20
|
+
`;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
module.exports = {
|
|
24
|
+
configCommand
|
|
25
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const { Command } = require('commander');
|
|
2
|
+
const { linkAction } = require('./actions/link');
|
|
3
|
+
|
|
4
|
+
const linkCommand = new Command('link')
|
|
5
|
+
.option('--path <path>', 'The path to your app directory')
|
|
6
|
+
.option('--client-id <client-id>', 'The client id of your app')
|
|
7
|
+
.action(linkAction);
|
|
8
|
+
|
|
9
|
+
module.exports = {
|
|
10
|
+
linkCommand
|
|
11
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const { Command } = require('commander');
|
|
2
|
+
const { useAction } = require('./actions/use');
|
|
3
|
+
|
|
4
|
+
const useCommand = new Command('use')
|
|
5
|
+
.option('--path <path>', 'The path to your app directory')
|
|
6
|
+
.description('Activate an app configuration')
|
|
7
|
+
.action(useAction);
|
|
8
|
+
|
|
9
|
+
module.exports = {
|
|
10
|
+
useCommand
|
|
11
|
+
};
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
const { withErrorHandling } = require('../../../utils/error');
|
|
2
|
+
const { getAppCompleteInfo } = require('../../../services/config');
|
|
3
|
+
const { parseTomlFile, modifyTomlFile } = require('../../../utils/toml');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const glob = require('glob');
|
|
6
|
+
const { getAppExtensionsRequest, generateVersionRequest, extensionDeploy } = require('../../../api/cli');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const { extensionDiff } = require('../../../services/extension-diff');
|
|
9
|
+
const { getPartnerAccessToken, getStoreAccessToken } = require('../../../services/auth');
|
|
10
|
+
const { upsertExtension } = require('../../../services/extension-upsert');
|
|
11
|
+
const ora = require('ora');
|
|
12
|
+
const { buildExtension } = require('../../../services/extension-build');
|
|
13
|
+
const { useOss } = require('../../../../oss');
|
|
14
|
+
const { successMessageRender, infoMessageRender } = require('../../../utils/views/message');
|
|
15
|
+
const chalk = require('chalk');
|
|
16
|
+
// 获取 localExtensions
|
|
17
|
+
function getLocalExtensions(projectDir = process.env.APP_PROJECT_DIR) {
|
|
18
|
+
const extensionsDir = path.join(projectDir, 'extensions');
|
|
19
|
+
const extensionFiles = glob.sync(path.join(extensionsDir, '**/*.toml'));
|
|
20
|
+
const result = extensionFiles.map((extensionFile) => {
|
|
21
|
+
const extensionInfo = parseTomlFile(extensionFile);
|
|
22
|
+
return {
|
|
23
|
+
extension_id: extensionInfo.id, // 扩展ID
|
|
24
|
+
extension_name: extensionInfo.name, // 扩展名称
|
|
25
|
+
extension_type: extensionInfo.type, // 扩展类型
|
|
26
|
+
extension_version: '', // 扩展版本
|
|
27
|
+
extension_version_id: '', // 扩展版本ID
|
|
28
|
+
resource_url: '', // 资源地址
|
|
29
|
+
configPath: extensionFile, // 扩展配置文件路径
|
|
30
|
+
distPath: '' // 打包后的资源路径
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 获取 remoteExtensions
|
|
37
|
+
async function getRemoteExtensions(appClientId, partnerId) {
|
|
38
|
+
const res = await getAppExtensionsRequest({ partner_id: partnerId, app_client_id: appClientId, is_dev: 1 });
|
|
39
|
+
|
|
40
|
+
return res.extensions.map((extension) => ({
|
|
41
|
+
extension_id: extension.extension_id,
|
|
42
|
+
extension_name: extension.extension_name,
|
|
43
|
+
extension_type: extension.extension_type,
|
|
44
|
+
resource_url: extension.resource_url,
|
|
45
|
+
extension_version: extension.extension_version,
|
|
46
|
+
extension_version_id: extension.extension_version_id
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 生成版本
|
|
51
|
+
async function generateNewVersion(partnerId, appClientId) {
|
|
52
|
+
const res = await generateVersionRequest({
|
|
53
|
+
partner_id: partnerId,
|
|
54
|
+
app_client_id: appClientId,
|
|
55
|
+
is_dev: true
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const { extensions, app_version } = res;
|
|
59
|
+
const extensionVersions = extensions.reduce((acc, { extension_id, extension_version }) => {
|
|
60
|
+
return {
|
|
61
|
+
...acc,
|
|
62
|
+
[extension_id]: extension_version
|
|
63
|
+
};
|
|
64
|
+
}, {});
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
newAppVersion: app_version,
|
|
68
|
+
newExtensionVersions: extensionVersions
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 成功提示
|
|
73
|
+
function successTips(appName, newAppVersion) {
|
|
74
|
+
successMessageRender(`New version ${appName}(${newAppVersion}) is deployed successfully`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// app 信息展示
|
|
78
|
+
function appInfoShow({ app, partner }) {
|
|
79
|
+
infoMessageRender(`${chalk.bold('Your app info:\n')}
|
|
80
|
+
• ${'Partner:'.padEnd(10)} ${partner.business_name}
|
|
81
|
+
• ${'App:'.padEnd(10)} ${app.name}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function deployAction(options) {
|
|
85
|
+
// 获取 app 信息
|
|
86
|
+
const { app, partner, user } = await getAppCompleteInfo();
|
|
87
|
+
|
|
88
|
+
appInfoShow({ app, partner });
|
|
89
|
+
|
|
90
|
+
const localExtensions = getLocalExtensions();
|
|
91
|
+
const remoteExtensions = await getRemoteExtensions(app.client_id, partner.id);
|
|
92
|
+
|
|
93
|
+
const { newAppVersion, newExtensionVersions } = await generateNewVersion(partner.id, app.client_id);
|
|
94
|
+
|
|
95
|
+
const appAccessToken = await getPartnerAccessToken(app.client_id, app.secret);
|
|
96
|
+
const {
|
|
97
|
+
addExtensions, // 需要创建新的 extension & version
|
|
98
|
+
updateExtensions, // 需要更新 version
|
|
99
|
+
deleteExtensions // 需要删除 extension 目前不支持删除,直接传回服务端
|
|
100
|
+
} = await extensionDiff(localExtensions, remoteExtensions);
|
|
101
|
+
|
|
102
|
+
// 更新 extension 版本
|
|
103
|
+
[...updateExtensions, ...deleteExtensions].forEach((extension) => {
|
|
104
|
+
extension.extension_version = newExtensionVersions[extension.extension_id];
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// 清空 app-deploy
|
|
108
|
+
fs.rmSync(path.join(process.env.APP_PROJECT_DIR, 'app-deploy'), { recursive: true, force: true });
|
|
109
|
+
fs.mkdirSync(path.join(process.env.APP_PROJECT_DIR, 'app-deploy'));
|
|
110
|
+
|
|
111
|
+
const buildExtensionResults = await Promise.all(
|
|
112
|
+
[...addExtensions, ...updateExtensions].map(async (extension) => {
|
|
113
|
+
const distPath = await buildExtension(extension);
|
|
114
|
+
extension.distPath = distPath;
|
|
115
|
+
return distPath;
|
|
116
|
+
})
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
// 🎯 获取动态的店铺认证信息
|
|
120
|
+
const { store_domain, access_token } = await getStoreAccessToken(app.client_id, partner.id);
|
|
121
|
+
|
|
122
|
+
// 上传资源到 OSS
|
|
123
|
+
await Promise.all(
|
|
124
|
+
[...addExtensions, ...updateExtensions].map(async (extension) => {
|
|
125
|
+
const { distPath } = extension;
|
|
126
|
+
// 🎯 使用 useOss 替换原来的上传逻辑
|
|
127
|
+
const { uploadOss } = useOss(access_token, store_domain, `✗ 未找到店铺信息。请检查app配置。`);
|
|
128
|
+
const resourceUrl = await uploadOss(distPath);
|
|
129
|
+
extension.resource_url = resourceUrl;
|
|
130
|
+
})
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
// 创建或更新 extension
|
|
135
|
+
const upsertExtensionResults = await Promise.all(
|
|
136
|
+
[...addExtensions, ...updateExtensions, ...deleteExtensions].map(async (extension) => {
|
|
137
|
+
const spinner = ora(`${extension.extension_name}(${extension.extension_version}) upserting...`).start();
|
|
138
|
+
try {
|
|
139
|
+
const res = await upsertExtension(extension, app.client_id, partner.id, appAccessToken);
|
|
140
|
+
extension.extension_id = res.extension_id;
|
|
141
|
+
extension.extension_version = res.extension_version;
|
|
142
|
+
extension.extension_version_id = res.extension_version_id;
|
|
143
|
+
spinner.succeed(`${extension.extension_name}(${extension.extension_version}) upsert success`);
|
|
144
|
+
return res;
|
|
145
|
+
} catch (error) {
|
|
146
|
+
spinner.fail(`${extension.extension_name}(${extension.extension_version}) upsert failed`);
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
// 更新本地配置文件信息
|
|
154
|
+
await Promise.all(
|
|
155
|
+
[...addExtensions, ...updateExtensions].map(async (extension) => {
|
|
156
|
+
try {
|
|
157
|
+
await modifyTomlFile(extension.configPath, (config) => {
|
|
158
|
+
config.id = extension.extension_id;
|
|
159
|
+
config.name = extension.extension_name;
|
|
160
|
+
config.type = extension.extension_type;
|
|
161
|
+
return config;
|
|
162
|
+
});
|
|
163
|
+
} catch (error) {
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
const completeExtensions = [...addExtensions, ...updateExtensions, ...deleteExtensions].map((extension) => ({
|
|
170
|
+
extension_id: extension.extension_id,
|
|
171
|
+
extension_name: extension.extension_name,
|
|
172
|
+
extension_type: extension.extension_type,
|
|
173
|
+
extension_version: extension.extension_version,
|
|
174
|
+
extension_version_id: extension.extension_version_id,
|
|
175
|
+
resource_url: extension.resource_url,
|
|
176
|
+
}));
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
const deployResponse = await extensionDeploy({
|
|
180
|
+
partner_id: partner.id,
|
|
181
|
+
app_client_id: app.client_id,
|
|
182
|
+
data: {
|
|
183
|
+
app: {
|
|
184
|
+
version: newAppVersion,
|
|
185
|
+
extensions: completeExtensions
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
successTips(app.name, newAppVersion);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
module.exports = {
|
|
195
|
+
deployAction: withErrorHandling(deployAction)
|
|
196
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const { Command } = require('commander');
|
|
2
|
+
const deployCommand = new Command('deploy');
|
|
3
|
+
const { deployAction } = require('./actions/deploy');
|
|
4
|
+
|
|
5
|
+
deployCommand.option('--path <path>', 'The path to your app directory');
|
|
6
|
+
|
|
7
|
+
deployCommand.action(deployAction);
|
|
8
|
+
|
|
9
|
+
module.exports = {
|
|
10
|
+
deployCommand
|
|
11
|
+
};
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
const { withErrorHandling } = require('../../../utils/error');
|
|
2
|
+
const { getAppCompleteInfo } = require('../../../services/config');
|
|
3
|
+
const { parseTomlFile, modifyTomlFile } = require('../../../utils/toml');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const glob = require('glob');
|
|
6
|
+
const { getAppExtensionsRequest, extensionDev, generateVersionRequest } = require('../../../api/cli');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const { extensionDiff } = require('../../../services/extension-diff');
|
|
9
|
+
const { getPartnerAccessToken, getStoreAccessToken } = require('../../../services/auth');
|
|
10
|
+
const { startDevServer } = require('../../../services/devServer');
|
|
11
|
+
const { upsertExtension } = require('../../../services/extension-upsert');
|
|
12
|
+
const { infoMessageRender } = require('../../../utils/views/message');
|
|
13
|
+
const ora = require('ora');
|
|
14
|
+
const { buildExtension } = require('../../../services/extension-build');
|
|
15
|
+
const chalk = require('chalk');
|
|
16
|
+
const { useOss } = require('../../../../oss');
|
|
17
|
+
// 获取 localExtensions
|
|
18
|
+
function getLocalExtensions(projectDir = process.env.APP_PROJECT_DIR) {
|
|
19
|
+
const extensionsDir = path.join(projectDir, 'extensions');
|
|
20
|
+
const extensionFiles = glob.sync(path.join(extensionsDir, '**/*.toml'));
|
|
21
|
+
const result = extensionFiles.map((extensionFile) => {
|
|
22
|
+
const extensionInfo = parseTomlFile(extensionFile);
|
|
23
|
+
return {
|
|
24
|
+
extension_id: extensionInfo.id, // 扩展ID
|
|
25
|
+
extension_name: extensionInfo.name, // 扩展名称
|
|
26
|
+
extension_type: extensionInfo.type, // 扩展类型
|
|
27
|
+
extension_version: '', // 扩展版本
|
|
28
|
+
extension_version_id: '', // 扩展版本ID
|
|
29
|
+
resource_url: '', // 资源地址
|
|
30
|
+
configPath: extensionFile, // 扩展配置文件路径
|
|
31
|
+
distPath: '' // 打包后的资源路径
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// 获取 remoteExtensions
|
|
38
|
+
async function getRemoteExtensions(appClientId, partnerId) {
|
|
39
|
+
const res = await getAppExtensionsRequest({ partner_id: partnerId, app_client_id: appClientId, is_dev: 1 });
|
|
40
|
+
return res.extensions.map((extension) => ({
|
|
41
|
+
extension_id: extension.extension_id,
|
|
42
|
+
extension_name: extension.extension_name,
|
|
43
|
+
extension_type: extension.extension_type,
|
|
44
|
+
resource_url: extension.resource_url
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 生成版本
|
|
49
|
+
async function generateNewVersion(partnerId, appClientId) {
|
|
50
|
+
const res = await generateVersionRequest({
|
|
51
|
+
partner_id: partnerId,
|
|
52
|
+
app_client_id: appClientId,
|
|
53
|
+
is_dev: true
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const { extensions, app_version } = res;
|
|
57
|
+
const extensionVersions = extensions.reduce((acc, { extension_id, extension_version }) => {
|
|
58
|
+
return {
|
|
59
|
+
...acc,
|
|
60
|
+
[extension_id]: extension_version
|
|
61
|
+
};
|
|
62
|
+
}, {});
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
newAppVersion: app_version,
|
|
66
|
+
newExtensionVersions: extensionVersions
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// app 信息展示
|
|
71
|
+
function appInfoShow({ app, partner }) {
|
|
72
|
+
infoMessageRender(`${chalk.bold('Your app info:\n')}
|
|
73
|
+
• ${'Partner:'.padEnd(10)} ${partner.business_name}
|
|
74
|
+
• ${'App:'.padEnd(10)} ${app.name}`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function devAction(options) {
|
|
78
|
+
// const { path: argPath = '.' } = options;
|
|
79
|
+
// 获取 app 信息
|
|
80
|
+
const { app, partner, user, configContent } = await getAppCompleteInfo();
|
|
81
|
+
|
|
82
|
+
appInfoShow({ app, partner });
|
|
83
|
+
|
|
84
|
+
const localExtensions = getLocalExtensions();
|
|
85
|
+
const remoteExtensions = await getRemoteExtensions(app.client_id, partner.id);
|
|
86
|
+
|
|
87
|
+
const appAccessToken = await getPartnerAccessToken(app.client_id, app.secret);
|
|
88
|
+
|
|
89
|
+
const { newAppVersion, newExtensionVersions } = await generateNewVersion(partner.id, app.client_id);
|
|
90
|
+
|
|
91
|
+
// 清空 app-deploy
|
|
92
|
+
fs.rmSync(path.join(process.env.APP_PROJECT_DIR, 'app-deploy'), { recursive: true, force: true });
|
|
93
|
+
fs.mkdirSync(path.join(process.env.APP_PROJECT_DIR, 'app-deploy'));
|
|
94
|
+
|
|
95
|
+
const {
|
|
96
|
+
addExtensions, // 需要创建新的 extension & version
|
|
97
|
+
updateExtensions, // 需要更新 version
|
|
98
|
+
deleteExtensions // 需要删除 extension 目前不支持删除,直接传回服务端
|
|
99
|
+
} = await extensionDiff(localExtensions, remoteExtensions);
|
|
100
|
+
|
|
101
|
+
[...updateExtensions, ...deleteExtensions].forEach((extension) => {
|
|
102
|
+
if (extension.extension_id in newExtensionVersions) {
|
|
103
|
+
extension.extension_version = newExtensionVersions[extension.extension_id];
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const buildFunctionResults = await Promise.all(
|
|
108
|
+
[...addExtensions, ...updateExtensions].map(async (extension) => {
|
|
109
|
+
const distPath = await buildExtension(extension);
|
|
110
|
+
extension.distPath = distPath;
|
|
111
|
+
return distPath;
|
|
112
|
+
})
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
// 🎯 获取动态的店铺认证信息
|
|
116
|
+
const { store_domain, access_token } = await getStoreAccessToken(app.client_id, partner.id);
|
|
117
|
+
|
|
118
|
+
// 上传资源到 OSS
|
|
119
|
+
await Promise.all(
|
|
120
|
+
[...addExtensions, ...updateExtensions].map(async (extension) => {
|
|
121
|
+
const { distPath } = extension;
|
|
122
|
+
|
|
123
|
+
// 🎯 使用 useOss 替换原来的上传逻辑
|
|
124
|
+
const { uploadOss } = useOss(access_token, store_domain, `✗ 未找到店铺信息。请检查app配置。`);
|
|
125
|
+
|
|
126
|
+
const resourceUrl = await uploadOss(distPath);
|
|
127
|
+
extension.resource_url = resourceUrl;
|
|
128
|
+
})
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
// 创建或更新 extension
|
|
133
|
+
const upsertExtensionResults = await Promise.all(
|
|
134
|
+
[...addExtensions, ...updateExtensions, ...deleteExtensions].map(async (extension) => {
|
|
135
|
+
const spinner = ora(`${extension.extension_name}(${extension.extension_version}) upserting...`).start();
|
|
136
|
+
try {
|
|
137
|
+
const res = await upsertExtension(extension, app.client_id, partner.id, appAccessToken);
|
|
138
|
+
extension.extension_id = res.extension_id;
|
|
139
|
+
extension.extension_version = res.extension_version;
|
|
140
|
+
extension.extension_version_id = res.extension_version_id;
|
|
141
|
+
spinner.succeed(`${extension.extension_name}(${extension.extension_version}) upsert success`);
|
|
142
|
+
return res;
|
|
143
|
+
} catch (error) {
|
|
144
|
+
spinner.fail(`${extension.extension_name}(${extension.extension_version}) upsert failed`);
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
})
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
// 更新本地配置文件信息
|
|
152
|
+
await Promise.all(
|
|
153
|
+
[...addExtensions, ...updateExtensions].map(async (extension) => {
|
|
154
|
+
try {
|
|
155
|
+
await modifyTomlFile(extension.configPath, (config) => {
|
|
156
|
+
config.id = extension.extension_id;
|
|
157
|
+
config.name = extension.extension_name;
|
|
158
|
+
config.type = extension.extension_type;
|
|
159
|
+
return config;
|
|
160
|
+
});
|
|
161
|
+
} catch (error) {
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
const completeExtensions = [...addExtensions, ...updateExtensions, ...deleteExtensions].map((extension) => ({
|
|
168
|
+
extension_id: extension.extension_id,
|
|
169
|
+
extension_name: extension.extension_name,
|
|
170
|
+
extension_type: extension.extension_type,
|
|
171
|
+
extension_version: extension.extension_version,
|
|
172
|
+
extension_version_id: extension.extension_version_id,
|
|
173
|
+
resource_url: extension.resource_url
|
|
174
|
+
}));
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
const { appUrl, redirectUrl } = await startDevServer({
|
|
178
|
+
clientId: app.client_id,
|
|
179
|
+
clientSecret: app.secret,
|
|
180
|
+
scopes: configContent.scopes
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// 展示 App URL 和 Redirect URL
|
|
184
|
+
|
|
185
|
+
const { install_url } = await extensionDev({
|
|
186
|
+
partner_id: partner.id,
|
|
187
|
+
app_client_id: app.client_id,
|
|
188
|
+
data: {
|
|
189
|
+
app: {
|
|
190
|
+
version: newAppVersion,
|
|
191
|
+
extensions: completeExtensions,
|
|
192
|
+
dev_app_uri: appUrl,
|
|
193
|
+
dev_redirect_uri: redirectUrl
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
console.log(chalk.bold('Your App URL:'), chalk.underline.green(appUrl));
|
|
199
|
+
console.log(chalk.bold('Your Redirect URL:'), chalk.underline.green(redirectUrl));
|
|
200
|
+
console.log(chalk.bold('Your Install URL:'), chalk.underline.green(install_url));
|
|
201
|
+
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
module.exports = {
|
|
205
|
+
devAction: withErrorHandling(devAction)
|
|
206
|
+
};
|