@optima-chat/tiktok-cli 0.10.0 → 0.10.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.
Files changed (3) hide show
  1. package/README.md +17 -1
  2. package/dist/index.js +76 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -44,12 +44,28 @@ tiktok <domain> <verb> --shop <shopId> [--flags]
44
44
  | `delivery-options --warehouse <id>` | 仓库交付方式 |
45
45
  | `images upload --file <path> --use-case MAIN_IMAGE [--out <f>]` | 上传本地图 → 返回 TikTok CDN `uri`(multipart,供拼 `main_images` 用) |
46
46
 
47
+ ## 传参写法
48
+
49
+ `--key value` 与 `--key=value` 等价,随便用哪种:
50
+
51
+ ```bash
52
+ tiktok promotions create-flashsale --shop <id> --price 11.9 # 空格式
53
+ tiktok promotions create-flashsale --shop=<id> --price=11.9 # 等号式
54
+ ```
55
+
56
+ (0.10.2 之前只认空格式,等号式会让那一格参数**静默消失**而命令照报成功,见 #11。)
57
+
58
+ **开关型 flag**(`--apply` / `--enable` / `--default` / `--unprocessed`)除了裸传,也能带值:
59
+ `true`/`1`/`yes`/`on` 为真,`false`/`0`/`no`/`off`/空串为假(大小写不敏感),
60
+ 给它别的值**当场报错**而不是猜。同一个 flag 写两次以后者为准(`--apply=false --apply` 会真发)。
61
+
47
62
  ## 写操作(Phase 2,安全护栏)
48
63
 
49
64
  写命令三道阀,把 A 轨「填完回读」纪律做进 CLI:
50
65
 
51
66
  1. **默认 dry-run** —— 不加 `--apply` 只打印将提交的 payload,不碰真实店铺
52
- 2. `--apply` 才真发
67
+ 2. `--apply` 才真发。它是开关,写成 `--apply=false` / `=0` / `=no` / `=off` 一样停在 dry-run;
68
+ `--apply=true` / `=1` / `=yes` / `=on` 才真发;给它一个看不懂的值(`--apply=maybe`)当场报错、不猜
53
69
  3. **成功后自动回读** —— 写完 GET 回资源,输出 `readback` 供 agent/人核对是否生效
54
70
 
55
71
  ```bash
package/dist/index.js CHANGED
@@ -202,6 +202,18 @@ function mergeSkus(existing, add) {
202
202
  });
203
203
  return [...existing, ...filledAdd];
204
204
  }
205
+ function fillEmptyList(data, listKey) {
206
+ if (!listKey) return;
207
+ if (!data || typeof data !== "object" || Array.isArray(data)) return;
208
+ const d = data;
209
+ if (!(listKey in d)) d[listKey] = [];
210
+ }
211
+ function commandUsage(cmd) {
212
+ return `tiktok ${cmd.name} --shop <shopId> [--flags]
213
+
214
+ ${cmd.summary}
215
+ `;
216
+ }
205
217
  var today = () => (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
206
218
  var daysAgo = (n) => new Date(Date.now() - n * 864e5).toISOString().slice(0, 10);
207
219
  var toEpoch = (v) => /^\d+$/.test(v) ? Number(v) : Math.floor(Date.parse(v) / 1e3);
@@ -209,6 +221,7 @@ var COMMANDS = [
209
221
  {
210
222
  name: "orders list",
211
223
  summary: "\u8BA2\u5355\u5217\u8868\uFF08\u9ED8\u8BA4\u8FD130\u5929\u3001\u6309\u521B\u5EFA\u65F6\u95F4\u5012\u5E8F\uFF1B--from/--to\uFF08unix\u79D2\u6216YYYY-MM-DD\uFF09--status --page-size --sort-order ASC/DESC --sort-field create_time/update_time\uFF09",
224
+ listKey: "orders",
212
225
  run: ({ shop, args: args2 }) => proxy("POST", shop, "/order/202309/orders/search", {
213
226
  query: {
214
227
  page_size: args2["page-size"] ?? "20",
@@ -235,6 +248,7 @@ var COMMANDS = [
235
248
  {
236
249
  name: "orders cancellations",
237
250
  summary: "\u53D6\u6D88\u5355\u5217\u8868\uFF08--status \u53EF\u9009\uFF0C--page-size\uFF09",
251
+ listKey: "cancellations",
238
252
  run: ({ shop, args: args2 }) => proxy("POST", shop, "/return_refund/202309/cancellations/search", {
239
253
  query: { page_size: String(args2["page-size"] ?? 20) },
240
254
  body: args2.status ? { cancel_status: args2.status } : {}
@@ -243,6 +257,7 @@ var COMMANDS = [
243
257
  {
244
258
  name: "orders returns",
245
259
  summary: "\u9000\u8D27\u5355\u5217\u8868\uFF08--status \u53EF\u9009\uFF0C--page-size\uFF09",
260
+ listKey: "return_orders",
246
261
  run: ({ shop, args: args2 }) => proxy("POST", shop, "/return_refund/202309/returns/search", {
247
262
  query: { page_size: String(args2["page-size"] ?? 20) },
248
263
  body: args2.status ? { return_status: args2.status } : {}
@@ -261,6 +276,7 @@ var COMMANDS = [
261
276
  {
262
277
  name: "orders reject-reasons",
263
278
  summary: "\u9A73\u56DE\u53D6\u6D88/\u9000\u8D27\u7684\u5408\u6CD5\u7406\u7531\uFF08--id return_or_cancel_id\uFF09",
279
+ listKey: "reasons",
264
280
  run: ({ shop, args: args2 }) => proxy("GET", shop, "/return_refund/202309/reject_reasons", {
265
281
  query: { return_or_cancel_id: args2.id }
266
282
  })
@@ -288,6 +304,7 @@ var COMMANDS = [
288
304
  {
289
305
  name: "packages search",
290
306
  summary: "\u5305\u88F9\u5217\u8868\uFF08--page-size\uFF09",
307
+ listKey: "packages",
291
308
  run: ({ shop, args: args2 }) => proxy("POST", shop, "/fulfillment/202309/packages/search", {
292
309
  query: { page_size: String(args2["page-size"] ?? 20) },
293
310
  body: {}
@@ -560,6 +577,7 @@ var COMMANDS = [
560
577
  {
561
578
  name: "products list",
562
579
  summary: "\u5546\u54C1\u5217\u8868\uFF08--status ACTIVATE \u53EA\u53D6\u5728\u552E\uFF1B\u4E0D\u4F20\u8FD4\u6240\u6709\u542B DELETED\uFF0C\u5199\u64CD\u4F5C\u524D\u52A1\u5FC5\u7B5B ACTIVATE\uFF09",
580
+ listKey: "products",
563
581
  run: ({ shop, args: args2 }) => proxy("POST", shop, "/product/202309/products/search", {
564
582
  query: { page_size: args2["page-size"] ?? "20" },
565
583
  body: args2.status ? { status: args2.status } : {}
@@ -573,6 +591,7 @@ var COMMANDS = [
573
591
  {
574
592
  name: "products diagnose",
575
593
  summary: "\u5546\u54C1\u5B98\u65B9\u95EE\u9898\u8BCA\u65AD\uFF08--product \u9017\u53F7\u5206\u9694\u672C\u5E97\u81EA\u6709\u5546\u54C1 id\uFF09",
594
+ listKey: "products",
576
595
  run: ({ shop, args: args2 }) => proxy("GET", shop, "/product/202405/products/diagnoses", {
577
596
  query: { product_ids: String(args2.product ?? "") }
578
597
  })
@@ -580,6 +599,7 @@ var COMMANDS = [
580
599
  {
581
600
  name: "promotions list",
582
601
  summary: "\u4FC3\u9500\u6D3B\u52A8\u5217\u8868\uFF08--status ONGOING/NOT_START/EXPIRED\uFF09",
602
+ listKey: "activities",
583
603
  run: ({ shop, args: args2 }) => proxy("POST", shop, "/promotion/202309/activities/search", {
584
604
  body: { status: args2.status ?? "ONGOING", page_size: Number(args2["page-size"] ?? 20) }
585
605
  })
@@ -587,6 +607,7 @@ var COMMANDS = [
587
607
  {
588
608
  name: "finance statements",
589
609
  summary: "\u7ED3\u7B97\u5355\u5217\u8868",
610
+ listKey: "statements",
590
611
  run: ({ shop, args: args2 }) => proxy("GET", shop, "/finance/202309/statements", {
591
612
  query: {
592
613
  page_size: args2["page-size"] ?? "20",
@@ -615,6 +636,7 @@ var COMMANDS = [
615
636
  {
616
637
  name: "categories recommend",
617
638
  summary: "\u7C7B\u76EE\u63A8\u8350\uFF08--title [--desc]\uFF09",
639
+ listKey: "categories",
618
640
  run: ({ shop, args: args2 }) => proxy("POST", shop, "/product/202309/categories/recommend", {
619
641
  body: {
620
642
  product_title: args2.title,
@@ -625,6 +647,7 @@ var COMMANDS = [
625
647
  {
626
648
  name: "categories tree",
627
649
  summary: "\u7C7B\u76EE\u6811\uFF08--version v2\uFF09",
650
+ listKey: "categories",
628
651
  run: ({ shop, args: args2 }) => proxy("GET", shop, "/product/202309/categories", {
629
652
  query: { category_version: args2.version ?? "v2" }
630
653
  })
@@ -646,6 +669,7 @@ var COMMANDS = [
646
669
  {
647
670
  name: "brands list",
648
671
  summary: "\u54C1\u724C\u5217\u8868\uFF08[--category] [--name]\uFF09",
672
+ listKey: "brands",
649
673
  run: ({ shop, args: args2 }) => proxy("GET", shop, "/product/202309/brands", {
650
674
  query: {
651
675
  page_size: args2["page-size"] ?? "50",
@@ -664,11 +688,13 @@ var COMMANDS = [
664
688
  {
665
689
  name: "warehouses list",
666
690
  summary: "\u4ED3\u5E93\u5217\u8868\uFF08\u8DE8\u5883\u8BA4 sub_type CB_*\uFF09",
691
+ listKey: "warehouses",
667
692
  run: ({ shop }) => proxy("GET", shop, "/logistics/202309/warehouses", {})
668
693
  },
669
694
  {
670
695
  name: "shipping-templates list",
671
696
  summary: "\u8FD0\u8D39\u6A21\u677F\u5217\u8868",
697
+ listKey: "templates",
672
698
  run: ({ shop }) => proxy("GET", shop, "/logistics/202510/seller_templates", {})
673
699
  },
674
700
  {
@@ -783,6 +809,7 @@ var COMMANDS = [
783
809
  {
784
810
  name: "affiliate creators search",
785
811
  summary: "\u8054\u76DF\u5E7F\u573A\u627E\u8FBE\u4EBA\uFF08--keyword\uFF0C--page-size 12|20\uFF0C\u9ED8\u8BA4 12\uFF09",
812
+ listKey: "creators",
786
813
  run: ({ shop, args: args2 }) => proxy("POST", shop, "/affiliate_seller/202508/marketplace_creators/search", {
787
814
  query: { page_size: String(args2["page-size"] ?? 12) },
788
815
  body: args2.keyword ? { keyword: args2.keyword } : {}
@@ -796,6 +823,7 @@ var COMMANDS = [
796
823
  {
797
824
  name: "affiliate target-collab search",
798
825
  summary: "\u5B9A\u5411\u9080\u7EA6\u5217\u8868\uFF08--status collaboration_status\uFF0C\u5982 ONGOING/EXPIRING/VALID/CANCELING/COMPLETED\uFF1B--page-size\uFF09",
826
+ listKey: "target_collaborations",
799
827
  run: ({ shop, args: args2 }) => proxy("POST", shop, "/affiliate_seller/202508/target_collaborations/search", {
800
828
  query: { page_size: String(args2["page-size"] ?? 20) },
801
829
  body: args2.status ? { collaboration_status: args2.status } : {}
@@ -809,6 +837,7 @@ var COMMANDS = [
809
837
  {
810
838
  name: "affiliate samples search",
811
839
  summary: "\u6837\u54C1\u7533\u8BF7\u5217\u8868\uFF08--page-size\uFF09",
840
+ listKey: "sample_applications",
812
841
  run: ({ shop, args: args2 }) => proxy("POST", shop, "/affiliate_seller/202508/sample_applications/search", {
813
842
  query: { page_size: String(args2["page-size"] ?? 20) },
814
843
  body: {}
@@ -817,6 +846,7 @@ var COMMANDS = [
817
846
  {
818
847
  name: "affiliate dm list",
819
848
  summary: "\u79C1\u4FE1\u4F1A\u8BDD\u5217\u8868\uFF08--page-size\uFF0C--status conversation_status \u53EF\u9009\uFF09\u3002\u26A0\uFE0F\u7248\u672C\u56FA\u5B9A 202412",
849
+ listKey: "conversations",
820
850
  run: ({ shop, args: args2 }) => proxy("GET", shop, "/affiliate_seller/202412/conversations", {
821
851
  query: {
822
852
  page_size: String(args2["page-size"] ?? 20),
@@ -832,6 +862,7 @@ var COMMANDS = [
832
862
  {
833
863
  name: "affiliate orders search",
834
864
  summary: "\u8054\u76DF\u8BA2\u5355\u5217\u8868\uFF08\u4F63\u91D1\u660E\u7EC6\uFF0C--page-size\uFF09",
865
+ listKey: "orders",
835
866
  run: ({ shop, args: args2 }) => proxy("POST", shop, "/affiliate_seller/202410/orders/search", {
836
867
  query: { page_size: String(args2["page-size"] ?? 20) },
837
868
  body: {}
@@ -840,6 +871,7 @@ var COMMANDS = [
840
871
  {
841
872
  name: "affiliate open-collab products-search",
842
873
  summary: "\u516C\u5F00\u5408\u4F5C\u53EF\u8BBE\u4F63\u54C1\u5217\u8868\uFF08--page-size\uFF09",
874
+ listKey: "products",
843
875
  run: ({ shop, args: args2 }) => proxy("POST", shop, "/affiliate_seller/202405/open_collaborations/products/search", {
844
876
  query: { page_size: String(args2["page-size"] ?? 20) },
845
877
  body: {}
@@ -848,6 +880,7 @@ var COMMANDS = [
848
880
  {
849
881
  name: "affiliate open-collab search",
850
882
  summary: "\u516C\u5F00\u5408\u4F5C\u751F\u6548\u5217\u8868\uFF08\u542B current_commission\uFF0C--page-size\uFF09",
883
+ listKey: "open_collaborations",
851
884
  run: ({ shop, args: args2 }) => proxy("POST", shop, "/affiliate_seller/202412/open_collaborations/search", {
852
885
  query: { page_size: String(args2["page-size"] ?? 20) },
853
886
  body: {}
@@ -947,6 +980,7 @@ var COMMANDS = [
947
980
  {
948
981
  name: "affiliate samples review",
949
982
  summary: "\u5BA1\u6279\u6837\u54C1\u7533\u8BF7\uFF08--id application_id --result review_result [--reject-reason]\uFF09\u3002\u9ED8\u8BA4 dry-run\uFF0C--apply \u624D\u53D1",
983
+ listKey: "sample_applications",
950
984
  write: true,
951
985
  preview: ({ args: args2 }) => [{
952
986
  step: "\u5BA1\u6279\u6837\u54C1\u7533\u8BF7",
@@ -1011,7 +1045,7 @@ var COMMANDS = [
1011
1045
  // ── 多 App 管理(admin 配置操作,鉴权走 x-admin-token,不走商家 --shop,也不走三道阀 dry-run/--apply)──
1012
1046
  {
1013
1047
  name: "apps add",
1014
- summary: "\u767B\u8BB0\u4E00\u4E2A TikTok App\uFF08--service-id --app-key --app-secret --type --label\uFF0C[--markets a,b] [--redirect] [--owner-entity]\uFF09",
1048
+ summary: "\u767B\u8BB0\u4E00\u4E2A TikTok App\uFF08--service-id --app-key --app-secret --type --label\uFF0C[--markets a,b] [--redirect] [--owner-entity] [--default]\uFF09",
1015
1049
  run: ({ args: args2 }) => adminApps("POST", {
1016
1050
  body: {
1017
1051
  serviceId: args2["service-id"],
@@ -1131,7 +1165,13 @@ function parseFlags(tokens) {
1131
1165
  const positional2 = [];
1132
1166
  for (let i = 0; i < tokens.length; i++) {
1133
1167
  const t = tokens[i];
1168
+ if (t === "--") continue;
1134
1169
  if (t.startsWith("--")) {
1170
+ const eq = t.indexOf("=");
1171
+ if (eq !== -1) {
1172
+ args2[t.slice(2, eq)] = t.slice(eq + 1);
1173
+ continue;
1174
+ }
1135
1175
  const key = t.slice(2);
1136
1176
  const next = tokens[i + 1];
1137
1177
  if (next && !next.startsWith("--")) {
@@ -1142,6 +1182,33 @@ function parseFlags(tokens) {
1142
1182
  }
1143
1183
  return { args: args2, positional: positional2 };
1144
1184
  }
1185
+ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["apply", "default", "unprocessed", "enable"]);
1186
+ var FLAG_TRUE = /* @__PURE__ */ new Set(["true", "1", "yes", "on"]);
1187
+ var FLAG_FALSE = /* @__PURE__ */ new Set(["false", "0", "no", "off", ""]);
1188
+ function normalizeBooleanFlags(args2) {
1189
+ for (const key of BOOLEAN_FLAGS) {
1190
+ if (!(key in args2)) continue;
1191
+ const raw = args2[key];
1192
+ const v = raw.toLowerCase();
1193
+ if (FLAG_TRUE.has(v)) {
1194
+ args2[key] = "true";
1195
+ continue;
1196
+ }
1197
+ if (FLAG_FALSE.has(v)) {
1198
+ delete args2[key];
1199
+ continue;
1200
+ }
1201
+ out({
1202
+ ok: false,
1203
+ error: {
1204
+ code: "VALIDATION",
1205
+ message: `--${key} \u662F\u5F00\u5173\uFF0C\u53EA\u63A5\u53D7 true/1/yes/on \u6216 false/0/no/off\uFF0C\u6536\u5230\u300C${raw}\u300D`,
1206
+ retryable: false
1207
+ }
1208
+ });
1209
+ process.exit(1);
1210
+ }
1211
+ }
1145
1212
  function out(obj) {
1146
1213
  process.stdout.write(JSON.stringify(obj, null, 2) + "\n");
1147
1214
  }
@@ -1180,7 +1247,14 @@ if (positional[0] === "images" && positional[1] === "upload") {
1180
1247
  out(r);
1181
1248
  process.exit(0);
1182
1249
  }
1250
+ var wantsHelp = argv.includes("--help") || argv.includes("-h");
1183
1251
  var match = findCommand(positional);
1252
+ if (wantsHelp) {
1253
+ if (match) process.stderr.write(commandUsage(match.cmd));
1254
+ else usage();
1255
+ process.exit(0);
1256
+ }
1257
+ normalizeBooleanFlags(args);
1184
1258
  if (!match) {
1185
1259
  out({ ok: false, error: { code: "VALIDATION", message: `\u672A\u77E5\u547D\u4EE4: ${positional.join(" ")}`, retryable: false } });
1186
1260
  usage();
@@ -1212,6 +1286,7 @@ if (match.cmd.write && !("apply" in args)) {
1212
1286
  process.exit(0);
1213
1287
  }
1214
1288
  var env = await match.cmd.run(ctx);
1289
+ fillEmptyList(env.data, match.cmd.listKey);
1215
1290
  if (match.cmd.write && env.ok) {
1216
1291
  const result = { ...env, applied: true };
1217
1292
  if (env.data?.warnings?.length) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optima-chat/tiktok-cli",
3
- "version": "0.10.0",
3
+ "version": "0.10.2",
4
4
  "description": "TikTok Shop CLI for Optima agents — 经 tiktok-backend 操作店铺",
5
5
  "type": "module",
6
6
  "bin": {