cyymall-cli 0.1.0 → 0.1.2
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 +14 -10
- package/bin/cyy.js +1 -1
- package/package.json +33 -33
- package/src/biz.js +14 -14
- package/src/cli.js +234 -208
- package/src/commands/apiCall.js +149 -149
- package/src/commands/auth.js +193 -19
- package/src/commands/cart.js +55 -55
- package/src/commands/order.js +399 -327
- package/src/commands/product.js +56 -56
- package/src/commands/serve.js +84 -84
- package/src/commands/shop.js +287 -287
- package/src/config.js +82 -82
- package/src/embeddedCyyKeys.js +16 -0
- package/src/encrypt.js +434 -0
- package/src/http.js +30 -3
package/src/commands/shop.js
CHANGED
|
@@ -1,287 +1,287 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const crypto = require("crypto");
|
|
4
|
-
const http = require("../http");
|
|
5
|
-
const config = require("../config");
|
|
6
|
-
const biz = require("../biz");
|
|
7
|
-
|
|
8
|
-
function envelope(success, message, upstream, exitCode) {
|
|
9
|
-
const traceId = `local-${crypto.randomBytes(8).toString("hex")}`;
|
|
10
|
-
console.log(
|
|
11
|
-
JSON.stringify(
|
|
12
|
-
{
|
|
13
|
-
success,
|
|
14
|
-
code: success ? "OK" : "UPSTREAM_ERROR",
|
|
15
|
-
message,
|
|
16
|
-
data: { upstream },
|
|
17
|
-
traceId,
|
|
18
|
-
},
|
|
19
|
-
null,
|
|
20
|
-
2,
|
|
21
|
-
),
|
|
22
|
-
);
|
|
23
|
-
process.exit(exitCode ?? (success ? 0 : 2));
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* POST /mall-multishop/shop/member/list — 当前会员门店分页(Body: GetShopReq)
|
|
28
|
-
* @param {{ page?: string, pageSize?: string, name?: string, objectCode?: string }} opts
|
|
29
|
-
*/
|
|
30
|
-
async function list(opts) {
|
|
31
|
-
const cfg = config.loadConfig();
|
|
32
|
-
if (!cfg?.token) {
|
|
33
|
-
console.error("cyy: not logged in. Run: cyy auth login");
|
|
34
|
-
process.exit(1);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const body = JSON.stringify({
|
|
38
|
-
pageNum: Number(opts.page || 1),
|
|
39
|
-
pageSize: Number(opts.pageSize || 20),
|
|
40
|
-
shopName: opts.name ?? "",
|
|
41
|
-
objectCode: Number(opts.objectCode ?? 3),
|
|
42
|
-
deliveryAddressProvince: "",
|
|
43
|
-
deliveryAddressCity: "",
|
|
44
|
-
deliveryAddressArea: "",
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const url = http.moduleUrl("DEFAULT", "/shop/member/list");
|
|
48
|
-
const headers = /** @type {Record<string,string>} */ (http.buildAuthHeaders(cfg));
|
|
49
|
-
|
|
50
|
-
const { ok, json } = await http.request(url, {
|
|
51
|
-
method: "POST",
|
|
52
|
-
headers,
|
|
53
|
-
body,
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
const success = ok && biz.isBizSuccess(json);
|
|
57
|
-
envelope(success, success ? "success" : "shop list failed", json, success ? 0 : 2);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* GET /mall-multishop/shop/member/store/list — 指定门店下的站点列表
|
|
62
|
-
* @param {{ shopId?: string, siteName?: string }} opts
|
|
63
|
-
*/
|
|
64
|
-
async function sites(opts) {
|
|
65
|
-
const cfg = config.loadConfig();
|
|
66
|
-
if (!cfg?.token) {
|
|
67
|
-
console.error("cyy: not logged in. Run: cyy auth login");
|
|
68
|
-
process.exit(1);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const shopId = opts.shopId ?? cfg.shop_id;
|
|
72
|
-
if (shopId === undefined || shopId === null || String(shopId).trim() === "") {
|
|
73
|
-
console.error("cyy: provide --shop-id or set shop_id in ~/.cyymall/config.json");
|
|
74
|
-
process.exit(1);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const base = http.moduleUrl("DEFAULT", "/shop/member/store/list");
|
|
78
|
-
const u = new URL(base);
|
|
79
|
-
u.searchParams.set("shopId", String(shopId));
|
|
80
|
-
if (opts.siteName != null && String(opts.siteName).length > 0) {
|
|
81
|
-
u.searchParams.set("siteName", String(opts.siteName));
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const headers = /** @type {Record<string,string>} */ (http.buildAuthHeaders(cfg));
|
|
85
|
-
delete headers["Content-Type"];
|
|
86
|
-
|
|
87
|
-
const { ok, json } = await http.request(u.toString(), {
|
|
88
|
-
method: "GET",
|
|
89
|
-
headers,
|
|
90
|
-
body: null,
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
const success = ok && biz.isBizSuccess(json);
|
|
94
|
-
envelope(success, success ? "success" : "site list failed", json, success ? 0 : 2);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* @param {unknown} json
|
|
99
|
-
* @returns {Array<Record<string, unknown>>}
|
|
100
|
-
*/
|
|
101
|
-
function parseSitesArray(json) {
|
|
102
|
-
if (!json || typeof json !== "object") return [];
|
|
103
|
-
const d = /** @type {{ data?: unknown }} */ (json).data;
|
|
104
|
-
return Array.isArray(d) ? /** @type {Array<Record<string, unknown>>} */ (d) : [];
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* @param {Record<string, unknown>} cfg
|
|
109
|
-
* @param {string|number} shopId
|
|
110
|
-
*/
|
|
111
|
-
async function fetchSitesJson(cfg, shopId) {
|
|
112
|
-
const base = http.moduleUrl("DEFAULT", "/shop/member/store/list");
|
|
113
|
-
const u = new URL(base);
|
|
114
|
-
u.searchParams.set("shopId", String(shopId));
|
|
115
|
-
const headers = /** @type {Record<string, string>} */ (http.buildAuthHeaders(cfg));
|
|
116
|
-
delete headers["Content-Type"];
|
|
117
|
-
return http.request(u.toString(), { method: "GET", headers, body: null });
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* @param {Array<Record<string, unknown>>} sitesList
|
|
122
|
-
* @param {string|number} siteId
|
|
123
|
-
*/
|
|
124
|
-
function siteIdInList(sitesList, siteId) {
|
|
125
|
-
const want = String(siteId);
|
|
126
|
-
return sitesList.some((row) => String(row.id) === want);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* @param {Record<string, unknown>} cfg
|
|
131
|
-
* @param {string|number} shopId
|
|
132
|
-
* @returns {Promise<boolean>}
|
|
133
|
-
*/
|
|
134
|
-
async function shopIdBelongsToMember(cfg, shopId) {
|
|
135
|
-
const target = Number(shopId);
|
|
136
|
-
if (Number.isNaN(target)) return false;
|
|
137
|
-
|
|
138
|
-
const url = http.moduleUrl("DEFAULT", "/shop/member/list");
|
|
139
|
-
const headers = /** @type {Record<string, string>} */ (http.buildAuthHeaders(cfg));
|
|
140
|
-
|
|
141
|
-
let page = 1;
|
|
142
|
-
const pageSize = 50;
|
|
143
|
-
for (;;) {
|
|
144
|
-
const body = JSON.stringify({
|
|
145
|
-
pageNum: page,
|
|
146
|
-
pageSize,
|
|
147
|
-
shopName: "",
|
|
148
|
-
objectCode: 3,
|
|
149
|
-
deliveryAddressProvince: "",
|
|
150
|
-
deliveryAddressCity: "",
|
|
151
|
-
deliveryAddressArea: "",
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
const { ok, json } = await http.request(url, {
|
|
155
|
-
method: "POST",
|
|
156
|
-
headers,
|
|
157
|
-
body,
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
if (!ok || !biz.isBizSuccess(json)) return false;
|
|
161
|
-
const data =
|
|
162
|
-
json && typeof json === "object" && "data" in json
|
|
163
|
-
? /** @type {{ data?: { list?: unknown[]; hasNextPage?: boolean } }} */ (json).data
|
|
164
|
-
: null;
|
|
165
|
-
const list = data && Array.isArray(data.list) ? data.list : [];
|
|
166
|
-
for (const row of list) {
|
|
167
|
-
const r = /** @type {{ id?: unknown }} */ (row);
|
|
168
|
-
if (Number(r.id) === target) return true;
|
|
169
|
-
}
|
|
170
|
-
if (!data?.hasNextPage) return false;
|
|
171
|
-
page += 1;
|
|
172
|
-
if (page > 200) return false;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Set default shop_id only in ~/.cyymall/config.json (does not change site_id).
|
|
178
|
-
* Validates id appears in POST /shop/member/list for current member.
|
|
179
|
-
* @param {{ shopId?: string }} opts
|
|
180
|
-
*/
|
|
181
|
-
async function useShop(opts) {
|
|
182
|
-
const cfg = config.loadConfig();
|
|
183
|
-
if (!cfg?.token) {
|
|
184
|
-
console.error("cyy: not logged in. Run: cyy auth login");
|
|
185
|
-
process.exit(1);
|
|
186
|
-
}
|
|
187
|
-
const shopId = opts.shopId;
|
|
188
|
-
if (shopId === undefined || shopId === null || String(shopId).trim() === "") {
|
|
189
|
-
console.error("cyy: shop use requires --shop-id");
|
|
190
|
-
process.exit(1);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const belongs = await shopIdBelongsToMember(cfg, shopId);
|
|
194
|
-
if (!belongs) {
|
|
195
|
-
console.error("cyy: shop id not in your shop list (see: cyy shop list)");
|
|
196
|
-
process.exit(2);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const prev = config.loadConfig() || {};
|
|
200
|
-
const saved = {
|
|
201
|
-
...prev,
|
|
202
|
-
shop_id: Number(shopId),
|
|
203
|
-
};
|
|
204
|
-
config.saveConfig(saved);
|
|
205
|
-
|
|
206
|
-
const traceId = `local-${crypto.randomBytes(8).toString("hex")}`;
|
|
207
|
-
console.log(
|
|
208
|
-
JSON.stringify(
|
|
209
|
-
{
|
|
210
|
-
success: true,
|
|
211
|
-
code: "OK",
|
|
212
|
-
message:
|
|
213
|
-
"default shop_id updated; site_id unchanged — use shop sites + shop use-site if you need a different site",
|
|
214
|
-
data: {
|
|
215
|
-
shop_id: saved.shop_id,
|
|
216
|
-
site_id: saved.site_id,
|
|
217
|
-
},
|
|
218
|
-
traceId,
|
|
219
|
-
},
|
|
220
|
-
null,
|
|
221
|
-
2,
|
|
222
|
-
),
|
|
223
|
-
);
|
|
224
|
-
process.exit(0);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Switch default site only for current session shop_id.
|
|
229
|
-
* @param {{ siteId?: string }} opts
|
|
230
|
-
*/
|
|
231
|
-
async function useSite(opts) {
|
|
232
|
-
const cfg = config.loadConfig();
|
|
233
|
-
if (!cfg?.token) {
|
|
234
|
-
console.error("cyy: not logged in. Run: cyy auth login");
|
|
235
|
-
process.exit(1);
|
|
236
|
-
}
|
|
237
|
-
const shopId = cfg.shop_id;
|
|
238
|
-
if (shopId === undefined || shopId === null || String(shopId).trim() === "") {
|
|
239
|
-
console.error("cyy: no shop_id in session; run: cyy shop use --shop-id <id>");
|
|
240
|
-
process.exit(1);
|
|
241
|
-
}
|
|
242
|
-
const siteId = opts.siteId;
|
|
243
|
-
if (siteId === undefined || siteId === null || String(siteId).trim() === "") {
|
|
244
|
-
console.error("cyy: shop use-site requires --site-id");
|
|
245
|
-
process.exit(1);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
const { ok, json } = await fetchSitesJson(cfg, shopId);
|
|
249
|
-
if (!ok || !biz.isBizSuccess(json)) {
|
|
250
|
-
console.error("cyy: failed to load sites for current shop");
|
|
251
|
-
process.exit(2);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
const sitesList = parseSitesArray(json);
|
|
255
|
-
if (!siteIdInList(sitesList, siteId)) {
|
|
256
|
-
console.error("cyy: --site-id is not valid for current shop; run: cyy shop sites");
|
|
257
|
-
process.exit(2);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const prev = config.loadConfig() || {};
|
|
261
|
-
const saved = {
|
|
262
|
-
...prev,
|
|
263
|
-
site_id: String(siteId),
|
|
264
|
-
};
|
|
265
|
-
config.saveConfig(saved);
|
|
266
|
-
|
|
267
|
-
const traceId = `local-${crypto.randomBytes(8).toString("hex")}`;
|
|
268
|
-
console.log(
|
|
269
|
-
JSON.stringify(
|
|
270
|
-
{
|
|
271
|
-
success: true,
|
|
272
|
-
code: "OK",
|
|
273
|
-
message: "default site updated",
|
|
274
|
-
data: {
|
|
275
|
-
shop_id: saved.shop_id,
|
|
276
|
-
site_id: saved.site_id,
|
|
277
|
-
},
|
|
278
|
-
traceId,
|
|
279
|
-
},
|
|
280
|
-
null,
|
|
281
|
-
2,
|
|
282
|
-
),
|
|
283
|
-
);
|
|
284
|
-
process.exit(0);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
module.exports = { list, sites, useShop, useSite };
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const crypto = require("crypto");
|
|
4
|
+
const http = require("../http");
|
|
5
|
+
const config = require("../config");
|
|
6
|
+
const biz = require("../biz");
|
|
7
|
+
|
|
8
|
+
function envelope(success, message, upstream, exitCode) {
|
|
9
|
+
const traceId = `local-${crypto.randomBytes(8).toString("hex")}`;
|
|
10
|
+
console.log(
|
|
11
|
+
JSON.stringify(
|
|
12
|
+
{
|
|
13
|
+
success,
|
|
14
|
+
code: success ? "OK" : "UPSTREAM_ERROR",
|
|
15
|
+
message,
|
|
16
|
+
data: { upstream },
|
|
17
|
+
traceId,
|
|
18
|
+
},
|
|
19
|
+
null,
|
|
20
|
+
2,
|
|
21
|
+
),
|
|
22
|
+
);
|
|
23
|
+
process.exit(exitCode ?? (success ? 0 : 2));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* POST /mall-multishop/shop/member/list — 当前会员门店分页(Body: GetShopReq)
|
|
28
|
+
* @param {{ page?: string, pageSize?: string, name?: string, objectCode?: string }} opts
|
|
29
|
+
*/
|
|
30
|
+
async function list(opts) {
|
|
31
|
+
const cfg = config.loadConfig();
|
|
32
|
+
if (!cfg?.token) {
|
|
33
|
+
console.error("cyy: not logged in. Run: cyy auth login");
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const body = JSON.stringify({
|
|
38
|
+
pageNum: Number(opts.page || 1),
|
|
39
|
+
pageSize: Number(opts.pageSize || 20),
|
|
40
|
+
shopName: opts.name ?? "",
|
|
41
|
+
objectCode: Number(opts.objectCode ?? 3),
|
|
42
|
+
deliveryAddressProvince: "",
|
|
43
|
+
deliveryAddressCity: "",
|
|
44
|
+
deliveryAddressArea: "",
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const url = http.moduleUrl("DEFAULT", "/shop/member/list");
|
|
48
|
+
const headers = /** @type {Record<string,string>} */ (http.buildAuthHeaders(cfg));
|
|
49
|
+
|
|
50
|
+
const { ok, json } = await http.request(url, {
|
|
51
|
+
method: "POST",
|
|
52
|
+
headers,
|
|
53
|
+
body,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const success = ok && biz.isBizSuccess(json);
|
|
57
|
+
envelope(success, success ? "success" : "shop list failed", json, success ? 0 : 2);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* GET /mall-multishop/shop/member/store/list — 指定门店下的站点列表
|
|
62
|
+
* @param {{ shopId?: string, siteName?: string }} opts
|
|
63
|
+
*/
|
|
64
|
+
async function sites(opts) {
|
|
65
|
+
const cfg = config.loadConfig();
|
|
66
|
+
if (!cfg?.token) {
|
|
67
|
+
console.error("cyy: not logged in. Run: cyy auth login");
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const shopId = opts.shopId ?? cfg.shop_id;
|
|
72
|
+
if (shopId === undefined || shopId === null || String(shopId).trim() === "") {
|
|
73
|
+
console.error("cyy: provide --shop-id or set shop_id in ~/.cyymall/config.json");
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const base = http.moduleUrl("DEFAULT", "/shop/member/store/list");
|
|
78
|
+
const u = new URL(base);
|
|
79
|
+
u.searchParams.set("shopId", String(shopId));
|
|
80
|
+
if (opts.siteName != null && String(opts.siteName).length > 0) {
|
|
81
|
+
u.searchParams.set("siteName", String(opts.siteName));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const headers = /** @type {Record<string,string>} */ (http.buildAuthHeaders(cfg));
|
|
85
|
+
delete headers["Content-Type"];
|
|
86
|
+
|
|
87
|
+
const { ok, json } = await http.request(u.toString(), {
|
|
88
|
+
method: "GET",
|
|
89
|
+
headers,
|
|
90
|
+
body: null,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const success = ok && biz.isBizSuccess(json);
|
|
94
|
+
envelope(success, success ? "success" : "site list failed", json, success ? 0 : 2);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {unknown} json
|
|
99
|
+
* @returns {Array<Record<string, unknown>>}
|
|
100
|
+
*/
|
|
101
|
+
function parseSitesArray(json) {
|
|
102
|
+
if (!json || typeof json !== "object") return [];
|
|
103
|
+
const d = /** @type {{ data?: unknown }} */ (json).data;
|
|
104
|
+
return Array.isArray(d) ? /** @type {Array<Record<string, unknown>>} */ (d) : [];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @param {Record<string, unknown>} cfg
|
|
109
|
+
* @param {string|number} shopId
|
|
110
|
+
*/
|
|
111
|
+
async function fetchSitesJson(cfg, shopId) {
|
|
112
|
+
const base = http.moduleUrl("DEFAULT", "/shop/member/store/list");
|
|
113
|
+
const u = new URL(base);
|
|
114
|
+
u.searchParams.set("shopId", String(shopId));
|
|
115
|
+
const headers = /** @type {Record<string, string>} */ (http.buildAuthHeaders(cfg));
|
|
116
|
+
delete headers["Content-Type"];
|
|
117
|
+
return http.request(u.toString(), { method: "GET", headers, body: null });
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @param {Array<Record<string, unknown>>} sitesList
|
|
122
|
+
* @param {string|number} siteId
|
|
123
|
+
*/
|
|
124
|
+
function siteIdInList(sitesList, siteId) {
|
|
125
|
+
const want = String(siteId);
|
|
126
|
+
return sitesList.some((row) => String(row.id) === want);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @param {Record<string, unknown>} cfg
|
|
131
|
+
* @param {string|number} shopId
|
|
132
|
+
* @returns {Promise<boolean>}
|
|
133
|
+
*/
|
|
134
|
+
async function shopIdBelongsToMember(cfg, shopId) {
|
|
135
|
+
const target = Number(shopId);
|
|
136
|
+
if (Number.isNaN(target)) return false;
|
|
137
|
+
|
|
138
|
+
const url = http.moduleUrl("DEFAULT", "/shop/member/list");
|
|
139
|
+
const headers = /** @type {Record<string, string>} */ (http.buildAuthHeaders(cfg));
|
|
140
|
+
|
|
141
|
+
let page = 1;
|
|
142
|
+
const pageSize = 50;
|
|
143
|
+
for (;;) {
|
|
144
|
+
const body = JSON.stringify({
|
|
145
|
+
pageNum: page,
|
|
146
|
+
pageSize,
|
|
147
|
+
shopName: "",
|
|
148
|
+
objectCode: 3,
|
|
149
|
+
deliveryAddressProvince: "",
|
|
150
|
+
deliveryAddressCity: "",
|
|
151
|
+
deliveryAddressArea: "",
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const { ok, json } = await http.request(url, {
|
|
155
|
+
method: "POST",
|
|
156
|
+
headers,
|
|
157
|
+
body,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
if (!ok || !biz.isBizSuccess(json)) return false;
|
|
161
|
+
const data =
|
|
162
|
+
json && typeof json === "object" && "data" in json
|
|
163
|
+
? /** @type {{ data?: { list?: unknown[]; hasNextPage?: boolean } }} */ (json).data
|
|
164
|
+
: null;
|
|
165
|
+
const list = data && Array.isArray(data.list) ? data.list : [];
|
|
166
|
+
for (const row of list) {
|
|
167
|
+
const r = /** @type {{ id?: unknown }} */ (row);
|
|
168
|
+
if (Number(r.id) === target) return true;
|
|
169
|
+
}
|
|
170
|
+
if (!data?.hasNextPage) return false;
|
|
171
|
+
page += 1;
|
|
172
|
+
if (page > 200) return false;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Set default shop_id only in ~/.cyymall/config.json (does not change site_id).
|
|
178
|
+
* Validates id appears in POST /shop/member/list for current member.
|
|
179
|
+
* @param {{ shopId?: string }} opts
|
|
180
|
+
*/
|
|
181
|
+
async function useShop(opts) {
|
|
182
|
+
const cfg = config.loadConfig();
|
|
183
|
+
if (!cfg?.token) {
|
|
184
|
+
console.error("cyy: not logged in. Run: cyy auth login");
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
const shopId = opts.shopId;
|
|
188
|
+
if (shopId === undefined || shopId === null || String(shopId).trim() === "") {
|
|
189
|
+
console.error("cyy: shop use requires --shop-id");
|
|
190
|
+
process.exit(1);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const belongs = await shopIdBelongsToMember(cfg, shopId);
|
|
194
|
+
if (!belongs) {
|
|
195
|
+
console.error("cyy: shop id not in your shop list (see: cyy shop list)");
|
|
196
|
+
process.exit(2);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const prev = config.loadConfig() || {};
|
|
200
|
+
const saved = {
|
|
201
|
+
...prev,
|
|
202
|
+
shop_id: Number(shopId),
|
|
203
|
+
};
|
|
204
|
+
config.saveConfig(saved);
|
|
205
|
+
|
|
206
|
+
const traceId = `local-${crypto.randomBytes(8).toString("hex")}`;
|
|
207
|
+
console.log(
|
|
208
|
+
JSON.stringify(
|
|
209
|
+
{
|
|
210
|
+
success: true,
|
|
211
|
+
code: "OK",
|
|
212
|
+
message:
|
|
213
|
+
"default shop_id updated; site_id unchanged — use shop sites + shop use-site if you need a different site",
|
|
214
|
+
data: {
|
|
215
|
+
shop_id: saved.shop_id,
|
|
216
|
+
site_id: saved.site_id,
|
|
217
|
+
},
|
|
218
|
+
traceId,
|
|
219
|
+
},
|
|
220
|
+
null,
|
|
221
|
+
2,
|
|
222
|
+
),
|
|
223
|
+
);
|
|
224
|
+
process.exit(0);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Switch default site only for current session shop_id.
|
|
229
|
+
* @param {{ siteId?: string }} opts
|
|
230
|
+
*/
|
|
231
|
+
async function useSite(opts) {
|
|
232
|
+
const cfg = config.loadConfig();
|
|
233
|
+
if (!cfg?.token) {
|
|
234
|
+
console.error("cyy: not logged in. Run: cyy auth login");
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
237
|
+
const shopId = cfg.shop_id;
|
|
238
|
+
if (shopId === undefined || shopId === null || String(shopId).trim() === "") {
|
|
239
|
+
console.error("cyy: no shop_id in session; run: cyy shop use --shop-id <id>");
|
|
240
|
+
process.exit(1);
|
|
241
|
+
}
|
|
242
|
+
const siteId = opts.siteId;
|
|
243
|
+
if (siteId === undefined || siteId === null || String(siteId).trim() === "") {
|
|
244
|
+
console.error("cyy: shop use-site requires --site-id");
|
|
245
|
+
process.exit(1);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const { ok, json } = await fetchSitesJson(cfg, shopId);
|
|
249
|
+
if (!ok || !biz.isBizSuccess(json)) {
|
|
250
|
+
console.error("cyy: failed to load sites for current shop");
|
|
251
|
+
process.exit(2);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const sitesList = parseSitesArray(json);
|
|
255
|
+
if (!siteIdInList(sitesList, siteId)) {
|
|
256
|
+
console.error("cyy: --site-id is not valid for current shop; run: cyy shop sites");
|
|
257
|
+
process.exit(2);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const prev = config.loadConfig() || {};
|
|
261
|
+
const saved = {
|
|
262
|
+
...prev,
|
|
263
|
+
site_id: String(siteId),
|
|
264
|
+
};
|
|
265
|
+
config.saveConfig(saved);
|
|
266
|
+
|
|
267
|
+
const traceId = `local-${crypto.randomBytes(8).toString("hex")}`;
|
|
268
|
+
console.log(
|
|
269
|
+
JSON.stringify(
|
|
270
|
+
{
|
|
271
|
+
success: true,
|
|
272
|
+
code: "OK",
|
|
273
|
+
message: "default site updated",
|
|
274
|
+
data: {
|
|
275
|
+
shop_id: saved.shop_id,
|
|
276
|
+
site_id: saved.site_id,
|
|
277
|
+
},
|
|
278
|
+
traceId,
|
|
279
|
+
},
|
|
280
|
+
null,
|
|
281
|
+
2,
|
|
282
|
+
),
|
|
283
|
+
);
|
|
284
|
+
process.exit(0);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
module.exports = { list, sites, useShop, useSite };
|