@youzan-cloud/zan-saas-cli 0.0.0-stage → 0.1.0-beta.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.
Files changed (329) hide show
  1. package/DEPENDENCIES.json +50 -0
  2. package/INSTALL.md +79 -0
  3. package/LICENSE +21 -0
  4. package/NOTICE +1 -0
  5. package/README.md +151 -2
  6. package/THIRD_PARTY_NOTICES.txt +162 -0
  7. package/bin/zan-saas-cli.js +28 -0
  8. package/internal/registry/index.js +123 -0
  9. package/internal/registry/manifest.json +424 -0
  10. package/npm-shrinkwrap.json +86 -0
  11. package/package.json +33 -4
  12. package/skills/README.md +30 -0
  13. package/skills/zan-saas/SKILL.md +54 -0
  14. package/skills/zan-saas/references/host-entry.md +25 -0
  15. package/skills/zan-saas-access/SKILL.md +37 -0
  16. package/skills/zan-saas-access/references/role-list.md +11 -0
  17. package/skills/zan-saas-access/references/staff-perms-get.md +11 -0
  18. package/skills/zan-saas-aftersale/SKILL.md +31 -0
  19. package/skills/zan-saas-aftersale/references/case-list.md +13 -0
  20. package/skills/zan-saas-aftersale/references/case-scan.md +31 -0
  21. package/skills/zan-saas-benefit/SKILL.md +46 -0
  22. package/skills/zan-saas-benefit/references/card-get.md +7 -0
  23. package/skills/zan-saas-benefit/references/card-grant-list.md +11 -0
  24. package/skills/zan-saas-benefit/references/card-list.md +7 -0
  25. package/skills/zan-saas-benefit/references/customer-card-get.md +7 -0
  26. package/skills/zan-saas-benefit/references/customer-card-list.md +7 -0
  27. package/skills/zan-saas-coupon/SKILL.md +41 -0
  28. package/skills/zan-saas-coupon/references/activity-get.md +11 -0
  29. package/skills/zan-saas-coupon/references/activity-list.md +15 -0
  30. package/skills/zan-saas-coupon/references/voucher-get.md +13 -0
  31. package/skills/zan-saas-coupon/references/voucher-list.md +25 -0
  32. package/skills/zan-saas-customer/SKILL.md +73 -0
  33. package/skills/zan-saas-customer/references/customer-scan.md +11 -0
  34. package/skills/zan-saas-customer/references/segment-list.md +22 -0
  35. package/skills/zan-saas-fulfillment/SKILL.md +36 -0
  36. package/skills/zan-saas-fulfillment/references/delivery-get.md +11 -0
  37. package/skills/zan-saas-fulfillment/references/shipment-list.md +11 -0
  38. package/skills/zan-saas-fulfillment/references/waybill-get.md +9 -0
  39. package/skills/zan-saas-interaction/SKILL.md +37 -0
  40. package/skills/zan-saas-interaction/references/lottery-get.md +11 -0
  41. package/skills/zan-saas-interaction/references/lottery-list.md +19 -0
  42. package/skills/zan-saas-item/SKILL.md +61 -0
  43. package/skills/zan-saas-item/references/attribute-list.md +11 -0
  44. package/skills/zan-saas-item/references/brand-list.md +7 -0
  45. package/skills/zan-saas-item/references/classification-get.md +7 -0
  46. package/skills/zan-saas-item/references/classification-list.md +7 -0
  47. package/skills/zan-saas-item/references/group-list.md +9 -0
  48. package/skills/zan-saas-item/references/item-content.md +9 -0
  49. package/skills/zan-saas-item/references/item-get.md +9 -0
  50. package/skills/zan-saas-item/references/item-search.md +23 -0
  51. package/skills/zan-saas-item/references/product-identity.md +11 -0
  52. package/skills/zan-saas-member/SKILL.md +41 -0
  53. package/skills/zan-saas-member/references/customer-level-get.md +7 -0
  54. package/skills/zan-saas-member/references/growth-log-list.md +17 -0
  55. package/skills/zan-saas-member/references/membership-get.md +7 -0
  56. package/skills/zan-saas-order/SKILL.md +56 -0
  57. package/skills/zan-saas-order/references/order-get.md +26 -0
  58. package/skills/zan-saas-order/references/order-list.md +25 -0
  59. package/skills/zan-saas-order/references/order-scan.md +35 -0
  60. package/skills/zan-saas-org/SKILL.md +37 -0
  61. package/skills/zan-saas-org/references/staff-get.md +15 -0
  62. package/skills/zan-saas-org/references/staff-role-get.md +11 -0
  63. package/skills/zan-saas-org/references/unit-get.md +11 -0
  64. package/skills/zan-saas-org/references/unit-list.md +15 -0
  65. package/skills/zan-saas-points/SKILL.md +42 -0
  66. package/skills/zan-saas-points/references/account-get.md +7 -0
  67. package/skills/zan-saas-points/references/log-list.md +17 -0
  68. package/skills/zan-saas-points/references/rule-list.md +2 -0
  69. package/skills/zan-saas-privacy/SKILL.md +30 -0
  70. package/skills/zan-saas-privacy/references/field-decrypt.md +19 -0
  71. package/skills/zan-saas-shared/SKILL.md +94 -0
  72. package/skills/zan-saas-shared/references/authentication.md +52 -0
  73. package/skills/zan-saas-shared/references/value-processing.md +27 -0
  74. package/skills/zan-saas-stock/SKILL.md +28 -0
  75. package/skills/zan-saas-stock/references/log-list.md +11 -0
  76. package/skills/zan-saas-valuecard/SKILL.md +37 -0
  77. package/skills/zan-saas-valuecard/references/card-get.md +13 -0
  78. package/skills/zan-saas-valuecard/references/card-list.md +11 -0
  79. package/src/auth/browser.js +28 -0
  80. package/src/auth/callback-server.js +99 -0
  81. package/src/auth/config.js +53 -0
  82. package/src/auth/credential-store.js +109 -0
  83. package/src/auth/oauth-client.js +105 -0
  84. package/src/auth/pkce.js +28 -0
  85. package/src/auth/session.js +178 -0
  86. package/src/auth/tool.js +25 -0
  87. package/src/cli/command-paths.js +126 -0
  88. package/src/cli/context-help.js +102 -0
  89. package/src/cli/diagnostic-command.js +57 -0
  90. package/src/cli/domain-catalog.js +42 -0
  91. package/src/cli/help-text.js +32 -0
  92. package/src/cli/native-loader.js +120 -0
  93. package/src/cli/native-path.js +22 -0
  94. package/src/cli/parser-policy.js +141 -0
  95. package/src/cli/program.js +134 -0
  96. package/src/cli/skill-catalog.js +241 -0
  97. package/src/commands/native/access/commands.index.json +24 -0
  98. package/src/commands/native/access/domain.json +3 -0
  99. package/src/commands/native/access/role/list/command.js +141 -0
  100. package/src/commands/native/access/role/list/schema.json +393 -0
  101. package/src/commands/native/access/staff-perms/get/command.js +119 -0
  102. package/src/commands/native/access/staff-perms/get/schema.json +703 -0
  103. package/src/commands/native/aftersale/case/get/command.js +104 -0
  104. package/src/commands/native/aftersale/case/get/exact-json.js +52 -0
  105. package/src/commands/native/aftersale/case/get/money.js +28 -0
  106. package/src/commands/native/aftersale/case/get/projection.js +120 -0
  107. package/src/commands/native/aftersale/case/get/query.js +72 -0
  108. package/src/commands/native/aftersale/case/get/schema.json +134 -0
  109. package/src/commands/native/aftersale/case/list/command.js +135 -0
  110. package/src/commands/native/aftersale/case/list/schema.json +1095 -0
  111. package/src/commands/native/aftersale/case/scan/command.js +110 -0
  112. package/src/commands/native/aftersale/case/scan/query.js +62 -0
  113. package/src/commands/native/aftersale/case/scan/scan.js +78 -0
  114. package/src/commands/native/aftersale/case/scan/schema.json +964 -0
  115. package/src/commands/native/aftersale/case/scan/search.js +108 -0
  116. package/src/commands/native/aftersale/commands.index.json +42 -0
  117. package/src/commands/native/aftersale/domain.json +3 -0
  118. package/src/commands/native/aftersale/refund/list/command.js +97 -0
  119. package/src/commands/native/aftersale/refund/list/money.js +25 -0
  120. package/src/commands/native/aftersale/refund/list/projection.js +50 -0
  121. package/src/commands/native/aftersale/refund/list/query.js +73 -0
  122. package/src/commands/native/aftersale/refund/list/schema.json +130 -0
  123. package/src/commands/native/aftersale/shared/query.js +58 -0
  124. package/src/commands/native/aftersale/shared/search.js +128 -0
  125. package/src/commands/native/benefit/card-definition/get/command.js +110 -0
  126. package/src/commands/native/benefit/card-definition/get/schema.json +545 -0
  127. package/src/commands/native/benefit/card-definition/list/command.js +105 -0
  128. package/src/commands/native/benefit/card-definition/list/schema.json +690 -0
  129. package/src/commands/native/benefit/card-grant/list/command.js +135 -0
  130. package/src/commands/native/benefit/card-grant/list/schema.json +758 -0
  131. package/src/commands/native/benefit/commands.index.json +51 -0
  132. package/src/commands/native/benefit/customer-card/get/command.js +110 -0
  133. package/src/commands/native/benefit/customer-card/get/schema.json +340 -0
  134. package/src/commands/native/benefit/customer-card/list/command.js +102 -0
  135. package/src/commands/native/benefit/customer-card/list/schema.json +731 -0
  136. package/src/commands/native/benefit/domain.json +3 -0
  137. package/src/commands/native/coupon/activity/get/command.js +183 -0
  138. package/src/commands/native/coupon/activity/get/schema.json +624 -0
  139. package/src/commands/native/coupon/activity/list/command.js +169 -0
  140. package/src/commands/native/coupon/activity/list/schema.json +845 -0
  141. package/src/commands/native/coupon/commands.index.json +42 -0
  142. package/src/commands/native/coupon/domain.json +3 -0
  143. package/src/commands/native/coupon/shared/query.js +15 -0
  144. package/src/commands/native/coupon/voucher/get/command.js +113 -0
  145. package/src/commands/native/coupon/voucher/get/schema.json +147 -0
  146. package/src/commands/native/coupon/voucher/list/command.js +155 -0
  147. package/src/commands/native/coupon/voucher/list/schema.json +772 -0
  148. package/src/commands/native/customer/commands.index.json +96 -0
  149. package/src/commands/native/customer/customer/get/adapter.js +82 -0
  150. package/src/commands/native/customer/customer/get/command.js +106 -0
  151. package/src/commands/native/customer/customer/get/schema.json +958 -0
  152. package/src/commands/native/customer/customer/list/command.js +78 -0
  153. package/src/commands/native/customer/customer/list/input.js +145 -0
  154. package/src/commands/native/customer/customer/list/query.js +103 -0
  155. package/src/commands/native/customer/customer/list/schema.json +969 -0
  156. package/src/commands/native/customer/customer/scan/command.js +80 -0
  157. package/src/commands/native/customer/customer/scan/scan.js +92 -0
  158. package/src/commands/native/customer/customer/scan/schema.json +211 -0
  159. package/src/commands/native/customer/customer-tag/get/command.js +166 -0
  160. package/src/commands/native/customer/customer-tag/get/schema.json +317 -0
  161. package/src/commands/native/customer/customer-tag/list/command.js +143 -0
  162. package/src/commands/native/customer/customer-tag/list/schema.json +259 -0
  163. package/src/commands/native/customer/domain.json +3 -0
  164. package/src/commands/native/customer/segment/list/command.js +96 -0
  165. package/src/commands/native/customer/segment/list/query.js +98 -0
  166. package/src/commands/native/customer/segment/list/schema.json +135 -0
  167. package/src/commands/native/customer/segment-customer/list/command.js +171 -0
  168. package/src/commands/native/customer/segment-customer/list/schema.json +123 -0
  169. package/src/commands/native/customer/shared/search-input.js +179 -0
  170. package/src/commands/native/customer/shared/search-page.js +54 -0
  171. package/src/commands/native/customer/tag/get/command.js +73 -0
  172. package/src/commands/native/customer/tag/get/schema.json +339 -0
  173. package/src/commands/native/customer/tagcategory/get/command.js +80 -0
  174. package/src/commands/native/customer/tagcategory/get/query.js +98 -0
  175. package/src/commands/native/customer/tagcategory/get/schema.json +339 -0
  176. package/src/commands/native/customer/tagcategory/list/command.js +127 -0
  177. package/src/commands/native/customer/tagcategory/list/schema.json +394 -0
  178. package/src/commands/native/fulfillment/commands.index.json +33 -0
  179. package/src/commands/native/fulfillment/delivery/get/command.js +107 -0
  180. package/src/commands/native/fulfillment/delivery/get/projection.js +142 -0
  181. package/src/commands/native/fulfillment/delivery/get/schema.json +173 -0
  182. package/src/commands/native/fulfillment/domain.json +3 -0
  183. package/src/commands/native/fulfillment/shipment/list/command.js +83 -0
  184. package/src/commands/native/fulfillment/shipment/list/projection.js +130 -0
  185. package/src/commands/native/fulfillment/shipment/list/schema.json +752 -0
  186. package/src/commands/native/fulfillment/waybill/get/command.js +193 -0
  187. package/src/commands/native/fulfillment/waybill/get/response.js +68 -0
  188. package/src/commands/native/fulfillment/waybill/get/schema.json +190 -0
  189. package/src/commands/native/interaction/commands.index.json +24 -0
  190. package/src/commands/native/interaction/domain.json +3 -0
  191. package/src/commands/native/interaction/lottery/get/command.js +61 -0
  192. package/src/commands/native/interaction/lottery/get/query.js +152 -0
  193. package/src/commands/native/interaction/lottery/get/schema.json +1004 -0
  194. package/src/commands/native/interaction/lottery/list/command.js +176 -0
  195. package/src/commands/native/interaction/lottery/list/schema.json +898 -0
  196. package/src/commands/native/item/attribute/list/command.js +122 -0
  197. package/src/commands/native/item/attribute/list/schema.json +727 -0
  198. package/src/commands/native/item/brand/list/command.js +114 -0
  199. package/src/commands/native/item/brand/list/schema.json +725 -0
  200. package/src/commands/native/item/classification/get/command.js +87 -0
  201. package/src/commands/native/item/classification/get/schema.json +596 -0
  202. package/src/commands/native/item/classification/list/command.js +105 -0
  203. package/src/commands/native/item/classification/list/schema.json +676 -0
  204. package/src/commands/native/item/commands.index.json +87 -0
  205. package/src/commands/native/item/domain.json +1 -0
  206. package/src/commands/native/item/group/list/command.js +122 -0
  207. package/src/commands/native/item/group/list/schema.json +809 -0
  208. package/src/commands/native/item/item/get/command.js +122 -0
  209. package/src/commands/native/item/item/get/schema.json +3799 -0
  210. package/src/commands/native/item/item/list/command.js +7 -0
  211. package/src/commands/native/item/item/list/schema.json +1118 -0
  212. package/src/commands/native/item/item/scan/command.js +7 -0
  213. package/src/commands/native/item/item/scan/schema.json +1046 -0
  214. package/src/commands/native/item/item-content/get/command.js +54 -0
  215. package/src/commands/native/item/item-content/get/schema.json +677 -0
  216. package/src/commands/native/item/shared/api.js +31 -0
  217. package/src/commands/native/item/shared/content.js +20 -0
  218. package/src/commands/native/item/shared/diagnostics.js +61 -0
  219. package/src/commands/native/item/shared/h5.js +63 -0
  220. package/src/commands/native/item/shared/identity.js +62 -0
  221. package/src/commands/native/item/shared/normalize.js +49 -0
  222. package/src/commands/native/item/shared/scope.js +22 -0
  223. package/src/commands/native/item/shared/search-command.js +61 -0
  224. package/src/commands/native/item/shared/search-options.js +150 -0
  225. package/src/commands/native/item/shared/search.js +158 -0
  226. package/src/commands/native/member/commands.index.json +60 -0
  227. package/src/commands/native/member/customer-level/get/command.js +122 -0
  228. package/src/commands/native/member/customer-level/get/schema.json +300 -0
  229. package/src/commands/native/member/domain.json +3 -0
  230. package/src/commands/native/member/growth/get/command.js +64 -0
  231. package/src/commands/native/member/growth/get/schema.json +283 -0
  232. package/src/commands/native/member/growth-log/list/command.js +203 -0
  233. package/src/commands/native/member/growth-log/list/schema.json +695 -0
  234. package/src/commands/native/member/level/get/command.js +70 -0
  235. package/src/commands/native/member/level/get/query.js +125 -0
  236. package/src/commands/native/member/level/get/schema.json +339 -0
  237. package/src/commands/native/member/level/list/command.js +50 -0
  238. package/src/commands/native/member/level/list/query.js +109 -0
  239. package/src/commands/native/member/level/list/schema.json +104 -0
  240. package/src/commands/native/member/membership/get/command.js +78 -0
  241. package/src/commands/native/member/membership/get/schema.json +283 -0
  242. package/src/commands/native/order/commands.index.json +33 -0
  243. package/src/commands/native/order/domain.json +3 -0
  244. package/src/commands/native/order/order/get/command.js +155 -0
  245. package/src/commands/native/order/order/get/schema.json +1167 -0
  246. package/src/commands/native/order/order/list/command.js +230 -0
  247. package/src/commands/native/order/order/list/schema.json +1363 -0
  248. package/src/commands/native/order/order/scan/command.js +148 -0
  249. package/src/commands/native/order/order/scan/scan.js +89 -0
  250. package/src/commands/native/order/order/scan/schema.json +1445 -0
  251. package/src/commands/native/order/shared/projection.js +183 -0
  252. package/src/commands/native/order/shared/query.js +84 -0
  253. package/src/commands/native/order/shared/search.js +112 -0
  254. package/src/commands/native/org/commands.index.json +42 -0
  255. package/src/commands/native/org/domain.json +3 -0
  256. package/src/commands/native/org/shared/single-staff.js +115 -0
  257. package/src/commands/native/org/staff/get/command.js +148 -0
  258. package/src/commands/native/org/staff/get/schema.json +114 -0
  259. package/src/commands/native/org/staff-role/get/command.js +45 -0
  260. package/src/commands/native/org/staff-role/get/schema.json +93 -0
  261. package/src/commands/native/org/unit/get/command.js +131 -0
  262. package/src/commands/native/org/unit/get/schema.json +478 -0
  263. package/src/commands/native/org/unit/list/command.js +187 -0
  264. package/src/commands/native/org/unit/list/schema.json +828 -0
  265. package/src/commands/native/points/account/get/command.js +65 -0
  266. package/src/commands/native/points/account/get/schema.json +303 -0
  267. package/src/commands/native/points/commands.index.json +33 -0
  268. package/src/commands/native/points/domain.json +3 -0
  269. package/src/commands/native/points/log/list/command.js +141 -0
  270. package/src/commands/native/points/log/list/schema.json +761 -0
  271. package/src/commands/native/points/rule/list/command.js +82 -0
  272. package/src/commands/native/points/rule/list/schema.json +294 -0
  273. package/src/commands/native/privacy/commands.index.json +15 -0
  274. package/src/commands/native/privacy/domain.json +3 -0
  275. package/src/commands/native/privacy/field/decrypt/command.js +185 -0
  276. package/src/commands/native/privacy/field/decrypt/schema.json +656 -0
  277. package/src/commands/native/privacy/shared/order-source.js +33 -0
  278. package/src/commands/native/stock/commands.index.json +15 -0
  279. package/src/commands/native/stock/domain.json +3 -0
  280. package/src/commands/native/stock/log/list/command.js +207 -0
  281. package/src/commands/native/stock/log/list/schema.json +922 -0
  282. package/src/commands/native/valuecard/card/get/command.js +107 -0
  283. package/src/commands/native/valuecard/card/get/schema.json +683 -0
  284. package/src/commands/native/valuecard/card/list/command.js +136 -0
  285. package/src/commands/native/valuecard/card/list/pagination.js +23 -0
  286. package/src/commands/native/valuecard/card/list/schema.json +780 -0
  287. package/src/commands/native/valuecard/commands.index.json +24 -0
  288. package/src/commands/native/valuecard/domain.json +3 -0
  289. package/src/commands/native/valuecard/shared/projection.js +57 -0
  290. package/src/commands/system/api.js +47 -0
  291. package/src/commands/system/auth.js +118 -0
  292. package/src/commands/system/contracts.js +373 -0
  293. package/src/commands/system/doctor.js +24 -0
  294. package/src/commands/system/install.js +41 -0
  295. package/src/commands/system/printer.js +16 -0
  296. package/src/commands/system/schema.js +162 -0
  297. package/src/commands/system/shop-guidance.js +9 -0
  298. package/src/commands/system/shop.js +237 -0
  299. package/src/commands/system/skills.js +49 -0
  300. package/src/execution/beijing-date-time.js +29 -0
  301. package/src/execution/beijing-time.js +21 -0
  302. package/src/execution/bounded-input.js +42 -0
  303. package/src/execution/command-io.js +137 -0
  304. package/src/execution/command-policy.js +41 -0
  305. package/src/execution/command-schema.js +131 -0
  306. package/src/execution/datetime.js +83 -0
  307. package/src/execution/error-details.js +399 -0
  308. package/src/execution/error-model.js +82 -0
  309. package/src/execution/exact-json.js +80 -0
  310. package/src/execution/list-total.js +10 -0
  311. package/src/execution/money.js +59 -0
  312. package/src/execution/parser-error.js +66 -0
  313. package/src/execution/privacy.js +197 -0
  314. package/src/execution/public-schema.js +52 -0
  315. package/src/execution/query-api.js +101 -0
  316. package/src/execution/range.js +84 -0
  317. package/src/execution/request-state.js +55 -0
  318. package/src/execution/schema-completeness.js +116 -0
  319. package/src/execution/shop-query.js +54 -0
  320. package/src/execution/target-shop-default.js +23 -0
  321. package/src/execution/target-shop.js +49 -0
  322. package/src/identity/context-store.js +54 -0
  323. package/src/identity/context.js +38 -0
  324. package/src/installation/install.js +158 -0
  325. package/src/installation/npm-error.js +93 -0
  326. package/src/installation/skill.js +113 -0
  327. package/src/transport/account-api.js +152 -0
  328. package/src/transport/api.js +199 -0
  329. package/src/transport/shop-app.js +63 -0
