shoplazza-cli 0.1.8 → 1.0.3

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 CHANGED
@@ -21,6 +21,7 @@ Shoplazza CLI accelerates your theme development process with the following feat
21
21
  - Upload themes to your store.
22
22
  - Watch for local changes and upload them automatically to Shoplazza.
23
23
  - Work on Linux, macOS, and Windows.
24
+ - Support customized Checkout page.
24
25
 
25
26
  ## Installation [shoplazza-cli](https://www.npmjs.com/package/shoplazza-themekit)
26
27
 
@@ -38,7 +39,74 @@ Before you start using Shoplazza CLI to develop themes, make sure that you do th
38
39
  - Note the URL of the store that you want to work on.
39
40
  - Make sure that you're connected to the internet. Most Shoplazza CLI commands need an internet connection to run.
40
41
 
41
- ## Getting started
42
+
43
+ ## Checkout Develop
44
+
45
+ You can use Shoplazza CLI to develop checkout, customized checkout page as you want.
46
+
47
+ ### Feature
48
+
49
+ - 支持本地开发和调试,支持热更新。
50
+ - 支持预览,在推送到店铺之后,通过预览链接进入可以进行预览。
51
+ - 支持部署extension,部署后所有用户都能看到变更。
52
+ - 支持下线extension,下线之后extension将不在店铺中生效。
53
+
54
+ ### Get Started
55
+
56
+ #### Step 1: 创建一个项目模板
57
+
58
+ 创建过程会要求你输入店铺地址和token,token可以在后台中应用->管理私有应用->创建应用 获得。创建过程还要求你输入一个extension名字,一个项目下支持存在多个extension,这是为了方便管理,它们互不影响。
59
+ ```
60
+ shoplazza checkout create
61
+ // 安装依赖
62
+ npm i
63
+ ```
64
+
65
+ #### Step2: 本地开发
66
+ extension支持本地开发,支持在线上店铺Checkout页面插入本地的extension代码,这仅在你的浏览器生效。
67
+ 首先,先启动本地开发服务器:
68
+ ```
69
+ shoplazza checkout dev
70
+ ```
71
+ 然后在checkout页面打开控制台切换为开发模式:
72
+ ```
73
+ CheckoutAPI.extension.DEV_switchDevMode()
74
+ ```
75
+ 在checkout页面即可看到extension变更。
76
+
77
+ #### Step3: 预览extension
78
+ 在完成本地开发之后,我们可以将extension推送到店铺进行预览。
79
+ ```
80
+ shoplazza checkout push
81
+ ```
82
+ 访问预览url即可看到效果。
83
+ #### Step4: 部署Extension
84
+ 在预览测试完成之后,可以在店铺发布extension,发布之后所有用户都可以看到。
85
+ ```
86
+ shoplazza checkout deploy
87
+ ```
88
+ 或者对将已发布的extension下线:
89
+ ```
90
+ shoplazza checkout undeploy
91
+
92
+ ```
93
+
94
+ ### Other command
95
+
96
+ #### 查看已部署的extension
97
+ ```
98
+ shoplazza checkout list
99
+
100
+ // 查看所有
101
+ shoplazza checkout list -a
102
+ ```
103
+
104
+ #### 预览extension
105
+ ```
106
+ shoplazza checkout preview
107
+ ```
108
+
109
+ ## Theme Develop
42
110
 
43
111
  ### Authenticate
44
112
 
@@ -1,4 +1,4 @@
1
- import { extend } from "@shoplazza/extension-ui";
1
+ import { extend } from "shoplazza-extension-ui";
2
2
 
