shoplazza-cli 1.0.5 → 1.0.6

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.
Files changed (63) hide show
  1. package/bin/shoplazza +3 -14
  2. package/lib/app/api/api.js +93 -0
  3. package/lib/app/api/request.js +72 -0
  4. package/lib/app/commands/build.js +74 -53
  5. package/lib/app/commands/create.js +100 -0
  6. package/lib/app/commands/deploy.js +39 -210
  7. package/lib/app/commands/list.js +31 -0
  8. package/lib/app/commands/serve.js +118 -0
  9. package/lib/app/commands/versions.js +44 -0
  10. package/lib/app/index.js +17 -29
  11. package/lib/app/template/basic-app/.ci/k8s.yaml +4 -0
  12. package/lib/app/template/basic-app/README.md +84 -0
  13. package/lib/app/template/basic-app/package.json +15 -0
  14. package/lib/app/template/basic-app/theme-app/assets/index.css +4 -0
  15. package/lib/app/template/basic-app/theme-app/blocks/index.liquid +14 -0
  16. package/lib/app/template/basic-app/theme-app/snippets/index.liquid +8 -0
  17. package/lib/app/template/basic-app/theme-app.config.json +4 -0
  18. package/lib/app/template/embed-app/.ci/k8s.yaml +4 -0
  19. package/lib/app/template/embed-app/README.md +84 -0
  20. package/lib/app/template/embed-app/package.json +15 -0
  21. package/lib/app/template/embed-app/theme-app/assets/index.css +4 -0
  22. package/lib/app/template/embed-app/theme-app/blocks/index.liquid +15 -0
  23. package/lib/app/template/embed-app/theme-app/locales/ar-SA.json +3 -0
  24. package/lib/app/template/embed-app/theme-app/locales/de-DE.json +3 -0
  25. package/lib/app/template/embed-app/theme-app/locales/en-US.json +3 -0
  26. package/lib/app/template/embed-app/theme-app/locales/es-ES.json +3 -0
  27. package/lib/app/template/embed-app/theme-app/locales/fr-FR.json +3 -0
  28. package/lib/app/template/embed-app/theme-app/locales/id-ID.json +3 -0
  29. package/lib/app/template/embed-app/theme-app/locales/it-IT.json +3 -0
  30. package/lib/app/template/embed-app/theme-app/locales/ja-JP.json +3 -0
  31. package/lib/app/template/embed-app/theme-app/locales/ko-KR.json +3 -0
  32. package/lib/app/template/embed-app/theme-app/locales/nl-NL.json +3 -0
  33. package/lib/app/template/embed-app/theme-app/locales/pl-PL.json +3 -0
  34. package/lib/app/template/embed-app/theme-app/locales/pt-PT.json +3 -0
  35. package/lib/app/template/embed-app/theme-app/locales/ru-RU.json +3 -0
  36. package/lib/app/template/embed-app/theme-app/locales/th-TH.json +3 -0
  37. package/lib/app/template/embed-app/theme-app/locales/zh-CN.json +3 -0
  38. package/lib/app/template/embed-app/theme-app/locales/zh-TW.json +3 -0
  39. package/lib/app/template/embed-app/theme-app/snippets/index.liquid +8 -0
  40. package/lib/app/template/embed-app/theme-app.config.json +4 -0
  41. package/lib/app/utils/config.js +29 -0
  42. package/lib/app/utils/index.js +220 -0
  43. package/lib/checkout/api.js +11 -34
  44. package/lib/checkout/build/plugin/vite-plugin-transform-extension-html.js +1 -1
  45. package/lib/checkout/dev/index.js +2 -1
  46. package/lib/commands/login.js +1 -1
  47. package/lib/commands/logout.js +1 -1
  48. package/lib/openAPI/index.js +21 -10
  49. package/lib/oss.js +102 -0
  50. package/lib/utils.js +52 -0
  51. package/package.json +2 -2
  52. package/lib/app/commands/generate.js +0 -50
  53. package/lib/app/commands/publish.js +0 -52
  54. package/lib/app/extensions/index.js +0 -13
  55. package/lib/app/extensions/theme-app.js +0 -103
  56. package/lib/app/inquirers/version.js +0 -131
  57. /package/lib/{app → common}/constants.js +0 -0
  58. /package/lib/{app → common}/db/partner.js +0 -0
  59. /package/lib/{app → common}/inquirers/choose-app.js +0 -0
  60. /package/lib/{app → common}/inquirers/choose-partner.js +0 -0
  61. /package/lib/{app → common}/log.js +0 -0
  62. /package/lib/{app → common}/login.js +0 -0
  63. /package/lib/{app → common}/logout.js +0 -0
