@wix/agent-skills 1.15.1 → 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 (322) hide show
  1. package/README.md +3 -7
  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 +1 -1
  8. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +28 -9
  9. package/skills/wix-app/references/SERVICE_PLUGIN.md +12 -10
  10. package/skills/wix-app/references/app-tools/TOOLS.md +75 -0
  11. package/skills/wix-app/references/dashboard-page/DASHBOARD_API.md +2 -2
  12. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW-REFERENCE.md +172 -0
  13. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW.md +138 -0
  14. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +23 -2
  15. package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +29 -0
  16. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +1 -1
  17. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +27 -2
  18. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +5 -3
  19. package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +18 -1
  20. package/skills/wix-app/references/editor-react-component/PARTS.md +15 -2
  21. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +2 -3
  22. package/skills/wix-app/references/service-plugin/BOOKINGS-STAFF-SORTING.md +13 -9
  23. package/skills/wix-app/references/service-plugin/DISCOUNT-TRIGGERS.md +4 -0
  24. package/skills/wix-app/references/service-plugin/GIFT-CARDS.md +4 -0
  25. package/skills/wix-app/references/service-plugin/PAYMENT-SETTINGS.md +3 -1
  26. package/skills/wix-app/references/service-plugin/SHIPPING-RATES.md +4 -0
  27. package/skills/wix-app/references/service-plugin/TOOLS_PROVIDER.md +54 -0
  28. package/skills/wix-app/references/stores/QUERY.md +32 -0
  29. package/skills/wix-docs/SKILL.md +35 -3
  30. package/skills/wix-headless/SKILL.md +3 -1
  31. package/skills/wix-headless/references/CONTENT.md +36 -0
  32. package/skills/wix-headless/references/DESIGN.md +54 -0
  33. package/skills/wix-headless/references/DISCOVERY.md +24 -0
  34. package/skills/wix-headless/references/IMAGE_GENERATION.md +10 -0
  35. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +3 -2
  36. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +32 -23
  37. package/skills/wix-headless/references/managed/CONNECT.md +1 -1
  38. package/skills/wix-headless/references/managed/CREATE.md +14 -0
  39. package/skills/wix-headless/references/managed/DEPLOYMENT.md +25 -0
  40. package/skills/wix-manage/SKILL.md +123 -7
  41. package/skills/wix-manage/references/analytics/analytics-dashboard-navigation.md +41 -0
  42. package/skills/wix-manage/references/app-installation/app-installation-dashboard-navigation.md +28 -0
  43. package/skills/wix-manage/references/blog/blog-dashboard-navigation.md +56 -0
  44. package/skills/wix-manage/references/blog/how-to-create-blog-posts.md +31 -6
  45. package/skills/wix-manage/references/bookings/booking-service-policy-setup.md +3 -1
  46. package/skills/wix-manage/references/bookings/bookings-dashboard-navigation.md +63 -0
  47. package/skills/wix-manage/references/bookings/diagnose-availability-issues.md +10 -1
  48. package/skills/wix-manage/references/cms/cms-dashboard-navigation.md +44 -0
  49. package/skills/wix-manage/references/cms/cms-data-items-crud.md +31 -3
  50. package/skills/wix-manage/references/cms/cms-publishing-flow.md +287 -0
  51. package/skills/wix-manage/references/cms/cms-schema-management.md +27 -1
  52. package/skills/wix-manage/references/contacts/contacts-dashboard-navigation.md +46 -0
  53. package/skills/wix-manage/references/contacts/create-a-contact.md +82 -0
  54. package/skills/wix-manage/references/contacts/update-a-contact.md +119 -0
  55. package/skills/wix-manage/references/dashboard-navigation/dashboard-navigation.md +82 -0
  56. package/skills/wix-manage/references/dashboard-navigation/routes.json +1733 -0
  57. package/skills/wix-manage/references/domains/domains-dashboard-navigation.md +32 -0
  58. package/skills/wix-manage/references/ecommerce/ecom-pricing.md +4 -4
  59. package/skills/wix-manage/references/ecommerce/ecom-shipping.md +1 -1
  60. package/skills/wix-manage/references/ecommerce/gift-cards/ecom-gift-cards-goal-sell-gift-cards.md +338 -0
  61. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-create-discount-rule.md +42 -78
  62. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-bundle-and-save.md +1 -1
  63. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-stock-mover.md +1 -1
  64. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-upsell-boost.md +1 -1
  65. package/skills/wix-manage/references/ecommerce/recommend-ecommerce-strategy.md +90 -92
  66. package/skills/wix-manage/references/events/create-wix-event.md +176 -0
  67. package/skills/wix-manage/references/events/manage-wix-events.md +174 -0
  68. package/skills/wix-manage/references/forms/forms-dashboard-navigation.md +44 -0
  69. package/skills/wix-manage/references/get-paid/get-paid-dashboard-navigation.md +52 -0
  70. package/skills/wix-manage/references/google-ads/billing-and-payment.md +80 -0
  71. package/skills/wix-manage/references/google-ads/create-performance-max-campaign.md +212 -0
  72. package/skills/wix-manage/references/google-ads/get-campaign-suggestions.md +110 -0
  73. package/skills/wix-manage/references/google-ads/google-ads-dashboard-navigation.md +25 -0
  74. package/skills/wix-manage/references/google-ads/install-and-create-account.md +155 -0
  75. package/skills/wix-manage/references/google-ads/manage-campaign-lifecycle.md +63 -0
  76. package/skills/wix-manage/references/google-ads/query-campaign-analytics.md +155 -0
  77. package/skills/wix-manage/references/marketing/marketing-dashboard-navigation.md +52 -0
  78. package/skills/wix-manage/references/pricing-plans/create-and-update-pricing-plans.md +99 -1
  79. package/skills/wix-manage/references/pricing-plans/pricing-plans-dashboard-navigation.md +45 -0
  80. package/skills/wix-manage/references/restaurants/restaurants-dashboard-navigation.md +68 -0
  81. package/skills/wix-manage/references/restaurants/wix-restaurants-setup.md +94 -125
  82. package/skills/wix-manage/references/site-properties/change-payment-currency-site-properties.md +48 -9
  83. package/skills/wix-manage/references/site-properties/site-properties-dashboard-navigation.md +31 -0
  84. package/skills/wix-manage/references/sites/create-headless-site.md +52 -0
  85. package/skills/wix-manage/references/sites/create-site-from-template.md +2 -25
  86. package/skills/wix-manage/references/sites/site-import.md +163 -190
  87. package/skills/wix-manage/references/sites/sites-dashboard-navigation.md +29 -0
  88. package/skills/wix-manage/references/stores/add-store-pages-to-site.md +17 -1
  89. package/skills/wix-manage/references/stores/find-products-query-and-search-catalog-v3.md +26 -8
  90. package/skills/wix-manage/references/stores/stores-dashboard-navigation.md +65 -0
  91. package/skills/wix-manage/references/stores/update-product-with-options.md +39 -7
  92. package/skills/wix-replatform/.publish-manifest.json +8 -0
  93. package/skills/wix-replatform/SKILL.md +693 -0
  94. package/skills/wix-replatform/lib/artifact-freshness.js +215 -0
  95. package/skills/wix-replatform/lib/completion-report.js +200 -0
  96. package/skills/wix-replatform/lib/config-env.js +59 -0
  97. package/skills/wix-replatform/lib/execution-manifest.js +185 -0
  98. package/skills/wix-replatform/lib/execution-state.js +173 -0
  99. package/skills/wix-replatform/lib/import-recovery.js +313 -0
  100. package/skills/wix-replatform/lib/local-state.js +642 -0
  101. package/skills/wix-replatform/lib/orchestration-preflight.js +143 -0
  102. package/skills/wix-replatform/lib/orchestration-router.js +122 -0
  103. package/skills/wix-replatform/lib/orchestration-state.js +455 -0
  104. package/skills/wix-replatform/lib/progress-log.js +224 -0
  105. package/skills/wix-replatform/lib/progress-log.sh +140 -0
  106. package/skills/wix-replatform/lib/url-preservation-state.js +391 -0
  107. package/skills/wix-replatform/resources/rp-discovery/SKILL.md +184 -0
  108. package/skills/wix-replatform/resources/rp-execute-import/SKILL.md +529 -0
  109. package/skills/wix-replatform/resources/rp-execute-setup/SKILL.md +316 -0
  110. package/skills/wix-replatform/resources/rp-execute-setup/scripts/mint-token.sh +64 -0
  111. package/skills/wix-replatform/resources/rp-import-codegen/SKILL.md +1114 -0
  112. package/skills/wix-replatform/resources/rp-mapper/SKILL.md +430 -0
  113. package/skills/wix-replatform/resources/rp-mapper/lib/mapping-resolve.js +217 -0
  114. package/skills/wix-replatform/resources/rp-mapper/scripts/resolve-mapping.js +148 -0
  115. package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +378 -0
  116. package/skills/wix-replatform/resources/rp-setup-discovery/SKILL.md +183 -0
  117. package/skills/wix-replatform/resources/rp-source-csv/SKILL.md +478 -0
  118. package/skills/wix-replatform/resources/rp-source-csv/lib/canonical-record.js +136 -0
  119. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fileset.js +0 -0
  120. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fingerprint.js +310 -0
  121. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-layout.js +1081 -0
  122. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-parse.js +618 -0
  123. package/skills/wix-replatform/resources/rp-source-csv/scripts/csv-discovery.js +949 -0
  124. package/skills/wix-replatform/resources/rp-source-csv/source-schema.example.json +196 -0
  125. package/skills/wix-replatform/resources/rp-source-csv/vendors/bigcommerce.json +66 -0
  126. package/skills/wix-replatform/resources/rp-source-csv/vendors/magento.json +60 -0
  127. package/skills/wix-replatform/resources/rp-source-csv/vendors/shopify.json +95 -0
  128. package/skills/wix-replatform/resources/rp-source-csv/vendors/woocommerce.json +82 -0
  129. package/skills/wix-replatform/resources/rp-source-wordpress/SKILL.md +256 -0
  130. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-http.js +249 -0
  131. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-route-classifier.js +444 -0
  132. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/wp-discovery.js +774 -0
  133. package/skills/wix-replatform/resources/rp-source-wordpress/source-schema.example.json +71 -0
  134. package/skills/wix-replatform/resources/rp-target-wix/SKILL.md +632 -0
  135. package/skills/wix-replatform/resources/rp-target-wix/SPEC-product-reviews-and-blog-authorship.md +330 -0
  136. package/skills/wix-replatform/resources/rp-target-wix/domains/README.md +21 -0
  137. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/domain.json +19 -0
  138. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/category.json +37 -0
  139. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/comment.json +37 -0
  140. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/post.json +39 -0
  141. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/tag.json +35 -0
  142. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/domain.json +14 -0
  143. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/collection.json +35 -0
  144. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/data-item.json +36 -0
  145. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/reference.json +35 -0
  146. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/domain.json +14 -0
  147. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/contact.json +131 -0
  148. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/email-subscription.json +37 -0
  149. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/label.json +37 -0
  150. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/domain.json +21 -0
  151. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-line-item.json +37 -0
  152. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-refund.json +37 -0
  153. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order.json +97 -0
  154. package/skills/wix-replatform/resources/rp-target-wix/domains/index.json +528 -0
  155. package/skills/wix-replatform/resources/rp-target-wix/domains/media/domain.json +14 -0
  156. package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-file.json +38 -0
  157. package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-folder.json +37 -0
  158. package/skills/wix-replatform/resources/rp-target-wix/domains/members/domain.json +13 -0
  159. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/badge.json +37 -0
  160. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/member.json +53 -0
  161. package/skills/wix-replatform/resources/rp-target-wix/domains/schema.json +84 -0
  162. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/domain.json +25 -0
  163. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/category.json +37 -0
  164. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/coupon.json +37 -0
  165. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/inventory-item.json +38 -0
  166. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product-tag.json +37 -0
  167. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product.json +90 -0
  168. package/skills/wix-replatform/resources/rp-target-wix/lib/audit-summary.js +64 -0
  169. package/skills/wix-replatform/resources/rp-target-wix/lib/contract-ledger.js +141 -0
  170. package/skills/wix-replatform/resources/rp-target-wix/lib/domain-knowledge.js +384 -0
  171. package/skills/wix-replatform/resources/rp-target-wix/lib/ndjson.js +260 -0
  172. package/skills/wix-replatform/resources/rp-target-wix/lib/stores-verification.js +238 -0
  173. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-build.js +237 -0
  174. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-target-spec.js +238 -0
  175. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-writers.js +2219 -0
  176. package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge-validate.js +31 -0
  177. package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge.js +100 -0
  178. package/skills/wix-replatform/resources/rp-target-wix/scripts/verify-stores.js +107 -0
  179. package/skills/wix-replatform/resources/rp-telemetry/SKILL.md +344 -0
  180. package/skills/wix-replatform/resources/rp-telemetry/lib/bi-sink.js +250 -0
  181. package/skills/wix-replatform/resources/rp-telemetry/lib/telemetry-recorder.js +1927 -0
  182. package/skills/wix-replatform/resources/rp-telemetry/scripts/meter-from-audit.js +83 -0
  183. package/skills/wix-replatform/resources/rp-telemetry/scripts/rp-telemetry.js +141 -0
  184. package/skills/wix-replatform/scripts/artifact-freshness.js +76 -0
  185. package/skills/wix-replatform/scripts/execution-manifest-validate.js +43 -0
  186. package/skills/wix-replatform/scripts/execution-state-prepare.js +128 -0
  187. package/skills/wix-replatform/scripts/orchestration-preflight.js +48 -0
  188. package/skills/wix-replatform/scripts/orchestration-route.js +46 -0
  189. package/skills/wix-replatform/scripts/orchestration-state.js +245 -0
  190. package/skills/wix-vibe-headless/SKILL.md +48 -25
  191. package/skills/wix-vibe-headless/install/deploy.cjs +95 -0
  192. package/skills/wix-vibe-headless/install/pin-agents-md.cjs +34 -0
  193. package/skills/wix-vibe-headless/platforms/README.md +8 -4
  194. package/skills/wix-vibe-headless/platforms/base44.md +133 -98
  195. package/skills/wix-vibe-headless/platforms/generic.md +99 -64
  196. package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +230 -119
  197. package/skills/wix-vibe-headless/references/blog/app/components/PostCard.jsx +43 -0
  198. package/skills/wix-vibe-headless/references/blog/app/components/PostChips.jsx +25 -0
  199. package/skills/wix-vibe-headless/references/blog/app/components/PostGrid.jsx +15 -0
  200. package/skills/wix-vibe-headless/references/blog/app/context/TaxonomyContext.jsx +35 -0
  201. package/skills/wix-vibe-headless/references/blog/app/hooks/usePostDetail.js +38 -0
  202. package/skills/wix-vibe-headless/references/blog/app/pages/Blog.jsx +40 -0
  203. package/skills/wix-vibe-headless/references/blog/app/pages/CategoryPage.jsx +54 -0
  204. package/skills/wix-vibe-headless/references/blog/app/pages/PostDetail.jsx +65 -0
  205. package/skills/wix-vibe-headless/references/blog/app/pages/TagPage.jsx +50 -0
  206. package/skills/wix-vibe-headless/references/blog/seed/SEED.md +103 -0
  207. package/skills/wix-vibe-headless/references/blog/seed/seed-blog.js +270 -0
  208. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +260 -149
  209. package/skills/wix-vibe-headless/references/bookings/app/components/BookingForm.jsx +65 -0
  210. package/skills/wix-vibe-headless/references/bookings/app/components/ServiceCard.jsx +47 -0
  211. package/skills/wix-vibe-headless/references/bookings/app/components/ServiceGrid.jsx +13 -0
  212. package/skills/wix-vibe-headless/references/bookings/app/components/SlotPicker.jsx +126 -0
  213. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServiceDetail.js +108 -0
  214. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServices.js +58 -0
  215. package/skills/wix-vibe-headless/references/bookings/app/lib/serviceFacts.js +95 -0
  216. package/skills/wix-vibe-headless/references/bookings/app/pages/ServiceDetail.jsx +94 -0
  217. package/skills/wix-vibe-headless/references/bookings/app/pages/Services.jsx +89 -0
  218. package/skills/wix-vibe-headless/references/bookings/{wix-bookings-checkout.js → app/rest/wix-bookings-checkout.js} +1 -1
  219. package/skills/wix-vibe-headless/references/bookings/{wix-bookings-services.js → app/rest/wix-bookings-services.js} +87 -11
  220. package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +117 -0
  221. package/skills/wix-vibe-headless/references/bookings/seed/seed-bookings.js +333 -0
  222. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +169 -147
  223. package/skills/wix-vibe-headless/references/cms/app/collection.config.js +31 -0
  224. package/skills/wix-vibe-headless/references/cms/app/lib/wixImage.js +18 -0
  225. package/skills/wix-vibe-headless/references/cms/{wix-cms.js → app/rest/wix-cms.js} +47 -2
  226. package/skills/wix-vibe-headless/references/cms/seed/SEED.md +145 -0
  227. package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +228 -131
  228. package/skills/wix-vibe-headless/references/events/app/components/CategoryFilter.jsx +23 -0
  229. package/skills/wix-vibe-headless/references/events/app/components/EventCard.jsx +43 -0
  230. package/skills/wix-vibe-headless/references/events/app/components/EventGrid.jsx +13 -0
  231. package/skills/wix-vibe-headless/references/events/app/components/EventRegistration.jsx +29 -0
  232. package/skills/wix-vibe-headless/references/events/app/components/RsvpForm.jsx +57 -0
  233. package/skills/wix-vibe-headless/references/events/app/components/TicketPicker.jsx +78 -0
  234. package/skills/wix-vibe-headless/references/events/app/hooks/useEventDetail.js +27 -0
  235. package/skills/wix-vibe-headless/references/events/app/hooks/useEventsList.js +54 -0
  236. package/skills/wix-vibe-headless/references/events/app/hooks/useRsvpForm.js +40 -0
  237. package/skills/wix-vibe-headless/references/events/app/hooks/useTicketing.js +81 -0
  238. package/skills/wix-vibe-headless/references/events/app/pages/EventDetail.jsx +48 -0
  239. package/skills/wix-vibe-headless/references/events/app/pages/Events.jsx +36 -0
  240. package/skills/wix-vibe-headless/references/events/{wix-events-browse.js → app/rest/wix-events-browse.js} +1 -1
  241. package/skills/wix-vibe-headless/references/events/seed/SEED.md +107 -0
  242. package/skills/wix-vibe-headless/references/events/seed/seed-events.js +251 -0
  243. package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +276 -188
  244. package/skills/wix-vibe-headless/references/members/app/components/LoginForm.jsx +101 -0
  245. package/skills/wix-vibe-headless/references/members/app/components/MemberMenu.jsx +33 -0
  246. package/skills/wix-vibe-headless/references/members/app/components/RequireAuth.jsx +21 -0
  247. package/skills/wix-vibe-headless/references/members/app/components/SocialButtons.jsx +29 -0
  248. package/skills/wix-vibe-headless/references/members/app/context/MemberContext.jsx +54 -0
  249. package/skills/wix-vibe-headless/references/members/app/hooks/useLoginForm.js +77 -0
  250. package/skills/wix-vibe-headless/references/members/app/pages/Account.jsx +36 -0
  251. package/skills/wix-vibe-headless/references/members/app/pages/Callback.jsx +32 -0
  252. package/skills/wix-vibe-headless/references/members/app/pages/Login.jsx +35 -0
  253. package/skills/wix-vibe-headless/references/members/{wix-members-auth.js → app/rest/wix-members-auth.js} +6 -3
  254. package/skills/wix-vibe-headless/references/members/install/Register.jsx +22 -0
  255. package/skills/wix-vibe-headless/references/members/seed/SEED.md +22 -0
  256. package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +233 -104
  257. package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionCard.jsx +31 -0
  258. package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionGrid.jsx +15 -0
  259. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectCard.jsx +39 -0
  260. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectGrid.jsx +15 -0
  261. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectMedia.jsx +29 -0
  262. package/skills/wix-vibe-headless/references/portfolio/app/hooks/useCollectionProjects.js +35 -0
  263. package/skills/wix-vibe-headless/references/portfolio/app/hooks/usePortfolioGallery.js +27 -0
  264. package/skills/wix-vibe-headless/references/portfolio/app/hooks/useProjectDetail.js +25 -0
  265. package/skills/wix-vibe-headless/references/portfolio/app/pages/CollectionPage.jsx +39 -0
  266. package/skills/wix-vibe-headless/references/portfolio/app/pages/Portfolio.jsx +27 -0
  267. package/skills/wix-vibe-headless/references/portfolio/app/pages/ProjectDetail.jsx +60 -0
  268. package/skills/wix-vibe-headless/references/portfolio/seed/SEED.md +94 -0
  269. package/skills/wix-vibe-headless/references/portfolio/seed/seed-portfolio.js +236 -0
  270. package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +240 -117
  271. package/skills/wix-vibe-headless/references/pricing-plans/app/components/OrderCard.jsx +35 -0
  272. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanCard.jsx +48 -0
  273. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanGrid.jsx +16 -0
  274. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanPrice.jsx +35 -0
  275. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/useMyPlans.js +25 -0
  276. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlanDetail.js +28 -0
  277. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlans.js +30 -0
  278. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/MyPlans.jsx +30 -0
  279. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/PlanDetail.jsx +53 -0
  280. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/Plans.jsx +28 -0
  281. package/skills/wix-vibe-headless/references/pricing-plans/seed/SEED.md +86 -0
  282. package/skills/wix-vibe-headless/references/pricing-plans/seed/seed-pricing-plans.js +251 -0
  283. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +248 -124
  284. package/skills/wix-vibe-headless/references/restaurants/app/components/ItemDialog.jsx +81 -0
  285. package/skills/wix-vibe-headless/references/restaurants/app/components/MenuItemCard.jsx +71 -0
  286. package/skills/wix-vibe-headless/references/restaurants/app/components/MenuList.jsx +43 -0
  287. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartButton.jsx +21 -0
  288. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +60 -0
  289. package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +63 -0
  290. package/skills/wix-vibe-headless/references/restaurants/app/hooks/useItemOrder.js +32 -0
  291. package/skills/wix-vibe-headless/references/restaurants/app/hooks/useReservation.js +73 -0
  292. package/skills/wix-vibe-headless/references/restaurants/app/pages/Menu.jsx +28 -0
  293. package/skills/wix-vibe-headless/references/restaurants/app/pages/Reservations.jsx +102 -0
  294. package/skills/wix-vibe-headless/references/restaurants/seed/SEED.md +180 -0
  295. package/skills/wix-vibe-headless/references/restaurants/seed/seed-restaurants.js +452 -0
  296. package/skills/wix-vibe-headless/references/shared/app/components/WixManageBanner.jsx +56 -0
  297. package/skills/wix-vibe-headless/references/shared/{wix-client.js → app/rest/wix-client.js} +6 -8
  298. package/skills/wix-vibe-headless/references/shared/app/rest/wix-config.js +6 -0
  299. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +263 -157
  300. package/skills/wix-vibe-headless/references/storefront/app/components/CartButton.jsx +20 -0
  301. package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +150 -0
  302. package/skills/wix-vibe-headless/references/storefront/app/components/ProductCard.jsx +167 -0
  303. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGallery.jsx +51 -0
  304. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGrid.jsx +54 -0
  305. package/skills/wix-vibe-headless/references/storefront/app/components/VariantPicker.jsx +119 -0
  306. package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +71 -0
  307. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +109 -0
  308. package/skills/wix-vibe-headless/references/storefront/app/hooks/useShop.js +98 -0
  309. package/skills/wix-vibe-headless/references/storefront/app/lib/storeImage.js +27 -0
  310. package/skills/wix-vibe-headless/references/storefront/app/pages/ProductDetail.jsx +139 -0
  311. package/skills/wix-vibe-headless/references/storefront/app/pages/Shop.jsx +75 -0
  312. package/skills/wix-vibe-headless/references/storefront/{wix-store-cart.js → app/rest/wix-store-cart.js} +1 -1
  313. package/skills/wix-vibe-headless/references/storefront/{wix-store-catalog.js → app/rest/wix-store-catalog.js} +20 -1
  314. package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +111 -0
  315. package/skills/wix-vibe-headless/references/storefront/seed/seed-store.js +299 -0
  316. /package/skills/wix-vibe-headless/references/blog/{wix-blog.js → app/rest/wix-blog.js} +0 -0
  317. /package/skills/wix-vibe-headless/references/events/{wix-events-registration.js → app/rest/wix-events-registration.js} +0 -0
  318. /package/skills/wix-vibe-headless/references/portfolio/{wix-portfolio.js → app/rest/wix-portfolio.js} +0 -0
  319. /package/skills/wix-vibe-headless/references/pricing-plans/{wix-pricing-plans.js → app/rest/wix-pricing-plans.js} +0 -0
  320. /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-menu.js → app/rest/wix-restaurants-menu.js} +0 -0
  321. /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-ordering.js → app/rest/wix-restaurants-ordering.js} +0 -0
  322. /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-reservations.js → app/rest/wix-restaurants-reservations.js} +0 -0
