@wix/agent-skills 1.21.0 → 1.22.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 (258) hide show
  1. package/package.json +1 -1
  2. package/skills/wix-app/SKILL.md +60 -4
  3. package/skills/wix-app/references/DASHBOARD_PAGE.md +11 -25
  4. package/skills/wix-app/references/DATA_COLLECTION.md +16 -219
  5. package/skills/wix-app/references/dashboard-page/DATA_SOURCES.md +182 -0
  6. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE.md +97 -0
  7. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_COLLECTION.md +184 -0
  8. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_ROUTER.md +203 -0
  9. package/skills/wix-app/references/dashboard-page/DRAFT_TEMPLATE_SETTINGS.md +44 -0
  10. package/skills/wix-app/references/dashboard-page/QUERY_AND_PAGING.md +182 -0
  11. package/skills/wix-app/references/dashboard-page/TABLE_STATE.md +133 -0
  12. package/skills/wix-app/references/dashboard-page/UX_SUCCESS_MODEL.md +10 -5
  13. package/skills/wix-app/references/data-collection/LIFECYCLE.md +68 -0
  14. package/skills/wix-app/references/data-collection/PERMISSIONS.md +47 -0
  15. package/skills/wix-app/references/data-collection/SCHEMA.md +181 -0
  16. package/skills/wix-app/references/data-collection/WIX_DATA.md +38 -66
  17. package/skills/wix-headless-fast/SKILL.md +61 -223
  18. package/skills/wix-headless-fast/cold-start/bootstrap.mjs +156 -0
  19. package/skills/wix-headless-fast/{entry/skill.md → cold-start/cold-start.md} +11 -12
  20. package/skills/wix-headless-fast/guides/existing-site.md +76 -0
  21. package/skills/wix-headless-fast/guides/reference-mode.md +97 -0
  22. package/skills/wix-headless-fast/install/AGENTS.md +6 -3
  23. package/skills/wix-headless-fast/install/attach.mjs +15 -47
  24. package/skills/wix-headless-fast/install/deploy.mjs +21 -60
  25. package/skills/wix-headless-fast/install/lock.mjs +55 -0
  26. package/skills/wix-headless-fast/install/setup.mjs +32 -12
  27. package/skills/wix-headless-fast/install/templates.mjs +168 -0
  28. package/skills/wix-manage/references/google-ads/google-ads-dashboard-navigation.md +27 -0
  29. package/skills/wix-manage/references/google-ads/manage-campaign-success-guide.md +83 -37
  30. package/skills/wix-headless-fast/references/blog/INSTRUCTIONS.md +0 -303
  31. package/skills/wix-headless-fast/references/blog/app/components/blog/BlogFeedView.tsx +0 -136
  32. package/skills/wix-headless-fast/references/blog/app/components/blog/PostView.tsx +0 -112
  33. package/skills/wix-headless-fast/references/blog/app/components/blog/RichContent.tsx +0 -42
  34. package/skills/wix-headless-fast/references/blog/app/hooks/blog/useBlogFeed.ts +0 -31
  35. package/skills/wix-headless-fast/references/blog/app/hooks/blog/usePost.ts +0 -22
  36. package/skills/wix-headless-fast/references/blog/app/wix/blog/blog-feed-store.ts +0 -137
  37. package/skills/wix-headless-fast/references/blog/app/wix/blog/post-store.ts +0 -78
  38. package/skills/wix-headless-fast/references/blog/app/wix/blog/posts-core.ts +0 -117
  39. package/skills/wix-headless-fast/references/blog/app/wix/blog/posts.ts +0 -52
  40. package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy-core.ts +0 -47
  41. package/skills/wix-headless-fast/references/blog/app/wix/blog/taxonomy.ts +0 -58
  42. package/skills/wix-headless-fast/references/blog/app/wix/blog/types.ts +0 -62
  43. package/skills/wix-headless-fast/references/blog/app-astro/layouts/SiteLayout.astro +0 -40
  44. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog/[...slug].astro +0 -97
  45. package/skills/wix-headless-fast/references/blog/app-astro/pages/blog.astro +0 -24
  46. package/skills/wix-headless-fast/references/blog/lock/astro/package-lock.json +0 -16156
  47. package/skills/wix-headless-fast/references/blog/rest/posts.ts +0 -42
  48. package/skills/wix-headless-fast/references/blog/rest/taxonomy.ts +0 -62
  49. package/skills/wix-headless-fast/references/blog/seed/SEED.md +0 -81
  50. package/skills/wix-headless-fast/references/blog/seed/read-site.mjs +0 -22
  51. package/skills/wix-headless-fast/references/blog/seed/seed-blog.mjs +0 -287
  52. package/skills/wix-headless-fast/references/bookings/INSTRUCTIONS.md +0 -277
  53. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServiceBookingView.tsx +0 -144
  54. package/skills/wix-headless-fast/references/bookings/app/components/bookings/ServicesView.tsx +0 -119
  55. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useBookingFlow.ts +0 -32
  56. package/skills/wix-headless-fast/references/bookings/app/hooks/bookings/useServices.ts +0 -23
  57. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-core.ts +0 -218
  58. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking-flow-store.ts +0 -169
  59. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/booking.ts +0 -121
  60. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-core.ts +0 -92
  61. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services-store.ts +0 -90
  62. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/services.ts +0 -57
  63. package/skills/wix-headless-fast/references/bookings/app/wix/bookings/types.ts +0 -72
  64. package/skills/wix-headless-fast/references/bookings/app-astro/layouts/SiteLayout.astro +0 -40
  65. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services/[slug].astro +0 -76
  66. package/skills/wix-headless-fast/references/bookings/app-astro/pages/services.astro +0 -22
  67. package/skills/wix-headless-fast/references/bookings/lock/astro/package-lock.json +0 -11962
  68. package/skills/wix-headless-fast/references/bookings/rest/booking.ts +0 -113
  69. package/skills/wix-headless-fast/references/bookings/rest/services.ts +0 -55
  70. package/skills/wix-headless-fast/references/bookings/seed/SEED.md +0 -71
  71. package/skills/wix-headless-fast/references/bookings/seed/read-site.mjs +0 -28
  72. package/skills/wix-headless-fast/references/bookings/seed/seed-bookings.mjs +0 -302
  73. package/skills/wix-headless-fast/references/cms/INSTRUCTIONS.md +0 -355
  74. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useCollection.ts +0 -50
  75. package/skills/wix-headless-fast/references/cms/app/hooks/cms/useItem.ts +0 -37
  76. package/skills/wix-headless-fast/references/cms/app/wix/cms/collection-store.ts +0 -158
  77. package/skills/wix-headless-fast/references/cms/app/wix/cms/item-store.ts +0 -93
  78. package/skills/wix-headless-fast/references/cms/app/wix/cms/items-core.ts +0 -177
  79. package/skills/wix-headless-fast/references/cms/app/wix/cms/items.ts +0 -123
  80. package/skills/wix-headless-fast/references/cms/app/wix/cms/types.ts +0 -75
  81. package/skills/wix-headless-fast/references/cms/app-astro/layouts/SiteLayout.astro +0 -41
  82. package/skills/wix-headless-fast/references/cms/lock/astro/package-lock.json +0 -11262
  83. package/skills/wix-headless-fast/references/cms/rest/items.ts +0 -125
  84. package/skills/wix-headless-fast/references/cms/seed/SEED.md +0 -112
  85. package/skills/wix-headless-fast/references/cms/seed/read-site.mjs +0 -20
  86. package/skills/wix-headless-fast/references/cms/seed/seed-cms.mjs +0 -324
  87. package/skills/wix-headless-fast/references/events/INSTRUCTIONS.md +0 -307
  88. package/skills/wix-headless-fast/references/events/app/components/events/EventConfirmationView.tsx +0 -66
  89. package/skills/wix-headless-fast/references/events/app/components/events/EventRegistrationView.tsx +0 -178
  90. package/skills/wix-headless-fast/references/events/app/components/events/EventsView.tsx +0 -118
  91. package/skills/wix-headless-fast/references/events/app/hooks/events/useEventRegistration.ts +0 -35
  92. package/skills/wix-headless-fast/references/events/app/hooks/events/useEvents.ts +0 -24
  93. package/skills/wix-headless-fast/references/events/app/wix/events/events-core.ts +0 -130
  94. package/skills/wix-headless-fast/references/events/app/wix/events/events-store.ts +0 -97
  95. package/skills/wix-headless-fast/references/events/app/wix/events/events.ts +0 -55
  96. package/skills/wix-headless-fast/references/events/app/wix/events/registration-core.ts +0 -113
  97. package/skills/wix-headless-fast/references/events/app/wix/events/registration-store.ts +0 -156
  98. package/skills/wix-headless-fast/references/events/app/wix/events/registration.ts +0 -97
  99. package/skills/wix-headless-fast/references/events/app/wix/events/types.ts +0 -61
  100. package/skills/wix-headless-fast/references/events/app-astro/layouts/SiteLayout.astro +0 -40
  101. package/skills/wix-headless-fast/references/events/app-astro/pages/event-confirmation.astro +0 -12
  102. package/skills/wix-headless-fast/references/events/app-astro/pages/events/[slug].astro +0 -80
  103. package/skills/wix-headless-fast/references/events/app-astro/pages/events.astro +0 -21
  104. package/skills/wix-headless-fast/references/events/lock/astro/package-lock.json +0 -11884
  105. package/skills/wix-headless-fast/references/events/rest/events.ts +0 -57
  106. package/skills/wix-headless-fast/references/events/rest/registration.ts +0 -83
  107. package/skills/wix-headless-fast/references/events/seed/SEED.md +0 -95
  108. package/skills/wix-headless-fast/references/events/seed/read-site.mjs +0 -26
  109. package/skills/wix-headless-fast/references/events/seed/seed-events.mjs +0 -276
  110. package/skills/wix-headless-fast/references/forms/INSTRUCTIONS.md +0 -340
  111. package/skills/wix-headless-fast/references/forms/app/hooks/forms/useWixForm.ts +0 -85
  112. package/skills/wix-headless-fast/references/forms/app/wix/forms/form-store.ts +0 -332
  113. package/skills/wix-headless-fast/references/forms/app/wix/forms/forms-core.ts +0 -238
  114. package/skills/wix-headless-fast/references/forms/app/wix/forms/forms.ts +0 -54
  115. package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions-core.ts +0 -216
  116. package/skills/wix-headless-fast/references/forms/app/wix/forms/submissions.ts +0 -59
  117. package/skills/wix-headless-fast/references/forms/app/wix/forms/types.ts +0 -135
  118. package/skills/wix-headless-fast/references/forms/lock/astro/package-lock.json +0 -10593
  119. package/skills/wix-headless-fast/references/forms/rest/forms.ts +0 -34
  120. package/skills/wix-headless-fast/references/forms/rest/submissions.ts +0 -56
  121. package/skills/wix-headless-fast/references/forms/seed/SEED.md +0 -116
  122. package/skills/wix-headless-fast/references/forms/seed/read-site.mjs +0 -20
  123. package/skills/wix-headless-fast/references/forms/seed/seed-forms.mjs +0 -327
  124. package/skills/wix-headless-fast/references/members/INSTRUCTIONS.md +0 -316
  125. package/skills/wix-headless-fast/references/members/app/components/members/AccountView.tsx +0 -60
  126. package/skills/wix-headless-fast/references/members/app/components/members/LoginForm.tsx +0 -155
  127. package/skills/wix-headless-fast/references/members/app/components/members/MemberMenu.tsx +0 -78
  128. package/skills/wix-headless-fast/references/members/app/components/members/RequireAuth.tsx +0 -47
  129. package/skills/wix-headless-fast/references/members/app/hooks/members/useMember.ts +0 -66
  130. package/skills/wix-headless-fast/references/members/app/wix/members/auth-core.ts +0 -105
  131. package/skills/wix-headless-fast/references/members/app/wix/members/auth.ts +0 -59
  132. package/skills/wix-headless-fast/references/members/app/wix/members/client.ts +0 -53
  133. package/skills/wix-headless-fast/references/members/app/wix/members/member-store.ts +0 -122
  134. package/skills/wix-headless-fast/references/members/app/wix/members/members-core.ts +0 -43
  135. package/skills/wix-headless-fast/references/members/app/wix/members/members.ts +0 -29
  136. package/skills/wix-headless-fast/references/members/app/wix/members/types.ts +0 -21
  137. package/skills/wix-headless-fast/references/members/app-astro/layouts/SiteLayout.astro +0 -42
  138. package/skills/wix-headless-fast/references/members/app-astro/pages/account.astro +0 -10
  139. package/skills/wix-headless-fast/references/members/app-astro/pages/login.astro +0 -11
  140. package/skills/wix-headless-fast/references/members/lock/astro/package-lock.json +0 -10329
  141. package/skills/wix-headless-fast/references/members/rest/auth.ts +0 -215
  142. package/skills/wix-headless-fast/references/members/rest/members.ts +0 -26
  143. package/skills/wix-headless-fast/references/members/seed/SEED.md +0 -39
  144. package/skills/wix-headless-fast/references/members/seed/read-site.mjs +0 -15
  145. package/skills/wix-headless-fast/references/members/seed/seed-members.mjs +0 -94
  146. package/skills/wix-headless-fast/references/portfolio/INSTRUCTIONS.md +0 -315
  147. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionProjectsView.tsx +0 -110
  148. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/CollectionsView.tsx +0 -90
  149. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/GalleryMedia.tsx +0 -35
  150. package/skills/wix-headless-fast/references/portfolio/app/components/portfolio/ProjectDetailView.tsx +0 -85
  151. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollectionProjects.ts +0 -32
  152. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useCollections.ts +0 -21
  153. package/skills/wix-headless-fast/references/portfolio/app/hooks/portfolio/useProjectDetail.ts +0 -31
  154. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collection-projects-store.ts +0 -82
  155. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/collections-store.ts +0 -58
  156. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio-core.ts +0 -177
  157. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/portfolio.ts +0 -78
  158. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/project-detail-store.ts +0 -81
  159. package/skills/wix-headless-fast/references/portfolio/app/wix/portfolio/types.ts +0 -55
  160. package/skills/wix-headless-fast/references/portfolio/app-astro/layouts/SiteLayout.astro +0 -40
  161. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio/[slug].astro +0 -30
  162. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/portfolio.astro +0 -21
  163. package/skills/wix-headless-fast/references/portfolio/app-astro/pages/projects/[slug].astro +0 -29
  164. package/skills/wix-headless-fast/references/portfolio/lock/astro/package-lock.json +0 -10197
  165. package/skills/wix-headless-fast/references/portfolio/rest/portfolio.ts +0 -75
  166. package/skills/wix-headless-fast/references/portfolio/seed/SEED.md +0 -86
  167. package/skills/wix-headless-fast/references/portfolio/seed/read-site.mjs +0 -20
  168. package/skills/wix-headless-fast/references/portfolio/seed/seed-portfolio.mjs +0 -256
  169. package/skills/wix-headless-fast/references/pricing-plans/INSTRUCTIONS.md +0 -296
  170. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlanDetailView.tsx +0 -47
  171. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/PlansView.tsx +0 -101
  172. package/skills/wix-headless-fast/references/pricing-plans/app/components/pricing-plans/SubscribeButton.tsx +0 -41
  173. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlanPurchase.ts +0 -16
  174. package/skills/wix-headless-fast/references/pricing-plans/app/hooks/pricing-plans/usePlans.ts +0 -22
  175. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plan-purchase-store.ts +0 -54
  176. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-core.ts +0 -106
  177. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans-store.ts +0 -64
  178. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/plans.ts +0 -27
  179. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase-core.ts +0 -43
  180. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/purchase.ts +0 -22
  181. package/skills/wix-headless-fast/references/pricing-plans/app/wix/pricing-plans/types.ts +0 -30
  182. package/skills/wix-headless-fast/references/pricing-plans/app-astro/layouts/SiteLayout.astro +0 -41
  183. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans/[slug].astro +0 -40
  184. package/skills/wix-headless-fast/references/pricing-plans/app-astro/pages/plans.astro +0 -21
  185. package/skills/wix-headless-fast/references/pricing-plans/lock/astro/package-lock.json +0 -11226
  186. package/skills/wix-headless-fast/references/pricing-plans/rest/plans.ts +0 -31
  187. package/skills/wix-headless-fast/references/pricing-plans/rest/purchase.ts +0 -20
  188. package/skills/wix-headless-fast/references/pricing-plans/seed/SEED.md +0 -79
  189. package/skills/wix-headless-fast/references/pricing-plans/seed/read-site.mjs +0 -21
  190. package/skills/wix-headless-fast/references/pricing-plans/seed/seed-pricing-plans.mjs +0 -279
  191. package/skills/wix-headless-fast/references/restaurants/INSTRUCTIONS.md +0 -360
  192. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/MenuView.tsx +0 -142
  193. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartButton.tsx +0 -26
  194. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/OrderCartDrawer.tsx +0 -121
  195. package/skills/wix-headless-fast/references/restaurants/app/components/restaurants/ReservationView.tsx +0 -155
  196. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useMenus.ts +0 -34
  197. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useOrderCart.ts +0 -43
  198. package/skills/wix-headless-fast/references/restaurants/app/hooks/restaurants/useReservation.ts +0 -34
  199. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-core.ts +0 -155
  200. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu-store.ts +0 -89
  201. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/menu.ts +0 -71
  202. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/order-store.ts +0 -103
  203. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering-core.ts +0 -124
  204. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/ordering.ts +0 -185
  205. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservation-store.ts +0 -193
  206. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations-core.ts +0 -94
  207. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/reservations.ts +0 -74
  208. package/skills/wix-headless-fast/references/restaurants/app/wix/restaurants/types.ts +0 -168
  209. package/skills/wix-headless-fast/references/restaurants/app-astro/layouts/SiteLayout.astro +0 -47
  210. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/menu.astro +0 -22
  211. package/skills/wix-headless-fast/references/restaurants/app-astro/pages/reservations.astro +0 -12
  212. package/skills/wix-headless-fast/references/restaurants/lock/astro/package-lock.json +0 -12560
  213. package/skills/wix-headless-fast/references/restaurants/rest/menu.ts +0 -60
  214. package/skills/wix-headless-fast/references/restaurants/rest/ordering.ts +0 -169
  215. package/skills/wix-headless-fast/references/restaurants/rest/reservations.ts +0 -68
  216. package/skills/wix-headless-fast/references/restaurants/seed/SEED.md +0 -89
  217. package/skills/wix-headless-fast/references/restaurants/seed/read-site.mjs +0 -25
  218. package/skills/wix-headless-fast/references/restaurants/seed/seed-restaurants.mjs +0 -499
  219. package/skills/wix-headless-fast/references/shared/CONTENT.md +0 -22
  220. package/skills/wix-headless-fast/references/shared/CUSTOM_OPERATIONS.md +0 -73
  221. package/skills/wix-headless-fast/references/shared/DESIGN.md +0 -26
  222. package/skills/wix-headless-fast/references/shared/SUPPLIED-CONTENT.md +0 -23
  223. package/skills/wix-headless-fast/references/shared/app/styles/global.css +0 -52
  224. package/skills/wix-headless-fast/references/shared/app/wix/config.ts +0 -15
  225. package/skills/wix-headless-fast/references/shared/app/wix/media.ts +0 -81
  226. package/skills/wix-headless-fast/references/shared/app/wix/money.ts +0 -24
  227. package/skills/wix-headless-fast/references/shared/app/wix/sdk.ts +0 -89
  228. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app/wix/media-upload/client.ts +0 -46
  229. package/skills/wix-headless-fast/references/shared/capabilities/media-upload/app-astro/pages/api/wix/media-upload.ts +0 -46
  230. package/skills/wix-headless-fast/references/shared/rest/client.ts +0 -155
  231. package/skills/wix-headless-fast/references/shared/rest/config.ts +0 -3
  232. package/skills/wix-headless-fast/references/shared/rest/media.ts +0 -65
  233. package/skills/wix-headless-fast/references/shared/seed/images.mjs +0 -145
  234. package/skills/wix-headless-fast/references/shared/seed/read-site.mjs +0 -99
  235. package/skills/wix-headless-fast/references/storefront/INSTRUCTIONS.md +0 -612
  236. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartButton.tsx +0 -26
  237. package/skills/wix-headless-fast/references/storefront/app/components/storefront/CartDrawer.tsx +0 -155
  238. package/skills/wix-headless-fast/references/storefront/app/components/storefront/FilterPanel.tsx +0 -266
  239. package/skills/wix-headless-fast/references/storefront/app/components/storefront/OptionPicker.tsx +0 -95
  240. package/skills/wix-headless-fast/references/storefront/app/components/storefront/QuickAdd.tsx +0 -136
  241. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useCart.ts +0 -48
  242. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useProductDetail.ts +0 -39
  243. package/skills/wix-headless-fast/references/storefront/app/hooks/storefront/useShop.ts +0 -34
  244. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-core.ts +0 -121
  245. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart-store.ts +0 -107
  246. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/cart.ts +0 -138
  247. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog-core.ts +0 -314
  248. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/catalog.ts +0 -133
  249. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/product-detail-store.ts +0 -147
  250. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/shop-store.ts +0 -289
  251. package/skills/wix-headless-fast/references/storefront/app/wix/storefront/types.ts +0 -169
  252. package/skills/wix-headless-fast/references/storefront/app-astro/layouts/SiteLayout.astro +0 -65
  253. package/skills/wix-headless-fast/references/storefront/lock/astro/package-lock.json +0 -12247
  254. package/skills/wix-headless-fast/references/storefront/rest/cart.ts +0 -132
  255. package/skills/wix-headless-fast/references/storefront/rest/catalog.ts +0 -123
  256. package/skills/wix-headless-fast/references/storefront/seed/SEED.md +0 -130
  257. package/skills/wix-headless-fast/references/storefront/seed/read-site.mjs +0 -38
  258. package/skills/wix-headless-fast/references/storefront/seed/seed-store.mjs +0 -561
