cyymall-cli 0.1.11 → 0.1.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cyymall-cli",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "CyyMall / 菜洋洋商城 API CLI (per app-api-cli-spec)",
5
5
  "bin": {
6
6
  "cyy": "bin/cyy.js"
@@ -19,7 +19,7 @@
19
19
  "scripts": {
20
20
  "start": "node bin/cyy.js",
21
21
  "lint": "node --check src/cli.js && node --check src/encrypt.js && node --check src/embeddedCyyKeys.js",
22
- "prepublishOnly": "node --check src/cli.js && node --check src/encrypt.js && node --check src/embeddedCyyKeys.js && node --check bin/cyy.js"
22
+ "prepublishOnly": "node --check src/cli.js && node --check src/cartProduct.js && node --check src/encrypt.js && node --check src/embeddedCyyKeys.js && node --check bin/cyy.js"
23
23
  },
24
24
  "keywords": [
25
25
  "cyymall",
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+
3
+ const http = require("./http");
4
+ const biz = require("./biz");
5
+
6
+ /**
7
+ * Search getSkuList; pick first hit; resolve price/unit from promotionList (matches `quick`/`checkout`).
8
+ * @param {Record<string, unknown>} cfg
9
+ * @param {{ keyword: string, shopId: number, siteId: number, quantity: number, unit: string }} opts
10
+ */
11
+ async function resolveProductLine(cfg, opts) {
12
+ const { keyword, shopId, siteId, quantity, unit } = opts;
13
+ const headers = /** @type {Record<string,string>} */ (http.buildAuthHeaders(cfg));
14
+
15
+ const searchUrl = http.moduleUrl("PRODUCT", "/app/product/getSkuList");
16
+ const searchBody = JSON.stringify({
17
+ pageNum: 1,
18
+ pageSize: 10,
19
+ shopId,
20
+ siteId,
21
+ spuName: keyword,
22
+ stockFlag: "0",
23
+ });
24
+
25
+ const r = await http.request(searchUrl, {
26
+ method: "POST",
27
+ headers,
28
+ body: searchBody,
29
+ });
30
+ if (!r.ok || !biz.isBizSuccess(r.json)) {
31
+ /** @type {Error & { cause?: unknown }} */
32
+ const err = new Error(`search failed for "${keyword}"`);
33
+ err.cause = r.json;
34
+ throw err;
35
+ }
36
+
37
+ const list =
38
+ r.json &&
39
+ typeof r.json === "object" &&
40
+ r.json.data &&
41
+ typeof r.json.data === "object"
42
+ ? /** @type {{ list?: unknown[] }} */ (r.json.data).list
43
+ : [];
44
+ const products = Array.isArray(list) ? list : [];
45
+ if (!products.length) {
46
+ throw new Error(`no products found for "${keyword}"`);
47
+ }
48
+
49
+ const product = /** @type {Record<string, unknown>} */ (products[0]);
50
+ const skuId = Number(product.id);
51
+ const skuCode = String(product.skuCode || "");
52
+ const skuName = String(product.spuName || "");
53
+ const stockQty = Number(product.stockAllQuantity ?? 0);
54
+ const promotionList = Array.isArray(product.promotionList) ? product.promotionList : [];
55
+
56
+ let price = 0;
57
+ let unitRate = 1;
58
+ let skuSaleUnit = unit;
59
+ for (const p of promotionList) {
60
+ const row = /** @type {Record<string, unknown>} */ (p);
61
+ if (row.skuSaleUnitName === unit) {
62
+ price = Number(row.salePrice || 0);
63
+ unitRate = Number(row.unitRate ?? 1);
64
+ skuSaleUnit = String(row.skuSaleUnitName || unit);
65
+ break;
66
+ }
67
+ }
68
+ if (!price) {
69
+ const availableUnits = promotionList.map(
70
+ (x) => /** @type {{ skuSaleUnitName?: string }} */ (x).skuSaleUnitName,
71
+ );
72
+ const err = new Error(`unit "${unit}" not found in promotionList for "${keyword}"`);
73
+ /** @type {Error & { availableUnits?: (string | undefined)[] }} */ (err).availableUnits = availableUnits;
74
+ throw err;
75
+ }
76
+
77
+ return {
78
+ skuId,
79
+ skuCode,
80
+ skuName,
81
+ skuQty: quantity,
82
+ skuSaleUnit,
83
+ listPrice: price,
84
+ salePrice: price,
85
+ unitRate,
86
+ stockQty,
87
+ };
88
+ }
89
+
90
+ module.exports = { resolveProductLine };
@@ -406,13 +406,27 @@ async function checkout(opts) {
406
406
  for (const spec of itemSpecs) {
407
407
  const kw = spec.keyword;
408
408
  if (!kw) continue;
409
- const line = await resolveProductLine(cfg, {
410
- keyword: kw,
411
- shopId,
412
- siteId,
413
- quantity: Number(spec.quantity ?? quantity),
414
- unit: String(spec.unit ?? unit),
415
- });
409
+ let line;
410
+ try {
411
+ line = await resolveProductLine(cfg, {
412
+ keyword: kw,
413
+ shopId,
414
+ siteId,
415
+ quantity: Number(spec.quantity ?? quantity),
416
+ unit: String(spec.unit ?? unit),
417
+ });
418
+ } catch (e) {
419
+ const msg = /** @type {Error & { cause?: unknown, availableUnits?: unknown }} */ (
420
+ typeof e === "object" && e !== null ? e : { message: String(e) }
421
+ );
422
+ envelope(
423
+ false,
424
+ msg.message || String(e),
425
+ { keyword: kw, upstream: msg.cause, availableUnits: msg.availableUnits },
426
+ 2,
427
+ );
428
+ return;
429
+ }
416
430
  lines.push(line);
417
431
  cartItemList.push({
418
432
  skuCode: line.skuCode,
package/src/Untitled DELETED
@@ -1 +0,0 @@
1
- shop