@wix/agent-skills 1.15.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (355) hide show
  1. package/README.md +5 -1
  2. package/package.json +1 -1
  3. package/skills/wix-app/SKILL.md +4 -1
  4. package/skills/wix-app/references/APP_TOOLS.md +134 -0
  5. package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +1 -1
  6. package/skills/wix-app/references/DASHBOARD_PAGE.md +0 -10
  7. package/skills/wix-app/references/DATA_COLLECTION.md +6 -4
  8. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +28 -7
  9. package/skills/wix-app/references/SERVICE_PLUGIN.md +12 -10
  10. package/skills/wix-app/references/STORES_VERSIONING.md +9 -211
  11. package/skills/wix-app/references/app-tools/TOOLS.md +75 -0
  12. package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +5 -0
  13. package/skills/wix-app/references/dashboard-page/DASHBOARD_API.md +2 -2
  14. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW-REFERENCE.md +172 -0
  15. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW.md +138 -0
  16. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +172 -0
  17. package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +29 -0
  18. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +1 -1
  19. package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +57 -0
  20. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +33 -2
  21. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +5 -3
  22. package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +18 -1
  23. package/skills/wix-app/references/editor-react-component/PARTS.md +15 -2
  24. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +4 -3
  25. package/skills/wix-app/references/service-plugin/BOOKINGS-STAFF-SORTING.md +13 -9
  26. package/skills/wix-app/references/service-plugin/DISCOUNT-TRIGGERS.md +4 -0
  27. package/skills/wix-app/references/service-plugin/GIFT-CARDS.md +4 -0
  28. package/skills/wix-app/references/service-plugin/PAYMENT-SETTINGS.md +3 -1
  29. package/skills/wix-app/references/service-plugin/SHIPPING-RATES.md +4 -0
  30. package/skills/wix-app/references/service-plugin/TOOLS_PROVIDER.md +54 -0
  31. package/skills/wix-app/references/stores/CATEGORIES.md +22 -0
  32. package/skills/wix-app/references/stores/GET_PRODUCT.md +99 -0
  33. package/skills/wix-app/references/stores/INVENTORY.md +37 -0
  34. package/skills/wix-app/references/stores/QUERY.md +119 -0
  35. package/skills/wix-app/references/stores/WRITE.md +55 -0
  36. package/skills/wix-docs/SKILL.md +35 -3
  37. package/skills/wix-headless/SKILL.md +9 -2
  38. package/skills/wix-headless/entry/bootstrap.mjs +2 -2
  39. package/skills/wix-headless/entry/skill.md +0 -2
  40. package/skills/wix-headless/references/CAPABILITIES.md +6 -4
  41. package/skills/wix-headless/references/CONTENT.md +36 -0
  42. package/skills/wix-headless/references/DESIGN.md +54 -0
  43. package/skills/wix-headless/references/DISCOVERY.md +25 -1
  44. package/skills/wix-headless/references/FEEDBACK.md +16 -5
  45. package/skills/wix-headless/references/IMAGE_GENERATION.md +10 -0
  46. package/skills/wix-headless/references/SDK_HANDOFF.md +2 -0
  47. package/skills/wix-headless/references/SEED.md +3 -1
  48. package/skills/wix-headless/references/SETUP.md +1 -1
  49. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +3 -2
  50. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-reservations.md +42 -2
  51. package/skills/wix-headless/references/inline-recipes/setup-bookings.md +5 -1
  52. package/skills/wix-headless/references/inline-recipes/setup-forms.md +1 -1
  53. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +33 -8
  54. package/skills/wix-headless/references/inline-recipes/setup-portfolio.md +3 -1
  55. package/skills/wix-headless/references/inline-recipes/setup-restaurant-experiences.md +73 -0
  56. package/skills/wix-headless/references/inline-recipes/setup-restaurant-orders.md +38 -2
  57. package/skills/wix-headless/references/inline-recipes/setup-restaurant-reservations.md +20 -1
  58. package/skills/wix-headless/references/inline-recipes/setup-restaurants.md +1 -1
  59. package/skills/wix-headless/references/managed/CONNECT.md +2 -2
  60. package/skills/wix-headless/references/managed/CREATE.md +15 -1
  61. package/skills/wix-headless/references/managed/DEPLOYMENT.md +47 -0
  62. package/skills/wix-headless/references/self-managed/DEPLOYMENT.md +8 -0
  63. package/skills/wix-headless/references/stripe/DEPLOYMENT.md +8 -0
  64. package/skills/wix-manage/SKILL.md +131 -12
  65. package/skills/wix-manage/references/analytics/analytics-dashboard-navigation.md +41 -0
  66. package/skills/wix-manage/references/analytics/query-site-analytics.md +66 -9
  67. package/skills/wix-manage/references/app-installation/app-installation-dashboard-navigation.md +28 -0
  68. package/skills/wix-manage/references/app-installation/install-wix-apps.md +3 -0
  69. package/skills/wix-manage/references/blog/blog-dashboard-navigation.md +56 -0
  70. package/skills/wix-manage/references/blog/how-to-create-blog-posts.md +31 -6
  71. package/skills/wix-manage/references/bookings/booking-service-policy-setup.md +3 -1
  72. package/skills/wix-manage/references/bookings/bookings-dashboard-navigation.md +63 -0
  73. package/skills/wix-manage/references/bookings/create-booking-service-from-prompt.md +6 -5
  74. package/skills/wix-manage/references/bookings/create-course-service.md +30 -5
  75. package/skills/wix-manage/references/bookings/diagnose-availability-issues.md +85 -42
  76. package/skills/wix-manage/references/cms/cms-dashboard-navigation.md +44 -0
  77. package/skills/wix-manage/references/cms/cms-data-items-crud.md +31 -3
  78. package/skills/wix-manage/references/cms/cms-publishing-flow.md +287 -0
  79. package/skills/wix-manage/references/cms/cms-schema-management.md +33 -1
  80. package/skills/wix-manage/references/contacts/contacts-dashboard-navigation.md +46 -0
  81. package/skills/wix-manage/references/contacts/create-a-contact.md +82 -0
  82. package/skills/wix-manage/references/contacts/update-a-contact.md +119 -0
  83. package/skills/wix-manage/references/dashboard-navigation/dashboard-navigation.md +82 -0
  84. package/skills/wix-manage/references/dashboard-navigation/routes.json +1733 -0
  85. package/skills/wix-manage/references/domains/domains-dashboard-navigation.md +32 -0
  86. package/skills/wix-manage/references/ecommerce/ecom-pricing.md +4 -4
  87. package/skills/wix-manage/references/ecommerce/ecom-shipping.md +1 -1
  88. package/skills/wix-manage/references/ecommerce/gift-cards/ecom-gift-cards-goal-sell-gift-cards.md +338 -0
  89. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-create-discount-rule.md +42 -78
  90. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-bundle-and-save.md +1 -1
  91. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-stock-mover.md +1 -1
  92. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-upsell-boost.md +1 -1
  93. package/skills/wix-manage/references/ecommerce/recommend-ecommerce-strategy.md +90 -92
  94. package/skills/wix-manage/references/events/create-wix-event.md +176 -0
  95. package/skills/wix-manage/references/events/manage-wix-events.md +174 -0
  96. package/skills/wix-manage/references/forms/forms-dashboard-navigation.md +44 -0
  97. package/skills/wix-manage/references/get-paid/get-paid-dashboard-navigation.md +52 -0
  98. package/skills/wix-manage/references/get-paid/how-to-setup-wix-payments.md +30 -7
  99. package/skills/wix-manage/references/google-ads/billing-and-payment.md +80 -0
  100. package/skills/wix-manage/references/google-ads/create-performance-max-campaign.md +212 -0
  101. package/skills/wix-manage/references/google-ads/get-campaign-suggestions.md +110 -0
  102. package/skills/wix-manage/references/google-ads/google-ads-dashboard-navigation.md +25 -0
  103. package/skills/wix-manage/references/google-ads/install-and-create-account.md +155 -0
  104. package/skills/wix-manage/references/google-ads/manage-campaign-lifecycle.md +63 -0
  105. package/skills/wix-manage/references/google-ads/query-campaign-analytics.md +155 -0
  106. package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +225 -144
  107. package/skills/wix-manage/references/marketing/generate-and-publish-marketing-plan.md +19 -10
  108. package/skills/wix-manage/references/marketing/marketing-dashboard-navigation.md +52 -0
  109. package/skills/wix-manage/references/pricing-plans/create-and-update-pricing-plans.md +99 -1
  110. package/skills/wix-manage/references/pricing-plans/pricing-plans-dashboard-navigation.md +45 -0
  111. package/skills/wix-manage/references/restaurants/restaurants-dashboard-navigation.md +68 -0
  112. package/skills/wix-manage/references/restaurants/wix-restaurants-setup.md +94 -125
  113. package/skills/wix-manage/references/site-properties/change-payment-currency-site-properties.md +48 -9
  114. package/skills/wix-manage/references/site-properties/site-properties-dashboard-navigation.md +31 -0
  115. package/skills/wix-manage/references/sites/create-headless-site.md +52 -0
  116. package/skills/wix-manage/references/sites/create-site-from-template.md +2 -25
  117. package/skills/wix-manage/references/sites/site-import.md +243 -0
  118. package/skills/wix-manage/references/sites/sites-dashboard-navigation.md +29 -0
  119. package/skills/wix-manage/references/stores/add-store-pages-to-site.md +17 -1
  120. package/skills/wix-manage/references/stores/create-product-from-image.md +8 -6
  121. package/skills/wix-manage/references/stores/create-product-with-options-catalog-v3.md +16 -10
  122. package/skills/wix-manage/references/stores/find-products-query-and-search-catalog-v3.md +26 -8
  123. package/skills/wix-manage/references/stores/stores-dashboard-navigation.md +65 -0
  124. package/skills/wix-manage/references/stores/update-product-with-options.md +39 -7
  125. package/skills/wix-replatform/.publish-manifest.json +8 -0
  126. package/skills/wix-replatform/SKILL.md +693 -0
  127. package/skills/wix-replatform/lib/artifact-freshness.js +215 -0
  128. package/skills/wix-replatform/lib/completion-report.js +200 -0
  129. package/skills/wix-replatform/lib/config-env.js +59 -0
  130. package/skills/wix-replatform/lib/execution-manifest.js +185 -0
  131. package/skills/wix-replatform/lib/execution-state.js +173 -0
  132. package/skills/wix-replatform/lib/import-recovery.js +313 -0
  133. package/skills/wix-replatform/lib/local-state.js +642 -0
  134. package/skills/wix-replatform/lib/orchestration-preflight.js +143 -0
  135. package/skills/wix-replatform/lib/orchestration-router.js +122 -0
  136. package/skills/wix-replatform/lib/orchestration-state.js +455 -0
  137. package/skills/wix-replatform/lib/progress-log.js +224 -0
  138. package/skills/wix-replatform/lib/progress-log.sh +140 -0
  139. package/skills/wix-replatform/lib/url-preservation-state.js +391 -0
  140. package/skills/wix-replatform/resources/rp-discovery/SKILL.md +184 -0
  141. package/skills/wix-replatform/resources/rp-execute-import/SKILL.md +529 -0
  142. package/skills/wix-replatform/resources/rp-execute-setup/SKILL.md +316 -0
  143. package/skills/wix-replatform/resources/rp-execute-setup/scripts/mint-token.sh +64 -0
  144. package/skills/wix-replatform/resources/rp-import-codegen/SKILL.md +1114 -0
  145. package/skills/wix-replatform/resources/rp-mapper/SKILL.md +430 -0
  146. package/skills/wix-replatform/resources/rp-mapper/lib/mapping-resolve.js +217 -0
  147. package/skills/wix-replatform/resources/rp-mapper/scripts/resolve-mapping.js +148 -0
  148. package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +378 -0
  149. package/skills/wix-replatform/resources/rp-setup-discovery/SKILL.md +183 -0
  150. package/skills/wix-replatform/resources/rp-source-csv/SKILL.md +478 -0
  151. package/skills/wix-replatform/resources/rp-source-csv/lib/canonical-record.js +136 -0
  152. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fileset.js +0 -0
  153. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fingerprint.js +310 -0
  154. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-layout.js +1081 -0
  155. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-parse.js +618 -0
  156. package/skills/wix-replatform/resources/rp-source-csv/scripts/csv-discovery.js +949 -0
  157. package/skills/wix-replatform/resources/rp-source-csv/source-schema.example.json +196 -0
  158. package/skills/wix-replatform/resources/rp-source-csv/vendors/bigcommerce.json +66 -0
  159. package/skills/wix-replatform/resources/rp-source-csv/vendors/magento.json +60 -0
  160. package/skills/wix-replatform/resources/rp-source-csv/vendors/shopify.json +95 -0
  161. package/skills/wix-replatform/resources/rp-source-csv/vendors/woocommerce.json +82 -0
  162. package/skills/wix-replatform/resources/rp-source-wordpress/SKILL.md +256 -0
  163. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-http.js +249 -0
  164. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-route-classifier.js +444 -0
  165. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/wp-discovery.js +774 -0
  166. package/skills/wix-replatform/resources/rp-source-wordpress/source-schema.example.json +71 -0
  167. package/skills/wix-replatform/resources/rp-target-wix/SKILL.md +632 -0
  168. package/skills/wix-replatform/resources/rp-target-wix/SPEC-product-reviews-and-blog-authorship.md +330 -0
  169. package/skills/wix-replatform/resources/rp-target-wix/domains/README.md +21 -0
  170. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/domain.json +19 -0
  171. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/category.json +37 -0
  172. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/comment.json +37 -0
  173. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/post.json +39 -0
  174. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/tag.json +35 -0
  175. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/domain.json +14 -0
  176. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/collection.json +35 -0
  177. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/data-item.json +36 -0
  178. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/reference.json +35 -0
  179. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/domain.json +14 -0
  180. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/contact.json +131 -0
  181. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/email-subscription.json +37 -0
  182. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/label.json +37 -0
  183. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/domain.json +21 -0
  184. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-line-item.json +37 -0
  185. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-refund.json +37 -0
  186. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order.json +97 -0
  187. package/skills/wix-replatform/resources/rp-target-wix/domains/index.json +528 -0
  188. package/skills/wix-replatform/resources/rp-target-wix/domains/media/domain.json +14 -0
  189. package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-file.json +38 -0
  190. package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-folder.json +37 -0
  191. package/skills/wix-replatform/resources/rp-target-wix/domains/members/domain.json +13 -0
  192. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/badge.json +37 -0
  193. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/member.json +53 -0
  194. package/skills/wix-replatform/resources/rp-target-wix/domains/schema.json +84 -0
  195. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/domain.json +25 -0
  196. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/category.json +37 -0
  197. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/coupon.json +37 -0
  198. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/inventory-item.json +38 -0
  199. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product-tag.json +37 -0
  200. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product.json +90 -0
  201. package/skills/wix-replatform/resources/rp-target-wix/lib/audit-summary.js +64 -0
  202. package/skills/wix-replatform/resources/rp-target-wix/lib/contract-ledger.js +141 -0
  203. package/skills/wix-replatform/resources/rp-target-wix/lib/domain-knowledge.js +384 -0
  204. package/skills/wix-replatform/resources/rp-target-wix/lib/ndjson.js +260 -0
  205. package/skills/wix-replatform/resources/rp-target-wix/lib/stores-verification.js +238 -0
  206. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-build.js +237 -0
  207. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-target-spec.js +238 -0
  208. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-writers.js +2219 -0
  209. package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge-validate.js +31 -0
  210. package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge.js +100 -0
  211. package/skills/wix-replatform/resources/rp-target-wix/scripts/verify-stores.js +107 -0
  212. package/skills/wix-replatform/resources/rp-telemetry/SKILL.md +344 -0
  213. package/skills/wix-replatform/resources/rp-telemetry/lib/bi-sink.js +250 -0
  214. package/skills/wix-replatform/resources/rp-telemetry/lib/telemetry-recorder.js +1927 -0
  215. package/skills/wix-replatform/resources/rp-telemetry/scripts/meter-from-audit.js +83 -0
  216. package/skills/wix-replatform/resources/rp-telemetry/scripts/rp-telemetry.js +141 -0
  217. package/skills/wix-replatform/scripts/artifact-freshness.js +76 -0
  218. package/skills/wix-replatform/scripts/execution-manifest-validate.js +43 -0
  219. package/skills/wix-replatform/scripts/execution-state-prepare.js +128 -0
  220. package/skills/wix-replatform/scripts/orchestration-preflight.js +48 -0
  221. package/skills/wix-replatform/scripts/orchestration-route.js +46 -0
  222. package/skills/wix-replatform/scripts/orchestration-state.js +245 -0
  223. package/skills/wix-vibe-headless/SKILL.md +54 -25
  224. package/skills/wix-vibe-headless/install/deploy.cjs +95 -0
  225. package/skills/wix-vibe-headless/install/pin-agents-md.cjs +34 -0
  226. package/skills/wix-vibe-headless/platforms/README.md +26 -0
  227. package/skills/wix-vibe-headless/platforms/base44.md +177 -0
  228. package/skills/wix-vibe-headless/platforms/generic.md +122 -0
  229. package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +230 -119
  230. package/skills/wix-vibe-headless/references/blog/app/components/PostCard.jsx +43 -0
  231. package/skills/wix-vibe-headless/references/blog/app/components/PostChips.jsx +25 -0
  232. package/skills/wix-vibe-headless/references/blog/app/components/PostGrid.jsx +15 -0
  233. package/skills/wix-vibe-headless/references/blog/app/context/TaxonomyContext.jsx +35 -0
  234. package/skills/wix-vibe-headless/references/blog/app/hooks/usePostDetail.js +38 -0
  235. package/skills/wix-vibe-headless/references/blog/app/pages/Blog.jsx +40 -0
  236. package/skills/wix-vibe-headless/references/blog/app/pages/CategoryPage.jsx +54 -0
  237. package/skills/wix-vibe-headless/references/blog/app/pages/PostDetail.jsx +65 -0
  238. package/skills/wix-vibe-headless/references/blog/app/pages/TagPage.jsx +50 -0
  239. package/skills/wix-vibe-headless/references/blog/seed/SEED.md +103 -0
  240. package/skills/wix-vibe-headless/references/blog/seed/seed-blog.js +270 -0
  241. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +260 -145
  242. package/skills/wix-vibe-headless/references/bookings/app/components/BookingForm.jsx +65 -0
  243. package/skills/wix-vibe-headless/references/bookings/app/components/ServiceCard.jsx +47 -0
  244. package/skills/wix-vibe-headless/references/bookings/app/components/ServiceGrid.jsx +13 -0
  245. package/skills/wix-vibe-headless/references/bookings/app/components/SlotPicker.jsx +126 -0
  246. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServiceDetail.js +108 -0
  247. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServices.js +58 -0
  248. package/skills/wix-vibe-headless/references/bookings/app/lib/serviceFacts.js +95 -0
  249. package/skills/wix-vibe-headless/references/bookings/app/pages/ServiceDetail.jsx +94 -0
  250. package/skills/wix-vibe-headless/references/bookings/app/pages/Services.jsx +89 -0
  251. package/skills/wix-vibe-headless/references/bookings/{wix-bookings-checkout.js → app/rest/wix-bookings-checkout.js} +1 -1
  252. package/skills/wix-vibe-headless/references/bookings/{wix-bookings-services.js → app/rest/wix-bookings-services.js} +90 -12
  253. package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +117 -0
  254. package/skills/wix-vibe-headless/references/bookings/seed/seed-bookings.js +333 -0
  255. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +169 -147
  256. package/skills/wix-vibe-headless/references/cms/app/collection.config.js +31 -0
  257. package/skills/wix-vibe-headless/references/cms/app/lib/wixImage.js +18 -0
  258. package/skills/wix-vibe-headless/references/cms/{wix-cms.js → app/rest/wix-cms.js} +47 -2
  259. package/skills/wix-vibe-headless/references/cms/seed/SEED.md +145 -0
  260. package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +228 -131
  261. package/skills/wix-vibe-headless/references/events/app/components/CategoryFilter.jsx +23 -0
  262. package/skills/wix-vibe-headless/references/events/app/components/EventCard.jsx +43 -0
  263. package/skills/wix-vibe-headless/references/events/app/components/EventGrid.jsx +13 -0
  264. package/skills/wix-vibe-headless/references/events/app/components/EventRegistration.jsx +29 -0
  265. package/skills/wix-vibe-headless/references/events/app/components/RsvpForm.jsx +57 -0
  266. package/skills/wix-vibe-headless/references/events/app/components/TicketPicker.jsx +78 -0
  267. package/skills/wix-vibe-headless/references/events/app/hooks/useEventDetail.js +27 -0
  268. package/skills/wix-vibe-headless/references/events/app/hooks/useEventsList.js +54 -0
  269. package/skills/wix-vibe-headless/references/events/app/hooks/useRsvpForm.js +40 -0
  270. package/skills/wix-vibe-headless/references/events/app/hooks/useTicketing.js +81 -0
  271. package/skills/wix-vibe-headless/references/events/app/pages/EventDetail.jsx +48 -0
  272. package/skills/wix-vibe-headless/references/events/app/pages/Events.jsx +36 -0
  273. package/skills/wix-vibe-headless/references/events/{wix-events-browse.js → app/rest/wix-events-browse.js} +3 -2
  274. package/skills/wix-vibe-headless/references/events/seed/SEED.md +107 -0
  275. package/skills/wix-vibe-headless/references/events/seed/seed-events.js +251 -0
  276. package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +276 -188
  277. package/skills/wix-vibe-headless/references/members/app/components/LoginForm.jsx +101 -0
  278. package/skills/wix-vibe-headless/references/members/app/components/MemberMenu.jsx +33 -0
  279. package/skills/wix-vibe-headless/references/members/app/components/RequireAuth.jsx +21 -0
  280. package/skills/wix-vibe-headless/references/members/app/components/SocialButtons.jsx +29 -0
  281. package/skills/wix-vibe-headless/references/members/app/context/MemberContext.jsx +54 -0
  282. package/skills/wix-vibe-headless/references/members/app/hooks/useLoginForm.js +77 -0
  283. package/skills/wix-vibe-headless/references/members/app/pages/Account.jsx +36 -0
  284. package/skills/wix-vibe-headless/references/members/app/pages/Callback.jsx +32 -0
  285. package/skills/wix-vibe-headless/references/members/app/pages/Login.jsx +35 -0
  286. package/skills/wix-vibe-headless/references/members/{wix-members-auth.js → app/rest/wix-members-auth.js} +6 -3
  287. package/skills/wix-vibe-headless/references/members/install/Register.jsx +22 -0
  288. package/skills/wix-vibe-headless/references/members/seed/SEED.md +22 -0
  289. package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +233 -104
  290. package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionCard.jsx +31 -0
  291. package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionGrid.jsx +15 -0
  292. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectCard.jsx +39 -0
  293. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectGrid.jsx +15 -0
  294. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectMedia.jsx +29 -0
  295. package/skills/wix-vibe-headless/references/portfolio/app/hooks/useCollectionProjects.js +35 -0
  296. package/skills/wix-vibe-headless/references/portfolio/app/hooks/usePortfolioGallery.js +27 -0
  297. package/skills/wix-vibe-headless/references/portfolio/app/hooks/useProjectDetail.js +25 -0
  298. package/skills/wix-vibe-headless/references/portfolio/app/pages/CollectionPage.jsx +39 -0
  299. package/skills/wix-vibe-headless/references/portfolio/app/pages/Portfolio.jsx +27 -0
  300. package/skills/wix-vibe-headless/references/portfolio/app/pages/ProjectDetail.jsx +60 -0
  301. package/skills/wix-vibe-headless/references/portfolio/{wix-portfolio.js → app/rest/wix-portfolio.js} +84 -55
  302. package/skills/wix-vibe-headless/references/portfolio/seed/SEED.md +94 -0
  303. package/skills/wix-vibe-headless/references/portfolio/seed/seed-portfolio.js +236 -0
  304. package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +240 -117
  305. package/skills/wix-vibe-headless/references/pricing-plans/app/components/OrderCard.jsx +35 -0
  306. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanCard.jsx +48 -0
  307. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanGrid.jsx +16 -0
  308. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanPrice.jsx +35 -0
  309. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/useMyPlans.js +25 -0
  310. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlanDetail.js +28 -0
  311. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlans.js +30 -0
  312. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/MyPlans.jsx +30 -0
  313. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/PlanDetail.jsx +53 -0
  314. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/Plans.jsx +28 -0
  315. package/skills/wix-vibe-headless/references/pricing-plans/seed/SEED.md +86 -0
  316. package/skills/wix-vibe-headless/references/pricing-plans/seed/seed-pricing-plans.js +251 -0
  317. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +248 -124
  318. package/skills/wix-vibe-headless/references/restaurants/app/components/ItemDialog.jsx +81 -0
  319. package/skills/wix-vibe-headless/references/restaurants/app/components/MenuItemCard.jsx +71 -0
  320. package/skills/wix-vibe-headless/references/restaurants/app/components/MenuList.jsx +43 -0
  321. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartButton.jsx +21 -0
  322. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +60 -0
  323. package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +63 -0
  324. package/skills/wix-vibe-headless/references/restaurants/app/hooks/useItemOrder.js +32 -0
  325. package/skills/wix-vibe-headless/references/restaurants/app/hooks/useReservation.js +73 -0
  326. package/skills/wix-vibe-headless/references/restaurants/app/pages/Menu.jsx +28 -0
  327. package/skills/wix-vibe-headless/references/restaurants/app/pages/Reservations.jsx +102 -0
  328. package/skills/wix-vibe-headless/references/restaurants/seed/SEED.md +180 -0
  329. package/skills/wix-vibe-headless/references/restaurants/seed/seed-restaurants.js +452 -0
  330. package/skills/wix-vibe-headless/references/shared/app/components/WixManageBanner.jsx +56 -0
  331. package/skills/wix-vibe-headless/references/shared/{wix-client.js → app/rest/wix-client.js} +6 -8
  332. package/skills/wix-vibe-headless/references/shared/app/rest/wix-config.js +6 -0
  333. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +263 -148
  334. package/skills/wix-vibe-headless/references/storefront/app/components/CartButton.jsx +20 -0
  335. package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +150 -0
  336. package/skills/wix-vibe-headless/references/storefront/app/components/ProductCard.jsx +167 -0
  337. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGallery.jsx +51 -0
  338. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGrid.jsx +54 -0
  339. package/skills/wix-vibe-headless/references/storefront/app/components/VariantPicker.jsx +119 -0
  340. package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +71 -0
  341. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +109 -0
  342. package/skills/wix-vibe-headless/references/storefront/app/hooks/useShop.js +98 -0
  343. package/skills/wix-vibe-headless/references/storefront/app/lib/storeImage.js +27 -0
  344. package/skills/wix-vibe-headless/references/storefront/app/pages/ProductDetail.jsx +139 -0
  345. package/skills/wix-vibe-headless/references/storefront/app/pages/Shop.jsx +75 -0
  346. package/skills/wix-vibe-headless/references/storefront/{wix-store-cart.js → app/rest/wix-store-cart.js} +1 -1
  347. package/skills/wix-vibe-headless/references/storefront/{wix-store-catalog.js → app/rest/wix-store-catalog.js} +25 -2
  348. package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +111 -0
  349. package/skills/wix-vibe-headless/references/storefront/seed/seed-store.js +299 -0
  350. /package/skills/wix-vibe-headless/references/blog/{wix-blog.js → app/rest/wix-blog.js} +0 -0
  351. /package/skills/wix-vibe-headless/references/events/{wix-events-registration.js → app/rest/wix-events-registration.js} +0 -0
  352. /package/skills/wix-vibe-headless/references/pricing-plans/{wix-pricing-plans.js → app/rest/wix-pricing-plans.js} +0 -0
  353. /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-menu.js → app/rest/wix-restaurants-menu.js} +0 -0
  354. /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-ordering.js → app/rest/wix-restaurants-ordering.js} +0 -0
  355. /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-reservations.js → app/rest/wix-restaurants-reservations.js} +0 -0