3
3
  extend({
4
4
  extensionPoint: "Checkout::ShippingLinesTitle::RenderAfter",
@@ -1,4 +1,4 @@
1
- import { extend } from '@shoplazza/extension-ui';
1
+ import { extend } from 'shoplazza-extension-ui';
2
2
  import index from './index.html';
3
3
 
4
4
  function App() {
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": "1.0",
3
+ "deleteTarget": [],
4
+ "placeholder": {},
5
+ "templateName": "checkout",
6
+ "themeName": "",
7
+ "extensionId": "",
8
+ "extensionName": "product-list",
9
+ "extensionDescription": ""
10
+ }
@@ -0,0 +1,5 @@
1
+ const productList = CheckoutAPI.summary.getProductList();
2
+
3
+ console.debug('productList', productList);
4
+
5
+ // do something, such as report
@@ -1,4 +1,4 @@
1
- import { extend } from '@shoplazza/extension-ui';
1
+ import { extend } from 'shoplazza-extension-ui';
2
2
  import index from './index.html';
3
3
 
4
4
  function App() {
@@ -0,0 +1,121 @@
1
+ {
2
+ "name": "checkout-extension",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "checkout-extension",
9
+ "version": "1.0.0",
10
+ "license": "ISC",
11
+ "dependencies": {
12
+ "fs-extra": "11.1.1",
13
+ "shoplazza-extension-ui": "1.0.0"
14
+ },
15
+ "devDependencies": {}
16
+ },
17
+ "node_modules/fs-extra": {
18
+ "version": "11.1.1",
19
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz",
20
+ "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==",
21
+ "license": "MIT",
22
+ "dependencies": {
23
+ "graceful-fs": "^4.2.0",
24
+ "jsonfile": "^6.0.1",
25
+ "universalify": "^2.0.0"
26
+ },
27
+ "engines": {
28
+ "node": ">=14.14"
29
+ }
30
+ },
31
+ "node_modules/graceful-fs": {
32
+ "version": "4.2.11",
33
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
34
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
35
+ "license": "ISC"
36
+ },
37
+ "node_modules/js-tokens": {
38
+ "version": "4.0.0",
39
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
40
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
41
+ "license": "MIT"
42
+ },
43
+ "node_modules/jsonfile": {
44
+ "version": "6.1.0",
45
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
46
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
47
+ "license": "MIT",
48
+ "dependencies": {
49
+ "universalify": "^2.0.0"
50
+ },
51
+ "optionalDependencies": {
52
+ "graceful-fs": "^4.1.6"
53
+ }
54
+ },
55
+ "node_modules/loose-envify": {
56
+ "version": "1.4.0",
57
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
58
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
59
+ "license": "MIT",
60
+ "dependencies": {
61
+ "js-tokens": "^3.0.0 || ^4.0.0"
62
+ },
63
+ "bin": {
64
+ "loose-envify": "cli.js"
65
+ }
66
+ },
67
+ "node_modules/react": {
68
+ "version": "18.3.1",
69
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
70
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
71
+ "license": "MIT",
72
+ "dependencies": {
73
+ "loose-envify": "^1.1.0"
74
+ },
75
+ "engines": {
76
+ "node": ">=0.10.0"
77
+ }
78
+ },
79
+ "node_modules/react-dom": {
80
+ "version": "18.3.1",
81
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
82
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
83
+ "license": "MIT",
84
+ "dependencies": {
85
+ "loose-envify": "^1.1.0",
86
+ "scheduler": "^0.23.2"
87
+ },
88
+ "peerDependencies": {
89
+ "react": "^18.3.1"
90
+ }
91
+ },
92
+ "node_modules/scheduler": {
93
+ "version": "0.23.2",
94
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
95
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
96
+ "license": "MIT",
97
+ "dependencies": {
98
+ "loose-envify": "^1.1.0"
99
+ }
100
+ },
101
+ "node_modules/shoplazza-extension-ui": {
102
+ "version": "1.0.0",
103
+ "resolved": "https://registry.npmjs.org/shoplazza-extension-ui/-/shoplazza-extension-ui-1.0.0.tgz",
104
+ "integrity": "sha512-gW2sWnfyEXwbWfi9Sje4K+r0ECCHjF7lID/igWplMi8opOiTI+88JurPHuwtBAhC3V0T2WZvBlcykHWjNQzYBA==",
105
+ "license": "MIT",
106
+ "dependencies": {
107
+ "react": "^18.2.0",
108
+ "react-dom": "^18.2.0"
109
+ }
110
+ },
111
+ "node_modules/universalify": {
112
+ "version": "2.0.1",
113
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
114
+ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
115
+ "license": "MIT",
116
+ "engines": {
117
+ "node": ">= 10.0.0"
118
+ }
119
+ }
120
+ }
121
+ }
@@ -5,7 +5,7 @@
5
5
  "main": "index.js",
6
6
  "dependencies": {
7
7
  "fs-extra": "11.1.1",
8
- "@shoplazza/extension-ui": "2.0.8"
8
+ "shoplazza-extension-ui": "1.0.0"
9
9
  },
10
10
  "devDependencies": {},
11
11
  "scripts": {
@@ -39,11 +39,20 @@ request.interceptors.request.use((config) => {
39
39
  return config;
40
40
  });
41
41
 
42
+ const handleResponseError = (response)=>{
43
+ if (response.data?.status === 3 && response.data?.message === 'INVALID_ARGUMENT') {
44
+ throw `Invalid argument at ${response.config.url}`;
45
+ }else if(response.data?.status === 13 && response.data?.message === 'INTERNAL_ERROR'){
46
+ throw `Internal error at ${response.config.url}`;
47
+ }
48
+ }
49
+
42
50
  request.interceptors.response.use(
43
51
  (response) => {
44
52
  if (isDebug()) {
45
53
  console.log(`\n<== ${response.status}: ${response.config.url}`);
46
54
  }
55
+ handleResponseError(response);
47
56
  return response;
48
57
  },
49
58
  (error) => {
@@ -151,6 +160,10 @@ module.exports = {
151
160
  ...data
152
161
  }
153
162
  };
154
- return request({ url: PREVIEW_URL, method: 'POST', data });
163
+ const res = await request({ url: PREVIEW_URL, method: 'POST', data });
164
+ if (res.data?.status === 14 && res.data?.message === 'ITEM_UNAVAILABLE') {
165
+ throw 'Failed to generate a preview URL because your store currently has no available items.';
166
+ }
167
+ return res;
155
168
  }
156
169
  };
@@ -22,8 +22,7 @@ async function viteBuild(command) {
22
22
  });
