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,176 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const inquirer = require('inquirer');
|
|
5
|
+
const simpleGit = require('simple-git');
|
|
6
|
+
|
|
7
|
+
const { getAppListRequest, createAppRequest, getTemplateGitRequest, getAppConfigRequest } = require('../../../api/cli');
|
|
8
|
+
|
|
9
|
+
const { checkGit } = require('../../../utils/git');
|
|
10
|
+
const { slugify } = require('../../../utils/path');
|
|
11
|
+
const { modifyTomlFile } = require('../../../utils/toml');
|
|
12
|
+
const { modifyJsonFile } = require('../../../utils/json');
|
|
13
|
+
const { selectOne } = require('../../../utils/views/select');
|
|
14
|
+
const { withErrorHandling } = require('../../../utils/error');
|
|
15
|
+
const { withTempDir } = require('../../../utils/withTempDir');
|
|
16
|
+
const { successMessageRender } = require('../../../utils/views/message');
|
|
17
|
+
const { getPartner, promptCreateOrConnect } = require('../../../services/partner');
|
|
18
|
+
const { ssoStore, configStore } = require('../../../store');
|
|
19
|
+
|
|
20
|
+
// 校验项目地址
|
|
21
|
+
async function checkProjectDir(projectDir) {
|
|
22
|
+
// 检查目录是否已存在
|
|
23
|
+
if (fs.existsSync(projectDir)) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
`A directory with this name (${path.basename(projectDir)}) already exists.\nChoose a new name for your app.`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 初始化项目
|
|
31
|
+
async function initProject(projectDir, app) {
|
|
32
|
+
// 检查 git 是否安装
|
|
33
|
+
checkGit();
|
|
34
|
+
|
|
35
|
+
await withTempDir(async (tempDir) => {
|
|
36
|
+
// 获取模板 git
|
|
37
|
+
const { https } = await getTemplateGitRequest('app');
|
|
38
|
+
|
|
39
|
+
// 克隆项目到本地
|
|
40
|
+
await simpleGit().clone(https, tempDir);
|
|
41
|
+
|
|
42
|
+
// 删除 .git 文件夹
|
|
43
|
+
fs.rmSync(path.resolve(tempDir, '.git'), { recursive: true, force: true });
|
|
44
|
+
|
|
45
|
+
// 修改 package.json
|
|
46
|
+
await modifyJsonFile(path.join(tempDir, 'package.json'), (packageJsonObj) => ({
|
|
47
|
+
...packageJsonObj,
|
|
48
|
+
name: app.name
|
|
49
|
+
}));
|
|
50
|
+
|
|
51
|
+
// 修改 shoplazza.app.toml
|
|
52
|
+
await modifyTomlFile(path.resolve(tempDir, 'shoplazza.app.toml'), (config) => {
|
|
53
|
+
config.client_id = app.client_id;
|
|
54
|
+
return config;
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// 复制项目到本地
|
|
58
|
+
fs.cpSync(tempDir, projectDir, { recursive: true });
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 成功提示
|
|
63
|
+
function successTips(projectDir) {
|
|
64
|
+
const appName = path.basename(projectDir);
|
|
65
|
+
successMessageRender(`${chalk.hex('#73cedd')(appName)} is ready for you to build!
|
|
66
|
+
|
|
67
|
+
Next steps:
|
|
68
|
+
• Run ${chalk.hex('#d079f8')(`\`cd ${appName}\``)}
|
|
69
|
+
• For extensions, run ${chalk.hex('#d079f8')('`shoplazza app generate extension`')}
|
|
70
|
+
• To see your app, run ${chalk.hex('#d079f8')('`shoplazza app deploy`')}
|
|
71
|
+
|
|
72
|
+
Reference
|
|
73
|
+
• Shoplazza docs [1]
|
|
74
|
+
• For an overview of commands, run ${chalk.hex('#d079f8')('`shoplazza app --help`')}`);
|
|
75
|
+
console.log(`[1] https://shoplazza.dev`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function initAction(options) {
|
|
79
|
+
const { path: argPath = '.', clientId: argClientId, name: argName } = options;
|
|
80
|
+
|
|
81
|
+
// 选取 partner
|
|
82
|
+
const partner = await getPartner(argClientId);
|
|
83
|
+
|
|
84
|
+
// 获取 appList
|
|
85
|
+
const appListRes = await getAppListRequest(partner.id);
|
|
86
|
+
|
|
87
|
+
// 判断 创建 还是 链接
|
|
88
|
+
const isCreate = argClientId ? false : await promptCreateOrConnect(appListRes);
|
|
89
|
+
|
|
90
|
+
if (isCreate) {
|
|
91
|
+
// 创建
|
|
92
|
+
const appName = await inquirer
|
|
93
|
+
.prompt({
|
|
94
|
+
type: 'input',
|
|
95
|
+
name: 'app_name',
|
|
96
|
+
message: 'App name:',
|
|
97
|
+
default: argName,
|
|
98
|
+
validate: (value) => {
|
|
99
|
+
return value.trim() !== '' ? true : "App name can't be empty";
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
.then((r) => r.app_name);
|
|
103
|
+
|
|
104
|
+
// 规范化 appName
|
|
105
|
+
const normalizedAppName = slugify(appName);
|
|
106
|
+
|
|
107
|
+
// 项目目录
|
|
108
|
+
const projectDir = path.resolve(process.cwd(), argPath, normalizedAppName);
|
|
109
|
+
|
|
110
|
+
// 校验项目地址
|
|
111
|
+
await checkProjectDir(projectDir);
|
|
112
|
+
|
|
113
|
+
// 创建 app
|
|
114
|
+
const { app } = await createAppRequest(partner.id, {
|
|
115
|
+
app_name: normalizedAppName
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// 初始化项目
|
|
119
|
+
await initProject(projectDir, app);
|
|
120
|
+
|
|
121
|
+
// 缓存 app 相关信息
|
|
122
|
+
configStore.setProjectConfig(projectDir, {
|
|
123
|
+
clientId: app.client_id,
|
|
124
|
+
directory: projectDir,
|
|
125
|
+
configFile: 'shoplazza.app.toml'
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// 成功提示
|
|
129
|
+
successTips(projectDir);
|
|
130
|
+
} else {
|
|
131
|
+
// 链接
|
|
132
|
+
const appListRes = await getAppListRequest(partner.id);
|
|
133
|
+
|
|
134
|
+
if (appListRes.total === 0) {
|
|
135
|
+
throw new Error("You haven't any apps yet, please create one first!");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// 选取 app
|
|
139
|
+
const appClientId =
|
|
140
|
+
argClientId ||
|
|
141
|
+
(await selectOne(appListRes.apps, {
|
|
142
|
+
message: 'Which app is this work for?',
|
|
143
|
+
autoPickSingle: false,
|
|
144
|
+
formatChoice: (a) => ({ name: a.name, value: a.client_id })
|
|
145
|
+
}));
|
|
146
|
+
|
|
147
|
+
// 获取 app 配置
|
|
148
|
+
const { app } = await getAppConfigRequest(partner.id, appClientId);
|
|
149
|
+
|
|
150
|
+
// 规范化 appName
|
|
151
|
+
const normalizedAppName = slugify(app.name);
|
|
152
|
+
|
|
153
|
+
// 项目目录
|
|
154
|
+
const projectDir = path.resolve(process.cwd(), argPath, normalizedAppName);
|
|
155
|
+
|
|
156
|
+
// 校验项目地址
|
|
157
|
+
await checkProjectDir(projectDir);
|
|
158
|
+
|
|
159
|
+
// 初始化项目
|
|
160
|
+
await initProject(projectDir, app);
|
|
161
|
+
|
|
162
|
+
// 缓存 app 相关信息
|
|
163
|
+
configStore.setProjectConfig(projectDir, {
|
|
164
|
+
clientId: app.client_id,
|
|
165
|
+
directory: projectDir,
|
|
166
|
+
configFile: 'shoplazza.app.toml'
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// 成功提示
|
|
170
|
+
successTips(projectDir);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
module.exports = {
|
|
175
|
+
initAction: withErrorHandling(initAction)
|
|
176
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const { Command } = require('commander');
|
|
2
|
+
const { initAction } = require('./actions/init');
|
|
3
|
+
const initCommand = new Command('init');
|
|
4
|
+
|
|
5
|
+
initCommand
|
|
6
|
+
.option('--path <path>', 'The path to your app directory')
|
|
7
|
+
.option('--client-id <client-id>', 'The client id of your app')
|
|
8
|
+
.option('--name <name>', 'The name of your app');
|
|
9
|
+
|
|
10
|
+
initCommand.action(initAction);
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
initCommand
|
|
14
|
+
};
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
const { withErrorHandling } = require('../../../utils/error');
|
|
2
|
+
const { getAppCompleteInfo } = require('../../../services/config');
|
|
3
|
+
const { getAppVersionsRequest } = require('../../../api/cli');
|
|
4
|
+
const { infoMessageRender } = require('../../../utils/views/message');
|
|
5
|
+
const inquirer = require('inquirer');
|
|
6
|
+
const chalk = require('chalk');
|
|
7
|
+
|
|
8
|
+
// 默认分页大小
|
|
9
|
+
const DEFAULT_PAGE_SIZE = 10;
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
// 格式化版本列表
|
|
13
|
+
function formatVersionList(versions, currentPage, totalPages, hasMore, pageSize) {
|
|
14
|
+
if (!versions || versions.length === 0) {
|
|
15
|
+
return chalk.yellow('No versions found');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let output = `${chalk.bold('📦 App Versions')}\n\n`;
|
|
19
|
+
|
|
20
|
+
// 版本列表
|
|
21
|
+
versions.forEach((version, index) => {
|
|
22
|
+
const number = (currentPage - 1) * pageSize + index + 1;
|
|
23
|
+
output += `${chalk.gray(`${number.toString().padStart(3, ' ')}. `)}`;
|
|
24
|
+
output += `${chalk.cyan('v' + version.version)} `;
|
|
25
|
+
output += `${chalk.gray('(ID: ' + version.id + ')')}\n`;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// 分页信息
|
|
29
|
+
output += '\n';
|
|
30
|
+
output += `${chalk.bold('Page:')} ${currentPage}`;
|
|
31
|
+
if (totalPages > 0) {
|
|
32
|
+
output += ` / ${totalPages}`;
|
|
33
|
+
}
|
|
34
|
+
output += ` | ${chalk.bold('Showing:')} ${versions.length} items`;
|
|
35
|
+
if (hasMore) {
|
|
36
|
+
output += ` | ${chalk.yellow('More versions available...')}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return output;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 非交互模式:只显示第一页
|
|
43
|
+
async function displayNonInteractive(app, partner, pageSize) {
|
|
44
|
+
try {
|
|
45
|
+
const { versions, has_more } = await getAppVersionsRequest({
|
|
46
|
+
partner_id: partner.id,
|
|
47
|
+
app_client_id: app.client_id,
|
|
48
|
+
offset: 0,
|
|
49
|
+
limit: pageSize
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const formattedList = formatVersionList(versions, 1, has_more ? '?' : 1, has_more, pageSize);
|
|
53
|
+
infoMessageRender(formattedList);
|
|
54
|
+
|
|
55
|
+
if (has_more) {
|
|
56
|
+
console.log(chalk.yellow('\n💡 Tip: Use interactive mode to browse more versions by removing the --no-interactive flag'));
|
|
57
|
+
}
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.error(chalk.red('❌ Failed to fetch versions:'), error.message);
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Get user action choice
|
|
65
|
+
async function getPaginationChoice(currentPage, hasMore, hasPrev) {
|
|
66
|
+
const choices = [];
|
|
67
|
+
|
|
68
|
+
if (hasMore) {
|
|
69
|
+
choices.push({
|
|
70
|
+
name: `📄 Next page (page ${currentPage + 1})`,
|
|
71
|
+
value: 'next'
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (hasPrev) {
|
|
76
|
+
choices.push({
|
|
77
|
+
name: `📄 Previous page (page ${currentPage - 1})`,
|
|
78
|
+
value: 'prev'
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
choices.push({
|
|
83
|
+
name: '🔄 Refresh current page',
|
|
84
|
+
value: 'refresh'
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
choices.push({
|
|
88
|
+
name: '🚪 Exit',
|
|
89
|
+
value: 'exit'
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const { action } = await inquirer.prompt({
|
|
93
|
+
type: 'list',
|
|
94
|
+
name: 'action',
|
|
95
|
+
message: 'Choose an action:',
|
|
96
|
+
choices
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return action;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// 分页处理逻辑
|
|
103
|
+
async function handlePagination(app, partner, pageSize) {
|
|
104
|
+
let currentPage = 1;
|
|
105
|
+
let totalPages = 0;
|
|
106
|
+
|
|
107
|
+
while (true) {
|
|
108
|
+
const offset = (currentPage - 1) * pageSize;
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const { versions, has_more } = await getAppVersionsRequest({
|
|
112
|
+
partner_id: partner.id,
|
|
113
|
+
app_client_id: app.client_id,
|
|
114
|
+
offset,
|
|
115
|
+
limit: pageSize
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// 估算总页数(如果有更多数据)
|
|
119
|
+
if (has_more) {
|
|
120
|
+
totalPages = Math.max(totalPages, currentPage + 1);
|
|
121
|
+
} else {
|
|
122
|
+
totalPages = currentPage;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 清屏并显示版本列表
|
|
126
|
+
console.clear();
|
|
127
|
+
const formattedList = formatVersionList(versions, currentPage, totalPages, has_more, pageSize);
|
|
128
|
+
infoMessageRender(formattedList);
|
|
129
|
+
|
|
130
|
+
// 如果没有版本记录且是第一页,直接退出
|
|
131
|
+
if (!versions || versions.length === 0) {
|
|
132
|
+
if (currentPage === 1) {
|
|
133
|
+
break;
|
|
134
|
+
} else {
|
|
135
|
+
// 回到前一页
|
|
136
|
+
currentPage = Math.max(1, currentPage - 1);
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 获取用户选择
|
|
142
|
+
const action = await getPaginationChoice(
|
|
143
|
+
currentPage,
|
|
144
|
+
has_more,
|
|
145
|
+
currentPage > 1
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
switch (action) {
|
|
149
|
+
case 'next':
|
|
150
|
+
if (has_more) {
|
|
151
|
+
currentPage++;
|
|
152
|
+
}
|
|
153
|
+
break;
|
|
154
|
+
case 'prev':
|
|
155
|
+
if (currentPage > 1) {
|
|
156
|
+
currentPage--;
|
|
157
|
+
}
|
|
158
|
+
break;
|
|
159
|
+
case 'refresh':
|
|
160
|
+
// 重新加载当前页
|
|
161
|
+
break;
|
|
162
|
+
case 'exit':
|
|
163
|
+
console.log(chalk.green('👋 Goodbye!'));
|
|
164
|
+
return;
|
|
165
|
+
default:
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
} catch (error) {
|
|
169
|
+
console.error(chalk.red('❌ Failed to fetch versions:'), error.message);
|
|
170
|
+
|
|
171
|
+
// 询问是否重试
|
|
172
|
+
const { retry } = await inquirer.prompt({
|
|
173
|
+
type: 'confirm',
|
|
174
|
+
name: 'retry',
|
|
175
|
+
message: 'Retry?',
|
|
176
|
+
default: true
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
if (!retry) {
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async function listAction(options) {
|
|
187
|
+
// 解析命令行选项
|
|
188
|
+
const pageSize = parseInt(options.pageSize) || DEFAULT_PAGE_SIZE;
|
|
189
|
+
const isInteractive = options.interactive !== false; // 默认是交互模式
|
|
190
|
+
|
|
191
|
+
// 验证 pageSize
|
|
192
|
+
if (pageSize < 1 || pageSize > 100) {
|
|
193
|
+
console.error(chalk.red('❌ Page size must be between 1 and 100'));
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const { app, partner, user } = await getAppCompleteInfo();
|
|
198
|
+
|
|
199
|
+
if (isInteractive) {
|
|
200
|
+
// 交互式分页模式
|
|
201
|
+
await handlePagination(app, partner, pageSize);
|
|
202
|
+
} else {
|
|
203
|
+
// 非交互模式:只显示第一页
|
|
204
|
+
await displayNonInteractive(app, partner, pageSize);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
module.exports = {
|
|
209
|
+
listAction: withErrorHandling(listAction)
|
|
210
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { Command } = require('commander');
|
|
3
|
+
const { listCommand } = require('./list');
|
|
4
|
+
|
|
5
|
+
const versionsCommand = new Command('versions');
|
|
6
|
+
|
|
7
|
+
versionsCommand.addCommand(listCommand);
|
|
8
|
+
|
|
9
|
+
versionsCommand.helpInformation = function () {
|
|
10
|
+
return `List deployed versions of your app.
|
|
11
|
+
|
|
12
|
+
${chalk.bold('USAGE')}
|
|
13
|
+
$ shoplazza app versions COMMAND
|
|
14
|
+
|
|
15
|
+
${chalk.bold('COMMANDS')}
|
|
16
|
+
app versions list List deployed versions of your app.
|
|
17
|
+
`;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
module.exports = {
|
|
21
|
+
versionsCommand
|
|
22
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const { Command } = require('commander');
|
|
2
|
+
const { listAction } = require('./actions/list');
|
|
3
|
+
|
|
4
|
+
const listCommand = new Command('list');
|
|
5
|
+
|
|
6
|
+
listCommand.option('--path <path>', 'The path to your app directory');
|
|
7
|
+
listCommand.option('--page-size <size>', 'Number of versions per page (default: 10)', '10');
|
|
8
|
+
listCommand.option('--no-interactive', 'Disable interactive pagination');
|
|
9
|
+
|
|
10
|
+
listCommand.action(listAction);
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
listCommand
|
|
14
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// 颜色常量
|
|
2
|
+
const COLORS = {
|
|
3
|
+
ERROR: '#df5953',
|
|
4
|
+
SUCCESS: '#97c070',
|
|
5
|
+
WHITE: '#acb2be',
|
|
6
|
+
GRAY: '#686c76',
|
|
7
|
+
RED: '#df5953',
|
|
8
|
+
GREEN: '#97c070',
|
|
9
|
+
YELLOW: '#f0ad4e',
|
|
10
|
+
|
|
11
|
+
// 色彩主题
|
|
12
|
+
PRIMARY: '#63b1c0', // 主色
|
|
13
|
+
CODE: '#d079f8', // 行内代码
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
module.exports = {
|
|
17
|
+
COLORS
|
|
18
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const EXTENSION_TYPES = {
|
|
2
|
+
THEME: 'theme',
|
|
3
|
+
CHECKOUT: 'checkout',
|
|
4
|
+
FUNCTION: 'function'
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const THEME_EXTENSION_TYPES = {
|
|
9
|
+
BASIC: 'basic',
|
|
10
|
+
EMBED: 'embed'
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
module.exports = {
|
|
14
|
+
EXTENSION_TYPES,
|
|
15
|
+
THEME_EXTENSION_TYPES
|
|
16
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
exports.CLI_HOST = {
|
|
2
|
+
PROD: 'https://partners.shoplazza.com',
|
|
3
|
+
DEV: 'https://partners.dev.shoplazza.com',
|
|
4
|
+
STG: 'https://partners.stg.shoplazza.com'
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
exports.SSO_HOST = {
|
|
8
|
+
PROD: 'https://sso.shoplazza.com',
|
|
9
|
+
DEV: 'https://sso.dev.shoplazza.com',
|
|
10
|
+
STG: 'https://sso.stg.shoplazza.com'
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
exports.ACCOUNT_HOST = {
|
|
14
|
+
PROD: 'https://myaccount.shoplazza.com',
|
|
15
|
+
DEV: 'https://myaccount.dev.shoplazza.com',
|
|
16
|
+
STG: 'https://myaccount.stg.shoplazza.com'
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
exports.SSO_CLIENT_ID = {
|
|
20
|
+
DEV: 'b630b285-e098-4c51-a7a4-d0240c9fc209',
|
|
21
|
+
STG: 'b630b285-e098-4c51-a7a4-d0240c9fc209',
|
|
22
|
+
PROD: '807525c9-dd77-4f4e-a738-d1e9d02c593d'
|
|
23
|
+
};
|
package/lib/app/index.js
CHANGED
|
@@ -1,29 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
program.command('create').description('Create a new theme extension').action(require('./commands/create').create);
|
|
5
|
-
|
|
6
|
-
program
|
|
7
|
-
.command('serve')
|
|
8
|
-
.description('Start a local development server for the theme extension')
|
|
9
|
-
.action(require('./commands/serve').serve);
|
|
10
|
-
|
|
11
|
-
program.command('build').description('Build the theme extension for production').action(require('./commands/build').build);
|
|
12
|
-
|
|
13
|
-
program
|
|
14
|
-
.command('versions')
|
|
15
|
-
.description('List all versions of the theme extension')
|
|
16
|
-
.action(require('./commands/versions').versions);
|
|
17
|
-
|
|
18
|
-
program.command('deploy').description('Deploy the theme extension').action(require('./commands/deploy').deploy);
|
|
19
|
-
|
|
20
|
-
program.command('list').description('List all theme extensions').action(require('./commands/list').list);
|
|
21
|
-
|
|
22
|
-
program.command('connect').description('Establish a connection between the theme extension and the shoplazza app').action(require('./commands/connect').connect);
|
|
23
|
-
|
|
24
|
-
program.command('release').description('Release a theme extension version to be applied in the shoplazza app').action(require('./commands/release').release);
|
|
1
|
+
const { appCommand } = require('./commands');
|
|
2
|
+
function makeAppCommand(_program) {
|
|
3
|
+
_program.addCommand(appCommand);
|
|
25
4
|
}
|
|
26
5
|
|
|
27
6
|
module.exports = {
|
|
28
|
-
|
|
7
|
+
makeAppCommand
|
|
29
8
|
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const { ACCOUNT_HOST, SSO_HOST, SSO_CLIENT_ID, CLI_HOST } = require('../../constant/host');
|
|
2
|
+
const { isDevDebug, isStgDebug } = require('../../utils/debug');
|
|
3
|
+
|
|
4
|
+
function getSSOHost() {
|
|
5
|
+
if (isDevDebug()) return SSO_HOST.DEV;
|
|
6
|
+
if (isStgDebug()) return SSO_HOST.STG;
|
|
7
|
+
return SSO_HOST.PROD;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function getAccountHost() {
|
|
11
|
+
if (isDevDebug()) return ACCOUNT_HOST.DEV;
|
|
12
|
+
if (isStgDebug()) return ACCOUNT_HOST.STG;
|
|
13
|
+
return ACCOUNT_HOST.PROD;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function getPartnerHost() {
|
|
17
|
+
if (isDevDebug()) return CLI_HOST.DEV;
|
|
18
|
+
if (isStgDebug()) return CLI_HOST.STG;
|
|
19
|
+
return CLI_HOST.PROD;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function getSSOClientId() {
|
|
23
|
+
if (isDevDebug()) return SSO_CLIENT_ID.DEV;
|
|
24
|
+
if (isStgDebug()) return SSO_CLIENT_ID.STG;
|
|
25
|
+
return SSO_CLIENT_ID.PROD;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports = {
|
|
29
|
+
getSSOHost,
|
|
30
|
+
getAccountHost,
|
|
31
|
+
getSSOClientId,
|
|
32
|
+
getPartnerHost
|
|
33
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const { getSSOAccessToken } = require('./sso-token');
|
|
2
|
+
const { getPartnerAccessToken } = require('./partner-token');
|
|
3
|
+
const { getStoreAccessToken } = require('./store-token');
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
getSSOAccessToken,
|
|
7
|
+
getPartnerAccessToken,
|
|
8
|
+
getStoreAccessToken
|
|
9
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const { createServer } = require('http');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const open = require('open');
|
|
4
|
+
|
|
5
|
+
function startOAuthServer(options = {}) {
|
|
6
|
+
const {
|
|
7
|
+
port = 3456,
|
|
8
|
+
timeout = 2 * 60 * 1000,
|
|
9
|
+
onGetUrl // 获取认证URL的回调
|
|
10
|
+
} = options;
|
|
11
|
+
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
let timeoutHandle = null;
|
|
14
|
+
|
|
15
|
+
const server = createServer((req, res) => {
|
|
16
|
+
const reqUrl = new URL(req.url, `http://localhost:${port}`);
|
|
17
|
+
const query = Object.fromEntries(reqUrl.searchParams);
|
|
18
|
+
|
|
19
|
+
// 发送成功页面
|
|
20
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
21
|
+
res.end(`
|
|
22
|
+
<!DOCTYPE html>
|
|
23
|
+
<html>
|
|
24
|
+
<head><title>Authentication successful</title></head>
|
|
25
|
+
<body>
|
|
26
|
+
<h1 style="color: green;">Authentication successful! You can close this page.</h1>
|
|
27
|
+
</body>
|
|
28
|
+
</html>
|
|
29
|
+
`);
|
|
30
|
+
|
|
31
|
+
if (query.code) {
|
|
32
|
+
clearTimeout(timeoutHandle);
|
|
33
|
+
resolve(query.code);
|
|
34
|
+
console.log(`${chalk.green('✔')} Login successful`);
|
|
35
|
+
server.close();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
server.listen(port, () => {
|
|
40
|
+
console.log('👉 Press any key to open the login page on your browser');
|
|
41
|
+
|
|
42
|
+
// 设置键盘监听
|
|
43
|
+
process.stdin.setRawMode(true);
|
|
44
|
+
process.stdin.resume();
|
|
45
|
+
process.stdin.once('data', async () => {
|
|
46
|
+
process.stdin.setRawMode(false);
|
|
47
|
+
process.stdin.pause();
|
|
48
|
+
|
|
49
|
+
// 获取并打开认证URL
|
|
50
|
+
if (onGetUrl) {
|
|
51
|
+
const authUrl = onGetUrl();
|
|
52
|
+
console.log('Opened link to start the auth process:', chalk.underline.green(authUrl), '\n');
|
|
53
|
+
await open(authUrl);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
server.on('error', (err) => {
|
|
59
|
+
reject(new Error(`SSO Server startup failed: ${err.message}`));
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// 设置超时
|
|
63
|
+
timeoutHandle = setTimeout(() => {
|
|
64
|
+
reject(new Error('SSO Server Timeout: No response within 2 minutes'));
|
|
65
|
+
server.close();
|
|
66
|
+
}, timeout);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = { startOAuthServer };
|