@@ -1,218 +1,47 @@
1
- const axios = require('axios');
2
- const ora = require('ora');
1
+ const inquirer = require('inquirer');
3
2
  const chalk = require('chalk');
4
- const fs = require('fs-extra');
5
- const SparkMD5 = require('spark-md5');
6
- const FormData = require('form-data');
7
- const path = require('path');
8
-
9
- const { PARNTER_URL } = require('../constants');
10
- const { getValue, PARTNER_KEYS, getApp, set } = require('../db/partner');
11
- const { getZipName } = require('./build');
12
- const { inputVersion } = require('../inquirers/version');
13
- const { line, done } = require('../log');
14
-
15
- const getZipPath = () => {
16
- const spinner = ora(chalk.cyan('Finding your built zip ...')).start();
17
- try {
18
- const zipName = getZipName();
19
- const filename = fs.readdirSync(process.cwd()).find((name) => {
20
- const extname = path.extname(name).replace('.', '');
21
- return extname === 'zip' && name.startsWith(zipName);
22
- });
23
-
24
- if (!filename) {
25
- throw new Error('not zip');
26
- }
27
-
28
- const fileInfo = fs.statSync(`${process.cwd()}/${filename}`);
29
-
30
- spinner.succeed(
31
- chalk.cyan(
32
- `Success to find your zip: ${chalk.green(`${filename} ${(fileInfo.size / (1024 * 1024)).toFixed(2)}M`)}`
33
- )
34
- );
35
- return path.resolve(process.cwd(), filename);
36
- } catch (e) {
37
- spinner.fail(chalk.red('Failed to find your zip, be sure you have built app in root dir!'));
38
- }
39
- };
40
-
41
- const getBufferAndMd5 = async (filePath) => {
42
- const spinner = ora(chalk.cyan('Begin to read zip and generate md5 code ...')).start();
43
-
44
- try {
45
- return await new Promise((resolve, reject) => {
46
- const spark = new SparkMD5.ArrayBuffer();
47
- let buffers = [];
48
-
49
- const rs = fs.createReadStream(filePath, { autoClose: true });
50
- rs.on('data', (data) => {
51
- buffers.push(data);
52
- spark.append(data);
53
- });
54
-
55
- rs.on('end', () => {
56
- const md5 = spark.end();
57
- const completedBuffer = Buffer.concat(buffers);
58
- spinner.succeed(chalk.cyan('Success to analyse zip'));
59
- resolve([completedBuffer, md5 + '.zip']);
60
- });
61
-
62
- rs.on('error', (err) => {
63
- reject(err);
64
- });
65
- });
66
- } catch (e) {
67
- spinner.fail(chalk.red('Failed to analyse zip, please try again!'));
68
- }
69
- };
70
-
71
- const getSign = async () => {
72
- const spinner = ora(chalk.cyan('Waiting get file sign ...')).start();
73
-
74
- try {
75
- const app = getApp();
76
- const partnerId = getValue(PARTNER_KEYS.PARTNER_ID);
77
- const sessionId = getValue(PARTNER_KEYS.SESSION_ID);
78
-
79
- const url = `${PARNTER_URL}/api/partner/apps/${app.uid}/theme_extensions/file/signv2`;
80
- const res = await axios.get(url, {
81
- headers: {
82
- Cookie: `awesomev2=${sessionId}`,
83
- 'x-shoplazza-partner-id': partnerId
84
- }
85
- });
86
- spinner.succeed(chalk.cyan('Success to get file sign'));
87
- return res.data;
88
- } catch (e) {
89
- spinner.fail(chalk.red(e.message || e));
90
- }
91
- };
92
-
93
- const deployOss = async () => {
94
- const path = getZipPath();
95
- if (path) {
96
- const [buffer, md5] = await getBufferAndMd5(path);
97
- const signData = await getSign();
98
- if (!signData) {
99
- return;
100
- }
101
-
102
- const spinner = ora(chalk.cyan('Deploying your zip to cdn ...')).start();
103
-
104
- try {
105
- const formData = new FormData();
106
- formData.append('policy', signData.policy);
107
- formData.append('OSSAccessKeyId', signData.access_id);
108
- formData.append('success_action_status', 200);
109
- formData.append('signature', signData.sign);
110
- formData.append('x-oss-forbid-overwrite', 'true');
111
- formData.append('key', md5);
112
- formData.append('file', buffer);
113
-
114
- const url = `https:${signData.write_host}/`;
115
- const res = await axios.post(url, formData, {
116
- global: true,
117
- maxContentLength: 100000000,
118
- maxBodyLength: 1000000000
119
- });
120
-
121
- if (res.status !== 200) {
122
- throw new Error(`${res.status} ${resstatusText}`);
123
- }
124
- spinner.succeed();
125
- return md5;
126
- } catch (e) {
127
- // 409 repeat filename
128
- if (e?.response?.status === 409) {
129
- spinner.succeed();
130
- return md5;
131
- }
132
- spinner.fail();
133
- console.log(chalk.red(e.message || e));
134
- }
135
- }
136
- };
137
-
138
- const deployPartner = async () => {
139
- const md5 = await deployOss();
140
- if (!md5) {
141
- return;
142
- }
143
-
144
- const spinner = ora(chalk.cyan('Deploying your zip to PARTNER ...')).start();
145
- try {
146
- const app = getApp();
147
- if (!app) {
148
- spinner.fail(chalk.red('Please choose your partner first!'));
149
- return;
3
+ const ora = require('ora');
4
+ const { getThemeAppConfig } = require('../utils');
5
+ const { getThemeAppVersionList, toDeployThemeApp } = require('../api/api');
6
+
7
+ // 调用后端 API 进行部署
8
+ async function deployVersion(appId, version) {
9
+ // await new Promise((resolve) => setTimeout(resolve, 2000));
10
+ await toDeployThemeApp({
11
+ extension_id: appId,
12
+ version,
13
+ type: 'enable'
14
+ });
15
+ console.log(chalk.green(`Version ${version} has been deployed successfully.`));
16
+ }
17
+
18
+ async function usePrompt(versionList) {
19
+ const choices = versionList.map((v) => ({
20
+ name: `${v.version} (${v.date}) - ${v.description}`,
21
+ value: v.version
22
+ }));
23
+ return inquirer.prompt([
24
+ {
25
+ type: 'list',
26
+ name: 'selectedVersion',
27
+ message: 'Select a version to deploy:',
28
+ choices
150
29
  }
30
+ ]);
31
+ }
151
32
 
152
- const partnerId = getValue(PARTNER_KEYS.PARTNER_ID);
153
- const url = `${PARNTER_URL}/api/partner/apps/${app.uid}/theme_extensions`;
154
- const res = await axios.put(
155
- url,
156
- {
157
- title: getZipName(),
158
- name: getZipName(),
159
- file_name: md5
160
- },
161
- {
162
- headers: {
163
- cookie: `awesomev2=${getValue(PARTNER_KEYS.SESSION_ID)};`,
164
- 'x-shoplazza-partner-id': partnerId
165
- }
166
- }
167
- );
168
-
169
- set({ [PARTNER_KEYS.EXTENSION_ID]: res.data.extension_id });
170
- spinner.succeed();
171
- return true;
172
- } catch (e) {
173
- spinner.fail();
174
- console.log(e.message || e);
175
- console.log(chalk.red(JSON.stringify(e.response.data)));
176
- }
177
- };
178
-
179
- const createVersion = async (version) => {
180
- const spinner = ora(chalk.cyan('Creating your version task ...')).start();
181
-
33
+ async function deploy() {
182
34
  try {
183
- const app = getApp();
184
- const extensionId = getValue(PARTNER_KEYS.EXTENSION_ID);
185
- const partnerId = getValue(PARTNER_KEYS.PARTNER_ID);
186
-
187
- const url = `${PARNTER_URL}/api/partner/apps/${app.uid}/theme_extensions/${extensionId}/version_tasks`;
188
- await axios.post(
189
- url,
190
- {
191
- version
192
- },
193
- {
194
- headers: {
195
- cookie: `awesomev2=${getValue(PARTNER_KEYS.SESSION_ID)};`,
196
- 'x-shoplazza-partner-id': partnerId
197
- }
198
- }
199
- );
200
- spinner.succeed();
201
- return true;
202
- } catch (e) {
203
- spinner.fail();
204
- console.log(chalk.red(e.message || e));
205
- console.log(chalk.red(JSON.stringify(e.response?.data)));
35
+ const { appId } = await getThemeAppConfig();
36
+ const spinner = ora('Fetching version list...').start();
37
+ const versionList = await getThemeAppVersionList();
38
+ spinner.succeed('Version list loaded.');
39
+ const { selectedVersion } = await usePrompt(versionList);
40
+ await deployVersion(appId, selectedVersion);
41
+ } catch (error) {
42
+ console.error(chalk.red(`[ERROR IN DEPLOY] ${error.message}`));
206
43
  }
207
- };
208
-
209
- const deploy = async () => {
210
- line();
211
- ora(chalk.cyan('Deploy Begin')).succeed();
212
- let version;
213
- (await deployPartner()) && (version = await inputVersion()) && (await createVersion(version)) && done();
214
- line();
215
- };
44
+ }
216
45
 
217
46
  module.exports = {
218
47
  deploy
@@ -0,0 +1,31 @@
1
+ const chalk = require('chalk');
2
+ const ora = require('ora');
3
+ const { getThemeAppConfig, renderTable } = require('../utils');
4
+ const { getThemeAppList } = require('../api/api');
5
+
6
+ /**
7
+ * 控制台提示
8
+ */
9
+ function consoleTips(versionList) {
10
+ console.log(chalk.green('\n📜 Available Theme Apps:'));
11
+ console.log(
12
+ renderTable(versionList, [
13
+ { label: 'Name', filed: 'name' },
14
+ { label: 'Version', filed: 'version', color: 'yellowBright' },
15
+ { label: 'Description', filed: 'description' }
16
+ ])
17
+ );
18
+ }
19
+
20
+ async function list() {
21
+ try {
22
+ const themeAppList = await getThemeAppList();
23
+ consoleTips(themeAppList);
24
+ } catch (error) {
25
+ console.error(chalk.red(`[ERROR IN LIST] ${error.message}`));
26
+ }
27
+ }
28
+
29
+ module.exports = {
30
+ list
31
+ };
@@ -0,0 +1,118 @@
1
+ const path = require('path');
2
+ const chalk = require('chalk');
3
+ const inquirer = require('inquirer');
4
+ const { STORE_DOMAIN, THEME_APP_PATH, EXCHANGE_TOKEN } = require('../utils/config');
5
+ const { compress, getThemeAppConfig, setThemeAppConfig } = require('../utils');
6
+ const { toCreateThemeApp, toUploadThemeApp, getTaskStatus, getThemeList } = require('../api/api');
7
+ const { initWatcher } = require('../../utils');
8
+ const { useOss } = require('../../oss');
9
+
10
+ /**
11
+ * 模拟上传文件到服务器
12
+ */
13
+ async function uploadFileToServer(filePath) {
14
+ console.log(chalk.blue(`[UPLOAD] ${filePath} - Uploading to server...`));
15
+ // TODO: 替换为实际的上传逻辑(例如调用后端 API 或 WebSocket 通信)
16
+ await new Promise((resolve) => setTimeout(resolve, 1000)); // 模拟网络延迟
17
+ console.log(chalk.green(`[SUCCESS] ${filePath} - Uploaded successfully.`));
18
+ }
19
+
20
+ /**
21
+ * 控制台提示信息
22
+ */
23
+ function consoleTips(selectedThemeId, appId) {
24
+ console.log(`\n======================================PREVIEW URLS======================================`);
25
+ console.log(chalk.cyan.bold('🔗 Admin Preview URL:'));
26
+ console.log(
27
+ chalk.blueBright(` https://${STORE_DOMAIN}/admin/card?theme_id=${selectedThemeId}&ext_debug=${appId}\n`)
28
+ );
29
+ console.log(chalk.cyan.bold('🔗 Storefront Preview URL:'));
30
+ console.log(chalk.blueBright(` https://${STORE_DOMAIN}?preview_theme_id=${selectedThemeId}&ext_debug[]=${appId}\n`));
31
+ console.log(`=====================================WATCHER RUNNING=====================================`);
32
+ console.log(chalk.green(`🎉 File watcher is now running!`));
33
+ console.log(chalk.green(`📂 Watching directory:`), chalk.blue(THEME_APP_PATH));
34
+ console.log(chalk.green(`✨ You can make changes to your files, and they will be processed automatically.`));
35
+ console.log(chalk.green(`🚀 Press Ctrl+C to stop.\n`));
36
+ }
37
+
38
+ /**
39
+ * 同步本地代码到远程服务器
40
+ */
41
+ async function syncLocalFiles(appId) {
42
+ const { zipPath, zipName } = await compress(THEME_APP_PATH);
43
+ const { uploadOss } = useOss(
44
+ EXCHANGE_TOKEN,
45
+ STORE_DOMAIN,
46
+ `✗ No store found. Please run ${chalk.cyan('shoplazza login')} to login to a specific store.`
47
+ );
48
+ const zipOssUrl = await uploadOss(zipPath, zipName);
49
+ const res = await toUploadThemeApp({
50
+ extension_id: appId,
51
+ resource_url: zipOssUrl
52
+ });
53
+ const taskId = res.data?.task_id;
54
+ // 轮询查看任务是否完成
55
+ while (true) {
56
+ const res = await getTaskStatus({ taskId });
57
+ if (res.data?.task?.state === 1) {
58
+ console.log(chalk.green(`[SUCCESS] Theme app pushed successfully.`));
59
+ break;
60
+ } else if (res.data?.task?.state === 2) {
61
+ console.error(chalk.red(`[ERROR] Theme app push failed: ${res.data?.task?.error_message}`));
62
+ break;
63
+ } else {
64
+ console.log(chalk.yellow(`[WAITING] Theme app push in progress...`));
65
+ await new Promise((resolve) => setTimeout(resolve, 1000));
66
+ }
67
+ }
68
+ }
69
+
70
+ /**
71
+ * 交互选择预览主题
72
+ */
73
+ async function usePrompt() {
74
+ const res = await getThemeList();
75
+ const themeList = res.data?.data?.themes || [];
76
+ const { selectedThemeId } = await inquirer.prompt([
77
+ {
78
+ type: 'list',
79
+ name: 'selectedThemeId',
80
+ message: 'Please select a theme to preview:',
81
+ choices: themeList.map((theme) => ({
82
+ name: theme.name,
83
+ value: theme.id
84
+ }))
85
+ }
86
+ ]);
87
+ return selectedThemeId;
88
+ }
89
+
90
+ /**
91
+ * 创建主题插件
92
+ */
93
+ async function createThemeApp(appName) {
94
+ const res = await toCreateThemeApp({
95
+ title: appName
96
+ });
97
+ const appId = res.data?.extension_id;
98
+ // QQQ1
99
+ await setThemeAppConfig({ appId });
100
+ return appId;
101
+ }
102
+
103
+ async function serve() {
104
+ try {
105
+ let { appId, appName } = await getThemeAppConfig();
106
+ // if (!appId) {
107
+ // appId = createThemeApp(appName);
108
+ // }
109
+ // await syncLocalFiles(appId);
110
+ const selectedThemeId = await usePrompt();
111
+ initWatcher(THEME_APP_PATH);
112
+ consoleTips(selectedThemeId, appId);
113
+ } catch (error) {
114
+ console.error(chalk.red(`[ERROR IN SERVE] ${error.message}`));
115
+ }
116
+ }
117
+
118
+ module.exports = { serve };
@@ -0,0 +1,44 @@
1
+ const chalk = require('chalk');
2
+ const ora = require('ora');
3
+ const { getThemeAppConfig, renderTable } = require('../utils');
4
+ const { getThemeAppVersionList } = require('../api/api');
5
+
6
+ /**
7
+ * 控制台提示
8
+ */
9
+ function consoleTips(versionList) {
10
+ console.log(chalk.green('\n📜 Available Versions:'));
11
+ console.log(
12
+ renderTable(versionList, [
13
+ {
14
+ label: 'Version',
15
+ filed: 'version',
16
+ color: 'yellowBright'
17
+ },
18
+ {
19
+ label: 'Date',
20
+ filed: 'date',
21
+ color: 'blackBright'
22
+ },
23
+ {
24
+ label: 'Description',
25
+ filed: 'description',
26
+ color: 'whiteBright'
27
+ }
28
+ ])
29
+ );
30
+ }
31
+
32
+ async function versions() {
33
+ try {
34
+ const { appId } = await getThemeAppConfig();
35
+ const versionList = await getThemeAppVersionList({ appId });
36
+ consoleTips(versionList);
37
+ } catch (error) {
38
+ console.error(chalk.red(`[ERROR IN VERSIONS] ${error.message}`));
39
+ }
40
+ }
41
+
42
+ module.exports = {
43
+ versions
44
+ };
package/lib/app/index.js CHANGED
@@ -1,37 +1,25 @@
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');
1
+ function initThemeAppCommand(_program) {
2
+ const program = _program.command('app').description('Shoplazza app CLI');
8
3
 
9
- const generateExtension = async () => {
10
- (await checkAndLogin()) && (await generate());
11
- };
4
+ program.command('create').description('Create a new theme app').action(require('./commands/create').create);
12
5
 
13
- const deployExtension = async () => {
14
- (await checkAndLogin()) && (await deploy());
15
- };
6
+ program
7
+ .command('serve')
8
+ .description('Start a local development server for the theme app')
9
+ .action(require('./commands/serve').serve);
16
10
 
17
- const publishExtension = async () => {
18
- (await checkAndLogin()) && (await publish());
19
- };
11
+ program.command('build').description('Build the theme app for production').action(require('./commands/build').build);
20
12
 
21
- const retry = async (options) => {
22
- if (options.partner) {
23
- (await checkAndLogin()) && (await choosePartner()) && (await chooseApp());
24
- }
13
+ program
14
+ .command('versions')
15
+ .description('List all versions of the theme app')
16
+ .action(require('./commands/versions').versions);
25
17
 
26
- if (options.app) {
27
- (await checkAndLogin()) && (await chooseApp());
28
- }
29
- };
18
+ program.command('deploy').description('Deploy the theme app').action(require('./commands/deploy').deploy);
19
+
20
+ program.command('list').description('List all theme apps').action(require('./commands/list').list);
21
+ }
30
22
 
31
23
  module.exports = {
32
- generateExtension,
33
- deployExtension,
34
- publishExtension,
35
- buildExtension: build,
36
- retry
24
+ initThemeAppCommand
37
25
  };
@@ -0,0 +1,4 @@
1
+ deployJob:
2
+ name: {{projectName}}-deployjob
3
+ alarmHandler:
4
+ group: none
@@ -0,0 +1,84 @@
1
+ # Theme Basic App
2
+
3
+ ## 概览
4
+
5
+ 一个基础的主题插件项目
6
+
7
+ ## 安装
8
+
9
+ 首先,确保您安装了“Shoplazza CLI”。如果没有,您可以使用以下命令全局安装它:
10
+
11
+ ```bash
12
+ npm install -g shoplazza-cli
13
+ ```
14
+
15
+ ## 可用的脚本
16
+
17
+ ### `create`
18
+
19
+ 创建主题插件项目模版
20
+
21
+ ```bash
22
+ shoplazza app create
23
+ ```
24
+
25
+ ---
26
+
27
+ 进入项目目录后,即可使用以下命令:
28
+
29
+ ### `start`
30
+
31
+ 启动开发模式
32
+
33
+ ```bash
34
+ npm start
35
+ ```
36
+
37
+ 或者
38
+
39
+ ```bash
40
+ shoplazza app serve
41
+ ```
42
+
43
+ ### `build`
44
+
45
+ 基于当前的草稿生成对应正式版本的主题插件
46
+
47
+ ```bash
48
+ npm run build
49
+ ```
50
+
51
+ 或者
52
+
53
+ ```bash
54
+ shoplazza app build
55
+ ```
56
+
57
+ ### `deploy`
58
+
59
+ 部署正式版本的主题插件(部署后插件在店铺的主题编辑器的app列表中可见)
60
+
61
+ ```bash
62
+ npm run deploy
63
+ ```
64
+
65
+ 或者
66
+
67
+ ```bash
68
+ shoplazza app deploy
69
+ ```
70
+
71
+ ### `versions`
72
+
73
+ 查询主题插件的历史正式版本列表
74
+
75
+ ```bash
76
+ npm run versions
77
+ ```
78
+
79
+ 或者
80
+
81
+ ```bash
82
+ shoplazza app versions
83
+ ```
84
+
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "version": "1.0.0",
4
+ "description": "theme basic app",
5
+ "main": "null",
6
+ "scripts": {
7
+ "start": "shoplazza app serve",
8
+ "build": "shoplazza app build",
9
+ "deploy": "shoplazza app deploy",
10
+ "versions": "shoplazza app versions"
11
+ },
12
+ "keywords": [],
13
+ "author": "",
14
+ "license": "ISC"
15
+ }
@@ -0,0 +1,4 @@
1
+ /* css code */
2
+ .container {
3
+ color: red;
4
+ }
@@ -0,0 +1,14 @@
1
+ <div id="{{projectName}}" class="container">
2
+ <p>Hello world</p>
3
+ </div>
4
+ {% include "{{projectName}}_snippet" %}
5
+
6
+ {% schema %}
7
+ {
8
+ "name": {
9
+ "en-US": "default name",
10
+ "zh-CN": "默认名称"
11
+ },
12
+ "settings": []
13
+ }
14
+ {% endschema %}
@@ -0,0 +1,8 @@
1
+ <div>
2
+ Shoplazza theme APP
3
+ </div>
4
+
5
+
6
+
7
+
8
+
@@ -0,0 +1,4 @@
1
+ {
2
+ "appId": "",
3
+ "appName": "{{projectName}}"
4
+ }
@@ -0,0 +1,4 @@
1
+ deployJob:
2
+ name: {{projectName}}-deployjob
3
+ alarmHandler:
4
+ group: none