23
23
  await build(viteConfig(pageEntry));
24
24
  } catch (err) {
25
- consoleError('build error: ', err);
26
- throw 'build_error';
25
+ throw 'build_error: ' + err;
27
26
  }
28
27
  }
29
28
 
@@ -41,7 +41,7 @@ async function deployExtension(extensionInfo) {
41
41
  {
42
42
  type: 'confirm',
43
43
  name: 'confirm',
44
- message: 'Are you sure you want to deploy?',
44
+ message: 'Are you sure you want to deploy?(After deployed, all users will be able to see this extension in the store.)',
45
45
  default: false
46
46
  }
47
47
  ]);
@@ -22,7 +22,7 @@ function makeCheckoutCommand(_program) {
22
22
  program
23
23
  .command('list')
24
24
  .description('fetch extension list.')
25
- .option('-i, --id <token>', 'extension id')
25
+ .option('-a, --all', 'show all extensions')
26
26
  .action(require('./pull'));
27
27
 
28
28
  program
@@ -4,7 +4,18 @@ const { verifyConfig } = require('./verify');
4
4
  module.exports = async (commands = {}) => {
5
5
  try {
6
6
  await verifyConfig(commands);
7
- const res = await api.getExtension();
8
- console.log(res.data?.extension_lists);
9
- } catch (err) {}
7
+ let data;
8
+ if (!commands.all) {
9
+ data = {
10
+ status: 'published'
11
+ };
12
+ }
13
+ const res = await api.getExtensionList(data);
14
+ const extensionList = res.data?.data?.extensions || [];
15
+ extensionList.forEach((extension) => {
16
+ console.log(`${extension.name || extension.extension_id}(${extension.publish_status}/${extension.extension_id})`);
17
+ });
18
+ } catch (error) {
19
+ error.response ? consoleError(`Error: ${error.response.status}-${error.response.config.url}`) : consoleError(error);
20
+ }
10
21
  };