@@ -0,0 +1,238 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const w = require('./wix-writers');
6
+
7
+ const DEFAULT_VERIFIED_SUBSCRIPTION_PATHS = [
8
+ 'product.subscriptionDetails',
9
+ 'product.subscriptionDetails.allowOneTimePurchases',
10
+ 'product.subscriptionDetails.subscriptions[]',
11
+ 'product.subscriptionDetails.subscriptions[].id',
12
+ 'product.subscriptionDetails.subscriptions[].title',
13
+ 'product.subscriptionDetails.subscriptions[].description',
14
+ 'product.subscriptionDetails.subscriptions[].frequency',
15
+ 'product.subscriptionDetails.subscriptions[].interval',
16
+ 'product.subscriptionDetails.subscriptions[].autoRenewal',
17
+ ];
18
+
19
+ function timestamp() {
20
+ return new Date().toISOString();
21
+ }
22
+
23
+ function defaultProbeProduct({ marker, name } = {}) {
24
+ const suffix = marker || `rp-probe-${Date.now()}`;
25
+ return {
26
+ name: name || `RePlatform subscription probe ${suffix}`,
27
+ productType: 'PHYSICAL',
28
+ visible: false,
29
+ sku: suffix,
30
+ price: { actualPrice: { amount: '1.00' } },
31
+ subscriptionDetails: {
32
+ allowOneTimePurchases: true,
33
+ subscriptions: [{
34
+ title: 'Monthly delivery',
35
+ description: 'Ships every month',
36
+ frequency: 'MONTH',
37
+ interval: 1,
38
+ autoRenewal: true,
39
+ }],
40
+ },
41
+ };
42
+ }
43
+
44
+ function artifactBase({ command, siteId, endpoint, method }) {
45
+ return {
46
+ schemaVersion: 1,
47
+ command,
48
+ targetSiteIdentifier: siteId || null,
49
+ endpoint,
50
+ method,
51
+ status: 'unknown',
52
+ verifiedPaths: [],
53
+ constraintsDiscovered: [],
54
+ probeRecordId: null,
55
+ cleanup: { attempted: false, status: 'not_applicable' },
56
+ warnings: [],
57
+ recoveryInstructions: [],
58
+ timestamp: timestamp(),
59
+ };
60
+ }
61
+
62
+ function valueAtPath(root, pathExpr) {
63
+ const parts = String(pathExpr).split('.');
64
+ let values = [root];
65
+ for (const part of parts) {
66
+ const arrayPart = part.endsWith('[]') ? part.slice(0, -2) : null;
67
+ const key = arrayPart || part;
68
+ const next = [];
69
+ for (const value of values) {
70
+ if (!value || typeof value !== 'object') continue;
71
+ const child = value[key];
72
+ if (arrayPart) {
73
+ if (Array.isArray(child)) next.push(...child);
74
+ } else {
75
+ next.push(child);
76
+ }
77
+ }
78
+ values = next;
79
+ }
80
+ return values.filter((value) => value !== undefined && value !== null);
81
+ }
82
+
83
+ function verifyPaths(root, paths) {
84
+ return paths.map((pathExpr) => ({
85
+ path: pathExpr,
86
+ present: valueAtPath(root, pathExpr).length > 0,
87
+ }));
88
+ }
89
+
90
+ function queryFilterByMarker({ markerPath, markerValue }) {
91
+ if (!markerPath || markerValue == null) {
92
+ throw new Error('product-by-source-marker requires --marker-path and --marker-value');
93
+ }
94
+ return {
95
+ filter: { [markerPath]: { $eq: markerValue } },
96
+ paging: { limit: 100, offset: 0 },
97
+ };
98
+ }
99
+
100
+ async function writeArtifact(file, result) {
101
+ if (!file) return result;
102
+ fs.mkdirSync(path.dirname(file), { recursive: true });
103
+ fs.writeFileSync(file, `${JSON.stringify(result, null, 2)}\n`);
104
+ return result;
105
+ }
106
+
107
+ async function verifyStoresSubscriptionCreate({ wix, siteId, artifactPath, probeProduct, marker, cleanup = true } = {}) {
108
+ const createRequest = w.buildCreateStoresProductRequest(probeProduct || defaultProbeProduct({ marker }));
109
+ const artifact = artifactBase({
110
+ command: 'stores subscription-create',
111
+ siteId,
112
+ endpoint: createRequest.url,
113
+ method: createRequest.method,
114
+ });
115
+
116
+ let createdProduct;
117
+ try {
118
+ createdProduct = (await wix.send(createRequest)).product;
119
+ artifact.probeRecordId = createdProduct && createdProduct.id;
120
+ if (!artifact.probeRecordId) throw new Error('create response did not include product.id');
121
+
122
+ const getRequest = w.buildGetStoresProductRequest(artifact.probeRecordId);
123
+ artifact.readback = { endpoint: getRequest.url, method: getRequest.method };
124
+ const readProduct = (await wix.send(getRequest)).product;
125
+ artifact.verifiedPaths = verifyPaths({ product: readProduct }, DEFAULT_VERIFIED_SUBSCRIPTION_PATHS);
126
+ artifact.constraintsDiscovered = w.STORES_SUBSCRIPTION_CONTRACT.constraints.map((constraint) => ({ ...constraint }));
127
+ artifact.status = artifact.verifiedPaths.every((entry) => entry.present) ? 'passed' : 'failed';
128
+ if (artifact.status === 'failed') {
129
+ artifact.warnings.push('Subscription readback did not include every expected nested path.');
130
+ }
131
+ } catch (error) {
132
+ artifact.status = 'failed';
133
+ artifact.error = error && error.message ? error.message : String(error);
134
+ } finally {
135
+ if (cleanup && artifact.probeRecordId) {
136
+ artifact.cleanup.attempted = true;
137
+ artifact.cleanup.endpoint = w.buildDeleteStoresProductRequest(artifact.probeRecordId).url;
138
+ artifact.cleanup.method = 'DELETE';
139
+ try {
140
+ await wix.send(w.buildDeleteStoresProductRequest(artifact.probeRecordId));
141
+ artifact.cleanup.status = 'deleted';
142
+ } catch (error) {
143
+ artifact.cleanup.status = 'failed';
144
+ artifact.cleanup.error = error && error.message ? error.message : String(error);
145
+ artifact.warnings.push(`Probe product cleanup failed for ${artifact.probeRecordId}.`);
146
+ artifact.recoveryInstructions.push(
147
+ `Delete probe product ${artifact.probeRecordId} from Wix Stores or run: verify stores delete-probe --product-id ${artifact.probeRecordId}`,
148
+ );
149
+ }
150
+ }
151
+ }
152
+
153
+ return writeArtifact(artifactPath, artifact);
154
+ }
155
+
156
+ async function verifyStoresProductCount({ wix, siteId, artifactPath, query = { paging: { limit: 1, offset: 0 } } } = {}) {
157
+ const request = w.buildQueryStoresProductsRequest(query);
158
+ const artifact = artifactBase({
159
+ command: 'stores product-count',
160
+ siteId,
161
+ endpoint: request.url,
162
+ method: request.method,
163
+ });
164
+ try {
165
+ const response = await wix.send(request);
166
+ const products = response.products || [];
167
+ artifact.count = Number.isInteger(response.totalCount) ? response.totalCount : products.length;
168
+ artifact.status = 'passed';
169
+ } catch (error) {
170
+ artifact.status = 'failed';
171
+ artifact.error = error && error.message ? error.message : String(error);
172
+ }
173
+ return writeArtifact(artifactPath, artifact);
174
+ }
175
+
176
+ async function verifyStoresProductBySourceMarker({ wix, siteId, artifactPath, markerPath, markerValue } = {}) {
177
+ const query = queryFilterByMarker({ markerPath, markerValue });
178
+ const request = w.buildQueryStoresProductsRequest(query);
179
+ const artifact = artifactBase({
180
+ command: 'stores product-by-source-marker',
181
+ siteId,
182
+ endpoint: request.url,
183
+ method: request.method,
184
+ });
185
+ artifact.marker = { path: markerPath, value: markerValue };
186
+ try {
187
+ const response = await wix.send(request);
188
+ artifact.products = (response.products || []).map((product) => ({
189
+ id: product.id,
190
+ name: product.name,
191
+ slug: product.slug,
192
+ revision: product.revision,
193
+ }));
194
+ artifact.count = artifact.products.length;
195
+ artifact.status = 'passed';
196
+ } catch (error) {
197
+ artifact.status = 'failed';
198
+ artifact.error = error && error.message ? error.message : String(error);
199
+ }
200
+ return writeArtifact(artifactPath, artifact);
201
+ }
202
+
203
+ async function verifyStoresDeleteProbe({ wix, siteId, artifactPath, productId } = {}) {
204
+ if (!productId) throw new Error('delete-probe requires --product-id');
205
+ const request = w.buildDeleteStoresProductRequest(productId);
206
+ const artifact = artifactBase({
207
+ command: 'stores delete-probe',
208
+ siteId,
209
+ endpoint: request.url,
210
+ method: request.method,
211
+ });
212
+ artifact.probeRecordId = productId;
213
+ artifact.cleanup = { attempted: true, endpoint: request.url, method: request.method, status: 'unknown' };
214
+ try {
215
+ await wix.send(request);
216
+ artifact.cleanup.status = 'deleted';
217
+ artifact.status = 'passed';
218
+ } catch (error) {
219
+ artifact.cleanup.status = 'failed';
220
+ artifact.status = 'failed';
221
+ artifact.error = error && error.message ? error.message : String(error);
222
+ artifact.warnings.push(`Probe product cleanup failed for ${productId}.`);
223
+ artifact.recoveryInstructions.push(`Delete probe product ${productId} manually in Wix Stores and keep this artifact with the cleanup evidence.`);
224
+ }
225
+ return writeArtifact(artifactPath, artifact);
226
+ }
227
+
228
+ module.exports = {
229
+ DEFAULT_VERIFIED_SUBSCRIPTION_PATHS,
230
+ defaultProbeProduct,
231
+ queryFilterByMarker,
232
+ valueAtPath,
233
+ verifyPaths,
234
+ verifyStoresSubscriptionCreate,
235
+ verifyStoresProductCount,
236
+ verifyStoresProductBySourceMarker,
237
+ verifyStoresDeleteProbe,
238
+ };
@@ -0,0 +1,237 @@
1
+ 'use strict';
2
+
3
+ // rp-target-wix — the DETERMINISTIC canonical -> Wix payload builder.
4
+ //
5
+ // Replaces the per-project, LLM-authored `src/import/transforms/to-wix.js`. Everything in here is
6
+ // vendor-independent: it consumes a CANONICAL record (see wix-target-spec.js CANONICAL_FIELDS) and
7
+ // emits a Wix Stores V3 create body. Nothing about Shopify, Woo, Magento or BigCommerce appears —
8
+ // that asymmetry is exactly why this layer never needed to be regenerated per run.
9
+ //
10
+ // Scalar placement is driven by the spec (payloadPath / wrap / coerce). The four structural
11
+ // builders — variants, options, media, seoData — are spec-*declared* (`via`) but hand-implemented,
12
+ // because a fully declarative encoding of "variants reference option choices BY NAME" would be a
13
+ // worse artifact than the twenty lines it replaces. The spec still owns WHICH canonical fields
14
+ // route through them, so coverage reporting stays complete.
15
+
16
+ const { STORES_V3_TARGET, CATEGORY_TARGET, CANONICAL_FIELDS } = require('./wix-target-spec.js');
17
+
18
+ // --- coercion --------------------------------------------------------------
19
+ // Money must be an OBJECT ({ amount: '20.00' }); a bare number 400s. Decimal STRINGS avoid float
20
+ // drift on amounts that came out of a CSV as text in the first place.
21
+ function money(amount) {
22
+ const n = Number(amount);
23
+ if (!Number.isFinite(n)) throw new Error(`money: "${amount}" is not a finite number`);
24
+ return { amount: n.toFixed(2) };
25
+ }
26
+
27
+ // Wix rejects a slug containing ^!“”$%&'*+,.:;<>=?@\/()[]{}_|` ~#. Vendors mint illegal ones
28
+ // routinely — Shopify turns a decimal size into an underscore (ph-5_5), which 400s the whole
29
+ // bulk batch, so this runs on EVERY slug rather than being a vendor quirk.
30
+ function toWixSlug(raw) {
31
+ const slug = String(raw == null ? '' : raw)
32
+ .toLowerCase()
33
+ .replace(/[^a-z0-9-]+/g, '-')
34
+ .replace(/-{2,}/g, '-')
35
+ .replace(/^-+|-+$/g, '');
36
+ if (!slug) throw new Error(`toWixSlug: "${raw}" sanitizes to an empty slug`);
37
+ return slug;
38
+ }
39
+
40
+ function coerceBoolean(value, fallback) {
41
+ if (value === true || value === false) return value;
42
+ if (value == null || value === '') return fallback;
43
+ const s = String(value).trim().toLowerCase();
44
+ if (['true', '1', 'yes', 'y', 'active', 'published', 'enabled', 'visible'].includes(s)) return true;
45
+ if (['false', '0', 'no', 'n', 'draft', 'archived', 'disabled', 'hidden'].includes(s)) return false;
46
+ return fallback;
47
+ }
48
+
49
+ const COERCE = { slug: toWixSlug, money, boolean: coerceBoolean };
50
+
51
+ function isBlank(value) {
52
+ return value == null || value === '' || (Array.isArray(value) && value.length === 0);
53
+ }
54
+
55
+ // --- structural builders ---------------------------------------------------
56
+ // Option definitions are derived from the variants' own choices, so a value that never occurs
57
+ // cannot produce a phantom choice. Order is first-seen, which preserves the source's ordering.
58
+ function buildOptions(product) {
59
+ const names = product.optionNames || [];
60
+ return names.map((name) => {
61
+ const seen = new Map();
62
+ for (const variant of product.variants || []) {
63
+ for (const choice of variant.choices || []) {
64
+ if (choice.optionName === name && !seen.has(choice.choiceName)) {
65
+ seen.set(choice.choiceName, { choiceType: 'CHOICE_TEXT', name: choice.choiceName });
66
+ }
67
+ }
68
+ }
69
+ return { name, optionRenderType: 'TEXT_CHOICES', choicesSettings: { choices: [...seen.values()] } };
70
+ });
71
+ }
72
+
73
+ // A variant references its option choices BY NAME; the API returns server-assigned choice ids.
74
+ // An empty `choices: []` is the correct encoding of "this product has no real options" — it must
75
+ // produce a single default variant, never a synthetic one-choice option.
76
+ function buildVariants(product, { inStock = true } = {}) {
77
+ return (product.variants || []).map((variant) => {
78
+ const out = {
79
+ visible: coerceBoolean(variant.visible, true),
80
+ choices: (variant.choices || []).map((choice) => ({
81
+ optionChoiceNames: {
82
+ optionName: choice.optionName,
83
+ choiceName: choice.choiceName,
84
+ renderType: 'TEXT_CHOICES',
85
+ },
86
+ })),
87
+ price: buildVariantPrice(variant),
88
+ inventoryItem: { inStock },
89
+ };
90
+ if (!isBlank(variant.sku)) out.sku = String(variant.sku);
91
+ // Weight is expected already converted to the site's unit by the adapter; the canonical field
92
+ // carries a number, not a unit-bearing string.
93
+ if (!isBlank(variant.weight)) out.physicalProperties = { weight: Number(variant.weight) };
94
+ return out;
95
+ });
96
+ }
97
+
98
+ // Implements STORES_V3_TARGET.priceResolution.
99
+ //
100
+ // Two vendor idioms converge here. Shopify ships (price, compareAtPrice); Woo / Magento /
101
+ // BigCommerce ship (regular price, sale price) — which the overlays map to
102
+ // (variant.price, variant.discountedPrice). Wix models `actualPrice` (charged) plus
103
+ // `compareAtPrice` (strike-through), so a sale price has to be PROMOTED to actualPrice and the
104
+ // regular price demoted to the strike-through. Getting this backwards silently overcharges every
105
+ // discounted product, which is why the rule lives in the spec instead of being re-decided per run.
106
+ //
107
+ // TRAP (verified): Wix rejects compareAtPrice <= actualPrice. Vendors write 0.00 — and Woo writes
108
+ // an empty cell — to mean "no discount", so a not-strictly-greater compare-at is DROPPED.
109
+ function buildVariantPrice(variant) {
110
+ const listPrice = Number(variant.price);
111
+ const discounted = variant.discountedPrice;
112
+
113
+ let actual = listPrice;
114
+ let compare = variant.compareAtPrice;
115
+ if (!isBlank(discounted) && Number(discounted) > 0 && Number(discounted) < listPrice) {
116
+ actual = Number(discounted);
117
+ compare = listPrice;
118
+ }
119
+
120
+ const out = { actualPrice: money(actual) };
121
+ if (!isBlank(compare) && Number(compare) > actual) out.compareAtPrice = money(compare);
122
+ return out;
123
+ }
124
+
125
+ // External URLs on media.itemsInfo.items[] are the preferred path: Wix ingests them server-side in
126
+ // the background, avoiding the throttled Media Manager pre-import. The FIRST item becomes the
127
+ // product's main media, so caller-side ordering matters.
128
+ // TRAP: reading these back needs `?fields=MEDIA_ITEMS_INFO`; a plain GET returns only media.main
129
+ // and looks empty even on a successful ingest.
130
+ function buildMedia(product) {
131
+ const items = (product.images || [])
132
+ .filter((image) => image && image.fetchable !== false && !isBlank(image.url))
133
+ .map((image) => ({ url: image.url, ...(isBlank(image.altText) ? {} : { altText: image.altText }) }));
134
+ return items.length ? { itemsInfo: { items } } : null;
135
+ }
136
+
137
+ // Emit a title tag only when it differs from the product name — a duplicate tag says nothing and
138
+ // is pure noise in the payload.
139
+ function buildSeoData(product) {
140
+ const tags = [];
141
+ if (!isBlank(product.seoTitle) && String(product.seoTitle).trim() !== String(product.name || '').trim()) {
142
+ tags.push({ type: 'title', children: String(product.seoTitle) });
143
+ }
144
+ if (!isBlank(product.seoDescription)) {
145
+ tags.push({ type: 'meta', props: { name: 'description', content: String(product.seoDescription) } });
146
+ }
147
+ return tags.length ? { tags } : null;
148
+ }
149
+
150
+ // --- product ---------------------------------------------------------------
151
+ function setPath(target, path, value) {
152
+ const parts = path.split('.');
153
+ let cursor = target;
154
+ for (let i = 0; i < parts.length - 1; i += 1) {
155
+ cursor[parts[i]] = cursor[parts[i]] || {};
156
+ cursor = cursor[parts[i]];
157
+ }
158
+ cursor[parts[parts.length - 1]] = value;
159
+ }
160
+
161
+ // Builds the Stores V3 create body from a canonical product record.
162
+ // `options.inStock` exists because availability is frequently the ONLY importable inventory signal
163
+ // (most vendor exports carry no quantity column); sending quantity 0 would mark a whole catalog
164
+ // out of stock, so the caller states the intent explicitly.
165
+ function buildProduct(product, { inStock = true, target = STORES_V3_TARGET } = {}) {
166
+ if (isBlank(product.name)) throw new Error('buildProduct: product.name is required');
167
+ const body = { ...target.constants };
168
+
169
+ // Spec-driven scalars.
170
+ for (const [canonicalPath, fieldSpec] of Object.entries(target.fields)) {
171
+ if (!fieldSpec.payloadPath) continue; // structural: handled below
172
+ const key = canonicalPath.replace(/^product\./, '');
173
+ let value = product[key];
174
+ const def = CANONICAL_FIELDS[canonicalPath] || {};
175
+ if (isBlank(value) && def.default !== undefined) value = def.default;
176
+ if (isBlank(value) && typeof value !== 'boolean') continue;
177
+ if (fieldSpec.coerce && COERCE[fieldSpec.coerce]) value = COERCE[fieldSpec.coerce](value);
178
+ else if (def.kind === 'boolean') value = coerceBoolean(value, def.default);
179
+ // A spec-declared length cap is enforced here rather than truncated: silently shortening a
180
+ // description is exactly the invisible data loss this pipeline exists to avoid, and the caller
181
+ // is the one who can decide between truncating, splitting into an info section, or skipping.
182
+ if (fieldSpec.maxLength && typeof value === 'string' && value.length > fieldSpec.maxLength) {
183
+ throw new Error(
184
+ `buildProduct: "${product.name}" has a ${value.length}-character ${canonicalPath} but Wix caps ${fieldSpec.payloadPath} at ${fieldSpec.maxLength}. Truncate it, move the overflow into an info section, or skip the field — and record the loss in mapping-gaps.json.`,
185
+ );
186
+ }
187
+ setPath(body, fieldSpec.payloadPath, fieldSpec.wrap ? fieldSpec.wrap(value) : value);
188
+ }
189
+
190
+ // Structural builders, declared in the spec via `via`.
191
+ const options = buildOptions(product);
192
+ if (options.length) body.options = options;
193
+ const media = buildMedia(product);
194
+ if (media) body.media = media;
195
+ const seoData = buildSeoData(product);
196
+ if (seoData) body.seoData = seoData;
197
+ body.variantsInfo = { variants: buildVariants(product, { inStock }) };
198
+ if (!body.variantsInfo.variants.length) {
199
+ throw new Error(`buildProduct: "${product.name}" produced no variant; every Wix product needs at least one`);
200
+ }
201
+ return body;
202
+ }
203
+
204
+ // --- category --------------------------------------------------------------
205
+ // Categories are created depth-ascending so a parent id is always resolvable. Dedupe against a
206
+ // live site must key on name + PARENT, never name alone: a real tree repeats a name at different
207
+ // depths (e.g. "Shampoo & Conditioner" under two different parents).
208
+ function buildCategory(category, { categoryIdByPath = new Map(), target = CATEGORY_TARGET } = {}) {
209
+ if (isBlank(category.name)) throw new Error('buildCategory: category.name is required');
210
+ const body = { ...target.constants };
211
+ for (const [canonicalPath, fieldSpec] of Object.entries(target.fields)) {
212
+ if (!fieldSpec.payloadPath) continue;
213
+ const key = canonicalPath.replace(/^category\./, '');
214
+ let value = category[key];
215
+ const def = CANONICAL_FIELDS[canonicalPath] || {};
216
+ if (isBlank(value) && def.default !== undefined) value = def.default;
217
+ if (isBlank(value) && typeof value !== 'boolean') continue;
218
+ if (def.kind === 'boolean') value = coerceBoolean(value, def.default);
219
+ setPath(body, fieldSpec.payloadPath, value);
220
+ }
221
+ const parentId = category.parentPath ? categoryIdByPath.get(category.parentPath) : null;
222
+ if (parentId) body.parentCategory = { id: parentId };
223
+ return body;
224
+ }
225
+
226
+ module.exports = {
227
+ money,
228
+ toWixSlug,
229
+ coerceBoolean,
230
+ buildOptions,
231
+ buildVariants,
232
+ buildVariantPrice,
233
+ buildMedia,
234
+ buildSeoData,
235
+ buildProduct,
236
+ buildCategory,
237
+ };