shop-cli 0.1.1

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 (350) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +392 -0
  3. package/bin/shop-cli.js +17 -0
  4. package/bin/shop.js +16 -0
  5. package/dist/adminClient.d.ts +34 -0
  6. package/dist/adminClient.js +144 -0
  7. package/dist/cli/client.d.ts +10 -0
  8. package/dist/cli/client.js +56 -0
  9. package/dist/cli/command.d.ts +5 -0
  10. package/dist/cli/command.js +62 -0
  11. package/dist/cli/errors.d.ts +4 -0
  12. package/dist/cli/errors.js +35 -0
  13. package/dist/cli/gid.d.ts +3 -0
  14. package/dist/cli/gid.js +42 -0
  15. package/dist/cli/globalFlags.d.ts +15 -0
  16. package/dist/cli/globalFlags.js +100 -0
  17. package/dist/cli/headers.d.ts +2 -0
  18. package/dist/cli/headers.js +79 -0
  19. package/dist/cli/help/format.d.ts +8 -0
  20. package/dist/cli/help/format.js +78 -0
  21. package/dist/cli/help/registry.d.ts +5 -0
  22. package/dist/cli/help/registry.js +6443 -0
  23. package/dist/cli/help/render.d.ts +8 -0
  24. package/dist/cli/help/render.js +399 -0
  25. package/dist/cli/help/spec.d.ts +39 -0
  26. package/dist/cli/help/spec.js +17 -0
  27. package/dist/cli/input.d.ts +9 -0
  28. package/dist/cli/input.js +104 -0
  29. package/dist/cli/introspection/deprecations.d.ts +1 -0
  30. package/dist/cli/introspection/deprecations.js +83 -0
  31. package/dist/cli/introspection/format.d.ts +6 -0
  32. package/dist/cli/introspection/format.js +63 -0
  33. package/dist/cli/introspection/index.d.ts +14 -0
  34. package/dist/cli/introspection/index.js +89 -0
  35. package/dist/cli/introspection/resources.d.ts +1 -0
  36. package/dist/cli/introspection/resources.js +127 -0
  37. package/dist/cli/output/computedFields.d.ts +39 -0
  38. package/dist/cli/output/computedFields.js +104 -0
  39. package/dist/cli/output.d.ts +37 -0
  40. package/dist/cli/output.js +332 -0
  41. package/dist/cli/parse-command.d.ts +18 -0
  42. package/dist/cli/parse-command.js +109 -0
  43. package/dist/cli/router.d.ts +29 -0
  44. package/dist/cli/router.js +480 -0
  45. package/dist/cli/selection/buildAllSelection.d.ts +13 -0
  46. package/dist/cli/selection/buildAllSelection.js +108 -0
  47. package/dist/cli/selection/graphqlSelection.d.ts +5 -0
  48. package/dist/cli/selection/graphqlSelection.js +301 -0
  49. package/dist/cli/selection/select.d.ts +13 -0
  50. package/dist/cli/selection/select.js +136 -0
  51. package/dist/cli/selection/stripDeprecated.d.ts +2 -0
  52. package/dist/cli/selection/stripDeprecated.js +63 -0
  53. package/dist/cli/suggest.d.ts +5 -0
  54. package/dist/cli/suggest.js +88 -0
  55. package/dist/cli/userErrors.d.ts +4 -0
  56. package/dist/cli/userErrors.js +41 -0
  57. package/dist/cli/verbs/_shared.d.ts +38 -0
  58. package/dist/cli/verbs/_shared.js +181 -0
  59. package/dist/cli/verbs/abandoned-checkouts.d.ts +6 -0
  60. package/dist/cli/verbs/abandoned-checkouts.js +259 -0
  61. package/dist/cli/verbs/app-billing.d.ts +6 -0
  62. package/dist/cli/verbs/app-billing.js +452 -0
  63. package/dist/cli/verbs/apps.d.ts +6 -0
  64. package/dist/cli/verbs/apps.js +296 -0
  65. package/dist/cli/verbs/articles.d.ts +6 -0
  66. package/dist/cli/verbs/articles.js +251 -0
  67. package/dist/cli/verbs/backup.d.ts +6 -0
  68. package/dist/cli/verbs/backup.js +94 -0
  69. package/dist/cli/verbs/blogs.d.ts +6 -0
  70. package/dist/cli/verbs/blogs.js +273 -0
  71. package/dist/cli/verbs/bulk-operations.d.ts +6 -0
  72. package/dist/cli/verbs/bulk-operations.js +272 -0
  73. package/dist/cli/verbs/business-entities.d.ts +6 -0
  74. package/dist/cli/verbs/business-entities.js +102 -0
  75. package/dist/cli/verbs/carrier-services.d.ts +6 -0
  76. package/dist/cli/verbs/carrier-services.js +195 -0
  77. package/dist/cli/verbs/cart-transforms.d.ts +6 -0
  78. package/dist/cli/verbs/cart-transforms.js +141 -0
  79. package/dist/cli/verbs/cash-tracking.d.ts +6 -0
  80. package/dist/cli/verbs/cash-tracking.js +118 -0
  81. package/dist/cli/verbs/catalogs.d.ts +6 -0
  82. package/dist/cli/verbs/catalogs.js +267 -0
  83. package/dist/cli/verbs/channels.d.ts +6 -0
  84. package/dist/cli/verbs/channels.js +120 -0
  85. package/dist/cli/verbs/checkout-branding.d.ts +6 -0
  86. package/dist/cli/verbs/checkout-branding.js +144 -0
  87. package/dist/cli/verbs/checkout-profiles.d.ts +6 -0
  88. package/dist/cli/verbs/checkout-profiles.js +124 -0
  89. package/dist/cli/verbs/collections.d.ts +6 -0
  90. package/dist/cli/verbs/collections.js +620 -0
  91. package/dist/cli/verbs/comments.d.ts +6 -0
  92. package/dist/cli/verbs/comments.js +160 -0
  93. package/dist/cli/verbs/companies.d.ts +6 -0
  94. package/dist/cli/verbs/companies.js +313 -0
  95. package/dist/cli/verbs/company-contacts.d.ts +6 -0
  96. package/dist/cli/verbs/company-contacts.js +318 -0
  97. package/dist/cli/verbs/company-locations.d.ts +6 -0
  98. package/dist/cli/verbs/company-locations.js +467 -0
  99. package/dist/cli/verbs/customer-account-pages.d.ts +6 -0
  100. package/dist/cli/verbs/customer-account-pages.js +97 -0
  101. package/dist/cli/verbs/customer-payment-methods.d.ts +6 -0
  102. package/dist/cli/verbs/customer-payment-methods.js +358 -0
  103. package/dist/cli/verbs/customer-privacy.d.ts +6 -0
  104. package/dist/cli/verbs/customer-privacy.js +167 -0
  105. package/dist/cli/verbs/customer-segments.d.ts +6 -0
  106. package/dist/cli/verbs/customer-segments.js +193 -0
  107. package/dist/cli/verbs/customers.d.ts +6 -0
  108. package/dist/cli/verbs/customers.js +793 -0
  109. package/dist/cli/verbs/delegate-tokens.d.ts +6 -0
  110. package/dist/cli/verbs/delegate-tokens.js +95 -0
  111. package/dist/cli/verbs/delivery-customizations.d.ts +6 -0
  112. package/dist/cli/verbs/delivery-customizations.js +205 -0
  113. package/dist/cli/verbs/delivery-profile-locations.d.ts +6 -0
  114. package/dist/cli/verbs/delivery-profile-locations.js +90 -0
  115. package/dist/cli/verbs/delivery-profiles.d.ts +6 -0
  116. package/dist/cli/verbs/delivery-profiles.js +207 -0
  117. package/dist/cli/verbs/delivery-promises.d.ts +6 -0
  118. package/dist/cli/verbs/delivery-promises.js +262 -0
  119. package/dist/cli/verbs/delivery-settings.d.ts +6 -0
  120. package/dist/cli/verbs/delivery-settings.js +85 -0
  121. package/dist/cli/verbs/discount-nodes.d.ts +6 -0
  122. package/dist/cli/verbs/discount-nodes.js +169 -0
  123. package/dist/cli/verbs/discount-redeem-codes.d.ts +6 -0
  124. package/dist/cli/verbs/discount-redeem-codes.js +102 -0
  125. package/dist/cli/verbs/discount-saved-searches.d.ts +6 -0
  126. package/dist/cli/verbs/discount-saved-searches.js +113 -0
  127. package/dist/cli/verbs/discounts-automatic.d.ts +6 -0
  128. package/dist/cli/verbs/discounts-automatic.js +501 -0
  129. package/dist/cli/verbs/discounts-code.d.ts +6 -0
  130. package/dist/cli/verbs/discounts-code.js +540 -0
  131. package/dist/cli/verbs/disputes.d.ts +6 -0
  132. package/dist/cli/verbs/disputes.js +154 -0
  133. package/dist/cli/verbs/draft-orders.d.ts +6 -0
  134. package/dist/cli/verbs/draft-orders.js +475 -0
  135. package/dist/cli/verbs/events.d.ts +6 -0
  136. package/dist/cli/verbs/events.js +182 -0
  137. package/dist/cli/verbs/file-saved-searches.d.ts +6 -0
  138. package/dist/cli/verbs/file-saved-searches.js +83 -0
  139. package/dist/cli/verbs/files.d.ts +6 -0
  140. package/dist/cli/verbs/files.js +329 -0
  141. package/dist/cli/verbs/finance.d.ts +6 -0
  142. package/dist/cli/verbs/finance.js +115 -0
  143. package/dist/cli/verbs/flow.d.ts +6 -0
  144. package/dist/cli/verbs/flow.js +94 -0
  145. package/dist/cli/verbs/fulfillment-constraint-rules.d.ts +6 -0
  146. package/dist/cli/verbs/fulfillment-constraint-rules.js +139 -0
  147. package/dist/cli/verbs/fulfillment-orders.d.ts +6 -0
  148. package/dist/cli/verbs/fulfillment-orders.js +689 -0
  149. package/dist/cli/verbs/fulfillment-services.d.ts +6 -0
  150. package/dist/cli/verbs/fulfillment-services.js +212 -0
  151. package/dist/cli/verbs/fulfillments.d.ts +6 -0
  152. package/dist/cli/verbs/fulfillments.js +279 -0
  153. package/dist/cli/verbs/gift-cards.d.ts +6 -0
  154. package/dist/cli/verbs/gift-cards.js +359 -0
  155. package/dist/cli/verbs/graphql.d.ts +14 -0
  156. package/dist/cli/verbs/graphql.js +285 -0
  157. package/dist/cli/verbs/inventory-items.d.ts +6 -0
  158. package/dist/cli/verbs/inventory-items.js +164 -0
  159. package/dist/cli/verbs/inventory-shipments.d.ts +6 -0
  160. package/dist/cli/verbs/inventory-shipments.js +276 -0
  161. package/dist/cli/verbs/inventory-transfers.d.ts +6 -0
  162. package/dist/cli/verbs/inventory-transfers.js +396 -0
  163. package/dist/cli/verbs/inventory.d.ts +6 -0
  164. package/dist/cli/verbs/inventory.js +557 -0
  165. package/dist/cli/verbs/locales.d.ts +6 -0
  166. package/dist/cli/verbs/locales.js +61 -0
  167. package/dist/cli/verbs/locations.d.ts +6 -0
  168. package/dist/cli/verbs/locations.js +385 -0
  169. package/dist/cli/verbs/market-localizations.d.ts +6 -0
  170. package/dist/cli/verbs/market-localizations.js +291 -0
  171. package/dist/cli/verbs/market-web-presences.d.ts +6 -0
  172. package/dist/cli/verbs/market-web-presences.js +139 -0
  173. package/dist/cli/verbs/marketing-activities.d.ts +6 -0
  174. package/dist/cli/verbs/marketing-activities.js +353 -0
  175. package/dist/cli/verbs/marketing-events.d.ts +6 -0
  176. package/dist/cli/verbs/marketing-events.js +132 -0
  177. package/dist/cli/verbs/markets.d.ts +6 -0
  178. package/dist/cli/verbs/markets.js +357 -0
  179. package/dist/cli/verbs/menus.d.ts +6 -0
  180. package/dist/cli/verbs/menus.js +251 -0
  181. package/dist/cli/verbs/metafield-definition-tools.d.ts +6 -0
  182. package/dist/cli/verbs/metafield-definition-tools.js +289 -0
  183. package/dist/cli/verbs/metafield-definitions.d.ts +6 -0
  184. package/dist/cli/verbs/metafield-definitions.js +240 -0
  185. package/dist/cli/verbs/metafields.d.ts +6 -0
  186. package/dist/cli/verbs/metafields.js +112 -0
  187. package/dist/cli/verbs/metaobject-definition-tools.d.ts +6 -0
  188. package/dist/cli/verbs/metaobject-definition-tools.js +83 -0
  189. package/dist/cli/verbs/metaobject-definitions.d.ts +6 -0
  190. package/dist/cli/verbs/metaobject-definitions.js +176 -0
  191. package/dist/cli/verbs/metaobjects.d.ts +6 -0
  192. package/dist/cli/verbs/metaobjects.js +306 -0
  193. package/dist/cli/verbs/mobile-platform-applications.d.ts +6 -0
  194. package/dist/cli/verbs/mobile-platform-applications.js +247 -0
  195. package/dist/cli/verbs/order-edit.d.ts +6 -0
  196. package/dist/cli/verbs/order-edit.js +596 -0
  197. package/dist/cli/verbs/orders.d.ts +6 -0
  198. package/dist/cli/verbs/orders.js +853 -0
  199. package/dist/cli/verbs/pages.d.ts +6 -0
  200. package/dist/cli/verbs/pages.js +234 -0
  201. package/dist/cli/verbs/payment-customizations.d.ts +6 -0
  202. package/dist/cli/verbs/payment-customizations.js +193 -0
  203. package/dist/cli/verbs/payment-terms.d.ts +6 -0
  204. package/dist/cli/verbs/payment-terms.js +228 -0
  205. package/dist/cli/verbs/point-of-sale.d.ts +6 -0
  206. package/dist/cli/verbs/point-of-sale.js +57 -0
  207. package/dist/cli/verbs/price-lists.d.ts +6 -0
  208. package/dist/cli/verbs/price-lists.js +426 -0
  209. package/dist/cli/verbs/product-feeds.d.ts +6 -0
  210. package/dist/cli/verbs/product-feeds.js +187 -0
  211. package/dist/cli/verbs/product-variants.d.ts +6 -0
  212. package/dist/cli/verbs/product-variants.js +439 -0
  213. package/dist/cli/verbs/products.d.ts +6 -0
  214. package/dist/cli/verbs/products.js +2309 -0
  215. package/dist/cli/verbs/publications.d.ts +6 -0
  216. package/dist/cli/verbs/publications.js +256 -0
  217. package/dist/cli/verbs/publishables.d.ts +6 -0
  218. package/dist/cli/verbs/publishables.js +73 -0
  219. package/dist/cli/verbs/refunds.d.ts +6 -0
  220. package/dist/cli/verbs/refunds.js +226 -0
  221. package/dist/cli/verbs/resource-feedback.d.ts +6 -0
  222. package/dist/cli/verbs/resource-feedback.js +119 -0
  223. package/dist/cli/verbs/returnable-fulfillments.d.ts +6 -0
  224. package/dist/cli/verbs/returnable-fulfillments.js +102 -0
  225. package/dist/cli/verbs/returns.d.ts +6 -0
  226. package/dist/cli/verbs/returns.js +506 -0
  227. package/dist/cli/verbs/reverse-deliveries.d.ts +6 -0
  228. package/dist/cli/verbs/reverse-deliveries.js +203 -0
  229. package/dist/cli/verbs/reverse-fulfillment-orders.d.ts +6 -0
  230. package/dist/cli/verbs/reverse-fulfillment-orders.js +157 -0
  231. package/dist/cli/verbs/saved-searches.d.ts +6 -0
  232. package/dist/cli/verbs/saved-searches.js +150 -0
  233. package/dist/cli/verbs/script-tags.d.ts +6 -0
  234. package/dist/cli/verbs/script-tags.js +179 -0
  235. package/dist/cli/verbs/segments.d.ts +6 -0
  236. package/dist/cli/verbs/segments.js +343 -0
  237. package/dist/cli/verbs/selling-plan-group-products.d.ts +6 -0
  238. package/dist/cli/verbs/selling-plan-group-products.js +115 -0
  239. package/dist/cli/verbs/selling-plan-groups.d.ts +6 -0
  240. package/dist/cli/verbs/selling-plan-groups.js +230 -0
  241. package/dist/cli/verbs/server-pixels.d.ts +6 -0
  242. package/dist/cli/verbs/server-pixels.js +172 -0
  243. package/dist/cli/verbs/shipping-packages.d.ts +6 -0
  244. package/dist/cli/verbs/shipping-packages.js +107 -0
  245. package/dist/cli/verbs/shop-policies.d.ts +6 -0
  246. package/dist/cli/verbs/shop-policies.js +91 -0
  247. package/dist/cli/verbs/shop-utils.d.ts +6 -0
  248. package/dist/cli/verbs/shop-utils.js +147 -0
  249. package/dist/cli/verbs/shop.d.ts +6 -0
  250. package/dist/cli/verbs/shop.js +177 -0
  251. package/dist/cli/verbs/shopify-functions.d.ts +6 -0
  252. package/dist/cli/verbs/shopify-functions.js +127 -0
  253. package/dist/cli/verbs/shopify-payments.d.ts +6 -0
  254. package/dist/cli/verbs/shopify-payments.js +111 -0
  255. package/dist/cli/verbs/staff.d.ts +6 -0
  256. package/dist/cli/verbs/staff.js +127 -0
  257. package/dist/cli/verbs/staged-uploads.d.ts +6 -0
  258. package/dist/cli/verbs/staged-uploads.js +128 -0
  259. package/dist/cli/verbs/store-credit.d.ts +6 -0
  260. package/dist/cli/verbs/store-credit.js +209 -0
  261. package/dist/cli/verbs/storefront-access-tokens.d.ts +6 -0
  262. package/dist/cli/verbs/storefront-access-tokens.js +183 -0
  263. package/dist/cli/verbs/subscription-billing-cycles.d.ts +6 -0
  264. package/dist/cli/verbs/subscription-billing-cycles.js +391 -0
  265. package/dist/cli/verbs/subscription-billing.d.ts +6 -0
  266. package/dist/cli/verbs/subscription-billing.js +391 -0
  267. package/dist/cli/verbs/subscription-contracts.d.ts +6 -0
  268. package/dist/cli/verbs/subscription-contracts.js +392 -0
  269. package/dist/cli/verbs/subscription-drafts.d.ts +6 -0
  270. package/dist/cli/verbs/subscription-drafts.js +315 -0
  271. package/dist/cli/verbs/tags.d.ts +6 -0
  272. package/dist/cli/verbs/tags.js +73 -0
  273. package/dist/cli/verbs/tax.d.ts +6 -0
  274. package/dist/cli/verbs/tax.js +114 -0
  275. package/dist/cli/verbs/taxonomy.d.ts +6 -0
  276. package/dist/cli/verbs/taxonomy.js +99 -0
  277. package/dist/cli/verbs/tender-transactions.d.ts +6 -0
  278. package/dist/cli/verbs/tender-transactions.js +105 -0
  279. package/dist/cli/verbs/themes.d.ts +6 -0
  280. package/dist/cli/verbs/themes.js +315 -0
  281. package/dist/cli/verbs/translations.d.ts +6 -0
  282. package/dist/cli/verbs/translations.js +221 -0
  283. package/dist/cli/verbs/types.d.ts +4 -0
  284. package/dist/cli/verbs/types.js +224 -0
  285. package/dist/cli/verbs/url-redirects.d.ts +6 -0
  286. package/dist/cli/verbs/url-redirects.js +465 -0
  287. package/dist/cli/verbs/validations.d.ts +6 -0
  288. package/dist/cli/verbs/validations.js +181 -0
  289. package/dist/cli/verbs/web-pixels.d.ts +6 -0
  290. package/dist/cli/verbs/web-pixels.js +145 -0
  291. package/dist/cli/verbs/web-presences.d.ts +6 -0
  292. package/dist/cli/verbs/web-presences.js +186 -0
  293. package/dist/cli/verbs/webhooks.d.ts +6 -0
  294. package/dist/cli/verbs/webhooks.js +336 -0
  295. package/dist/cli/workflows/files/stagedUploads.d.ts +28 -0
  296. package/dist/cli/workflows/files/stagedUploads.js +227 -0
  297. package/dist/cli/workflows/files/stdinFile.d.ts +7 -0
  298. package/dist/cli/workflows/files/stdinFile.js +65 -0
  299. package/dist/cli/workflows/files/urlDownloads.d.ts +14 -0
  300. package/dist/cli/workflows/files/urlDownloads.js +114 -0
  301. package/dist/cli/workflows/files/waitForReady.d.ts +20 -0
  302. package/dist/cli/workflows/files/waitForReady.js +114 -0
  303. package/dist/cli/workflows/inventory/resolveInventoryItemId.d.ts +6 -0
  304. package/dist/cli/workflows/inventory/resolveInventoryItemId.js +59 -0
  305. package/dist/cli/workflows/productVariants/upsert.d.ts +8 -0
  306. package/dist/cli/workflows/productVariants/upsert.js +110 -0
  307. package/dist/cli/workflows/products/metafieldsUpsert.d.ts +6 -0
  308. package/dist/cli/workflows/products/metafieldsUpsert.js +94 -0
  309. package/dist/cli/workflows/products/publishablePublish.d.ts +21 -0
  310. package/dist/cli/workflows/products/publishablePublish.js +131 -0
  311. package/dist/cli/workflows/publications/resolvePublicationId.d.ts +17 -0
  312. package/dist/cli/workflows/publications/resolvePublicationId.js +93 -0
  313. package/dist/cli.d.ts +1 -0
  314. package/dist/cli.js +238 -0
  315. package/dist/defaults.d.ts +2 -0
  316. package/dist/defaults.js +38 -0
  317. package/dist/generated/admin-2026-04/index.d.ts +25 -0
  318. package/dist/generated/admin-2026-04/index.js +70 -0
  319. package/dist/generated/admin-2026-04/runtime/batcher.d.ts +105 -0
  320. package/dist/generated/admin-2026-04/runtime/batcher.js +203 -0
  321. package/dist/generated/admin-2026-04/runtime/createClient.d.ts +17 -0
  322. package/dist/generated/admin-2026-04/runtime/createClient.js +59 -0
  323. package/dist/generated/admin-2026-04/runtime/error.d.ts +18 -0
  324. package/dist/generated/admin-2026-04/runtime/error.js +44 -0
  325. package/dist/generated/admin-2026-04/runtime/fetcher.d.ts +10 -0
  326. package/dist/generated/admin-2026-04/runtime/fetcher.js +104 -0
  327. package/dist/generated/admin-2026-04/runtime/generateGraphqlOperation.d.ts +30 -0
  328. package/dist/generated/admin-2026-04/runtime/generateGraphqlOperation.js +191 -0
  329. package/dist/generated/admin-2026-04/runtime/index.d.ts +11 -0
  330. package/dist/generated/admin-2026-04/runtime/index.js +46 -0
  331. package/dist/generated/admin-2026-04/runtime/linkTypeMap.d.ts +9 -0
  332. package/dist/generated/admin-2026-04/runtime/linkTypeMap.js +142 -0
  333. package/dist/generated/admin-2026-04/runtime/typeSelection.d.ts +28 -0
  334. package/dist/generated/admin-2026-04/runtime/typeSelection.js +17 -0
  335. package/dist/generated/admin-2026-04/runtime/types.d.ts +55 -0
  336. package/dist/generated/admin-2026-04/runtime/types.js +17 -0
  337. package/dist/generated/admin-2026-04/schema.d.ts +102240 -0
  338. package/dist/generated/admin-2026-04/schema.graphql +91596 -0
  339. package/dist/generated/admin-2026-04/schema.js +20322 -0
  340. package/dist/generated/admin-2026-04/types.d.ts +24224 -0
  341. package/dist/generated/admin-2026-04/types.js +62299 -0
  342. package/dist/generated/help/schema-help.d.ts +30 -0
  343. package/dist/generated/help/schema-help.js +61833 -0
  344. package/dist/graphqlValidator.d.ts +17 -0
  345. package/dist/graphqlValidator.js +84 -0
  346. package/dist/index.d.ts +1 -0
  347. package/dist/index.js +23 -0
  348. package/package.json +66 -0
  349. package/schema/2026-04.graphql +61256 -0
  350. package/schema/2026-04.introspection.json +1 -0