@@ -22,13 +22,13 @@ module.exports = async () => {
22
22
  const extensionInfo = await initSelectedExtensionInfo();
23
23
  consoleBlue('Starting to build:');
24
24
  const composeCommands = {
25
- id: extensionInfo.name
25
+ id: extensionInfo.name || extensionInfo.extension_id
26
26
  }; // 兼容旧代码处理
27
27
  await viteBuild(composeCommands);
28
28
  consoleBlue('Starting to upload:');
29
29
  await uploadOSS(composeCommands);
30
30
  consoleBlue('Starting to push:');
31
- await pushExtension(composeCommands);
31
+ await pushExtension(composeCommands, extensionInfo);
32
32
  } catch (error) {
33
33
  error.response ? consoleError(`Error: ${error.response.status}-${error.response.config.url}`) : consoleError(error);
34
34
  }
@@ -63,21 +63,23 @@ async function uploadOSS(command) {
63
63
  * 发布
64
64
  * @returns
65
65
  */
66
- async function pushExtension(command) {
66
+ async function pushExtension(command, extraInfo) {
67
67
  const info = getExtensionInfo(command.id);
68
68
  const load = loading(`start push the extension ${info.id}.`).start();
69
69
  try {
70
70
  const config = getExtensionConfig(command.id);
71
+ // 兼容低版本extension配置文件
71
72
  const data = {
72
73
  resource_url: `https://cn.static.shoplazza.com/chick-extension/${info.distName}`,
73
74
  version: config.version,
74
75
  scope: '',
75
- template_name: config.templateName,
76
- theme_name: config.themeName,
77
- name: config.extensionName,
78
- description: config.extensionDescription
76
+ template_name: config.templateName || config.template_name,
77
+ theme_name: config.themeName || config.theme_name,
78
+ name: config.extensionName || config.extensionId,
79
+ description: config.extensionDescription || '',
80
+ extends_fields: JSON.stringify(config)
79
81
  };
80
- const isFirstPush = !config.extensionId; // 非首次推送
82
+ const isFirstPush = !extraInfo.extension_id; // 非首次推送
81
83
  if (!isFirstPush) {
82
84
  data.extension_id = config.extensionId;
83
85
  }
@@ -88,27 +90,31 @@ async function pushExtension(command) {
88
90
  if (isFirstPush) {
89
91
  setExtensionConfig(command.id, {
90
92
  ...config,
91
- extensionId: extensionInfo.extension_id
93
+ extensionId: extensionInfo.extension_id,
94
+ extensionName: extensionInfo.name,
92
95
  });
93
96
  }
94
97
 
98
+ load.stop();
99
+ consoleSuccess('Successfully pushed the extension.');
95
100
  // 预览
96
- const resp = await api.previewExtension({
97
- extension_id: extensionInfo.extension_id,
98
- id: extensionInfo.id
99
- });
100
- const checkoutUrl = resp.data?.data?.checkout_url;
101
- const { store: baseUrl } = getProjectConfig();
102
- const url = new URL(checkoutUrl, baseUrl);
103
- url.searchParams.append('step', 'contact_information');
101
+ try {
102
+ const resp = await api.previewExtension({
103
+ extension_id: extensionInfo.extension_id,
104
+ id: extensionInfo.id
105
+ });
106
+ const checkoutUrl = resp.data?.data?.checkout_url;
107
+ const { store: baseUrl } = getProjectConfig();
108
+ const url = new URL(checkoutUrl, baseUrl);
109
+ url.searchParams.append('step', 'contact_information');
110
+ consoleBlue(`Your extension's preview URL: ${url.toString()}`);
111
+ } catch (error) {
112
+ consoleError(error);
113
+ }
104
114
 
105
- consoleSuccess('\nSuccessfully pushed the extension.');
106
- consoleBlue(`Your extension's preview URL: ${url.toString()}`);
107
115
  } catch (err) {
108
- consoleError('\n Failed to push the extension: ', err);
109
- throw 'push_failed';
110
- } finally {
111
116
  load.stop();
117
+ throw '\nFailed to push the extension: ' + err;
112
118
  }
113
119
  }
114
120
 
@@ -1,4 +1,4 @@
1
- import { extend } from '@shoplazza/extension-ui';
1
+ import { extend } from 'shoplazza-extension-ui';
2
2
  import index from './index.html';
3
3
 
4
4
  function App() {
@@ -5,7 +5,7 @@
5
5
  "main": "index.js",
6
6
  "dependencies": {
7
7
  "fs-extra": "11.1.1",
8
- "@shoplazza/extension-ui": "2.0.8"
8
+ "shoplazza-extension-ui": "1.0.0"
9
9
  },
10
10
  "devDependencies": {},
11
11
  "scripts": {
@@ -27,13 +27,13 @@ async function undeployExtension(extensionInfo) {
27
27
  {
28
28
  type: 'confirm',
29
29
  name: 'confirm',
30
- message: 'Are you sure you want to undeploy?',
30
+ message: 'Are you sure you want to undeploy?(After undeployed, all users will not be able to see this extension in the store.)',
31
31
  default: false
32
32
  }
33
33
  ]);
34
34
  if (confirm) {
35
35
  await api.undeployExtension({ extension_id: extensionInfo.extension_id });
36
- consoleSuccess(`Successfully undeployed the extension '${extensionInfo.name}'.`);
36
+ consoleSuccess(`Successfully undeployed the extension '${extensionInfo.name || extensionInfo.extension_id}'.`);
37
37
  } else {
38
38
  consoleBlue('Undeploy cancelled');
39
39
  }
@@ -39,8 +39,7 @@ function getExtensionInfo(extensionId) {
39
39
  } else if (extensionId) {
40
40
  const extensionPath = path.join(cwd, !cwd.includes('/extensions') ? 'extensions' : '', extensionId);
41
41
  if (!fs.existsSync(extensionPath)) {
42
- consoleError(`The extension '${extensionId}' does not exist.`);
43
- throw `The extension '${extensionId}' does not exist.`;
42
+ throw `The extension '${extensionId}' does not exist in your local project.`;
44
43
  }
45
44
 
46
45
  result = {
@@ -120,7 +119,7 @@ function copyDir(srcDir, destDir) {
120
119
  */
121
120
  async function useSelectExtensionMode(extensionList = [], type = 'push') {
122
121
  const choices = extensionList.map((item, index) => ({
123
- name: (type === 'push' && index === 0) ? item.name : `${item.name}(${item.extension_id})`,
122
+ name: (type === 'push' && index === 0) ? item.name : `${item.name || item.extension_id}(${item.extension_id})`,
124
123
  value: item.extension_id
125
124
  }))
126
125
  if (!choices.length) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shoplazza-cli",
3
- "version": "0.1.8",
3
+ "version": "1.0.3",
4
4
  "description": "",
5
5
  "main": "bin/shoplazza",
6
6
  "engines": {
@@ -13,10 +13,6 @@
13
13
  "prettier": "prettier --write ./lib",
14
14
  "test": "jest --runInBand --forceExit"
15
15
  },
16
- "repository": {
17
- "type": "git",
18
- "url": "git@gitlab.shoplazza.site:shoplaza/frontend/openapi/shoplazza-cli.git"
19
- },
20
16
  "keywords": [],
21
17
  "author": "",
22
18
  "license": "ISC",
@@ -28,7 +24,6 @@
28
24
  "dependencies": {
29
25
  "@sentry/node": "^6.19.7",
30
26
  "@sentry/tracing": "^6.19.7",
31
- "@shoplazza/extension-ui": "^1.0.0",
32
27
  "adm-zip": "^0.5.9",
33
28
  "ali-oss": "^6.17.1",
34
29
  "archiver": "^5.3.1",