@optima-chat/tiktok-cli 0.16.1 → 0.17.0
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 +25 -0
- package/dist/index.js +188 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -115,6 +115,31 @@ tiktok products set-price --shop <id> --product <pid> --sku <sid> --price 29.90
|
|
|
115
115
|
|
|
116
116
|
**秒杀字段坑**(OAS 未标、实测撞出):商品级 `quantity_limit` 在 VARIATION 模式必须 `-1`(限量由 SKU 级控制);秒杀价须**低于该 SKU 近 30 天最低成交价**且**不超折扣上限**。这些复杂度被 CLI 吸收,agent 一次成型。
|
|
117
117
|
|
|
118
|
+
## 写命令参数清单(`tiktok schema --json`)
|
|
119
|
+
|
|
120
|
+
给 Optima COO 的「写入数值守门」用(#56;optima-coo 的设计文档 `2026-10-01-optima-coo-write-value-guard-design.md` §4.2):COO 放行一条 `tiktok … --apply` 之前,按这份清单把命令里的数换算成店主口径,再和店主批过的 playbook 核对。
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
tiktok schema --json > tiktok-cli@$(node -p "require('./package.json').version").json # 不需要 --shop;输出裸 JSON,不包 {ok,data}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
- 覆盖每条 `write: true` 的命令;每个参数恰好落在一处:`params`(带钱的,写 `semantic` 和单位:`type` / `pair` / `factor` / `means` / `scale` / `currency_flag` / `currency_default`)、`subject`(作用对象)、`unchecked`(不是钱:id、标题、小时数、库存)、`opaque`(数值藏在文件里:`--body-file`)。每条命令都认的 `--shop` / `--actor` / `--apply` / `--help` 在顶层 `global_flags`。
|
|
127
|
+
- 标注写在 `src/commands.ts` 每条写命令的 `values` 上(和 `flags` 挨着),`src/schema.ts` 生成并自查:漏写、一个参数写两处、钱没写币种、折扣没写 `means` ⇒ 当场抛错;`tests/schema.test.mts` 钉着。**加写命令或参数时一起改 `values`。**
|
|
128
|
+
- 词表(`semantic`)以 optima-coo `packages/contracts/src/value-guard.ts` 的 `VALUE_SEMANTICS` 为准。
|
|
129
|
+
- `version` 取自 `package.json`。COO 按版本固定清单副本,**改了任何写命令的参数就要发新版本**,否则 COO 那边按旧清单核对。
|
|
130
|
+
- 没有 `repeatable` 的参数:同一个参数写两次 CLI 取后者,COO 按写法错误退回;多个值用逗号连成一个(`--price A:12,B:15`)。
|
|
131
|
+
|
|
132
|
+
数值范围(validate 里查,dry-run 与 `--apply` 共用、在发请求之前):
|
|
133
|
+
|
|
134
|
+
| 参数 | 范围 |
|
|
135
|
+
|---|---|
|
|
136
|
+
| `affiliate open-collab set-commission --rate` | 800–8000 的整数(单位百分比×100:1350 = 13.5%,8%–80%);必填 |
|
|
137
|
+
| `affiliate open-collab settings edit --rate` | 给了就必须是 1–10000 的整数(不超过 100%) |
|
|
138
|
+
| `promotions create-flashsale --hours` | 大于 0、小于 72(平台硬上限) |
|
|
139
|
+
| `products set-price --price`、`promotions create-flashsale --price` | 大于 0 的十进制数,最多两位小数,不要前导零和币种符号;必填 |
|
|
140
|
+
|
|
141
|
+
dry-run 的 `plan[].human` 写换算后的店主口径:改价「SKU S 售价改为 29.90 MYR」、秒杀「秒杀价 9.90 MYR,限量 100 件……持续 48 小时」、佣金「佣金率设为 13.5%(--rate 1350)」、折扣「减 85%(按原价 15% 售卖)」。
|
|
142
|
+
|
|
118
143
|
## 错误分类(agent 靠此决策)
|
|
119
144
|
|
|
120
145
|
`error.code` + `retryable` 让 agent 判断重试还是停止:
|
package/dist/index.js
CHANGED
|
@@ -354,6 +354,13 @@ var ADD_TEXT = {
|
|
|
354
354
|
AN3_MIS: "\u503C\u4E0D\u7B26\u7684\u6309\u8BFB\u56DE\u7684\u503C\u751F\u6548\uFF0C\u6539\u4EF7 / \u6539\u6298\u6263\u4E0D\u5728\u672C\u547D\u4EE4\u8303\u56F4\u3002",
|
|
355
355
|
AN4: (shop, id) => `\u52A0\u5546\u54C1\u5931\u8D25\uFF0C\u56DE\u8BFB\u4E5F\u5931\u8D25\u4E86\uFF0C\u67E5\u4E0D\u5230\u6D3B\u52A8 ${id} \u91CC\u672C\u6B21\u7684 SKU \u6709\u6CA1\u6709\u6302\u4E0A\u3002\u5148\u7528 \`tiktok promotions get --shop ${shop} --id ${id}\` \u6838\u5BF9\uFF0C\u518D\u51B3\u5B9A\u662F\u5426\u91CD\u8DD1\uFF08\u5DF2\u6302\u4E0A\u7684\u4F1A\u5728\u9884\u8BFB\u90A3\u6B65\u88AB\u8BC6\u522B\uFF0C\u91CD\u8DD1\u4E0D\u4F1A\u91CD\u590D\u52A0\uFF09\u3002`
|
|
356
356
|
};
|
|
357
|
+
var DISCOUNT_VALUE_PARAMS = {
|
|
358
|
+
// 一口价不带币种,平台按店铺本币收;本 CLI 只接马来站 ⇒ MYR。PRICE_ITEM 只收两位小数
|
|
359
|
+
price: { semantic: "promo_price", type: "pairs", pair: ["sku_id", "decimal"], scale: 2, currency_default: "MYR" },
|
|
360
|
+
// PCT_ITEM:1–99 的整数,「减 N%」(85 = 按原价 15% 卖)
|
|
361
|
+
percent: { semantic: "discount_pct", type: "pairs", pair: ["sku_id", "int"], means: "off" }
|
|
362
|
+
};
|
|
363
|
+
var COMMISSION_RATE = { semantic: "commission_pct", type: "int", factor: 0.01 };
|
|
357
364
|
var COMMANDS = [
|
|
358
365
|
{
|
|
359
366
|
name: "orders list",
|
|
@@ -478,6 +485,7 @@ var COMMANDS = [
|
|
|
478
485
|
summary: "\u6279\u51C6\u53D6\u6D88\u5355\uFF08--id cancel_id\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u6279\u3002\u4E0D\u53EF\u9006",
|
|
479
486
|
flags: ["id"],
|
|
480
487
|
write: true,
|
|
488
|
+
values: { unchecked: ["id"] },
|
|
481
489
|
preview: ({ args: args2 }) => [{
|
|
482
490
|
step: "\u6279\u51C6\u53D6\u6D88\u5355",
|
|
483
491
|
method: "POST",
|
|
@@ -491,6 +499,7 @@ var COMMANDS = [
|
|
|
491
499
|
summary: "\u9A73\u56DE\u53D6\u6D88\u5355\uFF08--id --reason\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u9A73\u3002\u4E0D\u53EF\u9006",
|
|
492
500
|
flags: ["id", "reason"],
|
|
493
501
|
write: true,
|
|
502
|
+
values: { unchecked: ["id", "reason"] },
|
|
494
503
|
preview: ({ args: args2 }) => [{
|
|
495
504
|
step: "\u9A73\u56DE\u53D6\u6D88\u5355",
|
|
496
505
|
method: "POST",
|
|
@@ -509,6 +518,7 @@ var COMMANDS = [
|
|
|
509
518
|
summary: "\u6279\u51C6\u9000\u8D27\u5355\uFF08--id return_id\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u6279\u3002\u4E0D\u53EF\u9006",
|
|
510
519
|
flags: ["id"],
|
|
511
520
|
write: true,
|
|
521
|
+
values: { unchecked: ["id"] },
|
|
512
522
|
preview: ({ args: args2 }) => [{
|
|
513
523
|
step: "\u6279\u51C6\u9000\u8D27\u5355",
|
|
514
524
|
method: "POST",
|
|
@@ -522,6 +532,7 @@ var COMMANDS = [
|
|
|
522
532
|
summary: "\u9A73\u56DE\u9000\u8D27\u5355\uFF08--id --reason\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u9A73\u3002\u4E0D\u53EF\u9006",
|
|
523
533
|
flags: ["id", "reason"],
|
|
524
534
|
write: true,
|
|
535
|
+
values: { unchecked: ["id", "reason"] },
|
|
525
536
|
preview: ({ args: args2 }) => [{
|
|
526
537
|
step: "\u9A73\u56DE\u9000\u8D27\u5355",
|
|
527
538
|
method: "POST",
|
|
@@ -540,6 +551,7 @@ var COMMANDS = [
|
|
|
540
551
|
summary: "\u4E3A\u8BA2\u5355\u5EFA\u5305\u88F9\uFF08--order id --body-file pkg.json\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u5EFA\u3002\u4EC5\u76F4\u53D1\u5546\u5BB6\uFF08\u7269\u6D41\u9ED8\u8BA4 ERP \u7BA1\uFF09",
|
|
541
552
|
flags: ["body-file", "order"],
|
|
542
553
|
write: true,
|
|
554
|
+
values: { unchecked: ["order"], opaque: ["body-file"] },
|
|
543
555
|
preview: ({ args: args2 }) => [{
|
|
544
556
|
step: "\u5EFA\u5305\u88F9",
|
|
545
557
|
method: "POST",
|
|
@@ -558,6 +570,7 @@ var COMMANDS = [
|
|
|
558
570
|
summary: "\u53D1\u8D27\uFF08--package id --body-file ship.json\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u53D1\u3002\u4E0D\u53EF\u9006\uFF0C\u4EC5\u76F4\u53D1\u5546\u5BB6",
|
|
559
571
|
flags: ["body-file", "package"],
|
|
560
572
|
write: true,
|
|
573
|
+
values: { unchecked: ["package"], opaque: ["body-file"] },
|
|
561
574
|
preview: ({ args: args2 }) => [{
|
|
562
575
|
step: "\u53D1\u8D27",
|
|
563
576
|
method: "POST",
|
|
@@ -590,6 +603,7 @@ var COMMANDS = [
|
|
|
590
603
|
summary: "\u6807\u4E8B\u4EF6\u5DF2\u5904\u7406\uFF08--ids id1,id2 \u6216 --before <ts>\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u6807",
|
|
591
604
|
flags: ["before", "ids"],
|
|
592
605
|
write: true,
|
|
606
|
+
values: { unchecked: ["before", "ids"] },
|
|
593
607
|
preview: ({ args: args2 }) => [{
|
|
594
608
|
step: "\u6807\u4E8B\u4EF6\u5DF2\u5904\u7406",
|
|
595
609
|
method: "POST",
|
|
@@ -946,28 +960,45 @@ var COMMANDS = [
|
|
|
946
960
|
// ===== 写操作(Phase 2):默认 --dry-run,--apply 才真发,成功后回读 =====
|
|
947
961
|
{
|
|
948
962
|
name: "products set-price",
|
|
949
|
-
summary: "\u6539 SKU \u552E\u4EF7\uFF08--product --sku --price [--currency MYR]\uFF09\u3002\u5199\u64CD\u4F5C,\u9ED8\u8BA4 dry-run",
|
|
963
|
+
summary: "\u6539 SKU \u552E\u4EF7\uFF08--product --sku --price [--currency MYR]\uFF0C\u4EF7\u683C\u5927\u4E8E 0\u3001\u6700\u591A\u4E24\u4F4D\u5C0F\u6570\uFF09\u3002\u5199\u64CD\u4F5C,\u9ED8\u8BA4 dry-run",
|
|
950
964
|
flags: ["currency", "price", "product", "sku"],
|
|
951
965
|
write: true,
|
|
966
|
+
validate: validateSetPrice,
|
|
967
|
+
values: {
|
|
968
|
+
subject: { flag: "sku", kind: "sku_id" },
|
|
969
|
+
params: {
|
|
970
|
+
price: { semantic: "list_price", type: "decimal", scale: 2, currency_flag: "currency", currency_default: "MYR" },
|
|
971
|
+
currency: { semantic: "currency" }
|
|
972
|
+
},
|
|
973
|
+
unchecked: ["product"]
|
|
974
|
+
},
|
|
952
975
|
preview: ({ args: args2 }) => [{
|
|
953
976
|
step: "\u6539\u4EF7",
|
|
954
977
|
method: "POST",
|
|
955
978
|
path: `/product/202309/products/${args2.product}/prices/update`,
|
|
956
|
-
body: priceBody(args2)
|
|
979
|
+
body: priceBody(args2),
|
|
980
|
+
human: priceHuman(args2)
|
|
957
981
|
}],
|
|
958
982
|
run: ({ shop, args: args2 }) => proxy("POST", shop, `/product/202309/products/${args2.product}/prices/update`, { body: priceBody(args2) }),
|
|
959
983
|
readback: ({ shop, args: args2 }) => proxy("GET", shop, `/product/202309/products/${args2.product}`, {})
|
|
960
984
|
},
|
|
961
985
|
{
|
|
962
986
|
name: "promotions create-flashsale",
|
|
963
|
-
summary: "\u5EFA\u79D2\u6740\u6D3B\u52A8\uFF08--title --product --sku --price [--limit] [--hours 48]\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u771F\u5EFA\u3002\u4E24\u6B65:\u5EFA\u58F3+\u52A0\u54C1",
|
|
987
|
+
summary: "\u5EFA\u79D2\u6740\u6D3B\u52A8\uFF08--title --product --sku --price [--limit] [--hours 48]\uFF1B--price \u5927\u4E8E 0\u3001\u6700\u591A\u4E24\u4F4D\u5C0F\u6570\uFF0C--hours \u5C0F\u4E8E 72\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u771F\u5EFA\u3002\u4E24\u6B65:\u5EFA\u58F3+\u52A0\u54C1",
|
|
964
988
|
flags: ["hours", "limit", "per-user", "price", "product", "sku", "start-in-min", "title"],
|
|
965
989
|
write: true,
|
|
990
|
+
validate: validateFlashsale,
|
|
991
|
+
values: {
|
|
992
|
+
subject: { flag: "sku", kind: "sku_id" },
|
|
993
|
+
// 秒杀价不带币种,平台按店铺本币收;本 CLI 只接马来站 ⇒ MYR
|
|
994
|
+
params: { price: { semantic: "promo_price", type: "decimal", scale: 2, currency_default: "MYR" } },
|
|
995
|
+
unchecked: ["hours", "limit", "per-user", "product", "start-in-min", "title"]
|
|
996
|
+
},
|
|
966
997
|
preview: ({ args: args2 }) => {
|
|
967
998
|
const { begin, end } = flashWindow(args2);
|
|
968
999
|
return [
|
|
969
1000
|
{ step: "1/2 \u5EFA\u6D3B\u52A8\u58F3", method: "POST", path: "/promotion/202309/activities", body: flashActivityBody(args2, begin, end) },
|
|
970
|
-
{ step: "2/2 \u52A0\u5546\u54C1+\u79D2\u6740\u4EF7", method: "PUT", path: "/promotion/202309/activities/{activity_id}/products", body: flashProductsBody(args2) }
|
|
1001
|
+
{ step: "2/2 \u52A0\u5546\u54C1+\u79D2\u6740\u4EF7", method: "PUT", path: "/promotion/202309/activities/{activity_id}/products", body: flashProductsBody(args2), human: flashHuman(args2) }
|
|
971
1002
|
];
|
|
972
1003
|
},
|
|
973
1004
|
run: async ({ shop, args: args2 }) => {
|
|
@@ -988,6 +1019,7 @@ var COMMANDS = [
|
|
|
988
1019
|
summary: "\u5EFA\u5546\u54C1\u6298\u6263\u6D3B\u52A8 FIXED_PRICE\uFF08--price \u4E00\u53E3\u4EF7\uFF09\u6216 DIRECT_DISCOUNT\uFF08--percent \u51CFN%\uFF09\uFF08--title [--product] --price <skuId>:<\u4E00\u53E3\u4EF7>|<productId>/<skuId>:<\u4E00\u53E3\u4EF7>[,...] \u6216 --percent <skuId>:<\u51CFN%>|<productId>/<skuId>:<\u51CFN%>[,...] [--days 180]\uFF09\u3002--percent 85 = \u51CF85%\u3001\u6309\u539F\u4EF715%\u5356\uFF08\u625385\u6298\u8981\u4F2015\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u771F\u5EFA\u3002\u4E24\u6B65:\u5EFA\u58F3+\u52A0\u54C1\uFF0C\u53EF\u591A\u5546\u54C1",
|
|
989
1020
|
flags: ["days", "percent", "price", "product", "title"],
|
|
990
1021
|
write: true,
|
|
1022
|
+
values: { params: DISCOUNT_VALUE_PARAMS, unchecked: ["days", "product", "title"] },
|
|
991
1023
|
validate: validateCreateDiscount,
|
|
992
1024
|
preview: ({ args: args2 }) => {
|
|
993
1025
|
const { begin, end } = discountWindow(args2);
|
|
@@ -1062,6 +1094,7 @@ var COMMANDS = [
|
|
|
1062
1094
|
summary: ADD_TEXT.SUM_ADD,
|
|
1063
1095
|
flags: ["id", "percent", "price", "product"],
|
|
1064
1096
|
write: true,
|
|
1097
|
+
values: { params: DISCOUNT_VALUE_PARAMS, unchecked: ["id", "product"] },
|
|
1065
1098
|
validate: validateAddProducts,
|
|
1066
1099
|
// 🔴 命令块只字面读 args.id / args.product,值旗标经 discountValueFlag / discountValueRaw(它们字面读 args.percent / args.price);
|
|
1067
1100
|
// ⛔ 不得提到 discountHuman / validateCreateDiscount / discountActivityBody / discountWindow(它们读 days / title,本命令没有)
|
|
@@ -1081,6 +1114,7 @@ var COMMANDS = [
|
|
|
1081
1114
|
summary: "\u7EC8\u6B62/\u505C\u7528\u4FC3\u9500\u6D3B\u52A8\uFF08--id \u5FC5\u586B\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u7EC8\u6B62\u3002\u4E0D\u53EF\u9006",
|
|
1082
1115
|
flags: ["id"],
|
|
1083
1116
|
write: true,
|
|
1117
|
+
values: { unchecked: ["id"] },
|
|
1084
1118
|
preview: ({ args: args2 }) => [{ step: "\u7EC8\u6B62\u6D3B\u52A8", method: "POST", path: `/promotion/202309/activities/${args2.id}/deactivate`, body: {} }],
|
|
1085
1119
|
run: ({ shop, args: args2 }) => proxy("POST", shop, `/promotion/202309/activities/${args2.id}/deactivate`, { body: {} })
|
|
1086
1120
|
},
|
|
@@ -1089,6 +1123,7 @@ var COMMANDS = [
|
|
|
1089
1123
|
summary: "\u6539 SKU \u5E93\u5B58\uFF08--product --sku --warehouse --quantity\uFF09\u3002\u5199\u64CD\u4F5C,\u9ED8\u8BA4 dry-run",
|
|
1090
1124
|
flags: ["product", "quantity", "sku", "warehouse"],
|
|
1091
1125
|
write: true,
|
|
1126
|
+
values: { unchecked: ["product", "quantity", "sku", "warehouse"] },
|
|
1092
1127
|
preview: ({ args: args2 }) => [{
|
|
1093
1128
|
step: "\u6539\u5E93\u5B58",
|
|
1094
1129
|
method: "POST",
|
|
@@ -1103,6 +1138,7 @@ var COMMANDS = [
|
|
|
1103
1138
|
summary: "\u5EFA\u54C1\uFF08--body-file [--apply]\uFF09\u3002dry-run \u8DD1 listing_check \u9884\u68C0\uFF1B\u5199\u64CD\u4F5C\u3002\u26A0\uFE0F --apply \u5373\u5EFA\u5B8C\u76F4\u63A5\u4E0A\u67B6\u9001\u5BA1\uFF1B\u7528\u6237\u8981\u5B58\u8349\u7A3F\u5C31\u505C\u624B\u95EE\u7528\u6237\uFF08#1958\uFF09",
|
|
1104
1139
|
flags: ["body-file"],
|
|
1105
1140
|
write: true,
|
|
1141
|
+
values: { opaque: ["body-file"] },
|
|
1106
1142
|
preview: () => [{ step: "listing_check \u9884\u68C0 \u2192 \u5EFA\u54C1", method: "POST", path: "/product/202309/products/listing_check", body: void 0 }],
|
|
1107
1143
|
precheck: ({ shop, args: args2 }) => proxy("POST", shop, "/product/202309/products/listing_check", { body: readBodyFile(args2["body-file"]) }),
|
|
1108
1144
|
run: async ({ shop, args: args2 }) => {
|
|
@@ -1118,6 +1154,7 @@ var COMMANDS = [
|
|
|
1118
1154
|
summary: "\u7ED9\u5546\u54C1\u52A0\u89C4\u683C SKU\uFF08--product --body-file skus-delta.json [--apply]\uFF09\u3002\u26A0\uFE0F --apply \u5373\u9001\u5BA1\u4E0A\u67B6\uFF1B\u7528\u6237\u8981\u5B58\u8349\u7A3F\u5C31\u505C\u624B\u95EE\u7528\u6237\uFF08#1958\uFF09",
|
|
1119
1155
|
flags: ["body-file", "product"],
|
|
1120
1156
|
write: true,
|
|
1157
|
+
values: { unchecked: ["product"], opaque: ["body-file"] },
|
|
1121
1158
|
preview: () => [{ step: "\u8BFB\u73B0\u6709 skus \u2192 append \u2192 partial_edit\u3002\u26A0\uFE0F \u9ED8\u8BA4 save_mode=LISTING\uFF1A--apply \u5373\u9001\u5BA1\u4E0A\u67B6\uFF08DRAFT \u5546\u54C1\u4F1A\u88AB\u63D0\u4EA4\uFF09\uFF1B\u672C\u547D\u4EE4\u81EA\u6784 body\uFF0Cbody-file \u91CC\u7684 save_mode \u4E0D\u900F\u4F20\u3001\u5199\u4E86\u4E5F\u65E0\u6548\u3002\u82E5\u7528\u6237\u8981\u6C42\u5B58\u8349\u7A3F/\u522B\u63D0\u4EA4 \u2192 \u4E0D\u8981 --apply\uFF0C\u505C\u624B\u95EE\u7528\u6237\uFF08#1958\uFF09", method: "POST", path: "/product/202309/products/{id}/partial_edit" }],
|
|
1122
1159
|
run: async ({ shop, args: args2 }) => {
|
|
1123
1160
|
const cur = await proxy("GET", shop, `/product/202309/products/${args2.product}`, {});
|
|
@@ -1132,6 +1169,8 @@ var COMMANDS = [
|
|
|
1132
1169
|
summary: "\u6574\u7EC4\u6362\u4E3B\u56FE\uFF08--product --body-file images.json [--apply]\uFF09\u3002\u26A0\uFE0F --apply \u5373\u9001\u5BA1\u4E0A\u67B6\uFF1B\u7528\u6237\u8981\u5B58\u8349\u7A3F\u5C31\u505C\u624B\u95EE\u7528\u6237\uFF08#1958\uFF09",
|
|
1133
1170
|
flags: ["body-file", "product"],
|
|
1134
1171
|
write: true,
|
|
1172
|
+
values: { unchecked: ["body-file", "product"] },
|
|
1173
|
+
// 只从文件里取 main_images,带不进价格
|
|
1135
1174
|
preview: () => [{ step: "main_images \u6574\u7EC4\u66FF\u6362 \u2192 partial_edit\u3002\u26A0\uFE0F \u9ED8\u8BA4 save_mode=LISTING\uFF1A--apply \u5373\u9001\u5BA1\u4E0A\u67B6\uFF08DRAFT \u5546\u54C1\u4F1A\u88AB\u63D0\u4EA4\uFF09\uFF1B\u672C\u547D\u4EE4\u81EA\u6784 body\uFF0Cbody-file \u91CC\u7684 save_mode \u4E0D\u900F\u4F20\u3001\u5199\u4E86\u4E5F\u65E0\u6548\u3002\u82E5\u7528\u6237\u8981\u6C42\u5B58\u8349\u7A3F/\u522B\u63D0\u4EA4 \u2192 \u4E0D\u8981 --apply\uFF0C\u505C\u624B\u95EE\u7528\u6237\uFF08#1958\uFF09", method: "POST", path: "/product/202309/products/{id}/partial_edit" }],
|
|
1136
1175
|
run: ({ shop, args: args2 }) => proxy("POST", shop, `/product/202309/products/${args2.product}/partial_edit`, { body: { main_images: readBodyFile(args2["body-file"]).main_images } }),
|
|
1137
1176
|
readback: ({ shop, args: args2 }) => proxy("GET", shop, `/product/202309/products/${args2.product}`, {})
|
|
@@ -1141,6 +1180,7 @@ var COMMANDS = [
|
|
|
1141
1180
|
summary: "\u6539\u5546\u54C1\u5B57\u6BB5\uFF08--product --body-file patch.json [--apply]\uFF09\u3002\u26A0\uFE0F --apply \u5373\u9001\u5BA1\u4E0A\u67B6\uFF1B\u7528\u6237\u8981\u5B58\u8349\u7A3F\u5C31\u505C\u624B\u95EE\u7528\u6237\uFF08#1958\uFF09",
|
|
1142
1181
|
flags: ["body-file", "product"],
|
|
1143
1182
|
write: true,
|
|
1183
|
+
values: { unchecked: ["product"], opaque: ["body-file"] },
|
|
1144
1184
|
preview: ({ args: args2 }) => [{ step: "partial_edit\uFF08\u5D4C\u5957\u5B57\u6BB5\u672A\u5217\u5B50\u9879\u4F1A\u88AB\u6E05\u7A7A\uFF09\u3002\u26A0\uFE0F \u9ED8\u8BA4 save_mode=LISTING\uFF1A--apply \u5373\u9001\u5BA1\u4E0A\u67B6\uFF08DRAFT \u5546\u54C1\u4F1A\u88AB\u63D0\u4EA4\uFF09\u3002\u82E5\u7528\u6237\u8981\u6C42\u5B58\u8349\u7A3F/\u522B\u63D0\u4EA4 \u2192 \u4E0D\u8981 --apply\uFF0C\u505C\u624B\u95EE\u7528\u6237\uFF08#1958\uFF09", method: "POST", path: `/product/202309/products/${args2.product}/partial_edit`, body: readBodyFile(args2["body-file"]) }],
|
|
1145
1185
|
run: ({ shop, args: args2 }) => proxy("POST", shop, `/product/202309/products/${args2.product}/partial_edit`, { body: readBodyFile(args2["body-file"]) }),
|
|
1146
1186
|
readback: ({ shop, args: args2 }) => proxy("GET", shop, `/product/202309/products/${args2.product}`, {})
|
|
@@ -1248,6 +1288,7 @@ var COMMANDS = [
|
|
|
1248
1288
|
summary: "\u53D1\u5B9A\u5411\u9080\u7EA6\uFF08--body-file collab.json\uFF0C\u542B creator_user_open_ids[]/products[]/free_sample_rule\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u53D1",
|
|
1249
1289
|
flags: ["body-file"],
|
|
1250
1290
|
write: true,
|
|
1291
|
+
values: { opaque: ["body-file"] },
|
|
1251
1292
|
preview: ({ args: args2 }) => [{
|
|
1252
1293
|
step: "\u53D1\u5B9A\u5411\u9080\u7EA6",
|
|
1253
1294
|
method: "POST",
|
|
@@ -1267,6 +1308,7 @@ var COMMANDS = [
|
|
|
1267
1308
|
summary: "\u6539\u5B9A\u5411\u9080\u7EA6\uFF08--id --body-file collab.json\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u63D0\u4EA4",
|
|
1268
1309
|
flags: ["body-file", "id"],
|
|
1269
1310
|
write: true,
|
|
1311
|
+
values: { unchecked: ["id"], opaque: ["body-file"] },
|
|
1270
1312
|
preview: ({ args: args2 }) => [{
|
|
1271
1313
|
step: "\u6539\u5B9A\u5411\u9080\u7EA6",
|
|
1272
1314
|
method: "PUT",
|
|
@@ -1283,6 +1325,7 @@ var COMMANDS = [
|
|
|
1283
1325
|
summary: "\u64A4\u56DE\u5B9A\u5411\u9080\u7EA6\uFF08--id \u5FC5\u586B\uFF0C\u64A4\u56DE\u5B89\u5168\u7F51\uFF09\u3002\u4E0D\u53EF\u9006\uFF0C\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u53D1",
|
|
1284
1326
|
flags: ["id"],
|
|
1285
1327
|
write: true,
|
|
1328
|
+
values: { unchecked: ["id"] },
|
|
1286
1329
|
preview: ({ args: args2 }) => [{
|
|
1287
1330
|
step: "\u64A4\u56DE\u5B9A\u5411\u9080\u7EA6",
|
|
1288
1331
|
method: "DELETE",
|
|
@@ -1296,6 +1339,7 @@ var COMMANDS = [
|
|
|
1296
1339
|
summary: "\u751F\u6210\u5B9A\u5411\u9080\u7EA6\u5206\u4EAB\u94FE\u63A5\uFF08--id \u5FC5\u586B\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u53D1",
|
|
1297
1340
|
flags: ["id"],
|
|
1298
1341
|
write: true,
|
|
1342
|
+
values: { unchecked: ["id"] },
|
|
1299
1343
|
preview: ({ args: args2 }) => [{
|
|
1300
1344
|
step: "\u751F\u6210\u9080\u7EA6\u94FE\u63A5",
|
|
1301
1345
|
method: "POST",
|
|
@@ -1309,6 +1353,7 @@ var COMMANDS = [
|
|
|
1309
1353
|
summary: "\u5F00\u8FBE\u4EBA\u79C1\u4FE1\u4F1A\u8BDD\uFF08--creator \u5FC5\u586B\uFF0Ccreator_open_id\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u53D1",
|
|
1310
1354
|
flags: ["creator"],
|
|
1311
1355
|
write: true,
|
|
1356
|
+
values: { unchecked: ["creator"] },
|
|
1312
1357
|
preview: ({ args: args2 }) => [{
|
|
1313
1358
|
step: "\u5F00\u79C1\u4FE1\u4F1A\u8BDD",
|
|
1314
1359
|
method: "POST",
|
|
@@ -1324,6 +1369,7 @@ var COMMANDS = [
|
|
|
1324
1369
|
summary: "\u7ED9\u8FBE\u4EBA\u53D1\u79C1\u4FE1\uFF08--conversation --content [--msg-type TEXT]\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u53D1",
|
|
1325
1370
|
flags: ["content", "conversation", "msg-type"],
|
|
1326
1371
|
write: true,
|
|
1372
|
+
values: { unchecked: ["content", "conversation", "msg-type"] },
|
|
1327
1373
|
preview: ({ args: args2 }) => [{
|
|
1328
1374
|
step: "\u53D1\u79C1\u4FE1",
|
|
1329
1375
|
method: "POST",
|
|
@@ -1340,6 +1386,7 @@ var COMMANDS = [
|
|
|
1340
1386
|
flags: ["id", "reject-reason", "result"],
|
|
1341
1387
|
listKey: "sample_applications",
|
|
1342
1388
|
write: true,
|
|
1389
|
+
values: { unchecked: ["id", "reject-reason", "result"] },
|
|
1343
1390
|
preview: ({ args: args2 }) => [{
|
|
1344
1391
|
step: "\u5BA1\u6279\u6837\u54C1\u7533\u8BF7",
|
|
1345
1392
|
method: "POST",
|
|
@@ -1360,11 +1407,14 @@ var COMMANDS = [
|
|
|
1360
1407
|
summary: "\u6309\u54C1\u8BBE\u516C\u5F00\u5408\u4F5C\u4F63\u91D1\u7387\uFF08--product product_id --rate\uFF0C\u5355\u4F4D=\u767E\u5206\u6BD4\xD7100\uFF0C\u5982 1350=13.5%\uFF0C\u8303\u56F4 800-8000\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u5B58",
|
|
1361
1408
|
flags: ["product", "rate"],
|
|
1362
1409
|
write: true,
|
|
1410
|
+
validate: validateCommissionRate,
|
|
1411
|
+
values: { subject: { flag: "product", kind: "product_id" }, params: { rate: COMMISSION_RATE } },
|
|
1363
1412
|
preview: ({ args: args2 }) => [{
|
|
1364
1413
|
step: "\u8BBE\u6309\u54C1\u516C\u5F00\u5408\u4F5C\u4F63\u91D1",
|
|
1365
1414
|
method: "POST",
|
|
1366
1415
|
path: "/affiliate_seller/202412/open_collaborations",
|
|
1367
|
-
body: { product_id: args2.product, commission_rate: Number(args2.rate) }
|
|
1416
|
+
body: { product_id: args2.product, commission_rate: Number(args2.rate) },
|
|
1417
|
+
human: `\u5546\u54C1 ${args2.product} \u7684\u516C\u5F00\u5408\u4F5C\u4F63\u91D1\u7387\u8BBE\u4E3A ${rateHuman(args2.rate)}`
|
|
1368
1418
|
}],
|
|
1369
1419
|
run: ({ shop, args: args2 }) => proxy("POST", shop, "/affiliate_seller/202412/open_collaborations", {
|
|
1370
1420
|
body: { product_id: args2.product, commission_rate: Number(args2.rate) }
|
|
@@ -1379,6 +1429,7 @@ var COMMANDS = [
|
|
|
1379
1429
|
summary: "\u79FB\u9664\u54C1\u7684\u516C\u5F00\u5408\u4F5C\uFF08--product product_id\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u53D1",
|
|
1380
1430
|
flags: ["product"],
|
|
1381
1431
|
write: true,
|
|
1432
|
+
values: { unchecked: ["product"] },
|
|
1382
1433
|
preview: ({ args: args2 }) => [{
|
|
1383
1434
|
step: "\u79FB\u9664\u516C\u5F00\u5408\u4F5C",
|
|
1384
1435
|
method: "DELETE",
|
|
@@ -1389,14 +1440,17 @@ var COMMANDS = [
|
|
|
1389
1440
|
},
|
|
1390
1441
|
{
|
|
1391
1442
|
name: "affiliate open-collab settings edit",
|
|
1392
|
-
summary: "\u6539\u516C\u5F00\u5408\u4F5C\u5168\u5C40\u9ED8\u8BA4\uFF08\u81EA\u52A8\u65B0\u589E\u54C1\u4F63\u91D1\uFF0C--rate --enable true|false\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u5B58",
|
|
1443
|
+
summary: "\u6539\u516C\u5F00\u5408\u4F5C\u5168\u5C40\u9ED8\u8BA4\uFF08\u81EA\u52A8\u65B0\u589E\u54C1\u4F63\u91D1\uFF0C--rate --enable true|false\uFF1B--rate \u5355\u4F4D=\u767E\u5206\u6BD4\xD7100\uFF0C1\u201310000 \u7684\u6574\u6570\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u5B58",
|
|
1393
1444
|
flags: ["enable", "rate"],
|
|
1394
1445
|
write: true,
|
|
1446
|
+
validate: validateSettingsRate,
|
|
1447
|
+
values: { params: { rate: COMMISSION_RATE }, unchecked: ["enable"] },
|
|
1395
1448
|
preview: ({ args: args2 }) => [{
|
|
1396
1449
|
step: "\u6539\u5168\u5C40\u9ED8\u8BA4",
|
|
1397
1450
|
method: "POST",
|
|
1398
1451
|
path: "/affiliate_seller/202405/open_collaboration_settings",
|
|
1399
|
-
body: { auto_add_product: { commission_rate: Number(args2.rate), enable: args2.enable === "true" } }
|
|
1452
|
+
body: { auto_add_product: { commission_rate: Number(args2.rate), enable: args2.enable === "true" } },
|
|
1453
|
+
human: `\u65B0\u4E0A\u67B6\u7684\u5546\u54C1${args2.enable === "true" ? "\u81EA\u52A8\u52A0\u5165" : "\u4E0D\u81EA\u52A8\u52A0\u5165"}\u516C\u5F00\u5408\u4F5C\uFF0C\u9ED8\u8BA4\u4F63\u91D1\u7387 ${rateHuman(args2.rate)}`
|
|
1400
1454
|
}],
|
|
1401
1455
|
run: ({ shop, args: args2 }) => proxy("POST", shop, "/affiliate_seller/202405/open_collaboration_settings", {
|
|
1402
1456
|
body: { auto_add_product: { commission_rate: Number(args2.rate), enable: args2.enable === "true" } }
|
|
@@ -1515,6 +1569,42 @@ function priceBody(args2) {
|
|
|
1515
1569
|
skus: [{ id: args2.sku, price: { amount: args2.price, currency: args2.currency ?? "MYR" } }]
|
|
1516
1570
|
};
|
|
1517
1571
|
}
|
|
1572
|
+
var PRICE_VALUE = /^(0|[1-9]\d*)(\.\d{1,2})?$/;
|
|
1573
|
+
var priceOk = (raw) => raw !== void 0 && PRICE_VALUE.test(raw) && Number(raw) > 0;
|
|
1574
|
+
var priceMessage = (raw) => `--price \u5FC5\u987B\u662F\u5927\u4E8E 0 \u7684\u5341\u8FDB\u5236\u6570\uFF0C\u6700\u591A\u4E24\u4F4D\u5C0F\u6570\u3001\u4E0D\u8981\u524D\u5BFC\u96F6\u548C\u5E01\u79CD\u7B26\u53F7\uFF08\u5982 29.90\uFF09\uFF1B\u6536\u5230\u300C${raw ?? "\uFF08\u6CA1\u4F20\uFF09"}\u300D`;
|
|
1575
|
+
function validateSetPrice({ args: args2 }) {
|
|
1576
|
+
return priceOk(args2.price) ? { ok: true } : { ok: false, message: priceMessage(args2.price) };
|
|
1577
|
+
}
|
|
1578
|
+
function validateFlashsale({ args: args2 }) {
|
|
1579
|
+
if (!priceOk(args2.price)) return { ok: false, message: priceMessage(args2.price) };
|
|
1580
|
+
if (args2.hours !== void 0) {
|
|
1581
|
+
const n = Number(args2.hours);
|
|
1582
|
+
if (!/^\d+(\.\d+)?$/.test(args2.hours) || !(n > 0 && n < 72)) {
|
|
1583
|
+
return { ok: false, message: `--hours \u662F\u79D2\u6740\u6301\u7EED\u7684\u5C0F\u65F6\u6570\uFF0C\u5FC5\u987B\u5927\u4E8E 0\u3001\u5C0F\u4E8E 72\uFF08\u5E73\u53F0\u786C\u4E0A\u9650\uFF0C\u9ED8\u8BA4 48\uFF09\uFF1B\u6536\u5230\u300C${args2.hours}\u300D` };
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
return { ok: true };
|
|
1587
|
+
}
|
|
1588
|
+
function rateProblem(raw, min, max) {
|
|
1589
|
+
if (raw !== void 0 && /^\d+$/.test(raw) && Number(raw) >= min && Number(raw) <= max) return null;
|
|
1590
|
+
return `--rate \u7684\u5355\u4F4D\u662F\u300C\u767E\u5206\u6BD4\xD7100\u300D\uFF081350 = 13.5%\uFF09\uFF0C\u5FC5\u987B\u662F ${min}\u2013${max} \u7684\u6574\u6570\uFF08${min / 100}%\u2013${max / 100}%\uFF09\uFF1B\u6536\u5230\u300C${raw ?? "\uFF08\u6CA1\u4F20\uFF09"}\u300D\u3002\u5E97\u4E3B\u8BF4\u300C\u4F63\u91D1 13.5%\u300D\u8981\u4F20 1350`;
|
|
1591
|
+
}
|
|
1592
|
+
function validateCommissionRate({ args: args2 }) {
|
|
1593
|
+
const p = rateProblem(args2.rate, 800, 8e3);
|
|
1594
|
+
return p ? { ok: false, message: p } : { ok: true };
|
|
1595
|
+
}
|
|
1596
|
+
function validateSettingsRate({ args: args2 }) {
|
|
1597
|
+
if (args2.rate === void 0) return { ok: true };
|
|
1598
|
+
const p = rateProblem(args2.rate, 1, 1e4);
|
|
1599
|
+
return p ? { ok: false, message: p } : { ok: true };
|
|
1600
|
+
}
|
|
1601
|
+
function priceHuman(args2) {
|
|
1602
|
+
return `\u5546\u54C1 ${args2.product} \u7684 SKU ${args2.sku} \u552E\u4EF7\u6539\u4E3A ${args2.price} ${args2.currency ?? "MYR"}`;
|
|
1603
|
+
}
|
|
1604
|
+
function flashHuman(args2) {
|
|
1605
|
+
return `\u5546\u54C1 ${args2.product} \u7684 SKU ${args2.sku} \u79D2\u6740\u4EF7 ${args2.price} MYR\uFF0C\u9650\u91CF ${args2.limit ?? 100} \u4EF6\u3001\u6BCF\u4EBA\u9650\u8D2D ${args2["per-user"] ?? 1} \u4EF6\uFF1B${args2["start-in-min"] ?? 15} \u5206\u949F\u540E\u5F00\u59CB\uFF0C\u6301\u7EED ${args2.hours ?? 48} \u5C0F\u65F6`;
|
|
1606
|
+
}
|
|
1607
|
+
var rateHuman = (raw) => `${Number(raw) / 100}%\uFF08--rate ${raw}\uFF09`;
|
|
1518
1608
|
function findCommand(tokens) {
|
|
1519
1609
|
for (const cmd of [...COMMANDS].sort((a, b) => b.name.length - a.name.length)) {
|
|
1520
1610
|
const parts = cmd.name.split(" ");
|
|
@@ -2007,6 +2097,86 @@ async function runAddProducts(shop, id, flag, raw, product) {
|
|
|
2007
2097
|
return { ok: true, data, meta: put.meta };
|
|
2008
2098
|
}
|
|
2009
2099
|
|
|
2100
|
+
// src/schema.ts
|
|
2101
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
2102
|
+
var VALUE_SEMANTICS = [
|
|
2103
|
+
"list_price",
|
|
2104
|
+
// SKU 挂牌价
|
|
2105
|
+
"promo_price",
|
|
2106
|
+
// 促销售价:折扣一口价、秒杀价
|
|
2107
|
+
"campaign_price",
|
|
2108
|
+
// 平台活动报价
|
|
2109
|
+
"discount_pct",
|
|
2110
|
+
// 降幅百分数(means 说是「减 N%」还是「按 N% 卖」)
|
|
2111
|
+
"ad_target_roi",
|
|
2112
|
+
// GMV Max 目标 ROI
|
|
2113
|
+
"ad_daily_budget",
|
|
2114
|
+
// GMV Max 日预算
|
|
2115
|
+
"commission_pct",
|
|
2116
|
+
// 达人佣金百分数
|
|
2117
|
+
"currency"
|
|
2118
|
+
// 同一条写里金额的币种
|
|
2119
|
+
];
|
|
2120
|
+
var MONEY = ["list_price", "promo_price", "campaign_price", "ad_daily_budget"];
|
|
2121
|
+
function cliVersion() {
|
|
2122
|
+
return JSON.parse(readFileSync3(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
2123
|
+
}
|
|
2124
|
+
var dash = (f) => `--${f}`;
|
|
2125
|
+
var sorted = (xs) => [...xs].sort().map(dash);
|
|
2126
|
+
function checkParam(where, p, params, problems) {
|
|
2127
|
+
if (!VALUE_SEMANTICS.includes(p.semantic)) problems.push(`${where}\uFF1Asemantic ${JSON.stringify(p.semantic)} \u4E0D\u5728\u8BCD\u8868\u91CC`);
|
|
2128
|
+
if (p.semantic === "currency") {
|
|
2129
|
+
if (Object.keys(p).some((k) => k !== "semantic" && k !== "type") || p.type !== void 0 && p.type !== "string") problems.push(`${where}\uFF1A\u5E01\u79CD\u53C2\u6570\u53EA\u5199 semantic`);
|
|
2130
|
+
return;
|
|
2131
|
+
}
|
|
2132
|
+
if (MONEY.includes(p.semantic) && p.currency_flag === void 0 && p.currency_default === void 0) problems.push(`${where}\uFF1A\u94B1\u8981\u5199\u5E01\u79CD\uFF08currency_flag \u6216 currency_default\uFF09`);
|
|
2133
|
+
if (!MONEY.includes(p.semantic) && (p.currency_flag !== void 0 || p.currency_default !== void 0)) problems.push(`${where}\uFF1A\u53EA\u6709\u91D1\u989D\u624D\u6709\u5E01\u79CD`);
|
|
2134
|
+
if (p.semantic === "discount_pct" !== (p.means !== void 0)) problems.push(`${where}\uFF1A\u964D\u5E45\u5FC5\u987B\u5199 means\uFF0C\u522B\u7684\u4E0D\u8BB8\u5199`);
|
|
2135
|
+
if (p.round !== void 0 && p.scale === void 0) problems.push(`${where}\uFF1Around \u8981\u548C scale \u4E00\u8D77\u5199`);
|
|
2136
|
+
if (p.type === "pairs" !== (p.pair !== void 0)) problems.push(`${where}\uFF1Apairs \u548C pair \u8981\u4E00\u8D77\u5199`);
|
|
2137
|
+
if (p.factor !== void 0 && !(Number.isFinite(p.factor) && p.factor > 0)) problems.push(`${where}\uFF1Afactor \u8981\u662F\u6B63\u6570`);
|
|
2138
|
+
if (p.currency_flag !== void 0 && params[p.currency_flag]?.semantic !== "currency") problems.push(`${where}\uFF1Acurrency_flag ${p.currency_flag} \u4E0D\u662F\u672C\u547D\u4EE4\u7684\u5E01\u79CD\u53C2\u6570`);
|
|
2139
|
+
}
|
|
2140
|
+
function buildSchema(commands, version) {
|
|
2141
|
+
const problems = [];
|
|
2142
|
+
const out2 = { tool: "tiktok-cli", version, global_flags: GLOBAL_FLAGS.map(dash), commands: {} };
|
|
2143
|
+
for (const cmd of commands) {
|
|
2144
|
+
if (!cmd.write) continue;
|
|
2145
|
+
const v = cmd.values;
|
|
2146
|
+
if (!v) {
|
|
2147
|
+
problems.push(`${cmd.name}\uFF1A\u5199\u547D\u4EE4\u6CA1\u6709 values \u6807\u6CE8`);
|
|
2148
|
+
continue;
|
|
2149
|
+
}
|
|
2150
|
+
const params = v.params ?? {};
|
|
2151
|
+
const seen = /* @__PURE__ */ new Map();
|
|
2152
|
+
const claim = (flag, place) => {
|
|
2153
|
+
if (GLOBAL_FLAGS.includes(flag)) problems.push(`${cmd.name}\uFF1A--${flag} \u662F\u5168\u5C40\u53C2\u6570\uFF0C\u4E0D\u5199\u8FDB\u547D\u4EE4\u81EA\u5DF1\u7684\u6E05\u5355`);
|
|
2154
|
+
if (seen.has(flag)) problems.push(`${cmd.name}\uFF1A--${flag} \u540C\u65F6\u5728 ${seen.get(flag)} \u548C ${place}`);
|
|
2155
|
+
seen.set(flag, place);
|
|
2156
|
+
if (!cmd.flags.includes(flag)) problems.push(`${cmd.name}\uFF1A\u6E05\u5355\u91CC\u7684 --${flag} \u4E0D\u662F\u8FD9\u6761\u547D\u4EE4\u8BA4\u7684\u53C2\u6570`);
|
|
2157
|
+
};
|
|
2158
|
+
for (const f of Object.keys(params)) claim(f, "params");
|
|
2159
|
+
if (v.subject) claim(v.subject.flag, "subject");
|
|
2160
|
+
for (const f of v.unchecked ?? []) claim(f, "unchecked");
|
|
2161
|
+
for (const f of v.opaque ?? []) claim(f, "opaque");
|
|
2162
|
+
for (const f of cmd.flags) if (!seen.has(f)) problems.push(`${cmd.name}\uFF1A--${f} \u6CA1\u5199\u8FDB\u6E05\u5355\uFF08\u5E26\u94B1\u7684\u8FDB params\uFF0C\u4E0D\u662F\u94B1\u7684\u8FDB unchecked\uFF09`);
|
|
2163
|
+
for (const f of v.repeatable ?? []) if (!seen.has(f) || seen.get(f) === "opaque") problems.push(`${cmd.name}\uFF1Arepeatable --${f} \u4E0D\u662F\u5B83\u7684\u53C2\u6570`);
|
|
2164
|
+
for (const [f, p] of Object.entries(params)) checkParam(`${cmd.name} --${f}`, p, params, problems);
|
|
2165
|
+
const m = { write: true, params: {} };
|
|
2166
|
+
if (v.subject) m.subject = { flag: dash(v.subject.flag), kind: v.subject.kind };
|
|
2167
|
+
for (const [f, p] of Object.entries(params)) {
|
|
2168
|
+
m.params[dash(f)] = { ...p, ...p.semantic === "currency" ? { type: "string" } : {}, ...p.currency_flag ? { currency_flag: dash(p.currency_flag) } : {} };
|
|
2169
|
+
}
|
|
2170
|
+
if (v.repeatable?.length) m.repeatable = sorted(v.repeatable);
|
|
2171
|
+
if (v.opaque?.length) m.opaque = sorted(v.opaque);
|
|
2172
|
+
if (v.unchecked?.length) m.unchecked = sorted(v.unchecked);
|
|
2173
|
+
out2.commands[cmd.name] = m;
|
|
2174
|
+
}
|
|
2175
|
+
if (problems.length) throw new Error(`\u5199\u547D\u4EE4\u6E05\u5355\u4E0D\u5B8C\u6574\uFF1A
|
|
2176
|
+
- ${problems.join("\n- ")}`);
|
|
2177
|
+
return out2;
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2010
2180
|
// src/index.ts
|
|
2011
2181
|
var NO_SHOP_COMMANDS = /* @__PURE__ */ new Set(["auth link", "apps add", "apps list", "apps disable", "apps available", "apps set-shop"]);
|
|
2012
2182
|
var SHOP_OPTIONAL_BUT_READ = /* @__PURE__ */ new Set(["auth link", "apps set-shop"]);
|
|
@@ -2063,11 +2233,13 @@ function normalizeBooleanFlags(args2) {
|
|
|
2063
2233
|
function out(obj) {
|
|
2064
2234
|
process.stdout.write(JSON.stringify(obj, null, 2) + "\n");
|
|
2065
2235
|
}
|
|
2236
|
+
var SCHEMA = { name: "schema", summary: "\u5199\u547D\u4EE4\u53C2\u6570\u6E05\u5355\uFF08--json\uFF1B\u4E0D\u9700\u8981 --shop\uFF09\uFF1A\u6BCF\u6761\u5199\u547D\u4EE4\u7684\u6BCF\u4E2A\u53C2\u6570\u662F\u4EC0\u4E48\u610F\u601D\u3001\u4EC0\u4E48\u5355\u4F4D\uFF0C\u4F9B Optima COO \u7684\u5199\u5165\u6570\u503C\u5B88\u95E8\u6309\u7248\u672C\u56FA\u5B9A", flags: ["json"], noShop: true };
|
|
2066
2237
|
function usage() {
|
|
2067
2238
|
const lines = ["tiktok <domain> <verb> --shop <shopId> [--flags]", "", "\u547D\u4EE4\uFF1A"];
|
|
2068
2239
|
for (const c of COMMANDS) lines.push(` ${c.name.padEnd(22)} ${c.summary}`);
|
|
2069
2240
|
lines.push(` ${"shops".padEnd(22)} \u67E5\u5F53\u524D\u767B\u5F55\u7528\u6237\u5DF2\u6388\u6743\u5E97\u94FA`);
|
|
2070
2241
|
lines.push(` ${"images upload".padEnd(22)} \u4E0A\u4F20\u672C\u5730\u56FE\u7247\uFF08--file --use-case [--out]\uFF09`);
|
|
2242
|
+
lines.push(` ${"schema".padEnd(22)} ${SCHEMA.summary}`);
|
|
2071
2243
|
lines.push("", "\u6BCF\u6761\u547D\u4EE4\u53EA\u8BA4\u5B83\u81EA\u5DF1\u7684\u53C2\u6570\uFF08`tiktok <\u547D\u4EE4> --help` \u770B\uFF09\uFF0C\u4E0D\u8BA4\u7684\u4F1A\u5F53\u573A\u62A5 VALIDATION \u2014\u2014 \u4E0D\u4F1A\u518D\u88AB\u9759\u9ED8\u4E22\u6389\u3002");
|
|
2072
2244
|
lines.push("", "\u901A\u7528\uFF1A--shop \u5FC5\u586B\uFF08\u9664 shops / auth link / apps add|list|disable\uFF09\uFF1B\u9ED8\u8BA4 JSON \u8F93\u51FA\uFF1BTIKTOK_BACKEND_URL \u663E\u5F0F\u6307\u5B9A backend\uFF08\u672A\u8BBE\u5219\u6309 OPTIMA_ENV \u6620\u5C04 cn-stage/cn-prod\uFF0C\u5426\u5219 localhost\uFF09\u3002");
|
|
2073
2245
|
process.stderr.write(lines.join("\n") + "\n");
|
|
@@ -2106,6 +2278,15 @@ if (positional[0] === "shops") {
|
|
|
2106
2278
|
out(await listShops());
|
|
2107
2279
|
process.exit(0);
|
|
2108
2280
|
}
|
|
2281
|
+
if (positional[0] === "schema") {
|
|
2282
|
+
if (wantsHelp) {
|
|
2283
|
+
process.stderr.write(commandUsage(SCHEMA));
|
|
2284
|
+
process.exit(0);
|
|
2285
|
+
}
|
|
2286
|
+
rejectUnknownFlags(SCHEMA.name, SCHEMA.flags, positional.slice(1), true);
|
|
2287
|
+
out(buildSchema(COMMANDS, cliVersion()));
|
|
2288
|
+
process.exit(0);
|
|
2289
|
+
}
|
|
2109
2290
|
if (positional[0] === "images" && positional[1] === "upload") {
|
|
2110
2291
|
if (wantsHelp) {
|
|
2111
2292
|
process.stderr.write(commandUsage(IMAGES_UPLOAD));
|