@@ -0,0 +1,2309 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var products_exports = {};
20
+ __export(products_exports, {
21
+ runProducts: () => runProducts
22
+ });
23
+ module.exports = __toCommonJS(products_exports);
24
+ var import_errors = require("../errors");
25
+ var import_gid = require("../gid");
26
+ var import_render = require("../help/render");
27
+ var import_input = require("../input");
28
+ var import_output = require("../output");
29
+ var import_computedFields = require("../output/computedFields");
30
+ var import_router = require("../router");
31
+ var import_select = require("../selection/select");
32
+ var import_userErrors = require("../userErrors");
33
+ var import_stagedUploads = require("../workflows/files/stagedUploads");
34
+ var import_waitForReady = require("../workflows/files/waitForReady");
35
+ var import_stdinFile = require("../workflows/files/stdinFile");
36
+ var import_metafieldsUpsert = require("../workflows/products/metafieldsUpsert");
37
+ var import_publishablePublish = require("../workflows/products/publishablePublish");
38
+ var import_resolvePublicationId = require("../workflows/publications/resolvePublicationId");
39
+ var import_shared = require("./_shared");
40
+ const requireProductIdForSubverb = (args) => {
41
+ if (args.id !== void 0) {
42
+ throw new import_errors.CliError("Unknown flag --id, did you mean --product-id?", 2);
43
+ }
44
+ return (0, import_shared.requireGidFlag)(args["product-id"], "--product-id", "Product");
45
+ };
46
+ const requireProductIdForRootVerb = (args) => {
47
+ const rawId = args.id;
48
+ const rawProductId = args["product-id"];
49
+ const hasId = typeof rawId === "string" && rawId.length > 0;
50
+ const hasProductId = typeof rawProductId === "string" && rawProductId.length > 0;
51
+ if (!hasId && !hasProductId) {
52
+ throw new import_errors.CliError("Missing --id", 2);
53
+ }
54
+ if (hasId && hasProductId) {
55
+ const a = (0, import_gid.coerceGid)(rawId, "Product");
56
+ const b = (0, import_gid.coerceGid)(rawProductId, "Product");
57
+ if (a !== b) throw new import_errors.CliError("Conflicting --id and --product-id", 2);
58
+ return a;
59
+ }
60
+ if (hasProductId) {
61
+ return (0, import_shared.requireGidFlag)(rawProductId, "--product-id", "Product");
62
+ }
63
+ return (0, import_shared.requireId)(rawId, "Product");
64
+ };
65
+ const productMediaSummarySelection = {
66
+ id: true,
67
+ mediaContentType: true,
68
+ status: true,
69
+ alt: true,
70
+ preview: { status: true, image: { url: true } }
71
+ };
72
+ const productMediaSelection = {
73
+ mediaErrors: { code: true, message: true },
74
+ mediaWarnings: { code: true, message: true },
75
+ ...productMediaSummarySelection
76
+ };
77
+ const productSummarySelection = {
78
+ id: true,
79
+ title: true,
80
+ handle: true,
81
+ status: true,
82
+ updatedAt: true
83
+ };
84
+ const productSummarySelectionForGet = {
85
+ ...productSummarySelection,
86
+ ...import_computedFields.computedPublicationsSelection
87
+ };
88
+ const productFullSelection = {
89
+ ...productSummarySelection,
90
+ createdAt: true,
91
+ tags: true
92
+ };
93
+ const productFullSelectionForGet = {
94
+ ...productFullSelection,
95
+ ...import_computedFields.computedPublicationsSelection
96
+ };
97
+ const productTagsSummarySelection = {
98
+ ...productSummarySelection,
99
+ tags: true
100
+ };
101
+ const productOptionSelection = {
102
+ id: true,
103
+ name: true,
104
+ position: true,
105
+ values: true
106
+ };
107
+ const productOptionListSummarySelection = {
108
+ id: true,
109
+ name: true,
110
+ position: true,
111
+ values: true
112
+ };
113
+ const productOptionListFullSelection = {
114
+ ...productOptionListSummarySelection,
115
+ optionValues: { id: true, name: true, hasVariants: true }
116
+ };
117
+ const getProductOptionListSelection = (view) => {
118
+ if (view === "ids") return { id: true };
119
+ if (view === "full") return productOptionListFullSelection;
120
+ if (view === "raw") return {};
121
+ return productOptionListSummarySelection;
122
+ };
123
+ const productOptionsSummarySelection = {
124
+ ...productSummarySelection,
125
+ options: {
126
+ __args: { first: 100 },
127
+ ...productOptionSelection
128
+ }
129
+ };
130
+ const productOptionsFullSelection = {
131
+ ...productFullSelection,
132
+ options: {
133
+ __args: { first: 100 },
134
+ ...productOptionSelection
135
+ }
136
+ };
137
+ const productVariantSummarySelection = {
138
+ id: true,
139
+ displayName: true,
140
+ sku: true,
141
+ price: true,
142
+ availableForSale: true
143
+ };
144
+ const productVariantFullSelection = {
145
+ ...productVariantSummarySelection,
146
+ barcode: true,
147
+ compareAtPrice: true,
148
+ inventoryQuantity: true,
149
+ product: { id: true, title: true },
150
+ inventoryItem: { id: true }
151
+ };
152
+ const getProductVariantSelection = (view) => {
153
+ if (view === "ids") return { id: true };
154
+ if (view === "full") return productVariantFullSelection;
155
+ if (view === "raw") return {};
156
+ return productVariantSummarySelection;
157
+ };
158
+ const getProductSelection = (view) => {
159
+ if (view === "ids") return { id: true };
160
+ if (view === "full") return productFullSelection;
161
+ if (view === "raw") return {};
162
+ return productSummarySelection;
163
+ };
164
+ const getProductSelectionForTags = (view) => {
165
+ if (view === "ids") return { id: true };
166
+ if (view === "full") return productFullSelection;
167
+ if (view === "raw") return {};
168
+ return productTagsSummarySelection;
169
+ };
170
+ const getProductSelectionForOptions = (view) => {
171
+ if (view === "ids") return { id: true };
172
+ if (view === "full") return productOptionsFullSelection;
173
+ if (view === "raw") return {};
174
+ return productOptionsSummarySelection;
175
+ };
176
+ const getProductSelectionForGet = (view) => {
177
+ if (view === "ids") return { id: true };
178
+ if (view === "full") return productFullSelectionForGet;
179
+ if (view === "raw") return {};
180
+ return productSummarySelectionForGet;
181
+ };
182
+ const getProductMediaSelection = (view) => {
183
+ if (view === "ids") return { id: true };
184
+ if (view === "summary") return productMediaSummarySelection;
185
+ return productMediaSelection;
186
+ };
187
+ const parseTags = (tags) => {
188
+ if (!tags) throw new import_errors.CliError("Missing --tags", 2);
189
+ const parts = tags.split(",").map((t) => t.trim()).filter(Boolean);
190
+ if (parts.length === 0) throw new import_errors.CliError("--tags must include at least one tag", 2);
191
+ return parts;
192
+ };
193
+ const normalizeMediaContentType = (value) => {
194
+ if (!value) return "IMAGE";
195
+ const v = value.toUpperCase();
196
+ if (v === "IMAGE" || v === "VIDEO" || v === "MODEL_3D" || v === "EXTERNAL_VIDEO") return v;
197
+ throw new import_errors.CliError("--media-content-type/--media-type must be IMAGE|VIDEO|MODEL_3D|EXTERNAL_VIDEO", 2);
198
+ };
199
+ const parsePositiveIntFlag = ({
200
+ value,
201
+ flag
202
+ }) => {
203
+ if (value === void 0) return void 0;
204
+ if (typeof value !== "string") throw new import_errors.CliError(`Invalid ${flag} value`, 2);
205
+ const trimmed = value.trim();
206
+ if (!trimmed) throw new import_errors.CliError(`Invalid ${flag} value`, 2);
207
+ const n = Number(trimmed);
208
+ if (!Number.isFinite(n) || !Number.isInteger(n) || n <= 0) {
209
+ throw new import_errors.CliError(`${flag} must be a positive integer`, 2);
210
+ }
211
+ return n;
212
+ };
213
+ const getTopProductMediaIds = async ({
214
+ ctx,
215
+ productId,
216
+ first = 250
217
+ }) => {
218
+ const result = await (0, import_router.runQuery)(ctx, {
219
+ product: {
220
+ __args: { id: productId },
221
+ media: {
222
+ __args: { first, reverse: true, sortKey: "POSITION" },
223
+ nodes: { id: true }
224
+ }
225
+ }
226
+ });
227
+ if (result === void 0) return [];
228
+ const nodes = result.product?.media?.nodes ?? [];
229
+ return nodes.map((n) => typeof n?.id === "string" ? n.id : void 0).filter((id) => typeof id === "string" && id.trim() !== "");
230
+ };
231
+ const normalizeMediaId = (value) => {
232
+ const raw = value.trim();
233
+ if (!raw) throw new import_errors.CliError("Media ID cannot be empty", 2);
234
+ if (raw.startsWith("gid://")) return raw;
235
+ throw new import_errors.CliError(
236
+ `Numeric media ID "${raw}" is ambiguous. Use the full GID from "shop products media list" (e.g. gid://shopify/MediaImage/${raw})`,
237
+ 2
238
+ );
239
+ };
240
+ const mediaTypeToStagedResource = (mediaType) => {
241
+ if (mediaType === "IMAGE") return "IMAGE";
242
+ if (mediaType === "VIDEO") return "VIDEO";
243
+ if (mediaType === "MODEL_3D") return "MODEL_3D";
244
+ throw new import_errors.CliError("--media-type EXTERNAL_VIDEO cannot be used with --file uploads", 2);
245
+ };
246
+ const stagedResourceToMediaType = (resource) => {
247
+ if (resource === "IMAGE") return "IMAGE";
248
+ if (resource === "VIDEO") return "VIDEO";
249
+ if (resource === "MODEL_3D") return "MODEL_3D";
250
+ throw new import_errors.CliError("Only IMAGE|VIDEO|MODEL_3D can be uploaded as product media", 2);
251
+ };
252
+ const parseVariantOptionValues = (value) => {
253
+ if (value === void 0 || value === null) return [];
254
+ const raw = Array.isArray(value) ? value : [value];
255
+ const optionValues = [];
256
+ for (const entry of raw) {
257
+ if (typeof entry !== "string") throw new import_errors.CliError("--variant-option must be a string", 2);
258
+ const trimmed = entry.trim();
259
+ if (!trimmed) continue;
260
+ const eq = trimmed.indexOf("=");
261
+ if (eq <= 0 || eq === trimmed.length - 1) {
262
+ throw new import_errors.CliError(`--variant-option must be in the form OptionName=Value. Got: ${entry}`, 2);
263
+ }
264
+ const optionName = trimmed.slice(0, eq).trim();
265
+ const name = trimmed.slice(eq + 1).trim();
266
+ if (!optionName || !name) {
267
+ throw new import_errors.CliError(`--variant-option must be in the form OptionName=Value. Got: ${entry}`, 2);
268
+ }
269
+ optionValues.push({ optionName, name });
270
+ }
271
+ return optionValues;
272
+ };
273
+ const parseRepeatableStrings = (value, flag, { allowEmpty = false } = {}) => {
274
+ if (value === void 0 || value === null) {
275
+ if (allowEmpty) return [];
276
+ throw new import_errors.CliError(`Missing ${flag}`, 2);
277
+ }
278
+ const raw = Array.isArray(value) ? value : [value];
279
+ const out = [];
280
+ for (const entry of raw) {
281
+ if (typeof entry !== "string") throw new import_errors.CliError(`${flag} must be a string (repeatable)`, 2);
282
+ const trimmed = entry.trim();
283
+ if (!trimmed) throw new import_errors.CliError(`${flag} cannot be empty`, 2);
284
+ out.push(trimmed);
285
+ }
286
+ if (out.length === 0) {
287
+ if (allowEmpty) return [];
288
+ throw new import_errors.CliError(`Missing ${flag}`, 2);
289
+ }
290
+ return out;
291
+ };
292
+ const parseOptionSpec = (value, flag) => {
293
+ const trimmed = value.trim();
294
+ const eq = trimmed.indexOf("=");
295
+ if (eq <= 0 || eq === trimmed.length - 1) {
296
+ throw new import_errors.CliError(`${flag} must be in the form Name=Value1,Value2,... Got: ${value}`, 2);
297
+ }
298
+ const name = trimmed.slice(0, eq).trim();
299
+ const valuesRaw = trimmed.slice(eq + 1).trim();
300
+ if (!name || !valuesRaw) {
301
+ throw new import_errors.CliError(`${flag} must be in the form Name=Value1,Value2,... Got: ${value}`, 2);
302
+ }
303
+ const valueNames = valuesRaw.split(",").map((v) => v.trim()).filter(Boolean);
304
+ if (valueNames.length === 0) {
305
+ throw new import_errors.CliError(`${flag} must include at least one value. Got: ${value}`, 2);
306
+ }
307
+ return {
308
+ name,
309
+ values: valueNames.map((v) => ({ name: v }))
310
+ };
311
+ };
312
+ const parseFromTo = (value, flag) => {
313
+ const trimmed = value.trim();
314
+ const eq = trimmed.indexOf("=");
315
+ if (eq <= 0 || eq === trimmed.length - 1) {
316
+ throw new import_errors.CliError(`${flag} must be in the form From=To. Got: ${value}`, 2);
317
+ }
318
+ const from = trimmed.slice(0, eq).trim();
319
+ const to = trimmed.slice(eq + 1).trim();
320
+ if (!from || !to) {
321
+ throw new import_errors.CliError(`${flag} must be in the form From=To. Got: ${value}`, 2);
322
+ }
323
+ return { from, to };
324
+ };
325
+ const looksLikeGidOrNumericId = (value) => /^gid:\/\//i.test(value) || /^\d+$/.test(value);
326
+ const normalizeProductOptionCreateVariantStrategy = (value) => {
327
+ if (value === void 0 || value === null || value === "") return void 0;
328
+ if (typeof value !== "string") throw new import_errors.CliError("--variant-strategy must be a string", 2);
329
+ const v = value.trim().toUpperCase();
330
+ if (v === "LEAVE_AS_IS" || v === "CREATE") return v;
331
+ throw new import_errors.CliError("--variant-strategy must be LEAVE_AS_IS|CREATE", 2);
332
+ };
333
+ const normalizeProductOptionUpdateVariantStrategy = (value) => {
334
+ if (value === void 0 || value === null || value === "") return void 0;
335
+ if (typeof value !== "string") throw new import_errors.CliError("--variant-strategy must be a string", 2);
336
+ const v = value.trim().toUpperCase();
337
+ if (v === "LEAVE_AS_IS" || v === "MANAGE") return v;
338
+ throw new import_errors.CliError("--variant-strategy must be LEAVE_AS_IS|MANAGE", 2);
339
+ };
340
+ const normalizeProductOptionDeleteStrategy = (value) => {
341
+ if (value === void 0 || value === null || value === "") return void 0;
342
+ if (typeof value !== "string") throw new import_errors.CliError("--strategy must be a string", 2);
343
+ const v = value.trim().toUpperCase();
344
+ if (v === "DEFAULT" || v === "NON_DESTRUCTIVE" || v === "POSITION") return v;
345
+ throw new import_errors.CliError("--strategy must be DEFAULT|NON_DESTRUCTIVE|POSITION", 2);
346
+ };
347
+ const productOptionResolveSelection = {
348
+ id: true,
349
+ name: true,
350
+ position: true,
351
+ values: true,
352
+ optionValues: { id: true, name: true }
353
+ };
354
+ const fetchProductOptionsForResolution = async ({ ctx, productId }) => {
355
+ const result = await (0, import_router.runQuery)(ctx, {
356
+ product: { __args: { id: productId }, options: productOptionResolveSelection }
357
+ });
358
+ if (result === void 0) return [];
359
+ return result.product?.options ?? [];
360
+ };
361
+ const resolveSingleOptionByName = (options, name) => {
362
+ const matches = options.filter((o) => typeof o?.name === "string" && o.name === name);
363
+ if (matches.length === 0) return void 0;
364
+ if (matches.length > 1) {
365
+ throw new import_errors.CliError(`Multiple product options named "${name}" exist. Use --option-id instead.`, 2);
366
+ }
367
+ return matches[0];
368
+ };
369
+ const parseInventoryPolicy = (value) => {
370
+ if (value === void 0 || value === null || value === "") return void 0;
371
+ if (typeof value !== "string") throw new import_errors.CliError("--inventory-policy must be a string", 2);
372
+ const normalized = value.trim().toUpperCase();
373
+ if (normalized === "DENY" || normalized === "CONTINUE") return normalized;
374
+ throw new import_errors.CliError(`--inventory-policy must be DENY|CONTINUE. Got: ${value}`, 2);
375
+ };
376
+ const runProducts = async ({
377
+ ctx,
378
+ verb,
379
+ argv
380
+ }) => {
381
+ const groupHelpVerbs = /* @__PURE__ */ new Set(["variants", "options", "media"]);
382
+ if (groupHelpVerbs.has(verb)) {
383
+ const groupHelp = (0, import_render.renderVerbGroupHelp)("products", verb);
384
+ if (groupHelp) console.log(groupHelp);
385
+ if (argv.length === 0 || argv.includes("--help") || argv.includes("-h")) return;
386
+ throw new import_errors.CliError(`
387
+ Missing <verb> for "products ${verb}"`, 2);
388
+ }
389
+ if (argv.includes("--help") || argv.includes("-h")) {
390
+ console.log(
391
+ [
392
+ "Usage:",
393
+ " shop products <verb> [flags]",
394
+ "",
395
+ "Verbs:",
396
+ " create|get|list|count|update|delete|duplicate|set-status|archive|unarchive",
397
+ " by-handle|by-identifier|operation|duplicate-job",
398
+ " tags|types|vendors",
399
+ " change-status|set",
400
+ " join-selling-plan-groups|leave-selling-plan-groups",
401
+ " options list|options create|options update|options delete|options reorder",
402
+ " variants list|variants create|variants update|variants delete|variants reorder",
403
+ " combined-listing-update",
404
+ " add-tags|remove-tags|set-price",
405
+ " publish|unpublish|publish-all",
406
+ " bundle-create|bundle-update",
407
+ " metafields upsert",
408
+ " media add|media upload|media list|media remove|media reorder|media update",
409
+ "",
410
+ "Common output flags:",
411
+ " --view summary|ids|full|raw",
412
+ " --select <path> (repeatable; dot paths; adds to base view selection)",
413
+ " --selection <graphql> (selection override; can be @file.gql)"
414
+ ].join("\n")
415
+ );
416
+ return;
417
+ }
418
+ if (verb === "variants list") {
419
+ const args = (0, import_router.parseStandardArgs)({
420
+ argv,
421
+ extraOptions: { "product-id": { type: "string" } }
422
+ });
423
+ if (args.query) {
424
+ throw new import_errors.CliError(
425
+ "--query is not supported for `shop products variants list` (product-scoped variants). Use `shop product-variants list --query ...` for global variant search.",
426
+ 2
427
+ );
428
+ }
429
+ const productId = requireProductIdForSubverb(args);
430
+ const first = (0, import_shared.parseFirst)(args.first);
431
+ const after = args.after;
432
+ const reverse = args.reverse;
433
+ const sortKey = args.sort;
434
+ const nodeSelection = (0, import_select.resolveSelection)({
435
+ typeName: "ProductVariant",
436
+ view: ctx.view,
437
+ baseSelection: getProductVariantSelection(ctx.view),
438
+ select: args.select,
439
+ selection: args.selection,
440
+ include: args.include,
441
+ ensureId: ctx.quiet,
442
+ defaultConnectionFirst: ctx.view === "all" ? 50 : 10
443
+ });
444
+ const result = await (0, import_router.runQuery)(ctx, {
445
+ product: {
446
+ __args: { id: productId },
447
+ variants: {
448
+ __args: { first, after, reverse, sortKey },
449
+ pageInfo: { hasNextPage: true, endCursor: true },
450
+ nodes: nodeSelection
451
+ }
452
+ }
453
+ });
454
+ if (result === void 0) return;
455
+ const connection = result.product?.variants;
456
+ if (!connection) throw new import_errors.CliError("Product not found", 2);
457
+ (0, import_output.printConnection)({
458
+ connection,
459
+ format: ctx.format,
460
+ quiet: ctx.quiet,
461
+ nextPageArgs: {
462
+ base: "shop products variants list",
463
+ first,
464
+ sort: typeof sortKey === "string" ? sortKey : void 0,
465
+ reverse: reverse === true,
466
+ extraFlags: [{ flag: "--product-id", value: productId }]
467
+ }
468
+ });
469
+ return;
470
+ }
471
+ if (verb === "variants create") {
472
+ const args = (0, import_router.parseStandardArgs)({
473
+ argv,
474
+ extraOptions: {
475
+ "product-id": { type: "string" },
476
+ "variant-option": { type: "string", multiple: true },
477
+ sku: { type: "string" },
478
+ barcode: { type: "string" },
479
+ price: { type: "string" },
480
+ "compare-at-price": { type: "string" },
481
+ "inventory-policy": { type: "string" },
482
+ strategy: { type: "string" }
483
+ }
484
+ });
485
+ const productId = requireProductIdForSubverb(args);
486
+ const optionValues = parseVariantOptionValues(args["variant-option"]);
487
+ if (optionValues.length === 0) {
488
+ throw new import_errors.CliError("Missing --variant-option OptionName=Value (repeatable)", 2);
489
+ }
490
+ const sku = args.sku;
491
+ const barcode = args.barcode;
492
+ const price = args.price;
493
+ const compareAtPrice = args["compare-at-price"];
494
+ const inventoryPolicy = parseInventoryPolicy(args["inventory-policy"]);
495
+ const strategy = args.strategy;
496
+ if (strategy && !["DEFAULT", "PRESERVE_STANDALONE_VARIANT", "REMOVE_STANDALONE_VARIANT"].includes(
497
+ strategy.trim().toUpperCase()
498
+ )) {
499
+ throw new import_errors.CliError(
500
+ `--strategy must be DEFAULT|PRESERVE_STANDALONE_VARIANT|REMOVE_STANDALONE_VARIANT. Got: ${strategy}`,
501
+ 2
502
+ );
503
+ }
504
+ const normalizedStrategy = strategy ? strategy.trim().toUpperCase() : void 0;
505
+ const variantSelection = (0, import_select.resolveSelection)({
506
+ typeName: "ProductVariant",
507
+ view: ctx.view,
508
+ baseSelection: getProductVariantSelection(ctx.view),
509
+ select: args.select,
510
+ selection: args.selection,
511
+ include: args.include,
512
+ ensureId: ctx.quiet,
513
+ defaultConnectionFirst: ctx.view === "all" ? 50 : 10
514
+ });
515
+ const variantInput = {
516
+ optionValues,
517
+ ...barcode ? { barcode } : {},
518
+ ...price ? { price } : {},
519
+ ...compareAtPrice ? { compareAtPrice } : {},
520
+ ...inventoryPolicy ? { inventoryPolicy } : {},
521
+ ...sku ? { inventoryItem: { sku } } : {}
522
+ };
523
+ const result = await (0, import_router.runMutation)(ctx, {
524
+ productVariantsBulkCreate: {
525
+ __args: {
526
+ productId,
527
+ variants: [variantInput],
528
+ ...normalizedStrategy ? { strategy: normalizedStrategy } : {}
529
+ },
530
+ userErrors: { field: true, message: true },
531
+ productVariants: variantSelection
532
+ }
533
+ });
534
+ if (result === void 0) return;
535
+ (0, import_userErrors.maybeFailOnUserErrors)({
536
+ payload: result.productVariantsBulkCreate,
537
+ failOnUserErrors: ctx.failOnUserErrors
538
+ });
539
+ const created = result.productVariantsBulkCreate?.productVariants?.[0];
540
+ (0, import_output.printNode)({ node: created, format: ctx.format, quiet: ctx.quiet });
541
+ return;
542
+ }
543
+ if (verb === "variants update") {
544
+ const args = (0, import_router.parseStandardArgs)({
545
+ argv,
546
+ extraOptions: {
547
+ "product-id": { type: "string" },
548
+ "variant-id": { type: "string" },
549
+ "variant-option": { type: "string", multiple: true },
550
+ sku: { type: "string" },
551
+ barcode: { type: "string" },
552
+ price: { type: "string" },
553
+ "compare-at-price": { type: "string" },
554
+ "inventory-policy": { type: "string" },
555
+ "allow-partial-updates": { type: "boolean" }
556
+ }
557
+ });
558
+ if (args.id !== void 0) {
559
+ if (args["product-id"] !== void 0) {
560
+ throw new import_errors.CliError("Unknown flag --id, did you mean --variant-id?", 2);
561
+ }
562
+ ;
563
+ args["product-id"] = args.id;
564
+ delete args.id;
565
+ }
566
+ const productId = requireProductIdForSubverb(args);
567
+ const variantId = (0, import_shared.requireId)(args["variant-id"], "ProductVariant", "--variant-id");
568
+ const optionValues = parseVariantOptionValues(args["variant-option"]);
569
+ const sku = args.sku;
570
+ const barcode = args.barcode;
571
+ const price = args.price;
572
+ const compareAtPrice = args["compare-at-price"];
573
+ const inventoryPolicy = parseInventoryPolicy(args["inventory-policy"]);
574
+ const allowPartialUpdates = args["allow-partial-updates"] === true;
575
+ const variantSelection = (0, import_select.resolveSelection)({
576
+ typeName: "ProductVariant",
577
+ view: ctx.view,
578
+ baseSelection: getProductVariantSelection(ctx.view),
579
+ select: args.select,
580
+ selection: args.selection,
581
+ include: args.include,
582
+ ensureId: ctx.quiet,
583
+ defaultConnectionFirst: ctx.view === "all" ? 50 : 10
584
+ });
585
+ const variantInput = {
586
+ id: variantId,
587
+ ...optionValues.length ? { optionValues } : {},
588
+ ...barcode ? { barcode } : {},
589
+ ...price ? { price } : {},
590
+ ...compareAtPrice ? { compareAtPrice } : {},
591
+ ...inventoryPolicy ? { inventoryPolicy } : {},
592
+ ...sku ? { inventoryItem: { sku } } : {}
593
+ };
594
+ const result = await (0, import_router.runMutation)(ctx, {
595
+ productVariantsBulkUpdate: {
596
+ __args: {
597
+ productId,
598
+ allowPartialUpdates,
599
+ variants: [variantInput]
600
+ },
601
+ userErrors: { field: true, message: true },
602
+ productVariants: variantSelection
603
+ }
604
+ });
605
+ if (result === void 0) return;
606
+ (0, import_userErrors.maybeFailOnUserErrors)({
607
+ payload: result.productVariantsBulkUpdate,
608
+ failOnUserErrors: ctx.failOnUserErrors
609
+ });
610
+ const updated = result.productVariantsBulkUpdate?.productVariants?.[0];
611
+ (0, import_output.printNode)({ node: updated, format: ctx.format, quiet: ctx.quiet });
612
+ return;
613
+ }
614
+ if (verb === "variants delete") {
615
+ const args = (0, import_router.parseStandardArgs)({
616
+ argv,
617
+ extraOptions: {
618
+ "product-id": { type: "string" },
619
+ "variant-id": { type: "string" }
620
+ }
621
+ });
622
+ const productId = requireProductIdForSubverb(args);
623
+ const variantId = (0, import_shared.requireId)(args["variant-id"], "ProductVariant", "--variant-id");
624
+ const result = await (0, import_router.runMutation)(ctx, {
625
+ productVariantsBulkDelete: {
626
+ __args: { productId, variantsIds: [variantId] },
627
+ product: { id: true },
628
+ userErrors: { field: true, message: true }
629
+ }
630
+ });
631
+ if (result === void 0) return;
632
+ (0, import_userErrors.maybeFailOnUserErrors)({
633
+ payload: result.productVariantsBulkDelete,
634
+ failOnUserErrors: ctx.failOnUserErrors
635
+ });
636
+ const verify = await (0, import_router.runQuery)(ctx, {
637
+ nodes: {
638
+ __args: { ids: [variantId] },
639
+ id: true
640
+ }
641
+ });
642
+ if (verify === void 0) return;
643
+ const stillThere = verify.nodes?.[0] !== null && verify.nodes?.[0] !== void 0;
644
+ const deletedVariantId = stillThere ? void 0 : variantId;
645
+ if (ctx.quiet) return (0, import_output.printIds)([deletedVariantId]);
646
+ (0, import_output.printJson)({ productId, deletedVariantId }, ctx.format !== "raw");
647
+ return;
648
+ }
649
+ if (verb === "variants reorder") {
650
+ const args = (0, import_router.parseStandardArgs)({
651
+ argv,
652
+ extraOptions: {
653
+ "product-id": { type: "string" },
654
+ "variant-id": { type: "string" },
655
+ position: { type: "string" }
656
+ }
657
+ });
658
+ const productId = requireProductIdForSubverb(args);
659
+ const variantId = (0, import_shared.requireId)(args["variant-id"], "ProductVariant", "--variant-id");
660
+ const position = (0, import_shared.parseIntFlag)("--position", args.position);
661
+ if (position <= 0) throw new import_errors.CliError("--position must be a positive integer (1-based)", 2);
662
+ const result = await (0, import_router.runMutation)(ctx, {
663
+ productVariantsBulkReorder: {
664
+ __args: { productId, positions: [{ id: variantId, position }] },
665
+ product: { id: true },
666
+ userErrors: { field: true, message: true }
667
+ }
668
+ });
669
+ if (result === void 0) return;
670
+ (0, import_userErrors.maybeFailOnUserErrors)({
671
+ payload: result.productVariantsBulkReorder,
672
+ failOnUserErrors: ctx.failOnUserErrors
673
+ });
674
+ if (ctx.quiet) return (0, import_output.printIds)([variantId]);
675
+ (0, import_output.printJson)({ productId, variantId, position }, ctx.format !== "raw");
676
+ return;
677
+ }
678
+ if (verb === "by-handle") {
679
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: { handle: { type: "string" } } });
680
+ const handle = args.handle;
681
+ if (!handle) throw new import_errors.CliError("Missing --handle", 2);
682
+ const selectValues = Array.isArray(args.select) ? args.select : args.select ? [args.select] : [];
683
+ const selectionOverride = typeof args.selection === "string" && args.selection.length > 0;
684
+ const select = !selectionOverride && ctx.view !== "raw" && ctx.view !== "ids" ? Array.from(/* @__PURE__ */ new Set([...selectValues, "resourcePublicationsV2.nodes.publication.name"])) : args.select;
685
+ const includeValues = Array.isArray(args.include) ? args.include : args.include ? [args.include] : [];
686
+ const include = ctx.view === "all" ? Array.from(/* @__PURE__ */ new Set([...includeValues, "resourcePublicationsV2"])) : args.include;
687
+ const selection = (0, import_select.resolveSelection)({
688
+ resource: "products",
689
+ view: ctx.view,
690
+ baseSelection: getProductSelectionForGet(ctx.view),
691
+ select,
692
+ selection: args.selection,
693
+ include,
694
+ ensureId: ctx.quiet,
695
+ defaultConnectionFirst: ctx.view === "all" ? 50 : 10
696
+ });
697
+ const result = await (0, import_router.runQuery)(ctx, { productByHandle: { __args: { handle }, ...selection } });
698
+ if (result === void 0) return;
699
+ const wantsResourcePublicationsV2 = Array.isArray(args.select) && args.select.some((p) => typeof p === "string" && p.startsWith("resourcePublicationsV2"));
700
+ const wantsResourcePublicationsV2ViaSelection = typeof args.selection === "string" && args.selection.includes("resourcePublicationsV2");
701
+ const stripResourcePublicationsV2 = !(wantsResourcePublicationsV2 || wantsResourcePublicationsV2ViaSelection);
702
+ const withComputed = (0, import_computedFields.applyComputedFieldsToNode)(result.productByHandle, {
703
+ view: ctx.view,
704
+ stripResourcePublicationsV2
705
+ });
706
+ (0, import_output.printNode)({ node: withComputed, format: ctx.format, quiet: ctx.quiet });
707
+ return;
708
+ }
709
+ if (verb === "by-identifier") {
710
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: { identifier: { type: "string" } } });
711
+ const identifier = (0, import_shared.parseJsonArg)(args.identifier, "--identifier");
712
+ const selectValues = Array.isArray(args.select) ? args.select : args.select ? [args.select] : [];
713
+ const selectionOverride = typeof args.selection === "string" && args.selection.length > 0;
714
+ const select = !selectionOverride && ctx.view !== "raw" && ctx.view !== "ids" ? Array.from(/* @__PURE__ */ new Set([...selectValues, "resourcePublicationsV2.nodes.publication.name"])) : args.select;
715
+ const includeValues = Array.isArray(args.include) ? args.include : args.include ? [args.include] : [];
716
+ const include = ctx.view === "all" ? Array.from(/* @__PURE__ */ new Set([...includeValues, "resourcePublicationsV2"])) : args.include;
717
+ const selection = (0, import_select.resolveSelection)({
718
+ resource: "products",
719
+ view: ctx.view,
720
+ baseSelection: getProductSelectionForGet(ctx.view),
721
+ select,
722
+ selection: args.selection,
723
+ include,
724
+ ensureId: ctx.quiet,
725
+ defaultConnectionFirst: ctx.view === "all" ? 50 : 10
726
+ });
727
+ const result = await (0, import_router.runQuery)(ctx, { productByIdentifier: { __args: { identifier }, ...selection } });
728
+ if (result === void 0) return;
729
+ const wantsResourcePublicationsV2 = Array.isArray(args.select) && args.select.some((p) => typeof p === "string" && p.startsWith("resourcePublicationsV2"));
730
+ const wantsResourcePublicationsV2ViaSelection = typeof args.selection === "string" && args.selection.includes("resourcePublicationsV2");
731
+ const stripResourcePublicationsV2 = !(wantsResourcePublicationsV2 || wantsResourcePublicationsV2ViaSelection);
732
+ const withComputed = (0, import_computedFields.applyComputedFieldsToNode)(result.productByIdentifier, {
733
+ view: ctx.view,
734
+ stripResourcePublicationsV2
735
+ });
736
+ (0, import_output.printNode)({ node: withComputed, format: ctx.format, quiet: ctx.quiet });
737
+ return;
738
+ }
739
+ if (verb === "duplicate-job") {
740
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: {} });
741
+ const id = args.id;
742
+ if (typeof id !== "string" || !id) throw new import_errors.CliError("Missing --id", 2);
743
+ const selection = (0, import_select.resolveSelection)({
744
+ typeName: "ProductDuplicateJob",
745
+ view: ctx.view,
746
+ baseSelection: { id: true, done: true },
747
+ select: args.select,
748
+ selection: args.selection,
749
+ include: args.include,
750
+ ensureId: ctx.quiet
751
+ });
752
+ const result = await (0, import_router.runQuery)(ctx, { productDuplicateJob: { __args: { id }, ...selection } });
753
+ if (result === void 0) return;
754
+ (0, import_output.printNode)({ node: result.productDuplicateJob, format: ctx.format, quiet: ctx.quiet });
755
+ return;
756
+ }
757
+ if (verb === "operation") {
758
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: {} });
759
+ const id = args.id;
760
+ if (typeof id !== "string" || !id) throw new import_errors.CliError("Missing --id", 2);
761
+ const getProductOperationSelection = (view) => {
762
+ if (view === "raw") return {};
763
+ if (view === "ids") {
764
+ return {
765
+ __typename: true,
766
+ on_ProductBundleOperation: { id: true },
767
+ on_ProductDeleteOperation: { id: true },
768
+ on_ProductDuplicateOperation: { id: true, newProduct: { id: true }, product: { id: true } },
769
+ on_ProductSetOperation: { id: true, product: { id: true } }
770
+ };
771
+ }
772
+ return {
773
+ __typename: true,
774
+ status: true,
775
+ product: { id: true, title: true, handle: true, status: true },
776
+ on_ProductBundleOperation: {
777
+ id: true,
778
+ status: true,
779
+ product: { id: true, title: true },
780
+ userErrors: { field: true, message: true }
781
+ },
782
+ on_ProductDeleteOperation: {
783
+ id: true,
784
+ status: true,
785
+ product: { id: true, title: true },
786
+ userErrors: { field: true, message: true }
787
+ },
788
+ on_ProductDuplicateOperation: {
789
+ id: true,
790
+ status: true,
791
+ product: { id: true, title: true },
792
+ newProduct: { id: true, title: true },
793
+ userErrors: { field: true, message: true }
794
+ },
795
+ on_ProductSetOperation: {
796
+ id: true,
797
+ status: true,
798
+ product: { id: true, title: true },
799
+ userErrors: { code: true, field: true, message: true }
800
+ }
801
+ };
802
+ };
803
+ const selection = (0, import_select.resolveSelection)({
804
+ typeName: "ProductOperation",
805
+ view: ctx.view,
806
+ baseSelection: getProductOperationSelection(ctx.view),
807
+ select: args.select,
808
+ selection: args.selection,
809
+ include: args.include,
810
+ ensureId: ctx.quiet
811
+ });
812
+ const result = await (0, import_router.runQuery)(ctx, { productOperation: { __args: { id }, ...selection } });
813
+ if (result === void 0) return;
814
+ (0, import_output.printNode)({ node: result.productOperation, format: ctx.format, quiet: ctx.quiet });
815
+ return;
816
+ }
817
+ if (verb === "tags" || verb === "types" || verb === "vendors") {
818
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: {} });
819
+ const first = (0, import_shared.parseFirst)(args.first);
820
+ const after = args.after;
821
+ const reverse = args.reverse;
822
+ const field = verb === "tags" ? "productTags" : verb === "types" ? "productTypes" : "productVendors";
823
+ const result = await (0, import_router.runQuery)(ctx, {
824
+ [field]: {
825
+ __args: { first, after, reverse },
826
+ pageInfo: { hasNextPage: true, endCursor: true },
827
+ nodes: true
828
+ }
829
+ });
830
+ if (result === void 0) return;
831
+ const connection = result[field];
832
+ if (ctx.quiet) {
833
+ for (const value of connection?.nodes ?? []) {
834
+ if (typeof value === "string" && value) process.stdout.write(`${value}
835
+ `);
836
+ }
837
+ return;
838
+ }
839
+ (0, import_output.printConnection)({
840
+ connection,
841
+ format: ctx.format,
842
+ quiet: false,
843
+ nextPageArgs: { base: `shop products ${verb}`, first, reverse: reverse === true }
844
+ });
845
+ return;
846
+ }
847
+ if (verb === "change-status") {
848
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: { "product-id": { type: "string" } } });
849
+ const productId = requireProductIdForRootVerb(args);
850
+ const status = args.status;
851
+ if (!status) throw new import_errors.CliError("Missing --status (ACTIVE|DRAFT|ARCHIVED)", 2);
852
+ const selection = (0, import_select.resolveSelection)({
853
+ resource: "products",
854
+ view: ctx.view,
855
+ baseSelection: getProductSelection(ctx.view),
856
+ select: args.select,
857
+ selection: args.selection,
858
+ include: args.include,
859
+ ensureId: ctx.quiet
860
+ });
861
+ const result = await (0, import_router.runMutation)(ctx, {
862
+ productChangeStatus: {
863
+ __args: { productId, status },
864
+ product: selection,
865
+ userErrors: { field: true, message: true }
866
+ }
867
+ });
868
+ if (result === void 0) return;
869
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.productChangeStatus, failOnUserErrors: ctx.failOnUserErrors });
870
+ (0, import_output.printNode)({ node: result.productChangeStatus?.product, format: ctx.format, quiet: ctx.quiet });
871
+ return;
872
+ }
873
+ if (verb === "set") {
874
+ const args = (0, import_router.parseStandardArgs)({
875
+ argv,
876
+ extraOptions: {
877
+ identifier: { type: "string" },
878
+ synchronous: { type: "string" }
879
+ }
880
+ });
881
+ const built = (0, import_input.buildInput)({
882
+ inputArg: args.input,
883
+ setArgs: args.set,
884
+ setJsonArgs: args["set-json"]
885
+ });
886
+ if (!built.used) throw new import_errors.CliError("Missing --input or --set/--set-json", 2);
887
+ const identifier = args.identifier ? (0, import_shared.parseJsonArg)(args.identifier, "--identifier") : void 0;
888
+ const synchronousRaw = args.synchronous;
889
+ const synchronous = (() => {
890
+ if (synchronousRaw === void 0 || synchronousRaw === null || synchronousRaw === "") return void 0;
891
+ const v = String(synchronousRaw).toLowerCase();
892
+ if (v === "true" || v === "1") return true;
893
+ if (v === "false" || v === "0") return false;
894
+ throw new import_errors.CliError("--synchronous must be true|false", 2);
895
+ })();
896
+ const result = await (0, import_router.runMutation)(ctx, {
897
+ productSet: {
898
+ __args: {
899
+ input: built.input,
900
+ ...identifier !== void 0 ? { identifier } : {},
901
+ ...synchronous !== void 0 ? { synchronous } : {}
902
+ },
903
+ product: productSummarySelection,
904
+ productSetOperation: {
905
+ id: true,
906
+ status: true,
907
+ product: productSummarySelection,
908
+ userErrors: { code: true, field: true, message: true }
909
+ },
910
+ userErrors: { code: true, field: true, message: true }
911
+ }
912
+ });
913
+ if (result === void 0) return;
914
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.productSet, failOnUserErrors: ctx.failOnUserErrors });
915
+ if (ctx.quiet) {
916
+ const pid = result.productSet?.product?.id;
917
+ const opId = result.productSet?.productSetOperation?.id;
918
+ return console.log(pid ?? opId ?? "");
919
+ }
920
+ (0, import_output.printJson)(result.productSet, ctx.format !== "raw");
921
+ return;
922
+ }
923
+ if (verb === "join-selling-plan-groups" || verb === "leave-selling-plan-groups") {
924
+ const args = (0, import_router.parseStandardArgs)({
925
+ argv,
926
+ extraOptions: { "product-id": { type: "string" }, "group-ids": { type: "string", multiple: true } }
927
+ });
928
+ const id = requireProductIdForRootVerb(args);
929
+ const sellingPlanGroupIds = (0, import_shared.parseIds)(args["group-ids"], "SellingPlanGroup");
930
+ const selection = (0, import_select.resolveSelection)({
931
+ resource: "products",
932
+ view: ctx.view,
933
+ baseSelection: getProductSelection(ctx.view),
934
+ select: args.select,
935
+ selection: args.selection,
936
+ include: args.include,
937
+ ensureId: ctx.quiet
938
+ });
939
+ const mutation = verb === "join-selling-plan-groups" ? "productJoinSellingPlanGroups" : "productLeaveSellingPlanGroups";
940
+ const result = await (0, import_router.runMutation)(ctx, {
941
+ [mutation]: {
942
+ __args: { id, sellingPlanGroupIds },
943
+ product: selection,
944
+ userErrors: { field: true, message: true }
945
+ }
946
+ });
947
+ if (result === void 0) return;
948
+ const payload = result[mutation];
949
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload, failOnUserErrors: ctx.failOnUserErrors });
950
+ (0, import_output.printNode)({ node: payload?.product, format: ctx.format, quiet: ctx.quiet });
951
+ return;
952
+ }
953
+ if (verb === "options list") {
954
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: { "product-id": { type: "string" } } });
955
+ const productId = requireProductIdForSubverb(args);
956
+ const selection = (0, import_select.resolveSelection)({
957
+ typeName: "ProductOption",
958
+ view: ctx.view,
959
+ baseSelection: getProductOptionListSelection(ctx.view),
960
+ select: args.select,
961
+ selection: args.selection,
962
+ include: args.include,
963
+ ensureId: ctx.quiet
964
+ });
965
+ const result = await (0, import_router.runQuery)(ctx, {
966
+ product: {
967
+ __args: { id: productId },
968
+ options: selection
969
+ }
970
+ });
971
+ if (result === void 0) return;
972
+ const options = result.product?.options ?? [];
973
+ (0, import_output.printConnection)({
974
+ connection: { nodes: options, pageInfo: void 0 },
975
+ format: ctx.format,
976
+ quiet: ctx.quiet
977
+ });
978
+ return;
979
+ }
980
+ if (verb === "options create") {
981
+ const args = (0, import_router.parseStandardArgs)({
982
+ argv,
983
+ extraOptions: {
984
+ "product-id": { type: "string" },
985
+ option: { type: "string", multiple: true },
986
+ "options-json": { type: "string" },
987
+ "variant-strategy": { type: "string" }
988
+ }
989
+ });
990
+ const productId = requireProductIdForSubverb(args);
991
+ const optionSpecs = parseRepeatableStrings(args.option, "--option", { allowEmpty: true });
992
+ const optionsJsonRaw = args["options-json"];
993
+ if (optionSpecs.length > 0 && optionsJsonRaw) {
994
+ throw new import_errors.CliError("Do not pass both --option and --options-json", 2);
995
+ }
996
+ const options = optionsJsonRaw !== void 0 ? (0, import_shared.parseJsonArg)(optionsJsonRaw, "--options-json") : optionSpecs.map((s) => parseOptionSpec(s, "--option"));
997
+ if (!Array.isArray(options) || options.length === 0) {
998
+ throw new import_errors.CliError("Missing options: pass one or more --option entries, or --options-json", 2);
999
+ }
1000
+ const variantStrategy = normalizeProductOptionCreateVariantStrategy(args["variant-strategy"]);
1001
+ const selection = (0, import_select.resolveSelection)({
1002
+ resource: "products",
1003
+ view: ctx.view,
1004
+ baseSelection: getProductSelectionForOptions(ctx.view),
1005
+ select: args.select,
1006
+ selection: args.selection,
1007
+ include: args.include,
1008
+ ensureId: ctx.quiet
1009
+ });
1010
+ const result = await (0, import_router.runMutation)(ctx, {
1011
+ productOptionsCreate: {
1012
+ __args: { productId, options, ...variantStrategy ? { variantStrategy } : {} },
1013
+ product: selection,
1014
+ userErrors: { code: true, field: true, message: true }
1015
+ }
1016
+ });
1017
+ if (result === void 0) return;
1018
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.productOptionsCreate, failOnUserErrors: ctx.failOnUserErrors });
1019
+ (0, import_output.printNode)({ node: result.productOptionsCreate?.product, format: ctx.format, quiet: ctx.quiet });
1020
+ return;
1021
+ }
1022
+ if (verb === "options update") {
1023
+ const args = (0, import_router.parseStandardArgs)({
1024
+ argv,
1025
+ extraOptions: {
1026
+ "product-id": { type: "string" },
1027
+ "option-id": { type: "string" },
1028
+ name: { type: "string" },
1029
+ position: { type: "string" },
1030
+ "add-value": { type: "string", multiple: true },
1031
+ "delete-value": { type: "string", multiple: true },
1032
+ "rename-value": { type: "string", multiple: true },
1033
+ "delete-value-id": { type: "string", multiple: true },
1034
+ "rename-value-id": { type: "string", multiple: true },
1035
+ "option-json": { type: "string" },
1036
+ "add-values-json": { type: "string" },
1037
+ "delete-value-ids-json": { type: "string" },
1038
+ "update-values-json": { type: "string" },
1039
+ "variant-strategy": { type: "string" }
1040
+ }
1041
+ });
1042
+ const productId = requireProductIdForSubverb(args);
1043
+ const optionIdRaw = args["option-id"];
1044
+ if (!optionIdRaw) throw new import_errors.CliError("Missing --option-id", 2);
1045
+ const optionId = (0, import_gid.coerceGid)(optionIdRaw, "ProductOption");
1046
+ const optionJsonRaw = args["option-json"];
1047
+ const addValuesJsonRaw = args["add-values-json"];
1048
+ const deleteValueIdsJsonRaw = args["delete-value-ids-json"];
1049
+ const updateValuesJsonRaw = args["update-values-json"];
1050
+ const hasJsonMode = Boolean(optionJsonRaw || addValuesJsonRaw || deleteValueIdsJsonRaw || updateValuesJsonRaw);
1051
+ const addValueNames = parseRepeatableStrings(args["add-value"], "--add-value", { allowEmpty: true });
1052
+ const deleteValueNames = parseRepeatableStrings(args["delete-value"], "--delete-value", { allowEmpty: true });
1053
+ const renameValueSpecs = parseRepeatableStrings(args["rename-value"], "--rename-value", { allowEmpty: true });
1054
+ const deleteValueIdSpecs = parseRepeatableStrings(args["delete-value-id"], "--delete-value-id", {
1055
+ allowEmpty: true
1056
+ });
1057
+ const renameValueIdSpecs = parseRepeatableStrings(args["rename-value-id"], "--rename-value-id", {
1058
+ allowEmpty: true
1059
+ });
1060
+ if (hasJsonMode) {
1061
+ if (addValueNames.length || deleteValueNames.length || renameValueSpecs.length || deleteValueIdSpecs.length || renameValueIdSpecs.length || args.name !== void 0 || args.position !== void 0) {
1062
+ throw new import_errors.CliError("Do not mix JSON flags with non-JSON option update flags", 2);
1063
+ }
1064
+ }
1065
+ const position = parsePositiveIntFlag({ value: args.position, flag: "--position" });
1066
+ const hasNonJsonOptionChange = typeof args.name === "string" && args.name.trim() !== "" || position !== void 0;
1067
+ const hasNonJsonValueChange = addValueNames.length > 0 || deleteValueNames.length > 0 || renameValueSpecs.length > 0 || deleteValueIdSpecs.length > 0 || renameValueIdSpecs.length > 0;
1068
+ if (!hasJsonMode && !hasNonJsonOptionChange && !hasNonJsonValueChange) {
1069
+ throw new import_errors.CliError(
1070
+ "No changes specified. Pass --name/--position and/or value change flags (e.g. --add-value, --delete-value, --rename-value).",
1071
+ 2
1072
+ );
1073
+ }
1074
+ const optionUpdate = optionJsonRaw !== void 0 ? (0, import_shared.parseJsonArg)(optionJsonRaw, "--option-json") : {
1075
+ id: optionId,
1076
+ ...typeof args.name === "string" && args.name.trim() ? { name: args.name.trim() } : {},
1077
+ ...position !== void 0 ? { position } : {}
1078
+ };
1079
+ if (!optionUpdate || typeof optionUpdate !== "object") {
1080
+ throw new import_errors.CliError("--option-json must be a JSON object", 2);
1081
+ }
1082
+ if (!optionUpdate.id) optionUpdate.id = optionId;
1083
+ const optionValuesToAdd = addValuesJsonRaw !== void 0 ? (0, import_shared.parseJsonArg)(addValuesJsonRaw, "--add-values-json") : addValueNames.map((name) => ({ name }));
1084
+ const optionValuesToDeleteJson = deleteValueIdsJsonRaw !== void 0 ? (0, import_shared.parseJsonArg)(deleteValueIdsJsonRaw, "--delete-value-ids-json") : void 0;
1085
+ const optionValuesToUpdate = updateValuesJsonRaw !== void 0 ? (0, import_shared.parseJsonArg)(updateValuesJsonRaw, "--update-values-json") : void 0;
1086
+ const optionValuesToDeleteFromIds = deleteValueIdSpecs.map((id) => (0, import_gid.coerceGid)(id, "ProductOptionValue"));
1087
+ const needsResolutionByName = deleteValueNames.length > 0 || renameValueSpecs.length > 0;
1088
+ if (needsResolutionByName && ctx.dryRun) {
1089
+ throw new import_errors.CliError(
1090
+ "Name-based value changes are not supported in --dry-run mode. Use --delete-value-id/--rename-value-id or JSON flags.",
1091
+ 2
1092
+ );
1093
+ }
1094
+ let resolvedDeletesFromNames = [];
1095
+ let resolvedUpdatesFromNames = [];
1096
+ if (needsResolutionByName) {
1097
+ const options = await fetchProductOptionsForResolution({ ctx, productId });
1098
+ const option = options.find((o) => typeof o?.id === "string" && o.id === optionId);
1099
+ if (!option) throw new import_errors.CliError(`Option not found on product: ${optionId}`, 2);
1100
+ const optionValues = option.optionValues ?? [];
1101
+ const byName = /* @__PURE__ */ new Map();
1102
+ for (const ov of optionValues) {
1103
+ const n = typeof ov?.name === "string" ? ov.name : void 0;
1104
+ if (!n) continue;
1105
+ const list = byName.get(n) ?? [];
1106
+ list.push(ov);
1107
+ byName.set(n, list);
1108
+ }
1109
+ for (const name of deleteValueNames) {
1110
+ const matches = byName.get(name) ?? [];
1111
+ if (matches.length === 0) throw new import_errors.CliError(`Option value not found: "${name}"`, 2);
1112
+ if (matches.length > 1) {
1113
+ throw new import_errors.CliError(`Multiple option values named "${name}" exist. Use --delete-value-id instead.`, 2);
1114
+ }
1115
+ const id = matches[0]?.id;
1116
+ if (typeof id !== "string" || !id) throw new import_errors.CliError(`Option value "${name}" is missing an ID`, 2);
1117
+ resolvedDeletesFromNames.push(id);
1118
+ }
1119
+ for (const spec of renameValueSpecs) {
1120
+ const { from, to } = parseFromTo(spec, "--rename-value");
1121
+ const matches = byName.get(from) ?? [];
1122
+ if (matches.length === 0) throw new import_errors.CliError(`Option value not found: "${from}"`, 2);
1123
+ if (matches.length > 1) {
1124
+ throw new import_errors.CliError(`Multiple option values named "${from}" exist. Use --rename-value-id instead.`, 2);
1125
+ }
1126
+ const id = matches[0]?.id;
1127
+ if (typeof id !== "string" || !id) throw new import_errors.CliError(`Option value "${from}" is missing an ID`, 2);
1128
+ resolvedUpdatesFromNames.push({ id, name: to });
1129
+ }
1130
+ }
1131
+ const renameUpdatesFromIds = [];
1132
+ for (const spec of renameValueIdSpecs) {
1133
+ const { from, to } = parseFromTo(spec, "--rename-value-id");
1134
+ renameUpdatesFromIds.push({ id: (0, import_gid.coerceGid)(from, "ProductOptionValue"), name: to });
1135
+ }
1136
+ const deletesFromJson = optionValuesToDeleteJson !== void 0 ? (() => {
1137
+ if (!Array.isArray(optionValuesToDeleteJson)) {
1138
+ throw new import_errors.CliError("--delete-value-ids-json must be a JSON array", 2);
1139
+ }
1140
+ return optionValuesToDeleteJson.map((id) => {
1141
+ if (typeof id !== "string" || !id.trim()) throw new import_errors.CliError("delete-value-ids-json must contain strings", 2);
1142
+ return id;
1143
+ });
1144
+ })() : [];
1145
+ const deletes = Array.from(/* @__PURE__ */ new Set([...optionValuesToDeleteFromIds, ...resolvedDeletesFromNames, ...deletesFromJson]));
1146
+ const updates = [
1147
+ ...Array.isArray(optionValuesToUpdate) ? optionValuesToUpdate : optionValuesToUpdate ? [optionValuesToUpdate] : [],
1148
+ ...resolvedUpdatesFromNames,
1149
+ ...renameUpdatesFromIds
1150
+ ];
1151
+ if (optionValuesToAdd !== void 0 && optionValuesToAdd !== null && !Array.isArray(optionValuesToAdd)) {
1152
+ throw new import_errors.CliError("--add-values-json must be a JSON array", 2);
1153
+ }
1154
+ if (optionValuesToUpdate !== void 0 && optionValuesToUpdate !== null && !Array.isArray(optionValuesToUpdate)) {
1155
+ throw new import_errors.CliError("--update-values-json must be a JSON array", 2);
1156
+ }
1157
+ const variantStrategy = normalizeProductOptionUpdateVariantStrategy(args["variant-strategy"]);
1158
+ const selection = (0, import_select.resolveSelection)({
1159
+ resource: "products",
1160
+ view: ctx.view,
1161
+ baseSelection: getProductSelectionForOptions(ctx.view),
1162
+ select: args.select,
1163
+ selection: args.selection,
1164
+ include: args.include,
1165
+ ensureId: ctx.quiet
1166
+ });
1167
+ const result = await (0, import_router.runMutation)(ctx, {
1168
+ productOptionUpdate: {
1169
+ __args: {
1170
+ productId,
1171
+ option: optionUpdate,
1172
+ ...Array.isArray(optionValuesToAdd) && optionValuesToAdd.length ? { optionValuesToAdd } : {},
1173
+ ...deletes.length ? { optionValuesToDelete: deletes } : {},
1174
+ ...updates.length ? { optionValuesToUpdate: updates } : {},
1175
+ ...variantStrategy ? { variantStrategy } : {}
1176
+ },
1177
+ product: selection,
1178
+ userErrors: { code: true, field: true, message: true }
1179
+ }
1180
+ });
1181
+ if (result === void 0) return;
1182
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.productOptionUpdate, failOnUserErrors: ctx.failOnUserErrors });
1183
+ (0, import_output.printNode)({ node: result.productOptionUpdate?.product, format: ctx.format, quiet: ctx.quiet });
1184
+ return;
1185
+ }
1186
+ if (verb === "options delete") {
1187
+ const args = (0, import_router.parseStandardArgs)({
1188
+ argv,
1189
+ extraOptions: {
1190
+ "product-id": { type: "string" },
1191
+ "option-id": { type: "string", multiple: true },
1192
+ "option-name": { type: "string", multiple: true },
1193
+ strategy: { type: "string" }
1194
+ }
1195
+ });
1196
+ const productId = requireProductIdForSubverb(args);
1197
+ const optionIdsRaw = (0, import_shared.parseStringList)(args["option-id"], "--option-id", { allowEmpty: true });
1198
+ const optionNames = (0, import_shared.parseStringList)(args["option-name"], "--option-name", { allowEmpty: true });
1199
+ const strategy = normalizeProductOptionDeleteStrategy(args.strategy);
1200
+ if (optionIdsRaw.length === 0 && optionNames.length === 0) {
1201
+ throw new import_errors.CliError("Missing options: pass one or more --option-id and/or --option-name entries", 2);
1202
+ }
1203
+ if (ctx.dryRun && optionNames.length > 0) {
1204
+ throw new import_errors.CliError("Option name resolution is not supported in --dry-run mode. Use --option-id instead.", 2);
1205
+ }
1206
+ const optionIds = optionIdsRaw.map((id) => (0, import_gid.coerceGid)(id, "ProductOption"));
1207
+ if (optionNames.length > 0) {
1208
+ const options = await fetchProductOptionsForResolution({ ctx, productId });
1209
+ for (const name of optionNames) {
1210
+ const opt = resolveSingleOptionByName(options, name);
1211
+ if (!opt) throw new import_errors.CliError(`Option not found on product: "${name}"`, 2);
1212
+ const id = opt?.id;
1213
+ if (typeof id !== "string" || !id) throw new import_errors.CliError(`Option "${name}" is missing an ID`, 2);
1214
+ optionIds.push(id);
1215
+ }
1216
+ }
1217
+ const uniqueOptionIds = Array.from(new Set(optionIds));
1218
+ const result = await (0, import_router.runMutation)(ctx, {
1219
+ productOptionsDelete: {
1220
+ __args: { productId, options: uniqueOptionIds, ...strategy ? { strategy } : {} },
1221
+ deletedOptionsIds: true,
1222
+ userErrors: { code: true, field: true, message: true }
1223
+ }
1224
+ });
1225
+ if (result === void 0) return;
1226
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.productOptionsDelete, failOnUserErrors: ctx.failOnUserErrors });
1227
+ const deleted = result.productOptionsDelete?.deletedOptionsIds ?? [];
1228
+ if (ctx.quiet) {
1229
+ for (const id of deleted) {
1230
+ if (typeof id === "string" && id) console.log(id);
1231
+ }
1232
+ return;
1233
+ }
1234
+ (0, import_output.printNode)({
1235
+ node: { deletedOptionsIds: deleted.filter((id) => typeof id === "string" && id.length > 0) },
1236
+ format: ctx.format,
1237
+ quiet: false
1238
+ });
1239
+ return;
1240
+ }
1241
+ if (verb === "options reorder") {
1242
+ const args = (0, import_router.parseStandardArgs)({
1243
+ argv,
1244
+ extraOptions: {
1245
+ "product-id": { type: "string" },
1246
+ order: { type: "string", multiple: true },
1247
+ "options-json": { type: "string" }
1248
+ }
1249
+ });
1250
+ const productId = requireProductIdForSubverb(args);
1251
+ const orderSpecs = parseRepeatableStrings(args.order, "--order", { allowEmpty: true });
1252
+ const optionsJsonRaw = args["options-json"];
1253
+ if (orderSpecs.length > 0 && optionsJsonRaw) {
1254
+ throw new import_errors.CliError("Do not pass both --order and --options-json", 2);
1255
+ }
1256
+ const selection = (0, import_select.resolveSelection)({
1257
+ resource: "products",
1258
+ view: ctx.view,
1259
+ baseSelection: getProductSelectionForOptions(ctx.view),
1260
+ select: args.select,
1261
+ selection: args.selection,
1262
+ include: args.include,
1263
+ ensureId: ctx.quiet
1264
+ });
1265
+ const optionsInput = optionsJsonRaw !== void 0 ? (0, import_shared.parseJsonArg)(optionsJsonRaw, "--options-json") : void 0;
1266
+ let options = [];
1267
+ if (optionsInput !== void 0) {
1268
+ if (!Array.isArray(optionsInput)) throw new import_errors.CliError("--options-json must be a JSON array", 2);
1269
+ options = optionsInput;
1270
+ } else {
1271
+ if (orderSpecs.length === 0) throw new import_errors.CliError("Missing order: pass one or more --order entries, or --options-json", 2);
1272
+ const parsed = [];
1273
+ const hasAnyValueOrder = orderSpecs.some((s) => s.includes("="));
1274
+ if (hasAnyValueOrder && ctx.dryRun) {
1275
+ throw new import_errors.CliError("Value reordering via --order is not supported in --dry-run mode. Use --options-json.", 2);
1276
+ }
1277
+ let optionsForValidation;
1278
+ if (hasAnyValueOrder) {
1279
+ optionsForValidation = await fetchProductOptionsForResolution({ ctx, productId });
1280
+ }
1281
+ for (const spec of orderSpecs) {
1282
+ const trimmed = spec.trim();
1283
+ const eq = trimmed.indexOf("=");
1284
+ const optionToken = (eq === -1 ? trimmed : trimmed.slice(0, eq)).trim();
1285
+ if (!optionToken) throw new import_errors.CliError("--order cannot be empty", 2);
1286
+ const optionInput = looksLikeGidOrNumericId(optionToken) ? { id: (0, import_gid.coerceGid)(optionToken, "ProductOption") } : { name: optionToken };
1287
+ if (eq !== -1) {
1288
+ const valuesPart = trimmed.slice(eq + 1).trim();
1289
+ if (!valuesPart) throw new import_errors.CliError(`--order "${spec}" must include at least one value after '='`, 2);
1290
+ const valueTokens = valuesPart.split(",").map((v) => v.trim()).filter(Boolean);
1291
+ if (valueTokens.length === 0) throw new import_errors.CliError(`--order "${spec}" must include at least one value after '='`, 2);
1292
+ if (!optionsForValidation) throw new import_errors.CliError("Internal error: missing options for validation", 2);
1293
+ const resolvedOption = "id" in optionInput ? optionsForValidation.find((o) => typeof o?.id === "string" && o.id === optionInput.id) : resolveSingleOptionByName(optionsForValidation, optionInput.name);
1294
+ if (!resolvedOption) {
1295
+ const ref = "id" in optionInput ? optionInput.id : `"${optionInput.name}"`;
1296
+ throw new import_errors.CliError(`Option not found on product: ${ref}`, 2);
1297
+ }
1298
+ const optionValues = resolvedOption.optionValues ?? [];
1299
+ const byName = /* @__PURE__ */ new Map();
1300
+ const existingIds = [];
1301
+ for (const ov of optionValues) {
1302
+ const id = typeof ov?.id === "string" ? ov.id : void 0;
1303
+ const name = typeof ov?.name === "string" ? ov.name : void 0;
1304
+ if (id) existingIds.push(id);
1305
+ if (name) {
1306
+ const list = byName.get(name) ?? [];
1307
+ list.push(ov);
1308
+ byName.set(name, list);
1309
+ }
1310
+ }
1311
+ const providedIds = [];
1312
+ for (const vt of valueTokens) {
1313
+ if (looksLikeGidOrNumericId(vt)) {
1314
+ providedIds.push((0, import_gid.coerceGid)(vt, "ProductOptionValue"));
1315
+ continue;
1316
+ }
1317
+ const matches = byName.get(vt) ?? [];
1318
+ if (matches.length === 0) throw new import_errors.CliError(`Option value not found: "${vt}"`, 2);
1319
+ if (matches.length > 1) throw new import_errors.CliError(`Multiple option values named "${vt}" exist. Use IDs.`, 2);
1320
+ const id = matches[0]?.id;
1321
+ if (typeof id !== "string" || !id) throw new import_errors.CliError(`Option value "${vt}" is missing an ID`, 2);
1322
+ providedIds.push(id);
1323
+ }
1324
+ const existingSet = new Set(existingIds);
1325
+ const providedSet = new Set(providedIds);
1326
+ if (providedSet.size !== providedIds.length) {
1327
+ throw new import_errors.CliError("Duplicate option values provided in --order value list", 2);
1328
+ }
1329
+ const missing = existingIds.filter((id) => !providedSet.has(id));
1330
+ const extra = providedIds.filter((id) => !existingSet.has(id));
1331
+ if (missing.length || extra.length) {
1332
+ throw new import_errors.CliError(
1333
+ `--order "${optionToken}=..." must include the full value order for that option.`,
1334
+ 2
1335
+ );
1336
+ }
1337
+ parsed.push({
1338
+ id: resolvedOption.id,
1339
+ values: providedIds.map((id) => ({ id }))
1340
+ });
1341
+ } else {
1342
+ parsed.push(optionInput);
1343
+ }
1344
+ }
1345
+ options = parsed;
1346
+ }
1347
+ const result = await (0, import_router.runMutation)(ctx, {
1348
+ productOptionsReorder: {
1349
+ __args: { productId, options },
1350
+ product: selection,
1351
+ userErrors: { code: true, field: true, message: true }
1352
+ }
1353
+ });
1354
+ if (result === void 0) return;
1355
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.productOptionsReorder, failOnUserErrors: ctx.failOnUserErrors });
1356
+ (0, import_output.printNode)({ node: result.productOptionsReorder?.product, format: ctx.format, quiet: ctx.quiet });
1357
+ return;
1358
+ }
1359
+ if (verb === "combined-listing-update") {
1360
+ const args = (0, import_router.parseStandardArgs)({
1361
+ argv,
1362
+ extraOptions: {
1363
+ "parent-product-id": { type: "string" },
1364
+ title: { type: "string" },
1365
+ "products-added": { type: "string" },
1366
+ "products-edited": { type: "string" },
1367
+ "products-removed-ids": { type: "string", multiple: true },
1368
+ "options-and-values": { type: "string" }
1369
+ }
1370
+ });
1371
+ const parentProductId = (0, import_shared.requireId)(args["parent-product-id"], "Product", "--parent-product-id");
1372
+ const optionsAndValues = args["options-and-values"] ? (0, import_shared.parseJsonArg)(args["options-and-values"], "--options-and-values") : void 0;
1373
+ const productsAdded = args["products-added"] ? (0, import_shared.parseJsonArg)(args["products-added"], "--products-added") : void 0;
1374
+ const productsEdited = args["products-edited"] ? (0, import_shared.parseJsonArg)(args["products-edited"], "--products-edited") : void 0;
1375
+ const productsRemovedIds = args["products-removed-ids"] ? (0, import_shared.parseIds)(args["products-removed-ids"], "Product") : void 0;
1376
+ const title = args.title;
1377
+ const selection = (0, import_select.resolveSelection)({
1378
+ resource: "products",
1379
+ view: ctx.view,
1380
+ baseSelection: getProductSelection(ctx.view),
1381
+ select: args.select,
1382
+ selection: args.selection,
1383
+ include: args.include,
1384
+ ensureId: ctx.quiet
1385
+ });
1386
+ const result = await (0, import_router.runMutation)(ctx, {
1387
+ combinedListingUpdate: {
1388
+ __args: {
1389
+ parentProductId,
1390
+ ...title ? { title } : {},
1391
+ ...optionsAndValues !== void 0 ? { optionsAndValues } : {},
1392
+ ...productsAdded !== void 0 ? { productsAdded } : {},
1393
+ ...productsEdited !== void 0 ? { productsEdited } : {},
1394
+ ...productsRemovedIds !== void 0 ? { productsRemovedIds } : {}
1395
+ },
1396
+ product: selection,
1397
+ userErrors: { code: true, field: true, message: true }
1398
+ }
1399
+ });
1400
+ if (result === void 0) return;
1401
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.combinedListingUpdate, failOnUserErrors: ctx.failOnUserErrors });
1402
+ (0, import_output.printNode)({ node: result.combinedListingUpdate?.product, format: ctx.format, quiet: ctx.quiet });
1403
+ return;
1404
+ }
1405
+ if (verb === "bundle-create" || verb === "bundle-update") {
1406
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: {} });
1407
+ const built = (0, import_input.buildInput)({
1408
+ inputArg: args.input,
1409
+ setArgs: args.set,
1410
+ setJsonArgs: args["set-json"]
1411
+ });
1412
+ if (!built.used) throw new import_errors.CliError("Missing --input or --set/--set-json", 2);
1413
+ const productSelection = (0, import_select.resolveSelection)({
1414
+ resource: "products",
1415
+ view: ctx.view,
1416
+ baseSelection: getProductSelection(ctx.view),
1417
+ select: args.select,
1418
+ selection: args.selection,
1419
+ include: args.include,
1420
+ ensureId: ctx.quiet
1421
+ });
1422
+ const mutation = verb === "bundle-create" ? "productBundleCreate" : "productBundleUpdate";
1423
+ const result = await (0, import_router.runMutation)(ctx, {
1424
+ [mutation]: {
1425
+ __args: { input: built.input },
1426
+ productBundleOperation: {
1427
+ id: true,
1428
+ status: true,
1429
+ product: productSelection
1430
+ },
1431
+ userErrors: { field: true, message: true }
1432
+ }
1433
+ });
1434
+ if (result === void 0) return;
1435
+ const payload = result[mutation];
1436
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload, failOnUserErrors: ctx.failOnUserErrors });
1437
+ const operation = payload?.productBundleOperation ? {
1438
+ id: payload.productBundleOperation.id,
1439
+ status: payload.productBundleOperation.status
1440
+ } : void 0;
1441
+ const product = payload?.productBundleOperation?.product;
1442
+ if (product && typeof product === "object") {
1443
+ (0, import_output.printNode)({
1444
+ node: { ...product, ...operation ? { operation } : {} },
1445
+ format: ctx.format,
1446
+ quiet: ctx.quiet
1447
+ });
1448
+ return;
1449
+ }
1450
+ if (ctx.quiet) return;
1451
+ (0, import_output.printJson)(
1452
+ {
1453
+ product: product ?? null,
1454
+ ...operation ? { operation } : {},
1455
+ userErrors: payload?.userErrors ?? []
1456
+ },
1457
+ ctx.format !== "raw"
1458
+ );
1459
+ return;
1460
+ }
1461
+ if (verb === "count") {
1462
+ const args = (0, import_router.parseStandardArgs)({
1463
+ argv,
1464
+ extraOptions: {
1465
+ limit: { type: "string" },
1466
+ "saved-search-id": { type: "string" }
1467
+ }
1468
+ });
1469
+ const query = args.query;
1470
+ const limitRaw = args.limit;
1471
+ const savedSearchIdRaw = args["saved-search-id"];
1472
+ const limit = limitRaw === void 0 || limitRaw === null || limitRaw === "" ? void 0 : Number(limitRaw);
1473
+ if (limit !== void 0 && (!Number.isFinite(limit) || limit <= 0)) {
1474
+ throw new import_errors.CliError("--limit must be a positive number", 2);
1475
+ }
1476
+ const savedSearchId = savedSearchIdRaw ? (0, import_gid.coerceGid)(String(savedSearchIdRaw), "SavedSearch") : void 0;
1477
+ const result = await (0, import_router.runQuery)(ctx, {
1478
+ productsCount: {
1479
+ __args: {
1480
+ ...query ? { query } : {},
1481
+ ...savedSearchId ? { savedSearchId } : {},
1482
+ ...limit !== void 0 ? { limit: Math.floor(limit) } : {}
1483
+ },
1484
+ count: true,
1485
+ precision: true
1486
+ }
1487
+ });
1488
+ if (result === void 0) return;
1489
+ if (ctx.quiet) return console.log(result.productsCount?.count ?? "");
1490
+ (0, import_output.printJson)(result.productsCount, ctx.format !== "raw");
1491
+ return;
1492
+ }
1493
+ if (verb === "publish" || verb === "unpublish") {
1494
+ const args = (0, import_router.parseStandardArgs)({
1495
+ argv,
1496
+ extraOptions: {
1497
+ "product-id": { type: "string" },
1498
+ "publication-id": { type: "string", multiple: true },
1499
+ publication: { type: "string", multiple: true },
1500
+ at: { type: "string" },
1501
+ now: { type: "boolean" }
1502
+ }
1503
+ });
1504
+ const id = requireProductIdForRootVerb(args);
1505
+ const publicationIds = args["publication-id"] ?? [];
1506
+ const publicationNames = args.publication ?? [];
1507
+ const resolvedPublicationIds = await (0, import_publishablePublish.resolvePublicationIds)({
1508
+ ctx,
1509
+ publicationIds,
1510
+ publicationNames
1511
+ });
1512
+ if (verb === "publish") {
1513
+ const publishDate = (0, import_publishablePublish.parsePublishDate)({ at: args.at, now: args.now });
1514
+ const payload2 = await (0, import_publishablePublish.publishProduct)({
1515
+ ctx,
1516
+ id,
1517
+ publicationIds: resolvedPublicationIds,
1518
+ publishDate
1519
+ });
1520
+ if (payload2 === void 0) return;
1521
+ if (ctx.quiet) return console.log(payload2?.publishable?.id ?? "");
1522
+ (0, import_output.printJson)(payload2);
1523
+ return;
1524
+ }
1525
+ const payload = await (0, import_publishablePublish.unpublishProduct)({
1526
+ ctx,
1527
+ id,
1528
+ publicationIds: resolvedPublicationIds
1529
+ });
1530
+ if (payload === void 0) return;
1531
+ if (ctx.quiet) return console.log(payload?.publishable?.id ?? "");
1532
+ (0, import_output.printJson)(payload);
1533
+ return;
1534
+ }
1535
+ if (verb === "publish-all") {
1536
+ const args = (0, import_router.parseStandardArgs)({
1537
+ argv,
1538
+ extraOptions: {
1539
+ "product-id": { type: "string" },
1540
+ at: { type: "string" },
1541
+ now: { type: "boolean" }
1542
+ }
1543
+ });
1544
+ if (ctx.dryRun) {
1545
+ await (0, import_resolvePublicationId.listPublications)(ctx);
1546
+ return;
1547
+ }
1548
+ const id = requireProductIdForRootVerb(args);
1549
+ const publishDate = (0, import_publishablePublish.parsePublishDate)({ at: args.at, now: args.now });
1550
+ const publications = await (0, import_resolvePublicationId.listPublications)(ctx);
1551
+ const publicationIds = publications.map((p) => p.id).filter(Boolean);
1552
+ if (publicationIds.length === 0) throw new import_errors.CliError("No publications found to publish to", 2);
1553
+ const payload = await (0, import_publishablePublish.publishProduct)({
1554
+ ctx,
1555
+ id,
1556
+ publicationIds,
1557
+ publishDate
1558
+ });
1559
+ if (payload === void 0) return;
1560
+ if (ctx.quiet) return console.log(payload?.publishable?.id ?? "");
1561
+ (0, import_output.printJson)(payload);
1562
+ return;
1563
+ }
1564
+ if (verb === "metafields upsert") {
1565
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: { "product-id": { type: "string" } } });
1566
+ const productId = requireProductIdForSubverb(args);
1567
+ const built = (0, import_input.buildInput)({
1568
+ inputArg: args.input,
1569
+ setArgs: args.set,
1570
+ setJsonArgs: args["set-json"]
1571
+ });
1572
+ if (!built.used) throw new import_errors.CliError("Missing --input or --set/--set-json", 2);
1573
+ const result = await (0, import_metafieldsUpsert.metafieldsUpsert)({ ctx, id: productId, input: built.input });
1574
+ if (result === void 0) return;
1575
+ (0, import_output.printJson)(result);
1576
+ return;
1577
+ }
1578
+ if (verb === "get") {
1579
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: { "product-id": { type: "string" } } });
1580
+ const id = requireProductIdForRootVerb(args);
1581
+ const selectValues = Array.isArray(args.select) ? args.select : args.select ? [args.select] : [];
1582
+ const selectionOverride = typeof args.selection === "string" && args.selection.length > 0;
1583
+ const select = !selectionOverride && ctx.view !== "raw" && ctx.view !== "ids" ? Array.from(/* @__PURE__ */ new Set([...selectValues, "resourcePublicationsV2.nodes.publication.name"])) : args.select;
1584
+ const includeValues = Array.isArray(args.include) ? args.include : args.include ? [args.include] : [];
1585
+ const include = ctx.view === "all" ? Array.from(/* @__PURE__ */ new Set([...includeValues, "resourcePublicationsV2"])) : args.include;
1586
+ const selection = (0, import_select.resolveSelection)({
1587
+ resource: "products",
1588
+ view: ctx.view,
1589
+ baseSelection: getProductSelectionForGet(ctx.view),
1590
+ select,
1591
+ selection: args.selection,
1592
+ include,
1593
+ ensureId: ctx.quiet,
1594
+ defaultConnectionFirst: ctx.view === "all" ? 50 : 10
1595
+ });
1596
+ const result = await (0, import_router.runQuery)(ctx, { product: { __args: { id }, ...selection } });
1597
+ if (result === void 0) return;
1598
+ const wantsResourcePublicationsV2 = Array.isArray(args.select) && args.select.some((p) => typeof p === "string" && p.startsWith("resourcePublicationsV2"));
1599
+ const wantsResourcePublicationsV2ViaSelection = typeof args.selection === "string" && args.selection.includes("resourcePublicationsV2");
1600
+ const stripResourcePublicationsV2 = !(wantsResourcePublicationsV2 || wantsResourcePublicationsV2ViaSelection);
1601
+ const withComputed = (0, import_computedFields.applyComputedFieldsToNode)(result.product, {
1602
+ view: ctx.view,
1603
+ stripResourcePublicationsV2
1604
+ });
1605
+ (0, import_output.printNode)({ node: withComputed, format: ctx.format, quiet: ctx.quiet });
1606
+ return;
1607
+ }
1608
+ if (verb === "list") {
1609
+ const args = (0, import_router.parseStandardArgs)({
1610
+ argv,
1611
+ extraOptions: {
1612
+ published: { type: "boolean" }
1613
+ }
1614
+ });
1615
+ const first = (0, import_shared.parseFirst)(args.first);
1616
+ const after = args.after;
1617
+ const userQuery = typeof args.query === "string" && args.query.trim() ? args.query.trim() : void 0;
1618
+ const published = args.published === true;
1619
+ const publishedFilter = "published_status:published";
1620
+ const query = published && typeof userQuery === "string" && userQuery.includes(publishedFilter) ? userQuery : published ? userQuery ? `${userQuery} ${publishedFilter}` : publishedFilter : userQuery;
1621
+ const reverse = args.reverse;
1622
+ const sortKey = args.sort;
1623
+ const nodeSelection = (0, import_select.resolveSelection)({
1624
+ resource: "products",
1625
+ view: ctx.view,
1626
+ baseSelection: getProductSelection(ctx.view),
1627
+ select: args.select,
1628
+ selection: args.selection,
1629
+ include: args.include,
1630
+ ensureId: ctx.quiet
1631
+ });
1632
+ const result = await (0, import_router.runQuery)(ctx, {
1633
+ products: {
1634
+ __args: { first, after, query, reverse, sortKey },
1635
+ pageInfo: { hasNextPage: true, endCursor: true },
1636
+ nodes: nodeSelection
1637
+ }
1638
+ });
1639
+ if (result === void 0) return;
1640
+ (0, import_output.printConnection)({
1641
+ connection: result.products,
1642
+ format: ctx.format,
1643
+ quiet: ctx.quiet,
1644
+ nextPageArgs: (0, import_shared.buildListNextPageArgs)(
1645
+ "products",
1646
+ { first, query: userQuery, sort: sortKey, reverse },
1647
+ published ? [{ flag: "--published", value: true }] : void 0
1648
+ )
1649
+ });
1650
+ return;
1651
+ }
1652
+ if (verb === "create") {
1653
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: {} });
1654
+ const built = (0, import_input.buildInput)({
1655
+ inputArg: args.input,
1656
+ setArgs: args.set,
1657
+ setJsonArgs: args["set-json"]
1658
+ });
1659
+ if (!built.used) throw new import_errors.CliError("Missing --input or --set/--set-json", 2);
1660
+ const selection = (0, import_select.resolveSelection)({
1661
+ resource: "products",
1662
+ view: ctx.view,
1663
+ baseSelection: getProductSelection(ctx.view),
1664
+ select: args.select,
1665
+ selection: args.selection,
1666
+ include: args.include,
1667
+ ensureId: ctx.quiet,
1668
+ defaultConnectionFirst: ctx.view === "all" ? 50 : 10
1669
+ });
1670
+ const result = await (0, import_router.runMutation)(ctx, {
1671
+ productCreate: {
1672
+ __args: { input: built.input },
1673
+ product: selection,
1674
+ userErrors: { field: true, message: true }
1675
+ }
1676
+ });
1677
+ if (result === void 0) return;
1678
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.productCreate, failOnUserErrors: ctx.failOnUserErrors });
1679
+ (0, import_output.printNode)({ node: result.productCreate?.product, format: ctx.format, quiet: ctx.quiet });
1680
+ return;
1681
+ }
1682
+ if (verb === "archive" || verb === "unarchive") {
1683
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: { "product-id": { type: "string" } } });
1684
+ const id = requireProductIdForRootVerb(args);
1685
+ const status = verb === "archive" ? "ARCHIVED" : args.status ?? "DRAFT";
1686
+ const selection = (0, import_select.resolveSelection)({
1687
+ resource: "products",
1688
+ view: ctx.view,
1689
+ baseSelection: getProductSelection(ctx.view),
1690
+ select: args.select,
1691
+ selection: args.selection,
1692
+ include: args.include,
1693
+ ensureId: ctx.quiet,
1694
+ defaultConnectionFirst: ctx.view === "all" ? 50 : 10
1695
+ });
1696
+ const result = await (0, import_router.runMutation)(ctx, {
1697
+ productUpdate: {
1698
+ __args: { input: { id, status } },
1699
+ product: selection,
1700
+ userErrors: { field: true, message: true }
1701
+ }
1702
+ });
1703
+ if (result === void 0) return;
1704
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.productUpdate, failOnUserErrors: ctx.failOnUserErrors });
1705
+ (0, import_output.printNode)({ node: result.productUpdate?.product, format: ctx.format, quiet: ctx.quiet });
1706
+ return;
1707
+ }
1708
+ if (verb === "update") {
1709
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: { "product-id": { type: "string" } } });
1710
+ const id = requireProductIdForRootVerb(args);
1711
+ const built = (0, import_input.buildInput)({
1712
+ inputArg: args.input,
1713
+ setArgs: args.set,
1714
+ setJsonArgs: args["set-json"]
1715
+ });
1716
+ if (!built.used) throw new import_errors.CliError("Missing --input or --set/--set-json", 2);
1717
+ const input = { ...built.input, id };
1718
+ const selection = (0, import_select.resolveSelection)({
1719
+ resource: "products",
1720
+ view: ctx.view,
1721
+ baseSelection: getProductSelection(ctx.view),
1722
+ select: args.select,
1723
+ selection: args.selection,
1724
+ include: args.include,
1725
+ ensureId: ctx.quiet,
1726
+ defaultConnectionFirst: ctx.view === "all" ? 50 : 10
1727
+ });
1728
+ const result = await (0, import_router.runMutation)(ctx, {
1729
+ productUpdate: {
1730
+ __args: { input },
1731
+ product: selection,
1732
+ userErrors: { field: true, message: true }
1733
+ }
1734
+ });
1735
+ if (result === void 0) return;
1736
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.productUpdate, failOnUserErrors: ctx.failOnUserErrors });
1737
+ (0, import_output.printNode)({ node: result.productUpdate?.product, format: ctx.format, quiet: ctx.quiet });
1738
+ return;
1739
+ }
1740
+ if (verb === "delete") {
1741
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: { "product-id": { type: "string" } } });
1742
+ const id = requireProductIdForRootVerb(args);
1743
+ if (!args.yes) throw new import_errors.CliError("Refusing to delete without --yes", 2);
1744
+ const result = await (0, import_router.runMutation)(ctx, {
1745
+ productDelete: {
1746
+ __args: { input: { id } },
1747
+ deletedProductId: true,
1748
+ userErrors: { field: true, message: true }
1749
+ }
1750
+ });
1751
+ if (result === void 0) return;
1752
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.productDelete, failOnUserErrors: ctx.failOnUserErrors });
1753
+ if (ctx.quiet) return console.log(result.productDelete?.deletedProductId ?? "");
1754
+ (0, import_output.printJson)(result.productDelete, ctx.format !== "raw");
1755
+ return;
1756
+ }
1757
+ if (verb === "duplicate") {
1758
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: { "product-id": { type: "string" } } });
1759
+ const id = requireProductIdForRootVerb(args);
1760
+ const built = (0, import_input.buildInput)({
1761
+ inputArg: void 0,
1762
+ setArgs: args.set,
1763
+ setJsonArgs: args["set-json"]
1764
+ });
1765
+ let newTitle = args["new-title"] ?? (built.used ? built.input?.newTitle : void 0);
1766
+ if (!newTitle) {
1767
+ const original = await (0, import_router.runQuery)(ctx, { product: { __args: { id }, title: true } });
1768
+ if (original === void 0) return;
1769
+ const title = original.product?.title;
1770
+ if (!title) throw new import_errors.CliError("Could not resolve original product title to auto-generate newTitle", 2);
1771
+ newTitle = `${title} (Copy)`;
1772
+ }
1773
+ const mutationArgs = {
1774
+ productId: id,
1775
+ newTitle,
1776
+ ...built.used ? built.input : {}
1777
+ };
1778
+ const selection = (0, import_select.resolveSelection)({
1779
+ resource: "products",
1780
+ view: ctx.view,
1781
+ baseSelection: getProductSelection(ctx.view),
1782
+ select: args.select,
1783
+ selection: args.selection,
1784
+ include: args.include,
1785
+ ensureId: ctx.quiet,
1786
+ defaultConnectionFirst: ctx.view === "all" ? 50 : 10
1787
+ });
1788
+ const result = await (0, import_router.runMutation)(ctx, {
1789
+ productDuplicate: {
1790
+ __args: mutationArgs,
1791
+ newProduct: selection,
1792
+ userErrors: { field: true, message: true }
1793
+ }
1794
+ });
1795
+ if (result === void 0) return;
1796
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.productDuplicate, failOnUserErrors: ctx.failOnUserErrors });
1797
+ (0, import_output.printNode)({ node: result.productDuplicate?.newProduct, format: ctx.format, quiet: ctx.quiet });
1798
+ return;
1799
+ }
1800
+ if (verb === "set-status") {
1801
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: { "product-id": { type: "string" } } });
1802
+ const id = requireProductIdForRootVerb(args);
1803
+ const status = args.status;
1804
+ if (!status) throw new import_errors.CliError("Missing --status (ACTIVE|DRAFT|ARCHIVED)", 2);
1805
+ const selection = (0, import_select.resolveSelection)({
1806
+ resource: "products",
1807
+ view: ctx.view,
1808
+ baseSelection: getProductSelection(ctx.view),
1809
+ select: args.select,
1810
+ selection: args.selection,
1811
+ include: args.include,
1812
+ ensureId: ctx.quiet,
1813
+ defaultConnectionFirst: ctx.view === "all" ? 50 : 10
1814
+ });
1815
+ const result = await (0, import_router.runMutation)(ctx, {
1816
+ productUpdate: {
1817
+ __args: { input: { id, status } },
1818
+ product: selection,
1819
+ userErrors: { field: true, message: true }
1820
+ }
1821
+ });
1822
+ if (result === void 0) return;
1823
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.productUpdate, failOnUserErrors: ctx.failOnUserErrors });
1824
+ (0, import_output.printNode)({ node: result.productUpdate?.product, format: ctx.format, quiet: ctx.quiet });
1825
+ return;
1826
+ }
1827
+ if (verb === "set-price") {
1828
+ const args = (0, import_router.parseStandardArgs)({
1829
+ argv,
1830
+ extraOptions: {
1831
+ "variant-id": { type: "string" },
1832
+ price: { type: "string" },
1833
+ "compare-at-price": { type: "string" },
1834
+ "product-id": { type: "string" }
1835
+ }
1836
+ });
1837
+ const variantId = (0, import_shared.requireId)(args["variant-id"], "ProductVariant", "--variant-id");
1838
+ const price = args.price;
1839
+ if (!price) throw new import_errors.CliError("Missing --price", 2);
1840
+ const compareAtPrice = args["compare-at-price"];
1841
+ const explicitProductId = args["product-id"];
1842
+ let productId;
1843
+ if (explicitProductId) {
1844
+ productId = (0, import_gid.coerceGid)(explicitProductId, "Product");
1845
+ } else {
1846
+ if (ctx.dryRun) {
1847
+ throw new import_errors.CliError(
1848
+ "In --dry-run mode, --product-id is required because resolving a productId from a variantId requires executing a query.",
1849
+ 2
1850
+ );
1851
+ }
1852
+ const resolved = await (0, import_router.runQuery)(ctx, {
1853
+ productVariant: { __args: { id: variantId }, product: { id: true } }
1854
+ });
1855
+ if (resolved === void 0) return;
1856
+ const pid = resolved.productVariant?.product?.id;
1857
+ if (!pid) throw new import_errors.CliError("Could not resolve productId from --variant-id", 2);
1858
+ productId = pid;
1859
+ }
1860
+ const variantSelection = (0, import_select.resolveSelection)({
1861
+ typeName: "ProductVariant",
1862
+ view: ctx.view,
1863
+ baseSelection: getProductVariantSelection(ctx.view),
1864
+ select: args.select,
1865
+ selection: args.selection,
1866
+ include: args.include,
1867
+ ensureId: ctx.quiet,
1868
+ defaultConnectionFirst: ctx.view === "all" ? 50 : 10
1869
+ });
1870
+ const result = await (0, import_router.runMutation)(ctx, {
1871
+ productVariantsBulkUpdate: {
1872
+ __args: {
1873
+ productId,
1874
+ variants: [
1875
+ {
1876
+ id: variantId,
1877
+ price,
1878
+ ...compareAtPrice ? { compareAtPrice } : {}
1879
+ }
1880
+ ]
1881
+ },
1882
+ userErrors: { field: true, message: true },
1883
+ productVariants: variantSelection
1884
+ }
1885
+ });
1886
+ if (result === void 0) return;
1887
+ (0, import_userErrors.maybeFailOnUserErrors)({
1888
+ payload: result.productVariantsBulkUpdate,
1889
+ failOnUserErrors: ctx.failOnUserErrors
1890
+ });
1891
+ const variant = result.productVariantsBulkUpdate?.productVariants?.[0];
1892
+ (0, import_output.printNode)({ node: variant, format: ctx.format, quiet: ctx.quiet });
1893
+ return;
1894
+ }
1895
+ if (verb === "add-tags" || verb === "remove-tags") {
1896
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: { "product-id": { type: "string" } } });
1897
+ const id = requireProductIdForRootVerb(args);
1898
+ const tags = parseTags(args.tags);
1899
+ const mutationField = verb === "add-tags" ? "tagsAdd" : "tagsRemove";
1900
+ const nodeSelection = (0, import_select.resolveSelection)({
1901
+ typeName: "Product",
1902
+ view: ctx.view,
1903
+ baseSelection: getProductSelectionForTags(ctx.view),
1904
+ select: args.select,
1905
+ selection: args.selection,
1906
+ include: args.include,
1907
+ ensureId: ctx.quiet,
1908
+ defaultConnectionFirst: ctx.view === "all" ? 50 : 10
1909
+ });
1910
+ const request = {
1911
+ [mutationField]: {
1912
+ __args: { id, tags },
1913
+ node: { __typename: true, on_Product: nodeSelection },
1914
+ userErrors: { field: true, message: true }
1915
+ }
1916
+ };
1917
+ const result = await (0, import_router.runMutation)(ctx, request);
1918
+ if (result === void 0) return;
1919
+ const payload = result[mutationField];
1920
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload, failOnUserErrors: ctx.failOnUserErrors });
1921
+ (0, import_output.printNode)({ node: payload?.node, format: ctx.format, quiet: ctx.quiet });
1922
+ return;
1923
+ }
1924
+ if (verb === "media add") {
1925
+ const args = (0, import_router.parseStandardArgs)({
1926
+ argv,
1927
+ extraOptions: {
1928
+ "product-id": { type: "string" },
1929
+ url: { type: "string", multiple: true },
1930
+ alt: { type: "string" },
1931
+ "media-type": { type: "string" },
1932
+ "media-content-type": { type: "string" },
1933
+ wait: { type: "boolean" },
1934
+ "poll-interval-ms": { type: "string" },
1935
+ "timeout-ms": { type: "string" }
1936
+ }
1937
+ });
1938
+ const productId = requireProductIdForSubverb(args);
1939
+ const urls = args.url ?? [];
1940
+ if (urls.length === 0) throw new import_errors.CliError("Missing --url (repeatable)", 2);
1941
+ const mediaContentTypeRaw = args["media-content-type"];
1942
+ const mediaTypeRaw = args["media-type"];
1943
+ if (mediaContentTypeRaw && mediaTypeRaw) {
1944
+ const a = mediaContentTypeRaw.trim().toUpperCase();
1945
+ const b = mediaTypeRaw.trim().toUpperCase();
1946
+ if (a && b && a !== b) {
1947
+ throw new import_errors.CliError("Do not pass both --media-content-type and --media-type with different values", 2);
1948
+ }
1949
+ }
1950
+ const mediaContentType = normalizeMediaContentType(mediaContentTypeRaw ?? mediaTypeRaw);
1951
+ const alt = args.alt;
1952
+ const wait = args.wait === true;
1953
+ const pollIntervalMs = parsePositiveIntFlag({ value: args["poll-interval-ms"], flag: "--poll-interval-ms" }) ?? 1e3;
1954
+ const timeoutMs = parsePositiveIntFlag({ value: args["timeout-ms"], flag: "--timeout-ms" }) ?? 10 * 60 * 1e3;
1955
+ const shouldWait = wait && !ctx.dryRun;
1956
+ const beforeIds = shouldWait ? await getTopProductMediaIds({ ctx, productId }) : [];
1957
+ const media = urls.map((url) => ({
1958
+ originalSource: url,
1959
+ mediaContentType,
1960
+ ...alt ? { alt } : {}
1961
+ }));
1962
+ const viewForSelection = ctx.view === "all" ? "full" : ctx.view;
1963
+ const nodeSelection = (0, import_select.resolveSelection)({
1964
+ typeName: "Media",
1965
+ view: viewForSelection,
1966
+ baseSelection: getProductMediaSelection(viewForSelection),
1967
+ select: args.select,
1968
+ selection: args.selection,
1969
+ include: args.include,
1970
+ ensureId: ctx.quiet,
1971
+ defaultConnectionFirst: 10
1972
+ });
1973
+ const result = await (0, import_router.runMutation)(ctx, {
1974
+ productUpdate: {
1975
+ __args: { product: { id: productId }, media },
1976
+ product: {
1977
+ id: true,
1978
+ media: {
1979
+ __args: { last: media.length, sortKey: "POSITION" },
1980
+ nodes: nodeSelection
1981
+ }
1982
+ },
1983
+ userErrors: { field: true, message: true }
1984
+ }
1985
+ });
1986
+ if (result === void 0) return;
1987
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.productUpdate, failOnUserErrors: ctx.failOnUserErrors });
1988
+ if (!shouldWait) {
1989
+ const connection = result.productUpdate?.product?.media ?? { nodes: [], pageInfo: void 0 };
1990
+ (0, import_output.printConnection)({ connection, format: ctx.format, quiet: ctx.quiet });
1991
+ return;
1992
+ }
1993
+ const afterIds = await getTopProductMediaIds({ ctx, productId });
1994
+ const before = new Set(beforeIds);
1995
+ const createdIds = afterIds.filter((mid) => !before.has(mid)).slice(0, urls.length);
1996
+ if (createdIds.length !== urls.length) {
1997
+ throw new import_errors.CliError(
1998
+ `Unable to determine created media IDs for waiting (expected ${urls.length}, got ${createdIds.length}).`,
1999
+ 2
2000
+ );
2001
+ }
2002
+ const final = await (0, import_waitForReady.waitForFilesReadyOrFailed)({ ctx, ids: createdIds, pollIntervalMs, timeoutMs });
2003
+ if (ctx.quiet) {
2004
+ for (const mid of createdIds) console.log(mid);
2005
+ } else {
2006
+ (0, import_output.printConnection)({
2007
+ connection: { nodes: final.nodes, pageInfo: void 0 },
2008
+ format: ctx.format,
2009
+ quiet: false
2010
+ });
2011
+ }
2012
+ if (final.failedIds.length > 0) {
2013
+ throw new import_errors.CliError(`One or more media files failed processing: ${final.failedIds.join(", ")}`, 2);
2014
+ }
2015
+ return;
2016
+ }
2017
+ if (verb === "media upload") {
2018
+ const args = (0, import_router.parseStandardArgs)({
2019
+ argv,
2020
+ extraOptions: {
2021
+ "product-id": { type: "string" },
2022
+ file: { type: "string", multiple: true },
2023
+ filename: { type: "string" },
2024
+ alt: { type: "string" },
2025
+ "content-type": { type: "string" },
2026
+ "mime-type": { type: "string" },
2027
+ "media-type": { type: "string" },
2028
+ "media-content-type": { type: "string" },
2029
+ wait: { type: "boolean" },
2030
+ "poll-interval-ms": { type: "string" },
2031
+ "timeout-ms": { type: "string" }
2032
+ }
2033
+ });
2034
+ const id = requireProductIdForSubverb(args);
2035
+ const filePaths = args.file ?? [];
2036
+ if (filePaths.length === 0) throw new import_errors.CliError("Missing --file (repeatable)", 2);
2037
+ const usesStdin = filePaths.includes("-");
2038
+ if (usesStdin && filePaths.length !== 1) {
2039
+ throw new import_errors.CliError("When using --file -, provide exactly one --file", 2);
2040
+ }
2041
+ let cleanupStdin;
2042
+ try {
2043
+ let effectiveFilePaths = filePaths;
2044
+ if (usesStdin) {
2045
+ const stdinFile = await (0, import_stdinFile.writeStdinToTempFile)({ filename: args.filename ?? "" });
2046
+ cleanupStdin = stdinFile.cleanup;
2047
+ effectiveFilePaths = [stdinFile.filePath];
2048
+ }
2049
+ const mediaContentTypeRaw = args["media-content-type"];
2050
+ const mediaTypeRaw = args["media-type"];
2051
+ if (mediaContentTypeRaw && mediaTypeRaw) {
2052
+ const a = mediaContentTypeRaw.trim().toUpperCase();
2053
+ const b = mediaTypeRaw.trim().toUpperCase();
2054
+ if (a && b && a !== b) {
2055
+ throw new import_errors.CliError("Do not pass both --media-content-type and --media-type with different values", 2);
2056
+ }
2057
+ }
2058
+ const forcedMediaType = mediaContentTypeRaw ?? mediaTypeRaw;
2059
+ const forced = forcedMediaType ? normalizeMediaContentType(forcedMediaType) : void 0;
2060
+ const resourceOverride = forced ? mediaTypeToStagedResource(forced) : void 0;
2061
+ const mimeTypeRaw = args["mime-type"];
2062
+ const contentTypeRaw = args["content-type"];
2063
+ if (mimeTypeRaw && contentTypeRaw) {
2064
+ const a = mimeTypeRaw.trim();
2065
+ const b = contentTypeRaw.trim();
2066
+ if (a && b && a !== b) {
2067
+ throw new import_errors.CliError("Do not pass both --mime-type and --content-type with different values", 2);
2068
+ }
2069
+ }
2070
+ const mimeType = mimeTypeRaw ?? contentTypeRaw;
2071
+ const wait = args.wait === true;
2072
+ const pollIntervalMs = parsePositiveIntFlag({ value: args["poll-interval-ms"], flag: "--poll-interval-ms" }) ?? 1e3;
2073
+ const timeoutMs = parsePositiveIntFlag({ value: args["timeout-ms"], flag: "--timeout-ms" }) ?? 10 * 60 * 1e3;
2074
+ const shouldWait = wait && !ctx.dryRun;
2075
+ const beforeIds = shouldWait ? await getTopProductMediaIds({ ctx, productId: id }) : [];
2076
+ const localFiles = await (0, import_stagedUploads.buildLocalFilesForStagedUpload)({
2077
+ filePaths: effectiveFilePaths,
2078
+ mimeType,
2079
+ resource: resourceOverride
2080
+ });
2081
+ const targets = await (0, import_stagedUploads.stagedUploadLocalFiles)(ctx, localFiles);
2082
+ if (targets === void 0) return;
2083
+ const alt = args.alt;
2084
+ const media = targets.map((t, i) => {
2085
+ const local = localFiles[i];
2086
+ if (!t.resourceUrl) throw new import_errors.CliError(`Missing staged target resourceUrl for ${local.filename}`, 2);
2087
+ return {
2088
+ originalSource: t.resourceUrl,
2089
+ mediaContentType: forced ?? stagedResourceToMediaType(local.resource),
2090
+ ...alt ? { alt } : {}
2091
+ };
2092
+ });
2093
+ const viewForSelection = ctx.view === "all" ? "full" : ctx.view;
2094
+ const nodeSelection = (0, import_select.resolveSelection)({
2095
+ typeName: "Media",
2096
+ view: viewForSelection,
2097
+ baseSelection: getProductMediaSelection(viewForSelection),
2098
+ select: args.select,
2099
+ selection: args.selection,
2100
+ include: args.include,
2101
+ ensureId: ctx.quiet,
2102
+ defaultConnectionFirst: 10
2103
+ });
2104
+ const result = await (0, import_router.runMutation)(ctx, {
2105
+ productUpdate: {
2106
+ __args: { product: { id }, media },
2107
+ product: {
2108
+ id: true,
2109
+ media: {
2110
+ __args: { last: media.length, sortKey: "POSITION" },
2111
+ nodes: nodeSelection
2112
+ }
2113
+ },
2114
+ userErrors: { field: true, message: true }
2115
+ }
2116
+ });
2117
+ if (result === void 0) return;
2118
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.productUpdate, failOnUserErrors: ctx.failOnUserErrors });
2119
+ const connection = result.productUpdate?.product?.media ?? { nodes: [], pageInfo: void 0 };
2120
+ if (!shouldWait) {
2121
+ (0, import_output.printConnection)({ connection, format: ctx.format, quiet: ctx.quiet });
2122
+ return;
2123
+ }
2124
+ const afterIds = await getTopProductMediaIds({ ctx, productId: id });
2125
+ const before = new Set(beforeIds);
2126
+ const expectedCount = localFiles.length;
2127
+ const createdIds = afterIds.filter((mid) => !before.has(mid)).slice(0, expectedCount);
2128
+ if (createdIds.length !== expectedCount) {
2129
+ throw new import_errors.CliError(
2130
+ `Unable to determine created media IDs for waiting (expected ${expectedCount}, got ${createdIds.length}).`,
2131
+ 2
2132
+ );
2133
+ }
2134
+ const final = await (0, import_waitForReady.waitForFilesReadyOrFailed)({ ctx, ids: createdIds, pollIntervalMs, timeoutMs });
2135
+ if (ctx.quiet) {
2136
+ for (const mid of createdIds) console.log(mid);
2137
+ } else {
2138
+ (0, import_output.printConnection)({
2139
+ connection: { nodes: final.nodes, pageInfo: void 0 },
2140
+ format: ctx.format,
2141
+ quiet: false
2142
+ });
2143
+ }
2144
+ if (final.failedIds.length > 0) {
2145
+ throw new import_errors.CliError(`One or more media files failed processing: ${final.failedIds.join(", ")}`, 2);
2146
+ }
2147
+ return;
2148
+ } finally {
2149
+ if (cleanupStdin) await cleanupStdin();
2150
+ }
2151
+ }
2152
+ if (verb === "media list") {
2153
+ const args = (0, import_router.parseStandardArgs)({ argv, extraOptions: { "product-id": { type: "string" } } });
2154
+ const id = requireProductIdForSubverb(args);
2155
+ const first = (0, import_shared.parseFirst)(args.first);
2156
+ const after = args.after;
2157
+ const result = await (0, import_router.runQuery)(ctx, {
2158
+ product: {
2159
+ __args: { id },
2160
+ media: {
2161
+ __args: { first, after },
2162
+ pageInfo: { hasNextPage: true, endCursor: true },
2163
+ nodes: productMediaSelection
2164
+ }
2165
+ }
2166
+ });
2167
+ if (result === void 0) return;
2168
+ const connection = result.product?.media ?? { nodes: [], pageInfo: void 0 };
2169
+ (0, import_output.printConnection)({
2170
+ connection,
2171
+ format: ctx.format,
2172
+ quiet: ctx.quiet,
2173
+ nextPageArgs: {
2174
+ base: "shop products media list",
2175
+ first,
2176
+ extraFlags: [{ flag: "--product-id", value: id }]
2177
+ }
2178
+ });
2179
+ return;
2180
+ }
2181
+ if (verb === "media remove") {
2182
+ const args = (0, import_router.parseStandardArgs)({
2183
+ argv,
2184
+ extraOptions: {
2185
+ "product-id": { type: "string" },
2186
+ "media-id": { type: "string", multiple: true }
2187
+ }
2188
+ });
2189
+ const productId = requireProductIdForSubverb(args);
2190
+ const mediaIds = args["media-id"] ?? [];
2191
+ if (mediaIds.length === 0) throw new import_errors.CliError("Missing --media-id (repeatable)", 2);
2192
+ const files = mediaIds.map((id) => ({
2193
+ id: normalizeMediaId(id),
2194
+ referencesToRemove: [productId]
2195
+ }));
2196
+ const result = await (0, import_router.runMutation)(ctx, {
2197
+ fileUpdate: {
2198
+ __args: { files },
2199
+ files: { id: true, alt: true, fileStatus: true, updatedAt: true },
2200
+ userErrors: { field: true, message: true }
2201
+ }
2202
+ });
2203
+ if (result === void 0) return;
2204
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.fileUpdate, failOnUserErrors: ctx.failOnUserErrors });
2205
+ const removedMediaIds = (result.fileUpdate?.files ?? []).map((f) => typeof f?.id === "string" ? f.id : void 0).filter((id) => typeof id === "string" && id.trim() !== "");
2206
+ if (ctx.quiet) return (0, import_output.printIds)(removedMediaIds);
2207
+ (0, import_output.printJson)(
2208
+ {
2209
+ productId,
2210
+ removedMediaIds
2211
+ },
2212
+ ctx.format !== "raw"
2213
+ );
2214
+ return;
2215
+ }
2216
+ if (verb === "media update") {
2217
+ const args = (0, import_router.parseStandardArgs)({
2218
+ argv,
2219
+ extraOptions: {
2220
+ "media-id": { type: "string" },
2221
+ alt: { type: "string" }
2222
+ }
2223
+ });
2224
+ const mediaIdRaw = args["media-id"];
2225
+ if (!mediaIdRaw) throw new import_errors.CliError("Missing --media-id", 2);
2226
+ const alt = args.alt;
2227
+ if (alt === void 0) throw new import_errors.CliError("Missing --alt", 2);
2228
+ const files = [{ id: normalizeMediaId(mediaIdRaw), alt }];
2229
+ const result = await (0, import_router.runMutation)(ctx, {
2230
+ fileUpdate: {
2231
+ __args: { files },
2232
+ files: { id: true, alt: true, fileStatus: true, updatedAt: true },
2233
+ userErrors: { field: true, message: true }
2234
+ }
2235
+ });
2236
+ if (result === void 0) return;
2237
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.fileUpdate, failOnUserErrors: ctx.failOnUserErrors });
2238
+ if (ctx.quiet) return console.log(files[0].id);
2239
+ (0, import_output.printJson)(result.fileUpdate, ctx.format !== "raw");
2240
+ return;
2241
+ }
2242
+ if (verb === "media reorder") {
2243
+ const args = (0, import_router.parseStandardArgs)({
2244
+ argv,
2245
+ extraOptions: {
2246
+ "product-id": { type: "string" },
2247
+ moves: { type: "string" },
2248
+ move: { type: "string", multiple: true }
2249
+ }
2250
+ });
2251
+ const id = requireProductIdForSubverb(args);
2252
+ let moves = [];
2253
+ if (args.moves) {
2254
+ try {
2255
+ const parsed = JSON.parse(args.moves);
2256
+ if (!Array.isArray(parsed)) throw new import_errors.CliError("--moves must be a JSON array", 2);
2257
+ moves = parsed;
2258
+ } catch (err) {
2259
+ throw new import_errors.CliError(`--moves must be valid JSON: ${err.message}`, 2);
2260
+ }
2261
+ } else if (args.move) {
2262
+ const raw = args.move;
2263
+ const parsedMoves = [];
2264
+ for (const item of raw) {
2265
+ const parts = item.split(":");
2266
+ if (parts.length !== 2) throw new import_errors.CliError("--move must be <mediaId>:<newPosition>", 2);
2267
+ const mediaId = parts[0].trim();
2268
+ const pos = Number(parts[1].trim());
2269
+ if (!mediaId) throw new import_errors.CliError("--move mediaId cannot be empty", 2);
2270
+ if (!Number.isFinite(pos) || pos < 0) throw new import_errors.CliError("--move newPosition must be a non-negative number", 2);
2271
+ parsedMoves.push({ id: normalizeMediaId(mediaId), newPosition: Math.floor(pos) });
2272
+ }
2273
+ moves = parsedMoves;
2274
+ }
2275
+ if (moves.length === 0) {
2276
+ throw new import_errors.CliError("Missing moves: pass either --moves <json> or --move <mediaId>:<newPosition> (repeatable)", 2);
2277
+ }
2278
+ const normalizedMoves = moves.map((move, i) => {
2279
+ const id2 = move?.id;
2280
+ const newPosition = move?.newPosition;
2281
+ if (typeof id2 !== "string" || !id2.trim()) {
2282
+ throw new import_errors.CliError(`moves[${i}].id is required`, 2);
2283
+ }
2284
+ const pos = Number(newPosition);
2285
+ if (!Number.isFinite(pos) || pos < 0) {
2286
+ throw new import_errors.CliError(`moves[${i}].newPosition must be a non-negative number`, 2);
2287
+ }
2288
+ return { id: normalizeMediaId(id2), newPosition: Math.floor(pos) };
2289
+ });
2290
+ const result = await (0, import_router.runMutation)(ctx, {
2291
+ productReorderMedia: {
2292
+ __args: { id, moves: normalizedMoves },
2293
+ job: { id: true, done: true },
2294
+ userErrors: { field: true, message: true }
2295
+ }
2296
+ });
2297
+ if (result === void 0) return;
2298
+ (0, import_userErrors.maybeFailOnUserErrors)({ payload: result.productReorderMedia, failOnUserErrors: ctx.failOnUserErrors });
2299
+ if (ctx.quiet) return console.log(result.productReorderMedia?.job?.id ?? "");
2300
+ (0, import_output.printJson)(result.productReorderMedia, ctx.format !== "raw");
2301
+ return;
2302
+ }
2303
+ throw new import_errors.CliError(`Unknown verb for products: ${verb}`, 2);
2304
+ };
2305
+ // Annotate the CommonJS export names for ESM import in node:
2306
+ 0 && (module.exports = {
2307
+ runProducts
2308
+ });
2309
+ //# sourceMappingURL=products.js.map