@@ -1,42 +0,0 @@
1
- // Post reads over REST — the twin of app/wix/blog/posts.ts. Same exports, same DTOs; the rules and
2
- // mappers come from posts-core (the SAME file the SDK transport uses, deployed flat next to this one
3
- // by deploy.mjs --stack static), so this file is only the transport: one fetch with a literal body
4
- // per function. Every call here is safe from a browser with a visitor token — only PUBLISHED posts
5
- // come back to it. Porting: keep the paths, keep the bodies, port the core once.
6
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/posts-stats/query-posts.md
7
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/posts-stats/get-post-by-slug.md
8
- import { wixRequest } from "./client.js";
9
- import { imgSrc } from "./media.js";
10
- import { BLOG_APP_ID, DETAIL_FIELDSETS, feedQuery, postMetaLine, slugQuery, toDetail, toSummary, type FetchPostsOptions, type Raw } from "./posts-core.js";
11
- import type { PostDetail, PostPage } from "./types.js";
12
-
13
- export { BLOG_APP_ID, postMetaLine, type FetchPostsOptions };
14
-
15
- const POSTS_QUERY = "/blog/v3/posts/query";
16
-
17
- /**
18
- * One page of published posts, newest first (pinned posts lead); `nextCursor` continues the same
19
- * query — send it alone, the filters ride inside it.
20
- * POST /blog/v3/posts/query { query: { filter?, sort, cursorPaging: { limit } } } — first page
21
- * POST /blog/v3/posts/query { query: { cursorPaging: { limit, cursor } } } — later pages
22
- */
23
- export async function fetchPosts(o: FetchPostsOptions = {}): Promise<PostPage> {
24
- const res = await wixRequest<Raw>(POSTS_QUERY, { body: { query: feedQuery(o) } });
25
- const paging: Raw = res?.pagingMetadata ?? {};
26
- return {
27
- posts: ((res?.posts ?? []) as Raw[]).map((p) => toSummary(p, imgSrc)),
28
- nextCursor: paging.hasNext ? (paging.cursors?.next ?? null) : null,
29
- };
30
- }
31
-
32
- /**
33
- * One post by URL slug with the full body (the RICH_CONTENT + CONTENT_TEXT fieldsets — without
34
- * them richContent and contentText are absent). Null when the slug resolves to nothing — a real
35
- * 404 for the page, never a fallback to another post.
36
- * POST /blog/v3/posts/query { fieldsets: ["RICH_CONTENT", "CONTENT_TEXT"], query: { filter: { slug: { $eq } }, cursorPaging: { limit: 1 } } }
37
- */
38
- export async function fetchPostBySlug(slug: string): Promise<PostDetail | null> {
39
- const res = await wixRequest<Raw>(POSTS_QUERY, { body: { fieldsets: DETAIL_FIELDSETS, query: slugQuery(slug) } });
40
- const raw: Raw | undefined = res?.posts?.[0];
41
- return raw ? toDetail(raw, imgSrc) : null;
42
- }
@@ -1,62 +0,0 @@
1
- // Category + tag reads over REST — the twin of app/wix/blog/taxonomy.ts. Same exports, same DTOs;
2
- // the mappers come from taxonomy-core (the SAME file the SDK transport uses, deployed flat next to
3
- // this one). Taxonomy queries page by OFFSET (`paging`), unlike posts (`cursorPaging`); a blog's
4
- // taxonomy fits in one read of 100. All four calls are visitor-safe.
5
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/category/query-categories.md
6
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/category/get-category-by-slug.md
7
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/tags/query-tags.md
8
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/tags/get-tag-by-slug.md
9
- import { wixRequest } from "./client.js";
10
- import { imgSrc } from "./media.js";
11
- import { CATEGORY_SORT, TAG_SORT, TAXONOMY_LIMIT, toCategory, toTag } from "./taxonomy-core.js";
12
- import type { Raw } from "./posts-core.js";
13
- import type { BlogCategory, BlogTag } from "./types.js";
14
-
15
- /**
16
- * Categories in menu order. Non-fatal: [] on failure (the feed renders without its filter row).
17
- * POST /blog/v3/categories/query { query: { sort: [{ fieldName: "displayPosition", order: "ASC" }], paging: { limit: 100 } } }
18
- */
19
- export async function fetchBlogCategories(): Promise<BlogCategory[]> {
20
- try {
21
- const res = await wixRequest<Raw>("/blog/v3/categories/query", { body: { query: { sort: CATEGORY_SORT, paging: { limit: TAXONOMY_LIMIT } } } });
22
- return ((res?.categories ?? []) as Raw[]).map((c) => toCategory(c, imgSrc)).filter((c) => c.id);
23
- } catch {
24
- return [];
25
- }
26
- }
27
-
28
- /**
29
- * Tags, most-published-posts first. Non-fatal: [] on failure.
30
- * POST /blog/v3/tags/query { query: { sort: [{ fieldName: "publishedPostCount", order: "DESC" }], paging: { limit: 100 } } }
31
- */
32
- export async function fetchBlogTags(): Promise<BlogTag[]> {
33
- try {
34
- const res = await wixRequest<Raw>("/blog/v3/tags/query", { body: { query: { sort: TAG_SORT, paging: { limit: TAXONOMY_LIMIT } } } });
35
- return ((res?.tags ?? []) as Raw[]).map(toTag).filter((t) => t.id);
36
- } catch {
37
- return [];
38
- }
39
- }
40
-
41
- // The two by-slug getters answer in DIFFERENT envelopes ({ category } and { tag }); a missing slug
42
- // is a 404 — mapped to null here, as the SDK transport does.
43
-
44
- /** One category by its URL slug. Null when not found. GET /blog/v3/categories/slugs/{slug} */
45
- export async function fetchCategoryBySlug(slug: string): Promise<BlogCategory | null> {
46
- try {
47
- const res = await wixRequest<Raw>(`/blog/v3/categories/slugs/${encodeURIComponent(slug)}`, { method: "GET" });
48
- return res?.category ? toCategory(res.category, imgSrc) : null;
49
- } catch {
50
- return null;
51
- }
52
- }
53
-
54
- /** One tag by its URL slug. Null when not found. GET /blog/v3/tags/slugs/{slug} */
55
- export async function fetchTagBySlug(slug: string): Promise<BlogTag | null> {
56
- try {
57
- const res = await wixRequest<Raw>(`/blog/v3/tags/slugs/${encodeURIComponent(slug)}`, { method: "GET" });
58
- return res?.tag ? toTag(res.tag) : null;
59
- } catch {
60
- return null;
61
- }
62
- }
@@ -1,81 +0,0 @@
1
- # Blog — seeding
2
-
3
- Seed by **running `seed-blog.mjs` with a plan file** — don't hand-write the REST calls.
4
- The script mints its own site token via the Wix CLI (logged-in session + `wix.config.json`
5
- required), installs the Blog app if needed, resolves a real author memberId (every post
6
- create requires one), and creates everything in the right order — categories/tags first,
7
- then **published** posts, then imported cover images (PATCH + re-publish).
8
-
9
- ```bash
10
- # from the project root (where wix.config.json lives):
11
- node <SKILL_ROOT>/references/blog/seed/seed-blog.mjs plan.json
12
- ```
13
-
14
- `plan.json` is plain data — write it from the brief. **Default to 3 posts** (the seed shows
15
- the shape; the owner writes the rest in the dashboard) and make them exercise the UI: group
16
- them into 2 categories when the brief has natural sections, tag a couple, vary the content
17
- blocks (heading + paragraphs + a quote or list per post), and give every post a cover — a
18
- feed without covers looks broken.
19
-
20
- ```json
21
- {
22
- "categories": ["Brewing", "Stories"],
23
- "posts": [
24
- { "title": "How We Roast Our Single-Origin Beans", "category": "Stories", "tags": ["coffee"],
25
- "coverImageUrl": "https://…",
26
- "content": [
27
- { "type": "heading", "text": "From farm to cup", "level": 2 },
28
- { "type": "paragraph", "text": "Every batch starts with beans sourced from a single estate." },
29
- { "type": "quote", "text": "Great coffee is grown, not made." }
30
- ] },
31
- { "title": "The Pour-Over, Step by Step", "category": "Brewing", "tags": ["guides"],
32
- "coverImageUrl": "https://…",
33
- "content": [
34
- { "type": "paragraph", "text": "A repeatable ritual in five minutes." },
35
- { "type": "ordered", "items": ["Rinse the filter", "Bloom 30 seconds", "Pour in circles"] }
36
- ] },
37
- { "title": "Why Water Matters More Than You Think", "category": "Brewing",
38
- "coverImageUrl": "https://…",
39
- "content": [
40
- { "type": "paragraph", "text": "Coffee is 98% water — its minerals decide the cup." },
41
- { "type": "bulleted", "items": ["Filtered, not distilled", "Aim for ~150 ppm hardness"] }
42
- ] }
43
- ]
44
- }
45
- ```
46
-
47
- - `content` blocks: `{type:"heading",text,level?}` · `{type:"paragraph",text}` ·
48
- `{type:"quote",text}` · `{type:"bulleted"|"ordered",items:[…]}`. For node types these don't
49
- cover (code, inline images), pass a pre-built Ricos `richContent` on the post instead.
50
- - `category`/`categories`/`tags` are display **names** — created idempotently and resolved to
51
- ids internally. Optional: skip them entirely when the brief doesn't group posts.
52
- - Cover — the default is a `coverImagePrompt` (AI-generated, ~1 Wix AI credit per image,
53
- account-billed): brand-contextual — subject, aesthetic/mood, palette, lighting — always
54
- ending "no text, no watermarks". At least one image in the set shows the real subject of the business — the actual product/space/service, not abstract decoration. For an asset the user actually supplied use
55
- `coverImagePath` (a file on this machine — uploaded to Wix Media) or `coverImageUrl` (their
56
- own hosted URL; verify it with `curl -sI` → 200) — never a stock-photo or guessed URL. Covers resolve
57
- in parallel and never block the seed; a failed cover leaves that post text-only (the script
58
- re-publishes each post it covers).
59
- - Posts are created **published** — an unpublished post never reaches visitors. The bulk
60
- create returns 200 even on partial failure: check each `posts[].success` in the result.
61
-
62
- **Seeding is additive — never delete or overwrite existing content**; ask first if a cleanup
63
- seems needed.
64
-
65
- ## Supplied content
66
-
67
- The general rules are in `references/shared/SUPPLIED-CONTENT.md`. For a blog, each post the user
68
- hands over is one entry. Its title becomes `title`; its body becomes `content` blocks, one block per
69
- paragraph, heading or list, whether the body arrived as text, HTML or Markdown; a category becomes
70
- `category` (and joins the `categories` list); tags become `tags`; their cover image becomes
71
- `coverImageUrl`. A post with no body is a question for the user. Authors and publish dates are
72
- not seeded — say so.
73
-
74
- ## Escape hatch — individual functions
75
- `setupBlog` composes exported steps — `installBlogApp`, `getAuthorMemberId`, `createPosts`,
76
- `createCategories`, `createTags`, `importImage`, `attachPostCovers`, plus `makeCtx()` —
77
- import them only for a partial re-seed.
78
-
79
- ## Reference
80
- Unexpected shape or an uncovered operation → read the live Wix API reference; the
81
- authoritative source recipe is `wix-headless/references/inline-recipes/setup-blog.md`.
@@ -1,22 +0,0 @@
1
- // What the blog holds: posts, categories, tags.
2
- // node <SKILL_ROOT>/references/blog/seed/read-site.mjs [--site <siteId>] [--limit <n>]
3
- import { runReader } from "../../shared/seed/read-site.mjs";
4
-
5
- const BLOG_APP_ID = "14bcded7-0066-7c35-14d7-466cb3f09103";
6
- const D = "https://dev.wix.com/docs/api-reference/business-solutions/blog";
7
-
8
- await runReader({
9
- vertical: "blog",
10
- appId: BLOG_APP_ID,
11
- async read(api, { limit }) {
12
- const posts = await api.call({ path: "/v3/posts/query", body: { fieldsets: ["URL"], query: { paging: { limit } } }, docs: `${D}/posts-stats/query-posts` });
13
- const cats = await api.tryCall({ path: "/blog/v3/categories/query", body: { query: { paging: { limit: 100 } } }, docs: `${D}/category/query-categories` });
14
- const tags = await api.tryCall({ path: "/v3/tags/query", body: { query: { paging: { limit: 100 } } }, docs: `${D}/tags/query-tags` });
15
- return {
16
- postCount: posts.metaData?.total ?? posts.pagingMetadata?.total ?? (posts.posts ?? []).length,
17
- posts: (posts.posts ?? []).map((p) => ({ title: p.title, slug: p.slug, published: p.firstPublishedDate ?? null, cover: !!p.coverMedia?.image, categories: (p.categoryIds ?? []).length, tags: (p.tagIds ?? []).length, minutesToRead: p.minutesToRead ?? null })),
18
- categories: (cats?.categories ?? []).map((c) => ({ id: c.id, label: c.label, slug: c.slug, postCount: c.postCount ?? null })),
19
- tags: (tags?.tags ?? []).map((t) => ({ id: t.id, label: t.label, postCount: t.postCount ?? null })),
20
- };
21
- },
22
- });
@@ -1,287 +0,0 @@
1
- // Blog seed — a BUILD-TIME script, never shipped in the app. Run from the project root
2
- // (where wix.config.json lives) with a plan file:
3
- //
4
- // node <SKILL_ROOT>/references/blog/seed/seed-blog.mjs plan.json
5
- //
6
- // It mints its own site token via the Wix CLI, installs the Wix Blog app if needed, resolves
7
- // a real author memberId (every post create requires one), creates categories/tags (idempotent
8
- // by label, with a fresh-install verify-retry), bulk-creates PUBLISHED posts with Ricos
9
- // richContent, and imports+attaches cover images (PATCH + re-publish). Prints a JSON result
10
- // to stdout.
11
- //
12
- // Plan shape (see SEED.md):
13
- // { "categories"?: [name], "tags"?: [name],
14
- // "posts": [{ "title", "content": [blocks] | "richContent"?, "category"?|"categories"?,
15
- // "tags"?, "coverImageUrl"? | "coverImagePrompt"? }] }
16
- // content blocks: { type:"heading", text, level? } | { type:"paragraph", text }
17
- // | { type:"quote", text } | { type:"bulleted"|"ordered", items:[text,…] }
18
- //
19
- // Seeding is ADDITIVE — never deletes or overwrites existing content. Unexpected shapes →
20
- // read the live API reference; authoritative source recipe:
21
- // wix-headless/references/inline-recipes/setup-blog.md.
22
- import { execFileSync } from "node:child_process";
23
- import { readFileSync } from "node:fs";
24
- import { resolveItemImages } from "../../shared/seed/images.mjs";
25
-
26
- const API = "https://www.wixapis.com";
27
- const BLOG_APP_ID = "14bcded7-0066-7c35-14d7-466cb3f09103";
28
-
29
- export function makeCtx({ cwd = process.cwd() } = {}) {
30
- const config = JSON.parse(readFileSync(`${cwd}/wix.config.json`, "utf8"));
31
- const siteId = config.siteId ?? config.projectId;
32
- if (!siteId) throw new Error("wix.config.json has no siteId — is this a Wix CLI project?");
33
- const token = execFileSync("npx", ["@wix/cli@latest", "token", "--site", siteId], {
34
- encoding: "utf8",
35
- cwd,
36
- }).trim();
37
- if (!token) throw new Error("The Wix CLI returned no token — run `npx @wix/cli@latest login` first.");
38
- return { token, siteId };
39
- }
40
-
41
- async function req(ctx, path, { method = "POST", body } = {}) {
42
- const res = await fetch(API + path, {
43
- method,
44
- headers: {
45
- Authorization: `Bearer ${ctx.token}`,
46
- "wix-site-id": ctx.siteId,
47
- "Content-Type": "application/json",
48
- },
49
- body: body ? JSON.stringify(body) : undefined,
50
- });
51
- const json = await res.json().catch(() => ({}));
52
- if (!res.ok) throw new Error(`${method} ${path} -> ${res.status}: ${JSON.stringify(json).slice(0, 400)}`);
53
- return json;
54
- }
55
-
56
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
57
-
58
- // ---- Ricos richContent builder (setup-blog.md § "CRITICAL RICOS NESTING") --------------------
59
- // Rules baked in: TEXT is always a leaf inside a container; BLOCKQUOTE / LIST_ITEM wrap a
60
- // PARAGRAPH; BULLETED_LIST / ORDERED_LIST wrap LIST_ITEM -> PARAGRAPH -> TEXT; every container
61
- // node gets a unique id, TEXT leaves use id "". For node types not covered here (code, images)
62
- // pass a pre-built `richContent` on the post instead — it's used verbatim.
63
- const mkText = (text) => ({ type: "TEXT", id: "", nodes: [], textData: { text: text || "", decorations: [] } });
64
- const mkParagraph = (id, text) => ({ type: "PARAGRAPH", id, nodes: [mkText(text)], paragraphData: {} });
65
-
66
- function mkRichContent(blocks = [], postIdx = 0) {
67
- let n = 0;
68
- const id = () => `p${postIdx}-n${n++}`;
69
- const nodes = [];
70
- for (const b of blocks) {
71
- switch (b.type) {
72
- case "heading":
73
- nodes.push({ type: "HEADING", id: id(), nodes: [mkText(b.text)], headingData: { level: b.level ?? 2 } });
74
- break;
75
- case "quote":
76
- nodes.push({ type: "BLOCKQUOTE", id: id(), nodes: [mkParagraph(id(), b.text)], blockquoteData: { indentation: 1 } });
77
- break;
78
- case "bulleted":
79
- case "ordered": {
80
- const listType = b.type === "bulleted" ? "BULLETED_LIST" : "ORDERED_LIST";
81
- nodes.push({
82
- type: listType, id: id(),
83
- nodes: (b.items ?? []).map((item) => ({ type: "LIST_ITEM", id: id(), nodes: [mkParagraph(id(), item)] })),
84
- });
85
- break;
86
- }
87
- case "paragraph":
88
- default:
89
- nodes.push(mkParagraph(id(), b.text));
90
- }
91
- }
92
- return { nodes };
93
- }
94
-
95
- // One post's plain data -> a flat Blog V3 draft-post object. media is omitted — covers are a
96
- // separate pass (attachPostCovers), per the recipe.
97
- function buildPost(p, i, memberId) {
98
- return {
99
- title: p.title,
100
- memberId,
101
- richContent: p.richContent ?? mkRichContent(p.content, i),
102
- ...(p.categoryIds ? { categoryIds: p.categoryIds } : {}),
103
- ...(p.tagIds ? { tagIds: p.tagIds } : {}),
104
- };
105
- }
106
-
107
- // ---- operations ----------------------------------------------------------------------------
108
-
109
- // docs: https://dev.wix.com/docs/api-reference/articles/work-with-wix-apis/platform/about-apps-created-by-wix.md
110
- export async function installBlogApp(ctx) {
111
- try {
112
- await req(ctx, "/apps-installer-service/v1/app-instance/install", { body: {
113
- tenant: { tenantType: "SITE", id: ctx.siteId },
114
- appInstance: { appDefId: BLOG_APP_ID, enabled: true },
115
- } });
116
- } catch {
117
- /* already installed is fine */
118
- }
119
- }
120
-
121
- // Every post create needs a REAL author memberId — a fabricated id fails with
122
- // "memberIds ... do not exist". A provisioned site has the owner as members[0].
123
- // docs: https://dev.wix.com/docs/api-reference/crm/members-contacts/members/members/list-members.md
124
- export async function getAuthorMemberId(ctx) {
125
- const r = await req(ctx, "/members/v1/members?fieldsets=PUBLIC&paging.limit=1", { method: "GET" });
126
- const id = r.members?.[0]?.id;
127
- if (!id) throw new Error(`No site member found for author attribution: ${JSON.stringify(r).slice(0, 400)}`);
128
- return id;
129
- }
130
-
131
- /**
132
- * Create posts, PUBLISHED (publish:true — unpublished posts never reach visitors).
133
- * Endpoint auto-selected per the recipe: single-post endpoint for exactly one (nested
134
- * `{ draftPost }` envelope), bulk for >= 2 — `bulk` sits BETWEEN v3 and draft-posts, and each
135
- * bulk item is FLAT (wrapping it in `draftPost` 400s). Returns [{ id, index, success }].
136
- * docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/draft-posts/create-draft-post.md
137
- * docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/draft-posts/bulk-create-draft-posts.md
138
- */
139
- export async function createPosts(ctx, posts, { memberId, publish = true } = {}) {
140
- if (!memberId) throw new Error("createPosts requires opts.memberId (see getAuthorMemberId)");
141
- if (posts.length === 1) {
142
- const r = await req(ctx, "/blog/v3/draft-posts", { body: { draftPost: buildPost(posts[0], 0, memberId), publish } });
143
- return [{ id: r.draftPost?.id, index: 0, success: !!r.draftPost?.id }];
144
- }
145
- const r = await req(ctx, "/blog/v3/bulk/draft-posts/create", {
146
- body: { draftPosts: posts.map((p, i) => buildPost(p, i, memberId)), publish },
147
- });
148
- // Bulk returns 200 even on partial failure — read per-item results[].itemMetadata.success.
149
- return (r.results ?? []).map((x) => ({
150
- id: x.itemMetadata?.id, index: x.itemMetadata?.originalIndex, success: !!x.itemMetadata?.success,
151
- }));
152
- }
153
-
154
- // Existing label -> id, straight from the query (the source of truth for what persisted).
155
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/category/query-categories.md
156
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/tags/query-tags.md
157
- async function labelIdMap(ctx, kind) {
158
- const path = kind === "categories" ? "/blog/v3/categories/query" : "/v3/tags/query";
159
- const r = await req(ctx, path, { body: { query: { paging: { limit: 100 } } } });
160
- return new Map((r[kind] ?? []).map((x) => [x.label, x.id]));
161
- }
162
-
163
- // Create category/tag labels resiliently. TWO hazards this absorbs:
164
- // 1. Fresh-install provisioning window — for a few seconds after the Blog app installs,
165
- // per-item category/tag creates return 200 with an id but DON'T persist (the id is a lie).
166
- // So the create response is never trusted — re-query, treat the query as truth, re-create
167
- // what's still missing until it sticks.
168
- // 2. Idempotency — an already-present label (a partial-failure re-run) is skipped.
169
- // Category bodies are NESTED (`{ category: { label } }`); tag bodies are FLAT (`{ label }`) —
170
- // a `{ tag: { label } }` body sends an empty top-level label and 400s. Returns [{ id, name }].
171
- async function ensureLabels(ctx, kind, createPath, mkBody, names) {
172
- let map = await labelIdMap(ctx, kind);
173
- for (let attempt = 0; attempt < 8; attempt++) {
174
- const missing = names.filter((n) => !map.has(n));
175
- if (!missing.length) break;
176
- if (attempt) await sleep(1500); // backoff only between retries — happy path pays nothing
177
- for (const name of missing) {
178
- try { await req(ctx, createPath, { body: mkBody(name) }); }
179
- catch (e) { if (!String(e.message).includes("-> 409")) throw e; } // 409 = raced, already there
180
- }
181
- map = await labelIdMap(ctx, kind);
182
- }
183
- return names.map((name) => ({ id: map.get(name), name }));
184
- }
185
-
186
- /** Create categories idempotently by label (no bulk endpoint). Feed ids into post.categoryIds. */
187
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/category/create-category.md
188
- export async function createCategories(ctx, names) {
189
- return ensureLabels(ctx, "categories", "/blog/v3/categories", (name) => ({ category: { label: name } }), names);
190
- }
191
-
192
- /** Create tags idempotently by label. Feed ids into post.tagIds. */
193
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/tags/create-tag.md
194
- export async function createTags(ctx, names) {
195
- return ensureLabels(ctx, "tags", "/blog/v3/tags", (name) => ({ label: name }), names);
196
- }
197
-
198
- // Blog binds a post cover by Wix Media file ID — an external url must be imported first; a
199
- // plan `coverImagePrompt` is generated (Wix AI, 1 credit) then imported. Both live in the
200
- // shared util (parallel, resilient, never blocks the seed).
201
- export { importImage } from "../../shared/seed/images.mjs";
202
-
203
- // covers: [{ postId, fileId }] where fileId is the Wix Media file.id from importImage. Per
204
- // post: PATCH /blog/v3/draft-posts/{id} (NOT POST …/{id}/update — that 404s), setting
205
- // media.displayed:true + media.custom:true + wixMedia.image.id (the id ALONE is a silent
206
- // no-op), then RE-PUBLISH — the PATCH sets hasUnpublishedChanges, so the live post stays
207
- // cover-less until republished. Image failures never block the run.
208
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/draft-posts/update-draft-post.md
209
- // docs: https://dev.wix.com/docs/api-reference/business-solutions/blog/draft-posts/publish-draft-post.md
210
- export async function attachPostCovers(ctx, covers) {
211
- let attached = 0;
212
- for (const { postId, fileId } of covers) {
213
- try {
214
- await req(ctx, `/blog/v3/draft-posts/${postId}`, {
215
- method: "PATCH",
216
- body: { draftPost: { media: { displayed: true, custom: true, wixMedia: { image: { id: fileId } } } } },
217
- });
218
- await req(ctx, `/blog/v3/draft-posts/${postId}/publish`, { method: "POST" });
219
- attached++;
220
- } catch (e) {
221
- console.error(`cover attach skipped for post ${postId}: ${e.message}`);
222
- }
223
- }
224
- return attached;
225
- }
226
-
227
- /**
228
- * ONE-CALL seed: install → author memberId → categories/tags (names resolved to ids) →
229
- * published posts → covers, ids threaded in memory. The default path.
230
- */
231
- export async function setupBlog(ctx, { posts = [], categories = [], tags = [] } = {}) {
232
- await installBlogApp(ctx);
233
- await sleep(3000); // let a fresh Blog install settle so the first category/tag writes stick
234
- // (correctness is still guaranteed by ensureLabels' verify-retry).
235
- const memberId = await getAuthorMemberId(ctx);
236
-
237
- const catNames = [...new Set([...categories, ...posts.flatMap((p) => [].concat(p.category ?? [], p.categories ?? []))])];
238
- const tagNames = [...new Set([...tags, ...posts.flatMap((p) => [].concat(p.tags ?? []))])];
239
- const cats = catNames.length ? await createCategories(ctx, catNames) : [];
240
- const tgs = tagNames.length ? await createTags(ctx, tagNames) : [];
241
- const catId = new Map(cats.map((c) => [c.name, c.id]));
242
- const tagId = new Map(tgs.map((t) => [t.name, t.id]));
243
-
244
- const created = await createPosts(ctx, posts.map((p) => {
245
- const cn = [].concat(p.category ?? [], p.categories ?? []);
246
- const tn = [].concat(p.tags ?? []);
247
- return {
248
- ...p,
249
- ...(cn.length ? { categoryIds: cn.map((n) => catId.get(n)).filter(Boolean) } : {}),
250
- ...(tn.length ? { tagIds: tn.map((n) => tagId.get(n)).filter(Boolean) } : {}),
251
- };
252
- }), { memberId });
253
-
254
- // Pass 2 — covers: resolve (import by url / generate by prompt) in one parallel wave, then
255
- // attach (PATCH + re-publish per post). Failures leave the post text-only; the seed's exit
256
- // never depends on images.
257
- const files = await resolveItemImages(ctx, created.map((c, i) => (
258
- c?.id && c?.success
259
- ? { path: posts[i]?.coverImagePath, url: posts[i]?.coverImageUrl, prompt: posts[i]?.coverImagePrompt, displayName: `post-${i}.png` }
260
- : null
261
- )));
262
- const covers = created
263
- .map((c, i) => (files[i] ? { postId: c.id, fileId: files[i].id } : null))
264
- .filter(Boolean);
265
- const coversAttached = covers.length ? await attachPostCovers(ctx, covers) : 0;
266
-
267
- return { posts: created, categories: cats, tags: tgs, coversAttached };
268
- }
269
-
270
- // ---- CLI entry ----------------------------------------------------------------------------------
271
-
272
- const invokedDirectly = process.argv[1] && import.meta.url.endsWith(process.argv[1].split("/").pop());
273
- if (invokedDirectly) {
274
- const planPath = process.argv[2];
275
- if (!planPath) {
276
- console.error("usage: node seed-blog.mjs <plan.json> (run from the project root)");
277
- process.exit(1);
278
- }
279
- const plan = JSON.parse(readFileSync(planPath, "utf8"));
280
- const ctx = makeCtx();
281
- setupBlog(ctx, plan)
282
- .then((result) => console.log(JSON.stringify(result, null, 2)))
283
- .catch((e) => {
284
- console.error(e.message);
285
- process.exit(1);
286
- });
287
- }