@@ -0,0 +1,70 @@
1
+ 'use strict';
2
+
3
+ const { withTargetShopDefault } = require('../../../../../execution/target-shop-default');
4
+
5
+ const { Command, Option } = require('commander');
6
+ const { createShopQuery, failure } = require('../../../../../execution/shop-query');
7
+ const {
8
+ buildLevelInvocation, executeLevelInvocation, LevelDefinitionError
9
+ } = require('./query');
10
+
11
+ const command = 'member.level.get';
12
+ const reject = (category, stage, scope, state, facts) =>
13
+ failure(command, category, stage, scope, state, facts);
14
+
15
+ function createCommand({ context } = {}) {
16
+ return new Command('get')
17
+ .description('按完整 alias 查询一个等级定义,保留已禁用等级')
18
+ .allowExcessArguments(false)
19
+ .exitOverride(error => {
20
+ if (['commander.helpDisplayed', 'commander.version'].includes(error.code)) throw error;
21
+ throw reject('parameter', 'input');
22
+ })
23
+ .requiredOption('--level-alias <alias>', '必填:完整等级别名;不是等级 ID、名称或序号')
24
+ .addOption(new Option('--level-type <type>', '1 免费,2 付费;省略时依次查询两类')
25
+ .choices(['1', '2']))
26
+ .option('--kdt-id <id>', '目标店铺正安全整数;省略取本次有效上下文 shopId')
27
+ .addOption(new Option('--format <format>', 'json 或 pretty,仅改变缩进')
28
+ .choices(['json', 'pretty']).default('json'))
29
+ .option('--dry-run', '本地预览店铺核验和固定查询计划,不读凭证、不联网')
30
+ .addHelpText('after', `
31
+ 输出 data.level;alias 唯一匹配才成功,不以等级值或名称替代主键。
32
+ 先核验凭证店铺,再请求指定类型一次,或按 1、2 固定请求两次。
33
+ 任一必要请求失败、重复匹配或模型不符整体失败;未返回不表示全局不存在。
34
+ 不分页、不返回全部权益、不重试、不切换店铺或身份。
35
+ 真实执行需有效四字段上下文和同店授权凭证;店铺回读不证明员工 OAuth。
36
+ 契约:zan-saas schema member.level.get
37
+ 示例:zan-saas member level get --level-alias level-1 --kdt-id 63077 --dry-run
38
+ `)
39
+ .action(async options => {
40
+ let invocation;
41
+ try { invocation = buildLevelInvocation(options, context); }
42
+ catch (error) {
43
+ if (error.cliDetails) throw error;
44
+ throw reject('parameter', 'input');
45
+ }
46
+ let output;
47
+ if (invocation.dryRun) {
48
+ output = invocation.plan;
49
+ } else {
50
+ const scope = invocation.plan.scope;
51
+ const read = await createShopQuery(scope, command);
52
+ let facts = {};
53
+ try {
54
+ output = await executeLevelInvocation(invocation, async request => {
55
+ const result = await read(request.path, request.body, 'level');
56
+ facts = result.facts;
57
+ return result.data;
58
+ });
59
+ } catch (error) {
60
+ if (!(error instanceof LevelDefinitionError)) throw error;
61
+ const category = error.code === 'LEVEL_NOT_RETURNED' ? 'not_found' :
62
+ error.code === 'LEVEL_AMBIGUOUS' ? 'ambiguous' : 'protocol';
63
+ throw reject(category, error.stage, scope, 'sent', facts);
64
+ }
65
+ }
66
+ process.stdout.write(`${JSON.stringify(output, null, options.format === 'pretty' ? 2 : 0)}\n`);
67
+ });
68
+ }
69
+
70
+ module.exports = { kind: 'atomic', risk: 'read', at: 'all', createCommand: withTargetShopDefault(createCommand) };
@@ -0,0 +1,125 @@
1
+ 'use strict';
2
+
3
+ const { validateCommandValue } = require('../../../../../execution/command-schema');
4
+ const { resolveTargetShop } = require('../../../../../execution/target-shop');
5
+ const { bindingPath } = require('../../../../../execution/shop-query');
6
+ const schema = require('./schema.json');
7
+
8
+ class LevelDefinitionError extends Error {
9
+ constructor(code, stage, message) {
10
+ super(message);
11
+ this.name = 'LevelDefinitionError';
12
+ this.code = code;
13
+ this.stage = stage;
14
+ }
15
+ }
16
+
17
+ function invalidInput() {
18
+ return new LevelDefinitionError('LEVEL_PARAMETER', 'selection-input',
19
+ 'Level lookup requires a positive safe target, a nonempty alias, an optional type of exactly 1 or 2 and json or pretty format.');
20
+ }
21
+
22
+ function parseLevelSelection(options) {
23
+ if (typeof options?.levelAlias !== 'string' || !options.levelAlias.trim()) {
24
+ throw invalidInput();
25
+ }
26
+ const selection = { levelAlias: options.levelAlias.trim() };
27
+ if (options.levelType !== undefined) {
28
+ if (!['1', '2'].includes(options.levelType)) throw invalidInput();
29
+ selection.levelType = Number(options.levelType);
30
+ }
31
+ return selection;
32
+ }
33
+
34
+ function buildLevelPlan(input) {
35
+ try { validateCommandValue(schema, 'input', input); }
36
+ catch { throw invalidInput(); }
37
+ const scope = Object.freeze({ kdtId: input.kdtId });
38
+ const selection = Object.freeze({ levelAlias: input.levelAlias });
39
+ const types = input.levelType === undefined ? [1, 2] : [input.levelType];
40
+ const requests = Object.freeze(types.map(levelType => Object.freeze({
41
+ method: 'POST',
42
+ path: schema.api.path,
43
+ body: Object.freeze({ level_type: levelType })
44
+ })));
45
+ const prerequisites = Object.freeze([Object.freeze({
46
+ method: 'POST', path: bindingPath, body: Object.freeze({})
47
+ })]);
48
+ const plan = Object.freeze({ scope, requests, selection, prerequisites });
49
+ validateCommandValue(schema, 'preview', plan);
50
+ return plan;
51
+ }
52
+
53
+ function buildLevelInvocation(options, context) {
54
+ const scope = resolveTargetShop(options, context, 'member.level.get');
55
+ const selection = parseLevelSelection(options);
56
+ if (options.format !== undefined && !['json', 'pretty'].includes(options.format)) {
57
+ throw invalidInput();
58
+ }
59
+ const input = Object.freeze({ ...scope, ...selection });
60
+ return Object.freeze({
61
+ input,
62
+ plan: buildLevelPlan(input),
63
+ format: options.format ?? 'json',
64
+ dryRun: options.dryRun === true
65
+ });
66
+ }
67
+
68
+ async function executeLevelInvocation(invocation, readData) {
69
+ if (invocation.dryRun) return invocation.plan;
70
+ return getLevelDefinition(invocation.input, readData);
71
+ }
72
+
73
+ function object(value) {
74
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
75
+ }
76
+
77
+ function invalidList() {
78
+ return new LevelDefinitionError('LEVEL_PROTOCOL', 'level-list',
79
+ 'Expected data.level_details with nonempty aliases and the requested level type.');
80
+ }
81
+
82
+ async function getLevelDefinition(input, readData) {
83
+ const plan = buildLevelPlan(input);
84
+ if (typeof readData !== 'function') throw new TypeError('A scoped data reader is required');
85
+ const matches = [];
86
+ for (const request of plan.requests) {
87
+ const data = await readData(request, plan.scope);
88
+ if (!object(data) || !Array.isArray(data.level_details)) throw invalidList();
89
+ for (const candidate of data.level_details) {
90
+ if (!object(candidate) || typeof candidate.level_alias !== 'string' ||
91
+ !candidate.level_alias.trim() || candidate.level_type !== request.body.level_type) {
92
+ throw invalidList();
93
+ }
94
+ if (candidate.level_alias === plan.selection.levelAlias) {
95
+ matches.push({
96
+ level_alias: candidate.level_alias,
97
+ name: candidate.name,
98
+ level_type: candidate.level_type,
99
+ level_value: candidate.level_value,
100
+ is_enabled: candidate.is_enabled
101
+ });
102
+ }
103
+ }
104
+ }
105
+ if (!matches.length) {
106
+ throw new LevelDefinitionError('LEVEL_NOT_RETURNED', 'level-selection',
107
+ 'Alias was not returned in the queried types; verify scope and collection completeness.');
108
+ }
109
+ if (matches.length !== 1) {
110
+ throw new LevelDefinitionError('LEVEL_AMBIGUOUS', 'level-selection',
111
+ 'Alias has multiple matches in the queried level definitions.');
112
+ }
113
+ const output = { data: { level: matches[0] } };
114
+ try { validateCommandValue(schema, 'output', output); }
115
+ catch {
116
+ throw new LevelDefinitionError('LEVEL_PROTOCOL', 'level-model',
117
+ 'The matched definition does not satisfy the required base level model.');
118
+ }
119
+ return output;
120
+ }
121
+
122
+ module.exports = {
123
+ parseLevelSelection, buildLevelPlan, buildLevelInvocation, executeLevelInvocation,
124
+ getLevelDefinition, LevelDefinitionError
125
+ };
@@ -0,0 +1,339 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "input": {
4
+ "type": "object",
5
+ "required": [
6
+ "kdtId",
7
+ "levelAlias"
8
+ ],
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "kdtId": {
12
+ "type": "integer",
13
+ "minimum": 1,
14
+ "maximum": 9007199254740991,
15
+ "description": "目标店铺 ID,省略选项时取有效上下文 shopId;不表示已经获准访问。"
16
+ },
17
+ "levelAlias": {
18
+ "type": "string",
19
+ "pattern": "\\S",
20
+ "description": "完整等级别名,按大小写精确匹配。"
21
+ },
22
+ "levelType": {
23
+ "type": "integer",
24
+ "enum": [
25
+ 1,
26
+ 2
27
+ ],
28
+ "description": "省略时固定依次查询免费和付费类型。"
29
+ }
30
+ },
31
+ "description": "CLI 解析参数并完成必要上下文补全后的业务输入;不是直接传入 CLI 的 JSON。原始选项、必填条件和默认值见 options。"
32
+ },
33
+ "output": {
34
+ "type": "object",
35
+ "required": [
36
+ "data"
37
+ ],
38
+ "additionalProperties": false,
39
+ "properties": {
40
+ "data": {
41
+ "type": "object",
42
+ "required": [
43
+ "level"
44
+ ],
45
+ "additionalProperties": false,
46
+ "properties": {
47
+ "level": {
48
+ "type": "object",
49
+ "required": [
50
+ "level_alias",
51
+ "name",
52
+ "level_type",
53
+ "level_value",
54
+ "is_enabled"
55
+ ],
56
+ "additionalProperties": false,
57
+ "properties": {
58
+ "level_alias": {
59
+ "type": "string",
60
+ "pattern": "\\S",
61
+ "description": "等级别名,不用 ID、名称或序号替代。"
62
+ },
63
+ "name": {
64
+ "type": "string",
65
+ "description": "等级名称,空字符串原样保留。"
66
+ },
67
+ "level_type": {
68
+ "type": "integer",
69
+ "enum": [
70
+ 1,
71
+ 2
72
+ ],
73
+ "description": "1 为免费、2 为付费,须与请求类型相同。"
74
+ },
75
+ "level_value": {
76
+ "type": "integer",
77
+ "minimum": -9007199254740991,
78
+ "maximum": 9007199254740991,
79
+ "description": "安全整数等级值,不作为主键。"
80
+ },
81
+ "is_enabled": {
82
+ "type": "boolean",
83
+ "description": "是否启用,false 仍是可读取的等级定义。"
84
+ }
85
+ }
86
+ }
87
+ }
88
+ }
89
+ }
90
+ },
91
+ "preview": {
92
+ "type": "object",
93
+ "required": [
94
+ "scope",
95
+ "requests",
96
+ "selection",
97
+ "prerequisites"
98
+ ],
99
+ "additionalProperties": false,
100
+ "properties": {
101
+ "scope": {
102
+ "type": "object",
103
+ "required": [
104
+ "kdtId"
105
+ ],
106
+ "additionalProperties": false,
107
+ "properties": {
108
+ "kdtId": {
109
+ "type": "integer",
110
+ "minimum": 1,
111
+ "maximum": 9007199254740991
112
+ }
113
+ }
114
+ },
115
+ "requests": {
116
+ "type": "array",
117
+ "minItems": 1,
118
+ "maxItems": 2,
119
+ "items": {
120
+ "type": "object",
121
+ "required": [
122
+ "method",
123
+ "path",
124
+ "body"
125
+ ],
126
+ "additionalProperties": false,
127
+ "properties": {
128
+ "method": {
129
+ "const": "POST"
130
+ },
131
+ "path": {
132
+ "const": "youzan.scrm.level.list/3.0.0"
133
+ },
134
+ "body": {
135
+ "type": "object",
136
+ "required": [
137
+ "level_type"
138
+ ],
139
+ "additionalProperties": false,
140
+ "properties": {
141
+ "level_type": {
142
+ "type": "integer",
143
+ "enum": [
144
+ 1,
145
+ 2
146
+ ]
147
+ }
148
+ }
149
+ }
150
+ }
151
+ }
152
+ },
153
+ "selection": {
154
+ "type": "object",
155
+ "required": [
156
+ "levelAlias"
157
+ ],
158
+ "additionalProperties": false,
159
+ "properties": {
160
+ "levelAlias": {
161
+ "type": "string",
162
+ "pattern": "\\S"
163
+ }
164
+ }
165
+ },
166
+ "prerequisites": {
167
+ "type": "array",
168
+ "minItems": 1,
169
+ "maxItems": 1,
170
+ "items": {
171
+ "type": "object",
172
+ "required": [
173
+ "method",
174
+ "path",
175
+ "body"
176
+ ],
177
+ "additionalProperties": false,
178
+ "properties": {
179
+ "method": {
180
+ "const": "POST"
181
+ },
182
+ "path": {
183
+ "const": "youzan.shop.basic.get/3.0.0"
184
+ },
185
+ "body": {
186
+ "type": "object",
187
+ "additionalProperties": false
188
+ }
189
+ }
190
+ }
191
+ }
192
+ }
193
+ },
194
+ "api": {
195
+ "method": "POST",
196
+ "path": "youzan.scrm.level.list/3.0.0"
197
+ },
198
+ "modules": {
199
+ "level": {
200
+ "base": true,
201
+ "upstreamPath": "data.level_details",
202
+ "required": true,
203
+ "description": "查询集合中按完整 alias 唯一匹配的等级定义。"
204
+ }
205
+ },
206
+ "notes": [
207
+ "按完整 alias 唯一匹配等级定义,区分大小写;禁用等级仍可返回,0 和 false 原样保留。",
208
+ "--level-type 1 为免费等级,2 为付费等级;省略时依次读取两种类型,必要请求失败整体失败。",
209
+ "只返回基础定义字段,不返回完整权益、不分页;未返回不证明全局不存在。",
210
+ "店铺默认取有效上下文 shopId,显式非法值不回退,非总部不能跨店;预览零网络。",
211
+ "本地 --dry-run 不读取凭证、不联网;预览只证明构造计划,不证明对象存在或权限有效。真实执行仍需有效上下文及目标范围授权,at 声明不替代服务端授权。"
212
+ ],
213
+ "error": {
214
+ "type": "object",
215
+ "required": [
216
+ "success",
217
+ "code",
218
+ "message",
219
+ "details"
220
+ ],
221
+ "additionalProperties": false,
222
+ "properties": {
223
+ "success": {
224
+ "const": false
225
+ },
226
+ "code": {
227
+ "const": -10001
228
+ },
229
+ "message": {
230
+ "type": "string",
231
+ "minLength": 1
232
+ },
233
+ "details": {
234
+ "type": "object",
235
+ "required": [
236
+ "category",
237
+ "stage",
238
+ "command",
239
+ "targetScope",
240
+ "requestState",
241
+ "nextStep"
242
+ ],
243
+ "additionalProperties": false,
244
+ "properties": {
245
+ "category": {
246
+ "type": "string",
247
+ "enum": [
248
+ "validation",
249
+ "configuration",
250
+ "parameter",
251
+ "permission",
252
+ "authentication",
253
+ "scope_unresolved",
254
+ "transport",
255
+ "http",
256
+ "protocol",
257
+ "business_rejected",
258
+ "not_found",
259
+ "target_mismatch",
260
+ "ambiguous"
261
+ ]
262
+ },
263
+ "stage": {
264
+ "type": "string",
265
+ "minLength": 1
266
+ },
267
+ "command": {
268
+ "const": "member.level.get"
269
+ },
270
+ "targetScope": {
271
+ "type": "object",
272
+ "additionalProperties": false,
273
+ "properties": {
274
+ "kdtId": {
275
+ "$ref": "#/definitions/shopId"
276
+ }
277
+ }
278
+ },
279
+ "requestState": {
280
+ "enum": [
281
+ "not_sent",
282
+ "sent",
283
+ "unknown"
284
+ ]
285
+ },
286
+ "nextStep": {
287
+ "type": "string",
288
+ "minLength": 1
289
+ },
290
+ "api": {
291
+ "type": "string"
292
+ },
293
+ "httpStatus": {
294
+ "type": "integer"
295
+ },
296
+ "businessCode": {
297
+ "anyOf": [
298
+ {
299
+ "type": "integer"
300
+ },
301
+ {
302
+ "type": "string"
303
+ }
304
+ ]
305
+ },
306
+ "gatewayCode": {
307
+ "anyOf": [
308
+ {
309
+ "type": "integer"
310
+ },
311
+ {
312
+ "type": "string"
313
+ }
314
+ ]
315
+ },
316
+ "trace_id": {
317
+ "type": "string"
318
+ },
319
+ "request_id": {
320
+ "type": "string"
321
+ }
322
+ }
323
+ }
324
+ }
325
+ },
326
+ "definitions": {
327
+ "shopId": {
328
+ "type": "integer",
329
+ "minimum": 1,
330
+ "maximum": 9007199254740991
331
+ }
332
+ },
333
+ "success": {
334
+ "description": "必要类型均成功读取,完整 alias 唯一匹配,基础定义满足模型后成功。"
335
+ },
336
+ "errors": {
337
+ "description": "失败 stdout 为空,stderr 为一份脱敏错误 JSON,退出码非零;不返回部分成功,不自动重试、切换身份或目标。按 error 模型及安全下一步处理。"
338
+ }
339
+ }
@@ -0,0 +1,50 @@
1
+ 'use strict';
2
+
3
+ const { withTargetShopDefault } = require('../../../../../execution/target-shop-default');
4
+
5
+ const { Command, Option } = require('commander');
6
+ const { buildInput, preview, listLevels, serialize, reject } = require('./query');
7
+
8
+ function createCommand({ context } = {}) {
9
+ const instance = new Command('list')
10
+ .description('查询商家当前免费、付费等级定义目录,保留禁用等级')
11
+ .allowExcessArguments(false)
12
+ .exitOverride(error => {
13
+ if (['commander.helpDisplayed', 'commander.version'].includes(error.code)) throw error;
14
+ throw reject('parameter', 'input');
15
+ })
16
+ .option('--kdt-id <id>', '目标店铺正安全整数;省略取本次有效上下文 shopId')
17
+ .addOption(new Option('--level-type <type>', '1=免费等级,2=付费等级;省略依次查询两类')
18
+ .choices(['1', '2']))
19
+ .addOption(new Option('--format <format>', 'json=单行 JSON,pretty=缩进 JSON,仅改变缩进')
20
+ .choices(['json', 'pretty']).default('json'))
21
+ .option('--dry-run', '本地预览目标和完整请求计划,不读凭证、不联网')
22
+ .addHelpText('after', `
23
+ 输出 data.levels,先免费再付费,各类保持响应原序,包含禁用及零等级值。
24
+ level_id 仅在源返回时提供,不能用 level_value、alias 或其它 ID 补造。
25
+ 目录定义不证明客户实际获得等级;按 alias 读取定义用 member level get。
26
+ 默认含店铺核验及两次计费目录请求;指定类型含核验及一次目录请求。
27
+ 不分页、不排序、不返回完整权益;任一必要请求、字段或重复同类型 alias 异常整体失败。
28
+ 每类最多1000条,合计2000条;每请求10秒,累计响应10MiB,含换行输出5MiB。
29
+ 不截断、不重试、不切换店铺或身份。真实执行需有效四字段上下文和同店授权。
30
+ 店铺回读和应用身份测试不证明员工 OAuth 或跨店权限。
31
+ 契约:zan-saas schema member.level.list
32
+ 示例:zan-saas member level list --kdt-id 63077 --dry-run
33
+ 示例:zan-saas member level list --level-type 2 --format pretty
34
+ `);
35
+ const supplied = new Set();
36
+ for (const option of instance.options) {
37
+ instance.on(`option:${option.name()}`, () => {
38
+ if (supplied.has(option.name())) throw reject('parameter', 'input');
39
+ supplied.add(option.name());
40
+ });
41
+ }
42
+ return instance.action(async options => {
43
+ const input = buildInput(options, context);
44
+ const output = options.dryRun ? preview(input) : await listLevels(input);
45
+ process.stdout.write(serialize(output, options.format, { kdtId: input.kdtId },
46
+ options.dryRun ? 'not_sent' : 'sent'));
47
+ });
48
+ }
49
+
50
+ module.exports = { kind: 'atomic', risk: 'read', at: 'all', createCommand: withTargetShopDefault(createCommand) };
@@ -0,0 +1,109 @@
1
+ 'use strict';
2
+
3
+ const { createBoundShopQuery, bindingPath, failure } = require('../../../../../execution/shop-query');
4
+ const { resolveTargetShop } = require('../../../../../execution/target-shop');
5
+ const { validateCommandValue } = require('../../../../../execution/command-schema');
6
+ const { object } = require('../../../../../execution/query-api');
7
+ const schema = require('./schema.json');
8
+
9
+ const command = 'member.level.list';
10
+ const responseLimit = 10 * 1024 * 1024;
11
+ const outputLimit = 5 * 1024 * 1024;
12
+
13
+ function reject(category, stage, scope = {}, state = 'not_sent', facts = {}) {
14
+ const error = failure(command, category, stage, scope, state, facts);
15
+ error.cliDetails.nextStep = '核对原店铺、所选等级类型、参数和服务端授权;不自动移除类型、切换店铺或身份、换源或重试。';
16
+ return error;
17
+ }
18
+
19
+ function adaptError(error, scope = {}, stage = 'input', api) {
20
+ const details = error.cliDetails;
21
+ if (!details) return reject('protocol', stage, scope, 'unknown', api ? { api } : {});
22
+ const mappedStage = ['context', 'configuration'].includes(details.stage) ? details.stage : stage;
23
+ const facts = {};
24
+ for (const key of ['api', 'httpStatus', 'businessCode', 'gatewayCode', 'trace_id', 'request_id']) {
25
+ if (Object.hasOwn(details, key)) facts[key] = details[key];
26
+ }
27
+ if (api) facts.api = api;
28
+ return reject(details.category, mappedStage, details.targetScope ?? scope,
29
+ details.requestState, facts);
30
+ }
31
+
32
+ function buildInput(options, context) {
33
+ let scope;
34
+ try { scope = resolveTargetShop(options, context, command); }
35
+ catch (error) { throw adaptError(error); }
36
+ if (options.levelType !== undefined && !['1', '2'].includes(options.levelType)) {
37
+ throw reject('validation', 'input', scope);
38
+ }
39
+ const input = { ...scope };
40
+ if (options.levelType !== undefined) input.levelType = Number(options.levelType);
41
+ validateCommandValue(schema, 'input', input);
42
+ return Object.freeze(input);
43
+ }
44
+
45
+ function preview(input) {
46
+ const types = input.levelType === undefined ? [1, 2] : [input.levelType];
47
+ return {
48
+ scope: { kdtId: input.kdtId },
49
+ requests: [
50
+ { method: 'POST', path: bindingPath, body: {} },
51
+ ...types.map(levelType => ({ method: 'POST', path: schema.api.path, body: { level_type: levelType } }))
52
+ ]
53
+ };
54
+ }
55
+
56
+ function projectLevels(data, levelType, scope, facts) {
57
+ const invalid = () => reject('protocol', 'levels', scope, 'sent', facts);
58
+ if (!object(data) || !Array.isArray(data.level_details)) throw invalid();
59
+ if (data.level_details.length > 1000) throw reject('limit', 'levels', scope, 'sent', facts);
60
+ const seen = new Set();
61
+ return data.level_details.map(source => {
62
+ if (!object(source) || typeof source.level_alias !== 'string' || !source.level_alias.trim() ||
63
+ source.level_type !== levelType || seen.has(source.level_alias)) throw invalid();
64
+ seen.add(source.level_alias);
65
+ const level = {
66
+ level_alias: source.level_alias, name: source.name, level_type: source.level_type,
67
+ level_value: source.level_value, is_enabled: source.is_enabled
68
+ };
69
+ if (Object.hasOwn(source, 'level_id')) {
70
+ if (!Number.isSafeInteger(source.level_id) || source.level_id < 1) throw invalid();
71
+ level.level_id = String(source.level_id);
72
+ }
73
+ if (Object.hasOwn(source, 'min_growth')) {
74
+ if (!Number.isSafeInteger(source.min_growth)) throw invalid();
75
+ level.min_growth = source.min_growth;
76
+ }
77
+ try { validateCommandValue(schema, 'output', { data: { levels: [level] } }); }
78
+ catch { throw invalid(); }
79
+ return level;
80
+ });
81
+ }
82
+
83
+ async function listLevels(input) {
84
+ const plan = preview(input), scope = plan.scope;
85
+ let responseBytes = 0, read;
86
+ try {
87
+ ({ read } = await createBoundShopQuery(scope, command, 'shop-binding', {
88
+ onResponse(response) { responseBytes += response.responseBytes; },
89
+ transportOptions: { shopApp: false, timeoutMs: 10000,
90
+ maxResponseBytes: () => responseLimit - responseBytes }
91
+ }));
92
+ } catch (error) { throw adaptError(error, scope, 'shop-binding', bindingPath); }
93
+ const levels = [];
94
+ for (const request of plan.requests.slice(1)) {
95
+ let result;
96
+ try { result = await read(request.path, request.body, 'levels'); }
97
+ catch (error) { throw adaptError(error, scope, 'levels', request.path); }
98
+ levels.push(...projectLevels(result.data, request.body.level_type, scope, result.facts));
99
+ }
100
+ return { data: { levels } };
101
+ }
102
+
103
+ function serialize(output, format, scope, state = 'sent') {
104
+ const text = `${JSON.stringify(output, null, format === 'pretty' ? 2 : 0)}\n`;
105
+ if (Buffer.byteLength(text, 'utf8') > outputLimit) throw reject('limit', 'output', scope, state);
106
+ return text;
107
+ }
108
+
109
+ module.exports = { buildInput, preview, listLevels, projectLevels, serialize, reject };