@@ -0,0 +1,618 @@
1
+ 'use strict';
2
+
3
+ // Shared CSV parse core.
4
+ //
5
+ // This module is the single source of truth for the mechanics a CSV reader must
6
+ // get right: dialect detection, RFC-4180 quoting, line endings, encoding/BOM,
7
+ // the empty-vs-absent decision, and streaming. It is imported by:
8
+ // - scripts/csv-discovery.js (discovery-time sampling), and
9
+ // - the bulk-extract reader generated by rp-import-codegen, which vendors a
10
+ // copy of this file into the migration project so the project stays
11
+ // self-contained.
12
+ // One parse core is what makes the sampler and the importer agree on what a
13
+ // file contains.
14
+ //
15
+ // Keep this file dependency-free (Node built-ins only) so the vendored copy
16
+ // needs no install step.
17
+
18
+ const fs = require('node:fs');
19
+ const fsp = require('node:fs/promises');
20
+ const { StringDecoder } = require('node:string_decoder');
21
+
22
+ const DELIMITER_CANDIDATES = [',', ';', '\t', '|'];
23
+ const DELIMITER_SAMPLE_LINES = 20;
24
+ const DELIMITER_MIN_SCORE = 1.0;
25
+ const DELIMITER_MIN_MARGIN = 1.25;
26
+ const DEFAULT_SAMPLE_BYTES = 256 * 1024;
27
+ const TAIL_SAMPLE_BYTES = 64 * 1024;
28
+
29
+ // How this writer represents an absent value. Detected per file rather than
30
+ // assumed: exporters that quote every field (Excel, Magento) can never produce
31
+ // an unquoted empty, and exporters that quote nothing unnecessary can never
32
+ // produce a quoted empty. Only a file containing BOTH forms is actually
33
+ // distinguishing them.
34
+ const EMPTY_POLICY = {
35
+ PRESENT_IF_QUOTED: 'present-if-quoted',
36
+ ALWAYS_EMPTY: 'always-empty',
37
+ };
38
+
39
+ const ENCODING_ALIASES = {
40
+ utf8: 'utf8',
41
+ 'utf-8': 'utf8',
42
+ ascii: 'ascii',
43
+ latin1: 'latin1',
44
+ 'iso-8859-1': 'latin1',
45
+ 'windows-1252': 'latin1',
46
+ cp1252: 'latin1',
47
+ utf16le: 'utf16le',
48
+ 'utf-16le': 'utf16le',
49
+ };
50
+
51
+ // Parser states. A field is quoted only when the quote opens at field position
52
+ // 0; a bare `"` anywhere else is a literal character.
53
+ const S_FIELD_START = 0;
54
+ const S_IN_FIELD = 1;
55
+ const S_IN_QUOTED = 2;
56
+ const S_QUOTE_IN_QUOTED = 3;
57
+
58
+ function nodeEncodingFor(encoding) {
59
+ const key = String(encoding || 'utf8').toLowerCase();
60
+ const mapped = ENCODING_ALIASES[key];
61
+ if (!mapped) {
62
+ throw new Error(`Unsupported CSV encoding "${encoding}". Set CSV_ENCODING to one of: ${Object.keys(ENCODING_ALIASES).join(', ')}.`);
63
+ }
64
+ return mapped;
65
+ }
66
+
67
+ function stripBom(text) {
68
+ if (typeof text === 'string' && text.charCodeAt(0) === 0xfeff) {
69
+ return { text: text.slice(1), bom: 'utf-8' };
70
+ }
71
+ return { text, bom: null };
72
+ }
73
+
74
+ // Byte-order marks decide the encoding before any decoding happens. UTF-16 is
75
+ // reported as unsupported rather than silently decoded as UTF-8 mojibake;
76
+ // full transcoding is deliberately out of scope (see SKILL.md → Encoding).
77
+ function detectEncoding(buffer) {
78
+ if (!buffer || buffer.length === 0) {
79
+ return { encoding: 'utf8', bom: null, supported: true };
80
+ }
81
+ if (buffer.length >= 3 && buffer[0] === 0xef && buffer[1] === 0xbb && buffer[2] === 0xbf) {
82
+ return { encoding: 'utf8', bom: 'utf-8', supported: true };
83
+ }
84
+ if (buffer.length >= 2 && buffer[0] === 0xff && buffer[1] === 0xfe) {
85
+ return { encoding: 'utf16le', bom: 'utf-16le', supported: false };
86
+ }
87
+ if (buffer.length >= 2 && buffer[0] === 0xfe && buffer[1] === 0xff) {
88
+ return { encoding: 'utf16be', bom: 'utf-16be', supported: false };
89
+ }
90
+ return { encoding: 'utf8', bom: null, supported: true };
91
+ }
92
+
93
+ function detectLineEnding(sampleText) {
94
+ const text = String(sampleText || '');
95
+ const crlf = (text.match(/\r\n/g) || []).length;
96
+ const cr = (text.match(/\r(?!\n)/g) || []).length;
97
+ const lf = (text.match(/(?<!\r)\n/g) || []).length;
98
+ const ranked = [['\r\n', crlf], ['\n', lf], ['\r', cr]].filter(([, count]) => count > 0);
99
+ if (ranked.length === 0) {
100
+ return null;
101
+ }
102
+ if (ranked.length > 1) {
103
+ return 'mixed';
104
+ }
105
+ return ranked[0][0];
106
+ }
107
+
108
+ // The one normalizer. Fingerprint, layout, and fileset all import this rather
109
+ // than rolling their own, so `Body (HTML)`, `body_html`, and `BODY HTML` are
110
+ // the same column everywhere in the adapter.
111
+ function normalizeHeaderName(name) {
112
+ return String(name === undefined || name === null ? '' : name)
113
+ .replace(/^\uFEFF/, '')
114
+ .normalize('NFKC')
115
+ .toLowerCase()
116
+ .replace(/[^a-z0-9]+/g, '');
117
+ }
118
+
119
+ // Chunk-fed RFC-4180 state machine.
120
+ //
121
+ // Returns rows as `{ values: string[], quoted?: boolean[], line }`. Values are
122
+ // ALWAYS strings — never null. Whether an empty string means "absent" is a
123
+ // property of the writer's quoting policy, not of the datum, so that decision
124
+ // is made once per file by detectEmptyPolicy and applied by coerceEmpty.
125
+ function createParser({ delimiter = ',', trackQuoted = false, skipEmptyLines = true } = {}) {
126
+ const delim = String(delimiter);
127
+ let state = S_FIELD_START;
128
+ let field = '';
129
+ let fieldWasQuoted = false;
130
+ let values = [];
131
+ let quotedFlags = [];
132
+ let pendingCR = false;
133
+ let lineNo = 1;
134
+ let rowStartLine = 1;
135
+ let blankLines = 0;
136
+
137
+ function endField() {
138
+ values.push(field);
139
+ if (trackQuoted) {
140
+ quotedFlags.push(fieldWasQuoted);
141
+ }
142
+ field = '';
143
+ fieldWasQuoted = false;
144
+ state = S_FIELD_START;
145
+ }
146
+
147
+ function endRow(rows) {
148
+ endField();
149
+ const isBlank = values.length === 1 && values[0] === '' && !(trackQuoted && quotedFlags[0]);
150
+ if (skipEmptyLines && isBlank) {
151
+ blankLines += 1;
152
+ } else {
153
+ const row = { values, line: rowStartLine };
154
+ if (trackQuoted) {
155
+ row.quoted = quotedFlags;
156
+ }
157
+ rows.push(row);
158
+ }
159
+ values = [];
160
+ quotedFlags = [];
161
+ lineNo += 1;
162
+ rowStartLine = lineNo;
163
+ }
164
+
165
+ function push(text) {
166
+ const rows = [];
167
+ const input = String(text);
168
+ for (let i = 0; i < input.length; i += 1) {
169
+ const ch = input[i];
170
+
171
+ // A lone \r can only be resolved by the next character, which may live in
172
+ // the next chunk — hence the flag rather than a lookahead.
173
+ if (pendingCR) {
174
+ pendingCR = false;
175
+ if (ch === '\n') {
176
+ continue;
177
+ }
178
+ }
179
+
180
+ switch (state) {
181
+ case S_FIELD_START:
182
+ if (ch === '"') {
183
+ state = S_IN_QUOTED;
184
+ fieldWasQuoted = true;
185
+ } else if (ch === delim) {
186
+ endField();
187
+ } else if (ch === '\n') {
188
+ endRow(rows);
189
+ } else if (ch === '\r') {
190
+ endRow(rows);
191
+ pendingCR = true;
192
+ } else {
193
+ field += ch;
194
+ state = S_IN_FIELD;
195
+ }
196
+ break;
197
+
198
+ case S_IN_FIELD:
199
+ if (ch === delim) {
200
+ endField();
201
+ } else if (ch === '\n') {
202
+ endRow(rows);
203
+ } else if (ch === '\r') {
204
+ endRow(rows);
205
+ pendingCR = true;
206
+ } else {
207
+ // A quote inside an unquoted field is a literal character.
208
+ field += ch;
209
+ }
210
+ break;
211
+
212
+ case S_IN_QUOTED:
213
+ if (ch === '"') {
214
+ state = S_QUOTE_IN_QUOTED;
215
+ } else {
216
+ // Newlines inside quotes are data and are preserved verbatim,
217
+ // including the \r of a \r\n pair.
218
+ if (ch === '\n') {
219
+ lineNo += 1;
220
+ }
221
+ field += ch;
222
+ }
223
+ break;
224
+
225
+ case S_QUOTE_IN_QUOTED:
226
+ if (ch === '"') {
227
+ field += '"';
228
+ state = S_IN_QUOTED;
229
+ } else if (ch === delim) {
230
+ endField();
231
+ } else if (ch === '\n') {
232
+ endRow(rows);
233
+ } else if (ch === '\r') {
234
+ endRow(rows);
235
+ pendingCR = true;
236
+ } else {
237
+ field += ch;
238
+ state = S_IN_FIELD;
239
+ }
240
+ break;
241
+
242
+ default:
243
+ break;
244
+ }
245
+ }
246
+ return rows;
247
+ }
248
+
249
+ function end() {
250
+ const rows = [];
251
+ const hasPendingContent = values.length > 0
252
+ || field !== ''
253
+ || fieldWasQuoted
254
+ || state === S_IN_QUOTED
255
+ || state === S_QUOTE_IN_QUOTED;
256
+ if (hasPendingContent) {
257
+ endRow(rows);
258
+ }
259
+ return rows;
260
+ }
261
+
262
+ function stats() {
263
+ return { blankLines, unterminatedQuote: state === S_IN_QUOTED };
264
+ }
265
+
266
+ return { push, end, stats };
267
+ }
268
+
269
+ function parseText(text, { delimiter = ',', trackQuoted = false, skipEmptyLines = true } = {}) {
270
+ const parser = createParser({ delimiter, trackQuoted, skipEmptyLines });
271
+ const stripped = stripBom(String(text === undefined || text === null ? '' : text));
272
+ const rows = parser.push(stripped.text);
273
+ return rows.concat(parser.end());
274
+ }
275
+
276
+ function quoteAwareFieldCounts(sampleText, delimiter, maxLines) {
277
+ const rows = parseText(sampleText, { delimiter });
278
+ return rows.slice(0, maxLines).map((row) => row.values.length);
279
+ }
280
+
281
+ // Score each candidate by how consistently it splits the sample AND by how many
282
+ // fields it produces. Consistency alone is not enough: a semicolon file whose
283
+ // text fields each contain one comma splits perfectly consistently on `,` too.
284
+ function detectDelimiter(sampleText, { candidates = DELIMITER_CANDIDATES, maxLines = DELIMITER_SAMPLE_LINES } = {}) {
285
+ const scored = candidates.map((delimiter) => {
286
+ const counts = quoteAwareFieldCounts(sampleText, delimiter, maxLines);
287
+ if (counts.length === 0 || counts[0] < 2) {
288
+ return { delimiter, fieldCount: counts[0] || 0, consistency: 0, score: 0 };
289
+ }
290
+ const consistency = counts.filter((count) => count === counts[0]).length / counts.length;
291
+ return {
292
+ delimiter,
293
+ fieldCount: counts[0],
294
+ consistency,
295
+ score: consistency * Math.log2(counts[0]),
296
+ };
297
+ });
298
+
299
+ const ranked = [...scored].sort((a, b) => b.score - a.score
300
+ || candidates.indexOf(a.delimiter) - candidates.indexOf(b.delimiter));
301
+ const winner = ranked[0];
302
+ const runnerUp = ranked[1];
303
+ const clearsScore = winner.score >= DELIMITER_MIN_SCORE;
304
+ const clearsMargin = !runnerUp || runnerUp.score === 0 || winner.score / runnerUp.score >= DELIMITER_MIN_MARGIN;
305
+ const ambiguous = !(clearsScore && clearsMargin);
306
+
307
+ return {
308
+ delimiter: ambiguous ? (candidates[0] || ',') : winner.delimiter,
309
+ confidence: ambiguous ? Math.min(0.5, winner.score / 2) : Math.min(1, 0.6 + winner.score / 10),
310
+ ambiguous,
311
+ candidates: ranked,
312
+ };
313
+ }
314
+
315
+ async function readSample(filePath, { bytes = DEFAULT_SAMPLE_BYTES, encoding = null } = {}) {
316
+ const handle = await fsp.open(filePath, 'r');
317
+ try {
318
+ const stat = await handle.stat();
319
+ const length = Math.min(bytes, stat.size);
320
+ const buffer = Buffer.alloc(length);
321
+ await handle.read(buffer, 0, length, 0);
322
+ const detected = detectEncoding(buffer);
323
+ if (!encoding && !detected.supported) {
324
+ throw new Error(`${filePath} looks like ${detected.encoding} (BOM ${detected.bom}); only UTF-8 family encodings are supported. Set CSV_ENCODING or convert the file to UTF-8.`);
325
+ }
326
+ const decoder = new StringDecoder(nodeEncodingFor(encoding || detected.encoding));
327
+ const decoded = stripBom(decoder.write(buffer) + decoder.end());
328
+ const truncated = length < stat.size;
329
+ // A truncated sample almost certainly ends mid-line; dropping the tail keeps
330
+ // field-count statistics honest.
331
+ const text = truncated ? decoded.text.slice(0, decoded.text.lastIndexOf('\n') + 1) : decoded.text;
332
+ return {
333
+ text,
334
+ bom: detected.bom,
335
+ encoding: encoding || detected.encoding,
336
+ truncated,
337
+ totalBytes: stat.size,
338
+ };
339
+ } finally {
340
+ await handle.close();
341
+ }
342
+ }
343
+
344
+ async function readHeaderRow(filePath, { delimiter = null, encoding = null, sampleBytes = TAIL_SAMPLE_BYTES } = {}) {
345
+ const sample = await readSample(filePath, { bytes: sampleBytes, encoding });
346
+ const dialect = delimiter
347
+ ? { delimiter, confidence: 1, ambiguous: false, candidates: [] }
348
+ : detectDelimiter(sample.text);
349
+ const rows = parseText(sample.text, { delimiter: dialect.delimiter });
350
+ const header = rows.length > 0 ? rows[0].values : [];
351
+ return {
352
+ header,
353
+ delimiter: dialect.delimiter,
354
+ delimiterAmbiguous: dialect.ambiguous,
355
+ delimiterCandidates: dialect.candidates,
356
+ encoding: sample.encoding,
357
+ bom: sample.bom,
358
+ lineEnding: detectLineEnding(sample.text),
359
+ rawHeaderLine: sample.text.split(/\r\n|\n|\r/)[0] || '',
360
+ };
361
+ }
362
+
363
+ // Read the last window of the file for tail samples. A quoted field containing
364
+ // a newline can straddle the window boundary and misparse silently, so the
365
+ // sample is only accepted when the quote count is even and every row has the
366
+ // header's width.
367
+ async function readTailSample(filePath, { bytes = TAIL_SAMPLE_BYTES, delimiter = ',', encoding = 'utf8', header = [] } = {}) {
368
+ const handle = await fsp.open(filePath, 'r');
369
+ try {
370
+ const stat = await handle.stat();
371
+ if (stat.size === 0) {
372
+ return { rows: [], skipped: false, reason: null };
373
+ }
374
+ const length = Math.min(bytes, stat.size);
375
+ const position = stat.size - length;
376
+ const buffer = Buffer.alloc(length);
377
+ await handle.read(buffer, 0, length, position);
378
+ const decoder = new StringDecoder(nodeEncodingFor(encoding));
379
+ let text = decoder.write(buffer) + decoder.end();
380
+ if (position > 0) {
381
+ const firstBreak = text.indexOf('\n');
382
+ if (firstBreak === -1) {
383
+ return { rows: [], skipped: true, reason: 'no-line-break-in-window' };
384
+ }
385
+ text = text.slice(firstBreak + 1);
386
+ } else {
387
+ text = stripBom(text).text;
388
+ }
389
+ const quoteCount = (text.match(/"/g) || []).length;
390
+ if (position > 0 && quoteCount % 2 !== 0) {
391
+ return { rows: [], skipped: true, reason: 'odd-quote-count-in-window' };
392
+ }
393
+ const rows = parseText(text, { delimiter });
394
+ const body = position > 0 ? rows : rows.slice(1);
395
+ if (header.length > 0 && body.some((row) => row.values.length !== header.length)) {
396
+ return { rows: [], skipped: true, reason: 'ragged-rows-in-window' };
397
+ }
398
+ return { rows: body, skipped: false, reason: null };
399
+ } finally {
400
+ await handle.close();
401
+ }
402
+ }
403
+
404
+ async function* streamRows(filePath, {
405
+ delimiter = null,
406
+ encoding = null,
407
+ trackQuoted = false,
408
+ skipEmptyLines = true,
409
+ maxRows = null,
410
+ } = {}) {
411
+ let resolvedDelimiter = delimiter;
412
+ let resolvedEncoding = encoding;
413
+ if (!resolvedDelimiter || !resolvedEncoding) {
414
+ const sample = await readSample(filePath, { encoding });
415
+ resolvedEncoding = resolvedEncoding || sample.encoding;
416
+ resolvedDelimiter = resolvedDelimiter || detectDelimiter(sample.text).delimiter;
417
+ }
418
+
419
+ const decoder = new StringDecoder(nodeEncodingFor(resolvedEncoding));
420
+ const parser = createParser({ delimiter: resolvedDelimiter, trackQuoted, skipEmptyLines });
421
+ const stream = fs.createReadStream(filePath);
422
+ let emitted = 0;
423
+ let first = true;
424
+
425
+ for await (const chunk of stream) {
426
+ let text = decoder.write(chunk);
427
+ if (first) {
428
+ text = stripBom(text).text;
429
+ first = false;
430
+ }
431
+ for (const row of parser.push(text)) {
432
+ yield row;
433
+ emitted += 1;
434
+ if (maxRows !== null && emitted >= maxRows) {
435
+ stream.destroy();
436
+ return;
437
+ }
438
+ }
439
+ }
440
+
441
+ const tail = decoder.end();
442
+ const pending = tail ? parser.push(tail) : [];
443
+ for (const row of pending.concat(parser.end())) {
444
+ yield row;
445
+ emitted += 1;
446
+ if (maxRows !== null && emitted >= maxRows) {
447
+ return;
448
+ }
449
+ }
450
+ }
451
+
452
+ async function* streamRecords(filePath, options = {}) {
453
+ let header = options.header || null;
454
+ for await (const row of streamRows(filePath, options)) {
455
+ if (!header) {
456
+ header = row.values;
457
+ continue;
458
+ }
459
+ yield { record: toRecord(header, row.values), row };
460
+ }
461
+ }
462
+
463
+ function toRecord(header, values) {
464
+ const record = {};
465
+ for (let i = 0; i < header.length; i += 1) {
466
+ record[header[i]] = i < values.length ? values[i] : '';
467
+ }
468
+ return record;
469
+ }
470
+
471
+ function rowWidthReport(header, values) {
472
+ return {
473
+ expected: header.length,
474
+ actual: values.length,
475
+ padded: values.length < header.length,
476
+ truncated: values.length > header.length,
477
+ ragged: values.length !== header.length,
478
+ };
479
+ }
480
+
481
+ // Requires rows parsed with `trackQuoted: true`.
482
+ function detectEmptyPolicy(rows) {
483
+ let sawQuotedEmpty = false;
484
+ let sawUnquotedEmpty = false;
485
+ for (const row of rows) {
486
+ const quoted = row.quoted || [];
487
+ for (let i = 0; i < row.values.length; i += 1) {
488
+ if (row.values[i] !== '') {
489
+ continue;
490
+ }
491
+ if (quoted[i]) {
492
+ sawQuotedEmpty = true;
493
+ } else {
494
+ sawUnquotedEmpty = true;
495
+ }
496
+ if (sawQuotedEmpty && sawUnquotedEmpty) {
497
+ return EMPTY_POLICY.PRESENT_IF_QUOTED;
498
+ }
499
+ }
500
+ }
501
+ return EMPTY_POLICY.ALWAYS_EMPTY;
502
+ }
503
+
504
+ // The one place empty-vs-absent is decided. Generated readers call this so a
505
+ // required Wix field is never fed an empty string the source did not have.
506
+ function coerceEmpty(value, isQuoted, policy) {
507
+ if (value !== '') {
508
+ return value;
509
+ }
510
+ if (policy === EMPTY_POLICY.PRESENT_IF_QUOTED) {
511
+ return isQuoted ? '' : null;
512
+ }
513
+ return '';
514
+ }
515
+
516
+ const TYPE_TESTS = [
517
+ ['integer', (value) => /^-?\d+$/.test(value)],
518
+ ['number', (value) => /^-?(\d+\.\d*|\.\d+|\d+)$/.test(value)],
519
+ ['date-time', (value) => /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}/.test(value)],
520
+ ['date', (value) => /^\d{4}-\d{2}-\d{2}$/.test(value)],
521
+ ['url', (value) => /^https?:\/\/\S+$/i.test(value)],
522
+ ['email', (value) => /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(value)],
523
+ ];
524
+
525
+ const BOOLEAN_VALUES = new Set(['true', 'false', 'yes', 'no']);
526
+
527
+ function inferValueType(values) {
528
+ const present = values.filter((value) => typeof value === 'string' && value.trim() !== '');
529
+ if (present.length === 0) {
530
+ return 'unknown';
531
+ }
532
+ if (present.every((value) => BOOLEAN_VALUES.has(value.trim().toLowerCase()))) {
533
+ return 'boolean';
534
+ }
535
+ for (const [type, test] of TYPE_TESTS) {
536
+ if (present.every((value) => test(value.trim()))) {
537
+ return type;
538
+ }
539
+ }
540
+ return 'string';
541
+ }
542
+
543
+ function summarizeColumn(name, samples, { maxExamples = 3, distinctCap = 5000 } = {}) {
544
+ const distinct = new Set();
545
+ let blankCount = 0;
546
+ let quotedEmptyCount = 0;
547
+ let maxLength = 0;
548
+ let multiValueHint = false;
549
+ const examples = [];
550
+ const present = [];
551
+
552
+ for (const sample of samples) {
553
+ const value = typeof sample === 'string' ? sample : sample.value;
554
+ const isQuoted = typeof sample === 'string' ? false : Boolean(sample.quoted);
555
+ if (value === '' || value === null || value === undefined) {
556
+ blankCount += 1;
557
+ if (isQuoted) {
558
+ quotedEmptyCount += 1;
559
+ }
560
+ continue;
561
+ }
562
+ present.push(value);
563
+ if (distinct.size < distinctCap) {
564
+ distinct.add(value);
565
+ }
566
+ maxLength = Math.max(maxLength, value.length);
567
+ if (!multiValueHint && /[,;|]/.test(value) && value.length < 200) {
568
+ multiValueHint = true;
569
+ }
570
+ if (examples.length < maxExamples) {
571
+ examples.push(value);
572
+ }
573
+ }
574
+
575
+ const total = samples.length;
576
+ return {
577
+ name,
578
+ type: inferValueType(present),
579
+ required: total > 0 && blankCount === 0,
580
+ blankCount,
581
+ quotedEmptyCount,
582
+ sampled: total,
583
+ distinctCount: distinct.size,
584
+ distinctCapped: distinct.size >= distinctCap,
585
+ unique: present.length > 0 && distinct.size === present.length && distinct.size < distinctCap,
586
+ maxLength,
587
+ multiValueHint,
588
+ examples,
589
+ };
590
+ }
591
+
592
+ module.exports = {
593
+ DELIMITER_CANDIDATES,
594
+ DELIMITER_SAMPLE_LINES,
595
+ DELIMITER_MIN_SCORE,
596
+ DELIMITER_MIN_MARGIN,
597
+ DEFAULT_SAMPLE_BYTES,
598
+ TAIL_SAMPLE_BYTES,
599
+ EMPTY_POLICY,
600
+ createParser,
601
+ parseText,
602
+ detectDelimiter,
603
+ detectEncoding,
604
+ detectLineEnding,
605
+ stripBom,
606
+ normalizeHeaderName,
607
+ readSample,
608
+ readHeaderRow,
609
+ readTailSample,
610
+ streamRows,
611
+ streamRecords,
612
+ toRecord,
613
+ rowWidthReport,
614
+ detectEmptyPolicy,
615
+ coerceEmpty,
616
+ inferValueType,
617
+ summarizeColumn,
618
+ };